/src/trezor-firmware/crypto/hmac.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * Copyright (c) 2013-2014 Tomas Dzetkulic |
3 | | * Copyright (c) 2013-2014 Pavol Rusnak |
4 | | * |
5 | | * Permission is hereby granted, free of charge, to any person obtaining |
6 | | * a copy of this software and associated documentation files (the "Software"), |
7 | | * to deal in the Software without restriction, including without limitation |
8 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 | | * and/or sell copies of the Software, and to permit persons to whom the |
10 | | * Software is furnished to do so, subject to the following conditions: |
11 | | * |
12 | | * The above copyright notice and this permission notice shall be included |
13 | | * in all copies or substantial portions of the Software. |
14 | | * |
15 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
16 | | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES |
19 | | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
20 | | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
21 | | * OTHER DEALINGS IN THE SOFTWARE. |
22 | | */ |
23 | | |
24 | | #include <string.h> |
25 | | |
26 | | #include "hmac.h" |
27 | | #include "memzero.h" |
28 | | #include "options.h" |
29 | | |
30 | | void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, |
31 | 233 | const uint32_t keylen) { |
32 | 233 | static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH]; |
33 | 233 | memzero(i_key_pad, SHA256_BLOCK_LENGTH); |
34 | 233 | if (keylen > SHA256_BLOCK_LENGTH) { |
35 | 76 | sha256_Raw(key, keylen, i_key_pad); |
36 | 157 | } else { |
37 | 157 | memcpy(i_key_pad, key, keylen); |
38 | 157 | } |
39 | 15.1k | for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) { |
40 | 14.9k | hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; |
41 | 14.9k | i_key_pad[i] ^= 0x36; |
42 | 14.9k | } |
43 | 233 | sha256_Init(&(hctx->ctx)); |
44 | 233 | sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH); |
45 | 233 | memzero(i_key_pad, sizeof(i_key_pad)); |
46 | 233 | } |
47 | | |
48 | | void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, |
49 | 17.9k | const uint32_t msglen) { |
50 | 17.9k | sha256_Update(&(hctx->ctx), msg, msglen); |
51 | 17.9k | } |
52 | | |
53 | 233 | void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) { |
54 | 233 | sha256_Final(&(hctx->ctx), hmac); |
55 | 233 | sha256_Init(&(hctx->ctx)); |
56 | 233 | sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH); |
57 | 233 | sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH); |
58 | 233 | sha256_Final(&(hctx->ctx), hmac); |
59 | 233 | memzero(hctx, sizeof(HMAC_SHA256_CTX)); |
60 | 233 | } |
61 | | |
62 | | void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, |
63 | 0 | const uint32_t msglen, uint8_t *hmac) { |
64 | 0 | static CONFIDENTIAL HMAC_SHA256_CTX hctx; |
65 | 0 | hmac_sha256_Init(&hctx, key, keylen); |
66 | 0 | hmac_sha256_Update(&hctx, msg, msglen); |
67 | 0 | hmac_sha256_Final(&hctx, hmac); |
68 | 0 | } |
69 | | |
70 | | void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, |
71 | 0 | uint32_t *opad_digest, uint32_t *ipad_digest) { |
72 | 0 | static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH / sizeof(uint32_t)]; |
73 | |
|
74 | 0 | memzero(key_pad, sizeof(key_pad)); |
75 | 0 | if (keylen > SHA256_BLOCK_LENGTH) { |
76 | 0 | static CONFIDENTIAL SHA256_CTX context; |
77 | 0 | sha256_Init(&context); |
78 | 0 | sha256_Update(&context, key, keylen); |
79 | 0 | sha256_Final(&context, (uint8_t *)key_pad); |
80 | 0 | } else { |
81 | 0 | memcpy(key_pad, key, keylen); |
82 | 0 | } |
83 | | |
84 | | /* compute o_key_pad and its digest */ |
85 | 0 | for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) { |
86 | 0 | uint32_t data = 0; |
87 | 0 | #if BYTE_ORDER == LITTLE_ENDIAN |
88 | 0 | REVERSE32(key_pad[i], data); |
89 | | #else |
90 | | data = key_pad[i]; |
91 | | #endif |
92 | 0 | key_pad[i] = data ^ 0x5c5c5c5c; |
93 | 0 | } |
94 | 0 | sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest); |
95 | | |
96 | | /* convert o_key_pad to i_key_pad and compute its digest */ |
97 | 0 | for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) { |
98 | 0 | key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636; |
99 | 0 | } |
100 | 0 | sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest); |
101 | 0 | memzero(key_pad, sizeof(key_pad)); |
102 | 0 | } |
103 | | |
104 | | void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, |
105 | 284 | const uint32_t keylen) { |
106 | 284 | static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH]; |
107 | 284 | memzero(i_key_pad, SHA512_BLOCK_LENGTH); |
108 | 284 | if (keylen > SHA512_BLOCK_LENGTH) { |
109 | 104 | sha512_Raw(key, keylen, i_key_pad); |
110 | 180 | } else { |
111 | 180 | memcpy(i_key_pad, key, keylen); |
112 | 180 | } |
113 | 36.6k | for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) { |
114 | 36.3k | hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; |
115 | 36.3k | i_key_pad[i] ^= 0x36; |
116 | 36.3k | } |
117 | 284 | sha512_Init(&(hctx->ctx)); |
118 | 284 | sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH); |
119 | 284 | memzero(i_key_pad, sizeof(i_key_pad)); |
120 | 284 | } |
121 | | |
122 | | void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, |
123 | 17.5k | const uint32_t msglen) { |
124 | 17.5k | sha512_Update(&(hctx->ctx), msg, msglen); |
125 | 17.5k | } |
126 | | |
127 | 284 | void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) { |
128 | 284 | sha512_Final(&(hctx->ctx), hmac); |
129 | 284 | sha512_Init(&(hctx->ctx)); |
130 | 284 | sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH); |
131 | 284 | sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH); |
132 | 284 | sha512_Final(&(hctx->ctx), hmac); |
133 | 284 | memzero(hctx, sizeof(HMAC_SHA512_CTX)); |
134 | 284 | } |
135 | | |
136 | | void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, |
137 | 0 | const uint32_t msglen, uint8_t *hmac) { |
138 | 0 | HMAC_SHA512_CTX hctx = {0}; |
139 | 0 | hmac_sha512_Init(&hctx, key, keylen); |
140 | 0 | hmac_sha512_Update(&hctx, msg, msglen); |
141 | 0 | hmac_sha512_Final(&hctx, hmac); |
142 | 0 | } |
143 | | |
144 | | void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, |
145 | 0 | uint64_t *opad_digest, uint64_t *ipad_digest) { |
146 | 0 | static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH / sizeof(uint64_t)]; |
147 | |
|
148 | 0 | memzero(key_pad, sizeof(key_pad)); |
149 | 0 | if (keylen > SHA512_BLOCK_LENGTH) { |
150 | 0 | static CONFIDENTIAL SHA512_CTX context; |
151 | 0 | sha512_Init(&context); |
152 | 0 | sha512_Update(&context, key, keylen); |
153 | 0 | sha512_Final(&context, (uint8_t *)key_pad); |
154 | 0 | } else { |
155 | 0 | memcpy(key_pad, key, keylen); |
156 | 0 | } |
157 | | |
158 | | /* compute o_key_pad and its digest */ |
159 | 0 | for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) { |
160 | 0 | uint64_t data = 0; |
161 | 0 | #if BYTE_ORDER == LITTLE_ENDIAN |
162 | 0 | REVERSE64(key_pad[i], data); |
163 | | #else |
164 | | data = key_pad[i]; |
165 | | #endif |
166 | 0 | key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c; |
167 | 0 | } |
168 | 0 | sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest); |
169 | | |
170 | | /* convert o_key_pad to i_key_pad and compute its digest */ |
171 | 0 | for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) { |
172 | 0 | key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636; |
173 | 0 | } |
174 | 0 | sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest); |
175 | 0 | memzero(key_pad, sizeof(key_pad)); |
176 | 0 | } |