]> git.ipfire.org Git - thirdparty/nettle.git/blame - ocb.c
Update config.guess and config.sub to 2024-01-01 versions.
[thirdparty/nettle.git] / ocb.c
CommitLineData
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. */
48static inline uint64_t
49extract(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
58void
59ocb_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. */
68static void
69update_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
86static void
87pad_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
94void
95ocb_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
133static void
134ocb_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
176void
177ocb_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
219static void
220ocb_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. */
267static void
268ocb_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
320void
321ocb_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
352void
353ocb_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
385void
386ocb_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
399void
400ocb_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
415int
416ocb_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}