Skip to content

fix: ENCODED_SIGNER_KEY in encryption context #196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,23 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM
async getEncryptionMaterials ({ suite, encryptionContext }: WebCryptoEncryptionRequest): Promise<WebCryptoEncryptionMaterial> {
suite = suite || new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384)

/* Precondition: WebCryptoDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.
* 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.
*/
needs(!encryptionContext.hasOwnProperty(ENCODED_SIGNER_KEY), `Reserved encryptionContext value ${ENCODED_SIGNER_KEY} not allowed.`)

const material = await this
.keyring
.onEncrypt(await this._initializeEncryptionMaterial(suite, encryptionContext))

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

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

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

return material
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,25 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => {
expect(material.encryptionContext).to.have.haveOwnProperty('some').and.to.equal('context')
})

it('Precondition: WebCryptoDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.', async () => {
class TestKeyring extends KeyringWebCrypto {
async _onEncrypt (): Promise<WebCryptoEncryptionMaterial> {
throw new Error('I should never see this error')
}
async _onDecrypt (): Promise<WebCryptoDecryptionMaterial> {
throw new Error('I should never see this error')
}
}

const keyring = new TestKeyring()
const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring)
const encryptionContext = {
[ENCODED_SIGNER_KEY]: 'context'
}

expect(cmm.getEncryptionMaterials({ encryptionContext })).to.rejectedWith(Error, 'Reserved encryptionContext value')
})

it('Postcondition: The WebCryptoEncryptionMaterial must contain a valid dataKey.', async () => {
class TestKeyring extends KeyringWebCrypto {
async _onEncrypt (material: WebCryptoEncryptionMaterial): Promise<WebCryptoEncryptionMaterial> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,23 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa
async getEncryptionMaterials ({ suite, encryptionContext }: NodeEncryptionRequest): Promise<NodeEncryptionMaterial> {
suite = suite || new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384)

/* Precondition: NodeDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.
* 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.
*/
needs(!encryptionContext.hasOwnProperty(ENCODED_SIGNER_KEY), `Reserved encryptionContext value ${ENCODED_SIGNER_KEY} not allowed.`)

const material = await this
.keyring
.onEncrypt(this._initializeEncryptionMaterial(suite, encryptionContext))

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

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,24 @@ describe('NodeDefaultCryptographicMaterialsManager', () => {
)).to.throw()
})

it('Precondition: NodeDefaultCryptographicMaterialsManager must reserve the ENCODED_SIGNER_KEY constant from @aws-crypto/serialize.', async () => {
class TestKeyring extends KeyringNode {
async _onEncrypt (): Promise<NodeEncryptionMaterial> {
throw new Error('this should never happen')
}
async _onDecrypt (): Promise<NodeDecryptionMaterial> {
throw new Error('this should never happen')
}
}
const keyring = new TestKeyring()
const cmm = new NodeDefaultCryptographicMaterialsManager(keyring)
const encryptionContext = {
[ENCODED_SIGNER_KEY]: 'something'
}

await expect(cmm.getEncryptionMaterials({ encryptionContext })).to.rejectedWith(Error, 'Reserved encryptionContext value')
})

it('Postcondition: The NodeEncryptionMaterial must contain a valid dataKey.', async () => {
const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256)

Expand Down