Skinny-C
 All Data Structures Files Functions Variables Groups Pages
mantis-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 "mantis-cipher.h"
24 #include "mantis-ctr-internal.h"
25 #include "skinny-internal.h"
26 #include <stdlib.h>
27 
29 typedef struct
30 {
33 
35  unsigned char counter[MANTIS_BLOCK_SIZE];
36 
38  unsigned char ecounter[MANTIS_BLOCK_SIZE];
39 
41  unsigned offset;
42 
44 
45 static int mantis_ctr_def_init(MantisCTR_t *ctr)
46 {
47  MantisCTRCtx_t *ctx;
48  if ((ctx = calloc(1, sizeof(MantisCTRCtx_t))) == NULL)
49  return 0;
51  ctr->ctx = ctx;
52  return 1;
53 }
54 
55 static void mantis_ctr_def_cleanup(MantisCTR_t *ctr)
56 {
57  if (ctr->ctx) {
58  skinny_cleanse(ctr->ctx, sizeof(MantisCTRCtx_t));
59  free(ctr->ctx);
60  ctr->ctx = 0;
61  }
62 }
63 
64 static int mantis_ctr_def_set_key
65  (MantisCTR_t *ctr, const void *key, unsigned size, unsigned rounds)
66 {
67  MantisCTRCtx_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 (!mantis_set_key(&(ctx->ks), key, size, rounds, MANTIS_ENCRYPT))
78  return 0;
79 
80  /* Reset the keystream */
82  return 1;
83 }
84 
85 static int mantis_ctr_def_set_tweak
86  (MantisCTR_t *ctr, const void *tweak, unsigned tweak_size)
87 {
88  MantisCTRCtx_t *ctx;
89 
90  /* Validate the parameters */
91  ctx = ctr->ctx;
92  if (!ctx)
93  return 0;
94 
95  /* Populate the underlying tweak */
96  if (!mantis_set_tweak(&(ctx->ks), tweak, tweak_size))
97  return 0;
98 
99  /* Reset the keystream */
100  ctx->offset = MANTIS_BLOCK_SIZE;
101  return 1;
102 }
103 
104 static int mantis_ctr_def_set_counter
105  (MantisCTR_t *ctr, const void *counter, unsigned size)
106 {
107  MantisCTRCtx_t *ctx;
108 
109  /* Validate the parameters */
110  if (size > MANTIS_BLOCK_SIZE)
111  return 0;
112  ctx = ctr->ctx;
113  if (!ctx)
114  return 0;
115 
116  /* Set the counter and reset the keystream to a block boundary */
117  if (counter) {
118  memset(ctx->counter, 0, MANTIS_BLOCK_SIZE - size);
119  memcpy(ctx->counter + MANTIS_BLOCK_SIZE - size, counter, size);
120  } else {
121  memset(ctx->counter, 0, MANTIS_BLOCK_SIZE);
122  }
123  ctx->offset = MANTIS_BLOCK_SIZE;
124  return 1;
125 }
126 
127 static int mantis_ctr_def_encrypt
128  (void *output, const void *input, size_t size, MantisCTR_t *ctr)
129 {
130  MantisCTRCtx_t *ctx;
131  uint8_t *out = (uint8_t *)output;
132  const uint8_t *in = (const uint8_t *)input;
133 
134  /* Validate the parameters */
135  if (!output || !input)
136  return 0;
137  ctx = ctr->ctx;
138  if (!ctx)
139  return 0;
140 
141  /* Encrypt the input in CTR mode to create the output */
142  while (size > 0) {
143  if (ctx->offset >= MANTIS_BLOCK_SIZE) {
144  /* We need a new keystream block */
145  mantis_ecb_crypt(ctx->ecounter, ctx->counter, &(ctx->ks));
146  skinny64_inc_counter(ctx->counter, 1);
147 
148  /* XOR an entire keystream block in one go if possible */
149  if (size >= MANTIS_BLOCK_SIZE) {
150  skinny64_xor(out, in, ctx->ecounter);
151  out += MANTIS_BLOCK_SIZE;
152  in += MANTIS_BLOCK_SIZE;
153  size -= MANTIS_BLOCK_SIZE;
154  } else {
155  /* Last partial block in the request */
156  skinny_xor(out, in, ctx->ecounter, size);
157  ctx->offset = size;
158  break;
159  }
160  } else {
161  /* Left-over keystream data from the last request */
162  size_t temp = MANTIS_BLOCK_SIZE - ctx->offset;
163  if (temp > size)
164  temp = size;
165  skinny_xor(out, in, ctx->ecounter + ctx->offset, temp);
166  ctx->offset += temp;
167  out += temp;
168  in += temp;
169  size -= temp;
170  }
171  }
172  return 1;
173 }
174 
176 static MantisCTRVtable_t const mantis_ctr_def = {
177  mantis_ctr_def_init,
178  mantis_ctr_def_cleanup,
179  mantis_ctr_def_set_key,
180  mantis_ctr_def_set_tweak,
181  mantis_ctr_def_set_counter,
182  mantis_ctr_def_encrypt
183 };
184 
185 /* Public API, which redirects to the specific backend implementation */
186 
188 {
189  const MantisCTRVtable_t *vtable;
190 
191  /* Validate the parameter */
192  if (!ctr)
193  return 0;
194 
195  /* Choose a backend implementation */
196  vtable = &mantis_ctr_def;
197  if (_skinny_has_vec128())
198  vtable = &_mantis_ctr_vec128;
199  ctr->vtable = vtable;
200 
201  /* Initialize the CTR mode context */
202  return (*(vtable->init))(ctr);
203 }
204 
206 {
207  if (ctr && ctr->vtable) {
208  const MantisCTRVtable_t *vtable = ctr->vtable;
209  (*(vtable->cleanup))(ctr);
210  ctr->vtable = 0;
211  }
212 }
213 
215  (MantisCTR_t *ctr, const void *key, unsigned size, unsigned rounds)
216 {
217  if (ctr && ctr->vtable) {
218  const MantisCTRVtable_t *vtable = ctr->vtable;
219  return (*(vtable->set_key))(ctr, key, size, rounds);
220  }
221  return 0;
222 }
223 
225  (MantisCTR_t *ctr, const void *tweak, unsigned tweak_size)
226 {
227  if (ctr && ctr->vtable) {
228  const MantisCTRVtable_t *vtable = ctr->vtable;
229  return (*(vtable->set_tweak))(ctr, tweak, tweak_size);
230  }
231  return 0;
232 }
233 
235  (MantisCTR_t *ctr, const void *counter, unsigned size)
236 {
237  if (ctr && ctr->vtable) {
238  const MantisCTRVtable_t *vtable = ctr->vtable;
239  return (*(vtable->set_counter))(ctr, counter, size);
240  }
241  return 0;
242 }
243 
245  (void *output, const void *input, size_t size, MantisCTR_t *ctr)
246 {
247  if (ctr && ctr->vtable) {
248  const MantisCTRVtable_t *vtable = ctr->vtable;
249  return (*(vtable->encrypt))(output, input, size, ctr);
250  }
251  return 0;
252 }
#define MANTIS_ENCRYPT
Mode that selects Mantis encryption when the key schedule is setup.
Definition: mantis-cipher.h:87
int mantis_ctr_encrypt(void *output, const void *input, size_t size, MantisCTR_t *ctr)
Encrypt a block of data using Mantis in CTR mode.
Definition: mantis-ctr.c:245
void mantis_ecb_crypt(void *output, const void *input, const MantisKey_t *ks)
Encrypts or decrypts a single block using the Mantis block cipher in ECB mode.
int mantis_set_tweak(MantisKey_t *ks, const void *tweak, unsigned size)
Sets the tweak value for a previously-initialized key schedule.
#define MANTIS_BLOCK_SIZE
Size of a block for Mantis block ciphers.
Definition: mantis-cipher.h:59
void mantis_ctr_cleanup(MantisCTR_t *ctr)
Cleans up a CTR control block for Mantis.
Definition: mantis-ctr.c:205
int mantis_ctr_init(MantisCTR_t *ctr)
Initializes Mantis in CTR mode.
Definition: mantis-ctr.c:187
const void * vtable
unsigned offset
Definition: mantis-ctr.c:41
int mantis_set_key(MantisKey_t *ks, const void *key, unsigned size, unsigned rounds, int mode)
Sets the key schedule for a Mantis block cipher.
MantisKey_t ks
Definition: mantis-ctr.c:32
State information for Mantis in CTR mode.
int mantis_ctr_set_counter(MantisCTR_t *ctr, const void *counter, unsigned size)
Sets the counter value in a Mantis CTR control block.
Definition: mantis-ctr.c:235
int mantis_ctr_set_tweak(MantisCTR_t *ctr, const void *tweak, unsigned tweak_size)
Changes the tweak value for a previously-initialized key schedule.
Definition: mantis-ctr.c:225
Key schedule for Mantis block ciphers.
unsigned char ecounter[MANTIS_BLOCK_SIZE]
Definition: mantis-ctr.c:38
int mantis_ctr_set_key(MantisCTR_t *ctr, const void *key, unsigned size, unsigned rounds)
Sets the key schedule for a Mantis block cipher in CTR mode.
Definition: mantis-ctr.c:215
unsigned char counter[MANTIS_BLOCK_SIZE]
Definition: mantis-ctr.c:35