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 #include "tomcrypt_private.h"
11 
12 /**
13   @file hmac_done.c
14   HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer
15 */
16 
17 #ifdef LTC_HMAC
18 
19 #define LTC_HMAC_BLOCKSIZE hash_descriptor[hash]->blocksize
20 
21 /**
22    Terminate an HMAC session
23    @param hmac    The HMAC state
24    @param out     [out] The destination of the HMAC authentication tag
25    @param outlen  [in/out]  The max size and resulting size of the HMAC authentication tag
26    @return CRYPT_OK if successful
27 */
hmac_done(hmac_state * hmac,unsigned char * out,unsigned long * outlen)28 int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen)
29 {
30     unsigned char *buf, *isha;
31     unsigned long hashsize, i;
32     int hash, err;
33 
34     LTC_ARGCHK(hmac  != NULL);
35     LTC_ARGCHK(out   != NULL);
36 
37     /* test hash */
38     hash = hmac->hash;
39     if((err = hash_is_valid(hash)) != CRYPT_OK) {
40         return err;
41     }
42 
43     /* get the hash message digest size */
44     hashsize = hash_descriptor[hash]->hashsize;
45 
46     /* allocate buffers */
47     buf  = XMALLOC(LTC_HMAC_BLOCKSIZE);
48     isha = XMALLOC(hashsize);
49     if (buf == NULL || isha == NULL) {
50        if (buf != NULL) {
51           XFREE(buf);
52        }
53        if (isha != NULL) {
54           XFREE(isha);
55        }
56        return CRYPT_MEM;
57     }
58 
59     /* Get the hash of the first HMAC vector plus the data */
60     if ((err = hash_descriptor[hash]->done(&hmac->md, isha)) != CRYPT_OK) {
61        goto LBL_ERR;
62     }
63 
64     /* Create the second HMAC vector vector for step (3) */
65     for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) {
66         buf[i] = hmac->key[i] ^ 0x5C;
67     }
68 
69     /* Now calculate the "outer" hash for step (5), (6), and (7) */
70     if ((err = hash_descriptor[hash]->init(&hmac->md)) != CRYPT_OK) {
71        goto LBL_ERR;
72     }
73     if ((err = hash_descriptor[hash]->process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) {
74        goto LBL_ERR;
75     }
76     if ((err = hash_descriptor[hash]->process(&hmac->md, isha, hashsize)) != CRYPT_OK) {
77        goto LBL_ERR;
78     }
79     if ((err = hash_descriptor[hash]->done(&hmac->md, buf)) != CRYPT_OK) {
80        goto LBL_ERR;
81     }
82 
83     /* copy to output  */
84     for (i = 0; i < hashsize && i < *outlen; i++) {
85         out[i] = buf[i];
86     }
87     *outlen = i;
88 
89     err = CRYPT_OK;
90 LBL_ERR:
91 #ifdef LTC_CLEAN_STACK
92     zeromem(isha, hashsize);
93     zeromem(buf,  hashsize);
94     zeromem(hmac, sizeof(*hmac));
95 #endif
96 
97     XFREE(isha);
98     XFREE(buf);
99 
100     return err;
101 }
102 
103 #endif
104 
105 /* ref:         $Format:%D$ */
106 /* git commit:  $Format:%H$ */
107 /* commit time: $Format:%ai$ */
108