XCBC mac added
[rofl0r-kripto.git] / lib / mac / xcbc.c
blob1e42a343c801c30b51a0eef9cae138a4995c422a
1 /*
2 * Written in 2013 by Gregor Pintar <grpintar@gmail.com>
4 * To the extent possible under law, the author(s) have dedicated
5 * all copyright and related and neighboring rights to this software
6 * to the public domain worldwide.
7 *
8 * This software is distributed without any warranty.
10 * You should have received a copy of the CC0 Public Domain Dedication.
11 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
14 #include <string.h>
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <assert.h>
19 #include <kripto/loadstore.h>
20 #include <kripto/memwipe.h>
21 #include <kripto/block.h>
22 #include <kripto/mac.h>
23 #include <kripto/desc/mac.h>
24 #include <kripto/object/mac.h>
26 #include <kripto/mac/xcbc.h>
28 struct kripto_mac
30 struct kripto_mac_object obj;
31 kripto_block *block;
32 uint8_t *buf;
33 uint8_t *k2;
34 uint8_t *k3;
35 unsigned int len;
36 unsigned int i;
37 int f;
40 static int xcbc_init(kripto_mac *s, unsigned int r)
42 unsigned int i;
44 /* key 1 */
45 for(i = 0; i < s->len; i++) s->buf[i] = 1;
46 kripto_block_encrypt(s->block, s->buf, s->buf);
48 /* key 2 */
49 for(i = 0; i < s->len; i++) s->k2[i] = 2;
50 kripto_block_encrypt(s->block, s->k2, s->k2);
52 /* key 3 */
53 for(i = 0; i < s->len; i++) s->k3[i] = 3;
54 kripto_block_encrypt(s->block, s->k3, s->k3);
56 s->block = kripto_block_recreate(s->block, r, s->buf, s->len);
57 if(!s->block) return -1;
59 memset(s->buf, 0, s->len);
60 s->i = 0;
61 s->f = 0;
63 return 0;
66 static void xcbc_input(kripto_mac *s, const void *in, size_t len)
68 size_t i;
70 for(i = 0; i < len; i++)
72 s->buf[s->i++] ^= CU8(in)[i];
74 if(s->i == s->len)
76 kripto_block_encrypt(s->block, s->buf, s->buf);
77 s->i = 0;
82 static void xcbc_tag(kripto_mac *s, void *tag, unsigned int len)
84 unsigned int i;
86 if(!s->f)
88 /* finish */
89 if(s->i)
91 /* pad */
92 s->buf[s->i] ^= 0x80;
94 /* key 3 */
95 for(i = 0; i < s->len; i++)
96 s->buf[i] ^= s->k3[i];
98 else
100 /* key 2 */
101 for(i = 0; i < s->len; i++)
102 s->buf[i] ^= s->k2[i];
105 kripto_block_encrypt(s->block, s->buf, s->buf);
106 s->i = 0;
107 s->f = -1;
110 /* output */
111 for(i = 0; i < len; i++)
113 assert(s->i < s->len);
114 U8(tag)[i] = s->buf[s->i++];
118 static void xcbc_destroy(kripto_mac *s)
120 kripto_block_destroy(s->block);
122 kripto_memwipe(s, sizeof(kripto_mac) + s->len * 3);
123 free(s);
126 struct ext
128 kripto_mac_desc desc;
129 const kripto_block_desc *block;
132 #define EXT(X) ((const struct ext *)(X))
134 static kripto_mac *xcbc_create
136 const kripto_mac_desc *desc,
137 unsigned int r,
138 const void *key,
139 unsigned int key_len,
140 unsigned int tag_len
143 kripto_mac *s;
145 (void)tag_len;
147 s = malloc(sizeof(kripto_mac) + desc->maxtag * 3);
148 if(!s) return 0;
150 s->obj.desc = desc;
151 s->len = desc->maxtag;
152 s->buf = (uint8_t *)s + sizeof(kripto_mac);
153 s->k2 = s->buf + s->len;
154 s->k3 = s->k2 + s->len;
155 s->block = kripto_block_create(EXT(desc)->block, r, key, key_len);
156 if(!s->block)
158 free(s);
159 return 0;
162 if(xcbc_init(s, r))
164 free(s);
165 return 0;
168 return s;
171 static kripto_mac *xcbc_recreate
173 kripto_mac *s,
174 unsigned int r,
175 const void *key,
176 unsigned int key_len,
177 unsigned int tag_len
180 (void)tag_len;
182 s->block = kripto_block_recreate(s->block, r, key, key_len);
183 if(!s->block) goto err;
185 if(xcbc_init(s, r)) goto err;
187 return s;
189 err:
190 kripto_memwipe(s, sizeof(kripto_mac) + s->obj.desc->maxtag * 3);
191 free(s);
192 return 0;
195 kripto_mac_desc *kripto_mac_xcbc(const kripto_block_desc *block)
197 struct ext *s;
199 s = malloc(sizeof(struct ext));
200 if(!s) return 0;
202 s->block = block;
204 s->desc.create = &xcbc_create;
205 s->desc.recreate = &xcbc_recreate;
206 s->desc.input = &xcbc_input;
207 s->desc.tag = &xcbc_tag;
208 s->desc.destroy = &xcbc_destroy;
209 s->desc.maxtag = kripto_block_size(block);
210 s->desc.maxkey = kripto_block_maxkey(block);
212 return (kripto_mac_desc *)s;