Skip to content

Commit 43813f4

Browse files
authored
Release 2.2.0 (aws#613)
See GHSA-h45p-w933-jxh3
1 parent 06211c8 commit 43813f4

File tree

99 files changed

+18236
-24637
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+18236
-24637
lines changed

.gitmodules

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[submodule "aws-encryption-sdk-test-vectors"]
22
path = aws-encryption-sdk-test-vectors
3-
url = https://github.com/awslabs/aws-encryption-sdk-test-vectors.git
3+
url = https://github.com/awslabs/private-aws-encryption-sdk-test-vectors-staging.git
4+
branch = known-invalid-test-vectors

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ A multi keyring can be used to compose keyrings together.
6363
### Wrapping Keys
6464

6565
Wrapping keys are used to protect data keys.
66-
An example of a wrapping key is a `KMS customer master key (CMK)`_.
66+
An example of a wrapping key is a `KMS customer master key (CMK)`.
6767

6868
### Data Keys
6969

modules/client-browser/src/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@ export * from '@aws-crypto/raw-aes-keyring-browser'
1010
export * from '@aws-crypto/raw-rsa-keyring-browser'
1111
export * from '@aws-crypto/web-crypto-backend'
1212

13-
import { CommitmentPolicy } from '@aws-crypto/material-management-browser'
13+
import {
14+
CommitmentPolicy,
15+
ClientOptions,
16+
} from '@aws-crypto/material-management-browser'
1417

1518
import { buildEncrypt } from '@aws-crypto/encrypt-browser'
1619
import { buildDecrypt } from '@aws-crypto/decrypt-browser'
1720

1821
export function buildClient(
19-
commitmentPolicy: CommitmentPolicy = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
22+
options?: CommitmentPolicy | ClientOptions
2023
): ReturnType<typeof buildEncrypt> & ReturnType<typeof buildDecrypt> {
2124
return {
22-
...buildEncrypt(commitmentPolicy),
23-
...buildDecrypt(commitmentPolicy),
25+
...buildEncrypt(options),
26+
...buildDecrypt(options),
2427
}
2528
}

modules/client-node/src/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@ export * from '@aws-crypto/kms-keyring-node'
99
export * from '@aws-crypto/raw-aes-keyring-node'
1010
export * from '@aws-crypto/raw-rsa-keyring-node'
1111

12-
import { CommitmentPolicy } from '@aws-crypto/material-management-node'
12+
import {
13+
CommitmentPolicy,
14+
ClientOptions,
15+
} from '@aws-crypto/material-management-node'
1316

1417
import { buildEncrypt } from '@aws-crypto/encrypt-node'
1518
import { buildDecrypt } from '@aws-crypto/decrypt-node'
1619

1720
export function buildClient(
18-
commitmentPolicy: CommitmentPolicy = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
21+
options?: CommitmentPolicy | ClientOptions
1922
): ReturnType<typeof buildEncrypt> & ReturnType<typeof buildDecrypt> {
2023
return {
21-
...buildEncrypt(commitmentPolicy),
22-
...buildDecrypt(commitmentPolicy),
24+
...buildEncrypt(options),
25+
...buildDecrypt(options),
2326
}
2427
}

modules/decrypt-browser/src/decrypt.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
WebCryptoMaterialsManager,
1212
CommitmentPolicy,
1313
CommitmentPolicySuites,
14+
ClientOptions,
1415
} from '@aws-crypto/material-management-browser'
1516
import {
1617
deserializeSignature,
@@ -34,20 +35,29 @@ export interface DecryptResult {
3435
}
3536

3637
export async function _decrypt(
37-
commitmentPolicy: CommitmentPolicy,
38+
{ commitmentPolicy, maxEncryptedDataKeys }: ClientOptions,
3839
cmm: KeyringWebCrypto | WebCryptoMaterialsManager,
3940
ciphertext: Uint8Array
4041
): Promise<DecryptResult> {
4142
/* Precondition: _decrypt needs a valid commitmentPolicy. */
4243
needs(CommitmentPolicy[commitmentPolicy], 'Invalid commitment policy.')
4344

45+
// buildDecrypt defaults this to false for backwards compatibility, so this is satisfied
46+
/* Precondition: _decrypt needs a valid maxEncryptedDataKeys. */
47+
needs(
48+
maxEncryptedDataKeys === false || maxEncryptedDataKeys >= 1,
49+
'Invalid maxEncryptedDataKeys value.'
50+
)
51+
4452
/* If the cmm is a Keyring, wrap it with WebCryptoDefaultCryptographicMaterialsManager. */
4553
cmm =
4654
cmm instanceof KeyringWebCrypto
4755
? new WebCryptoDefaultCryptographicMaterialsManager(cmm)
4856
: cmm
4957

50-
const headerInfo = deserialize.deserializeMessageHeader(ciphertext)
58+
const headerInfo = deserialize.deserializeMessageHeader(ciphertext, {
59+
maxEncryptedDataKeys,
60+
})
5161
if (headerInfo === false) throw new Error('Unable to parse Header')
5262
const { messageHeader, algorithmSuite } = headerInfo
5363
const { rawHeader, headerAuth } = headerInfo

modules/decrypt-browser/src/decrypt_client.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { _decrypt } from './decrypt'
55
import {
66
CommitmentPolicy,
7+
ClientOptions,
78
needs,
89
} from '@aws-crypto/material-management-browser'
910

@@ -15,13 +16,28 @@ type CurryFirst<fn extends (...a: any[]) => any> = fn extends (
1516
: []
1617

1718
export function buildDecrypt(
18-
commitmentPolicy: CommitmentPolicy = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
19+
options: CommitmentPolicy | Partial<ClientOptions> = {}
1920
): {
2021
decrypt: (...args: CurryFirst<typeof _decrypt>) => ReturnType<typeof _decrypt>
2122
} {
23+
const {
24+
commitmentPolicy = CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
25+
maxEncryptedDataKeys = false,
26+
} = typeof options === 'string' ? { commitmentPolicy: options } : options
27+
2228
/* Precondition: browser buildDecrypt needs a valid commitmentPolicy. */
2329
needs(CommitmentPolicy[commitmentPolicy], 'Invalid commitment policy.')
30+
/* Precondition: browser buildDecrypt needs a valid maxEncryptedDataKeys. */
31+
needs(
32+
maxEncryptedDataKeys === false || maxEncryptedDataKeys >= 1,
33+
'Invalid maxEncryptedDataKeys value.'
34+
)
35+
36+
const clientOptions: ClientOptions = {
37+
commitmentPolicy,
38+
maxEncryptedDataKeys,
39+
}
2440
return {
25-
decrypt: _decrypt.bind({}, commitmentPolicy),
41+
decrypt: _decrypt.bind({}, clientOptions),
2642
}
2743
}

modules/decrypt-browser/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
export { buildDecrypt } from './decrypt_client'
5+
export { DecryptResult } from './decrypt'
56
export { MessageHeader } from '@aws-crypto/serialize'

modules/decrypt-browser/test/decrypt.test.ts

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/* eslint-env mocha */
55

66
import * as chai from 'chai'
7+
// @ts-ignore
78
import chaiAsPromised from 'chai-as-promised'
89
import { buildDecrypt } from '../src/index'
910
import { _decrypt } from '../src/decrypt'
@@ -44,14 +45,34 @@ describe('decrypt', () => {
4445

4546
it('Precondition: _decrypt needs a valid commitmentPolicy.', async () => {
4647
await expect(
47-
_decrypt('fake_policy' as any, {} as any, {} as any)
48+
_decrypt(
49+
{ commitmentPolicy: 'fake_policy' as any, maxEncryptedDataKeys: false },
50+
{} as any,
51+
{} as any
52+
)
4853
).to.rejectedWith(Error, 'Invalid commitment policy.')
4954
})
5055

56+
it('Precondition: _decrypt needs a valid maxEncryptedDataKeys.', async () => {
57+
await expect(
58+
_decrypt(
59+
{
60+
commitmentPolicy: CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
61+
maxEncryptedDataKeys: 0,
62+
},
63+
{} as any,
64+
{} as any
65+
)
66+
).to.rejectedWith(Error, 'Invalid maxEncryptedDataKeys value.')
67+
})
68+
5169
it('Precondition: The parsed header algorithmSuite in _decrypt must be supported by the commitmentPolicy.', async () => {
5270
await expect(
5371
_decrypt(
54-
CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
72+
{
73+
commitmentPolicy: CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
74+
maxEncryptedDataKeys: false,
75+
},
5576
fixtures.decryptKeyring(),
5677
fixtures.base64CiphertextAlgAes256GcmIv12Tag16HkdfSha384EcdsaP384With4Frames()
5778
)
@@ -74,7 +95,10 @@ describe('decrypt', () => {
7495
} as any
7596
await expect(
7697
_decrypt(
77-
CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
98+
{
99+
commitmentPolicy: CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
100+
maxEncryptedDataKeys: false,
101+
},
78102
cmm,
79103
fromBase64(fixtures.compatibilityVectors().tests[0].ciphertext)
80104
)
@@ -142,6 +166,40 @@ describe('decrypt', () => {
142166
await expect(decrypt(keyring, data.slice(0, i))).to.rejectedWith(Error)
143167
}
144168
})
169+
170+
it('can decrypt data with less than maxEncryptedDataKeys', async () => {
171+
const { decrypt } = buildDecrypt({
172+
commitmentPolicy: CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT,
173+
maxEncryptedDataKeys: 3,
174+
})
175+
const { plaintext } = await decrypt(
176+
fixtures.decryptKeyring(),
177+
fixtures.twoEdksMessage()
178+
)
179+
expect(plaintext).to.deep.equal(Buffer.from('asdf'))
180+
})
181+
182+
it('can decrypt data with exactly maxEncryptedDataKeys', async () => {
183+
const { decrypt } = buildDecrypt({
184+
commitmentPolicy: CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT,
185+
maxEncryptedDataKeys: 3,
186+
})
187+
const { plaintext } = await decrypt(
188+
fixtures.decryptKeyring(),
189+
fixtures.threeEdksMessage()
190+
)
191+
expect(plaintext).to.deep.equal(Buffer.from('asdf'))
192+
})
193+
194+
it('will not decrypt data with more than maxEncryptedDataKeys', async () => {
195+
const { decrypt } = buildDecrypt({
196+
commitmentPolicy: CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT,
197+
maxEncryptedDataKeys: 3,
198+
})
199+
await expect(
200+
decrypt(fixtures.decryptKeyring(), fixtures.fourEdksMessage())
201+
).to.rejectedWith(Error, 'maxEncryptedDataKeys exceeded.')
202+
})
145203
})
146204

147205
// prettier-ignore

modules/decrypt-browser/test/decrypt_client.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/* eslint-env mocha */
55

66
import * as chai from 'chai'
7+
// @ts-ignore
78
import chaiAsPromised from 'chai-as-promised'
89
import { CommitmentPolicy } from '@aws-crypto/material-management-node'
910
import { buildDecrypt } from '../src/index'
@@ -13,11 +14,34 @@ const { expect } = chai
1314

1415
describe('buildDecrypt', () => {
1516
it('can build a client', () => {
17+
const test = buildDecrypt()
18+
expect(test).to.have.property('decrypt').and.to.be.a('function')
19+
})
20+
21+
it('can build a client with a commitment policy', () => {
1622
const test = buildDecrypt(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)
1723
expect(test).to.have.property('decrypt').and.to.be.a('function')
1824
})
1925

26+
it('can build a client with max encrypted data keys', () => {
27+
for (const numKeys of [1, 10, Math.pow(2, 16) - 1, Math.pow(2, 16)]) {
28+
const test = buildDecrypt({ maxEncryptedDataKeys: numKeys })
29+
expect(test).to.have.property('decrypt').and.to.be.a('function')
30+
}
31+
})
32+
2033
it('Precondition: browser buildDecrypt needs a valid commitmentPolicy.', () => {
21-
expect(() => buildDecrypt({} as any)).to.throw('Invalid commitment policy.')
34+
expect(() => buildDecrypt('BAD_POLICY' as any)).to.throw(
35+
'Invalid commitment policy.'
36+
)
37+
})
38+
39+
it('Precondition: browser buildDecrypt needs a valid maxEncryptedDataKeys.', () => {
40+
expect(() => buildDecrypt({ maxEncryptedDataKeys: 0 })).to.throw(
41+
'Invalid maxEncryptedDataKeys value.'
42+
)
43+
expect(() => buildDecrypt({ maxEncryptedDataKeys: -1 })).to.throw(
44+
'Invalid maxEncryptedDataKeys value.'
45+
)
2246
})
2347
})

0 commit comments

Comments
 (0)