tor-browser

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

aes_gcm_nss.c (13343B)


      1 /*
      2 * aes_gcm_nss.c
      3 *
      4 * AES Galois Counter Mode
      5 *
      6 * Richard L. Barnes
      7 * Cisco Systems, Inc.
      8 *
      9 */
     10 
     11 /*
     12 *
     13 * Copyright (c) 2013-2017, Cisco Systems, Inc.
     14 * All rights reserved.
     15 *
     16 * Redistribution and use in source and binary forms, with or without
     17 * modification, are permitted provided that the following conditions
     18 * are met:
     19 *
     20 *   Redistributions of source code must retain the above copyright
     21 *   notice, this list of conditions and the following disclaimer.
     22 *
     23 *   Redistributions in binary form must reproduce the above
     24 *   copyright notice, this list of conditions and the following
     25 *   disclaimer in the documentation and/or other materials provided
     26 *   with the distribution.
     27 *
     28 *   Neither the name of the Cisco Systems, Inc. nor the names of its
     29 *   contributors may be used to endorse or promote products derived
     30 *   from this software without specific prior written permission.
     31 *
     32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     35 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     36 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     37 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     38 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     39 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     42 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     43 * OF THE POSSIBILITY OF SUCH DAMAGE.
     44 *
     45 */
     46 
     47 #ifdef HAVE_CONFIG_H
     48 #include <config.h>
     49 #endif
     50 
     51 #include "aes_gcm.h"
     52 #include "alloc.h"
     53 #include "err.h" /* for srtp_debug */
     54 #include "crypto_types.h"
     55 #include "cipher_types.h"
     56 #include "cipher_test_cases.h"
     57 #include <secerr.h>
     58 #include <nspr.h>
     59 
     60 srtp_debug_module_t srtp_mod_aes_gcm = {
     61    0,            /* debugging is off by default */
     62    "aes gcm nss" /* printable module name       */
     63 };
     64 
     65 /*
     66 * For now we only support 8 and 16 octet tags.  The spec allows for
     67 * optional 12 byte tag, which may be supported in the future.
     68 */
     69 #define GCM_IV_LEN 12
     70 #define GCM_AUTH_TAG_LEN 16
     71 #define GCM_AUTH_TAG_LEN_8 8
     72 
     73 /*
     74 * This function allocates a new instance of this crypto engine.
     75 * The key_len parameter should be one of 28 or 44 for
     76 * AES-128-GCM or AES-256-GCM respectively.  Note that the
     77 * key length includes the 14 byte salt value that is used when
     78 * initializing the KDF.
     79 */
     80 static srtp_err_status_t srtp_aes_gcm_nss_alloc(srtp_cipher_t **c,
     81                                                int key_len,
     82                                                int tlen)
     83 {
     84    srtp_aes_gcm_ctx_t *gcm;
     85    NSSInitContext *nss;
     86 
     87    debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d",
     88                key_len);
     89    debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %d", tlen);
     90 
     91    /*
     92     * Verify the key_len is valid for one of: AES-128/256
     93     */
     94    if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
     95        key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
     96        return (srtp_err_status_bad_param);
     97    }
     98 
     99    if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
    100        return (srtp_err_status_bad_param);
    101    }
    102 
    103    /* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
    104    nss = NSS_InitContext("", "", "", "", NULL,
    105                          NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
    106                              NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
    107                              NSS_INIT_OPTIMIZESPACE);
    108    if (!nss) {
    109        return (srtp_err_status_cipher_fail);
    110    }
    111 
    112    /* allocate memory a cipher of type aes_gcm */
    113    *c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
    114    if (*c == NULL) {
    115        NSS_ShutdownContext(nss);
    116        return (srtp_err_status_alloc_fail);
    117    }
    118 
    119    gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
    120    if (gcm == NULL) {
    121        NSS_ShutdownContext(nss);
    122        srtp_crypto_free(*c);
    123        *c = NULL;
    124        return (srtp_err_status_alloc_fail);
    125    }
    126 
    127    gcm->nss = nss;
    128 
    129    /* set pointers */
    130    (*c)->state = gcm;
    131 
    132    /* setup cipher attributes */
    133    switch (key_len) {
    134    case SRTP_AES_GCM_128_KEY_LEN_WSALT:
    135        (*c)->type = &srtp_aes_gcm_128;
    136        (*c)->algorithm = SRTP_AES_GCM_128;
    137        gcm->key_size = SRTP_AES_128_KEY_LEN;
    138        gcm->tag_size = tlen;
    139        gcm->params.ulTagBits = 8 * tlen;
    140        break;
    141    case SRTP_AES_GCM_256_KEY_LEN_WSALT:
    142        (*c)->type = &srtp_aes_gcm_256;
    143        (*c)->algorithm = SRTP_AES_GCM_256;
    144        gcm->key_size = SRTP_AES_256_KEY_LEN;
    145        gcm->tag_size = tlen;
    146        gcm->params.ulTagBits = 8 * tlen;
    147        break;
    148    default:
    149        /* this should never hit, but to be sure... */
    150        return (srtp_err_status_bad_param);
    151    }
    152 
    153    /* set key size and tag size*/
    154    (*c)->key_len = key_len;
    155 
    156    return (srtp_err_status_ok);
    157 }
    158 
    159 /*
    160 * This function deallocates a GCM session
    161 */
    162 static srtp_err_status_t srtp_aes_gcm_nss_dealloc(srtp_cipher_t *c)
    163 {
    164    srtp_aes_gcm_ctx_t *ctx;
    165 
    166    ctx = (srtp_aes_gcm_ctx_t *)c->state;
    167    if (ctx) {
    168        /* release NSS resources */
    169        if (ctx->key) {
    170            PK11_FreeSymKey(ctx->key);
    171        }
    172 
    173        if (ctx->nss) {
    174            NSS_ShutdownContext(ctx->nss);
    175            ctx->nss = NULL;
    176        }
    177 
    178        /* zeroize the key material */
    179        octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
    180        srtp_crypto_free(ctx);
    181    }
    182 
    183    /* free memory */
    184    srtp_crypto_free(c);
    185 
    186    return (srtp_err_status_ok);
    187 }
    188 
    189 /*
    190 * aes_gcm_nss_context_init(...) initializes the aes_gcm_context
    191 * using the value in key[].
    192 *
    193 * the key is the secret key
    194 */
    195 static srtp_err_status_t srtp_aes_gcm_nss_context_init(void *cv,
    196                                                       const uint8_t *key)
    197 {
    198    srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
    199 
    200    c->dir = srtp_direction_any;
    201 
    202    debug_print(srtp_mod_aes_gcm, "key:  %s",
    203                srtp_octet_string_hex_string(key, c->key_size));
    204 
    205    if (c->key) {
    206        PK11_FreeSymKey(c->key);
    207        c->key = NULL;
    208    }
    209 
    210    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_GCM, NULL);
    211    if (!slot) {
    212        return (srtp_err_status_cipher_fail);
    213    }
    214 
    215    /* explicitly cast away const of key */
    216    SECItem key_item = { siBuffer, (unsigned char *)(uintptr_t)key,
    217                         c->key_size };
    218    c->key = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
    219                               CKA_ENCRYPT, &key_item, NULL);
    220    PK11_FreeSlot(slot);
    221 
    222    if (!c->key) {
    223        return (srtp_err_status_cipher_fail);
    224    }
    225 
    226    return (srtp_err_status_ok);
    227 }
    228 
    229 /*
    230 * aes_gcm_nss_set_iv(c, iv) sets the counter value to the exor of iv with
    231 * the offset
    232 */
    233 static srtp_err_status_t srtp_aes_gcm_nss_set_iv(
    234    void *cv,
    235    uint8_t *iv,
    236    srtp_cipher_direction_t direction)
    237 {
    238    srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
    239 
    240    if (direction != srtp_direction_encrypt &&
    241        direction != srtp_direction_decrypt) {
    242        return (srtp_err_status_bad_param);
    243    }
    244    c->dir = direction;
    245 
    246    debug_print(srtp_mod_aes_gcm, "setting iv: %s",
    247                srtp_octet_string_hex_string(iv, GCM_IV_LEN));
    248 
    249    memcpy(c->iv, iv, GCM_IV_LEN);
    250 
    251    return (srtp_err_status_ok);
    252 }
    253 
    254 /*
    255 * This function processes the AAD
    256 *
    257 * Parameters:
    258 *	c	Crypto context
    259 *	aad	Additional data to process for AEAD cipher suites
    260 *	aad_len	length of aad buffer
    261 */
    262 static srtp_err_status_t srtp_aes_gcm_nss_set_aad(void *cv,
    263                                                  const uint8_t *aad,
    264                                                  uint32_t aad_len)
    265 {
    266    srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
    267 
    268    debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
    269                srtp_octet_string_hex_string(aad, aad_len));
    270 
    271    if (aad_len + c->aad_size > MAX_AD_SIZE) {
    272        return srtp_err_status_bad_param;
    273    }
    274 
    275    memcpy(c->aad + c->aad_size, aad, aad_len);
    276    c->aad_size += aad_len;
    277 
    278    return (srtp_err_status_ok);
    279 }
    280 
    281 static srtp_err_status_t srtp_aes_gcm_nss_do_crypto(void *cv,
    282                                                    int encrypt,
    283                                                    unsigned char *buf,
    284                                                    unsigned int *enc_len)
    285 {
    286    srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
    287 
    288    c->params.pIv = c->iv;
    289    c->params.ulIvLen = GCM_IV_LEN;
    290    c->params.pAAD = c->aad;
    291    c->params.ulAADLen = c->aad_size;
    292 
    293    // Reset AAD
    294    c->aad_size = 0;
    295 
    296    int rv;
    297    SECItem param = { siBuffer, (unsigned char *)&c->params,
    298                      sizeof(CK_GCM_PARAMS) };
    299    if (encrypt) {
    300        rv = PK11_Encrypt(c->key, CKM_AES_GCM, &param, buf, enc_len,
    301                          *enc_len + 16, buf, *enc_len);
    302    } else {
    303        rv = PK11_Decrypt(c->key, CKM_AES_GCM, &param, buf, enc_len, *enc_len,
    304                          buf, *enc_len);
    305    }
    306 
    307    srtp_err_status_t status = (srtp_err_status_ok);
    308    if (rv != SECSuccess) {
    309        status = (srtp_err_status_cipher_fail);
    310    }
    311 
    312    return status;
    313 }
    314 
    315 /*
    316 * This function encrypts a buffer using AES GCM mode
    317 *
    318 * XXX(rlb@ipv.sx): We're required to break off and cache the tag
    319 * here, because the get_tag() method is separate and the tests expect
    320 * encrypt() not to change the size of the plaintext.  It might be
    321 * good to update the calling API so that this is cleaner.
    322 *
    323 * Parameters:
    324 *	c	Crypto context
    325 *	buf	data to encrypt
    326 *	enc_len	length of encrypt buffer
    327 */
    328 static srtp_err_status_t srtp_aes_gcm_nss_encrypt(void *cv,
    329                                                  unsigned char *buf,
    330                                                  unsigned int *enc_len)
    331 {
    332    srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
    333 
    334    // When we get a non-NULL buffer, we know that the caller is
    335    // prepared to also take the tag.  When we get a NULL buffer,
    336    // even though there's no data, we need to give NSS a buffer
    337    // where it can write the tag.  We can't just use c->tag because
    338    // memcpy has undefined behavior on overlapping ranges.
    339    unsigned char tagbuf[16];
    340    unsigned char *non_null_buf = buf;
    341    if (!non_null_buf && (*enc_len == 0)) {
    342        non_null_buf = tagbuf;
    343    } else if (!non_null_buf) {
    344        return srtp_err_status_bad_param;
    345    }
    346 
    347    srtp_err_status_t status =
    348        srtp_aes_gcm_nss_do_crypto(cv, 1, non_null_buf, enc_len);
    349    if (status != srtp_err_status_ok) {
    350        return status;
    351    }
    352 
    353    memcpy(c->tag, non_null_buf + (*enc_len - c->tag_size), c->tag_size);
    354    *enc_len -= c->tag_size;
    355    return srtp_err_status_ok;
    356 }
    357 
    358 /*
    359 * This function calculates and returns the GCM tag for a given context.
    360 * This should be called after encrypting the data.  The *len value
    361 * is increased by the tag size.  The caller must ensure that *buf has
    362 * enough room to accept the appended tag.
    363 *
    364 * Parameters:
    365 *	c	Crypto context
    366 *	buf	data to encrypt
    367 *	len	length of encrypt buffer
    368 */
    369 static srtp_err_status_t srtp_aes_gcm_nss_get_tag(void *cv,
    370                                                  uint8_t *buf,
    371                                                  uint32_t *len)
    372 {
    373    srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
    374    *len = c->tag_size;
    375    memcpy(buf, c->tag, c->tag_size);
    376    return (srtp_err_status_ok);
    377 }
    378 
    379 /*
    380 * This function decrypts a buffer using AES GCM mode
    381 *
    382 * Parameters:
    383 *	c	Crypto context
    384 *	buf	data to encrypt
    385 *	enc_len	length of encrypt buffer
    386 */
    387 static srtp_err_status_t srtp_aes_gcm_nss_decrypt(void *cv,
    388                                                  unsigned char *buf,
    389                                                  unsigned int *enc_len)
    390 {
    391    srtp_err_status_t status = srtp_aes_gcm_nss_do_crypto(cv, 0, buf, enc_len);
    392    if (status != srtp_err_status_ok) {
    393        int err = PR_GetError();
    394        if (err == SEC_ERROR_BAD_DATA) {
    395            status = srtp_err_status_auth_fail;
    396        }
    397    }
    398 
    399    return status;
    400 }
    401 
    402 /*
    403 * Name of this crypto engine
    404 */
    405 static const char srtp_aes_gcm_128_nss_description[] = "AES-128 GCM using NSS";
    406 static const char srtp_aes_gcm_256_nss_description[] = "AES-256 GCM using NSS";
    407 
    408 /*
    409 * This is the vector function table for this crypto engine.
    410 */
    411 /* clang-format off */
    412 const srtp_cipher_type_t srtp_aes_gcm_128 = {
    413    srtp_aes_gcm_nss_alloc,
    414    srtp_aes_gcm_nss_dealloc,
    415    srtp_aes_gcm_nss_context_init,
    416    srtp_aes_gcm_nss_set_aad,
    417    srtp_aes_gcm_nss_encrypt,
    418    srtp_aes_gcm_nss_decrypt,
    419    srtp_aes_gcm_nss_set_iv,
    420    srtp_aes_gcm_nss_get_tag,
    421    srtp_aes_gcm_128_nss_description,
    422    &srtp_aes_gcm_128_test_case_0,
    423    SRTP_AES_GCM_128
    424 };
    425 /* clang-format on */
    426 
    427 /*
    428 * This is the vector function table for this crypto engine.
    429 */
    430 /* clang-format off */
    431 const srtp_cipher_type_t srtp_aes_gcm_256 = {
    432    srtp_aes_gcm_nss_alloc,
    433    srtp_aes_gcm_nss_dealloc,
    434    srtp_aes_gcm_nss_context_init,
    435    srtp_aes_gcm_nss_set_aad,
    436    srtp_aes_gcm_nss_encrypt,
    437    srtp_aes_gcm_nss_decrypt,
    438    srtp_aes_gcm_nss_set_iv,
    439    srtp_aes_gcm_nss_get_tag,
    440    srtp_aes_gcm_256_nss_description,
    441    &srtp_aes_gcm_256_test_case_0,
    442    SRTP_AES_GCM_256
    443 };
    444 /* clang-format on */