hmac.c (7556B)
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 { 65 extern const srtp_auth_type_t srtp_hmac; 66 uint8_t *pointer; 67 68 debug_print(srtp_mod_hmac, "allocating auth func with key length %d", 69 key_len); 70 debug_print(srtp_mod_hmac, " tag length %d", 71 out_len); 72 73 /* 74 * check key length - note that we don't support keys larger 75 * than 20 bytes yet 76 */ 77 if (key_len > 20) { 78 return srtp_err_status_bad_param; 79 } 80 81 /* check output length - should be less than 20 bytes */ 82 if (out_len > 20) { 83 return srtp_err_status_bad_param; 84 } 85 86 /* allocate memory for auth and srtp_hmac_ctx_t structures */ 87 pointer = (uint8_t *)srtp_crypto_alloc(sizeof(srtp_hmac_ctx_t) + 88 sizeof(srtp_auth_t)); 89 if (pointer == NULL) { 90 return srtp_err_status_alloc_fail; 91 } 92 93 /* set pointers */ 94 *a = (srtp_auth_t *)pointer; 95 (*a)->type = &srtp_hmac; 96 (*a)->state = pointer + sizeof(srtp_auth_t); 97 (*a)->out_len = out_len; 98 (*a)->key_len = key_len; 99 (*a)->prefix_len = 0; 100 101 return srtp_err_status_ok; 102 } 103 104 static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a) 105 { 106 /* zeroize entire state*/ 107 octet_string_set_to_zero(a, sizeof(srtp_hmac_ctx_t) + sizeof(srtp_auth_t)); 108 109 /* free memory */ 110 srtp_crypto_free(a); 111 112 return srtp_err_status_ok; 113 } 114 115 static srtp_err_status_t srtp_hmac_init(void *statev, 116 const uint8_t *key, 117 int key_len) 118 { 119 srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; 120 int i; 121 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 if (key_len > 20) { 128 return srtp_err_status_bad_param; 129 } 130 131 /* 132 * set values of ipad and opad by exoring the key into the 133 * appropriate constant values 134 */ 135 for (i = 0; i < key_len; i++) { 136 ipad[i] = key[i] ^ 0x36; 137 state->opad[i] = key[i] ^ 0x5c; 138 } 139 /* set the rest of ipad, opad to constant values */ 140 for (; i < 64; i++) { 141 ipad[i] = 0x36; 142 ((uint8_t *)state->opad)[i] = 0x5c; 143 } 144 145 debug_print(srtp_mod_hmac, "ipad: %s", 146 srtp_octet_string_hex_string(ipad, 64)); 147 148 /* initialize sha1 context */ 149 srtp_sha1_init(&state->init_ctx); 150 151 /* hash ipad ^ key */ 152 srtp_sha1_update(&state->init_ctx, ipad, 64); 153 memcpy(&state->ctx, &state->init_ctx, sizeof(srtp_sha1_ctx_t)); 154 155 return srtp_err_status_ok; 156 } 157 158 static srtp_err_status_t srtp_hmac_start(void *statev) 159 { 160 srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; 161 162 memcpy(&state->ctx, &state->init_ctx, sizeof(srtp_sha1_ctx_t)); 163 164 return srtp_err_status_ok; 165 } 166 167 static srtp_err_status_t srtp_hmac_update(void *statev, 168 const uint8_t *message, 169 int msg_octets) 170 { 171 srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; 172 173 debug_print(srtp_mod_hmac, "input: %s", 174 srtp_octet_string_hex_string(message, msg_octets)); 175 176 /* hash message into sha1 context */ 177 srtp_sha1_update(&state->ctx, message, msg_octets); 178 179 return srtp_err_status_ok; 180 } 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 { 188 srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; 189 uint32_t hash_value[5]; 190 uint32_t H[5]; 191 int i; 192 193 /* check tag length, return error if we can't provide the value expected */ 194 if (tag_len > 20) { 195 return srtp_err_status_bad_param; 196 } 197 198 /* hash message, copy output into H */ 199 srtp_hmac_update(state, message, msg_octets); 200 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 debug_print(srtp_mod_hmac, "intermediate state: %s", 207 srtp_octet_string_hex_string((uint8_t *)H, 20)); 208 209 /* re-initialize hash context */ 210 srtp_sha1_init(&state->ctx); 211 212 /* hash opad ^ key */ 213 srtp_sha1_update(&state->ctx, (uint8_t *)state->opad, 64); 214 215 /* hash the result of the inner hash */ 216 srtp_sha1_update(&state->ctx, (uint8_t *)H, 20); 217 218 /* the result is returned in the array hash_value[] */ 219 srtp_sha1_final(&state->ctx, hash_value); 220 221 /* copy hash_value to *result */ 222 for (i = 0; i < tag_len; i++) { 223 result[i] = ((uint8_t *)hash_value)[i]; 224 } 225 226 debug_print(srtp_mod_hmac, "output: %s", 227 srtp_octet_string_hex_string((uint8_t *)hash_value, tag_len)); 228 229 return srtp_err_status_ok; 230 } 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 };