diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2015-12-15 18:15:16 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2015-12-16 14:17:53 +0000 |
commit | 3f3504bdaf4f43971a1e584b566d7a5281a33c43 (patch) | |
tree | e70b94cf9be77eec9e648210d3ae392a191f6039 /ssl | |
parent | 44d4f8f2d761d919fd6267cce112dad36590879f (diff) |
Add ECDH/DH utility functions.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/s3_lib.c | 71 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 2 |
2 files changed, 73 insertions, 0 deletions
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index fd101285c4..4585c9ef0a 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -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; +} diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index b161387b71..6323ddd717 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -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); |