status update, probably last commit
[rofl0r-kripto.git] / lib / stream / ctr.c
blob4ff5897d70cffe144fbd7fdc9a4b292bdbc0885a
1 /*
2 * Written in 2011 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 <stdint.h>
15 #include <string.h>
16 #include <stdlib.h>
18 #include <kripto/cast.h>
19 #include <kripto/memwipe.h>
20 #include <kripto/block.h>
21 #include <kripto/stream.h>
22 #include <kripto/desc/stream.h>
23 #include <kripto/object/stream.h>
25 #include <kripto/stream/ctr.h>
27 struct kripto_stream
29 struct kripto_stream_object obj;
30 kripto_block *block;
31 uint8_t *x;
32 uint8_t *buf;
33 unsigned int blocksize;
34 unsigned int used;
37 static void ctr_crypt
39 kripto_stream *s,
40 const void *in,
41 void *out,
42 size_t len
45 size_t i;
46 unsigned int n;
48 for(i = 0; i < len; i++)
50 if(s->used == s->blocksize)
52 kripto_block_encrypt(s->block, s->x, s->buf);
53 s->used = 0;
55 for(n = s->blocksize - 1; n; n--)
56 if(++s->x[n]) break;
59 U8(out)[i] = CU8(in)[i] ^ s->buf[s->used++];
63 static void ctr_prng
65 kripto_stream *s,
66 void *out,
67 size_t len
70 size_t i;
71 unsigned int n;
73 for(i = 0; i < len; i++)
75 if(s->used == s->blocksize)
77 kripto_block_encrypt(s->block, s->x, s->buf);
78 s->used = 0;
80 for(n = s->blocksize - 1; n; n--)
81 if(++s->x[n]) break;
84 U8(out)[i] = s->buf[s->used++];
88 static void ctr_destroy(kripto_stream *s)
90 kripto_block_destroy(s->block);
91 kripto_memwipe(s, sizeof(kripto_stream) + (s->blocksize << 1));
92 free(s);
95 struct ext
97 kripto_stream_desc desc;
98 const kripto_block_desc *block;
101 #define EXT(X) ((const struct ext *)(X))
103 static kripto_stream *ctr_create
105 const kripto_stream_desc *desc,
106 unsigned int rounds,
107 const void *key,
108 unsigned int key_len,
109 const void *iv,
110 unsigned int iv_len
113 kripto_stream *s;
115 s = malloc(sizeof(kripto_stream) + (desc->maxiv << 1));
116 if(!s) return 0;
118 s->obj.desc = desc;
119 s->obj.multof = 1;
121 s->used = s->blocksize = desc->maxiv;
123 s->x = (uint8_t *)s + sizeof(kripto_stream);
124 s->buf = s->x + s->blocksize;
126 /* block cipher */
127 s->block = kripto_block_create(EXT(desc)->block, rounds, key, key_len);
128 if(!s->block)
130 kripto_memwipe(s, sizeof(kripto_stream) + (s->blocksize << 1));
131 free(s);
132 return 0;
135 /* IV (nonce) */
136 if(iv_len) memcpy(s->x, iv, iv_len);
137 memset(s->x + iv_len, 0, s->blocksize - iv_len);
139 return s;
142 static kripto_stream *ctr_recreate
144 kripto_stream *s,
145 unsigned int rounds,
146 const void *key,
147 unsigned int key_len,
148 const void *iv,
149 unsigned int iv_len
152 /* block cipher */
153 s->block = kripto_block_recreate(s->block, rounds, key, key_len);
154 if(!s->block)
156 kripto_memwipe(s, sizeof(kripto_stream) + (s->blocksize << 1));
157 free(s);
158 return 0;
161 /* IV (nonce) */
162 if(iv_len) memcpy(s->x, iv, iv_len);
163 memset(s->x + iv_len, 0, s->blocksize - iv_len);
165 s->used = s->blocksize;
167 return s;
170 kripto_stream_desc *kripto_stream_ctr(const kripto_block_desc *block)
172 struct ext *s;
174 s = malloc(sizeof(struct ext));
175 if(!s) return 0;
177 s->block = block;
179 s->desc.create = &ctr_create;
180 s->desc.recreate = &ctr_recreate;
181 s->desc.encrypt = &ctr_crypt;
182 s->desc.decrypt = &ctr_crypt;
183 s->desc.prng = &ctr_prng;
184 s->desc.destroy = &ctr_destroy;
185 s->desc.maxkey = kripto_block_maxkey(block);
186 s->desc.maxiv = kripto_block_size(block);
188 return (kripto_stream_desc *)s;