]> pd.if.org Git - zpackage/blob - libtomcrypt/src/encauth/gcm/gcm_done.c
commit files needed for zpm-fetchurl
[zpackage] / libtomcrypt / src / encauth / gcm / gcm_done.c
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2  *
3  * LibTomCrypt is a library that provides various cryptographic
4  * algorithms in a highly modular and flexible manner.
5  *
6  * The library is free for all purposes without any express
7  * guarantee it works.
8  */
9
10 /**
11    @file gcm_done.c
12    GCM implementation, Terminate the stream, by Tom St Denis
13 */
14 #include "tomcrypt.h"
15
16 #ifdef LTC_GCM_MODE
17
18 /**
19   Terminate a GCM stream
20   @param gcm     The GCM state
21   @param tag     [out] The destination for the MAC tag
22   @param taglen  [in/out]  The length of the MAC tag
23   @return CRYPT_OK on success
24  */
25 int gcm_done(gcm_state *gcm,
26                      unsigned char *tag,    unsigned long *taglen)
27 {
28    unsigned long x;
29    int err;
30
31    LTC_ARGCHK(gcm     != NULL);
32    LTC_ARGCHK(tag     != NULL);
33    LTC_ARGCHK(taglen  != NULL);
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    if (gcm->mode == LTC_GCM_MODE_IV) {
44       /* let's process the IV */
45       if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err;
46    }
47
48    if (gcm->mode == LTC_GCM_MODE_AAD) {
49       /* let's process the AAD */
50       if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != CRYPT_OK) return err;
51    }
52
53    if (gcm->mode != LTC_GCM_MODE_TEXT) {
54       return CRYPT_INVALID_ARG;
55    }
56
57    /* handle remaining ciphertext */
58    if (gcm->buflen) {
59       gcm->pttotlen += gcm->buflen * CONST64(8);
60       gcm_mult_h(gcm, gcm->X);
61    }
62
63    /* length */
64    STORE64H(gcm->totlen, gcm->buf);
65    STORE64H(gcm->pttotlen, gcm->buf+8);
66    for (x = 0; x < 16; x++) {
67        gcm->X[x] ^= gcm->buf[x];
68    }
69    gcm_mult_h(gcm, gcm->X);
70
71    /* encrypt original counter */
72    if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) {
73       return err;
74    }
75    for (x = 0; x < 16 && x < *taglen; x++) {
76        tag[x] = gcm->buf[x] ^ gcm->X[x];
77    }
78    *taglen = x;
79
80    cipher_descriptor[gcm->cipher].done(&gcm->K);
81
82    return CRYPT_OK;
83 }
84
85 #endif
86
87
88 /* ref:         $Format:%D$ */
89 /* git commit:  $Format:%H$ */
90 /* commit time: $Format:%ai$ */