Skip to content

Commit

Permalink
Add OQS_KEX generic hybrid ECDHE ciphersuite to libssl
Browse files Browse the repository at this point in the history
  • Loading branch information
dstebila committed Aug 25, 2016
1 parent 951b73a commit 58090ad
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 11 deletions.
86 changes: 83 additions & 3 deletions ssl/s3_clnt.c
Expand Up @@ -1804,8 +1804,7 @@ int ssl3_get_key_exchange(SSL *s)
#endif /* !OPENSSL_NO_DH */

#ifndef OPENSSL_NO_OQSKEX
else if (alg_k & SSL_kOQSKEXGENERIC)
{
else if ((alg_k & SSL_kOQSKEXGENERIC) && !(alg_k & SSL_kEECDH)) {
/* Get the OQSKEX message */
srvr_oqskex_msg_len = (p[0] << 8) | p[1];
p += 2;
Expand Down Expand Up @@ -1928,6 +1927,34 @@ int ssl3_get_key_exchange(SSL *s)
n -= param_len;
p += encoded_pt_len;

#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
if (alg_k & SSL_kOQSKEXGENERIC) {
/* Get the OQSKEX message */
srvr_oqskex_msg_len = (p[0] << 8) | p[1];
p += 2;
n -= 2;

if (srvr_oqskex_msg_len >= n) {
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_LENGTH);
goto f_err;
}
if ((srvr_oqskex_msg = malloc(srvr_oqskex_msg_len)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
goto err;
}

memcpy(srvr_oqskex_msg, p, srvr_oqskex_msg_len);

n -= srvr_oqskex_msg_len;
p += srvr_oqskex_msg_len;
param_len += 2 + srvr_oqskex_msg_len;

s->session->sess_cert->peer_oqskex_msg_tmp = srvr_oqskex_msg;
s->session->sess_cert->peer_oqskex_msg_len_tmp = srvr_oqskex_msg_len;
}
#endif

/*
* The ECC/TLS specification does not mention the use of DSA to sign
* ECParameters in the server key exchange message. We do support RSA
Expand Down Expand Up @@ -2962,6 +2989,39 @@ int ssl3_send_client_key_exchange(SSL *s)
goto err;
}

#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
if (alg_k & SSL_kOQSKEXGENERIC) {
srvr_oqskex_msg = s->session->sess_cert->peer_oqskex_msg_tmp;
srvr_oqskex_msg_len = s->session->sess_cert->peer_oqskex_msg_len_tmp;

if (srvr_oqskex_msg == NULL) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}

if ((oqskex_rand = OQS_RAND_new()) == NULL) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
goto err;
}
if (alg_k & SSL_kOQSKEXGENERIC) {
if ((oqskex_kex = OQS_KEX_new(oqskex_rand, NULL, 0)) == NULL) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
goto err;
}
}

if (OQS_KEX_bob(oqskex_kex, srvr_oqskex_msg, srvr_oqskex_msg_len, &clnt_oqskex_msg, &clnt_oqskex_msg_len, &pprime_oqskex, &nprime_oqskex) != 1) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}

// FIXME: I have no idea if this is safe, as I don't know how big p is, but let's try it anyway for testing purposes.
memcpy(p + n, pprime_oqskex, nprime_oqskex);
n += nprime_oqskex;
OPENSSL_free(pprime_oqskex);
}
#endif

/* generate master key from the result */
s->session->master_key_length =
s->method->ssl3_enc->generate_master_secret(s,
Expand Down Expand Up @@ -3005,10 +3065,30 @@ int ssl3_send_client_key_exchange(SSL *s)
p += 1;
/* copy the point */
memcpy((unsigned char *)p, encodedPoint, n);
#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
p += n;
#endif
/* increment n to account for length field */
n += 1;
}

#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
if (alg_k & SSL_kOQSKEXGENERIC) {
p[0] = (clnt_oqskex_msg_len >> 8) & 0xFF;
p[1] = clnt_oqskex_msg_len & 0xFF;
p += 2;
memcpy((unsigned char *) p, clnt_oqskex_msg, clnt_oqskex_msg_len);
p += clnt_oqskex_msg_len;

n += 2 + clnt_oqskex_msg_len;

/* Free allocated memory */
OPENSSL_free(clnt_oqskex_msg);
OQS_KEX_free(oqskex_kex);
OQS_RAND_free(oqskex_rand);
}
#endif

/* Free allocated memory */
BN_CTX_free(bn_ctx);
if (encodedPoint != NULL)
Expand All @@ -3019,7 +3099,7 @@ int ssl3_send_client_key_exchange(SSL *s)
}
#endif /* !OPENSSL_NO_ECDH */
#ifndef OPENSSL_NO_OQSKEX
else if (alg_k & SSL_kOQSKEXGENERIC) {
else if ((alg_k & SSL_kOQSKEXGENERIC) && !(alg_k & SSL_kEECDH)) {
srvr_oqskex_msg = s->session->sess_cert->peer_oqskex_msg_tmp;
srvr_oqskex_msg_len = s->session->sess_cert->peer_oqskex_msg_len_tmp;

Expand Down
67 changes: 67 additions & 0 deletions ssl/s3_lib.c
Expand Up @@ -2955,6 +2955,73 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {

#endif /* OPENSSL_NO_OQSKEX */

#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
/* Cipher FF04 */
{
1,
TLS1_TXT_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
SSL_kOQSKEXGENERIC|SSL_kEECDH,
SSL_aRSA,
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
128,
128,
},

/* Cipher FF05 */
{
1,
TLS1_TXT_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
SSL_kOQSKEXGENERIC|SSL_kEECDH,
SSL_aECDSA,
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
128,
128,
},

/* Cipher FF06 */
{
1,
TLS1_TXT_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
SSL_kOQSKEXGENERIC|SSL_kEECDH,
SSL_aRSA,
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
256,
256,
},

/* Cipher FF07 */
{
1,
TLS1_TXT_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
SSL_kOQSKEXGENERIC|SSL_kEECDH,
SSL_aECDSA,
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
256,
256,
},

#endif /* OPENSSL_NO_HYBRID_OQSKEX_ECDHE */

#ifdef TEMP_GOST_TLS
/* Cipher FF00 */
{
Expand Down
88 changes: 80 additions & 8 deletions ssl/s3_srvr.c
Expand Up @@ -1833,10 +1833,33 @@ int ssl3_send_server_key_exchange(SSL *s)
r[1] = NULL;
r[2] = NULL;
r[3] = NULL;

#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
if (type & SSL_kOQSKEXGENERIC) {
if ((s->s3->tmp.oqskex_rand = OQS_RAND_new()) == NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
goto err;
}
if (type & SSL_kOQSKEXGENERIC) {
if ((s->s3->tmp.oqskex_kex = OQS_KEX_new(s->s3->tmp.oqskex_rand, NULL, 0)) == NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
goto err;
}
}

if (OQS_KEX_alice_0(s->s3->tmp.oqskex_kex, &(s->s3->tmp.oqskex_priv), &oqskex_srvr_msg, &oqskex_srvr_msg_len) != 1) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
goto err;
}

n += 2 + oqskex_srvr_msg_len;
}
#endif

} else
#endif /* !OPENSSL_NO_ECDH */
#ifndef OPENSSL_NO_OQSKEX
if (type & SSL_kOQSKEXGENERIC) {
if ((type & SSL_kOQSKEXGENERIC) && !(type & SSL_kEECDH)) {
if ((s->s3->tmp.oqskex_rand = OQS_RAND_new()) == NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
goto err;
Expand Down Expand Up @@ -2740,7 +2763,7 @@ int ssl3_get_client_key_exchange(SSL *s)
/* Get encoded point length */
i = *p;
p += 1;
if (n != 1 + i) {
if (n < 1 + i) {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
al = SSL_AD_DECODE_ERROR;
goto f_err;
Expand All @@ -2750,12 +2773,40 @@ int ssl3_get_client_key_exchange(SSL *s)
al = SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
/*
* p is pointing to somewhere in the buffer currently, so set it
* to the start
*/
p = (unsigned char *)s->init_buf->data;
#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
p += i;
n -= 1 + i;
#endif
}

#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
if (alg_k & SSL_kOQSKEXGENERIC) {
/* Parse client message */
if (n < 2) {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_BAD_LENGTH);
goto err;
}
clnt_oqskex_msg_len = (p[0] << 8) | p[1];
p += 2;
if (n < 2 + clnt_oqskex_msg_len) {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_BAD_LENGTH);
goto err;
}
clnt_oqskex_msg = OPENSSL_malloc(clnt_oqskex_msg_len);
if (clnt_oqskex_msg == NULL) {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(clnt_oqskex_msg, p, clnt_oqskex_msg_len);
p += clnt_oqskex_msg_len;
}
#endif

/*
* p is pointing to somewhere in the buffer currently, so set it
* to the start
*/
p = (unsigned char *)s->init_buf->data;

/* Compute the shared pre-master secret */
field_size = EC_GROUP_get_degree(group);
Expand All @@ -2777,6 +2828,27 @@ int ssl3_get_client_key_exchange(SSL *s)
EC_KEY_free(s->s3->tmp.ecdh);
s->s3->tmp.ecdh = NULL;

#ifndef OPENSSL_NO_HYBRID_OQSKEX_ECDHE
if (alg_k & SSL_kOQSKEXGENERIC) {
if (OQS_KEX_alice_1(s->s3->tmp.oqskex_kex, s->s3->tmp.oqskex_priv, clnt_oqskex_msg, clnt_oqskex_msg_len, &pprime_oqskex, &nprime_oqskex) != 1) {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(clnt_oqskex_msg);
OQS_KEX_alice_priv_free(s->s3->tmp.oqskex_kex, s->s3->tmp.oqskex_priv);
OQS_KEX_free(s->s3->tmp.oqskex_kex);
OQS_RAND_free(s->s3->tmp.oqskex_rand);
s->s3->tmp.oqskex_priv = NULL;
s->s3->tmp.oqskex_kex = NULL;
s->s3->tmp.oqskex_rand = NULL;

// FIXME: I have no idea if this is safe, as I don't know how big p is, but let's try it anyway for testing purposes.
memcpy(p + i, pprime_oqskex, nprime_oqskex);
i += nprime_oqskex;
OPENSSL_free(pprime_oqskex);
}
#endif

/* Compute the master secret */
s->session->master_key_length =
s->method->ssl3_enc->generate_master_secret(s,
Expand All @@ -2789,7 +2861,7 @@ int ssl3_get_client_key_exchange(SSL *s)
} else
#endif
#ifndef OPENSSL_NO_OQSKEX
if (alg_k & SSL_kOQSKEXGENERIC) {
if ((alg_k & SSL_kOQSKEXGENERIC) && !(alg_k & SSL_kEECDH)) {
int ret = 1;

/* Parse client message */
Expand Down
1 change: 1 addition & 0 deletions ssl/ssl.h
Expand Up @@ -280,6 +280,7 @@ extern "C" {
# define SSL_TXT_EECDH "EECDH"/* same as "kEECDH:-AECDH" */
# define SSL_TXT_ECDHE "ECDHE"/* alias for ECDHE" */
# define SSL_TXT_OQSKEXGENERIC "OQSKEXGENERIC"
# define SSL_TXT_OQSKEXGENERICECDHE "OQSKEXGENERIC-ECDHE"
# define SSL_TXT_AECDH "AECDH"
# define SSL_TXT_ECDSA "ECDSA"
# define SSL_TXT_KRB5 "KRB5"
Expand Down
15 changes: 15 additions & 0 deletions ssl/ssl_ciph.c
Expand Up @@ -297,6 +297,7 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_PSK, 0, SSL_kPSK, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_SRP, 0, SSL_kSRP, 0, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_OQSKEXGENERIC, 0, SSL_kOQSKEXGENERIC, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_OQSKEXGENERICECDHE, 0, SSL_kEECDH|SSL_kOQSKEXGENERIC, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},

/* symmetric encryption aliases */
{0, SSL_TXT_DES, 0, 0, 0, SSL_DES, 0, 0, 0, 0, 0, 0},
Expand Down Expand Up @@ -1033,6 +1034,20 @@ static void ssl_cipher_apply_rule(unsigned long cipher_id,
#endif
if (alg_mkey && !(alg_mkey & cp->algorithm_mkey))
continue;
if ((alg_mkey & SSL_kEECDH) && (alg_mkey ^ SSL_kEECDH)) {
if (!(cp->algorithm_mkey & SSL_kEECDH))
continue;
unsigned long alg_mkey_sans_EECDH = alg_mkey ^ SSL_kEECDH;
if (!(cp->algorithm_mkey & alg_mkey_sans_EECDH))
continue;
}
if ((cp->algorithm_mkey & SSL_kEECDH) && (cp->algorithm_mkey ^ SSL_kEECDH)) {
if (!(alg_mkey & SSL_kEECDH))
continue;
unsigned long cp_alg_mkey_sans_EECDH = cp->algorithm_mkey ^ SSL_kEECDH;
if (!(alg_mkey & cp_alg_mkey_sans_EECDH))
continue;
}
if (alg_auth && !(alg_auth & cp->algorithm_auth))
continue;
if (alg_enc && !(alg_enc & cp->algorithm_enc))
Expand Down
8 changes: 8 additions & 0 deletions ssl/tls1.h
Expand Up @@ -568,6 +568,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
# define TLS1_CK_OQSKEXGENERIC_ECDSA_WITH_AES_128_GCM_SHA256 0x0300FF01
# define TLS1_CK_OQSKEXGENERIC_RSA_WITH_AES_256_GCM_SHA384 0x0300FF02
# define TLS1_CK_OQSKEXGENERIC_ECDSA_WITH_AES_256_GCM_SHA384 0x0300FF03
# define TLS1_CK_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300FF04
# define TLS1_CK_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300FF05
# define TLS1_CK_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300FF06
# define TLS1_CK_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300FF07

/*
* XXX * Backward compatibility alert: + * Older versions of OpenSSL gave
Expand Down Expand Up @@ -724,6 +728,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
# define TLS1_TXT_OQSKEXGENERIC_ECDSA_WITH_AES_128_GCM_SHA256 "OQSKEXGENERIC-ECDSA-AES128-GCM-SHA256"
# define TLS1_TXT_OQSKEXGENERIC_RSA_WITH_AES_256_GCM_SHA384 "OQSKEXGENERIC-RSA-AES256-GCM-SHA384"
# define TLS1_TXT_OQSKEXGENERIC_ECDSA_WITH_AES_256_GCM_SHA384 "OQSKEXGENERIC-ECDSA-AES256-GCM-SHA384"
# define TLS1_TXT_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "OQSKEXGENERIC-ECDHE-RSA-AES128-GCM-SHA256"
# define TLS1_TXT_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "OQSKEXGENERIC-ECDHE-ECDSA-AES128-GCM-SHA256"
# define TLS1_TXT_OQSKEXGENERIC_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "OQSKEXGENERIC-ECDHE-RSA-AES256-GCM-SHA384"
# define TLS1_TXT_OQSKEXGENERIC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "OQSKEXGENERIC-ECDHE-ECDSA-AES256-GCM-SHA384"

# define TLS_CT_RSA_SIGN 1
# define TLS_CT_DSS_SIGN 2
Expand Down

0 comments on commit 58090ad

Please sign in to comment.