From b1eb25b073e300d032c12d200f9979e88c1e44fd Mon Sep 17 00:00:00 2001 From: seebees Date: Tue, 2 Jul 2019 12:27:18 -0700 Subject: [PATCH] fix: 192 bit algorithm suite support in browsers Resolves: # 72 Browsers do not support 192 bit keys. The proper place for this is in the WebCryptoAlgorithmSuite class. Move the logic from the CMM to WebCryptoAlgorithmSuite Add tests to cover the precondition. --- ...browser_cryptographic_materials_manager.ts | 9 ------ .../src/web_crypto_algorithms.ts | 31 +++++++++++++++++++ .../test/web_crypto_algorithms.test.ts | 6 ++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts index 82529f7c3..9e442e3a8 100644 --- a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts +++ b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts @@ -49,11 +49,6 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM async getEncryptionMaterials ({ suite, encryptionContext }: WebCryptoEncryptionRequest): Promise { suite = suite || new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) const material = new WebCryptoEncryptionMaterial(suite) - /* Precondition: Browsers do not support 192 bit keys so I do not support encrypt. - * This is primarily an error in decrypt but this make it clear. - * The error can manifest deep in the decrypt loop making it hard to debug. - */ - needs(suite.keyLength !== 192, '192-bit AES keys are not supported') const context = await this._generateSigningKeyAndUpdateEncryptionContext(material, encryptionContext) @@ -69,10 +64,6 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM } async decryptMaterials ({ suite, encryptedDataKeys, encryptionContext }: WebCryptoDecryptionRequest): Promise { - /* Precondition: Browsers do not support 192 bit keys, do not attempt decrypt. - * The error can manifest deep in the decrypt loop making it hard to debug. - */ - needs(suite.keyLength !== 192, '192-bit AES keys are not supported') const material = await this._loadVerificationKeyFromEncryptionContext(new WebCryptoDecryptionMaterial(suite), encryptionContext) await this.keyring.onDecrypt(material, encryptedDataKeys.slice(), encryptionContext) diff --git a/modules/material-management/src/web_crypto_algorithms.ts b/modules/material-management/src/web_crypto_algorithms.ts index 044c2f9a9..b24201ad3 100644 --- a/modules/material-management/src/web_crypto_algorithms.ts +++ b/modules/material-management/src/web_crypto_algorithms.ts @@ -28,6 +28,7 @@ import { IWebCryptoAlgorithmSuite, WebCryptoEncryption, WebCryptoHash, // eslint-disable-line no-unused-vars WebCryptoECDHCurve, AlgorithmSuiteTypeWebCrypto // eslint-disable-line no-unused-vars } from './algorithm_suites' +import { needs } from './needs' /* References to https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/algorithms-reference.html * These are the composed parameters for each algorithm suite specification for @@ -41,6 +42,7 @@ const webCryptoAlgAes128GcmIv12Tag16: IWebCryptoAlgorithmSuite = { tagLength: 128, cacheSafe: false } +/* Web browsers do not support 192 bit key lengths at this time. */ const webCryptoAlgAes192GcmIv12Tag16: IWebCryptoAlgorithmSuite = { id: AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16, encryption: 'AES-GCM', @@ -67,6 +69,7 @@ const webCryptoAlgAes128GcmIv12Tag16HkdfSha256: IWebCryptoAlgorithmSuite = { kdfHash: 'SHA-256', cacheSafe: true } +/* Web browsers do not support 192 bit key lengths at this time. */ const webCryptoAlgAes192GcmIv12Tag16HkdfSha256: IWebCryptoAlgorithmSuite = { id: AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA256, encryption: 'AES-GCM', @@ -99,6 +102,7 @@ const webCryptoAlgAes128GcmIv12Tag16HkdfSha256EcdsaP256: IWebCryptoAlgorithmSuit signatureCurve: 'P-256', signatureHash: 'SHA-256' } +/* Web browsers do not support 192 bit key lengths at this time. */ const webCryptoAlgAes192GcmIv12Tag16HkdfSha384EcdsaP384: IWebCryptoAlgorithmSuite = { id: AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, encryption: 'AES-GCM', @@ -137,6 +141,28 @@ const webCryptoAlgorithms: WebCryptoAlgorithms = Object.freeze({ [AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384]: Object.freeze(webCryptoAlgAes256GcmIv12Tag16HkdfSha384EcdsaP384) }) +/* Web browsers do not support 192 bit key lengths at this time. + * To maintain type compatibility and TypeScript happiness between Algorithm Suites + * I need to have the same list of AlgorithmSuiteIdentifier. + * This list is maintained here to make sure that the error message is helpful. + */ +type WebCryptoAlgorithmSuiteIdentifier = Exclude, + AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA256>, + AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384> +type SupportedWebCryptoAlgorithms = Readonly<{[id in WebCryptoAlgorithmSuiteIdentifier]: IWebCryptoAlgorithmSuite}> +const supportedWebCryptoAlgorithms: SupportedWebCryptoAlgorithms = Object.freeze({ + [AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16]: Object.freeze(webCryptoAlgAes128GcmIv12Tag16), + // [AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16]: Object.freeze(webCryptoAlgAes192GcmIv12Tag16), + [AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16]: Object.freeze(webCryptoAlgAes256GcmIv12Tag16), + [AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256]: Object.freeze(webCryptoAlgAes128GcmIv12Tag16HkdfSha256), + // [AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA256]: Object.freeze(webCryptoAlgAes192GcmIv12Tag16HkdfSha256), + [AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256]: Object.freeze(webCryptoAlgAes256GcmIv12Tag16HkdfSha256), + [AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256]: Object.freeze(webCryptoAlgAes128GcmIv12Tag16HkdfSha256EcdsaP256), + // [AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384]: Object.freeze(webCryptoAlgAes192GcmIv12Tag16HkdfSha384EcdsaP384), + [AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384]: Object.freeze(webCryptoAlgAes256GcmIv12Tag16HkdfSha384EcdsaP384) +}) + export class WebCryptoAlgorithmSuite extends AlgorithmSuite implements IWebCryptoAlgorithmSuite { encryption!: WebCryptoEncryption kdfHash?: WebCryptoHash @@ -145,6 +171,11 @@ export class WebCryptoAlgorithmSuite extends AlgorithmSuite implements IWebCrypt type: AlgorithmSuiteTypeWebCrypto = 'webCrypto' constructor (id: AlgorithmSuiteIdentifier) { super(webCryptoAlgorithms[id]) + /* Precondition: Browsers do not support 192 bit keys so the AlgorithmSuiteIdentifier is removed. + * This is primarily an error in decrypt but this make it clear. + * The error can manifest deep in the decrypt loop making it hard to debug. + */ + needs(supportedWebCryptoAlgorithms.hasOwnProperty(id), '192-bit AES keys are not supported') Object.setPrototypeOf(this, WebCryptoAlgorithmSuite.prototype) Object.freeze(this) } diff --git a/modules/material-management/test/web_crypto_algorithms.test.ts b/modules/material-management/test/web_crypto_algorithms.test.ts index b5ad185f5..0d8a246c1 100644 --- a/modules/material-management/test/web_crypto_algorithms.test.ts +++ b/modules/material-management/test/web_crypto_algorithms.test.ts @@ -40,4 +40,10 @@ describe('WebCryptoAlgorithmSuite', () => { expect(Object.isFrozen(WebCryptoAlgorithmSuite)).to.equal(true) expect(Object.isFrozen(WebCryptoAlgorithmSuite.prototype)).to.equal(true) }) + + it('Precondition: Browsers do not support 192 bit keys so the AlgorithmSuiteIdentifier is removed.', () => { + expect(() => new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16)).to.throw() + expect(() => new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA256)).to.throw() + expect(() => new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384)).to.throw() + }) })