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, ¶m, buf, enc_len, 301 *enc_len + 16, buf, *enc_len); 302 } else { 303 rv = PK11_Decrypt(c->key, CKM_AES_GCM, ¶m, 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 */