tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 };