* Initial crack at TLS 1.2 client side only (server side is seriously broken).

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@263 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich 2016-07-27 11:05:09 +00:00
parent 287ed7dc14
commit e23d6c390c
10 changed files with 341 additions and 172 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2015, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -200,6 +200,8 @@ void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
/**************************************************************************
* RSA declarations

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -103,3 +103,37 @@ void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
SHA1_Update(&context, digest, SHA1_SIZE);
SHA1_Final(digest, &context);
}
/**
* Perform HMAC-SHA256
* NOTE: does not handle keys larger than the block size.
*/
void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest)
{
SHA256_CTX context;
uint8_t k_ipad[64];
uint8_t k_opad[64];
int i;
memset(k_ipad, 0, sizeof k_ipad);
memset(k_opad, 0, sizeof k_opad);
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
SHA256_Init(&context);
SHA256_Update(&context, k_ipad, 64);
SHA256_Update(&context, msg, length);
SHA256_Final(digest, &context);
SHA256_Init(&context);
SHA256_Update(&context, k_opad, 64);
SHA256_Update(&context, digest, SHA256_SIZE);
SHA256_Final(digest, &context);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -857,12 +857,12 @@ static void display_cipher(SSL *ssl)
printf("AES256-SHA");
break;
case SSL_RC4_128_SHA:
printf("RC4-SHA");
case SSL_AES128_SHA256:
printf("AES128-SHA256");
break;
case SSL_RC4_128_MD5:
printf("RC4-MD5");
case SSL_AES256_SHA256:
printf("AES256-SHA256");
break;
default:

View file

@ -87,21 +87,24 @@ choice
config CONFIG_SSL_PROT_LOW
bool "Low"
help
Chooses the cipher in the order of RC4-SHA, AES128-SHA, AES256-SHA.
Chooses the cipher in the order of AES128-SHA, AES128-SHA256,
AES256-SHA256.
This will use the fastest cipher(s) but at the expense of security.
config CONFIG_SSL_PROT_MEDIUM
bool "Medium"
help
Chooses the cipher in the order of AES128-SHA, AES256-SHA, RC4-SHA.
Chooses the cipher in the order of AES128-SHA256, AES256-SHA256,
AES128-SHA
This mode is a balance between speed and security and is the default.
config CONFIG_SSL_PROT_HIGH
bool "High"
help
Chooses the cipher in the order of AES256-SHA, AES128-SHA, RC4-SHA.
Chooses the cipher in the order of AES256-SHA256, AES128-SHA256,
AES128-SHA.
This will use the strongest cipher(s) at the cost of speed.

View file

@ -96,6 +96,7 @@ extern "C" {
#define SSL_ERROR_INVALID_PROT_MSG -261
#define SSL_ERROR_INVALID_HMAC -262
#define SSL_ERROR_INVALID_VERSION -263
#define SSL_ERROR_UNSUPPORTED_EXTENSION -264
#define SSL_ERROR_INVALID_SESSION -265
#define SSL_ERROR_NO_CIPHER -266
#define SSL_ERROR_BAD_CERTIFICATE -268
@ -127,12 +128,13 @@ extern "C" {
#define SSL_ALERT_DECRYPT_ERROR 51
#define SSL_ALERT_INVALID_VERSION 70
#define SSL_ALERT_NO_RENEGOTIATION 100
#define SSL_ALERT_UNSUPPORTED_EXTENSION 110
/* The ciphers that are supported */
#define SSL_AES128_SHA 0x2f
#define SSL_AES256_SHA 0x35
#define SSL_RC4_128_SHA 0x05
#define SSL_RC4_128_MD5 0x04
#define SSL_AES128_SHA256 0x3c
#define SSL_AES256_SHA256 0x3d
/* build mode ids' */
#define SSL_BUILD_SKELETON_MODE 0x01

View file

@ -176,78 +176,6 @@ end:
return res;
}
/**************************************************************************
* RC4 tests
*
* ARC4 tests vectors from OpenSSL (crypto/rc4/rc4test.c)
**************************************************************************/
static const uint8_t keys[7][30]=
{
{8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
{8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
{8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{4,0xef,0x01,0x23,0x45},
{8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
{4,0xef,0x01,0x23,0x45},
};
static const uint8_t data_len[7]={8,8,8,20,28,10};
static uint8_t data[7][30]=
{
{0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xff},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xff},
{0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
0x12,0x34,0x56,0x78,0xff},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
{0},
};
static const uint8_t output[7][30]=
{
{0x75,0xb7,0x87,0x80,0x99,0xe0,0xc5,0x96,0x00},
{0x74,0x94,0xc2,0xe7,0x10,0x4b,0x08,0x79,0x00},
{0xde,0x18,0x89,0x41,0xa3,0x37,0x5d,0x3a,0x00},
{0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,
0xbd,0x61,0x5a,0x11,0x62,0xe1,0xc7,0xba,
0x36,0xb6,0x78,0x58,0x00},
{0x66,0xa0,0x94,0x9f,0x8a,0xf7,0xd6,0x89,
0x1f,0x7f,0x83,0x2b,0xa8,0x33,0xc0,0x0c,
0x89,0x2e,0xbe,0x30,0x14,0x3c,0xe2,0x87,
0x40,0x01,0x1e,0xcf,0x00},
{0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,0xbd,0x61,0x00},
{0},
};
static int RC4_test(BI_CTX *bi_ctx)
{
int i, res = 1;
RC4_CTX s;
for (i = 0; i < 6; i++)
{
RC4_setup(&s, &keys[i][1], keys[i][0]);
RC4_crypt(&s, data[i], data[i], data_len[i]);
if (memcmp(data[i], output[i], data_len[i]))
{
printf("Error: RC4 CRYPT #%d failed\n", i);
goto end;
}
}
res = 0;
printf("All RC4 tests passed\n");
end:
return res;
}
/**************************************************************************
* SHA1 tests
*
@ -522,9 +450,9 @@ end:
**************************************************************************/
static int HMAC_test(BI_CTX *bi_ctx)
{
uint8_t key[SHA1_SIZE];
uint8_t ct[SHA1_SIZE];
uint8_t dgst[SHA1_SIZE];
uint8_t key[SHA256_SIZE];
uint8_t ct[SHA256_SIZE];
uint8_t dgst[SHA256_SIZE];
int res = 1;
const char *key_str;
@ -553,8 +481,8 @@ static int HMAC_test(BI_CTX *bi_ctx)
data_str = "Hi There";
key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
bi_export(bi_ctx, key_bi, key, SHA1_SIZE);
ct_bi = bi_str_import(bi_ctx, "B617318655057264E28BC0B6FB378C8EF146BE00");
bi_export(bi_ctx, key_bi, key, SHA1_SIZE);
bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
hmac_sha1((const uint8_t *)data_str, 8,
@ -570,13 +498,78 @@ static int HMAC_test(BI_CTX *bi_ctx)
ct_bi = bi_str_import(bi_ctx, "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79");
bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
hmac_sha1((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 5, dgst);
hmac_sha1((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 4, dgst);
if (memcmp(dgst, ct, SHA1_SIZE))
{
printf("HMAC SHA1 failed\n");
exit(1);
printf("HMAC SHA1 #2 failed\n");
goto end;
}
data_str = "Hi There";
key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
ct_bi = bi_str_import(bi_ctx,
"B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32CFF7");
bi_export(bi_ctx, key_bi, key, 20);
bi_export(bi_ctx, ct_bi, ct, SHA256_SIZE);
hmac_sha256((const uint8_t *)data_str, 8,
(const uint8_t *)key, 20, dgst);
if (memcmp(dgst, ct, SHA256_SIZE))
{
printf("HMAC SHA256 #1 failed\n");
goto end;
}
data_str = "what do ya want for nothing?";
key_str = "Jefe";
ct_bi = bi_str_import(bi_ctx,
"5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC3843");
bi_export(bi_ctx, ct_bi, ct, SHA256_SIZE);
hmac_sha256((const uint8_t *)data_str, 28,
(const uint8_t *)key_str, 4, dgst);
if (memcmp(dgst, ct, SHA256_SIZE))
{
printf("HMAC SHA256 #2 failed\n");
goto end;
}
// other test
/*uint8_t secret[16];
key_str = "9BBE436BA940F017B17652849A71DB35";
ct_bi = bi_str_import(bi_ctx, key_str);
bi_export(bi_ctx, ct_bi, secret, 16);
uint8_t random[26];
data_str = "74657374206C6162656CA0BA9F936CDA311827A6F796FFD5198C";
ct_bi = bi_str_import(bi_ctx, data_str);
bi_export(bi_ctx, ct_bi, random, 26);
uint8_t output[256];
p_hash_sha256(secret, 16, random, 26, output, 100);
ct_bi = bi_import(bi_ctx, output, 100);
bi_print("RESULT", ct_bi);
*/
uint8_t secret[48];
uint8_t random[256];
uint8_t output[256];
key_str =
"8C6D256467157DAEC7BAEBC1371E6DABFF1AB686EFA7DCF6B65242AA6EEBFC0A7472A1E583C4F2B23F784F25A6DE05A6";
ct_bi = bi_str_import(bi_ctx, key_str);
bi_export(bi_ctx, ct_bi, secret, 48);
data_str =
"636C69656E742066696E697368656475F80B2E4375CFA44105D16694A5E2D232302FF27241BDF52BA681C13E2CDF9F";
ct_bi = bi_str_import(bi_ctx, data_str);
bi_export(bi_ctx, ct_bi, random, 47);
p_hash_sha256(secret, 48, random, 47, output, 12);
ct_bi = bi_import(bi_ctx, output, 12);
bi_print("RESULT1", ct_bi);
res = 0;
printf("All HMAC tests passed\n");
@ -2306,13 +2299,6 @@ int main(int argc, char *argv[])
}
TTY_FLUSH();
if (RC4_test(bi_ctx))
{
printf("RC4 tests failed\n");
goto cleanup;
}
TTY_FLUSH();
if (MD5_test(bi_ctx))
{
printf("MD5 tests failed\n");

View file

@ -62,13 +62,14 @@ static void session_free(SSL_SESSION *ssl_sessions[], int sess_index);
#endif
const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] =
#ifdef CONFIG_SSL_PROT_LOW /* same as medium for now */
{ SSL_AES128_SHA, SSL_AES256_SHA };
#ifdef CONFIG_SSL_PROT_LOW /* low security, fast speed */
{ SSL_AES128_SHA, SSL_AES128_SHA256, SSL_AES256_SHA, SSL_AES256_SHA256 };
#elif CONFIG_SSL_PROT_MEDIUM /* medium security, medium speed */
{ SSL_AES128_SHA, SSL_AES256_SHA };
{ SSL_AES128_SHA256, SSL_AES256_SHA256, SSL_AES256_SHA, SSL_AES128_SHA };
#else /* CONFIG_SSL_PROT_HIGH */ /* high security, low speed */
{ SSL_AES256_SHA, SSL_AES128_SHA };
{ SSL_AES256_SHA, SSL_AES128_SHA256, SSL_AES_256_SHA, SSL_AES128_SHA };
#endif
/**
* The cipher map containing all the essentials for each cipher.
*/
@ -78,9 +79,9 @@ static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
SSL_AES128_SHA, /* AES128-SHA */
16, /* key size */
16, /* iv size */
2*(SHA1_SIZE+16+16), /* key block size */
16, /* block padding size */
SHA1_SIZE, /* digest size */
2*(SHA1_SIZE+16+16), /* key block size */
hmac_sha1, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
@ -89,16 +90,39 @@ static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
SSL_AES256_SHA, /* AES256-SHA */
32, /* key size */
16, /* iv size */
2*(SHA1_SIZE+32+16), /* key block size */
16, /* block padding size */
SHA1_SIZE, /* digest size */
2*(SHA1_SIZE+32+16), /* key block size */
hmac_sha1, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
},
{ /* AES128-SHA256 */
SSL_AES128_SHA256, /* AES128-SHA256 */
16, /* key size */
16, /* iv size */
16, /* block padding size */
SHA256_SIZE, /* digest size */
2*(SHA256_SIZE+32+16), /* key block size */
hmac_sha256, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
},
{ /* AES256-SHA256 */
SSL_AES256_SHA256, /* AES256-SHA256 */
32, /* key size */
16, /* iv size */
16, /* block padding size */
SHA256_SIZE, /* digest size */
2*(SHA256_SIZE+32+16), /* key block size */
hmac_sha256, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
}
};
static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
static void prf(SSL *ssl, const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len,
uint8_t *out, int olen);
static const cipher_info_t *get_cipher_info(uint8_t cipher);
static void increment_read_sequence(SSL *ssl);
@ -602,7 +626,7 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
const uint8_t *buf, int buf_len, uint8_t *hmac_buf)
{
int hmac_len = buf_len + 8 + SSL_RECORD_SIZE;
uint8_t *t_buf = (uint8_t *)alloca(hmac_len+10);
uint8_t *t_buf = (uint8_t *)alloca(buf_len);
memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ?
ssl->write_sequence : ssl->read_sequence, 8);
@ -636,7 +660,7 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
print_blob("client mac",
ssl->client_mac, ssl->cipher_info->digest_size);
}
print_blob("hmac", hmac_buf, SHA1_SIZE);
print_blob("hmac", hmac_buf, ssl->cipher_info->digest_size);
#endif
}
@ -645,7 +669,7 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
*/
static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
{
uint8_t hmac_buf[SHA1_SIZE];
uint8_t hmac_buf[SHA256_SIZE];
int hmac_offset;
if (ssl->cipher_info->padding_size)
@ -700,8 +724,15 @@ static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
*/
void add_packet(SSL *ssl, const uint8_t *pkt, int len)
{
MD5_Update(&ssl->dc->md5_ctx, pkt, len);
SHA1_Update(&ssl->dc->sha1_ctx, pkt, len);
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2
{
SHA256_Update(&ssl->dc->sha256_ctx, pkt, len);
}
else // TLS1.0/1.0
{
MD5_Update(&ssl->dc->md5_ctx, pkt, len);
SHA1_Update(&ssl->dc->sha1_ctx, pkt, len);
}
}
/**
@ -760,27 +791,63 @@ static void p_hash_sha1(const uint8_t *sec, int sec_len,
}
}
/**
* Work out the SHA256 PRF.
*/
static void p_hash_sha256(const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len, uint8_t *out, int olen)
{
uint8_t a1[128];
/* A(1) */
hmac_sha256(seed, seed_len, sec, sec_len, a1);
memcpy(&a1[SHA256_SIZE], seed, seed_len);
hmac_sha256(a1, SHA256_SIZE+seed_len, sec, sec_len, out);
while (olen > SHA256_SIZE)
{
uint8_t a2[SHA256_SIZE];
out += SHA256_SIZE;
olen -= SHA256_SIZE;
// A(N)
hmac_sha256(a1, SHA256_SIZE, sec, sec_len, a2);
memcpy(a1, a2, SHA256_SIZE);
// work out the actual hash
hmac_sha256(a1, SHA256_SIZE+seed_len, sec, sec_len, out);
}
}
/**
* Work out the PRF.
*/
static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
static void prf(SSL *ssl, const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len,
uint8_t *out, int olen)
{
int len, i;
const uint8_t *S1, *S2;
uint8_t xbuf[256]; /* needs to be > the amount of key data */
uint8_t ybuf[256]; /* needs to be > the amount of key data */
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2
{
p_hash_sha256(sec, sec_len, seed, seed_len, out, olen);
}
else // TLS1.0/1.1
{
int len, i;
const uint8_t *S1, *S2;
uint8_t xbuf[256]; /* needs to be > the amount of key data */
uint8_t ybuf[256]; /* needs to be > the amount of key data */
len = sec_len/2;
S1 = sec;
S2 = &sec[len];
len += (sec_len & 1); /* add for odd, make longer */
len = sec_len/2;
S1 = sec;
S2 = &sec[len];
len += (sec_len & 1); /* add for odd, make longer */
p_hash_md5(S1, len, seed, seed_len, xbuf, olen);
p_hash_sha1(S2, len, seed, seed_len, ybuf, olen);
p_hash_md5(S1, len, seed, seed_len, xbuf, olen);
p_hash_sha1(S2, len, seed, seed_len, ybuf, olen);
for (i = 0; i < olen; i++)
out[i] = xbuf[i] ^ ybuf[i];
for (i = 0; i < olen; i++)
out[i] = xbuf[i] ^ ybuf[i];
}
}
/**
@ -790,24 +857,32 @@ static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret)
{
uint8_t buf[128]; /* needs to be > 13+32+32 in size */
//print_blob("premaster secret", premaster_secret, 48);
strcpy((char *)buf, "master secret");
memcpy(&buf[13], ssl->dc->client_random, SSL_RANDOM_SIZE);
memcpy(&buf[45], ssl->dc->server_random, SSL_RANDOM_SIZE);
prf(premaster_secret, SSL_SECRET_SIZE, buf, 77, ssl->dc->master_secret,
prf(ssl, premaster_secret, SSL_SECRET_SIZE, buf, 77, ssl->dc->master_secret,
SSL_SECRET_SIZE);
#if 0
print_blob("client random", ssl->dc->client_random, 32);
print_blob("server random", ssl->dc->server_random, 32);
print_blob("master secret", ssl->dc->master_secret, 48);
#endif
}
/**
* Generate a 'random' blob of data used for the generation of keys.
*/
static void generate_key_block(uint8_t *client_random, uint8_t *server_random,
static void generate_key_block(SSL *ssl,
uint8_t *client_random, uint8_t *server_random,
uint8_t *master_secret, uint8_t *key_block, int key_block_size)
{
uint8_t buf[128];
strcpy((char *)buf, "key expansion");
memcpy(&buf[13], server_random, SSL_RANDOM_SIZE);
memcpy(&buf[45], client_random, SSL_RANDOM_SIZE);
prf(master_secret, SSL_SECRET_SIZE, buf, 77, key_block, key_block_size);
prf(ssl, master_secret, SSL_SECRET_SIZE, buf, 77,
key_block, key_block_size);
}
/**
@ -818,8 +893,6 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest)
{
uint8_t mac_buf[128];
uint8_t *q = mac_buf;
MD5_CTX md5_ctx = ssl->dc->md5_ctx;
SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx;
if (label)
{
@ -827,25 +900,47 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest)
q += strlen(label);
}
MD5_Final(q, &md5_ctx);
q += MD5_SIZE;
SHA1_Final(q, &sha1_ctx);
q += SHA1_SIZE;
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2
{
SHA256_CTX sha256_ctx = ssl->dc->sha256_ctx; // interim copy
SHA256_Final(q, &sha256_ctx);
q += SHA256_SIZE;
if (label)
{
prf(ssl->dc->master_secret, SSL_SECRET_SIZE, mac_buf, (int)(q-mac_buf),
digest, SSL_FINISHED_HASH_SIZE);
if (label)
{
prf(ssl, ssl->dc->master_secret, SSL_SECRET_SIZE,
mac_buf, (int)(q-mac_buf), digest,
SSL_FINISHED_HASH_SIZE);
}
else // for use in a certificate verify
{
memcpy(digest, mac_buf, SHA256_SIZE);
}
}
else /* for use in a certificate verify */
else // TLS1.0/1.1
{
memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE);
MD5_CTX md5_ctx = ssl->dc->md5_ctx; // interim copy
SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx;
MD5_Final(q, &md5_ctx);
q += MD5_SIZE;
SHA1_Final(q, &sha1_ctx);
q += SHA1_SIZE;
if (label)
{
prf(ssl, ssl->dc->master_secret, SSL_SECRET_SIZE,
mac_buf, (int)(q-mac_buf), digest, SSL_FINISHED_HASH_SIZE);
}
else /* for use in a certificate verify */
{
memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE);
}
}
#if 0
printf("label: %s\n", label);
print_blob("master secret", ssl->dc->master_secret, 48);
print_blob("mac_buf", mac_buf, q-mac_buf);
print_blob("finished digest", digest, SSL_FINISHED_HASH_SIZE);
#endif
@ -859,6 +954,7 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
switch (ssl->cipher)
{
case SSL_AES128_SHA:
case SSL_AES128_SHA256:
{
AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
AES_set_key(aes_ctx, key, iv, AES_MODE_128);
@ -872,6 +968,7 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
}
case SSL_AES256_SHA:
case SSL_AES256_SHA256:
{
AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
AES_set_key(aes_ctx, key, iv, AES_MODE_256);
@ -883,6 +980,7 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
return (void *)aes_ctx;
}
}
return NULL; /* its all gone wrong */
@ -1017,7 +1115,7 @@ int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
increment_write_sequence(ssl);
/* add the explicit IV for TLS1.1 */
if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_1 &&
ssl->cipher_info->iv_size)
{
uint8_t iv_size = ssl->cipher_info->iv_size;
@ -1067,16 +1165,14 @@ static int set_key_block(SSL *ssl, int is_write)
return -1;
/* only do once in a handshake */
if (ssl->dc->key_block == NULL)
if (ssl->dc->bm_proc_index ==0 )
{
ssl->dc->key_block = (uint8_t *)malloc(ciph_info->key_block_size);
#if 0
print_blob("client", ssl->dc->client_random, 32);
print_blob("server", ssl->dc->server_random, 32);
print_blob("master", ssl->dc->master_secret, SSL_SECRET_SIZE);
#endif
generate_key_block(ssl->dc->client_random, ssl->dc->server_random,
generate_key_block(ssl, ssl->dc->client_random, ssl->dc->server_random,
ssl->dc->master_secret, ssl->dc->key_block,
ciph_info->key_block_size);
#if 0
@ -1104,13 +1200,10 @@ static int set_key_block(SSL *ssl, int is_write)
memcpy(server_key, q, ciph_info->key_size);
q += ciph_info->key_size;
if (ciph_info->iv_size) /* RC4 has no IV, AES does */
{
memcpy(client_iv, q, ciph_info->iv_size);
q += ciph_info->iv_size;
memcpy(server_iv, q, ciph_info->iv_size);
q += ciph_info->iv_size;
}
memcpy(client_iv, q, ciph_info->iv_size);
q += ciph_info->iv_size;
memcpy(server_iv, q, ciph_info->iv_size);
q += ciph_info->iv_size;
free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx);
@ -1220,7 +1313,7 @@ int basic_read(SSL *ssl, uint8_t **in_data)
{
ssl->cipher_info->decrypt(ssl->decrypt_ctx, buf, buf, read_len);
if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_1 &&
ssl->cipher_info->iv_size)
{
buf += ssl->cipher_info->iv_size;
@ -1388,7 +1481,7 @@ int send_change_cipher_spec(SSL *ssl)
*/
int send_finished(SSL *ssl)
{
uint8_t buf[SSL_FINISHED_HASH_SIZE+4] = {
uint8_t buf[128] = {
HS_FINISHED, 0, 0, SSL_FINISHED_HASH_SIZE };
/* now add the finished digest mac (12 bytes) */
@ -1577,6 +1670,7 @@ void disposable_new(SSL *ssl)
if (ssl->dc == NULL)
{
ssl->dc = (DISPOSABLE_CTX *)calloc(1, sizeof(DISPOSABLE_CTX));
SHA256_Init(&ssl->dc->sha256_ctx);
MD5_Init(&ssl->dc->md5_ctx);
SHA1_Init(&ssl->dc->sha1_ctx);
}
@ -1589,7 +1683,6 @@ void disposable_free(SSL *ssl)
{
if (ssl->dc)
{
free(ssl->dc->key_block);
memset(ssl->dc, 0, sizeof(DISPOSABLE_CTX));
free(ssl->dc);
ssl->dc = NULL;

View file

@ -48,9 +48,9 @@ extern "C" {
#include "crypto_misc.h"
#define SSL_PROTOCOL_MIN_VERSION 0x31 /* TLS v1.0 */
#define SSL_PROTOCOL_MINOR_VERSION 0x02 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION_MAX 0x32 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION1_1 0x32 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION_MAX 0x33 /* TLS v1.2 */
#define SSL_PROTOCOL_VERSION_TLS1_1 0x32 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION_TLS1_2 0x33 /* TLS v1.2 */
#define SSL_RANDOM_SIZE 32
#define SSL_SECRET_SIZE 48
#define SSL_FINISHED_HASH_SIZE 12
@ -80,7 +80,8 @@ extern "C" {
#define RT_EXTRA 1024
#define BM_RECORD_OFFSET 5
#define NUM_PROTOCOLS 2
#define NUM_PROTOCOLS 4
#define SIG_ALG_EXTENSION 0x0d
#define PARANOIA_CHECK(A, B) if (A < B) { \
ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
@ -114,9 +115,9 @@ typedef struct
uint8_t cipher;
uint8_t key_size;
uint8_t iv_size;
uint8_t key_block_size;
uint8_t padding_size;
uint8_t digest_size;
uint8_t key_block_size;
hmac_func hmac;
crypt_func encrypt;
crypt_func decrypt;
@ -147,11 +148,12 @@ typedef struct
{
MD5_CTX md5_ctx;
SHA1_CTX sha1_ctx;
uint8_t final_finish_mac[SSL_FINISHED_HASH_SIZE];
uint8_t *key_block;
uint8_t master_secret[SSL_SECRET_SIZE];
SHA256_CTX sha256_ctx;
uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
uint8_t final_finish_mac[128];
uint8_t master_secret[SSL_SECRET_SIZE];
uint8_t key_block[256];
uint16_t bm_proc_index;
} DISPOSABLE_CTX;
@ -188,10 +190,10 @@ struct _SSL
#endif
uint8_t session_id[SSL_SESSION_ID_SIZE];
uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t server_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t read_sequence[8]; /* 64 bit sequence number */
uint8_t write_sequence[8]; /* 64 bit sequence number */
uint8_t client_mac[SHA256_SIZE]; /* for HMAC verification */
uint8_t server_mac[SHA256_SIZE]; /* for HMAC verification */
uint8_t read_sequence[8]; /* 64 bit sequence number */
uint8_t write_sequence[8]; /* 64 bit sequence number */
uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */
};

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -37,6 +37,11 @@
#ifdef CONFIG_SSL_ENABLE_CLIENT /* all commented out if no client */
/* support sha512/384/256/224/1 rsa */
static const uint8_t g_sig_alg[] = { 0x00, 0x10,
0x00, SIG_ALG_EXTENSION, 0x00, 0x0c, 0x00, 0x0a,
0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03, 0x01, 0x02, 0x01 };
static int send_client_hello(SSL *ssl);
static int process_server_hello(SSL *ssl);
static int process_server_hello_done(SSL *ssl);
@ -219,6 +224,13 @@ static int send_client_hello(SSL *ssl)
buf[offset++] = 1; /* no compression */
buf[offset++] = 0;
if (ssl->version > SSL_PROTOCOL_VERSION_TLS1_1)
{
memcpy(&buf[offset], g_sig_alg, sizeof(g_sig_alg));
offset += sizeof(g_sig_alg);
}
buf[3] = offset - 4; /* handshake size */
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
@ -279,13 +291,46 @@ static int process_server_hello(SSL *ssl)
ssl->sess_id_size = sess_id_size;
offset += sess_id_size;
/* get the real cipher we are using */
/* get the real cipher we are using - ignore MSB */
ssl->cipher = buf[++offset];
ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ?
HS_FINISHED : HS_CERTIFICATE;
offset++; // skip the compr
PARANOIA_CHECK(pkt_size, offset);
// Check for extensions from the server - only the signature algorithm
// is supported
if (pkt_size > offset)
{
if (buf[offset++] > 0) // MSB of extension len must be 0
{
ret = SSL_ALERT_UNSUPPORTED_EXTENSION;
goto error;
}
offset++; // ignore the extension size as we only look at one
if (buf[offset++] == 0 && buf[offset++] == SIG_ALG_EXTENSION)
{
if (buf[offset++] != 0) // MSB of alg_sig_len must be 0
{
ret = SSL_ALERT_UNSUPPORTED_EXTENSION;
goto error;
}
int alg_sig_len = buf[offset++];
offset += alg_sig_len;
PARANOIA_CHECK(pkt_size, offset);
// we don't use what comes back (for now)
}
else
{
ret = SSL_ALERT_UNSUPPORTED_EXTENSION;
goto error;
}
}
ssl->dc->bm_proc_index = offset+1;
error:
@ -313,8 +358,10 @@ static int send_client_key_xchg(SSL *ssl)
buf[0] = HS_CLIENT_KEY_XCHG;
buf[1] = 0;
premaster_secret[0] = 0x03; /* encode the version number */
premaster_secret[1] = SSL_PROTOCOL_MINOR_VERSION; /* must be TLS 1.1 */
// spec says client must use the what is initially negotiated -
// and this is our current version
premaster_secret[0] = 0x03;
premaster_secret[1] = SSL_PROTOCOL_VERSION_MAX & 0x0f;
if (get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]) < 0)
return SSL_NOT_OK;

View file

@ -279,7 +279,7 @@ static int send_server_hello(SSL *ssl)
buf[offset++] = 0; /* cipher we are using */
buf[offset++] = ssl->cipher;
buf[offset++] = 0; /* no compression */
buf[offset++] = 0; /* no compression and no extensions supported */
buf[3] = offset - 4; /* handshake size */
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
}