chiark / gitweb /
New blockcipher mac stuff. New hbytes clockincrement.
[chiark-tcl.git] / crypto / bcmode.c
1 /*
2  */
3   
4 #include "hbytes.h"
5
6 static const char *mode_cbc_encrypt(Byte *data, int blocks,
7                                     const Byte *iv, Byte *chain,
8                                     const BlockCipherAlgInfo *alg, int encr,
9                                     const void *sch) {
10   int blocksize= alg->blocksize;
11   memcpy(chain,iv,blocksize);
12   alg->byteswap(chain);
13   
14   while (blocks > 0) {
15     alg->byteswap(data);
16
17     memxor(data, chain, blocksize);
18     alg->encrypt.crypt(sch, data, data);
19     memcpy(chain, data, blocksize);
20
21     alg->byteswap(data);
22     blocks--; data += blocksize;
23   }
24   return 0;
25 }
26
27 static const char *mode_cbc_decrypt(Byte *data, int blocks,
28                                     const Byte *iv, Byte *chain,
29                                     const BlockCipherAlgInfo *alg, int encr,
30                                     const void *sch) {
31   int blocksize= alg->blocksize;
32   int cchain= 0;
33
34   memcpy(chain,iv,blocksize);
35   alg->byteswap(chain);
36   
37   while (blocks > 0) {
38     alg->byteswap(data);
39     
40     memcpy(chain + (cchain^blocksize), data, blocksize);
41     alg->decrypt.crypt(sch, data, data);
42     memxor(data, chain + cchain, blocksize);
43     cchain ^= blocksize;
44
45     alg->byteswap(data);
46     blocks--; data += blocksize;
47   }
48   return 0;
49 }
50
51 static void cbcmac_core(const Byte *data, int blocks,
52                         const Byte *iv, Byte *buf,
53                         const BlockCipherAlgInfo *alg,
54                         const void *sch) {
55   int blocksize= alg->blocksize;
56
57   memcpy(buf,iv,blocksize);
58   alg->byteswap(buf);
59   
60   while (blocks > 0) {
61     memcpy(buf + blocksize, data, blocksize);
62     alg->byteswap(buf + blocksize);
63     memxor(buf, buf + blocksize, blocksize);
64     
65     alg->encrypt.crypt(sch, buf, buf);
66
67     blocks--; data += blocksize;
68   }
69 }  
70
71 static const char *mode_cbc_mac(const Byte *data, int blocks,
72                                 const Byte *iv, Byte *buf,
73                                 const BlockCipherAlgInfo *alg,
74                                 const void *sch) {
75   cbcmac_core(data,blocks,iv,buf,alg,sch);
76   alg->byteswap(buf);
77   return 0;
78 }
79
80 static const char *mode_cbc_mac2(const Byte *data, int blocks,
81                                  const Byte *iv, Byte *buf,
82                                  const BlockCipherAlgInfo *alg,
83                                  const void *sch) {
84   cbcmac_core(data,blocks,iv,buf,alg,sch);
85   alg->encrypt.crypt(sch, buf, buf);
86   alg->byteswap(buf);
87   return 0;
88 }
89
90 static const char *mode_ecb(Byte *data, int blocks,
91                             const Byte *iv, Byte *chain,
92                             const BlockCipherAlgInfo *alg, int encr,
93                             const void *sch) {
94   int blocksize= alg->blocksize;
95   
96   while (blocks > 0) {
97     alg->byteswap(data);
98     (encr ? &alg->encrypt : &alg->decrypt)->crypt(sch, data, data);
99     alg->byteswap(data);
100     blocks--; data += blocksize;
101   }
102   return 0;
103 }
104
105 const BlockCipherModeInfo blockciphermodeinfos[]= {
106   { "cbc",      1, 2, 1, mode_cbc_encrypt, mode_cbc_decrypt, mode_cbc_mac  },
107   { "cbc-mac2", 1, 2, 1, 0,                0,                mode_cbc_mac2 },
108   { "ecb",      0, 0, 0, mode_ecb,         mode_ecb,         0             },
109   { 0 }
110 };