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