err_status_t aes_icm_context_init(aes_icm_ctx_t *c, const octet_t *key) { v128_t tmp_key; /* set counter and initial values to 'offset' value */ /* FIX!!! this assumes the salt is at key + 16, and thus that the */ /* FIX!!! cipher key length is 16! Also note this copies past the end of the 'key' array by 2 bytes! */ v128_copy_octet_string(&c->counter, key + 16); v128_copy_octet_string(&c->offset, key + 16); /* force last two octets of the offset to zero (for srtp compatibility) */ c->offset.octet[14] = c->offset.octet[15] = 0; c->counter.octet[14] = c->counter.octet[15] = 0; /* set tmp_key (for alignment) */ v128_copy_octet_string(&tmp_key, key); debug_print(mod_aes_icm, "key: %s", v128_hex_string(&tmp_key)); debug_print(mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); /* expand key */ aes_expand_encryption_key(tmp_key, c->expanded_key); /* indicate that the keystream_buffer is empty */ c->bytes_in_buffer = 0; return err_status_ok; }
inline void aes_icm_advance(aes_icm_ctx_t *c) { #if GENERIC_AESICM uint32_t temp; #endif /* fill buffer with new keystream */ v128_copy(&c->keystream_buffer, &c->counter); aes_encrypt(&c->keystream_buffer, c->expanded_key); c->bytes_in_buffer = 16; debug_print(mod_aes_icm, "counter: %s", v128_hex_string(&c->counter)); debug_print(mod_aes_icm, "ciphertext: %s", v128_hex_string(&c->keystream_buffer)); /* clock counter forward */ #if GENERIC_AESICM //alex's clock counter forward temp = ntohl(c->counter.v32[3]); c->counter.v32[3] = htonl(++temp); #else if (!++(c->counter.octet[15])) ++(c->counter.octet[14]); #endif }
/* * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ err_status_t aes_icm_openssl_set_iv (aes_icm_ctx_t *c, void *iv, int dir) { const EVP_CIPHER *evp; v128_t *nonce = (v128_t*)iv; debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(nonce)); v128_xor(&c->counter, &c->offset, nonce); debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); switch (c->key_size) { case AES_256_KEYSIZE: evp = EVP_aes_256_ctr(); break; case AES_192_KEYSIZE: evp = EVP_aes_192_ctr(); break; case AES_128_KEYSIZE: evp = EVP_aes_128_ctr(); break; default: return err_status_bad_param; break; } if (!EVP_EncryptInit_ex(&c->ctx, evp, NULL, c->key.v8, c->counter.v8)) { return err_status_fail; } else { return err_status_ok; } }
/* * aes_icm_openssl_context_init(...) initializes the aes_icm_context * using the value in key[]. * * the key is the secret key * * the salt is unpredictable (but not necessarily secret) data which * randomizes the starting point in the keystream */ err_status_t aes_icm_openssl_context_init (aes_icm_ctx_t *c, const uint8_t *key) { /* set counter and initial values to 'offset' value */ /* FIX!!! this assumes the salt is at key + 16, and thus that the */ /* FIX!!! cipher key length is 16! Also note this copies past the end of the 'key' array by 2 bytes! */ v128_copy_octet_string(&c->counter, key + c->key_size); v128_copy_octet_string(&c->offset, key + c->key_size); /* force last two octets of the offset to zero (for srtp compatibility) */ c->offset.v8[SALT_SIZE] = c->offset.v8[SALT_SIZE + 1] = 0; c->counter.v8[SALT_SIZE] = c->counter.v8[SALT_SIZE + 1] = 0; /* copy key to be used later when CiscoSSL crypto context is created */ v128_copy_octet_string((v128_t*)&c->key, key); /* if the key is greater than 16 bytes, copy the second * half. Note, we treat AES-192 and AES-256 the same here * for simplicity. The storage location receiving the * key is statically allocated to handle a full 32 byte key * regardless of the cipher in use. */ if (c->key_size == AES_256_KEYSIZE || c->key_size == AES_192_KEYSIZE) { debug_print(mod_aes_icm, "Copying last 16 bytes of key: %s", v128_hex_string((v128_t*)(key + AES_128_KEYSIZE))); v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1, key + AES_128_KEYSIZE); } debug_print(mod_aes_icm, "key: %s", v128_hex_string((v128_t*)&c->key)); debug_print(mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); EVP_CIPHER_CTX_cleanup(&c->ctx); return err_status_ok; }
/* * aes_icm_advance(...) refills the keystream_buffer and * advances the block index of the sicm_context forward by one * * this is an internal, hopefully inlined function */ static void srtp_aes_icm_advance_ismacryp (srtp_aes_icm_ctx_t *c, uint8_t forIsmacryp) { /* fill buffer with new keystream */ v128_copy(&c->keystream_buffer, &c->counter); srtp_aes_encrypt(&c->keystream_buffer, &c->expanded_key); c->bytes_in_buffer = sizeof(v128_t); debug_print(srtp_mod_aes_icm, "counter: %s", v128_hex_string(&c->counter)); debug_print(srtp_mod_aes_icm, "ciphertext: %s", v128_hex_string(&c->keystream_buffer)); /* clock counter forward */ if (forIsmacryp) { uint32_t temp; //alex's clock counter forward temp = ntohl(c->counter.v32[3]); ++temp; c->counter.v32[3] = htonl(temp); } else { if (!++(c->counter.v8[15])) { ++(c->counter.v8[14]); } } }
// int main(int argc, char *argv[]) { int aes_calc(char *key8, char *phrase8, char *cipher8) { v128_t data, key; aes_expanded_key_t exp_key; int len; int verbose = 0; /* read in key, checking length */ if (strlen(key8) > AES_KEY_LEN * 2) { fprintf(stderr, "error: too many digits in key " "(should be %d hexadecimal digits, found %u)\n", AES_KEY_LEN * 2, (unsigned) strlen(key8)); return(1); } len = hex_string_to_octet_string((char *) &key, key8, AES_KEY_LEN*2); /* check that hex string is the right length */ if (len < AES_KEY_LEN * 2) { fprintf(stderr, "error: too few digits in key " "(should be %d hexadecimal digits, found %d)\n", AES_KEY_LEN * 2, len); return(1); } /* read in plaintext, checking length */ if (strlen(phrase8) > 16 * 2) { fprintf(stderr, "error: too many digits in plaintext " "(should be %d hexadecimal digits, found %u)\n", 16 * 2, (unsigned) strlen(phrase8)); return(1); } len = hex_string_to_octet_string((char *) (&data), phrase8, 16 * 2); /* check that hex string is the right length */ if (len < 16 * 2) { fprintf(stderr, "error: too few digits in plaintext " "(should be %d hexadecimal digits, found %d)\n", 16 * 2, len); return(1); } if (verbose) { /* print out plaintext */ printf("plaintext:\t%s\n", octet_string_hex_string((uint8_t *) &data, 16)); } /* encrypt plaintext */ aes_expand_encryption_key(&key, exp_key); aes_encrypt(&data, exp_key); /* write ciphertext to output */ if (verbose) { printf("key:\t\t%s\n", v128_hex_string(&key)); printf("ciphertext:\t"); } printf("%s\n", v128_hex_string(&data)); return strcmp(v128_hex_string(&data), cipher8); }
err_status_t aes_cbc_encrypt(aes_cbc_ctx_t *c, unsigned char *data, unsigned int *bytes_in_data) { int i; unsigned char *input = data; /* pointer to data being read */ unsigned char *output = data; /* pointer to data being written */ int bytes_to_encr = *bytes_in_data; /* * verify that we're 16-octet aligned */ if (*bytes_in_data & 0xf) return err_status_bad_param; /* * note that we assume that the initialization vector has already * been set, e.g. by calling aes_cbc_set_iv() */ debug_print(mod_aes_cbc, "iv: %s", v128_hex_string(&c->state)); /* * loop over plaintext blocks, exoring state into plaintext then * encrypting and writing to output */ while (bytes_to_encr > 0) { /* exor plaintext into state */ for (i=0; i < 16; i++) c->state.v8[i] ^= *input++; debug_print(mod_aes_cbc, "inblock: %s", v128_hex_string(&c->state)); aes_encrypt(&c->state, &c->expanded_key); debug_print(mod_aes_cbc, "outblock: %s", v128_hex_string(&c->state)); /* copy ciphertext to output */ for (i=0; i < 16; i++) *output++ = c->state.v8[i]; bytes_to_encr -= 16; } return err_status_ok; }
err_status_t aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv, int direction) { err_status_t status; int i; /* v128_t *input = iv; */ uint8_t *input = (uint8_t*) iv; /* set state and 'previous' block to iv */ for (i=0; i < 16; i++) c->previous.v8[i] = c->state.v8[i] = input[i]; debug_print(mod_aes_cbc, "setting iv: %s", v128_hex_string(&c->state)); /* expand key for the appropriate direction */ switch (direction) { case (direction_encrypt): status = aes_expand_encryption_key(c->key, c->key_len, &c->expanded_key); memset(c->key, 0, 32); if (status) return status; break; case (direction_decrypt): status = aes_expand_decryption_key(c->key, c->key_len, &c->expanded_key); memset(c->key, 0, 32); if (status) return status; break; default: return err_status_bad_param; } return err_status_ok; }
/* * aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ static srtp_err_status_t srtp_aes_gcm_openssl_set_iv( void *cv, uint8_t *iv, srtp_cipher_direction_t direction) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; if (direction != srtp_direction_encrypt && direction != srtp_direction_decrypt) { return (srtp_err_status_bad_param); } c->dir = direction; debug_print(srtp_mod_aes_gcm, "setting iv: %s", v128_hex_string((v128_t *)iv)); if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) { return (srtp_err_status_init_fail); } if (!EVP_CipherInit_ex(c->ctx, NULL, NULL, NULL, iv, (c->dir == srtp_direction_encrypt ? 1 : 0))) { return (srtp_err_status_init_fail); } return (srtp_err_status_ok); }
err_status_t aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, cipher_direction_t dir) { v128_t tmp_key; /* set tmp_key (for alignment) */ v128_copy_octet_string(&tmp_key, key); debug_print(mod_aes_cbc, "key: %s", v128_hex_string(&tmp_key)); /* expand key for the appropriate direction */ switch (dir) { case (direction_encrypt): aes_expand_encryption_key(&tmp_key, c->expanded_key); break; case (direction_decrypt): aes_expand_decryption_key(&tmp_key, c->expanded_key); break; default: return err_status_bad_param; } return err_status_ok; }
err_status_t aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) { v128_t *nonce = iv; debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(nonce)); v128_xor(&c->counter, &c->offset, nonce); debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); /* indicate that the keystream_buffer is empty */ c->bytes_in_buffer = 0; return err_status_ok; }
/* * aes_icm_advance(...) refills the keystream_buffer and * advances the block index of the sicm_context forward by one * * this is an internal, hopefully inlined function */ static void srtp_aes_icm_advance (srtp_aes_icm_ctx_t *c) { /* fill buffer with new keystream */ v128_copy(&c->keystream_buffer, &c->counter); srtp_aes_encrypt(&c->keystream_buffer, &c->expanded_key); c->bytes_in_buffer = sizeof(v128_t); debug_print(srtp_mod_aes_icm, "counter: %s", v128_hex_string(&c->counter)); debug_print(srtp_mod_aes_icm, "ciphertext: %s", v128_hex_string(&c->keystream_buffer)); /* clock counter forward */ if (!++(c->counter.v8[15])) { ++(c->counter.v8[14]); } }
/* * aes_icm_openssl_context_init(...) initializes the aes_icm_context * using the value in key[]. * * the key is the secret key * * the salt is unpredictable (but not necessarily secret) data which * randomizes the starting point in the keystream */ err_status_t aes_icm_openssl_context_init (aes_icm_ctx_t *c, const uint8_t *key, int len) { /* * set counter and initial values to 'offset' value, being careful not to * go past the end of the key buffer */ if (c->key_size + SALT_SIZE != len) return err_status_bad_param; v128_set_to_zero(&c->counter); v128_set_to_zero(&c->offset); memcpy(&c->counter, key + c->key_size, SALT_SIZE); memcpy(&c->offset, key + c->key_size, SALT_SIZE); /* force last two octets of the offset to zero (for srtp compatibility) */ c->offset.v8[SALT_SIZE] = c->offset.v8[SALT_SIZE + 1] = 0; c->counter.v8[SALT_SIZE] = c->counter.v8[SALT_SIZE + 1] = 0; /* copy key to be used later when CiscoSSL crypto context is created */ v128_copy_octet_string((v128_t*)&c->key, key); /* if the key is greater than 16 bytes, copy the second * half. Note, we treat AES-192 and AES-256 the same here * for simplicity. The storage location receiving the * key is statically allocated to handle a full 32 byte key * regardless of the cipher in use. */ if (c->key_size == AES_256_KEYSIZE #ifndef BORINGSSL || c->key_size == AES_192_KEYSIZE #endif ) { debug_print(mod_aes_icm, "Copying last 16 bytes of key: %s", v128_hex_string((v128_t*)(key + AES_128_KEYSIZE))); v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1, key + AES_128_KEYSIZE); } debug_print(mod_aes_icm, "key: %s", v128_hex_string((v128_t*)&c->key)); debug_print(mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); EVP_CIPHER_CTX_cleanup(&c->ctx); return err_status_ok; }
/* * aes_gcm_openssl_context_init(...) initializes the aes_gcm_context * using the value in key[]. * * the key is the secret key */ err_status_t aes_gcm_openssl_context_init (aes_gcm_ctx_t *c, const uint8_t *key) { c->dir = direction_any; /* copy key to be used later when CiscoSSL crypto context is created */ v128_copy_octet_string((v128_t*)&c->key, key); if (c->key_size == AES_256_KEYSIZE) { debug_print(mod_aes_gcm, "Copying last 16 bytes of key: %s", v128_hex_string((v128_t*)(key + AES_128_KEYSIZE))); v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1, key + AES_128_KEYSIZE); } debug_print(mod_aes_gcm, "key: %s", v128_hex_string((v128_t*)&c->key)); EVP_CIPHER_CTX_cleanup(&c->ctx); return (err_status_ok); }
static srtp_err_status_t srtp_aes_icm_set_iv (srtp_aes_icm_ctx_t *c, uint8_t *iv, int direction) { v128_t nonce; /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); v128_xor(&c->counter, &c->offset, &nonce); debug_print(srtp_mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); /* indicate that the keystream_buffer is empty */ c->bytes_in_buffer = 0; return srtp_err_status_ok; }
/* * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ static srtp_err_status_t srtp_aes_icm_openssl_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t dir) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; v128_t nonce; /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); v128_xor(&c->counter, &c->offset, &nonce); debug_print(srtp_mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); if (!EVP_EncryptInit_ex(c->ctx, NULL, NULL, NULL, c->counter.v8)) { return srtp_err_status_fail; } else { return srtp_err_status_ok; } }
void byte_order(void) { int i; v128_t e; #if 0 v16_t b; v32_t c; v64_t d; for (i=0; i < sizeof(b); i++) b.octet[i] = i; for (i=0; i < sizeof(c); i++) c.octet[i] = i; for (i=0; i < sizeof(d); i++) d.octet[i] = i; printf("v128_t:\t%s\n", v128_hex_string(&e)); printf("v64_t:\t%s\n", v64_hex_string(&d)); printf("v32_t:\t%s\n", v32_hex_string(c)); printf("v16_t:\t%s\n", v16_hex_string(b)); c.value = 0x01020304; printf("v32_t:\t%s\n", v32_hex_string(c)); b.value = 0x0102; printf("v16_t:\t%s\n", v16_hex_string(b)); printf("uint16_t ordering:\n"); c.value = 0x00010002; printf("v32_t:\t%x%x\n", c.v16[0], c.v16[1]); #endif printf("byte ordering of crypto/math datatypes:\n"); for (i=0; i < sizeof(e); i++) e.v8[i] = i; printf("v128_t: %s\n", v128_hex_string(&e)); }
/* * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ err_status_t aes_icm_openssl_set_iv (aes_icm_ctx_t *c, void *iv, int dir) { const EVP_CIPHER *evp; v128_t nonce; /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); v128_xor(&c->counter, &c->offset, &nonce); debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); switch (c->key_size) { case AES_256_KEYSIZE: evp = EVP_aes_256_ctr(); break; #ifndef BORINGSSL case AES_192_KEYSIZE: evp = EVP_aes_192_ctr(); break; #endif case AES_128_KEYSIZE: evp = EVP_aes_128_ctr(); break; default: return err_status_bad_param; break; } if (!EVP_EncryptInit_ex(&c->ctx, evp, NULL, c->key.v8, c->counter.v8)) { return err_status_fail; } else { return err_status_ok; } }
err_status_t aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) { int i; /* v128_t *input = iv; */ uint8_t *input = iv; /* set state and 'previous' block to iv */ for (i=0; i < 16; i++) c->previous.v8[i] = c->state.v8[i] = input[i]; debug_print(mod_aes_cbc, "setting iv: %s", v128_hex_string(&c->state)); return err_status_ok; }
err_status_t aes_icm_set_octet(aes_icm_ctx_t *c, uint64_t octet_num) { int tail_num = octet_num % 16; uint64_t block_num = octet_num / 16; /* set counter value */ c->counter.v64[0] = c->offset.v64[0]; c->counter.v64[0] = c->offset.v64[0] ^ block_num; debug_print(mod_aes_icm, "set_octet: %s", v128_hex_string(&c->counter)); /* fill keystream buffer, if needed */ if (tail_num) { v128_copy(&c->keystream_buffer, &c->counter); aes_encrypt(&c->keystream_buffer, c->expanded_key); c->bytes_in_buffer = 16; debug_print(mod_aes_icm, "counter: %s", v128_hex_string(&c->counter)); debug_print(mod_aes_icm, "ciphertext: %s", v128_hex_string(&c->keystream_buffer)); /* indicate number of bytes in keystream_buffer */ c->bytes_in_buffer = 16 - tail_num; } else { /* indicate that keystream_buffer is empty */ c->bytes_in_buffer = 0; } return err_status_ok; }
static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; srtp_err_status_t status; int base_key_len, copy_len; if (c->key_size > 16 && c->key_size < 30) { /* Ismacryp */ base_key_len = 16; } else if (c->key_size == 30 || c->key_size == 38 || c->key_size == 46) { base_key_len = c->key_size - 14; } else{ return srtp_err_status_bad_param; } /* * set counter and initial values to 'offset' value, being careful not to * go past the end of the key buffer */ v128_set_to_zero(&c->counter); v128_set_to_zero(&c->offset); copy_len = c->key_size - base_key_len; /* force last two octets of the offset to be left zero (for srtp compatibility) */ if (copy_len > 14) { copy_len = 14; } memcpy(&c->counter, key + base_key_len, copy_len); memcpy(&c->offset, key + base_key_len, copy_len); debug_print(srtp_mod_aes_icm, "key: %s", srtp_octet_string_hex_string(key, base_key_len)); debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); /* expand key */ status = srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key); if (status) { v128_set_to_zero(&c->counter); v128_set_to_zero(&c->offset); return status; } /* indicate that the keystream_buffer is empty */ c->bytes_in_buffer = 0; return srtp_err_status_ok; }
/* * aes_icm_openssl_context_init(...) initializes the aes_icm_context * using the value in key[]. * * the key is the secret key * * the salt is unpredictable (but not necessarily secret) data which * randomizes the starting point in the keystream */ static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint8_t *key) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; const EVP_CIPHER *evp; /* * set counter and initial values to 'offset' value, being careful not to * go past the end of the key buffer */ v128_set_to_zero(&c->counter); v128_set_to_zero(&c->offset); memcpy(&c->counter, key + c->key_size, SRTP_SALT_SIZE); memcpy(&c->offset, key + c->key_size, SRTP_SALT_SIZE); /* force last two octets of the offset to zero (for srtp compatibility) */ c->offset.v8[SRTP_SALT_SIZE] = c->offset.v8[SRTP_SALT_SIZE + 1] = 0; c->counter.v8[SRTP_SALT_SIZE] = c->counter.v8[SRTP_SALT_SIZE + 1] = 0; debug_print(srtp_mod_aes_icm, "key: %s", srtp_octet_string_hex_string(key, c->key_size)); debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); switch (c->key_size) { case SRTP_AES_256_KEYSIZE: evp = EVP_aes_256_ctr(); break; #ifndef SRTP_NO_AES192 case SRTP_AES_192_KEYSIZE: evp = EVP_aes_192_ctr(); break; #endif case SRTP_AES_128_KEYSIZE: evp = EVP_aes_128_ctr(); break; default: return srtp_err_status_bad_param; break; } if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) { return srtp_err_status_fail; } else { return srtp_err_status_ok; } return srtp_err_status_ok; }
/* * This function encrypts a buffer using AES CTR mode * * Parameters: * c Crypto context * buf data to encrypt * enc_len length of encrypt buffer */ err_status_t aes_icm_openssl_encrypt (aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) { int len = 0; debug_print(mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter)); if (!EVP_EncryptUpdate(&c->ctx, buf, &len, buf, *enc_len)) { return err_status_cipher_fail; } *enc_len = len; if (!EVP_EncryptFinal_ex(&c->ctx, buf, (int*)&len)) { return err_status_cipher_fail; } *enc_len += len; return err_status_ok; }
/* * aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ err_status_t aes_gcm_openssl_set_iv (aes_gcm_ctx_t *c, void *iv, int direction) { const EVP_CIPHER *evp; v128_t *nonce = iv; if (direction != direction_encrypt && direction != direction_decrypt) { return (err_status_bad_param); } c->dir = direction; debug_print(mod_aes_gcm, "setting iv: %s", v128_hex_string(nonce)); switch (c->key_size) { case AES_256_KEYSIZE: evp = EVP_aes_256_gcm(); break; case AES_128_KEYSIZE: evp = EVP_aes_128_gcm(); break; default: return (err_status_bad_param); break; } if (!EVP_CipherInit_ex(&c->ctx, evp, NULL, (const unsigned char*)&c->key.v8, NULL, (c->dir == direction_encrypt ? 1 : 0))) { return (err_status_init_fail); } /* set IV len and the IV value, the followiong 3 calls are required */ if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) { return (err_status_init_fail); } if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) { return (err_status_init_fail); } if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_IV_GEN, 0, iv)) { return (err_status_init_fail); } return (err_status_ok); }
/* * This function encrypts a buffer using AES CTR mode * * Parameters: * c Crypto context * buf data to encrypt * enc_len length of encrypt buffer */ static srtp_err_status_t srtp_aes_icm_openssl_encrypt (void *cv, unsigned char *buf, unsigned int *enc_len) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; int len = 0; debug_print(srtp_mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter)); if (!EVP_EncryptUpdate(c->ctx, buf, &len, buf, *enc_len)) { return srtp_err_status_cipher_fail; } *enc_len = len; if (!EVP_EncryptFinal_ex(c->ctx, buf, &len)) { return srtp_err_status_cipher_fail; } *enc_len += len; return srtp_err_status_ok; }
err_status_t aes_cbc_decrypt(aes_cbc_ctx_t *c, unsigned char *data, unsigned int *bytes_in_data) { int i; v128_t state, previous; unsigned char *input = data; /* pointer to data being read */ unsigned char *output = data; /* pointer to data being written */ int bytes_to_encr = *bytes_in_data; uint8_t tmp; /* * verify that we're 16-octet aligned */ if (*bytes_in_data & 0x0f) return err_status_bad_param; /* set 'previous' block to iv*/ for (i=0; i < 16; i++) { previous.v8[i] = c->previous.v8[i]; } debug_print(mod_aes_cbc, "iv: %s", v128_hex_string(&previous)); /* * loop over ciphertext blocks, decrypting then exoring with state * then writing plaintext to output */ while (bytes_to_encr > 0) { /* set state to ciphertext input block */ for (i=0; i < 16; i++) { state.v8[i] = *input++; } debug_print(mod_aes_cbc, "inblock: %s", v128_hex_string(&state)); /* decrypt state */ aes_decrypt(&state, &c->expanded_key); debug_print(mod_aes_cbc, "outblock: %s", v128_hex_string(&state)); /* * exor previous ciphertext block out of plaintext, and write new * plaintext block to output, while copying old ciphertext block * to the 'previous' block */ for (i=0; i < 16; i++) { tmp = *output; *output++ = state.v8[i] ^ previous.v8[i]; previous.v8[i] = tmp; } bytes_to_encr -= 16; } return err_status_ok; }