/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * ECC cipher suite support in OpenSSL originally developed by
- * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
- */
-
#include <stdio.h>
+#include <sys/types.h>
-#include "e_os.h"
-#ifndef NO_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
+#include "internal/nelem.h"
#include "internal/o_dir.h"
-#include <openssl/lhash.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
+#include "internal/refcount.h"
#include "ssl_locl.h"
+#include "ssl_cert_table.h"
#include "internal/thread_once.h"
static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
if (c == NULL)
return;
-
CRYPTO_DOWN_REF(&c->references, &i, c->lock);
REF_PRINT_COUNT("CERT", c);
if (i > 0)
STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
{
int i;
+ const int num = sk_X509_NAME_num(sk);
STACK_OF(X509_NAME) *ret;
X509_NAME *name;
- ret = sk_X509_NAME_new_null();
+ ret = sk_X509_NAME_new_reserve(NULL, num);
if (ret == NULL) {
SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
return NULL;
}
- for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ for (i = 0; i < num; i++) {
name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
- if (name == NULL || !sk_X509_NAME_push(ret, name)) {
+ if (name == NULL) {
+ SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
sk_X509_NAME_pop_free(ret, X509_NAME_free);
- X509_NAME_free(name);
return NULL;
}
+ sk_X509_NAME_push(ret, name); /* Cannot fail after reserve call */
}
- return (ret);
+ return ret;
}
void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
{
- SSL_CTX_set0_CA_list(ctx, name_list);
+ set0_CA_list(&ctx->client_ca_names, name_list);
}
STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
{
- return ctx->ca_names;
+ return ctx->client_ca_names;
}
void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
{
- SSL_set0_CA_list(s, name_list);
+ set0_CA_list(&s->client_ca_names, name_list);
}
const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s)
{
if (!s->server)
return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL;
- return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names;
+ return s->client_ca_names != NULL ? s->client_ca_names
+ : s->ctx->client_ca_names;
}
static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x)
return 1;
}
-int SSL_add1_CA_list(SSL *ssl, const X509 *x)
+int SSL_add1_to_CA_list(SSL *ssl, const X509 *x)
{
return add_ca_name(&ssl->ca_names, x);
}
-int SSL_CTX_add1_CA_list(SSL_CTX *ctx, const X509 *x)
+int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x)
{
return add_ca_name(&ctx->ca_names, x);
}
+/*
+ * The following two are older names are to be replaced with
+ * SSL(_CTX)_add1_to_CA_list
+ */
int SSL_add_client_CA(SSL *ssl, X509 *x)
{
- return add_ca_name(&ssl->ca_names, x);
+ return add_ca_name(&ssl->client_ca_names, x);
}
int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
{
- return add_ca_name(&ctx->ca_names, x);
+ return add_ca_name(&ctx->client_ca_names, x);
}
-static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
+static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
{
- return (X509_NAME_cmp(*a, *b));
+ unsigned char *abuf = NULL, *bbuf = NULL;
+ int alen, blen, ret;
+
+ /* X509_NAME_cmp() itself casts away constness in this way, so
+ * assume it's safe:
+ */
+ alen = i2d_X509_NAME((X509_NAME *)a, &abuf);
+ blen = i2d_X509_NAME((X509_NAME *)b, &bbuf);
+
+ if (alen < 0 || blen < 0)
+ ret = -2;
+ else if (alen != blen)
+ ret = alen - blen;
+ else /* alen == blen */
+ ret = memcmp(abuf, bbuf, alen);
+
+ OPENSSL_free(abuf);
+ OPENSSL_free(bbuf);
+
+ return ret;
}
-static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
+static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
{
- return X509_NAME_cmp(a, b);
+ return xname_cmp(*a, *b);
}
static unsigned long xname_hash(const X509_NAME *a)
lh_X509_NAME_free(name_hash);
if (ret != NULL)
ERR_clear_error();
- return (ret);
+ return ret;
}
/**
char buf[1024];
int r;
- if (strlen(dir) + strlen(filename) + 2 > sizeof buf) {
+ if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,
SSL_R_PATH_TOO_LONG);
goto err;
}
#ifdef OPENSSL_SYS_VMS
- r = BIO_snprintf(buf, sizeof buf, "%s%s", dir, filename);
+ r = BIO_snprintf(buf, sizeof(buf), "%s%s", dir, filename);
#else
- r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename);
+ r = BIO_snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
#endif
if (r <= 0 || r >= (int)sizeof(buf))
goto err;
STACK_OF(X509) *chain = NULL, *untrusted = NULL;
X509 *x;
int i, rv = 0;
- unsigned long error;
if (!cpk->x509) {
SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
goto err;
for (i = 0; i < sk_X509_num(cpk->chain); i++) {
x = sk_X509_value(cpk->chain, i);
- if (!X509_STORE_add_cert(chain_store, x)) {
- error = ERR_peek_last_error();
- if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
- ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
- goto err;
- ERR_clear_error();
- }
- }
- /* Add EE cert too: it might be self signed */
- if (!X509_STORE_add_cert(chain_store, cpk->x509)) {
- error = ERR_peek_last_error();
- if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
- ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
+ if (!X509_STORE_add_cert(chain_store, x))
goto err;
- ERR_clear_error();
}
+ /* Add EE cert too: it might be self signed */
+ if (!X509_STORE_add_cert(chain_store, cpk->x509))
+ goto err;
} else {
if (c->chain_store)
chain_store = c->chain_store;
if (level >= 2 && c->algorithm_enc == SSL_RC4)
return 0;
/* Level 3: forward secure ciphersuites only */
- if (level >= 3 && !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)))
+ if (level >= 3 && c->min_tls != TLS1_3_VERSION &&
+ !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)))
return 0;
break;
}
return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other,
ctx->cert->sec_ex);
}
+
+int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
+ if (ssl_cert_info[i].nid == nid) {
+ *pidx = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
+{
+ int nid = EVP_PKEY_id(pk);
+ size_t tmpidx;
+
+ if (nid == NID_undef)
+ return NULL;
+
+ if (!ssl_cert_lookup_by_nid(nid, &tmpidx))
+ return NULL;
+
+ if (pidx != NULL)
+ *pidx = tmpidx;
+
+ return &ssl_cert_info[tmpidx];
+}
+
+const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
+{
+ if (idx >= OSSL_NELEM(ssl_cert_info))
+ return NULL;
+ return &ssl_cert_info[idx];
+}