Issue #719:
[openssl.git] / ssl / ssl_rsa.c
index a02230d0f1b14ab839470faeba0837fef749e6cc..34632bbe2d3d89399285e48ca28ca6834c9dade7 100644 (file)
@@ -1,4 +1,3 @@
-/* ssl/ssl_rsa.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -196,8 +195,8 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
          * Don't check the public/private key, this is mostly for smart
          * cards.
          */
-        if ((pkey->type == EVP_PKEY_RSA) &&
-            (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ;
+        if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA
+            && RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK);
         else
 #endif
         if (!X509_check_private_key(c->pkeys[i].x509, pkey)) {
@@ -208,7 +207,7 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
     }
 
     EVP_PKEY_free(c->pkeys[i].privatekey);
-    CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+    EVP_PKEY_up_ref(pkey);
     c->pkeys[i].privatekey = pkey;
     c->key = &(c->pkeys[i]);
     return (1);
@@ -378,7 +377,12 @@ static int ssl_set_cert(CERT *c, X509 *x)
         SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
         return 0;
     }
-
+#ifndef OPENSSL_NO_EC
+    if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) {
+        SSLerr(SSL_F_SSL_SET_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+        return 0;
+    }
+#endif
     if (c->pkeys[i].privatekey != NULL) {
         /*
          * The return code from EVP_PKEY_copy_parameters is deliberately
@@ -392,9 +396,9 @@ static int ssl_set_cert(CERT *c, X509 *x)
          * Don't check the public/private key, this is mostly for smart
          * cards.
          */
-        if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) &&
-            (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) &
-             RSA_METHOD_FLAG_NO_CHECK)) ;
+        if (EVP_PKEY_id(c->pkeys[i].privatekey) == EVP_PKEY_RSA
+            && RSA_flags(EVP_PKEY_get0_RSA(c->pkeys[i].privatekey)) &
+               RSA_METHOD_FLAG_NO_CHECK) ;
         else
 #endif                          /* OPENSSL_NO_RSA */
         if (!X509_check_private_key(x, c->pkeys[i].privatekey)) {
@@ -827,7 +831,7 @@ static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type,
             return 0;           /* No extension found, don't send extension */
         return 1;               /* Send extension */
     }
-    return -1;                  /* No serverinfo data found, don't send
+    return 0;                   /* No serverinfo data found, don't send
                                  * extension */
 }
 
@@ -856,12 +860,27 @@ static int serverinfo_process_buffer(const unsigned char *serverinfo,
 
         /* Register callbacks for extensions */
         ext_type = (serverinfo[0] << 8) + serverinfo[1];
-        if (ctx && !SSL_CTX_add_server_custom_ext(ctx, ext_type,
-                                                  serverinfo_srv_add_cb,
-                                                  NULL, NULL,
-                                                  serverinfo_srv_parse_cb,
-                                                  NULL))
-            return 0;
+        if (ctx) {
+            int have_ext_cbs = 0;
+            size_t i;
+            custom_ext_methods *exts = &ctx->cert->srv_ext;
+            custom_ext_method *meth = exts->meths;
+
+            /* check for existing callbacks for this extension */
+            for (i = 0; i < exts->meths_count; i++, meth++) {
+                if (ext_type == meth->ext_type) {
+                    have_ext_cbs = 1;
+                    break;
+                }
+            }
+
+            if (!have_ext_cbs && !SSL_CTX_add_server_custom_ext(ctx, ext_type,
+                                                                serverinfo_srv_add_cb,
+                                                                NULL, NULL,
+                                                                serverinfo_srv_parse_cb,
+                                                                NULL))
+                return 0;
+        }
 
         serverinfo += 2;
         serverinfo_length -= 2;