1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 
4 /**
5    @file gcm_add_iv.c
6    GCM implementation, add IV data to the state, by Tom St Denis
7 */
8 #include "tomcrypt_private.h"
9 
10 #ifdef LTC_GCM_MODE
11 
12 /**
13   Add IV data to the GCM state
14   @param gcm    The GCM state
15   @param IV     The initial value data to add
16   @param IVlen  The length of the IV
17   @return CRYPT_OK on success
18  */
gcm_add_iv(gcm_state * gcm,const unsigned char * IV,unsigned long IVlen)19 int gcm_add_iv(gcm_state *gcm,
20                const unsigned char *IV,     unsigned long IVlen)
21 {
22    unsigned long x, y;
23    int           err;
24 
25    LTC_ARGCHK(gcm != NULL);
26    if (IVlen > 0) {
27       LTC_ARGCHK(IV  != NULL);
28    }
29 
30    /* must be in IV mode */
31    if (gcm->mode != LTC_GCM_MODE_IV) {
32       return CRYPT_INVALID_ARG;
33    }
34 
35    if (gcm->buflen >= 16 || gcm->buflen < 0) {
36       return CRYPT_INVALID_ARG;
37    }
38 
39    if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
40       return err;
41    }
42 
43 
44    /* trip the ivmode flag */
45    if (IVlen + gcm->buflen > 12) {
46       gcm->ivmode |= 1;
47    }
48 
49    x = 0;
50 #ifdef LTC_FAST
51    if (gcm->buflen == 0) {
52       for (x = 0; x < (IVlen & ~15); x += 16) {
53           for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
54               *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&IV[x + y]));
55           }
56           gcm_mult_h(gcm, gcm->X);
57           gcm->totlen += 128;
58       }
59       IV += x;
60    }
61 #endif
62 
63    /* start adding IV data to the state */
64    for (; x < IVlen; x++) {
65        gcm->buf[gcm->buflen++] = *IV++;
66 
67       if (gcm->buflen == 16) {
68          /* GF mult it */
69          for (y = 0; y < 16; y++) {
70              gcm->X[y] ^= gcm->buf[y];
71          }
72          gcm_mult_h(gcm, gcm->X);
73          gcm->buflen = 0;
74          gcm->totlen += 128;
75       }
76    }
77 
78    return CRYPT_OK;
79 }
80 
81 #endif
82 
83