Skip to content

Commit f642b29

Browse files
authored
fix: ENCODED_SIGNER_KEY in encryption context (#196)
A CryptographicMaterialsManager can change entries to the encryptionContext but changing these values has consequences. The DefaultCryptographicMaterialsManager uses the value in the encryption context to store public signing key. If the caller is using this value in their encryption context the Default CMM is probably not the CMM they want to use.
2 parents cd002d5 + 23b9e31 commit f642b29

File tree

4 files changed

+72
-4
lines changed

4 files changed

+72
-4
lines changed

modules/material-management-browser/src/browser_cryptographic_materials_manager.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,23 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM
4949
async getEncryptionMaterials ({ suite, encryptionContext }: WebCryptoEncryptionRequest): Promise<WebCryptoEncryptionMaterial> {
5050
suite = suite || new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384)
5151

52+
/* Precondition: WebCryptoDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.
53+
* A CryptographicMaterialsManager can change entries to the encryptionContext
54+
* but changing these values has consequences.
55+
* The DefaultCryptographicMaterialsManager uses the value in the encryption context to store public signing key.
56+
* If the caller is using this value in their encryption context the Default CMM is probably not the CMM they want to use.
57+
*/
58+
needs(!encryptionContext.hasOwnProperty(ENCODED_SIGNER_KEY), `Reserved encryptionContext value ${ENCODED_SIGNER_KEY} not allowed.`)
59+
5260
const material = await this
5361
.keyring
5462
.onEncrypt(await this._initializeEncryptionMaterial(suite, encryptionContext))
5563

56-
/* Postcondition: The WebCryptoEncryptionMaterial must contain a valid dataKey. */
64+
/* Postcondition: The WebCryptoEncryptionMaterial must contain a valid dataKey.
65+
* This verifies that the data key matches the algorithm suite specification
66+
* and that the unencrypted data key is non-NULL.
67+
* See: cryptographic_materials.ts, `getUnencryptedDataKey`
68+
*/
5769
needs(material.hasValidKey(), 'Unencrypted data key is invalid.')
5870

5971
/* Postcondition: The WebCryptoEncryptionMaterial must contain at least 1 EncryptedDataKey. */
@@ -67,7 +79,12 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM
6779
.keyring
6880
.onDecrypt(await this._initializeDecryptionMaterial(suite, encryptionContext), encryptedDataKeys.slice())
6981

70-
/* Postcondition: The WebCryptoDecryptionMaterial must contain a valid dataKey. */
82+
/* Postcondition: The WebCryptoDecryptionMaterial must contain a valid dataKey.
83+
* See: cryptographic_materials.ts, `getUnencryptedDataKey` also verifies
84+
* that the unencrypted data key has not been manipulated,
85+
* that the data key matches the algorithm suite specification
86+
* and that the unencrypted data key is non-NULL.
87+
*/
7188
needs(material.hasValidKey(), 'Unencrypted data key is invalid.')
7289

7390
return material

modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,25 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => {
240240
expect(material.encryptionContext).to.have.haveOwnProperty('some').and.to.equal('context')
241241
})
242242

243+
it('Precondition: WebCryptoDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.', async () => {
244+
class TestKeyring extends KeyringWebCrypto {
245+
async _onEncrypt (): Promise<WebCryptoEncryptionMaterial> {
246+
throw new Error('I should never see this error')
247+
}
248+
async _onDecrypt (): Promise<WebCryptoDecryptionMaterial> {
249+
throw new Error('I should never see this error')
250+
}
251+
}
252+
253+
const keyring = new TestKeyring()
254+
const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring)
255+
const encryptionContext = {
256+
[ENCODED_SIGNER_KEY]: 'context'
257+
}
258+
259+
expect(cmm.getEncryptionMaterials({ encryptionContext })).to.rejectedWith(Error, 'Reserved encryptionContext value')
260+
})
261+
243262
it('Postcondition: The WebCryptoEncryptionMaterial must contain a valid dataKey.', async () => {
244263
class TestKeyring extends KeyringWebCrypto {
245264
async _onEncrypt (material: WebCryptoEncryptionMaterial): Promise<WebCryptoEncryptionMaterial> {

modules/material-management-node/src/node_cryptographic_materials_manager.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,23 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa
4949
async getEncryptionMaterials ({ suite, encryptionContext }: NodeEncryptionRequest): Promise<NodeEncryptionMaterial> {
5050
suite = suite || new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384)
5151

52+
/* Precondition: NodeDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.
53+
* A CryptographicMaterialsManager can change entries to the encryptionContext
54+
* but changing these values has consequences.
55+
* The DefaultCryptographicMaterialsManager uses the value in the encryption context to store public signing key.
56+
* If the caller is using this value in their encryption context the Default CMM is probably not the CMM they want to use.
57+
*/
58+
needs(!encryptionContext.hasOwnProperty(ENCODED_SIGNER_KEY), `Reserved encryptionContext value ${ENCODED_SIGNER_KEY} not allowed.`)
59+
5260
const material = await this
5361
.keyring
5462
.onEncrypt(this._initializeEncryptionMaterial(suite, encryptionContext))
5563

56-
/* Postcondition: The NodeEncryptionMaterial must contain a valid dataKey. */
64+
/* Postcondition: The NodeEncryptionMaterial must contain a valid dataKey.
65+
* This verifies that the data key matches the algorithm suite specification
66+
* and that the unencrypted data key is non-NULL.
67+
* See: cryptographic_materials.ts, `getUnencryptedDataKey`
68+
*/
5769
needs(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.')
5870

5971
/* Postcondition: The NodeEncryptionMaterial must contain at least 1 EncryptedDataKey. */
@@ -69,7 +81,9 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa
6981

7082
/* Postcondition: The NodeDecryptionMaterial must contain a valid dataKey.
7183
* See: cryptographic_materials.ts, `getUnencryptedDataKey` also verifies
72-
* that the unencrypted data key has not been manipulated.
84+
* that the unencrypted data key has not been manipulated,
85+
* that the data key matches the algorithm suite specification
86+
* and that the unencrypted data key is non-NULL.
7387
*/
7488
needs(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.')
7589

modules/material-management-node/test/node_cryptographic_materials_manager.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,24 @@ describe('NodeDefaultCryptographicMaterialsManager', () => {
183183
)).to.throw()
184184
})
185185

186+
it('Precondition: NodeDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.', async () => {
187+
class TestKeyring extends KeyringNode {
188+
async _onEncrypt (): Promise<NodeEncryptionMaterial> {
189+
throw new Error('this should never happen')
190+
}
191+
async _onDecrypt (): Promise<NodeDecryptionMaterial> {
192+
throw new Error('this should never happen')
193+
}
194+
}
195+
const keyring = new TestKeyring()
196+
const cmm = new NodeDefaultCryptographicMaterialsManager(keyring)
197+
const encryptionContext = {
198+
[ENCODED_SIGNER_KEY]: 'something'
199+
}
200+
201+
await expect(cmm.getEncryptionMaterials({ encryptionContext })).to.rejectedWith(Error, 'Reserved encryptionContext value')
202+
})
203+
186204
it('Postcondition: The NodeEncryptionMaterial must contain a valid dataKey.', async () => {
187205
const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256)
188206

0 commit comments

Comments
 (0)