double auth_bits_per_second(auth_t *a, int msg_len_octets) { int i; clock_t timer; uint8_t *result; int msg_len = (msg_len_octets + 1)/2; uint16_t *msg_string; /* create random message */ msg_string = (uint16_t *) crypto_alloc(msg_len_octets); if (msg_string == NULL) return 0.0; /* indicate failure */ for (i=0; i < msg_len; i++) msg_string[i] = (uint16_t) random(); /* allocate temporary storage for authentication tag */ result = crypto_alloc(auth_get_tag_length(a)); if (result == NULL) { free(msg_string); return 0.0; /* indicate failure */ } timer = clock(); for (i=0; i < NUM_TRIALS; i++) { auth_compute(a, (uint8_t *)msg_string, msg_len_octets, (uint8_t *)result); } timer = clock() - timer; free(msg_string); free(result); return (double) NUM_TRIALS * 8 * msg_len_octets * CLOCKS_PER_SEC / timer; }
err_status_t null_cipher_alloc(cipher_t **c, int key_len) { extern cipher_type_t null_cipher; uint8_t *pointer; debug_print(mod_cipher, "allocating cipher with key length %d", key_len); /* allocate memory a cipher of type null_cipher */ pointer = crypto_alloc(sizeof(null_cipher_ctx_t) + sizeof(cipher_t)); if (pointer == NULL) return err_status_alloc_fail; /* set pointers */ *c = (cipher_t *)pointer; (*c)->type = &null_cipher; (*c)->state = pointer + sizeof(cipher_t); /* set key size */ (*c)->key_len = key_len; /* increment ref_count */ null_cipher.ref_count++; return err_status_ok; }
int bitvector_alloc(bitvector_t *v, unsigned long length) { unsigned long l; /* Round length up to a multiple of bits_per_word */ length = (length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1)); l = length / bits_per_word * bytes_per_word; /* allocate memory, then set parameters */ if (l == 0) v->word = NULL; else { v->word = (uint32_t*)crypto_alloc(l); if (v->word == NULL) { v->word = NULL; v->length = 0; return -1; } } v->length = length; /* initialize bitvector to zero */ bitvector_set_to_zero(v); return 0; }
err_status_t null_auth_alloc(auth_t **a, int key_len, int out_len) { extern auth_type_t null_auth; uint8_t *pointer; debug_print(mod_auth, "allocating auth func with key length %d", key_len); debug_print(mod_auth, " tag length %d", out_len); /* allocate memory for auth and null_auth_ctx_t structures */ pointer = (uint8_t*)crypto_alloc(sizeof(null_auth_ctx_t) + sizeof(auth_t)); if (pointer == NULL) return err_status_alloc_fail; /* set pointers */ *a = (auth_t *)pointer; (*a)->type = &null_auth; (*a)->state = pointer + sizeof (auth_t); (*a)->out_len = out_len; (*a)->prefix_len = out_len; (*a)->key_len = key_len; /* increment global count of all null_auth uses */ null_auth.ref_count++; return err_status_ok; }
uint64_t cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) { int i; v128_t nonce; clock_t timer; unsigned char *enc_buf; unsigned int len = octets_in_buffer; enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer); if (enc_buf == NULL) return 0; /* indicate bad parameters by returning null */ /* time repeated trials */ v128_set_to_zero(&nonce); timer = clock(); for(i=0; i < num_trials; i++, nonce.v32[3] = i) { cipher_set_iv(c, &nonce); cipher_encrypt(c, enc_buf, &len); } timer = clock() - timer; crypto_free(enc_buf); if (timer == 0) { /* Too fast! */ return 0; } return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; }
err_status_t aes_cbc_alloc(cipher_t **c, int key_len) { extern cipher_type_t aes_cbc; uint8_t *pointer; int tmp; debug_print(mod_aes_cbc, "allocating cipher with key length %d", key_len); if (key_len != 16 && key_len != 24 && key_len != 32) return err_status_bad_param; /* allocate memory a cipher of type aes_cbc */ tmp = (sizeof(aes_cbc_ctx_t) + sizeof(cipher_t)); pointer = (uint8_t*)crypto_alloc(tmp); if (pointer == NULL) return err_status_alloc_fail; /* set pointers */ *c = (cipher_t *)pointer; (*c)->type = &aes_cbc; (*c)->state = pointer + sizeof(cipher_t); /* increment ref_count */ aes_cbc.ref_count++; /* set key size */ (*c)->key_len = key_len; return err_status_ok; }
err_status_t crypto_kernel_do_load_auth_type(auth_type_t *new_at, auth_type_id_t id, int replace) { kernel_auth_type_t *atype, *new_atype; err_status_t status; /* defensive coding */ if (new_at == NULL) return err_status_bad_param; if (new_at->id != id) return err_status_bad_param; /* check auth type by running self-test */ status = auth_type_self_test(new_at); if (status) { return status; } /* walk down list, checking if this type is in the list already */ atype = crypto_kernel.auth_type_list; while (atype != NULL) { if (id == atype->id) { if (!replace) return err_status_bad_param; status = auth_type_test(new_at, atype->auth_type->test_data); if (status) return status; new_atype = atype; break; } else if (new_at == atype->auth_type) return err_status_bad_param; atype = atype->next; } /* if not found, put new_at at the head of the list */ if (atype == NULL) { /* allocate memory */ new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t)); if (new_atype == NULL) return err_status_alloc_fail; new_atype->next = crypto_kernel.auth_type_list; /* set head of list to new auth type */ crypto_kernel.auth_type_list = new_atype; } /* set fields */ new_atype->auth_type = new_at; new_atype->id = id; /* load debug module, if there is one present */ if (new_at->debug != NULL) crypto_kernel_load_debug_module(new_at->debug); /* we could check for errors here */ return err_status_ok; }
/* * This function allocates a new instance of this crypto engine. * The key_len parameter should be one of 28 or 44 for * AES-128-GCM or AES-256-GCM respectively. Note that the * key length includes the 14 byte salt value that is used when * initializing the KDF. */ err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len, int tlen) { aes_gcm_ctx_t *gcm; int tmp; uint8_t *allptr; debug_print(mod_aes_gcm, "allocating cipher with key length %d", key_len); debug_print(mod_aes_gcm, "allocating cipher with tag length %d", tlen); /* * Verify the key_len is valid for one of: AES-128/256 */ if (key_len != AES_128_GCM_KEYSIZE_WSALT && key_len != AES_256_GCM_KEYSIZE_WSALT) { return (err_status_bad_param); } if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) { return (err_status_bad_param); } /* allocate memory a cipher of type aes_gcm */ tmp = sizeof(cipher_t) + sizeof(aes_gcm_ctx_t); allptr = crypto_alloc(tmp); if (allptr == NULL) { return (err_status_alloc_fail); } /* set pointers */ *c = (cipher_t*)allptr; (*c)->state = allptr + sizeof(cipher_t); gcm = (aes_gcm_ctx_t *)(*c)->state; /* increment ref_count */ switch (key_len) { case AES_128_GCM_KEYSIZE_WSALT: (*c)->type = &aes_gcm_128_openssl; (*c)->algorithm = AES_128_GCM; aes_gcm_128_openssl.ref_count++; ((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE; ((aes_gcm_ctx_t*)(*c)->state)->tag_len = tlen; break; case AES_256_GCM_KEYSIZE_WSALT: (*c)->type = &aes_gcm_256_openssl; (*c)->algorithm = AES_256_GCM; aes_gcm_256_openssl.ref_count++; ((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE; ((aes_gcm_ctx_t*)(*c)->state)->tag_len = tlen; break; } /* set key size */ (*c)->key_len = key_len; EVP_CIPHER_CTX_init(&gcm->ctx); return (err_status_ok); }
/* * This function allocates a new instance of this crypto engine. * The key_len parameter should be one of 30, 38, or 46 for * AES-128, AES-192, and AES-256 respectively. Note, this key_len * value is inflated, as it also accounts for the 112 bit salt * value. */ err_status_t aes_icm_openssl_alloc (cipher_t **c, int key_len, int x) { aes_icm_ctx_t *icm; int tmp; uint8_t *allptr; debug_print(mod_aes_icm, "allocating cipher with key length %d", key_len); /* * Verify the key_len is valid for one of: AES-128/192/256 */ if (key_len != AES_128_KEYSIZE_WSALT && key_len != AES_192_KEYSIZE_WSALT && key_len != AES_256_KEYSIZE_WSALT) { return err_status_bad_param; } /* allocate memory a cipher of type aes_icm */ tmp = sizeof(cipher_t) + sizeof(aes_icm_ctx_t); allptr = (uint8_t*)crypto_alloc(tmp); if (allptr == NULL) { return err_status_alloc_fail; } /* set pointers */ *c = (cipher_t*)allptr; (*c)->state = allptr + sizeof(cipher_t); icm = (aes_icm_ctx_t*)(*c)->state; /* increment ref_count */ switch (key_len) { case AES_128_KEYSIZE_WSALT: (*c)->algorithm = AES_128_ICM; (*c)->type = &aes_icm; aes_icm.ref_count++; ((aes_icm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE; break; case AES_192_KEYSIZE_WSALT: (*c)->algorithm = AES_192_ICM; (*c)->type = &aes_icm_192; aes_icm_192.ref_count++; ((aes_icm_ctx_t*)(*c)->state)->key_size = AES_192_KEYSIZE; break; case AES_256_KEYSIZE_WSALT: (*c)->algorithm = AES_256_ICM; (*c)->type = &aes_icm_256; aes_icm_256.ref_count++; ((aes_icm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE; break; } /* set key size */ (*c)->key_len = key_len; EVP_CIPHER_CTX_init(&icm->ctx); return err_status_ok; }
err_status_t cipher_array_alloc_init(cipher_t ***ca, int num_ciphers, cipher_type_t *ctype, int klen) { int i, j; err_status_t status; uint8_t *key; cipher_t **cipher_array; /* pad klen allocation, to handle aes_icm reading 16 bytes for the 14-byte salt */ int klen_pad = ((klen + 15) >> 4) << 4; /* allocate array of pointers to ciphers */ cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_ciphers); if (cipher_array == NULL) return err_status_alloc_fail; /* set ca to location of cipher_array */ *ca = cipher_array; /* allocate key */ key = crypto_alloc(klen_pad); if (key == NULL) { free(cipher_array); return err_status_alloc_fail; } /* allocate and initialize an array of ciphers */ for (i=0; i < num_ciphers; i++) { /* allocate cipher */ status = cipher_type_alloc(ctype, cipher_array, klen, 16); if (status) return status; /* generate random key and initialize cipher */ for (j=0; j < klen; j++) key[j] = (uint8_t) rand(); for (; j < klen_pad; j++) key[j] = 0; status = cipher_init(*cipher_array, key); if (status) return status; /* printf("%dth cipher is at %p\n", i, *cipher_array); */ /* printf("%dth cipher description: %s\n", i, */ /* (*cipher_array)->type->description); */ /* advance cipher array pointer */ cipher_array++; } crypto_free(key); return err_status_ok; }
err_status_t cipher_array_alloc_init (cipher_t ***ca, int num_ciphers, cipher_type_t *ctype, int klen) { int i, j; err_status_t status; uint8_t *key; cipher_t **cipher_array; /* allocate array of pointers to ciphers */ cipher_array = (cipher_t**)malloc(sizeof(cipher_t *) * num_ciphers); if (cipher_array == NULL) { return err_status_alloc_fail; } /* set ca to location of cipher_array */ *ca = cipher_array; /* allocate key */ key = crypto_alloc(klen); if (key == NULL) { free(cipher_array); return err_status_alloc_fail; } /* allocate and initialize an array of ciphers */ for (i = 0; i < num_ciphers; i++) { /* allocate cipher */ status = cipher_type_alloc(ctype, cipher_array, klen); if (status) { return status; } /* generate random key and initialize cipher */ for (j = 0; j < klen; j++) { key[j] = (uint8_t)rand(); } status = cipher_init(*cipher_array, key); if (status) { return status; } /* printf("%dth cipher is at %p\n", i, *cipher_array); */ /* printf("%dth cipher description: %s\n", i, */ /* (*cipher_array)->type->description); */ /* advance cipher array pointer */ cipher_array++; } return err_status_ok; }
err_status_t crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { kernel_cipher_type_t *ctype, *new_ctype; err_status_t status; /* defensive coding */ if (new_ct == NULL) return err_status_bad_param; /* check cipher type by running self-test */ status = cipher_type_self_test(new_ct); if (status) { return status; } /* walk down list, checking if this type is in the list already */ ctype = crypto_kernel.cipher_type_list; while (ctype != NULL) { if ((new_ct == ctype->cipher_type) || (id == ctype->id)) return err_status_bad_param; ctype = ctype->next; } /* put new_ct at the head of the list */ /* allocate memory */ new_ctype = (kernel_cipher_type_t *) crypto_alloc( sizeof(kernel_cipher_type_t)); if (new_ctype == NULL) return err_status_alloc_fail; /* set fields */ new_ctype->cipher_type = new_ct; new_ctype->id = id; new_ctype->next = crypto_kernel.cipher_type_list; /* set head of list to new cipher type */ crypto_kernel.cipher_type_list = new_ctype; /* load debug module, if there is one present */ if (new_ct->debug != NULL) crypto_kernel_load_debug_module(new_ct->debug); /* we could check for errors here */ return err_status_ok; }
err_status_t hmac_alloc (auth_t **a, int key_len, int out_len) { extern auth_type_t hmac; uint8_t *pointer; hmac_ctx_t *new_hmac_ctx; debug_print(mod_hmac, "allocating auth func with key length %d", key_len); debug_print(mod_hmac, " tag length %d", out_len); /* * check key length - note that we don't support keys larger * than 20 bytes yet */ if (key_len > HMAC_KEYLEN_MAX) { return err_status_bad_param; } /* check output length - should be less than 20 bytes */ if (out_len > HMAC_KEYLEN_MAX) { return err_status_bad_param; } /* allocate memory for auth and hmac_ctx_t structures */ pointer = (uint8_t*)crypto_alloc(sizeof(hmac_ctx_t) + sizeof(auth_t)); if (pointer == NULL) { return err_status_alloc_fail; } /* set pointers */ *a = (auth_t*)pointer; (*a)->type = &hmac; (*a)->state = pointer + sizeof(auth_t); (*a)->out_len = out_len; (*a)->key_len = key_len; (*a)->prefix_len = 0; new_hmac_ctx = (hmac_ctx_t*)((*a)->state); memset(new_hmac_ctx, 0, sizeof(hmac_ctx_t)); /* increment global count of all hmac uses */ hmac.ref_count++; return err_status_ok; }
uint64_t cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher, unsigned octets_in_buffer, int num_trials) { int i; v128_t nonce; clock_t timer; unsigned char *enc_buf; int cipher_index = rand() % num_cipher; /* Over-alloc, for NIST CBC padding */ enc_buf = crypto_alloc(octets_in_buffer+17); if (enc_buf == NULL) return 0; /* indicate bad parameters by returning null */ memset(enc_buf, 0, octets_in_buffer); /* time repeated trials */ v128_set_to_zero(&nonce); timer = clock(); for(i=0; i < num_trials; i++, nonce.v32[3] = i) { /* length parameter to cipher_encrypt is in/out -- out is total, padded * length -- so reset it each time. */ unsigned octets_to_encrypt = octets_in_buffer; /* encrypt buffer with cipher */ cipher_set_iv(cipher_array[cipher_index], &nonce, direction_encrypt); cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_to_encrypt); /* choose a cipher at random from the array*/ cipher_index = (*((uint32_t *)enc_buf)) % num_cipher; } timer = clock() - timer; free(enc_buf); if (timer == 0) { /* Too fast! */ return 0; } return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; }
uint64_t cipher_array_bits_per_second (cipher_t *cipher_array[], int num_cipher, unsigned octets_in_buffer, int num_trials) { int i; v128_t nonce; clock_t timer; unsigned char *enc_buf; int cipher_index = 0; enc_buf = crypto_alloc(octets_in_buffer); if (enc_buf == NULL) { return 0; /* indicate bad parameters by returning null */ } /* time repeated trials */ v128_set_to_zero(&nonce); timer = clock(); for (i = 0; i < num_trials; i++, nonce.v32[3] = i) { /* choose a cipher at random from the array*/ cipher_index = (*((uint32_t*)enc_buf)) % num_cipher; /* encrypt buffer with cipher */ cipher_set_iv(cipher_array[cipher_index], &nonce, direction_encrypt); cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_in_buffer); } timer = clock() - timer; free(enc_buf); if (timer == 0) { /* Too fast! */ return 0; } return CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; }
err_status_t aes_icm_alloc(cipher_t **c, int key_len) { extern cipher_type_t aes_icm; uint8_t *pointer; int tmp; debug_print(mod_aes_icm, "allocating cipher with key length %d", key_len); #if GENERIC_AESICM // Ismacryp, for example, uses 16 byte key + 8 byte // salt so this function is called with key_len = 24. // The check for key_len = 30 does not apply. Our usage // of aes functions with key_len = values other than 30 // has not broken anything. Don't know what would be the // effect of skipping this check for srtp in general. #else if (key_len != 30) return err_status_bad_param; #endif /* allocate memory a cipher of type aes_icm */ tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t)); pointer = crypto_alloc(tmp); if (pointer == NULL) return err_status_alloc_fail; /* set pointers */ *c = (cipher_t *)pointer; (*c)->type = &aes_icm; (*c)->state = pointer + sizeof(cipher_t); /* increment ref_count */ aes_icm.ref_count++; /* set key size */ (*c)->key_len = key_len; return err_status_ok; }