Skip to content

Commit cd002d5

Browse files
authored
fix: cloned material that exceeds limits (#195)
It is posible for material that is created in the caching CMM to imidialy exced the caching limits. In this case the materials clearly should not be cached, but also they should not be cloned.
1 parent fc91a71 commit cd002d5

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

modules/cache-material/src/caching_cryptographic_materials_decorators.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,15 @@ export function getEncryptionMaterials<S extends SupportedAlgorithmSuites> (
110110
}
111111
if (!this._cacheEntryHasExceededLimits(testEntry)) {
112112
this._cache.putEncryptionMaterial(cacheKey, material, plaintextLength, this._maxAge)
113+
return cloneResponse(material)
114+
} else {
115+
/* Postcondition: If the material has exceeded limits it MUST NOT be cloned.
116+
* If it is cloned, and the clone is returned,
117+
* then there exist a copy of the unencrypted data key.
118+
* It is true that this data would be caught by GC, it is better to just not rely on that.
119+
*/
120+
return material
113121
}
114-
115-
return cloneResponse(material)
116122
}
117123
}
118124

modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,69 @@ describe('Cryptographic Material Functions', () => {
393393
expect(assertCount).to.equal(1)
394394
expect(test === encryptionMaterial).to.equal(true)
395395
})
396+
397+
it('Postcondition: If the material has exceeded limits it MUST NOT be cloned.', async () => {
398+
let assertCount = 0
399+
400+
const suiteId = AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256
401+
402+
const nodeSuite = new NodeAlgorithmSuite(suiteId)
403+
const udk128 = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
404+
const trace = {
405+
keyNamespace: 'keyNamespace',
406+
keyName: 'keyName',
407+
flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY | KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY
408+
}
409+
410+
const edk1 = new EncryptedDataKey({ providerId: 'keyNamespace', providerInfo: 'keyName', encryptedDataKey: new Uint8Array([1]) })
411+
const edk2 = new EncryptedDataKey({ providerId: 'p2', providerInfo: 'pi2', encryptedDataKey: new Uint8Array([2]) })
412+
413+
const encryptionMaterial = new NodeEncryptionMaterial(nodeSuite, {})
414+
.setUnencryptedDataKey(udk128, trace)
415+
.addEncryptedDataKey(edk1, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY)
416+
.addEncryptedDataKey(edk2, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY)
417+
418+
const testCMM = {
419+
_partition,
420+
_maxAge,
421+
_maxBytesEncrypted,
422+
_maxMessagesEncrypted,
423+
_cache: {
424+
getEncryptionMaterial () {
425+
assertCount += 1
426+
return false
427+
},
428+
del () {}
429+
},
430+
_backingMaterialsManager: {
431+
getEncryptionMaterials () {
432+
assertCount += 1
433+
return encryptionMaterial
434+
}
435+
},
436+
_cacheEntryHasExceededLimits: () => {
437+
// This is the test.
438+
// If the entry is cashable,
439+
// but has exceeded limit...
440+
assertCount += 1
441+
return true
442+
},
443+
getEncryptionMaterials: getEncryptionMaterials(cacheKeyHelpers),
444+
decryptMaterials: () => {
445+
throw new Error('this should never happen')
446+
}
447+
} as any
448+
449+
const test = await testCMM.getEncryptionMaterials({
450+
suite: nodeSuite,
451+
encryptionContext: context,
452+
frameLength: 10,
453+
plaintextLength: 10
454+
})
455+
456+
expect(assertCount).to.equal(3)
457+
expect(test === encryptionMaterial).to.equal(true)
458+
})
396459
})
397460

398461
describe('decryptionMaterial', () => {

0 commit comments

Comments
 (0)