summaryrefslogtreecommitdiff
path: root/third_party/srtp/crypto/cipher
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/srtp/crypto/cipher')
-rw-r--r--third_party/srtp/crypto/cipher/aes.c393
-rw-r--r--third_party/srtp/crypto/cipher/aes_cbc.c177
-rw-r--r--third_party/srtp/crypto/cipher/aes_gcm_ossl.c570
-rw-r--r--third_party/srtp/crypto/cipher/aes_icm.c155
-rw-r--r--third_party/srtp/crypto/cipher/aes_icm_ossl.c563
-rw-r--r--third_party/srtp/crypto/cipher/cipher.c147
-rw-r--r--third_party/srtp/crypto/cipher/null_cipher.c19
7 files changed, 1836 insertions, 188 deletions
diff --git a/third_party/srtp/crypto/cipher/aes.c b/third_party/srtp/crypto/cipher/aes.c
index f1286c36..e91e5254 100644
--- a/third_party/srtp/crypto/cipher/aes.c
+++ b/third_party/srtp/crypto/cipher/aes.c
@@ -43,6 +43,9 @@
*
*/
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
#include "aes.h"
#include "err.h"
@@ -1358,51 +1361,50 @@ static uint32_t U4[256] = {
extern debug_module_t mod_aes_icm;
-void
-aes_expand_encryption_key(const v128_t *key,
- aes_expanded_key_t expanded_key) {
+static void
+aes_128_expand_encryption_key(const uint8_t *key,
+ aes_expanded_key_t *expanded_key) {
int i;
gf2_8 rc;
/* initialize round constant */
rc = 1;
- expanded_key[0].v32[0] = key->v32[0];
- expanded_key[0].v32[1] = key->v32[1];
- expanded_key[0].v32[2] = key->v32[2];
- expanded_key[0].v32[3] = key->v32[3];
+ expanded_key->num_rounds = 10;
+
+ v128_copy_octet_string(&expanded_key->round[0], key);
#if 0
debug_print(mod_aes_icm,
- "expanded key[0]: %s", v128_hex_string(&expanded_key[0]));
+ "expanded key[0]: %s", v128_hex_string(&expanded_key->round[0]));
#endif
/* loop over round keys */
for (i=1; i < 11; i++) {
/* munge first word of round key */
- expanded_key[i].v8[0] = aes_sbox[expanded_key[i-1].v8[13]] ^ rc;
- expanded_key[i].v8[1] = aes_sbox[expanded_key[i-1].v8[14]];
- expanded_key[i].v8[2] = aes_sbox[expanded_key[i-1].v8[15]];
- expanded_key[i].v8[3] = aes_sbox[expanded_key[i-1].v8[12]];
+ expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc;
+ expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]];
+ expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]];
+ expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[12]];
- expanded_key[i].v32[0] ^= expanded_key[i-1].v32[0];
+ expanded_key->round[i].v32[0] ^= expanded_key->round[i-1].v32[0];
/* set remaining 32 bit words to the exor of the one previous with
* the one four words previous */
- expanded_key[i].v32[1] =
- expanded_key[i].v32[0] ^ expanded_key[i-1].v32[1];
+ expanded_key->round[i].v32[1] =
+ expanded_key->round[i].v32[0] ^ expanded_key->round[i-1].v32[1];
- expanded_key[i].v32[2] =
- expanded_key[i].v32[1] ^ expanded_key[i-1].v32[2];
+ expanded_key->round[i].v32[2] =
+ expanded_key->round[i].v32[1] ^ expanded_key->round[i-1].v32[2];
- expanded_key[i].v32[3] =
- expanded_key[i].v32[2] ^ expanded_key[i-1].v32[3];
+ expanded_key->round[i].v32[3] =
+ expanded_key->round[i].v32[2] ^ expanded_key->round[i-1].v32[3];
#if 0
debug_print2(mod_aes_icm,
- "expanded key[%d]: %s", i,v128_hex_string(&expanded_key[i]));
+ "expanded key[%d]: %s", i,v128_hex_string(&expanded_key->round[i]));
#endif
/* modify round constant */
@@ -1411,19 +1413,107 @@ aes_expand_encryption_key(const v128_t *key,
}
}
-void
-aes_expand_decryption_key(const v128_t *key,
- aes_expanded_key_t expanded_key) {
+static void
+aes_256_expand_encryption_key(const unsigned char *key,
+ aes_expanded_key_t *expanded_key) {
+ int i;
+ gf2_8 rc;
+
+ /* initialize round constant */
+ rc = 1;
+
+ expanded_key->num_rounds = 14;
+
+ v128_copy_octet_string(&expanded_key->round[0], key);
+ v128_copy_octet_string(&expanded_key->round[1], key+16);
+
+#if 0
+ debug_print(mod_aes_icm,
+ "expanded key[0]: %s", v128_hex_string(&expanded_key->round[0]));
+ debug_print(mod_aes_icm,
+ "expanded key[1]: %s", v128_hex_string(&expanded_key->round[1]));
+#endif
+
+ /* loop over rest of round keys */
+ for (i=2; i < 15; i++) {
+
+ /* munge first word of round key */
+ if ((i & 1) == 0) {
+ expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc;
+ expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]];
+ expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]];
+ expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[12]];
+
+ /* modify round constant */
+ rc = gf2_8_shift(rc);
+ }
+ else {
+ expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[12]];
+ expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[13]];
+ expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[14]];
+ expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[15]];
+ }
+
+ expanded_key->round[i].v32[0] ^= expanded_key->round[i-2].v32[0];
+
+ /* set remaining 32 bit words to the exor of the one previous with
+ * the one eight words previous */
+
+ expanded_key->round[i].v32[1] =
+ expanded_key->round[i].v32[0] ^ expanded_key->round[i-2].v32[1];
+
+ expanded_key->round[i].v32[2] =
+ expanded_key->round[i].v32[1] ^ expanded_key->round[i-2].v32[2];
+
+ expanded_key->round[i].v32[3] =
+ expanded_key->round[i].v32[2] ^ expanded_key->round[i-2].v32[3];
+
+#if 0
+ debug_print2(mod_aes_icm,
+ "expanded key[%d]: %s", i,v128_hex_string(&expanded_key->round[i]));
+#endif
+
+ }
+}
+
+err_status_t
+aes_expand_encryption_key(const uint8_t *key,
+ int key_len,
+ aes_expanded_key_t *expanded_key) {
+ if (key_len == 16) {
+ aes_128_expand_encryption_key(key, expanded_key);
+ return err_status_ok;
+ }
+ else if (key_len == 24) {
+ /* AES-192 not yet supported */
+ return err_status_bad_param;
+ }
+ else if (key_len == 32) {
+ aes_256_expand_encryption_key(key, expanded_key);
+ return err_status_ok;
+ }
+ else
+ return err_status_bad_param;
+}
+
+err_status_t
+aes_expand_decryption_key(const uint8_t *key,
+ int key_len,
+ aes_expanded_key_t *expanded_key) {
int i;
+ err_status_t status;
+ int num_rounds = expanded_key->num_rounds;
- aes_expand_encryption_key(key, expanded_key);
+ status = aes_expand_encryption_key(key, key_len, expanded_key);
+ if (status)
+ return status;
/* invert the order of the round keys */
- for (i=0; i < 5; i++) {
+ for (i=0; i < num_rounds/2; i++) {
v128_t tmp;
- v128_copy(&tmp, &expanded_key[10-i]);
- v128_copy(&expanded_key[10-i], &expanded_key[i]);
- v128_copy(&expanded_key[i], &tmp);
+ v128_copy(&tmp, &expanded_key->round[num_rounds-i]);
+ v128_copy(&expanded_key->round[num_rounds-i], &expanded_key->round[i]);
+ v128_copy(&expanded_key->round[i], &tmp);
}
/*
@@ -1434,68 +1524,101 @@ aes_expand_decryption_key(const v128_t *key,
* followed by the T4 table (which cancels out the use of the sbox
* in the U-tables)
*/
- for (i=1; i < 10; i++) {
+ for (i=1; i < num_rounds; i++) {
#ifdef CPU_RISC
uint32_t tmp;
- tmp = expanded_key[i].v32[0];
- expanded_key[i].v32[0] =
+#ifdef WORDS_BIGENDIAN
+ tmp = expanded_key->round[i].v32[0];
+ expanded_key->round[i].v32[0] =
U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 0xff] & 0xff] ^
U3[T4[(tmp) & 0xff] & 0xff];
- tmp = expanded_key[i].v32[1];
- expanded_key[i].v32[1] =
+ tmp = expanded_key->round[i].v32[1];
+ expanded_key->round[i].v32[1] =
U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 0xff] & 0xff] ^
U3[T4[(tmp) & 0xff] & 0xff];
- tmp = expanded_key[i].v32[2];
- expanded_key[i].v32[2] =
+ tmp = expanded_key->round[i].v32[2];
+ expanded_key->round[i].v32[2] =
U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 0xff] & 0xff] ^
U3[T4[(tmp) & 0xff] & 0xff];
- tmp = expanded_key[i].v32[3];
- expanded_key[i].v32[3] =
+ tmp = expanded_key->round[i].v32[3];
+ expanded_key->round[i].v32[3] =
U0[T4[(tmp >> 24) ] & 0xff] ^
U1[T4[(tmp >> 16) & 0xff] & 0xff] ^
U2[T4[(tmp >> 8) & 0xff] & 0xff] ^
U3[T4[(tmp) & 0xff] & 0xff];
+#else
+ tmp = expanded_key->round[i].v32[0];
+ expanded_key->round[i].v32[0] =
+ U3[T4[(tmp >> 24) ] & 0xff] ^
+ U2[T4[(tmp >> 16) & 0xff] & 0xff] ^
+ U1[T4[(tmp >> 8) & 0xff] & 0xff] ^
+ U0[T4[(tmp) & 0xff] & 0xff];
+
+ tmp = expanded_key->round[i].v32[1];
+ expanded_key->round[i].v32[1] =
+ U3[T4[(tmp >> 24) ] & 0xff] ^
+ U2[T4[(tmp >> 16) & 0xff] & 0xff] ^
+ U1[T4[(tmp >> 8) & 0xff] & 0xff] ^
+ U0[T4[(tmp) & 0xff] & 0xff];
+
+ tmp = expanded_key->round[i].v32[2];
+ expanded_key->round[i].v32[2] =
+ U3[T4[(tmp >> 24) ] & 0xff] ^
+ U2[T4[(tmp >> 16) & 0xff] & 0xff] ^
+ U1[T4[(tmp >> 8) & 0xff] & 0xff] ^
+ U0[T4[(tmp) & 0xff] & 0xff];
+
+ tmp = expanded_key->round[i].v32[3];
+ expanded_key->round[i].v32[3] =
+ U3[T4[(tmp >> 24) ] & 0xff] ^
+ U2[T4[(tmp >> 16) & 0xff] & 0xff] ^
+ U1[T4[(tmp >> 8) & 0xff] & 0xff] ^
+ U0[T4[(tmp) & 0xff] & 0xff];
+#endif /* WORDS_BIGENDIAN */
+
#else /* assume CPU_CISC */
uint32_t c0, c1, c2, c3;
- c0 = U0[aes_sbox[expanded_key[i].v8[0]]]
- ^ U1[aes_sbox[expanded_key[i].v8[1]]]
- ^ U2[aes_sbox[expanded_key[i].v8[2]]]
- ^ U3[aes_sbox[expanded_key[i].v8[3]]];
+ c0 = U0[aes_sbox[expanded_key->round[i].v8[0]]]
+ ^ U1[aes_sbox[expanded_key->round[i].v8[1]]]
+ ^ U2[aes_sbox[expanded_key->round[i].v8[2]]]
+ ^ U3[aes_sbox[expanded_key->round[i].v8[3]]];
- c1 = U0[aes_sbox[expanded_key[i].v8[4]]]
- ^ U1[aes_sbox[expanded_key[i].v8[5]]]
- ^ U2[aes_sbox[expanded_key[i].v8[6]]]
- ^ U3[aes_sbox[expanded_key[i].v8[7]]];
+ c1 = U0[aes_sbox[expanded_key->round[i].v8[4]]]
+ ^ U1[aes_sbox[expanded_key->round[i].v8[5]]]
+ ^ U2[aes_sbox[expanded_key->round[i].v8[6]]]
+ ^ U3[aes_sbox[expanded_key->round[i].v8[7]]];
- c2 = U0[aes_sbox[expanded_key[i].v8[8]]]
- ^ U1[aes_sbox[expanded_key[i].v8[9]]]
- ^ U2[aes_sbox[expanded_key[i].v8[10]]]
- ^ U3[aes_sbox[expanded_key[i].v8[11]]];
+ c2 = U0[aes_sbox[expanded_key->round[i].v8[8]]]
+ ^ U1[aes_sbox[expanded_key->round[i].v8[9]]]
+ ^ U2[aes_sbox[expanded_key->round[i].v8[10]]]
+ ^ U3[aes_sbox[expanded_key->round[i].v8[11]]];
- c3 = U0[aes_sbox[expanded_key[i].v8[12]]]
- ^ U1[aes_sbox[expanded_key[i].v8[13]]]
- ^ U2[aes_sbox[expanded_key[i].v8[14]]]
- ^ U3[aes_sbox[expanded_key[i].v8[15]]];
+ c3 = U0[aes_sbox[expanded_key->round[i].v8[12]]]
+ ^ U1[aes_sbox[expanded_key->round[i].v8[13]]]
+ ^ U2[aes_sbox[expanded_key->round[i].v8[14]]]
+ ^ U3[aes_sbox[expanded_key->round[i].v8[15]]];
- expanded_key[i].v32[0] = c0;
- expanded_key[i].v32[1] = c1;
- expanded_key[i].v32[2] = c2;
- expanded_key[i].v32[3] = c3;
+ expanded_key->round[i].v32[0] = c0;
+ expanded_key->round[i].v32[1] = c1;
+ expanded_key->round[i].v32[2] = c2;
+ expanded_key->round[i].v32[3] = c3;
#endif
}
+
+ return err_status_ok;
}
#ifdef CPU_CISC
@@ -1676,7 +1799,6 @@ aes_inv_round(v128_t *state, const v128_t *round_key) {
of state, using the tables U0, U1, U2, U3 */
#ifdef WORDS_BIGENDIAN
- /* FIX! WRong indexes */
column0 = U0[state->v32[0] >> 24] ^ U1[(state->v32[3] >> 16) & 0xff]
^ U2[(state->v32[2] >> 8) & 0xff] ^ U3[state->v32[1] & 0xff];
@@ -1689,17 +1811,17 @@ aes_inv_round(v128_t *state, const v128_t *round_key) {
column3 = U0[state->v32[3] >> 24] ^ U1[(state->v32[2] >> 16) & 0xff]
^ U2[(state->v32[1] >> 8) & 0xff] ^ U3[state->v32[0] & 0xff];
#else
- column0 = U0[state->v32[0] & 0xff] ^ U1[(state->v32[1] >> 8) & 0xff]
- ^ U2[(state->v32[2] >> 16) & 0xff] ^ U3[state->v32[3] >> 24];
+ column0 = U0[state->v32[0] & 0xff] ^ U1[(state->v32[3] >> 8) & 0xff]
+ ^ U2[(state->v32[2] >> 16) & 0xff] ^ U3[(state->v32[1] >> 24) & 0xff];
- column1 = U0[state->v32[1] & 0xff] ^ U1[(state->v32[2] >> 8) & 0xff]
- ^ U2[(state->v32[3] >> 16) & 0xff] ^ U3[state->v32[0] >> 24];
+ column1 = U0[state->v32[1] & 0xff] ^ U1[(state->v32[0] >> 8) & 0xff]
+ ^ U2[(state->v32[3] >> 16) & 0xff] ^ U3[(state->v32[2] >> 24) & 0xff];
- column2 = U0[state->v32[2] & 0xff] ^ U1[(state->v32[3] >> 8) & 0xff]
- ^ U2[(state->v32[0] >> 16) & 0xff] ^ U3[state->v32[1] >> 24];
+ column2 = U0[state->v32[2] & 0xff] ^ U1[(state->v32[1] >> 8) & 0xff]
+ ^ U2[(state->v32[0] >> 16) & 0xff] ^ U3[(state->v32[3] >> 24) & 0xff];
- column3 = U0[state->v32[3] & 0xff] ^ U1[(state->v32[0] >> 8) & 0xff]
- ^ U2[(state->v32[1] >> 16) & 0xff] ^ U3[state->v32[2] >> 24];
+ column3 = U0[state->v32[3] & 0xff] ^ U1[(state->v32[2] >> 8) & 0xff]
+ ^ U2[(state->v32[1] >> 16) & 0xff] ^ U3[(state->v32[0] >> 24) & 0xff];
#endif /* WORDS_BIGENDIAN */
state->v32[0] = column0 ^ round_key->v32[0];
@@ -1713,6 +1835,7 @@ static inline void
aes_final_round(v128_t *state, const v128_t *round_key) {
uint32_t tmp0, tmp1, tmp2, tmp3;
+#ifdef WORDS_BIGENDIAN
tmp0 = (T4[(state->v32[0] >> 24)] & 0xff000000)
^ (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000)
^ (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00)
@@ -1736,6 +1859,31 @@ aes_final_round(v128_t *state, const v128_t *round_key) {
^ (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00)
^ (T4[(state->v32[2] ) & 0xff] & 0x000000ff)
^ round_key->v32[3];
+#else
+ tmp0 = (T4[(state->v32[3] >> 24)] & 0xff000000)
+ ^ (T4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000)
+ ^ (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00)
+ ^ (T4[(state->v32[0] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[0];
+
+ tmp1 = (T4[(state->v32[0] >> 24)] & 0xff000000)
+ ^ (T4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000)
+ ^ (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00)
+ ^ (T4[(state->v32[1] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[1];
+
+ tmp2 = (T4[(state->v32[1] >> 24)] & 0xff000000)
+ ^ (T4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000)
+ ^ (T4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00)
+ ^ (T4[(state->v32[2] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[2];
+
+ tmp3 = (T4[(state->v32[2] >> 24)] & 0xff000000)
+ ^ (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000)
+ ^ (T4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00)
+ ^ (T4[(state->v32[3] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[3];
+#endif /* WORDS_BIGENDIAN */
state->v32[0] = tmp0;
state->v32[1] = tmp1;
@@ -1748,6 +1896,7 @@ static inline void
aes_inv_final_round(v128_t *state, const v128_t *round_key) {
uint32_t tmp0, tmp1, tmp2, tmp3;
+#ifdef WORDS_BIGENDIAN
tmp0 = (U4[(state->v32[0] >> 24)] & 0xff000000)
^ (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000)
^ (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00)
@@ -1771,6 +1920,31 @@ aes_inv_final_round(v128_t *state, const v128_t *round_key) {
^ (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00)
^ (U4[(state->v32[0] ) & 0xff] & 0x000000ff)
^ round_key->v32[3];
+#else
+ tmp0 = (U4[(state->v32[1] >> 24)] & 0xff000000)
+ ^ (U4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000)
+ ^ (U4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00)
+ ^ (U4[(state->v32[0] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[0];
+
+ tmp1 = (U4[(state->v32[2] >> 24)] & 0xff000000)
+ ^ (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000)
+ ^ (U4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00)
+ ^ (U4[(state->v32[1] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[1];
+
+ tmp2 = (U4[(state->v32[3] >> 24)] & 0xff000000)
+ ^ (U4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000)
+ ^ (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00)
+ ^ (U4[(state->v32[2] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[2];
+
+ tmp3 = (U4[(state->v32[0] >> 24)] & 0xff000000)
+ ^ (U4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000)
+ ^ (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00)
+ ^ (U4[(state->v32[3] ) & 0xff] & 0x000000ff)
+ ^ round_key->v32[3];
+#endif /* WORDS_BIGENDIAN */
state->v32[0] = tmp0;
state->v32[1] = tmp1;
@@ -1910,42 +2084,67 @@ aes_inv_final_round(v128_t *state, const v128_t *round_key) {
void
-aes_encrypt(v128_t *plaintext, const aes_expanded_key_t exp_key) {
+aes_encrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key) {
/* add in the subkey */
- v128_xor_eq(plaintext, exp_key + 0);
-
- /* now do nine rounds */
- aes_round(plaintext, exp_key + 1);
- aes_round(plaintext, exp_key + 2);
- aes_round(plaintext, exp_key + 3);
- aes_round(plaintext, exp_key + 4);
- aes_round(plaintext, exp_key + 5);
- aes_round(plaintext, exp_key + 6);
- aes_round(plaintext, exp_key + 7);
- aes_round(plaintext, exp_key + 8);
- aes_round(plaintext, exp_key + 9);
- /* the last round is different */
-
- aes_final_round(plaintext, exp_key + 10);
+ v128_xor_eq(plaintext, &exp_key->round[0]);
+
+ /* now do the rounds */
+ aes_round(plaintext, &exp_key->round[1]);
+ aes_round(plaintext, &exp_key->round[2]);
+ aes_round(plaintext, &exp_key->round[3]);
+ aes_round(plaintext, &exp_key->round[4]);
+ aes_round(plaintext, &exp_key->round[5]);
+ aes_round(plaintext, &exp_key->round[6]);
+ aes_round(plaintext, &exp_key->round[7]);
+ aes_round(plaintext, &exp_key->round[8]);
+ aes_round(plaintext, &exp_key->round[9]);
+ if (exp_key->num_rounds == 10) {
+ aes_final_round(plaintext, &exp_key->round[10]);
+ }
+ else if (exp_key->num_rounds == 12) {
+ aes_round(plaintext, &exp_key->round[10]);
+ aes_round(plaintext, &exp_key->round[11]);
+ aes_final_round(plaintext, &exp_key->round[12]);
+ }
+ else if (exp_key->num_rounds == 14) {
+ aes_round(plaintext, &exp_key->round[10]);
+ aes_round(plaintext, &exp_key->round[11]);
+ aes_round(plaintext, &exp_key->round[12]);
+ aes_round(plaintext, &exp_key->round[13]);
+ aes_final_round(plaintext, &exp_key->round[14]);
+ }
}
void
-aes_decrypt(v128_t *plaintext, const aes_expanded_key_t exp_key) {
+aes_decrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key) {
/* add in the subkey */
- v128_xor_eq(plaintext, exp_key + 0);
-
- /* now do nine rounds */
- aes_inv_round(plaintext, exp_key + 1);
- aes_inv_round(plaintext, exp_key + 2);
- aes_inv_round(plaintext, exp_key + 3);
- aes_inv_round(plaintext, exp_key + 4);
- aes_inv_round(plaintext, exp_key + 5);
- aes_inv_round(plaintext, exp_key + 6);
- aes_inv_round(plaintext, exp_key + 7);
- aes_inv_round(plaintext, exp_key + 8);
- aes_inv_round(plaintext, exp_key + 9);
- /* the last round is different */
- aes_inv_final_round(plaintext, exp_key + 10);
+ v128_xor_eq(plaintext, &exp_key->round[0]);
+
+ /* now do the rounds */
+ aes_inv_round(plaintext, &exp_key->round[1]);
+ aes_inv_round(plaintext, &exp_key->round[2]);
+ aes_inv_round(plaintext, &exp_key->round[3]);
+ aes_inv_round(plaintext, &exp_key->round[4]);
+ aes_inv_round(plaintext, &exp_key->round[5]);
+ aes_inv_round(plaintext, &exp_key->round[6]);
+ aes_inv_round(plaintext, &exp_key->round[7]);
+ aes_inv_round(plaintext, &exp_key->round[8]);
+ aes_inv_round(plaintext, &exp_key->round[9]);
+ if (exp_key->num_rounds == 10) {
+ aes_inv_final_round(plaintext, &exp_key->round[10]);
+ }
+ else if (exp_key->num_rounds == 12) {
+ aes_inv_round(plaintext, &exp_key->round[10]);
+ aes_inv_round(plaintext, &exp_key->round[11]);
+ aes_inv_final_round(plaintext, &exp_key->round[12]);
+ }
+ else if (exp_key->num_rounds == 14) {
+ aes_inv_round(plaintext, &exp_key->round[10]);
+ aes_inv_round(plaintext, &exp_key->round[11]);
+ aes_inv_round(plaintext, &exp_key->round[12]);
+ aes_inv_round(plaintext, &exp_key->round[13]);
+ aes_inv_final_round(plaintext, &exp_key->round[14]);
+ }
}
diff --git a/third_party/srtp/crypto/cipher/aes_cbc.c b/third_party/srtp/crypto/cipher/aes_cbc.c
index 8fc6a327..11953bf2 100644
--- a/third_party/srtp/crypto/cipher/aes_cbc.c
+++ b/third_party/srtp/crypto/cipher/aes_cbc.c
@@ -43,6 +43,9 @@
*
*/
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
#include "aes_cbc.h"
#include "alloc.h"
@@ -55,7 +58,7 @@ debug_module_t mod_aes_cbc = {
err_status_t
-aes_cbc_alloc(cipher_t **c, int key_len) {
+aes_cbc_alloc(cipher_t **c, int key_len, int tlen) {
extern cipher_type_t aes_cbc;
uint8_t *pointer;
int tmp;
@@ -63,10 +66,10 @@ aes_cbc_alloc(cipher_t **c, int key_len) {
debug_print(mod_aes_cbc,
"allocating cipher with key length %d", key_len);
- if (key_len != 16)
+ if (key_len != 16 && key_len != 24 && key_len != 32)
return err_status_bad_param;
- /* allocate memory a cipher of type aes_icm */
+ /* 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)
@@ -74,6 +77,7 @@ aes_cbc_alloc(cipher_t **c, int key_len) {
/* set pointers */
*c = (cipher_t *)pointer;
+ (*c)->algorithm = AES_CBC;
(*c)->type = &aes_cbc;
(*c)->state = pointer + sizeof(cipher_t);
@@ -104,35 +108,25 @@ aes_cbc_dealloc(cipher_t *c) {
}
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);
+aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, int key_len) {
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;
- }
+ "key: %s", octet_string_hex_string(key, key_len));
+ /*
+ * Save the key until we have the IV later. We don't
+ * know the direction until the IV is set.
+ */
+ c->key_len = (key_len <= 32 ? key_len : 32);
+ memcpy(c->key, key, c->key_len);
return err_status_ok;
}
err_status_t
-aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) {
+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;
@@ -143,6 +137,24 @@ aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) {
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;
}
@@ -181,7 +193,7 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c,
debug_print(mod_aes_cbc, "inblock: %s",
v128_hex_string(&c->state));
- aes_encrypt(&c->state, c->expanded_key);
+ aes_encrypt(&c->state, &c->expanded_key);
debug_print(mod_aes_cbc, "outblock: %s",
v128_hex_string(&c->state));
@@ -236,7 +248,7 @@ aes_cbc_decrypt(aes_cbc_ctx_t *c,
v128_hex_string(&state));
/* decrypt state */
- aes_decrypt(&state, c->expanded_key);
+ aes_decrypt(&state, &c->expanded_key);
debug_print(mod_aes_cbc, "outblock: %s",
v128_hex_string(&state));
@@ -332,7 +344,7 @@ char
aes_cbc_description[] = "aes cipher block chaining (cbc) mode";
/*
- * Test case 0 is derived from FIPS 197 Appendix A; it uses an
+ * Test case 0 is derived from FIPS 197 Appendix C; it uses an
* all-zero IV, so that the first block encryption matches the test
* case in that appendix. This property provides a check of the base
* AES encryption and decryption algorithms; if CBC fails on some
@@ -374,6 +386,9 @@ cipher_test_case_t aes_cbc_test_case_0 = {
aes_cbc_test_case_0_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_cbc_test_case_0_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
NULL /* pointer to next testcase */
};
@@ -425,20 +440,126 @@ cipher_test_case_t aes_cbc_test_case_1 = {
aes_cbc_test_case_1_plaintext, /* plaintext */
80, /* octets in ciphertext */
aes_cbc_test_case_1_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
&aes_cbc_test_case_0 /* pointer to next testcase */
};
+/*
+ * Test case 2 is like test case 0, but for 256-bit keys. (FIPS 197
+ * appendix C.3).
+ */
+
+
+uint8_t aes_cbc_test_case_2_key[32] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+uint8_t aes_cbc_test_case_2_plaintext[64] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
+};
+
+uint8_t aes_cbc_test_case_2_ciphertext[80] = {
+ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+ 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89,
+ 0x72, 0x72, 0x6e, 0xe7, 0x71, 0x39, 0xbf, 0x11,
+ 0xe5, 0x40, 0xe2, 0x7c, 0x54, 0x65, 0x1d, 0xee
+};
+
+uint8_t aes_cbc_test_case_2_iv[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+cipher_test_case_t aes_cbc_test_case_2 = {
+ 32, /* octets in key */
+ aes_cbc_test_case_2_key, /* key */
+ aes_cbc_test_case_2_iv, /* initialization vector */
+ 16, /* octets in plaintext */
+ aes_cbc_test_case_2_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ aes_cbc_test_case_2_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
+ &aes_cbc_test_case_1 /* pointer to next testcase */
+};
+
+
+/*
+ * this test case is taken directly from Appendix F.2 of NIST Special
+ * Publication SP 800-38A
+ */
+
+uint8_t aes_cbc_test_case_3_key[32] = {
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+ 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+};
+
+uint8_t aes_cbc_test_case_3_plaintext[64] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+
+uint8_t aes_cbc_test_case_3_ciphertext[80] = {
+ 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+ 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+ 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+ 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+ 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+ 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+ 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+ 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b,
+ 0xfb, 0x98, 0x20, 0x2c, 0x45, 0xb2, 0xe4, 0xa0,
+ 0x63, 0xc4, 0x68, 0xba, 0x84, 0x39, 0x16, 0x5a
+};
+
+uint8_t aes_cbc_test_case_3_iv[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+
+cipher_test_case_t aes_cbc_test_case_3 = {
+ 32, /* octets in key */
+ aes_cbc_test_case_3_key, /* key */
+ aes_cbc_test_case_3_iv, /* initialization vector */
+ 64, /* octets in plaintext */
+ aes_cbc_test_case_3_plaintext, /* plaintext */
+ 80, /* octets in ciphertext */
+ aes_cbc_test_case_3_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
+ &aes_cbc_test_case_2 /* pointer to next testcase */
+};
+
cipher_type_t aes_cbc = {
(cipher_alloc_func_t) aes_cbc_alloc,
(cipher_dealloc_func_t) aes_cbc_dealloc,
(cipher_init_func_t) aes_cbc_context_init,
+ (cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_cbc_nist_encrypt,
(cipher_decrypt_func_t) aes_cbc_nist_decrypt,
(cipher_set_iv_func_t) aes_cbc_set_iv,
+ (cipher_get_tag_func_t) 0,
(char *) aes_cbc_description,
(int) 0, /* instance count */
- (cipher_test_case_t *) &aes_cbc_test_case_0,
- (debug_module_t *) &mod_aes_cbc
+ (cipher_test_case_t *) &aes_cbc_test_case_3,
+ (debug_module_t *) &mod_aes_cbc,
+ (cipher_type_id_t) AES_CBC
};
diff --git a/third_party/srtp/crypto/cipher/aes_gcm_ossl.c b/third_party/srtp/crypto/cipher/aes_gcm_ossl.c
new file mode 100644
index 00000000..dce2a337
--- /dev/null
+++ b/third_party/srtp/crypto/cipher/aes_gcm_ossl.c
@@ -0,0 +1,570 @@
+/*
+ * aes_gcm_ossl.c
+ *
+ * AES Galois Counter Mode
+ *
+ * John A. Foley
+ * Cisco Systems, Inc.
+ *
+ */
+
+/*
+ *
+ * Copyright (c) 2013, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#include <openssl/evp.h>
+#include "aes_icm_ossl.h"
+#include "aes_gcm_ossl.h"
+#include "alloc.h"
+#include "crypto_types.h"
+
+
+debug_module_t mod_aes_gcm = {
+ 0, /* debugging is off by default */
+ "aes gcm" /* printable module name */
+};
+
+/*
+ * The following are the global singleton instances for the
+ * 128-bit and 256-bit GCM ciphers.
+ */
+extern cipher_type_t aes_gcm_128_openssl;
+extern cipher_type_t aes_gcm_256_openssl;
+
+/*
+ * For now we only support 8 and 16 octet tags. The spec allows for
+ * optional 12 byte tag, which may be supported in the future.
+ */
+#define GCM_AUTH_TAG_LEN 16
+#define GCM_AUTH_TAG_LEN_8 8
+
+
+/*
+ * 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 deallocates a GCM session
+ */
+err_status_t aes_gcm_openssl_dealloc (cipher_t *c)
+{
+ aes_gcm_ctx_t *ctx;
+
+ ctx = (aes_gcm_ctx_t*)c->state;
+ if (ctx) {
+ EVP_CIPHER_CTX_cleanup(&ctx->ctx);
+ /* decrement ref_count for the appropriate engine */
+ switch (ctx->key_size) {
+ case AES_256_KEYSIZE:
+ aes_gcm_256_openssl.ref_count--;
+ break;
+ case AES_128_KEYSIZE:
+ aes_gcm_128_openssl.ref_count--;
+ break;
+ default:
+ return (err_status_dealloc_fail);
+ break;
+ }
+ }
+
+ /* zeroize entire state*/
+ octet_string_set_to_zero((uint8_t*)c, sizeof(cipher_t) + sizeof(aes_gcm_ctx_t));
+
+ /* free memory */
+ crypto_free(c);
+
+ 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);
+}
+
+
+/*
+ * 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;
+
+ 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(iv));
+
+ 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 processes the AAD
+ *
+ * Parameters:
+ * c Crypto context
+ * aad Additional data to process for AEAD cipher suites
+ * aad_len length of aad buffer
+ */
+err_status_t aes_gcm_openssl_set_aad (aes_gcm_ctx_t *c, unsigned char *aad,
+ unsigned int aad_len)
+{
+ int rv;
+
+ /*
+ * Set dummy tag, OpenSSL requires the Tag to be set before
+ * processing AAD
+ */
+ EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len, aad);
+
+ rv = EVP_Cipher(&c->ctx, NULL, aad, aad_len);
+ if (rv != aad_len) {
+ return (err_status_algo_fail);
+ } else {
+ return (err_status_ok);
+ }
+}
+
+/*
+ * This function encrypts a buffer using AES GCM mode
+ *
+ * Parameters:
+ * c Crypto context
+ * buf data to encrypt
+ * enc_len length of encrypt buffer
+ */
+err_status_t aes_gcm_openssl_encrypt (aes_gcm_ctx_t *c, unsigned char *buf,
+ unsigned int *enc_len)
+{
+ if (c->dir != direction_encrypt && c->dir != direction_decrypt) {
+ return (err_status_bad_param);
+ }
+
+ /*
+ * Encrypt the data
+ */
+ EVP_Cipher(&c->ctx, buf, buf, *enc_len);
+
+ return (err_status_ok);
+}
+
+/*
+ * This function calculates and returns the GCM tag for a given context.
+ * This should be called after encrypting the data. The *len value
+ * is increased by the tag size. The caller must ensure that *buf has
+ * enough room to accept the appended tag.
+ *
+ * Parameters:
+ * c Crypto context
+ * buf data to encrypt
+ * len length of encrypt buffer
+ */
+err_status_t aes_gcm_openssl_get_tag (aes_gcm_ctx_t *c, unsigned char *buf,
+ int *len)
+{
+ /*
+ * Calculate the tag
+ */
+ EVP_Cipher(&c->ctx, NULL, NULL, 0);
+
+ /*
+ * Retreive the tag
+ */
+ EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_GET_TAG, c->tag_len, buf);
+
+ /*
+ * Increase encryption length by desired tag size
+ */
+ *len = c->tag_len;
+
+ return (err_status_ok);
+}
+
+
+/*
+ * This function decrypts a buffer using AES GCM mode
+ *
+ * Parameters:
+ * c Crypto context
+ * buf data to encrypt
+ * enc_len length of encrypt buffer
+ */
+err_status_t aes_gcm_openssl_decrypt (aes_gcm_ctx_t *c, unsigned char *buf,
+ unsigned int *enc_len)
+{
+ if (c->dir != direction_encrypt && c->dir != direction_decrypt) {
+ return (err_status_bad_param);
+ }
+
+ /*
+ * Set the tag before decrypting
+ */
+ EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len,
+ buf + (*enc_len - c->tag_len));
+ EVP_Cipher(&c->ctx, buf, buf, *enc_len - c->tag_len);
+
+ /*
+ * Check the tag
+ */
+ if (EVP_Cipher(&c->ctx, NULL, NULL, 0)) {
+ return (err_status_auth_fail);
+ }
+
+ /*
+ * Reduce the buffer size by the tag length since the tag
+ * is not part of the original payload
+ */
+ *enc_len -= c->tag_len;
+
+ return (err_status_ok);
+}
+
+
+
+/*
+ * Name of this crypto engine
+ */
+char aes_gcm_128_openssl_description[] = "AES-128 GCM using openssl";
+char aes_gcm_256_openssl_description[] = "AES-256 GCM using openssl";
+
+
+/*
+ * KAT values for AES self-test. These
+ * values we're derived from independent test code
+ * using OpenSSL.
+ */
+uint8_t aes_gcm_test_case_0_key[AES_128_GCM_KEYSIZE_WSALT] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c,
+};
+
+uint8_t aes_gcm_test_case_0_iv[12] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+};
+
+uint8_t aes_gcm_test_case_0_plaintext[60] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+};
+
+uint8_t aes_gcm_test_case_0_aad[20] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2
+};
+
+uint8_t aes_gcm_test_case_0_ciphertext[76] = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91,
+ /* the last 16 bytes are the tag */
+ 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47,
+};
+
+cipher_test_case_t aes_gcm_test_case_0a = {
+ AES_128_GCM_KEYSIZE_WSALT, /* octets in key */
+ aes_gcm_test_case_0_key, /* key */
+ aes_gcm_test_case_0_iv, /* packet index */
+ 60, /* octets in plaintext */
+ aes_gcm_test_case_0_plaintext, /* plaintext */
+ 68, /* octets in ciphertext */
+ aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ aes_gcm_test_case_0_aad, /* AAD */
+ GCM_AUTH_TAG_LEN_8,
+ NULL /* pointer to next testcase */
+};
+
+cipher_test_case_t aes_gcm_test_case_0 = {
+ AES_128_GCM_KEYSIZE_WSALT, /* octets in key */
+ aes_gcm_test_case_0_key, /* key */
+ aes_gcm_test_case_0_iv, /* packet index */
+ 60, /* octets in plaintext */
+ aes_gcm_test_case_0_plaintext, /* plaintext */
+ 76, /* octets in ciphertext */
+ aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ aes_gcm_test_case_0_aad, /* AAD */
+ GCM_AUTH_TAG_LEN,
+ &aes_gcm_test_case_0a /* pointer to next testcase */
+};
+
+uint8_t aes_gcm_test_case_1_key[AES_256_GCM_KEYSIZE_WSALT] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c,
+ 0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c,
+
+};
+
+uint8_t aes_gcm_test_case_1_iv[12] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+};
+
+uint8_t aes_gcm_test_case_1_plaintext[60] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+};
+
+uint8_t aes_gcm_test_case_1_aad[20] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2
+};
+
+uint8_t aes_gcm_test_case_1_ciphertext[76] = {
+ 0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46,
+ 0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a,
+ 0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86,
+ 0x1b, 0xc7, 0x93, 0xed, 0x75, 0x7f, 0x23, 0x5a,
+ 0xda, 0xfd, 0xd3, 0xe2, 0x0e, 0x80, 0x87, 0xa9,
+ 0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80,
+ 0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10,
+ 0x09, 0xc9, 0x86, 0xc1,
+ /* the last 16 bytes are the tag */
+ 0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f,
+ 0x81, 0xcb, 0x8e, 0x5b, 0x46, 0x65, 0x63, 0x1d,
+};
+
+cipher_test_case_t aes_gcm_test_case_1a = {
+ AES_256_GCM_KEYSIZE_WSALT, /* octets in key */
+ aes_gcm_test_case_1_key, /* key */
+ aes_gcm_test_case_1_iv, /* packet index */
+ 60, /* octets in plaintext */
+ aes_gcm_test_case_1_plaintext, /* plaintext */
+ 68, /* octets in ciphertext */
+ aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ aes_gcm_test_case_1_aad, /* AAD */
+ GCM_AUTH_TAG_LEN_8,
+ NULL /* pointer to next testcase */
+};
+
+cipher_test_case_t aes_gcm_test_case_1 = {
+ AES_256_GCM_KEYSIZE_WSALT, /* octets in key */
+ aes_gcm_test_case_1_key, /* key */
+ aes_gcm_test_case_1_iv, /* packet index */
+ 60, /* octets in plaintext */
+ aes_gcm_test_case_1_plaintext, /* plaintext */
+ 76, /* octets in ciphertext */
+ aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */
+ 20, /* octets in AAD */
+ aes_gcm_test_case_1_aad, /* AAD */
+ GCM_AUTH_TAG_LEN,
+ &aes_gcm_test_case_1a /* pointer to next testcase */
+};
+
+/*
+ * This is the vector function table for this crypto engine.
+ */
+cipher_type_t aes_gcm_128_openssl = {
+ (cipher_alloc_func_t) aes_gcm_openssl_alloc,
+ (cipher_dealloc_func_t) aes_gcm_openssl_dealloc,
+ (cipher_init_func_t) aes_gcm_openssl_context_init,
+ (cipher_set_aad_func_t) aes_gcm_openssl_set_aad,
+ (cipher_encrypt_func_t) aes_gcm_openssl_encrypt,
+ (cipher_decrypt_func_t) aes_gcm_openssl_decrypt,
+ (cipher_set_iv_func_t) aes_gcm_openssl_set_iv,
+ (cipher_get_tag_func_t) aes_gcm_openssl_get_tag,
+ (char*) aes_gcm_128_openssl_description,
+ (int) 0, /* instance count */
+ (cipher_test_case_t*) &aes_gcm_test_case_0,
+ (debug_module_t*) &mod_aes_gcm,
+ (cipher_type_id_t) AES_128_GCM
+};
+
+/*
+ * This is the vector function table for this crypto engine.
+ */
+cipher_type_t aes_gcm_256_openssl = {
+ (cipher_alloc_func_t) aes_gcm_openssl_alloc,
+ (cipher_dealloc_func_t) aes_gcm_openssl_dealloc,
+ (cipher_init_func_t) aes_gcm_openssl_context_init,
+ (cipher_set_aad_func_t) aes_gcm_openssl_set_aad,
+ (cipher_encrypt_func_t) aes_gcm_openssl_encrypt,
+ (cipher_decrypt_func_t) aes_gcm_openssl_decrypt,
+ (cipher_set_iv_func_t) aes_gcm_openssl_set_iv,
+ (cipher_get_tag_func_t) aes_gcm_openssl_get_tag,
+ (char*) aes_gcm_256_openssl_description,
+ (int) 0, /* instance count */
+ (cipher_test_case_t*) &aes_gcm_test_case_1,
+ (debug_module_t*) &mod_aes_gcm,
+ (cipher_type_id_t) AES_256_GCM
+};
+
diff --git a/third_party/srtp/crypto/cipher/aes_icm.c b/third_party/srtp/crypto/cipher/aes_icm.c
index e7e8c599..3d97e2ba 100644
--- a/third_party/srtp/crypto/cipher/aes_icm.c
+++ b/third_party/srtp/crypto/cipher/aes_icm.c
@@ -9,7 +9,7 @@
/*
*
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,9 @@
*
*/
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
#define ALIGN_32 0
@@ -101,12 +104,13 @@ aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) {
/*
* 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
+ * The check for key_len = 30/38/46 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.
*/
- if (!forIsmacryp && key_len != 30)
+ if (!(forIsmacryp && key_len > 16 && key_len < 30) &&
+ key_len != 30 && key_len != 38 && key_len != 46)
return err_status_bad_param;
/* allocate memory a cipher of type aes_icm */
@@ -117,6 +121,17 @@ aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) {
/* set pointers */
*c = (cipher_t *)pointer;
+ switch (key_len) {
+ case 46:
+ (*c)->algorithm = AES_256_ICM;
+ break;
+ case 38:
+ (*c)->algorithm = AES_192_ICM;
+ break;
+ default:
+ (*c)->algorithm = AES_128_ICM;
+ break;
+ }
(*c)->type = &aes_icm;
(*c)->state = pointer + sizeof(cipher_t);
@@ -162,30 +177,44 @@ aes_icm_dealloc(cipher_t *c) {
*/
err_status_t
-aes_icm_context_init(aes_icm_ctx_t *c, const uint8_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.v8[14] = c->offset.v8[15] = 0;
- c->counter.v8[14] = c->counter.v8[15] = 0;
-
- /* set tmp_key (for alignment) */
- v128_copy_octet_string(&tmp_key, key);
+aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key, int key_len) {
+ err_status_t status;
+ int base_key_len, copy_len;
+
+ if (key_len > 16 && key_len < 30) /* Ismacryp */
+ base_key_len = 16;
+ else if (key_len == 30 || key_len == 38 || key_len == 46)
+ base_key_len = key_len - 14;
+ else
+ return 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 = key_len - 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(mod_aes_icm,
- "key: %s", v128_hex_string(&tmp_key));
+ "key: %s", octet_string_hex_string(key, base_key_len));
debug_print(mod_aes_icm,
"offset: %s", v128_hex_string(&c->offset));
/* expand key */
- aes_expand_encryption_key(&tmp_key, c->expanded_key);
+ status = 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;
@@ -210,7 +239,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
((high32(octet_num) & 0x0f)<<(32-4)) |
(low32(octet_num) >> 4));
#else
- int tail_num = octet_num % 16;
+ int tail_num = (int)(octet_num % 16);
uint64_t block_num = octet_num / 16;
#endif
@@ -231,7 +260,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
/* fill keystream buffer, if needed */
if (tail_num) {
v128_copy(&c->keystream_buffer, &c->counter);
- aes_encrypt(&c->keystream_buffer, c->expanded_key);
+ aes_encrypt(&c->keystream_buffer, &c->expanded_key);
c->bytes_in_buffer = sizeof(v128_t);
debug_print(mod_aes_icm, "counter: %s",
@@ -257,13 +286,16 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
*/
err_status_t
-aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
- v128_t *nonce = (v128_t *) iv;
+aes_icm_set_iv(aes_icm_ctx_t *c, void *iv, int direction) {
+ 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));
+ "setting iv: %s", v128_hex_string(&nonce));
- v128_xor(&c->counter, &c->offset, nonce);
+ v128_xor(&c->counter, &c->offset, &nonce);
debug_print(mod_aes_icm,
"set_counter: %s", v128_hex_string(&c->counter));
@@ -287,7 +319,7 @@ static inline void
aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
/* fill buffer with new keystream */
v128_copy(&c->keystream_buffer, &c->counter);
- aes_encrypt(&c->keystream_buffer, c->expanded_key);
+ aes_encrypt(&c->keystream_buffer, &c->expanded_key);
c->bytes_in_buffer = sizeof(v128_t);
debug_print(mod_aes_icm, "counter: %s",
@@ -301,18 +333,14 @@ aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
uint32_t temp;
//alex's clock counter forward
temp = ntohl(c->counter.v32[3]);
- c->counter.v32[3] = htonl(++temp);
+ ++temp;
+ c->counter.v32[3] = htonl(temp);
} else {
if (!++(c->counter.v8[15]))
++(c->counter.v8[14]);
}
}
-inline void aes_icm_advance(aes_icm_ctx_t *c) {
- aes_icm_advance_ismacryp(c, 0);
-}
-
-
/*e
* icm_encrypt deals with the following cases:
*
@@ -440,7 +468,7 @@ aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
}
err_status_t
-aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
+aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, unsigned int num_octets_to_output) {
unsigned int len = num_octets_to_output;
/* zeroize the buffer */
@@ -450,6 +478,10 @@ aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
return aes_icm_encrypt(c, buffer, &len);
}
+uint16_t
+aes_icm_bytes_encrypted(aes_icm_ctx_t *c) {
+ return htons(c->counter.v16[7]);
+}
char
aes_icm_description[] = "aes integer counter mode";
@@ -488,9 +520,55 @@ cipher_test_case_t aes_icm_test_case_0 = {
aes_icm_test_case_0_plaintext, /* plaintext */
32, /* octets in ciphertext */
aes_icm_test_case_0_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
NULL /* pointer to next testcase */
};
+uint8_t aes_icm_test_case_1_key[46] = {
+ 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
+ 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
+ 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
+ 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+
+uint8_t aes_icm_test_case_1_nonce[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+uint8_t aes_icm_test_case_1_plaintext[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t aes_icm_test_case_1_ciphertext[32] = {
+ 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
+ 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
+ 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
+ 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
+};
+
+cipher_test_case_t aes_icm_test_case_1 = {
+ 46, /* octets in key */
+ aes_icm_test_case_1_key, /* key */
+ aes_icm_test_case_1_nonce, /* packet index */
+ 32, /* octets in plaintext */
+ aes_icm_test_case_1_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ aes_icm_test_case_1_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
+ &aes_icm_test_case_0 /* pointer to next testcase */
+};
+
+
/*
* note: the encrypt function is identical to the decrypt function
@@ -500,12 +578,15 @@ cipher_type_t aes_icm = {
(cipher_alloc_func_t) aes_icm_alloc,
(cipher_dealloc_func_t) aes_icm_dealloc,
(cipher_init_func_t) aes_icm_context_init,
+ (cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) aes_icm_encrypt,
(cipher_decrypt_func_t) aes_icm_encrypt,
(cipher_set_iv_func_t) aes_icm_set_iv,
+ (cipher_get_tag_func_t) 0,
(char *) aes_icm_description,
(int) 0, /* instance count */
- (cipher_test_case_t *) &aes_icm_test_case_0,
- (debug_module_t *) &mod_aes_icm
+ (cipher_test_case_t *) &aes_icm_test_case_1,
+ (debug_module_t *) &mod_aes_icm,
+ (cipher_type_id_t) AES_ICM
};
diff --git a/third_party/srtp/crypto/cipher/aes_icm_ossl.c b/third_party/srtp/crypto/cipher/aes_icm_ossl.c
new file mode 100644
index 00000000..eb585391
--- /dev/null
+++ b/third_party/srtp/crypto/cipher/aes_icm_ossl.c
@@ -0,0 +1,563 @@
+/*
+ * aes_icm_ossl.c
+ *
+ * AES Integer Counter Mode
+ *
+ * John A. Foley
+ * Cisco Systems, Inc.
+ *
+ * 2/24/2012: This module was modified to use CiscoSSL for AES counter
+ * mode. Eddy Lem contributed the code to allow this.
+ *
+ * 12/20/2012: Added support for AES-192 and AES-256.
+ */
+
+/*
+ *
+ * Copyright (c) 2013, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#include <openssl/evp.h>
+#include "aes_icm_ossl.h"
+#include "crypto_types.h"
+#include "alloc.h"
+#include "crypto_types.h"
+
+
+debug_module_t mod_aes_icm = {
+ 0, /* debugging is off by default */
+ "aes icm ossl" /* printable module name */
+};
+extern cipher_test_case_t aes_icm_test_case_0;
+extern cipher_type_t aes_icm;
+#ifndef SRTP_NO_AES192
+extern cipher_type_t aes_icm_192;
+#endif
+extern cipher_type_t aes_icm_256;
+
+/*
+ * integer counter mode works as follows:
+ *
+ * 16 bits
+ * <----->
+ * +------+------+------+------+------+------+------+------+
+ * | nonce | packet index | ctr |---+
+ * +------+------+------+------+------+------+------+------+ |
+ * |
+ * +------+------+------+------+------+------+------+------+ v
+ * | salt |000000|->(+)
+ * +------+------+------+------+------+------+------+------+ |
+ * |
+ * +---------+
+ * | encrypt |
+ * +---------+
+ * |
+ * +------+------+------+------+------+------+------+------+ |
+ * | keystream block |<--+
+ * +------+------+------+------+------+------+------+------+
+ *
+ * All fields are big-endian
+ *
+ * ctr is the block counter, which increments from zero for
+ * each packet (16 bits wide)
+ *
+ * packet index is distinct for each packet (48 bits wide)
+ *
+ * nonce can be distinct across many uses of the same key, or
+ * can be a fixed value per key, or can be per-packet randomness
+ * (64 bits)
+ *
+ */
+
+/*
+ * 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. The tlen argument is for the AEAD tag length, which
+ * isn't used in counter mode.
+ */
+err_status_t aes_icm_openssl_alloc (cipher_t **c, int key_len, int tlen)
+{
+ 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 &&
+#ifndef SRTP_NO_AES192
+ key_len != AES_192_KEYSIZE_WSALT &&
+#endif
+ 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;
+#ifndef SRTP_NO_AES192
+ 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;
+#endif
+ 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;
+}
+
+
+/*
+ * This function deallocates an instance of this engine
+ */
+err_status_t aes_icm_openssl_dealloc (cipher_t *c)
+{
+ aes_icm_ctx_t *ctx;
+
+ if (c == NULL) {
+ return err_status_bad_param;
+ }
+
+ /*
+ * Free the EVP context
+ */
+ ctx = (aes_icm_ctx_t*)c->state;
+ if (ctx != NULL) {
+ EVP_CIPHER_CTX_cleanup(&ctx->ctx);
+ /* decrement ref_count for the appropriate engine */
+ switch (ctx->key_size) {
+ case AES_256_KEYSIZE:
+ aes_icm_256.ref_count--;
+ break;
+#ifndef SRTP_NO_AES192
+ case AES_192_KEYSIZE:
+ aes_icm_192.ref_count--;
+ break;
+#endif
+ case AES_128_KEYSIZE:
+ aes_icm.ref_count--;
+ break;
+ default:
+ return err_status_dealloc_fail;
+ break;
+ }
+ }
+
+ /* zeroize entire state*/
+ octet_string_set_to_zero((uint8_t*)c,
+ sizeof(cipher_t) + sizeof(aes_icm_ctx_t));
+
+ /* free memory */
+ crypto_free(c);
+
+ 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, 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 SRTP_NO_AES192
+ || 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_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 SRTP_NO_AES192
+ 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;
+ }
+}
+
+/*
+ * 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, &len)) {
+ return err_status_cipher_fail;
+ }
+ *enc_len += len;
+
+ return err_status_ok;
+}
+
+uint16_t aes_icm_bytes_encrypted(aes_icm_ctx_t *c)
+{
+ return htons(c->counter.v16[7]);
+}
+
+/*
+ * Name of this crypto engine
+ */
+char aes_icm_openssl_description[] = "AES-128 counter mode using openssl";
+#ifndef SRTP_NO_AES192
+char aes_icm_192_openssl_description[] = "AES-192 counter mode using openssl";
+#endif
+char aes_icm_256_openssl_description[] = "AES-256 counter mode using openssl";
+
+
+/*
+ * KAT values for AES self-test. These
+ * values came from the legacy libsrtp code.
+ */
+uint8_t aes_icm_test_case_0_key[AES_128_KEYSIZE_WSALT] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+
+uint8_t aes_icm_test_case_0_nonce[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+uint8_t aes_icm_test_case_0_plaintext[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t aes_icm_test_case_0_ciphertext[32] = {
+ 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
+ 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
+ 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
+ 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
+};
+
+cipher_test_case_t aes_icm_test_case_0 = {
+ AES_128_KEYSIZE_WSALT, /* octets in key */
+ aes_icm_test_case_0_key, /* key */
+ aes_icm_test_case_0_nonce, /* packet index */
+ 32, /* octets in plaintext */
+ aes_icm_test_case_0_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ aes_icm_test_case_0_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
+ NULL /* pointer to next testcase */
+};
+
+#ifndef SRTP_NO_AES192
+/*
+ * KAT values for AES-192-CTR self-test. These
+ * values came from section 7 of RFC 6188.
+ */
+uint8_t aes_icm_192_test_case_1_key[AES_192_KEYSIZE_WSALT] = {
+ 0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d,
+ 0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21,
+ 0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+
+uint8_t aes_icm_192_test_case_1_nonce[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+uint8_t aes_icm_192_test_case_1_plaintext[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t aes_icm_192_test_case_1_ciphertext[32] = {
+ 0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d,
+ 0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c,
+ 0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61,
+ 0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a
+};
+
+cipher_test_case_t aes_icm_192_test_case_1 = {
+ AES_192_KEYSIZE_WSALT, /* octets in key */
+ aes_icm_192_test_case_1_key, /* key */
+ aes_icm_192_test_case_1_nonce, /* packet index */
+ 32, /* octets in plaintext */
+ aes_icm_192_test_case_1_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ aes_icm_192_test_case_1_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
+ NULL /* pointer to next testcase */
+};
+#endif
+
+/*
+ * KAT values for AES-256-CTR self-test. These
+ * values came from section 7 of RFC 6188.
+ */
+uint8_t aes_icm_256_test_case_2_key[AES_256_KEYSIZE_WSALT] = {
+ 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
+ 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
+ 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
+ 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
+};
+
+uint8_t aes_icm_256_test_case_2_nonce[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+uint8_t aes_icm_256_test_case_2_plaintext[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t aes_icm_256_test_case_2_ciphertext[32] = {
+ 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
+ 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
+ 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
+ 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
+};
+
+cipher_test_case_t aes_icm_256_test_case_2 = {
+ AES_256_KEYSIZE_WSALT, /* octets in key */
+ aes_icm_256_test_case_2_key, /* key */
+ aes_icm_256_test_case_2_nonce, /* packet index */
+ 32, /* octets in plaintext */
+ aes_icm_256_test_case_2_plaintext, /* plaintext */
+ 32, /* octets in ciphertext */
+ aes_icm_256_test_case_2_ciphertext, /* ciphertext */
+ 0,
+ NULL,
+ 0,
+ NULL /* pointer to next testcase */
+};
+
+/*
+ * This is the function table for this crypto engine.
+ * note: the encrypt function is identical to the decrypt function
+ */
+cipher_type_t aes_icm = {
+ (cipher_alloc_func_t) aes_icm_openssl_alloc,
+ (cipher_dealloc_func_t) aes_icm_openssl_dealloc,
+ (cipher_init_func_t) aes_icm_openssl_context_init,
+ (cipher_set_aad_func_t) 0,
+ (cipher_encrypt_func_t) aes_icm_openssl_encrypt,
+ (cipher_decrypt_func_t) aes_icm_openssl_encrypt,
+ (cipher_set_iv_func_t) aes_icm_openssl_set_iv,
+ (cipher_get_tag_func_t) 0,
+ (char*) aes_icm_openssl_description,
+ (int) 0, /* instance count */
+ (cipher_test_case_t*) &aes_icm_test_case_0,
+ (debug_module_t*) &mod_aes_icm,
+ (cipher_type_id_t) AES_ICM
+};
+
+#ifndef SRTP_NO_AES192
+/*
+ * This is the function table for this crypto engine.
+ * note: the encrypt function is identical to the decrypt function
+ */
+cipher_type_t aes_icm_192 = {
+ (cipher_alloc_func_t) aes_icm_openssl_alloc,
+ (cipher_dealloc_func_t) aes_icm_openssl_dealloc,
+ (cipher_init_func_t) aes_icm_openssl_context_init,
+ (cipher_set_aad_func_t) 0,
+ (cipher_encrypt_func_t) aes_icm_openssl_encrypt,
+ (cipher_decrypt_func_t) aes_icm_openssl_encrypt,
+ (cipher_set_iv_func_t) aes_icm_openssl_set_iv,
+ (cipher_get_tag_func_t) 0,
+ (char*) aes_icm_192_openssl_description,
+ (int) 0, /* instance count */
+ (cipher_test_case_t*) &aes_icm_192_test_case_1,
+ (debug_module_t*) &mod_aes_icm,
+ (cipher_type_id_t) AES_192_ICM
+};
+#endif
+
+/*
+ * This is the function table for this crypto engine.
+ * note: the encrypt function is identical to the decrypt function
+ */
+cipher_type_t aes_icm_256 = {
+ (cipher_alloc_func_t) aes_icm_openssl_alloc,
+ (cipher_dealloc_func_t) aes_icm_openssl_dealloc,
+ (cipher_init_func_t) aes_icm_openssl_context_init,
+ (cipher_set_aad_func_t) 0,
+ (cipher_encrypt_func_t) aes_icm_openssl_encrypt,
+ (cipher_decrypt_func_t) aes_icm_openssl_encrypt,
+ (cipher_set_iv_func_t) aes_icm_openssl_set_iv,
+ (cipher_get_tag_func_t) 0,
+ (char*) aes_icm_256_openssl_description,
+ (int) 0, /* instance count */
+ (cipher_test_case_t*) &aes_icm_256_test_case_2,
+ (debug_module_t*) &mod_aes_icm,
+ (cipher_type_id_t) AES_256_ICM
+};
+
diff --git a/third_party/srtp/crypto/cipher/cipher.c b/third_party/srtp/crypto/cipher/cipher.c
index 489a52d9..15b9088f 100644
--- a/third_party/srtp/crypto/cipher/cipher.c
+++ b/third_party/srtp/crypto/cipher/cipher.c
@@ -10,7 +10,7 @@
/*
*
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,12 @@
*
*/
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
#include "cipher.h"
+#include "crypto_types.h"
#include "rand_source.h" /* used in invertibiltiy tests */
#include "alloc.h" /* for crypto_alloc(), crypto_free() */
@@ -71,8 +76,8 @@ cipher_get_key_length(const cipher_t *c) {
}
/*
- * cipher_type_self_test(ct) tests a cipher of type ct against test cases
- * provided in an array of values of key, salt, xtd_seq_num_t,
+ * cipher_type_test(ct, test_data) tests a cipher of type ct against
+ * test cases provided in a list test_data of values of key, salt, iv,
* plaintext, and ciphertext that is known to be good
*/
@@ -81,12 +86,13 @@ cipher_get_key_length(const cipher_t *c) {
#define MAX_KEY_LEN 64
err_status_t
-cipher_type_self_test(const cipher_type_t *ct) {
- const cipher_test_case_t *test_case = ct->test_data;
+cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) {
+ const cipher_test_case_t *test_case = test_data;
cipher_t *c;
err_status_t status;
uint8_t buffer[SELF_TEST_BUF_OCTETS];
uint8_t buffer2[SELF_TEST_BUF_OCTETS];
+ int tag_len;
unsigned int len;
int i, j, case_num = 0;
@@ -105,9 +111,8 @@ cipher_type_self_test(const cipher_type_t *ct) {
* encryption and decryption functions
*/
while (test_case != NULL) {
-
/* allocate cipher */
- status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
+ status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets);
if (status)
return status;
@@ -117,7 +122,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
debug_print(mod_cipher, "testing encryption", NULL);
/* initialize cipher */
- status = cipher_init(c, test_case->key, direction_encrypt);
+ status = cipher_init(c, test_case->key);
if (status) {
cipher_dealloc(c);
return status;
@@ -136,12 +141,30 @@ cipher_type_self_test(const cipher_type_t *ct) {
test_case->plaintext_length_octets));
/* set the initialization vector */
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_encrypt);
if (status) {
cipher_dealloc(c);
return status;
}
+ if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
+ debug_print(mod_cipher, "IV: %s",
+ octet_string_hex_string(test_case->idx, 12));
+
+ /*
+ * Set the AAD
+ */
+ status = cipher_set_aad(c, test_case->aad,
+ test_case->aad_length_octets);
+ if (status) {
+ cipher_dealloc(c);
+ return status;
+ }
+ debug_print(mod_cipher, "AAD: %s",
+ octet_string_hex_string(test_case->aad,
+ test_case->aad_length_octets));
+ }
+
/* encrypt */
len = test_case->plaintext_length_octets;
status = cipher_encrypt(c, buffer, &len);
@@ -150,6 +173,18 @@ cipher_type_self_test(const cipher_type_t *ct) {
return status;
}
+ if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
+ /*
+ * Get the GCM tag
+ */
+ status = cipher_get_tag(c, buffer + len, &tag_len);
+ if (status) {
+ cipher_dealloc(c);
+ return status;
+ }
+ len += tag_len;
+ }
+
debug_print(mod_cipher, "ciphertext: %s",
octet_string_hex_string(buffer,
test_case->ciphertext_length_octets));
@@ -184,7 +219,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
debug_print(mod_cipher, "testing decryption", NULL);
/* re-initialize cipher for decryption */
- status = cipher_init(c, test_case->key, direction_decrypt);
+ status = cipher_init(c, test_case->key);
if (status) {
cipher_dealloc(c);
return status;
@@ -203,12 +238,27 @@ cipher_type_self_test(const cipher_type_t *ct) {
test_case->plaintext_length_octets));
/* set the initialization vector */
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_decrypt);
if (status) {
cipher_dealloc(c);
return status;
}
+ if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
+ /*
+ * Set the AAD
+ */
+ status = cipher_set_aad(c, test_case->aad,
+ test_case->aad_length_octets);
+ if (status) {
+ cipher_dealloc(c);
+ return status;
+ }
+ debug_print(mod_cipher, "AAD: %s",
+ octet_string_hex_string(test_case->aad,
+ test_case->aad_length_octets));
+ }
+
/* decrypt */
len = test_case->ciphertext_length_octets;
status = cipher_decrypt(c, buffer, &len);
@@ -260,8 +310,8 @@ cipher_type_self_test(const cipher_type_t *ct) {
/* now run some random invertibility tests */
/* allocate cipher, using paramaters from the first test case */
- test_case = ct->test_data;
- status = cipher_type_alloc(ct, &c, test_case->key_length_octets);
+ test_case = test_data;
+ status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets);
if (status)
return status;
@@ -269,7 +319,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
for (j=0; j < NUM_RAND_TESTS; j++) {
unsigned length;
- unsigned plaintext_len;
+ int plaintext_len;
uint8_t key[MAX_KEY_LEN];
uint8_t iv[MAX_KEY_LEN];
@@ -297,19 +347,34 @@ cipher_type_self_test(const cipher_type_t *ct) {
if (status) return status;
/* initialize cipher */
- status = cipher_init(c, key, direction_encrypt);
+ status = cipher_init(c, key);
if (status) {
cipher_dealloc(c);
return status;
}
/* set initialization vector */
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_encrypt);
if (status) {
cipher_dealloc(c);
return status;
}
+ if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
+ /*
+ * Set the AAD
+ */
+ status = cipher_set_aad(c, test_case->aad,
+ test_case->aad_length_octets);
+ if (status) {
+ cipher_dealloc(c);
+ return status;
+ }
+ debug_print(mod_cipher, "AAD: %s",
+ octet_string_hex_string(test_case->aad,
+ test_case->aad_length_octets));
+ }
+
/* encrypt buffer with cipher */
plaintext_len = length;
status = cipher_encrypt(c, buffer, &length);
@@ -317,6 +382,17 @@ cipher_type_self_test(const cipher_type_t *ct) {
cipher_dealloc(c);
return status;
}
+ if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
+ /*
+ * Get the GCM tag
+ */
+ status = cipher_get_tag(c, buffer + length, &tag_len);
+ if (status) {
+ cipher_dealloc(c);
+ return status;
+ }
+ length += tag_len;
+ }
debug_print(mod_cipher, "ciphertext: %s",
octet_string_hex_string(buffer, length));
@@ -324,16 +400,30 @@ cipher_type_self_test(const cipher_type_t *ct) {
* re-initialize cipher for decryption, re-set the iv, then
* decrypt the ciphertext
*/
- status = cipher_init(c, key, direction_decrypt);
+ status = cipher_init(c, key);
if (status) {
cipher_dealloc(c);
return status;
}
- status = cipher_set_iv(c, test_case->idx);
+ status = cipher_set_iv(c, test_case->idx, direction_decrypt);
if (status) {
cipher_dealloc(c);
return status;
}
+ if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) {
+ /*
+ * Set the AAD
+ */
+ status = cipher_set_aad(c, test_case->aad,
+ test_case->aad_length_octets);
+ if (status) {
+ cipher_dealloc(c);
+ return status;
+ }
+ debug_print(mod_cipher, "AAD: %s",
+ octet_string_hex_string(test_case->aad,
+ test_case->aad_length_octets));
+ }
status = cipher_decrypt(c, buffer, &length);
if (status) {
cipher_dealloc(c);
@@ -344,8 +434,9 @@ cipher_type_self_test(const cipher_type_t *ct) {
octet_string_hex_string(buffer, length));
/* compare the resulting plaintext with the original one */
- if (length != plaintext_len)
+ if (length != plaintext_len) {
return err_status_algo_fail;
+ }
status = err_status_ok;
for (i=0; i < plaintext_len; i++)
if (buffer[i] != buffer2[i]) {
@@ -359,13 +450,25 @@ cipher_type_self_test(const cipher_type_t *ct) {
}
}
-
- cipher_dealloc(c);
+
+ status = cipher_dealloc(c);
+ if (status)
+ return status;
return err_status_ok;
}
+/*
+ * cipher_type_self_test(ct) performs cipher_type_test on ct's internal
+ * list of test data.
+ */
+
+err_status_t
+cipher_type_self_test(const cipher_type_t *ct) {
+ return cipher_type_test(ct, ct->test_data);
+}
+
/*
* cipher_bits_per_second(c, l, t) computes (an estimate of) the
* number of bits that a cipher implementation can encrypt in a second
@@ -393,7 +496,7 @@ cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_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_set_iv(c, &nonce, direction_encrypt);
cipher_encrypt(c, enc_buf, &len);
}
timer = clock() - timer;
diff --git a/third_party/srtp/crypto/cipher/null_cipher.c b/third_party/srtp/crypto/cipher/null_cipher.c
index 721f50cf..3cd49fb9 100644
--- a/third_party/srtp/crypto/cipher/null_cipher.c
+++ b/third_party/srtp/crypto/cipher/null_cipher.c
@@ -10,7 +10,7 @@
/*
*
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,6 +44,10 @@
*
*/
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
#include "datatypes.h"
#include "null_cipher.h"
#include "alloc.h"
@@ -53,7 +57,7 @@
extern debug_module_t mod_cipher;
err_status_t
-null_cipher_alloc(cipher_t **c, int key_len) {
+null_cipher_alloc(cipher_t **c, int key_len, int tlen) {
extern cipher_type_t null_cipher;
uint8_t *pointer;
@@ -67,6 +71,7 @@ null_cipher_alloc(cipher_t **c, int key_len) {
/* set pointers */
*c = (cipher_t *)pointer;
+ (*c)->algorithm = NULL_CIPHER;
(*c)->type = &null_cipher;
(*c)->state = pointer + sizeof(cipher_t);
@@ -99,7 +104,7 @@ null_cipher_dealloc(cipher_t *c) {
}
err_status_t
-null_cipher_init(null_cipher_ctx_t *ctx, const uint8_t *key) {
+null_cipher_init(null_cipher_ctx_t *ctx, const uint8_t *key, int key_len) {
debug_print(mod_cipher, "initializing null cipher", NULL);
@@ -129,6 +134,9 @@ null_cipher_test_0 = {
NULL, /* plaintext */
0, /* octets in plaintext */
NULL, /* ciphertext */
+ 0,
+ NULL,
+ 0,
NULL /* pointer to next testcase */
};
@@ -141,12 +149,15 @@ cipher_type_t null_cipher = {
(cipher_alloc_func_t) null_cipher_alloc,
(cipher_dealloc_func_t) null_cipher_dealloc,
(cipher_init_func_t) null_cipher_init,
+ (cipher_set_aad_func_t) 0,
(cipher_encrypt_func_t) null_cipher_encrypt,
(cipher_decrypt_func_t) null_cipher_encrypt,
(cipher_set_iv_func_t) null_cipher_set_iv,
+ (cipher_get_tag_func_t) 0,
(char *) null_cipher_description,
(int) 0,
(cipher_test_case_t *) &null_cipher_test_0,
- (debug_module_t *) NULL
+ (debug_module_t *) NULL,
+ (cipher_type_id_t) NULL_CIPHER
};