commit 30e7157d779b3a25053927c4763966cf6b71bf0a
parent b263d63733877a326247bfeef98324e1ed54dafd
Author: Armin Preiml <apreiml@strohwolke.at>
Date: Sun, 21 Nov 2021 20:30:11 +0100
caller must provide a buffer for cipher::cbc mode
Signed-off-by: Armin Preiml <apreiml@strohwolke.at>
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
3 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/crypto/aes/aes_ct64.ha b/crypto/aes/aes_ct64.ha
@@ -34,6 +34,10 @@ def CT64_NPARALLEL: size = 4;
// Size of the buffer used for [[crypto::cipher::ctr]].
export def CTR_BUFSIZE: size = BLOCKSIZE * (CT64_NPARALLEL + 1);
+// Size of the buffer used for [[crypto::cipher::cbc_encryptor]] and
+// [[crypto::cipher::cbc_decryptor]].
+export def CBC_BUFSIZE: size = BLOCKSIZE * 2;
+
export type ct64_block = struct {
cipher::block,
rounds: uint,
diff --git a/crypto/aes/cbc+test.ha b/crypto/aes/cbc+test.ha
@@ -35,16 +35,15 @@ use bytes;
];
let result: [64]u8 = [0...];
+ let buf: [CBC_BUFSIZE]u8 = [0...];
let b = ct64(key);
- let cbc = cipher::cbc_encryptor(&b, iv[..]);
- defer cipher::cbc_finish(&cbc);
+ let cbc = cipher::cbc_encryptor(&b, iv[..], buf[..]);
cipher::cbc_encrypt(&cbc, result, plain);
assert(bytes::equal(cipher, result));
- let cbcd = cipher::cbc_decryptor(&b, iv[..]);
- defer cipher::cbc_finish(&cbcd);
+ let cbcd = cipher::cbc_decryptor(&b, iv[..], buf[..]);
cipher::cbc_decrypt(&cbcd, result, cipher);
assert(bytes::equal(plain, result));
@@ -84,16 +83,15 @@ use bytes;
];
let result: [64]u8 = plain;
+ let buf: [CBC_BUFSIZE]u8 = [0...];
let b = ct64(key);
- let cbc = cipher::cbc_encryptor(&b, iv[..]);
- defer cipher::cbc_finish(&cbc);
+ let cbc = cipher::cbc_encryptor(&b, iv[..], buf[..]);
cipher::cbc_encrypt(&cbc, result, result);
assert(bytes::equal(cipher, result));
- let cbcd = cipher::cbc_decryptor(&b, iv[..]);
- defer cipher::cbc_finish(&cbcd);
+ let cbcd = cipher::cbc_decryptor(&b, iv[..], buf[..]);
cipher::cbc_decrypt(&cbcd, result, result);
assert(bytes::equal(plain, result));
diff --git a/crypto/cipher/cbc.ha b/crypto/cipher/cbc.ha
@@ -5,39 +5,51 @@ export type cbc_mode = struct {
b: *block,
encrypt: bool,
carry: []u8,
+ carrybuf: []u8,
};
-// Creates a cipher block chaining mode encryptor. The encryptor will
-// keep its state, so data can be encrypted using multiple cbc_encrypt calls.
-// Needs to be finished with [[crypto::cipher::cbc_finish]]
-export fn cbc_encryptor(b: *block, iv: []u8) cbc_mode = {
- assert(len(iv) == sz(b), "len(iv) must be the same as block length sz");
+// Creates a cipher block chaining mode encryptor. The encryptor will keep its
+// state, so data can be encrypted using multiple cbc_encrypt calls. The size
+// of the buffer depends on the block cipher. Use [[crypto::aes::CBC_BUFSIZE]]
+// for the stdlib AES implementation.
+export fn cbc_encryptor(b: *block, iv: []u8, buf: []u8) cbc_mode = {
+ assert(len(iv) == sz(b), "len(iv) must be the same as the block size");
+ assert(len(buf) == sz(b) * 2,
+ "buffer needs to be two times of the block size");
+
+ let bsz = sz(b);
+ let carry = buf[0..bsz];
+ bytes::copy(carry, iv);
return cbc_mode {
b = b,
encrypt = true,
- carry = alloc(iv),
+ carry = carry,
+ carrybuf = buf[bsz..],
};
};
-// Creates a cipher block chaining mode decryptor. The decryptor will
-// keep its state, so data can be encrypted using multiple cbc_decrypt calls.
-// Needs to be finished with [[crypto::cipher::cbc_finish]]
-export fn cbc_decryptor(b: *block, iv: []u8) cbc_mode = {
+// Creates a cipher block chaining mode decryptor. The decryptor will keep its
+// state, so data can be encrypted using multiple cbc_decrypt calls. The size
+// of the buffer depends on the block cipher. Use [[crypto::aes::CBC_BUFSIZE]]
+// for the stdlib AES implementation.
+export fn cbc_decryptor(b: *block, iv: []u8, buf: []u8) cbc_mode = {
assert(len(iv) == sz(b), "len(iv) must be the same as block length sz");
+ assert(len(buf) == sz(b) * 2,
+ "buffer needs to be two times of the block size");
+
+ let bsz = sz(b);
+ let carry = buf[0..bsz];
+ bytes::copy(carry, iv);
return cbc_mode {
b = b,
encrypt = false,
- carry = alloc(iv),
+ carry = carry,
+ carrybuf = buf[bsz..],
};
};
-// Frees a cipher block chaining mode encryptor or decryptor
-export fn cbc_finish(c: *cbc_mode) void = {
- free(c.carry);
-};
-
// Encrypts given blocks with a length that is a multiple of the block size.
// In place encryption only works if dest and src point exactly at the
// same range.
@@ -66,14 +78,11 @@ export fn cbc_decrypt(c: *cbc_mode, dest: []u8, src: []u8) void = {
assert(len(dest) % sz == 0 && len(src) == len(dest),
"size of dest and src needs to match and be a multiple of block size");
- let carry = alloc(c.carry);
- defer free(carry);
-
for (let i = 0z; i < len(dest); i += sz) {
let eb = i + sz;
- bytes::copy(carry, c.carry);
+ bytes::copy(c.carrybuf, c.carry);
bytes::copy(c.carry, src[i..eb]);
decrypt(c.b, dest[i..eb], src[i..eb]);
- crypto::math::xor(dest[i..eb], dest[i..eb], carry);
+ crypto::math::xor(dest[i..eb], dest[i..eb], c.carrybuf);
};
};