xref: /nrf52832-nimble/packages/NimBLE-latest/ext/tinycrypt/src/hmac.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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