tor-browser

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

hmac_nss.c (8539B)


      1 /*
      2 *
      3 * Copyright(c) 2013-2017, Cisco Systems, Inc.
      4 * All rights reserved.
      5 *
      6 * Redistribution and use in source and binary forms, with or without
      7 * modification, are permitted provided that the following conditions
      8 * are met:
      9 *
     10 *   Redistributions of source code must retain the above copyright
     11 *   notice, this list of conditions and the following disclaimer.
     12 *
     13 *   Redistributions in binary form must reproduce the above
     14 *   copyright notice, this list of conditions and the following
     15 *   disclaimer in the documentation and/or other materials provided
     16 *   with the distribution.
     17 *
     18 *   Neither the name of the Cisco Systems, Inc. nor the names of its
     19 *   contributors may be used to endorse or promote products derived
     20 *   from this software without specific prior written permission.
     21 *
     22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     33 * OF THE POSSIBILITY OF SUCH DAMAGE.
     34 *
     35 */
     36 
     37 #ifdef HAVE_CONFIG_H
     38 #include <config.h>
     39 #endif
     40 
     41 #include "auth.h"
     42 #include "alloc.h"
     43 #include "err.h" /* for srtp_debug */
     44 #include "auth_test_cases.h"
     45 
     46 #define NSS_PKCS11_2_0_COMPAT 1
     47 
     48 #include <nss.h>
     49 #include <pk11pub.h>
     50 
     51 #define SHA1_DIGEST_SIZE 20
     52 
     53 /* the debug module for authentiation */
     54 
     55 srtp_debug_module_t srtp_mod_hmac = {
     56    0,               /* debugging is off by default */
     57    "hmac sha-1 nss" /* printable name for module   */
     58 };
     59 
     60 typedef struct {
     61    NSSInitContext *nss;
     62    PK11SymKey *key;
     63    PK11Context *ctx;
     64 } srtp_hmac_nss_ctx_t;
     65 
     66 static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a,
     67                                         int key_len,
     68                                         int out_len)
     69 {
     70    extern const srtp_auth_type_t srtp_hmac;
     71    srtp_hmac_nss_ctx_t *hmac;
     72    NSSInitContext *nss;
     73 
     74    debug_print(srtp_mod_hmac, "allocating auth func with key length %d",
     75                key_len);
     76    debug_print(srtp_mod_hmac, "                          tag length %d",
     77                out_len);
     78 
     79    /* check output length - should be less than 20 bytes */
     80    if (out_len > SHA1_DIGEST_SIZE) {
     81        return srtp_err_status_bad_param;
     82    }
     83 
     84    /* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
     85    nss = NSS_InitContext("", "", "", "", NULL,
     86                          NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
     87                              NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
     88                              NSS_INIT_OPTIMIZESPACE);
     89    if (!nss) {
     90        return srtp_err_status_auth_fail;
     91    }
     92 
     93    *a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
     94    if (*a == NULL) {
     95        NSS_ShutdownContext(nss);
     96        return srtp_err_status_alloc_fail;
     97    }
     98 
     99    hmac =
    100        (srtp_hmac_nss_ctx_t *)srtp_crypto_alloc(sizeof(srtp_hmac_nss_ctx_t));
    101    if (hmac == NULL) {
    102        NSS_ShutdownContext(nss);
    103        srtp_crypto_free(*a);
    104        *a = NULL;
    105        return srtp_err_status_alloc_fail;
    106    }
    107 
    108    hmac->nss = nss;
    109    hmac->key = NULL;
    110    hmac->ctx = NULL;
    111 
    112    /* set pointers */
    113    (*a)->state = hmac;
    114    (*a)->type = &srtp_hmac;
    115    (*a)->out_len = out_len;
    116    (*a)->key_len = key_len;
    117    (*a)->prefix_len = 0;
    118 
    119    return srtp_err_status_ok;
    120 }
    121 
    122 static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a)
    123 {
    124    srtp_hmac_nss_ctx_t *hmac;
    125 
    126    hmac = (srtp_hmac_nss_ctx_t *)a->state;
    127    if (hmac) {
    128        /* free any PK11 values that have been created */
    129        if (hmac->key) {
    130            PK11_FreeSymKey(hmac->key);
    131            hmac->key = NULL;
    132        }
    133 
    134        if (hmac->ctx) {
    135            PK11_DestroyContext(hmac->ctx, PR_TRUE);
    136            hmac->ctx = NULL;
    137        }
    138 
    139        if (hmac->nss) {
    140            NSS_ShutdownContext(hmac->nss);
    141            hmac->nss = NULL;
    142        }
    143 
    144        /* zeroize everything */
    145        octet_string_set_to_zero(hmac, sizeof(srtp_hmac_nss_ctx_t));
    146        srtp_crypto_free(hmac);
    147    }
    148 
    149    /* free memory */
    150    srtp_crypto_free(a);
    151 
    152    return srtp_err_status_ok;
    153 }
    154 
    155 static srtp_err_status_t srtp_hmac_start(void *statev)
    156 {
    157    srtp_hmac_nss_ctx_t *hmac;
    158    hmac = (srtp_hmac_nss_ctx_t *)statev;
    159 
    160    if (PK11_DigestBegin(hmac->ctx) != SECSuccess) {
    161        return srtp_err_status_auth_fail;
    162    }
    163    return srtp_err_status_ok;
    164 }
    165 
    166 static srtp_err_status_t srtp_hmac_init(void *statev,
    167                                        const uint8_t *key,
    168                                        int key_len)
    169 {
    170    srtp_hmac_nss_ctx_t *hmac;
    171    hmac = (srtp_hmac_nss_ctx_t *)statev;
    172    PK11SymKey *sym_key;
    173    PK11Context *ctx;
    174 
    175    if (hmac->ctx) {
    176        PK11_DestroyContext(hmac->ctx, PR_TRUE);
    177        hmac->ctx = NULL;
    178    }
    179 
    180    if (hmac->key) {
    181        PK11_FreeSymKey(hmac->key);
    182        hmac->key = NULL;
    183    }
    184 
    185    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL);
    186    if (!slot) {
    187        return srtp_err_status_bad_param;
    188    }
    189 
    190    /* explicitly cast away const of key */
    191    SECItem key_item = { siBuffer, (unsigned char *)(uintptr_t)key, key_len };
    192    sym_key = PK11_ImportSymKey(slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap,
    193                                CKA_SIGN, &key_item, NULL);
    194    PK11_FreeSlot(slot);
    195 
    196    if (!sym_key) {
    197        return srtp_err_status_auth_fail;
    198    }
    199 
    200    SECItem param_item = { siBuffer, NULL, 0 };
    201    ctx = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, sym_key,
    202                                     &param_item);
    203    if (!ctx) {
    204        PK11_FreeSymKey(sym_key);
    205        return srtp_err_status_auth_fail;
    206    }
    207 
    208    hmac->key = sym_key;
    209    hmac->ctx = ctx;
    210 
    211    return srtp_err_status_ok;
    212 }
    213 
    214 static srtp_err_status_t srtp_hmac_update(void *statev,
    215                                          const uint8_t *message,
    216                                          int msg_octets)
    217 {
    218    srtp_hmac_nss_ctx_t *hmac;
    219    hmac = (srtp_hmac_nss_ctx_t *)statev;
    220 
    221    debug_print(srtp_mod_hmac, "input: %s",
    222                srtp_octet_string_hex_string(message, msg_octets));
    223 
    224    if (PK11_DigestOp(hmac->ctx, message, msg_octets) != SECSuccess) {
    225        return srtp_err_status_auth_fail;
    226    }
    227 
    228    return srtp_err_status_ok;
    229 }
    230 
    231 static srtp_err_status_t srtp_hmac_compute(void *statev,
    232                                           const uint8_t *message,
    233                                           int msg_octets,
    234                                           int tag_len,
    235                                           uint8_t *result)
    236 {
    237    srtp_hmac_nss_ctx_t *hmac;
    238    hmac = (srtp_hmac_nss_ctx_t *)statev;
    239    uint8_t hash_value[SHA1_DIGEST_SIZE];
    240    int i;
    241    unsigned int len;
    242 
    243    debug_print(srtp_mod_hmac, "input: %s",
    244                srtp_octet_string_hex_string(message, msg_octets));
    245 
    246    /* check tag length, return error if we can't provide the value expected */
    247    if (tag_len > SHA1_DIGEST_SIZE) {
    248        return srtp_err_status_bad_param;
    249    }
    250 
    251    if (PK11_DigestOp(hmac->ctx, message, msg_octets) != SECSuccess) {
    252        return srtp_err_status_auth_fail;
    253    }
    254 
    255    if (PK11_DigestFinal(hmac->ctx, hash_value, &len, SHA1_DIGEST_SIZE) !=
    256        SECSuccess) {
    257        return srtp_err_status_auth_fail;
    258    }
    259 
    260    if (tag_len < 0 || len < (unsigned int)tag_len)
    261        return srtp_err_status_auth_fail;
    262 
    263    /* copy hash_value to *result */
    264    for (i = 0; i < tag_len; i++) {
    265        result[i] = hash_value[i];
    266    }
    267 
    268    debug_print(srtp_mod_hmac, "output: %s",
    269                srtp_octet_string_hex_string(hash_value, tag_len));
    270 
    271    return srtp_err_status_ok;
    272 }
    273 
    274 static const char srtp_hmac_description[] =
    275    "hmac sha-1 authentication function";
    276 
    277 /*
    278 * srtp_auth_type_t hmac is the hmac metaobject
    279 */
    280 
    281 const srtp_auth_type_t srtp_hmac = {
    282    srtp_hmac_alloc,        /* */
    283    srtp_hmac_dealloc,      /* */
    284    srtp_hmac_init,         /* */
    285    srtp_hmac_compute,      /* */
    286    srtp_hmac_update,       /* */
    287    srtp_hmac_start,        /* */
    288    srtp_hmac_description,  /* */
    289    &srtp_hmac_test_case_0, /* */
    290    SRTP_HMAC_SHA1          /* */
    291 };