From 379852d4f29027351e7863de2fd130eb9cde5f78 Mon Sep 17 00:00:00 2001 From: Hannes Mehnert Date: Wed, 27 Mar 2024 17:21:15 +0100 Subject: [PATCH] mirage-crypto: revise DES to avoid global state in key derivation / key usage --- src/cipher_block.ml | 6 +- src/native.ml | 6 +- src/native/des_generic.c | 297 ++++----------------------------------- src/native/des_generic.h | 155 -------------------- 4 files changed, 32 insertions(+), 432 deletions(-) delete mode 100644 src/native/des_generic.h diff --git a/src/cipher_block.ml b/src/cipher_block.ml index 21a4b3ab..299c7094 100644 --- a/src/cipher_block.ml +++ b/src/cipher_block.ml @@ -428,8 +428,7 @@ module DES = struct invalid_arg "DES.of_secret: key length %u" (String.length key) ; let key = Bytes.of_string key in let keybuf = Bytes.create k_s in - Native.DES.des3key key direction ; - Native.DES.cp3key keybuf ; + Native.DES.des3key key direction keybuf; Bytes.unsafe_to_string keybuf let e_of_secret = gen_of_secret ~direction:0 @@ -438,8 +437,7 @@ module DES = struct let of_secret secret = (e_of_secret secret, d_of_secret secret) let encrypt ~key ~blocks src off1 dst off2 = - Native.DES.use3key key ; - Native.DES.ddes src off1 dst off2 blocks + Native.DES.ddes src off1 dst off2 blocks key let decrypt = encrypt end diff --git a/src/native.ml b/src/native.ml index 5684235a..55437a70 100644 --- a/src/native.ml +++ b/src/native.ml @@ -9,10 +9,8 @@ module AES = struct end module DES = struct - external ddes : string -> int -> bytes -> int -> int -> unit = "mc_des_ddes" [@@noalloc] - external des3key : bytes -> int -> unit = "mc_des_des3key" [@@noalloc] - external cp3key : bytes -> unit = "mc_des_cp3key" [@@noalloc] - external use3key : string -> unit = "mc_des_use3key" [@@noalloc] + external ddes : string -> int -> bytes -> int -> int -> string -> unit = "mc_des_ddes_bc" "mc_des_ddes" [@@noalloc] + external des3key : bytes -> int -> bytes -> unit = "mc_des_des3key" [@@noalloc] external k_s : unit -> int = "mc_des_key_size" [@@noalloc] end diff --git a/src/native/des_generic.c b/src/native/des_generic.c index c743cc56..ea659a24 100644 --- a/src/native/des_generic.c +++ b/src/native/des_generic.c @@ -16,20 +16,14 @@ */ #include "mirage_crypto.h" -#include "des_generic.h" + +#define EN0 0 /* MODE == encrypt */ +#define DE1 1 /* MODE == decrypt */ static void scrunch(const unsigned char *, unsigned long *); static void unscrun(unsigned long *, unsigned char *); static void desfunc(unsigned long *, unsigned long *); -static void cookey(unsigned long *); - -static unsigned long KnL[32] = { 0L }; -static unsigned long KnR[32] = { 0L }; -static unsigned long Kn3[32] = { 0L }; -static unsigned char Df_Key[24] = { - 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, - 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, - 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; +static void cookey(unsigned long *, unsigned long[32]); static unsigned short bytebit[8] = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; @@ -59,7 +53,7 @@ static unsigned char pc2[48] = { 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; -void mc_deskey(unsigned char key[8], short edf) /* Thanks to James Gillogly & Phil Karn! */ +void mc_deskey(unsigned char key[8], short edf, unsigned long into[32]) /* Thanks to James Gillogly & Phil Karn! */ { int i, j, l, m, n; unsigned char pc1m[56], pcr[56]; @@ -90,11 +84,11 @@ void mc_deskey(unsigned char key[8], short edf) /* Thanks to James Gillogly & Ph if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; } } - cookey(kn); + cookey(kn, into); return; } -static void cookey(unsigned long *raw1) +static void cookey(unsigned long *raw1, unsigned long into[32]) { unsigned long *cook, *raw0; unsigned long dough[32]; @@ -112,39 +106,12 @@ static void cookey(unsigned long *raw1) *cook |= (*raw1 & 0x0003f000L) >> 4; *cook++ |= (*raw1 & 0x0000003fL); } - mc_usekey(dough); - return; - } - -void mc_cpkey(unsigned long into[32]) -{ - unsigned long *from, *endp; - - from = KnL, endp = &KnL[32]; - while( from < endp ) *into++ = *from++; - return; - } - -void mc_usekey(unsigned long from[32]) -{ - unsigned long *to, *endp; - - to = KnL, endp = &KnL[32]; - while( to < endp ) *to++ = *from++; - return; - } - -void mc_des(unsigned char inblock[8], unsigned char outblock[8]) -{ - unsigned long work[2]; - - scrunch(inblock, work); - desfunc(work, KnL); - unscrun(work, outblock); + for( i = 0; i < 32; i++) { + into[i] = dough[i]; + } return; } - static void scrunch(const unsigned char *outof, unsigned long *into) { *into = (*outof++ & 0xffL) << 24; @@ -390,132 +357,19 @@ static void desfunc(unsigned long *block, unsigned long *keys) return; } -#ifdef D2_DES - -void mc_des2key(unsigned char hexkey[16], short mode) /* stomps on Kn3 too */ -{ - short revmod; - - revmod = (mode == EN0) ? DE1 : EN0; - mc_deskey(&hexkey[8], revmod); - mc_cpkey(KnR); - mc_deskey(hexkey, mode); - mc_cpkey(Kn3); /* Kn3 = KnL */ - return; - } - -void mc_Ddes(const unsigned char from[8], unsigned char into[8]) +void mc_Ddes(const unsigned char from[8], unsigned char into[8], unsigned long* key1, unsigned long* key2, unsigned long* key3) { unsigned long work[2]; scrunch(from, work); - desfunc(work, KnL); - desfunc(work, KnR); - desfunc(work, Kn3); + desfunc(work, key1); + desfunc(work, key2); + desfunc(work, key3); unscrun(work, into); return; } -void mc_D2des(unsigned char from[16], unsigned char into[16]) -{ - unsigned long *right, *l1, swap; - unsigned long leftt[2], bufR[2]; - - right = bufR; - l1 = &leftt[1]; - scrunch(from, leftt); - scrunch(&from[8], right); - desfunc(leftt, KnL); - desfunc(right, KnL); - swap = *l1; - *l1 = *right; - *right = swap; - desfunc(leftt, KnR); - desfunc(right, KnR); - swap = *l1; - *l1 = *right; - *right = swap; - desfunc(leftt, Kn3); - desfunc(right, Kn3); - unscrun(leftt, into); - unscrun(right, &into[8]); - return; - } - -void mc_makekey(char *aptr /* NULL-terminated */, unsigned char kptr[8]) -{ - unsigned char *store; - int first, i; - unsigned long savek[96]; - - cpDkey(savek); - mc_des2key(Df_Key, EN0); - for( i = 0; i < 8; i++ ) kptr[i] = Df_Key[i]; - first = 1; - while( (*aptr != '\0') || first ) { - store = kptr; - for( i = 0; i < 8 && (*aptr != '\0'); i++ ) { - *store++ ^= *aptr & 0x7f; - *aptr++ = '\0'; - } - mc_Ddes(kptr, kptr); - first = 0; - } - useDkey(savek); - return; - } - -void mc_make2key(char *aptr /* NULL-terminated */, unsigned char kptr[16]) -{ - unsigned char *store; - int first, i; - unsigned long savek[96]; - - cpDkey(savek); - mc_des2key(Df_Key, EN0); - for( i = 0; i < 16; i++ ) kptr[i] = Df_Key[i]; - first = 1; - while( (*aptr != '\0') || first ) { - store = kptr; - for( i = 0; i < 16 && (*aptr != '\0'); i++ ) { - *store++ ^= *aptr & 0x7f; - *aptr++ = '\0'; - } - mc_D2des(kptr, kptr); - first = 0; - } - useDkey(savek); - return; - } - -#ifndef D3_DES /* D2_DES only */ - -void mc_cp2key(unsigned long into[64]) -{ - unsigned long *from, *endp; - - cpkey(into); - into = &into[32]; - from = KnR, endp = &KnR[32]; - while( from < endp ) *into++ = *from++; - return; - } - -void mc_use2key(unsigned long from[64]) /* stomps on Kn3 too */ -{ - unsigned long *to, *endp; - - usekey(from); - from = &from[32]; - to = KnR, endp = &KnR[32]; - while( to < endp ) *to++ = *from++; - cpkey(Kn3); /* Kn3 = KnL */ - return; - } - -#else /* D3_DES too */ - -void mc_des3key(unsigned char hexkey[24], short mode) +void mc_des3key(unsigned char hexkey[24], short mode, unsigned long into[96]) { unsigned char *first, *third; short revmod; @@ -530,100 +384,12 @@ void mc_des3key(unsigned char hexkey[24], short mode) first = &hexkey[16]; third = hexkey; } - mc_deskey(&hexkey[8], revmod); - mc_cpkey(KnR); - mc_deskey(third, mode); - mc_cpkey(Kn3); - mc_deskey(first, mode); - return; - } - -void mc_cp3key(unsigned long into[96]) -{ - unsigned long *from, *endp; - - mc_cpkey(into); - into = &into[32]; - from = KnR, endp = &KnR[32]; - while( from < endp ) *into++ = *from++; - from = Kn3, endp = &Kn3[32]; - while( from < endp ) *into++ = *from++; - return; - } - -void mc_use3key(unsigned long from[96]) -{ - unsigned long *to, *endp; - - mc_usekey(from); - from = &from[32]; - to = KnR, endp = &KnR[32]; - while( to < endp ) *to++ = *from++; - to = Kn3, endp = &Kn3[32]; - while( to < endp ) *to++ = *from++; - return; - } - -static void D3des(unsigned char from[24], unsigned char into[24]) /* amateur theatrics */ -{ - unsigned long swap, leftt[2], middl[2], right[2]; - - scrunch(from, leftt); - scrunch(&from[8], middl); - scrunch(&from[16], right); - desfunc(leftt, KnL); - desfunc(middl, KnL); - desfunc(right, KnL); - swap = leftt[1]; - leftt[1] = middl[0]; - middl[0] = swap; - swap = middl[1]; - middl[1] = right[0]; - right[0] = swap; - desfunc(leftt, KnR); - desfunc(middl, KnR); - desfunc(right, KnR); - swap = leftt[1]; - leftt[1] = middl[0]; - middl[0] = swap; - swap = middl[1]; - middl[1] = right[0]; - right[0] = swap; - desfunc(leftt, Kn3); - desfunc(middl, Kn3); - desfunc(right, Kn3); - unscrun(leftt, into); - unscrun(middl, &into[8]); - unscrun(right, &into[16]); - return; - } - -void mc_make3key(char *aptr /* NULL-terminated */, unsigned char kptr[24]) -{ - unsigned char *store; - int first, i; - unsigned long savek[96]; - - mc_cp3key(savek); - mc_des3key(Df_Key, EN0); - for( i = 0; i < 24; i++ ) kptr[i] = Df_Key[i]; - first = 1; - while( (*aptr != '\0') || first ) { - store = kptr; - for( i = 0; i < 24 && (*aptr != '\0'); i++ ) { - *store++ ^= *aptr & 0x7f; - *aptr++ = '\0'; - } - D3des(kptr, kptr); - first = 0; - } - mc_use3key(savek); + mc_deskey(&hexkey[8], revmod, into); + mc_deskey(third, mode, &into[32]); + mc_deskey(first, mode, &into[64]); return; } -#endif /* D3_DES */ -#endif /* D2_DES */ - /* Validation sets: * * Single-length key, single-length plaintext - @@ -657,9 +423,12 @@ void mc_make3key(char *aptr /* NULL-terminated */, unsigned char kptr[24]) /* OCaml front-end */ -static inline void _mc_ddes (const unsigned char *src, unsigned char *dst, unsigned int blocks) { +static inline void _mc_ddes (const unsigned char *src, unsigned char *dst, unsigned int blocks, unsigned long* key) { + unsigned long* key1 = key; + unsigned long* key2 = key + 32; + unsigned long* key3 = key + 64; while (blocks --) { - mc_Ddes (src, dst); + mc_Ddes (src, dst, key1, key2, key3); src += 8 ; dst += 8; } } @@ -670,25 +439,15 @@ mc_des_key_size (__unit ()) { } CAMLprim value -mc_des_des3key (value key, value direction) { - mc_des3key (_bp_uint8 (key), Int_val (direction)); - return Val_unit; -} - -CAMLprim value -mc_des_cp3key (value dst) { - mc_cp3key ((unsigned long *) _bp_uint8 (dst)); +mc_des_des3key (value key, value direction, value dst) { + mc_des3key (_bp_uint8 (key), Int_val (direction), (unsigned long *) _bp_uint8 (dst)); return Val_unit; } CAMLprim value -mc_des_use3key (value src) { - mc_use3key ((unsigned long *) _bp_uint8 (src)); +mc_des_ddes (value src, value off1, value dst, value off2, value blocks, value key) { + _mc_ddes (_st_uint8_off (src, off1), _bp_uint8_off (dst, off2), Int_val (blocks), (unsigned long *) _bp_uint8 (key)); return Val_unit; } -CAMLprim value -mc_des_ddes (value src, value off1, value dst, value off2, value blocks) { - _mc_ddes (_st_uint8_off (src, off1), _bp_uint8_off (dst, off2), Int_val (blocks)); - return Val_unit; -} +__define_bc_6(mc_des_ddes) diff --git a/src/native/des_generic.h b/src/native/des_generic.h deleted file mode 100644 index 4c3fe0ed..00000000 --- a/src/native/des_generic.h +++ /dev/null @@ -1,155 +0,0 @@ -/* d3des.h - - * - * Headers and defines for d3des.c - * Graven Imagery, 1992. - * - * THIS SOFTWARE PLACED IN THE PUBLIC DOMAIN BY THE AUTHOUR - * 920825 19:42 EDST - * - * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge - * (GEnie : OUTER; CIS : [71755,204]) - */ - -#define D2_DES /* include double-length support */ -#define D3_DES /* include triple-length support */ - -#ifdef D3_DES -#ifndef D2_DES -#define D2_DES /* D2_DES is needed for D3_DES */ -#endif -#endif - -#define EN0 0 /* MODE == encrypt */ -#define DE1 1 /* MODE == decrypt */ - -/* Useful on 68000-ish machines, but NOT USED here. */ - -typedef union { - unsigned long blok[2]; - unsigned short word[4]; - unsigned char byte[8]; - } M68K; - -typedef union { - unsigned long dblok[4]; - unsigned short dword[8]; - unsigned char dbyte[16]; - } M68K2; - -extern void mc_deskey(unsigned char [8], short); -/* hexkey[8] MODE - * Sets the internal key register according to the hexadecimal - * key contained in the 8 bytes of hexkey, according to the DES, - * for encryption or decryption according to MODE. - */ - -extern void mc_usekey(unsigned long [32]); -/* cookedkey[32] - * Loads the internal key register with the data in cookedkey. - */ - -extern void mc_cpkey(unsigned long [32]); -/* cookedkey[32] - * Copies the contents of the internal key register into the storage - * located at &cookedkey[0]. - */ - -extern void mc_des(unsigned char [8], unsigned char [8]); -/* from[8] to[8] - * Encrypts/Decrypts (according to the key currently loaded in the - * internal key register) one block of eight bytes at address 'from' - * into the block at address 'to'. They can be the same. - */ - -#ifdef D2_DES - -#define desDkey(a,b) mc_des2key((a),(b)) -extern void mc_des2key(unsigned char [16], short); -/* hexkey[16] MODE - * Sets the internal key registerS according to the hexadecimal - * keyS contained in the 16 bytes of hexkey, according to the DES, - * for DOUBLE encryption or decryption according to MODE. - * NOTE: this clobbers all three key registers! - */ - -extern void mc_Ddes(const unsigned char [8], unsigned char [8]); -/* from[8] to[8] - * Encrypts/Decrypts (according to the keyS currently loaded in the - * internal key registerS) one block of eight bytes at address 'from' - * into the block at address 'to'. They can be the same. - */ - -extern void mc_D2des(unsigned char [16], unsigned char [16]); -/* from[16] to[16] - * Encrypts/Decrypts (according to the keyS currently loaded in the - * internal key registerS) one block of SIXTEEN bytes at address 'from' - * into the block at address 'to'. They can be the same. - */ - -extern void mc_makekey(char *, unsigned char [8]); -/* *password, single-length key[8] - * With a double-length default key, this routine hashes a NULL-terminated - * string into an eight-byte random-looking key, suitable for use with the - * deskey() routine. - */ - -#define makeDkey(a,b) mc_make2key((a),(b)) -extern void mc_make2key(char *, unsigned char [16]); -/* *password, double-length key[16] - * With a double-length default key, this routine hashes a NULL-terminated - * string into a sixteen-byte random-looking key, suitable for use with the - * des2key() routine. - */ - -#ifndef D3_DES /* D2_DES only */ - -#define useDkey(a) mc_use2key((a)) -#define cpDkey(a) mc_cp2key((a)) - -extern void mc_use2key(unsigned long [64]); -/* cookedkey[64] - * Loads the internal key registerS with the data in cookedkey. - * NOTE: this clobbers all three key registers! - */ - -extern void mc_cp2key(unsigned long [64]); -/* cookedkey[64] - * Copies the contents of the internal key registerS into the storage - * located at &cookedkey[0]. - */ - -#else /* D3_DES too */ - -#define useDkey(a) mc_use3key((a)) -#define cpDkey(a) mc_cp3key((a)) - -extern void mc_des3key(unsigned char [24], short); -/* hexkey[24] MODE - * Sets the internal key registerS according to the hexadecimal - * keyS contained in the 24 bytes of hexkey, according to the DES, - * for DOUBLE encryption or decryption according to MODE. - */ - -extern void mc_use3key(unsigned long [96]); -/* cookedkey[96] - * Loads the 3 internal key registerS with the data in cookedkey. - */ - -extern void mc_cp3key(unsigned long [96]); -/* cookedkey[96] - * Copies the contents of the 3 internal key registerS into the storage - * located at &cookedkey[0]. - */ - -extern void mc_make3key(char *, unsigned char [24]); -/* *password, triple-length key[24] - * With a triple-length default key, this routine hashes a NULL-terminated - * string into a twenty-four-byte random-looking key, suitable for use with - * the des3key() routine. - */ - -#endif /* D3_DES */ -#endif /* D2_DES */ - -/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery - ********************************************************************/