tor-browser

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

aes_icm.c (14081B)


      1 /*
      2 * aes_icm.c
      3 *
      4 * AES Integer Counter Mode
      5 *
      6 * David A. McGrew
      7 * Cisco Systems, Inc.
      8 */
      9 
     10 /*
     11 *
     12 * Copyright (c) 2001-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 #define ALIGN_32 0
     51 
     52 #include "aes_icm.h"
     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" /* printable module name       */
     60 };
     61 
     62 /*
     63 * integer counter mode works as follows:
     64 *
     65 * 16 bits
     66 * <----->
     67 * +------+------+------+------+------+------+------+------+
     68 * |           nonce           |    pakcet 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 static srtp_err_status_t srtp_aes_icm_alloc(srtp_cipher_t **c,
     97                                            int key_len,
     98                                            int tlen)
     99 {
    100    srtp_aes_icm_ctx_t *icm;
    101    (void)tlen;
    102 
    103    debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
    104                key_len);
    105 
    106    /*
    107     * The check for key_len = 30/46 does not apply. Our usage
    108     * of aes functions with key_len = values other than 30
    109     * has not broken anything. Don't know what would be the
    110     * effect of skipping this check for srtp in general.
    111     */
    112    if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT &&
    113        key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
    114        return srtp_err_status_bad_param;
    115    }
    116 
    117    /* allocate memory a cipher of type aes_icm */
    118    *c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
    119    if (*c == NULL) {
    120        return srtp_err_status_alloc_fail;
    121    }
    122 
    123    icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
    124    if (icm == NULL) {
    125        srtp_crypto_free(*c);
    126        *c = NULL;
    127        return srtp_err_status_alloc_fail;
    128    }
    129 
    130    /* set pointers */
    131    (*c)->state = icm;
    132 
    133    switch (key_len) {
    134    case SRTP_AES_ICM_256_KEY_LEN_WSALT:
    135        (*c)->algorithm = SRTP_AES_ICM_256;
    136        (*c)->type = &srtp_aes_icm_256;
    137        break;
    138    default:
    139        (*c)->algorithm = SRTP_AES_ICM_128;
    140        (*c)->type = &srtp_aes_icm_128;
    141        break;
    142    }
    143 
    144    /* set key size        */
    145    icm->key_size = key_len;
    146    (*c)->key_len = key_len;
    147 
    148    return srtp_err_status_ok;
    149 }
    150 
    151 static srtp_err_status_t srtp_aes_icm_dealloc(srtp_cipher_t *c)
    152 {
    153    srtp_aes_icm_ctx_t *ctx;
    154 
    155    if (c == NULL) {
    156        return srtp_err_status_bad_param;
    157    }
    158 
    159    ctx = (srtp_aes_icm_ctx_t *)c->state;
    160    if (ctx) {
    161        /* zeroize the key material */
    162        octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
    163        srtp_crypto_free(ctx);
    164    }
    165 
    166    /* free the cipher context */
    167    srtp_crypto_free(c);
    168 
    169    return srtp_err_status_ok;
    170 }
    171 
    172 /*
    173 * aes_icm_context_init(...) initializes the aes_icm_context
    174 * using the value in key[].
    175 *
    176 * the key is the secret key
    177 *
    178 * the salt is unpredictable (but not necessarily secret) data which
    179 * randomizes the starting point in the keystream
    180 */
    181 
    182 static srtp_err_status_t srtp_aes_icm_context_init(void *cv, const uint8_t *key)
    183 {
    184    srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
    185    srtp_err_status_t status;
    186    int base_key_len, copy_len;
    187 
    188    if (c->key_size == SRTP_AES_ICM_128_KEY_LEN_WSALT ||
    189        c->key_size == SRTP_AES_ICM_256_KEY_LEN_WSALT) {
    190        base_key_len = c->key_size - SRTP_SALT_LEN;
    191    } else {
    192        return srtp_err_status_bad_param;
    193    }
    194 
    195    /*
    196     * set counter and initial values to 'offset' value, being careful not to
    197     * go past the end of the key buffer
    198     */
    199    v128_set_to_zero(&c->counter);
    200    v128_set_to_zero(&c->offset);
    201 
    202    copy_len = c->key_size - base_key_len;
    203    /* force last two octets of the offset to be left zero (for srtp
    204     * compatibility) */
    205    if (copy_len > SRTP_SALT_LEN) {
    206        copy_len = SRTP_SALT_LEN;
    207    }
    208 
    209    memcpy(&c->counter, key + base_key_len, copy_len);
    210    memcpy(&c->offset, key + base_key_len, copy_len);
    211 
    212    debug_print(srtp_mod_aes_icm, "key:  %s",
    213                srtp_octet_string_hex_string(key, base_key_len));
    214    debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
    215 
    216    /* expand key */
    217    status =
    218        srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
    219    if (status) {
    220        v128_set_to_zero(&c->counter);
    221        v128_set_to_zero(&c->offset);
    222        return status;
    223    }
    224 
    225    /* indicate that the keystream_buffer is empty */
    226    c->bytes_in_buffer = 0;
    227 
    228    return srtp_err_status_ok;
    229 }
    230 
    231 /*
    232 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
    233 * the offset
    234 */
    235 
    236 static srtp_err_status_t srtp_aes_icm_set_iv(void *cv,
    237                                             uint8_t *iv,
    238                                             srtp_cipher_direction_t direction)
    239 {
    240    srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
    241    v128_t nonce;
    242    (void)direction;
    243 
    244    /* set nonce (for alignment) */
    245    v128_copy_octet_string(&nonce, iv);
    246 
    247    debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce));
    248 
    249    v128_xor(&c->counter, &c->offset, &nonce);
    250 
    251    debug_print(srtp_mod_aes_icm, "set_counter: %s",
    252                v128_hex_string(&c->counter));
    253 
    254    /* indicate that the keystream_buffer is empty */
    255    c->bytes_in_buffer = 0;
    256 
    257    return srtp_err_status_ok;
    258 }
    259 
    260 /*
    261 * aes_icm_advance(...) refills the keystream_buffer and
    262 * advances the block index of the sicm_context forward by one
    263 *
    264 * this is an internal, hopefully inlined function
    265 */
    266 static void srtp_aes_icm_advance(srtp_aes_icm_ctx_t *c)
    267 {
    268    /* fill buffer with new keystream */
    269    v128_copy(&c->keystream_buffer, &c->counter);
    270    srtp_aes_encrypt(&c->keystream_buffer, &c->expanded_key);
    271    c->bytes_in_buffer = sizeof(v128_t);
    272 
    273    debug_print(srtp_mod_aes_icm, "counter:    %s",
    274                v128_hex_string(&c->counter));
    275    debug_print(srtp_mod_aes_icm, "ciphertext: %s",
    276                v128_hex_string(&c->keystream_buffer));
    277 
    278    /* clock counter forward */
    279    if (!++(c->counter.v8[15])) {
    280        ++(c->counter.v8[14]);
    281    }
    282 }
    283 
    284 /*
    285 * icm_encrypt deals with the following cases:
    286 *
    287 * bytes_to_encr < bytes_in_buffer
    288 *  - add keystream into data
    289 *
    290 * bytes_to_encr > bytes_in_buffer
    291 *  - add keystream into data until keystream_buffer is depleted
    292 *  - loop over blocks, filling keystream_buffer and then
    293 *    adding keystream into data
    294 *  - fill buffer then add in remaining (< 16) bytes of keystream
    295 */
    296 
    297 static srtp_err_status_t srtp_aes_icm_encrypt(void *cv,
    298                                              unsigned char *buf,
    299                                              unsigned int *enc_len)
    300 {
    301    srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
    302    unsigned int bytes_to_encr = *enc_len;
    303    unsigned int i;
    304    uint32_t *b;
    305 
    306    /* check that there's enough segment left*/
    307    unsigned int bytes_of_new_keystream = bytes_to_encr - c->bytes_in_buffer;
    308    unsigned int blocks_of_new_keystream = (bytes_of_new_keystream + 15) >> 4;
    309    if ((blocks_of_new_keystream + htons(c->counter.v16[7])) > 0xffff) {
    310        return srtp_err_status_terminus;
    311    }
    312 
    313    debug_print(srtp_mod_aes_icm, "block index: %d", htons(c->counter.v16[7]));
    314    if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
    315        /* deal with odd case of small bytes_to_encr */
    316        for (i = (sizeof(v128_t) - c->bytes_in_buffer);
    317             i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++) {
    318            *buf++ ^= c->keystream_buffer.v8[i];
    319        }
    320 
    321        c->bytes_in_buffer -= bytes_to_encr;
    322 
    323        /* return now to avoid the main loop */
    324        return srtp_err_status_ok;
    325 
    326    } else {
    327        /* encrypt bytes until the remaining data is 16-byte aligned */
    328        for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t);
    329             i++) {
    330            *buf++ ^= c->keystream_buffer.v8[i];
    331        }
    332 
    333        bytes_to_encr -= c->bytes_in_buffer;
    334        c->bytes_in_buffer = 0;
    335    }
    336 
    337    /* now loop over entire 16-byte blocks of keystream */
    338    for (i = 0; i < (bytes_to_encr / sizeof(v128_t)); i++) {
    339        /* fill buffer with new keystream */
    340        srtp_aes_icm_advance(c);
    341 
    342        /*
    343         * add keystream into the data buffer (this would be a lot faster
    344         * if we could assume 32-bit alignment!)
    345         */
    346 
    347 #if ALIGN_32
    348        b = (uint32_t *)buf;
    349        *b++ ^= c->keystream_buffer.v32[0];
    350        *b++ ^= c->keystream_buffer.v32[1];
    351        *b++ ^= c->keystream_buffer.v32[2];
    352        *b++ ^= c->keystream_buffer.v32[3];
    353        buf = (uint8_t *)b;
    354 #else
    355        if ((((uintptr_t)buf) & 0x03) != 0) {
    356            *buf++ ^= c->keystream_buffer.v8[0];
    357            *buf++ ^= c->keystream_buffer.v8[1];
    358            *buf++ ^= c->keystream_buffer.v8[2];
    359            *buf++ ^= c->keystream_buffer.v8[3];
    360            *buf++ ^= c->keystream_buffer.v8[4];
    361            *buf++ ^= c->keystream_buffer.v8[5];
    362            *buf++ ^= c->keystream_buffer.v8[6];
    363            *buf++ ^= c->keystream_buffer.v8[7];
    364            *buf++ ^= c->keystream_buffer.v8[8];
    365            *buf++ ^= c->keystream_buffer.v8[9];
    366            *buf++ ^= c->keystream_buffer.v8[10];
    367            *buf++ ^= c->keystream_buffer.v8[11];
    368            *buf++ ^= c->keystream_buffer.v8[12];
    369            *buf++ ^= c->keystream_buffer.v8[13];
    370            *buf++ ^= c->keystream_buffer.v8[14];
    371            *buf++ ^= c->keystream_buffer.v8[15];
    372        } else {
    373            b = (uint32_t *)buf;
    374            *b++ ^= c->keystream_buffer.v32[0];
    375            *b++ ^= c->keystream_buffer.v32[1];
    376            *b++ ^= c->keystream_buffer.v32[2];
    377            *b++ ^= c->keystream_buffer.v32[3];
    378            buf = (uint8_t *)b;
    379        }
    380 #endif /* #if ALIGN_32 */
    381    }
    382 
    383    /* if there is a tail end of the data, process it */
    384    if ((bytes_to_encr & 0xf) != 0) {
    385        /* fill buffer with new keystream */
    386        srtp_aes_icm_advance(c);
    387 
    388        for (i = 0; i < (bytes_to_encr & 0xf); i++) {
    389            *buf++ ^= c->keystream_buffer.v8[i];
    390        }
    391 
    392        /* reset the keystream buffer size to right value */
    393        c->bytes_in_buffer = sizeof(v128_t) - i;
    394    } else {
    395        /* no tail, so just reset the keystream buffer size to zero */
    396        c->bytes_in_buffer = 0;
    397    }
    398 
    399    return srtp_err_status_ok;
    400 }
    401 
    402 static const char srtp_aes_icm_128_description[] =
    403    "AES-128 integer counter mode";
    404 static const char srtp_aes_icm_256_description[] =
    405    "AES-256 integer counter mode";
    406 
    407 /*
    408 * note: the encrypt function is identical to the decrypt function
    409 */
    410 
    411 const srtp_cipher_type_t srtp_aes_icm_128 = {
    412    srtp_aes_icm_alloc,            /* */
    413    srtp_aes_icm_dealloc,          /* */
    414    srtp_aes_icm_context_init,     /* */
    415    0,                             /* set_aad */
    416    srtp_aes_icm_encrypt,          /* */
    417    srtp_aes_icm_encrypt,          /* */
    418    srtp_aes_icm_set_iv,           /* */
    419    0,                             /* get_tag */
    420    srtp_aes_icm_128_description,  /* */
    421    &srtp_aes_icm_128_test_case_0, /* */
    422    SRTP_AES_ICM_128               /* */
    423 };
    424 
    425 const srtp_cipher_type_t srtp_aes_icm_256 = {
    426    srtp_aes_icm_alloc,            /* */
    427    srtp_aes_icm_dealloc,          /* */
    428    srtp_aes_icm_context_init,     /* */
    429    0,                             /* set_aad */
    430    srtp_aes_icm_encrypt,          /* */
    431    srtp_aes_icm_encrypt,          /* */
    432    srtp_aes_icm_set_iv,           /* */
    433    0,                             /* get_tag */
    434    srtp_aes_icm_256_description,  /* */
    435    &srtp_aes_icm_256_test_case_0, /* */
    436    SRTP_AES_ICM_256               /* */
    437 };