mirror of
https://github.com/openssl/openssl.git
synced 2025-04-12 20:30:52 +08:00
[ssl] Support ssl_decapsulate on client side
Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/13018)
This commit is contained in:
parent
c1a74f59ac
commit
a011b5861b
@ -1401,6 +1401,7 @@ SSL_F_SSL_CTX_USE_SERVERINFO_EX:543:SSL_CTX_use_serverinfo_ex
|
||||
SSL_F_SSL_CTX_USE_SERVERINFO_FILE:337:SSL_CTX_use_serverinfo_file
|
||||
SSL_F_SSL_DANE_DUP:403:ssl_dane_dup
|
||||
SSL_F_SSL_DANE_ENABLE:395:SSL_dane_enable
|
||||
SSL_F_SSL_DECAPSULATE:643:
|
||||
SSL_F_SSL_DERIVE:590:ssl_derive
|
||||
SSL_F_SSL_DO_CONFIG:391:ssl_do_config
|
||||
SSL_F_SSL_DO_HANDSHAKE:180:SSL_do_handshake
|
||||
|
@ -183,6 +183,7 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_SSL_CTX_USE_SERVERINFO_FILE 0
|
||||
# define SSL_F_SSL_DANE_DUP 0
|
||||
# define SSL_F_SSL_DANE_ENABLE 0
|
||||
# define SSL_F_SSL_DECAPSULATE 0
|
||||
# define SSL_F_SSL_DERIVE 0
|
||||
# define SSL_F_SSL_DO_CONFIG 0
|
||||
# define SSL_F_SSL_DO_HANDSHAKE 0
|
||||
|
97
ssl/s3_lib.c
97
ssl/s3_lib.c
@ -4832,6 +4832,33 @@ EVP_PKEY *ssl_generate_param_group(SSL *s, uint16_t id)
|
||||
return pkey;
|
||||
}
|
||||
|
||||
/* Generate secrets from pms */
|
||||
__owur static
|
||||
int ssl_gensecret(SSL *s, unsigned char *pms, size_t pmslen)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
/* SSLfatal() called as appropriate in the below functions */
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/*
|
||||
* If we are resuming then we already generated the early secret
|
||||
* when we created the ClientHello, so don't recreate it.
|
||||
*/
|
||||
if (!s->hit)
|
||||
rv = tls13_generate_secret(s, ssl_handshake_md(s), NULL, NULL,
|
||||
0,
|
||||
(unsigned char *)&s->early_secret);
|
||||
else
|
||||
rv = 1;
|
||||
|
||||
rv = rv && tls13_generate_handshake_secret(s, pms, pmslen);
|
||||
} else {
|
||||
rv = ssl_generate_master_secret(s, pms, pmslen, 0);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Derive secrets for ECDH/DH */
|
||||
int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
|
||||
{
|
||||
@ -4876,22 +4903,62 @@ int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
|
||||
|
||||
if (gensecret) {
|
||||
/* SSLfatal() called as appropriate in the below functions */
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/*
|
||||
* If we are resuming then we already generated the early secret
|
||||
* when we created the ClientHello, so don't recreate it.
|
||||
*/
|
||||
if (!s->hit)
|
||||
rv = tls13_generate_secret(s, ssl_handshake_md(s), NULL, NULL,
|
||||
0,
|
||||
(unsigned char *)&s->early_secret);
|
||||
else
|
||||
rv = 1;
|
||||
rv = ssl_gensecret(s, pms, pmslen);
|
||||
} else {
|
||||
/* Save premaster secret */
|
||||
s->s3.tmp.pms = pms;
|
||||
s->s3.tmp.pmslen = pmslen;
|
||||
pms = NULL;
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
rv = rv && tls13_generate_handshake_secret(s, pms, pmslen);
|
||||
} else {
|
||||
rv = ssl_generate_master_secret(s, pms, pmslen, 0);
|
||||
}
|
||||
err:
|
||||
OPENSSL_clear_free(pms, pmslen);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Decapsulate secrets for KEM */
|
||||
int ssl_decapsulate(SSL *s, EVP_PKEY *privkey,
|
||||
const unsigned char *ct, size_t ctlen,
|
||||
int gensecret)
|
||||
{
|
||||
int rv = 0;
|
||||
unsigned char *pms = NULL;
|
||||
size_t pmslen = 0;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
|
||||
if (privkey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DECAPSULATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, privkey, s->ctx->propq);
|
||||
|
||||
if (EVP_PKEY_decapsulate_init(pctx) <= 0
|
||||
|| EVP_PKEY_decapsulate(pctx, NULL, &pmslen, ct, ctlen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DECAPSULATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pms = OPENSSL_malloc(pmslen);
|
||||
if (pms == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DECAPSULATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_decapsulate(pctx, pms, &pmslen, ct, ctlen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DECAPSULATE,
|
||||
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;
|
||||
|
@ -2456,6 +2456,9 @@ __owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
|
||||
__owur EVP_PKEY *ssl_generate_pkey(SSL *s, EVP_PKEY *pm);
|
||||
__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 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);
|
||||
|
@ -1830,6 +1830,7 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
unsigned int group_id;
|
||||
PACKET encoded_pt;
|
||||
EVP_PKEY *ckey = s->s3.tmp.pkey, *skey = NULL;
|
||||
const TLS_GROUP_INFO *ginf = NULL;
|
||||
|
||||
/* Sanity check */
|
||||
if (ckey == NULL || s->s3.peer_tmp != NULL) {
|
||||
@ -1893,6 +1894,12 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ginf = tls1_group_id_lookup(s->ctx, group_id)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_BAD_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
|
||||
|| PACKET_remaining(&encoded_pt) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
@ -1900,27 +1907,39 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
return 0;
|
||||
}
|
||||
|
||||
skey = EVP_PKEY_new();
|
||||
if (skey == NULL || EVP_PKEY_copy_parameters(skey, ckey) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_COPY_PARAMETERS_FAILED);
|
||||
return 0;
|
||||
}
|
||||
if (!ginf->is_kem) {
|
||||
/* Regular KEX */
|
||||
skey = EVP_PKEY_new();
|
||||
if (skey == NULL || EVP_PKEY_copy_parameters(skey, ckey) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_COPY_PARAMETERS_FAILED);
|
||||
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,
|
||||
SSL_R_BAD_ECPOINT);
|
||||
EVP_PKEY_free(skey);
|
||||
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,
|
||||
SSL_R_BAD_ECPOINT);
|
||||
EVP_PKEY_free(skey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ssl_derive(s, ckey, skey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
EVP_PKEY_free(skey);
|
||||
return 0;
|
||||
if (ssl_derive(s, ckey, skey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
EVP_PKEY_free(skey);
|
||||
return 0;
|
||||
}
|
||||
s->s3.peer_tmp = skey;
|
||||
} else {
|
||||
/* KEM Mode */
|
||||
const unsigned char *ct = PACKET_data(&encoded_pt);
|
||||
size_t ctlen = PACKET_remaining(&encoded_pt);
|
||||
|
||||
if (ssl_decapsulate(s, ckey, ct, ctlen, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
s->s3.peer_tmp = skey;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user