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