Skinny-C
 All Data Structures Files Functions Variables Groups Pages
skinny128-ctr.c
1 /*
2  * Copyright (C) 2017 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "skinny128-cipher.h"
24 #include "skinny128-ctr-internal.h"
25 #include "skinny-internal.h"
26 #include <stdlib.h>
27 
29 typedef struct
30 {
33 
35  unsigned char counter[SKINNY128_BLOCK_SIZE];
36 
38  unsigned char ecounter[SKINNY128_BLOCK_SIZE];
39 
41  unsigned offset;
42 
44 
45 static int skinny128_ctr_def_init(Skinny128CTR_t *ctr)
46 {
47  Skinny128CTRCtx_t *ctx;
48  if ((ctx = calloc(1, sizeof(Skinny128CTRCtx_t))) == NULL)
49  return 0;
51  ctr->ctx = ctx;
52  return 1;
53 }
54 
55 static void skinny128_ctr_def_cleanup(Skinny128CTR_t *ctr)
56 {
57  if (ctr->ctx) {
58  skinny_cleanse(ctr->ctx, sizeof(Skinny128CTRCtx_t));
59  free(ctr->ctx);
60  ctr->ctx = 0;
61  }
62 }
63 
64 static int skinny128_ctr_def_set_key(Skinny128CTR_t *ctr, const void *key, unsigned size)
65 {
66  Skinny128CTRCtx_t *ctx;
67 
68  /* Validate the parameters */
69  if (!key)
70  return 0;
71  ctx = ctr->ctx;
72  if (!ctx)
73  return 0;
74 
75  /* Populate the underlying key schedule */
76  if (!skinny128_set_key(&(ctx->kt.ks), key, size))
77  return 0;
78 
79  /* Reset the keystream */
81  return 1;
82 }
83 
84 static int skinny128_ctr_def_set_tweaked_key
85  (Skinny128CTR_t *ctr, const void *key, unsigned key_size)
86 {
87  Skinny128CTRCtx_t *ctx;
88 
89  /* Validate the parameters */
90  if (!key)
91  return 0;
92  ctx = ctr->ctx;
93  if (!ctx)
94  return 0;
95 
96  /* Populate the underlying key schedule */
97  if (!skinny128_set_tweaked_key(&(ctx->kt), key, key_size))
98  return 0;
99 
100  /* Reset the keystream */
102  return 1;
103 }
104 
105 static int skinny128_ctr_def_set_tweak
106  (Skinny128CTR_t *ctr, const void *tweak, unsigned tweak_size)
107 {
108  Skinny128CTRCtx_t *ctx;
109 
110  /* Validate the parameters */
111  ctx = ctr->ctx;
112  if (!ctx)
113  return 0;
114 
115  /* Populate the underlying tweak */
116  if (!skinny128_set_tweak(&(ctx->kt), tweak, tweak_size))
117  return 0;
118 
119  /* Reset the keystream */
121  return 1;
122 }
123 
124 static int skinny128_ctr_def_set_counter
125  (Skinny128CTR_t *ctr, const void *counter, unsigned size)
126 {
127  Skinny128CTRCtx_t *ctx;
128 
129  /* Validate the parameters */
130  if (size > SKINNY128_BLOCK_SIZE)
131  return 0;
132  ctx = ctr->ctx;
133  if (!ctx)
134  return 0;
135 
136  /* Set the counter and reset the keystream to a block boundary */
137  if (counter) {
138  memset(ctx->counter, 0, SKINNY128_BLOCK_SIZE - size);
139  memcpy(ctx->counter + SKINNY128_BLOCK_SIZE - size, counter, size);
140  } else {
141  memset(ctx->counter, 0, SKINNY128_BLOCK_SIZE);
142  }
144  return 1;
145 }
146 
147 static int skinny128_ctr_def_encrypt
148  (void *output, const void *input, size_t size, Skinny128CTR_t *ctr)
149 {
150  Skinny128CTRCtx_t *ctx;
151  uint8_t *out = (uint8_t *)output;
152  const uint8_t *in = (const uint8_t *)input;
153 
154  /* Validate the parameters */
155  if (!output || !input)
156  return 0;
157  ctx = ctr->ctx;
158  if (!ctx)
159  return 0;
160 
161  /* Encrypt the input in CTR mode to create the output */
162  while (size > 0) {
163  if (ctx->offset >= SKINNY128_BLOCK_SIZE) {
164  /* We need a new keystream block */
165  skinny128_ecb_encrypt(ctx->ecounter, ctx->counter, &(ctx->kt.ks));
166  skinny128_inc_counter(ctx->counter, 1);
167 
168  /* XOR an entire keystream block in one go if possible */
169  if (size >= SKINNY128_BLOCK_SIZE) {
170  skinny128_xor(out, in, ctx->ecounter);
171  out += SKINNY128_BLOCK_SIZE;
172  in += SKINNY128_BLOCK_SIZE;
173  size -= SKINNY128_BLOCK_SIZE;
174  } else {
175  /* Last partial block in the request */
176  skinny_xor(out, in, ctx->ecounter, size);
177  ctx->offset = size;
178  break;
179  }
180  } else {
181  /* Left-over keystream data from the last request */
182  size_t temp = SKINNY128_BLOCK_SIZE - ctx->offset;
183  if (temp > size)
184  temp = size;
185  skinny_xor(out, in, ctx->ecounter + ctx->offset, temp);
186  ctx->offset += temp;
187  out += temp;
188  in += temp;
189  size -= temp;
190  }
191  }
192  return 1;
193 }
194 
196 static Skinny128CTRVtable_t const skinny128_ctr_def = {
197  skinny128_ctr_def_init,
198  skinny128_ctr_def_cleanup,
199  skinny128_ctr_def_set_key,
200  skinny128_ctr_def_set_tweaked_key,
201  skinny128_ctr_def_set_tweak,
202  skinny128_ctr_def_set_counter,
203  skinny128_ctr_def_encrypt
204 };
205 
206 /* Public API, which redirects to the specific backend implementation */
207 
209 {
210  const Skinny128CTRVtable_t *vtable;
211 
212  /* Validate the parameter */
213  if (!ctr)
214  return 0;
215 
216  /* Choose a backend implementation */
217  vtable = &skinny128_ctr_def;
218  if (_skinny_has_vec128())
219  vtable = &_skinny128_ctr_vec128;
220  if (_skinny_has_vec256())
221  vtable = &_skinny128_ctr_vec256;
222  ctr->vtable = vtable;
223 
224  /* Initialize the CTR mode context */
225  return (*(vtable->init))(ctr);
226 }
227 
229 {
230  if (ctr && ctr->vtable) {
231  const Skinny128CTRVtable_t *vtable = ctr->vtable;
232  (*(vtable->cleanup))(ctr);
233  ctr->vtable = 0;
234  }
235 }
236 
237 int skinny128_ctr_set_key(Skinny128CTR_t *ctr, const void *key, unsigned size)
238 {
239  if (ctr && ctr->vtable) {
240  const Skinny128CTRVtable_t *vtable = ctr->vtable;
241  return (*(vtable->set_key))(ctr, key, size);
242  }
243  return 0;
244 }
245 
247  (Skinny128CTR_t *ctr, const void *key, unsigned key_size)
248 {
249  if (ctr && ctr->vtable) {
250  const Skinny128CTRVtable_t *vtable = ctr->vtable;
251  return (*(vtable->set_tweaked_key))(ctr, key, key_size);
252  }
253  return 0;
254 }
255 
257  (Skinny128CTR_t *ctr, const void *tweak, unsigned tweak_size)
258 {
259  if (ctr && ctr->vtable) {
260  const Skinny128CTRVtable_t *vtable = ctr->vtable;
261  return (*(vtable->set_tweak))(ctr, tweak, tweak_size);
262  }
263  return 0;
264 }
265 
267  (Skinny128CTR_t *ctr, const void *counter, unsigned size)
268 {
269  if (ctr && ctr->vtable) {
270  const Skinny128CTRVtable_t *vtable = ctr->vtable;
271  return (*(vtable->set_counter))(ctr, counter, size);
272  }
273  return 0;
274 }
275 
277  (void *output, const void *input, size_t size, Skinny128CTR_t *ctr)
278 {
279  if (ctr && ctr->vtable) {
280  const Skinny128CTRVtable_t *vtable = ctr->vtable;
281  return (*(vtable->encrypt))(output, input, size, ctr);
282  }
283  return 0;
284 }
State information for Skinny-128 in CTR mode.
int skinny128_ctr_set_key(Skinny128CTR_t *ctr, const void *key, unsigned size)
Sets the key schedule for a Skinny128 block cipher in CTR mode.
Key schedule for Skinny128 block ciphers when a tweak is in use.
int skinny128_ctr_encrypt(void *output, const void *input, size_t size, Skinny128CTR_t *ctr)
Encrypt a block of data using Skinny-128 in CTR mode.
const void * vtable
int skinny128_set_tweaked_key(Skinny128TweakedKey_t *ks, const void *key, unsigned key_size)
Sets the key schedule for a Skinny128 block cipher, and prepare for tweaked encryption.
int skinny128_ctr_set_tweak(Skinny128CTR_t *ctr, const void *tweak, unsigned tweak_size)
Changes the tweak value for a previously-initialized key schedule.
void skinny128_ecb_encrypt(void *output, const void *input, const Skinny128Key_t *ks)
Encrypts a single block using the Skinny128 block cipher in ECB mode.
Skinny128TweakedKey_t kt
Definition: skinny128-ctr.c:32
unsigned char ecounter[SKINNY128_BLOCK_SIZE]
Definition: skinny128-ctr.c:38
int skinny128_set_key(Skinny128Key_t *ks, const void *key, unsigned size)
Sets the key schedule for a Skinny128 block cipher.
int skinny128_ctr_init(Skinny128CTR_t *ctr)
Initializes Skinny-128 in CTR mode.
#define SKINNY128_BLOCK_SIZE
Size of a block for Skinny128 block ciphers.
int skinny128_ctr_set_counter(Skinny128CTR_t *ctr, const void *counter, unsigned size)
Sets the counter value in a Skinny-128 CTR control block.
unsigned char counter[SKINNY128_BLOCK_SIZE]
Definition: skinny128-ctr.c:35
int skinny128_set_tweak(Skinny128TweakedKey_t *ks, const void *tweak, unsigned tweak_size)
Changes the tweak value for a previously-initialized key schedule.
int skinny128_ctr_set_tweaked_key(Skinny128CTR_t *ctr, const void *key, unsigned key_size)
Sets the key schedule for a Skinny128 block cipher in CTR mode, and prepare for tweaked encryption...
void skinny128_ctr_cleanup(Skinny128CTR_t *ctr)
Cleans up a CTR control block for Skinny-128.