/src/nettle-with-libgmp/ocb.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ocb.c |
2 | | |
3 | | OCB AEAD mode, RFC 7253 |
4 | | |
5 | | Copyright (C) 2021 Niels Möller |
6 | | |
7 | | This file is part of GNU Nettle. |
8 | | |
9 | | GNU Nettle is free software: you can redistribute it and/or |
10 | | modify it under the terms of either: |
11 | | |
12 | | * the GNU Lesser General Public License as published by the Free |
13 | | Software Foundation; either version 3 of the License, or (at your |
14 | | option) any later version. |
15 | | |
16 | | or |
17 | | |
18 | | * the GNU General Public License as published by the Free |
19 | | Software Foundation; either version 2 of the License, or (at your |
20 | | option) any later version. |
21 | | |
22 | | or both in parallel, as here. |
23 | | |
24 | | GNU Nettle is distributed in the hope that it will be useful, |
25 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
27 | | General Public License for more details. |
28 | | |
29 | | You should have received copies of the GNU General Public License and |
30 | | the GNU Lesser General Public License along with this program. If |
31 | | not, see http://www.gnu.org/licenses/. |
32 | | */ |
33 | | |
34 | | #if HAVE_CONFIG_H |
35 | | # include "config.h" |
36 | | #endif |
37 | | |
38 | | #include <string.h> |
39 | | |
40 | | #include "ocb.h" |
41 | | #include "block-internal.h" |
42 | | #include "bswap-internal.h" |
43 | | #include "memops.h" |
44 | | |
45 | 2.03k | #define OCB_MAX_BLOCKS 16 |
46 | | |
47 | | /* Returns 64 bits from the concatenation (u0, u1), starting from bit offset. */ |
48 | | static inline uint64_t |
49 | | extract(uint64_t u0, uint64_t u1, unsigned offset) |
50 | 1.95k | { |
51 | 1.95k | if (offset == 0) |
52 | 290 | return u0; |
53 | 1.66k | u0 = bswap64_if_le(u0); |
54 | 1.66k | u1 = bswap64_if_le(u1); |
55 | 1.66k | return bswap64_if_le((u0 << offset) | (u1 >> (64 - offset))); |
56 | 1.95k | } |
57 | | |
58 | | void |
59 | | ocb_set_key (struct ocb_key *key, const void *cipher, nettle_cipher_func *f) |
60 | 975 | { |
61 | 975 | static const union nettle_block16 zero_block; |
62 | 975 | f (cipher, OCB_BLOCK_SIZE, key->L[0].b, zero_block.b); |
63 | 975 | block16_mulx_be (&key->L[1], &key->L[0]); |
64 | 975 | block16_mulx_be (&key->L[2], &key->L[1]); |
65 | 975 | } |
66 | | |
67 | | /* Add x^k L[2], where k is the number of trailing zero bits in i. */ |
68 | | static void |
69 | | update_offset(const struct ocb_key *key, |
70 | | union nettle_block16 *offset, size_t i) |
71 | 740 | { |
72 | 740 | if (i & 1) |
73 | 0 | block16_xor (offset, &key->L[2]); |
74 | 740 | else |
75 | 740 | { |
76 | 740 | assert (i > 0); |
77 | 740 | union nettle_block16 diff; |
78 | 740 | block16_mulx_be (&diff, &key->L[2]); |
79 | 1.17k | for (i >>= 1; !(i&1); i >>= 1) |
80 | 432 | block16_mulx_be (&diff, &diff); |
81 | | |
82 | 740 | block16_xor (offset, &diff); |
83 | 740 | } |
84 | 740 | } |
85 | | |
86 | | static void |
87 | | pad_block (union nettle_block16 *block, size_t length, const uint8_t *data) |
88 | 998 | { |
89 | 998 | memcpy (block->b, data, length); |
90 | 998 | block->b[length] = 0x80; |
91 | 998 | memset (block->b + length + 1, 0, OCB_BLOCK_SIZE - 1 - length); |
92 | 998 | } |
93 | | |
94 | | void |
95 | | ocb_set_nonce (struct ocb_ctx *ctx, |
96 | | const void *cipher, nettle_cipher_func *f, |
97 | | size_t tag_length, |
98 | | size_t nonce_length, const uint8_t *nonce) |
99 | 975 | { |
100 | 975 | union nettle_block16 top; |
101 | 975 | uint64_t stretch; |
102 | | |
103 | 975 | unsigned bottom; |
104 | 975 | assert (nonce_length < 16); |
105 | 975 | assert (tag_length > 0); |
106 | 975 | assert (tag_length <= 16); |
107 | | |
108 | | /* Bit size, or zero for tag_length == 16 */ |
109 | 975 | top.b[0] = (tag_length & 15) << 4; |
110 | 975 | memset (top.b + 1, 0, 15 - nonce_length); |
111 | 975 | top.b[15 - nonce_length] |= 1; |
112 | 975 | memcpy (top.b + 16 - nonce_length, nonce, nonce_length); |
113 | 975 | bottom = top.b[15] & 0x3f; |
114 | 975 | top.b[15] &= 0xc0; |
115 | | |
116 | 975 | f (cipher, OCB_BLOCK_SIZE, top.b, top.b); |
117 | | |
118 | 975 | stretch = top.u64[0]; |
119 | | #if WORDS_BIGENDIAN |
120 | | stretch ^= (top.u64[0] << 8) | (top.u64[1] >> 56); |
121 | | #else |
122 | 975 | stretch ^= (top.u64[0] >> 8) | (top.u64[1] << 56); |
123 | 975 | #endif |
124 | | |
125 | 975 | ctx->initial.u64[0] = extract(top.u64[0], top.u64[1], bottom); |
126 | 975 | ctx->initial.u64[1] = extract(top.u64[1], stretch, bottom); |
127 | 975 | ctx->sum.u64[0] = ctx->sum.u64[1] = 0; |
128 | 975 | ctx->checksum.u64[0] = ctx->checksum.u64[1] = 0; |
129 | | |
130 | 975 | ctx->data_count = ctx->message_count = 0; |
131 | 975 | } |
132 | | |
133 | | static void |
134 | | ocb_fill_n (const struct ocb_key *key, |
135 | | union nettle_block16 *offset, size_t count, |
136 | | size_t n, union nettle_block16 *o) |
137 | 1.86k | { |
138 | 1.86k | assert (n > 0); |
139 | 1.86k | union nettle_block16 *prev; |
140 | 1.86k | if (count & 1) |
141 | 722 | prev = offset; |
142 | 1.14k | else |
143 | 1.14k | { |
144 | | /* Do a single block to align block count. */ |
145 | 1.14k | count++; /* Always odd. */ |
146 | 1.14k | block16_xor (offset, &key->L[2]); |
147 | 1.14k | block16_set (&o[0], offset); |
148 | 1.14k | prev = o; |
149 | 1.14k | n--; o++; |
150 | 1.14k | } |
151 | | |
152 | 5.13k | for (; n >= 2; n -= 2, o += 2) |
153 | 3.27k | { |
154 | 3.27k | size_t i; |
155 | 3.27k | count += 2; /* Always odd. */ |
156 | | |
157 | | /* Based on trailing zeros of ctx->message_count - 1, the |
158 | | initial shift below discards a one bit. */ |
159 | 3.27k | block16_mulx_be (&o[0], &key->L[2]); |
160 | 5.73k | for (i = count >> 1; !(i&1); i >>= 1) |
161 | 2.45k | block16_mulx_be (&o[0], &o[0]); |
162 | | |
163 | 3.27k | block16_xor (&o[0], prev); |
164 | 3.27k | block16_xor3 (&o[1], &o[0], &key->L[2]); |
165 | 3.27k | prev = &o[1]; |
166 | 3.27k | } |
167 | 1.86k | block16_set(offset, prev); |
168 | | |
169 | 1.86k | if (n > 0) |
170 | 740 | { |
171 | 740 | update_offset (key, offset, ++count); |
172 | 740 | block16_set (o, offset); |
173 | 740 | } |
174 | 1.86k | } |
175 | | |
176 | | void |
177 | | ocb_update (struct ocb_ctx *ctx, const struct ocb_key *key, |
178 | | const void *cipher, nettle_cipher_func *f, |
179 | | size_t length, const uint8_t *data) |
180 | 9.24k | { |
181 | 9.24k | union nettle_block16 block[OCB_MAX_BLOCKS]; |
182 | 9.24k | size_t n = length / OCB_BLOCK_SIZE; |
183 | 9.24k | assert (ctx->message_count == 0); |
184 | | |
185 | 9.24k | if (ctx->data_count == 0) |
186 | 881 | ctx->offset.u64[0] = ctx->offset.u64[1] = 0; |
187 | | |
188 | 10.2k | while (n > 0) |
189 | 1.00k | { |
190 | 1.00k | size_t size, i; |
191 | 1.00k | size_t blocks = (n <= OCB_MAX_BLOCKS) ? n |
192 | 1.00k | : OCB_MAX_BLOCKS - 1 + (ctx->data_count & 1); |
193 | | |
194 | 1.00k | ocb_fill_n (key, &ctx->offset, ctx->data_count, blocks, block); |
195 | 1.00k | ctx->data_count += blocks; |
196 | | |
197 | 1.00k | size = blocks * OCB_BLOCK_SIZE; |
198 | 1.00k | memxor (block[0].b, data, size); |
199 | 1.00k | f (cipher, size, block[0].b, block[0].b); |
200 | 4.89k | for (i = 0; i < blocks; i++) |
201 | 3.89k | block16_xor(&ctx->sum, &block[i]); |
202 | | |
203 | 1.00k | n -= blocks; data += size; |
204 | 1.00k | } |
205 | | |
206 | 9.24k | length &= 15; |
207 | 9.24k | if (length > 0) |
208 | 416 | { |
209 | 416 | union nettle_block16 block; |
210 | 416 | pad_block (&block, length, data); |
211 | 416 | block16_xor (&ctx->offset, &key->L[0]); |
212 | 416 | block16_xor (&block, &ctx->offset); |
213 | | |
214 | 416 | f (cipher, OCB_BLOCK_SIZE, block.b, block.b); |
215 | 416 | block16_xor (&ctx->sum, &block); |
216 | 416 | } |
217 | 9.24k | } |
218 | | |
219 | | static void |
220 | | ocb_crypt_n (struct ocb_ctx *ctx, const struct ocb_key *key, |
221 | | const void *cipher, nettle_cipher_func *f, |
222 | | size_t n, uint8_t *dst, const uint8_t *src) |
223 | 725 | { |
224 | 725 | union nettle_block16 o[OCB_MAX_BLOCKS], block[OCB_MAX_BLOCKS]; |
225 | 725 | size_t size; |
226 | | |
227 | 1.58k | while (n > 0) |
228 | 855 | { |
229 | 855 | size_t blocks = (n <= OCB_MAX_BLOCKS) ? n |
230 | 855 | : OCB_MAX_BLOCKS - 1 + (ctx->message_count & 1); |
231 | | |
232 | 855 | ocb_fill_n (key, &ctx->offset, ctx->message_count, blocks, o); |
233 | 855 | ctx->message_count += blocks; |
234 | | |
235 | 855 | size = blocks * OCB_BLOCK_SIZE; |
236 | 855 | memxor3 (block[0].b, o[0].b, src, size); |
237 | 855 | f (cipher, size, block[0].b, block[0].b); |
238 | 855 | memxor3 (dst, block[0].b, o[0].b, size); |
239 | | |
240 | 855 | n -= blocks; src += size; dst += size; |
241 | 855 | } |
242 | 725 | } |
243 | | |
244 | | /* Rotate bytes c positions to the right, in memory order. */ |
245 | | #if WORDS_BIGENDIAN |
246 | | # define MEM_ROTATE_RIGHT(c, s0, s1) do { \ |
247 | | uint64_t __rotate_t = ((s0) >> (8*(c))) | ((s1) << (64-8*(c))); \ |
248 | | (s1) = ((s1) >> (8*(c))) | ((s0) << (64-8*(c))); \ |
249 | | (s0) = __rotate_t; \ |
250 | | } while (0) |
251 | | #else |
252 | 0 | # define MEM_ROTATE_RIGHT(c, s0, s1) do { \ |
253 | 0 | uint64_t __rotate_t = ((s0) << (8*(c))) | ((s1) >> (64-8*(c))); \ |
254 | 0 | (s1) = ((s1) << (8*(c))) | ((s0) >> (64-8*(c))); \ |
255 | 0 | (s0) = __rotate_t; \ |
256 | 0 | } while (0) |
257 | | #endif |
258 | | |
259 | | /* Mask for the first c bytes in memory */ |
260 | | #if WORDS_BIGENDIAN |
261 | | # define MEM_MASK(c) (-((uint64_t) 1 << (64 - 8*(c)))) |
262 | | #else |
263 | 0 | # define MEM_MASK(c) (((uint64_t) 1 << (8*(c))) - 1) |
264 | | #endif |
265 | | |
266 | | /* Checksum of n complete blocks. */ |
267 | | static void |
268 | | ocb_checksum_n (union nettle_block16 *checksum, |
269 | | size_t n, const uint8_t *src) |
270 | 725 | { |
271 | 725 | unsigned initial; |
272 | 725 | uint64_t edge_word = 0; |
273 | 725 | uint64_t s0, s1; |
274 | | |
275 | 725 | if (n == 1) |
276 | 444 | { |
277 | 444 | memxor (checksum->b, src, OCB_BLOCK_SIZE); |
278 | 444 | return; |
279 | 444 | } |
280 | | |
281 | | /* Initial unaligned bytes. */ |
282 | 281 | initial = -(uintptr_t) src & 7; |
283 | | |
284 | 281 | if (initial > 0) |
285 | 0 | { |
286 | | /* Input not 64-bit aligned. Read initial bytes. */ |
287 | 0 | unsigned i; |
288 | | /* Edge word is read in big-endian order */ |
289 | 0 | for (i = initial; i > 0; i--) |
290 | 0 | edge_word = (edge_word << 8) + *src++; |
291 | 0 | n--; |
292 | 0 | } |
293 | | |
294 | | /* Now src is 64-bit aligned, so do 64-bit reads. */ |
295 | 4.37k | for (s0 = s1 = 0 ; n > 0; n--, src += OCB_BLOCK_SIZE) |
296 | 4.09k | { |
297 | 4.09k | s0 ^= ((const uint64_t *) src)[0]; |
298 | 4.09k | s1 ^= ((const uint64_t *) src)[1]; |
299 | 4.09k | } |
300 | 281 | if (initial > 0) |
301 | 0 | { |
302 | 0 | unsigned i; |
303 | 0 | uint64_t mask; |
304 | 0 | s0 ^= ((const uint64_t *) src)[0]; |
305 | 0 | for (i = 8 - initial, src += 8; i > 0; i--) |
306 | 0 | edge_word = (edge_word << 8) + *src++; |
307 | | |
308 | | /* Rotate [s0, s1] right initial bytes. */ |
309 | 0 | MEM_ROTATE_RIGHT(initial, s0, s1); |
310 | | /* Add in the edge bytes. */ |
311 | 0 | mask = MEM_MASK(initial); |
312 | 0 | edge_word = bswap64_if_le (edge_word); |
313 | 0 | s0 ^= (edge_word & mask); |
314 | 0 | s1 ^= (edge_word & ~mask); |
315 | 0 | } |
316 | 281 | checksum->u64[0] ^= s0; |
317 | 281 | checksum->u64[1] ^= s1; |
318 | 281 | } |
319 | | |
320 | | void |
321 | | ocb_encrypt (struct ocb_ctx *ctx, const struct ocb_key *key, |
322 | | const void *cipher, nettle_cipher_func *f, |
323 | | size_t length, uint8_t *dst, const uint8_t *src) |
324 | 4.79k | { |
325 | 4.79k | size_t n = length / OCB_BLOCK_SIZE; |
326 | | |
327 | 4.79k | if (ctx->message_count == 0) |
328 | 3.63k | ctx->offset = ctx->initial; |
329 | | |
330 | 4.79k | if (n > 0) |
331 | 346 | { |
332 | 346 | ocb_checksum_n (&ctx->checksum, n, src); |
333 | 346 | ocb_crypt_n (ctx, key, cipher, f, n, dst, src); |
334 | 346 | length &= 15; |
335 | 346 | } |
336 | 4.79k | if (length > 0) |
337 | 246 | { |
338 | 246 | union nettle_block16 block; |
339 | | |
340 | 246 | src += n*OCB_BLOCK_SIZE; dst += n*OCB_BLOCK_SIZE; |
341 | | |
342 | 246 | pad_block (&block, length, src); |
343 | 246 | block16_xor (&ctx->checksum, &block); |
344 | | |
345 | 246 | block16_xor (&ctx->offset, &key->L[0]); |
346 | 246 | f (cipher, OCB_BLOCK_SIZE, block.b, ctx->offset.b); |
347 | 246 | memxor3 (dst, block.b, src, length); |
348 | 246 | ctx->message_count++; |
349 | 246 | } |
350 | 4.79k | } |
351 | | |
352 | | void |
353 | | ocb_decrypt (struct ocb_ctx *ctx, const struct ocb_key *key, |
354 | | const void *encrypt_ctx, nettle_cipher_func *encrypt, |
355 | | const void *decrypt_ctx, nettle_cipher_func *decrypt, |
356 | | size_t length, uint8_t *dst, const uint8_t *src) |
357 | 2.84k | { |
358 | 2.84k | size_t n = length / OCB_BLOCK_SIZE; |
359 | | |
360 | 2.84k | if (ctx->message_count == 0) |
361 | 1.63k | ctx->offset = ctx->initial; |
362 | | |
363 | 2.84k | if (n > 0) |
364 | 379 | { |
365 | 379 | ocb_crypt_n (ctx, key, decrypt_ctx, decrypt, n, dst, src); |
366 | 379 | ocb_checksum_n (&ctx->checksum, n, dst); |
367 | 379 | length &= 15; |
368 | 379 | } |
369 | 2.84k | if (length > 0) |
370 | 336 | { |
371 | 336 | union nettle_block16 block; |
372 | | |
373 | 336 | src += n*OCB_BLOCK_SIZE; dst += n*OCB_BLOCK_SIZE; |
374 | | |
375 | 336 | block16_xor (&ctx->offset, &key->L[0]); |
376 | 336 | encrypt (encrypt_ctx, OCB_BLOCK_SIZE, block.b, ctx->offset.b); |
377 | 336 | memxor3 (dst, block.b, src, length); |
378 | | |
379 | 336 | pad_block (&block, length, dst); |
380 | 336 | block16_xor (&ctx->checksum, &block); |
381 | 336 | ctx->message_count++; |
382 | 336 | } |
383 | 2.84k | } |
384 | | |
385 | | void |
386 | | ocb_digest (const struct ocb_ctx *ctx, const struct ocb_key *key, |
387 | | const void *cipher, nettle_cipher_func *f, |
388 | | size_t length, uint8_t *digest) |
389 | 975 | { |
390 | 975 | union nettle_block16 block; |
391 | 975 | assert (length <= OCB_DIGEST_SIZE); |
392 | 975 | block16_xor3 (&block, &key->L[1], |
393 | 975 | (ctx->message_count > 0) ? &ctx->offset : &ctx->initial); |
394 | 975 | block16_xor (&block, &ctx->checksum); |
395 | 975 | f (cipher, OCB_BLOCK_SIZE, block.b, block.b); |
396 | 975 | memxor3 (digest, block.b, ctx->sum.b, length); |
397 | 975 | } |
398 | | |
399 | | void |
400 | | ocb_encrypt_message (const struct ocb_key *key, |
401 | | const void *cipher, nettle_cipher_func *f, |
402 | | size_t nlength, const uint8_t *nonce, |
403 | | size_t alength, const uint8_t *adata, |
404 | | size_t tlength, |
405 | | size_t clength, uint8_t *dst, const uint8_t *src) |
406 | 0 | { |
407 | 0 | struct ocb_ctx ctx; |
408 | 0 | assert (clength >= tlength); |
409 | 0 | ocb_set_nonce (&ctx, cipher, f, tlength, nlength, nonce); |
410 | 0 | ocb_update (&ctx, key, cipher, f, alength, adata); |
411 | 0 | ocb_encrypt (&ctx, key, cipher, f, clength - tlength, dst, src); |
412 | 0 | ocb_digest (&ctx, key, cipher, f, tlength, dst + clength - tlength); |
413 | 0 | } |
414 | | |
415 | | int |
416 | | ocb_decrypt_message (const struct ocb_key *key, |
417 | | const void *encrypt_ctx, nettle_cipher_func *encrypt, |
418 | | const void *decrypt_ctx, nettle_cipher_func *decrypt, |
419 | | size_t nlength, const uint8_t *nonce, |
420 | | size_t alength, const uint8_t *adata, |
421 | | size_t tlength, |
422 | | size_t mlength, uint8_t *dst, const uint8_t *src) |
423 | 0 | { |
424 | 0 | struct ocb_ctx ctx; |
425 | 0 | union nettle_block16 digest; |
426 | 0 | ocb_set_nonce (&ctx, encrypt_ctx, encrypt, tlength, nlength, nonce); |
427 | 0 | ocb_update (&ctx, key, encrypt_ctx, encrypt, alength, adata); |
428 | 0 | ocb_decrypt (&ctx, key, encrypt_ctx, encrypt, decrypt_ctx, decrypt, |
429 | 0 | mlength, dst, src); |
430 | 0 | ocb_digest (&ctx, key, encrypt_ctx, encrypt, tlength, digest.b); |
431 | 0 | return memeql_sec(digest.b, src + mlength, tlength); |
432 | 0 | } |