mirror of
https://github.com/strongswan/strongswan.git
synced 2025-12-03 00:00:23 -05:00
Refactored common used operations into TLS crypto helper
This commit is contained in:
parent
3e7e777941
commit
84d67ead4e
@ -49,6 +49,11 @@ struct private_tls_crypto_t {
|
|||||||
*/
|
*/
|
||||||
tls_t *tls;
|
tls_t *tls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All handshake data concatentated
|
||||||
|
*/
|
||||||
|
chunk_t handshake;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection state TLS PRF
|
* Connection state TLS PRF
|
||||||
*/
|
*/
|
||||||
@ -346,7 +351,128 @@ METHOD(tls_crypto_t, select_cipher_suite, tls_cipher_suite_t,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_crypto_t, derive_master_secret, void,
|
METHOD(tls_crypto_t, append_handshake, void,
|
||||||
|
private_tls_crypto_t *this, tls_handshake_type_t type, chunk_t data)
|
||||||
|
{
|
||||||
|
u_int32_t header;
|
||||||
|
|
||||||
|
/* reconstruct handshake header */
|
||||||
|
header = htonl(data.len | (type << 24));
|
||||||
|
this->handshake = chunk_cat("mcc", this->handshake,
|
||||||
|
chunk_from_thing(header), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a hash of the stored handshake data
|
||||||
|
*/
|
||||||
|
static bool hash_handshake(private_tls_crypto_t *this, chunk_t *hash)
|
||||||
|
{
|
||||||
|
if (this->tls->get_version(this->tls) >= TLS_1_2)
|
||||||
|
{
|
||||||
|
hasher_t *hasher;
|
||||||
|
suite_algs_t *alg;
|
||||||
|
|
||||||
|
alg = find_suite(this->suite);
|
||||||
|
if (!alg)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
hasher = lib->crypto->create_hasher(lib->crypto, alg->hash);
|
||||||
|
if (!hasher)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "%N not supported", hash_algorithm_names, alg->hash);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
hasher->allocate_hash(hasher, this->handshake, hash);
|
||||||
|
hasher->destroy(hasher);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hasher_t *md5, *sha1;
|
||||||
|
char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1];
|
||||||
|
|
||||||
|
md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
||||||
|
if (!md5)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "%N not supported", hash_algorithm_names, HASH_MD5);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
md5->get_hash(md5, this->handshake, buf);
|
||||||
|
md5->destroy(md5);
|
||||||
|
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
||||||
|
if (!sha1)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "%N not supported", hash_algorithm_names, HASH_SHA1);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
sha1->get_hash(sha1, this->handshake, buf + HASH_SIZE_MD5);
|
||||||
|
sha1->destroy(sha1);
|
||||||
|
|
||||||
|
*hash = chunk_clone(chunk_from_thing(buf));
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_crypto_t, sign_handshake, bool,
|
||||||
|
private_tls_crypto_t *this, private_key_t *key, chunk_t *sig)
|
||||||
|
{
|
||||||
|
if (this->tls->get_version(this->tls) >= TLS_1_2)
|
||||||
|
{
|
||||||
|
u_int16_t length;
|
||||||
|
u_int8_t hash_alg;
|
||||||
|
u_int8_t sig_alg;
|
||||||
|
|
||||||
|
if (!key->sign(key, SIGN_RSA_EMSA_PKCS1_SHA1, this->handshake, sig))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* TODO: signature scheme to hashsign algorithm mapping */
|
||||||
|
hash_alg = 2; /* sha1 */
|
||||||
|
sig_alg = 1; /* RSA */
|
||||||
|
length = htons(sig->len);
|
||||||
|
*sig = chunk_cat("cccm", chunk_from_thing(hash_alg),
|
||||||
|
chunk_from_thing(sig_alg), chunk_from_thing(length), *sig);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u_int16_t length;
|
||||||
|
chunk_t hash;
|
||||||
|
|
||||||
|
if (!hash_handshake(this, &hash))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!key->sign(key, SIGN_RSA_EMSA_PKCS1_NULL, hash, sig))
|
||||||
|
{
|
||||||
|
free(hash.ptr);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
free(hash.ptr);
|
||||||
|
length = htons(sig->len);
|
||||||
|
*sig = chunk_cat("cm", chunk_from_thing(length), *sig);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_crypto_t, calculate_finished, bool,
|
||||||
|
private_tls_crypto_t *this, char *label, char out[12])
|
||||||
|
{
|
||||||
|
chunk_t seed;
|
||||||
|
|
||||||
|
if (!this->prf)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!hash_handshake(this, &seed))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
this->prf->get_bytes(this->prf, label, seed, 12, out);
|
||||||
|
free(seed.ptr);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_crypto_t, derive_secrets, void,
|
||||||
private_tls_crypto_t *this, chunk_t premaster,
|
private_tls_crypto_t *this, chunk_t premaster,
|
||||||
chunk_t client_random, chunk_t server_random)
|
chunk_t client_random, chunk_t server_random)
|
||||||
{
|
{
|
||||||
@ -363,11 +489,6 @@ METHOD(tls_crypto_t, derive_master_secret, void,
|
|||||||
this->prf->set_key(this->prf, chunk_from_thing(master));
|
this->prf->set_key(this->prf, chunk_from_thing(master));
|
||||||
memset(master, 0, sizeof(master));
|
memset(master, 0, sizeof(master));
|
||||||
|
|
||||||
/* MSK for EAP-TLS */
|
|
||||||
this->msk = chunk_alloc(64);
|
|
||||||
this->prf->get_bytes(this->prf, "client EAP encryption", seed,
|
|
||||||
this->msk.len, this->msk.ptr);
|
|
||||||
|
|
||||||
/* derive key block for key expansion */
|
/* derive key block for key expansion */
|
||||||
mks = this->signer_out->get_key_size(this->signer_out);
|
mks = this->signer_out->get_key_size(this->signer_out);
|
||||||
if (this->crypter_out)
|
if (this->crypter_out)
|
||||||
@ -452,10 +573,16 @@ METHOD(tls_crypto_t, change_cipher, void,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_crypto_t, get_prf, tls_prf_t*,
|
METHOD(tls_crypto_t, derive_eap_msk, void,
|
||||||
private_tls_crypto_t *this)
|
private_tls_crypto_t *this, chunk_t client_random, chunk_t server_random)
|
||||||
{
|
{
|
||||||
return this->prf;
|
chunk_t seed;
|
||||||
|
|
||||||
|
seed = chunk_cata("cc", client_random, server_random);
|
||||||
|
free(this->msk.ptr);
|
||||||
|
this->msk = chunk_alloc(64);
|
||||||
|
this->prf->get_bytes(this->prf, "client EAP encryption", seed,
|
||||||
|
this->msk.len, this->msk.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_crypto_t, get_eap_msk, chunk_t,
|
METHOD(tls_crypto_t, get_eap_msk, chunk_t,
|
||||||
@ -473,6 +600,7 @@ METHOD(tls_crypto_t, destroy, void,
|
|||||||
DESTROY_IF(this->crypter_out);
|
DESTROY_IF(this->crypter_out);
|
||||||
free(this->iv_in.ptr);
|
free(this->iv_in.ptr);
|
||||||
free(this->iv_out.ptr);
|
free(this->iv_out.ptr);
|
||||||
|
free(this->handshake.ptr);
|
||||||
free(this->msk.ptr);
|
free(this->msk.ptr);
|
||||||
DESTROY_IF(this->prf);
|
DESTROY_IF(this->prf);
|
||||||
free(this->suites);
|
free(this->suites);
|
||||||
@ -490,9 +618,12 @@ tls_crypto_t *tls_crypto_create(tls_t *tls)
|
|||||||
.public = {
|
.public = {
|
||||||
.get_cipher_suites = _get_cipher_suites,
|
.get_cipher_suites = _get_cipher_suites,
|
||||||
.select_cipher_suite = _select_cipher_suite,
|
.select_cipher_suite = _select_cipher_suite,
|
||||||
.derive_master_secret = _derive_master_secret,
|
.append_handshake = _append_handshake,
|
||||||
|
.sign_handshake = _sign_handshake,
|
||||||
|
.calculate_finished = _calculate_finished,
|
||||||
|
.derive_secrets = _derive_secrets,
|
||||||
.change_cipher = _change_cipher,
|
.change_cipher = _change_cipher,
|
||||||
.get_prf = _get_prf,
|
.derive_eap_msk = _derive_eap_msk,
|
||||||
.get_eap_msk = _get_eap_msk,
|
.get_eap_msk = _get_eap_msk,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -26,6 +26,8 @@ typedef struct tls_crypto_t tls_crypto_t;
|
|||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
#include "tls_prf.h"
|
#include "tls_prf.h"
|
||||||
|
|
||||||
|
#include <credentials/keys/private_key.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS crypto helper functions.
|
* TLS crypto helper functions.
|
||||||
*/
|
*/
|
||||||
@ -50,14 +52,41 @@ struct tls_crypto_t {
|
|||||||
tls_cipher_suite_t *suites, int count);
|
tls_cipher_suite_t *suites, int count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive the master secret and load it into the PRF.
|
* Store exchanged handshake data, used for cryptographic operations.
|
||||||
|
*
|
||||||
|
* @param type handshake sub type
|
||||||
|
* @param data data to append to handshake buffer
|
||||||
|
*/
|
||||||
|
void (*append_handshake)(tls_crypto_t *this,
|
||||||
|
tls_handshake_type_t type, chunk_t data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a signature of the handshake data using a given private key.
|
||||||
|
*
|
||||||
|
* @param key private key to use for signature
|
||||||
|
* @param sig allocated signature
|
||||||
|
* @return TRUE if signature create successfully
|
||||||
|
*/
|
||||||
|
bool (*sign_handshake)(tls_crypto_t *this, private_key_t *key, chunk_t *sig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the data of a TLS finished message.
|
||||||
|
*
|
||||||
|
* @param label ASCII label to use for calculation
|
||||||
|
* @param out buffer to write finished data to
|
||||||
|
* @return TRUE if calculation successful
|
||||||
|
*/
|
||||||
|
bool (*calculate_finished)(tls_crypto_t *this, char *label, char out[12]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive the master secret, MAC and encryption keys.
|
||||||
*
|
*
|
||||||
* @param premaster premaster secret
|
* @param premaster premaster secret
|
||||||
* @param client_random random data from client hello
|
* @param client_random random data from client hello
|
||||||
* @param server_random random data from server hello
|
* @param server_random random data from server hello
|
||||||
*/
|
*/
|
||||||
void (*derive_master_secret)(tls_crypto_t *this, chunk_t premaster,
|
void (*derive_secrets)(tls_crypto_t *this, chunk_t premaster,
|
||||||
chunk_t client_random, chunk_t server_random);
|
chunk_t client_random, chunk_t server_random);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the cipher used at protection layer.
|
* Change the cipher used at protection layer.
|
||||||
@ -67,11 +96,13 @@ struct tls_crypto_t {
|
|||||||
void (*change_cipher)(tls_crypto_t *this, bool inbound);
|
void (*change_cipher)(tls_crypto_t *this, bool inbound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the connection state PRF.
|
* Derive the EAP-TLS MSK.
|
||||||
*
|
*
|
||||||
* @return PRF, NULL if not supported
|
* @param client_random random data from client hello
|
||||||
|
* @param server_random random data from server hello
|
||||||
*/
|
*/
|
||||||
tls_prf_t* (*get_prf)(tls_crypto_t *this);
|
void (*derive_eap_msk)(tls_crypto_t *this,
|
||||||
|
chunk_t client_random, chunk_t server_random);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the MSK to use in EAP-TLS.
|
* Get the MSK to use in EAP-TLS.
|
||||||
|
|||||||
@ -69,11 +69,6 @@ struct private_tls_peer_t {
|
|||||||
*/
|
*/
|
||||||
peer_state_t state;
|
peer_state_t state;
|
||||||
|
|
||||||
/**
|
|
||||||
* All handshake data concatentated
|
|
||||||
*/
|
|
||||||
chunk_t handshake;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hello random data selected by client
|
* Hello random data selected by client
|
||||||
*/
|
*/
|
||||||
@ -100,20 +95,6 @@ struct private_tls_peer_t {
|
|||||||
private_key_t *private;
|
private_key_t *private;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a handshake message to the handshake data buffer
|
|
||||||
*/
|
|
||||||
static void append_handshake(private_tls_peer_t *this,
|
|
||||||
tls_handshake_type_t type, chunk_t data)
|
|
||||||
{
|
|
||||||
u_int32_t header;
|
|
||||||
|
|
||||||
/* reconstruct handshake header */
|
|
||||||
header = htonl(data.len | (type << 24));
|
|
||||||
this->handshake = chunk_cat("mcc", this->handshake,
|
|
||||||
chunk_from_thing(header), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a server hello message
|
* Process a server hello message
|
||||||
*/
|
*/
|
||||||
@ -125,7 +106,8 @@ static status_t process_server_hello(private_tls_peer_t *this,
|
|||||||
chunk_t random, session, ext = chunk_empty;
|
chunk_t random, session, ext = chunk_empty;
|
||||||
tls_cipher_suite_t suite;
|
tls_cipher_suite_t suite;
|
||||||
|
|
||||||
append_handshake(this, TLS_SERVER_HELLO, reader->peek(reader));
|
this->crypto->append_handshake(this->crypto,
|
||||||
|
TLS_SERVER_HELLO, reader->peek(reader));
|
||||||
|
|
||||||
if (!reader->read_uint16(reader, &version) ||
|
if (!reader->read_uint16(reader, &version) ||
|
||||||
!reader->read_data(reader, sizeof(this->server_random), &random) ||
|
!reader->read_data(reader, sizeof(this->server_random), &random) ||
|
||||||
@ -164,7 +146,8 @@ static status_t process_certificate(private_tls_peer_t *this,
|
|||||||
chunk_t data;
|
chunk_t data;
|
||||||
bool first = TRUE;
|
bool first = TRUE;
|
||||||
|
|
||||||
append_handshake(this, TLS_CERTIFICATE, reader->peek(reader));
|
this->crypto->append_handshake(this->crypto,
|
||||||
|
TLS_CERTIFICATE, reader->peek(reader));
|
||||||
|
|
||||||
if (!reader->read_data24(reader, &data))
|
if (!reader->read_data24(reader, &data))
|
||||||
{
|
{
|
||||||
@ -217,7 +200,8 @@ static status_t process_certreq(private_tls_peer_t *this, tls_reader_t *reader)
|
|||||||
identification_t *id;
|
identification_t *id;
|
||||||
certificate_t *cert;
|
certificate_t *cert;
|
||||||
|
|
||||||
append_handshake(this, TLS_CERTIFICATE_REQUEST, reader->peek(reader));
|
this->crypto->append_handshake(this->crypto,
|
||||||
|
TLS_CERTIFICATE_REQUEST, reader->peek(reader));
|
||||||
|
|
||||||
if (!reader->read_data8(reader, &types))
|
if (!reader->read_data8(reader, &types))
|
||||||
{
|
{
|
||||||
@ -267,7 +251,8 @@ static status_t process_certreq(private_tls_peer_t *this, tls_reader_t *reader)
|
|||||||
static status_t process_hello_done(private_tls_peer_t *this,
|
static status_t process_hello_done(private_tls_peer_t *this,
|
||||||
tls_reader_t *reader)
|
tls_reader_t *reader)
|
||||||
{
|
{
|
||||||
append_handshake(this, TLS_SERVER_HELLO_DONE, reader->peek(reader));
|
this->crypto->append_handshake(this->crypto,
|
||||||
|
TLS_SERVER_HELLO_DONE, reader->peek(reader));
|
||||||
this->state = STATE_HELLO_DONE;
|
this->state = STATE_HELLO_DONE;
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
@ -277,61 +262,28 @@ static status_t process_hello_done(private_tls_peer_t *this,
|
|||||||
*/
|
*/
|
||||||
static status_t process_finished(private_tls_peer_t *this, tls_reader_t *reader)
|
static status_t process_finished(private_tls_peer_t *this, tls_reader_t *reader)
|
||||||
{
|
{
|
||||||
chunk_t seed, received;
|
chunk_t received;
|
||||||
tls_prf_t *prf;
|
char buf[12];
|
||||||
char data[12];
|
|
||||||
|
|
||||||
if (!reader->read_data(reader, sizeof(data), &received))
|
if (!reader->read_data(reader, sizeof(buf), &received))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received server finished too short");
|
DBG1(DBG_IKE, "received server finished too short");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
if (!this->crypto->calculate_finished(this->crypto, "server finished", buf))
|
||||||
if (this->tls->get_version(this->tls) >= TLS_1_2)
|
|
||||||
{
|
|
||||||
/* TODO: use hash of cipher suite only */
|
|
||||||
seed = chunk_empty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hasher_t *md5, *sha1;
|
|
||||||
char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1];
|
|
||||||
|
|
||||||
md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
|
||||||
if (!md5)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "unable to create %N Finished, MD5 not supported",
|
|
||||||
tls_version_names, this->tls->get_version(this->tls));
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
md5->get_hash(md5, this->handshake, buf);
|
|
||||||
md5->destroy(md5);
|
|
||||||
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
|
||||||
if (!sha1)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "unable to sign %N Finished, SHA1 not supported",
|
|
||||||
tls_version_names, this->tls->get_version(this->tls));
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
sha1->get_hash(sha1, this->handshake, buf + HASH_SIZE_MD5);
|
|
||||||
sha1->destroy(sha1);
|
|
||||||
|
|
||||||
seed = chunk_clonea(chunk_from_thing(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
prf = this->crypto->get_prf(this->crypto);
|
|
||||||
if (!prf)
|
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_IKE, "calculating server finished failed");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
prf->get_bytes(prf, "server finished", seed, sizeof(data), data);
|
if (!chunk_equals(received, chunk_from_thing(buf)))
|
||||||
|
|
||||||
if (!chunk_equals(received, chunk_from_thing(data)))
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received server finished invalid");
|
DBG1(DBG_IKE, "received server finished invalid");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
this->state = STATE_COMPLETE;
|
this->state = STATE_COMPLETE;
|
||||||
|
this->crypto->derive_eap_msk(this->crypto,
|
||||||
|
chunk_from_thing(this->client_random),
|
||||||
|
chunk_from_thing(this->server_random));
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,7 +360,7 @@ static status_t send_hello(private_tls_peer_t *this,
|
|||||||
|
|
||||||
*type = TLS_CLIENT_HELLO;
|
*type = TLS_CLIENT_HELLO;
|
||||||
this->state = STATE_HELLO_SENT;
|
this->state = STATE_HELLO_SENT;
|
||||||
append_handshake(this, *type, writer->get_buf(writer));
|
this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +414,7 @@ static status_t send_certificate(private_tls_peer_t *this,
|
|||||||
|
|
||||||
*type = TLS_CERTIFICATE;
|
*type = TLS_CERTIFICATE;
|
||||||
this->state = STATE_CERT_SENT;
|
this->state = STATE_CERT_SENT;
|
||||||
append_handshake(this, *type, writer->get_buf(writer));
|
this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,9 +441,9 @@ static status_t send_key_exchange(private_tls_peer_t *this,
|
|||||||
rng->destroy(rng);
|
rng->destroy(rng);
|
||||||
htoun16(premaster, TLS_1_2);
|
htoun16(premaster, TLS_1_2);
|
||||||
|
|
||||||
this->crypto->derive_master_secret(this->crypto, chunk_from_thing(premaster),
|
this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
|
||||||
chunk_from_thing(this->client_random),
|
chunk_from_thing(this->client_random),
|
||||||
chunk_from_thing(this->server_random));
|
chunk_from_thing(this->server_random));
|
||||||
|
|
||||||
enumerator = charon->credentials->create_public_enumerator(
|
enumerator = charon->credentials->create_public_enumerator(
|
||||||
charon->credentials, KEY_ANY, this->server, this->server_auth);
|
charon->credentials, KEY_ANY, this->server, this->server_auth);
|
||||||
@ -520,7 +472,7 @@ static status_t send_key_exchange(private_tls_peer_t *this,
|
|||||||
|
|
||||||
*type = TLS_CLIENT_KEY_EXCHANGE;
|
*type = TLS_CLIENT_KEY_EXCHANGE;
|
||||||
this->state = STATE_KEY_EXCHANGE_SENT;
|
this->state = STATE_KEY_EXCHANGE_SENT;
|
||||||
append_handshake(this, *type, writer->get_buf(writer));
|
this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,60 +484,18 @@ static status_t send_certificate_verify(private_tls_peer_t *this,
|
|||||||
{
|
{
|
||||||
chunk_t signature;
|
chunk_t signature;
|
||||||
|
|
||||||
if (!this->private)
|
if (!this->private ||
|
||||||
|
!this->crypto->sign_handshake(this->crypto, this->private, &signature))
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_IKE, "creating TLS Certificate Verify signature failed");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
writer->write_data(writer, signature);
|
||||||
if (this->tls->get_version(this->tls) >= TLS_1_2)
|
|
||||||
{
|
|
||||||
if (!this->private->sign(this->private, SIGN_RSA_EMSA_PKCS1_SHA1,
|
|
||||||
this->handshake, &signature))
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "creating TLS Certificate Verify signature failed");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
/* TODO: signature scheme to hashsign algorithm mapping */
|
|
||||||
writer->write_uint8(writer, 2); /* sha1 */
|
|
||||||
writer->write_uint8(writer, 1); /* RSA */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hasher_t *md5, *sha1;
|
|
||||||
char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1];
|
|
||||||
|
|
||||||
md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
|
||||||
if (!md5)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "unable to sign %N Verify, MD5 not supported",
|
|
||||||
tls_version_names, this->tls->get_version(this->tls));
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
md5->get_hash(md5, this->handshake, buf);
|
|
||||||
md5->destroy(md5);
|
|
||||||
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
|
||||||
if (!sha1)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "unable to sign %N Verify, SHA1 not supported",
|
|
||||||
tls_version_names, this->tls->get_version(this->tls));
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
sha1->get_hash(sha1, this->handshake, buf + HASH_SIZE_MD5);
|
|
||||||
sha1->destroy(sha1);
|
|
||||||
|
|
||||||
if (!this->private->sign(this->private, SIGN_RSA_EMSA_PKCS1_NULL,
|
|
||||||
chunk_from_thing(buf), &signature))
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "creating TLS Certificate Verify signature failed");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer->write_data16(writer, signature);
|
|
||||||
free(signature.ptr);
|
free(signature.ptr);
|
||||||
|
|
||||||
*type = TLS_CERTIFICATE_VERIFY;
|
*type = TLS_CERTIFICATE_VERIFY;
|
||||||
this->state = STATE_VERIFY_SENT;
|
this->state = STATE_VERIFY_SENT;
|
||||||
append_handshake(this, *type, writer->get_buf(writer));
|
this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,54 +505,19 @@ static status_t send_certificate_verify(private_tls_peer_t *this,
|
|||||||
static status_t send_finished(private_tls_peer_t *this,
|
static status_t send_finished(private_tls_peer_t *this,
|
||||||
tls_handshake_type_t *type, tls_writer_t *writer)
|
tls_handshake_type_t *type, tls_writer_t *writer)
|
||||||
{
|
{
|
||||||
chunk_t seed;
|
char buf[12];
|
||||||
tls_prf_t *prf;
|
|
||||||
char data[12];
|
|
||||||
|
|
||||||
if (this->tls->get_version(this->tls) >= TLS_1_2)
|
if (!this->crypto->calculate_finished(this->crypto, "client finished", buf))
|
||||||
{
|
|
||||||
/* TODO: use hash of cipher suite only */
|
|
||||||
seed = chunk_empty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hasher_t *md5, *sha1;
|
|
||||||
char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1];
|
|
||||||
|
|
||||||
md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
|
||||||
if (!md5)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "unable to create %N Finished, MD5 not supported",
|
|
||||||
tls_version_names, this->tls->get_version(this->tls));
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
md5->get_hash(md5, this->handshake, buf);
|
|
||||||
md5->destroy(md5);
|
|
||||||
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
|
||||||
if (!sha1)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "unable to sign %N Finished, SHA1 not supported",
|
|
||||||
tls_version_names, this->tls->get_version(this->tls));
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
sha1->get_hash(sha1, this->handshake, buf + HASH_SIZE_MD5);
|
|
||||||
sha1->destroy(sha1);
|
|
||||||
|
|
||||||
seed = chunk_clonea(chunk_from_thing(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
prf = this->crypto->get_prf(this->crypto);
|
|
||||||
if (!prf)
|
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_IKE, "calculating client finished data failed");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
prf->get_bytes(prf, "client finished", seed, sizeof(data), data);
|
|
||||||
|
|
||||||
writer->write_data(writer, chunk_from_thing(data));
|
writer->write_data(writer, chunk_from_thing(buf));
|
||||||
|
|
||||||
*type = TLS_FINISHED;
|
*type = TLS_FINISHED;
|
||||||
this->state = STATE_FINISHED_SENT;
|
this->state = STATE_FINISHED_SENT;
|
||||||
append_handshake(this, *type, writer->get_buf(writer));
|
this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,7 +571,6 @@ METHOD(tls_handshake_t, destroy, void,
|
|||||||
private_tls_peer_t *this)
|
private_tls_peer_t *this)
|
||||||
{
|
{
|
||||||
DESTROY_IF(this->private);
|
DESTROY_IF(this->private);
|
||||||
free(this->handshake.ptr);
|
|
||||||
this->peer_auth->destroy(this->peer_auth);
|
this->peer_auth->destroy(this->peer_auth);
|
||||||
this->server_auth->destroy(this->server_auth);
|
this->server_auth->destroy(this->server_auth);
|
||||||
free(this);
|
free(this);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user