Skinny-C
 All Data Structures Files Functions Variables Groups Pages
skinny64-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 "skinny64-cipher.h"
24 #include "skinny64-ctr-internal.h"
25 #include "skinny-internal.h"
26 #include <stdlib.h>
27 
29 typedef struct
30 {
33 
35  unsigned char counter[SKINNY64_BLOCK_SIZE];
36 
38  unsigned char ecounter[SKINNY64_BLOCK_SIZE];
39 
41  unsigned offset;
42 
44 
45 static int skinny64_ctr_def_init(Skinny64CTR_t *ctr)
46 {
47  Skinny64CTRCtx_t *ctx;
48  if ((ctx = calloc(1, sizeof(Skinny64CTRCtx_t))) == NULL)
49  return 0;
51  ctr->ctx = ctx;
52  return 1;
53 }
54 
55 static void skinny64_ctr_def_cleanup(Skinny64CTR_t *ctr)
56 {
57  if (ctr->ctx) {
58  skinny_cleanse(ctr->ctx, sizeof(Skinny64CTRCtx_t));
59  free(ctr->ctx);
60  ctr->ctx = 0;
61  }
62 }
63 
64 static int skinny64_ctr_def_set_key
65  (Skinny64CTR_t *ctr, const void *key, unsigned size)
66 {
67  Skinny64CTRCtx_t *ctx;
68 
69  /* Validate the parameters */
70  if (!key)
71  return 0;
72  ctx = ctr->ctx;
73  if (!ctx)
74  return 0;
75 
76  /* Populate the underlying key schedule */
77  if (!skinny64_set_key(&(ctx->kt.ks), key, size))
78  return 0;
79 
80  /* Reset the keystream */
82  return 1;
83 }
84 
85 static int skinny64_ctr_def_set_tweaked_key
86  (Skinny64CTR_t *ctr, const void *key, unsigned key_size)
87 {
88  Skinny64CTRCtx_t *ctx;
89 
90  /* Validate the parameters */
91  if (!key)
92  return 0;
93  ctx = ctr->ctx;
94  if (!ctx)
95  return 0;
96 
97  /* Populate the underlying key schedule */
98  if (!skinny64_set_tweaked_key(&(ctx->kt), key, key_size))
99  return 0;
100 
101  /* Reset the keystream */
103  return 1;
104 }
105 
106 static int skinny64_ctr_def_set_tweak
107  (Skinny64CTR_t *ctr, const void *tweak, unsigned tweak_size)
108 {
109  Skinny64CTRCtx_t *ctx;
110 
111  /* Validate the parameters */
112  ctx = ctr->ctx;
113  if (!ctx)
114  return 0;
115 
116  /* Populate the underlying tweak */
117  if (!skinny64_set_tweak(&(ctx->kt), tweak, tweak_size))
118  return 0;
119 
120  /* Reset the keystream */
122  return 1;
123 }
124 
125 static int skinny64_ctr_def_set_counter
126  (Skinny64CTR_t *ctr, const void *counter, unsigned size)
127 {
128  Skinny64CTRCtx_t *ctx;
129 
130  /* Validate the parameters */
131  if (size > SKINNY64_BLOCK_SIZE)
132  return 0;
133  ctx = ctr->ctx;
134  if (!ctx)
135  return 0;
136 
137  /* Set the counter and reset the keystream to a block boundary */
138  if (counter) {
139  memset(ctx->counter, 0, SKINNY64_BLOCK_SIZE - size);
140  memcpy(ctx->counter + SKINNY64_BLOCK_SIZE - size, counter, size);
141  } else {
142  memset(ctx->counter, 0, SKINNY64_BLOCK_SIZE);
143  }
145  return 1;
146 }
147 
148 static int skinny64_ctr_def_encrypt
149  (void *output, const void *input, size_t size, Skinny64CTR_t *ctr)
150 {
151  Skinny64CTRCtx_t *ctx;
152  uint8_t *out = (uint8_t *)output;
153  const uint8_t *in = (const uint8_t *)input;
154 
155  /* Validate the parameters */
156  if (!output || !input)
157  return 0;
158  ctx = ctr->ctx;
159  if (!ctx)
160  return 0;
161 
162  /* Encrypt the input in CTR mode to create the output */
163  while (size > 0) {
164  if (ctx->offset >= SKINNY64_BLOCK_SIZE) {
165  /* We need a new keystream block */
166  skinny64_ecb_encrypt(ctx->ecounter, ctx->counter, &(ctx->kt.ks));
167  skinny64_inc_counter(ctx->counter, 1);
168 
169  /* XOR an entire keystream block in one go if possible */
170  if (size >= SKINNY64_BLOCK_SIZE) {
171  skinny64_xor(out, in, ctx->ecounter);
172  out += SKINNY64_BLOCK_SIZE;
173  in += SKINNY64_BLOCK_SIZE;
174  size -= SKINNY64_BLOCK_SIZE;
175  } else {
176  /* Last partial block in the request */
177  skinny_xor(out, in, ctx->ecounter, size);
178  ctx->offset = size;
179  break;
180  }
181  } else {
182  /* Left-over keystream data from the last request */
183  size_t temp = SKINNY64_BLOCK_SIZE - ctx->offset;
184  if (temp > size)
185  temp = size;
186  skinny_xor(out, in, ctx->ecounter + ctx->offset, temp);
187  ctx->offset += temp;
188  out += temp;
189  in += temp;
190  size -= temp;
191  }
192  }
193  return 1;
194 }
195 
197 static Skinny64CTRVtable_t const skinny64_ctr_def = {
198  skinny64_ctr_def_init,
199  skinny64_ctr_def_cleanup,
200  skinny64_ctr_def_set_key,
201  skinny64_ctr_def_set_tweaked_key,
202  skinny64_ctr_def_set_tweak,
203  skinny64_ctr_def_set_counter,
204  skinny64_ctr_def_encrypt
205 };
206 
207 /* Public API, which redirects to the specific backend implementation */
208 
210 {
211  const Skinny64CTRVtable_t *vtable;
212 
213  /* Validate the parameter */
214  if (!ctr)
215  return 0;
216 
217  /* Choose a backend implementation */
218  vtable = &skinny64_ctr_def;
219  if (_skinny_has_vec128())
220  vtable = &_skinny64_ctr_vec128;
221  ctr->vtable = vtable;
222 
223  /* Initialize the CTR mode context */
224  return (*(vtable->init))(ctr);
225 }
226 
228 {
229  if (ctr && ctr->vtable) {
230  const Skinny64CTRVtable_t *vtable = ctr->vtable;
231  (*(vtable->cleanup))(ctr);
232  ctr->vtable = 0;
233  }
234 }
235 
236 int skinny64_ctr_set_key(Skinny64CTR_t *ctr, const void *key, unsigned size)
237 {
238  if (ctr && ctr->vtable) {
239  const Skinny64CTRVtable_t *vtable = ctr->vtable;
240  return (*(vtable->set_key))(ctr, key, size);
241  }
242  return 0;
243 }
244 
246  (Skinny64CTR_t *ctr, const void *key, unsigned key_size)
247 {
248  if (ctr && ctr->vtable) {
249  const Skinny64CTRVtable_t *vtable = ctr->vtable;
250  return (*(vtable->set_tweaked_key))(ctr, key, key_size);
251  }
252  return 0;
253 }
254 
256  (Skinny64CTR_t *ctr, const void *tweak, unsigned tweak_size)
257 {
258  if (ctr && ctr->vtable) {
259  const Skinny64CTRVtable_t *vtable = ctr->vtable;
260  return (*(vtable->set_tweak))(ctr, tweak, tweak_size);
261  }
262  return 0;
263 }
264 
266  (Skinny64CTR_t *ctr, const void *counter, unsigned size)
267 {
268  if (ctr && ctr->vtable) {
269  const Skinny64CTRVtable_t *vtable = ctr->vtable;
270  return (*(vtable->set_counter))(ctr, counter, size);
271  }
272  return 0;
273 }
274 
276  (void *output, const void *input, size_t size, Skinny64CTR_t *ctr)
277 {
278  if (ctr && ctr->vtable) {
279  const Skinny64CTRVtable_t *vtable = ctr->vtable;
280  return (*(vtable->encrypt))(output, input, size, ctr);
281  }
282  return 0;
283 }
const void * vtable
unsigned char ecounter[SKINNY64_BLOCK_SIZE]
Definition: skinny64-ctr.c:38
void skinny64_ctr_cleanup(Skinny64CTR_t *ctr)
Cleans up a CTR control block for Skinny-64.
Definition: skinny64-ctr.c:227
int skinny64_set_tweak(Skinny64TweakedKey_t *ks, const void *tweak, unsigned tweak_size)
Changes the tweak value for a previously-initialized key schedule.
int skinny64_ctr_set_key(Skinny64CTR_t *ctr, const void *key, unsigned size)
Sets the key schedule for a Skinny64 block cipher in CTR mode.
Definition: skinny64-ctr.c:236
int skinny64_set_key(Skinny64Key_t *ks, const void *key, unsigned size)
Sets the key schedule for a Skinny64 block cipher.
int skinny64_ctr_init(Skinny64CTR_t *ctr)
Initializes Skinny-64 in CTR mode.
Definition: skinny64-ctr.c:209
int skinny64_ctr_encrypt(void *output, const void *input, size_t size, Skinny64CTR_t *ctr)
Encrypt a block of data using Skinny-64 in CTR mode.
Definition: skinny64-ctr.c:276
int skinny64_set_tweaked_key(Skinny64TweakedKey_t *ks, const void *key, unsigned key_size)
Sets the key schedule for a Skinny64 block cipher, and prepare for tweaked encryption.
Key schedule for Skinny64 block ciphers when a tweak is in use.
void skinny64_ecb_encrypt(void *output, const void *input, const Skinny64Key_t *ks)
Encrypts a single block using the Skinny64 block cipher in ECB mode.
Skinny64TweakedKey_t kt
Definition: skinny64-ctr.c:32
int skinny64_ctr_set_counter(Skinny64CTR_t *ctr, const void *counter, unsigned size)
Sets the counter value in a Skinny-64 CTR control block.
Definition: skinny64-ctr.c:266
unsigned char counter[SKINNY64_BLOCK_SIZE]
Definition: skinny64-ctr.c:35
#define SKINNY64_BLOCK_SIZE
Size of a block for Skinny64 block ciphers.
State information for Skinny-64 in CTR mode.
int skinny64_ctr_set_tweak(Skinny64CTR_t *ctr, const void *tweak, unsigned tweak_size)
Changes the tweak value for a previously-initialized key schedule.
Definition: skinny64-ctr.c:256
int skinny64_ctr_set_tweaked_key(Skinny64CTR_t *ctr, const void *key, unsigned key_size)
Sets the key schedule for a Skinny64 block cipher in CTR mode, and prepare for tweaked encryption...
Definition: skinny64-ctr.c:246