diff --git a/internal/compatibility/generated/node-v24-backlog.json b/internal/compatibility/generated/node-v24-backlog.json index e03c17638..9020d31eb 100644 --- a/internal/compatibility/generated/node-v24-backlog.json +++ b/internal/compatibility/generated/node-v24-backlog.json @@ -6564,6 +6564,12 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", + "packages/runtime/test/cipher.test.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -6601,6 +6607,12 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", + "packages/runtime/test/cipher.test.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8145,6 +8157,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8182,6 +8199,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8219,6 +8241,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8256,6 +8283,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8293,6 +8325,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8330,6 +8367,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8367,6 +8409,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8404,6 +8451,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8441,6 +8493,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8478,6 +8535,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8515,6 +8577,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } @@ -8552,6 +8619,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] } diff --git a/internal/compatibility/generated/node-v24-internal.json b/internal/compatibility/generated/node-v24-internal.json index 64f3b8e4c..4fbe40422 100644 --- a/internal/compatibility/generated/node-v24-internal.json +++ b/internal/compatibility/generated/node-v24-internal.json @@ -19821,6 +19821,7 @@ "status": "partial", "evidence": "derived:descendants", "tests": [ + "packages/runtime/test/cipher.test.ts", "tests/corpus/1358-crypto-random.ts", "tests/corpus/1534-crypto-hash-chain.ts", "tests/corpus/2556-crypto-introspection.ts", @@ -19835,6 +19836,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/corpus/5435-crypto-hash-algorithms.ts", "tests/corpus/5436-crypto-hash-names.js", "tests/corpus/5437-crypto-hmac-algorithms.ts", @@ -20235,6 +20241,12 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", + "packages/runtime/test/cipher.test.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -20271,6 +20283,12 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", + "packages/runtime/test/cipher.test.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22246,6 +22264,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22282,6 +22305,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22318,6 +22346,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22354,6 +22387,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22390,6 +22428,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22426,6 +22469,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22462,6 +22510,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22498,6 +22551,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22534,6 +22592,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22570,6 +22633,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22606,6 +22674,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, @@ -22642,6 +22715,11 @@ "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", + "tests/corpus/5355-cipher-bulk.ts", + "tests/corpus/5356-cipher-counters.ts", + "tests/corpus/5357-cipher-chacha-bulk.ts", + "tests/corpus/5358-cipher-cbc-bulk.ts", + "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts" ] }, diff --git a/internal/compatibility/static-support.json b/internal/compatibility/static-support.json index 63c032c73..e56601617 100644 --- a/internal/compatibility/static-support.json +++ b/internal/compatibility/static-support.json @@ -41,8 +41,8 @@ "node-builtin.child_process": ["tests/corpus/1361-spawn-events.ts", "tests/corpus/1565-spawn-pipe-streams.ts", "tests/corpus/2911-execfile-callback.ts", "tests/corpus/2939-child-shell-text.ts", "tests/corpus/2946-child-fork-ipc/main.ts", "tests/corpus/3127-spawn-runtime-options.ts", "tests/corpus/3130-child-generic-streams.ts", "tests/corpus/3131-child-rest-listeners.js", "tests/corpus/3132-child-generic-stream-completion.ts"], "node-builtin.cluster": ["tests/corpus/957-builtins-namespace.ts"], "node-builtin.console": ["tests/corpus/console-imports.cjs", "tests/corpus/2440-console-inspect-args.ts", "tests/corpus/console-native-value.js", "tests/harness/npm-static.test.ts"], - "node-builtin.crypto.createCipheriv": ["tests/corpus/5250-cipher-aes-gcm.ts", "tests/corpus/5251-cipher-aes-cbc.ts", "tests/corpus/5252-cipher-aes-ctr.ts", "tests/corpus/5253-cipher-chacha20-poly1305.ts", "tests/corpus/5254-cipher-errors.js", "tests/corpus/5255-cipher-encodings.cjs", "tests/corpus/5256-cipher-deprecation.cjs", "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", "tests/fixtures/node-types/cipher.ts"], - "node-builtin.crypto.createDecipheriv": ["tests/corpus/5250-cipher-aes-gcm.ts", "tests/corpus/5251-cipher-aes-cbc.ts", "tests/corpus/5252-cipher-aes-ctr.ts", "tests/corpus/5253-cipher-chacha20-poly1305.ts", "tests/corpus/5254-cipher-errors.js", "tests/corpus/5255-cipher-encodings.cjs", "tests/corpus/5256-cipher-deprecation.cjs", "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", "tests/fixtures/node-types/cipher.ts"], + "node-builtin.crypto.createCipheriv": ["tests/corpus/5250-cipher-aes-gcm.ts", "tests/corpus/5251-cipher-aes-cbc.ts", "tests/corpus/5252-cipher-aes-ctr.ts", "tests/corpus/5253-cipher-chacha20-poly1305.ts", "tests/corpus/5254-cipher-errors.js", "tests/corpus/5255-cipher-encodings.cjs", "tests/corpus/5256-cipher-deprecation.cjs", "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", "tests/corpus/5355-cipher-bulk.ts", "tests/corpus/5356-cipher-counters.ts", "tests/corpus/5357-cipher-chacha-bulk.ts", "tests/corpus/5358-cipher-cbc-bulk.ts", "tests/corpus/5359-cipher-tamper.ts", "packages/runtime/test/cipher.test.ts", "tests/fixtures/node-types/cipher.ts"], + "node-builtin.crypto.createDecipheriv": ["tests/corpus/5250-cipher-aes-gcm.ts", "tests/corpus/5251-cipher-aes-cbc.ts", "tests/corpus/5252-cipher-aes-ctr.ts", "tests/corpus/5253-cipher-chacha20-poly1305.ts", "tests/corpus/5254-cipher-errors.js", "tests/corpus/5255-cipher-encodings.cjs", "tests/corpus/5256-cipher-deprecation.cjs", "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", "tests/corpus/5355-cipher-bulk.ts", "tests/corpus/5356-cipher-counters.ts", "tests/corpus/5357-cipher-chacha-bulk.ts", "tests/corpus/5358-cipher-cbc-bulk.ts", "tests/corpus/5359-cipher-tamper.ts", "packages/runtime/test/cipher.test.ts", "tests/fixtures/node-types/cipher.ts"], "node-builtin.crypto": ["tests/corpus/1358-crypto-random.ts", "tests/corpus/1534-crypto-hash-chain.ts", "tests/corpus/2556-crypto-introspection.ts", "tests/corpus/2890-crypto-static-utility.ts", "tests/harness/npm-static.test.ts", "tests/corpus/node24-crypto-sha2.ts", "tests/corpus/node24-crypto-kdf.ts", "tests/corpus/node24-crypto-kdf-errors.ts", "tests/corpus/node24-crypto-kdf-options.ts"], "node-builtin.dgram": ["tests/corpus/2597-dgram-send-ladders.cjs"], "node-builtin.diagnostics_channel": ["tests/corpus/2214-dc-bind-store.cjs"], @@ -367,7 +367,7 @@ { "symbols": ["assert.partialDeepStrictEqual"], "status": "partial", "evidence": ["tests/corpus/5517-assert-partial-deep-equal.js", "tests/corpus/5518-assert-partial-deep-typed.ts", "tests/corpus/5519-assert-partial-deep-typed-edges.ts"] }, { "symbols": ["assert.deepEqual", "assert.notDeepEqual"], "status": "partial", "evidence": ["tests/corpus/5513-assert-deep-equal-loose.js", "tests/corpus/5514-assert-deep-equal-typed.ts", "tests/corpus/5516-assert-deep-equal-edges.js"] }, { "symbols": ["assert", "assert.ok", "assert.equal", "assert.notEqual", "assert.strictEqual", "assert.notStrictEqual", "assert.deepStrictEqual", "assert.notDeepStrictEqual", "assert.fail", "assert.match", "assert.doesNotMatch", "assert.throws", "assert.rejects", "assert.ifError"], "status": "partial", "evidence": ["tests/corpus/1600-assert-passing.ts", "tests/corpus/1604-assert-deep-structures.ts", "tests/corpus/1609-assert-async.ts", "tests/corpus/1721-assert-throws-regex-class.ts", "tests/corpus/2936-static-loose-equality.ts", "tests/corpus/5515-assert-deep-strict-typed-messages.ts"] }, - { "chapter": "crypto", "symbols": ["Cipheriv", "cipher.update", "cipher.final", "cipher.setAAD", "cipher.getAuthTag", "cipher.setAutoPadding", "Decipheriv", "decipher.update", "decipher.final", "decipher.setAAD", "decipher.setAuthTag", "decipher.setAutoPadding"], "status": "partial", "evidence": ["tests/corpus/5250-cipher-aes-gcm.ts", "tests/corpus/5251-cipher-aes-cbc.ts", "tests/corpus/5252-cipher-aes-ctr.ts", "tests/corpus/5253-cipher-chacha20-poly1305.ts", "tests/corpus/5254-cipher-errors.js", "tests/corpus/5255-cipher-encodings.cjs", "tests/corpus/5256-cipher-deprecation.cjs", "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", "tests/fixtures/node-types/cipher.ts"] }, + { "chapter": "crypto", "symbols": ["Cipheriv", "cipher.update", "cipher.final", "cipher.setAAD", "cipher.getAuthTag", "cipher.setAutoPadding", "Decipheriv", "decipher.update", "decipher.final", "decipher.setAAD", "decipher.setAuthTag", "decipher.setAutoPadding"], "status": "partial", "evidence": ["tests/corpus/5250-cipher-aes-gcm.ts", "tests/corpus/5251-cipher-aes-cbc.ts", "tests/corpus/5252-cipher-aes-ctr.ts", "tests/corpus/5253-cipher-chacha20-poly1305.ts", "tests/corpus/5254-cipher-errors.js", "tests/corpus/5255-cipher-encodings.cjs", "tests/corpus/5256-cipher-deprecation.cjs", "tests/corpus/5257-cipher-vectors.ts", "tests/corpus/5258-cipher-handles.js", "tests/corpus/5259-cipher-chunked.ts", "tests/corpus/5355-cipher-bulk.ts", "tests/corpus/5356-cipher-counters.ts", "tests/corpus/5357-cipher-chacha-bulk.ts", "tests/corpus/5358-cipher-cbc-bulk.ts", "tests/corpus/5359-cipher-tamper.ts", "tests/fixtures/node-types/cipher.ts"] }, { "symbols": ["crypto.createHash", "Hash", "hash.update", "hash.digest", "hash.copy", "crypto.createHmac", "Hmac", "hmac.update", "hmac.digest", "crypto.hash", "crypto.pbkdf2", "crypto.pbkdf2Sync"], "status": "partial", "evidence": ["tests/corpus/5760-crypto-hash-stream.ts", "tests/corpus/5761-crypto-hash-stream-states.ts", "tests/corpus/5762-crypto-hash-stream.cjs", "tests/corpus/2890-crypto-static-utility.ts", "tests/corpus/node24-crypto-sha2.ts", "tests/corpus/5435-crypto-hash-algorithms.ts", "tests/corpus/5436-crypto-hash-names.js", "tests/corpus/5437-crypto-hmac-algorithms.ts", "tests/corpus/5438-crypto-kdf-digests.ts", "tests/corpus/5440-crypto-hash-encodings.js", "tests/corpus/5441-crypto-hash-output-length.ts", "tests/harness/npm-static.test.ts"] }, { "symbols": ["crypto.randomFill", "crypto.randomFillSync", "crypto.randomUUID", "crypto.randomUUIDv7"], "status": "supported", "evidence": ["tests/corpus/5442-crypto-random-values.ts", "tests/corpus/5443-crypto-random-arguments.js", "tests/corpus/1358-crypto-random.ts"] }, { "symbols": ["crypto.createSecretKey", "crypto.generateKey", "crypto.generateKeySync", "KeyObject", "keyObject.export", "keyObject.equals", "keyObject.symmetricKeySize", "keyObject.type"], "status": "partial", "evidence": ["tests/corpus/5445-crypto-secret-key-objects.ts", "tests/corpus/5446-crypto-secret-key-errors.js"] }, diff --git a/packages/compiler/src/backend/native/executable.ts b/packages/compiler/src/backend/native/executable.ts index 549e9ebbf..e729ff86f 100644 --- a/packages/compiler/src/backend/native/executable.ts +++ b/packages/compiler/src/backend/native/executable.ts @@ -585,7 +585,9 @@ export async function compileCInternal( "-I", join(vendorTlsDir(), "include"), ...(tls ? [rt(join(rtDir, "scr_tls.c"))] : []), - ...(cipher ? [rt(join(rtDir, "scr_cipher.c"))] : []), + ...(cipher + ? [rt(join(rtDir, "scr_cipher.c")), rt(join(rtDir, "scr_cipher_simd.c"))] + : []), tlsArchive, // mbedTLS's win32 entropy poll is BCryptGenRandom (bcrypt.h). // The unconditional win32 libs above do not carry it. diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5355-cipher-bulk.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5355-cipher-bulk.ts.json new file mode 100644 index 000000000..90fc259db --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5355-cipher-bulk.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5355-cipher-bulk.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5356-cipher-counters.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5356-cipher-counters.ts.json new file mode 100644 index 000000000..65e1284be --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5356-cipher-counters.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5356-cipher-counters.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5357-cipher-chacha-bulk.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5357-cipher-chacha-bulk.ts.json new file mode 100644 index 000000000..5734f045c --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5357-cipher-chacha-bulk.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5357-cipher-chacha-bulk.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5358-cipher-cbc-bulk.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5358-cipher-cbc-bulk.ts.json new file mode 100644 index 000000000..7ae97da23 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5358-cipher-cbc-bulk.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5358-cipher-cbc-bulk.ts" + ], + "diags": [] +} diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5359-cipher-tamper.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5359-cipher-tamper.ts.json new file mode 100644 index 000000000..4a831261f --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/5359-cipher-tamper.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/5359-cipher-tamper.ts" + ], + "diags": [] +} diff --git a/packages/runtime-darwin-arm64/runtime-pack-matrix.mjs b/packages/runtime-darwin-arm64/runtime-pack-matrix.mjs index 54e789624..ff140be16 100644 --- a/packages/runtime-darwin-arm64/runtime-pack-matrix.mjs +++ b/packages/runtime-darwin-arm64/runtime-pack-matrix.mjs @@ -112,6 +112,7 @@ const optional = [ ["scr_tls_ca.c", "tlsCaEffective"], ["scr_tls.c", "tlsEffective"], ["scr_cipher.c", "cipher"], + ["scr_cipher_simd.c", "cipher"], ["scr_fetch.c", "nativeFetch"], ]; diff --git a/packages/runtime-pack-common/runtime-pack-matrix.mjs b/packages/runtime-pack-common/runtime-pack-matrix.mjs index 6b5052482..cd55830c7 100644 --- a/packages/runtime-pack-common/runtime-pack-matrix.mjs +++ b/packages/runtime-pack-common/runtime-pack-matrix.mjs @@ -102,6 +102,7 @@ const OPTIONAL = [ ["scr_tls_ca.c", "tlsCaEffective"], ["scr_tls.c", "tlsEffective"], ["scr_cipher.c", "cipher"], + ["scr_cipher_simd.c", "cipher"], ["scr_fetch.c", "nativeFetch"], ]; diff --git a/packages/runtime-wasm32-wasi/scripts/build.mjs b/packages/runtime-wasm32-wasi/scripts/build.mjs index ca0786607..11afc0a80 100644 --- a/packages/runtime-wasm32-wasi/scripts/build.mjs +++ b/packages/runtime-wasm32-wasi/scripts/build.mjs @@ -20,6 +20,7 @@ process.env.SCRIPTC_RUNTIME_PACK_CONFIG = JSON.stringify({ "scr_tls_ca.c", "scr_tls.c", "scr_cipher.c", + "scr_cipher_simd.c", "scr_fetch.c", ], omitArchives: ["mbedtls"], diff --git a/packages/runtime/src/scr_cipher.c b/packages/runtime/src/scr_cipher.c index 97b7a3e97..ea7c49794 100644 --- a/packages/runtime/src/scr_cipher.c +++ b/packages/runtime/src/scr_cipher.c @@ -7,8 +7,11 @@ * padding follow OpenSSL 3's generic block provider, so every update() * returns the same number of bytes as Node's. String output goes through * the runtime StringDecoder, which carries partial characters and base64 - * groups between calls as Node's does. chacha20-poly1305 follows OpenSSL's - * construction, which also accepts AAD after data. Authentication tags are + * groups between calls as Node's does. On x86-64 CPUs with AES-NI and + * PCLMULQDQ (AES) or AVX2 (chacha20-poly1305), the transforms use the + * kernels in scr_cipher_simd.c, which produce the same output as mbedTLS. + * chacha20-poly1305 follows OpenSSL's construction, which also accepts AAD + * after data. Authentication tags are * compared in constant time. All arguments are borrowed. */ #include "scr_runtime.h" @@ -20,6 +23,7 @@ #include "mbedtls/chacha20.h" #include "mbedtls/gcm.h" #include "mbedtls/poly1305.h" +#include "scr_cipher_simd.h" #include "mbedtls/platform_util.h" typedef enum { SC_CBC, SC_CTR, SC_GCM, SC_CHACHA } ScCipherMode; @@ -98,6 +102,11 @@ typedef struct ScCipher { mbedtls_gcm_context gcm; mbedtls_chacha20_context chacha; mbedtls_poly1305_context poly; + bool simd; /* the scr_cipher_simd.c kernels replace mbedTLS */ + ScCsAesKey simd_key; /* CBC and CTR; the decryption schedule for CBC decryption */ + ScCsGcm simd_gcm; + ScCsChaCha simd_chacha; + ScCsPoly1305 simd_poly; uint64_t aad_len; /* chacha20-poly1305 AAD bytes */ uint64_t text_len; /* chacha20-poly1305 data bytes */ bool aad_open; /* AAD was added since the last data or padding */ @@ -548,7 +557,34 @@ static ScrDyn *sc_cipher_new(bool decrypt, ScrDyn *cipher, ScrDyn *key, ScrDyn * mbedtls_poly1305_init(&c->poly); int rc = 0; unsigned bits = spec->key_len * 8; - switch (spec->mode) { + c->simd = spec->mode == SC_CHACHA ? scr_cs_chacha_available() : scr_cs_aes_available(); + if (c->simd) { + switch (spec->mode) { + case SC_CBC: { + ScCsAesKey enc; + scr_cs_aes_setkey(&enc, decrypt ? &c->simd_key : NULL, key_bytes->data, spec->key_len); + if (!decrypt) c->simd_key = enc; + mbedtls_platform_zeroize(&enc, sizeof enc); + memcpy(c->block, iv_bytes->data, 16); + break; + } + case SC_CTR: + scr_cs_aes_setkey(&c->simd_key, NULL, key_bytes->data, spec->key_len); + memcpy(c->block, iv_bytes->data, 16); + break; + case SC_GCM: + scr_cs_gcm_start(&c->simd_gcm, key_bytes->data, spec->key_len, iv_bytes->data, iv_len, decrypt); + break; + case SC_CHACHA: { + unsigned char poly_key[64] = {0}; + scr_cs_chacha_start(&c->simd_chacha, key_bytes->data, iv_bytes->data, 0); + scr_cs_chacha_xor(&c->simd_chacha, poly_key, poly_key, sizeof poly_key); + scr_cs_poly_start(&c->simd_poly, poly_key); + mbedtls_platform_zeroize(poly_key, sizeof poly_key); + break; + } + } + } else switch (spec->mode) { case SC_CBC: rc = decrypt ? mbedtls_aes_setkey_dec(&c->aes, key_bytes->data, bits) : mbedtls_aes_setkey_enc(&c->aes, key_bytes->data, bits); @@ -608,6 +644,11 @@ done: /* Raw CBC over whole blocks. */ static bool sc_cbc_blocks(ScCipher *c, const unsigned char *in, size_t len, unsigned char *out) { + if (c->simd) { + if (c->decrypt) scr_cs_aes_cbc_decrypt(&c->simd_key, c->block, in, out, len / 16); + else scr_cs_aes_cbc_encrypt(&c->simd_key, c->block, in, out, len / 16); + return true; + } return mbedtls_aes_crypt_cbc(&c->aes, c->decrypt ? MBEDTLS_AES_DECRYPT : MBEDTLS_AES_ENCRYPT, len, c->block, in, out) == 0; } @@ -698,11 +739,17 @@ static bool sc_tag_equal(const unsigned char *a, const unsigned char *b, size_t return diff == 0; } +static bool sc_poly_update(ScCipher *c, const unsigned char *data, size_t len) { + if (!c->simd) return mbedtls_poly1305_update(&c->poly, data, len) == 0; + scr_cs_poly_update(&c->simd_poly, data, len); + return true; +} + /* Poly1305 zero padding to the next 16-byte boundary of `length`. */ static bool sc_poly_pad(ScCipher *c, uint64_t length) { static const unsigned char zero[16] = {0}; size_t rem = (size_t)(length % 16); - return rem == 0 || mbedtls_poly1305_update(&c->poly, zero, 16 - rem) == 0; + return rem == 0 || sc_poly_update(c, zero, 16 - rem); } /* OpenSSL's chacha20-poly1305 data step: pending AAD is padded first, and @@ -712,9 +759,10 @@ static bool sc_chacha_update(ScCipher *c, const unsigned char *in, size_t len, u if (!sc_poly_pad(c, c->aad_len)) return false; c->aad_open = false; } - if (c->decrypt && mbedtls_poly1305_update(&c->poly, in, len) != 0) return false; - if (mbedtls_chacha20_update(&c->chacha, len, in, out) != 0) return false; - if (!c->decrypt && mbedtls_poly1305_update(&c->poly, out, len) != 0) return false; + if (c->decrypt && !sc_poly_update(c, in, len)) return false; + if (c->simd) scr_cs_chacha_xor(&c->simd_chacha, in, out, len); + else if (mbedtls_chacha20_update(&c->chacha, len, in, out) != 0) return false; + if (!c->decrypt && !sc_poly_update(c, out, len)) return false; c->text_len += len; return true; } @@ -727,7 +775,12 @@ static bool sc_chacha_finish(ScCipher *c, unsigned char tag[16]) { lengths[i] = (unsigned char)(c->aad_len >> (8 * i)); lengths[8 + i] = (unsigned char)(c->text_len >> (8 * i)); } - return mbedtls_poly1305_update(&c->poly, lengths, sizeof lengths) == 0 && mbedtls_poly1305_finish(&c->poly, tag) == 0; + if (!sc_poly_update(c, lengths, sizeof lengths)) return false; + if (c->simd) { + scr_cs_poly_finish(&c->simd_poly, tag); + return true; + } + return mbedtls_poly1305_finish(&c->poly, tag) == 0; } /* The cipher output of an update over len bytes (+1 Buffer), or NULL @@ -747,11 +800,17 @@ static ScrBytes *sc_transform(ScCipher *c, const unsigned char *in, size_t len) break; } case SC_CTR: - ok = len == 0 || mbedtls_aes_crypt_ctr(&c->aes, len, &c->bufsz, c->block, c->buf, in, out->data) == 0; + if (len && c->simd) scr_cs_aes_ctr(&c->simd_key, c->block, c->buf, &c->bufsz, in, out->data, len); + else ok = len == 0 || mbedtls_aes_crypt_ctr(&c->aes, len, &c->bufsz, c->block, c->buf, in, out->data) == 0; produced = len; break; case SC_GCM: - ok = len == 0 || mbedtls_gcm_update(&c->gcm, in, len, out->data, room, &produced) == 0; + if (len && c->simd) { + ok = scr_cs_gcm_update(&c->simd_gcm, in, out->data, len); + produced = len; + } else { + ok = len == 0 || mbedtls_gcm_update(&c->gcm, in, len, out->data, room, &produced) == 0; + } break; case SC_CHACHA: ok = len == 0 || sc_chacha_update(c, in, len, out->data); @@ -911,7 +970,8 @@ static ScrDyn *sc_final(ScCipher *c, ScrDyn *output_encoding) { case SC_GCM: { unsigned char full[16]; size_t ignored; - backend = mbedtls_gcm_finish(&c->gcm, NULL, 0, &ignored, full, 16) == 0; + if (c->simd) scr_cs_gcm_finish(&c->simd_gcm, full); + else backend = mbedtls_gcm_finish(&c->gcm, NULL, 0, &ignored, full, 16) == 0; if (!backend) { /* No tag is computed or compared. */ } else if (c->decrypt) { @@ -974,9 +1034,10 @@ static ScrDyn *sc_set_aad(ScCipher *c, ScrDyn *self, ScrDyn *buffer, ScrDyn *opt * non-empty AAD. */ bool ok = c->active && sc_aead(c) && !(c->data_started && (c->mode == SC_GCM || aad->len > 0)); bool backend = true; - if (ok && c->mode == SC_GCM) backend = mbedtls_gcm_update_ad(&c->gcm, aad->data, aad->len) == 0; + if (ok && c->mode == SC_GCM && c->simd) backend = scr_cs_gcm_aad(&c->simd_gcm, aad->data, aad->len); + else if (ok && c->mode == SC_GCM) backend = mbedtls_gcm_update_ad(&c->gcm, aad->data, aad->len) == 0; if (ok && c->mode == SC_CHACHA && aad->len > 0) { - backend = mbedtls_poly1305_update(&c->poly, aad->data, aad->len) == 0; + backend = sc_poly_update(c, aad->data, aad->len); c->aad_len += aad->len; c->aad_open = true; } @@ -1134,5 +1195,5 @@ static bool sc_set(void *h, const char *key, size_t key_len, const ScrDyn *value return true; } -static ScrDynHandleOps sc_ops_cipher = {"Cipheriv", sc_retain, sc_release, sc_invoke, sc_get, sc_set, NULL, NULL, NULL}; -static ScrDynHandleOps sc_ops_decipher = {"Decipheriv", sc_retain, sc_release, sc_invoke, sc_get, sc_set, NULL, NULL, NULL}; +static ScrDynHandleOps sc_ops_cipher = {"Cipheriv", sc_retain, sc_release, sc_invoke, sc_get, sc_set, NULL, NULL, NULL, NULL}; +static ScrDynHandleOps sc_ops_decipher = {"Decipheriv", sc_retain, sc_release, sc_invoke, sc_get, sc_set, NULL, NULL, NULL, NULL}; diff --git a/packages/runtime/src/scr_cipher_simd.c b/packages/runtime/src/scr_cipher_simd.c new file mode 100644 index 000000000..f6754800a --- /dev/null +++ b/packages/runtime/src/scr_cipher_simd.c @@ -0,0 +1,1101 @@ +/* x86-64 cipher kernels (see scr_cipher_simd.h). Each function that uses + * an instruction-set extension carries a target attribute, so the unit + * builds with the runtime's ordinary flags and the instructions run only + * after scr_cs_aes_available() or scr_cs_chacha_available() has checked + * CPUID. On other architectures both checks report false and the kernels + * are not called. */ +#include "scr_cipher_simd.h" + +#include + +#if defined(__x86_64__) && (defined(__clang__) || defined(__GNUC__)) && defined(__SIZEOF_INT128__) + +#include +#include + +#define SC_AES __attribute__((target("aes,pclmul,ssse3,sse4.1"))) +#define SC_AVX2 __attribute__((target("avx2"))) +/* Clang 18 to 21 require evex512 for 512-bit vectors; clang 22 dropped it. */ +#if defined(__clang__) && __clang_major__ >= 18 && __clang_major__ < 22 +#define SC_AVX512 __attribute__((target("avx512f,evex512"))) +#define SC_IFMA __attribute__((target("avx512f,avx512ifma,evex512"))) +#define SC_VAES __attribute__((target("aes,pclmul,avx512f,avx512bw,vaes,vpclmulqdq,evex512"))) +#else +#define SC_AVX512 __attribute__((target("avx512f"))) +#define SC_IFMA __attribute__((target("avx512f,avx512ifma"))) +#define SC_VAES __attribute__((target("aes,pclmul,avx512f,avx512bw,vaes,vpclmulqdq"))) +#endif + +/* CPUID leaf 1 ECX bits and leaf 7 EBX bit 5 (AVX2). */ +static unsigned sc_leaf1_ecx(void) { + unsigned a, b, c, d; + return __get_cpuid(1, &a, &b, &c, &d) ? c : 0; +} + +bool scr_cs_aes_available(void) { + unsigned c = sc_leaf1_ecx(); + return (c & (1u << 25)) && (c & (1u << 1)) && (c & (1u << 9)) && (c & (1u << 19)); +} + +/* Bit 0: AVX2 usable; bit 1: AVX-512F usable; bit 2: AVX-512 IFMA usable; + * bit 3: AVX-512BW, VAES and VPCLMULQDQ usable. */ +static unsigned sc_vector_features(void) { + unsigned c = sc_leaf1_ecx(); + if (!(c & (1u << 27)) || !(c & (1u << 28))) return 0; /* OSXSAVE, AVX */ + unsigned lo, hi; + __asm__ volatile("xgetbv" : "=a"(lo), "=d"(hi) : "c"(0)); + (void)hi; + if ((lo & 6) != 6) return 0; /* XMM and YMM state enabled */ + unsigned a, b, d; + if (!__get_cpuid_count(7, 0, &a, &b, &c, &d) || !(b & (1u << 5))) return 0; + /* AVX-512F with opmask, ZMM0-15 upper halves and ZMM16-31 enabled. */ + if (!(b & (1u << 16)) || (lo & 0xe0) != 0xe0) return 1; + unsigned features = 3; + if (b & (1u << 21)) features |= 4; /* leaf 7 EBX bit 21: AVX-512 IFMA */ + /* Leaf 7 EBX bit 30: AVX-512BW; ECX bits 9 and 10: VAES, VPCLMULQDQ. */ + if ((b & (1u << 30)) && (c & (1u << 9)) && (c & (1u << 10))) features |= 8; + return features; +} + +bool scr_cs_chacha_available(void) { + return sc_vector_features() != 0; +} + +static uint32_t sc_le32(const uint8_t *p) { + return (uint32_t)p[0] | (uint32_t)p[1] << 8 | (uint32_t)p[2] << 16 | (uint32_t)p[3] << 24; +} + +static void sc_put_le32(uint8_t *p, uint32_t v) { + p[0] = (uint8_t)v; + p[1] = (uint8_t)(v >> 8); + p[2] = (uint8_t)(v >> 16); + p[3] = (uint8_t)(v >> 24); +} + +static uint64_t sc_le64(const uint8_t *p) { + return (uint64_t)sc_le32(p) | (uint64_t)sc_le32(p + 4) << 32; +} + +static void sc_put_le64(uint8_t *p, uint64_t v) { + sc_put_le32(p, (uint32_t)v); + sc_put_le32(p + 4, (uint32_t)(v >> 32)); +} + +static uint64_t sc_be64(const uint8_t *p) { + uint64_t v = 0; + for (int i = 0; i < 8; i++) v = v << 8 | p[i]; + return v; +} + +static void sc_put_be64(uint8_t *p, uint64_t v) { + for (int i = 7; i >= 0; i--) { + p[i] = (uint8_t)v; + v >>= 8; + } +} + +/* ── AES ──────────────────────────────────────────────────────────────── */ + +/* SubWord through AESKEYGENASSIST: dword 0 of the result is SubWord of + * source dword 1. */ +SC_AES static uint32_t sc_subword(uint32_t w) { + __m128i v = _mm_aeskeygenassist_si128(_mm_set_epi32(0, 0, (int)w, 0), 0); + return (uint32_t)_mm_cvtsi128_si32(v); +} + +/* FIPS-197 key expansion over little-endian words. */ +SC_AES void scr_cs_aes_setkey(ScCsAesKey *enc, ScCsAesKey *dec, const uint8_t *key, size_t key_len) { + unsigned nk = (unsigned)(key_len / 4); + unsigned rounds = nk + 6; + unsigned total = 4 * (rounds + 1); + uint32_t w[60]; + for (unsigned i = 0; i < nk; i++) w[i] = sc_le32(key + 4 * i); + uint32_t rcon = 1; + for (unsigned i = nk; i < total; i++) { + uint32_t t = w[i - 1]; + if (i % nk == 0) { + uint32_t s = sc_subword(t); + t = ((s >> 8) | (s << 24)) ^ rcon; + rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x11b : 0); + } else if (nk > 6 && i % nk == 4) { + t = sc_subword(t); + } + w[i] = w[i - nk] ^ t; + } + for (unsigned i = 0; i < total; i++) sc_put_le32(enc->rk + 4 * i, w[i]); + enc->rounds = rounds; + if (dec) { + dec->rounds = rounds; + memcpy(dec->rk, enc->rk + 16 * rounds, 16); + for (unsigned r = 1; r < rounds; r++) { + __m128i k = _mm_loadu_si128((const __m128i *)(enc->rk + 16 * (rounds - r))); + _mm_storeu_si128((__m128i *)(dec->rk + 16 * r), _mm_aesimc_si128(k)); + } + memcpy(dec->rk + 16 * rounds, enc->rk, 16); + } + memset(w, 0, sizeof w); +} + +#define SC_RK(k, r) _mm_loadu_si128((const __m128i *)((k)->rk + 16 * (r))) + +SC_AES static inline __m128i sc_encrypt1(const ScCsAesKey *k, __m128i b) { + b = _mm_xor_si128(b, SC_RK(k, 0)); + for (unsigned r = 1; r < k->rounds; r++) b = _mm_aesenc_si128(b, SC_RK(k, r)); + return _mm_aesenclast_si128(b, SC_RK(k, k->rounds)); +} + +SC_AES static inline void sc_encrypt8(const ScCsAesKey *k, __m128i b[8]) { + __m128i key = SC_RK(k, 0); + for (int i = 0; i < 8; i++) b[i] = _mm_xor_si128(b[i], key); + for (unsigned r = 1; r < k->rounds; r++) { + key = SC_RK(k, r); + for (int i = 0; i < 8; i++) b[i] = _mm_aesenc_si128(b[i], key); + } + key = SC_RK(k, k->rounds); + for (int i = 0; i < 8; i++) b[i] = _mm_aesenclast_si128(b[i], key); +} + +SC_AES static inline void sc_decrypt8(const ScCsAesKey *k, __m128i b[8]) { + __m128i key = SC_RK(k, 0); + for (int i = 0; i < 8; i++) b[i] = _mm_xor_si128(b[i], key); + for (unsigned r = 1; r < k->rounds; r++) { + key = SC_RK(k, r); + for (int i = 0; i < 8; i++) b[i] = _mm_aesdec_si128(b[i], key); + } + key = SC_RK(k, k->rounds); + for (int i = 0; i < 8; i++) b[i] = _mm_aesdeclast_si128(b[i], key); +} + +SC_AES static inline __m128i sc_decrypt1(const ScCsAesKey *k, __m128i b) { + b = _mm_xor_si128(b, SC_RK(k, 0)); + for (unsigned r = 1; r < k->rounds; r++) b = _mm_aesdec_si128(b, SC_RK(k, r)); + return _mm_aesdeclast_si128(b, SC_RK(k, k->rounds)); +} + +/* The counter block hi||lo as big-endian bytes. */ +SC_AES static inline __m128i sc_ctr_block(uint64_t hi, uint64_t lo) { + return _mm_set_epi64x((long long)__builtin_bswap64(lo), (long long)__builtin_bswap64(hi)); +} + +SC_AES void scr_cs_aes_ctr(const ScCsAesKey *key, uint8_t counter[16], uint8_t stream[16], size_t *offset, + const uint8_t *in, uint8_t *out, size_t len) { + size_t n = *offset; + while (n != 0 && len > 0) { + *out++ = *in++ ^ stream[n]; + n = (n + 1) & 15; + len--; + } + uint64_t hi = sc_be64(counter), lo = sc_be64(counter + 8); + while (len >= 128) { + __m128i b[8]; + for (int i = 0; i < 8; i++) { + uint64_t l = lo + (uint64_t)i; + b[i] = sc_ctr_block(l < lo ? hi + 1 : hi, l); + } + sc_encrypt8(key, b); + for (int i = 0; i < 8; i++) { + __m128i d = _mm_loadu_si128((const __m128i *)(in + 16 * i)); + _mm_storeu_si128((__m128i *)(out + 16 * i), _mm_xor_si128(d, b[i])); + } + uint64_t next = lo + 8; + if (next < lo) hi++; + lo = next; + in += 128; + out += 128; + len -= 128; + } + while (len >= 16) { + __m128i b = sc_encrypt1(key, sc_ctr_block(hi, lo)); + _mm_storeu_si128((__m128i *)out, _mm_xor_si128(_mm_loadu_si128((const __m128i *)in), b)); + if (++lo == 0) hi++; + in += 16; + out += 16; + len -= 16; + } + if (len > 0) { + _mm_storeu_si128((__m128i *)stream, sc_encrypt1(key, sc_ctr_block(hi, lo))); + if (++lo == 0) hi++; + for (size_t i = 0; i < len; i++) out[i] = in[i] ^ stream[i]; + n = len; + } + sc_put_be64(counter, hi); + sc_put_be64(counter + 8, lo); + *offset = n; +} + +SC_AES void scr_cs_aes_cbc_encrypt(const ScCsAesKey *enc, uint8_t iv[16], const uint8_t *in, uint8_t *out, + size_t blocks) { + __m128i chain = _mm_loadu_si128((const __m128i *)iv); + for (size_t i = 0; i < blocks; i++) { + chain = sc_encrypt1(enc, _mm_xor_si128(chain, _mm_loadu_si128((const __m128i *)(in + 16 * i)))); + _mm_storeu_si128((__m128i *)(out + 16 * i), chain); + } + _mm_storeu_si128((__m128i *)iv, chain); +} + +SC_AES void scr_cs_aes_cbc_decrypt(const ScCsAesKey *dec, uint8_t iv[16], const uint8_t *in, uint8_t *out, + size_t blocks) { + __m128i chain = _mm_loadu_si128((const __m128i *)iv); + while (blocks >= 8) { + __m128i c[8], p[8]; + for (int i = 0; i < 8; i++) c[i] = p[i] = _mm_loadu_si128((const __m128i *)(in + 16 * i)); + sc_decrypt8(dec, p); + p[0] = _mm_xor_si128(p[0], chain); + for (int i = 1; i < 8; i++) p[i] = _mm_xor_si128(p[i], c[i - 1]); + for (int i = 0; i < 8; i++) _mm_storeu_si128((__m128i *)(out + 16 * i), p[i]); + chain = c[7]; + in += 128; + out += 128; + blocks -= 8; + } + for (; blocks > 0; blocks--) { + __m128i c = _mm_loadu_si128((const __m128i *)in); + _mm_storeu_si128((__m128i *)out, _mm_xor_si128(sc_decrypt1(dec, c), chain)); + chain = c; + in += 16; + out += 16; + } + _mm_storeu_si128((__m128i *)iv, chain); +} + +/* ── GHASH ────────────────────────────────────────────────────────────── */ + +/* GHASH works on byte-reflected blocks, as in Intel's "Carry-Less + * Multiplication and Its Usage for Computing the GCM Mode". */ +SC_AES static inline __m128i sc_bswap(__m128i v) { + return _mm_shuffle_epi8(v, _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); +} + +/* Accumulates the unreduced 256-bit product a·b into lo/mid/hi. */ +SC_AES static inline void sc_clmul_acc(__m128i a, __m128i b, __m128i *lo, __m128i *mid, __m128i *hi) { + *lo = _mm_xor_si128(*lo, _mm_clmulepi64_si128(a, b, 0x00)); + *hi = _mm_xor_si128(*hi, _mm_clmulepi64_si128(a, b, 0x11)); + *mid = _mm_xor_si128(*mid, _mm_xor_si128(_mm_clmulepi64_si128(a, b, 0x10), _mm_clmulepi64_si128(a, b, 0x01))); +} + +/* Shifts the reflected 256-bit product left by one bit and reduces it + * modulo x^128 + x^7 + x^2 + x + 1. */ +SC_AES static inline __m128i sc_gf_reduce(__m128i lo, __m128i mid, __m128i hi) { + __m128i t3 = _mm_xor_si128(lo, _mm_slli_si128(mid, 8)); + __m128i t6 = _mm_xor_si128(hi, _mm_srli_si128(mid, 8)); + __m128i t7 = _mm_srli_epi32(t3, 31); + __m128i t8 = _mm_srli_epi32(t6, 31); + t3 = _mm_slli_epi32(t3, 1); + t6 = _mm_slli_epi32(t6, 1); + __m128i t9 = _mm_srli_si128(t7, 12); + t8 = _mm_slli_si128(t8, 4); + t7 = _mm_slli_si128(t7, 4); + t3 = _mm_or_si128(t3, t7); + t6 = _mm_or_si128(_mm_or_si128(t6, t8), t9); + t7 = _mm_xor_si128(_mm_xor_si128(_mm_slli_epi32(t3, 31), _mm_slli_epi32(t3, 30)), _mm_slli_epi32(t3, 25)); + t8 = _mm_srli_si128(t7, 4); + t7 = _mm_slli_si128(t7, 12); + t3 = _mm_xor_si128(t3, t7); + __m128i t2 = _mm_xor_si128(_mm_xor_si128(_mm_srli_epi32(t3, 1), _mm_srli_epi32(t3, 2)), _mm_srli_epi32(t3, 7)); + t2 = _mm_xor_si128(t2, t8); + t3 = _mm_xor_si128(t3, t2); + return _mm_xor_si128(t6, t3); +} + +SC_AES static inline __m128i sc_gf_mul(__m128i a, __m128i b) { + __m128i lo = _mm_setzero_si128(), mid = lo, hi = lo; + sc_clmul_acc(a, b, &lo, &mid, &hi); + return sc_gf_reduce(lo, mid, hi); +} + +#define SC_H(g, i) _mm_loadu_si128((const __m128i *)(g)->h[i]) + +/* Folds whole 16-byte blocks into the accumulator, eight at a time. */ +SC_AES static void sc_ghash_blocks(ScCsGcm *g, const uint8_t *p, size_t blocks) { + __m128i x = _mm_loadu_si128((const __m128i *)g->x); + while (blocks >= 8) { + __m128i lo = _mm_setzero_si128(), mid = lo, hi = lo; + for (int i = 0; i < 8; i++) { + __m128i b = sc_bswap(_mm_loadu_si128((const __m128i *)(p + 16 * i))); + if (i == 0) b = _mm_xor_si128(b, x); + sc_clmul_acc(b, SC_H(g, 7 - i), &lo, &mid, &hi); + } + x = sc_gf_reduce(lo, mid, hi); + p += 128; + blocks -= 8; + } + for (; blocks > 0; blocks--) { + x = sc_gf_mul(_mm_xor_si128(x, sc_bswap(_mm_loadu_si128((const __m128i *)p))), SC_H(g, 0)); + p += 16; + } + _mm_storeu_si128((__m128i *)g->x, x); +} + +/* Adds bytes to the GHASH input stream. */ +SC_AES static void sc_ghash_absorb(ScCsGcm *g, const uint8_t *p, size_t len) { + if (g->partial_len > 0) { + size_t take = 16 - g->partial_len < len ? 16 - g->partial_len : len; + memcpy(g->partial + g->partial_len, p, take); + g->partial_len += take; + p += take; + len -= take; + if (g->partial_len < 16) return; + sc_ghash_blocks(g, g->partial, 1); + g->partial_len = 0; + } + if (len >= 16) { + sc_ghash_blocks(g, p, len / 16); + p += len & ~(size_t)15; + len &= 15; + } + if (len > 0) { + memcpy(g->partial, p, len); + g->partial_len = len; + } +} + +/* Zero-pads and folds a partial GHASH block. */ +SC_AES static void sc_ghash_pad(ScCsGcm *g) { + if (g->partial_len == 0) return; + memset(g->partial + g->partial_len, 0, 16 - g->partial_len); + sc_ghash_blocks(g, g->partial, 1); + g->partial_len = 0; +} + +SC_AES void scr_cs_gcm_start(ScCsGcm *g, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len, + bool decrypt) { + memset(g, 0, sizeof *g); + scr_cs_aes_setkey(&g->key, NULL, key, key_len); + __m128i h = sc_bswap(sc_encrypt1(&g->key, _mm_setzero_si128())); + __m128i power = h; + for (int i = 0; i < 16; i++) { + _mm_storeu_si128((__m128i *)g->h[i], power); + power = sc_gf_mul(power, h); + } + if (iv_len == 12) { + memcpy(g->j0, iv, 12); + g->j0[15] = 1; + } else { + sc_ghash_absorb(g, iv, iv_len); + sc_ghash_pad(g); + uint8_t lengths[16] = {0}; + sc_put_be64(lengths + 8, (uint64_t)iv_len * 8); + sc_ghash_blocks(g, lengths, 1); + _mm_storeu_si128((__m128i *)g->j0, sc_bswap(_mm_loadu_si128((const __m128i *)g->x))); + memset(g->x, 0, 16); + } + g->counter = ((uint32_t)g->j0[12] << 24 | (uint32_t)g->j0[13] << 16 | (uint32_t)g->j0[14] << 8 | g->j0[15]) + 1; + g->stream_off = 16; + g->decrypt = decrypt; + g->wide = (sc_vector_features() & 8) != 0; +} + +bool scr_cs_gcm_aad(ScCsGcm *g, const uint8_t *aad, size_t len) { + /* AAD is limited to 2^61 bytes. */ + if (g->aad_len + len < g->aad_len || (g->aad_len + len) >> 61 != 0) return false; + g->aad_len += len; + sc_ghash_absorb(g, aad, len); + return true; +} + +SC_AES static inline __m128i sc_gcm_block(const ScCsGcm *g, uint32_t counter) { + return _mm_insert_epi32(_mm_loadu_si128((const __m128i *)g->j0), (int)__builtin_bswap32(counter), 3); +} + +/* Encrypts eight counter blocks while folding eight byte-reflected + * ciphertext blocks `c` from the previous step, so the AES rounds and the + * carry-less multiplies run on separate execution ports. Returns the + * reduced GHASH accumulator; `c[0]` already includes the previous one. */ +SC_AES static inline __m128i sc_gcm_encrypt8_ghash(const ScCsGcm *g, __m128i b[8], const __m128i c[8]) { + const ScCsAesKey *k = &g->key; + __m128i key = SC_RK(k, 0); + for (int i = 0; i < 8; i++) b[i] = _mm_xor_si128(b[i], key); + __m128i lo = _mm_setzero_si128(), mid = lo, hi = lo; + /* AES-128 has 10 rounds, so rounds 1 to 8 are always aesenc rounds. */ + for (unsigned r = 1; r <= 8; r++) { + key = SC_RK(k, r); + for (int i = 0; i < 8; i++) b[i] = _mm_aesenc_si128(b[i], key); + sc_clmul_acc(c[r - 1], SC_H(g, 8 - r), &lo, &mid, &hi); + } + for (unsigned r = 9; r < k->rounds; r++) { + key = SC_RK(k, r); + for (int i = 0; i < 8; i++) b[i] = _mm_aesenc_si128(b[i], key); + } + key = SC_RK(k, k->rounds); + for (int i = 0; i < 8; i++) b[i] = _mm_aesenclast_si128(b[i], key); + return sc_gf_reduce(lo, mid, hi); +} + +/* Byte reversal within each 128-bit lane. */ +SC_VAES static inline __m512i sc_bswap512(__m512i v) { + return _mm512_shuffle_epi8(v, _mm512_broadcast_i32x4(_mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15))); +} + +SC_VAES static inline void sc_clmul_acc512(__m512i a, __m512i b, __m512i *lo, __m512i *mid, __m512i *hi) { + *lo = _mm512_xor_si512(*lo, _mm512_clmulepi64_epi128(a, b, 0x00)); + *hi = _mm512_xor_si512(*hi, _mm512_clmulepi64_epi128(a, b, 0x11)); + *mid = _mm512_xor_si512(*mid, _mm512_xor_si512(_mm512_clmulepi64_epi128(a, b, 0x10), + _mm512_clmulepi64_epi128(a, b, 0x01))); +} + +/* XOR of the four 128-bit lanes. */ +SC_VAES static inline __m128i sc_fold512(__m512i v) { + __m256i t = _mm256_xor_si256(_mm512_castsi512_si256(v), _mm512_extracti64x4_epi64(v, 1)); + return _mm_xor_si128(_mm256_castsi256_si128(t), _mm256_extracti128_si256(t, 1)); +} + +/* `groups` runs of sixteen blocks with VAES and VPCLMULQDQ, four blocks per + * instruction. As in the eight-block loop, each run's ciphertext is folded + * into GHASH during the next run's AES rounds. */ +SC_VAES static void sc_gcm_vaes(ScCsGcm *g, const uint8_t *in, uint8_t *out, size_t groups) { + const ScCsAesKey *k = &g->key; + __m512i rk[15]; + for (unsigned r = 0; r <= k->rounds; r++) rk[r] = _mm512_broadcast_i32x4(SC_RK(k, r)); + /* Vector j holds blocks 4j .. 4j + 3, which take H^(16 - 4j) .. H^(13 - 4j). */ + __m512i hp[4]; + for (int j = 0; j < 4; j++) { + __m512i v = _mm512_castsi128_si512(SC_H(g, 15 - 4 * j)); + v = _mm512_inserti32x4(v, SC_H(g, 14 - 4 * j), 1); + v = _mm512_inserti32x4(v, SC_H(g, 13 - 4 * j), 2); + hp[j] = _mm512_inserti32x4(v, SC_H(g, 12 - 4 * j), 3); + } + /* Byte-reversed counter blocks keep the 32-bit counter in dword 0 of each + * lane, where a 32-bit add gives GCM's inc32. */ + __m512i ctr = _mm512_add_epi32(_mm512_broadcast_i32x4(sc_bswap(sc_gcm_block(g, g->counter))), + _mm512_set_epi32(0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0)); + const __m512i four = _mm512_set_epi32(0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4); + __m128i x = _mm_loadu_si128((const __m128i *)g->x); + __m512i c[4]; + for (size_t n = 0; n < groups; n++) { + __m512i b[4]; + for (int j = 0; j < 4; j++) { + b[j] = _mm512_xor_si512(sc_bswap512(ctr), rk[0]); + ctr = _mm512_add_epi32(ctr, four); + } + __m512i lo = _mm512_setzero_si512(), mid = lo, hi = lo; + if (n == 0) { + for (unsigned r = 1; r <= 4; r++) + for (int j = 0; j < 4; j++) b[j] = _mm512_aesenc_epi128(b[j], rk[r]); + } else { + for (unsigned r = 1; r <= 4; r++) { + for (int j = 0; j < 4; j++) b[j] = _mm512_aesenc_epi128(b[j], rk[r]); + sc_clmul_acc512(c[r - 1], hp[r - 1], &lo, &mid, &hi); + } + } + for (unsigned r = 5; r < k->rounds; r++) + for (int j = 0; j < 4; j++) b[j] = _mm512_aesenc_epi128(b[j], rk[r]); + for (int j = 0; j < 4; j++) b[j] = _mm512_aesenclast_epi128(b[j], rk[k->rounds]); + if (n > 0) x = sc_gf_reduce(sc_fold512(lo), sc_fold512(mid), sc_fold512(hi)); + for (int j = 0; j < 4; j++) { + __m512i d = _mm512_loadu_si512((const void *)(in + 64 * j)); + __m512i r = _mm512_xor_si512(d, b[j]); + _mm512_storeu_si512((void *)(out + 64 * j), r); + c[j] = sc_bswap512(g->decrypt ? d : r); + } + c[0] = _mm512_xor_si512(c[0], _mm512_zextsi128_si512(x)); + in += 256; + out += 256; + } + __m512i lo = _mm512_setzero_si512(), mid = lo, hi = lo; + for (int j = 0; j < 4; j++) sc_clmul_acc512(c[j], hp[j], &lo, &mid, &hi); + x = sc_gf_reduce(sc_fold512(lo), sc_fold512(mid), sc_fold512(hi)); + _mm_storeu_si128((__m128i *)g->x, x); + g->counter += (uint32_t)(16 * groups); +} + +SC_AES bool scr_cs_gcm_update(ScCsGcm *g, const uint8_t *in, uint8_t *out, size_t len) { + if (len == 0) return true; + /* A message is limited to 2^36 - 32 bytes (NIST SP 800-38D). */ + if (len > SC_GCM_MAX_TEXT || g->text_len > SC_GCM_MAX_TEXT - len) return false; + if (!g->data) { + sc_ghash_pad(g); + g->data = true; + } + g->text_len += len; + /* GHASH reads the ciphertext: the output when encrypting, the input + * when decrypting. */ + while (g->stream_off < 16 && len > 0) { + uint8_t c = *in; + uint8_t p = c ^ g->stream[g->stream_off++]; + *out = p; + sc_ghash_absorb(g, g->decrypt ? &c : &p, 1); + in++; + out++; + len--; + } + if (g->wide && len >= 256) { + size_t groups = len / 256; + sc_gcm_vaes(g, in, out, groups); + in += 256 * groups; + out += 256 * groups; + len -= 256 * groups; + } + size_t bulk = len & ~(size_t)127; + if (bulk) { + /* Each step folds the ciphertext of the step before it; `c` holds + * the blocks still to fold. */ + __m128i x = _mm_loadu_si128((const __m128i *)g->x); + uint32_t counter = g->counter; + __m128i c[8]; + for (size_t done = 0; done < bulk; done += 128) { + __m128i b[8]; + for (int i = 0; i < 8; i++) b[i] = sc_gcm_block(g, counter + (uint32_t)i); + counter += 8; + if (done == 0) { + sc_encrypt8(&g->key, b); + } else { + x = sc_gcm_encrypt8_ghash(g, b, c); + } + for (int i = 0; i < 8; i++) { + __m128i d = _mm_loadu_si128((const __m128i *)(in + done + 16 * i)); + __m128i r = _mm_xor_si128(d, b[i]); + _mm_storeu_si128((__m128i *)(out + done + 16 * i), r); + c[i] = sc_bswap(g->decrypt ? d : r); + } + c[0] = _mm_xor_si128(c[0], x); + } + __m128i lo = _mm_setzero_si128(), mid = lo, hi = lo; + for (int i = 0; i < 8; i++) sc_clmul_acc(c[i], SC_H(g, 7 - i), &lo, &mid, &hi); + x = sc_gf_reduce(lo, mid, hi); + _mm_storeu_si128((__m128i *)g->x, x); + g->counter = counter; + in += bulk; + out += bulk; + len -= bulk; + } + while (len >= 16) { + __m128i d = _mm_loadu_si128((const __m128i *)in); + __m128i r = _mm_xor_si128(d, sc_encrypt1(&g->key, sc_gcm_block(g, g->counter++))); + _mm_storeu_si128((__m128i *)out, r); + sc_ghash_blocks(g, g->decrypt ? in : out, 1); + in += 16; + out += 16; + len -= 16; + } + if (len > 0) { + _mm_storeu_si128((__m128i *)g->stream, sc_encrypt1(&g->key, sc_gcm_block(g, g->counter++))); + for (size_t i = 0; i < len; i++) out[i] = in[i] ^ g->stream[i]; + sc_ghash_absorb(g, g->decrypt ? in : out, len); + g->stream_off = len; + } + return true; +} + +SC_AES void scr_cs_gcm_finish(ScCsGcm *g, uint8_t tag[16]) { + sc_ghash_pad(g); + uint8_t lengths[16]; + sc_put_be64(lengths, g->aad_len * 8); + sc_put_be64(lengths + 8, g->text_len * 8); + sc_ghash_blocks(g, lengths, 1); + __m128i s = sc_bswap(_mm_loadu_si128((const __m128i *)g->x)); + __m128i e = sc_encrypt1(&g->key, _mm_loadu_si128((const __m128i *)g->j0)); + _mm_storeu_si128((__m128i *)tag, _mm_xor_si128(s, e)); +} + +/* ── Poly1305 ─────────────────────────────────────────────────────────── */ + +#define SC_M44 0xfffffffffffULL +#define SC_M42 0x3ffffffffffULL + +typedef unsigned __int128 sc_u128; + +/* Reduces d0..d2 (each below 2^128) to 44/44/42-bit limbs. */ +static inline void sc_poly_carry(sc_u128 d0, sc_u128 d1, sc_u128 d2, uint64_t h[3]) { + uint64_t c = (uint64_t)(d0 >> 44); + uint64_t h0 = (uint64_t)d0 & SC_M44; + d1 += c; + c = (uint64_t)(d1 >> 44); + uint64_t h1 = (uint64_t)d1 & SC_M44; + d2 += c; + c = (uint64_t)(d2 >> 42); + uint64_t h2 = (uint64_t)d2 & SC_M42; + h0 += c * 5; + c = h0 >> 44; + h0 &= SC_M44; + h1 += c; + h[0] = h0; + h[1] = h1; + h[2] = h2; +} + +/* a · r mod 2^130 - 5 for limbs a and r, accumulated into d. */ +static inline void sc_poly_mul_acc(const uint64_t a[3], const uint64_t r[3], sc_u128 d[3]) { + uint64_t s1 = r[1] * (5 << 2), s2 = r[2] * (5 << 2); + d[0] += (sc_u128)a[0] * r[0] + (sc_u128)a[1] * s2 + (sc_u128)a[2] * s1; + d[1] += (sc_u128)a[0] * r[1] + (sc_u128)a[1] * r[0] + (sc_u128)a[2] * s2; + d[2] += (sc_u128)a[0] * r[2] + (sc_u128)a[1] * r[1] + (sc_u128)a[2] * r[0]; +} + +static inline void sc_poly_limbs(const uint8_t *m, uint64_t hibit, uint64_t out[3]) { + uint64_t t0 = sc_le64(m), t1 = sc_le64(m + 8); + out[0] = t0 & SC_M44; + out[1] = ((t0 >> 44) | (t1 << 20)) & SC_M44; + out[2] = ((t1 >> 24) & SC_M42) | hibit; +} + +/* Four blocks as h = (h + m1)·r^4 + m2·r^3 + m3·r^2 + m4·r, so the four + * products are independent. */ +static inline void sc_poly_step4(const ScCsPoly1305 *p, uint64_t h[3], const uint8_t *m, uint64_t hibit) { + uint64_t a[3], b[3], c[3], e[3]; + sc_poly_limbs(m, hibit, a); + sc_poly_limbs(m + 16, hibit, b); + sc_poly_limbs(m + 32, hibit, c); + sc_poly_limbs(m + 48, hibit, e); + a[0] += h[0]; + a[1] += h[1]; + a[2] += h[2]; + sc_u128 d[3] = {0, 0, 0}; + sc_poly_mul_acc(a, p->r4, d); + sc_poly_mul_acc(b, p->r3, d); + sc_poly_mul_acc(c, p->r2, d); + sc_poly_mul_acc(e, p->r, d); + sc_poly_carry(d[0], d[1], d[2], h); +} + +/* Four blocks per step (sc_poly_step4), then two blocks with r^2 and r; a + * final odd block uses h = (h + m)·r. */ +static void sc_poly_blocks(ScCsPoly1305 *p, const uint8_t *m, size_t len, uint64_t hibit) { + uint64_t h[3] = {p->h[0], p->h[1], p->h[2]}; + while (len >= 64) { + sc_poly_step4(p, h, m, hibit); + m += 64; + len -= 64; + } + while (len >= 32) { + uint64_t a[3], b[3]; + sc_poly_limbs(m, hibit, a); + sc_poly_limbs(m + 16, hibit, b); + a[0] += h[0]; + a[1] += h[1]; + a[2] += h[2]; + sc_u128 d[3] = {0, 0, 0}; + sc_poly_mul_acc(a, p->r2, d); + sc_poly_mul_acc(b, p->r, d); + sc_poly_carry(d[0], d[1], d[2], h); + m += 32; + len -= 32; + } + if (len >= 16) { + uint64_t a[3]; + sc_poly_limbs(m, hibit, a); + a[0] += h[0]; + a[1] += h[1]; + a[2] += h[2]; + sc_u128 d[3] = {0, 0, 0}; + sc_poly_mul_acc(a, p->r, d); + sc_poly_carry(d[0], d[1], d[2], h); + } + p->h[0] = h[0]; + p->h[1] = h[1]; + p->h[2] = h[2]; +} + +/* Eight lanes of 44/44/42-bit limbs in 64-bit elements. */ +typedef struct { + __m512i l0, l1, l2; +} ScPolyVec; + +/* a · r per lane with 52-bit multiply-adds: each 88-bit limb product is + * split into its low and high 52 bits, and the carries move the high parts + * up one limb (2^52 = 2^44 · 2^8, and 2^130 ≡ 5). Inputs below 2^52. */ +SC_IFMA static inline ScPolyVec sc_poly_vmul(ScPolyVec a, ScPolyVec r) { + const __m512i m44 = _mm512_set1_epi64((long long)SC_M44), m42 = _mm512_set1_epi64((long long)SC_M42); + /* s = r · 20 as (r << 4) + (r << 2). */ + __m512i s1 = _mm512_add_epi64(_mm512_slli_epi64(r.l1, 4), _mm512_slli_epi64(r.l1, 2)); + __m512i s2 = _mm512_add_epi64(_mm512_slli_epi64(r.l2, 4), _mm512_slli_epi64(r.l2, 2)); + __m512i z = _mm512_setzero_si512(); + __m512i lo0 = _mm512_madd52lo_epu64(_mm512_madd52lo_epu64(_mm512_madd52lo_epu64(z, a.l0, r.l0), a.l1, s2), a.l2, s1); + __m512i hi0 = _mm512_madd52hi_epu64(_mm512_madd52hi_epu64(_mm512_madd52hi_epu64(z, a.l0, r.l0), a.l1, s2), a.l2, s1); + __m512i lo1 = _mm512_madd52lo_epu64(_mm512_madd52lo_epu64(_mm512_madd52lo_epu64(z, a.l0, r.l1), a.l1, r.l0), a.l2, s2); + __m512i hi1 = _mm512_madd52hi_epu64(_mm512_madd52hi_epu64(_mm512_madd52hi_epu64(z, a.l0, r.l1), a.l1, r.l0), a.l2, s2); + __m512i lo2 = _mm512_madd52lo_epu64(_mm512_madd52lo_epu64(_mm512_madd52lo_epu64(z, a.l0, r.l2), a.l1, r.l1), a.l2, r.l0); + __m512i hi2 = _mm512_madd52hi_epu64(_mm512_madd52hi_epu64(_mm512_madd52hi_epu64(z, a.l0, r.l2), a.l1, r.l1), a.l2, r.l0); + ScPolyVec h; + __m512i c = _mm512_add_epi64(_mm512_srli_epi64(lo0, 44), _mm512_slli_epi64(hi0, 8)); + h.l0 = _mm512_and_si512(lo0, m44); + __m512i t = _mm512_add_epi64(lo1, c); + c = _mm512_add_epi64(_mm512_srli_epi64(t, 44), _mm512_slli_epi64(hi1, 8)); + h.l1 = _mm512_and_si512(t, m44); + t = _mm512_add_epi64(lo2, c); + c = _mm512_add_epi64(_mm512_srli_epi64(t, 42), _mm512_slli_epi64(hi2, 10)); + h.l2 = _mm512_and_si512(t, m42); + h.l0 = _mm512_add_epi64(h.l0, _mm512_add_epi64(c, _mm512_slli_epi64(c, 2))); + c = _mm512_srli_epi64(h.l0, 44); + h.l0 = _mm512_and_si512(h.l0, m44); + h.l1 = _mm512_add_epi64(h.l1, c); + return h; +} + +/* Eight consecutive blocks, block j in lane j. */ +SC_IFMA static inline ScPolyVec sc_poly_vload(const uint8_t *m) { + const __m512i m44 = _mm512_set1_epi64((long long)SC_M44), m42 = _mm512_set1_epi64((long long)SC_M42); + __m512i q0 = _mm512_loadu_si512((const void *)m), q1 = _mm512_loadu_si512((const void *)(m + 64)); + __m512i t0 = _mm512_permutex2var_epi64(q0, _mm512_set_epi64(14, 12, 10, 8, 6, 4, 2, 0), q1); + __m512i t1 = _mm512_permutex2var_epi64(q0, _mm512_set_epi64(15, 13, 11, 9, 7, 5, 3, 1), q1); + ScPolyVec v; + v.l0 = _mm512_and_si512(t0, m44); + v.l1 = _mm512_and_si512(_mm512_or_si512(_mm512_srli_epi64(t0, 44), _mm512_slli_epi64(t1, 20)), m44); + v.l2 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi64(t1, 24), m42), _mm512_set1_epi64(1LL << 40)); + return v; +} + +/* `groups` runs of eight full blocks. Lane j accumulates blocks j, j + 8, + * ... by Horner's rule in r^8, so h = Σ lane_j · r^(8 - j). */ +SC_IFMA static void sc_poly_ifma(ScCsPoly1305 *p, const uint8_t *m, size_t groups) { + const uint64_t (*rp)[3] = (const uint64_t (*)[3])p->rp; + ScPolyVec r8 = {_mm512_set1_epi64((long long)rp[7][0]), _mm512_set1_epi64((long long)rp[7][1]), + _mm512_set1_epi64((long long)rp[7][2])}; + ScPolyVec a = sc_poly_vload(m); + a.l0 = _mm512_add_epi64(a.l0, _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, (long long)p->h[0])); + a.l1 = _mm512_add_epi64(a.l1, _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, (long long)p->h[1])); + a.l2 = _mm512_add_epi64(a.l2, _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, (long long)p->h[2])); + for (size_t g = 1; g < groups; g++) { + a = sc_poly_vmul(a, r8); + ScPolyVec b = sc_poly_vload(m + 128 * g); + a.l0 = _mm512_add_epi64(a.l0, b.l0); + a.l1 = _mm512_add_epi64(a.l1, b.l1); + a.l2 = _mm512_add_epi64(a.l2, b.l2); + } +#define SC_POW(k) _mm512_set_epi64((long long)rp[0][k], (long long)rp[1][k], (long long)rp[2][k], (long long)rp[3][k], \ + (long long)rp[4][k], (long long)rp[5][k], (long long)rp[6][k], (long long)rp[7][k]) + ScPolyVec powers = {SC_POW(0), SC_POW(1), SC_POW(2)}; +#undef SC_POW + a = sc_poly_vmul(a, powers); + sc_poly_carry((sc_u128)(uint64_t)_mm512_reduce_add_epi64(a.l0), (sc_u128)(uint64_t)_mm512_reduce_add_epi64(a.l1), + (sc_u128)(uint64_t)_mm512_reduce_add_epi64(a.l2), p->h); +} + +void scr_cs_poly_start(ScCsPoly1305 *p, const uint8_t key[32]) { + uint64_t t0 = sc_le64(key), t1 = sc_le64(key + 8); + p->r[0] = t0 & 0xffc0fffffffULL; + p->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffffULL; + p->r[2] = (t1 >> 24) & 0x00ffffffc0fULL; + p->h[0] = p->h[1] = p->h[2] = 0; + sc_u128 d[3] = {0, 0, 0}; + sc_poly_mul_acc(p->r, p->r, d); + sc_poly_carry(d[0], d[1], d[2], p->r2); + d[0] = d[1] = d[2] = 0; + sc_poly_mul_acc(p->r2, p->r, d); + sc_poly_carry(d[0], d[1], d[2], p->r3); + d[0] = d[1] = d[2] = 0; + sc_poly_mul_acc(p->r2, p->r2, d); + sc_poly_carry(d[0], d[1], d[2], p->r4); + p->wide = (sc_vector_features() & 4) != 0; + if (p->wide) { + /* rp[k] = r^(k + 1). */ + memcpy(p->rp[0], p->r, sizeof p->r); + for (int k = 1; k < 8; k++) { + d[0] = d[1] = d[2] = 0; + sc_poly_mul_acc(p->rp[k - 1], p->r, d); + sc_poly_carry(d[0], d[1], d[2], p->rp[k]); + } + } + p->pad[0] = sc_le64(key + 16); + p->pad[1] = sc_le64(key + 24); + p->leftover = 0; +} + +void scr_cs_poly_update(ScCsPoly1305 *p, const uint8_t *m, size_t len) { + if (p->leftover) { + size_t take = 16 - p->leftover < len ? 16 - p->leftover : len; + memcpy(p->buf + p->leftover, m, take); + p->leftover += take; + m += take; + len -= take; + if (p->leftover < 16) return; + sc_poly_blocks(p, p->buf, 16, 1ULL << 40); + p->leftover = 0; + } + if (p->wide && len >= 256) { + size_t groups = len / 128; + sc_poly_ifma(p, m, groups); + m += 128 * groups; + len -= 128 * groups; + } + if (len >= 16) { + size_t whole = len & ~(size_t)15; + sc_poly_blocks(p, m, whole, 1ULL << 40); + m += whole; + len -= whole; + } + if (len) { + memcpy(p->buf, m, len); + p->leftover = len; + } +} + +void scr_cs_poly_finish(ScCsPoly1305 *p, uint8_t mac[16]) { + if (p->leftover) { + p->buf[p->leftover] = 1; + memset(p->buf + p->leftover + 1, 0, 15 - p->leftover); + sc_poly_blocks(p, p->buf, 16, 0); + } + uint64_t h0 = p->h[0], h1 = p->h[1], h2 = p->h[2], c; + c = h1 >> 44; h1 &= SC_M44; h2 += c; + c = h2 >> 42; h2 &= SC_M42; h0 += c * 5; + c = h0 >> 44; h0 &= SC_M44; h1 += c; + c = h1 >> 44; h1 &= SC_M44; h2 += c; + c = h2 >> 42; h2 &= SC_M42; h0 += c * 5; + c = h0 >> 44; h0 &= SC_M44; h1 += c; + /* h - p, selected without a branch when it does not underflow. */ + uint64_t g0 = h0 + 5; + c = g0 >> 44; g0 &= SC_M44; + uint64_t g1 = h1 + c; + c = g1 >> 44; g1 &= SC_M44; + uint64_t g2 = h2 + c - (1ULL << 42); + c = (g2 >> 63) - 1; + g0 &= c; g1 &= c; g2 &= c; + c = ~c; + h0 = (h0 & c) | g0; + h1 = (h1 & c) | g1; + h2 = (h2 & c) | g2; + uint64_t t0 = p->pad[0], t1 = p->pad[1]; + h0 += t0 & SC_M44; + c = h0 >> 44; h0 &= SC_M44; + h1 += (((t0 >> 44) | (t1 << 20)) & SC_M44) + c; + c = h1 >> 44; h1 &= SC_M44; + h2 += ((t1 >> 24) & SC_M42) + c; + h2 &= SC_M42; + sc_put_le64(mac, h0 | (h1 << 44)); + sc_put_le64(mac + 8, (h1 >> 20) | (h2 << 24)); + memset(p, 0, sizeof *p); +} + +/* ── ChaCha20 ─────────────────────────────────────────────────────────── */ + +static inline uint32_t sc_rotl(uint32_t v, int n) { + return (v << n) | (v >> (32 - n)); +} + +#define SC_QR(x, a, b, c, d) \ + do { \ + x[a] += x[b]; x[d] = sc_rotl(x[d] ^ x[a], 16); \ + x[c] += x[d]; x[b] = sc_rotl(x[b] ^ x[c], 12); \ + x[a] += x[b]; x[d] = sc_rotl(x[d] ^ x[a], 8); \ + x[c] += x[d]; x[b] = sc_rotl(x[b] ^ x[c], 7); \ + } while (0) + +static void sc_chacha_block(uint32_t state[16], uint8_t out[64]) { + uint32_t x[16]; + memcpy(x, state, sizeof x); + for (int i = 0; i < 10; i++) { + SC_QR(x, 0, 4, 8, 12); + SC_QR(x, 1, 5, 9, 13); + SC_QR(x, 2, 6, 10, 14); + SC_QR(x, 3, 7, 11, 15); + SC_QR(x, 0, 5, 10, 15); + SC_QR(x, 1, 6, 11, 12); + SC_QR(x, 2, 7, 8, 13); + SC_QR(x, 3, 4, 9, 14); + } + for (int i = 0; i < 16; i++) sc_put_le32(out + 4 * i, x[i] + state[i]); + state[12]++; +} + +SC_AVX2 static inline __m256i sc_rotl256(__m256i v, int n) { + return _mm256_or_si256(_mm256_slli_epi32(v, n), _mm256_srli_epi32(v, 32 - n)); +} + +/* Eight blocks with one block per 32-bit lane, then a transpose back to + * byte order. */ +SC_AVX2 static void sc_chacha8(uint32_t state[16], const uint8_t *in, uint8_t *out) { + const __m256i rot16 = _mm256_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2, + 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + const __m256i rot8 = _mm256_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3, + 14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3); + __m256i s[16], x[16]; + for (int j = 0; j < 16; j++) s[j] = _mm256_set1_epi32((int)state[j]); + s[12] = _mm256_add_epi32(s[12], _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)); + for (int j = 0; j < 16; j++) x[j] = s[j]; +#define SC_QR8(a, b, c, d) \ + do { \ + x[a] = _mm256_add_epi32(x[a], x[b]); \ + x[d] = _mm256_shuffle_epi8(_mm256_xor_si256(x[d], x[a]), rot16); \ + x[c] = _mm256_add_epi32(x[c], x[d]); \ + x[b] = sc_rotl256(_mm256_xor_si256(x[b], x[c]), 12); \ + x[a] = _mm256_add_epi32(x[a], x[b]); \ + x[d] = _mm256_shuffle_epi8(_mm256_xor_si256(x[d], x[a]), rot8); \ + x[c] = _mm256_add_epi32(x[c], x[d]); \ + x[b] = sc_rotl256(_mm256_xor_si256(x[b], x[c]), 7); \ + } while (0) + for (int i = 0; i < 10; i++) { + SC_QR8(0, 4, 8, 12); + SC_QR8(1, 5, 9, 13); + SC_QR8(2, 6, 10, 14); + SC_QR8(3, 7, 11, 15); + SC_QR8(0, 5, 10, 15); + SC_QR8(1, 6, 11, 12); + SC_QR8(2, 7, 8, 13); + SC_QR8(3, 4, 9, 14); + } +#undef SC_QR8 + for (int j = 0; j < 16; j++) x[j] = _mm256_add_epi32(x[j], s[j]); + for (int half = 0; half < 2; half++) { + __m256i *a = x + 8 * half; + __m256i t0 = _mm256_unpacklo_epi32(a[0], a[1]), t1 = _mm256_unpackhi_epi32(a[0], a[1]); + __m256i t2 = _mm256_unpacklo_epi32(a[2], a[3]), t3 = _mm256_unpackhi_epi32(a[2], a[3]); + __m256i t4 = _mm256_unpacklo_epi32(a[4], a[5]), t5 = _mm256_unpackhi_epi32(a[4], a[5]); + __m256i t6 = _mm256_unpacklo_epi32(a[6], a[7]), t7 = _mm256_unpackhi_epi32(a[6], a[7]); + __m256i u0 = _mm256_unpacklo_epi64(t0, t2), u1 = _mm256_unpackhi_epi64(t0, t2); + __m256i u2 = _mm256_unpacklo_epi64(t1, t3), u3 = _mm256_unpackhi_epi64(t1, t3); + __m256i u4 = _mm256_unpacklo_epi64(t4, t6), u5 = _mm256_unpackhi_epi64(t4, t6); + __m256i u6 = _mm256_unpacklo_epi64(t5, t7), u7 = _mm256_unpackhi_epi64(t5, t7); + __m256i rows[8] = { + _mm256_permute2x128_si256(u0, u4, 0x20), _mm256_permute2x128_si256(u1, u5, 0x20), + _mm256_permute2x128_si256(u2, u6, 0x20), _mm256_permute2x128_si256(u3, u7, 0x20), + _mm256_permute2x128_si256(u0, u4, 0x31), _mm256_permute2x128_si256(u1, u5, 0x31), + _mm256_permute2x128_si256(u2, u6, 0x31), _mm256_permute2x128_si256(u3, u7, 0x31), + }; + for (int k = 0; k < 8; k++) { + size_t at = 64 * (size_t)k + 32 * (size_t)half; + __m256i d = _mm256_loadu_si256((const __m256i *)(in + at)); + _mm256_storeu_si256((__m256i *)(out + at), _mm256_xor_si256(d, rows[k])); + } + } + state[12] += 8; +} + +/* Sixteen blocks with one block per 32-bit lane. After the rounds, each + * 128-bit lane of a group of four word vectors is transposed so the lane + * holds four words of one block, then the four groups are interleaved by + * 128-bit lane into whole blocks. */ +SC_AVX512 static void sc_chacha16(uint32_t state[16], const uint8_t *in, uint8_t *out) { + __m512i s[16], x[16]; + for (int j = 0; j < 16; j++) s[j] = _mm512_set1_epi32((int)state[j]); + s[12] = _mm512_add_epi32(s[12], _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + for (int j = 0; j < 16; j++) x[j] = s[j]; +#define SC_QR16(a, b, c, d) \ + do { \ + x[a] = _mm512_add_epi32(x[a], x[b]); \ + x[d] = _mm512_rol_epi32(_mm512_xor_si512(x[d], x[a]), 16); \ + x[c] = _mm512_add_epi32(x[c], x[d]); \ + x[b] = _mm512_rol_epi32(_mm512_xor_si512(x[b], x[c]), 12); \ + x[a] = _mm512_add_epi32(x[a], x[b]); \ + x[d] = _mm512_rol_epi32(_mm512_xor_si512(x[d], x[a]), 8); \ + x[c] = _mm512_add_epi32(x[c], x[d]); \ + x[b] = _mm512_rol_epi32(_mm512_xor_si512(x[b], x[c]), 7); \ + } while (0) + for (int i = 0; i < 10; i++) { + SC_QR16(0, 4, 8, 12); + SC_QR16(1, 5, 9, 13); + SC_QR16(2, 6, 10, 14); + SC_QR16(3, 7, 11, 15); + SC_QR16(0, 5, 10, 15); + SC_QR16(1, 6, 11, 12); + SC_QR16(2, 7, 8, 13); + SC_QR16(3, 4, 9, 14); + } +#undef SC_QR16 + for (int j = 0; j < 16; j++) x[j] = _mm512_add_epi32(x[j], s[j]); + /* u[g][i]: lane l holds words 4g..4g+3 of block 4l+i. */ + __m512i u[4][4]; + for (int g = 0; g < 4; g++) { + __m512i *a = x + 4 * g; + __m512i t0 = _mm512_unpacklo_epi32(a[0], a[1]), t1 = _mm512_unpackhi_epi32(a[0], a[1]); + __m512i t2 = _mm512_unpacklo_epi32(a[2], a[3]), t3 = _mm512_unpackhi_epi32(a[2], a[3]); + u[g][0] = _mm512_unpacklo_epi64(t0, t2); + u[g][1] = _mm512_unpackhi_epi64(t0, t2); + u[g][2] = _mm512_unpacklo_epi64(t1, t3); + u[g][3] = _mm512_unpackhi_epi64(t1, t3); + } + for (int i = 0; i < 4; i++) { + __m512i t0 = _mm512_shuffle_i32x4(u[0][i], u[1][i], 0x44), t1 = _mm512_shuffle_i32x4(u[0][i], u[1][i], 0xee); + __m512i t2 = _mm512_shuffle_i32x4(u[2][i], u[3][i], 0x44), t3 = _mm512_shuffle_i32x4(u[2][i], u[3][i], 0xee); + __m512i blocks[4] = { + _mm512_shuffle_i32x4(t0, t2, 0x88), _mm512_shuffle_i32x4(t0, t2, 0xdd), + _mm512_shuffle_i32x4(t1, t3, 0x88), _mm512_shuffle_i32x4(t1, t3, 0xdd), + }; + for (int l = 0; l < 4; l++) { + size_t at = 64 * (size_t)(4 * l + i); + __m512i d = _mm512_loadu_si512((const void *)(in + at)); + _mm512_storeu_si512((void *)(out + at), _mm512_xor_si512(d, blocks[l])); + } + } + state[12] += 16; +} + + +void scr_cs_chacha_start(ScCsChaCha *c, const uint8_t key[32], const uint8_t nonce[12], uint32_t counter) { + c->wide = (sc_vector_features() & 2) != 0; + c->state[0] = 0x61707865; + c->state[1] = 0x3320646e; + c->state[2] = 0x79622d32; + c->state[3] = 0x6b206574; + for (int i = 0; i < 8; i++) c->state[4 + i] = sc_le32(key + 4 * i); + c->state[12] = counter; + for (int i = 0; i < 3; i++) c->state[13 + i] = sc_le32(nonce + 4 * i); + c->used = 64; +} + +void scr_cs_chacha_xor(ScCsChaCha *c, const uint8_t *in, uint8_t *out, size_t len) { + while (c->used < 64 && len > 0) { + *out++ = *in++ ^ c->stream[c->used++]; + len--; + } + while (c->wide && len >= 1024) { + sc_chacha16(c->state, in, out); + in += 1024; + out += 1024; + len -= 1024; + } + while (len >= 512) { + sc_chacha8(c->state, in, out); + in += 512; + out += 512; + len -= 512; + } + while (len >= 64) { + uint8_t block[64]; + sc_chacha_block(c->state, block); + for (int i = 0; i < 64; i++) out[i] = in[i] ^ block[i]; + in += 64; + out += 64; + len -= 64; + } + if (len > 0) { + sc_chacha_block(c->state, c->stream); + for (size_t i = 0; i < len; i++) out[i] = in[i] ^ c->stream[i]; + c->used = len; + } +} + +#else + +bool scr_cs_aes_available(void) { return false; } +bool scr_cs_chacha_available(void) { return false; } +void scr_cs_aes_setkey(ScCsAesKey *enc, ScCsAesKey *dec, const uint8_t *key, size_t key_len) { + (void)enc; (void)dec; (void)key; (void)key_len; +} +void scr_cs_aes_ctr(const ScCsAesKey *key, uint8_t counter[16], uint8_t stream[16], size_t *offset, + const uint8_t *in, uint8_t *out, size_t len) { + (void)key; (void)counter; (void)stream; (void)offset; (void)in; (void)out; (void)len; +} +void scr_cs_aes_cbc_encrypt(const ScCsAesKey *enc, uint8_t iv[16], const uint8_t *in, uint8_t *out, + size_t blocks) { + (void)enc; (void)iv; (void)in; (void)out; (void)blocks; +} +void scr_cs_aes_cbc_decrypt(const ScCsAesKey *dec, uint8_t iv[16], const uint8_t *in, uint8_t *out, + size_t blocks) { + (void)dec; (void)iv; (void)in; (void)out; (void)blocks; +} +void scr_cs_gcm_start(ScCsGcm *g, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len, + bool decrypt) { + (void)g; (void)key; (void)key_len; (void)iv; (void)iv_len; (void)decrypt; +} +bool scr_cs_gcm_aad(ScCsGcm *g, const uint8_t *aad, size_t len) { + (void)g; (void)aad; (void)len; + return false; +} +bool scr_cs_gcm_update(ScCsGcm *g, const uint8_t *in, uint8_t *out, size_t len) { + (void)g; (void)in; (void)out; (void)len; + return false; +} +void scr_cs_gcm_finish(ScCsGcm *g, uint8_t tag[16]) { (void)g; (void)tag; } +void scr_cs_chacha_start(ScCsChaCha *c, const uint8_t key[32], const uint8_t nonce[12], uint32_t counter) { + (void)c; (void)key; (void)nonce; (void)counter; +} +void scr_cs_chacha_xor(ScCsChaCha *c, const uint8_t *in, uint8_t *out, size_t len) { + (void)c; (void)in; (void)out; (void)len; +} +void scr_cs_poly_start(ScCsPoly1305 *p, const uint8_t key[32]) { (void)p; (void)key; } +void scr_cs_poly_update(ScCsPoly1305 *p, const uint8_t *m, size_t len) { (void)p; (void)m; (void)len; } +void scr_cs_poly_finish(ScCsPoly1305 *p, uint8_t mac[16]) { (void)p; (void)mac; } + + +#endif diff --git a/packages/runtime/src/scr_cipher_simd.h b/packages/runtime/src/scr_cipher_simd.h new file mode 100644 index 000000000..82937e107 --- /dev/null +++ b/packages/runtime/src/scr_cipher_simd.h @@ -0,0 +1,102 @@ +/* x86-64 cipher kernels for scr_cipher.c: AES-NI key schedules, CTR and + * CBC; AES-GCM with PCLMULQDQ GHASH, or VAES and VPCLMULQDQ; ChaCha20 (AVX2 or AVX-512F); and + * Poly1305 (scalar, or AVX-512 IFMA). + * scr_cipher.c uses them when scr_cs_aes_available() or + * scr_cs_chacha_available() reports CPU support at run time and the + * mbedTLS implementations otherwise. Both produce the same output; the + * runtime C test checks each against Node-generated vectors. The header + * does not depend on scr_runtime.h so the test can link the unit alone. */ +#ifndef SCR_CIPHER_SIMD_H +#define SCR_CIPHER_SIMD_H + +#include +#include +#include + +/* AES-NI, PCLMULQDQ, SSSE3 and SSE4.1. AES-GCM also uses VAES and + * VPCLMULQDQ with AVX-512BW when they are available. */ +bool scr_cs_aes_available(void); +/* AVX2 with operating-system support for the YMM state. ChaCha20 also + * uses AVX-512F, and Poly1305 AVX-512 IFMA, when they are available. */ +bool scr_cs_chacha_available(void); + +/* An expanded AES key: rounds + 1 round keys of 16 bytes. */ +typedef struct { + uint8_t rk[15 * 16]; + unsigned rounds; +} ScCsAesKey; + +/* Expands a 16, 24 or 32-byte key. `dec` (optional) receives the + * equivalent inverse schedule for decryption. */ +void scr_cs_aes_setkey(ScCsAesKey *enc, ScCsAesKey *dec, const uint8_t *key, size_t key_len); + +/* CTR with a 128-bit big-endian counter, keeping mbedtls_aes_crypt_ctr's + * state: `stream` holds the last keystream block and `*offset` the next + * unused byte in it (0 when a new block is needed). */ +void scr_cs_aes_ctr(const ScCsAesKey *key, uint8_t counter[16], uint8_t stream[16], size_t *offset, + const uint8_t *in, uint8_t *out, size_t len); + +/* CBC over whole blocks; `iv` is updated to the last ciphertext block. */ +void scr_cs_aes_cbc_encrypt(const ScCsAesKey *enc, uint8_t iv[16], const uint8_t *in, uint8_t *out, + size_t blocks); +void scr_cs_aes_cbc_decrypt(const ScCsAesKey *dec, uint8_t iv[16], const uint8_t *in, uint8_t *out, + size_t blocks); + +/* Streaming AES-GCM. AAD must be added before the first non-empty update. */ +typedef struct { + ScCsAesKey key; + uint8_t h[16][16]; /* H^1 .. H^16, byte-reflected */ + uint8_t j0[16]; + uint8_t x[16]; /* GHASH accumulator, byte-reflected */ + uint8_t partial[16]; /* GHASH input not yet folded */ + size_t partial_len; + uint8_t stream[16]; /* keystream block of a partial data block */ + size_t stream_off; /* next unused byte in `stream`; 16 when none */ + uint32_t counter; /* next 32-bit block counter */ + uint64_t aad_len; + uint64_t text_len; + bool decrypt; + bool data; + bool wide; /* VAES and VPCLMULQDQ: sixteen blocks per step */ +} ScCsGcm; + +void scr_cs_gcm_start(ScCsGcm *g, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len, + bool decrypt); +/* AAD and update return false, changing nothing, past GCM's limits: + * 2^61 bytes of AAD and SC_GCM_MAX_TEXT bytes of data. */ +#define SC_GCM_MAX_TEXT 0xFFFFFFFE0ull +bool scr_cs_gcm_aad(ScCsGcm *g, const uint8_t *aad, size_t len); +bool scr_cs_gcm_update(ScCsGcm *g, const uint8_t *in, uint8_t *out, size_t len); +void scr_cs_gcm_finish(ScCsGcm *g, uint8_t tag[16]); + +/* RFC 8439 ChaCha20 with a 32-bit block counter and a 96-bit nonce. */ +typedef struct { + uint32_t state[16]; + uint8_t stream[64]; + size_t used; /* bytes of `stream` already used; 64 when none are left */ + bool wide; /* AVX-512F: sixteen blocks per step instead of eight */ +} ScCsChaCha; + +void scr_cs_chacha_start(ScCsChaCha *c, const uint8_t key[32], const uint8_t nonce[12], uint32_t counter); +void scr_cs_chacha_xor(ScCsChaCha *c, const uint8_t *in, uint8_t *out, size_t len); + +/* Poly1305 with 44-bit limbs; eight lanes with AVX-512 IFMA when available. */ +typedef struct { + uint64_t r[3]; + uint64_t r2[3]; /* r^2, r^3 and r^4, partially reduced */ + uint64_t r3[3]; + uint64_t r4[3]; + uint64_t h[3]; + uint64_t pad[2]; + uint64_t rp[8][3]; /* r^1 .. r^8 for the AVX-512 IFMA kernel */ + uint8_t buf[16]; + size_t leftover; + bool wide; /* AVX-512 IFMA: eight blocks per step */ +} ScCsPoly1305; + +void scr_cs_poly_start(ScCsPoly1305 *p, const uint8_t key[32]); +void scr_cs_poly_update(ScCsPoly1305 *p, const uint8_t *m, size_t len); +void scr_cs_poly_finish(ScCsPoly1305 *p, uint8_t mac[16]); + + +#endif diff --git a/packages/runtime/test/cipher-cases.txt b/packages/runtime/test/cipher-cases.txt new file mode 100644 index 000000000..7b9f9e68f --- /dev/null +++ b/packages/runtime/test/cipher-cases.txt @@ -0,0 +1,500 @@ +aes-128-cbc 1 c6e504234261809fbeddfc1b3a597897 0 0 21c9c35357dab5313e4c92d910dc7cb4799841a238676be90c9d2614f80a1fcf - +aes-128-cbc 2 cdec0b2a496887a6c5e4032241607f9e 0 1 57ab65c7a41de6ec2b69e2c172837e4d209d66bfc44e4e2ee7a60c54cb8d04de - +aes-128-cbc 3 d4f31231506f8eadcceb0a29486786a5 0 15 0786fea5548e965991a0d78bfead972351557814a3727f2f3bc9efd0eb60b55c - +aes-128-cbc 4 dbfa1938577695b4d3f211304f6e8dac 0 16 fda8b61a893e1a29c618bd29281087c9897cae1d6803fddbad8883fd03908560 - +aes-128-cbc 5 e201203f5e7d9cbbdaf91837567594b3 0 17 4ed70bae6eb588338051d98dfd22b2a5373b32504e4d1420e8f36a17c245750a - +aes-128-cbc 6 e90827466584a3c2e1001f3e5d7c9bba 0 63 91a1db29d19aaf60f54f2a74eafdcbc0ea2be1e116363d7689dc47309d658fcc - +aes-128-cbc 7 f00f2e4d6c8baac9e80726456483a2c1 0 64 7bb9b80f88756635b88c945e10c89086c4a46f14cd59a7f7a01c8f3a1e60570f - +aes-128-cbc 8 f71635547392b1d0ef0e2d4c6b8aa9c8 0 65 a5e3efc9b11e2f103689560adfbd275c8e181e19f72af76e06942e36015c31ea - +aes-128-cbc 9 fe1d3c5b7a99b8d7f61534537291b0cf 0 127 7a069da4cdeb3355322f038e41c583e2c38b555ab7c63446e3904ae6f7cf9a77 - +aes-128-cbc 10 0524436281a0bfdefd1c3b5a7998b7d6 0 128 ff13800bc411a065cc0deff771450881f533ad7a7e8bfe9587ccc30a59870b88 - +aes-128-cbc 11 0c2b4a6988a7c6e504234261809fbedd 0 129 017f14a58002c5e4a95686688e8e1009c616e912c9ab7094d045a02685281552 - +aes-128-cbc 12 133251708faecdec0b2a496887a6c5e4 0 255 2293a8a4f584fdb069dbf138e32c4fa2abdf6161f69187690e133d8ad637db06 - +aes-128-cbc 13 1a39587796b5d4f31231506f8eadcceb 0 256 6d010acfc4009bfa1c3874293e652b97b3717141f7e0b6a88c902c5f1066a236 - +aes-128-cbc 14 21405f7e9dbcdbfa1938577695b4d3f2 0 511 6718d9b09720949f8f6f7d00ccf2fd618032d8c7c288c26212811f2a0926a8f3 - +aes-128-cbc 15 28476685a4c3e201203f5e7d9cbbdaf9 0 512 8321e36bef4cba57b08ea35d865ff9ef064f811a4feccdcb700de712eb5d7cca - +aes-128-cbc 16 2f4e6d8cabcae90827466584a3c2e100 0 513 be34bc5970a93a3c24115e3e45814bb827a3da2d0ea2af768f2001d42c6876a3 - +aes-128-cbc 17 36557493b2d1f00f2e4d6c8baac9e807 0 1023 79401858f25fa82ae47b79e4a95b94eb510a181fdb72e6fe53ac3459a63ceead - +aes-128-cbc 18 3d5c7b9ab9d8f71635547392b1d0ef0e 0 1024 c9d603c257dae7112f66a2f7fc37f4f91b0f0e13650080c9bb62aa7d812c0893 - +aes-128-cbc 19 446382a1c0dffe1d3c5b7a99b8d7f615 0 1025 70ee4ec56bcbc4b3ef0eb6a5bbeb0918003a5a26befe37ef8e401717e25e78c1 - +aes-128-cbc 20 4b6a89a8c7e60524436281a0bfdefd1c 0 4103 eb356d61b78d1f75ac8c8177bd39f9d8dcc566d3d54b007f145328303178ace9 - +aes-192-cbc 21 527190afceed0c2b4a6988a7c6e50423 0 0 886e45d69bd51c80857c2697dd4777bcbdb3a49f14bce482147783dbd4397ae7 - +aes-192-cbc 22 597897b6d5f4133251708faecdec0b2a 0 1 fb8d1aa5d342de87237e0ccfa19da827d62bd27a071be3dbd8c4c6d7af48fa3c - +aes-192-cbc 23 607f9ebddcfb1a39587796b5d4f31231 0 15 c82ffbfa31baa6180242cc35e945aad4116c84b7048e2def117ee4b61a88465e - +aes-192-cbc 24 6786a5c4e30221405f7e9dbcdbfa1938 0 16 c66987b1fa1821de6d05045bf921bcb25bafb36eae3b8f85442510d494f9db14 - +aes-192-cbc 25 6e8daccbea0928476685a4c3e201203f 0 17 7eca4fd1e34a575c733084dea0968e6433397713f2cb82a42f27c5ac9bfb4bfe - +aes-192-cbc 26 7594b3d2f1102f4e6d8cabcae9082746 0 63 5a3f29116b25f9f94eab0e8e8ab87852217074a2ede933f0e2a8d424b14fa8da - +aes-192-cbc 27 7c9bbad9f81736557493b2d1f00f2e4d 0 64 74685a84a0bf2f2b3b1c6550544d3c454222dd178279b3c04835b4adcb3f2cfb - +aes-192-cbc 28 83a2c1e0ff1e3d5c7b9ab9d8f7163554 0 65 44cc242153a0b90bb1405f600fbc349a6c16cdfed98a059658dc0b75c9e5c891 - +aes-192-cbc 29 8aa9c8e70625446382a1c0dffe1d3c5b 0 127 183a4dc6a6deaaebdd5f42cc582a90e1d2301de45f008cd8a5015cc4a9c869bb - +aes-192-cbc 30 91b0cfee0d2c4b6a89a8c7e605244362 0 128 0066af0d4019340f0dccd414d79d6736085d4587bd713ab1f2763deb422b0e60 - +aes-192-cbc 31 98b7d6f51433527190afceed0c2b4a69 0 129 bbdff39333fe6cd635d009726a7dc45ac6f5a494569f6dac2eaa7205a2cb6f8c - +aes-192-cbc 32 9fbeddfc1b3a597897b6d5f413325170 0 255 3a258fc2c16fa0dbb1bc68a33d7145593d96f3c57da7ef89db49fb235241615b - +aes-192-cbc 33 a6c5e4032241607f9ebddcfb1a395877 0 256 e5f1c6c6360e3f84e57d35fad31e93299172e448797f1cb0d95b9ee541240c88 - +aes-192-cbc 34 adcceb0a29486786a5c4e30221405f7e 0 511 c856128fa1fcdf3e8bd4909dfcd718ab2071997623dab7fcb20d7876167a743d - +aes-192-cbc 35 b4d3f211304f6e8daccbea0928476685 0 512 2f65a9f23eabb436c0feb6edf6b9fa7b197969c3c5bc4afdd2de540ad72ae48d - +aes-192-cbc 36 bbdaf91837567594b3d2f1102f4e6d8c 0 513 c06e6ae447a476f2e27cfa21f2ce5857f38a8b790dc4cd96cc536dc6e83c81e6 - +aes-192-cbc 37 c2e1001f3e5d7c9bbad9f81736557493 0 1023 39ce09b34aacb348c552702e18fade2b74f634f67548b8d06b99b7ab324e24c9 - +aes-192-cbc 38 c9e80726456483a2c1e0ff1e3d5c7b9a 0 1024 7141eff6acbdbe1737fa7b83acfd0422383196e27372b078ae857c1e7cfd6e7f - +aes-192-cbc 39 d0ef0e2d4c6b8aa9c8e70625446382a1 0 1025 d38d5b924c08513fd5d468c13765f3d6f57dc5fc47fb0498871b02e3e04481d9 - +aes-192-cbc 40 d7f61534537291b0cfee0d2c4b6a89a8 0 4103 d2cf123487156e3bef5e19c04c2f9dfd4a19f533d0bc8cc4996e9d4378f9c8b1 - +aes-256-cbc 41 defd1c3b5a7998b7d6f51433527190af 0 0 8b581289ba19368eb316c092b6fedc8522604eaabf17cb29c8c4b27c893cf43e - +aes-256-cbc 42 e504234261809fbeddfc1b3a597897b6 0 1 f08c49a88016f8a537255c0123efd03e98dd6c59a0d647823658019a2873d5d3 - +aes-256-cbc 43 ec0b2a496887a6c5e4032241607f9ebd 0 15 5886418f0fc399d8b971cdff9c3a509120a298a632bdc774428f2ee97beb86bd - +aes-256-cbc 44 f31231506f8eadcceb0a29486786a5c4 0 16 721a512c90793eb3a4ecfa56f551782d67d5ff0d3dfe93fad00ff24a654d2885 - +aes-256-cbc 45 fa1938577695b4d3f211304f6e8daccb 0 17 0ebd734281dc5867fbe8ac1935288cd603a66b22fea56cbe126a3b4b7886b48d - +aes-256-cbc 46 01203f5e7d9cbbdaf91837567594b3d2 0 63 f0f289706e26bd426c88c6c7712af2972b4ecb2184a9e61ec4625a1db857c23f - +aes-256-cbc 47 0827466584a3c2e1001f3e5d7c9bbad9 0 64 40a0ca6909d3404c0e3a424c45de079ec42dccbe294217942539e7eb07427da3 - +aes-256-cbc 48 0f2e4d6c8baac9e80726456483a2c1e0 0 65 e02a61589a478ddc0347e237f7875dec9c6d09607b638780002ead27f70423a8 - +aes-256-cbc 49 1635547392b1d0ef0e2d4c6b8aa9c8e7 0 127 5bddd75301eb241baa13fc1a00026e073fc4620ed6f24bc1e0e293ca4fda9053 - +aes-256-cbc 50 1d3c5b7a99b8d7f61534537291b0cfee 0 128 8e8fc03d10c431543dd1d9f4d7743b41dcc1dc9b7d6aff91a72bd19fa23c2de2 - +aes-256-cbc 51 24436281a0bfdefd1c3b5a7998b7d6f5 0 129 ac98b913335c2d3079d010fdcfb462e1bd7592c72bcd97f3857def8c8ee585c9 - +aes-256-cbc 52 2b4a6988a7c6e504234261809fbeddfc 0 255 3da21c0c3fd9502985446f233804986109c0b49b0d3d2b0e166f10c05af7d22e - +aes-256-cbc 53 3251708faecdec0b2a496887a6c5e403 0 256 69ce913274a0680118da18d1eb23f98c69a45026f77025bcef778d5a939f3473 - +aes-256-cbc 54 39587796b5d4f31231506f8eadcceb0a 0 511 33fdfdab202e26b8f376c081034b088988b23826a5ad1c5897b28ed28f691178 - +aes-256-cbc 55 405f7e9dbcdbfa1938577695b4d3f211 0 512 8d6e081a0bbe7ff3262a7a83bc5c640171d4f2eebe6dcb3227da302e775ede38 - +aes-256-cbc 56 476685a4c3e201203f5e7d9cbbdaf918 0 513 e81f3064227dde5c54809bbcf3c4dc7f095e0a53f5da99c6d20dfe1203f9d15b - +aes-256-cbc 57 4e6d8cabcae90827466584a3c2e1001f 0 1023 dc91995f3b092603e1a31566a4cbe06fa90539f46e000faebf2b8a2f5f1fd2fe - +aes-256-cbc 58 557493b2d1f00f2e4d6c8baac9e80726 0 1024 39a6265fa6d9f1eca4ddeee862e74e8c37fb67a908448f1ba360b1f1c489719d - +aes-256-cbc 59 5c7b9ab9d8f71635547392b1d0ef0e2d 0 1025 d9f630413f89d97abbb707f1dea7784de17e69ec08fb027320539be9e0ab4c5e - +aes-256-cbc 60 6382a1c0dffe1d3c5b7a99b8d7f61534 0 4103 cf38774ade5637efc189a192031624ed2457cb3922b551b09ceff75def703879 - +aes-128-ctr 61 6a89a8c7e60524436281a0bfdefd1c3b 0 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - +aes-128-ctr 62 7190afceed0c2b4a6988a7c6e5042342 0 1 f8d20e598df20877e4d826246fc31ffb4615cbc059aec9ec8e5b28951d844a3f - +aes-128-ctr 63 7897b6d5f4133251708faecdec0b2a49 0 15 b841e445f5ba65ef9d45c6f6990cb8dfb7fd97160ff2901d3beac032bd92b762 - +aes-128-ctr 64 7f9ebddcfb1a39587796b5d4f3123150 0 16 50636f4dad62f1fcf5e303d038c9da21344dd31a21e27af79e3585e34f8e43d3 - +aes-128-ctr 65 86a5c4e30221405f7e9dbcdbfa193857 0 17 8d9fb4ecaa1a033d9aeb454538ddca705f5ad7dc7aaada4c40fa8d5d72ed0e31 - +aes-128-ctr 66 8daccbea0928476685a4c3e201203f5e 0 63 85778e938b5f5ea657846b23a129e1ab5371df076ac8b11b08b303e3ce3fd71a - +aes-128-ctr 67 94b3d2f1102f4e6d8cabcae908274665 0 64 550b6a414c78b4645611f7c9650d54db6466374e125d488c0f9a6695c75ce24c - +aes-128-ctr 68 9bbad9f81736557493b2d1f00f2e4d6c 0 65 a9ee34451bc56edd246fd75e16942e268f6a4f066e4d13744b2b8f2f7f9492ad - +aes-128-ctr 69 a2c1e0ff1e3d5c7b9ab9d8f716355473 0 127 81532e555e4fbc2e3cb61d20fdee9513d11ebc88b2b4e53a9a652d662eeddd48 - +aes-128-ctr 70 a9c8e70625446382a1c0dffe1d3c5b7a 0 128 95f850136ce9e744721506ca5eed51984166fb440d073c5c8fc414fd14e731a8 - +aes-128-ctr 71 b0cfee0d2c4b6a89a8c7e60524436281 0 129 616ded85063182d2cd447972a3393d961fce17aafc9823ff21858edf5b106086 - +aes-128-ctr 72 b7d6f51433527190afceed0c2b4a6988 0 255 cad7bbbbbeec9720f5fe77fa692a6da699826b84e8033c368bfa05addebbc289 - +aes-128-ctr 73 beddfc1b3a597897b6d5f4133251708f 0 256 640a26dc5519b06a1d2b209cf9791df2c7a8b264e46bd5c9d72dc01c8b41da81 - +aes-128-ctr 74 c5e4032241607f9ebddcfb1a39587796 0 511 366c38323f63e5a7885142b5d80a75657112e8a0c703af1e668a34e5cf50ad6f - +aes-128-ctr 75 cceb0a29486786a5c4e30221405f7e9d 0 512 c5b77b22ba12381c09788fb2a4deeb1fe6338a8912ddedb85ccf2e882a4f587d - +aes-128-ctr 76 d3f211304f6e8daccbea0928476685a4 0 513 83a8bda41b818de83a6e87b85cc60c9a3ef3353bc181a003ef0eff643d6d5396 - +aes-128-ctr 77 daf91837567594b3d2f1102f4e6d8cab 0 1023 2cee4739cc36481875c05cb3f8f678c49d201a57792bd88eef170de2c69ebab8 - +aes-128-ctr 78 e1001f3e5d7c9bbad9f81736557493b2 0 1024 2ad27fc6ef21ec018e979f3d09187b7ff99bd8b973e165222dbf14240d4fb706 - +aes-128-ctr 79 e80726456483a2c1e0ff1e3d5c7b9ab9 0 1025 84481322b7dccf4a64c6759e7fbae022dba00dd184dbd84cbb313c2c5a2dcdae - +aes-128-ctr 80 ef0e2d4c6b8aa9c8e70625446382a1c0 0 4103 bbdb84cd47365022b598a8ef007df26848ab05656fc46eaf33fc86cc34363b1b - +aes-192-ctr 81 f61534537291b0cfee0d2c4b6a89a8c7 0 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - +aes-192-ctr 82 fd1c3b5a7998b7d6f51433527190afce 0 1 32ebb1abcc1c601ceb9c4e3c4faba0caa5b85bb98c4f1e6612c40faa528a91c9 - +aes-192-ctr 83 04234261809fbeddfc1b3a597897b6d5 0 15 6135c2ee480b741ebf7b7afc08f7b8b69fcfbfe0ff1063210765bf74e66bedfe - +aes-192-ctr 84 0b2a496887a6c5e4032241607f9ebddc 0 16 e379f33bfbb7d609c6c17ffe1ac6b83d7f06b2a0312af2edf40acfca8831b07d - +aes-192-ctr 85 1231506f8eadcceb0a29486786a5c4e3 0 17 974dbd0ea0ba19e664883cc387170713bdb77568271fd396743a4fab4ed1701c - +aes-192-ctr 86 1938577695b4d3f211304f6e8daccbea 0 63 975784a36612825422a385ee2d488922bbd4c593dd965974383307fbaa56e7c3 - +aes-192-ctr 87 203f5e7d9cbbdaf91837567594b3d2f1 0 64 4d782b8af8e879f3656a0e9bb24b1a8b67ebeb6dfd172f9df57a9ddf58e22c27 - +aes-192-ctr 88 27466584a3c2e1001f3e5d7c9bbad9f8 0 65 a213ca92bdc5cf4952aa70d7e1aca63ccba8c63a907379eaa16056444a8f2baa - +aes-192-ctr 89 2e4d6c8baac9e80726456483a2c1e0ff 0 127 e92531ca51542fdc0c8e4699f1a307075fdff3178eacc1c1910e8b3aed230d62 - +aes-192-ctr 90 35547392b1d0ef0e2d4c6b8aa9c8e706 0 128 5c06670ac6db1f84e461d6a3f6bd68da54a1bfa4a39743701a7b6d36a452c4be - +aes-192-ctr 91 3c5b7a99b8d7f61534537291b0cfee0d 0 129 eb86ce81bbdbf592f9edbf0dce4f731a72e6b793f9f52cf53058d0e1c2694164 - +aes-192-ctr 92 436281a0bfdefd1c3b5a7998b7d6f514 0 255 4d225751eadfab7b894b933f08ae235f4ad9d73677493cdd16f71a742e3c56ca - +aes-192-ctr 93 4a6988a7c6e504234261809fbeddfc1b 0 256 dea137b4ae11d7256bab412514fe9b0acf7bf68f1205b58f8b59e5d39d6205ef - +aes-192-ctr 94 51708faecdec0b2a496887a6c5e40322 0 511 432d329f9897df47b9d324076ee457396e746b0c4c5d945bd976e783d0cdde8a - +aes-192-ctr 95 587796b5d4f31231506f8eadcceb0a29 0 512 304eb9fbf37d575a6848f3faa5921dc4098393eead892a2e96ef6fc3ddcae3d5 - +aes-192-ctr 96 5f7e9dbcdbfa1938577695b4d3f21130 0 513 031f79397c302192ff86a4130c109be7a26543fb7e8cf381740840a2e96127ee - +aes-192-ctr 97 6685a4c3e201203f5e7d9cbbdaf91837 0 1023 bcbd283fb3fd8425d91c7de213622e252e01b079706394d454c4b1e2e33eb16b - +aes-192-ctr 98 6d8cabcae90827466584a3c2e1001f3e 0 1024 412145d1e768b6c973b3e5110145d497c491731c0717114700e239478ab88729 - +aes-192-ctr 99 7493b2d1f00f2e4d6c8baac9e8072645 0 1025 1c91eee5b21e554fb86bac4026c0bcc61582b085e24573a6f7458eb32938835e - +aes-192-ctr 100 7b9ab9d8f71635547392b1d0ef0e2d4c 0 4103 dc3c2ac10772d68735fb2f6cea0600a4a2aca9175bcbd6c85b4cd12da97f0112 - +aes-256-ctr 101 82a1c0dffe1d3c5b7a99b8d7f6153453 0 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - +aes-256-ctr 102 89a8c7e60524436281a0bfdefd1c3b5a 0 1 414a21e525a759e3ffeb22556be6348a92d5a13e40b61a0805f36f18c2909513 - +aes-256-ctr 103 90afceed0c2b4a6988a7c6e504234261 0 15 9ec5641491fd6f5d71c56b53a53adab80aefc668841b5a788eedd5b7ddd618f6 - +aes-256-ctr 104 97b6d5f4133251708faecdec0b2a4968 0 16 16bd0a285ef8425c5154218fc584f66bf64316a56b84c823a86c31931d62264c - +aes-256-ctr 105 9ebddcfb1a39587796b5d4f31231506f 0 17 be2c06f918687bb134f0010cdca76e531314432943565ed6643675534e596eef - +aes-256-ctr 106 a5c4e30221405f7e9dbcdbfa19385776 0 63 3ccdda46943506553ee58c9bb3bc64bf070e3fafac298b20b22a5d2d8a584d54 - +aes-256-ctr 107 accbea0928476685a4c3e201203f5e7d 0 64 8e97522c6d9a2d58f3566d8d5de3923551e2c7ebca704526441e2ecd8fee5515 - +aes-256-ctr 108 b3d2f1102f4e6d8cabcae90827466584 0 65 e36c9223ac003ea19eb804ad01c8c5ea31d557b67f7e400f4e57e512fcf2177b - +aes-256-ctr 109 bad9f81736557493b2d1f00f2e4d6c8b 0 127 810e74b365e16cb2bf79c20d9dd224858ef5b6725bd003aab00fe6e45ce7f016 - +aes-256-ctr 110 c1e0ff1e3d5c7b9ab9d8f71635547392 0 128 df18293df5e3f66b49ee463f7dd1529806ded11db30f34be6414baf068f53cb2 - +aes-256-ctr 111 c8e70625446382a1c0dffe1d3c5b7a99 0 129 dd545eaed9a8f4fdec5866582ec1eecd862eaca591cecbd97e0478c4ca7003e8 - +aes-256-ctr 112 cfee0d2c4b6a89a8c7e60524436281a0 0 255 83770a857fe0e47b71829388ad5511f9ab8176d1fa793626990452202ac4530a - +aes-256-ctr 113 d6f51433527190afceed0c2b4a6988a7 0 256 48d833c2e6a046523de77634d75246169e616b6e1d21e148d0543617dbc05343 - +aes-256-ctr 114 ddfc1b3a597897b6d5f4133251708fae 0 511 006ad08f4cbf314fa52e62e99f873b07f9258ffca8001b73da731899d6020266 - +aes-256-ctr 115 e4032241607f9ebddcfb1a39587796b5 0 512 33cb494c3eebca642d9a14e7101e956ecfcf492ba454d672d8bee3be401b5b44 - +aes-256-ctr 116 eb0a29486786a5c4e30221405f7e9dbc 0 513 3c6889c7300748ca0ea4bb73d29ab7bf200f2d432a42edc63f2bb48d985ca616 - +aes-256-ctr 117 f211304f6e8daccbea0928476685a4c3 0 1023 f90142b81957675db85fd801ce77d7ad2ead8765a309f73f59f44980e55e32f1 - +aes-256-ctr 118 f91837567594b3d2f1102f4e6d8cabca 0 1024 f30cd6791e60eca4d226602a1461a0bac00009b587db80d15d60516244b9fa9b - +aes-256-ctr 119 001f3e5d7c9bbad9f81736557493b2d1 0 1025 9e2db8787a58dd36b0d910871259badc98853d337e53e5c3dc3a57b1d3ab8056 - +aes-256-ctr 120 0726456483a2c1e0ff1e3d5c7b9ab9d8 0 4103 850035fd64ecdf43c266ccbcef508b64054c70859622fb4ff792afb458b9826e - +aes-128-gcm 121 0e2d4c6b8aa9c8e706254463 0 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 e21a43baa8709b5d1569dc25817ee6d6 +aes-128-gcm 122 1534537291b0cfee0d2c4b6a 1 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 a73da95ddb14d9648f5c9c435ac61103 +aes-128-gcm 123 1c3b5a7998b7d6f514335271 16 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 b6c3e97b5174046157e83c99dfcbbf8c +aes-128-gcm 124 234261809fbeddfc1b3a5978 33 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 a238720a3d10b2c6060813c8ceaf036c +aes-128-gcm 125 2a496887a6c5e4032241607f 0 1 a25513c7e0f6eaa80a3337ee18081b9e2ed09e00af8531c8f7bb2542764027e7 fb06a63b13ec4cb40b9d6dd72f2df4fc +aes-128-gcm 126 31506f8eadcceb0a29486786 1 1 d10b36aa74a59bcf4a88185837f658afaf3646eff2bb16c3928d0e9335e945d2 a4ce66834d23ba6122272ffae730d047 +aes-128-gcm 127 38577695b4d3f211304f6e8d 16 1 a9f51566bd6705f7ea6ad54bb9deb449f795582d6529a0e22207b8981233ec58 a3e4454fc432dbf9ca4cff9a4f5b219c +aes-128-gcm 128 3f5e7d9cbbdaf91837567594 33 1 c3641f8544d7c02f3580b07c0f9887f0c6a27ff5ab1d4a3e29caf197cfc299ae e147e8bfd72fec263c5ad8c797fca11c +aes-128-gcm 129 466584a3c2e1001f3e5d7c9b 0 15 0577522dbae5f72e2a6d7853d2852e0715bca9c4ae8376bd0530d78a4c4ac8b8 8af736a4a8e64e0ee9cd409e4c00664b +aes-128-gcm 130 4d6c8baac9e80726456483a2 1 15 95fa9e1e98c887cef7becfd4fe3a15f55c6cac34e8df353b88b054e6757b9bbf 747ce28481a10016ce81d70c42ffa81a +aes-128-gcm 131 547392b1d0ef0e2d4c6b8aa9 16 15 2cc9eaa0df91dd1140c8ca980ca865bbfac014ab113a3cd21d8c84c30d5a19b7 197e0cdf5ab20cde4a087fb53e863f92 +aes-128-gcm 132 5b7a99b8d7f61534537291b0 33 15 c4e5febef07220ba1b514538ca3740194d6d438f54029e972f372a9432e9f2b4 d4c6fb7a1393e20d89c40cf52d21f97c +aes-128-gcm 133 6281a0bfdefd1c3b5a7998b7 0 16 2b3326ad354369270ef5f988b785f49204f762b2108bfed951ecfec3b9ed6192 80c0fcbbc5d6ac663b7c8f0c5359a44a +aes-128-gcm 134 6988a7c6e504234261809fbe 1 16 ac7f8e6031bc8e9e9dc16b5862ffe2a669d21b36144e876bea448f7eced851c7 469ed721e52d62fe35b54249eb39df7c +aes-128-gcm 135 708faecdec0b2a496887a6c5 16 16 97f8bc2e2725df3e869927c324fb3f40e54112ee43bea10b5fd4689d7db46793 9480ad6b9cbfd097603824f7d0760d1a +aes-128-gcm 136 7796b5d4f31231506f8eadcc 33 16 13248dc30081e34dbd24cd54570c81e01bfe01fead6a0a20021f0a8de136eb85 66b21b0f69a3e1b6d9746a8c517ca204 +aes-128-gcm 137 7e9dbcdbfa1938577695b4d3 0 17 2add0ca8335314fbbe18a9574167a0eaeab3ea26c39ac8396ad23475db020fd7 44ec9d54c1871852f1052a26e8de62bc +aes-128-gcm 138 85a4c3e201203f5e7d9cbbda 1 17 017adcbc139cf8b39d895f3c92de85781fbd676136bc352ae46329a61f152541 7b3adcaacaa0049478df891e393c4418 +aes-128-gcm 139 8cabcae90827466584a3c2e1 16 17 252f27ead799a7f153615871e5a3eadb094f8b9bdf5f96e8ebdce9f1507974a6 c346282c233879c63923535a76d09a73 +aes-128-gcm 140 93b2d1f00f2e4d6c8baac9e8 33 17 167471eb63027d96b7146080e461fc01129d7ec313e39455969f0716c9fd90a8 7cd29b67c5e2b49b144dda38cbb5d3ef +aes-128-gcm 141 9ab9d8f71635547392b1d0ef 0 63 8157df2195d925ab9dd0a1a3a7a58e495d92ede00564c517786549e08ca3dd6e 8fe82c9f277301f77426261f11c63ca4 +aes-128-gcm 142 a1c0dffe1d3c5b7a99b8d7f6 1 63 4bb2a833df4b8209d9282e8aecdcbddf6a64e1ee3b38d031304b17d216278549 57c3687f2e2e74a20df57a70be7f43fe +aes-128-gcm 143 a8c7e60524436281a0bfdefd 16 63 ad00899813ce5b2d8570bf50aa884c7a7a7a4e7a7b883053f209b063617564b0 19b0951e917d8326b59657ca4ffcdf5e +aes-128-gcm 144 afceed0c2b4a6988a7c6e504 33 63 72f9dfb4bececf27d2a951cb17b4a3494ed200deb3d96206889417eaed8d13ac 0d496c8aee2db7189b3b339501fb4a93 +aes-128-gcm 145 b6d5f4133251708faecdec0b 0 64 31fa94c31bdf9e0f453ddfa10e29ee5e82810b8ce0649ac9d2f7a2dbd3627cae 1222a2c4f2b6764a6eae2a7b58b678fd +aes-128-gcm 146 bddcfb1a39587796b5d4f312 1 64 19922f2c79eb6be60f0e2d6a02ab39841bf64b2befd0430201c3e4ddfa2323d4 e125e716b0450f3bf14bbf9c07c38468 +aes-128-gcm 147 c4e30221405f7e9dbcdbfa19 16 64 d540467c8d261c46bebc3d06d43149cf794c4eb8ba720e2dabf297b5b29a5059 379c9df26a6ae9fd12d51b685e9b385f +aes-128-gcm 148 cbea0928476685a4c3e20120 33 64 3a2c19cadac78f999784498d763ec0446b5ba2bbdd1420893b6aaa04ce4a398e 6ae77ae25874ab61b1243a339a9ba9bd +aes-128-gcm 149 d2f1102f4e6d8cabcae90827 0 65 a0957b4a7f1881d11b13ae3a4761f3b9332f50409262af3af1bf68de26b4d602 6020434b505d03767684f6a1ccee449d +aes-128-gcm 150 d9f81736557493b2d1f00f2e 1 65 9c2cb644121e9081addd01cc51637c8e69c752d96b3a3c00cd321874195b712d a2498b90a72a19a0ca76b8a855ea6bc9 +aes-128-gcm 151 e0ff1e3d5c7b9ab9d8f71635 16 65 6d51bb5dbbd99197aa80928f59fb9af0ed89a92421a6b3c06b37dfe0ed6932c3 9afea83b67dbb2cf508d5c5eec8c3ce6 +aes-128-gcm 152 e70625446382a1c0dffe1d3c 33 65 0967ed12efe9d6fccfcdc486e3c15aef44913495d82e1d0cadfb4ff3478138a0 67bf39177b823356080e8390d721cc7f +aes-128-gcm 153 ee0d2c4b6a89a8c7e6052443 0 127 0b92f091af85e7ef677f912461cf7f4834fbcabdba8b34c068de7d5e983bdc8d 608a78dc0cf161c82959a8a4a2455ff5 +aes-128-gcm 154 f51433527190afceed0c2b4a 1 127 346cc1914c5b576cb292ac241b000672d5f9472b47b8b6d8b05acc0e90234dfa 21f2fd61bfe07262e755d84ec0da3c62 +aes-128-gcm 155 fc1b3a597897b6d5f4133251 16 127 040912a9bcd8e9cc8887c389a917f2ef11e478454716f003153fe70d3f7f3004 4e6eaa58c124357dd6efb70dcd7adab7 +aes-128-gcm 156 032241607f9ebddcfb1a3958 33 127 05de55c978dc53278fb2052e32b6473d787995226b0348c2a129063cf462d4e0 901d1ee20d8808423714cc42f75c88f0 +aes-128-gcm 157 0a29486786a5c4e30221405f 0 128 4081360aff5e8b0617d2f3ba6128e430494b327c6ddb709c9f62dd36d7c783ee a4a5c6ad90da7ddab9cb9f767dc2f170 +aes-128-gcm 158 11304f6e8daccbea09284766 1 128 133a74549b6caeff4ede038241c2ff26cf94212b35e8ac3cf7c73df1cea9c4c9 9543b1ac85e590e300cbb2c764ce119b +aes-128-gcm 159 1837567594b3d2f1102f4e6d 16 128 5df49be0f0f90856f8f79b2df143bcb3bd0625600f84000c19cca056f90a0ecc 59c198d9dc5c38da21647c99ae58ed92 +aes-128-gcm 160 1f3e5d7c9bbad9f817365574 33 128 b5d197c0e801b61fd49bb548af7a5e02c5c49da3b1ec4d6dea1c22c88beaeb86 739f0a85125f48a78f5f794f975e9154 +aes-128-gcm 161 26456483a2c1e0ff1e3d5c7b 0 129 d8f542ae468ef26c0a419fb8c9f9b1873cba514cdaec64095b191cd2cd964c30 1d2f3d7f281975283556aee8ca9ac7ea +aes-128-gcm 162 2d4c6b8aa9c8e70625446382 1 129 9ef224fa99908329d880a7a7db514e4e2933a05cdb907515a45003017a223e6e 6b3a210ec19008501f874d453d8604bb +aes-128-gcm 163 34537291b0cfee0d2c4b6a89 16 129 cf6fae92cd9f8029e627c3a9bf91dd9022870fcd00a34f2571a1c241c169ec30 d07f52c31b7c9ac4b791a654456b05ce +aes-128-gcm 164 3b5a7998b7d6f51433527190 33 129 f527be41edba1735459fd1dd4e95b18df59804c28e3bb2cbec52bc0572a6a1e7 73dff7384601aadebda1754c99bc2084 +aes-128-gcm 165 4261809fbeddfc1b3a597897 0 255 2153478143e477b125e490b7a26a57358190e311ba220771d629ad79993acf8a 83a2aae699204703a672f8b843d8343e +aes-128-gcm 166 496887a6c5e4032241607f9e 1 255 f09cf914076041e7302013f67222cd239fad8e0c4200325dc02f0cf2d315d24d 89b85b03591de0954e65869e847e3256 +aes-128-gcm 167 506f8eadcceb0a29486786a5 16 255 2778cb650403f5ee336cda3919a004ddc264ff849bb3db13ea3dc350f73092af 6f27a3161fe2945b4c02bb8866ef6e84 +aes-128-gcm 168 577695b4d3f211304f6e8dac 33 255 cdf9641657b31ee5cbfc9f867428baf4d42afd0066690e8098ca91f602d8148f d4e059098d858d441914cf3d151dbf7c +aes-128-gcm 169 5e7d9cbbdaf91837567594b3 0 256 0ecde346124460b954742ea000389d9d1b2327e7e280335059cd4e2fb7e1dcb1 8fe835eff91d061336c144ef80663d63 +aes-128-gcm 170 6584a3c2e1001f3e5d7c9bba 1 256 260ce3bd54b8c602f1266c23bd9ea52559e5173d164bf5e5e7d24d26c0195cc6 e08e46cdc8d08d38e0307a8cd6eeac63 +aes-128-gcm 171 6c8baac9e80726456483a2c1 16 256 2ccb9c542e92cdbc25a31245644ca8c8e80fe6712ae4fd2c286ada4ccce8c1b8 d7bfb28c3cf9a65e382c3a9dac6576d3 +aes-128-gcm 172 7392b1d0ef0e2d4c6b8aa9c8 33 256 c85c40cbe79bf8eebeb5445c63ff5d3253972dd8367dcdf43338364c682360d9 3a40acca267091686a5dac19c3b338f5 +aes-128-gcm 173 7a99b8d7f61534537291b0cf 0 511 dfa6eb477b44b520087e6fbe27383efff485b17b686c2c7f0aeac37159e7b684 462fc13c28e60dc2d07c308262693b9d +aes-128-gcm 174 81a0bfdefd1c3b5a7998b7d6 1 511 e1554883c8d609e4be6cb6d2aa952a050d8bf98786f9928b83f9f9b8cda91264 9dbb0c8fc9b99f9f6a93900fe88538ab +aes-128-gcm 175 88a7c6e504234261809fbedd 16 511 a91564249a7d1b0c9909ebea691e9054836b23873caab2b52950afe2d5c87e2c ff114a7523474ebf1da3ea9b02e8330c +aes-128-gcm 176 8faecdec0b2a496887a6c5e4 33 511 b1a8631825cd551d36bd0a7a2d9f9851f1e7ec1b93bd2bd4c81e30a178f7e028 0fcb8c8d2cfa0402776df25f75a78bbe +aes-128-gcm 177 96b5d4f31231506f8eadcceb 0 512 7521b5388a93adaf420523fedf9564a65ff10a306143bdeab89892184a9b2672 0886e32a682a070b9c15986c0e55ad08 +aes-128-gcm 178 9dbcdbfa1938577695b4d3f2 1 512 a05a632883b90bbbb6d7659aa372c9eaa64dd008f317894bbe35a1e8c68835cf 4fe2188b20af581e6e1818ed5b1a48cb +aes-128-gcm 179 a4c3e201203f5e7d9cbbdaf9 16 512 8cd65d10cb5e7ceb0bd3dcd73f2d79ac13172f2b08564f3d80a43c920fc700c5 43cd35c506b2933cd32e2bc952da3cbe +aes-128-gcm 180 abcae90827466584a3c2e100 33 512 0c924d6b2667090028ba129237dd773d35f40b2b11dacea2aa0817cb172a9ebc b26bbc0fef0cb5e6b6f13925f73be749 +aes-128-gcm 181 b2d1f00f2e4d6c8baac9e807 0 513 d606cfe0aa99a82e4e7ee7376e1dac26411195e4c7f8f7c0e0c03ec59e9c0505 86b5a858ecf8ade0c24c2fe287b8ace2 +aes-128-gcm 182 b9d8f71635547392b1d0ef0e 1 513 140e0458613d86f0418b8426207735bec0dd2d2b0c7d457b7c3a3e79714c7188 542bb452490795935c608557bfab7b40 +aes-128-gcm 183 c0dffe1d3c5b7a99b8d7f615 16 513 71c5e99e3f634e46245bece6689023fe902cb9780530991b2c30e191f911e58b 70c8903625ba7398e4b270f71331c200 +aes-128-gcm 184 c7e60524436281a0bfdefd1c 33 513 6ebf1f30a447747e624de0eecd78765f80122996155d2caa2e8df9188bd32f02 ee60b793f6e19e6d18947388b9c07b0e +aes-128-gcm 185 ceed0c2b4a6988a7c6e50423 0 1023 d6212e41d5c54f22e070d3ba530a23166e830654c8eb552c7ca14304dbe16173 b0c05338a5097ba35134cdc2030ed9f7 +aes-128-gcm 186 d5f4133251708faecdec0b2a 1 1023 0afe61f5b5444eb75226fdd9306c837d0c14a9d1cc58721c52cd47d0f69f4d9c 3534b7a5b383e666d8e219807d839d34 +aes-128-gcm 187 dcfb1a39587796b5d4f31231 16 1023 c4e98ca4a83dfe81fc0b84bd57db484f9aef4ef08dfeb86905d67ce2cc8e7ac8 6fc4cf72b158fc36cdf2baa65a409478 +aes-128-gcm 188 e30221405f7e9dbcdbfa1938 33 1023 7d6ef96227ce456c0a534f04262392ec7f6cc6fd327bd63dc093279c676784d4 038022910500e529369ef4957cf97dd8 +aes-128-gcm 189 ea0928476685a4c3e201203f 0 1024 15a2a17318cb8c8eb791ffd8a365223047b334e44cbf09a16bb83aacb1938b2d bb0e3469ba6e7f6e6672fe400fb2ce73 +aes-128-gcm 190 f1102f4e6d8cabcae9082746 1 1024 6bcd003b57c83ac42fbea586739bc035b47a4caf5ebd353a077800e922ebf757 6067824f92c10372b750eb57597edba8 +aes-128-gcm 191 f81736557493b2d1f00f2e4d 16 1024 e6562eb3195d27f0a1ee7ee6b8d2ad6adaf33c898bb1bf6e9132d7fb094a5759 0a13044bc5bf99cc4fe90913fbb00d54 +aes-128-gcm 192 ff1e3d5c7b9ab9d8f7163554 33 1024 a96412f265ded222da9aeaf3df874f5daca56b092503b0b9eed28a2c408f72fd 0446e79d242282d0b8ef82b963d03512 +aes-128-gcm 193 0625446382a1c0dffe1d3c5b 0 1025 fdc3c9b1fdd7f05719519ccde64ddb39206994f8ff3d710fc592aea0c99e394d 2b9ef9c338836b74e703b22cf7bc9246 +aes-128-gcm 194 0d2c4b6a89a8c7e605244362 1 1025 321d0c0469419027784a95ee79b25d9d2c631b53c3cb9ee741a2e15f6824c45e 92328b8913a2a0f295911ba867d2675b +aes-128-gcm 195 1433527190afceed0c2b4a69 16 1025 ee96d4b5867f810a27a15506b07d2083884334e54ee8fbedccfd3f21ffab92f1 e604aedbea85f8e16cadc4eba8ebd41b +aes-128-gcm 196 1b3a597897b6d5f413325170 33 1025 d856658fac0212168c658eac7c4645c2602f75b14c3639d12f325380ec0db6d4 ad86c49313436a0ed46606e400608c55 +aes-128-gcm 197 2241607f9ebddcfb1a395877 0 4103 7f319d5d1725b27b7376215511d991e29a77ee0e519252d92f443fd139ca3d04 ccd40fb5948469c4d97b598c188aa1a4 +aes-128-gcm 198 29486786a5c4e30221405f7e 1 4103 9da52390890f3914bdabf7c3bf52a2b124a37f0b5a7bd57dc0b18733a0307390 b9e1f5ebc11b9c57a5f5c946061e163f +aes-128-gcm 199 304f6e8daccbea0928476685 16 4103 21d3ea4b6158bc12d6175c83f8ec2d86499b4d6dc6c50f5fef491afa3ef314dd e318c71cf24db8aa1f6704cc0213324b +aes-128-gcm 200 37567594b3d2f1102f4e6d8c 33 4103 973b8cb52052f70f9ac9a11de01b0d7cddd5262014046b1ab0e29a60924c4be7 6bff432708e9226d64c7cf21ff44b7e5 +aes-192-gcm 201 3e5d7c9bbad9f81736557493 0 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 5966734c36f0c73c07e0119c86f70685 +aes-192-gcm 202 456483a2c1e0ff1e3d5c7b9a 1 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 7f18d4bd6e75e278f356350beaff9ad7 +aes-192-gcm 203 4c6b8aa9c8e70625446382a1 16 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 a2958b8a18c2dff320637b349b835366 +aes-192-gcm 204 537291b0cfee0d2c4b6a89a8 33 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 22e166aa953c67d438fcdd7d400aea37 +aes-192-gcm 205 5a7998b7d6f51433527190af 0 1 594e519ae499312b29433b7dd8a97ff068defcba9755b6d5d00e84c524d67b06 fd4eaf46c69548417940007175cbbc87 +aes-192-gcm 206 61809fbeddfc1b3a597897b6 1 1 334359b90efed75da5f0ada1d5e6b256f4a6bd0aee7eb39c0f90182a021ffc8b a9d8e8c5d1b0c451a81c0cfd3e815f37 +aes-192-gcm 207 6887a6c5e4032241607f9ebd 16 1 cd0aa9856147b6c5b4ff2b7dfee5da20aa38253099ef1b4a64aced233c9afe29 7dba5fe0fe800ec449b6d5fff20f1d7b +aes-192-gcm 208 6f8eadcceb0a29486786a5c4 33 1 83891d7fe85c33e52c8b4e5814c92fb6a3b9467299200538a6babaa8b452d879 72bd70ab50f8bfc0112a0239a0609d38 +aes-192-gcm 209 7695b4d3f211304f6e8daccb 0 15 c4f6f2a7d442c563373b266821b7fe1e881d9b0dba79a4f5f4c1c031ded1ff81 a7a033d636c2a965907cb4d4c5f3167c +aes-192-gcm 210 7d9cbbdaf91837567594b3d2 1 15 6af3b7ac1aa8ee2c06a4a90cf5606c0cfb298aa12528d5a5bd57ddcd38dbbd9e e3ec5a5f09aeb92f770521690bf208de +aes-192-gcm 211 84a3c2e1001f3e5d7c9bbad9 16 15 0f1ee7c7d912a34906ff38b76007b35c2d257830b713ef250883b83c2e2f5271 dc816e8db8e78f10069ec3ae83abb7a9 +aes-192-gcm 212 8baac9e80726456483a2c1e0 33 15 5780ad54606868a5b5e68079dd5085cb7f47e0851d44f4a7ddf930608637c0c7 a0005450904699e22dabb50cc6a7f438 +aes-192-gcm 213 92b1d0ef0e2d4c6b8aa9c8e7 0 16 dea9120d2cafe99e5ccdc42f595ee2c2c504dc2e189beb62fe7e132795402748 7b85b34e04e783a39096f885f805002c +aes-192-gcm 214 99b8d7f61534537291b0cfee 1 16 04c11a11ec26bee14df80c17de984989dc465a1f0f2e892b8bed9d641a797474 5138b4f2853ad4760d9f5068d9c44bc1 +aes-192-gcm 215 a0bfdefd1c3b5a7998b7d6f5 16 16 f3f2cecf76df073853a105d7de5c859db2d6d4efee8a60b62080d98d729520ff bd22f0c96e42647f2b820fb385cb3efd +aes-192-gcm 216 a7c6e504234261809fbeddfc 33 16 03426341cb2ae392b0d98b1ecbadeabcf474dc03a1fc337e1856cb3ed05cce24 f2c938529df52cc4ec547c7d778231d1 +aes-192-gcm 217 aecdec0b2a496887a6c5e403 0 17 c95b71d37b0c4bc496bcf9e51e90322aa29cc0791b977e2434b68c97ba662be1 306c2e0b3a6e1569dc31d211e600cbf3 +aes-192-gcm 218 b5d4f31231506f8eadcceb0a 1 17 6d0a52f58bd86db7e34faf12c2e5e6f721e499cac97dcc519dc366159e0514cc e977ebcd9f29996bd76d589600f8e207 +aes-192-gcm 219 bcdbfa1938577695b4d3f211 16 17 8fc40de891b336875311d5baf8db8173807b595319048cb41b406613b5958f6d 18009c88ab29446d17dcbb046b9e1d92 +aes-192-gcm 220 c3e201203f5e7d9cbbdaf918 33 17 210ff25bfe71cc7dbecb065eadd16aaa4cdf4c768033844034f107ce1b72570f 4f1312cb7fce861cd038c0a98b7c9793 +aes-192-gcm 221 cae90827466584a3c2e1001f 0 63 433ba3396c359afbf119b1b615cb70799ef2e4ab85f6f69af9cd4af5cc22d6c0 93da838121485c2e5b1562691c2e2fe8 +aes-192-gcm 222 d1f00f2e4d6c8baac9e80726 1 63 1a405479b6585e1cc6c7d6ca747771380f8952ea062d79e20f392871cbbd255d efbe9d69f1df4d47b01abbd2588aba38 +aes-192-gcm 223 d8f71635547392b1d0ef0e2d 16 63 ecebba7091926f55418f53c602601a0dcc736e166b9ecefd599f093cddd914c1 08d72a2c1fc212396a04e13f62641d3c +aes-192-gcm 224 dffe1d3c5b7a99b8d7f61534 33 63 74ef4cb3dbc9151d3e4bd8b7413075a1c44fa140842828aa99bdadfed3c19a0d 60f6f1173da16fc46ed439bd2ab28797 +aes-192-gcm 225 e60524436281a0bfdefd1c3b 0 64 b115940d3ac2a9164a2949e44a0575b63269ec89de22ac4ce2bb739d5891db14 1f6517c3a4a642ef9b2a179b27a272dd +aes-192-gcm 226 ed0c2b4a6988a7c6e5042342 1 64 adbb6b3007b9152e6d59e36d55e545984f1c17bf75509929b22f63f774a1294c 75c6aae3ad7dde1a46a11afd06376693 +aes-192-gcm 227 f4133251708faecdec0b2a49 16 64 d668cf7a84a6d877bb11e285dacde9df51a4ebc5d5b705223a771fb525849ee2 d31418a3fe3037ed3d1a1b9546e6765d +aes-192-gcm 228 fb1a39587796b5d4f3123150 33 64 c877fa1031530a122287fda94951023de2856167e7d81c918c47fffaa632cf21 64dac9c8bff701d13a061b48468bcfe2 +aes-192-gcm 229 0221405f7e9dbcdbfa193857 0 65 e423fde894eec1e3d236fd50ec4f81324a4fbd4c93ea482a5bfd83cddb34caf1 79e8d342c46c993c65b8b2836fd8f8fc +aes-192-gcm 230 0928476685a4c3e201203f5e 1 65 e78bfd7c84414c0600e443694bf7489969b01f1a02d2b3d472281d3efa8a9170 e323bfd4ee502acb0e4dc0ccdfbf3b15 +aes-192-gcm 231 102f4e6d8cabcae908274665 16 65 a5e2e6dd808030cfdcc2eb258e692e95df86cc4463713b90d284c6ca30ecb6b0 1a0d8dee267a0ce8751947f7ca6712c6 +aes-192-gcm 232 1736557493b2d1f00f2e4d6c 33 65 89b317392e473ce579ef30f42670cd4d809b89fbbd6463e588dbc335783f4619 a49f088c8e2dd4c9d301036035472f6c +aes-192-gcm 233 1e3d5c7b9ab9d8f716355473 0 127 7126d2fbd76d52c45d8c1932734451672cea009d72577f30db297d78e0f44726 0b8a08ab042a7abe2e7d237667e545df +aes-192-gcm 234 25446382a1c0dffe1d3c5b7a 1 127 836e16fbc4c2a9ff7687c4f89f1490efe92763776061339bc5446fe15ded4e73 73c5aff70de29b2212273e5d5857d3d3 +aes-192-gcm 235 2c4b6a89a8c7e60524436281 16 127 1f3d7cbb16ffaeafe7f7b468743d77c0cb7118ddc38dad658c256dd7262e0515 680eb58ee3d0f6512727f87b3793dffa +aes-192-gcm 236 33527190afceed0c2b4a6988 33 127 88849d4df914123931396ac476fb4cb8dc78853fb36cbf2bea5dd06e7a2fdc57 d951f5ee54beae561849b09defa75624 +aes-192-gcm 237 3a597897b6d5f4133251708f 0 128 46fb5dd649ee7592041e88e2887e40124f47c61112bb77a9afe6027e9c85f9e4 d090573b91a9c16d78c4750c1763972d +aes-192-gcm 238 41607f9ebddcfb1a39587796 1 128 bd4df9c3b94d0fbb6a166184eb0e9dc5fded1615376e6295133f3e2202af9099 b37a6765c21480eebbe97f999765e5f1 +aes-192-gcm 239 486786a5c4e30221405f7e9d 16 128 ab8cdd9cd33f6ee03c4e46cd4c1a9fdf2b85bcf8d3b6a931cc951744ce86a539 8cd07f9e53fdc7222448a712bb007d81 +aes-192-gcm 240 4f6e8daccbea0928476685a4 33 128 dbffa1a6d2c150c12e942c9c3f003ce20bd25e12a4bb3607bf9562161d7e22d9 58fa7882185ce40d79e76b8485c1848d +aes-192-gcm 241 567594b3d2f1102f4e6d8cab 0 129 68745906c32a697a64962a767ec6da96ff19be993007ff4a5fc9c5db08ea8d40 2b1ae32bfc3cc2c7002ba35fa2b89ae7 +aes-192-gcm 242 5d7c9bbad9f81736557493b2 1 129 ef02f3922748143a11b3eea289a2f33253c7acbcb449d33cf367201e95740c71 f200e9340f4877b1808f36a6886bdd1b +aes-192-gcm 243 6483a2c1e0ff1e3d5c7b9ab9 16 129 e1eabd2b2e2c24fe8d691f9e3292682550e94daa6aaac6e641feb6240cb22232 b11b133c8103fd6962d0dba6e88ed679 +aes-192-gcm 244 6b8aa9c8e70625446382a1c0 33 129 749ba5004aef92040add7565c6c7770474ada22f7f3a71a9095ce310c60f41d2 3663dc414b1beeeb2bdfb0d9c223a066 +aes-192-gcm 245 7291b0cfee0d2c4b6a89a8c7 0 255 40e1681e191f9a01b33c462c061e749841baa1cd4303c2623199951a6bb0cd60 4e84362927a39bb52eee0f9cbd468423 +aes-192-gcm 246 7998b7d6f51433527190afce 1 255 09ed22d14151a2ad6a495312abe155f4c83000cf5ae7707e5351209cb1aef62b 6127a04b0da3be63ebd3300c634bec26 +aes-192-gcm 247 809fbeddfc1b3a597897b6d5 16 255 d4d2679e1460a24f2b3ec1a412a18b624128d0d3e96442918783b8e05e915aaf 412e97f53126b35dea3964fedba4837c +aes-192-gcm 248 87a6c5e4032241607f9ebddc 33 255 7f5d9d2c326b55c5c56175068eef1b636a17ca33c2dc503e12af8ebfe6e3c319 012d4049a5d0e97331bc83db66949532 +aes-192-gcm 249 8eadcceb0a29486786a5c4e3 0 256 6c91fd99f66a99f38f59f3c48892869e414cd3a535f1d18035d0515e2878f13b ae9bc4cf340ffabbbac593a42143d019 +aes-192-gcm 250 95b4d3f211304f6e8daccbea 1 256 a847b2146aacc5bb58af057b7c7c2e6024d8a40d23c62a3cd23c7d64e5e25ccc d643a0ecde35351cbd22329148c95b9b +aes-192-gcm 251 9cbbdaf91837567594b3d2f1 16 256 1ddab5d4764d41bc69e7ed86d5bd88c3765343add54d9d6aa6e006a52886206b 1d998d8e61041be0e0620f6d6a2bbd19 +aes-192-gcm 252 a3c2e1001f3e5d7c9bbad9f8 33 256 62ba726d7b3e2bb88c4965b737bc6c6f7b20d6b2e564f9fd5c3b33b330989101 2979620a960a00e0fbac0bc3b200723c +aes-192-gcm 253 aac9e80726456483a2c1e0ff 0 511 1090859665fce8afb9513e3bee623a8b11a1cfbec6f4c772acaaf6890ab8ec4f 8ed1b9ff3afc225198a302e2179a62e3 +aes-192-gcm 254 b1d0ef0e2d4c6b8aa9c8e706 1 511 a1c236bc97e29af6164a9732a3d81776260cfec91db3f8c4e48d2e9d8294b119 6164b27765830bd38dfe283e47a5f029 +aes-192-gcm 255 b8d7f61534537291b0cfee0d 16 511 3dec19564c3bcbc48719a8aff30b592cfc79ad4c50e8a844d3e90809904ac1d1 42beed999295495d92aba510d2bcc967 +aes-192-gcm 256 bfdefd1c3b5a7998b7d6f514 33 511 5428d054c30afc17fe09820feed4143ff0b39d668f0d9594ffaea23c7c83ea74 0964fe0c6ca22acf681625d3a82c9d99 +aes-192-gcm 257 c6e504234261809fbeddfc1b 0 512 cd9ae03e900f5920b386ecf5de2d7e1d09140b9da01da6183651a5675321a039 747d757aaec3fa113aac82f778e54b09 +aes-192-gcm 258 cdec0b2a496887a6c5e40322 1 512 b4965ccdcb8414e564c136c7f6d628b5bc875ea45fc666a5b53795d1d17ed0ea e53e5e90863dadcf20fd70ff1b8f81e2 +aes-192-gcm 259 d4f31231506f8eadcceb0a29 16 512 551e4f56647f43aeff54be44c7f0feea053e32c6a77665da2e4de41ba2f60160 7cdd5db93e78853cade526bbe2bb2c1f +aes-192-gcm 260 dbfa1938577695b4d3f21130 33 512 8c688e6810abd2156dca363f967bc4592bcd288e2aa11760d246593669672832 7e95fadd76adea1823b83f4100b947ae +aes-192-gcm 261 e201203f5e7d9cbbdaf91837 0 513 78521812a6917c1c73dd88b4c613a31328e42e3c3cd8b194e1a93bee6cab00eb f6c9ad443b4c0ce32d7ca706e33a5837 +aes-192-gcm 262 e90827466584a3c2e1001f3e 1 513 b5c992ab367c260986002cef77a545596dffbc55254afd7a2687dfb77a039b99 3d7eec01125b44c10db1df891d05181a +aes-192-gcm 263 f00f2e4d6c8baac9e8072645 16 513 575ea5e315717e4d84e45da3401f72b55acd9125592ac93909e8044910496e1a c6689b3368273f86ca92f7f4f9764a63 +aes-192-gcm 264 f71635547392b1d0ef0e2d4c 33 513 798682010ea63ccd2dc083b8d9e232020044357e8a56e4e369ac74f25cbac05b bd54f0ec9effc99b5fa0a1a220a0ca8f +aes-192-gcm 265 fe1d3c5b7a99b8d7f6153453 0 1023 b0b6ecfc1b9331bf2d205bd51012c2cfc9de6bee1a6bacf997e46c82da88fb93 6bf8b33637828218d8e1c75e00c1f4b7 +aes-192-gcm 266 0524436281a0bfdefd1c3b5a 1 1023 e7222bd345ac8b97a169cd2bbdd4d5503cef9909738236996c399234e4e7d701 82eecb56e6d71142f019c66b37008787 +aes-192-gcm 267 0c2b4a6988a7c6e504234261 16 1023 11cbf893abf08308ff9dfc13e8fd81118c0807b52fa6df9b5b965d69aca57515 ed68ea48a3724909562732ce4f9296fe +aes-192-gcm 268 133251708faecdec0b2a4968 33 1023 8b37aa25c43a629c074d99ecebc904b0823a03193f639bb994099b371e50cfa9 fe9b9503e68b80ad0eedbd055e27e56f +aes-192-gcm 269 1a39587796b5d4f31231506f 0 1024 4a75e0b4ef0bcf4ae7902d41131a31afed46c04680ab50a08a9bcdf0d83bdccf 9b4084769417d27e66bb0d9cecad6662 +aes-192-gcm 270 21405f7e9dbcdbfa19385776 1 1024 4a2101f8706c3957571248ef524fe741d73cf4c4bf39004cd946138d60111953 009c735e8696103588f0bf0f756c7208 +aes-192-gcm 271 28476685a4c3e201203f5e7d 16 1024 f0402a3344903b5a2ac28bebcea2dbdd564cee97aeb9fb656127e9712238c3fd d3fe289e546c7396dc7491aa1b0ef4d2 +aes-192-gcm 272 2f4e6d8cabcae90827466584 33 1024 dc0ba64288bb3f3772bbd2ec8a40a4e13887a83e76f8da4ebce9d4be268617df ba7a680003e2fab8295d75d679087042 +aes-192-gcm 273 36557493b2d1f00f2e4d6c8b 0 1025 449eeca5c905d9d648db5b093c47f690ac2ace65bf3ea386e9b597c65b8b36f5 460ad682b08ec8fbf63b1d882bbd5db6 +aes-192-gcm 274 3d5c7b9ab9d8f71635547392 1 1025 c171e105d37c2d2baa86950634fddd265fb42890ca7a78e7c1e5a1ee41374912 0c44123a1d7398c9ec1412c34c8ac29d +aes-192-gcm 275 446382a1c0dffe1d3c5b7a99 16 1025 94a66601b5cc004a09219034b9278d0f6c341060d35f2676e0b6a2d6a0fcc2ed e6793bf977a8bdb2f7ada91a4c661630 +aes-192-gcm 276 4b6a89a8c7e60524436281a0 33 1025 4adf0e8c44c774de70e4991ff0c3038ed1635a1f4f9aefe7daf0788c18c5300d 8185ca09a38c684250013a3aa52a71f4 +aes-192-gcm 277 527190afceed0c2b4a6988a7 0 4103 32b1934553f53dc137fe37ef957e3cbf96592d88a158df456e530ed733d126ca 6a0f11819fcb0c1fe70fe3a6af863000 +aes-192-gcm 278 597897b6d5f4133251708fae 1 4103 93017c66af21df7a001ff98eec5e5a3937aafe3cea8e3dda6de13ced8faecbed 311b68f9db9d7dd33b996b233a4f045c +aes-192-gcm 279 607f9ebddcfb1a39587796b5 16 4103 0c627af893cb345a42c4491e34cc0735392d5931d90abbac7dc27d59cb8b76ca 39a5c0055e1aa17ccaff541760095d5b +aes-192-gcm 280 6786a5c4e30221405f7e9dbc 33 4103 6d044fffe5d0bc06dbe499b4fe9918e2038473fe6ac002f8a388a7f6b7c1b68b 8f7abed688c629de756f677ada1e7c08 +aes-256-gcm 281 6e8daccbea0928476685a4c3 0 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 33410131706bae46a3c9b6a10066a7a8 +aes-256-gcm 282 7594b3d2f1102f4e6d8cabca 1 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 fdbda5bf405c823a070f952083ba56f0 +aes-256-gcm 283 7c9bbad9f81736557493b2d1 16 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 281aa82f5cc9884eea5d8a8b89f24c8d +aes-256-gcm 284 83a2c1e0ff1e3d5c7b9ab9d8 33 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 052f7dbb5fd1b5b9544474bfc44060ac +aes-256-gcm 285 8aa9c8e70625446382a1c0df 0 1 334359b90efed75da5f0ada1d5e6b256f4a6bd0aee7eb39c0f90182a021ffc8b 0233a111e6f882a3d15fde4c56de82b8 +aes-256-gcm 286 91b0cfee0d2c4b6a89a8c7e6 1 1 c4694f2e93d5c4e7d51f9c5deb75e6cc8be5e1114178c6a45b6fc2c566a0aa8c b1fe09e93b935a43d87a4fb8e0742a87 +aes-256-gcm 287 98b7d6f51433527190afceed 16 1 1dd8312636f6a0bf3d21fa2855e63072507453e93a5ced4301b364e91c9d87d6 6ce7fcf63c53c40c663166974e6d0625 +aes-256-gcm 288 9fbeddfc1b3a597897b6d5f4 33 1 09fc96082d34c2dfc1295d92073b5ea1dc8ef8da95f14dfded011ffb96d3e54b 17f1bcab1421d18cba5eec17557484d3 +aes-256-gcm 289 a6c5e4032241607f9ebddcfb 0 15 bdd5d92c70922e6cb941a8f4255b1257c9f11d612a3a4e0e6369040c57e122d4 ef3a0987197e2c3532ad68b93c5366f2 +aes-256-gcm 290 adcceb0a29486786a5c4e302 1 15 d713c4cda010de809755b9dd3a04b81545e992c0cd8668107f00bdbdaf53d2c0 1ab66ebd82c80c5f7e35b93063e5e69f +aes-256-gcm 291 b4d3f211304f6e8daccbea09 16 15 8d7e04f92c9d74bb270d46affdbdabaf9e35e5556be44a4c9780df7ed61fab1d 095a54425c6a7bf900ed1a9170ddabf6 +aes-256-gcm 292 bbdaf91837567594b3d2f110 33 15 6c20e05c50da5c97312d2e706ed924b5185dd63f06125b75e8b4a7869d0bec8f 06a4428b578721f610ad50c8d031072f +aes-256-gcm 293 c2e1001f3e5d7c9bbad9f817 0 16 69a3ad6a4c4549e4ca6c74cd4420d2d452d3b2f610e4d57934963c0c98ccc799 df8f9a2099856f37b30c6a6c047d5ad1 +aes-256-gcm 294 c9e80726456483a2c1e0ff1e 1 16 aeb0a092b45e16e4b487d16ae343fd9fbcb9a6687eb35c1da2b69b1013b013bd 455b50be8545de73becc126e65827137 +aes-256-gcm 295 d0ef0e2d4c6b8aa9c8e70625 16 16 a854435340c905f727c5ebdd77c196bc852162c318be6af810bc99273c85b003 a10fd8ecf7c6b3374fd9fdfa73b4f392 +aes-256-gcm 296 d7f61534537291b0cfee0d2c 33 16 220750da49bf51672ab1acad557fe3716a737e6bc3f3482f1e96216bde8fb067 02d9ec4f21448e6366361351451b129b +aes-256-gcm 297 defd1c3b5a7998b7d6f51433 0 17 fe30d5dc588a8adc987c1d557120961e943682980d191f48cee4b73c3872737b 7ae664aed22cc08c12b849396749e953 +aes-256-gcm 298 e504234261809fbeddfc1b3a 1 17 8abe751282abd3cd59cfea3a775d401551099e5e9ebf57c00230a44e77d6c428 160ea3b77d7585709f67b29d1c8197b6 +aes-256-gcm 299 ec0b2a496887a6c5e4032241 16 17 dafd8dccabd81b8009a9fb99708c950475d344eabd2ca3390902a5eecba93559 82061effdfe44d13ee412afd0b8e8efe +aes-256-gcm 300 f31231506f8eadcceb0a2948 33 17 f624f43bd031014b594c7857a048cac1a77875d1c81e891c4a6b2a3ae2ed31de a1c0b672e56d6b94285b9428b2822ffe +aes-256-gcm 301 fa1938577695b4d3f211304f 0 63 3f2b0dd0c896ad352688ccf3d5e00fddcf7776a81a38e9a9b0906cf18c5ed9ac 24d9b27f1d666df1cd699faf4e65c959 +aes-256-gcm 302 01203f5e7d9cbbdaf9183756 1 63 f3fcba195f943174539bae872160d9831bb4338e45e60dbc7b129b389aa80d7e 133a0de080f9dd3b6cefeff68d55ed13 +aes-256-gcm 303 0827466584a3c2e1001f3e5d 16 63 9465bc9e1e42201a7e92488d28dc8e73d4f41055dd25b160517f80c615debc4d d0d1dadf50c01ed546dbc2d402940949 +aes-256-gcm 304 0f2e4d6c8baac9e807264564 33 63 4ddeab13de09d952c3bdf699c8ce1c25687d96f3c958fd42628d010d75fb5364 92e60818b0e6783f80ce251d5896b751 +aes-256-gcm 305 1635547392b1d0ef0e2d4c6b 0 64 cf04b9fdffd35a482101935cec20b5f597062a058f4a4bdd6fd47c0ed07aa1d9 954f2efa87d05bc352e91246194e597f +aes-256-gcm 306 1d3c5b7a99b8d7f615345372 1 64 36ca62a793ae920e25276255961d34aa02fabc54e03e73d58a1ad9862f2d0f7c 667a377b7e906fc60498607e9103c14e +aes-256-gcm 307 24436281a0bfdefd1c3b5a79 16 64 2a567fac2ed788bc8cb3334e546d2c5c0d44e2033e07a7e3585d700706f6044a 0dd399907ba193ea0fea430aa892f5b7 +aes-256-gcm 308 2b4a6988a7c6e50423426180 33 64 0cbb243c69fdc303ab18e34c14b3cf6a0b4982dbacbe2a4688f9245a1b9ef4a4 c2b1e37b715d1a9c6314479f28733648 +aes-256-gcm 309 3251708faecdec0b2a496887 0 65 38091448caf2b8a69aa1e38a448372be4702e0c04284bb6ee56a2f2bfd8f4b40 b996c1bf2002d6239cbaa054b57ac4c6 +aes-256-gcm 310 39587796b5d4f31231506f8e 1 65 4acc2f489064ea9456b899f46a17b6dd60e181faa05c904f1b065714eac25cb0 93593018b06ced8d03e43174a9282659 +aes-256-gcm 311 405f7e9dbcdbfa1938577695 16 65 cd941bca1a0d8e4b05bb66c4f5a7f54d34213531ee6f82a4cd0f65d1028524c2 dde27648423747be7dbb915991c84340 +aes-256-gcm 312 476685a4c3e201203f5e7d9c 33 65 7eeb836b70f503049b0f5d1bf0e948aa727b8fef8bb8f5aea6dd64be5c709b6e 1e0317c243a65aa0732f6048586852b4 +aes-256-gcm 313 4e6d8cabcae90827466584a3 0 127 0defcbe6a4a9d1dfd3f6b076107d14f61bbdd9c1bb2fe109ac8cb6f5aeb3983d dee2c9896e4de2dd2a338eeaaa44c295 +aes-256-gcm 314 557493b2d1f00f2e4d6c8baa 1 127 d9c911bcd86b05100207e6f9724a3e505c7ba95dd70fdbc8dfd9466272d46e54 9226c591f3474d2f82c1b24e24dffe96 +aes-256-gcm 315 5c7b9ab9d8f71635547392b1 16 127 c7d18d2e2209162680c6c8e3f315b1ee7575a1d1f7ffeac8d3fd671d9a79174a de87bead892a0337626cb0c44e3147fa +aes-256-gcm 316 6382a1c0dffe1d3c5b7a99b8 33 127 37fa46c410753cf3f69544820038ae343c6332781c3eedf3d9dc77d164246ea7 2ab151daf2a5b14fd0bc1d7a3f578dc3 +aes-256-gcm 317 6a89a8c7e60524436281a0bf 0 128 7780121a47e8a85d0af60f960f7b9a283daf229b375a600403427d182d0e8696 d7606a9da81a060c18c012871fa5fa90 +aes-256-gcm 318 7190afceed0c2b4a6988a7c6 1 128 f9b65f94a50089f5e320a56dbdf542be037a32b1bbbf9c8e7900f2b0f6e52045 14beba3f8d771db64f73e90c3bfc1fa9 +aes-256-gcm 319 7897b6d5f4133251708faecd 16 128 df224c900c5e5465644922eea368fb55ef3c13319620fe9f35d24f4a2d639bd8 b9a323329941254ec5bcb2c791c9b733 +aes-256-gcm 320 7f9ebddcfb1a39587796b5d4 33 128 f53fe4f3aedf999d3a705879ed0621df1432039ead31bb5cd9b66139fe2de7f2 b53f8c159995830a30860a4eac38994f +aes-256-gcm 321 86a5c4e30221405f7e9dbcdb 0 129 f020556b29808c1860432833b8e0ae2b93d86f26d3049671579e68bb0042e7d9 48fce8e69bd9f1f433af6286cad4a235 +aes-256-gcm 322 8daccbea0928476685a4c3e2 1 129 1d64e286f0da8b437e04bf6d516be92ef232cc959e35d061246f784449ad49f2 6bcb6ead008fddb67ca442a6141f5cca +aes-256-gcm 323 94b3d2f1102f4e6d8cabcae9 16 129 9db06a23c41160a21355aacf55349ff3937ab6da11e75ced374297933f251ea3 eed874ddad484ea2dad09d94c899e315 +aes-256-gcm 324 9bbad9f81736557493b2d1f0 33 129 f84f5d4788a026721a6f4ad2228d4169235515852d0c4e2b3a1e815a09a17675 4101ef35c29fa05495d64c0f58574ce9 +aes-256-gcm 325 a2c1e0ff1e3d5c7b9ab9d8f7 0 255 0d7b91b2d3f993240768ac62f27d135c8af71af45a3b42b3250d2b7dc477ea5b 5d45bb8447a0ba6c57f4b874ebc7e148 +aes-256-gcm 326 a9c8e70625446382a1c0dffe 1 255 f17f869cf9df650cccb47c5bf3730cdf9328810a725baf5d61b5db6a286662f8 f84095acceb67938c62717d6f16db708 +aes-256-gcm 327 b0cfee0d2c4b6a89a8c7e605 16 255 c1f41c928bca0ff55836ff47388a7ef2c407ed506e9b11cea9de5d41b31d3b67 e400112609375a141404fadde1f63c5c +aes-256-gcm 328 b7d6f51433527190afceed0c 33 255 3efb444a0d49a190d2814c8164770a0f4356b7e3525c2279cc504fd80b4c2b52 95631c68d8f8f54339703eb38d620906 +aes-256-gcm 329 beddfc1b3a597897b6d5f413 0 256 46179068a648f74b55196614ade0e26229974dae81f75875b0af31fa3356a8aa 5c5575b2bf66cc7de2114db5550cfd8b +aes-256-gcm 330 c5e4032241607f9ebddcfb1a 1 256 b40e025bcc4168acffbfef00248ae654a9351befad2748e9b7534e6f46a4e2d7 dbd6659421219464ef60544d6a9200af +aes-256-gcm 331 cceb0a29486786a5c4e30221 16 256 c989c46341e887dd90822860794516ce5e3b0d14a4b5a2734145c74ef056c696 620cf97c84889353da0f5da87c0c0856 +aes-256-gcm 332 d3f211304f6e8daccbea0928 33 256 e2e75d203109690d3e775388d027911ee13032a55203e6303c9dae800a942836 9cc4dda039008a9d3f9090b574bd59eb +aes-256-gcm 333 daf91837567594b3d2f1102f 0 511 a7953cf4a67bae809794d8a7690511a22c1eb76169cd39d5de8abb9559813620 87729eb448ce452a067890a3a80f59b5 +aes-256-gcm 334 e1001f3e5d7c9bbad9f81736 1 511 ce3076e03984aa9a93859b46083bc898883f4c9e254fb5b2a6d9835d1cc44e70 c44a103163c09daaad0321e7c2bf9fc3 +aes-256-gcm 335 e80726456483a2c1e0ff1e3d 16 511 f54f36ef9d34287d2e4c979939a460aee090cb3b8e9fa4525b2ba17e61a07488 514ac8050b0381dd5e85e1c6571a2a40 +aes-256-gcm 336 ef0e2d4c6b8aa9c8e7062544 33 511 5d5777174145363a233741d2b4bc174f8c60240e8d90fcf5b982d09ee2f83cdb d897fd18b45522789f6a56918996f5c7 +aes-256-gcm 337 f61534537291b0cfee0d2c4b 0 512 e5f7398176db8e2d595705ceca797a9a85cbcbc804969c0dc77290a1a216efc5 71c5f9917534354d1f6f39c2bffb167c +aes-256-gcm 338 fd1c3b5a7998b7d6f5143352 1 512 134516884bda35682b14f8e062c566b7357190a01fa44599736a1fdde34d8e1e 00558f33d25785abf5718055bd78b45a +aes-256-gcm 339 04234261809fbeddfc1b3a59 16 512 a27b2d7a00a105f69abb20b7ec69ef394c17149363d76d3c104c36f8e65bac89 6c6edff762f62083b60bdfaa46f8c45c +aes-256-gcm 340 0b2a496887a6c5e403224160 33 512 4117d16d9f70c4e3986440cdf0bfbf074c42d99223db61eafc8bf5811fd52434 7a5afbc9be33088e6a6e1b8adcb11771 +aes-256-gcm 341 1231506f8eadcceb0a294867 0 513 87dfa6a35ddf601f0f6b75f8e1cf1d9c862c16401823f21c2dc904e842aca7ba 8e2315754b08c4029b1938c89651ad90 +aes-256-gcm 342 1938577695b4d3f211304f6e 1 513 fd4d581acbd67ef44fd6d6d99f4aff8afd971a621778c9976cfaf93009278941 6d4e2b505883cb73006828d670fdf37c +aes-256-gcm 343 203f5e7d9cbbdaf918375675 16 513 69d4fd329505f10338c1a675582d984da148c9a384771fb5655db8182804b074 5999eda72042a8eb986cab5d182d6f91 +aes-256-gcm 344 27466584a3c2e1001f3e5d7c 33 513 7ee1b7484ca6b662e8697dd190f1661cbb308b05e56b7a34ed4855401d35af57 72becfc79d92ba995727d2d48e963752 +aes-256-gcm 345 2e4d6c8baac9e80726456483 0 1023 d0cb765a25317bd60e5888549f6813fc8dbfb13b34c3dde20073989bfa582eae a49b33e10e4f1a525bb6058083e27c3c +aes-256-gcm 346 35547392b1d0ef0e2d4c6b8a 1 1023 31bde2b5640269b1851883f699452ceef04ef89d3572ec541cca93e75fa02bac 55698f1476f82cb08fc7adb168ba4d3c +aes-256-gcm 347 3c5b7a99b8d7f61534537291 16 1023 a8f6315b06e87c1f084be90f987260289663f40201d1dd09da5592eaf7923116 b1d5457e0241f3aa6ad0fe9204628baa +aes-256-gcm 348 436281a0bfdefd1c3b5a7998 33 1023 bcb494f7800a7385a31121b3cf376ee160833b5fb35dd37e578b0ab1e59cc837 5d3fc47c36fae660740ea80c39f56831 +aes-256-gcm 349 4a6988a7c6e504234261809f 0 1024 8fa4a5829d4c754c6a0c432d71d077fe70f4b71928b15848e9eacd8749cb770a de9878c9a6f59a33735b90b23b135cc2 +aes-256-gcm 350 51708faecdec0b2a496887a6 1 1024 dc12f548e0aca0c992ef106c27c2eb3121aecbd88246d5dc0e6b756f6a87e626 7beaf97ccad230c96ab935c1091cffd4 +aes-256-gcm 351 587796b5d4f31231506f8ead 16 1024 2f6c36a639ca309ba091bb79cf3bdaa2ff8a85c5fe4c965b673b70f66fa6c1b6 b5af507cf02061b765600d877b3020c7 +aes-256-gcm 352 5f7e9dbcdbfa1938577695b4 33 1024 de3f5a714bad3b4eb1f33a38b8be3715a37a5ac9f46c024d6aa0936ae49883bd b4f3af1191e81fb0b54d71749883495e +aes-256-gcm 353 6685a4c3e201203f5e7d9cbb 0 1025 be2f01c22cca619f30763b1d844d0457ca2a6bdb852127870b907a833a7a106e a038eb5e1da1c0d27fb0f52ac3d9667d +aes-256-gcm 354 6d8cabcae90827466584a3c2 1 1025 fa2702b86d5539405b763de8ec079ccb3517beb08d24831178beaaa7d3a62862 0c927f9cbac5ec0f8a995bc019aa3f06 +aes-256-gcm 355 7493b2d1f00f2e4d6c8baac9 16 1025 b0a3e588d2ca97b994eb0d598ed3da01867ab18384b9861c3b5f61350fd29af3 13ed29abd1be60f6b78ccaf142becee6 +aes-256-gcm 356 7b9ab9d8f71635547392b1d0 33 1025 f3d2aca797f7ce8c2ae7b58e3375f3f12c8f849fc2bc42d27f1f1ae82ec283ed b8dc91a2cde8a0f090c98b33e31c2b73 +aes-256-gcm 357 82a1c0dffe1d3c5b7a99b8d7 0 4103 61daacb051e5b7da9b634581b290affc1ecadfa13cec67d20cd95ef487be821d d4a5e1935df188c00ef64e1579669d52 +aes-256-gcm 358 89a8c7e60524436281a0bfde 1 4103 5e097f626b36af99b247d2ddb270370bf373c335eb7575efa80c032898dd35a8 c509a97a77887e6d2f4f575fe90e740e +aes-256-gcm 359 90afceed0c2b4a6988a7c6e5 16 4103 ab18e09c8dde19be2fc55721e3009be97e49c32e93ba36ca44d295dcf6c9a49e 2dbb18d3af8c88d5fb1281fddd75c278 +aes-256-gcm 360 97b6d5f4133251708faecdec 33 4103 59021bf20ac1c54b4eb86085123a66330a5c2c941e4524db4884e7199a171442 6e05b2ad7cff0ad755c5515d4e854403 +chacha20-poly1305 361 9ebddcfb1a39587796b5d4f3 0 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 810fa7683f3087f10746e0ed15f8dbc6 +chacha20-poly1305 362 a5c4e30221405f7e9dbcdbfa 1 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 a169b6e643ff1b5513aa13a7be8eb4ee +chacha20-poly1305 363 accbea0928476685a4c3e201 16 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 1485ee34706f05495a649335fa655451 +chacha20-poly1305 364 b3d2f1102f4e6d8cabcae908 33 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 3dd9325a40c2166264779cf6e5467790 +chacha20-poly1305 365 bad9f81736557493b2d1f00f 0 1 ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb 546b5701a9c31568b58f523cf2cec57f +chacha20-poly1305 366 c1e0ff1e3d5c7b9ab9d8f716 1 1 68aa2e2ee5dff96e3355e6c7ee373e3d6a4e17f75f9518d843709c0c9bc3e3d4 118af9962300a1a32ffa43cc5e6a5f8f +chacha20-poly1305 367 c8e70625446382a1c0dffe1d 16 1 2f0fd1e89b8de1d57292742ec380ea47066e307ad645f5bc3adad8a06ff58608 59603c4cc57c452d52b4a7716e42ead9 +chacha20-poly1305 368 cfee0d2c4b6a89a8c7e60524 33 1 f4f97c88c409dcf3789b5b518da3f7d266c488066e97a606e38a150779880735 6867aba09d4f4187d335515111b18836 +chacha20-poly1305 369 d6f51433527190afceed0c2b 0 15 d601884a223c870cd12b360067413a5a960cbd844fa0cc835426c9f36845a801 4ae7375e1238f165da6fba8f75b5fe5e +chacha20-poly1305 370 ddfc1b3a597897b6d5f41332 1 15 5df7b7b25e78a3ca51035621bfe7f006d850c9efc8cd4198ad8b4b23073ea581 c093cf7b85b12100491def765d34b4fe +chacha20-poly1305 371 e4032241607f9ebddcfb1a39 16 15 bb05f090e0094c1050a3f877cc24c3ca9eb31d4d7fa775e26851a4814decbc95 6d9bbdccc892172875312e9c60c95445 +chacha20-poly1305 372 eb0a29486786a5c4e3022140 33 15 632b575ca18e908200d570f5ba8c9f966c3a8168cbe50fdd4f02c7f65823f047 dc566bb58ee4f280011dfa4017a889e5 +chacha20-poly1305 373 f211304f6e8daccbea092847 0 16 b0e00e131dc211d393b4b8074dff7470c3463136cffa0dd6b30d13b31a1c1072 9e2d65907c235b599e4621324c300d94 +chacha20-poly1305 374 f91837567594b3d2f1102f4e 1 16 62ef05523e5dc583a91a30af268723789397e9fa0405329cc33ec1393e5f086e 810e240fd45da75387351ea656e69f3b +chacha20-poly1305 375 001f3e5d7c9bbad9f8173655 16 16 ab7a81e6c20952b478f8bbb14f93f123eb34127c1b16048c58b44c0efc42fce2 838c152717ce6377cb00bc616d694956 +chacha20-poly1305 376 0726456483a2c1e0ff1e3d5c 33 16 728cae74fbdd1481987e60ecb7e6eaa5333789209f4c0fec0c66346af4f20f56 f1a8b83aa0ba5f6595a6c674bafefa4f +chacha20-poly1305 377 0e2d4c6b8aa9c8e706254463 0 17 1191aca5bbcf72e8ca8b07ba1a7267042dbccc0235aabb20089a76086cc4c33a ee2417a7c7db53c3a22dbc3094d3836a +chacha20-poly1305 378 1534537291b0cfee0d2c4b6a 1 17 d566f336568d214538349eafb173a47149b0489e00a0b64b42cffd316d0a2a04 108530ad02cfdd8b7b28f9057e8d0595 +chacha20-poly1305 379 1c3b5a7998b7d6f514335271 16 17 66f5da2b96541c1312bff9d193b003bd2191cd655e222093cb9c2af32da53272 996abee8d0a41fcfb074cbaaf1dec65c +chacha20-poly1305 380 234261809fbeddfc1b3a5978 33 17 2cbcadbb4294282979026555056c46739ce29b6263e4224b7d5e9d8306375734 6dcfbef1ed788bcd6c13bf26816080b6 +chacha20-poly1305 381 2a496887a6c5e4032241607f 0 63 9dac206562e7bb9a64ff48ce2ebc72320537e0a79a48ec2025b74fdd21166793 491539bb96645856954de90774bdf724 +chacha20-poly1305 382 31506f8eadcceb0a29486786 1 63 5725e3643e2ba1d2e5ded38740048edc9b4ec948856933e202f22cd1dcf498b7 3a8f39095ce96689718add341dc7bc93 +chacha20-poly1305 383 38577695b4d3f211304f6e8d 16 63 e5b4e9e311c0fc06cff1b4a759595330bc8ef849d9c502643276e56f95b03dc4 845fff51954fd6802bcd009639884ee6 +chacha20-poly1305 384 3f5e7d9cbbdaf91837567594 33 63 9f31af7f8ba2dab029d96ec52cc6909451a7d3716291ca830026d542aafb11e0 e99a0cc68f88e5bbe681925b0f618da4 +chacha20-poly1305 385 466584a3c2e1001f3e5d7c9b 0 64 bc90f1f9dee57625e14f91b031a0176c4ae5cd5ac4507f15edfd9ec2b8e27cd0 5fd177bf4fa3f1be99533fa56263d7ea +chacha20-poly1305 386 4d6c8baac9e80726456483a2 1 64 889fae7733ab70b84ee63e718304c6a2630f07b8253b95ab6aec2bd04b21a310 35cef86bf52c52cd65ea7a2ab4c554bf +chacha20-poly1305 387 547392b1d0ef0e2d4c6b8aa9 16 64 98988749134e50f1c95b1482bb6e7b9d51b3849532136b9bafba19970100088e fde9bdb284bd92032bba80977eaeb196 +chacha20-poly1305 388 5b7a99b8d7f61534537291b0 33 64 682658cb0fb010613d68bc979c8a926259a3dc5d9f7d6880ce7ce390acb23fe3 3ff48e442a0dac2919f18653a0bccabe +chacha20-poly1305 389 6281a0bfdefd1c3b5a7998b7 0 65 3dee558cffd49f471362bec713b45c99d2510e604ffa4a406555ed00a410ebee 5cb178606ae2297a61a497aec1d1e527 +chacha20-poly1305 390 6988a7c6e504234261809fbe 1 65 43637796721b244a5df0188be8b67ab8bc097ffbb2deb2277cc365f2f3156670 d666ed74a06396e09ff217e6242ac9ba +chacha20-poly1305 391 708faecdec0b2a496887a6c5 16 65 3f27ca1949096584dc2c44e721c2d57a1feb9a40a1b00734d383563197b5760d 448950f6053efe5dbef45ddc376b400c +chacha20-poly1305 392 7796b5d4f31231506f8eadcc 33 65 940f8d177e2d934733aa37975bec4310b9a3f7b0d48ea0b3fc6a98dfb053aa44 6a89cd94ad28af28145c2542b5f589f1 +chacha20-poly1305 393 7e9dbcdbfa1938577695b4d3 0 127 e77d32df372cef2dcdd45b8196502b86bd6e4c9add633e543612fca87ce6d655 5314265ca608666456deb61820c6dbac +chacha20-poly1305 394 85a4c3e201203f5e7d9cbbda 1 127 4f5d24836496da4aae0f9b7807580c6f0c4655660f0224f12d696a6694953b3a c4cb70636550c32518e245c7b0dd8fd4 +chacha20-poly1305 395 8cabcae90827466584a3c2e1 16 127 b5e467778cf3de13d627bff9ec2ba86653f9bd0966d93f88c6d867ca9de0e699 727784c71e44fd071602b17be1796924 +chacha20-poly1305 396 93b2d1f00f2e4d6c8baac9e8 33 127 dd04ae14dbbc625ef5049493b91804897c6ef20c19c6f771bf0f1feee5bb5acd 234357861cb6545490ffc2dde5cafefd +chacha20-poly1305 397 9ab9d8f71635547392b1d0ef 0 128 b893e3f9fc8f83a150f6da8bccc09cefa7ae6a044b2f1c689a57b689c7ee92db edb16e3882ba2949723b459b587fd6bc +chacha20-poly1305 398 a1c0dffe1d3c5b7a99b8d7f6 1 128 35c26b0c40f44db35c663bd3eae193467b9bde5316c9611ffe4f1e8b59a4237c f1710466378f212374ed26799d93e9fd +chacha20-poly1305 399 a8c7e60524436281a0bfdefd 16 128 5e87c1041be13c9c6f2eba1606581e67dee3d50e1a01a3138ff0598cb92db34f b34ffad05e1274bf5b307863b8855c76 +chacha20-poly1305 400 afceed0c2b4a6988a7c6e504 33 128 15d03b6fdf265d47d1ca1cac58deb9b567d1292c2449600c98487057fefbb81d 754161b6f0be561ffd3c1d896fb4ca76 +chacha20-poly1305 401 b6d5f4133251708faecdec0b 0 129 4e08927839099d084c002d4fdce298f5290ac43e42c403addf7c205782c4866a ad78ff2ecd127f63e5efbae5ca3981cd +chacha20-poly1305 402 bddcfb1a39587796b5d4f312 1 129 5363659887e7bc7118f1981901b01f67c233494193a98fc24690bf9b5ff004cf 3ebaa42c32fbbc8edec3961252fe07ca +chacha20-poly1305 403 c4e30221405f7e9dbcdbfa19 16 129 1caf651d65311921ec7dd471a2c0b8e7e6339482bf46ff4e82a30b6da0fcc60b 222f0be8d5aab92b36a43c24c956d0f0 +chacha20-poly1305 404 cbea0928476685a4c3e20120 33 129 2adb54ba1c7a86722f80b3a6d290cd538a89b2e4bc9de8befc79d98f666ec885 b648e302b620f3cab2add43ceb81571c +chacha20-poly1305 405 d2f1102f4e6d8cabcae90827 0 255 db9a2b2923104b3ef6c89b209a00b2e9050a633ac35ff7a98a5dd54355b4c620 37a35ee0f6797d4dce1fb923eccef810 +chacha20-poly1305 406 d9f81736557493b2d1f00f2e 1 255 c2f739bd6f4cad3183a98d467ba071b7de439685ae7db93fd349b084d6f7c502 c38d8ff66dc9a4490ad7a36c294b42f1 +chacha20-poly1305 407 e0ff1e3d5c7b9ab9d8f71635 16 255 5b8354f8d42a6521ff7a1ad4c8566e46c6be50560bb8f5035d2e4f7300a7a1c7 982254c68097c0794e436df3deb9ab0a +chacha20-poly1305 408 e70625446382a1c0dffe1d3c 33 255 93adfbb704cecefe2fd82d9a50fd04c0c815ed0f38cd68c69ef3a6e3f869968e 6e4d89bb61c438c44857a7e2565ae1e7 +chacha20-poly1305 409 ee0d2c4b6a89a8c7e6052443 0 256 a02a894ed501cb37a50b87eaf4c23249bc467c4a45961d6b4c0d652ac825cb66 a22ab05c7e74fb2ff49a679c5d6d61fd +chacha20-poly1305 410 f51433527190afceed0c2b4a 1 256 cdec66de03ec68b2f8fede1a245e1c6b71816a53d5b59969a21c66eb76c20dd9 2a292053520f10be59cda416666ae25b +chacha20-poly1305 411 fc1b3a597897b6d5f4133251 16 256 682d45060157fae3f34d3fe61f078aa63b0fa46f36d6fa5583b15c6bd974cdca 84986aebe648eee33ead19a98beaeda1 +chacha20-poly1305 412 032241607f9ebddcfb1a3958 33 256 7a16bbee426bbceb6fd2b8e95aa6d847ccbefb82694302dac83875159ffdeae9 552bd6b76e47ac7115deb0923d34249a +chacha20-poly1305 413 0a29486786a5c4e30221405f 0 511 5e3810c8f0bcbe326d251ef2b84b3880eaccac5ec297d721035c27162007a1d7 7550c7c7f068f6beb69a4e6e42e4752d +chacha20-poly1305 414 11304f6e8daccbea09284766 1 511 c7ea1e801971ce7704e5e5a20dfdbc9b49013e1b18c567ff41ab0a5c6820df48 28a34941750f4e3a8b6713d5b85173b4 +chacha20-poly1305 415 1837567594b3d2f1102f4e6d 16 511 90ff924ef30f45ca41ccddffc1eaf0fd0fc07c988a20bd860606bfcd6dc944b7 68e7e5ed9a35e2c1b336ac41b45fd869 +chacha20-poly1305 416 1f3e5d7c9bbad9f817365574 33 511 8826112fb61c05a88ad7951b72e9f13792809573ee7a2141a8ed8f4fd4fcac76 749a13aec9e087e954530f265bff5e91 +chacha20-poly1305 417 26456483a2c1e0ff1e3d5c7b 0 512 9e2a917abb0ffe7a16db825466f998783206b43b66dbbe58f9256368ba756e2f 0e79dd420a219c44b76640c65c13f009 +chacha20-poly1305 418 2d4c6b8aa9c8e70625446382 1 512 901552e162b6a7bdeb4b61bf4cedea44977ed53223875e65f7a1c1f362164bd9 0fda6dcf384b4fdbfefc4a17ac2bf5dc +chacha20-poly1305 419 34537291b0cfee0d2c4b6a89 16 512 208f761096791d95a146d72becd506099ef7bdba2fd72bf109e91336cc003d2f 23c8177ae9cb6efc5a61df11e830572e +chacha20-poly1305 420 3b5a7998b7d6f51433527190 33 512 61b5ab98e215b33bd38a8afb01642581163a818ac7737fc3c79dbc083070120e bdfc7b4581c49b7a801a95fa153e11d5 +chacha20-poly1305 421 4261809fbeddfc1b3a597897 0 513 85a0190e4a57a7f6e38aa5dcf0db618645caacddbfb686500efef12144360758 954b11b87b0d1c7e52e5b2ad73ddce2d +chacha20-poly1305 422 496887a6c5e4032241607f9e 1 513 bd42faaa75efc8d2770116253ff94f4f605477e7fb7a715433b79abc0dae237e 51b130551962b4873c6a4b4eb0e03faf +chacha20-poly1305 423 506f8eadcceb0a29486786a5 16 513 86e24148202a25de11c54339f86cbfc09e957066bf35471c0cb121d87bb3c423 76ccd2a6cf578ff163c9a7c843581d40 +chacha20-poly1305 424 577695b4d3f211304f6e8dac 33 513 372554ac5247934cf86b4b760ad72299bb9cc615f44831d3d57dcb154be92ee3 eb7a1f22501f5a16d919281895faa372 +chacha20-poly1305 425 5e7d9cbbdaf91837567594b3 0 1023 60a0a3ca2e7fb419ac1e90f18206096326f5b96ee66a750e62cbe81f35f5bf88 391c6d948d6e8bcc1990f123f6bd1ad6 +chacha20-poly1305 426 6584a3c2e1001f3e5d7c9bba 1 1023 ddce7d21d7a39aa940eab999f9863d970ee0d48fea887fad5fb748937517cfab bfd17e9052a44a3d569e09fc31e86ba0 +chacha20-poly1305 427 6c8baac9e80726456483a2c1 16 1023 ffce97a9252db53e3cb108c28a94d1578758e577279c4bab029cfc8c28f95096 7bddfc8f0dd903a0500862193b0156f3 +chacha20-poly1305 428 7392b1d0ef0e2d4c6b8aa9c8 33 1023 c2c0fd5f7f95e7af70b6249c5c14a6b7dc7d3c355dff2819107bad9218578bb5 5fda7bc67b6d3a3d3e08e99a69315dd9 +chacha20-poly1305 429 7a99b8d7f61534537291b0cf 0 1024 f47c1d08ff5c5f9176dd5efcd97c2d5eb6d5da020ac90ac472b20a784008ccab 2cfad5574b7c14814423acad5f981c6e +chacha20-poly1305 430 81a0bfdefd1c3b5a7998b7d6 1 1024 fba91b9afbddf0d826d8ca037f9692495e3ba9d93f4342e1e03210dc44e8fcf4 f1bc391c2996cd9646cb6d36b1ce853e +chacha20-poly1305 431 88a7c6e504234261809fbedd 16 1024 25f664fdc2e4c0c65063d3afab01293e87eef15dd2788cae66eb85d746ef1d05 4344fed850ff9552ce350a4d7d3f81ec +chacha20-poly1305 432 8faecdec0b2a496887a6c5e4 33 1024 7bdbc7dd8deb8de5db5eeae5a886bed826b193a51522a466cf1c31b2ad53af3c 69347627cf9e99c33532c316b1703280 +chacha20-poly1305 433 96b5d4f31231506f8eadcceb 0 1025 277539455719202083bb29e840ff23c0c36d44da400c6c0d4d915bd4983b25f9 4cd70b6235052356b278f25a939c3dad +chacha20-poly1305 434 9dbcdbfa1938577695b4d3f2 1 1025 7d25b7e92f01dbd5182b25ce89d9f4306218b7590852cc5963b8cf0da7b2e862 75f5a11cd3e3e689bd06d90b397538b1 +chacha20-poly1305 435 a4c3e201203f5e7d9cbbdaf9 16 1025 7f64e88fab456c01f1996e5759d3cf0f97a37a2a086dff7b34b41860e6aac828 354e834d6983267c65fd1ac7eb24c06d +chacha20-poly1305 436 abcae90827466584a3c2e100 33 1025 5a922ddfc8c9d8d0bfc48008fe4e64ceb08a8795114d305b5e7da175ac8cd5fe c83bc0041d63f165fce8acdc6ed3243b +chacha20-poly1305 437 b2d1f00f2e4d6c8baac9e807 0 4103 fe60b26e3bdcfab992be47d45b032604737260eacd05db47bd0b478f0bcbe819 e54dcf0c765c100f90b657b3790ded95 +chacha20-poly1305 438 b9d8f71635547392b1d0ef0e 1 4103 afbf186c2bc17cba68613b70b42ba27c7ce6fe9ec5054b4e624f3613efcfb172 de58fbc9c87e9ab482330d556c248682 +chacha20-poly1305 439 c0dffe1d3c5b7a99b8d7f615 16 4103 1c66cd449d36b0e9fae2fb20d4e2a670055b6fa4400a43a4f7aaa9572f310945 f517264decf52ff3252d9004812e3ad5 +chacha20-poly1305 440 c7e60524436281a0bfdefd1c 33 4103 39b74399bbb63227ce20488ce57c9749da31143b0a4eee1048442ec4d091084e 59a8e3d300fa2edf144fcc41dd2a92da +aes-128-ctr 441 ffffffffffffffffffffffffffffffff 0 16 dbab6053d984eea645d470f5c413bed29835661c10046e1e26a36dd46b05a4b7 - +aes-128-ctr 442 ffffffffffffffffffffffffffffffff 0 100 bf60ddaa1fe63b7c3989adbc8bc4f97e7396baee02ecfcf94e4f7d68cc2a9a95 - +aes-128-ctr 443 ffffffffffffffffffffffffffffffff 0 129 d055990e0194d1b6dc1c5ed0e88be1838d0348b7793bb8c978618b262b2cd4e7 - +aes-128-ctr 444 ffffffffffffffffffffffffffffffff 0 300 0bd2a7140b01f4d90717e0d11775a89f707980f5512d54d66304573a740eede6 - +aes-128-ctr 445 0000000000000000fffffffffffffffa 0 16 c1fb8806cf6fc8704e414ca70ad270dfd3e06a97e0578306202cad8dfb034acf - +aes-128-ctr 446 0000000000000000fffffffffffffffa 0 100 126a054950801970115590b93a10c98055a57a257200d3b78aa693fb4b636166 - +aes-128-ctr 447 0000000000000000fffffffffffffffa 0 129 b77f461e4b8bc534410807388da3c70146da73f32c42c39377268998b1004167 - +aes-128-ctr 448 0000000000000000fffffffffffffffa 0 300 f53c81ed10ea327b4c86df974643f577e40fcd4b5b9a1b11b402b825a29ab68e - +aes-128-ctr 449 00000000000000fffffffffffffffff9 0 16 9c28a16f64867d66c4b4a9dee58c57151edf68ff04f5b8994c95037e545990c9 - +aes-128-ctr 450 00000000000000fffffffffffffffff9 0 100 8822f1bec5659eab65f1a77bb823356e0bf88f252d1265215ca1f9a1e98d6f8a - +aes-128-ctr 451 00000000000000fffffffffffffffff9 0 129 fd8a24f502626ccc8b76437346fd9bcd0a8491dd9eefa6aed280416ad0a05056 - +aes-128-ctr 452 00000000000000fffffffffffffffff9 0 300 e2f81e86c90c588bd7ef715fd10ef624ba842e442cd7307d4015e054673d5326 - +aes-256-ctr 453 ffffffffffffffffffffffffffffffff 0 16 d1e197ddeb79f7295d9e10a87b40f94c7c4e284e6768f31441eed394377127d0 - +aes-256-ctr 454 ffffffffffffffffffffffffffffffff 0 100 7919c332cff842d927f5eb525a6f1afbe6c5288bf369737428021c119e3cd377 - +aes-256-ctr 455 ffffffffffffffffffffffffffffffff 0 129 19d9b1180ad9a06296fcce5c380bd2ca30bd9199a23758d7ee6603f0a8d43efb - +aes-256-ctr 456 ffffffffffffffffffffffffffffffff 0 300 32615d1389b1475157eb7ab979ec59fd84d19263f68f3cb3eb948960506da9e6 - +aes-256-ctr 457 0000000000000000fffffffffffffffa 0 16 c0cf24861ed203875c98f16db5b1feb065ed83b932b17c9a4db84ecea4fe2003 - +aes-256-ctr 458 0000000000000000fffffffffffffffa 0 100 839781805122608b341f3e41d1344688bfca057a6e2733c9576557eb5f8f9f14 - +aes-256-ctr 459 0000000000000000fffffffffffffffa 0 129 2b1256619e1341bbb26131c34fe538dc753d177d2af053f5efcd02e6490ed4c9 - +aes-256-ctr 460 0000000000000000fffffffffffffffa 0 300 cf70c345f1879aa9b0dd9e94e449b57fda2d5f33ed8d23ddcc3bd063453af42a - +aes-256-ctr 461 00000000000000fffffffffffffffff9 0 16 673b30fe431c16df69f383ca19191e4da158bf63b6c751bd462111e9dc000885 - +aes-256-ctr 462 00000000000000fffffffffffffffff9 0 100 b07e2bef276494bdb693ad99900eae91c2dc90d259682d23a9dcee6799dac11a - +aes-256-ctr 463 00000000000000fffffffffffffffff9 0 129 c4efea91bd611a5f137bbef2a51ae862426622dbf321e7b91e404fc3ef3ca1ca - +aes-256-ctr 464 00000000000000fffffffffffffffff9 0 300 0271333d4e4484f1229fdbf231bca20b350c4ce2826afd76dd7bb7efca9dabcf - +aes-128-gcm 465 32 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 ee047600ed1491f46dd7378eb27c4945 +aes-128-gcm 466 39 20 33 1418759f797fc8171850e31ebe08fd7b4c221edde863184659ec7d9979cc0928 5f4de0dedc9243d255cff93a326ce36f +aes-128-gcm 467 40 20 200 8ee67355c135052199ab5eb48e6b2a3b621592439ceda8c861c59e1dd980f3ae 0d1f949a0f34ff202292ad807ab2cc1e +aes-128-gcm 468 476685a4c3e20120 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 c0a9adc4e782bb780df74774686bab4b +aes-128-gcm 469 4e6d8cabcae90827 20 33 6b265efde4799e20d586070fc8b4dafdf2c883d8b869768d401076cf4a6b459b 2b536b6e86af82f0f13376822470e2df +aes-128-gcm 470 557493b2d1f00f2e 20 200 dca252264a10e62898d36beee74ed11dbdd532c4e52a3a4c8993a4cbbc87311a efc836909141ebe1c1630efca2b42d90 +aes-128-gcm 471 5c7b9ab9d8f71635547392b1d0 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 3490834580c5cb08061103deb3a39091 +aes-128-gcm 472 6382a1c0dffe1d3c5b7a99b8d7 20 33 b046b151184acb0532dd6bc2c9731572e060b8644517934222cbf9b0a3de7a46 fc800f5480a89aa102c44dae5ce26f73 +aes-128-gcm 473 6a89a8c7e60524436281a0bfde 20 200 c1e50a87ee22a0a51fb03cd26051e3a7e797970fb46cee8cc1cfb9958772757b c02e15313928aee66585a26bd33d126f +aes-128-gcm 474 7190afceed0c2b4a6988a7c6e5042342 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 2273b4b99c8ef20bcde44d10a7539ea9 +aes-128-gcm 475 7897b6d5f4133251708faecdec0b2a49 20 33 8b9adb248671e864c05b919029d3ee01069641e7f0ced3f0c5f145445b182237 12e8daf37db93e6452c0933a310833b8 +aes-128-gcm 476 7f9ebddcfb1a39587796b5d4f3123150 20 200 58d0beddceff72f26966e7a1a8addaffa759658de05882d9f05b8830f5162374 cf4d15ae11dbc089c1053579e8cdf1b0 +aes-128-gcm 477 86a5c4e30221405f7e9dbcdbfa1938577695b4d3f211304f6e8daccbea0928476685a4c3e201203f5e7d9cbbdaf91837567594b3d2f1102f4e6d8cab 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 bff45422b553c95d27e5b11ef79616c5 +aes-128-gcm 478 8daccbea0928476685a4c3e201203f5e7d9cbbdaf91837567594b3d2f1102f4e6d8cabcae90827466584a3c2e1001f3e5d7c9bbad9f81736557493b2 20 33 cffb787f7a5722bb2d472e0b28da9571a01ec57d25c6c475fd7c0cc1730ddd06 dd2765f215d20e6d837791ada0b778d2 +aes-128-gcm 479 94b3d2f1102f4e6d8cabcae90827466584a3c2e1001f3e5d7c9bbad9f81736557493b2d1f00f2e4d6c8baac9e80726456483a2c1e0ff1e3d5c7b9ab9 20 200 10af376fd20214b6d5e8bad44fbdb52ea37fa473ee1340210ee40a08bc4b50a9 9bb95ef30ac7fac8a4e9dd263ae40a38 +aes-128-gcm 480 9bbad9f81736557493b2d1f00f2e4d6c8baac9e80726456483a2c1e0ff1e3d5c7b9ab9d8f71635547392b1d0ef0e2d4c6b8aa9c8e70625446382a1c0dffe1d3c 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 4124b81db55b258126138ce7f0386be7 +aes-128-gcm 481 a2c1e0ff1e3d5c7b9ab9d8f71635547392b1d0ef0e2d4c6b8aa9c8e70625446382a1c0dffe1d3c5b7a99b8d7f61534537291b0cfee0d2c4b6a89a8c7e6052443 20 33 6b79ecb8569f0e2614c8e3707096f1ffd1a8332d83c2184b216ae9157454735f 1a457276574a3d05ca0c68725e005d33 +aes-128-gcm 482 a9c8e70625446382a1c0dffe1d3c5b7a99b8d7f61534537291b0cfee0d2c4b6a89a8c7e60524436281a0bfdefd1c3b5a7998b7d6f51433527190afceed0c2b4a 20 200 6e037efc7b6272f36c578e7b23d3308efc33ca90dbd71ec54b420d825f87bf58 21ad274b8153fea020b0c09cb4ab004f +aes-256-gcm 483 b0 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 ad3a62c0fef9c6d11685b20188d60a0f +aes-256-gcm 484 b7 20 33 be568a0d7e319505f34bfdc2cbc8e3cc6638b416bffa994d931e7805e4177883 01c92b54b1eca5b314c17c54c673298d +aes-256-gcm 485 be 20 200 40c48da80b42555525d409b8947d14b2b08dd59e4a78314820bcef15a561d496 349bb8d6e95c4dd1e17ee32022b706b2 +aes-256-gcm 486 c5e4032241607f9e 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 21943470d16fd695937e1ab736c7ec01 +aes-256-gcm 487 cceb0a29486786a5 20 33 adbaf6d9f4604d44f8fd4dea00c6ee4650607338de0856df1b6f38edac8b30d3 3fa3b53175761782f70c8772066b21a0 +aes-256-gcm 488 d3f211304f6e8dac 20 200 aab1159a68f475e1360f931d341833c8a091c05aa6d49c2c974e52176b753203 8378ad7a24c2027065bd40b1df0719b8 +aes-256-gcm 489 daf91837567594b3d2f1102f4e 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 9b52aae426057aa30180534f0092b321 +aes-256-gcm 490 e1001f3e5d7c9bbad9f8173655 20 33 c55864cb8929d75fdaf6370ef4c327f92b623a60232666d417f08ee1d4cfad4e 3284d305cef3b9542e6396ba8aa2e839 +aes-256-gcm 491 e80726456483a2c1e0ff1e3d5c 20 200 0bc053491060ace461d7a4877187773f84eb41f76b3ddc49c2493034641b1216 1be99d4ed1ae6fe21774906de6c623f1 +aes-256-gcm 492 ef0e2d4c6b8aa9c8e70625446382a1c0 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 5e637175a00cac71cbbded12c749d893 +aes-256-gcm 493 f61534537291b0cfee0d2c4b6a89a8c7 20 33 7ecb0f02e2bcd9bbae0b12c5aceb2057ca15c94b127df4a43c5905e1bfa9528e 12d452b47fbc62d6809702a67ca1922a +aes-256-gcm 494 fd1c3b5a7998b7d6f51433527190afce 20 200 de845d2985f62e4e859f896960d09fcc13ab21497693338ccab5a4e5c0b434dc dd7f25816859e9acc81cfb4e8780066e +aes-256-gcm 495 04234261809fbeddfc1b3a597897b6d5f4133251708faecdec0b2a496887a6c5e4032241607f9ebddcfb1a39587796b5d4f31231506f8eadcceb0a29 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 405637d1519cf4e0b8e9988532b61cf9 +aes-256-gcm 496 0b2a496887a6c5e4032241607f9ebddcfb1a39587796b5d4f31231506f8eadcceb0a29486786a5c4e30221405f7e9dbcdbfa1938577695b4d3f21130 20 33 6871559f18ab183b9687034e337bbd8938ddae3c5e8535a61e6e851bcd280d51 925d0f2726801323355b252caa28b80f +aes-256-gcm 497 1231506f8eadcceb0a29486786a5c4e30221405f7e9dbcdbfa1938577695b4d3f211304f6e8daccbea0928476685a4c3e201203f5e7d9cbbdaf91837 20 200 a5d45e09c7c16f5d396b0f2142db164bdd2fb31dfd4ed746bac3bcf2700f0139 ba8d10de85eca2905cc2575736ee2425 +aes-256-gcm 498 1938577695b4d3f211304f6e8daccbea0928476685a4c3e201203f5e7d9cbbdaf91837567594b3d2f1102f4e6d8cabcae90827466584a3c2e1001f3e5d7c9bba 20 0 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 7dab970ba2e822ab8030cd77b027cc50 +aes-256-gcm 499 203f5e7d9cbbdaf91837567594b3d2f1102f4e6d8cabcae90827466584a3c2e1001f3e5d7c9bbad9f81736557493b2d1f00f2e4d6c8baac9e80726456483a2c1 20 33 4b853d5b026aaaec22b7ba7f95af3e7d56dcc07cd5a73726053beb09039392c8 1cb02f06202f0050507658ad854531a0 +aes-256-gcm 500 27466584a3c2e1001f3e5d7c9bbad9f81736557493b2d1f00f2e4d6c8baac9e80726456483a2c1e0ff1e3d5c7b9ab9d8f71635547392b1d0ef0e2d4c6b8aa9c8 20 200 d10a620d1db9f18617edc28317012b19ae9abc3b97dd3fdf310314ed7a597627 0f76b4a3cdfddb0537494a7e098f5571 diff --git a/packages/runtime/test/cipher-kernels.test.ts b/packages/runtime/test/cipher-kernels.test.ts new file mode 100644 index 000000000..22baebc96 --- /dev/null +++ b/packages/runtime/test/cipher-kernels.test.ts @@ -0,0 +1,44 @@ +import { execFile } from "node:child_process"; +import { mkdir, readdir } from "node:fs/promises"; +import { join } from "node:path"; +import { promisify } from "node:util"; +import { beforeAll, expect, test } from "vitest"; + +const execFileAsync = promisify(execFile); +const testDir = import.meta.dirname; +const bin = join(testDir, "build", "test_cipher_kernels"); +const mbedtls = join(testDir, "../vendor/mbedtls"); + +// Compiles the cipher kernels with the vendored mbedTLS library, under +// ASan, once. +beforeAll(async () => { + await mkdir(join(testDir, "build"), { recursive: true }); + const library = (await readdir(join(mbedtls, "library"))) + .filter((name) => name.endsWith(".c")) + .sort() + .map((name) => join(mbedtls, "library", name)); + await execFileAsync("clang", [ + "-std=c11", + "-O1", + "-fsanitize=address", + "-I", + join(testDir, "../src"), + "-I", + join(mbedtls, "include"), + "-I", + join(mbedtls, "library"), + "-o", + bin, + join(testDir, "test_cipher_kernels.c"), + join(testDir, "../src/scr_cipher_simd.c"), + ...library, + ]); +}, 300_000); + +// Runs against the committed case file (generated from Node v24 by +// gen-cipher-cases.mjs). On x86-64 CPUs with AES-NI, PCLMULQDQ and AVX2, +// every case also runs through the SIMD kernels with several chunkings. +test("cipher kernels match Node on committed cases", async () => { + const { stderr } = await execFileAsync(bin, [join(testDir, "cipher-cases.txt")]); + expect(stderr.trim()).toMatch(/^cases 500 simd \d+ failures 0$/); +}); diff --git a/packages/runtime/test/cipher.test.ts b/packages/runtime/test/cipher.test.ts index 6b44a4b4b..94980f084 100644 --- a/packages/runtime/test/cipher.test.ts +++ b/packages/runtime/test/cipher.test.ts @@ -13,6 +13,7 @@ const runtimeSources = [ "scr_shared.c", "scr_bytes.c", "scr_bytes.test.c", + "scr_cipher_simd.c", "scr_bytes_io.c", "scr_fs_cp.c", "scr_zlib.c", @@ -64,10 +65,11 @@ const mbedtlsSources = [ ]; // Compiled once with ASan + the RC audit. test_cipher.c includes -// scr_cipher.c, moves contexts next to mbedTLS's GCM message and AAD -// limits, and checks that a failed update() or setAAD() returns no data -// and leaves every later call throwing, and that chacha20-poly1305 -// decryption without a tag fails in final(). +// scr_cipher.c, moves contexts next to the GCM message and AAD limits (in +// the x86-64 kernels or mbedTLS, whichever the CPU selects), and checks +// that a failed update() or setAAD() returns no data and leaves every +// later call throwing, and that chacha20-poly1305 decryption without a +// tag fails in final(). beforeAll(async () => { await mkdir(join(testDir, "build"), { recursive: true }); await execFileAsync("clang", [ diff --git a/packages/runtime/test/gen-cipher-cases.mjs b/packages/runtime/test/gen-cipher-cases.mjs new file mode 100644 index 000000000..b2678c3d1 --- /dev/null +++ b/packages/runtime/test/gen-cipher-cases.mjs @@ -0,0 +1,73 @@ +// Generates cipher test cases with Node as the oracle. +// Each line: \t\t\t\t\t\t +// +// node gen-cipher-cases.mjs > cipher-cases.txt +// +// Keys, AAD and plaintexts are pattern(length, seed) bytes, which +// test_cipher_kernels.c recomputes, so the file stores only the IV, the lengths, +// a digest of the ciphertext and the authentication tag. Lengths cover +// partial blocks and the 128-byte (AES) and 512-byte (ChaCha20) batch +// boundaries of the SIMD kernels; IVs cover CTR counter carries and GCM +// IVs other than 12 bytes. CBC ciphertexts include Node's PKCS#7 padding. +import { createCipheriv, createHash } from "node:crypto"; +import { stdout } from "node:process"; + +const pattern = (length, seed) => + Buffer.from(Array.from({ length }, (_, i) => (i * 31 + seed * 7 + 3) & 0xff)); + +const ciphers = [ + ["aes-128-cbc", 16], + ["aes-192-cbc", 24], + ["aes-256-cbc", 32], + ["aes-128-ctr", 16], + ["aes-192-ctr", 24], + ["aes-256-ctr", 32], + ["aes-128-gcm", 16], + ["aes-192-gcm", 24], + ["aes-256-gcm", 32], + ["chacha20-poly1305", 32], +]; +const lengths = [ + 0, 1, 15, 16, 17, 63, 64, 65, 127, 128, 129, 255, 256, 511, 512, 513, 1023, 1024, 1025, 4103, +]; +const lines = []; +let seed = 1; + +function add(name, keyLength, iv, aadLength, length) { + const s = seed++; + const cipher = createCipheriv(name, pattern(keyLength, s), iv); + const aead = name.endsWith("gcm") || name.startsWith("chacha"); + if (aead && aadLength > 0) cipher.setAAD(pattern(aadLength, s + 1)); + const ciphertext = Buffer.concat([cipher.update(pattern(length, s + 2)), cipher.final()]); + const tag = aead ? cipher.getAuthTag().toString("hex") : "-"; + const digest = createHash("sha256").update(ciphertext).digest("hex"); + lines.push([name, s, iv.toString("hex"), aadLength, length, digest, tag].join("\t")); +} + +for (const [name, keyLength] of ciphers) { + const ivLength = name.endsWith("cbc") || name.endsWith("ctr") ? 16 : 12; + const aadLengths = name.endsWith("gcm") || name.startsWith("chacha") ? [0, 1, 16, 33] : [0]; + for (const length of lengths) { + for (const aadLength of aadLengths) + add(name, keyLength, pattern(ivLength, seed + 100), aadLength, length); + } +} +for (const name of ["aes-128-ctr", "aes-256-ctr"]) { + const keyLength = name.includes("128") ? 16 : 32; + for (const ivHex of [ + "ffffffffffffffffffffffffffffffff", + "0000000000000000fffffffffffffffa", + "00000000000000fffffffffffffffff9", + ]) { + for (const length of [16, 100, 129, 300]) + add(name, keyLength, Buffer.from(ivHex, "hex"), 0, length); + } +} +for (const name of ["aes-128-gcm", "aes-256-gcm"]) { + const keyLength = name.includes("128") ? 16 : 32; + for (const ivLength of [1, 8, 13, 16, 60, 64]) { + for (const length of [0, 33, 200]) + add(name, keyLength, pattern(ivLength, seed + 200), 20, length); + } +} +stdout.write(lines.join("\n") + "\n"); diff --git a/packages/runtime/test/test_cipher.c b/packages/runtime/test/test_cipher.c index 18bd9fea8..1d42bd017 100644 --- a/packages/runtime/test/test_cipher.c +++ b/packages/runtime/test/test_cipher.c @@ -123,8 +123,10 @@ static void test_gcm_message_limit(bool decrypt) { scr_dyn_release(call(h, "setAuthTag", tag, NULL)); scr_dyn_release(tag); } - /* As if GCM_MAX - 32 bytes had been processed. */ + /* As if GCM_MAX - 32 bytes had been processed, on either backend. */ ctx(h)->gcm.MBEDTLS_PRIVATE(len) = GCM_MAX - 32; + ctx(h)->simd_gcm.text_len = GCM_MAX - 32; + ctx(h)->simd_gcm.data = true; ctx(h)->data_started = true; ScrDyn *block = buffer(16, 9); ScrDyn *r = call(h, "update", block, NULL); @@ -153,6 +155,7 @@ static void test_gcm_aad_limit(void) { check(h != NULL, "create aes-128-gcm"); if (!h) return; ctx(h)->gcm.MBEDTLS_PRIVATE(add_len) = (1ull << 61) - 8; + ctx(h)->simd_gcm.aad_len = (1ull << 61) - 8; ScrDyn *aad = buffer(16, 3); ScrDyn *r = call(h, "setAAD", aad, NULL); check(!r && take_error("Error: Invalid state for operation setAAD", "ERR_CRYPTO_INVALID_STATE"), diff --git a/packages/runtime/test/test_cipher_kernels.c b/packages/runtime/test/test_cipher_kernels.c new file mode 100644 index 000000000..42383c6b7 --- /dev/null +++ b/packages/runtime/test/test_cipher_kernels.c @@ -0,0 +1,269 @@ +/* Checks the mbedTLS cipher path and the scr_cipher_simd.c kernels against + * Node-generated cases (gen-cipher-cases.mjs). Each case is encrypted in + * one call on the mbedTLS path and, when the CPU supports the kernels, + * with several chunkings on the SIMD path; the SIMD path also decrypts + * the ciphertext back with a different chunking. Prints a summary to + * stderr and exits nonzero on the first mismatch. */ +#include "scr_cipher_simd.h" + +#include +#include +#include + +#include "mbedtls/aes.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/gcm.h" +#include "mbedtls/sha256.h" + +typedef struct { + char name[32]; + unsigned seed; + unsigned char iv[64]; + size_t iv_len; + size_t aad_len; + size_t pt_len; + unsigned char digest[32]; + unsigned char tag[16]; + bool has_tag; +} Case; + +static void pattern(unsigned char *out, size_t length, unsigned seed) { + for (size_t i = 0; i < length; i++) out[i] = (unsigned char)((i * 31 + seed * 7 + 3) & 0xff); +} + +static size_t unhex(const char *s, unsigned char *out, size_t cap) { + size_t n = strlen(s) / 2; + if (n > cap) n = cap; + for (size_t i = 0; i < n; i++) { + unsigned v; + sscanf(s + 2 * i, "%2x", &v); + out[i] = (unsigned char)v; + } + return n; +} + +static size_t key_len_of(const char *name) { + if (strstr(name, "128")) return 16; + if (strstr(name, "192")) return 24; + return 32; +} + +static bool ends_with(const char *s, const char *suffix) { + size_t a = strlen(s), b = strlen(suffix); + return a >= b && strcmp(s + a - b, suffix) == 0; +} + +static int failures = 0; + +static void check(const Case *c, const char *path, const unsigned char *ct, size_t ct_len, const unsigned char *tag) { + unsigned char digest[32]; + mbedtls_sha256(ct, ct_len, digest, 0); + bool ok = memcmp(digest, c->digest, 32) == 0 && (!c->has_tag || memcmp(tag, c->tag, 16) == 0); + if (!ok && failures++ < 10) + fprintf(stderr, "mismatch: %s seed=%u aad=%zu len=%zu iv=%zu path=%s\n", c->name, c->seed, c->aad_len, + c->pt_len, c->iv_len, path); +} + +/* The PKCS#7-padded plaintext length for CBC. */ +static size_t padded(size_t length) { + return length + 16 - length % 16; +} + +static void run_portable(const Case *c, const unsigned char *key, const unsigned char *aad, + const unsigned char *pt, unsigned char *ct) { + size_t key_len = key_len_of(c->name); + unsigned char tag[16] = {0}; + if (ends_with(c->name, "cbc")) { + size_t n = padded(c->pt_len); + unsigned char *in = malloc(n); + memcpy(in, pt, c->pt_len); + memset(in + c->pt_len, (int)(n - c->pt_len), n - c->pt_len); + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + mbedtls_aes_setkey_enc(&aes, key, (unsigned)key_len * 8); + unsigned char iv[16]; + memcpy(iv, c->iv, 16); + mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, n, iv, in, ct); + mbedtls_aes_free(&aes); + free(in); + check(c, "mbedtls", ct, n, tag); + } else if (ends_with(c->name, "ctr")) { + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + mbedtls_aes_setkey_enc(&aes, key, (unsigned)key_len * 8); + unsigned char counter[16], stream[16]; + size_t offset = 0; + memcpy(counter, c->iv, 16); + mbedtls_aes_crypt_ctr(&aes, c->pt_len, &offset, counter, stream, pt, ct); + mbedtls_aes_free(&aes); + check(c, "mbedtls", ct, c->pt_len, tag); + } else if (ends_with(c->name, "gcm")) { + mbedtls_gcm_context gcm; + mbedtls_gcm_init(&gcm); + mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, key, (unsigned)key_len * 8); + mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, c->pt_len, c->iv, c->iv_len, aad, c->aad_len, pt, ct, 16, tag); + mbedtls_gcm_free(&gcm); + check(c, "mbedtls", ct, c->pt_len, tag); + } else { + mbedtls_chachapoly_context chacha; + mbedtls_chachapoly_init(&chacha); + mbedtls_chachapoly_setkey(&chacha, key); + mbedtls_chachapoly_encrypt_and_tag(&chacha, c->pt_len, c->iv, aad, c->aad_len, pt, ct, tag); + mbedtls_chachapoly_free(&chacha); + check(c, "mbedtls", ct, c->pt_len, tag); + } +} + +/* RFC 8439 composition over the SIMD ChaCha20 and Poly1305 kernels. */ +static void chachapoly(const unsigned char *key, const unsigned char *nonce, const unsigned char *aad, + size_t aad_len, const unsigned char *in, unsigned char *out, size_t len, size_t chunk, + bool decrypt, unsigned char tag[16]) { + static const unsigned char zero[16] = {0}; + ScCsChaCha chacha; + ScCsPoly1305 poly; + unsigned char poly_key[64] = {0}; + scr_cs_chacha_start(&chacha, key, nonce, 0); + scr_cs_chacha_xor(&chacha, poly_key, poly_key, sizeof poly_key); + scr_cs_poly_start(&poly, poly_key); + scr_cs_poly_update(&poly, aad, aad_len); + if (aad_len % 16) scr_cs_poly_update(&poly, zero, 16 - aad_len % 16); + for (size_t at = 0; at < len; at += chunk) { + size_t n = len - at < chunk ? len - at : chunk; + if (decrypt) scr_cs_poly_update(&poly, in + at, n); + scr_cs_chacha_xor(&chacha, in + at, out + at, n); + if (!decrypt) scr_cs_poly_update(&poly, out + at, n); + } + if (len % 16) scr_cs_poly_update(&poly, zero, 16 - len % 16); + unsigned char lengths[16]; + for (int i = 0; i < 8; i++) { + lengths[i] = (unsigned char)((unsigned long long)aad_len >> (8 * i)); + lengths[8 + i] = (unsigned char)((unsigned long long)len >> (8 * i)); + } + scr_cs_poly_update(&poly, lengths, 16); + scr_cs_poly_finish(&poly, tag); +} + +static void gcm_pass(const Case *c, const unsigned char *key, size_t key_len, const unsigned char *aad, + const unsigned char *pt, unsigned char *ct, unsigned char *back, size_t chunk, size_t back_chunk, + bool narrow, unsigned char tag[16], unsigned char check_tag[16]) { + ScCsGcm gcm; + scr_cs_gcm_start(&gcm, key, key_len, c->iv, c->iv_len, false); + if (narrow) gcm.wide = false; + for (size_t at = 0; at < c->aad_len; at += 5) scr_cs_gcm_aad(&gcm, aad + at, c->aad_len - at < 5 ? c->aad_len - at : 5); + for (size_t at = 0; at < c->pt_len; at += chunk) { + size_t n = c->pt_len - at < chunk ? c->pt_len - at : chunk; + scr_cs_gcm_update(&gcm, pt + at, ct + at, n); + } + scr_cs_gcm_finish(&gcm, tag); + scr_cs_gcm_start(&gcm, key, key_len, c->iv, c->iv_len, true); + if (narrow) gcm.wide = false; + scr_cs_gcm_aad(&gcm, aad, c->aad_len); + for (size_t at = 0; at < c->pt_len; at += back_chunk) { + size_t n = c->pt_len - at < back_chunk ? c->pt_len - at : back_chunk; + scr_cs_gcm_update(&gcm, ct + at, back + at, n); + } + scr_cs_gcm_finish(&gcm, check_tag); + if ((memcmp(back, pt, c->pt_len) != 0 || memcmp(tag, check_tag, 16) != 0) && failures++ < 10) + fprintf(stderr, "gcm decrypt mismatch seed=%u%s\n", c->seed, narrow ? " (narrow)" : ""); +} + +static void run_simd(const Case *c, const unsigned char *key, const unsigned char *aad, const unsigned char *pt, + unsigned char *ct, unsigned char *back) { + static const size_t chunks[] = {(size_t)-1, 1, 7, 100, 129, 513}; + size_t key_len = key_len_of(c->name); + for (size_t k = 0; k < sizeof chunks / sizeof chunks[0]; k++) { + size_t chunk = chunks[k]; + unsigned char tag[16] = {0}, check_tag[16] = {0}; + char path[32]; + snprintf(path, sizeof path, "simd/%zu", chunk == (size_t)-1 ? (size_t)0 : chunk); + size_t back_chunk = chunk == 1 ? 333 : 1; + size_t ct_len = c->pt_len; + if (ends_with(c->name, "cbc")) { + size_t n = padded(c->pt_len); + unsigned char *in = malloc(n); + memcpy(in, pt, c->pt_len); + memset(in + c->pt_len, (int)(n - c->pt_len), n - c->pt_len); + ScCsAesKey enc, dec; + scr_cs_aes_setkey(&enc, &dec, key, key_len); + unsigned char iv[16]; + memcpy(iv, c->iv, 16); + size_t step = chunk == (size_t)-1 ? n : (chunk + 15) / 16 * 16; + for (size_t at = 0; at < n; at += step) scr_cs_aes_cbc_encrypt(&enc, iv, in + at, ct + at, (n - at < step ? n - at : step) / 16); + memcpy(iv, c->iv, 16); + for (size_t at = 0; at < n; at += 16 * back_chunk) { + size_t m = n - at < 16 * back_chunk ? n - at : 16 * back_chunk; + scr_cs_aes_cbc_decrypt(&dec, iv, ct + at, back + at, m / 16); + } + if (memcmp(back, in, n) != 0 && failures++ < 10) fprintf(stderr, "cbc decrypt mismatch seed=%u\n", c->seed); + free(in); + ct_len = n; + } else if (ends_with(c->name, "ctr")) { + ScCsAesKey enc; + scr_cs_aes_setkey(&enc, NULL, key, key_len); + unsigned char counter[16], stream[16]; + size_t offset = 0; + memcpy(counter, c->iv, 16); + for (size_t at = 0; at < c->pt_len; at += chunk) { + size_t n = c->pt_len - at < chunk ? c->pt_len - at : chunk; + scr_cs_aes_ctr(&enc, counter, stream, &offset, pt + at, ct + at, n); + } + memcpy(counter, c->iv, 16); + offset = 0; + for (size_t at = 0; at < c->pt_len; at += back_chunk) { + size_t n = c->pt_len - at < back_chunk ? c->pt_len - at : back_chunk; + scr_cs_aes_ctr(&enc, counter, stream, &offset, ct + at, back + at, n); + } + if (memcmp(back, pt, c->pt_len) != 0 && failures++ < 10) fprintf(stderr, "ctr decrypt mismatch seed=%u\n", c->seed); + } else if (ends_with(c->name, "gcm")) { + /* The narrow pass keeps VAES hosts testing the eight-block loop. */ + gcm_pass(c, key, key_len, aad, pt, ct, back, chunk, back_chunk, true, tag, check_tag); + char narrow_path[40]; + snprintf(narrow_path, sizeof narrow_path, "simd-narrow/%zu", chunk == (size_t)-1 ? (size_t)0 : chunk); + check(c, narrow_path, ct, ct_len, tag); + gcm_pass(c, key, key_len, aad, pt, ct, back, chunk, back_chunk, false, tag, check_tag); + } else { + chachapoly(key, c->iv, aad, c->aad_len, pt, ct, c->pt_len, chunk, false, tag); + chachapoly(key, c->iv, aad, c->aad_len, ct, back, c->pt_len, back_chunk, true, check_tag); + if ((memcmp(back, pt, c->pt_len) != 0 || memcmp(tag, check_tag, 16) != 0) && failures++ < 10) + fprintf(stderr, "chacha20-poly1305 decrypt mismatch seed=%u\n", c->seed); + } + check(c, path, ct, ct_len, tag); + } +} + +int main(int argc, char **argv) { + if (argc < 2) return 2; + FILE *f = fopen(argv[1], "r"); + if (!f) return 2; + bool aes = scr_cs_aes_available(), chacha = scr_cs_chacha_available(); + char line[512]; + size_t cases = 0, simd_cases = 0; + while (fgets(line, sizeof line, f)) { + Case c = {0}; + char iv[160], digest[80], tag[40]; + if (sscanf(line, "%31s %u %159s %zu %zu %79s %39s", c.name, &c.seed, iv, &c.aad_len, &c.pt_len, digest, tag) != 7) + continue; + c.iv_len = unhex(iv, c.iv, sizeof c.iv); + unhex(digest, c.digest, 32); + c.has_tag = strcmp(tag, "-") != 0; + if (c.has_tag) unhex(tag, c.tag, 16); + unsigned char key[32], aad[64]; + unsigned char *pt = malloc(c.pt_len + 1), *ct = malloc(c.pt_len + 32), *back = malloc(c.pt_len + 32); + pattern(key, key_len_of(c.name), c.seed); + pattern(aad, c.aad_len, c.seed + 1); + pattern(pt, c.pt_len, c.seed + 2); + run_portable(&c, key, aad, pt, ct); + bool simd = strncmp(c.name, "chacha", 6) == 0 ? chacha : aes; + if (simd) { + run_simd(&c, key, aad, pt, ct, back); + simd_cases++; + } + free(pt); + free(ct); + free(back); + cases++; + } + fclose(f); + fprintf(stderr, "cases %zu simd %zu failures %d\n", cases, simd_cases, failures); + return failures == 0 && cases > 0 ? 0 : 1; +} diff --git a/tests/corpus/5355-cipher-bulk.ts b/tests/corpus/5355-cipher-bulk.ts new file mode 100644 index 000000000..04a756e70 --- /dev/null +++ b/tests/corpus/5355-cipher-bulk.ts @@ -0,0 +1,47 @@ +// Bulk encryption and decryption of 1 MiB with every supported cipher, +// split into update() calls whose sizes cross the 128-byte, 512-byte and +// 1 KiB batch boundaries of the native kernels: the SHA-256 of the +// ciphertext, the authentication tag and the decrypted data match Node. +import { createCipheriv, createDecipheriv, createHash, type CipherGCM, type DecipherGCM } from "node:crypto"; + +const data = Buffer.alloc(1024 * 1024); +for (let i = 0; i < data.length; i++) data[i] = (i * 167 + (i >> 9)) & 0xff; +const sizes = [1, 127, 128, 129, 511, 512, 513, 1023, 1024, 1025, 4096, 65536, 3]; + +for (const name of [ + "aes-128-cbc", "aes-192-cbc", "aes-256-cbc", + "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", + "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", + "chacha20-poly1305", +]) { + const keyLength = name.includes("128") ? 16 : name.includes("192") ? 24 : 32; + const key = Buffer.alloc(keyLength, keyLength + 1); + const iv = Buffer.alloc(name.includes("cbc") || name.includes("ctr") ? 16 : 12, 9); + const aead = name.includes("gcm") || name.includes("chacha"); + const cipher = createCipheriv(name, key, iv); + if (aead) (cipher as CipherGCM).setAAD(Buffer.from("bulk header")); + const hash = createHash("sha256"); + const parts: Buffer[] = []; + let offset = 0; + for (let i = 0; offset < data.length; i++) { + const size = Math.min(sizes[i % sizes.length]!, data.length - offset); + const part = cipher.update(data.subarray(offset, offset + size)); + hash.update(part); + parts.push(part); + offset += size; + } + const last = cipher.final(); + hash.update(last); + parts.push(last); + const tag = aead ? (cipher as CipherGCM).getAuthTag().toString("hex") : ""; + const ciphertext = Buffer.concat(parts); + const decipher = createDecipheriv(name, key, iv); + if (aead) { + (decipher as DecipherGCM).setAAD(Buffer.from("bulk header")); + (decipher as DecipherGCM).setAuthTag(Buffer.from(tag, "hex")); + } + const plain: Buffer[] = []; + for (let at = 0; at < ciphertext.length; at += 70000) plain.push(decipher.update(ciphertext.subarray(at, at + 70000))); + plain.push(decipher.final()); + console.log(name, ciphertext.length, hash.digest("hex").slice(0, 32), tag, Buffer.concat(plain).equals(data)); +} diff --git a/tests/corpus/5356-cipher-counters.ts b/tests/corpus/5356-cipher-counters.ts new file mode 100644 index 000000000..821a69e98 --- /dev/null +++ b/tests/corpus/5356-cipher-counters.ts @@ -0,0 +1,56 @@ +// AES-CTR counter carries inside and across the native kernels' 8-block +// batches, including the 128-bit wrap from all ones to zero, and AES-GCM +// with IVs other than 12 bytes, whose initial counter comes from GHASH, +// encrypted with chunk sizes that split batches. Outputs are printed as +// SHA-256 prefixes and tags. +import { createCipheriv, createDecipheriv, createHash, type CipherGCM, type DecipherGCM } from "node:crypto"; + +const digest = (b: Buffer) => createHash("sha256").update(b).digest("hex").slice(0, 24); +const data = Buffer.alloc(3000); +for (let i = 0; i < data.length; i++) data[i] = (i * 13 + 5) & 0xff; + +const counters = [ + "fffffffffffffffffffffffffffffff8", + "ffffffffffffffffffffffffffffffff", + "0000000000000000fffffffffffffffd", + "00000000000000fffffffffffffffff0", + "0123456789abcdef0123456789abcdef", +]; +for (const counter of counters) { + for (const bits of [128, 256]) { + const key = Buffer.alloc(bits / 8, 3); + const iv = Buffer.from(counter, "hex"); + const whole = createCipheriv(`aes-${bits}-ctr`, key, iv).update(data); + const chunked = createCipheriv(`aes-${bits}-ctr`, key, iv); + const parts: Buffer[] = []; + for (let at = 0, i = 0; at < data.length; i++) { + const size = [5, 123, 128, 200, 17][i % 5]!; + parts.push(chunked.update(data.subarray(at, at + size))); + at += size; + } + const back = createDecipheriv(`aes-${bits}-ctr`, key, iv).update(whole); + console.log("ctr", bits, counter, digest(whole), Buffer.concat(parts).equals(whole), back.equals(data)); + } +} + +for (const ivLength of [1, 7, 13, 16, 32, 64, 100]) { + const iv = Buffer.alloc(ivLength); + for (let i = 0; i < ivLength; i++) iv[i] = (i * 41 + ivLength) & 0xff; + const key = Buffer.alloc(32, ivLength); + const cipher = createCipheriv("aes-256-gcm", key, iv); + cipher.setAAD(Buffer.alloc(ivLength, 1)); + const parts: Buffer[] = []; + for (let at = 0, i = 0; at < data.length; i++) { + const size = [129, 1, 255, 300][i % 4]!; + parts.push(cipher.update(data.subarray(at, at + size))); + at += size; + } + parts.push(cipher.final()); + const ciphertext = Buffer.concat(parts); + const tag = (cipher as CipherGCM).getAuthTag(); + const decipher = createDecipheriv("aes-256-gcm", key, iv) as DecipherGCM; + decipher.setAAD(Buffer.alloc(ivLength, 1)); + decipher.setAuthTag(tag); + const plain = Buffer.concat([decipher.update(ciphertext), decipher.final()]); + console.log("gcm iv", ivLength, digest(ciphertext), tag.toString("hex"), plain.equals(data)); +} diff --git a/tests/corpus/5357-cipher-chacha-bulk.ts b/tests/corpus/5357-cipher-chacha-bulk.ts new file mode 100644 index 000000000..7175a5ff7 --- /dev/null +++ b/tests/corpus/5357-cipher-chacha-bulk.ts @@ -0,0 +1,57 @@ +// chacha20-poly1305 over large inputs: 256 KiB encrypted with update() +// sizes that cross the 64-byte block, 512-byte and 1 KiB batch boundaries, +// AAD before data, empty AAD after data and the refusal of non-empty AAD +// after data, truncated tags, and decryption with a different chunking. +// Outputs are printed as SHA-256 prefixes and tags. +import { createCipheriv, createDecipheriv, createHash } from "node:crypto"; + +const digest = (b: Buffer): string => createHash("sha256").update(b).digest("hex").slice(0, 24); +const data = Buffer.alloc(256 * 1024); +for (let i = 0; i < data.length; i++) data[i] = (i * 7 + (i >> 11)) & 0xff; +const key = Buffer.alloc(32, 0x42); + +interface Run { + label: string; + sizes: number[]; + lateAad: boolean; + tagLength: number; +} +const runs: Run[] = [ + { label: "blocks", sizes: [64, 64, 128], lateAad: false, tagLength: 16 }, + { label: "batches", sizes: [511, 513, 1024, 1025, 1], lateAad: false, tagLength: 16 }, + { label: "late aad", sizes: [3000, 70000], lateAad: true, tagLength: 16 }, + { label: "truncated", sizes: [999, 1001], lateAad: false, tagLength: 7 }, + { label: "single", sizes: [256 * 1024], lateAad: true, tagLength: 12 }, +]; +for (let run = 0; run < runs.length; run++) { + const { label, sizes, lateAad, tagLength } = runs[run]!; + const nonce = Buffer.alloc(12, run + 3); + const cipher = createCipheriv("chacha20-poly1305", key, nonce, { authTagLength: tagLength }); + cipher.setAAD(Buffer.from("before")); + const parts: Buffer[] = []; + let at = 0; + for (let i = 0; at < data.length; i++) { + const size = Math.min(sizes[i % sizes.length]!, data.length - at); + parts.push(cipher.update(data.subarray(at, at + size))); + at += size; + if (lateAad && i === 0) { + cipher.setAAD(Buffer.alloc(0)); + try { + cipher.setAAD(Buffer.from("after the first chunk")); + } catch (error) { + console.log(label, "late aad", (error as Error & { code?: string }).code); + } + } + } + parts.push(cipher.final()); + const ciphertext = Buffer.concat(parts); + const tag = cipher.getAuthTag(); + console.log(label, digest(ciphertext), tag.toString("hex")); + const decipher = createDecipheriv("chacha20-poly1305", key, nonce, { authTagLength: tagLength }); + decipher.setAAD(Buffer.from("before")); + decipher.setAuthTag(tag); + const plain: Buffer[] = []; + for (let p = 0; p < ciphertext.length; p += 4097) plain.push(decipher.update(ciphertext.subarray(p, p + 4097))); + plain.push(decipher.final()); + console.log(label, "decrypted", Buffer.concat(plain).equals(data)); +} diff --git a/tests/corpus/5358-cipher-cbc-bulk.ts b/tests/corpus/5358-cipher-cbc-bulk.ts new file mode 100644 index 000000000..c5213c401 --- /dev/null +++ b/tests/corpus/5358-cipher-cbc-bulk.ts @@ -0,0 +1,42 @@ +// AES-CBC over large inputs: encryption and decryption of 200 KiB with +// update() sizes that cross the native kernels' 8-block decryption +// batches, with and without automatic padding, checking the bytes each +// update() returns (decryption holds the last block back for padding). +import { createCipheriv, createDecipheriv, createHash } from "node:crypto"; + +const digest = (b: Buffer): string => createHash("sha256").update(b).digest("hex").slice(0, 24); +const data = Buffer.alloc(200 * 1024); +for (let i = 0; i < data.length; i++) data[i] = (i * 3 + (i >> 8)) & 0xff; +const encryptSizes = [100, 128, 129, 2048, 15]; +const decryptSizes = [128, 144, 7, 4096]; + +for (const bits of [128, 192, 256]) { + for (const pad of [true, false]) { + const key = Buffer.alloc(bits / 8, bits & 0xff); + const iv = Buffer.alloc(16, 0x11); + const cipher = createCipheriv(`aes-${bits}-cbc`, key, iv).setAutoPadding(pad); + const lengths: number[] = []; + const parts: Buffer[] = []; + for (let at = 0, i = 0; at < data.length; i++) { + const size = encryptSizes[i % encryptSizes.length]!; + const part = cipher.update(data.subarray(at, at + size)); + if (i < 6) lengths.push(part.length); + parts.push(part); + at += size; + } + parts.push(cipher.final()); + const ciphertext = Buffer.concat(parts); + const decipher = createDecipheriv(`aes-${bits}-cbc`, key, iv).setAutoPadding(pad); + const backLengths: number[] = []; + const plain: Buffer[] = []; + for (let at = 0, i = 0; at < ciphertext.length; i++) { + const size = decryptSizes[i % decryptSizes.length]!; + const part = decipher.update(ciphertext.subarray(at, at + size)); + if (i < 6) backLengths.push(part.length); + plain.push(part); + at += size; + } + plain.push(decipher.final()); + console.log(bits, pad, ciphertext.length, digest(ciphertext), lengths.join(","), backLengths.join(","), Buffer.concat(plain).equals(data)); + } +} diff --git a/tests/corpus/5359-cipher-tamper.ts b/tests/corpus/5359-cipher-tamper.ts new file mode 100644 index 000000000..f4c7c717d --- /dev/null +++ b/tests/corpus/5359-cipher-tamper.ts @@ -0,0 +1,37 @@ +// Authentication failures on large AES-GCM and chacha20-poly1305 inputs: +// a flipped bit in the first byte, inside the bulk region, in the final +// partial block, or in the tag makes final() throw Node's error, while the +// decrypted bytes returned by update() still have the input's length. +import { createCipheriv, createDecipheriv, type CipherGCM, type DecipherGCM } from "node:crypto"; + +const data = Buffer.alloc(100_003); +for (let i = 0; i < data.length; i++) data[i] = (i * 29 + 1) & 0xff; + +for (const name of ["aes-128-gcm", "aes-256-gcm", "chacha20-poly1305"]) { + const key = Buffer.alloc(name.includes("128") ? 16 : 32, 0x5a); + const iv = Buffer.alloc(12, 0x0c); + const cipher = createCipheriv(name, key, iv) as CipherGCM; + const ciphertext = Buffer.concat([cipher.update(data), cipher.final()]); + const tag = cipher.getAuthTag(); + for (const [label, position] of [ + ["none", -1], + ["first byte", 0], + ["bulk", 50_000], + ["final block", data.length - 2], + ["tag", -2], + ] as const) { + const changed = Buffer.from(ciphertext); + const changedTag = Buffer.from(tag); + if (position >= 0) changed[position] = changed[position]! ^ 0x10; + if (position === -2) changedTag[5] = changedTag[5]! ^ 0x01; + const decipher = createDecipheriv(name, key, iv) as DecipherGCM; + decipher.setAuthTag(changedTag); + const plain = decipher.update(changed); + try { + decipher.final(); + console.log(name, label, plain.length, "authenticated", plain.equals(data)); + } catch (error) { + console.log(name, label, plain.length, (error as Error).message); + } + } +}