/*
* Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
* 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/trace.h>
#include <openssl/bio.h>
#include <openssl/ocsp.h> /* for OCSP_REVOKED_STATUS_* */
#include "crypto/x509.h" /* for x509v3_cache_extensions() */
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/cmp.h>
#include <openssl/crmf.h>
#include <openssl/err.h>
/*
* Get current certificate store containing trusted root CA certs
*/
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->trusted;
}
/*
* Set certificate store containing trusted (root) CA certs and possibly CRLs
* and a cert verification callback function used for CMP server authentication.
* Any already existing store entry is freed. Given NULL, the entry is reset.
*/
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
X509_STORE_free(ctx->trusted);
ctx->trusted = store;
return 1;
}
/* Get current list of non-trusted intermediate certs */
STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->untrusted;
}
/*
* Set untrusted certificates for path construction in authentication of
* the CMP server and potentially others (TLS server, newly enrolled cert).
*/
int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
{
STACK_OF(X509) *untrusted;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if ((untrusted = sk_X509_new_null()) == NULL)
return 0;
if (X509_add_certs(untrusted, certs,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP) != 1)
goto err;
sk_X509_pop_free(ctx->untrusted, X509_free);
ctx->untrusted = untrusted;
return 1;
err:
sk_X509_pop_free(untrusted, X509_free);
return 0;
}
static int cmp_ctx_set_md(OSSL_CMP_CTX *ctx, EVP_MD **pmd, int nid)
{
EVP_MD *md = EVP_MD_fetch(ctx->libctx, OBJ_nid2sn(nid), ctx->propq);
/* fetching in advance to be able to throw error early if unsupported */
if (md == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
EVP_MD_free(*pmd);
*pmd = md;
return 1;
}
/*
* Allocates and initializes OSSL_CMP_CTX context structure with default values.
* Returns new context on success, NULL on error
*/
OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
{
OSSL_CMP_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL)
goto err;
ctx->libctx = libctx;
if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)
goto err;
ctx->log_verbosity = OSSL_CMP_LOG_INFO;
ctx->status = -1;
ctx->failInfoCode =