]>
Commit | Line | Data |
---|---|---|
9cf0e2d2 NM |
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 | #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 | { | |
51 | if (offset == 0) | |
52 | return u0; | |
53 | u0 = bswap64_if_le(u0); | |
54 | u1 = bswap64_if_le(u1); | |
55 | return bswap64_if_le((u0 << offset) | (u1 >> (64 - offset))); | |
56 | } | |
57 | ||
58 | void | |
59 | ocb_set_key (struct ocb_key *key, const void *cipher, nettle_cipher_func *f) | |
60 | { | |
61 | static const union nettle_block16 zero_block; | |
62 | f (cipher, OCB_BLOCK_SIZE, key->L[0].b, zero_block.b); | |
63 | block16_mulx_be (&key->L[1], &key->L[0]); | |
64 | block16_mulx_be (&key->L[2], &key->L[1]); | |
65 | } | |
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 | { | |
72 | if (i & 1) | |
73 | block16_xor (offset, &key->L[2]); | |
74 | else | |
75 | { | |
76 | assert (i > 0); | |
77 | union nettle_block16 diff; | |
78 | block16_mulx_be (&diff, &key->L[2]); | |
79 | for (i >>= 1; !(i&1); i >>= 1) | |
80 | block16_mulx_be (&diff, &diff); | |
81 | ||
82 | block16_xor (offset, &diff); | |
83 | } | |
84 | } | |
85 | ||
86 | static void | |
87 | pad_block (union nettle_block16 *block, size_t length, const uint8_t *data) | |
88 | { | |
89 | memcpy (block->b, data, length); | |
90 | block->b[length] = 0x80; | |
91 | memset (block->b + length + 1, 0, OCB_BLOCK_SIZE - 1 - length); | |
92 | } | |
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 | { | |
100 | union nettle_block16 top; | |
101 | uint64_t stretch; | |
102 | ||
103 | unsigned bottom; | |
104 | assert (nonce_length < 16); | |
105 | assert (tag_length > 0); | |
106 | assert (tag_length <= 16); | |
107 | ||
108 | /* Bit size, or zero for tag_length == 16 */ | |
109 | top.b[0] = (tag_length & 15) << 4; | |
110 | memset (top.b + 1, 0, 15 - nonce_length); | |
111 | top.b[15 - nonce_length] |= 1; | |
112 | memcpy (top.b + 16 - nonce_length, nonce, nonce_length); | |
113 | bottom = top.b[15] & 0x3f; | |
114 | top.b[15] &= 0xc0; | |
115 | ||
116 | f (cipher, OCB_BLOCK_SIZE, top.b, top.b); | |
117 | ||
118 | stretch = top.u64[0]; | |
119 | #if WORDS_BIGENDIAN | |
120 | stretch ^= (top.u64[0] << 8) | (top.u64[1] >> 56); | |
121 | #else | |
122 | stretch ^= (top.u64[0] >> 8) | (top.u64[1] << 56); | |
123 | #endif | |
124 | ||
125 | ctx->initial.u64[0] = extract(top.u64[0], top.u64[1], bottom); | |
126 | ctx->initial.u64[1] = extract(top.u64[1], stretch, bottom); | |
127 | ctx->sum.u64[0] = ctx->sum.u64[1] = 0; | |
128 | ctx->checksum.u64[0] = ctx->checksum.u64[1] = 0; | |
129 | ||
130 | ctx->data_count = ctx->message_count = 0; | |
131 | } | |
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 | { | |
138 | assert (n > 0); | |
139 | union nettle_block16 *prev; | |
140 | if (count & 1) | |
141 | prev = offset; | |
142 | else | |
143 | { | |
144 | /* Do a single block to align block count. */ | |
145 | count++; /* Always odd. */ | |
146 | block16_xor (offset, &key->L[2]); | |
147 | block16_set (&o[0], offset); | |
148 | prev = o; | |
149 | n--; o++; | |
150 | } | |
151 | ||
152 | for (; n >= 2; n -= 2, o += 2) | |
153 | { | |
154 | size_t i; | |
155 | 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 | block16_mulx_be (&o[0], &key->L[2]); | |
160 | for (i = count >> 1; !(i&1); i >>= 1) | |
161 | block16_mulx_be (&o[0], &o[0]); | |
162 | ||
163 | block16_xor (&o[0], prev); | |
164 | block16_xor3 (&o[1], &o[0], &key->L[2]); | |
165 | prev = &o[1]; | |
166 | } | |
167 | block16_set(offset, prev); | |
168 | ||
169 | if (n > 0) | |
170 | { | |
171 | update_offset (key, offset, ++count); | |
172 | block16_set (o, offset); | |
173 | } | |
174 | } | |
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 | { | |
181 | union nettle_block16 block[OCB_MAX_BLOCKS]; | |
182 | size_t n = length / OCB_BLOCK_SIZE; | |
183 | assert (ctx->message_count == 0); | |
184 | ||
185 | if (ctx->data_count == 0) | |
186 | ctx->offset.u64[0] = ctx->offset.u64[1] = 0; | |
187 | ||
188 | while (n > 0) | |
189 | { | |
190 | size_t size, i; | |
191 | size_t blocks = (n <= OCB_MAX_BLOCKS) ? n | |
192 | : OCB_MAX_BLOCKS - 1 + (ctx->data_count & 1); | |
193 | ||
194 | ocb_fill_n (key, &ctx->offset, ctx->data_count, blocks, block); | |
195 | ctx->data_count += blocks; | |
196 | ||
197 | size = blocks * OCB_BLOCK_SIZE; | |
198 | memxor (block[0].b, data, size); | |
199 | f (cipher, size, block[0].b, block[0].b); | |
200 | for (i = 0; i < blocks; i++) | |
201 | block16_xor(&ctx->sum, &block[i]); | |
202 | ||
203 | n -= blocks; data += size; | |
204 | } | |
205 | ||
206 | length &= 15; | |
207 | if (length > 0) | |
208 | { | |
209 | union nettle_block16 block; | |
210 | pad_block (&block, length, data); | |
211 | block16_xor (&ctx->offset, &key->L[0]); | |
212 | block16_xor (&block, &ctx->offset); | |
213 | ||
214 | f (cipher, OCB_BLOCK_SIZE, block.b, block.b); | |
215 | block16_xor (&ctx->sum, &block); | |
216 | } | |
217 | } | |
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 | { | |
224 | union nettle_block16 o[OCB_MAX_BLOCKS], block[OCB_MAX_BLOCKS]; | |
225 | size_t size; | |
226 | ||
227 | while (n > 0) | |
228 | { | |
229 | size_t blocks = (n <= OCB_MAX_BLOCKS) ? n | |
230 | : OCB_MAX_BLOCKS - 1 + (ctx->message_count & 1); | |
231 | ||
232 | ocb_fill_n (key, &ctx->offset, ctx->message_count, blocks, o); | |
867a4548 | 233 | ctx->message_count += blocks; |
9cf0e2d2 NM |
234 | |
235 | size = blocks * OCB_BLOCK_SIZE; | |
236 | memxor3 (block[0].b, o[0].b, src, size); | |
237 | f (cipher, size, block[0].b, block[0].b); | |
238 | memxor3 (dst, block[0].b, o[0].b, size); | |
239 | ||
867a4548 | 240 | n -= blocks; src += size; dst += size; |
9cf0e2d2 NM |
241 | } |
242 | } | |
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 | # define MEM_ROTATE_RIGHT(c, s0, s1) do { \ | |
253 | uint64_t __rotate_t = ((s0) << (8*(c))) | ((s1) >> (64-8*(c))); \ | |
254 | (s1) = ((s1) << (8*(c))) | ((s0) >> (64-8*(c))); \ | |
255 | (s0) = __rotate_t; \ | |
256 | } 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 | # 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 | { | |
271 | unsigned initial; | |
272 | uint64_t edge_word = 0; | |
273 | uint64_t s0, s1; | |
274 | ||
275 | if (n == 1) | |
276 | { | |
277 | memxor (checksum->b, src, OCB_BLOCK_SIZE); | |
278 | return; | |
279 | } | |
280 | ||
281 | /* Initial unaligned bytes. */ | |
282 | initial = -(uintptr_t) src & 7; | |
283 | ||
284 | if (initial > 0) | |
285 | { | |
286 | /* Input not 64-bit aligned. Read initial bytes. */ | |
287 | unsigned i; | |
288 | /* Edge word is read in big-endian order */ | |
289 | for (i = initial; i > 0; i--) | |
290 | edge_word = (edge_word << 8) + *src++; | |
291 | n--; | |
292 | } | |
293 | ||
294 | /* Now src is 64-bit aligned, so do 64-bit reads. */ | |
295 | for (s0 = s1 = 0 ; n > 0; n--, src += OCB_BLOCK_SIZE) | |
296 | { | |
297 | s0 ^= ((const uint64_t *) src)[0]; | |
298 | s1 ^= ((const uint64_t *) src)[1]; | |
299 | } | |
300 | if (initial > 0) | |
301 | { | |
302 | unsigned i; | |
303 | uint64_t mask; | |
304 | s0 ^= ((const uint64_t *) src)[0]; | |
305 | for (i = 8 - initial, src += 8; i > 0; i--) | |
306 | edge_word = (edge_word << 8) + *src++; | |
307 | ||
308 | /* Rotate [s0, s1] right initial bytes. */ | |
309 | MEM_ROTATE_RIGHT(initial, s0, s1); | |
310 | /* Add in the edge bytes. */ | |
311 | mask = MEM_MASK(initial); | |
312 | edge_word = bswap64_if_le (edge_word); | |
313 | s0 ^= (edge_word & mask); | |
314 | s1 ^= (edge_word & ~mask); | |
315 | } | |
316 | checksum->u64[0] ^= s0; | |
317 | checksum->u64[1] ^= s1; | |
318 | } | |
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 | { | |
325 | size_t n = length / OCB_BLOCK_SIZE; | |
326 | ||
327 | if (ctx->message_count == 0) | |
328 | ctx->offset = ctx->initial; | |
329 | ||
330 | if (n > 0) | |
331 | { | |
332 | ocb_checksum_n (&ctx->checksum, n, src); | |
333 | ocb_crypt_n (ctx, key, cipher, f, n, dst, src); | |
334 | length &= 15; | |
335 | } | |
336 | if (length > 0) | |
337 | { | |
338 | union nettle_block16 block; | |
339 | ||
340 | src += n*OCB_BLOCK_SIZE; dst += n*OCB_BLOCK_SIZE; | |
341 | ||
342 | pad_block (&block, length, src); | |
343 | block16_xor (&ctx->checksum, &block); | |
344 | ||
345 | block16_xor (&ctx->offset, &key->L[0]); | |
346 | f (cipher, OCB_BLOCK_SIZE, block.b, ctx->offset.b); | |
347 | memxor3 (dst, block.b, src, length); | |
348 | ctx->message_count++; | |
349 | } | |
350 | } | |
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 | { | |
358 | size_t n = length / OCB_BLOCK_SIZE; | |
359 | ||
360 | if (ctx->message_count == 0) | |
361 | ctx->offset = ctx->initial; | |
362 | ||
363 | if (n > 0) | |
364 | { | |
365 | ocb_crypt_n (ctx, key, decrypt_ctx, decrypt, n, dst, src); | |
366 | ocb_checksum_n (&ctx->checksum, n, dst); | |
367 | length &= 15; | |
368 | } | |
369 | if (length > 0) | |
370 | { | |
371 | union nettle_block16 block; | |
372 | ||
373 | src += n*OCB_BLOCK_SIZE; dst += n*OCB_BLOCK_SIZE; | |
374 | ||
375 | block16_xor (&ctx->offset, &key->L[0]); | |
376 | encrypt (encrypt_ctx, OCB_BLOCK_SIZE, block.b, ctx->offset.b); | |
377 | memxor3 (dst, block.b, src, length); | |
378 | ||
379 | pad_block (&block, length, dst); | |
380 | block16_xor (&ctx->checksum, &block); | |
381 | ctx->message_count++; | |
382 | } | |
383 | } | |
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 | { | |
390 | union nettle_block16 block; | |
391 | assert (length <= OCB_DIGEST_SIZE); | |
392 | block16_xor3 (&block, &key->L[1], | |
393 | (ctx->message_count > 0) ? &ctx->offset : &ctx->initial); | |
394 | block16_xor (&block, &ctx->checksum); | |
395 | f (cipher, OCB_BLOCK_SIZE, block.b, block.b); | |
396 | memxor3 (digest, block.b, ctx->sum.b, length); | |
397 | } | |
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 | { | |
407 | struct ocb_ctx ctx; | |
408 | assert (clength >= tlength); | |
409 | ocb_set_nonce (&ctx, cipher, f, tlength, nlength, nonce); | |
410 | ocb_update (&ctx, key, cipher, f, alength, adata); | |
411 | ocb_encrypt (&ctx, key, cipher, f, clength - tlength, dst, src); | |
412 | ocb_digest (&ctx, key, cipher, f, tlength, dst + clength - tlength); | |
413 | } | |
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 | { | |
424 | struct ocb_ctx ctx; | |
425 | union nettle_block16 digest; | |
426 | ocb_set_nonce (&ctx, encrypt_ctx, encrypt, tlength, nlength, nonce); | |
427 | ocb_update (&ctx, key, encrypt_ctx, encrypt, alength, adata); | |
428 | ocb_decrypt (&ctx, key, encrypt_ctx, encrypt, decrypt_ctx, decrypt, | |
429 | mlength, dst, src); | |
430 | ocb_digest (&ctx, key, encrypt_ctx, encrypt, tlength, digest.b); | |
431 | return memeql_sec(digest.b, src + mlength, tlength); | |
432 | } |