summaryrefslogtreecommitdiffstats
path: root/ssl/s3_lib.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2015-12-15 18:15:16 +0000
committerDr. Stephen Henson <steve@openssl.org>2015-12-16 14:17:53 +0000
commit3f3504bdaf4f43971a1e584b566d7a5281a33c43 (patch)
treee70b94cf9be77eec9e648210d3ae392a191f6039 /ssl/s3_lib.c
parent44d4f8f2d761d919fd6267cce112dad36590879f (diff)
Add ECDH/DH utility functions.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Diffstat (limited to 'ssl/s3_lib.c')
-rw-r--r--ssl/s3_lib.c71
1 files changed, 71 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;
+}