tls: rearrange function order, improve comments
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
345
networking/tls.c
345
networking/tls.c
@ -284,6 +284,145 @@ static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buff
|
|||||||
sha256_hash(ctx, buffer, len)
|
sha256_hash(ctx, buffer, len)
|
||||||
#endif /* not TLS_DEBUG >= 2 */
|
#endif /* not TLS_DEBUG >= 2 */
|
||||||
|
|
||||||
|
// RFC 2104
|
||||||
|
// HMAC(key, text) based on a hash H (say, sha256) is:
|
||||||
|
// ipad = [0x36 x INSIZE]
|
||||||
|
// opad = [0x5c x INSIZE]
|
||||||
|
// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text))
|
||||||
|
//
|
||||||
|
// H(key XOR opad) and H(key XOR ipad) can be precomputed
|
||||||
|
// if we often need HMAC hmac with the same key.
|
||||||
|
//
|
||||||
|
// text is often given in disjoint pieces.
|
||||||
|
static void hmac_sha256_precomputed_v(uint8_t out[SHA256_OUTSIZE],
|
||||||
|
sha256_ctx_t *hashed_key_xor_ipad,
|
||||||
|
sha256_ctx_t *hashed_key_xor_opad,
|
||||||
|
va_list va)
|
||||||
|
{
|
||||||
|
uint8_t *text;
|
||||||
|
|
||||||
|
/* hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
|
||||||
|
/* hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
|
||||||
|
|
||||||
|
/* calculate out = H((key XOR ipad) + text) */
|
||||||
|
while ((text = va_arg(va, uint8_t*)) != NULL) {
|
||||||
|
unsigned text_size = va_arg(va, unsigned);
|
||||||
|
sha256_hash(hashed_key_xor_ipad, text, text_size);
|
||||||
|
}
|
||||||
|
sha256_end(hashed_key_xor_ipad, out);
|
||||||
|
|
||||||
|
/* out = H((key XOR opad) + out) */
|
||||||
|
sha256_hash(hashed_key_xor_opad, out, SHA256_OUTSIZE);
|
||||||
|
sha256_end(hashed_key_xor_opad, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...)
|
||||||
|
{
|
||||||
|
sha256_ctx_t hashed_key_xor_ipad;
|
||||||
|
sha256_ctx_t hashed_key_xor_opad;
|
||||||
|
uint8_t key_xor_ipad[SHA256_INSIZE];
|
||||||
|
uint8_t key_xor_opad[SHA256_INSIZE];
|
||||||
|
uint8_t tempkey[SHA256_OUTSIZE];
|
||||||
|
va_list va;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
va_start(va, key_size);
|
||||||
|
|
||||||
|
// "The authentication key can be of any length up to INSIZE, the
|
||||||
|
// block length of the hash function. Applications that use keys longer
|
||||||
|
// than INSIZE bytes will first hash the key using H and then use the
|
||||||
|
// resultant OUTSIZE byte string as the actual key to HMAC."
|
||||||
|
if (key_size > SHA256_INSIZE) {
|
||||||
|
hash_sha256(tempkey, key, key_size);
|
||||||
|
key = tempkey;
|
||||||
|
key_size = SHA256_OUTSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < key_size; i++) {
|
||||||
|
key_xor_ipad[i] = key[i] ^ 0x36;
|
||||||
|
key_xor_opad[i] = key[i] ^ 0x5c;
|
||||||
|
}
|
||||||
|
for (; i < SHA256_INSIZE; i++) {
|
||||||
|
key_xor_ipad[i] = 0x36;
|
||||||
|
key_xor_opad[i] = 0x5c;
|
||||||
|
}
|
||||||
|
sha256_begin(&hashed_key_xor_ipad);
|
||||||
|
sha256_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA256_INSIZE);
|
||||||
|
sha256_begin(&hashed_key_xor_opad);
|
||||||
|
sha256_hash(&hashed_key_xor_opad, key_xor_opad, SHA256_INSIZE);
|
||||||
|
|
||||||
|
hmac_sha256_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC 5246:
|
||||||
|
// 5. HMAC and the Pseudorandom Function
|
||||||
|
//...
|
||||||
|
// In this section, we define one PRF, based on HMAC. This PRF with the
|
||||||
|
// SHA-256 hash function is used for all cipher suites defined in this
|
||||||
|
// document and in TLS documents published prior to this document when
|
||||||
|
// TLS 1.2 is negotiated.
|
||||||
|
//...
|
||||||
|
// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
|
||||||
|
// HMAC_hash(secret, A(2) + seed) +
|
||||||
|
// HMAC_hash(secret, A(3) + seed) + ...
|
||||||
|
// where + indicates concatenation.
|
||||||
|
// A() is defined as:
|
||||||
|
// A(0) = seed
|
||||||
|
// A(1) = HMAC_hash(secret, A(0)) = HMAC_hash(secret, seed)
|
||||||
|
// A(i) = HMAC_hash(secret, A(i-1))
|
||||||
|
// P_hash can be iterated as many times as necessary to produce the
|
||||||
|
// required quantity of data. For example, if P_SHA256 is being used to
|
||||||
|
// create 80 bytes of data, it will have to be iterated three times
|
||||||
|
// (through A(3)), creating 96 bytes of output data; the last 16 bytes
|
||||||
|
// of the final iteration will then be discarded, leaving 80 bytes of
|
||||||
|
// output data.
|
||||||
|
//
|
||||||
|
// TLS's PRF is created by applying P_hash to the secret as:
|
||||||
|
//
|
||||||
|
// PRF(secret, label, seed) = P_<hash>(secret, label + seed)
|
||||||
|
//
|
||||||
|
// The label is an ASCII string.
|
||||||
|
static void tls_prf_hmac_sha256(
|
||||||
|
uint8_t *outbuf, unsigned outbuf_size,
|
||||||
|
uint8_t *secret, unsigned secret_size,
|
||||||
|
const char *label,
|
||||||
|
uint8_t *seed, unsigned seed_size)
|
||||||
|
{
|
||||||
|
uint8_t a[SHA256_OUTSIZE];
|
||||||
|
uint8_t *out_p = outbuf;
|
||||||
|
unsigned label_size = strlen(label);
|
||||||
|
|
||||||
|
/* In P_hash() calculation, "seed" is "label + seed": */
|
||||||
|
#define SEED label, label_size, seed, seed_size
|
||||||
|
#define SECRET secret, secret_size
|
||||||
|
#define A a, (int)(sizeof(a))
|
||||||
|
|
||||||
|
/* A(1) = HMAC_hash(secret, seed) */
|
||||||
|
hmac_sha256(a, SECRET, SEED, NULL);
|
||||||
|
//TODO: convert hmac_sha256 to precomputed
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
/* HMAC_hash(secret, A(1) + seed) */
|
||||||
|
if (outbuf_size <= SHA256_OUTSIZE) {
|
||||||
|
/* Last, possibly incomplete, block */
|
||||||
|
/* (use a[] as temp buffer) */
|
||||||
|
hmac_sha256(a, SECRET, A, SEED, NULL);
|
||||||
|
memcpy(out_p, a, outbuf_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Not last block. Store directly to result buffer */
|
||||||
|
hmac_sha256(out_p, SECRET, A, SEED, NULL);
|
||||||
|
out_p += SHA256_OUTSIZE;
|
||||||
|
outbuf_size -= SHA256_OUTSIZE;
|
||||||
|
/* A(2) = HMAC_hash(secret, A(1)) */
|
||||||
|
hmac_sha256(a, SECRET, A, NULL);
|
||||||
|
}
|
||||||
|
#undef A
|
||||||
|
#undef SECRET
|
||||||
|
#undef SEED
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
tls_state_t *new_tls_state(void)
|
tls_state_t *new_tls_state(void)
|
||||||
{
|
{
|
||||||
@ -293,11 +432,13 @@ tls_state_t *new_tls_state(void)
|
|||||||
return tls;
|
return tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...);
|
static void tls_error_die(tls_state_t *tls)
|
||||||
|
|
||||||
static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size)
|
|
||||||
{
|
{
|
||||||
// rfc5246
|
dump_tls_record(tls->inbuf, tls->insize + tls->tail);
|
||||||
|
xfunc_die();
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC 5246
|
||||||
// 6.2.3.1. Null or Standard Stream Cipher
|
// 6.2.3.1. Null or Standard Stream Cipher
|
||||||
//
|
//
|
||||||
// Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6)
|
// Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6)
|
||||||
@ -310,18 +451,14 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size
|
|||||||
// } GenericStreamCipher;
|
// } GenericStreamCipher;
|
||||||
//
|
//
|
||||||
// The MAC is generated as:
|
// The MAC is generated as:
|
||||||
//
|
|
||||||
// MAC(MAC_write_key, seq_num +
|
// MAC(MAC_write_key, seq_num +
|
||||||
// TLSCompressed.type +
|
// TLSCompressed.type +
|
||||||
// TLSCompressed.version +
|
// TLSCompressed.version +
|
||||||
// TLSCompressed.length +
|
// TLSCompressed.length +
|
||||||
// TLSCompressed.fragment);
|
// TLSCompressed.fragment);
|
||||||
//
|
|
||||||
// where "+" denotes concatenation.
|
// where "+" denotes concatenation.
|
||||||
//
|
|
||||||
// seq_num
|
// seq_num
|
||||||
// The sequence number for this record.
|
// The sequence number for this record.
|
||||||
//
|
|
||||||
// MAC
|
// MAC
|
||||||
// The MAC algorithm specified by SecurityParameters.mac_algorithm.
|
// The MAC algorithm specified by SecurityParameters.mac_algorithm.
|
||||||
//
|
//
|
||||||
@ -345,23 +482,26 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size
|
|||||||
// MD5 HMAC-MD5 16 16
|
// MD5 HMAC-MD5 16 16
|
||||||
// SHA HMAC-SHA1 20 20
|
// SHA HMAC-SHA1 20 20
|
||||||
// SHA256 HMAC-SHA256 32 32
|
// SHA256 HMAC-SHA256 32 32
|
||||||
|
static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size)
|
||||||
|
{
|
||||||
uint8_t mac_hash[SHA256_OUTSIZE];
|
uint8_t mac_hash[SHA256_OUTSIZE];
|
||||||
struct record_hdr *xhdr = buf;
|
struct record_hdr *xhdr = buf;
|
||||||
|
|
||||||
if (tls->encrypt_on_write) {
|
if (tls->encrypt_on_write) {
|
||||||
|
//TODO: convert hmac_sha256 to precomputed
|
||||||
hmac_sha256(mac_hash,
|
hmac_sha256(mac_hash,
|
||||||
tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key),
|
tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key),
|
||||||
&tls->write_seq64_be, sizeof(tls->write_seq64_be),
|
&tls->write_seq64_be, sizeof(tls->write_seq64_be),
|
||||||
buf, size,
|
buf, size,
|
||||||
NULL);
|
NULL);
|
||||||
tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be));
|
tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be));
|
||||||
|
/* Temporarily change for writing */
|
||||||
xhdr->len16_lo += SHA256_OUTSIZE;
|
xhdr->len16_lo += SHA256_OUTSIZE;
|
||||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FIXME
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xwrite(tls->fd, buf, size);
|
xwrite(tls->fd, buf, size);
|
||||||
dbg("wrote %u bytes\n", size);
|
dbg("wrote %u bytes\n", size);
|
||||||
|
|
||||||
if (tls->encrypt_on_write) {
|
if (tls->encrypt_on_write) {
|
||||||
xwrite(tls->fd, mac_hash, sizeof(mac_hash));
|
xwrite(tls->fd, mac_hash, sizeof(mac_hash));
|
||||||
dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash));
|
dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash));
|
||||||
@ -374,12 +514,6 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tls_error_die(tls_state_t *tls)
|
|
||||||
{
|
|
||||||
dump_tls_record(tls->inbuf, tls->insize + tls->tail);
|
|
||||||
xfunc_die();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int xread_tls_block(tls_state_t *tls)
|
static int xread_tls_block(tls_state_t *tls)
|
||||||
{
|
{
|
||||||
struct record_hdr *xhdr;
|
struct record_hdr *xhdr;
|
||||||
@ -417,7 +551,7 @@ static int xread_tls_block(tls_state_t *tls)
|
|||||||
target -= sizeof(*xhdr);
|
target -= sizeof(*xhdr);
|
||||||
|
|
||||||
/* RFC 5246 is not saying it explicitly, but sha256 hash
|
/* RFC 5246 is not saying it explicitly, but sha256 hash
|
||||||
* in our FINISHED packet must include hashes of incoming packets too!
|
* in our FINISHED record must include data of incoming packets too!
|
||||||
*/
|
*/
|
||||||
if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) {
|
if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) {
|
||||||
sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, target);
|
sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, target);
|
||||||
@ -427,23 +561,9 @@ static int xread_tls_block(tls_state_t *tls)
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xread_tls_handshake_block(tls_state_t *tls, int min_len)
|
/*
|
||||||
{
|
* DER parsing routines
|
||||||
struct record_hdr *xhdr;
|
*/
|
||||||
int len = xread_tls_block(tls);
|
|
||||||
|
|
||||||
xhdr = (void*)tls->inbuf;
|
|
||||||
if (len < min_len
|
|
||||||
|| xhdr->type != RECORD_TYPE_HANDSHAKE
|
|
||||||
|| xhdr->proto_maj != TLS_MAJ
|
|
||||||
|| xhdr->proto_min != TLS_MIN
|
|
||||||
) {
|
|
||||||
tls_error_die(tls);
|
|
||||||
}
|
|
||||||
dbg("got HANDSHAKE\n");
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end)
|
static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end)
|
||||||
{
|
{
|
||||||
unsigned len, len1;
|
unsigned len, len1;
|
||||||
@ -653,147 +773,26 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
|
|||||||
dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size);
|
dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC 2104: HMAC(key, text) based on a hash H (say, sha256) is:
|
|
||||||
// ipad = [0x36 x INSIZE]
|
|
||||||
// opad = [0x5c x INSIZE]
|
|
||||||
// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text))
|
|
||||||
//
|
|
||||||
// H(key XOR opad) and H(key XOR ipad) can be precomputed
|
|
||||||
// if we often need HMAC hmac with the same key.
|
|
||||||
//
|
|
||||||
// text is often given in disjoint pieces.
|
|
||||||
static void hmac_sha256_precomputed_v(uint8_t out[SHA256_OUTSIZE],
|
|
||||||
sha256_ctx_t *hashed_key_xor_ipad,
|
|
||||||
sha256_ctx_t *hashed_key_xor_opad,
|
|
||||||
va_list va)
|
|
||||||
{
|
|
||||||
uint8_t *text;
|
|
||||||
|
|
||||||
/* hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
|
|
||||||
/* hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
|
|
||||||
|
|
||||||
/* calculate out = H((key XOR ipad) + text) */
|
|
||||||
while ((text = va_arg(va, uint8_t*)) != NULL) {
|
|
||||||
unsigned text_size = va_arg(va, unsigned);
|
|
||||||
sha256_hash(hashed_key_xor_ipad, text, text_size);
|
|
||||||
}
|
|
||||||
sha256_end(hashed_key_xor_ipad, out);
|
|
||||||
|
|
||||||
/* out = H((key XOR opad) + out) */
|
|
||||||
sha256_hash(hashed_key_xor_opad, out, SHA256_OUTSIZE);
|
|
||||||
sha256_end(hashed_key_xor_opad, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...)
|
|
||||||
{
|
|
||||||
sha256_ctx_t hashed_key_xor_ipad;
|
|
||||||
sha256_ctx_t hashed_key_xor_opad;
|
|
||||||
uint8_t key_xor_ipad[SHA256_INSIZE];
|
|
||||||
uint8_t key_xor_opad[SHA256_INSIZE];
|
|
||||||
uint8_t tempkey[SHA256_OUTSIZE];
|
|
||||||
va_list va;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
va_start(va, key_size);
|
|
||||||
|
|
||||||
// "The authentication key can be of any length up to INSIZE, the
|
|
||||||
// block length of the hash function. Applications that use keys longer
|
|
||||||
// than INSIZE bytes will first hash the key using H and then use the
|
|
||||||
// resultant OUTSIZE byte string as the actual key to HMAC."
|
|
||||||
if (key_size > SHA256_INSIZE) {
|
|
||||||
hash_sha256(tempkey, key, key_size);
|
|
||||||
key = tempkey;
|
|
||||||
key_size = SHA256_OUTSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < key_size; i++) {
|
|
||||||
key_xor_ipad[i] = key[i] ^ 0x36;
|
|
||||||
key_xor_opad[i] = key[i] ^ 0x5c;
|
|
||||||
}
|
|
||||||
for (; i < SHA256_INSIZE; i++) {
|
|
||||||
key_xor_ipad[i] = 0x36;
|
|
||||||
key_xor_opad[i] = 0x5c;
|
|
||||||
}
|
|
||||||
sha256_begin(&hashed_key_xor_ipad);
|
|
||||||
sha256_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA256_INSIZE);
|
|
||||||
sha256_begin(&hashed_key_xor_opad);
|
|
||||||
sha256_hash(&hashed_key_xor_opad, key_xor_opad, SHA256_INSIZE);
|
|
||||||
|
|
||||||
hmac_sha256_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va);
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
// RFC 5246:
|
|
||||||
// 5. HMAC and the Pseudorandom Function
|
|
||||||
//...
|
|
||||||
// In this section, we define one PRF, based on HMAC. This PRF with the
|
|
||||||
// SHA-256 hash function is used for all cipher suites defined in this
|
|
||||||
// document and in TLS documents published prior to this document when
|
|
||||||
// TLS 1.2 is negotiated.
|
|
||||||
//...
|
|
||||||
// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
|
|
||||||
// HMAC_hash(secret, A(2) + seed) +
|
|
||||||
// HMAC_hash(secret, A(3) + seed) + ...
|
|
||||||
// where + indicates concatenation.
|
|
||||||
// A() is defined as:
|
|
||||||
// A(0) = seed
|
|
||||||
// A(1) = HMAC_hash(secret, A(0)) = HMAC_hash(secret, seed)
|
|
||||||
// A(i) = HMAC_hash(secret, A(i-1))
|
|
||||||
// P_hash can be iterated as many times as necessary to produce the
|
|
||||||
// required quantity of data. For example, if P_SHA256 is being used to
|
|
||||||
// create 80 bytes of data, it will have to be iterated three times
|
|
||||||
// (through A(3)), creating 96 bytes of output data; the last 16 bytes
|
|
||||||
// of the final iteration will then be discarded, leaving 80 bytes of
|
|
||||||
// output data.
|
|
||||||
//
|
|
||||||
// TLS's PRF is created by applying P_hash to the secret as:
|
|
||||||
//
|
|
||||||
// PRF(secret, label, seed) = P_<hash>(secret, label + seed)
|
|
||||||
//
|
|
||||||
// The label is an ASCII string.
|
|
||||||
static void tls_prf_hmac_sha256(
|
|
||||||
uint8_t *outbuf, unsigned outbuf_size,
|
|
||||||
uint8_t *secret, unsigned secret_size,
|
|
||||||
const char *label,
|
|
||||||
uint8_t *seed, unsigned seed_size)
|
|
||||||
{
|
|
||||||
uint8_t a[SHA256_OUTSIZE];
|
|
||||||
uint8_t *out_p = outbuf;
|
|
||||||
unsigned label_size = strlen(label);
|
|
||||||
|
|
||||||
/* In P_hash() calculation, "seed" is "label + seed": */
|
|
||||||
#define SEED label, label_size, seed, seed_size
|
|
||||||
#define SECRET secret, secret_size
|
|
||||||
#define A a, (int)(sizeof(a))
|
|
||||||
|
|
||||||
/* A(1) = HMAC_hash(secret, seed) */
|
|
||||||
hmac_sha256(a, SECRET, SEED, NULL);
|
|
||||||
//TODO: convert hmac_sha256 to precomputed
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
/* HMAC_hash(secret, A(1) + seed) */
|
|
||||||
if (outbuf_size <= SHA256_OUTSIZE) {
|
|
||||||
/* Last, possibly incomplete, block */
|
|
||||||
/* (use a[] as temp buffer) */
|
|
||||||
hmac_sha256(a, SECRET, A, SEED, NULL);
|
|
||||||
memcpy(out_p, a, outbuf_size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Not last block. Store directly to result buffer */
|
|
||||||
hmac_sha256(out_p, SECRET, A, SEED, NULL);
|
|
||||||
out_p += SHA256_OUTSIZE;
|
|
||||||
outbuf_size -= SHA256_OUTSIZE;
|
|
||||||
/* A(2) = HMAC_hash(secret, A(1)) */
|
|
||||||
hmac_sha256(a, SECRET, A, NULL);
|
|
||||||
}
|
|
||||||
#undef A
|
|
||||||
#undef SECRET
|
|
||||||
#undef SEED
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TLS Handshake routines
|
* TLS Handshake routines
|
||||||
*/
|
*/
|
||||||
|
static int xread_tls_handshake_block(tls_state_t *tls, int min_len)
|
||||||
|
{
|
||||||
|
struct record_hdr *xhdr;
|
||||||
|
int len = xread_tls_block(tls);
|
||||||
|
|
||||||
|
xhdr = (void*)tls->inbuf;
|
||||||
|
if (len < min_len
|
||||||
|
|| xhdr->type != RECORD_TYPE_HANDSHAKE
|
||||||
|
|| xhdr->proto_maj != TLS_MAJ
|
||||||
|
|| xhdr->proto_min != TLS_MIN
|
||||||
|
) {
|
||||||
|
tls_error_die(tls);
|
||||||
|
}
|
||||||
|
dbg("got HANDSHAKE\n");
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
static void send_client_hello(tls_state_t *tls)
|
static void send_client_hello(tls_state_t *tls)
|
||||||
{
|
{
|
||||||
struct client_hello {
|
struct client_hello {
|
||||||
@ -1055,7 +1054,7 @@ static void send_change_cipher_spec(tls_state_t *tls)
|
|||||||
dbg(">> CHANGE_CIPHER_SPEC\n");
|
dbg(">> CHANGE_CIPHER_SPEC\n");
|
||||||
xwrite(tls->fd, rec, sizeof(rec));
|
xwrite(tls->fd, rec, sizeof(rec));
|
||||||
|
|
||||||
tls->write_seq64_be = 0;
|
/* tls->write_seq64_be = 0; - already is */
|
||||||
tls->encrypt_on_write = 1;
|
tls->encrypt_on_write = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user