tor-browser

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

aes_icm_nss.c (13172B)


      1 /*
      2 * aes_icm_nss.c
      3 *
      4 * AES Integer Counter Mode
      5 *
      6 * Richard L. Barnes
      7 * Cisco Systems, Inc.
      8 */
      9 
     10 /*
     11 *
     12 * Copyright (c) 2013-2017, Cisco Systems, Inc.
     13 * All rights reserved.
     14 *
     15 * Redistribution and use in source and binary forms, with or without
     16 * modification, are permitted provided that the following conditions
     17 * are met:
     18 *
     19 *   Redistributions of source code must retain the above copyright
     20 *   notice, this list of conditions and the following disclaimer.
     21 *
     22 *   Redistributions in binary form must reproduce the above
     23 *   copyright notice, this list of conditions and the following
     24 *   disclaimer in the documentation and/or other materials provided
     25 *   with the distribution.
     26 *
     27 *   Neither the name of the Cisco Systems, Inc. nor the names of its
     28 *   contributors may be used to endorse or promote products derived
     29 *   from this software without specific prior written permission.
     30 *
     31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     34 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     35 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     36 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     38 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     42 * OF THE POSSIBILITY OF SUCH DAMAGE.
     43 *
     44 */
     45 
     46 #ifdef HAVE_CONFIG_H
     47 #include <config.h>
     48 #endif
     49 
     50 #include "aes_icm_ext.h"
     51 #include "crypto_types.h"
     52 #include "err.h" /* for srtp_debug */
     53 #include "alloc.h"
     54 #include "cipher_types.h"
     55 #include "cipher_test_cases.h"
     56 
     57 srtp_debug_module_t srtp_mod_aes_icm = {
     58    0,            /* debugging is off by default */
     59    "aes icm nss" /* printable module name       */
     60 };
     61 
     62 /*
     63 * integer counter mode works as follows:
     64 *
     65 * 16 bits
     66 * <----->
     67 * +------+------+------+------+------+------+------+------+
     68 * |           nonce           |    packet index    |  ctr |---+
     69 * +------+------+------+------+------+------+------+------+   |
     70 *                                                             |
     71 * +------+------+------+------+------+------+------+------+   v
     72 * |                      salt                      |000000|->(+)
     73 * +------+------+------+------+------+------+------+------+   |
     74 *                                                             |
     75 *                                                        +---------+
     76 *                                                        | encrypt |
     77 *                                                        +---------+
     78 *                                                             |
     79 * +------+------+------+------+------+------+------+------+   |
     80 * |                    keystream block                    |<--+
     81 * +------+------+------+------+------+------+------+------+
     82 *
     83 * All fields are big-endian
     84 *
     85 * ctr is the block counter, which increments from zero for
     86 * each packet (16 bits wide)
     87 *
     88 * packet index is distinct for each packet (48 bits wide)
     89 *
     90 * nonce can be distinct across many uses of the same key, or
     91 * can be a fixed value per key, or can be per-packet randomness
     92 * (64 bits)
     93 *
     94 */
     95 
     96 /*
     97 * This function allocates a new instance of this crypto engine.
     98 * The key_len parameter should be one of 30, 38, or 46 for
     99 * AES-128, AES-192, and AES-256 respectively.  Note, this key_len
    100 * value is inflated, as it also accounts for the 112 bit salt
    101 * value.  The tlen argument is for the AEAD tag length, which
    102 * isn't used in counter mode.
    103 */
    104 static srtp_err_status_t srtp_aes_icm_nss_alloc(srtp_cipher_t **c,
    105                                                int key_len,
    106                                                int tlen)
    107 {
    108    srtp_aes_icm_ctx_t *icm;
    109    NSSInitContext *nss;
    110    (void)tlen;
    111 
    112    debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
    113                key_len);
    114 
    115    /*
    116     * Verify the key_len is valid for one of: AES-128/192/256
    117     */
    118    if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT &&
    119        key_len != SRTP_AES_ICM_192_KEY_LEN_WSALT &&
    120        key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
    121        return srtp_err_status_bad_param;
    122    }
    123 
    124    /* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
    125    nss = NSS_InitContext("", "", "", "", NULL,
    126                          NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
    127                              NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
    128                              NSS_INIT_OPTIMIZESPACE);
    129    if (!nss) {
    130        return (srtp_err_status_cipher_fail);
    131    }
    132 
    133    /* allocate memory a cipher of type aes_icm */
    134    *c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
    135    if (*c == NULL) {
    136        NSS_ShutdownContext(nss);
    137        return srtp_err_status_alloc_fail;
    138    }
    139 
    140    icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
    141    if (icm == NULL) {
    142        NSS_ShutdownContext(nss);
    143        srtp_crypto_free(*c);
    144        *c = NULL;
    145        return srtp_err_status_alloc_fail;
    146    }
    147 
    148    icm->key = NULL;
    149    icm->ctx = NULL;
    150    icm->nss = nss;
    151 
    152    /* set pointers */
    153    (*c)->state = icm;
    154 
    155    /* setup cipher parameters */
    156    switch (key_len) {
    157    case SRTP_AES_ICM_128_KEY_LEN_WSALT:
    158        (*c)->algorithm = SRTP_AES_ICM_128;
    159        (*c)->type = &srtp_aes_icm_128;
    160        icm->key_size = SRTP_AES_128_KEY_LEN;
    161        break;
    162    case SRTP_AES_ICM_192_KEY_LEN_WSALT:
    163        (*c)->algorithm = SRTP_AES_ICM_192;
    164        (*c)->type = &srtp_aes_icm_192;
    165        icm->key_size = SRTP_AES_192_KEY_LEN;
    166        break;
    167    case SRTP_AES_ICM_256_KEY_LEN_WSALT:
    168        (*c)->algorithm = SRTP_AES_ICM_256;
    169        (*c)->type = &srtp_aes_icm_256;
    170        icm->key_size = SRTP_AES_256_KEY_LEN;
    171        break;
    172    }
    173 
    174    /* set key size        */
    175    (*c)->key_len = key_len;
    176 
    177    return srtp_err_status_ok;
    178 }
    179 
    180 /*
    181 * This function deallocates an instance of this engine
    182 */
    183 static srtp_err_status_t srtp_aes_icm_nss_dealloc(srtp_cipher_t *c)
    184 {
    185    srtp_aes_icm_ctx_t *ctx;
    186 
    187    ctx = (srtp_aes_icm_ctx_t *)c->state;
    188    if (ctx) {
    189        /* free any PK11 values that have been created */
    190        if (ctx->key) {
    191            PK11_FreeSymKey(ctx->key);
    192            ctx->key = NULL;
    193        }
    194 
    195        if (ctx->ctx) {
    196            PK11_DestroyContext(ctx->ctx, PR_TRUE);
    197            ctx->ctx = NULL;
    198        }
    199 
    200        if (ctx->nss) {
    201            NSS_ShutdownContext(ctx->nss);
    202            ctx->nss = NULL;
    203        }
    204 
    205        /* zeroize everything */
    206        octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
    207        srtp_crypto_free(ctx);
    208    }
    209 
    210    /* free memory */
    211    srtp_crypto_free(c);
    212 
    213    return (srtp_err_status_ok);
    214 }
    215 
    216 /*
    217 * aes_icm_nss_context_init(...) initializes the aes_icm_context
    218 * using the value in key[].
    219 *
    220 * the key is the secret key
    221 *
    222 * the salt is unpredictable (but not necessarily secret) data which
    223 * randomizes the starting point in the keystream
    224 */
    225 static srtp_err_status_t srtp_aes_icm_nss_context_init(void *cv,
    226                                                       const uint8_t *key)
    227 {
    228    srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
    229 
    230    /*
    231     * set counter and initial values to 'offset' value, being careful not to
    232     * go past the end of the key buffer
    233     */
    234    v128_set_to_zero(&c->counter);
    235    v128_set_to_zero(&c->offset);
    236    memcpy(&c->counter, key + c->key_size, SRTP_SALT_LEN);
    237    memcpy(&c->offset, key + c->key_size, SRTP_SALT_LEN);
    238 
    239    /* force last two octets of the offset to zero (for srtp compatibility) */
    240    c->offset.v8[SRTP_SALT_LEN] = c->offset.v8[SRTP_SALT_LEN + 1] = 0;
    241    c->counter.v8[SRTP_SALT_LEN] = c->counter.v8[SRTP_SALT_LEN + 1] = 0;
    242 
    243    debug_print(srtp_mod_aes_icm, "key:  %s",
    244                srtp_octet_string_hex_string(key, c->key_size));
    245    debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
    246 
    247    if (c->key) {
    248        PK11_FreeSymKey(c->key);
    249        c->key = NULL;
    250    }
    251 
    252    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_CTR, NULL);
    253    if (!slot) {
    254        return srtp_err_status_bad_param;
    255    }
    256 
    257    /* explicitly cast away const of key */
    258    SECItem keyItem = { siBuffer, (unsigned char *)(uintptr_t)key,
    259                        c->key_size };
    260    c->key = PK11_ImportSymKey(slot, CKM_AES_CTR, PK11_OriginUnwrap,
    261                               CKA_ENCRYPT, &keyItem, NULL);
    262    PK11_FreeSlot(slot);
    263 
    264    if (!c->key) {
    265        return srtp_err_status_cipher_fail;
    266    }
    267 
    268    return (srtp_err_status_ok);
    269 }
    270 
    271 /*
    272 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
    273 * the offset
    274 */
    275 static srtp_err_status_t srtp_aes_icm_nss_set_iv(void *cv,
    276                                                 uint8_t *iv,
    277                                                 srtp_cipher_direction_t dir)
    278 {
    279    srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
    280    v128_t nonce;
    281    (void)dir;
    282 
    283    /* set nonce (for alignment) */
    284    v128_copy_octet_string(&nonce, iv);
    285 
    286    debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce));
    287 
    288    v128_xor(&c->counter, &c->offset, &nonce);
    289 
    290    debug_print(srtp_mod_aes_icm, "set_counter: %s",
    291                v128_hex_string(&c->counter));
    292 
    293    /* set up the PK11 context now that we have all the info */
    294    CK_AES_CTR_PARAMS param;
    295    param.ulCounterBits = 16;
    296    memcpy(param.cb, &c->counter, 16);
    297 
    298    if (!c->key) {
    299        return srtp_err_status_bad_param;
    300    }
    301 
    302    if (c->ctx) {
    303        PK11_DestroyContext(c->ctx, PR_TRUE);
    304    }
    305 
    306    SECItem paramItem = { siBuffer, (unsigned char *)&param,
    307                          sizeof(CK_AES_CTR_PARAMS) };
    308    c->ctx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, c->key,
    309                                        &paramItem);
    310    if (!c->ctx) {
    311        return srtp_err_status_cipher_fail;
    312    }
    313 
    314    return srtp_err_status_ok;
    315 }
    316 
    317 /*
    318 * This function encrypts a buffer using AES CTR mode
    319 *
    320 * Parameters:
    321 *	c	Crypto context
    322 *	buf	data to encrypt
    323 *	enc_len	length of encrypt buffer
    324 */
    325 static srtp_err_status_t srtp_aes_icm_nss_encrypt(void *cv,
    326                                                  unsigned char *buf,
    327                                                  unsigned int *enc_len)
    328 {
    329    srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
    330 
    331    if (!c->ctx) {
    332        return srtp_err_status_bad_param;
    333    }
    334 
    335    int rv =
    336        PK11_CipherOp(c->ctx, buf, (int *)enc_len, *enc_len, buf, *enc_len);
    337 
    338    srtp_err_status_t status = (srtp_err_status_ok);
    339    if (rv != SECSuccess) {
    340        status = (srtp_err_status_cipher_fail);
    341    }
    342 
    343    return status;
    344 }
    345 
    346 /*
    347 * Name of this crypto engine
    348 */
    349 static const char srtp_aes_icm_128_nss_description[] =
    350    "AES-128 counter mode using NSS";
    351 static const char srtp_aes_icm_192_nss_description[] =
    352    "AES-192 counter mode using NSS";
    353 static const char srtp_aes_icm_256_nss_description[] =
    354    "AES-256 counter mode using NSS";
    355 
    356 /*
    357 * This is the function table for this crypto engine.
    358 * note: the encrypt function is identical to the decrypt function
    359 */
    360 const srtp_cipher_type_t srtp_aes_icm_128 = {
    361    srtp_aes_icm_nss_alloc,           /* */
    362    srtp_aes_icm_nss_dealloc,         /* */
    363    srtp_aes_icm_nss_context_init,    /* */
    364    0,                                /* set_aad */
    365    srtp_aes_icm_nss_encrypt,         /* */
    366    srtp_aes_icm_nss_encrypt,         /* */
    367    srtp_aes_icm_nss_set_iv,          /* */
    368    0,                                /* get_tag */
    369    srtp_aes_icm_128_nss_description, /* */
    370    &srtp_aes_icm_128_test_case_0,    /* */
    371    SRTP_AES_ICM_128                  /* */
    372 };
    373 
    374 /*
    375 * This is the function table for this crypto engine.
    376 * note: the encrypt function is identical to the decrypt function
    377 */
    378 const srtp_cipher_type_t srtp_aes_icm_192 = {
    379    srtp_aes_icm_nss_alloc,           /* */
    380    srtp_aes_icm_nss_dealloc,         /* */
    381    srtp_aes_icm_nss_context_init,    /* */
    382    0,                                /* set_aad */
    383    srtp_aes_icm_nss_encrypt,         /* */
    384    srtp_aes_icm_nss_encrypt,         /* */
    385    srtp_aes_icm_nss_set_iv,          /* */
    386    0,                                /* get_tag */
    387    srtp_aes_icm_192_nss_description, /* */
    388    &srtp_aes_icm_192_test_case_0,    /* */
    389    SRTP_AES_ICM_192                  /* */
    390 };
    391 
    392 /*
    393 * This is the function table for this crypto engine.
    394 * note: the encrypt function is identical to the decrypt function
    395 */
    396 const srtp_cipher_type_t srtp_aes_icm_256 = {
    397    srtp_aes_icm_nss_alloc,           /* */
    398    srtp_aes_icm_nss_dealloc,         /* */
    399    srtp_aes_icm_nss_context_init,    /* */
    400    0,                                /* set_aad */
    401    srtp_aes_icm_nss_encrypt,         /* */
    402    srtp_aes_icm_nss_encrypt,         /* */
    403    srtp_aes_icm_nss_set_iv,          /* */
    404    0,                                /* get_tag */
    405    srtp_aes_icm_256_nss_description, /* */
    406    &srtp_aes_icm_256_test_case_0,    /* */
    407    SRTP_AES_ICM_256                  /* */
    408 };