From fa11284b9469c1c79af7f8f129da934c1ebcf594 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 29 Sep 2002 23:50:10 +0000 Subject: [PATCH 1/1] Drop alg->byteswap; implement counter mode; split padding so now we do PKCS#5 and RFC2406. --- base/chiark-tcl.h | 12 ++-- base/tables-examples.tct | 16 +++-- crypto/algtables.c | 1 - crypto/bcmode.c | 37 +++++++----- crypto/crypto.c | 124 +++++++++++++++++++++++++++++++-------- hbytes/hbytes.h | 12 ++-- 6 files changed, 152 insertions(+), 50 deletions(-) diff --git a/base/chiark-tcl.h b/base/chiark-tcl.h index 06c98fc..ff5220b 100644 --- a/base/chiark-tcl.h +++ b/base/chiark-tcl.h @@ -28,8 +28,13 @@ * +1 A is B plus a nonempty suffix (ie, A has B as a prefix) * +2 A is lexically later than B and does not have B as a prefix * - * hbytes pkcs5 pa|ua VAR ALG => worked? (always 1 for p) - * hbytes pkcs5 pn|un VAR BLOCKSIZE => worked? (always 1 for p) + * hbytes pad pa|ua VAR ALG METH [METHARGS] => worked? (always 1 for p) + * hbytes pad pn|un VAR BS METH [METHARGS] => worked? (always 1 for p) + * hbytes pad pa|pn VAR ALG|BS pkcs5 => 1 + * hbytes pad ua|un VAR ALG|BS pkcs5 => worked? + * hbytes pad pa|pn VAR ALG|BS rfc2406 NXTHDR => 1 + * hbytes pad ua|un VAR ALG|BS rfc2406 NXTHDRVAR => worked? + * * hbytes blockcipher d|e VAR ALG KEY MODE [IV] => IV * hbytes blockcipher mac MSG ALG KEY MODE IV => final block * hbytes blockcipher prop PROPERTY ALG => property value @@ -237,7 +242,7 @@ void memxor(Byte *dest, const Byte *src, int l); typedef struct { const char *name; int pad, use_algname; -} PadMethod; +} PadOp; extern Tcl_ObjType blockcipherkey_type; @@ -269,7 +274,6 @@ typedef struct { typedef struct { const char *name; int blocksize, schedule_size, key_min, key_max; - void (*byteswap)(void *block); BlockCipherPerDirectionInfo encrypt, decrypt; } BlockCipherAlgInfo; diff --git a/base/tables-examples.tct b/base/tables-examples.tct index 56fd4ab..7cbf312 100644 --- a/base/tables-examples.tct +++ b/base/tables-examples.tct @@ -131,11 +131,12 @@ Table hbytes HBytes_SubCommand random length int => hb - pkcs5 - meth enum(PadMethod, "hbytes pad subcommand") + pad + op enum(PadOp, "hbytes pad subcommand") v hbv - block obj - => int + blocksz obj + meth enum(PadMethodInfo, "pad method") + ... methargs blockcipher op enum(BlockCipherOp, "op") ... obj @@ -154,6 +155,13 @@ Table hbytes HBytes_SubCommand alg enum(HashAlgInfo, "alg") => int +Table padmethodinfo PadMethodInfo + pkcs5 + => int + rfc2406 + nxthdr obj + => int + Table dgram_socket DgramSocket_SubCommand create local sockaddr diff --git a/crypto/algtables.c b/crypto/algtables.c index 8d7b0a2..8f796ce 100644 --- a/crypto/algtables.c +++ b/crypto/algtables.c @@ -39,7 +39,6 @@ const BlockCipherAlgInfo blockcipheralginfos[]= { #define ALIAS(alias,name,NAME) \ { #alias, NAME##_BLOCK_SIZE, sizeof(struct name##_ctx), \ NAME##_MIN_KEY_SIZE, NAME##_MAX_KEY_SIZE, \ - 0, \ { alg_##name##_makekey, alg_##name##_encr }, \ { alg_##name##_makekey, alg_##name##_decr } \ }, diff --git a/crypto/bcmode.c b/crypto/bcmode.c index 9a5ae92..e413de7 100644 --- a/crypto/bcmode.c +++ b/crypto/bcmode.c @@ -9,16 +9,12 @@ static const char *mode_cbc_encrypt(Byte *data, int blocks, const void *sch) { int blocksize= alg->blocksize; memcpy(chain,iv,blocksize); - if (alg->byteswap) alg->byteswap(chain); while (blocks > 0) { - if (alg->byteswap) alg->byteswap(data); - memxor(data, chain, blocksize); alg->encrypt.crypt(sch, data, data); memcpy(chain, data, blocksize); - if (alg->byteswap) alg->byteswap(data); blocks--; data += blocksize; } return 0; @@ -32,17 +28,13 @@ static const char *mode_cbc_decrypt(Byte *data, int blocks, int cchain= 0; memcpy(chain,iv,blocksize); - if (alg->byteswap) alg->byteswap(chain); while (blocks > 0) { - if (alg->byteswap) alg->byteswap(data); - memcpy(chain + (cchain^blocksize), data, blocksize); alg->decrypt.crypt(sch, data, data); memxor(data, chain + cchain, blocksize); cchain ^= blocksize; - if (alg->byteswap) alg->byteswap(data); blocks--; data += blocksize; } return 0; @@ -55,11 +47,9 @@ static void cbcmac_core(const Byte *data, int blocks, int blocksize= alg->blocksize; memcpy(buf,iv,blocksize); - if (alg->byteswap) alg->byteswap(buf); while (blocks > 0) { memcpy(buf + blocksize, data, blocksize); - if (alg->byteswap) alg->byteswap(buf + blocksize); memxor(buf, buf + blocksize, blocksize); alg->encrypt.crypt(sch, buf, buf); @@ -73,7 +63,6 @@ static const char *mode_cbc_mac(const Byte *data, int blocks, const BlockCipherAlgInfo *alg, const void *sch) { cbcmac_core(data,blocks,iv,buf,alg,sch); - if (alg->byteswap) alg->byteswap(buf); return 0; } @@ -83,7 +72,6 @@ static const char *mode_cbc_mac2(const Byte *data, int blocks, const void *sch) { cbcmac_core(data,blocks,iv,buf,alg,sch); alg->encrypt.crypt(sch, buf, buf); - if (alg->byteswap) alg->byteswap(buf); return 0; } @@ -94,17 +82,38 @@ static const char *mode_ecb(Byte *data, int blocks, int blocksize= alg->blocksize; while (blocks > 0) { - if (alg->byteswap) alg->byteswap(data); (encr ? &alg->encrypt : &alg->decrypt)->crypt(sch, data, data); - if (alg->byteswap) alg->byteswap(data); blocks--; data += blocksize; } return 0; } +static const char *mode_ctr(Byte *data, int blocks, + const Byte *iv, Byte *counter, + const BlockCipherAlgInfo *alg, int encr, + const void *sch) { + int blocksize= alg->blocksize; + Byte *cipher= counter + blocksize; + int byte; + + memcpy(counter, iv, blocksize); + while (blocks > 0) { + alg->encrypt.crypt(sch, counter, cipher); + memxor(data, cipher, blocksize); + for (byte=blocksize-1; byte>=0; byte--) { + if (++counter[byte]) break; + /* new value of zero implies carry, so increment next byte */ + } + blocks--; + data += blocksize; + } + return 0; +} + const BlockCipherModeInfo blockciphermodeinfos[]= { { "cbc", 1, 2, 1, mode_cbc_encrypt, mode_cbc_decrypt, mode_cbc_mac }, { "cbc-mac2", 1, 2, 1, 0, 0, mode_cbc_mac2 }, { "ecb", 0, 0, 0, mode_ecb, mode_ecb, 0 }, + { "ctr-sif", 1, 2, 0, mode_ctr, mode_ctr, 0 }, { 0 } }; diff --git a/crypto/crypto.c b/crypto/crypto.c index 9b79881..49a409f 100644 --- a/crypto/crypto.c +++ b/crypto/crypto.c @@ -5,13 +5,12 @@ #include "hbytes.h" #include "tables.h" -#include "serpent.h" void memxor(Byte *dest, const Byte *src, int l) { while (l--) *dest++ ^= *src++; } -const PadMethod padmethods[]= { +const PadOp padops[]= { { "un", 0, 0 }, { "ua", 0, 1 }, { "pn", 1, 0 }, @@ -19,35 +18,114 @@ const PadMethod padmethods[]= { { 0 } }; -int do_hbytes_pkcs5(ClientData cd, Tcl_Interp *ip, - const PadMethod *meth, HBytes_Var v, Tcl_Obj *block, - int *ok) { - int rc, blocksize, padlen, old_len, i; - Byte *padding; - const Byte *unpad; +typedef struct { + HBytes_Value *hb; + int pad, blocksize; /* 0 or 1 */ +} PadMethodClientData; + +int do_hbytes_pad(ClientData cd, Tcl_Interp *ip, const PadOp *op, + HBytes_Var v, Tcl_Obj *blocksz, const PadMethodInfo *meth, + int methargsc, Tcl_Obj *const *methargsv) { + PadMethodClientData pmcd; + int rc; - if (meth->use_algname) { + if (op->use_algname) { const BlockCipherAlgInfo *alg; - alg= enum_lookup_cached(ip,block,blockcipheralginfos,"cipher alg for pad"); + alg= enum_lookup_cached(ip,blocksz,blockcipheralginfos, + "blockcipher alg for pad"); if (!alg) return TCL_ERROR; - blocksize= alg->blocksize; + pmcd.blocksize= alg->blocksize; + } else { + rc= Tcl_GetIntFromObj(ip, blocksz, &pmcd.blocksize); if (rc) return rc; + if (pmcd.blocksize < 1) staticerr(ip, "block size must be at least 1", 0); + } + + pmcd.hb= v.hb; + pmcd.pad= op->pad; + + return meth->func(&pmcd,ip,methargsc,methargsv); +} + +int do_padmethodinfo_rfc2406(ClientData cd, Tcl_Interp *ip, + Tcl_Obj *nxthdr_arg, int *ok) { + const PadMethodClientData *pmcd= (const void*)cd; + int i, rc, padlen, old_len; + + if (pmcd->blocksize > 256) + return staticerr(ip, "block size too large for RFC2406 padding", 0); + + if (pmcd->pad) { + Byte *padding; + HBytes_Value nxthdr; + + rc= pat_hb(ip,nxthdr_arg,&nxthdr); + if (rc) return rc; + + if (hbytes_len(&nxthdr) != 1) return + staticerr(ip, "RFC2406 next header field must be exactly 1 byte", 0); + padlen= pmcd->blocksize-1 - ((hbytes_len(pmcd->hb)+1) % pmcd->blocksize); + padding= hbytes_append(pmcd->hb, padlen+2); + for (i=1; i<=padlen; i++) + *padding++ = i; + *padding++ = padlen; + *padding++ = hbytes_data(&nxthdr)[0]; + *ok= 1; + } else { - rc= Tcl_GetIntFromObj(ip, block, &blocksize); if (rc) return rc; - if (blocksize < 1 || blocksize > 255) - return staticerr(ip, "block size out of pkcs#5 range 1..255", 0); + const Byte *padding, *trailer; + HBytes_Value nxthdr; + Tcl_Obj *nxthdr_valobj, *ro; + + *ok= 0; + old_len= hbytes_len(pmcd->hb); if (old_len % pmcd->blocksize) goto quit; + trailer= hbytes_unappend(pmcd->hb, 2); if (!trailer) goto quit; + + padlen= trailer[0]; + hbytes_array(&nxthdr,trailer+1,1); + nxthdr_valobj= ret_hb(ip,nxthdr); + ro= Tcl_ObjSetVar2(ip,nxthdr_arg,0,nxthdr_valobj,TCL_LEAVE_ERR_MSG); + if (!ro) { Tcl_DecrRefCount(nxthdr_valobj); return TCL_ERROR; } + + padding= hbytes_unappend(pmcd->hb, padlen); + for (i=1; i<=padlen; i++) + if (*padding++ != i) goto quit; + + *ok= 1; + + quit: + } - if (meth->pad) { - padlen= blocksize - (hbytes_len(v.hb) % blocksize); - padding= hbytes_append(v.hb, padlen); + return TCL_OK; +} + +int do_padmethodinfo_pkcs5(ClientData cd, Tcl_Interp *ip, int *ok) { + const PadMethodClientData *pmcd= (const void*)cd; + int padlen, old_len, i; + + if (pmcd->blocksize > 255) + return staticerr(ip, "block size too large for pkcs#5", 0); + + if (pmcd->pad) { + + Byte *padding; + + padlen= pmcd->blocksize - (hbytes_len(pmcd->hb) % pmcd->blocksize); + padding= hbytes_append(pmcd->hb, padlen); memset(padding, padlen, padlen); + } else { - old_len= hbytes_len(v.hb); if (old_len % blocksize) goto bad; - unpad= hbytes_unappend(v.hb, 1); if (!unpad) goto bad; - padlen= *unpad; - if (padlen < 1 || padlen > blocksize) goto bad; - unpad= hbytes_unappend(v.hb, padlen-1); if (!unpad) goto bad; - for (i=0; ihb); if (old_len % pmcd->blocksize) goto bad; + padding= hbytes_unappend(pmcd->hb, 1); if (!padding) goto bad; + padlen= *padding; + if (padlen < 1 || padlen > pmcd->blocksize) goto bad; + padding= hbytes_unappend(pmcd->hb, padlen-1); if (!padding) goto bad; + + for (i=0; i worked? (always 1 for p) - * hbytes pkcs5 pn|un VAR BLOCKSIZE => worked? (always 1 for p) + * hbytes pad pa|ua VAR ALG METH [METHARGS] => worked? (always 1 for p) + * hbytes pad pn|un VAR BS METH [METHARGS] => worked? (always 1 for p) + * hbytes pad pa|pn VAR ALG|BS pkcs5 => 1 + * hbytes pad ua|un VAR ALG|BS pkcs5 => worked? + * hbytes pad pa|pn VAR ALG|BS rfc2406 NXTHDR => 1 + * hbytes pad ua|un VAR ALG|BS rfc2406 NXTHDRVAR => worked? + * * hbytes blockcipher d|e VAR ALG KEY MODE [IV] => IV * hbytes blockcipher mac MSG ALG KEY MODE IV => final block * hbytes blockcipher prop PROPERTY ALG => property value @@ -237,7 +242,7 @@ void memxor(Byte *dest, const Byte *src, int l); typedef struct { const char *name; int pad, use_algname; -} PadMethod; +} PadOp; extern Tcl_ObjType blockcipherkey_type; @@ -269,7 +274,6 @@ typedef struct { typedef struct { const char *name; int blocksize, schedule_size, key_min, key_max; - void (*byteswap)(void *block); BlockCipherPerDirectionInfo encrypt, decrypt; } BlockCipherAlgInfo; -- 2.30.2