core/asn1/x509_thread_safe.c (286 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "x509_thread_safe.h"
#ifdef X509_ENABLE_CREATE_CERTIFICATES
int x509_thread_safe_create_csr (const struct x509_engine *engine, const uint8_t *priv_key,
size_t key_length, enum hash_type sig_hash, const char *name, int type, const uint8_t *eku,
size_t eku_length, const struct x509_extension_builder *const *extra_extensions,
size_t ext_count, uint8_t **csr, size_t *csr_length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->create_csr (x509->engine, priv_key, key_length, sig_hash, name, type,
eku, eku_length, extra_extensions, ext_count, csr, csr_length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_create_self_signed_certificate (const struct x509_engine *engine,
struct x509_certificate *cert, const uint8_t *priv_key, size_t key_length,
enum hash_type sig_hash, const uint8_t *serial_num, size_t serial_length, const char *name,
int type, const struct x509_extension_builder *const *extra_extensions, size_t ext_count)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->create_self_signed_certificate (x509->engine, cert, priv_key, key_length,
sig_hash, serial_num, serial_length, name, type, extra_extensions, ext_count);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_create_ca_signed_certificate (const struct x509_engine *engine,
struct x509_certificate *cert, const uint8_t *key, size_t key_length, const uint8_t *serial_num,
size_t serial_length, const char *name, int type, const uint8_t *ca_priv_key,
size_t ca_key_length, enum hash_type sig_hash, const struct x509_certificate *ca_cert,
const struct x509_extension_builder *const *extra_extensions, size_t ext_count)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->create_ca_signed_certificate (x509->engine, cert, key, key_length,
serial_num, serial_length, name, type, ca_priv_key, ca_key_length, sig_hash, ca_cert,
extra_extensions, ext_count);
platform_mutex_unlock (&x509->state->lock);
return status;
}
#endif
int x509_thread_safe_load_certificate (const struct x509_engine *engine,
struct x509_certificate *cert, const uint8_t *der, size_t length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->load_certificate (x509->engine, cert, der, length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
void x509_thread_safe_release_certificate (const struct x509_engine *engine,
struct x509_certificate *cert)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
if (engine == NULL) {
return;
}
platform_mutex_lock (&x509->state->lock);
x509->engine->release_certificate (x509->engine, cert);
platform_mutex_unlock (&x509->state->lock);
}
#ifdef X509_ENABLE_CREATE_CERTIFICATES
int x509_thread_safe_get_certificate_der (const struct x509_engine *engine,
const struct x509_certificate *cert, uint8_t **der, size_t *length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->get_certificate_der (x509->engine, cert, der, length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
#endif
#ifdef X509_ENABLE_AUTHENTICATION
int x509_thread_safe_get_certificate_version (const struct x509_engine *engine,
const struct x509_certificate *cert)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->get_certificate_version (x509->engine, cert);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_get_serial_number (const struct x509_engine *engine,
const struct x509_certificate *cert, uint8_t *serial_num, size_t length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->get_serial_number (x509->engine, cert, serial_num, length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_get_public_key_type (const struct x509_engine *engine,
const struct x509_certificate *cert)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->get_public_key_type (x509->engine, cert);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_get_public_key_length (const struct x509_engine *engine,
const struct x509_certificate *cert)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->get_public_key_length (x509->engine, cert);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_get_public_key (const struct x509_engine *engine,
const struct x509_certificate *cert, uint8_t **key, size_t *key_length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->get_public_key (x509->engine, cert, key, key_length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_init_ca_cert_store (const struct x509_engine *engine,
struct x509_ca_certs *store)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->init_ca_cert_store (x509->engine, store);
platform_mutex_unlock (&x509->state->lock);
return status;
}
void x509_thread_safe_release_ca_cert_store (const struct x509_engine *engine,
struct x509_ca_certs *store)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
if (engine == NULL) {
return;
}
platform_mutex_lock (&x509->state->lock);
x509->engine->release_ca_cert_store (x509->engine, store);
platform_mutex_unlock (&x509->state->lock);
}
int x509_thread_safe_add_root_ca (const struct x509_engine *engine, struct x509_ca_certs *store,
const uint8_t *der, size_t length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->add_root_ca (x509->engine, store, der, length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_add_trusted_ca (const struct x509_engine *engine, struct x509_ca_certs *store,
const uint8_t *der, size_t length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->add_trusted_ca (x509->engine, store, der, length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_add_intermediate_ca (const struct x509_engine *engine,
struct x509_ca_certs *store, const uint8_t *der, size_t length)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->add_intermediate_ca (x509->engine, store, der, length);
platform_mutex_unlock (&x509->state->lock);
return status;
}
int x509_thread_safe_authenticate (const struct x509_engine *engine,
const struct x509_certificate *cert, const struct x509_ca_certs *store)
{
const struct x509_engine_thread_safe *x509 = (const struct x509_engine_thread_safe*) engine;
int status;
if (engine == NULL) {
return X509_ENGINE_INVALID_ARGUMENT;
}
platform_mutex_lock (&x509->state->lock);
status = x509->engine->authenticate (x509->engine, cert, store);
platform_mutex_unlock (&x509->state->lock);
return status;
}
#endif
/**
* Initialize a thread-safe wrapper for a Base64 engine.
*
* @param engine The thread-safe engine to initialize.
* @param state Variable context for the thread-safe engine This must be uninitialized.
* @param target The target engine that will be used to execute operations.
*
* @return 0 if the engine was successfully initialized or an error code.
*/
int x509_thread_safe_init (struct x509_engine_thread_safe *engine,
struct x509_engine_thread_safe_state *state, const struct x509_engine *target)
{
if ((engine == NULL) || (state == NULL) || (target == NULL)) {
return X509_ENGINE_INVALID_ARGUMENT;
}
memset (engine, 0, sizeof (struct x509_engine_thread_safe));
#ifdef X509_ENABLE_CREATE_CERTIFICATES
engine->base.create_csr = x509_thread_safe_create_csr;
engine->base.create_self_signed_certificate = x509_thread_safe_create_self_signed_certificate;
engine->base.create_ca_signed_certificate = x509_thread_safe_create_ca_signed_certificate;
#endif
engine->base.load_certificate = x509_thread_safe_load_certificate;
engine->base.release_certificate = x509_thread_safe_release_certificate;
#ifdef X509_ENABLE_CREATE_CERTIFICATES
engine->base.get_certificate_der = x509_thread_safe_get_certificate_der;
#endif
#ifdef X509_ENABLE_AUTHENTICATION
engine->base.get_certificate_version = x509_thread_safe_get_certificate_version;
engine->base.get_serial_number = x509_thread_safe_get_serial_number;
engine->base.get_public_key_type = x509_thread_safe_get_public_key_type;
engine->base.get_public_key_length = x509_thread_safe_get_public_key_length;
engine->base.get_public_key = x509_thread_safe_get_public_key;
engine->base.init_ca_cert_store = x509_thread_safe_init_ca_cert_store;
engine->base.release_ca_cert_store = x509_thread_safe_release_ca_cert_store;
engine->base.add_root_ca = x509_thread_safe_add_root_ca;
engine->base.add_trusted_ca = x509_thread_safe_add_trusted_ca;
engine->base.add_intermediate_ca = x509_thread_safe_add_intermediate_ca;
engine->base.authenticate = x509_thread_safe_authenticate;
#endif
engine->state = state;
engine->engine = target;
return x509_thread_safe_init_state (engine);
}
/**
* Initialize only the variable state of thread-state X.509 engine wrapper. The rest of the
* instance is assumed to already have been initialized.
*
* This would generally be used with a statically initialized instance.
*
* @param engine The X.509 engine that contains the state to initialize.
*
* @return 0 if the state was successfully initialized or an error code.
*/
int x509_thread_safe_init_state (const struct x509_engine_thread_safe *engine)
{
if ((engine == NULL) || (engine->state == NULL) || (engine->engine == NULL)) {
return X509_ENGINE_INVALID_ARGUMENT;
}
memset (engine->state, 0, sizeof (*engine->state));
return platform_mutex_init (&engine->state->lock);
}
/**
* Release the resources used for a thread-safe Base64 wrapper.
*
* @param engine The thread-safe engine to release.
*/
void x509_thread_safe_release (const struct x509_engine_thread_safe *engine)
{
if (engine != NULL) {
platform_mutex_free (&engine->state->lock);
}
}