hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mcrypto/aes/aes_ct64.ha | 4++++
Mcrypto/aes/cbc+test.ha | 14++++++--------
Mcrypto/cipher/cbc.ha | 51++++++++++++++++++++++++++++++---------------------
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); }; };