chiark / gitweb /
changelog: start 1.3.2
[chiark-tcl.git] / crypto / bcmode.c
1 /*
2  * crypto - Tcl bindings for parts of the `nettle' crypto library
3  * Copyright 2006-2012 Ian Jackson
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this library; if not, see <http://www.gnu.org/licenses/>.
17  */
18
19   
20 #include "chiark_tcl_crypto.h"
21
22 static const char *mode_cbc_encrypt(Byte *data, int blocks,
23                                     const Byte *iv, Byte *chain,
24                                     const BlockCipherAlgInfo *alg, int encr,
25                                     const void *sch) {
26   int blocksize= alg->blocksize;
27   memcpy(chain,iv,blocksize);
28   
29   while (blocks > 0) {
30     memxor(data, chain, blocksize);
31     alg->encrypt.crypt(sch, data, data);
32     memcpy(chain, data, blocksize);
33
34     blocks--; data += blocksize;
35   }
36   return 0;
37 }
38
39 static const char *mode_cbc_decrypt(Byte *data, int blocks,
40                                     const Byte *iv, Byte *chain,
41                                     const BlockCipherAlgInfo *alg, int encr,
42                                     const void *sch) {
43   int blocksize= alg->blocksize;
44   int cchain= 0;
45
46   memcpy(chain,iv,blocksize);
47   
48   while (blocks > 0) {
49     memcpy(chain + (cchain^blocksize), data, blocksize);
50     alg->decrypt.crypt(sch, data, data);
51     memxor(data, chain + cchain, blocksize);
52     cchain ^= blocksize;
53
54     blocks--; data += blocksize;
55   }
56   return 0;
57 }
58
59 static void cbcmac_core(const Byte *data, int blocks,
60                         const Byte *iv, Byte *buf,
61                         const BlockCipherAlgInfo *alg,
62                         const void *sch) {
63   int blocksize= alg->blocksize;
64
65   memcpy(buf,iv,blocksize);
66   
67   while (blocks > 0) {
68     memcpy(buf + blocksize, data, blocksize);
69     memxor(buf, buf + blocksize, blocksize);
70     
71     alg->encrypt.crypt(sch, buf, buf);
72
73     blocks--; data += blocksize;
74   }
75 }  
76
77 static const char *mode_cbc_mac(const Byte *data, int blocks,
78                                 const Byte *iv, Byte *buf,
79                                 const BlockCipherAlgInfo *alg,
80                                 const void *sch) {
81   cbcmac_core(data,blocks,iv,buf,alg,sch);
82   return 0;
83 }
84
85 static const char *mode_cbc_mac2(const Byte *data, int blocks,
86                                  const Byte *iv, Byte *buf,
87                                  const BlockCipherAlgInfo *alg,
88                                  const void *sch) {
89   cbcmac_core(data,blocks,iv,buf,alg,sch);
90   alg->encrypt.crypt(sch, buf, buf);
91   return 0;
92 }
93
94 static const char *mode_ecb(Byte *data, int blocks,
95                             const Byte *iv, Byte *chain,
96                             const BlockCipherAlgInfo *alg, int encr,
97                             const void *sch) {
98   int blocksize= alg->blocksize;
99   
100   while (blocks > 0) {
101     (encr ? &alg->encrypt : &alg->decrypt)->crypt(sch, data, data);
102     blocks--; data += blocksize;
103   }
104   return 0;
105 }
106
107 static const char *mode_ctr(Byte *data, int blocks,
108                             const Byte *iv, Byte *counter,
109                             const BlockCipherAlgInfo *alg, int encr,
110                             const void *sch) {
111   int blocksize= alg->blocksize;
112   Byte *cipher= counter + blocksize;
113   int byte;
114
115   memcpy(counter, iv, blocksize);
116   while (blocks > 0) {
117     alg->encrypt.crypt(sch, counter, cipher);
118     memxor(data, cipher, blocksize);
119     for (byte=blocksize-1; byte>=0; byte--) {
120       if (++counter[byte]) break;
121       /* new value of zero implies carry, so increment next byte */
122     }
123     blocks--;
124     data += blocksize;
125   }
126   return 0;
127 }
128
129 const BlockCipherModeInfo cht_blockciphermodeinfo_entries[]= {
130   { "cbc",      1, 2, 1, mode_cbc_encrypt, mode_cbc_decrypt, mode_cbc_mac  },
131   { "cbc-mac2", 1, 2, 1, 0,                0,                mode_cbc_mac2 },
132   { "ecb",      0, 0, 0, mode_ecb,         mode_ecb,         0             },
133   { "ctr-sif",  1, 2, 0, mode_ctr,         mode_ctr,         0             },
134   { 0 }
135 };