• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libtom / libtomcrypt / 12690005093

09 Jan 2025 12:36PM UTC coverage: 89.675% (-0.001%) from 89.676%
12690005093

push

github

web-flow
Merge pull request #319 from libtom/add/SIV

Add SIV

224 of 256 new or added lines in 2 files covered. (87.5%)

1 existing line in 1 file now uncovered.

16276 of 18150 relevant lines covered (89.67%)

2050165.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.1
/src/encauth/siv/siv.c
1
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2
/* SPDX-License-Identifier: Unlicense */
3
#include "tomcrypt_private.h"
4
#include <stdarg.h>
5

6
/**
7
  @file siv.c
8
  RFC 5297  SIV - Synthetic Initialization Vector, Steffen Jaeckel
9
*/
10

11
#ifdef LTC_SIV_MODE
12

13
/* RFC 5297 - Chapter 7 - Security Considerations
14
 *
15
 * [...] S2V must not be
16
 * passed more than 127 components.  Since SIV includes the plaintext as
17
 * a component to S2V, that limits the number of components of
18
 * associated data that can be safely passed to SIV to 126.
19
 */
20
static const unsigned long s_siv_max_aad_components = 126;
21

22
static LTC_INLINE void s_siv_dbl(unsigned char *inout)
80✔
23
{
24
   int y, mask, msb, len;
25

26
   /* setup the system */
27
   mask = 0x87;
28
   len = 16;
29

30
   /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */
31
   msb = inout[0] >> 7;
80✔
32

33
   /* shift left */
34
   for (y = 0; y < (len - 1); y++) {
1,280✔
35
      inout[y] = ((inout[y] << 1) | (inout[y + 1] >> 7)) & 255;
1,200✔
36
   }
37
   inout[len - 1] = ((inout[len - 1] << 1) ^ (msb ? mask : 0)) & 255;
80✔
38
}
80✔
39

40
static LTC_INLINE int s_siv_S2V_one(int cipher,
41
                    const unsigned char *key,    unsigned long keylen,
42
                          unsigned char *V,      unsigned long *Vlen)
43
{
44
   /* if n = 0 then
45
    *   return V = AES-CMAC(K, <one>)
46
    */
47
   unsigned char zero_or_one[16] = {0};
8,000✔
48
   zero_or_one[0] = 1;
8,000✔
49
   return omac_memory(cipher, key, keylen, zero_or_one, sizeof(zero_or_one), V, Vlen);
8,000✔
50
}
51

52
typedef struct siv_omac_ctx_t {
53
   omac_state omac;
54
   int cipher;
55
} siv_omac_ctx_t;
56

57
static LTC_INLINE int s_siv_ctx_init(int cipher,
58
                     const unsigned char *key,    unsigned long keylen,
59
                          siv_omac_ctx_t *ctx)
60
{
61
   ctx->cipher = cipher;
32✔
62
   return omac_init(&ctx->omac, cipher, key, keylen);
32✔
63
}
64

65
static LTC_INLINE int s_siv_omac_memory(siv_omac_ctx_t *ctx,
112✔
66
                                   const unsigned char *in,  unsigned long inlen,
67
                                         unsigned char *out, unsigned long *outlen)
68
{
69
   int err;
70
   omac_state omac = ctx->omac;
112✔
71
   if ((err = omac_process(&omac, in, inlen)) != CRYPT_OK) {
112✔
72
      return err;
73
   }
74
   err = omac_done(&omac, out, outlen);
112✔
75
   zeromem(&omac, sizeof(omac));
112✔
76
   return err;
112✔
77
}
78

79
static LTC_INLINE int s_siv_S2V_zero(siv_omac_ctx_t *ctx,
80
                                      unsigned char *D,      unsigned long *Dlen)
81
{
82
   /* D = AES-CMAC(K, <zero>) */
83
   const unsigned char zero_or_one[16] = {0};
32✔
84
   return s_siv_omac_memory(ctx, zero_or_one, sizeof(zero_or_one), D, Dlen);
16✔
85
}
86

87
static LTC_INLINE int s_siv_S2V_dbl_xor_cmac(siv_omac_ctx_t *ctx,
64✔
88
                                        const unsigned char *aad, unsigned long aadlen,
89
                                              unsigned char *D,   unsigned long Dlen)
90
{
91
   /* for i = 1 to n-1 do
92
    *   D = dbl(D) xor AES-CMAC(K, Si)
93
    * done
94
    */
95
   int err;
96
   unsigned char TMP[16];
97
   unsigned long i, TMPlen = sizeof(TMP);
64✔
98
   s_siv_dbl(D);
64✔
99
   if ((err = s_siv_omac_memory(ctx, aad, aadlen, TMP, &TMPlen)) != CRYPT_OK) {
64✔
100
      return err;
101
   }
102
   for (i = 0; i < Dlen; ++i) {
1,088✔
103
      D[i] ^= TMP[i];
1,024✔
104
   }
105
   return err;
106
}
107

108
static LTC_INLINE int s_siv_omac_memory_multi(siv_omac_ctx_t *ctx,
16✔
109
                                               unsigned char *out, unsigned long *outlen,
110
                                         const unsigned char *in,  unsigned long inlen,
111
                                                              ...)
112
{
113
   int err;
114
   va_list args;
115
   omac_state omac = ctx->omac;
16✔
116
   va_start(args, inlen);
16✔
117

118
   if ((err = omac_vprocess(&omac, in, inlen, args)) != CRYPT_OK) {
16✔
119
      return err;
120
   }
121
   err = omac_done(&omac, out, outlen);
16✔
122
   zeromem(&omac, sizeof(omac));
16✔
123
   return err;
16✔
124
}
125

126
static LTC_INLINE int s_siv_S2V_T(siv_omac_ctx_t *ctx,
32✔
127
                             const unsigned char *in,     unsigned long inlen,
128
                                   unsigned char *D,
129
                                   unsigned char *V,      unsigned long *Vlen)
130
{
131
   int err;
132
   unsigned long i;
133
   unsigned char T[16];
134

135
   /* if len(Sn) >= 128 then
136
    *   T = Sn xorend D
137
    * else
138
    *   T = dbl(D) xor pad(Sn)
139
    * fi
140
    */
141
   if (inlen >= 16) {
32✔
142
      XMEMCPY(T, &in[inlen - 16], 16);
16✔
143
      for(i = 0; i < 16; ++i) {
272✔
144
         T[i] ^= D[i];
256✔
145
      }
146
      err = s_siv_omac_memory_multi(ctx, V, Vlen, in, inlen - 16, T, 16uL, NULL);
16✔
147
   } else {
148
      s_siv_dbl(D);
16✔
149
      XMEMCPY(T, in, inlen);
150
      T[inlen] = 0x80;
16✔
151
      for (i = inlen + 1; i < 16; ++i) {
32✔
152
         T[i] = 0x0;
16✔
153
      }
154
      for(i = 0; i < 16; ++i) {
272✔
155
         T[i] ^= D[i];
256✔
156
      }
157

158
      err = s_siv_omac_memory(ctx, T, 16, V, Vlen);
16✔
159
   }
160
   return err;
32✔
161
}
162

163
static int s_siv_S2V(int cipher,
16✔
164
    const unsigned char *key,    unsigned long keylen,
165
    const unsigned char **ad,    unsigned long *adlen,
166
    const unsigned char *in,     unsigned long inlen,
167
          unsigned char *V,      unsigned long *Vlen)
168
{
169
   int err;
170
   unsigned char D[16];
171
   unsigned long Dlen = sizeof(D), n = 0;
16✔
172
   siv_omac_ctx_t ctx;
173

174
   if(ad == NULL || adlen == NULL || ad[0] == NULL || adlen[0] == 0) {
16✔
NEW
175
      err = s_siv_S2V_one(cipher, key, keylen, V, Vlen);
×
176
   } else {
177
      if ((err = s_siv_ctx_init(cipher, key, keylen, &ctx)) != CRYPT_OK) {
16✔
178
         return err;
179
      }
180
      Dlen = sizeof(D);
16✔
181
      if ((err = s_siv_S2V_zero(&ctx, D, &Dlen)) != CRYPT_OK) {
16✔
182
         return err;
183
      }
184

185
      while(ad[n] != NULL && adlen[n] != 0) {
48✔
186
         if (n >= s_siv_max_aad_components) {
32✔
187
            return CRYPT_INPUT_TOO_LONG;
188
         }
189
         if ((err = s_siv_S2V_dbl_xor_cmac(&ctx, ad[n], adlen[n], D, Dlen)) != CRYPT_OK) {
32✔
NEW
190
            return err;
×
191
         }
192
         n++;
32✔
193
      }
194

195
      err = s_siv_S2V_T(&ctx, in, inlen, D, V, Vlen);
16✔
196
   }
197

198
   return err;
199
}
200

201
static LTC_INLINE void s_siv_bitand(const unsigned char* V, unsigned char* Q)
8,032✔
202
{
203
   int n;
204
   XMEMSET(Q, 0xff, 16);
205
   Q[8] = Q[12] = 0x7f;
8,032✔
206
   for (n = 0; n < 16; ++n) {
136,544✔
207
      Q[n] &= V[n];
128,512✔
208
   }
209
}
8,032✔
210

211
static LTC_INLINE int s_ctr_crypt_memory(int   cipher,
8,032✔
212
                          const unsigned char *IV,
213
                          const unsigned char *key,           int keylen,
214
                          const unsigned char *in,
215
                                unsigned char *out, unsigned long len)
216
{
217
   int err;
218
   symmetric_CTR ctr;
219

220
   if ((err = ctr_start(cipher, IV, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN | 16, &ctr)) != CRYPT_OK) {
8,032✔
NEW
221
      goto out;
×
222
   }
223
   if ((err = ctr_encrypt(in, out, len, &ctr)) != CRYPT_OK) {
8,032✔
NEW
224
      goto out;
×
225
   }
226
   if ((err = ctr_done(&ctr)) != CRYPT_OK) {
8,032✔
NEW
227
      goto out;
×
228
   }
229

230
out:
8,032✔
231
   zeromem(&ctr, sizeof(ctr));
8,032✔
232
   return err;
8,032✔
233
}
234

235
typedef struct {
236
   unsigned char Q[16], V[16];
237
} siv_state;
238

239
/**
240
   SIV encrypt
241

242
   @param cipher     The index of the cipher desired
243
   @param key        The secret key to use
244
   @param keylen     The length of the secret key (octets)
245
   @param ad         An array of Associated Data pointers (must be NULL terminated)
246
   @param adlen      An array with the lengths of the Associated Data
247
   @param pt         The plaintext
248
   @param ptlen      The length of the plaintext
249
   @param ct         The ciphertext
250
   @param ctlen      [in/out] The length of the ciphertext
251
   @return CRYPT_OK if successful
252
*/
253
int siv_encrypt_memory(                int  cipher,
8✔
254
                       const unsigned char *key,    unsigned long  keylen,
255
                       const unsigned char *ad[],   unsigned long  adlen[],
256
                       const unsigned char *pt,     unsigned long  ptlen,
257
                             unsigned char *ct,     unsigned long *ctlen)
258
{
259
   int err;
260
   const unsigned char *K1, *K2;
261
   unsigned long Vlen;
262
   siv_state siv;
263

264
   LTC_ARGCHK(key    != NULL);
8✔
265
   LTC_ARGCHK(ad     != NULL);
8✔
266
   LTC_ARGCHK(adlen  != NULL);
8✔
267
   LTC_ARGCHK(pt     != NULL);
8✔
268
   LTC_ARGCHK(ct     != NULL);
8✔
269
   LTC_ARGCHK(ctlen  != NULL);
8✔
270

271
   if (ptlen + 16 < ptlen) {
8✔
272
      return CRYPT_OVERFLOW;
273
   }
274
   if (*ctlen < ptlen + 16) {
8✔
NEW
275
      *ctlen = ptlen + 16;
×
NEW
276
      return CRYPT_BUFFER_OVERFLOW;
×
277
   }
278
   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
8✔
279
      return err;
280
   }
281

282

283
   K1 = key;
284
   K2 = &key[keylen/2];
8✔
285

286
   Vlen = sizeof(siv.V);
8✔
287
   err = s_siv_S2V(cipher, K1, keylen/2, ad, adlen, pt, ptlen, siv.V, &Vlen);
8✔
288
#ifdef LTC_CLEAN_STACK
289
   burn_stack(3 * 16 + 7 * sizeof(unsigned long) + 1 * sizeof(void*));
290
#endif
291
   if (err != CRYPT_OK) {
8✔
292
      return err;
293
   }
294

295
   s_siv_bitand(siv.V, siv.Q);
8✔
296
   XMEMCPY(ct, siv.V, 16);
297
   ct += 16;
8✔
298

299
   if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, pt, ct, ptlen)) != CRYPT_OK) {
8✔
NEW
300
      zeromem(ct, ptlen + 16);
×
NEW
301
      goto out;
×
302
   }
303
   *ctlen = ptlen + 16;
8✔
304

305
out:
306
#ifdef LTC_CLEAN_STACK
307
   zeromem(&siv, sizeof(siv));
308
#endif
309

310
   return err;
311
}
312

313
/**
314
   SIV decrypt
315

316
   @param cipher     The index of the cipher desired
317
   @param key        The secret key to use
318
   @param keylen     The length of the secret key (octets)
319
   @param ad         An array of Associated Data pointers (must be NULL terminated)
320
   @param adlen      An array with the lengths of the Associated Data
321
   @param ct         The ciphertext
322
   @param ctlen      The length of the ciphertext
323
   @param pt         The plaintext
324
   @param ptlen      [in/out] The length of the plaintext
325
   @return CRYPT_OK if successful
326
*/
327
int siv_decrypt_memory(                int  cipher,
8✔
328
                       const unsigned char *key,    unsigned long  keylen,
329
                       const unsigned char *ad[],   unsigned long  adlen[],
330
                       const unsigned char *ct,     unsigned long  ctlen,
331
                             unsigned char *pt,     unsigned long *ptlen)
332
{
333
   int err;
334
   unsigned char *pt_work;
335
   const unsigned char *K1, *K2, *ct_work;
336
   unsigned long Vlen;
337
   siv_state siv;
338

339
   LTC_ARGCHK(key    != NULL);
8✔
340
   LTC_ARGCHK(ad     != NULL);
8✔
341
   LTC_ARGCHK(adlen  != NULL);
8✔
342
   LTC_ARGCHK(ct     != NULL);
8✔
343
   LTC_ARGCHK(pt     != NULL);
8✔
344
   LTC_ARGCHK(ptlen  != NULL);
8✔
345

346
   if (ctlen < 16) {
8✔
347
      return CRYPT_INVALID_ARG;
348
   }
349
   if (*ptlen < (ctlen - 16)) {
8✔
NEW
350
      *ptlen = ctlen - 16;
×
NEW
351
      return CRYPT_BUFFER_OVERFLOW;
×
352
   }
353

354
   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
8✔
355
      return err;
356
   }
357
   *ptlen = ctlen - 16;
8✔
358
   pt_work = XMALLOC(*ptlen);
8✔
359
   if (pt_work == NULL) {
8✔
360
      return CRYPT_MEM;
361
   }
362

363
   K1 = key;
364
   K2 = &key[keylen/2];
8✔
365

366
   ct_work = ct;
367
   s_siv_bitand(ct_work, siv.Q);
8✔
368
   ct_work += 16;
8✔
369

370
   if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, ct_work, pt_work, *ptlen)) != CRYPT_OK) {
8✔
NEW
371
      goto out;
×
372
   }
373
   Vlen = sizeof(siv.V);
8✔
374
   if ((err = s_siv_S2V(cipher, K1, keylen/2, ad, adlen, pt_work, *ptlen, siv.V, &Vlen)) != CRYPT_OK) {
8✔
NEW
375
      goto out;
×
376
   }
377

378
   err = XMEM_NEQ(siv.V, ct, Vlen);
8✔
379
   copy_or_zeromem(pt_work, pt, *ptlen, err);
8✔
380
out:
8✔
381
#ifdef LTC_CLEAN_STACK
382
   zeromem(&siv, sizeof(siv));
383
#endif
384
   zeromem(pt_work, *ptlen);
8✔
385
   XFREE(pt_work);
8✔
386

387
   return err;
8✔
388
}
389

390
/**
391
  Process an entire SIV packet in one call.
392

393
  @param cipher            The index of the cipher desired
394
  @param direction         Encrypt or Decrypt mode (LTC_ENCRYPT or LTC_DECRYPT)
395
  @param key               The secret key to use
396
  @param keylen            The length of the secret key (octets)
397
  @param in                The input
398
  @param inlen             The length of the input
399
  @param out               The output
400
  @param outlen            [in/out]  The max size and resulting size of the output
401
  @remark <...> is of the form <pointer, length> (void*, unsigned long) and contains the Associated Data
402
  @return CRYPT_OK on success
403
 */
404
int siv_memory(                int  cipher,           int  direction,
8,016✔
405
               const unsigned char *key,    unsigned long  keylen,
406
               const unsigned char *in,     unsigned long  inlen,
407
                     unsigned char *out,    unsigned long *outlen,
408
                                   ...)
409
{
410
   int err;
411
   va_list args;
412
   siv_state siv;
413
   unsigned char D[16], *in_buf = NULL, *out_work;
414
   const unsigned char *aad, *K1, *K2, *in_work;
415
   unsigned long n = 0, aadlen, Dlen = sizeof(D), Vlen = sizeof(siv.V), in_work_len;
8,016✔
416

417
   LTC_ARGCHK(key    != NULL);
8,016✔
418
   LTC_ARGCHK(in     != NULL);
8,016✔
419
   LTC_ARGCHK(out    != NULL);
8,016✔
420
   LTC_ARGCHK(outlen != NULL);
8,016✔
421

422
   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
8,016✔
423
      return err;
424
   }
425
   if (direction == LTC_ENCRYPT && *outlen < inlen + 16) {
8,016✔
NEW
426
      *outlen = inlen + 16;
×
NEW
427
      return CRYPT_BUFFER_OVERFLOW;
×
428
   } else if (direction == LTC_DECRYPT && (inlen < 16 || *outlen < inlen - 16)) {
8,016✔
NEW
429
      *outlen = inlen - 16;
×
NEW
430
      return CRYPT_BUFFER_OVERFLOW;
×
431
   }
432

433
   K1 = key;
434
   K2 = &key[keylen/2];
8,016✔
435
   in_work = in;
436
   in_work_len = inlen;
437
   out_work = out;
438

439
   if (direction == LTC_DECRYPT) {
8,016✔
440
      in_work_len -= 16;
4,008✔
441
      in_buf = XMALLOC(in_work_len);
4,008✔
442
      if (in_buf == NULL)
4,008✔
443
         return CRYPT_MEM;
444
      s_siv_bitand(in_work, siv.Q);
4,008✔
445
      in_work += 16;
4,008✔
446

447
      if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, in_work, in_buf, in_work_len)) != CRYPT_OK) {
4,008✔
NEW
448
         goto err_out;
×
449
      }
450
      in_work = in_buf;
451
   }
452

453
   va_start(args, outlen);
8,016✔
454
   aad = va_arg(args, const unsigned char*);
8,016✔
455
   aadlen = aad ? va_arg(args, unsigned long) : 0;
8,016✔
456
   if (aad == NULL || aadlen == 0) {
8,016✔
457
      if ((err = s_siv_S2V_one(cipher, K1, keylen/2, siv.V, &Vlen)) != CRYPT_OK) {
8,000✔
NEW
458
         goto err_out;
×
459
      }
460
   } else {
461
      siv_omac_ctx_t ctx;
462
      if ((err = s_siv_ctx_init(cipher, K1, keylen/2, &ctx)) != CRYPT_OK) {
16✔
NEW
463
         goto err_out;
×
464
      }
465
      if ((err = s_siv_S2V_zero(&ctx, D, &Dlen)) != CRYPT_OK) {
16✔
NEW
466
         goto err_out;
×
467
      }
468

469
      do {
470
         if (n >= s_siv_max_aad_components) {
32✔
471
            err = CRYPT_INPUT_TOO_LONG;
NEW
472
            goto err_out;
×
473
         }
474
         if ((err = s_siv_S2V_dbl_xor_cmac(&ctx, aad, aadlen, D, Dlen)) != CRYPT_OK) {
32✔
NEW
475
            goto err_out;
×
476
         }
477
         aad = va_arg(args, const unsigned char*);
32✔
478
         if (aad == NULL)
32✔
479
            break;
480
         aadlen = va_arg(args, unsigned long);
16✔
481
         n++;
16✔
482
      } while (aadlen);
16✔
483

484
      if ((err = s_siv_S2V_T(&ctx, in_work, in_work_len, D, siv.V, &Vlen)) != CRYPT_OK) {
16✔
NEW
485
         goto err_out;
×
486
      }
487
   }
488

489
   if (direction == LTC_DECRYPT) {
8,016✔
490
      err = XMEM_NEQ(siv.V, in, Vlen);
4,008✔
491
      copy_or_zeromem(in_work, out, in_work_len, err);
4,008✔
492
      *outlen = in_work_len;
4,008✔
493
   } else {
494
      s_siv_bitand(siv.V, siv.Q);
4,008✔
495
      XMEMCPY(out_work, siv.V, 16);
496
      out_work += 16;
4,008✔
497

498
      if ((err = s_ctr_crypt_memory(cipher, siv.Q, K2, keylen/2, in, out_work, inlen)) != CRYPT_OK) {
4,008✔
NEW
499
         zeromem(out, inlen + 16);
×
NEW
500
         goto err_out;
×
501
      }
502
      *outlen = inlen + 16;
4,008✔
503
   }
504
err_out:
8,016✔
505
   if (in_buf) {
8,016✔
506
      zeromem(in_buf, in_work_len);
4,008✔
507
      XFREE(in_buf);
4,008✔
508
   }
509
   va_end(args);
8,016✔
510
#ifdef LTC_CLEAN_STACK
511
   zeromem(D, sizeof(D));
512
   zeromem(&siv, sizeof(siv));
513
#endif
514
   return err;
8,016✔
515
}
516

517
int siv_test(void)
4✔
518
{
519
#ifndef LTC_TEST
520
   return CRYPT_NOP;
521
#else
522
   /*
523
    * RFC5297 - A.1.  Deterministic Authenticated Encryption Example
524
    */
525
   const unsigned char Key_A1[] =
4✔
526
      { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
527
        0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
528
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
529
        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
530
   const unsigned char AD_A1[] =
4✔
531
      { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
532
        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
533
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 };
534
   const unsigned char Plaintext_A1[] =
4✔
535
      { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
536
        0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
537
   const unsigned char output_A1[] =
4✔
538
      { 0x85, 0x63, 0x2d, 0x07, 0xc6, 0xe8, 0xf3, 0x7f,
539
        0x95, 0x0a, 0xcd, 0x32, 0x0a, 0x2e, 0xcc, 0x93,
540
        0x40, 0xc0, 0x2b, 0x96, 0x90, 0xc4, 0xdc, 0x04,
541
        0xda, 0xef, 0x7f, 0x6a, 0xfe, 0x5c };
542
   const unsigned char *ad_A1[] =
4✔
543
      { AD_A1, NULL };
544
   unsigned long adlen_A1[] =
4✔
545
      { sizeof(AD_A1), 0 };
546

547
   const unsigned char Key_A2[] =
4✔
548
      { 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
549
        0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
550
        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
551
        0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
552
   const unsigned char AD1_A2[] =
4✔
553
      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
554
        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
555
        0xde, 0xad, 0xda, 0xda, 0xde, 0xad, 0xda, 0xda,
556
        0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
557
        0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 };
558
   const unsigned char AD2_A2[] =
4✔
559
      { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
560
        0x90, 0xa0 };
561
   const unsigned char AD3_A2[] =
4✔
562
      { 0x09, 0xf9, 0x11, 0x02, 0x9d, 0x74, 0xe3, 0x5b,
563
        0xd8, 0x41, 0x56, 0xc5, 0x63, 0x56, 0x88, 0xc0 };
564
   const unsigned char Plaintext_A2[] =
4✔
565
      { 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
566
        0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x6c, 0x61,
567
        0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x74,
568
        0x6f, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
569
        0x74, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20,
570
        0x53, 0x49, 0x56, 0x2d, 0x41, 0x45, 0x53 };
571
   const unsigned char output_A2[] =
4✔
572
      { 0x7b, 0xdb, 0x6e, 0x3b, 0x43, 0x26, 0x67, 0xeb,
573
        0x06, 0xf4, 0xd1, 0x4b, 0xff, 0x2f, 0xbd, 0x0f,
574
        0xcb, 0x90, 0x0f, 0x2f, 0xdd, 0xbe, 0x40, 0x43,
575
        0x26, 0x60, 0x19, 0x65, 0xc8, 0x89, 0xbf, 0x17,
576
        0xdb, 0xa7, 0x7c, 0xeb, 0x09, 0x4f, 0xa6, 0x63,
577
        0xb7, 0xa3, 0xf7, 0x48, 0xba, 0x8a, 0xf8, 0x29,
578
        0xea, 0x64, 0xad, 0x54, 0x4a, 0x27, 0x2e, 0x9c,
579
        0x48, 0x5b, 0x62, 0xa3, 0xfd, 0x5c, 0x0d };
580
   const unsigned char *ad_A2[] =
4✔
581
      { AD1_A2, AD2_A2, AD3_A2, NULL };
582
   unsigned long adlen_A2[] =
4✔
583
      { sizeof(AD1_A2), sizeof(AD2_A2), sizeof(AD3_A2), 0 };
584

585
#define PL_PAIR(n) n, sizeof(n)
586
   struct {
587
      const unsigned char* Key;
588
            unsigned long  Keylen;
589
      const unsigned char* Plaintext;
590
            unsigned long  Plaintextlen;
591
      const          void* ADs;
592
                     void* ADlens;
593
      const unsigned char* output;
594
            unsigned long  outputlen;
595
      const          char* name;
596
   } siv_tests[] = {
4✔
597
     { PL_PAIR(Key_A1), PL_PAIR(Plaintext_A1), &ad_A1, &adlen_A1, PL_PAIR(output_A1), "RFC5297 - A.1.  Deterministic Authenticated Encryption Example" },
598
     { PL_PAIR(Key_A2), PL_PAIR(Plaintext_A2), &ad_A2, &adlen_A2, PL_PAIR(output_A2), "RFC5297 - A.2.  Nonce-Based Authenticated Encryption Example" }
599
   };
600
#undef PL_PAIR
601

602
   int err, cipher;
603
   unsigned n;
604
   unsigned long buflen, tmplen;
605
   unsigned char buf[MAX(sizeof(output_A1), sizeof(output_A2))];
606
   const unsigned long niter = 1000;
607
   unsigned char *tmpe, *tmpd;
608
   const unsigned long tmpmax = 16 + niter * 16;
4✔
609

610
   cipher = find_cipher("aes");
4✔
611

612
   for (n = 0; n < sizeof(siv_tests)/sizeof(siv_tests[0]); ++n) {
12✔
613
      buflen = sizeof(buf);
8✔
614
      if ((err = siv_encrypt_memory(cipher,
8✔
615
                             siv_tests[n].Key, siv_tests[n].Keylen,
616
                             (const unsigned char **)siv_tests[n].ADs, siv_tests[n].ADlens,
8✔
617
                             siv_tests[n].Plaintext, siv_tests[n].Plaintextlen,
618
                             buf, &buflen)) != CRYPT_OK) {
NEW
619
         return err;
×
620
      }
621
      if (compare_testvector(buf, buflen, siv_tests[n].output, siv_tests[n].outputlen, siv_tests[n].name, n) != 0) {
8✔
622
         return CRYPT_FAIL_TESTVECTOR;
623
      }
624
      buflen = sizeof(buf);
8✔
625
      if ((err = siv_decrypt_memory(cipher,
8✔
626
                             siv_tests[n].Key, siv_tests[n].Keylen,
627
                             (const unsigned char **)siv_tests[n].ADs, siv_tests[n].ADlens,
628
                             siv_tests[n].output, siv_tests[n].outputlen,
629
                             buf, &buflen)) != CRYPT_OK) {
NEW
630
         return err;
×
631
      }
632
      if (compare_testvector(buf, buflen, siv_tests[n].Plaintext, siv_tests[n].Plaintextlen, siv_tests[n].name, n + 0x1000) != 0) {
8✔
633
         return CRYPT_FAIL_TESTVECTOR;
634
      }
635
   }
636

637
   /* Testcase 0x2 */
638
   buflen = sizeof(buf);
4✔
639
   if ((err = siv_memory(cipher, LTC_ENCRYPT,
4✔
640
                         siv_tests[0].Key, siv_tests[0].Keylen,
641
                         siv_tests[0].Plaintext, siv_tests[0].Plaintextlen,
642
                         buf, &buflen,
643
                         AD_A1, sizeof(AD_A1),
644
                         NULL)) != CRYPT_OK) {
645
      return err;
646
   }
647
   if (compare_testvector(buf, buflen, siv_tests[0].output, siv_tests[0].outputlen, siv_tests[0].name, n) != 0) {
4✔
648
      return CRYPT_FAIL_TESTVECTOR;
649
   }
650
   /* Testcase 0x1002 */
651
   buflen = sizeof(buf);
4✔
652
   if ((err = siv_memory(cipher, LTC_DECRYPT,
4✔
653
                         siv_tests[0].Key, siv_tests[0].Keylen,
654
                         siv_tests[0].output, siv_tests[0].outputlen,
655
                         buf, &buflen,
656
                         AD_A1, sizeof(AD_A1),
657
                         NULL)) != CRYPT_OK) {
658
      return err;
659
   }
660
   if (compare_testvector(buf, buflen, siv_tests[0].Plaintext, siv_tests[0].Plaintextlen, siv_tests[0].name, n + 0x1000) != 0) {
4✔
661
      return CRYPT_FAIL_TESTVECTOR;
662
   }
663

664
   n++;
665

666
   /* Testcase 0x3 */
667
   buflen = sizeof(buf);
4✔
668
   if ((err = siv_memory(cipher, LTC_ENCRYPT,
4✔
669
                         siv_tests[1].Key, siv_tests[1].Keylen,
670
                         siv_tests[1].Plaintext, siv_tests[1].Plaintextlen,
671
                         buf, &buflen,
672
                         ad_A2[0], adlen_A2[0],
673
                         ad_A2[1], adlen_A2[1],
674
                         ad_A2[2], adlen_A2[2],
675
                         NULL)) != CRYPT_OK) {
676
      return err;
677
   }
678
   if (compare_testvector(buf, buflen, siv_tests[1].output, siv_tests[1].outputlen, siv_tests[1].name, n) != 0) {
4✔
679
      return CRYPT_FAIL_TESTVECTOR;
680
   }
681
   /* Testcase 0x1003 */
682
   buflen = sizeof(buf);
4✔
683
   if ((err = siv_memory(cipher, LTC_DECRYPT,
4✔
684
                         siv_tests[1].Key, siv_tests[1].Keylen,
685
                         siv_tests[1].output, siv_tests[1].outputlen,
686
                         buf, &buflen,
687
                         ad_A2[0], adlen_A2[0],
688
                         ad_A2[1], adlen_A2[1],
689
                         ad_A2[2], adlen_A2[2],
690
                         NULL)) != CRYPT_OK) {
691
      return err;
692
   }
693
   if (compare_testvector(buf, buflen, siv_tests[1].Plaintext, siv_tests[1].Plaintextlen, siv_tests[1].name, n + 0x1000) != 0) {
4✔
694
      return CRYPT_FAIL_TESTVECTOR;
695
   }
696

697
   tmpe = XCALLOC(1, tmpmax);
4✔
698
   if (tmpe == NULL) {
4✔
699
      return CRYPT_MEM;
700
   }
701
   tmpd = XCALLOC(1, tmpmax);
4✔
702
   if (tmpd == NULL) {
4✔
703
      err = CRYPT_MEM;
NEW
704
      goto out_tmpd;
×
705
   }
706
   tmplen = 16;
707
   for (n = 0; n < niter; ++n) {
4,004✔
708
      buflen = tmpmax;
4,000✔
709
      if ((err = siv_memory(cipher, LTC_ENCRYPT,
4,000✔
710
                            siv_tests[0].Key, siv_tests[0].Keylen,
711
                            tmpe, tmplen,
712
                            tmpe, &buflen,
713
                            NULL)) != CRYPT_OK) {
NEW
714
         goto out;
×
715
      }
716
      tmplen = buflen;
4,000✔
717
   }
718
   if (compare_testvector(&buflen, sizeof(buflen), &tmpmax, sizeof(tmpmax), "Multiple encrypt length", -(int)niter)) {
4✔
719
      err = CRYPT_FAIL_TESTVECTOR;
NEW
720
      goto out;
×
721
   }
722
   XMEMCPY(tmpd, tmpe, buflen);
4✔
723
   for (n = 0; n < niter; ++n) {
4,004✔
724
      buflen = tmpmax;
4,000✔
725
      if ((err = siv_memory(cipher, LTC_DECRYPT,
4,000✔
726
                            siv_tests[0].Key, siv_tests[0].Keylen,
727
                            tmpd, tmplen,
728
                            tmpd, &buflen,
729
                            NULL)) != CRYPT_OK) {
NEW
730
         goto out;
×
731
      }
732
      tmplen = buflen;
4,000✔
733
   }
734
   if (compare_testvector(tmpd, tmplen, tmpe, tmplen, "Multi decrypt", niter + 0x2000)) {
4✔
735
      err = CRYPT_FAIL_TESTVECTOR;
736
   }
737

738
out:
4✔
739
   XFREE(tmpd);
4✔
740
out_tmpd:
4✔
741
   XFREE(tmpe);
4✔
742

743
   return err;
4✔
744
#endif
745
}
746

747
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc