1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 
4 /**
5    @file gcm_add_aad.c
6    GCM implementation, Add AAD data to the stream, by Tom St Denis
7 */
8 #include "tomcrypt_private.h"
9 
10 #ifdef LTC_GCM_MODE
11 
12 /**
13   Add AAD to the GCM state
14   @param gcm       The GCM state
15   @param adata     The additional authentication data to add to the GCM state
16   @param adatalen  The length of the AAD data.
17   @return CRYPT_OK on success
18  */
gcm_add_aad(gcm_state * gcm,const unsigned char * adata,unsigned long adatalen)19 int gcm_add_aad(gcm_state *gcm,
20                const unsigned char *adata,  unsigned long adatalen)
21 {
22    unsigned long x;
23    int           err;
24 #ifdef LTC_FAST
25    unsigned long y;
26 #endif
27 
28    LTC_ARGCHK(gcm    != NULL);
29    if (adatalen > 0) {
30       LTC_ARGCHK(adata  != NULL);
31    }
32 
33    if (gcm->buflen > 16 || gcm->buflen < 0) {
34       return CRYPT_INVALID_ARG;
35    }
36 
37    if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
38       return err;
39    }
40 
41    /* in IV mode? */
42    if (gcm->mode == LTC_GCM_MODE_IV) {
43       /* IV length must be > 0 */
44       if (gcm->buflen == 0 && gcm->totlen == 0) return CRYPT_ERROR;
45       /* let's process the IV */
46       if (gcm->ivmode || gcm->buflen != 12) {
47          for (x = 0; x < (unsigned long)gcm->buflen; x++) {
48              gcm->X[x] ^= gcm->buf[x];
49          }
50          if (gcm->buflen) {
51             gcm->totlen += gcm->buflen * CONST64(8);
52             gcm_mult_h(gcm, gcm->X);
53          }
54 
55          /* mix in the length */
56          zeromem(gcm->buf, 8);
57          STORE64H(gcm->totlen, gcm->buf+8);
58          for (x = 0; x < 16; x++) {
59              gcm->X[x] ^= gcm->buf[x];
60          }
61          gcm_mult_h(gcm, gcm->X);
62 
63          /* copy counter out */
64          XMEMCPY(gcm->Y, gcm->X, 16);
65          zeromem(gcm->X, 16);
66       } else {
67          XMEMCPY(gcm->Y, gcm->buf, 12);
68          gcm->Y[12] = 0;
69          gcm->Y[13] = 0;
70          gcm->Y[14] = 0;
71          gcm->Y[15] = 1;
72       }
73       XMEMCPY(gcm->Y_0, gcm->Y, 16);
74       zeromem(gcm->buf, 16);
75       gcm->buflen = 0;
76       gcm->totlen = 0;
77       gcm->mode   = LTC_GCM_MODE_AAD;
78    }
79 
80    if (gcm->mode != LTC_GCM_MODE_AAD || gcm->buflen >= 16) {
81       return CRYPT_INVALID_ARG;
82    }
83 
84    x = 0;
85 #ifdef LTC_FAST
86    if (gcm->buflen == 0 && adatalen > 15) {
87       for (x = 0; x < (adatalen & ~15); x += 16) {
88           for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
89               *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&adata[x + y]));
90           }
91           gcm_mult_h(gcm, gcm->X);
92           gcm->totlen += 128;
93       }
94       adata += x;
95    }
96 #endif
97 
98 
99    /* start adding AAD data to the state */
100    for (; x < adatalen; x++) {
101       gcm->X[gcm->buflen++] ^= *adata++;
102 
103       if (gcm->buflen == 16) {
104          /* GF mult it */
105          gcm_mult_h(gcm, gcm->X);
106          gcm->buflen = 0;
107          gcm->totlen += 128;
108       }
109    }
110 
111    return CRYPT_OK;
112 }
113 #endif
114 
115