/src/boringssl/crypto/fipsmodule/hmac/hmac.c.inc
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | | * All rights reserved. |
3 | | * |
4 | | * This package is an SSL implementation written |
5 | | * by Eric Young (eay@cryptsoft.com). |
6 | | * The implementation was written so as to conform with Netscapes SSL. |
7 | | * |
8 | | * This library is free for commercial and non-commercial use as long as |
9 | | * the following conditions are aheared to. The following conditions |
10 | | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | | * included with this distribution is covered by the same copyright terms |
13 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | | * |
15 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | | * the code are not to be removed. |
17 | | * If this package is used in a product, Eric Young should be given attribution |
18 | | * as the author of the parts of the library used. |
19 | | * This can be in the form of a textual message at program startup or |
20 | | * in documentation (online or textual) provided with the package. |
21 | | * |
22 | | * Redistribution and use in source and binary forms, with or without |
23 | | * modification, are permitted provided that the following conditions |
24 | | * are met: |
25 | | * 1. Redistributions of source code must retain the copyright |
26 | | * notice, this list of conditions and the following disclaimer. |
27 | | * 2. Redistributions in binary form must reproduce the above copyright |
28 | | * notice, this list of conditions and the following disclaimer in the |
29 | | * documentation and/or other materials provided with the distribution. |
30 | | * 3. All advertising materials mentioning features or use of this software |
31 | | * must display the following acknowledgement: |
32 | | * "This product includes cryptographic software written by |
33 | | * Eric Young (eay@cryptsoft.com)" |
34 | | * The word 'cryptographic' can be left out if the rouines from the library |
35 | | * being used are not cryptographic related :-). |
36 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | | * the apps directory (application code) you must include an acknowledgement: |
38 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | | * |
40 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | | * SUCH DAMAGE. |
51 | | * |
52 | | * The licence and distribution terms for any publically available version or |
53 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | | * copied and put under another distribution licence |
55 | | * [including the GNU Public Licence.] */ |
56 | | |
57 | | #include <openssl/hmac.h> |
58 | | |
59 | | #include <assert.h> |
60 | | #include <string.h> |
61 | | |
62 | | #include <openssl/digest.h> |
63 | | #include <openssl/mem.h> |
64 | | |
65 | | #include "../../internal.h" |
66 | | #include "../service_indicator/internal.h" |
67 | | |
68 | | |
69 | | uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len, |
70 | | const uint8_t *data, size_t data_len, uint8_t *out, |
71 | 73 | unsigned int *out_len) { |
72 | 73 | HMAC_CTX ctx; |
73 | 73 | HMAC_CTX_init(&ctx); |
74 | | |
75 | | // The underlying hash functions should not set the FIPS service indicator |
76 | | // until all operations have completed. |
77 | 73 | FIPS_service_indicator_lock_state(); |
78 | 73 | const int ok = HMAC_Init_ex(&ctx, key, key_len, evp_md, NULL) && |
79 | 73 | HMAC_Update(&ctx, data, data_len) && |
80 | 73 | HMAC_Final(&ctx, out, out_len); |
81 | 73 | FIPS_service_indicator_unlock_state(); |
82 | | |
83 | 73 | HMAC_CTX_cleanup(&ctx); |
84 | | |
85 | 73 | if (!ok) { |
86 | 0 | return NULL; |
87 | 0 | } |
88 | | |
89 | 73 | HMAC_verify_service_indicator(evp_md); |
90 | 73 | return out; |
91 | 73 | } |
92 | | |
93 | 77.9k | void HMAC_CTX_init(HMAC_CTX *ctx) { |
94 | 77.9k | ctx->md = NULL; |
95 | 77.9k | EVP_MD_CTX_init(&ctx->i_ctx); |
96 | 77.9k | EVP_MD_CTX_init(&ctx->o_ctx); |
97 | 77.9k | EVP_MD_CTX_init(&ctx->md_ctx); |
98 | 77.9k | } |
99 | | |
100 | 38.7k | HMAC_CTX *HMAC_CTX_new(void) { |
101 | 38.7k | HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX)); |
102 | 38.7k | if (ctx != NULL) { |
103 | 38.7k | HMAC_CTX_init(ctx); |
104 | 38.7k | } |
105 | 38.7k | return ctx; |
106 | 38.7k | } |
107 | | |
108 | 40.2k | void HMAC_CTX_cleanup(HMAC_CTX *ctx) { |
109 | 40.2k | EVP_MD_CTX_cleanup(&ctx->i_ctx); |
110 | 40.2k | EVP_MD_CTX_cleanup(&ctx->o_ctx); |
111 | 40.2k | EVP_MD_CTX_cleanup(&ctx->md_ctx); |
112 | 40.2k | OPENSSL_cleanse(ctx, sizeof(HMAC_CTX)); |
113 | 40.2k | } |
114 | | |
115 | 0 | void HMAC_CTX_cleanse(HMAC_CTX *ctx) { |
116 | 0 | EVP_MD_CTX_cleanse(&ctx->i_ctx); |
117 | 0 | EVP_MD_CTX_cleanse(&ctx->o_ctx); |
118 | 0 | EVP_MD_CTX_cleanse(&ctx->md_ctx); |
119 | 0 | OPENSSL_cleanse(ctx, sizeof(HMAC_CTX)); |
120 | 0 | } |
121 | | |
122 | 38.7k | void HMAC_CTX_free(HMAC_CTX *ctx) { |
123 | 38.7k | if (ctx == NULL) { |
124 | 0 | return; |
125 | 0 | } |
126 | | |
127 | 38.7k | HMAC_CTX_cleanup(ctx); |
128 | 38.7k | OPENSSL_free(ctx); |
129 | 38.7k | } |
130 | | |
131 | | int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, |
132 | 16.5k | const EVP_MD *md, ENGINE *impl) { |
133 | 16.5k | int ret = 0; |
134 | 16.5k | FIPS_service_indicator_lock_state(); |
135 | | |
136 | 16.5k | if (md == NULL) { |
137 | 15.5k | md = ctx->md; |
138 | 15.5k | } |
139 | | |
140 | | // If either |key| is non-NULL or |md| has changed, initialize with a new key |
141 | | // rather than rewinding the previous one. |
142 | | // |
143 | | // TODO(davidben,eroman): Passing the previous |md| with a NULL |key| is |
144 | | // ambiguous between using the empty key and reusing the previous key. There |
145 | | // exist callers which intend the latter, but the former is an awkward edge |
146 | | // case. Fix to API to avoid this. |
147 | 16.5k | if (md != ctx->md || key != NULL) { |
148 | 1.00k | uint8_t pad[EVP_MAX_MD_BLOCK_SIZE]; |
149 | 1.00k | uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE]; |
150 | 1.00k | unsigned key_block_len; |
151 | | |
152 | 1.00k | size_t block_size = EVP_MD_block_size(md); |
153 | 1.00k | assert(block_size <= sizeof(key_block)); |
154 | 1.00k | assert(EVP_MD_size(md) <= block_size); |
155 | 1.00k | if (block_size < key_len) { |
156 | | // Long keys are hashed. |
157 | 773 | if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl) || |
158 | 773 | !EVP_DigestUpdate(&ctx->md_ctx, key, key_len) || |
159 | 773 | !EVP_DigestFinal_ex(&ctx->md_ctx, key_block, &key_block_len)) { |
160 | 0 | goto out; |
161 | 0 | } |
162 | 773 | } else { |
163 | 232 | assert(key_len <= sizeof(key_block)); |
164 | 232 | OPENSSL_memcpy(key_block, key, key_len); |
165 | 232 | key_block_len = (unsigned)key_len; |
166 | 232 | } |
167 | | // Keys are then padded with zeros. |
168 | 1.00k | OPENSSL_memset(key_block + key_block_len, 0, block_size - key_block_len); |
169 | | |
170 | 81.9k | for (size_t i = 0; i < block_size; i++) { |
171 | 80.8k | pad[i] = 0x36 ^ key_block[i]; |
172 | 80.8k | } |
173 | 1.00k | if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) || |
174 | 1.00k | !EVP_DigestUpdate(&ctx->i_ctx, pad, block_size)) { |
175 | 0 | goto out; |
176 | 0 | } |
177 | | |
178 | 81.9k | for (size_t i = 0; i < block_size; i++) { |
179 | 80.8k | pad[i] = 0x5c ^ key_block[i]; |
180 | 80.8k | } |
181 | 1.00k | if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) || |
182 | 1.00k | !EVP_DigestUpdate(&ctx->o_ctx, pad, block_size)) { |
183 | 0 | goto out; |
184 | 0 | } |
185 | | |
186 | 1.00k | ctx->md = md; |
187 | 1.00k | } |
188 | | |
189 | 16.5k | ret = EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx); |
190 | | |
191 | 16.5k | out: |
192 | 16.5k | FIPS_service_indicator_unlock_state(); |
193 | 16.5k | return ret; |
194 | 16.5k | } |
195 | | |
196 | 69.4k | int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, size_t data_len) { |
197 | 69.4k | return EVP_DigestUpdate(&ctx->md_ctx, data, data_len); |
198 | 69.4k | } |
199 | | |
200 | 16.2k | int HMAC_Final(HMAC_CTX *ctx, uint8_t *out, unsigned int *out_len) { |
201 | 16.2k | int ret = 0; |
202 | 16.2k | unsigned int i; |
203 | 16.2k | uint8_t buf[EVP_MAX_MD_SIZE]; |
204 | | |
205 | 16.2k | FIPS_service_indicator_lock_state(); |
206 | | // TODO(davidben): The only thing that can officially fail here is |
207 | | // |EVP_MD_CTX_copy_ex|, but even that should be impossible in this case. |
208 | 16.2k | if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i) || |
209 | 16.2k | !EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx) || |
210 | 16.2k | !EVP_DigestUpdate(&ctx->md_ctx, buf, i) || |
211 | 16.2k | !EVP_DigestFinal_ex(&ctx->md_ctx, out, out_len)) { |
212 | 0 | *out_len = 0; |
213 | 0 | goto out; |
214 | 0 | } |
215 | | |
216 | 16.2k | ret = 1; |
217 | | |
218 | 16.2k | out: |
219 | 16.2k | FIPS_service_indicator_unlock_state(); |
220 | 16.2k | if (ret) { |
221 | 16.2k | HMAC_verify_service_indicator(ctx->md); |
222 | 16.2k | } |
223 | 16.2k | return ret; |
224 | 16.2k | } |
225 | | |
226 | | size_t HMAC_size(const HMAC_CTX *ctx) { return EVP_MD_size(ctx->md); } |
227 | | |
228 | 0 | const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx) { return ctx->md; } |
229 | | |
230 | 37.7k | int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src) { |
231 | 37.7k | if (!EVP_MD_CTX_copy_ex(&dest->i_ctx, &src->i_ctx) || |
232 | 37.7k | !EVP_MD_CTX_copy_ex(&dest->o_ctx, &src->o_ctx) || |
233 | 37.7k | !EVP_MD_CTX_copy_ex(&dest->md_ctx, &src->md_ctx)) { |
234 | 1.55k | return 0; |
235 | 1.55k | } |
236 | | |
237 | 36.1k | dest->md = src->md; |
238 | 36.1k | return 1; |
239 | 37.7k | } |
240 | | |
241 | 1.05k | void HMAC_CTX_reset(HMAC_CTX *ctx) { |
242 | 1.05k | HMAC_CTX_cleanup(ctx); |
243 | 1.05k | HMAC_CTX_init(ctx); |
244 | 1.05k | } |
245 | | |
246 | | int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md) { |
247 | | if (key && md) { |
248 | | HMAC_CTX_init(ctx); |
249 | | } |
250 | | return HMAC_Init_ex(ctx, key, key_len, md, NULL); |
251 | | } |
252 | | |
253 | 37.7k | int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src) { |
254 | 37.7k | HMAC_CTX_init(dest); |
255 | 37.7k | return HMAC_CTX_copy_ex(dest, src); |
256 | 37.7k | } |