hare

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

commit e0660d87a2e8d03a2010f3d272496a4da9b2128e
parent a8f7d7c6e462ad01a845ae7b3caa3c46ad6bc951
Author: Armin Preiml <apreiml@strohwolke.at>
Date:   Fri, 16 Dec 2022 14:53:49 +0100

crypto::cipher: block vtable

Signed-off-by: Armin Preiml <apreiml@strohwolke.at>

Diffstat:
Mcrypto/aes/+x86_64/ni.ha | 16++++++++++------
Mcrypto/aes/aes_ct64.ha | 19+++++++++++++------
Mcrypto/blowfish/blowfish.ha | 22+++++++++++++---------
Mcrypto/cipher/block.ha | 4+++-
4 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/crypto/aes/+x86_64/ni.ha b/crypto/aes/+x86_64/ni.ha @@ -7,12 +7,20 @@ def RKLEN_192: size = 208; def RKLEN_256: size = 240; export type x86ni_block = struct { - cipher::block, + block: cipher::block, enc_rk: [RKLEN_256]u8, dec_rk: [RKLEN_256]u8, rklen: u8, }; +const x86ni_vtable: cipher::blockvtable = cipher::blockvtable { + blocksz = BLOCKSIZE, + nparallel = 1, + encrypt = &x86ni_encrypt, + decrypt = &x86ni_decrypt, + finish = &x86ni_finish, +}; + // Checks if the native AES interface is available. export fn x86ni_available() bool = { return rt::cpuid_hasflags(0, rt::cpuid_ecxflags::AES); @@ -27,11 +35,7 @@ export fn x86ni_available() bool = { // state. export fn x86ni() x86ni_block = { return x86ni_block { - blocksz = BLOCKSIZE, - nparallel = 1, - encrypt = &x86ni_encrypt, - decrypt = &x86ni_decrypt, - finish = &x86ni_finish, + block = &x86ni_vtable, ... }; }; diff --git a/crypto/aes/aes_ct64.ha b/crypto/aes/aes_ct64.ha @@ -27,6 +27,7 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. use crypto::cipher; +use crypto::cipher::{blocksz,nparallel}; use crypto::math; use endian; @@ -43,7 +44,7 @@ export def CTR_BUFSIZE: size = BLOCKSIZE * (CT64_NPARALLEL + 1); export def CBC_BUFSIZE: size = BLOCKSIZE * 2; export type ct64_block = struct { - cipher::block, + block: cipher::block, rounds: uint, sk_exp: [120]u64, }; @@ -56,12 +57,16 @@ export type ct64_block = struct { // using the cipher to securely erase any secret data stored in the cipher // state. export fn ct64() ct64_block = ct64_block { + block = &ct64_vtable, + ... +}; + +const ct64_vtable: cipher::blockvtable = cipher::blockvtable { blocksz = BLOCKSIZE, nparallel = CT64_NPARALLEL, encrypt = &aes_ct64_encrypt, decrypt = &aes_ct64_decrypt, finish = &aes_ct64_finish, - ... }; // Initializes the ct64 AES implementation with an encryption key. @@ -75,10 +80,11 @@ export fn ct64_init(cipher: *ct64_block, key: []u8) void = { fn aes_ct64_encrypt(block: *cipher::block, dest: []u8, src: []u8) void = { let b = block: *ct64_block; - assert(len(src) % b.blocksz == 0 && (len(src) / b.blocksz) <= b.nparallel, + assert(len(src) % blocksz(b) == 0 + && (len(src) / blocksz(b)) <= nparallel(b), "invalid block size"); - let nblocks = len(src) / b.blocksz; + let nblocks = len(src) / blocksz(b); let q: [8]u64 = [0...]; let w: [16]u32 = [0...]; @@ -103,10 +109,11 @@ fn aes_ct64_encrypt(block: *cipher::block, dest: []u8, src: []u8) void = { fn aes_ct64_decrypt(block: *cipher::block, dest: []u8, src: []u8) void = { let b = block: *ct64_block; - assert(len(src) % b.blocksz == 0 && (len(src) / b.blocksz) <= b.nparallel, + assert(len(src) % blocksz(b) == 0 + && (len(src) / blocksz(b)) <= nparallel(b), "invalid block size"); - const nblocks = len(src) / b.blocksz; + const nblocks = len(src) / blocksz(b); let q: [8]u64 = [0...]; let w: [16]u32 = [0...]; diff --git a/crypto/blowfish/blowfish.ha b/crypto/blowfish/blowfish.ha @@ -11,7 +11,7 @@ use endian; export def BLOCKSIZE: size = 8; export type state = struct { - cipher::block, + block: cipher::block, p: [18]u32, s0: [256]u32, s1: [256]u32, @@ -19,17 +19,21 @@ export type state = struct { s3: [256]u32, }; +const vtable: cipher::blockvtable = cipher::blockvtable { + blocksz = BLOCKSIZE, + nparallel = 1, + encrypt = &block_encrypt, + decrypt = &block_decrypt, + finish = &block_finish, +}; + // Initializes a new Blowfish cipher. The user should must call [[init]] or // [[init_salt]] prior to use, then may use [[crypto::cipher::encrypt]] et al. // The user must call [[finish]] when they are done using the stream to securely // erase secret information stored in the stream state. export fn new() state = { return state { - blocksz = BLOCKSIZE, - nparallel = 1, - encrypt = &block_encrypt, - decrypt = &block_decrypt, - finish = &block_finish, + block = &vtable, p = p, s0 = s0, s1 = s1, @@ -106,7 +110,7 @@ fn init_vector_salt( fn block_encrypt(c: *cipher::block, dest: []u8, src: []u8) void = { const c = c: *state; - assert(c.encrypt == &block_encrypt); + assert(c.block.encrypt == &block_encrypt); let l = src[0]<<24u32 | src[1]<<16u32 | src[2]<<8u32 | src[3]: u32; let r = src[4]<<24u32 | src[5]<<16u32 | src[6]<<8u32 | src[7]: u32; @@ -125,7 +129,7 @@ fn block_encrypt(c: *cipher::block, dest: []u8, src: []u8) void = { fn block_decrypt(c: *cipher::block, dest: []u8, src: []u8) void = { const c = c: *state; - assert(c.decrypt == &block_decrypt); + assert(c.block.decrypt == &block_decrypt); let l = src[0]<<24u32 | src[1]<<16u32 | src[2]<<8u32 | src[3]: u32; let r = src[4]<<24u32 | src[5]<<16u32 | src[6]<<8u32 | src[7]: u32; @@ -144,7 +148,7 @@ fn block_decrypt(c: *cipher::block, dest: []u8, src: []u8) void = { fn block_finish(cipher: *cipher::block) void = { const cipher = cipher: *state; - assert(cipher.finish == &block_finish); + assert(cipher.block.finish == &block_finish); bytes::zero((&cipher.p: *[*]u8)[..len(cipher.p) * size(u32)]); bytes::zero((&cipher.s0: *[*]u8)[..len(cipher.s0) * size(u32)]); bytes::zero((&cipher.s1: *[*]u8)[..len(cipher.s1) * size(u32)]); diff --git a/crypto/cipher/block.ha b/crypto/cipher/block.ha @@ -3,7 +3,7 @@ // (c) 2021 Drew DeVault <sir@cmpwn.com> // An abstract interface for implementing block ciphers. -export type block = struct { +export type blockvtable = struct { blocksz: size, nparallel: size, @@ -13,6 +13,8 @@ export type block = struct { finish: *fn(b: *block) void, }; +export type block = *blockvtable; + // Returns the block size in bytes for a [[block]] cipher. export fn blocksz(b: *block) size = b.blocksz;