From 3cdaab7894cdba91c581c0d58991e024c06be90a Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:29:04 +0200 Subject: [PATCH] Check session key size on v3 SKESK and PKESK packet decryption For v3 SKESK and PKESK packets, the session key algorithm is part of the payload, so we can check the session key size on packet decryption. This is helpful to catch errors early, when using e.g. `decryptSessionKeys`. In v6 packets, the session key size check can only be done on SEIPDv2 decryption. --- src/packet/public_key_encrypted_session_key.js | 13 ++++++++----- src/packet/sym_encrypted_session_key.js | 6 +++++- test/crypto/eax.js | 2 +- test/crypto/gcm.js | 4 ++-- test/general/openpgp.js | 4 ++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/packet/public_key_encrypted_session_key.js b/src/packet/public_key_encrypted_session_key.js index f0bdc402..eaa5dacd 100644 --- a/src/packet/public_key_encrypted_session_key.js +++ b/src/packet/public_key_encrypted_session_key.js @@ -208,11 +208,14 @@ class PublicKeyEncryptedSessionKeyPacket { const { sessionKey, sessionKeyAlgorithm } = decodeSessionKey(this.version, this.publicKeyAlgorithm, decryptedData, randomSessionKey); - // v3 Montgomery curves have cleartext cipher algo - if (this.version === 3 && ( - this.publicKeyAlgorithm !== enums.publicKey.x25519 && this.publicKeyAlgorithm !== enums.publicKey.x448) - ) { - this.sessionKeyAlgorithm = sessionKeyAlgorithm; + if (this.version === 3) { + // v3 Montgomery curves have cleartext cipher algo + const hasEncryptedAlgo = this.publicKeyAlgorithm !== enums.publicKey.x25519 && this.publicKeyAlgorithm !== enums.publicKey.x448; + this.sessionKeyAlgorithm = hasEncryptedAlgo ? sessionKeyAlgorithm : this.sessionKeyAlgorithm; + + if (sessionKey.length !== crypto.getCipherParams(this.sessionKeyAlgorithm).keySize) { + throw new Error('Unexpected session key size'); + } } this.sessionKey = sessionKey; } diff --git a/src/packet/sym_encrypted_session_key.js b/src/packet/sym_encrypted_session_key.js index 464be72e..4ea592f9 100644 --- a/src/packet/sym_encrypted_session_key.js +++ b/src/packet/sym_encrypted_session_key.js @@ -56,7 +56,7 @@ class SymEncryptedSessionKeyPacket { * Algorithm to encrypt the message with * @type {enums.symmetric} */ - this.sessionKeyAlgorithm = enums.symmetric.aes256; + this.sessionKeyAlgorithm = null; /** * AEAD mode to encrypt the session key with (if AEAD protection is enabled) * @type {enums.aead} @@ -177,7 +177,11 @@ class SymEncryptedSessionKeyPacket { this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); this.sessionKey = decrypted.subarray(1, decrypted.length); + if (this.sessionKey.length !== crypto.getCipherParams(this.sessionKeyAlgorithm).keySize) { + throw new Error('Unexpected session key size'); + } } else { + // session key size is checked as part of SEIPDv2 decryption, where we know the expected symmetric algo this.sessionKey = key; } } diff --git a/test/crypto/eax.js b/test/crypto/eax.js index d5191b37..a18688a2 100644 --- a/test/crypto/eax.js +++ b/test/crypto/eax.js @@ -159,7 +159,7 @@ export default () => describe('Symmetric AES-EAX', function() { testAESEAX(); }); - describe('Symmetric AES-EAX (asm.js fallback)', function() { + describe('Symmetric AES-EAX (non-native fallback)', function() { beforeEach(function () { sinonSandbox = sinon.createSandbox(); disableNative(); diff --git a/test/crypto/gcm.js b/test/crypto/gcm.js index f564c400..cf4e6600 100644 --- a/test/crypto/gcm.js +++ b/test/crypto/gcm.js @@ -77,11 +77,11 @@ export default () => describe('Symmetric AES-GCM (experimental)', function() { testAESGCM('12345678901234567890123456789012345678901234567890', true, true); }); - describe('Symmetric AES-GCM (asm.js fallback)', function() { + describe('Symmetric AES-GCM (non-native)', function() { testAESGCM('12345678901234567890123456789012345678901234567890', false, false); }); - describe('Symmetric AES-GCM (native encrypt, asm.js decrypt)', function() { + describe('Symmetric AES-GCM (native encrypt, non-native decrypt)', function() { testAESGCM('12345678901234567890123456789012345678901234567890', true, false); }); }); diff --git a/test/general/openpgp.js b/test/general/openpgp.js index fe9ae8c2..c141206e 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -2532,7 +2532,7 @@ XfA3pqV4mTzF } }); - tryTests('CFB mode (asm.js)', tests, { + tryTests('CFB mode', tests, { if: true, beforeEach: function() { openpgp.config.aeadProtect = false; @@ -2582,7 +2582,7 @@ XfA3pqV4mTzF function tests() { describe('encryptSessionKey, decryptSessionKeys', function() { - const sk = new Uint8Array([0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01]); + const sk = new Uint8Array([0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01]); let decryptedPrivateKey; // to avoid decrypting key before each test beforeEach(async function() {