diff options
Diffstat (limited to 'source/crypto')
| -rw-r--r-- | source/crypto/Aes.mc | 23 | ||||
| -rw-r--r-- | source/crypto/SealedBox.mc | 21 |
2 files changed, 40 insertions, 4 deletions
diff --git a/source/crypto/Aes.mc b/source/crypto/Aes.mc index 242448b..9e4f320 100644 --- a/source/crypto/Aes.mc +++ b/source/crypto/Aes.mc @@ -42,19 +42,34 @@ module Aes { // Encrypt with PKCS#7 padding: 1 to 16 bytes, each holding the pad length. function cbcEncrypt(key as ByteArray, iv as ByteArray, plaintext as ByteArray) as ByteArray { + return cbcEncryptKeep(key, iv, plaintext, null); + } + + // As cbcEncrypt(); with `leftovers`, the padded copy is added there for + // the caller to wipe (in steps, for kilobytes) instead of wiped here. + function cbcEncryptKeep(key as ByteArray, iv as ByteArray, plaintext as ByteArray, leftovers as Array<ByteArray>?) as ByteArray { var padLength = BLOCK_BYTES - (plaintext.size() % BLOCK_BYTES); var padded = Bytes.copy(plaintext); for (var i = 0; i < padLength; i++) { padded.add(padLength); } var out = cbcRaw(key, iv, padded, true); - Bytes.wipe(padded); + if (leftovers != null) { + leftovers.add(padded); + } else { + Bytes.wipe(padded); + } return out; } // Decrypt and remove PKCS#7 padding; null when the length or the padding is // wrong. function cbcDecrypt(key as ByteArray, iv as ByteArray, ciphertext as ByteArray) as ByteArray? { + return cbcDecryptKeep(key, iv, ciphertext, null); + } + + // As cbcDecrypt(); with `leftovers`, the padded plaintext is added there. + function cbcDecryptKeep(key as ByteArray, iv as ByteArray, ciphertext as ByteArray, leftovers as Array<ByteArray>?) as ByteArray? { var size = ciphertext.size(); if (size == 0 || size % BLOCK_BYTES != 0) { return null; @@ -68,7 +83,11 @@ module Aes { } } var plaintext = valid ? padded.slice(0, size - padLength) : null; - Bytes.wipe(padded); + if (leftovers != null) { + leftovers.add(padded); + } else { + Bytes.wipe(padded); + } return plaintext; } } diff --git a/source/crypto/SealedBox.mc b/source/crypto/SealedBox.mc index 765a1d8..3877e1a 100644 --- a/source/crypto/SealedBox.mc +++ b/source/crypto/SealedBox.mc @@ -55,7 +55,19 @@ module SealedBox { // Seal with a given IV. Only tests call this directly (fixed IVs make the // output reproducible); reusing an IV in real use would be a mistake. function sealWithIv(keys as Keys, aad as ByteArray, plaintext as ByteArray, iv as ByteArray) as ByteArray { - var ciphertext = Aes.cbcEncrypt(keys.encKey, iv, plaintext); + return sealKeepWithIv(keys, aad, plaintext, iv, null); + } + + // As seal(); with `leftovers`, the padded plaintext copy is added there + // for the caller to wipe in steps (zeroing 4 KB is a large part of a + // watchdog step) instead of wiped here. + function sealKeep(keys as Keys, aad as ByteArray, plaintext as ByteArray, leftovers as Array<ByteArray>?) as ByteArray { + return sealKeepWithIv(keys, aad, plaintext, Cryptography.randomBytes(IV_BYTES), leftovers); + } + + function sealKeepWithIv(keys as Keys, aad as ByteArray, plaintext as ByteArray, iv as ByteArray, + leftovers as Array<ByteArray>?) as ByteArray { + var ciphertext = Aes.cbcEncryptKeep(keys.encKey, iv, plaintext, leftovers); var box = [VERSION]b; box.addAll(iv); box.addAll(ciphertext); @@ -66,6 +78,11 @@ module SealedBox { // The plaintext, or null if the box is malformed, was sealed with another // key or aad, or was changed in any way. function open(keys as Keys, aad as ByteArray, box as ByteArray) as ByteArray? { + return openKeep(keys, aad, box, null); + } + + // As open(); with `leftovers`, the padded plaintext is added there. + function openKeep(keys as Keys, aad as ByteArray, box as ByteArray, leftovers as Array<ByteArray>?) as ByteArray? { var size = box.size(); if (size < MIN_SIZE || (size - 1 - IV_BYTES - TAG_BYTES) % Aes.BLOCK_BYTES != 0 || box[0] != VERSION) { return null; @@ -77,7 +94,7 @@ module SealedBox { if (!valid) { return null; } - return Aes.cbcDecrypt(keys.encKey, box.slice(1, 1 + IV_BYTES), box.slice(1 + IV_BYTES, size - TAG_BYTES)); + return Aes.cbcDecryptKeep(keys.encKey, box.slice(1, 1 + IV_BYTES), box.slice(1 + IV_BYTES, size - TAG_BYTES), leftovers); } // HMAC over the label, the aad (with its length) and the box body. |
