Changeset 5614 for pjproject/trunk/third_party/srtp/crypto/hash/hmac_ossl.c
- Timestamp:
- Jul 4, 2017 5:22:51 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/third_party/srtp/crypto/hash/hmac_ossl.c
r5261 r5614 2 2 * hmac_ossl.c 3 3 * 4 * Implementation of hmac auth_type_t that leverages OpenSSL4 * Implementation of hmac srtp_auth_type_t that leverages OpenSSL 5 5 * 6 6 * John A. Foley … … 9 9 /* 10 10 * 11 * Copyright(c) 2013 , Cisco Systems, Inc.11 * Copyright(c) 2013-2017, Cisco Systems, Inc. 12 12 * All rights reserved. 13 13 * … … 47 47 #endif 48 48 49 #include " hmac.h"49 #include "auth.h" 50 50 #include "alloc.h" 51 #include "err.h" /* for srtp_debug */ 51 52 #include <openssl/evp.h> 52 53 #define HMAC_KEYLEN_MAX 20 53 #include <openssl/hmac.h> 54 55 #define SHA1_DIGEST_SIZE 20 54 56 55 57 /* the debug module for authentiation */ 56 58 57 debug_module_tmod_hmac = {59 srtp_debug_module_t srtp_mod_hmac = { 58 60 0, /* debugging is off by default */ 59 61 "hmac sha-1 openssl" /* printable name for module */ … … 61 63 62 64 63 err_status_t 64 hmac_alloc (auth_t **a, int key_len, int out_len) 65 { 66 extern auth_type_t hmac; 67 uint8_t *pointer; 68 hmac_ctx_t *new_hmac_ctx; 69 70 debug_print(mod_hmac, "allocating auth func with key length %d", key_len); 71 debug_print(mod_hmac, " tag length %d", 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 > HMAC_KEYLEN_MAX) { 78 return err_status_bad_param; 79 } 65 static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_len) 66 { 67 extern const srtp_auth_type_t srtp_hmac; 68 69 debug_print(srtp_mod_hmac, "allocating auth func with key length %d", key_len); 70 debug_print(srtp_mod_hmac, " tag length %d", out_len); 80 71 81 72 /* check output length - should be less than 20 bytes */ 82 if (out_len > HMAC_KEYLEN_MAX) { 83 return err_status_bad_param; 84 } 85 86 /* allocate memory for auth and hmac_ctx_t structures */ 87 pointer = (uint8_t*)crypto_alloc(sizeof(hmac_ctx_t) + sizeof(auth_t)); 88 if (pointer == NULL) { 89 return err_status_alloc_fail; 90 } 73 if (out_len > SHA1_DIGEST_SIZE) { 74 return srtp_err_status_bad_param; 75 } 76 77 /* OpenSSL 1.1.0 made HMAC_CTX an opaque structure, which must be allocated 78 using HMAC_CTX_new. But this function doesn't exist in OpenSSL 1.0.x. */ 79 #if OPENSSL_VERSION_NUMBER < 0x10100000L 80 { 81 /* allocate memory for auth and HMAC_CTX structures */ 82 uint8_t* pointer; 83 HMAC_CTX *new_hmac_ctx; 84 pointer = (uint8_t*)srtp_crypto_alloc(sizeof(HMAC_CTX) + sizeof(srtp_auth_t)); 85 if (pointer == NULL) { 86 return srtp_err_status_alloc_fail; 87 } 88 *a = (srtp_auth_t*)pointer; 89 (*a)->state = pointer + sizeof(srtp_auth_t); 90 new_hmac_ctx = (HMAC_CTX*)((*a)->state); 91 92 HMAC_CTX_init(new_hmac_ctx); 93 } 94 95 #else 96 *a = (srtp_auth_t*)srtp_crypto_alloc(sizeof(srtp_auth_t)); 97 if (*a == NULL) { 98 return srtp_err_status_alloc_fail; 99 } 100 101 (*a)->state = HMAC_CTX_new(); 102 if ((*a)->state == NULL) { 103 srtp_crypto_free(*a); 104 *a = NULL; 105 return srtp_err_status_alloc_fail; 106 } 107 #endif 91 108 92 109 /* set pointers */ 93 *a = (auth_t*)pointer; 94 (*a)->type = &hmac; 95 (*a)->state = pointer + sizeof(auth_t); 110 (*a)->type = &srtp_hmac; 96 111 (*a)->out_len = out_len; 97 112 (*a)->key_len = key_len; 98 113 (*a)->prefix_len = 0; 99 new_hmac_ctx = (hmac_ctx_t*)((*a)->state); 100 memset(new_hmac_ctx, 0, sizeof(hmac_ctx_t)); 101 102 /* increment global count of all hmac uses */ 103 hmac.ref_count++; 104 105 return err_status_ok; 106 } 107 108 err_status_t 109 hmac_dealloc (auth_t *a) 110 { 111 extern auth_type_t hmac; 112 hmac_ctx_t *hmac_ctx; 113 114 hmac_ctx = (hmac_ctx_t*)a->state; 115 if (hmac_ctx->ctx_initialized) { 116 EVP_MD_CTX_cleanup(&hmac_ctx->ctx); 117 } 118 if (hmac_ctx->init_ctx_initialized) { 119 EVP_MD_CTX_cleanup(&hmac_ctx->init_ctx); 120 } 114 115 return srtp_err_status_ok; 116 } 117 118 static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a) 119 { 120 HMAC_CTX *hmac_ctx; 121 122 hmac_ctx = (HMAC_CTX*)a->state; 123 124 #if OPENSSL_VERSION_NUMBER < 0x10100000L 125 HMAC_CTX_cleanup(hmac_ctx); 121 126 122 127 /* zeroize entire state*/ 123 octet_string_set_to_zero((uint8_t*)a, 124 sizeof(hmac_ctx_t) + sizeof(auth_t)); 128 octet_string_set_to_zero(a, sizeof(HMAC_CTX) + sizeof(srtp_auth_t)); 129 130 #else 131 HMAC_CTX_free(hmac_ctx); 132 133 /* zeroize entire state*/ 134 octet_string_set_to_zero(a, sizeof(srtp_auth_t)); 135 #endif 125 136 126 137 /* free memory */ 127 crypto_free(a); 128 129 /* decrement global count of all hmac uses */ 130 hmac.ref_count--; 131 132 return err_status_ok; 133 } 134 135 err_status_t 136 hmac_init (hmac_ctx_t *state, const uint8_t *key, int key_len) 137 { 138 srtp_crypto_free(a); 139 140 return srtp_err_status_ok; 141 } 142 143 static srtp_err_status_t srtp_hmac_start (void *statev) 144 { 145 HMAC_CTX *state = (HMAC_CTX *)statev; 146 147 if (HMAC_Init_ex(state, NULL, 0, NULL, NULL) == 0) 148 return srtp_err_status_auth_fail; 149 150 return srtp_err_status_ok; 151 } 152 153 static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int key_len) 154 { 155 HMAC_CTX *state = (HMAC_CTX *)statev; 156 157 if (HMAC_Init_ex(state, key, key_len, EVP_sha1(), NULL) == 0) 158 return srtp_err_status_auth_fail; 159 160 return srtp_err_status_ok; 161 } 162 163 static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message, int msg_octets) 164 { 165 HMAC_CTX *state = (HMAC_CTX *)statev; 166 167 debug_print(srtp_mod_hmac, "input: %s", 168 srtp_octet_string_hex_string(message, msg_octets)); 169 170 if (HMAC_Update(state, message, msg_octets) == 0) 171 return srtp_err_status_auth_fail; 172 173 return srtp_err_status_ok; 174 } 175 176 static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message, 177 int msg_octets, int tag_len, uint8_t *result) 178 { 179 HMAC_CTX *state = (HMAC_CTX *)statev; 180 uint8_t hash_value[SHA1_DIGEST_SIZE]; 138 181 int i; 139 uint8_t ipad[64]; 140 141 /* 142 * check key length - note that we don't support keys larger 143 * than 20 bytes yet 144 */ 145 if (key_len > HMAC_KEYLEN_MAX) { 146 return err_status_bad_param; 147 } 148 149 /* 150 * set values of ipad and opad by exoring the key into the 151 * appropriate constant values 152 */ 153 for (i = 0; i < key_len; i++) { 154 ipad[i] = key[i] ^ 0x36; 155 state->opad[i] = key[i] ^ 0x5c; 156 } 157 /* set the rest of ipad, opad to constant values */ 158 for (; i < sizeof(ipad); i++) { 159 ipad[i] = 0x36; 160 ((uint8_t*)state->opad)[i] = 0x5c; 161 } 162 163 debug_print(mod_hmac, "ipad: %s", octet_string_hex_string(ipad, sizeof(ipad))); 164 165 /* initialize sha1 context */ 166 sha1_init(&state->init_ctx); 167 state->init_ctx_initialized = 1; 168 169 /* hash ipad ^ key */ 170 sha1_update(&state->init_ctx, ipad, sizeof(ipad)); 171 return (hmac_start(state)); 172 } 173 174 err_status_t 175 hmac_start (hmac_ctx_t *state) 176 { 177 if (state->ctx_initialized) { 178 EVP_MD_CTX_cleanup(&state->ctx); 179 } 180 if (!EVP_MD_CTX_copy(&state->ctx, &state->init_ctx)) { 181 return err_status_auth_fail; 182 } else { 183 state->ctx_initialized = 1; 184 return err_status_ok; 185 } 186 } 187 188 err_status_t 189 hmac_update (hmac_ctx_t *state, const uint8_t *message, int msg_octets) 190 { 191 debug_print(mod_hmac, "input: %s", 192 octet_string_hex_string(message, msg_octets)); 193 194 /* hash message into sha1 context */ 195 sha1_update(&state->ctx, message, msg_octets); 196 197 return err_status_ok; 198 } 199 200 err_status_t 201 hmac_compute (hmac_ctx_t *state, const void *message, 202 int msg_octets, int tag_len, uint8_t *result) 203 { 204 uint32_t hash_value[5]; 205 uint32_t H[5]; 206 int i; 182 unsigned int len; 207 183 208 184 /* check tag length, return error if we can't provide the value expected */ 209 if (tag_len > HMAC_KEYLEN_MAX) {210 return err_status_bad_param;185 if (tag_len > SHA1_DIGEST_SIZE) { 186 return srtp_err_status_bad_param; 211 187 } 212 188 213 189 /* hash message, copy output into H */ 214 sha1_update(&state->ctx, message, msg_octets); 215 sha1_final(&state->ctx, H); 216 217 /* 218 * note that we don't need to debug_print() the input, since the 219 * function hmac_update() already did that for us 220 */ 221 debug_print(mod_hmac, "intermediate state: %s", 222 octet_string_hex_string((uint8_t*)H, sizeof(H))); 223 224 /* re-initialize hash context */ 225 sha1_init(&state->ctx); 226 227 /* hash opad ^ key */ 228 sha1_update(&state->ctx, (uint8_t*)state->opad, sizeof(state->opad)); 229 230 /* hash the result of the inner hash */ 231 sha1_update(&state->ctx, (uint8_t*)H, sizeof(H)); 232 233 /* the result is returned in the array hash_value[] */ 234 sha1_final(&state->ctx, hash_value); 190 if (HMAC_Update(state, message, msg_octets) == 0) 191 return srtp_err_status_auth_fail; 192 193 if (HMAC_Final(state, hash_value, &len) == 0) 194 return srtp_err_status_auth_fail; 195 196 if (len < tag_len) 197 return srtp_err_status_auth_fail; 235 198 236 199 /* copy hash_value to *result */ 237 200 for (i = 0; i < tag_len; i++) { 238 result[i] = ((uint8_t*)hash_value)[i];239 } 240 241 debug_print( mod_hmac, "output: %s",242 octet_string_hex_string((uint8_t*)hash_value, tag_len));243 244 return err_status_ok;201 result[i] = hash_value[i]; 202 } 203 204 debug_print(srtp_mod_hmac, "output: %s", 205 srtp_octet_string_hex_string(hash_value, tag_len)); 206 207 return srtp_err_status_ok; 245 208 } 246 209 … … 248 211 /* begin test case 0 */ 249 212 250 uint8_t 251 hmac_test_case_0_key[HMAC_KEYLEN_MAX] = { 213 static const uint8_t srtp_hmac_test_case_0_key[SHA1_DIGEST_SIZE] = { 252 214 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 253 215 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, … … 255 217 }; 256 218 257 uint8_t 258 hmac_test_case_0_data[8] = { 219 static const uint8_t srtp_hmac_test_case_0_data[8] = { 259 220 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */ 260 221 }; 261 222 262 uint8_t 263 hmac_test_case_0_tag[HMAC_KEYLEN_MAX] = { 223 static const uint8_t srtp_hmac_test_case_0_tag[SHA1_DIGEST_SIZE] = { 264 224 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 265 225 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, … … 267 227 }; 268 228 269 auth_test_case_t 270 hmac_test_case_0 = { 271 sizeof(hmac_test_case_0_key), /* octets in key */ 272 hmac_test_case_0_key, /* key */ 273 sizeof(hmac_test_case_0_data), /* octets in data */ 274 hmac_test_case_0_data, /* data */ 275 sizeof(hmac_test_case_0_tag), /* octets in tag */ 276 hmac_test_case_0_tag, /* tag */ 229 static const srtp_auth_test_case_t srtp_hmac_test_case_0 = { 230 sizeof(srtp_hmac_test_case_0_key), /* octets in key */ 231 srtp_hmac_test_case_0_key, /* key */ 232 sizeof(srtp_hmac_test_case_0_data), /* octets in data */ 233 srtp_hmac_test_case_0_data, /* data */ 234 sizeof(srtp_hmac_test_case_0_tag), /* octets in tag */ 235 srtp_hmac_test_case_0_tag, /* tag */ 277 236 NULL /* pointer to next testcase */ 278 237 }; … … 280 239 /* end test case 0 */ 281 240 282 charhmac_description[] = "hmac sha-1 authentication function";241 static const char srtp_hmac_description[] = "hmac sha-1 authentication function"; 283 242 284 243 /* 285 * auth_type_t hmac is the hmac metaobject244 * srtp_auth_type_t hmac is the hmac metaobject 286 245 */ 287 246 288 auth_type_t 289 hmac = { 290 (auth_alloc_func) hmac_alloc, 291 (auth_dealloc_func) hmac_dealloc, 292 (auth_init_func) hmac_init, 293 (auth_compute_func) hmac_compute, 294 (auth_update_func) hmac_update, 295 (auth_start_func) hmac_start, 296 (char*) hmac_description, 297 (int) 0, /* instance count */ 298 (auth_test_case_t*) &hmac_test_case_0, 299 (debug_module_t*) &mod_hmac, 300 (auth_type_id_t) HMAC_SHA1 301 }; 302 247 const srtp_auth_type_t srtp_hmac = { 248 srtp_hmac_alloc, 249 srtp_hmac_dealloc, 250 srtp_hmac_init, 251 srtp_hmac_compute, 252 srtp_hmac_update, 253 srtp_hmac_start, 254 srtp_hmac_description, 255 &srtp_hmac_test_case_0, 256 SRTP_HMAC_SHA1 257 }; 258
Note: See TracChangeset
for help on using the changeset viewer.