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