@@ -93,6 +93,67 @@ function run_test() {
9393 all_promises . push ( promise ) ;
9494 } ) ;
9595
96+ // Check for encryption of an empty value if the buffer is transferred while calling encrypt.
97+ passingVectors . forEach ( function ( vector ) {
98+ var plaintext = copyBuffer ( vector . plaintext ) ;
99+ var promise = importVectorKey ( vector , [ "encrypt" , "decrypt" ] )
100+ . then ( function ( vector ) {
101+ promise_test ( function ( test ) {
102+ var operation = subtle . encrypt ( {
103+ ...vector . algorithm ,
104+ get name ( ) {
105+ plaintext . buffer . transfer ( ) ;
106+ return vector . algorithm . name ;
107+ }
108+ } , vector . key , plaintext )
109+ . then ( function ( result ) {
110+ var expectedLength =
111+ [ "AES-GCM" , "AES-OCB" ] . includes ( vector . algorithm . name ) ? vector . algorithm . tagLength / 8 :
112+ vector . algorithm . name === "AES-CBC" ? 16 :
113+ 0 ;
114+ assert_equals ( result . byteLength , expectedLength , "Transferred plaintext yields an empty ciphertext" ) ;
115+ } , function ( err ) {
116+ assert_unreached ( "encrypt error for test " + vector . name + ": " + err . message ) ;
117+ } ) ;
118+ return operation ;
119+ } , vector . name + " with transferred plaintext during call" ) ;
120+ } , function ( err ) {
121+ // We need a failed test if the importVectorKey operation fails, so
122+ // we know we never tested encryption
123+ promise_test ( function ( test ) {
124+ assert_unreached ( "importKey failed for " + vector . name ) ;
125+ } , "importKey step: " + vector . name + " with transferred plaintext during call" ) ;
126+ } ) ;
127+
128+ all_promises . push ( promise ) ;
129+ } ) ;
130+
131+ // Check for successful encryption even if the buffer is transferred after calling encrypt.
132+ passingVectors . forEach ( function ( vector ) {
133+ var plaintext = copyBuffer ( vector . plaintext ) ;
134+ var promise = importVectorKey ( vector , [ "encrypt" , "decrypt" ] )
135+ . then ( function ( vector ) {
136+ promise_test ( function ( test ) {
137+ var operation = subtle . encrypt ( vector . algorithm , vector . key , plaintext )
138+ . then ( function ( result ) {
139+ assert_true ( equalBuffers ( result , vector . result ) , "Should return expected result" ) ;
140+ } , function ( err ) {
141+ assert_unreached ( "encrypt error for test " + vector . name + ": " + err . message ) ;
142+ } ) ;
143+ plaintext . buffer . transfer ( ) ;
144+ return operation ;
145+ } , vector . name + " with transferred plaintext after call" ) ;
146+ } , function ( err ) {
147+ // We need a failed test if the importVectorKey operation fails, so
148+ // we know we never tested encryption
149+ promise_test ( function ( test ) {
150+ assert_unreached ( "importKey failed for " + vector . name ) ;
151+ } , "importKey step: " + vector . name + " with transferred plaintext after call" ) ;
152+ } ) ;
153+
154+ all_promises . push ( promise ) ;
155+ } ) ;
156+
96157 // Check for successful decryption.
97158 passingVectors . forEach ( function ( vector ) {
98159 var promise = importVectorKey ( vector , [ "encrypt" , "decrypt" ] )
@@ -174,6 +235,71 @@ function run_test() {
174235 all_promises . push ( promise ) ;
175236 } ) ;
176237
238+ // Check for decryption when ciphertext is transferred while calling decrypt.
239+ passingVectors . forEach ( function ( vector ) {
240+ var ciphertext = copyBuffer ( vector . result ) ;
241+ var promise = importVectorKey ( vector , [ "encrypt" , "decrypt" ] )
242+ . then ( function ( vector ) {
243+ promise_test ( function ( test ) {
244+ var operation = subtle . decrypt ( {
245+ ...vector . algorithm ,
246+ get name ( ) {
247+ ciphertext . buffer . transfer ( ) ;
248+ return vector . algorithm . name ;
249+ }
250+ } , vector . key , ciphertext )
251+ . then ( function ( result ) {
252+ if ( vector . algorithm . name === "AES-CTR" ) {
253+ assert_equals ( result . byteLength , 0 , "Transferred ciphertext yields empty plaintext" ) ;
254+ } else {
255+ assert_unreached ( "decrypt should not have succeeded for " + vector . name ) ;
256+ }
257+ } , function ( err ) {
258+ if ( vector . algorithm . name === "AES-CTR" ) {
259+ assert_unreached ( "decrypt error for test " + vector . name + ": " + err . message ) ;
260+ } else {
261+ assert_equals ( err . name , "OperationError" , "Should throw an OperationError instead of " + err . message ) ;
262+ }
263+ } ) ;
264+ return operation ;
265+ } , vector . name + " decryption with transferred ciphertext during call" ) ;
266+ } , function ( err ) {
267+ // We need a failed test if the importVectorKey operation fails, so
268+ // we know we never tested encryption
269+ promise_test ( function ( test ) {
270+ assert_unreached ( "importKey failed for " + vector . name ) ;
271+ } , "importKey step for decryption: " + vector . name + " with transferred ciphertext during call" ) ;
272+ } ) ;
273+
274+ all_promises . push ( promise ) ;
275+ } ) ;
276+
277+ // Check for successful decryption even if ciphertext is transferred after calling encrypt.
278+ passingVectors . forEach ( function ( vector ) {
279+ var ciphertext = copyBuffer ( vector . result ) ;
280+ var promise = importVectorKey ( vector , [ "encrypt" , "decrypt" ] )
281+ . then ( function ( vector ) {
282+ promise_test ( function ( test ) {
283+ var operation = subtle . decrypt ( vector . algorithm , vector . key , ciphertext )
284+ . then ( function ( result ) {
285+ assert_true ( equalBuffers ( result , vector . plaintext ) , "Should return expected result" ) ;
286+ } , function ( err ) {
287+ assert_unreached ( "decrypt error for test " + vector . name + ": " + err . message ) ;
288+ } ) ;
289+ ciphertext . buffer . transfer ( ) ;
290+ return operation ;
291+ } , vector . name + " decryption with transferred ciphertext after call" ) ;
292+ } , function ( err ) {
293+ // We need a failed test if the importVectorKey operation fails, so
294+ // we know we never tested encryption
295+ promise_test ( function ( test ) {
296+ assert_unreached ( "importKey failed for " + vector . name ) ;
297+ } , "importKey step for decryption: " + vector . name + " with transferred ciphertext after call" ) ;
298+ } ) ;
299+
300+ all_promises . push ( promise ) ;
301+ } ) ;
302+
177303 // Everything that succeeded should fail if no "encrypt" usage.
178304 passingVectors . forEach ( function ( vector ) {
179305 // Don't want to overwrite key being used for success tests!
0 commit comments