better standard compliance
[rofl0r-kripto.git] / lib / block / speck128.c
blob2ac0016fe665fc9db07f1255273203dd44051222
1 /*
2 * Copyright (C) 2013 Gregor Pintar <grpintar@gmail.com>
4 * Permission is granted to deal in this work without any restriction,
5 * including unlimited rights to use, publicly perform, publish,
6 * reproduce, relicence, modify, merge, and/or distribute in any form,
7 * for any purpose, with or without fee, and by any means.
9 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind,
10 * to the utmost extent permitted by applicable law. In no event
11 * shall a licensor, author or contributor be held liable for any
12 * issues arising in any way out of dealing in the work.
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <limits.h>
19 #include <kripto/cast.h>
20 #include <kripto/loadstore.h>
21 #include <kripto/rotate.h>
22 #include <kripto/memwipe.h>
23 #include <kripto/block.h>
24 #include <kripto/desc/block.h>
25 #include <kripto/object/block.h>
27 #include <kripto/block/speck128.h>
29 struct kripto_block
31 struct kripto_block_object obj;
32 unsigned int rounds;
33 size_t size;
34 uint64_t *k;
37 #define R(A, B, K) \
38 { \
39 A = (ROR64(A, 8) + B) ^ K; \
40 B = ROL64(B, 3) ^ A; \
43 #define IR(A, B, K) \
44 { \
45 B = ROR64(B ^ A, 3); \
46 A = ROL64((A ^ K) - B, 8); \
49 static void speck128_encrypt
51 const kripto_block *s,
52 const void *pt,
53 void *ct
56 uint64_t a;
57 uint64_t b;
58 unsigned int i;
60 a = LOAD64B(CU8(pt));
61 b = LOAD64B(CU8(pt) + 8);
63 for(i = 0; i < s->rounds; i++)
64 R(a, b, s->k[i]);
66 STORE64B(a, U8(ct));
67 STORE64B(b, U8(ct) + 8);
70 static void speck128_decrypt
72 const kripto_block *s,
73 const void *ct,
74 void *pt
77 uint64_t a;
78 uint64_t b;
79 unsigned int i;
81 a = LOAD64B(CU8(ct));
82 b = LOAD64B(CU8(ct) + 8);
84 for(i = s->rounds; i--;)
85 IR(a, b, s->k[i]);
87 STORE64B(a, U8(pt));
88 STORE64B(b, U8(pt) + 8);
91 static void speck128_setup
93 kripto_block *s,
94 const uint8_t *key,
95 unsigned int len
98 unsigned int i;
99 unsigned int m;
100 uint64_t k[4] = {0, 0, 0, 0};
102 m = ((len + 7) >> 3) - 1;
104 for(i = 0; i < len; i++)
105 k[m - (i >> 3)] |= (uint64_t)key[i] << (56 - ((i & 7) << 3));
107 s->k[0] = k[0];
109 for(i = 0; i < s->rounds - 1;)
111 R(k[(i % m) + 1], k[0], i);
112 s->k[++i] = k[0];
115 kripto_memwipe(k, 32);
118 static kripto_block *speck128_create
120 unsigned int r,
121 const void *key,
122 unsigned int key_len
125 kripto_block *s;
127 if(!r) r = 30 + ((key_len + 7) >> 3);
129 s = malloc(sizeof(kripto_block) + (r << 3));
130 if(!s) return 0;
132 s->obj.desc = kripto_block_speck128;
133 s->size = sizeof(kripto_block) + (r << 3);
134 s->k = (uint64_t *)(((uint8_t *)s) + sizeof(kripto_block));
135 s->rounds = r;
137 speck128_setup(s, key, key_len);
139 return s;
142 static void speck128_destroy(kripto_block *s)
144 kripto_memwipe(s, s->size);
145 free(s);
148 static kripto_block *speck128_recreate
150 kripto_block *s,
151 unsigned int r,
152 const void *key,
153 unsigned int key_len
156 if(!r) r = 30 + ((key_len + 7) >> 3);
158 if(sizeof(kripto_block) + (r << 3) > s->size)
160 speck128_destroy(s);
161 s = speck128_create(r, key, key_len);
163 else
165 s->rounds = r;
166 speck128_setup(s, key, key_len);
169 return s;
172 static const kripto_block_desc speck128 =
174 &speck128_create,
175 &speck128_recreate,
177 &speck128_encrypt,
178 &speck128_decrypt,
179 &speck128_destroy,
180 16, /* block size */
181 32 /* max key */
184 const kripto_block_desc *const kripto_block_speck128 = &speck128;