/*
* Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core.h>
#include <openssl/core_numbers.h>
#include <openssl/core_names.h>
#include <openssl/provider.h>
#include <openssl/params.h>
#include <openssl/opensslv.h>
#include "crypto/cryptlib.h"
#include "internal/nelem.h"
#include "internal/thread_once.h"
#include "internal/provider.h"
#include "internal/refcount.h"
#include "provider_local.h"
#ifndef FIPS_MODULE
# include <openssl/self_test.h>
#endif
static OSSL_PROVIDER *provider_new(const char *name,
OSSL_provider_init_fn *init_function);
/*-
* Provider Object structure
* =========================
*/
typedef struct {
char *name;
char *value;
} INFOPAIR;
DEFINE_STACK_OF(INFOPAIR)
struct provider_store_st; /* Forward declaration */
struct ossl_provider_st {
/* Flag bits */
unsigned int flag_initialized:1;
unsigned int flag_fallback:1;
/* OpenSSL library side data */
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *refcnt_lock; /* For the ref counter */
char *name;
char *path;
DSO *module;
OSSL_provider_init_fn *init_function;
STACK_OF(INFOPAIR) *parameters;
OPENSSL_CTX *libctx; /* The library context this instance is in */
struct provider_store_st *store; /* The store this instance belongs to */
#ifndef FIPS_MODULE
/*
* In the FIPS module inner provider, this isn't needed, since the
* error upcalls are always direct calls to the outer provider.
*/
int error_lib; /* ERR library number, one for each provider */
# ifndef OPENSSL_NO_ERR
ERR_STRING_DATA *error_strings; /* Copy of what the provider gives us */
# endif
#endif
/* Provider side functions */
OSSL_provider_teardown_fn *teardown;
OSSL_provider_gettable_params_fn *gettable_params;
OSSL_provider_get_params_fn *get_params;
OSSL_provider_query_operation_fn *query_operation;
/*
* Cache of bit to indicate of query_operation() has been called on
* a specific operation or not.
*/
unsigned char *operation_bits;
size_t operation_bits_sz;
/* Provider side data */
void *provctx;
};
DEFINE_STACK_OF(OSSL_PROVIDER)
static int ossl_provider_cmp(const OSSL_PROVIDER * const *a,
const OSSL_PROVIDER * const *b)
{
return strcmp((*a)->name, (*b)->name);
}
/*-
* Provider Object store
* =====================
*
* The Provider Object store is a library context object, and therefore needs
* an index.
*/
struct provider_store_st {
STACK_OF(OSSL_PROVIDER) *providers;
CRYPTO_RWLOCK *lock;
char *default_path;
unsigned int use_fallbacks:1;
};
static void provider_store_free(void *vstore)
{
struct provider_store_st *store = vstore;
if (store == NULL)
return;
OPENSSL_free(store->default_path);
sk_OSSL_PROVIDER_pop_free(store->providers, ossl_provider_free);
CRYPTO_THREAD_lock_free(store->lock);
OPENSSL_free(store);
}
static void *provider_store_new(OPENSSL_CTX *ctx)
{
struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store));
const struct predefined_providers_st *p = NULL;
if (store == NULL
|| (store->providers = sk_OSSL_PROVIDER_new(ossl_provider_cmp)) == NULL
|| (store->lock = CRYPTO_THREAD_lock_new()) == NULL) {
provider_store_free(store);
return NULL;
}
store->use_fallbacks = 1;
for (p = predefined_providers; p->name != NULL; p++) {
OSSL_PROVIDER *prov = NULL;
/*
* We use the internal constructor directly here,
* otherwise we get a call loop
*/
prov = provider_new(p->name, p->init);
if (prov == NULL
|| sk_OSSL_PROVIDER_push(store->providers, prov) == 0) {
ossl_provider_free(prov);
provider_store_free(store);
CRYPTOerr(CRYPTO_F_PROVIDER_STORE_NEW, ERR_R_INTERNAL_ERROR);
return NULL;
}
prov->libctx = ctx;
prov->store = store;
#ifndef FIPS_MODULE
prov->error_lib =