mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
[ssl] Support ssl_encapsulate on server side
Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/13018)
This commit is contained in:
parent
a011b5861b
commit
8b17fbaf46
@ -1407,6 +1407,7 @@ SSL_F_SSL_DO_CONFIG:391:ssl_do_config
|
||||
SSL_F_SSL_DO_HANDSHAKE:180:SSL_do_handshake
|
||||
SSL_F_SSL_DUP_CA_LIST:408:SSL_dup_CA_list
|
||||
SSL_F_SSL_ENABLE_CT:402:SSL_enable_ct
|
||||
SSL_F_SSL_ENCAPSULATE:644:
|
||||
SSL_F_SSL_GENERATE_PKEY_GROUP:559:ssl_generate_pkey_group
|
||||
SSL_F_SSL_GENERATE_SESSION_ID:547:ssl_generate_session_id
|
||||
SSL_F_SSL_GET_NEW_SESSION:181:ssl_get_new_session
|
||||
|
@ -189,6 +189,7 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_SSL_DO_HANDSHAKE 0
|
||||
# define SSL_F_SSL_DUP_CA_LIST 0
|
||||
# define SSL_F_SSL_ENABLE_CT 0
|
||||
# define SSL_F_SSL_ENCAPSULATE 0
|
||||
# define SSL_F_SSL_GENERATE_PKEY_GROUP 0
|
||||
# define SSL_F_SSL_GENERATE_SESSION_ID 0
|
||||
# define SSL_F_SSL_GET_NEW_SESSION 0
|
||||
|
65
ssl/s3_lib.c
65
ssl/s3_lib.c
@ -4833,7 +4833,6 @@ EVP_PKEY *ssl_generate_param_group(SSL *s, uint16_t id)
|
||||
}
|
||||
|
||||
/* Generate secrets from pms */
|
||||
__owur static
|
||||
int ssl_gensecret(SSL *s, unsigned char *pms, size_t pmslen)
|
||||
{
|
||||
int rv = 0;
|
||||
@ -4973,6 +4972,70 @@ int ssl_decapsulate(SSL *s, EVP_PKEY *privkey,
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ssl_encapsulate(SSL *s, EVP_PKEY *pubkey,
|
||||
unsigned char **ctp, size_t *ctlenp,
|
||||
int gensecret)
|
||||
{
|
||||
int rv = 0;
|
||||
unsigned char *pms = NULL, *ct = NULL;
|
||||
size_t pmslen = 0, ctlen = 0;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
|
||||
if (pubkey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ENCAPSULATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pubkey, s->ctx->propq);
|
||||
|
||||
if (EVP_PKEY_encapsulate_init(pctx) <= 0
|
||||
|| EVP_PKEY_encapsulate(pctx, NULL, &ctlen, NULL, &pmslen) <= 0
|
||||
|| pmslen == 0 || ctlen == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ENCAPSULATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pms = OPENSSL_malloc(pmslen);
|
||||
ct = OPENSSL_malloc(ctlen);
|
||||
if (pms == NULL || ct == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ENCAPSULATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_encapsulate(pctx, ct, &ctlen, pms, &pmslen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ENCAPSULATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (gensecret) {
|
||||
/* SSLfatal() called as appropriate in the below functions */
|
||||
rv = ssl_gensecret(s, pms, pmslen);
|
||||
} else {
|
||||
/* Save premaster secret */
|
||||
s->s3.tmp.pms = pms;
|
||||
s->s3.tmp.pmslen = pmslen;
|
||||
pms = NULL;
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
if (rv > 0) {
|
||||
/* Pass ownership of ct to caller */
|
||||
*ctp = ct;
|
||||
*ctlenp = ctlen;
|
||||
ct = NULL;
|
||||
}
|
||||
|
||||
err:
|
||||
OPENSSL_clear_free(pms, pmslen);
|
||||
OPENSSL_free(ct);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_DH
|
||||
EVP_PKEY *ssl_dh_to_pkey(DH *dh)
|
||||
{
|
||||
|
@ -2454,11 +2454,15 @@ __owur int ssl_fill_hello_random(SSL *s, int server, unsigned char *field,
|
||||
__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
|
||||
int free_pms);
|
||||
__owur EVP_PKEY *ssl_generate_pkey(SSL *s, EVP_PKEY *pm);
|
||||
__owur int ssl_gensecret(SSL *s, unsigned char *pms, size_t pmslen);
|
||||
__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey,
|
||||
int genmaster);
|
||||
__owur int ssl_decapsulate(SSL *s, EVP_PKEY *privkey,
|
||||
const unsigned char *ct, size_t ctlen,
|
||||
int gensecret);
|
||||
__owur int ssl_encapsulate(SSL *s, EVP_PKEY *pubkey,
|
||||
unsigned char **ctp, size_t *ctlenp,
|
||||
int gensecret);
|
||||
__owur EVP_PKEY *ssl_dh_to_pkey(DH *dh);
|
||||
__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl);
|
||||
__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl);
|
||||
|
@ -1696,6 +1696,7 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned char *encodedPoint;
|
||||
size_t encoded_pt_len = 0;
|
||||
EVP_PKEY *ckey = s->s3.peer_tmp, *skey = NULL;
|
||||
const TLS_GROUP_INFO *ginf = NULL;
|
||||
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
if (ckey != NULL) {
|
||||
@ -1733,37 +1734,92 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
skey = ssl_generate_pkey(s, ckey);
|
||||
if (skey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
if ((ginf = tls1_group_id_lookup(s->ctx, s->s3.group_id)) == NULL) {
|
||||
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) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_EC_LIB);
|
||||
EVP_PKEY_free(skey);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
if (!ginf->is_kem) {
|
||||
/* Regular KEX */
|
||||
skey = ssl_generate_pkey(s, ckey);
|
||||
if (skey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(skey);
|
||||
/* Generate encoding of server key */
|
||||
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
|
||||
if (encoded_pt_len == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_EC_LIB);
|
||||
EVP_PKEY_free(skey);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(skey);
|
||||
OPENSSL_free(encodedPoint);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
OPENSSL_free(encodedPoint);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
OPENSSL_free(encodedPoint);
|
||||
|
||||
/* This causes the crypto state to be updated based on the derived keys */
|
||||
s->s3.tmp.pkey = skey;
|
||||
if (ssl_derive(s, skey, ckey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
/*
|
||||
* This causes the crypto state to be updated based on the derived keys
|
||||
*/
|
||||
s->s3.tmp.pkey = skey;
|
||||
if (ssl_derive(s, skey, ckey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
} else {
|
||||
/* KEM mode */
|
||||
unsigned char *ct = NULL;
|
||||
size_t ctlen = 0;
|
||||
|
||||
/*
|
||||
* This does not update the crypto state.
|
||||
*
|
||||
* The generated pms is stored in `s->s3.tmp.pms` to be later used via
|
||||
* ssl_gensecret().
|
||||
*/
|
||||
if (ssl_encapsulate(s, ckey, &ct, &ctlen, 0) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (ctlen == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
OPENSSL_free(ct);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, ct, ctlen)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
OPENSSL_free(ct);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
OPENSSL_free(ct);
|
||||
|
||||
/*
|
||||
* This causes the crypto state to be updated based on the generated pms
|
||||
*/
|
||||
if (ssl_gensecret(s, s->s3.tmp.pms, s->s3.tmp.pmslen) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
return EXT_RETURN_SENT;
|
||||
#else
|
||||
|
Loading…
Reference in New Issue
Block a user