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