X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=crypto%2Fbcmode.c;h=e413de72e78677b8af9ff57b91693fc651e405e7;hp=7d5a5d4f6ea500e03835393f79b61e9470b36147;hb=79afa3a523e92a1d552d46729b1e1d04db97f72c;hpb=9b7d11070d3e9dc1eb61cbccd5155f47a27047c3 diff --git a/crypto/bcmode.c b/crypto/bcmode.c index 7d5a5d4..e413de7 100644 --- a/crypto/bcmode.c +++ b/crypto/bcmode.c @@ -3,50 +3,117 @@ #include "hbytes.h" -const char *mode_cbc_encrypt(Byte *data, int blocks, - const Byte *iv, Byte *chain, - const BlockCipherAlgInfo *alg, int encr, - int blocksize, const void *sch) { +static const char *mode_cbc_encrypt(Byte *data, int blocks, + const Byte *iv, Byte *chain, + const BlockCipherAlgInfo *alg, int encr, + const void *sch) { + int blocksize= alg->blocksize; memcpy(chain,iv,blocksize); - alg->byteswap(chain); while (blocks > 0) { - alg->byteswap(data); - memxor(data, chain, blocksize); alg->encrypt.crypt(sch, data, data); memcpy(chain, data, blocksize); - alg->byteswap(data); blocks--; data += blocksize; } return 0; } -const char *mode_cbc_decrypt(Byte *data, int blocks, - const Byte *iv, Byte *chain, - const BlockCipherAlgInfo *alg, int encr, - int blocksize, const void *sch) { +static const char *mode_cbc_decrypt(Byte *data, int blocks, + const Byte *iv, Byte *chain, + const BlockCipherAlgInfo *alg, int encr, + const void *sch) { + int blocksize= alg->blocksize; int cchain= 0; memcpy(chain,iv,blocksize); - alg->byteswap(chain); while (blocks > 0) { - alg->byteswap(data); - memcpy(chain + (cchain^blocksize), data, blocksize); alg->decrypt.crypt(sch, data, data); memxor(data, chain + cchain, blocksize); cchain ^= blocksize; - alg->byteswap(data); blocks--; data += blocksize; } return 0; } +static void cbcmac_core(const Byte *data, int blocks, + const Byte *iv, Byte *buf, + const BlockCipherAlgInfo *alg, + const void *sch) { + int blocksize= alg->blocksize; + + memcpy(buf,iv,blocksize); + + while (blocks > 0) { + memcpy(buf + blocksize, data, blocksize); + memxor(buf, buf + blocksize, blocksize); + + alg->encrypt.crypt(sch, buf, buf); + + blocks--; data += blocksize; + } +} + +static const char *mode_cbc_mac(const Byte *data, int blocks, + const Byte *iv, Byte *buf, + const BlockCipherAlgInfo *alg, + const void *sch) { + cbcmac_core(data,blocks,iv,buf,alg,sch); + return 0; +} + +static const char *mode_cbc_mac2(const Byte *data, int blocks, + const Byte *iv, Byte *buf, + const BlockCipherAlgInfo *alg, + const void *sch) { + cbcmac_core(data,blocks,iv,buf,alg,sch); + alg->encrypt.crypt(sch, buf, buf); + return 0; +} + +static const char *mode_ecb(Byte *data, int blocks, + const Byte *iv, Byte *chain, + const BlockCipherAlgInfo *alg, int encr, + const void *sch) { + int blocksize= alg->blocksize; + + while (blocks > 0) { + (encr ? &alg->encrypt : &alg->decrypt)->crypt(sch, data, 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, mode_cbc_encrypt, mode_cbc_decrypt }, + { "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 } };