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