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