| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 1bff901 commit 3bac77f
10 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -399,7 +399,7 @@ const conditionalAlgorithms = { | |||
| 399 | 399 | 'Argon2d': !!Argon2Job, | |
| 400 | 400 | 'Argon2i': !!Argon2Job, | |
| 401 | 401 | 'Argon2id': !!Argon2Job, | |
| 402 | - 'ChaCha20-Poly1305': !process.features.openssl_is_boringssl || | ||
| 402 | + 'ChaCha20-Poly1305': process.features.openssl_is_boringssl || | ||
| 403 | 403 | ArrayPrototypeIncludes(getCiphers(), 'chacha20-poly1305'), | |
| 404 | 404 | 'cSHAKE128': !process.features.openssl_is_boringssl || | |
| 405 | 405 | ArrayPrototypeIncludes(getHashes(), 'shake128'), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,9 @@ | |||
| 10 | 10 | #include "v8.h" | |
| 11 | 11 | ||
| 12 | 12 | #include <openssl/evp.h> | |
| 13 | + #ifdef OPENSSL_IS_BORINGSSL | ||
| 14 | + #include <openssl/aead.h> | ||
| 15 | + #endif | ||
| 13 | 16 | ||
| 14 | 17 | namespace node { | |
| 15 | 18 | ||
@@ -110,10 +113,15 @@ Maybe<void> ChaCha20Poly1305CipherTraits::AdditionalConfig( | |||
| 110 | 113 | params->mode = mode; | |
| 111 | 114 | params->cipher = ncrypto::Cipher::CHACHA20_POLY1305; | |
| 112 | 115 | ||
| 116 | + #ifndef OPENSSL_IS_BORINGSSL | ||
| 117 | + // On BoringSSL, ChaCha20-Poly1305 is not exposed via the EVP_CIPHER registry | ||
| 118 | + // so FromNid() returns a null Cipher. We use EVP_AEAD directly in DoCipher | ||
| 119 | + // instead. | ||
| 113 | 120 | if (!params->cipher) { | |
| 114 | 121 | THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env); | |
| 115 | 122 | return Nothing<void>(); | |
| 116 | 123 | } | |
| 124 | + #endif | ||
| 117 | 125 | ||
| 118 | 126 | // IV parameter (required) | |
| 119 | 127 | if (!ValidateIV(env, mode, args[offset], params)) { | |
@@ -144,6 +152,75 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( | |||
| 144 | 152 | return WebCryptoCipherStatus::INVALID_KEY_TYPE; | |
| 145 | 153 | } | |
| 146 | 154 | ||
| 155 | + #ifdef OPENSSL_IS_BORINGSSL | ||
| 156 | + // BoringSSL does not expose ChaCha20-Poly1305 via the EVP_CIPHER registry; | ||
| 157 | + // it is only available through the EVP_AEAD API. Matches Chromium's | ||
| 158 | + // WebCrypto ChaCha20-Poly1305 implementation. | ||
| 159 | + const auto key_bytes = | ||
| 160 | + reinterpret_cast<const unsigned char*>(key_data.GetSymmetricKey()); | ||
| 161 | + const auto ad_bytes = params.additional_data.data<unsigned char>(); | ||
| 162 | + const auto ad_len = params.additional_data.size(); | ||
| 163 | + const auto iv_bytes = params.iv.data<unsigned char>(); | ||
| 164 | + const auto iv_len = params.iv.size(); | ||
| 165 | + | ||
| 166 | + bssl::ScopedEVP_AEAD_CTX ctx; | ||
| 167 | + if (!EVP_AEAD_CTX_init(ctx.get(), | ||
| 168 | + EVP_aead_chacha20_poly1305(), | ||
| 169 | + key_bytes, | ||
| 170 | + key_data.GetSymmetricKeySize(), | ||
| 171 | + kChaCha20Poly1305TagSize, | ||
| 172 | + nullptr)) { | ||
| 173 | + return WebCryptoCipherStatus::FAILED; | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + if (cipher_mode == kWebCryptoCipherEncrypt) { | ||
| 177 | + size_t out_len = 0; | ||
| 178 | + const size_t max_out_len = in.size() + kChaCha20Poly1305TagSize; | ||
| 179 | + auto buf = DataPointer::Alloc(max_out_len); | ||
| 180 | + if (!EVP_AEAD_CTX_seal(ctx.get(), | ||
| 181 | + static_cast<unsigned char*>(buf.get()), | ||
| 182 | + &out_len, | ||
| 183 | + max_out_len, | ||
| 184 | + iv_bytes, | ||
| 185 | + iv_len, | ||
| 186 | + in.data<unsigned char>(), | ||
| 187 | + in.size(), | ||
| 188 | + ad_bytes, | ||
| 189 | + ad_len)) { | ||
| 190 | + return WebCryptoCipherStatus::FAILED; | ||
| 191 | + } | ||
| 192 | + buf = buf.resize(out_len); | ||
| 193 | + *out = ByteSource::Allocated(buf.release()); | ||
| 194 | + return WebCryptoCipherStatus::OK; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + // Decrypt | ||
| 198 | + if (in.size() < kChaCha20Poly1305TagSize) { | ||
| 199 | + return WebCryptoCipherStatus::FAILED; | ||
| 200 | + } | ||
| 201 | + size_t out_len = 0; | ||
| 202 | + const size_t max_out_len = in.size(); // at most |in_len| bytes written | ||
| 203 | + auto buf = DataPointer::Alloc(max_out_len == 0 ? 1 : max_out_len); | ||
| 204 | + if (!EVP_AEAD_CTX_open(ctx.get(), | ||
| 205 | + static_cast<unsigned char*>(buf.get()), | ||
| 206 | + &out_len, | ||
| 207 | + max_out_len, | ||
| 208 | + iv_bytes, | ||
| 209 | + iv_len, | ||
| 210 | + in.data<unsigned char>(), | ||
| 211 | + in.size(), | ||
| 212 | + ad_bytes, | ||
| 213 | + ad_len)) { | ||
| 214 | + return WebCryptoCipherStatus::FAILED; | ||
| 215 | + } | ||
| 216 | + if (out_len == 0) { | ||
| 217 | + *out = ByteSource(); | ||
| 218 | + } else { | ||
| 219 | + buf = buf.resize(out_len); | ||
| 220 | + *out = ByteSource::Allocated(buf.release()); | ||
| 221 | + } | ||
| 222 | + return WebCryptoCipherStatus::OK; | ||
| 223 | + #else | ||
| 147 | 224 | auto ctx = CipherCtxPointer::New(); | |
| 148 | 225 | CHECK(ctx); | |
| 149 | 226 | ||
@@ -252,6 +329,7 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( | |||
| 252 | 329 | *out = ByteSource::Allocated(buf.release()); | |
| 253 | 330 | ||
| 254 | 331 | return WebCryptoCipherStatus::OK; | |
| 332 | + #endif // OPENSSL_IS_BORINGSSL | ||
| 255 | 333 | } | |
| 256 | 334 | ||
| 257 | 335 | void ChaCha20Poly1305::Initialize(Environment* env, Local<Object> target) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,6 @@ const pqc = hasOpenSSL(3, 5); | |||
| 6 | 6 | const argon2 = hasOpenSSL(3, 2); | |
| 7 | 7 | const shake128 = crypto.getHashes().includes('shake128'); | |
| 8 | 8 | const shake256 = crypto.getHashes().includes('shake256'); | |
| 9 | - const chacha = crypto.getCiphers().includes('chacha20-poly1305'); | ||
| 10 | 9 | const ocb = hasOpenSSL(3); | |
| 11 | 10 | const kmac = hasOpenSSL(3); | |
| 12 | 11 | const boringSSL = process.features.openssl_is_boringssl; | |
@@ -78,7 +77,7 @@ export const vectors = { | |||
| 78 | 77 | [pqc, 'ML-KEM-512'], | |
| 79 | 78 | [pqc, 'ML-KEM-768'], | |
| 80 | 79 | [pqc, 'ML-KEM-1024'], | |
| 81 | - [chacha, 'ChaCha20-Poly1305'], | ||
| 80 | + [true, 'ChaCha20-Poly1305'], | ||
| 82 | 81 | [ocb, { name: 'AES-OCB', length: 128 }], | |
| 83 | 82 | [false, 'Argon2d'], | |
| 84 | 83 | [false, 'Argon2i'], | |
@@ -99,7 +98,7 @@ export const vectors = { | |||
| 99 | 98 | [pqc, 'ML-KEM-512'], | |
| 100 | 99 | [pqc, 'ML-KEM-768'], | |
| 101 | 100 | [pqc, 'ML-KEM-1024'], | |
| 102 | - [chacha, 'ChaCha20-Poly1305'], | ||
| 101 | + [true, 'ChaCha20-Poly1305'], | ||
| 103 | 102 | [ocb, { name: 'AES-OCB', length: 128 }], | |
| 104 | 103 | [argon2, 'Argon2d'], | |
| 105 | 104 | [argon2, 'Argon2i'], | |
@@ -120,7 +119,7 @@ export const vectors = { | |||
| 120 | 119 | [pqc, 'ML-KEM-512'], | |
| 121 | 120 | [pqc, 'ML-KEM-768'], | |
| 122 | 121 | [pqc, 'ML-KEM-1024'], | |
| 123 | - [chacha, 'ChaCha20-Poly1305'], | ||
| 122 | + [true, 'ChaCha20-Poly1305'], | ||
| 124 | 123 | [ocb, 'AES-OCB'], | |
| 125 | 124 | [false, 'Argon2d'], | |
| 126 | 125 | [false, 'Argon2i'], | |
@@ -183,9 +182,9 @@ export const vectors = { | |||
| 183 | 182 | [false, { name: 'Argon2d', nonce: Buffer.alloc(0), parallelism: 16777215, memory: 8, passes: 1 }, 32], | |
| 184 | 183 | ], | |
| 185 | 184 | 'encrypt': [ | |
| 186 | - [chacha, { name: 'ChaCha20-Poly1305', iv: Buffer.alloc(12) }], | ||
| 185 | + [true, { name: 'ChaCha20-Poly1305', iv: Buffer.alloc(12) }], | ||
| 187 | 186 | [false, { name: 'ChaCha20-Poly1305', iv: Buffer.alloc(16) }], | |
| 188 | - [chacha, { name: 'ChaCha20-Poly1305', iv: Buffer.alloc(12), tagLength: 128 }], | ||
| 187 | + [true, { name: 'ChaCha20-Poly1305', iv: Buffer.alloc(12), tagLength: 128 }], | ||
| 189 | 188 | [false, { name: 'ChaCha20-Poly1305', iv: Buffer.alloc(12), tagLength: 64 }], | |
| 190 | 189 | [false, 'ChaCha20-Poly1305'], | |
| 191 | 190 | [ocb, { name: 'AES-OCB', iv: Buffer.alloc(15) }], | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,15 +26,10 @@ function assertCryptoKey(cryptoKey, keyObject, algorithm, extractable, usages) { | |||
| 26 | 26 | { | |
| 27 | 27 | for (const length of [128, 192, 256]) { | |
| 28 | 28 | const key = createSecretKey(randomBytes(length >> 3)); | |
| 29 | - let algorithms = ['AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW']; | ||
| 29 | + const algorithms = ['AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW']; | ||
| 30 | 30 | if (length === 256) | |
| 31 | 31 | algorithms.push('ChaCha20-Poly1305'); | |
| 32 | 32 | ||
| 33 | - if (process.features.openssl_is_boringssl) { | ||
| 34 | - algorithms = algorithms.filter((a) => a !== 'ChaCha20-Poly1305'); | ||
| 35 | - common.printSkipMessage('Skipping unsupported ChaCha20-Poly1305 test case'); | ||
| 36 | - } | ||
| 37 | - | ||
| 38 | 33 | for (const algorithm of algorithms) { | |
| 39 | 34 | const usages = algorithm === 'AES-KW' ? ['wrapKey', 'unwrapKey'] : ['encrypt', 'decrypt']; | |
| 40 | 35 | for (const extractable of [true, false]) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,14 +29,11 @@ async function test(algorithmName, keyLength, ivLength, format = 'raw') { | |||
| 29 | 29 | ||
| 30 | 30 | const tests = [ | |
| 31 | 31 | test('AES-GCM', 32, 12), | |
| 32 | + test('ChaCha20-Poly1305', 32, 12, 'raw-secret'), | ||
| 32 | 33 | ]; | |
| 33 | 34 | ||
| 34 | 35 | if (hasOpenSSL(3)) { | |
| 35 | 36 | tests.push(test('AES-OCB', 32, 12, 'raw-secret')); | |
| 36 | 37 | } | |
| 37 | 38 | ||
| 38 | - if (!process.features.openssl_is_boringssl) { | ||
| 39 | - tests.push(test('ChaCha20-Poly1305', 32, 12, 'raw-secret')); | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | 39 | Promise.all(tests).then(common.mustCall()); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -45,6 +45,9 @@ function assertSameSet(actual, expected, msg) { | |||
| 45 | 45 | { algorithm: { name: 'AES-KW', length: 128 }, | |
| 46 | 46 | usages: ['wrapKey', 'unwrapKey', 'wrapKey', 'unwrapKey'], | |
| 47 | 47 | expected: ['wrapKey', 'unwrapKey'] }, | |
| 48 | + { algorithm: { name: 'ChaCha20-Poly1305' }, | ||
| 49 | + usages: ['wrapKey', 'decrypt', 'encrypt', 'unwrapKey', 'wrapKey', 'encrypt'], | ||
| 50 | + expected: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'] }, | ||
| 48 | 51 | ]; | |
| 49 | 52 | ||
| 50 | 53 | if (hasOpenSSL(3)) { | |
@@ -62,16 +65,6 @@ function assertSameSet(actual, expected, msg) { | |||
| 62 | 65 | common.printSkipMessage('AES-OCB and KMAC require OpenSSL >= 3'); | |
| 63 | 66 | } | |
| 64 | 67 | ||
| 65 | - if (!process.features.openssl_is_boringssl) { | ||
| 66 | - symmetric.push({ | ||
| 67 | - algorithm: { name: 'ChaCha20-Poly1305' }, | ||
| 68 | - usages: ['wrapKey', 'decrypt', 'encrypt', 'unwrapKey', 'wrapKey', 'encrypt'], | ||
| 69 | - expected: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], | ||
| 70 | - }); | ||
| 71 | - } else { | ||
| 72 | - common.printSkipMessage('ChaCha20-Poly1305 is not supported in BoringSSL'); | ||
| 73 | - } | ||
| 74 | - | ||
| 75 | 68 | for (const { algorithm, usages, expected } of symmetric) { | |
| 76 | 69 | tests.push((async () => { | |
| 77 | 70 | const key = await subtle.generateKey(algorithm, true, usages); | |
@@ -328,20 +321,16 @@ function assertSameSet(actual, expected, msg) { | |||
| 328 | 321 | })()); | |
| 329 | 322 | ||
| 330 | 323 | // ChaCha20-Poly1305 raw-secret import. | |
| 331 | - if (!process.features.openssl_is_boringssl) { | ||
| 332 | - tests.push((async () => { | ||
| 333 | - const key = await subtle.importKey( | ||
| 334 | - 'raw-secret', | ||
| 335 | - new Uint8Array(32), | ||
| 336 | - { name: 'ChaCha20-Poly1305' }, | ||
| 337 | - true, | ||
| 338 | - ['decrypt', 'encrypt', 'decrypt', 'encrypt']); | ||
| 339 | - assertSameSet(key.usages, ['encrypt', 'decrypt']); | ||
| 340 | - assert.strictEqual(key.usages.length, 2); | ||
| 341 | - })()); | ||
| 342 | - } else { | ||
| 343 | - common.printSkipMessage('ChaCha20-Poly1305 is not supported in BoringSSL'); | ||
| 344 | - } | ||
| 324 | + tests.push((async () => { | ||
| 325 | + const key = await subtle.importKey( | ||
| 326 | + 'raw-secret', | ||
| 327 | + new Uint8Array(32), | ||
| 328 | + { name: 'ChaCha20-Poly1305' }, | ||
| 329 | + true, | ||
| 330 | + ['decrypt', 'encrypt', 'decrypt', 'encrypt']); | ||
| 331 | + assertSameSet(key.usages, ['encrypt', 'decrypt']); | ||
| 332 | + assert.strictEqual(key.usages.length, 2); | ||
| 333 | + })()); | ||
| 345 | 334 | ||
| 346 | 335 | // AES-OCB raw-secret import. | |
| 347 | 336 | if (hasOpenSSL(3)) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,9 +5,6 @@ const common = require('../common'); | |||
| 5 | 5 | if (!common.hasCrypto) | |
| 6 | 6 | common.skip('missing crypto'); | |
| 7 | 7 | ||
| 8 | - if (process.features.openssl_is_boringssl) | ||
| 9 | - common.skip('Skipping unsupported ChaCha20-Poly1305 test case'); | ||
| 10 | - | ||
| 11 | 8 | const assert = require('assert'); | |
| 12 | 9 | const { subtle } = globalThis.crypto; | |
| 13 | 10 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -142,7 +142,16 @@ const vectors = { | |||
| 142 | 142 | 'wrapKey', | |
| 143 | 143 | 'unwrapKey', | |
| 144 | 144 | ], | |
| 145 | - } | ||
| 145 | + }, | ||
| 146 | + 'ChaCha20-Poly1305': { | ||
| 147 | + result: 'CryptoKey', | ||
| 148 | + usages: [ | ||
| 149 | + 'encrypt', | ||
| 150 | + 'decrypt', | ||
| 151 | + 'wrapKey', | ||
| 152 | + 'unwrapKey', | ||
| 153 | + ], | ||
| 154 | + }, | ||
| 146 | 155 | }; | |
| 147 | 156 | ||
| 148 | 157 | if (!process.features.openssl_is_boringssl) { | |
@@ -160,15 +169,6 @@ if (!process.features.openssl_is_boringssl) { | |||
| 160 | 169 | 'deriveBits', | |
| 161 | 170 | ], | |
| 162 | 171 | }; | |
| 163 | - vectors['ChaCha20-Poly1305'] = { | ||
| 164 | - result: 'CryptoKey', | ||
| 165 | - usages: [ | ||
| 166 | - 'encrypt', | ||
| 167 | - 'decrypt', | ||
| 168 | - 'wrapKey', | ||
| 169 | - 'unwrapKey', | ||
| 170 | - ], | ||
| 171 | - }; | ||
| 172 | 172 | } else { | |
| 173 | 173 | common.printSkipMessage('Skipping unsupported test cases'); | |
| 174 | 174 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -44,21 +44,15 @@ const kWrappingData = { | |||
| 44 | 44 | wrap: { }, | |
| 45 | 45 | pair: false | |
| 46 | 46 | }, | |
| 47 | - }; | ||
| 48 | - | ||
| 49 | - | ||
| 50 | - if (!process.features.openssl_is_boringssl) { | ||
| 51 | - kWrappingData['ChaCha20-Poly1305'] = { | ||
| 47 | + 'ChaCha20-Poly1305': { | ||
| 52 | 48 | wrap: { | |
| 53 | 49 | iv: new Uint8Array(12), | |
| 54 | 50 | additionalData: new Uint8Array(16), | |
| 55 | 51 | tagLength: 128 | |
| 56 | 52 | }, | |
| 57 | 53 | pair: false | |
| 58 | - }; | ||
| 59 | - } else { | ||
| 60 | - common.printSkipMessage('Skipping unsupported ChaCha20-Poly1305 test case'); | ||
| 61 | - } | ||
| 54 | + } | ||
| 55 | + }; | ||
| 62 | 56 | ||
| 63 | 57 | if (hasOpenSSL(3)) { | |
| 64 | 58 | kWrappingData['AES-OCB'] = { | |
@@ -197,19 +191,14 @@ async function generateKeysToWrap() { | |||
| 197 | 191 | usages: ['wrapKey', 'unwrapKey'], | |
| 198 | 192 | pair: false, | |
| 199 | 193 | }, | |
| 200 | - ]; | ||
| 201 | - | ||
| 202 | - if (!process.features.openssl_is_boringssl) { | ||
| 203 | - parameters.push({ | ||
| 194 | + { | ||
| 204 | 195 | algorithm: { | |
| 205 | 196 | name: 'ChaCha20-Poly1305' | |
| 206 | 197 | }, | |
| 207 | 198 | usages: ['encrypt', 'decrypt'], | |
| 208 | 199 | pair: false, | |
| 209 | - }); | ||
| 210 | - } else { | ||
| 211 | - common.printSkipMessage('Skipping unsupported ChaCha20-Poly1305 test case'); | ||
| 212 | - } | ||
| 200 | + }, | ||
| 201 | + ]; | ||
| 213 | 202 | ||
| 214 | 203 | if (hasOpenSSL(3, 5)) { | |
| 215 | 204 | for (const name of ['ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87']) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -67,23 +67,16 @@ if (process.features.openssl_is_boringssl) { | |||
| 67 | 67 | 'derive_bits_keys/cfrg_curves_keys_curve448.tentative.https.any.js', | |
| 68 | 68 | 'digest/cshake.tentative.https.any.js', | |
| 69 | 69 | 'digest/sha3.tentative.https.any.js', | |
| 70 | - 'encrypt_decrypt/chacha20_poly1305.tentative.https.any.js', | ||
| 71 | 70 | 'generateKey/failures_Ed448.tentative.https.any.js', | |
| 72 | 71 | 'generateKey/failures_X448.tentative.https.any.js', | |
| 73 | - 'generateKey/failures_chacha20_poly1305.tentative.https.any.js', | ||
| 74 | 72 | 'generateKey/successes_Ed448.tentative.https.any.js', | |
| 75 | 73 | 'generateKey/successes_X448.tentative.https.any.js', | |
| 76 | - 'generateKey/successes_chacha20_poly1305.tentative.https.any.js', | ||
| 77 | - 'import_export/ChaCha20-Poly1305_importKey.tentative.https.any.js', | ||
| 78 | 74 | 'import_export/okp_importKey_Ed448.tentative.https.any.js', | |
| 79 | 75 | 'import_export/okp_importKey_failures_Ed448.tentative.https.any.js', | |
| 80 | 76 | 'import_export/okp_importKey_failures_X448.tentative.https.any.js', | |
| 81 | 77 | 'import_export/okp_importKey_X448.tentative.https.any.js', | |
| 82 | 78 | 'sign_verify/eddsa_curve448.tentative.https.any.js'); | |
| 83 | 79 | ||
| 84 | - skipSubtests( | ||
| 85 | - ['supports-modern.tentative.https.any.js', /ChaCha20-Poly1305/], | ||
| 86 | - ['supports-modern.tentative.https.any.js', /^supports returns true for algorithm objects with valid parameters$/]); | ||
| 87 | 80 | } | |
| 88 | 81 | ||
| 89 | 82 | function assertNoOverlap(fileSkips, subtestSkips) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments