Add ECDH/DH utility functions.
[openssl.git] / ssl / s3_lib.c
index 24cf5f03225a9fc9fe2d08c0d320eb3234f0c003..4585c9ef0aee0f466701b7f2f13f08c0a63ee2a1 100644 (file)
@@ -245,22 +245,6 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      },
 #endif
 
      },
 #endif
 
-/* Cipher 09 */
-    {
-     1,
-     SSL3_TXT_RSA_DES_64_CBC_SHA,
-     SSL3_CK_RSA_DES_64_CBC_SHA,
-     SSL_kRSA,
-     SSL_aRSA,
-     SSL_DES,
-     SSL_SHA1,
-     SSL_SSLV3,
-     SSL_NOT_DEFAULT | SSL_LOW,
-     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
-     56,
-     56,
-     },
-
 /* Cipher 0A */
     {
      1,
 /* Cipher 0A */
     {
      1,
@@ -277,22 +261,6 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      168,
      },
 
      168,
      },
 
-/* Cipher 0C */
-    {
-     1,
-     SSL3_TXT_DH_DSS_DES_64_CBC_SHA,
-     SSL3_CK_DH_DSS_DES_64_CBC_SHA,
-     SSL_kDHd,
-     SSL_aDH,
-     SSL_DES,
-     SSL_SHA1,
-     SSL_SSLV3,
-     SSL_NOT_DEFAULT | SSL_LOW,
-     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
-     56,
-     56,
-     },
-
 /* Cipher 0D */
     {
      1,
 /* Cipher 0D */
     {
      1,
@@ -309,22 +277,6 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      168,
      },
 
      168,
      },
 
-/* Cipher 0F */
-    {
-     1,
-     SSL3_TXT_DH_RSA_DES_64_CBC_SHA,
-     SSL3_CK_DH_RSA_DES_64_CBC_SHA,
-     SSL_kDHr,
-     SSL_aDH,
-     SSL_DES,
-     SSL_SHA1,
-     SSL_SSLV3,
-     SSL_NOT_DEFAULT | SSL_LOW,
-     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
-     56,
-     56,
-     },
-
 /* Cipher 10 */
     {
      1,
 /* Cipher 10 */
     {
      1,
@@ -341,22 +293,6 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      168,
      },
 
      168,
      },
 
-/* Cipher 12 */
-    {
-     1,
-     SSL3_TXT_DHE_DSS_DES_64_CBC_SHA,
-     SSL3_CK_DHE_DSS_DES_64_CBC_SHA,
-     SSL_kDHE,
-     SSL_aDSS,
-     SSL_DES,
-     SSL_SHA1,
-     SSL_SSLV3,
-     SSL_NOT_DEFAULT | SSL_LOW,
-     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
-     56,
-     56,
-     },
-
 /* Cipher 13 */
     {
      1,
 /* Cipher 13 */
     {
      1,
@@ -373,22 +309,6 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      168,
      },
 
      168,
      },
 
-/* Cipher 15 */
-    {
-     1,
-     SSL3_TXT_DHE_RSA_DES_64_CBC_SHA,
-     SSL3_CK_DHE_RSA_DES_64_CBC_SHA,
-     SSL_kDHE,
-     SSL_aRSA,
-     SSL_DES,
-     SSL_SHA1,
-     SSL_SSLV3,
-     SSL_NOT_DEFAULT | SSL_LOW,
-     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
-     56,
-     56,
-     },
-
 /* Cipher 16 */
     {
      1,
 /* Cipher 16 */
     {
      1,
@@ -421,22 +341,6 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      128,
      },
 
      128,
      },
 
-/* Cipher 1A */
-    {
-     1,
-     SSL3_TXT_ADH_DES_64_CBC_SHA,
-     SSL3_CK_ADH_DES_64_CBC_SHA,
-     SSL_kDHE,
-     SSL_aNULL,
-     SSL_DES,
-     SSL_SHA1,
-     SSL_SSLV3,
-     SSL_NOT_DEFAULT | SSL_LOW,
-     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
-     56,
-     56,
-     },
-
 /* Cipher 1B */
     {
      1,
 /* Cipher 1B */
     {
      1,
@@ -3623,6 +3527,119 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      256,
      256,
      },
      256,
      256,
      },
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+# ifndef OPENSSL_NO_EC
+    /* Cipher CCA8 as per draft-ietf-tls-chacha20-poly1305-03 */
+    {
+     1,
+     TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+     SSL_kECDHE,
+     SSL_aRSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCA9 */
+    {
+     1,
+     TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+     SSL_kECDHE,
+     SSL_aECDSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+# endif
+# ifndef OPENSSL_NO_RSA
+    /* Cipher CCAA */
+    {
+     1,
+     TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305,
+     SSL_kDHE,
+     SSL_aRSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+# endif
+# ifndef OPENSSL_NO_PSK
+    /* Cipher CCAB */
+    {
+     1,
+     TLS1_TXT_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCAC */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCAD */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCAE */
+    {
+     1,
+     TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kRSAPSK,
+     SSL_aRSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+# endif
+#endif
 #ifndef OPENSSL_NO_GOST
     {
      1,
 #ifndef OPENSSL_NO_GOST
     {
      1,
@@ -4233,16 +4250,14 @@ long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void))
 
 long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
 {
 
 long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
 {
-    CERT *cert;
-
-    cert = ctx->cert;
-
     switch (cmd) {
 #ifndef OPENSSL_NO_DH
     case SSL_CTRL_SET_TMP_DH:
         {
             DH *new = NULL, *dh;
     switch (cmd) {
 #ifndef OPENSSL_NO_DH
     case SSL_CTRL_SET_TMP_DH:
         {
             DH *new = NULL, *dh;
+            CERT *cert;
 
 
+            cert = ctx->cert;
             dh = (DH *)parg;
             if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
                                   DH_security_bits(dh), 0, dh)) {
             dh = (DH *)parg;
             if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
                                   DH_security_bits(dh), 0, dh)) {
@@ -4447,15 +4462,11 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
 
 long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
 {
 
 long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
 {
-    CERT *cert;
-
-    cert = ctx->cert;
-
     switch (cmd) {
 #ifndef OPENSSL_NO_DH
     case SSL_CTRL_SET_TMP_DH_CB:
         {
     switch (cmd) {
 #ifndef OPENSSL_NO_DH
     case SSL_CTRL_SET_TMP_DH_CB:
         {
-            cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
+            ctx->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
         }
         break;
 #endif
         }
         break;
 #endif
@@ -4711,14 +4722,8 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
         p[ret++] = SSL3_CT_DSS_SIGN;
 #endif
 #ifndef OPENSSL_NO_EC
         p[ret++] = SSL3_CT_DSS_SIGN;
 #endif
 #ifndef OPENSSL_NO_EC
-    if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->version >= TLS1_VERSION)) {
-        if (nostrict || !(alg_a & SSL_aRSA))
-            p[ret++] = TLS_CT_RSA_FIXED_ECDH;
-        if (nostrict || !(alg_a & SSL_aECDSA))
-            p[ret++] = TLS_CT_ECDSA_FIXED_ECDH;
-    }
     /*
     /*
-     * ECDSA certs can be used with RSA cipher suites as well so we don't
+     * ECDSA certs can be used with RSA cipher suites too so we don't
      * need to check for SSL_kECDH or SSL_kECDHE
      */
     if (s->version >= TLS1_VERSION) {
      * need to check for SSL_kECDH or SSL_kECDHE
      */
     if (s->version >= TLS1_VERSION) {
@@ -4980,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;
 }
         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;
+}