/src/pjsip/third_party/srtp/crypto/hash/hmac.c
Line | Count | Source |
1 | | /* |
2 | | * hmac.c |
3 | | * |
4 | | * implementation of hmac srtp_auth_type_t |
5 | | * |
6 | | * David A. McGrew |
7 | | * Cisco Systems, Inc. |
8 | | */ |
9 | | /* |
10 | | * |
11 | | * Copyright(c) 2001-2017 Cisco Systems, Inc. |
12 | | * All rights reserved. |
13 | | * |
14 | | * Redistribution and use in source and binary forms, with or without |
15 | | * modification, are permitted provided that the following conditions |
16 | | * are met: |
17 | | * |
18 | | * Redistributions of source code must retain the above copyright |
19 | | * notice, this list of conditions and the following disclaimer. |
20 | | * |
21 | | * Redistributions in binary form must reproduce the above |
22 | | * copyright notice, this list of conditions and the following |
23 | | * disclaimer in the documentation and/or other materials provided |
24 | | * with the distribution. |
25 | | * |
26 | | * Neither the name of the Cisco Systems, Inc. nor the names of its |
27 | | * contributors may be used to endorse or promote products derived |
28 | | * from this software without specific prior written permission. |
29 | | * |
30 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
31 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
32 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
33 | | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
34 | | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
35 | | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
36 | | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
37 | | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
38 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
39 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
40 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
41 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
42 | | * |
43 | | */ |
44 | | |
45 | | #ifdef HAVE_CONFIG_H |
46 | | #include <config.h> |
47 | | #endif |
48 | | |
49 | | #include "hmac.h" |
50 | | #include "alloc.h" |
51 | | #include "cipher_types.h" |
52 | | #include "auth_test_cases.h" |
53 | | |
54 | | /* the debug module for authentiation */ |
55 | | |
56 | | srtp_debug_module_t srtp_mod_hmac = { |
57 | | 0, /* debugging is off by default */ |
58 | | "hmac sha-1" /* printable name for module */ |
59 | | }; |
60 | | |
61 | | static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a, |
62 | | int key_len, |
63 | | int out_len) |
64 | 4.79k | { |
65 | 4.79k | extern const srtp_auth_type_t srtp_hmac; |
66 | 4.79k | uint8_t *pointer; |
67 | | |
68 | 4.79k | debug_print(srtp_mod_hmac, "allocating auth func with key length %d", |
69 | 4.79k | key_len); |
70 | 4.79k | debug_print(srtp_mod_hmac, " tag length %d", |
71 | 4.79k | out_len); |
72 | | |
73 | | /* |
74 | | * check key length - note that we don't support keys larger |
75 | | * than 20 bytes yet |
76 | | */ |
77 | 4.79k | if (key_len > 20) { |
78 | 0 | return srtp_err_status_bad_param; |
79 | 0 | } |
80 | | |
81 | | /* check output length - should be less than 20 bytes */ |
82 | 4.79k | if (out_len > 20) { |
83 | 0 | return srtp_err_status_bad_param; |
84 | 0 | } |
85 | | |
86 | | /* allocate memory for auth and srtp_hmac_ctx_t structures */ |
87 | 4.79k | pointer = (uint8_t *)srtp_crypto_alloc(sizeof(srtp_hmac_ctx_t) + |
88 | 4.79k | sizeof(srtp_auth_t)); |
89 | 4.79k | if (pointer == NULL) { |
90 | 0 | return srtp_err_status_alloc_fail; |
91 | 0 | } |
92 | | |
93 | | /* set pointers */ |
94 | 4.79k | *a = (srtp_auth_t *)pointer; |
95 | 4.79k | (*a)->type = &srtp_hmac; |
96 | 4.79k | (*a)->state = pointer + sizeof(srtp_auth_t); |
97 | 4.79k | (*a)->out_len = out_len; |
98 | 4.79k | (*a)->key_len = key_len; |
99 | 4.79k | (*a)->prefix_len = 0; |
100 | | |
101 | 4.79k | return srtp_err_status_ok; |
102 | 4.79k | } |
103 | | |
104 | | static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a) |
105 | 4.79k | { |
106 | | /* zeroize entire state*/ |
107 | 4.79k | octet_string_set_to_zero(a, sizeof(srtp_hmac_ctx_t) + sizeof(srtp_auth_t)); |
108 | | |
109 | | /* free memory */ |
110 | 4.79k | srtp_crypto_free(a); |
111 | | |
112 | 4.79k | return srtp_err_status_ok; |
113 | 4.79k | } |
114 | | |
115 | | static srtp_err_status_t srtp_hmac_init(void *statev, |
116 | | const uint8_t *key, |
117 | | int key_len) |
118 | 4.79k | { |
119 | 4.79k | srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; |
120 | 4.79k | int i; |
121 | 4.79k | uint8_t ipad[64]; |
122 | | |
123 | | /* |
124 | | * check key length - note that we don't support keys larger |
125 | | * than 20 bytes yet |
126 | | */ |
127 | 4.79k | if (key_len > 20) { |
128 | 0 | return srtp_err_status_bad_param; |
129 | 0 | } |
130 | | |
131 | | /* |
132 | | * set values of ipad and opad by exoring the key into the |
133 | | * appropriate constant values |
134 | | */ |
135 | 100k | for (i = 0; i < key_len; i++) { |
136 | 95.9k | ipad[i] = key[i] ^ 0x36; |
137 | 95.9k | state->opad[i] = key[i] ^ 0x5c; |
138 | 95.9k | } |
139 | | /* set the rest of ipad, opad to constant values */ |
140 | 215k | for (; i < 64; i++) { |
141 | 210k | ipad[i] = 0x36; |
142 | 210k | ((uint8_t *)state->opad)[i] = 0x5c; |
143 | 210k | } |
144 | | |
145 | 4.79k | debug_print(srtp_mod_hmac, "ipad: %s", |
146 | 4.79k | srtp_octet_string_hex_string(ipad, 64)); |
147 | | |
148 | | /* initialize sha1 context */ |
149 | 4.79k | srtp_sha1_init(&state->init_ctx); |
150 | | |
151 | | /* hash ipad ^ key */ |
152 | 4.79k | srtp_sha1_update(&state->init_ctx, ipad, 64); |
153 | 4.79k | memcpy(&state->ctx, &state->init_ctx, sizeof(srtp_sha1_ctx_t)); |
154 | | |
155 | 4.79k | return srtp_err_status_ok; |
156 | 4.79k | } |
157 | | |
158 | | static srtp_err_status_t srtp_hmac_start(void *statev) |
159 | 3.32k | { |
160 | 3.32k | srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; |
161 | | |
162 | 3.32k | memcpy(&state->ctx, &state->init_ctx, sizeof(srtp_sha1_ctx_t)); |
163 | | |
164 | 3.32k | return srtp_err_status_ok; |
165 | 3.32k | } |
166 | | |
167 | | static srtp_err_status_t srtp_hmac_update(void *statev, |
168 | | const uint8_t *message, |
169 | | int msg_octets) |
170 | 3.48k | { |
171 | 3.48k | srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; |
172 | | |
173 | 3.48k | debug_print(srtp_mod_hmac, "input: %s", |
174 | 3.48k | srtp_octet_string_hex_string(message, msg_octets)); |
175 | | |
176 | | /* hash message into sha1 context */ |
177 | 3.48k | srtp_sha1_update(&state->ctx, message, msg_octets); |
178 | | |
179 | 3.48k | return srtp_err_status_ok; |
180 | 3.48k | } |
181 | | |
182 | | static srtp_err_status_t srtp_hmac_compute(void *statev, |
183 | | const uint8_t *message, |
184 | | int msg_octets, |
185 | | int tag_len, |
186 | | uint8_t *result) |
187 | 3.32k | { |
188 | 3.32k | srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; |
189 | 3.32k | uint32_t hash_value[5]; |
190 | 3.32k | uint32_t H[5]; |
191 | 3.32k | int i; |
192 | | |
193 | | /* check tag length, return error if we can't provide the value expected */ |
194 | 3.32k | if (tag_len > 20) { |
195 | 0 | return srtp_err_status_bad_param; |
196 | 0 | } |
197 | | |
198 | | /* hash message, copy output into H */ |
199 | 3.32k | srtp_hmac_update(state, message, msg_octets); |
200 | 3.32k | srtp_sha1_final(&state->ctx, H); |
201 | | |
202 | | /* |
203 | | * note that we don't need to debug_print() the input, since the |
204 | | * function hmac_update() already did that for us |
205 | | */ |
206 | 3.32k | debug_print(srtp_mod_hmac, "intermediate state: %s", |
207 | 3.32k | srtp_octet_string_hex_string((uint8_t *)H, 20)); |
208 | | |
209 | | /* re-initialize hash context */ |
210 | 3.32k | srtp_sha1_init(&state->ctx); |
211 | | |
212 | | /* hash opad ^ key */ |
213 | 3.32k | srtp_sha1_update(&state->ctx, (uint8_t *)state->opad, 64); |
214 | | |
215 | | /* hash the result of the inner hash */ |
216 | 3.32k | srtp_sha1_update(&state->ctx, (uint8_t *)H, 20); |
217 | | |
218 | | /* the result is returned in the array hash_value[] */ |
219 | 3.32k | srtp_sha1_final(&state->ctx, hash_value); |
220 | | |
221 | | /* copy hash_value to *result */ |
222 | 66.7k | for (i = 0; i < tag_len; i++) { |
223 | 63.4k | result[i] = ((uint8_t *)hash_value)[i]; |
224 | 63.4k | } |
225 | | |
226 | 3.32k | debug_print(srtp_mod_hmac, "output: %s", |
227 | 3.32k | srtp_octet_string_hex_string((uint8_t *)hash_value, tag_len)); |
228 | | |
229 | 3.32k | return srtp_err_status_ok; |
230 | 3.32k | } |
231 | | |
232 | | static const char srtp_hmac_description[] = |
233 | | "hmac sha-1 authentication function"; |
234 | | |
235 | | /* |
236 | | * srtp_auth_type_t hmac is the hmac metaobject |
237 | | */ |
238 | | |
239 | | const srtp_auth_type_t srtp_hmac = { |
240 | | srtp_hmac_alloc, /* */ |
241 | | srtp_hmac_dealloc, /* */ |
242 | | srtp_hmac_init, /* */ |
243 | | srtp_hmac_compute, /* */ |
244 | | srtp_hmac_update, /* */ |
245 | | srtp_hmac_start, /* */ |
246 | | srtp_hmac_description, /* */ |
247 | | &srtp_hmac_test_case_0, /* */ |
248 | | SRTP_HMAC_SHA1 /* */ |
249 | | }; |