diff options
author | Nicola Tuveri <nic.tuv@gmail.com> | 2020-09-28 04:32:03 +0300 |
---|---|---|
committer | Nicola Tuveri <nic.tuv@gmail.com> | 2020-10-14 18:42:59 +0300 |
commit | 8b17fbaf46ae8a1319be5975ad8da3e0f4932e77 (patch) | |
tree | 811bba9ea6a476e61615163eee67a1574848f589 /ssl/s3_lib.c | |
parent | a011b5861b545b40df3c6f111df4fbde74cd7c82 (diff) |
[ssl] Support ssl_encapsulate on server side
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13018)
Diffstat (limited to 'ssl/s3_lib.c')
-rw-r--r-- | ssl/s3_lib.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 96569ae0bd..1fd424a52e 100644 --- a/ssl/s3_lib.c +++ b/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) { |