@@ -133,6 +133,11 @@ protected:
133133 CRYPTO_memcmp (keyData.begin (), other.begin (), keyData.size ()) == 0 ;
134134 }
135135
136+ bool equals (const jsg::BufferSource& other) const override final {
137+ return keyData.size () == other.size () &&
138+ CRYPTO_memcmp (keyData.begin (), other.asArrayPtr ().begin (), keyData.size ()) == 0 ;
139+ }
140+
136141 kj::StringPtr jsgGetMemoryName () const override {
137142 return " AesKeyBase" _kjc;
138143 }
@@ -149,7 +154,7 @@ private:
149154 return keyAlgorithm;
150155 }
151156
152- SubtleCrypto::ExportKeyData exportKey (kj::StringPtr format) const override final {
157+ SubtleCrypto::ExportKeyData exportKey (jsg::Lock& js, kj::StringPtr format) const override final {
153158 JSG_REQUIRE (format == " raw" || format == " jwk" , DOMNotSupportedError, getAlgorithmName (),
154159 " key only supports exporting \" raw\" & \" jwk\" , not \" " , format, " \" ." );
155160
@@ -184,7 +189,10 @@ private:
184189 return jwk;
185190 }
186191
187- return kj::heapArray (keyData.asPtr ());
192+ // Every export should be a separate copy.
193+ auto backing = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, keyData.size ());
194+ backing.asArrayPtr ().copyFrom (keyData);
195+ return jsg::BufferSource (js, kj::mv (backing));
188196 }
189197
190198protected:
@@ -201,7 +209,8 @@ public:
201209 : AesKeyBase(kj::mv(keyData), kj::mv(keyAlgorithm), extractable, usages) {}
202210
203211private:
204- kj::Array<kj::byte> encrypt (SubtleCrypto::EncryptAlgorithm&& algorithm,
212+ jsg::BufferSource encrypt (jsg::Lock& js,
213+ SubtleCrypto::EncryptAlgorithm&& algorithm,
205214 kj::ArrayPtr<const kj::byte> plainText) const override {
206215 kj::ArrayPtr<kj::byte> iv =
207216 JSG_REQUIRE_NONNULL (algorithm.iv , TypeError, " Missing field \" iv\" in \" algorithm\" ." );
@@ -242,31 +251,32 @@ private:
242251 // a stream cipher in that it does not add padding and can process partial blocks, meaning that
243252 // we know the exact ciphertext size in advance.
244253 auto tagByteSize = tagLength / 8 ;
245- auto cipherText = kj::heapArray<kj::byte>( plainText.size () + tagByteSize);
254+ auto cipherText = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, plainText.size () + tagByteSize);
246255
247256 // Perform the actual encryption.
248257
249258 int cipherSize = 0 ;
250- OSSLCALL (EVP_EncryptUpdate (
251- cipherCtx. get (), cipherText. begin (), &cipherSize, plainText.begin (), plainText.size ()));
259+ OSSLCALL (EVP_EncryptUpdate (cipherCtx. get (), cipherText. asArrayPtr (). begin (), &cipherSize,
260+ plainText.begin (), plainText.size ()));
252261 KJ_ASSERT (cipherSize == plainText.size (), " EVP_EncryptUpdate should encrypt all at once" );
253262
254263 int finalCipherSize = 0 ;
255- OSSLCALL (
256- EVP_EncryptFinal_ex ( cipherCtx.get (), cipherText.begin () + cipherSize, &finalCipherSize));
264+ OSSLCALL (EVP_EncryptFinal_ex (
265+ cipherCtx.get (), cipherText. asArrayPtr () .begin () + cipherSize, &finalCipherSize));
257266 KJ_ASSERT (finalCipherSize == 0 , " EVP_EncryptFinal_ex should not output any data" );
258267
259268 // Concatenate the tag onto the cipher text.
260269 KJ_ASSERT (cipherSize + tagByteSize == cipherText.size (), " imminent buffer overrun" );
261- OSSLCALL (EVP_CIPHER_CTX_ctrl (
262- cipherCtx. get (), EVP_CTRL_GCM_GET_TAG, tagByteSize, cipherText .begin () + cipherSize));
270+ OSSLCALL (EVP_CIPHER_CTX_ctrl (cipherCtx. get (), EVP_CTRL_GCM_GET_TAG, tagByteSize,
271+ cipherText. asArrayPtr () .begin () + cipherSize));
263272 cipherSize += tagByteSize;
264273 KJ_ASSERT (cipherSize == cipherText.size (), " buffer overrun" );
265274
266- return cipherText;
275+ return jsg::BufferSource (js, kj::mv ( cipherText)) ;
267276 }
268277
269- kj::Array<kj::byte> decrypt (SubtleCrypto::EncryptAlgorithm&& algorithm,
278+ jsg::BufferSource decrypt (jsg::Lock& js,
279+ SubtleCrypto::EncryptAlgorithm&& algorithm,
270280 kj::ArrayPtr<const kj::byte> cipherText) const override {
271281 kj::ArrayPtr<kj::byte> iv =
272282 JSG_REQUIRE_NONNULL (algorithm.iv , TypeError, " Missing field \" iv\" in \" algorithm\" ." );
@@ -303,10 +313,10 @@ private:
303313 auto actualCipherText = cipherText.first (cipherText.size () - tagLength / 8 );
304314 auto tagText = cipherText.slice (actualCipherText.size (), cipherText.size ());
305315
306- auto plainText = kj::heapArray<kj::byte>( actualCipherText.size ());
316+ auto plainText = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, actualCipherText.size ());
307317
308318 // Perform the actual decryption.
309- OSSLCALL (EVP_DecryptUpdate (cipherCtx.get (), plainText.begin (), &plainSize,
319+ OSSLCALL (EVP_DecryptUpdate (cipherCtx.get (), plainText.asArrayPtr (). begin (), &plainSize,
310320 actualCipherText.begin (), actualCipherText.size ()));
311321 KJ_ASSERT (plainSize == plainText.size ());
312322
@@ -322,10 +332,10 @@ private:
322332 const_cast <kj::byte*>(tagText.begin ())));
323333
324334 plainSize += decryptFinalHelper (getAlgorithmName (), actualCipherText.size (), plainSize,
325- cipherCtx.get (), plainText.begin () + plainSize);
335+ cipherCtx.get (), plainText.asArrayPtr (). begin () + plainSize);
326336 KJ_ASSERT (plainSize == plainText.size ());
327337
328- return plainText;
338+ return jsg::BufferSource (js, kj::mv ( plainText)) ;
329339 }
330340};
331341
@@ -338,7 +348,8 @@ public:
338348 : AesKeyBase(kj::mv(keyData), kj::mv(keyAlgorithm), extractable, usages) {}
339349
340350private:
341- kj::Array<kj::byte> encrypt (SubtleCrypto::EncryptAlgorithm&& algorithm,
351+ jsg::BufferSource encrypt (jsg::Lock& js,
352+ SubtleCrypto::EncryptAlgorithm&& algorithm,
342353 kj::ArrayPtr<const kj::byte> plainText) const override {
343354 kj::ArrayPtr<kj::byte> iv =
344355 JSG_REQUIRE_NONNULL (algorithm.iv , TypeError, " Missing field \" iv\" in \" algorithm\" ." );
@@ -355,29 +366,30 @@ private:
355366
356367 auto blockSize = EVP_CIPHER_CTX_block_size (cipherCtx.get ());
357368 size_t paddingSize = blockSize - (plainText.size () % blockSize);
358- auto cipherText = kj::heapArray<kj::byte>( plainText.size () + paddingSize);
369+ auto cipherText = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, plainText.size () + paddingSize);
359370
360371 // Perform the actual encryption.
361372 //
362373 // Note: We don't worry about PKCS padding (see RFC2315 section 10.3 step 2) because BoringSSL
363374 // takes care of it for us by default in EVP_EncryptFinal_ex().
364375
365376 int cipherSize = 0 ;
366- OSSLCALL (EVP_EncryptUpdate (
367- cipherCtx. get (), cipherText. begin (), &cipherSize, plainText.begin (), plainText.size ()));
377+ OSSLCALL (EVP_EncryptUpdate (cipherCtx. get (), cipherText. asArrayPtr (). begin (), &cipherSize,
378+ plainText.begin (), plainText.size ()));
368379 KJ_ASSERT (cipherSize <= cipherText.size (), " buffer overrun" );
369380
370381 KJ_ASSERT (cipherSize + blockSize <= cipherText.size (), " imminent buffer overrun" );
371382 int finalCipherSize = 0 ;
372- OSSLCALL (
373- EVP_EncryptFinal_ex ( cipherCtx.get (), cipherText.begin () + cipherSize, &finalCipherSize));
383+ OSSLCALL (EVP_EncryptFinal_ex (
384+ cipherCtx.get (), cipherText. asArrayPtr () .begin () + cipherSize, &finalCipherSize));
374385 cipherSize += finalCipherSize;
375386 KJ_ASSERT (cipherSize == cipherText.size (), " buffer overrun" );
376387
377- return cipherText;
388+ return jsg::BufferSource (js, kj::mv ( cipherText)) ;
378389 }
379390
380- kj::Array<kj::byte> decrypt (SubtleCrypto::EncryptAlgorithm&& algorithm,
391+ jsg::BufferSource decrypt (jsg::Lock& js,
392+ SubtleCrypto::EncryptAlgorithm&& algorithm,
381393 kj::ArrayPtr<const kj::byte> cipherText) const override {
382394 kj::ArrayPtr<kj::byte> iv =
383395 JSG_REQUIRE_NONNULL (algorithm.iv , TypeError, " Missing field \" iv\" in \" algorithm\" ." );
@@ -408,7 +420,9 @@ private:
408420 KJ_ASSERT (plainSize <= plainText.size ());
409421
410422 // TODO(perf): Avoid this copy, see comment in the encrypt implementation functions.
411- return kj::heapArray (plainText.begin (), plainSize);
423+ auto backing = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, plainSize);
424+ backing.asArrayPtr ().copyFrom (plainText.first (plainSize));
425+ return jsg::BufferSource (js, kj::mv (backing));
412426 }
413427};
414428
@@ -422,14 +436,16 @@ public:
422436 CryptoKeyUsageSet usages)
423437 : AesKeyBase(kj::mv(keyData), kj::mv(keyAlgorithm), extractable, usages) {}
424438
425- kj::Array<kj::byte> encrypt (SubtleCrypto::EncryptAlgorithm&& algorithm,
439+ jsg::BufferSource encrypt (jsg::Lock& js,
440+ SubtleCrypto::EncryptAlgorithm&& algorithm,
426441 kj::ArrayPtr<const kj::byte> plainText) const override {
427- return encryptOrDecrypt (kj::mv (algorithm), plainText);
442+ return encryptOrDecrypt (js, kj::mv (algorithm), plainText);
428443 }
429444
430- kj::Array<kj::byte> decrypt (SubtleCrypto::EncryptAlgorithm&& algorithm,
445+ jsg::BufferSource decrypt (jsg::Lock& js,
446+ SubtleCrypto::EncryptAlgorithm&& algorithm,
431447 kj::ArrayPtr<const kj::byte> cipherText) const override {
432- return encryptOrDecrypt (kj::mv (algorithm), cipherText);
448+ return encryptOrDecrypt (js, kj::mv (algorithm), cipherText);
433449 }
434450
435451protected:
@@ -448,8 +464,9 @@ protected:
448464 KJ_FAIL_ASSERT (" CryptoKey has invalid data length" );
449465 }
450466
451- kj::Array<kj::byte> encryptOrDecrypt (
452- SubtleCrypto::EncryptAlgorithm&& algorithm, kj::ArrayPtr<const kj::byte> data) const {
467+ jsg::BufferSource encryptOrDecrypt (jsg::Lock& js,
468+ SubtleCrypto::EncryptAlgorithm&& algorithm,
469+ kj::ArrayPtr<const kj::byte> data) const {
453470 auto & counter = JSG_REQUIRE_NONNULL (
454471 algorithm.counter , TypeError, " Missing \" counter\" member in \" algorithm\" ." );
455472 JSG_REQUIRE (counter.size () == expectedCounterByteSize, DOMOperationError,
@@ -472,9 +489,8 @@ protected:
472489
473490 const auto & cipher = lookupAesType (keyData.size ());
474491
475- kj::Vector<kj::byte> result;
476492 // The output of AES-CTR is the same size as the input.
477- result. resize ( data.size ());
493+ auto result = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, data.size ());
478494
479495 auto numCounterValues = newBignum ();
480496 JSG_REQUIRE (BN_lshift (numCounterValues.get (), BN_value_one (), counterBitLength),
@@ -505,15 +521,15 @@ protected:
505521
506522 if (BN_cmp (numBlocksUntilReset.get (), numOutputBlocks.get ()) >= 0 ) {
507523 // If the counter doesn't need any wrapping, can evaluate this as a single call.
508- process (&cipher, data, counter, result.asPtr ());
509- return result. releaseAsArray ( );
524+ process (&cipher, data, counter, result.asArrayPtr ());
525+ return jsg::BufferSource (js, kj::mv (result) );
510526 }
511527
512528 // Need this to be done in 2 parts using the current counter block and then resetting the
513529 // counter portion of the block back to zero.
514530 auto inputSizePart1 = BN_get_word (numBlocksUntilReset.get ()) * AES_BLOCK_SIZE;
515531
516- process (&cipher, data.first (inputSizePart1), counter, result.asPtr ());
532+ process (&cipher, data.first (inputSizePart1), counter, result.asArrayPtr ());
517533
518534 // Zero the counter bits of the block. Chromium creates a copy but we own our buffer.
519535 {
@@ -528,9 +544,9 @@ protected:
528544 }
529545
530546 process (&cipher, data.slice (inputSizePart1, data.size ()), counter,
531- result.slice (inputSizePart1, result.size ()));
547+ result.asArrayPtr (). slice (inputSizePart1, result.size ()));
532548
533- return result. releaseAsArray ( );
549+ return jsg::BufferSource (js, kj::mv (result) );
534550 }
535551
536552private:
@@ -620,7 +636,8 @@ public:
620636 CryptoKeyUsageSet usages)
621637 : AesKeyBase(kj::mv(keyData), kj::mv(keyAlgorithm), extractable, usages) {}
622638
623- kj::Array<kj::byte> wrapKey (SubtleCrypto::EncryptAlgorithm&& algorithm,
639+ jsg::BufferSource wrapKey (jsg::Lock& js,
640+ SubtleCrypto::EncryptAlgorithm&& algorithm,
624641 kj::ArrayPtr<const kj::byte> unwrappedKey) const override {
625642 // Resources used to implement this:
626643 // https://www.ietf.org/rfc/rfc3394.txt
@@ -636,8 +653,7 @@ public:
636653 " equal to 16 and less than or equal to " ,
637654 SIZE_MAX - 8 );
638655
639- kj::Vector<kj::byte> wrapped (unwrappedKey.size () + 8 );
640- wrapped.resize (unwrappedKey.size () + 8 );
656+ auto wrapped = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, unwrappedKey.size () + 8 );
641657 // Wrapping adds 8 bytes of overhead for storing the IV which we check on decryption.
642658
643659 AES_KEY aesKey;
@@ -646,14 +662,15 @@ public:
646662 internalDescribeOpensslErrors ());
647663
648664 JSG_REQUIRE (wrapped.size () ==
649- AES_wrap_key (
650- &aesKey, nullptr , wrapped. begin (), unwrappedKey. begin (), unwrappedKey.size ()),
665+ AES_wrap_key (&aesKey, nullptr , wrapped. asArrayPtr (). begin (), unwrappedKey. begin (),
666+ unwrappedKey.size ()),
651667 DOMOperationError, getAlgorithmName (), " key wrapping failed" , tryDescribeOpensslErrors ());
652668
653- return wrapped. releaseAsArray ( );
669+ return jsg::BufferSource (js, kj::mv (wrapped) );
654670 }
655671
656- kj::Array<kj::byte> unwrapKey (SubtleCrypto::EncryptAlgorithm&& algorithm,
672+ jsg::BufferSource unwrapKey (jsg::Lock& js,
673+ SubtleCrypto::EncryptAlgorithm&& algorithm,
657674 kj::ArrayPtr<const kj::byte> wrappedKey) const override {
658675 // Resources used to implement this:
659676 // https://www.ietf.org/rfc/rfc3394.txt
@@ -667,9 +684,7 @@ public:
667684 " Provided a wrapped key to unwrap this is " , wrappedKey.size () * 8 ,
668685 " bits that is less than the minimal length of 192 bits." );
669686
670- kj::Vector<kj::byte> unwrapped (wrappedKey.size () - 8 );
671- // Key wrap adds 8 bytes of overhead because it mixes in the IV.
672- unwrapped.resize (wrappedKey.size () - 8 );
687+ auto unwrapped = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, wrappedKey.size () - 8 );
673688
674689 AES_KEY aesKey;
675690 JSG_REQUIRE (0 == AES_set_decrypt_key (keyData.begin (), keyData.size () * 8 , &aesKey),
@@ -679,12 +694,12 @@ public:
679694 // null for the IV value here will tell OpenSSL to validate using the default IV from RFC3394.
680695 // https://github.com/openssl/openssl/blob/13a574d8bb2523181f8150de49bc041c9841f59d/crypto/modes/wrap128.c
681696 JSG_REQUIRE (unwrapped.size () ==
682- AES_unwrap_key (
683- &aesKey, nullptr , unwrapped. begin (), wrappedKey. begin (), wrappedKey.size ()),
697+ AES_unwrap_key (&aesKey, nullptr , unwrapped. asArrayPtr (). begin (), wrappedKey. begin (),
698+ wrappedKey.size ()),
684699 DOMOperationError, getAlgorithmName (), " key unwrapping failed" ,
685700 tryDescribeOpensslErrors ());
686701
687- return unwrapped. releaseAsArray ( );
702+ return jsg::BufferSource (js, kj::mv (unwrapped) );
688703 }
689704};
690705
0 commit comments