1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file hmac_init.c
7   HMAC support, initialize state, Tom St Denis/Dobes Vandermeer
8 */
9 
10 #ifdef LTC_HMAC
11 
12 #define LTC_HMAC_BLOCKSIZE hash_descriptor[hash]->blocksize
13 
14 /**
15    Initialize an HMAC context.
16    @param hmac     The HMAC state
17    @param hash     The index of the hash you want to use
18    @param key      The secret key
19    @param keylen   The length of the secret key (octets)
20    @return CRYPT_OK if successful
21 */
hmac_init(hmac_state * hmac,int hash,const unsigned char * key,unsigned long keylen)22 int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)
23 {
24     unsigned char *buf;
25     unsigned long hashsize;
26     unsigned long i, z;
27     int err;
28 
29     LTC_ARGCHK(hmac != NULL);
30     LTC_ARGCHK(key  != NULL);
31 
32     /* valid hash? */
33     if ((err = hash_is_valid(hash)) != CRYPT_OK) {
34         return err;
35     }
36     hmac->hash = hash;
37     hashsize   = hash_descriptor[hash]->hashsize;
38 
39     /* valid key length? */
40     if (keylen == 0) {
41         return CRYPT_INVALID_KEYSIZE;
42     }
43 
44     /* allocate ram for buf */
45     buf = XMALLOC(LTC_HMAC_BLOCKSIZE);
46     if (buf == NULL) {
47        return CRYPT_MEM;
48     }
49 
50     /* check hash block fits */
51     if (sizeof(hmac->key) < LTC_HMAC_BLOCKSIZE) {
52         err = CRYPT_BUFFER_OVERFLOW;
53         goto LBL_ERR;
54     }
55 
56     /* (1) make sure we have a large enough key */
57     if(keylen > LTC_HMAC_BLOCKSIZE) {
58         z = LTC_HMAC_BLOCKSIZE;
59         if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {
60            goto LBL_ERR;
61         }
62         keylen = hashsize;
63     } else {
64         XMEMCPY(hmac->key, key, (size_t)keylen);
65     }
66 
67     if(keylen < LTC_HMAC_BLOCKSIZE) {
68        zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen));
69     }
70 
71     /* Create the initialization vector for step (3) */
72     for(i=0; i < LTC_HMAC_BLOCKSIZE;   i++) {
73        buf[i] = hmac->key[i] ^ 0x36;
74     }
75 
76     /* Pre-pend that to the hash data */
77     if ((err = hash_descriptor[hash]->init(&hmac->md)) != CRYPT_OK) {
78        goto LBL_ERR;
79     }
80 
81     if ((err = hash_descriptor[hash]->process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) {
82        goto LBL_ERR;
83     }
84 
85 LBL_ERR:
86 #ifdef LTC_CLEAN_STACK
87    zeromem(buf, LTC_HMAC_BLOCKSIZE);
88 #endif
89 
90    XFREE(buf);
91    return err;
92 }
93 
94 #endif
95