1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 /**
5 @file gcm_done.c
6 GCM implementation, Terminate the stream, by Tom St Denis
7 */
8 #include "tomcrypt_private.h"
9
10 #ifdef LTC_GCM_MODE
11
12 /**
13 Terminate a GCM stream
14 @param gcm The GCM state
15 @param tag [out] The destination for the MAC tag
16 @param taglen [in/out] The length of the MAC tag
17 @return CRYPT_OK on success
18 */
gcm_done(gcm_state * gcm,unsigned char * tag,unsigned long * taglen)19 int gcm_done(gcm_state *gcm,
20 unsigned char *tag, unsigned long *taglen)
21 {
22 unsigned long x;
23 int err;
24
25 LTC_ARGCHK(gcm != NULL);
26 LTC_ARGCHK(tag != NULL);
27 LTC_ARGCHK(taglen != NULL);
28
29 if (gcm->buflen > 16 || gcm->buflen < 0) {
30 return CRYPT_INVALID_ARG;
31 }
32
33 if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
34 return err;
35 }
36
37 if (gcm->mode == LTC_GCM_MODE_IV) {
38 /* let's process the IV */
39 if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err;
40 }
41
42 if (gcm->mode == LTC_GCM_MODE_AAD) {
43 /* let's process the AAD */
44 if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != CRYPT_OK) return err;
45 }
46
47 if (gcm->mode != LTC_GCM_MODE_TEXT) {
48 return CRYPT_INVALID_ARG;
49 }
50
51 /* handle remaining ciphertext */
52 if (gcm->buflen) {
53 gcm->pttotlen += gcm->buflen * CONST64(8);
54 gcm_mult_h(gcm, gcm->X);
55 }
56
57 /* length */
58 STORE64H(gcm->totlen, gcm->buf);
59 STORE64H(gcm->pttotlen, gcm->buf+8);
60 for (x = 0; x < 16; x++) {
61 gcm->X[x] ^= gcm->buf[x];
62 }
63 gcm_mult_h(gcm, gcm->X);
64
65 /* encrypt original counter */
66 if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) {
67 return err;
68 }
69 for (x = 0; x < 16 && x < *taglen; x++) {
70 tag[x] = gcm->buf[x] ^ gcm->X[x];
71 }
72 *taglen = x;
73
74 cipher_descriptor[gcm->cipher]->done(&gcm->K);
75
76 return CRYPT_OK;
77 }
78
79 #endif
80
81