1*042d53a7SEvalZero /* hmac.c - TinyCrypt implementation of the HMAC algorithm */
2*042d53a7SEvalZero
3*042d53a7SEvalZero /*
4*042d53a7SEvalZero * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
5*042d53a7SEvalZero *
6*042d53a7SEvalZero * Redistribution and use in source and binary forms, with or without
7*042d53a7SEvalZero * modification, are permitted provided that the following conditions are met:
8*042d53a7SEvalZero *
9*042d53a7SEvalZero * - Redistributions of source code must retain the above copyright notice,
10*042d53a7SEvalZero * this list of conditions and the following disclaimer.
11*042d53a7SEvalZero *
12*042d53a7SEvalZero * - Redistributions in binary form must reproduce the above copyright
13*042d53a7SEvalZero * notice, this list of conditions and the following disclaimer in the
14*042d53a7SEvalZero * documentation and/or other materials provided with the distribution.
15*042d53a7SEvalZero *
16*042d53a7SEvalZero * - Neither the name of Intel Corporation nor the names of its contributors
17*042d53a7SEvalZero * may be used to endorse or promote products derived from this software
18*042d53a7SEvalZero * without specific prior written permission.
19*042d53a7SEvalZero *
20*042d53a7SEvalZero * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21*042d53a7SEvalZero * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*042d53a7SEvalZero * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*042d53a7SEvalZero * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24*042d53a7SEvalZero * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25*042d53a7SEvalZero * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26*042d53a7SEvalZero * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*042d53a7SEvalZero * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*042d53a7SEvalZero * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*042d53a7SEvalZero * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30*042d53a7SEvalZero * POSSIBILITY OF SUCH DAMAGE.
31*042d53a7SEvalZero */
32*042d53a7SEvalZero
33*042d53a7SEvalZero #include <tinycrypt/hmac.h>
34*042d53a7SEvalZero #include <tinycrypt/constants.h>
35*042d53a7SEvalZero #include <tinycrypt/utils.h>
36*042d53a7SEvalZero
rekey(uint8_t * key,const uint8_t * new_key,unsigned int key_size)37*042d53a7SEvalZero static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
38*042d53a7SEvalZero {
39*042d53a7SEvalZero const uint8_t inner_pad = (uint8_t) 0x36;
40*042d53a7SEvalZero const uint8_t outer_pad = (uint8_t) 0x5c;
41*042d53a7SEvalZero unsigned int i;
42*042d53a7SEvalZero
43*042d53a7SEvalZero for (i = 0; i < key_size; ++i) {
44*042d53a7SEvalZero key[i] = inner_pad ^ new_key[i];
45*042d53a7SEvalZero key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i];
46*042d53a7SEvalZero }
47*042d53a7SEvalZero for (; i < TC_SHA256_BLOCK_SIZE; ++i) {
48*042d53a7SEvalZero key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad;
49*042d53a7SEvalZero }
50*042d53a7SEvalZero }
51*042d53a7SEvalZero
tc_hmac_set_key(TCHmacState_t ctx,const uint8_t * key,unsigned int key_size)52*042d53a7SEvalZero int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
53*042d53a7SEvalZero unsigned int key_size)
54*042d53a7SEvalZero {
55*042d53a7SEvalZero
56*042d53a7SEvalZero /* input sanity check: */
57*042d53a7SEvalZero if (ctx == (TCHmacState_t) 0 ||
58*042d53a7SEvalZero key == (const uint8_t *) 0 ||
59*042d53a7SEvalZero key_size == 0) {
60*042d53a7SEvalZero return TC_CRYPTO_FAIL;
61*042d53a7SEvalZero }
62*042d53a7SEvalZero
63*042d53a7SEvalZero const uint8_t dummy_key[key_size];
64*042d53a7SEvalZero struct tc_hmac_state_struct dummy_state;
65*042d53a7SEvalZero
66*042d53a7SEvalZero if (key_size <= TC_SHA256_BLOCK_SIZE) {
67*042d53a7SEvalZero /*
68*042d53a7SEvalZero * The next three lines consist of dummy calls just to avoid
69*042d53a7SEvalZero * certain timing attacks. Without these dummy calls,
70*042d53a7SEvalZero * adversaries would be able to learn whether the key_size is
71*042d53a7SEvalZero * greater than TC_SHA256_BLOCK_SIZE by measuring the time
72*042d53a7SEvalZero * consumed in this process.
73*042d53a7SEvalZero */
74*042d53a7SEvalZero (void)tc_sha256_init(&dummy_state.hash_state);
75*042d53a7SEvalZero (void)tc_sha256_update(&dummy_state.hash_state,
76*042d53a7SEvalZero dummy_key,
77*042d53a7SEvalZero key_size);
78*042d53a7SEvalZero (void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE],
79*042d53a7SEvalZero &dummy_state.hash_state);
80*042d53a7SEvalZero
81*042d53a7SEvalZero /* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */
82*042d53a7SEvalZero rekey(ctx->key, key, key_size);
83*042d53a7SEvalZero } else {
84*042d53a7SEvalZero (void)tc_sha256_init(&ctx->hash_state);
85*042d53a7SEvalZero (void)tc_sha256_update(&ctx->hash_state, key, key_size);
86*042d53a7SEvalZero (void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE],
87*042d53a7SEvalZero &ctx->hash_state);
88*042d53a7SEvalZero rekey(ctx->key,
89*042d53a7SEvalZero &ctx->key[TC_SHA256_DIGEST_SIZE],
90*042d53a7SEvalZero TC_SHA256_DIGEST_SIZE);
91*042d53a7SEvalZero }
92*042d53a7SEvalZero
93*042d53a7SEvalZero return TC_CRYPTO_SUCCESS;
94*042d53a7SEvalZero }
95*042d53a7SEvalZero
tc_hmac_init(TCHmacState_t ctx)96*042d53a7SEvalZero int tc_hmac_init(TCHmacState_t ctx)
97*042d53a7SEvalZero {
98*042d53a7SEvalZero
99*042d53a7SEvalZero /* input sanity check: */
100*042d53a7SEvalZero if (ctx == (TCHmacState_t) 0) {
101*042d53a7SEvalZero return TC_CRYPTO_FAIL;
102*042d53a7SEvalZero }
103*042d53a7SEvalZero
104*042d53a7SEvalZero (void) tc_sha256_init(&ctx->hash_state);
105*042d53a7SEvalZero (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE);
106*042d53a7SEvalZero
107*042d53a7SEvalZero return TC_CRYPTO_SUCCESS;
108*042d53a7SEvalZero }
109*042d53a7SEvalZero
tc_hmac_update(TCHmacState_t ctx,const void * data,unsigned int data_length)110*042d53a7SEvalZero int tc_hmac_update(TCHmacState_t ctx,
111*042d53a7SEvalZero const void *data,
112*042d53a7SEvalZero unsigned int data_length)
113*042d53a7SEvalZero {
114*042d53a7SEvalZero
115*042d53a7SEvalZero /* input sanity check: */
116*042d53a7SEvalZero if (ctx == (TCHmacState_t) 0) {
117*042d53a7SEvalZero return TC_CRYPTO_FAIL;
118*042d53a7SEvalZero }
119*042d53a7SEvalZero
120*042d53a7SEvalZero (void)tc_sha256_update(&ctx->hash_state, data, data_length);
121*042d53a7SEvalZero
122*042d53a7SEvalZero return TC_CRYPTO_SUCCESS;
123*042d53a7SEvalZero }
124*042d53a7SEvalZero
tc_hmac_final(uint8_t * tag,unsigned int taglen,TCHmacState_t ctx)125*042d53a7SEvalZero int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx)
126*042d53a7SEvalZero {
127*042d53a7SEvalZero
128*042d53a7SEvalZero /* input sanity check: */
129*042d53a7SEvalZero if (tag == (uint8_t *) 0 ||
130*042d53a7SEvalZero taglen != TC_SHA256_DIGEST_SIZE ||
131*042d53a7SEvalZero ctx == (TCHmacState_t) 0) {
132*042d53a7SEvalZero return TC_CRYPTO_FAIL;
133*042d53a7SEvalZero }
134*042d53a7SEvalZero
135*042d53a7SEvalZero (void) tc_sha256_final(tag, &ctx->hash_state);
136*042d53a7SEvalZero
137*042d53a7SEvalZero (void)tc_sha256_init(&ctx->hash_state);
138*042d53a7SEvalZero (void)tc_sha256_update(&ctx->hash_state,
139*042d53a7SEvalZero &ctx->key[TC_SHA256_BLOCK_SIZE],
140*042d53a7SEvalZero TC_SHA256_BLOCK_SIZE);
141*042d53a7SEvalZero (void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE);
142*042d53a7SEvalZero (void)tc_sha256_final(tag, &ctx->hash_state);
143*042d53a7SEvalZero
144*042d53a7SEvalZero /* destroy the current state */
145*042d53a7SEvalZero _set(ctx, 0, sizeof(*ctx));
146*042d53a7SEvalZero
147*042d53a7SEvalZero return TC_CRYPTO_SUCCESS;
148*042d53a7SEvalZero }
149