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_done.c
13 GCM implementation, Terminate the stream, by Tom St Denis
14 */
15 #include "tomcrypt_private.h"
16
17 #ifdef LTC_GCM_MODE
18
19 /**
20 Terminate a GCM stream
21 @param gcm The GCM state
22 @param tag [out] The destination for the MAC tag
23 @param taglen [in/out] The length of the MAC tag
24 @return CRYPT_OK on success
25 */
gcm_done(gcm_state * gcm,unsigned char * tag,unsigned long * taglen)26 int gcm_done(gcm_state *gcm,
27 unsigned char *tag, unsigned long *taglen)
28 {
29 unsigned long x;
30 int err;
31
32 LTC_ARGCHK(gcm != NULL);
33 LTC_ARGCHK(tag != NULL);
34 LTC_ARGCHK(taglen != NULL);
35
36 if (gcm->buflen > 16 || gcm->buflen < 0) {
37 return CRYPT_INVALID_ARG;
38 }
39
40 if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
41 return err;
42 }
43
44 if (gcm->mode == LTC_GCM_MODE_IV) {
45 /* let's process the IV */
46 if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err;
47 }
48
49 if (gcm->mode == LTC_GCM_MODE_AAD) {
50 /* let's process the AAD */
51 if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != CRYPT_OK) return err;
52 }
53
54 if (gcm->mode != LTC_GCM_MODE_TEXT) {
55 return CRYPT_INVALID_ARG;
56 }
57
58 /* handle remaining ciphertext */
59 if (gcm->buflen) {
60 gcm->pttotlen += gcm->buflen * CONST64(8);
61 gcm_mult_h(gcm, gcm->X);
62 }
63
64 /* length */
65 STORE64H(gcm->totlen, gcm->buf);
66 STORE64H(gcm->pttotlen, gcm->buf+8);
67 for (x = 0; x < 16; x++) {
68 gcm->X[x] ^= gcm->buf[x];
69 }
70 gcm_mult_h(gcm, gcm->X);
71
72 /* encrypt original counter */
73 if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) {
74 return err;
75 }
76 for (x = 0; x < 16 && x < *taglen; x++) {
77 tag[x] = gcm->buf[x] ^ gcm->X[x];
78 }
79 *taglen = x;
80
81 cipher_descriptor[gcm->cipher]->done(&gcm->K);
82
83 return CRYPT_OK;
84 }
85
86 #endif
87
88
89 /* ref: $Format:%D$ */
90 /* git commit: $Format:%H$ */
91 /* commit time: $Format:%ai$ */
92