GeezerVison is showing github.com — crypto: add AES-OCB Web Cryptography algorithm · nodejs/node@152c5ef
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: deps/ncrypto/ncrypto.cc +8Lines changed: 8 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -3041,6 +3041,9 @@ const Cipher Cipher::AES_256_GCM = Cipher::FromNid(NID_aes_256_gcm); | 3041 | 3041 | const Cipher Cipher::AES_128_KW = Cipher::FromNid(NID_id_aes128_wrap); | 3042 | 3042 | const Cipher Cipher::AES_192_KW = Cipher::FromNid(NID_id_aes192_wrap); | 3043 | 3043 | const Cipher Cipher::AES_256_KW = Cipher::FromNid(NID_id_aes256_wrap); | | 3044 | +const Cipher Cipher::AES_128_OCB = Cipher::FromNid(NID_aes_128_ocb); | | 3045 | +const Cipher Cipher::AES_192_OCB = Cipher::FromNid(NID_aes_192_ocb); | | 3046 | +const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb); | 3044 | 3047 | const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305); | 3045 | 3048 |
| 3046 | 3049 | bool Cipher::isGcmMode() const { | @@ -3243,6 +3246,11 @@ bool CipherCtxPointer::isGcmMode() const { | 3243 | 3246 | return getMode() == EVP_CIPH_GCM_MODE; | 3244 | 3247 | } | 3245 | 3248 |
| | 3249 | +bool CipherCtxPointer::isOcbMode() const { | | 3250 | + if (!ctx_) return false; | | 3251 | + return getMode() == EVP_CIPH_OCB_MODE; | | 3252 | +} | | 3253 | + | 3246 | 3254 | bool CipherCtxPointer::isCcmMode() const { | 3247 | 3255 | if (!ctx_) return false; | 3248 | 3256 | return getMode() == EVP_CIPH_CCM_MODE; | |
Collapse file Copy file name to clipboardExpand all lines: deps/ncrypto/ncrypto.h +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -373,6 +373,9 @@ class Cipher final { | 373 | 373 | static const Cipher AES_128_KW; | 374 | 374 | static const Cipher AES_192_KW; | 375 | 375 | static const Cipher AES_256_KW; | | 376 | + static const Cipher AES_128_OCB; | | 377 | + static const Cipher AES_192_OCB; | | 378 | + static const Cipher AES_256_OCB; | 376 | 379 | static const Cipher CHACHA20_POLY1305; | 377 | 380 |
| 378 | 381 | struct CipherParams { | @@ -738,6 +741,7 @@ class CipherCtxPointer final { | 738 | 741 | int getNid() const; | 739 | 742 |
| 740 | 743 | bool isGcmMode() const; | | 744 | + bool isOcbMode() const; | 741 | 745 | bool isCcmMode() const; | 742 | 746 | bool isWrapMode() const; | 743 | 747 | bool isChaCha20Poly1305() const; | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/webcrypto.md +31-3Lines changed: 31 additions & 3 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 |
| 3 | 3 | <!-- YAML | 4 | 4 | changes: | | 5 | + - version: REPLACEME | | 6 | + pr-url: https://github.com/nodejs/node/pull/59539 | | 7 | + description: AES-OCB algorithm is now supported. | 5 | 8 | - version: REPLACEME | 6 | 9 | pr-url: https://github.com/nodejs/node/pull/59569 | 7 | 10 | description: ML-KEM algorithms are now supported. | @@ -103,6 +106,7 @@ WICG proposal: | 103 | 106 |
| 104 | 107 | Algorithms: | 105 | 108 |
| | 109 | +* `'AES-OCB'`[^openssl30] | 106 | 110 | * `'ChaCha20-Poly1305'` | 107 | 111 | * `'cSHAKE128'` | 108 | 112 | * `'cSHAKE256'` | @@ -500,6 +504,7 @@ implementation and the APIs supported for each: | 500 | 504 | | `'AES-CTR'` | ✔ | ✔ | ✔ | | | 501 | 505 | | `'AES-GCM'` | ✔ | ✔ | ✔ | | | 502 | 506 | | `'AES-KW'` | ✔ | ✔ | ✔ | | | | 507 | +| `'AES-OCB'` | ✔ | ✔ | ✔ | | | 503 | 508 | | `'ChaCha20-Poly1305'`[^modern-algos] | ✔ | ✔ | ✔ | | | 504 | 509 | | `'ECDH'` | ✔ | ✔ | ✔ | ✔ | | 505 | 510 | | `'ECDSA'` | ✔ | ✔ | ✔ | ✔ | | @@ -538,6 +543,7 @@ implementation and the APIs supported for each: | 538 | 543 | | `'AES-CTR'` | ✔ | | | ✔ | | | | 539 | 544 | | `'AES-GCM'` | ✔ | | | ✔ | | | | 540 | 545 | | `'AES-KW'` | | | | ✔ | | | | | 546 | +| `'AES-OCB'` | ✔ | | | ✔ | | | | 541 | 547 | | `'ChaCha20-Poly1305'`[^modern-algos] | ✔ | | | ✔ | | | | 542 | 548 | | `'cSHAKE128'`[^modern-algos] | | | | | | ✔ | | 543 | 549 | | `'cSHAKE256'`[^modern-algos] | | | | | | ✔ | | @@ -706,6 +712,7 @@ Valid key usages depend on the key algorithm (identified by | 706 | 712 | | `'AES-CTR'` | ✔ | | | ✔ | | | 707 | 713 | | `'AES-GCM'` | ✔ | | | ✔ | | | 708 | 714 | | `'AES-KW'` | | | | ✔ | | | | 715 | +| `'AES-OCB'` | ✔ | | | ✔ | | | 709 | 716 | | `'ChaCha20-Poly1305'`[^modern-algos] | ✔ | | | ✔ | | | 710 | 717 | | `'ECDH'` | | | ✔ | | | | 711 | 718 | | `'ECDSA'` | | ✔ | | | | | @@ -824,6 +831,9 @@ The algorithms currently supported include: | 824 | 831 | <!-- YAML | 825 | 832 | added: v15.0.0 | 826 | 833 | changes: | | 834 | + - version: REPLACEME | | 835 | + pr-url: https://github.com/nodejs/node/pull/59539 | | 836 | + description: AES-OCB algorithm is now supported. | 827 | 837 | - version: REPLACEME | 828 | 838 | pr-url: https://github.com/nodejs/node/pull/59365 | 829 | 839 | description: ChaCha20-Poly1305 algorithm is now supported. | @@ -844,6 +854,7 @@ The algorithms currently supported include: | 844 | 854 | * `'AES-CBC'` | 845 | 855 | * `'AES-CTR'` | 846 | 856 | * `'AES-GCM'` | | 857 | +* `'AES-OCB'`[^modern-algos] | 847 | 858 | * `'ChaCha20-Poly1305'`[^modern-algos] | 848 | 859 | * `'RSA-OAEP'` | 849 | 860 |
| @@ -1014,6 +1025,9 @@ The algorithms currently supported include: | 1014 | 1025 | <!-- YAML | 1015 | 1026 | added: v15.0.0 | 1016 | 1027 | changes: | | 1028 | + - version: REPLACEME | | 1029 | + pr-url: https://github.com/nodejs/node/pull/59539 | | 1030 | + description: AES-OCB algorithm is now supported. | 1017 | 1031 | - version: REPLACEME | 1018 | 1032 | pr-url: https://github.com/nodejs/node/pull/59365 | 1019 | 1033 | description: ChaCha20-Poly1305 algorithm is now supported. | @@ -1034,6 +1048,7 @@ The algorithms currently supported include: | 1034 | 1048 | * `'AES-CBC'` | 1035 | 1049 | * `'AES-CTR'` | 1036 | 1050 | * `'AES-GCM'` | | 1051 | +* `'AES-OCB'`[^modern-algos] | 1037 | 1052 | * `'ChaCha20-Poly1305'`[^modern-algos] | 1038 | 1053 | * `'RSA-OAEP'` | 1039 | 1054 |
| @@ -1085,6 +1100,7 @@ specification. | 1085 | 1100 | | `'AES-CTR'` | | | ✔ | ✔ | ✔ | | | | 1086 | 1101 | | `'AES-GCM'` | | | ✔ | ✔ | ✔ | | | | 1087 | 1102 | | `'AES-KW'` | | | ✔ | ✔ | ✔ | | | | | 1103 | +| `'AES-OCB'`[^modern-algos] | | | ✔ | | ✔ | | | | 1088 | 1104 | | `'ChaCha20-Poly1305'`[^modern-algos] | | | ✔ | | ✔ | | | | 1089 | 1105 | | `'ECDH'` | ✔ | ✔ | ✔ | ✔ | | ✔ | | | 1090 | 1106 | | `'ECDSA'` | ✔ | ✔ | ✔ | ✔ | | ✔ | | | @@ -1170,6 +1186,7 @@ The {CryptoKey} (secret key) generating algorithms supported include: | 1170 | 1186 | * `'AES-CTR'` | 1171 | 1187 | * `'AES-GCM'` | 1172 | 1188 | * `'AES-KW'` | | 1189 | +* `'AES-OCB'`[^modern-algos] | 1173 | 1190 | * `'ChaCha20-Poly1305'`[^modern-algos] | 1174 | 1191 | * `'HMAC'` | 1175 | 1192 |
| @@ -1227,6 +1244,7 @@ The algorithms currently supported include: | 1227 | 1244 | | `'AES-CTR'` | | | ✔ | ✔ | ✔ | | | | 1228 | 1245 | | `'AES-GCM'` | | | ✔ | ✔ | ✔ | | | | 1229 | 1246 | | `'AES-KW'` | | | ✔ | ✔ | ✔ | | | | | 1247 | +| `'AES-OCB'`[^modern-algos] | | | ✔ | | ✔ | | | | 1230 | 1248 | | `'ChaCha20-Poly1305'`[^modern-algos] | | | ✔ | | ✔ | | | | 1231 | 1249 | | `'ECDH'` | ✔ | ✔ | ✔ | ✔ | | ✔ | | | 1232 | 1250 | | `'ECDSA'` | ✔ | ✔ | ✔ | ✔ | | ✔ | | | @@ -1293,6 +1311,9 @@ The algorithms currently supported include: | 1293 | 1311 | <!-- YAML | 1294 | 1312 | added: v15.0.0 | 1295 | 1313 | changes: | | 1314 | + - version: REPLACEME | | 1315 | + pr-url: https://github.com/nodejs/node/pull/59539 | | 1316 | + description: AES-OCB algorithm is now supported. | 1296 | 1317 | - version: REPLACEME | 1297 | 1318 | pr-url: https://github.com/nodejs/node/pull/59365 | 1298 | 1319 | description: ChaCha20-Poly1305 algorithm is now supported. | @@ -1329,6 +1350,7 @@ The wrapping algorithms currently supported include: | 1329 | 1350 | * `'AES-CTR'` | 1330 | 1351 | * `'AES-GCM'` | 1331 | 1352 | * `'AES-KW'` | | 1353 | +* `'AES-OCB'`[^modern-algos] | 1332 | 1354 | * `'ChaCha20-Poly1305'`[^modern-algos] | 1333 | 1355 | * `'RSA-OAEP'` | 1334 | 1356 |
| @@ -1338,6 +1360,7 @@ The unwrapped key algorithms supported include: | 1338 | 1360 | * `'AES-CTR'` | 1339 | 1361 | * `'AES-GCM'` | 1340 | 1362 | * `'AES-KW'` | | 1363 | +* `'AES-OCB'`[^modern-algos] | 1341 | 1364 | * `'ChaCha20-Poly1305'`[^modern-algos] | 1342 | 1365 | * `'ECDH'` | 1343 | 1366 | * `'ECDSA'` | @@ -1403,6 +1426,9 @@ The algorithms currently supported include: | 1403 | 1426 | <!-- YAML | 1404 | 1427 | added: v15.0.0 | 1405 | 1428 | changes: | | 1429 | + - version: REPLACEME | | 1430 | + pr-url: https://github.com/nodejs/node/pull/59539 | | 1431 | + description: AES-OCB algorithm is now supported. | 1406 | 1432 | - version: REPLACEME | 1407 | 1433 | pr-url: https://github.com/nodejs/node/pull/59365 | 1408 | 1434 | description: ChaCha20-Poly1305 algorithm is now supported. | @@ -1435,6 +1461,7 @@ The wrapping algorithms currently supported include: | 1435 | 1461 | * `'AES-CTR'` | 1436 | 1462 | * `'AES-GCM'` | 1437 | 1463 | * `'AES-KW'` | | 1464 | +* `'AES-OCB'`[^modern-algos] | 1438 | 1465 | * `'ChaCha20-Poly1305'`[^modern-algos] | 1439 | 1466 | * `'RSA-OAEP'` | 1440 | 1467 |
| @@ -1492,7 +1519,7 @@ given key. | 1492 | 1519 | added: v15.0.0 | 1493 | 1520 | --> | 1494 | 1521 |
| 1495 | | -* Type: {string} Must be `'AES-GCM'` or `'ChaCha20-Poly1305'`. | | 1522 | +* Type: {string} Must be `'AES-GCM'`, `'AES-OCB'`, or `'ChaCha20-Poly1305'`. | 1496 | 1523 |
| 1497 | 1524 | #### `aeadParams.tagLength` | 1498 | 1525 |
| @@ -1514,8 +1541,7 @@ added: v15.0.0 | 1514 | 1541 | added: v15.0.0 | 1515 | 1542 | --> | 1516 | 1543 |
| 1517 | | -* Type: {string} Must be one of `'AES-CBC'`, `'AES-CTR'`, `'AES-GCM'`, or | 1518 | | - `'AES-KW'` | | 1544 | +* Type: {string} Must be one of `'AES-CBC'`, `'AES-CTR'`, `'AES-GCM'`, `'AES-OCB'`, or `'AES-KW'` | 1519 | 1545 |
| 1520 | 1546 | #### `aesDerivedKeyParams.length` | 1521 | 1547 |
| @@ -2391,6 +2417,8 @@ The length (in bytes) of the random salt to use. | 2391 | 2417 |
| 2392 | 2418 | [^modern-algos]: See [Modern Algorithms in the Web Cryptography API][] | 2393 | 2419 |
| | 2420 | +[^openssl30]: Requires OpenSSL >= 3.0 | | 2421 | +
| 2394 | 2422 | [^openssl35]: Requires OpenSSL >= 3.5 | 2395 | 2423 |
| 2396 | 2424 | [JSON Web Key]: https://tools.ietf.org/html/rfc7517 | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/aes.js +53Lines changed: 53 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -18,14 +18,17 @@ const { | 18 | 18 | kKeyVariantAES_CBC_128, | 19 | 19 | kKeyVariantAES_GCM_128, | 20 | 20 | kKeyVariantAES_KW_128, | | 21 | + kKeyVariantAES_OCB_128, | 21 | 22 | kKeyVariantAES_CTR_192, | 22 | 23 | kKeyVariantAES_CBC_192, | 23 | 24 | kKeyVariantAES_GCM_192, | 24 | 25 | kKeyVariantAES_KW_192, | | 26 | + kKeyVariantAES_OCB_192, | 25 | 27 | kKeyVariantAES_CTR_256, | 26 | 28 | kKeyVariantAES_CBC_256, | 27 | 29 | kKeyVariantAES_GCM_256, | 28 | 30 | kKeyVariantAES_KW_256, | | 31 | + kKeyVariantAES_OCB_256, | 29 | 32 | kWebCryptoCipherDecrypt, | 30 | 33 | kWebCryptoCipherEncrypt, | 31 | 34 | } = internalBinding('crypto'); | @@ -62,6 +65,7 @@ function getAlgorithmName(name, length) { | 62 | 65 | case 'AES-CTR': return `A${length}CTR`; | 63 | 66 | case 'AES-GCM': return `A${length}GCM`; | 64 | 67 | case 'AES-KW': return `A${length}KW`; | | 68 | + case 'AES-OCB': return `A${length}OCB`; | 65 | 69 | } | 66 | 70 | } | 67 | 71 |
| @@ -100,6 +104,13 @@ function getVariant(name, length) { | 100 | 104 | case 256: return kKeyVariantAES_KW_256; | 101 | 105 | } | 102 | 106 | break; | | 107 | + case 'AES-OCB': | | 108 | + switch (length) { | | 109 | + case 128: return kKeyVariantAES_OCB_128; | | 110 | + case 192: return kKeyVariantAES_OCB_192; | | 111 | + case 256: return kKeyVariantAES_OCB_256; | | 112 | + } | | 113 | + break; | 103 | 114 | } | 104 | 115 | } | 105 | 116 |
| @@ -173,11 +184,49 @@ function asyncAesGcmCipher(mode, key, data, algorithm) { | 173 | 184 | algorithm.additionalData)); | 174 | 185 | } | 175 | 186 |
| | 187 | +function asyncAesOcbCipher(mode, key, data, algorithm) { | | 188 | + const { tagLength = 128 } = algorithm; | | 189 | + | | 190 | + const tagByteLength = tagLength / 8; | | 191 | + let tag; | | 192 | + switch (mode) { | | 193 | + case kWebCryptoCipherDecrypt: { | | 194 | + const slice = ArrayBufferIsView(data) ? | | 195 | + TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice; | | 196 | + tag = slice(data, -tagByteLength); | | 197 | + | | 198 | + // Similar to GCM, OCB requires the tag to be present for decryption | | 199 | + if (tagByteLength > tag.byteLength) { | | 200 | + return PromiseReject(lazyDOMException( | | 201 | + 'The provided data is too small.', | | 202 | + 'OperationError')); | | 203 | + } | | 204 | + | | 205 | + data = slice(data, 0, -tagByteLength); | | 206 | + break; | | 207 | + } | | 208 | + case kWebCryptoCipherEncrypt: | | 209 | + tag = tagByteLength; | | 210 | + break; | | 211 | + } | | 212 | + | | 213 | + return jobPromise(() => new AESCipherJob( | | 214 | + kCryptoJobAsync, | | 215 | + mode, | | 216 | + key[kKeyObject][kHandle], | | 217 | + data, | | 218 | + getVariant('AES-OCB', key.algorithm.length), | | 219 | + algorithm.iv, | | 220 | + tag, | | 221 | + algorithm.additionalData)); | | 222 | +} | | 223 | + | 176 | 224 | function aesCipher(mode, key, data, algorithm) { | 177 | 225 | switch (algorithm.name) { | 178 | 226 | case 'AES-CTR': return asyncAesCtrCipher(mode, key, data, algorithm); | 179 | 227 | case 'AES-CBC': return asyncAesCbcCipher(mode, key, data, algorithm); | 180 | 228 | case 'AES-GCM': return asyncAesGcmCipher(mode, key, data, algorithm); | | 229 | + case 'AES-OCB': return asyncAesOcbCipher(mode, key, data, algorithm); | 181 | 230 | case 'AES-KW': return asyncAesKwCipher(mode, key, data); | 182 | 231 | } | 183 | 232 | } | @@ -236,7 +285,11 @@ function aesImportKey( | 236 | 285 | keyObject = keyData; | 237 | 286 | break; | 238 | 287 | } | | 288 | + case 'raw-secret': | 239 | 289 | case 'raw': { | | 290 | + if (format === 'raw' && name === 'AES-OCB') { | | 291 | + return undefined; | | 292 | + } | 240 | 293 | validateKeyLength(keyData.byteLength * 8); | 241 | 294 | keyObject = createSecretKey(keyData); | 242 | 295 | break; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/keys.js +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -199,6 +199,8 @@ const { | 199 | 199 | case 'AES-GCM': | 200 | 200 | // Fall through | 201 | 201 | case 'AES-KW': | | 202 | + // Fall through | | 203 | + case 'AES-OCB': | 202 | 204 | result = require('internal/crypto/aes') | 203 | 205 | .aesImportKey(algorithm, 'KeyObject', this, extractable, keyUsages); | 204 | 206 | break; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/util.js +11Lines changed: 11 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -39,6 +39,7 @@ const { | 39 | 39 | EVP_PKEY_ML_KEM_512, | 40 | 40 | EVP_PKEY_ML_KEM_768, | 41 | 41 | EVP_PKEY_ML_KEM_1024, | | 42 | + kKeyVariantAES_OCB_128: hasAesOcbMode, | 42 | 43 | } = internalBinding('crypto'); | 43 | 44 |
| 44 | 45 | const { getOptionValue } = require('internal/options'); | @@ -208,6 +209,14 @@ const kAlgorithmDefinitions = { | 208 | 209 | 'wrapKey': null, | 209 | 210 | 'unwrapKey': null, | 210 | 211 | }, | | 212 | + 'AES-OCB': { | | 213 | + 'generateKey': 'AesKeyGenParams', | | 214 | + 'exportKey': null, | | 215 | + 'importKey': null, | | 216 | + 'encrypt': 'AeadParams', | | 217 | + 'decrypt': 'AeadParams', | | 218 | + 'get key length': 'AesDerivedKeyParams', | | 219 | + }, | 211 | 220 | 'ChaCha20-Poly1305': { | 212 | 221 | 'generateKey': null, | 213 | 222 | 'exportKey': null, | @@ -350,6 +359,7 @@ const kAlgorithmDefinitions = { | 350 | 359 | // Conditionally supported algorithms | 351 | 360 | const conditionalAlgorithms = { | 352 | 361 | 'AES-KW': !process.features.openssl_is_boringssl, | | 362 | + 'AES-OCB': !!hasAesOcbMode, | 353 | 363 | 'ChaCha20-Poly1305': !process.features.openssl_is_boringssl || | 354 | 364 | ArrayPrototypeIncludes(getCiphers(), 'chacha20-poly1305'), | 355 | 365 | 'cSHAKE128': !process.features.openssl_is_boringssl || | @@ -374,6 +384,7 @@ const conditionalAlgorithms = { | 374 | 384 |
| 375 | 385 | // Experimental algorithms | 376 | 386 | const experimentalAlgorithms = [ | | 387 | + 'AES-OCB', | 377 | 388 | 'ChaCha20-Poly1305', | 378 | 389 | 'cSHAKE128', | 379 | 390 | 'cSHAKE256', | |
|