chiark / gitweb /
Debian package wip
[chiark-tcl.git] / crypto / bcmode.c
1 /*
2  * crypto - Tcl bindings for parts of the `nettle' crypto library
3  * Copyright 2006 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, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301, USA.
19  */
20
21   
22 #include "chiark_tcl_crypto.h"
23
24 static const char *mode_cbc_encrypt(Byte *data, int blocks,
25                                     const Byte *iv, Byte *chain,
26                                     const BlockCipherAlgInfo *alg, int encr,
27                                     const void *sch) {
28   int blocksize= alg->blocksize;
29   memcpy(chain,iv,blocksize);
30   
31   while (blocks > 0) {
32     memxor(data, chain, blocksize);
33     alg->encrypt.crypt(sch, data, data);
34     memcpy(chain, data, blocksize);
35
36     blocks--; data += blocksize;
37   }
38   return 0;
39 }
40
41 static const char *mode_cbc_decrypt(Byte *data, int blocks,
42                                     const Byte *iv, Byte *chain,
43                                     const BlockCipherAlgInfo *alg, int encr,
44                                     const void *sch) {
45   int blocksize= alg->blocksize;
46   int cchain= 0;
47
48   memcpy(chain,iv,blocksize);
49   
50   while (blocks > 0) {
51     memcpy(chain + (cchain^blocksize), data, blocksize);
52     alg->decrypt.crypt(sch, data, data);
53     memxor(data, chain + cchain, blocksize);
54     cchain ^= blocksize;
55
56     blocks--; data += blocksize;
57   }
58   return 0;
59 }
60
61 static void cbcmac_core(const Byte *data, int blocks,
62                         const Byte *iv, Byte *buf,
63                         const BlockCipherAlgInfo *alg,
64                         const void *sch) {
65   int blocksize= alg->blocksize;
66
67   memcpy(buf,iv,blocksize);
68   
69   while (blocks > 0) {
70     memcpy(buf + blocksize, data, blocksize);
71     memxor(buf, buf + blocksize, blocksize);
72     
73     alg->encrypt.crypt(sch, buf, buf);
74
75     blocks--; data += blocksize;
76   }
77 }  
78
79 static const char *mode_cbc_mac(const Byte *data, int blocks,
80                                 const Byte *iv, Byte *buf,
81                                 const BlockCipherAlgInfo *alg,
82                                 const void *sch) {
83   cbcmac_core(data,blocks,iv,buf,alg,sch);
84   return 0;
85 }
86
87 static const char *mode_cbc_mac2(const Byte *data, int blocks,
88                                  const Byte *iv, Byte *buf,
89                                  const BlockCipherAlgInfo *alg,
90                                  const void *sch) {
91   cbcmac_core(data,blocks,iv,buf,alg,sch);
92   alg->encrypt.crypt(sch, buf, buf);
93   return 0;
94 }
95
96 static const char *mode_ecb(Byte *data, int blocks,
97                             const Byte *iv, Byte *chain,
98                             const BlockCipherAlgInfo *alg, int encr,
99                             const void *sch) {
100   int blocksize= alg->blocksize;
101   
102   while (blocks > 0) {
103     (encr ? &alg->encrypt : &alg->decrypt)->crypt(sch, data, data);
104     blocks--; data += blocksize;
105   }
106   return 0;
107 }
108
109 static const char *mode_ctr(Byte *data, int blocks,
110                             const Byte *iv, Byte *counter,
111                             const BlockCipherAlgInfo *alg, int encr,
112                             const void *sch) {
113   int blocksize= alg->blocksize;
114   Byte *cipher= counter + blocksize;
115   int byte;
116
117   memcpy(counter, iv, blocksize);
118   while (blocks > 0) {
119     alg->encrypt.crypt(sch, counter, cipher);
120     memxor(data, cipher, blocksize);
121     for (byte=blocksize-1; byte>=0; byte--) {
122       if (++counter[byte]) break;
123       /* new value of zero implies carry, so increment next byte */
124     }
125     blocks--;
126     data += blocksize;
127   }
128   return 0;
129 }
130
131 const BlockCipherModeInfo cht_blockciphermodeinfo_entries[]= {
132   { "cbc",      1, 2, 1, mode_cbc_encrypt, mode_cbc_decrypt, mode_cbc_mac  },
133   { "cbc-mac2", 1, 2, 1, 0,                0,                mode_cbc_mac2 },
134   { "ecb",      0, 0, 0, mode_ecb,         mode_ecb,         0             },
135   { "ctr-sif",  1, 2, 0, mode_ctr,         mode_ctr,         0             },
136   { 0 }
137 };