diff options
Diffstat (limited to 'third_party/srtp/crypto/cipher')
-rw-r--r-- | third_party/srtp/crypto/cipher/aes.c | 393 | ||||
-rw-r--r-- | third_party/srtp/crypto/cipher/aes_cbc.c | 177 | ||||
-rw-r--r-- | third_party/srtp/crypto/cipher/aes_gcm_ossl.c | 570 | ||||
-rw-r--r-- | third_party/srtp/crypto/cipher/aes_icm.c | 155 | ||||
-rw-r--r-- | third_party/srtp/crypto/cipher/aes_icm_ossl.c | 563 | ||||
-rw-r--r-- | third_party/srtp/crypto/cipher/cipher.c | 147 | ||||
-rw-r--r-- | third_party/srtp/crypto/cipher/null_cipher.c | 19 |
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 }; |