aboutsummaryrefslogtreecommitdiff
path: root/source/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'source/crypto')
-rw-r--r--source/crypto/Aes.mc23
-rw-r--r--source/crypto/SealedBox.mc21
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.