Add ECDH/DH utility functions.

Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
Dr. Stephen Henson 2015-12-15 18:15:16 +00:00
parent 44d4f8f2d7
commit 3f3504bdaf
2 changed files with 73 additions and 0 deletions

View file

@ -4985,3 +4985,74 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
s->s3->tmp.pms = NULL;
return s->session->master_key_length >= 0;
}
/* Generate a private key from parameters or a curve NID */
EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm, int nid)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
if (pm != NULL) {
pctx = EVP_PKEY_CTX_new(pm, NULL);
} else {
/* Generate a new key for this curve */
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
}
if (pctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(pctx) <= 0)
goto err;
if (pm == NULL && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0)
goto err;
if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
err:
EVP_PKEY_CTX_free(pctx);
return pkey;
}
/* Derive premaster or master secret for ECDH/DH */
int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey)
{
int rv = 0;
unsigned char *pms = NULL;
size_t pmslen = 0;
EVP_PKEY_CTX *pctx;
if (privkey == NULL || pubkey == NULL)
return 0;
pctx = EVP_PKEY_CTX_new(privkey, NULL);
if (EVP_PKEY_derive_init(pctx) <= 0
|| EVP_PKEY_derive_set_peer(pctx, pubkey) <= 0
|| EVP_PKEY_derive(pctx, NULL, &pmslen) <= 0) {
goto err;
}
pms = OPENSSL_malloc(pmslen);
if (pms == NULL)
goto err;
if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0)
goto err;
if (s->server) {
/* For server generate master secret and discard premaster */
rv = ssl_generate_master_secret(s, pms, pmslen, 1);
pms = NULL;
} else {
/* For client just save premaster secret */
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
pms = NULL;
rv = 1;
}
err:
OPENSSL_clear_free(pms, pmslen);
EVP_PKEY_CTX_free(pctx);
return rv;
}

View file

@ -1870,6 +1870,8 @@ void ssl_load_ciphers(void);
__owur int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);
__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
int free_pms);
__owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm, int nid);
__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey);
__owur const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
__owur int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p);