Latest update (add quic)
This commit is contained in:
+43
-1
@@ -56,6 +56,10 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent);
|
||||
static int final_early_data(SSL *s, unsigned int context, int sent);
|
||||
static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
|
||||
static int init_post_handshake_auth(SSL *s, unsigned int context);
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
static int init_quic_transport_params(SSL *s, unsigned int context);
|
||||
static int final_quic_transport_params(SSL *s, unsigned int context, int sent);
|
||||
#endif
|
||||
|
||||
/* Structure to define a built-in extension */
|
||||
typedef struct extensions_definition_st {
|
||||
@@ -374,6 +378,19 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
tls_construct_certificate_authorities,
|
||||
tls_construct_certificate_authorities, NULL,
|
||||
},
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
{
|
||||
TLSEXT_TYPE_quic_transport_parameters,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
| SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
|
||||
init_quic_transport_params,
|
||||
tls_parse_ctos_quic_transport_params, tls_parse_stoc_quic_transport_params,
|
||||
tls_construct_stoc_quic_transport_params, tls_construct_ctos_quic_transport_params,
|
||||
final_quic_transport_params,
|
||||
},
|
||||
#else
|
||||
INVALID_EXTENSION,
|
||||
#endif
|
||||
{
|
||||
/* Must be immediately before pre_shared_key */
|
||||
TLSEXT_TYPE_padding,
|
||||
@@ -1169,13 +1186,26 @@ static int init_etm(SSL *s, unsigned int context)
|
||||
|
||||
static int init_ems(SSL *s, unsigned int context)
|
||||
{
|
||||
s->s3.flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
|
||||
if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) {
|
||||
s->s3.flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
|
||||
s->s3.flags |= TLS1_FLAGS_REQUIRED_EXTMS;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int final_ems(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
/*
|
||||
* Check extended master secret extension is not dropped on
|
||||
* renegotiation.
|
||||
*/
|
||||
if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)
|
||||
&& (s->s3.flags & TLS1_FLAGS_REQUIRED_EXTMS)) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
|
||||
SSL_R_INCONSISTENT_EXTMS);
|
||||
return 0;
|
||||
}
|
||||
if (!s->server && s->hit) {
|
||||
/*
|
||||
* Check extended master secret extension is consistent with
|
||||
@@ -1701,3 +1731,15 @@ static int init_post_handshake_auth(SSL *s, unsigned int context)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
static int init_quic_transport_params(SSL *s, unsigned int context)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int final_quic_transport_params(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -648,21 +648,6 @@ static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(key_share_key);
|
||||
if (EVP_PKEY_id(key_share_key) == EVP_PKEY_NONE) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
|
||||
ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode the public key. */
|
||||
@@ -1273,7 +1258,28 @@ EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/* SAME AS tls_construct_stoc_quic_transport_params() */
|
||||
EXT_RETURN tls_construct_ctos_quic_transport_params(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (s->ext.quic_transport_params == NULL
|
||||
|| s->ext.quic_transport_params_len == 0) {
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_quic_transport_parameters)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.quic_transport_params,
|
||||
s->ext.quic_transport_params_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Parse the server's renegotiation binding and abort if it's not right
|
||||
*/
|
||||
@@ -1926,22 +1932,6 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(skey);
|
||||
if (EVP_PKEY_id(skey) == EVP_PKEY_NONE) {
|
||||
EVP_PKEY_free(skey);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
|
||||
PACKET_remaining(&encoded_pt))) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
@@ -1990,6 +1980,18 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/*
|
||||
* QUIC server must send 0xFFFFFFFF or it's a PROTOCOL_VIOLATION
|
||||
* per draft-ietf-quic-tls-24 S4.5
|
||||
*/
|
||||
if (s->quic_method != NULL && max_early_data != 0xFFFFFFFF) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
|
||||
SSL_R_INVALID_MAX_EARLY_DATA);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
s->session->ext.max_early_data = max_early_data;
|
||||
|
||||
return 1;
|
||||
@@ -2077,3 +2079,22 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
|
||||
return 1;
|
||||
}
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/* SAME AS tls_parse_ctos_quic_transport_params() */
|
||||
int tls_parse_stoc_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
OPENSSL_free(s->ext.peer_quic_transport_params);
|
||||
s->ext.peer_quic_transport_params = NULL;
|
||||
s->ext.peer_quic_transport_params_len = 0;
|
||||
|
||||
if (!PACKET_memdup(pkt,
|
||||
&s->ext.peer_quic_transport_params,
|
||||
&s->ext.peer_quic_transport_params_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -715,21 +715,6 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(s->s3.peer_tmp);
|
||||
if (EVP_PKEY_id(s->s3.peer_tmp) == EVP_PKEY_NONE) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3.group_id = group_id;
|
||||
|
||||
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3.peer_tmp,
|
||||
@@ -1326,6 +1311,26 @@ int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/* SAME AS tls_parse_stoc_quic_transport_params() */
|
||||
int tls_parse_ctos_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
OPENSSL_free(s->ext.peer_quic_transport_params);
|
||||
s->ext.peer_quic_transport_params = NULL;
|
||||
s->ext.peer_quic_transport_params_len = 0;
|
||||
|
||||
if (!PACKET_memdup(pkt,
|
||||
&s->ext.peer_quic_transport_params,
|
||||
&s->ext.peer_quic_transport_params_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add the server's renegotiation binding
|
||||
*/
|
||||
@@ -1647,7 +1652,9 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
if (s->s3.tmp.new_cipher->algorithm_mac == SSL_AEAD
|
||||
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_RC4
|
||||
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
|
||||
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
|
||||
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12
|
||||
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_MAGMA
|
||||
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_KUZNYECHIK) {
|
||||
s->ext.use_etm = 0;
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
@@ -1754,21 +1761,6 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(skey);
|
||||
if (EVP_PKEY_id(skey) == EVP_PKEY_NONE) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/* Generate encoding of server key */
|
||||
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
|
||||
if (encoded_pt_len == 0) {
|
||||
@@ -1966,12 +1958,20 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
|
||||
if (s->max_early_data == 0)
|
||||
uint32_t max_early_data = s->max_early_data;
|
||||
|
||||
if (max_early_data == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/* QUIC server must always send 0xFFFFFFFF, per draft-ietf-quic-tls-24 S4.5 */
|
||||
if (s->quic_method != NULL)
|
||||
max_early_data = 0xFFFFFFFF;
|
||||
#endif
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u32(pkt, s->max_early_data)
|
||||
|| !WPACKET_put_bytes_u32(pkt, max_early_data)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
|
||||
@@ -2012,3 +2012,26 @@ EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/* SAME AS tls_construct_ctos_quic_transport_params() */
|
||||
EXT_RETURN tls_construct_stoc_quic_transport_params(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (s->ext.quic_transport_params == NULL
|
||||
|| s->ext.quic_transport_params_len == 0) {
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_quic_transport_parameters)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.quic_transport_params,
|
||||
s->ext.quic_transport_params_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
+18
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -576,6 +576,10 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
* In DTLS we get the whole message in one go - header and body
|
||||
*/
|
||||
ret = dtls_get_message(s, &mt, &len);
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
} else if (SSL_IS_QUIC(s)) {
|
||||
ret = quic_get_message(s, &mt, &len);
|
||||
#endif
|
||||
} else {
|
||||
ret = tls_get_message_header(s, &mt);
|
||||
}
|
||||
@@ -605,8 +609,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
/* dtls_get_message already did this */
|
||||
if (!SSL_IS_DTLS(s)
|
||||
/* dtls_get_message/quic_get_message already did this */
|
||||
if (!SSL_IS_DTLS(s) && !SSL_IS_QUIC(s)
|
||||
&& s->s3.tmp.message_size > 0
|
||||
&& !grow_init_buf(s, s->s3.tmp.message_size
|
||||
+ SSL3_HM_HEADER_LENGTH)) {
|
||||
@@ -619,8 +623,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
/* Fall through */
|
||||
|
||||
case READ_STATE_BODY:
|
||||
if (!SSL_IS_DTLS(s)) {
|
||||
/* We already got this above for DTLS */
|
||||
if (!SSL_IS_DTLS(s) && !SSL_IS_QUIC(s)) {
|
||||
/* We already got this above for DTLS & QUIC */
|
||||
ret = tls_get_message_body(s, &len);
|
||||
if (ret == 0) {
|
||||
/* Could be non-blocking IO */
|
||||
@@ -901,6 +905,15 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
int statem_flush(SSL *s)
|
||||
{
|
||||
s->rwstate = SSL_WRITING;
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
if (SSL_IS_QUIC(s)) {
|
||||
if (!s->quic_method->flush_flight(s)) {
|
||||
/* NOTE: BIO_flush() does not generate an error */
|
||||
SSLerr(SSL_F_STATEM_FLUSH, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (BIO_flush(s->wbio) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+149
-30
@@ -914,6 +914,14 @@ int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_END_OF_EARLY_DATA:
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
/* QUIC does not send EndOfEarlyData, draft-ietf-quic-tls-24 S8.3 */
|
||||
if (s->quic_method != NULL) {
|
||||
*confunc = NULL;
|
||||
*mt = SSL3_MT_DUMMY;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
*confunc = tls_construct_end_of_early_data;
|
||||
*mt = SSL3_MT_END_OF_EARLY_DATA;
|
||||
break;
|
||||
@@ -2231,21 +2239,6 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(s->s3.peer_tmp);
|
||||
if (EVP_PKEY_id(s->s3.peer_tmp) == EVP_PKEY_NONE) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3.peer_tmp,
|
||||
PACKET_data(&encoded_pt),
|
||||
PACKET_remaining(&encoded_pt))) {
|
||||
@@ -3148,21 +3141,6 @@ static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(ckey);
|
||||
if (EVP_PKEY_id(skey) == EVP_PKEY_NONE) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ssl_derive(s, ckey, skey, 0) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
@@ -3314,6 +3292,144 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
int gost18_cke_cipher_nid(const SSL *s)
|
||||
{
|
||||
if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_MAGMA) != 0)
|
||||
return NID_magma_ctr;
|
||||
else if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_KUZNYECHIK) != 0)
|
||||
return NID_kuznyechik_ctr;
|
||||
|
||||
return NID_undef;
|
||||
}
|
||||
|
||||
int gost_ukm(const SSL *s, unsigned char *dgst_buf)
|
||||
{
|
||||
EVP_MD_CTX * hash = NULL;
|
||||
unsigned int md_len;
|
||||
const EVP_MD *md = EVP_get_digestbynid(NID_id_GostR3411_2012_256);
|
||||
|
||||
if (md == NULL)
|
||||
return 0;
|
||||
|
||||
if ((hash = EVP_MD_CTX_new()) == NULL
|
||||
|| EVP_DigestInit(hash, md) <= 0
|
||||
|| EVP_DigestUpdate(hash, s->s3.client_random, SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_DigestUpdate(hash, s->s3.server_random, SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_DigestFinal_ex(hash, dgst_buf, &md_len) <= 0) {
|
||||
EVP_MD_CTX_free(hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(hash);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tls_construct_cke_gost18(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
/* GOST 2018 key exchange message creation */
|
||||
unsigned char rnd_dgst[32], tmp[255];
|
||||
EVP_PKEY_CTX *pkey_ctx = NULL;
|
||||
X509 *peer_cert;
|
||||
unsigned char *pms = NULL;
|
||||
size_t pmslen = 0;
|
||||
size_t msglen;
|
||||
int cipher_nid = gost18_cke_cipher_nid(s);
|
||||
|
||||
if (cipher_nid == NID_undef) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gost_ukm(s, rnd_dgst) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Pre-master secret - random bytes */
|
||||
pmslen = 32;
|
||||
pms = OPENSSL_malloc(pmslen);
|
||||
if (pms == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (RAND_bytes_ex(s->ctx->libctx, pms, (int)pmslen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get server certificate PKEY and create ctx from it */
|
||||
peer_cert = s->session->peer;
|
||||
if (peer_cert == NULL) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, X509_get0_pubkey(peer_cert), s->ctx->propq);
|
||||
if (pkey_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 ) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
};
|
||||
|
||||
/* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code */
|
||||
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
|
||||
EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
|
||||
EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
msglen = 255;
|
||||
if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!WPACKET_memcpy(pkt, tmp, msglen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX_free(pkey_ctx);
|
||||
s->s3.tmp.pms = pms;
|
||||
s->s3.tmp.pmslen = pmslen;
|
||||
|
||||
return 1;
|
||||
err:
|
||||
EVP_PKEY_CTX_free(pkey_ctx);
|
||||
OPENSSL_clear_free(pms, pmslen);
|
||||
return 0;
|
||||
#else
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
@@ -3370,6 +3486,9 @@ int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
|
||||
} else if (alg_k & SSL_kGOST) {
|
||||
if (!tls_construct_cke_gost(s, pkt))
|
||||
goto err;
|
||||
} else if (alg_k & SSL_kGOST18) {
|
||||
if (!tls_construct_cke_gost18(s, pkt))
|
||||
goto err;
|
||||
} else if (alg_k & SSL_kSRP) {
|
||||
if (!tls_construct_cke_srp(s, pkt))
|
||||
goto err;
|
||||
|
||||
+17
-2
@@ -48,9 +48,23 @@ int ssl3_do_write(SSL *s, int type)
|
||||
{
|
||||
int ret;
|
||||
size_t written = 0;
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
if (SSL_IS_QUIC(s) && type == SSL3_RT_HANDSHAKE) {
|
||||
ret = s->quic_method->add_handshake_data(s, s->quic_write_level,
|
||||
(const uint8_t*)&s->init_buf->data[s->init_off],
|
||||
s->init_num);
|
||||
if (!ret) {
|
||||
ret = -1;
|
||||
/* QUIC can't sent anything out sice the above failed */
|
||||
SSLerr(SSL_F_SSL3_DO_WRITE, SSL_R_INTERNAL_ERROR);
|
||||
} else {
|
||||
written = s->init_num;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
|
||||
s->init_num, &written);
|
||||
|
||||
ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
|
||||
s->init_num, &written);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
if (type == SSL3_RT_HANDSHAKE)
|
||||
@@ -1183,6 +1197,7 @@ int tls_get_message_header(SSL *s, int *mt)
|
||||
|
||||
do {
|
||||
while (s->init_num < SSL3_HM_HEADER_LENGTH) {
|
||||
/* QUIC: either create a special ssl_read_bytes... or if/else this */
|
||||
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
|
||||
&p[s->init_num],
|
||||
SSL3_HM_HEADER_LENGTH - s->init_num,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -93,6 +93,7 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
|
||||
__owur int tls_get_message_header(SSL *s, int *mt);
|
||||
__owur int tls_get_message_body(SSL *s, size_t *len);
|
||||
__owur int dtls_get_message(SSL *s, int *mt, size_t *len);
|
||||
__owur int quic_get_message(SSL *s, int *mt, size_t *len);
|
||||
|
||||
/* Message construction and processing functions */
|
||||
__owur int tls_process_initial_server_flight(SSL *s);
|
||||
@@ -153,6 +154,11 @@ __owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
|
||||
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
|
||||
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
|
||||
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
/* These functions are used in GOST18 CKE, both for client and server */
|
||||
int gost18_cke_cipher_nid(const SSL *s);
|
||||
int gost_ukm(const SSL *s, unsigned char *dgst_buf);
|
||||
#endif
|
||||
|
||||
/* Extension processing */
|
||||
|
||||
@@ -236,6 +242,10 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
int tls_parse_ctos_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
@@ -298,6 +308,11 @@ EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
EXT_RETURN tls_construct_stoc_quic_transport_params(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
|
||||
/* Client Extension processing */
|
||||
EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
@@ -369,6 +384,11 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
EXT_RETURN tls_construct_ctos_quic_transport_params(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
|
||||
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
@@ -414,6 +434,10 @@ int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
int tls_parse_stoc_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
|
||||
int tls_handle_alpn(SSL *s);
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "../ssl_local.h"
|
||||
#include "statem_local.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#ifdef OPENSSL_NO_QUIC
|
||||
NON_EMPTY_TRANSLATION_UNIT
|
||||
#else
|
||||
|
||||
int quic_get_message(SSL *s, int *mt, size_t *len)
|
||||
{
|
||||
size_t l;
|
||||
QUIC_DATA *qd = s->quic_input_data_head;
|
||||
uint8_t *p;
|
||||
|
||||
if (qd == NULL || (qd->length - qd->offset) != 0) {
|
||||
s->rwstate = SSL_READING;
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is where we check for the proper level, not when data is given */
|
||||
if (qd->level != s->quic_read_level) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_GET_MESSAGE,
|
||||
SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED);
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BUF_MEM_grow_clean(s->init_buf, (int)qd->length)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_GET_MESSAGE,
|
||||
ERR_R_BUF_LIB);
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy buffered data */
|
||||
memcpy(s->init_buf->data, (void*)(qd + 1), qd->length);
|
||||
s->init_buf->length = qd->length;
|
||||
s->quic_input_data_head = qd->next;
|
||||
if (s->quic_input_data_head == NULL)
|
||||
s->quic_input_data_tail = NULL;
|
||||
OPENSSL_free(qd);
|
||||
|
||||
s->s3.tmp.message_type = *mt = *(s->init_buf->data);
|
||||
p = (uint8_t*)s->init_buf->data + 1;
|
||||
n2l3(p, l);
|
||||
s->init_num = s->s3.tmp.message_size = *len = l;
|
||||
s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
|
||||
|
||||
/* No CCS in QUIC/TLSv1.3? */
|
||||
if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_QUIC_GET_MESSAGE,
|
||||
SSL_R_CCS_RECEIVED_EARLY);
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If receiving Finished, record MAC of prior handshake messages for
|
||||
* Finished verification.
|
||||
*/
|
||||
if (*mt == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
|
||||
/* SSLfatal() already called */
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We defer feeding in the HRR until later. We'll do it as part of
|
||||
* processing the message
|
||||
* The TLsv1.3 handshake transcript stops at the ClientFinished
|
||||
* message.
|
||||
*/
|
||||
#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
|
||||
/* KeyUpdate and NewSessionTicket do not need to be added */
|
||||
if (!SSL_IS_TLS13(s) || (s->s3.tmp.message_type != SSL3_MT_NEWSESSION_TICKET
|
||||
&& s->s3.tmp.message_type != SSL3_MT_KEY_UPDATE)) {
|
||||
if (s->s3.tmp.message_type != SSL3_MT_SERVER_HELLO
|
||||
|| s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
|
||||
|| memcmp(hrrrandom,
|
||||
s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
|
||||
SSL3_RANDOM_SIZE) != 0) {
|
||||
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
|
||||
s->init_num + SSL3_HM_HEADER_LENGTH)) {
|
||||
/* SSLfatal() already called */
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
|
||||
(size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s,
|
||||
s->msg_callback_arg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
+94
-30
@@ -77,7 +77,8 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
|
||||
} else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
|
||||
&& !SSL_IS_QUIC(s)) {
|
||||
if (mt == SSL3_MT_END_OF_EARLY_DATA) {
|
||||
st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
|
||||
return 1;
|
||||
@@ -2637,20 +2638,6 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(s->s3.tmp.pkey);
|
||||
if (EVP_PKEY_id(s->s3.tmp.pkey) == EVP_PKEY_NONE) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 0, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Encode the public key. */
|
||||
encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3.tmp.pkey,
|
||||
&encodedPoint);
|
||||
@@ -3235,21 +3222,6 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
|
||||
* knows how to get a key from an encoded point with the help of
|
||||
* a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
|
||||
* downgrades an EVP_PKEY to contain a legacy key.
|
||||
*
|
||||
* THIS IS TEMPORARY
|
||||
*/
|
||||
EVP_PKEY_get0(ckey);
|
||||
if (EVP_PKEY_id(ckey) == EVP_PKEY_NONE) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
|
||||
ERR_R_EC_LIB);
|
||||
@@ -3431,6 +3403,93 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_cke_gost18(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
unsigned char rnd_dgst[32];
|
||||
EVP_PKEY_CTX *pkey_ctx = NULL;
|
||||
EVP_PKEY *pk = NULL;
|
||||
unsigned char premaster_secret[32];
|
||||
const unsigned char *start = NULL;
|
||||
size_t outlen = 32, inlen = 0;
|
||||
int ret = 0;
|
||||
int cipher_nid = gost18_cke_cipher_nid(s);
|
||||
|
||||
if (cipher_nid == NID_undef) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gost_ukm(s, rnd_dgst) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get our certificate private key */
|
||||
pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey != NULL ?
|
||||
s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey :
|
||||
s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
|
||||
if (pk == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
|
||||
SSL_R_BAD_HANDSHAKE_STATE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pk, s->ctx->propq);
|
||||
if (pkey_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code depending on size */
|
||||
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
|
||||
EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
|
||||
EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
inlen = PACKET_remaining(pkt);
|
||||
start = PACKET_data(pkt);
|
||||
|
||||
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
|
||||
SSL_R_DECRYPTION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
/* Generate master secret */
|
||||
if (!ssl_generate_master_secret(s, premaster_secret,
|
||||
sizeof(premaster_secret), 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EVP_PKEY_CTX_free(pkey_ctx);
|
||||
return ret;
|
||||
#else
|
||||
/* Should never happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
|
||||
{
|
||||
unsigned long alg_k;
|
||||
@@ -3481,6 +3540,11 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & SSL_kGOST18) {
|
||||
if (!tls_process_cke_gost18(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
|
||||
Reference in New Issue
Block a user