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