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:
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;