Remove SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER and SSL_OP_TLS_D5_BUG support.
[openssl.git] / ssl / ssl_rsa.c
index d046020..a23b28e 100644 (file)
@@ -79,10 +79,6 @@ int SSL_use_certificate(SSL *ssl, X509 *x)
         return 0;
     }
 
-    if (!ssl_cert_inst(&ssl->cert)) {
-        SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_MALLOC_FAILURE);
-        return (0);
-    }
     return (ssl_set_cert(ssl->cert, x));
 }
 
@@ -94,7 +90,7 @@ int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
     int ret = 0;
     X509 *x = NULL;
 
-    in = BIO_new(BIO_s_file_internal());
+    in = BIO_new(BIO_s_file());
     if (in == NULL) {
         SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
         goto end;
@@ -123,10 +119,8 @@ int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
 
     ret = SSL_use_certificate(ssl, x);
  end:
-    if (x != NULL)
-        X509_free(x);
-    if (in != NULL)
-        BIO_free(in);
+    X509_free(x);
+    BIO_free(in);
     return (ret);
 }
 #endif
@@ -157,17 +151,16 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
         SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
         return (0);
     }
-    if (!ssl_cert_inst(&ssl->cert)) {
-        SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_MALLOC_FAILURE);
-        return (0);
-    }
     if ((pkey = EVP_PKEY_new()) == NULL) {
         SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB);
         return (0);
     }
 
     RSA_up_ref(rsa);
-    EVP_PKEY_assign_RSA(pkey, rsa);
+    if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+        RSA_free(rsa);
+        return 0;
+    }
 
     ret = ssl_set_pkey(ssl->cert, pkey);
     EVP_PKEY_free(pkey);
@@ -178,22 +171,7 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa)
 static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
 {
     int i;
-    /*
-     * Special case for DH: check two DH certificate types for a match. This
-     * means for DH certificates we must set the certificate first.
-     */
-    if (pkey->type == EVP_PKEY_DH) {
-        X509 *x;
-        i = -1;
-        x = c->pkeys[SSL_PKEY_DH_RSA].x509;
-        if (x && X509_check_private_key(x, pkey))
-            i = SSL_PKEY_DH_RSA;
-        x = c->pkeys[SSL_PKEY_DH_DSA].x509;
-        if (i == -1 && x && X509_check_private_key(x, pkey))
-            i = SSL_PKEY_DH_DSA;
-        ERR_clear_error();
-    } else
-        i = ssl_cert_type(NULL, pkey);
+    i = ssl_cert_type(NULL, pkey);
     if (i < 0) {
         SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
         return (0);
@@ -202,6 +180,15 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
     if (c->pkeys[i].x509 != NULL) {
         EVP_PKEY *pktmp;
         pktmp = X509_get_pubkey(c->pkeys[i].x509);
+        if (pktmp == NULL) {
+            SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE);
+            EVP_PKEY_free(pktmp);
+            return 0;
+        }
+        /*
+         * The return code from EVP_PKEY_copy_parameters is deliberately
+         * ignored. Some EVP_PKEY types cannot do this.
+         */
         EVP_PKEY_copy_parameters(pktmp, pkey);
         EVP_PKEY_free(pktmp);
         ERR_clear_error();
@@ -222,13 +209,10 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
         }
     }
 
-    if (c->pkeys[i].privatekey != NULL)
-        EVP_PKEY_free(c->pkeys[i].privatekey);
+    EVP_PKEY_free(c->pkeys[i].privatekey);
     CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
     c->pkeys[i].privatekey = pkey;
     c->key = &(c->pkeys[i]);
-
-    c->valid = 0;
     return (1);
 }
 
@@ -240,7 +224,7 @@ int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
     BIO *in;
     RSA *rsa = NULL;
 
-    in = BIO_new(BIO_s_file_internal());
+    in = BIO_new(BIO_s_file());
     if (in == NULL) {
         SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB);
         goto end;
@@ -270,8 +254,7 @@ int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type)
     ret = SSL_use_RSAPrivateKey(ssl, rsa);
     RSA_free(rsa);
  end:
-    if (in != NULL)
-        BIO_free(in);
+    BIO_free(in);
     return (ret);
 }
 # endif
@@ -302,10 +285,6 @@ int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
         SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
         return (0);
     }
-    if (!ssl_cert_inst(&ssl->cert)) {
-        SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE);
-        return (0);
-    }
     ret = ssl_set_pkey(ssl->cert, pkey);
     return (ret);
 }
@@ -317,7 +296,7 @@ int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
     BIO *in;
     EVP_PKEY *pkey = NULL;
 
-    in = BIO_new(BIO_s_file_internal());
+    in = BIO_new(BIO_s_file());
     if (in == NULL) {
         SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
         goto end;
@@ -347,8 +326,7 @@ int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type)
     ret = SSL_use_PrivateKey(ssl, pkey);
     EVP_PKEY_free(pkey);
  end:
-    if (in != NULL)
-        BIO_free(in);
+    BIO_free(in);
     return (ret);
 }
 #endif
@@ -383,10 +361,6 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, rv);
         return 0;
     }
-    if (!ssl_cert_inst(&ctx->cert)) {
-        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, ERR_R_MALLOC_FAILURE);
-        return (0);
-    }
     return (ssl_set_cert(ctx->cert, x));
 }
 
@@ -409,6 +383,10 @@ static int ssl_set_cert(CERT *c, X509 *x)
     }
 
     if (c->pkeys[i].privatekey != NULL) {
+        /*
+         * The return code from EVP_PKEY_copy_parameters is deliberately
+         * ignored. Some EVP_PKEY types cannot do this.
+         */
         EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey);
         ERR_clear_error();
 
@@ -437,13 +415,11 @@ static int ssl_set_cert(CERT *c, X509 *x)
 
     EVP_PKEY_free(pkey);
 
-    if (c->pkeys[i].x509 != NULL)
-        X509_free(c->pkeys[i].x509);
-    CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+    X509_free(c->pkeys[i].x509);
+    X509_up_ref(x);
     c->pkeys[i].x509 = x;
     c->key = &(c->pkeys[i]);
 
-    c->valid = 0;
     return (1);
 }
 
@@ -455,7 +431,7 @@ int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
     int ret = 0;
     X509 *x = NULL;
 
-    in = BIO_new(BIO_s_file_internal());
+    in = BIO_new(BIO_s_file());
     if (in == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB);
         goto end;
@@ -484,10 +460,8 @@ int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
 
     ret = SSL_CTX_use_certificate(ctx, x);
  end:
-    if (x != NULL)
-        X509_free(x);
-    if (in != NULL)
-        BIO_free(in);
+    X509_free(x);
+    BIO_free(in);
     return (ret);
 }
 #endif
@@ -519,17 +493,16 @@ int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa)
         SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
         return (0);
     }
-    if (!ssl_cert_inst(&ctx->cert)) {
-        SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_MALLOC_FAILURE);
-        return (0);
-    }
     if ((pkey = EVP_PKEY_new()) == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB);
         return (0);
     }
 
     RSA_up_ref(rsa);
-    EVP_PKEY_assign_RSA(pkey, rsa);
+    if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+        RSA_free(rsa);
+        return 0;
+    }
 
     ret = ssl_set_pkey(ctx->cert, pkey);
     EVP_PKEY_free(pkey);
@@ -543,7 +516,7 @@ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
     BIO *in;
     RSA *rsa = NULL;
 
-    in = BIO_new(BIO_s_file_internal());
+    in = BIO_new(BIO_s_file());
     if (in == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB);
         goto end;
@@ -572,8 +545,7 @@ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type)
     ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
     RSA_free(rsa);
  end:
-    if (in != NULL)
-        BIO_free(in);
+    BIO_free(in);
     return (ret);
 }
 # endif
@@ -603,10 +575,6 @@ int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
         SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER);
         return (0);
     }
-    if (!ssl_cert_inst(&ctx->cert)) {
-        SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE);
-        return (0);
-    }
     return (ssl_set_pkey(ctx->cert, pkey));
 }
 
@@ -617,7 +585,7 @@ int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
     BIO *in;
     EVP_PKEY *pkey = NULL;
 
-    in = BIO_new(BIO_s_file_internal());
+    in = BIO_new(BIO_s_file());
     if (in == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
         goto end;
@@ -646,8 +614,7 @@ int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
     ret = SSL_CTX_use_PrivateKey(ctx, pkey);
     EVP_PKEY_free(pkey);
  end:
-    if (in != NULL)
-        BIO_free(in);
+    BIO_free(in);
     return (ret);
 }
 #endif
@@ -676,34 +643,47 @@ int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
  * followed by a sequence of CA certificates that should be sent to the peer
  * in the Certificate message.
  */
-int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
+static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
 {
     BIO *in;
     int ret = 0;
     X509 *x = NULL;
+    pem_password_cb *passwd_callback;
+    void *passwd_callback_userdata;
 
     ERR_clear_error();          /* clear error stack for
                                  * SSL_CTX_use_certificate() */
 
-    in = BIO_new(BIO_s_file_internal());
+    if (ctx != NULL) {
+        passwd_callback = ctx->default_passwd_callback;
+        passwd_callback_userdata = ctx->default_passwd_callback_userdata;
+    } else {
+        passwd_callback = ssl->default_passwd_callback;
+        passwd_callback_userdata = ssl->default_passwd_callback_userdata;
+    }
+
+    in = BIO_new(BIO_s_file());
     if (in == NULL) {
-        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
+        SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
         goto end;
     }
 
     if (BIO_read_filename(in, file) <= 0) {
-        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB);
+        SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB);
         goto end;
     }
 
-    x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
-                              ctx->default_passwd_callback_userdata);
+    x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback,
+                              passwd_callback_userdata);
     if (x == NULL) {
-        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
+        SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
         goto end;
     }
 
-    ret = SSL_CTX_use_certificate(ctx, x);
+    if (ctx)
+        ret = SSL_CTX_use_certificate(ctx, x);
+    else
+        ret = SSL_use_certificate(ssl, x);
 
     if (ERR_peek_error() != 0)
         ret = 0;                /* Key/certificate mismatch doesn't imply
@@ -717,23 +697,33 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
         int r;
         unsigned long err;
 
-        SSL_CTX_clear_chain_certs(ctx);
+        if (ctx)
+            r = SSL_CTX_clear_chain_certs(ctx);
+        else
+            r = SSL_clear_chain_certs(ssl);
+
+        if (r == 0) {
+            ret = 0;
+            goto end;
+        }
 
-        while ((ca = PEM_read_bio_X509(in, NULL,
-                                       ctx->default_passwd_callback,
-                                       ctx->default_passwd_callback_userdata))
-               != NULL) {
-            r = SSL_CTX_add0_chain_cert(ctx, ca);
+        while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
+                                       passwd_callback_userdata))
+                != NULL) {
+            if (ctx)
+                r = SSL_CTX_add0_chain_cert(ctx, ca);
+            else
+                r = SSL_add0_chain_cert(ssl, ca);
+            /*
+             * Note that we must not free ca if it was successfully added to
+             * the chain (while we must free the main certificate, since its
+             * reference count is increased by SSL_CTX_use_certificate).
+             */
             if (!r) {
                 X509_free(ca);
                 ret = 0;
                 goto end;
             }
-            /*
-             * Note that we must not free r if it was successfully added to
-             * the chain (while we must free the main certificate, since its
-             * reference count is increased by SSL_CTX_use_certificate).
-             */
         }
         /* When the while loop ends, it's usually just EOF. */
         err = ERR_peek_last_error();
@@ -745,15 +735,22 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
     }
 
  end:
-    if (x != NULL)
-        X509_free(x);
-    if (in != NULL)
-        BIO_free(in);
+    X509_free(x);
+    BIO_free(in);
     return (ret);
 }
+
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
+{
+    return use_certificate_chain_file(ctx, NULL, file);
+}
+
+int SSL_use_certificate_chain_file(SSL *ssl, const char *file)
+{
+    return use_certificate_chain_file(NULL, ssl, file);
+}
 #endif
 
-#ifndef OPENSSL_NO_TLSEXT
 static int serverinfo_find_extension(const unsigned char *serverinfo,
                                      size_t serverinfo_length,
                                      unsigned int extension_type,
@@ -763,31 +760,31 @@ static int serverinfo_find_extension(const unsigned char *serverinfo,
     *extension_data = NULL;
     *extension_length = 0;
     if (serverinfo == NULL || serverinfo_length == 0)
-        return 0;
+        return -1;
     for (;;) {
         unsigned int type = 0;
         size_t len = 0;
 
         /* end of serverinfo */
         if (serverinfo_length == 0)
-            return -1;          /* Extension not found */
+            return 0;           /* Extension not found */
 
         /* read 2-byte type field */
         if (serverinfo_length < 2)
-            return 0;           /* Error */
+            return -1;          /* Error */
         type = (serverinfo[0] << 8) + serverinfo[1];
         serverinfo += 2;
         serverinfo_length -= 2;
 
         /* read 2-byte len field */
         if (serverinfo_length < 2)
-            return 0;           /* Error */
+            return -1;          /* Error */
         len = (serverinfo[0] << 8) + serverinfo[1];
         serverinfo += 2;
         serverinfo_length -= 2;
 
         if (len > serverinfo_length)
-            return 0;           /* Error */
+            return -1;          /* Error */
 
         if (type == extension_type) {
             *extension_data = serverinfo;
@@ -798,7 +795,7 @@ static int serverinfo_find_extension(const unsigned char *serverinfo,
         serverinfo += len;
         serverinfo_length -= len;
     }
-    return 0;                   /* Error */
+    /* Unreachable */
 }
 
 static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type,
@@ -827,10 +824,12 @@ static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type,
         /* Find the relevant extension from the serverinfo */
         int retval = serverinfo_find_extension(serverinfo, serverinfo_length,
                                                ext_type, out, outlen);
+        if (retval == -1) {
+            *al = SSL_AD_DECODE_ERROR;
+            return -1;          /* Error */
+        }
         if (retval == 0)
-            return 0;           /* Error */
-        if (retval == -1)
-            return -1;          /* No extension found, don't send extension */
+            return 0;           /* No extension found, don't send extension */
         return 1;               /* Send extension */
     }
     return -1;                  /* No serverinfo data found, don't send
@@ -900,10 +899,6 @@ int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
         SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA);
         return 0;
     }
-    if (!ssl_cert_inst(&ctx->cert)) {
-        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_MALLOC_FAILURE);
-        return 0;
-    }
     if (ctx->cert->key == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_INTERNAL_ERROR);
         return 0;
@@ -929,7 +924,6 @@ int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
     return 1;
 }
 
-# ifndef OPENSSL_NO_STDIO
 int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
 {
     unsigned char *serverinfo = NULL;
@@ -949,7 +943,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
         goto end;
     }
 
-    bin = BIO_new(BIO_s_file_internal());
+    bin = BIO_new(BIO_s_file());
     if (bin == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB);
         goto end;
@@ -1016,9 +1010,6 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
     OPENSSL_free(header);
     OPENSSL_free(extension);
     OPENSSL_free(serverinfo);
-    if (bin != NULL)
-        BIO_free(bin);
+    BIO_free(bin);
     return ret;
 }
-# endif                         /* OPENSSL_NO_STDIO */
-#endif                          /* OPENSSL_NO_TLSEXT */