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