/*
* Copyright 2007-2021 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 "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>
#define DEFINE_OSSL_CMP_CTX_get0(FIELD, TYPE) \
DEFINE_OSSL_CMP_CTX_get0_NAME(FIELD, FIELD, TYPE)
#define DEFINE_OSSL_CMP_CTX_get0_NAME(NAME, FIELD, TYPE) \
TYPE *OSSL_CMP_CTX_get0_##NAME(const OSSL_CMP_CTX *ctx) \
{ \
if (ctx == NULL) { \
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
return NULL; \
} \
return ctx->FIELD; \
}
/*
* Get current certificate store containing trusted root CA certs
*/
DEFINE_OSSL_CMP_CTX_get0_NAME(trusted, trusted, X509_STORE)
#define DEFINE_OSSL_set0(PREFIX, FIELD, TYPE) \
DEFINE_OSSL_set0_NAME(PREFIX, FIELD, FIELD, TYPE)
#define DEFINE_OSSL_set0_NAME(PREFIX, NAME, FIELD, TYPE) \
int PREFIX##_set0##_##NAME(OSSL_CMP_CTX *ctx, TYPE *val) \
{ \
if (ctx == NULL) { \
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
return 0; \
} \
TYPE##_free(ctx->FIELD); \
ctx->FIELD = val; \
return 1; \
}
/*
* 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.
*/
DEFINE_OSSL_set0_NAME(OSSL_CMP_CTX, trusted, trusted, X509_STORE)
DEFINE_OSSL_CMP_CTX_get0(libctx, OSSL_LIB_CTX)
DEFINE_OSSL_CMP_CTX_get0(propq, const char)
/* Get current list of non-trusted intermediate certs */
DEFINE_OSSL_CMP_CTX_get0(untrusted, STACK_OF(X509))
/*
* 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 = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (!ossl_x509_add_certs_new(&untrusted, certs,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
goto err;
OSSL_STACK_OF_X509_free(ctx->untrusted);
ctx->untrusted = untrusted;
return 1;
err:
OSSL_STACK_OF_X509_free(untrusted);
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 = OSSL_CMP_PKISTATUS_unspecified;
ctx->failInfoCode = -1;
ctx->keep_alive = 1;
ctx->msg_timeout = -1;
if ((ctx->untrusted = sk_X509_new_null()) == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
goto err;
}
ctx->pbm_slen = 16;
if (!cmp_ctx_set_md(ctx, &ctx->pbm_owf, NID_sha256))
goto err;
ctx->pbm_itercnt = 500;
ctx->pbm_mac = NID_hmac_sha1;
if (!cmp_ctx_set_md(ctx, &ctx->digest, NID_sha256))
goto err;
ctx->popoMethod = OSSL_CRMF_POPO_SIGNATURE;
ctx->revocationReason = CRL_REASON_NONE;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
err:
OSSL_CMP_CTX_free(ctx);
return NULL;
}
#define OSSL_CMP_ITAVs_free(itavs) \
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
#define X509_EXTENSIONS_free(exts) \
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free)
#define OSSL_CMP_PKIFREETEXT_free(text) \
sk_ASN1_UTF8STRING_pop_free(text, ASN1_UTF8STRING_free)
/* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX */
int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (ctx->http_ctx != NULL) {
(void)OSSL_HTTP_close(ctx->http_ctx, 1);
ossl_cmp_debug