Lightweight Cryptography Primitives
 All Data Structures Files Functions Variables Typedefs Macros Pages
internal-ocb.h
1 /*
2  * Copyright (C) 2020 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 #ifndef LW_INTERNAL_OCB_H
24 #define LW_INTERNAL_OCB_H
25 
26 #include "internal-util.h"
27 #include <string.h>
28 
29 /* We expect a number of macros to be defined before this file
30  * is included to configure the underlying block cipher:
31  *
32  * OCB_ALG_NAME Name of the algorithm that is using OCB mode.
33  * OCB_BLOCK_SIZE Size of the block for the underlying cipher in bytes.
34  * OCB_NONCE_SIZE Size of the nonce which must be < OCB_BLOCK_SIZE.
35  * OCB_TAG_SIZE Size of the authentication tag.
36  * OCB_KEY_SCHEDULE Type for the key schedule.
37  * OCB_SETUP_KEY Name of the key schedule setup function.
38  * OCB_ENCRYPT_BLOCK Name of the block cipher ECB encrypt function.
39  * OCB_DECRYPT_BLOCK Name of the block cipher ECB decrypt function.
40  * OCB_DOUBLE_L Name of the function to double L (optional).
41  */
42 #if defined(OCB_ENCRYPT_BLOCK)
43 
58 #define OCB_CONCAT_INNER(name,suffix) name##suffix
59 #define OCB_CONCAT(name,suffix) OCB_CONCAT_INNER(name,suffix)
60 
61 #if !defined(OCB_DOUBLE_L)
62 
63 #define OCB_DOUBLE_L OCB_CONCAT(OCB_ALG_NAME,_double_l)
64 
65 #if OCB_BLOCK_SIZE == 16
66 
67 /* Double a value in GF(128) */
68 static void OCB_DOUBLE_L(unsigned char out[16], const unsigned char in[16])
69 {
70  unsigned index;
71  unsigned char mask = (unsigned char)(((signed char)in[0]) >> 7);
72  for (index = 0; index < 15; ++index)
73  out[index] = (in[index] << 1) | (in[index + 1] >> 7);
74  out[15] = (in[15] << 1) ^ (mask & 0x87);
75 }
76 
77 #elif OCB_BLOCK_SIZE == 12
78 
79 /* Double a value in GF(96) */
80 static void OCB_DOUBLE_L
81  (unsigned char out[12], const unsigned char in[12])
82 {
83  unsigned index;
84  unsigned char mask = (unsigned char)(((signed char)in[0]) >> 7);
85  for (index = 0; index < 11; ++index)
86  out[index] = (in[index] << 1) | (in[index + 1] >> 7);
87  out[11] = (in[11] << 1) ^ (mask & 0x41);
88  out[10] ^= (mask & 0x06);
89 }
90 
91 #else
92 #error "Unknown block size for OCB"
93 #endif
94 
95 #endif
96 
97 /* State information for OCB functions */
98 #define OCB_STATE OCB_CONCAT(OCB_ALG_NAME,_state_t)
99 typedef struct
100 {
101  OCB_KEY_SCHEDULE ks;
102  unsigned char Lstar[OCB_BLOCK_SIZE];
103  unsigned char Ldollar[OCB_BLOCK_SIZE];
104  unsigned char L0[OCB_BLOCK_SIZE];
105  unsigned char L1[OCB_BLOCK_SIZE];
106 
107 } OCB_STATE;
108 
109 /* Initializes the OCB state from the key and nonce */
110 static void OCB_CONCAT(OCB_ALG_NAME,_init)
111  (OCB_STATE *state, const unsigned char *k, const unsigned char *nonce,
112  unsigned char offset[OCB_BLOCK_SIZE])
113 {
114  unsigned bottom;
115 
116  /* Set up the key schedule */
117  OCB_SETUP_KEY(&(state->ks), k);
118 
119  /* Derive the values of L*, L$, L0, and L1 */
120  memset(state->Lstar, 0, sizeof(state->Lstar));
121  OCB_ENCRYPT_BLOCK(&(state->ks), state->Lstar, state->Lstar);
122  OCB_DOUBLE_L(state->Ldollar, state->Lstar);
123  OCB_DOUBLE_L(state->L0, state->Ldollar);
124  OCB_DOUBLE_L(state->L1, state->L0);
125 
126  /* Derive the initial offset from the nonce */
127  memset(offset, 0, OCB_BLOCK_SIZE);
128  memcpy(offset + OCB_BLOCK_SIZE - OCB_NONCE_SIZE, nonce, OCB_NONCE_SIZE);
129  offset[0] = ((OCB_TAG_SIZE * 8) & 0x7F) << 1;
130  offset[OCB_BLOCK_SIZE - OCB_NONCE_SIZE - 1] |= 0x01;
131  bottom = offset[OCB_BLOCK_SIZE - 1] & 0x3F;
132  offset[OCB_BLOCK_SIZE - 1] &= 0xC0;
133  {
134  unsigned index;
135  unsigned byte_posn = bottom / 8;
136 #if OCB_BLOCK_SIZE == 16
137  /* Standard OCB with a 128-bit block */
138  unsigned char stretch[24];
139  OCB_ENCRYPT_BLOCK(&(state->ks), stretch, offset);
140  memcpy(stretch + 16, stretch + 1, 8);
141  lw_xor_block(stretch + 16, stretch, 8);
142 #elif OCB_BLOCK_SIZE == 12
143  /* 96-bit block handling from the Pyjamask specification */
144  unsigned char stretch[20];
145  OCB_ENCRYPT_BLOCK(&(state->ks), stretch, offset);
146  for (index = 0; index < 8; ++index) {
147  stretch[index + 12] =
148  (stretch[index + 1] << 1) | (stretch[index + 2] >> 7);
149  }
150  lw_xor_block(stretch + 12, stretch, 8);
151 #else
152  unsigned char stretch[OCB_BLOCK_SIZE + 8] = {0};
153  #error "unsupported block size for OCB mode"
154 #endif
155  bottom %= 8;
156  if (bottom != 0) {
157  for (index = 0; index < OCB_BLOCK_SIZE; ++index) {
158  offset[index] =
159  (stretch[index + byte_posn] << bottom) |
160  (stretch[index + byte_posn + 1] >> (8 - bottom));
161  }
162  } else {
163  memcpy(offset, stretch + byte_posn, OCB_BLOCK_SIZE);
164  }
165  }
166 }
167 
168 /* Calculate L_{ntz(i)} when the last two bits of i are zero */
169 static void OCB_CONCAT(OCB_ALG_NAME,_calculate_L)
170  (OCB_STATE *state, unsigned char L[OCB_BLOCK_SIZE], unsigned long long i)
171 {
172  OCB_DOUBLE_L(L, state->L1);
173  i >>= 2;
174  while ((i & 1) == 0) {
175  OCB_DOUBLE_L(L, L);
176  i >>= 1;
177  }
178 }
179 
180 /* Process associated data with OCB */
181 static void OCB_CONCAT(OCB_ALG_NAME,_process_ad)
182  (OCB_STATE *state, unsigned char tag[OCB_BLOCK_SIZE],
183  const unsigned char *ad, unsigned long long adlen)
184 {
185  unsigned char offset[OCB_BLOCK_SIZE];
186  unsigned char block[OCB_BLOCK_SIZE];
187  unsigned long long block_number;
188 
189  /* Process all full blocks */
190  memset(offset, 0, sizeof(offset));
191  block_number = 1;
192  while (adlen >= OCB_BLOCK_SIZE) {
193  if (block_number & 1) {
194  lw_xor_block(offset, state->L0, OCB_BLOCK_SIZE);
195  } else if ((block_number & 3) == 2) {
196  lw_xor_block(offset, state->L1, OCB_BLOCK_SIZE);
197  } else {
198  OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(state, block, block_number);
199  lw_xor_block(offset, block, OCB_BLOCK_SIZE);
200  }
201  lw_xor_block_2_src(block, offset, ad, OCB_BLOCK_SIZE);
202  OCB_ENCRYPT_BLOCK(&(state->ks), block, block);
203  lw_xor_block(tag, block, OCB_BLOCK_SIZE);
204  ad += OCB_BLOCK_SIZE;
205  adlen -= OCB_BLOCK_SIZE;
206  ++block_number;
207  }
208 
209  /* Pad and process the last partial block */
210  if (adlen > 0) {
211  unsigned temp = (unsigned)adlen;
212  lw_xor_block(offset, state->Lstar, OCB_BLOCK_SIZE);
213  lw_xor_block(offset, ad, temp);
214  offset[temp] ^= 0x80;
215  OCB_ENCRYPT_BLOCK(&(state->ks), block, offset);
216  lw_xor_block(tag, block, OCB_BLOCK_SIZE);
217  }
218 }
219 
220 int OCB_CONCAT(OCB_ALG_NAME,_aead_encrypt)
221  (unsigned char *c, unsigned long long *clen,
222  const unsigned char *m, unsigned long long mlen,
223  const unsigned char *ad, unsigned long long adlen,
224  const unsigned char *nsec,
225  const unsigned char *npub,
226  const unsigned char *k)
227 {
228  OCB_STATE state;
229  unsigned char offset[OCB_BLOCK_SIZE];
230  unsigned char sum[OCB_BLOCK_SIZE];
231  unsigned char block[OCB_BLOCK_SIZE];
232  unsigned long long block_number;
233  (void)nsec;
234 
235  /* Set the length of the returned ciphertext */
236  *clen = mlen + OCB_TAG_SIZE;
237 
238  /* Initialize the OCB state */
239  OCB_CONCAT(OCB_ALG_NAME,_init)(&state, k, npub, offset);
240 
241  /* Process all plaintext blocks except the last */
242  memset(sum, 0, sizeof(sum));
243  block_number = 1;
244  while (mlen >= OCB_BLOCK_SIZE) {
245  if (block_number & 1) {
246  lw_xor_block(offset, state.L0, OCB_BLOCK_SIZE);
247  } else if ((block_number & 3) == 2) {
248  lw_xor_block(offset, state.L1, OCB_BLOCK_SIZE);
249  } else {
250  OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(&state, block, block_number);
251  lw_xor_block(offset, block, OCB_BLOCK_SIZE);
252  }
253  lw_xor_block(sum, m, OCB_BLOCK_SIZE);
254  lw_xor_block_2_src(block, offset, m, OCB_BLOCK_SIZE);
255  OCB_ENCRYPT_BLOCK(&(state.ks), block, block);
256  lw_xor_block_2_src(c, block, offset, OCB_BLOCK_SIZE);
257  c += OCB_BLOCK_SIZE;
258  m += OCB_BLOCK_SIZE;
259  mlen -= OCB_BLOCK_SIZE;
260  ++block_number;
261  }
262 
263  /* Pad and process the last plaintext block */
264  if (mlen > 0) {
265  unsigned temp = (unsigned)mlen;
266  lw_xor_block(sum, m, temp);
267  sum[temp] ^= 0x80;
268  lw_xor_block(offset, state.Lstar, OCB_BLOCK_SIZE);
269  OCB_ENCRYPT_BLOCK(&(state.ks), block, offset);
270  lw_xor_block_2_src(c, block, m, temp);
271  c += temp;
272  }
273 
274  /* Finalize the encryption phase */
275  lw_xor_block(sum, offset, OCB_BLOCK_SIZE);
276  lw_xor_block(sum, state.Ldollar, OCB_BLOCK_SIZE);
277  OCB_ENCRYPT_BLOCK(&(state.ks), sum, sum);
278 
279  /* Process the associated data and compute the final authentication tag */
280  OCB_CONCAT(OCB_ALG_NAME,_process_ad)(&state, sum, ad, adlen);
281  memcpy(c, sum, OCB_TAG_SIZE);
282  return 0;
283 }
284 
285 int OCB_CONCAT(OCB_ALG_NAME,_aead_decrypt)
286  (unsigned char *m, unsigned long long *mlen,
287  unsigned char *nsec,
288  const unsigned char *c, unsigned long long clen,
289  const unsigned char *ad, unsigned long long adlen,
290  const unsigned char *npub,
291  const unsigned char *k)
292 {
293  OCB_STATE state;
294  unsigned char *mtemp = m;
295  unsigned char offset[OCB_BLOCK_SIZE];
296  unsigned char sum[OCB_BLOCK_SIZE];
297  unsigned char block[OCB_BLOCK_SIZE];
298  unsigned long long block_number;
299  (void)nsec;
300 
301  /* Validate the ciphertext length and set the return "mlen" value */
302  if (clen < OCB_TAG_SIZE)
303  return -1;
304  *mlen = clen - OCB_TAG_SIZE;
305 
306  /* Initialize the OCB state */
307  OCB_CONCAT(OCB_ALG_NAME,_init)(&state, k, npub, offset);
308 
309  /* Process all ciphertext blocks except the last */
310  memset(sum, 0, sizeof(sum));
311  block_number = 1;
312  clen -= OCB_TAG_SIZE;
313  while (clen >= OCB_BLOCK_SIZE) {
314  if (block_number & 1) {
315  lw_xor_block(offset, state.L0, OCB_BLOCK_SIZE);
316  } else if ((block_number & 3) == 2) {
317  lw_xor_block(offset, state.L1, OCB_BLOCK_SIZE);
318  } else {
319  OCB_CONCAT(OCB_ALG_NAME,_calculate_L)(&state, block, block_number);
320  lw_xor_block(offset, block, OCB_BLOCK_SIZE);
321  }
322  lw_xor_block_2_src(block, offset, c, OCB_BLOCK_SIZE);
323  OCB_DECRYPT_BLOCK(&(state.ks), block, block);
324  lw_xor_block_2_src(m, block, offset, OCB_BLOCK_SIZE);
325  lw_xor_block(sum, m, OCB_BLOCK_SIZE);
326  c += OCB_BLOCK_SIZE;
327  m += OCB_BLOCK_SIZE;
328  clen -= OCB_BLOCK_SIZE;
329  ++block_number;
330  }
331 
332  /* Pad and process the last ciphertext block */
333  if (clen > 0) {
334  unsigned temp = (unsigned)clen;
335  lw_xor_block(offset, state.Lstar, OCB_BLOCK_SIZE);
336  OCB_ENCRYPT_BLOCK(&(state.ks), block, offset);
337  lw_xor_block_2_src(m, block, c, temp);
338  lw_xor_block(sum, m, temp);
339  sum[temp] ^= 0x80;
340  c += temp;
341  }
342 
343  /* Finalize the decryption phase */
344  lw_xor_block(sum, offset, OCB_BLOCK_SIZE);
345  lw_xor_block(sum, state.Ldollar, OCB_BLOCK_SIZE);
346  OCB_ENCRYPT_BLOCK(&(state.ks), sum, sum);
347 
348  /* Process the associated data and check the final authentication tag */
349  OCB_CONCAT(OCB_ALG_NAME,_process_ad)(&state, sum, ad, adlen);
350  return aead_check_tag(mtemp, *mlen, sum, c, OCB_TAG_SIZE);
351 }
352 
353 #endif /* OCB_ENCRYPT_BLOCK */
354 
355 #endif /* LW_INTERNAL_OCB_H */
int aead_check_tag(unsigned char *plaintext, unsigned long long plaintext_len, const unsigned char *tag1, const unsigned char *tag2, unsigned tag_len)
Check an authentication tag in constant time.
Definition: aead-common.c:26