Latest update.
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]= cmp_asn.c cmp_err.c
|
||||
SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c
|
||||
+24
-4
@@ -7,13 +7,11 @@
|
||||
* 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
|
||||
*
|
||||
* CMP implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
|
||||
*/
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
#include "cmp_int.h"
|
||||
#include "cmp_local.h"
|
||||
|
||||
/* explicit #includes not strictly needed since implied by the above: */
|
||||
#include <openssl/cmp.h>
|
||||
@@ -166,8 +164,10 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
|
||||
{
|
||||
int created = 0;
|
||||
|
||||
if (itav_sk_p == NULL)
|
||||
if (itav_sk_p == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (*itav_sk_p == NULL) {
|
||||
if ((*itav_sk_p = sk_OSSL_CMP_ITAV_new_null()) == NULL)
|
||||
@@ -187,6 +187,26 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get ASN.1 encoded integer, return -1 on error */
|
||||
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
|
||||
{
|
||||
int64_t res;
|
||||
|
||||
if (!ASN1_INTEGER_get_int64(&res, a)) {
|
||||
CMPerr(0, ASN1_R_INVALID_NUMBER);
|
||||
return -1;
|
||||
}
|
||||
if (res < INT_MIN) {
|
||||
CMPerr(0, ASN1_R_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
if (res > INT_MAX) {
|
||||
CMPerr(0, ASN1_R_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
ASN1_CHOICE(OSSL_CMP_CERTORENCCERT) = {
|
||||
/* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
|
||||
ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.certificate, X509, 0),
|
||||
|
||||
@@ -0,0 +1,1086 @@
|
||||
/*
|
||||
* Copyright 2007-2019 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>
|
||||
|
||||
/*
|
||||
* Get current certificate store containing trusted root CA certs
|
||||
*/
|
||||
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, 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.
|
||||
* returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, 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_certs(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
return ctx->untrusted_certs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set untrusted certificates for path construction in authentication of
|
||||
* the CMP server and potentially others (TLS server, newly enrolled cert).
|
||||
* returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set1_untrusted_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
sk_X509_pop_free(ctx->untrusted_certs, X509_free);
|
||||
if ((ctx->untrusted_certs = sk_X509_new_null()) == NULL)
|
||||
return 0;
|
||||
return ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, certs, 0, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(void)
|
||||
{
|
||||
OSSL_CMP_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx->log_verbosity = OSSL_CMP_LOG_INFO;
|
||||
|
||||
ctx->status = -1;
|
||||
ctx->failInfoCode = -1;
|
||||
|
||||
ctx->serverPort = OSSL_CMP_DEFAULT_PORT;
|
||||
ctx->proxyPort = OSSL_CMP_DEFAULT_PORT;
|
||||
ctx->msgtimeout = 2 * 60;
|
||||
|
||||
if ((ctx->untrusted_certs = sk_X509_new_null()) == NULL)
|
||||
goto err;
|
||||
|
||||
ctx->pbm_slen = 16;
|
||||
ctx->pbm_owf = NID_sha256;
|
||||
ctx->pbm_itercnt = 500;
|
||||
ctx->pbm_mac = NID_hmac_sha1;
|
||||
|
||||
ctx->digest = NID_sha256;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->status = -1;
|
||||
ctx->failInfoCode = -1;
|
||||
|
||||
return ossl_cmp_ctx_set0_statusString(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set0_newCert(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set1_caPubs(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL)
|
||||
&& OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
|
||||
&& OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)
|
||||
&& ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new()
|
||||
*/
|
||||
void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
OPENSSL_free(ctx->serverPath);
|
||||
OPENSSL_free(ctx->serverName);
|
||||
OPENSSL_free(ctx->proxyName);
|
||||
|
||||
X509_free(ctx->srvCert);
|
||||
X509_free(ctx->validatedSrvCert);
|
||||
X509_NAME_free(ctx->expected_sender);
|
||||
X509_STORE_free(ctx->trusted);
|
||||
sk_X509_pop_free(ctx->untrusted_certs, X509_free);
|
||||
|
||||
X509_free(ctx->clCert);
|
||||
EVP_PKEY_free(ctx->pkey);
|
||||
ASN1_OCTET_STRING_free(ctx->referenceValue);
|
||||
if (ctx->secretValue != NULL)
|
||||
OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
|
||||
ASN1_OCTET_STRING_free(ctx->secretValue);
|
||||
|
||||
X509_NAME_free(ctx->recipient);
|
||||
ASN1_OCTET_STRING_free(ctx->transactionID);
|
||||
ASN1_OCTET_STRING_free(ctx->senderNonce);
|
||||
ASN1_OCTET_STRING_free(ctx->recipNonce);
|
||||
sk_OSSL_CMP_ITAV_pop_free(ctx->geninfo_ITAVs, OSSL_CMP_ITAV_free);
|
||||
sk_X509_pop_free(ctx->extraCertsOut, X509_free);
|
||||
|
||||
EVP_PKEY_free(ctx->newPkey);
|
||||
X509_NAME_free(ctx->issuer);
|
||||
X509_NAME_free(ctx->subjectName);
|
||||
sk_GENERAL_NAME_pop_free(ctx->subjectAltNames, GENERAL_NAME_free);
|
||||
sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
|
||||
sk_POLICYINFO_pop_free(ctx->policies, POLICYINFO_free);
|
||||
X509_free(ctx->oldCert);
|
||||
X509_REQ_free(ctx->p10CSR);
|
||||
|
||||
sk_OSSL_CMP_ITAV_pop_free(ctx->genm_ITAVs, OSSL_CMP_ITAV_free);
|
||||
|
||||
sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
|
||||
X509_free(ctx->newCert);
|
||||
sk_X509_pop_free(ctx->caPubs, X509_free);
|
||||
sk_X509_pop_free(ctx->extraCertsIn, X509_free);
|
||||
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
ctx->status = status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the PKIStatus from the last CertRepMessage
|
||||
* or Revocation Response or error message, -1 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return -1;
|
||||
}
|
||||
return ctx->status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the statusString from the last CertRepMessage
|
||||
* or Revocation Response or error message, NULL on error
|
||||
*/
|
||||
OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
return ctx->statusString;
|
||||
}
|
||||
|
||||
int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
|
||||
OSSL_CMP_PKIFREETEXT *text)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
|
||||
ctx->statusString = text;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
X509_free(ctx->validatedSrvCert);
|
||||
ctx->validatedSrvCert = cert;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set callback function for checking if the cert is ok or should
|
||||
* it be rejected.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->certConf_cb = cb;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set argument, respectively a pointer to a structure containing arguments,
|
||||
* optionally to be used by the certConf callback.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->certConf_cb_arg = arg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get argument, respectively the pointer to a structure containing arguments,
|
||||
* optionally to be used by certConf callback.
|
||||
* Returns callback argument set previously (NULL if not set or on error)
|
||||
*/
|
||||
void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
return ctx->certConf_cb_arg;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_TRACE
|
||||
static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
|
||||
int category, int cmd, void *vdata)
|
||||
{
|
||||
OSSL_CMP_CTX *ctx = vdata;
|
||||
const char *prefix_msg;
|
||||
OSSL_CMP_severity level = -1;
|
||||
char *func = NULL;
|
||||
char *file = NULL;
|
||||
int line = 0;
|
||||
|
||||
if (buf == NULL || cnt == 0 || cmd != OSSL_TRACE_CTRL_WRITE || ctx == NULL)
|
||||
return 0;
|
||||
if (ctx->log_cb == NULL)
|
||||
return 1; /* silently drop message */
|
||||
|
||||
prefix_msg = ossl_cmp_log_parse_metadata(buf, &level, &func, &file, &line);
|
||||
|
||||
if (level > ctx->log_verbosity) /* excludes the case level is unknown */
|
||||
goto end; /* suppress output since severity is not sufficient */
|
||||
|
||||
if (!ctx->log_cb(func != NULL ? func : "(no func)",
|
||||
file != NULL ? file : "(no file)",
|
||||
line, level, prefix_msg))
|
||||
cnt = 0;
|
||||
|
||||
end:
|
||||
OPENSSL_free(func);
|
||||
OPENSSL_free(file);
|
||||
return cnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set a callback function for error reporting and logging messages.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_log_cb_t cb)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->log_cb = cb;
|
||||
|
||||
#ifndef OPENSSL_NO_TRACE
|
||||
/* do also in case cb == NULL, to switch off logging output: */
|
||||
if (!OSSL_trace_set_callback(OSSL_TRACE_CATEGORY_CMP,
|
||||
ossl_cmp_log_trace_cb, ctx))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print OpenSSL and CMP errors via the log cb of the ctx or ERR_print_errors */
|
||||
void OSSL_CMP_CTX_print_errors(OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
OSSL_CMP_print_errors_cb(ctx == NULL ? NULL : ctx->log_cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set or clear the reference value to be used for identification
|
||||
* (i.e., the user name) when using PBMAC.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
|
||||
const unsigned char *ref, int len)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
return ossl_cmp_asn1_octet_string_set1_bytes(&ctx->referenceValue, ref,
|
||||
len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set or clear the password to be used for protecting messages with PBMAC.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
|
||||
const int len)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->secretValue != NULL)
|
||||
OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
|
||||
return ossl_cmp_asn1_octet_string_set1_bytes(&ctx->secretValue, sec, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the stack of certificates received in a response message.
|
||||
* The stack is duplicated so the caller must handle freeing it!
|
||||
* Returns pointer to created stack on success, NULL on error
|
||||
*/
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
if (ctx->extraCertsIn == NULL)
|
||||
return sk_X509_new_null();
|
||||
return X509_chain_up_ref(ctx->extraCertsIn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies any given stack of inbound X509 certificates to extraCertsIn
|
||||
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
|
||||
* Returns 1 on success, 0 on error.
|
||||
*/
|
||||
int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
|
||||
STACK_OF(X509) *extraCertsIn)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
|
||||
sk_X509_pop_free(ctx->extraCertsIn, X509_free);
|
||||
ctx->extraCertsIn = NULL;
|
||||
if (extraCertsIn == NULL)
|
||||
return 1;
|
||||
return (ctx->extraCertsIn = X509_chain_up_ref(extraCertsIn)) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplicate and set the given stack as the new stack of X509
|
||||
* certificates to send out in the extraCerts field.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
|
||||
STACK_OF(X509) *extraCertsOut)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sk_X509_pop_free(ctx->extraCertsOut, X509_free);
|
||||
ctx->extraCertsOut = NULL;
|
||||
if (extraCertsOut == NULL)
|
||||
return 1;
|
||||
return (ctx->extraCertsOut = X509_chain_up_ref(extraCertsOut)) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the given policy info object
|
||||
* to the X509_EXTENSIONS of the requested certificate template.
|
||||
* Returns 1 on success, 0 on error.
|
||||
*/
|
||||
int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
|
||||
{
|
||||
if (ctx == NULL || pinfo == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->policies == NULL
|
||||
&& (ctx->policies = CERTIFICATEPOLICIES_new()) == NULL)
|
||||
return 0;
|
||||
|
||||
return sk_POLICYINFO_push(ctx->policies, pinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an ITAV for geninfo of the PKI message header
|
||||
*/
|
||||
int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
return OSSL_CMP_ITAV_push0_stack_item(&ctx->geninfo_ITAVs, itav);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an itav for the body of outgoing general messages
|
||||
*/
|
||||
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
return OSSL_CMP_ITAV_push0_stack_item(&ctx->genm_ITAVs, itav);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a duplicate of the stack of X509 certificates that
|
||||
* were received in the caPubs field of the last CertRepMessage.
|
||||
* Returns NULL on error
|
||||
*/
|
||||
STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
if (ctx->caPubs == NULL)
|
||||
return sk_X509_new_null();
|
||||
return X509_chain_up_ref(ctx->caPubs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplicate and copy the given stack of certificates to the given
|
||||
* OSSL_CMP_CTX structure so that they may be retrieved later.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
|
||||
sk_X509_pop_free(ctx->caPubs, X509_free);
|
||||
ctx->caPubs = NULL;
|
||||
if (caPubs == NULL)
|
||||
return 1;
|
||||
return (ctx->caPubs = X509_chain_up_ref(caPubs)) != NULL;
|
||||
}
|
||||
|
||||
#define char_dup OPENSSL_strdup
|
||||
#define char_free OPENSSL_free
|
||||
#define DEFINE_OSSL_CMP_CTX_set1(FIELD, TYPE) /* this uses _dup */ \
|
||||
int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, const TYPE *val) \
|
||||
{ \
|
||||
TYPE *val_dup = NULL; \
|
||||
\
|
||||
if (ctx == NULL) { \
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
if (val != NULL && (val_dup = TYPE##_dup(val)) == NULL) \
|
||||
return 0; \
|
||||
TYPE##_free(ctx->FIELD); \
|
||||
ctx->FIELD = val_dup; \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define DEFINE_OSSL_CMP_CTX_set1_up_ref(FIELD, TYPE) \
|
||||
int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
|
||||
{ \
|
||||
if (ctx == NULL) { \
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
if (val != NULL && !TYPE##_up_ref(val)) \
|
||||
return 0; \
|
||||
TYPE##_free(ctx->FIELD); \
|
||||
ctx->FIELD = val; \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Pins the server certificate to be directly trusted (even if it is expired)
|
||||
* for verifying response messages.
|
||||
* Cert pointer is not consumed. It may be NULL to clear the entry.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509)
|
||||
|
||||
/*
|
||||
* Set the X509 name of the recipient. Set in the PKIHeader.
|
||||
* returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME)
|
||||
|
||||
/*
|
||||
* Store the X509 name of the expected sender in the PKIHeader of responses.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME)
|
||||
|
||||
/*
|
||||
* Set the X509 name of the issuer. Set in the PKIHeader.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME)
|
||||
|
||||
/*
|
||||
* Set the subject name that will be placed in the certificate
|
||||
* request. This will be the subject name on the received certificate.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(subjectName, X509_NAME)
|
||||
|
||||
/*
|
||||
* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0 && exts != NULL
|
||||
&& X509v3_get_ext_by_NID(exts, NID_subject_alt_name, -1) >= 0) {
|
||||
CMPerr(0, CMP_R_MULTIPLE_SAN_SOURCES);
|
||||
return 0;
|
||||
}
|
||||
sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
|
||||
ctx->reqExtensions = exts;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* returns 1 if ctx contains a Subject Alternative Name extension, else 0 */
|
||||
int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return -1;
|
||||
}
|
||||
/* if one of the following conditions 'fail' this is not an error */
|
||||
return ctx->reqExtensions != NULL
|
||||
&& X509v3_get_ext_by_NID(ctx->reqExtensions,
|
||||
NID_subject_alt_name, -1) >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a GENERAL_NAME structure that will be added to the CRMF
|
||||
* request's extensions field to request subject alternative names.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
|
||||
const GENERAL_NAME *name)
|
||||
{
|
||||
GENERAL_NAME *name_dup;
|
||||
|
||||
if (ctx == NULL || name == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1) {
|
||||
CMPerr(0, CMP_R_MULTIPLE_SAN_SOURCES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->subjectAltNames == NULL
|
||||
&& (ctx->subjectAltNames = sk_GENERAL_NAME_new_null()) == NULL)
|
||||
return 0;
|
||||
if ((name_dup = GENERAL_NAME_dup(name)) == NULL)
|
||||
return 0;
|
||||
if (!sk_GENERAL_NAME_push(ctx->subjectAltNames, name_dup)) {
|
||||
GENERAL_NAME_free(name_dup);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set our own client certificate, used for example in KUR and when
|
||||
* doing the IR with existing certificate.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1_up_ref(clCert, X509)
|
||||
|
||||
/*
|
||||
* Set the old certificate that we are updating in KUR
|
||||
* or the certificate to be revoked in RR, respectively.
|
||||
* Also used as reference cert (defaulting to clCert) for deriving subject DN
|
||||
* and SANs. Its issuer is used as default recipient in the CMP message header.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509)
|
||||
|
||||
/*
|
||||
* Set the PKCS#10 CSR to be sent in P10CR.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
|
||||
|
||||
/*
|
||||
* Sets the (newly received in IP/KUP/CP) certificate in the context.
|
||||
* Returns 1 on success, 0 on error
|
||||
* TODO: this only permits for one cert to be enrolled at a time.
|
||||
*/
|
||||
int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
|
||||
X509_free(ctx->newCert);
|
||||
ctx->newCert = cert;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the (newly received in IP/KUP/CP) client certificate from the context
|
||||
* TODO: this only permits for one client cert to be received...
|
||||
*/
|
||||
X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
return ctx->newCert;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the client's current private key.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY)
|
||||
|
||||
/*
|
||||
* Set new key pair. Used e.g. when doing Key Update.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(ctx->newPkey);
|
||||
ctx->newPkey = pkey;
|
||||
ctx->newPkey_priv = priv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* gets the private/public key to use for certificate enrollment, NULL on error
|
||||
*/
|
||||
EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctx->newPkey != NULL)
|
||||
return priv && !ctx->newPkey_priv ? NULL : ctx->newPkey;
|
||||
if (ctx->p10CSR != NULL)
|
||||
return priv ? NULL : X509_REQ_get0_pubkey(ctx->p10CSR);
|
||||
return ctx->pkey; /* may be NULL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the given transactionID to the context.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
|
||||
const ASN1_OCTET_STRING *id)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id);
|
||||
}
|
||||
|
||||
/*
|
||||
* sets the given nonce to be used for the recipNonce in the next message to be
|
||||
* created.
|
||||
* returns 1 on success, 0 on error
|
||||
*/
|
||||
int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
|
||||
const ASN1_OCTET_STRING *nonce)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stores the given nonce as the last senderNonce sent out.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
|
||||
const ASN1_OCTET_STRING *nonce)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the host name of the (HTTP) proxy server to use for all connections
|
||||
* returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(proxyName, char)
|
||||
|
||||
/*
|
||||
* Set the (HTTP) host name of the CA server.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(serverName, char)
|
||||
|
||||
/*
|
||||
* Sets the (HTTP) proxy port to be used.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->proxyPort = port;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* sets the http connect/disconnect callback function to be used for HTTP(S)
|
||||
* returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_http_cb_t cb)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->http_cb = cb;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set argument optionally to be used by the http connect/disconnect callback.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->http_cb_arg = arg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get argument optionally to be used by the http connect/disconnect callback
|
||||
* Returns callback argument set previously (NULL if not set or on error)
|
||||
*/
|
||||
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
return ctx->http_cb_arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set callback function for sending CMP request and receiving response.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->transfer_cb = cb;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set argument optionally to be used by the transfer callback.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->transfer_cb_arg = arg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get argument optionally to be used by the transfer callback.
|
||||
* Returns callback argument set previously (NULL if not set or on error)
|
||||
*/
|
||||
void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
return ctx->transfer_cb_arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the (HTTP) server port to be used.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
ctx->serverPort = port;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the HTTP path to be used on the server (e.g "pkix/").
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
DEFINE_OSSL_CMP_CTX_set1(serverPath, char)
|
||||
|
||||
/*
|
||||
* Set the failInfo error code as bit encoding in OSSL_CMP_CTX.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
ctx->failInfoCode = fail_info;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the failInfo error code in OSSL_CMP_CTX as bit encoding.
|
||||
* Returns bit string as integer on success, -1 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return -1;
|
||||
}
|
||||
return ctx->failInfoCode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a Boolean or integer option of the context to the "val" arg.
|
||||
* Returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) {
|
||||
int min_val;
|
||||
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case OSSL_CMP_OPT_REVOCATION_REASON:
|
||||
min_val = OCSP_REVOKED_STATUS_NOSTATUS;
|
||||
break;
|
||||
case OSSL_CMP_OPT_POPOMETHOD:
|
||||
min_val = OSSL_CRMF_POPO_NONE;
|
||||
break;
|
||||
default:
|
||||
min_val = 0;
|
||||
break;
|
||||
}
|
||||
if (val < min_val) {
|
||||
CMPerr(0, CMP_R_INVALID_ARGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case OSSL_CMP_OPT_LOG_VERBOSITY:
|
||||
if (val > OSSL_CMP_LOG_DEBUG) {
|
||||
CMPerr(0, CMP_R_INVALID_ARGS);
|
||||
return 0;
|
||||
}
|
||||
ctx->log_verbosity = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_IMPLICITCONFIRM:
|
||||
ctx->implicitConfirm = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_DISABLECONFIRM:
|
||||
ctx->disableConfirm = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_UNPROTECTED_SEND:
|
||||
ctx->unprotectedSend = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
|
||||
ctx->unprotectedErrors = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_VALIDITYDAYS:
|
||||
ctx->days = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
|
||||
ctx->SubjectAltName_nodefault = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
|
||||
ctx->setSubjectAltNameCritical = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_POLICIES_CRITICAL:
|
||||
ctx->setPoliciesCritical = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
|
||||
ctx->ignore_keyusage = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_POPOMETHOD:
|
||||
if (val > OSSL_CRMF_POPO_KEYAGREE) {
|
||||
CMPerr(0, CMP_R_INVALID_ARGS);
|
||||
return 0;
|
||||
}
|
||||
ctx->popoMethod = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_DIGEST_ALGNID:
|
||||
ctx->digest = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_OWF_ALGNID:
|
||||
ctx->pbm_owf = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_MAC_ALGNID:
|
||||
ctx->pbm_mac = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_MSGTIMEOUT:
|
||||
ctx->msgtimeout = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_TOTALTIMEOUT:
|
||||
ctx->totaltimeout = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
|
||||
ctx->permitTAInExtraCertsForIR = val;
|
||||
break;
|
||||
case OSSL_CMP_OPT_REVOCATION_REASON:
|
||||
if (val > OCSP_REVOKED_STATUS_AACOMPROMISE) {
|
||||
CMPerr(0, CMP_R_INVALID_ARGS);
|
||||
return 0;
|
||||
}
|
||||
ctx->revocationReason = val;
|
||||
break;
|
||||
default:
|
||||
CMPerr(0, CMP_R_INVALID_ARGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a Boolean or integer option value from the context.
|
||||
* Returns -1 on error (which is the default OSSL_CMP_OPT_REVOCATION_REASON)
|
||||
*/
|
||||
int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) {
|
||||
if (ctx == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case OSSL_CMP_OPT_LOG_VERBOSITY:
|
||||
return ctx->log_verbosity;
|
||||
case OSSL_CMP_OPT_IMPLICITCONFIRM:
|
||||
return ctx->implicitConfirm;
|
||||
case OSSL_CMP_OPT_DISABLECONFIRM:
|
||||
return ctx->disableConfirm;
|
||||
case OSSL_CMP_OPT_UNPROTECTED_SEND:
|
||||
return ctx->unprotectedSend;
|
||||
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
|
||||
return ctx->unprotectedErrors;
|
||||
case OSSL_CMP_OPT_VALIDITYDAYS:
|
||||
return ctx->days;
|
||||
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
|
||||
return ctx->SubjectAltName_nodefault;
|
||||
case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
|
||||
return ctx->setSubjectAltNameCritical;
|
||||
case OSSL_CMP_OPT_POLICIES_CRITICAL:
|
||||
return ctx->setPoliciesCritical;
|
||||
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
|
||||
return ctx->ignore_keyusage;
|
||||
case OSSL_CMP_OPT_POPOMETHOD:
|
||||
return ctx->popoMethod;
|
||||
case OSSL_CMP_OPT_DIGEST_ALGNID:
|
||||
return ctx->digest;
|
||||
case OSSL_CMP_OPT_OWF_ALGNID:
|
||||
return ctx->pbm_owf;
|
||||
case OSSL_CMP_OPT_MAC_ALGNID:
|
||||
return ctx->pbm_mac;
|
||||
case OSSL_CMP_OPT_MSGTIMEOUT:
|
||||
return ctx->msgtimeout;
|
||||
case OSSL_CMP_OPT_TOTALTIMEOUT:
|
||||
return ctx->totaltimeout;
|
||||
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
|
||||
return ctx->permitTAInExtraCertsForIR;
|
||||
case OSSL_CMP_OPT_REVOCATION_REASON:
|
||||
return ctx->revocationReason;
|
||||
default:
|
||||
CMPerr(0, CMP_R_INVALID_ARGS);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2007-2019 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
|
||||
@@ -14,6 +15,11 @@
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA CMP_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_SAN_SOURCES),
|
||||
"multiple san sources"},
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_STDIO), "no stdio"},
|
||||
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NULL_ARGUMENT), "null argument"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,12 +7,10 @@
|
||||
* 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
|
||||
*
|
||||
* CMP implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
|
||||
*/
|
||||
|
||||
#ifndef OSSL_HEADER_CMP_INT_H
|
||||
# define OSSL_HEADER_CMP_INT_H
|
||||
#ifndef OSSL_CRYPTO_CMP_LOCAL_H
|
||||
# define OSSL_CRYPTO_CMP_LOCAL_H
|
||||
|
||||
# include "internal/cryptlib.h"
|
||||
|
||||
@@ -21,11 +19,105 @@
|
||||
|
||||
/* explicit #includes not strictly needed since implied by the above: */
|
||||
# include <openssl/crmf.h>
|
||||
# include <openssl/ossl_typ.h>
|
||||
# include <openssl/types.h>
|
||||
# include <openssl/safestack.h>
|
||||
# include <openssl/x509.h>
|
||||
# include <openssl/x509v3.h>
|
||||
|
||||
/*
|
||||
* this structure is used to store the context for CMP sessions
|
||||
*/
|
||||
struct ossl_cmp_ctx_st {
|
||||
OSSL_cmp_log_cb_t log_cb; /* log callback for error/debug/etc. output */
|
||||
OSSL_CMP_severity log_verbosity; /* level of verbosity of log output */
|
||||
|
||||
/* message transfer */
|
||||
OSSL_cmp_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */
|
||||
void *transfer_cb_arg; /* allows to store optional argument to cb */
|
||||
/* HTTP-based transfer */
|
||||
char *serverPath;
|
||||
char *serverName;
|
||||
int serverPort;
|
||||
char *proxyName;
|
||||
int proxyPort;
|
||||
int msgtimeout; /* max seconds to wait for each CMP message round trip */
|
||||
int totaltimeout; /* maximum number seconds an enrollment may take, incl. */
|
||||
/* attempts polling for a response if a 'waiting' PKIStatus is received */
|
||||
time_t end_time; /* session start time + totaltimeout */
|
||||
OSSL_cmp_http_cb_t http_cb;
|
||||
void *http_cb_arg; /* allows to store optional argument to cb */
|
||||
|
||||
/* server authentication */
|
||||
int unprotectedErrors; /* accept neg. response with no/invalid protection */
|
||||
/* to cope with broken server */
|
||||
X509 *srvCert; /* certificate used to identify the server */
|
||||
X509 *validatedSrvCert; /* caches any already validated server cert */
|
||||
X509_NAME *expected_sender; /* expected sender in pkiheader of response */
|
||||
X509_STORE *trusted; /* trust store maybe w CRLs and cert verify callback */
|
||||
STACK_OF(X509) *untrusted_certs; /* untrusted (intermediate) certs */
|
||||
int ignore_keyusage; /* ignore key usage entry when validating certs */
|
||||
int permitTAInExtraCertsForIR; /* allow use of root certs in extracerts */
|
||||
/* when validating message protection; used for 3GPP-style E.7 */
|
||||
|
||||
/* client authentication */
|
||||
int unprotectedSend; /* send unprotected PKI messages */
|
||||
X509 *clCert; /* client cert used to identify and sign for MSG_SIG_ALG */
|
||||
EVP_PKEY *pkey; /* the key pair corresponding to clCert */
|
||||
ASN1_OCTET_STRING *referenceValue; /* optional user name for MSG_MAC_ALG */
|
||||
ASN1_OCTET_STRING *secretValue; /* password/shared secret for MSG_MAC_ALG */
|
||||
/* PBMParameters for MSG_MAC_ALG */
|
||||
size_t pbm_slen; /* currently fixed to 16 */
|
||||
int pbm_owf; /* NID of one-way function (OWF), default: SHA256 */
|
||||
int pbm_itercnt; /* currently fixed to 500 */
|
||||
int pbm_mac; /* NID of MAC algorithm, default: HMAC-SHA1 as per RFC 4210 */
|
||||
|
||||
/* CMP message header and extra certificates */
|
||||
X509_NAME *recipient; /* to set in recipient in pkiheader */
|
||||
int digest; /* NID of digest used in MSG_SIG_ALG and POPO, default SHA256 */
|
||||
ASN1_OCTET_STRING *transactionID; /* the current transaction ID */
|
||||
ASN1_OCTET_STRING *senderNonce; /* last nonce sent */
|
||||
ASN1_OCTET_STRING *recipNonce; /* last nonce received */
|
||||
STACK_OF(OSSL_CMP_ITAV) *geninfo_ITAVs;
|
||||
int implicitConfirm; /* set implicitConfirm in IR/KUR/CR messages */
|
||||
int disableConfirm; /* disable certConf in IR/KUR/CR for broken servers */
|
||||
STACK_OF(X509) *extraCertsOut; /* to be included in request messages */
|
||||
|
||||
/* certificate template */
|
||||
EVP_PKEY *newPkey; /* explicit new private/public key for cert enrollment */
|
||||
int newPkey_priv; /* flag indicating if newPkey contains private key */
|
||||
X509_NAME *issuer; /* issuer name to used in cert template */
|
||||
int days; /* Number of days new certificates are asked to be valid for */
|
||||
X509_NAME *subjectName; /* subject name to be used in the cert template */
|
||||
STACK_OF(GENERAL_NAME) *subjectAltNames; /* to add to the cert template */
|
||||
int SubjectAltName_nodefault;
|
||||
int setSubjectAltNameCritical;
|
||||
X509_EXTENSIONS *reqExtensions; /* exts to be added to cert template */
|
||||
CERTIFICATEPOLICIES *policies; /* policies to be included in extensions */
|
||||
int setPoliciesCritical;
|
||||
int popoMethod; /* Proof-of-possession mechanism; default: signature */
|
||||
X509 *oldCert; /* cert to be updated (via KUR) or to be revoked (via RR) */
|
||||
X509_REQ *p10CSR; /* for P10CR: PKCS#10 CSR to be sent */
|
||||
|
||||
/* misc body contents */
|
||||
int revocationReason; /* revocation reason code to be included in RR */
|
||||
STACK_OF(OSSL_CMP_ITAV) *genm_ITAVs; /* content of general message */
|
||||
|
||||
/* result returned in responses */
|
||||
int status; /* PKIStatus of last received IP/CP/KUP/RP/error or -1 */
|
||||
/* TODO: this should be a stack since there could be more than one */
|
||||
OSSL_CMP_PKIFREETEXT *statusString; /* of last IP/CP/KUP/RP/error */
|
||||
int failInfoCode; /* failInfoCode of last received IP/CP/KUP/error, or -1 */
|
||||
/* TODO: this should be a stack since there could be more than one */
|
||||
X509 *newCert; /* newly enrolled cert received from the CA */
|
||||
/* TODO: this should be a stack since there could be more than one */
|
||||
STACK_OF(X509) *caPubs; /* CA certs received from server (in IP message) */
|
||||
STACK_OF(X509) *extraCertsIn; /* extraCerts received from server */
|
||||
|
||||
/* certificate confirmation */
|
||||
OSSL_cmp_certConf_cb_t certConf_cb; /* callback for app checking new cert */
|
||||
void *certConf_cb_arg; /* allows to store an argument individual to cb */
|
||||
} /* OSSL_CMP_CTX */;
|
||||
|
||||
/*
|
||||
* ##########################################################################
|
||||
* ASN.1 DECLARATIONS
|
||||
@@ -42,7 +134,7 @@
|
||||
* -- extra CRL details (e.g., crl number, reason, location, etc.)
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_revanncontent_st {
|
||||
typedef struct ossl_cmp_revanncontent_st {
|
||||
ASN1_INTEGER *status;
|
||||
OSSL_CRMF_CERTID *certId;
|
||||
ASN1_GENERALIZEDTIME *willBeRevokedAt;
|
||||
@@ -75,7 +167,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVANNCONTENT)
|
||||
* -- }
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_challenge_st {
|
||||
typedef struct ossl_cmp_challenge_st {
|
||||
X509_ALGOR *owf;
|
||||
ASN1_OCTET_STRING *witness;
|
||||
ASN1_OCTET_STRING *challenge;
|
||||
@@ -89,7 +181,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CHALLENGE)
|
||||
* newWithNew Certificate
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_cakeyupdanncontent_st {
|
||||
typedef struct ossl_cmp_cakeyupdanncontent_st {
|
||||
X509 *oldWithNew;
|
||||
X509 *newWithOld;
|
||||
X509 *newWithNew;
|
||||
@@ -109,7 +201,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_MSGS)
|
||||
* infoValue ANY DEFINED BY infoType OPTIONAL
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_itav_st {
|
||||
struct ossl_cmp_itav_st {
|
||||
ASN1_OBJECT *infoType;
|
||||
union {
|
||||
char *ptr;
|
||||
@@ -148,8 +240,7 @@ struct OSSL_cmp_itav_st {
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
|
||||
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
|
||||
|
||||
|
||||
typedef struct OSSL_cmp_certorenccert_st {
|
||||
typedef struct ossl_cmp_certorenccert_st {
|
||||
int type;
|
||||
union {
|
||||
X509 *certificate;
|
||||
@@ -166,7 +257,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
|
||||
* publicationInfo [1] PKIPublicationInfo OPTIONAL
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_certifiedkeypair_st {
|
||||
typedef struct ossl_cmp_certifiedkeypair_st {
|
||||
OSSL_CMP_CERTORENCCERT *certOrEncCert;
|
||||
OSSL_CRMF_ENCRYPTEDVALUE *privateKey;
|
||||
OSSL_CRMF_PKIPUBLICATIONINFO *publicationInfo;
|
||||
@@ -180,7 +271,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR)
|
||||
* failInfo PKIFailureInfo OPTIONAL
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_pkisi_st {
|
||||
struct ossl_cmp_pkisi_st {
|
||||
OSSL_CMP_PKISTATUS *status;
|
||||
OSSL_CMP_PKIFREETEXT *statusString;
|
||||
OSSL_CMP_PKIFAILUREINFO *failInfo;
|
||||
@@ -196,7 +287,7 @@ DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
|
||||
* crlEntryDetails Extensions OPTIONAL
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_revdetails_st {
|
||||
typedef struct ossl_cmp_revdetails_st {
|
||||
OSSL_CRMF_CERTTEMPLATE *certDetails;
|
||||
X509_EXTENSIONS *crlEntryDetails;
|
||||
} OSSL_CMP_REVDETAILS;
|
||||
@@ -216,7 +307,7 @@ DEFINE_STACK_OF(OSSL_CMP_REVDETAILS)
|
||||
* -- the resulting CRLs (there may be more than one)
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_revrepcontent_st {
|
||||
struct ossl_cmp_revrepcontent_st {
|
||||
STACK_OF(OSSL_CMP_PKISI) *status;
|
||||
STACK_OF(OSSL_CRMF_CERTID) *revCerts;
|
||||
STACK_OF(X509_CRL) *crls;
|
||||
@@ -233,7 +324,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVREPCONTENT)
|
||||
* CertifiedKeyPair OPTIONAL
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_keyrecrepcontent_st {
|
||||
typedef struct ossl_cmp_keyrecrepcontent_st {
|
||||
OSSL_CMP_PKISI *status;
|
||||
X509 *newSigCert;
|
||||
STACK_OF(X509) *caCerts;
|
||||
@@ -250,7 +341,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_KEYRECREPCONTENT)
|
||||
* -- implementation-specific error details
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_errormsgcontent_st {
|
||||
typedef struct ossl_cmp_errormsgcontent_st {
|
||||
OSSL_CMP_PKISI *pKIStatusInfo;
|
||||
ASN1_INTEGER *errorCode;
|
||||
OSSL_CMP_PKIFREETEXT *errorDetails;
|
||||
@@ -269,7 +360,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT)
|
||||
* statusInfo PKIStatusInfo OPTIONAL
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_certstatus_st {
|
||||
struct ossl_cmp_certstatus_st {
|
||||
ASN1_OCTET_STRING *certHash;
|
||||
ASN1_INTEGER *certReqId;
|
||||
OSSL_CMP_PKISI *statusInfo;
|
||||
@@ -292,7 +383,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTCONFIRMCONTENT)
|
||||
* -- for regInfo in CertReqMsg [CRMF]
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_certresponse_st {
|
||||
struct ossl_cmp_certresponse_st {
|
||||
ASN1_INTEGER *certReqId;
|
||||
OSSL_CMP_PKISI *status;
|
||||
OSSL_CMP_CERTIFIEDKEYPAIR *certifiedKeyPair;
|
||||
@@ -307,7 +398,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTRESPONSE)
|
||||
* response SEQUENCE OF CertResponse
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_certrepmessage_st {
|
||||
struct ossl_cmp_certrepmessage_st {
|
||||
STACK_OF(X509) *caPubs;
|
||||
STACK_OF(OSSL_CMP_CERTRESPONSE) *response;
|
||||
} /* OSSL_CMP_CERTREPMESSAGE */;
|
||||
@@ -318,7 +409,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTREPMESSAGE)
|
||||
* certReqId INTEGER
|
||||
* }
|
||||
*/
|
||||
typedef struct OSSL_cmp_pollreq_st {
|
||||
typedef struct ossl_cmp_pollreq_st {
|
||||
ASN1_INTEGER *certReqId;
|
||||
} OSSL_CMP_POLLREQ;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREQ)
|
||||
@@ -333,7 +424,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREQCONTENT)
|
||||
* reason PKIFreeText OPTIONAL
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_pollrep_st {
|
||||
struct ossl_cmp_pollrep_st {
|
||||
ASN1_INTEGER *certReqId;
|
||||
ASN1_INTEGER *checkAfter;
|
||||
OSSL_CMP_PKIFREETEXT *reason;
|
||||
@@ -377,7 +468,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREPCONTENT)
|
||||
* -- (this field not primarily intended for human consumption)
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_pkiheader_st {
|
||||
struct ossl_cmp_pkiheader_st {
|
||||
ASN1_INTEGER *pvno;
|
||||
GENERAL_NAME *sender;
|
||||
GENERAL_NAME *recipient;
|
||||
@@ -435,7 +526,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_GENREPCONTENT)
|
||||
* pollReq [25] PollReqContent, --Polling request
|
||||
* pollRep [26] PollRepContent --Polling response
|
||||
*/
|
||||
typedef struct OSSL_cmp_pkibody_st {
|
||||
typedef struct ossl_cmp_pkibody_st {
|
||||
int type;
|
||||
union {
|
||||
OSSL_CRMF_MSGS *ir; /* 0 */
|
||||
@@ -521,7 +612,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKIBODY)
|
||||
* OPTIONAL
|
||||
* }
|
||||
*/
|
||||
struct OSSL_cmp_msg_st {
|
||||
struct ossl_cmp_msg_st {
|
||||
OSSL_CMP_PKIHEADER *header;
|
||||
OSSL_CMP_PKIBODY *body;
|
||||
ASN1_BIT_STRING *protection; /* 0 */
|
||||
@@ -529,6 +620,7 @@ struct OSSL_cmp_msg_st {
|
||||
STACK_OF(X509) *extraCerts; /* 1 */
|
||||
} /* OSSL_CMP_MSG */;
|
||||
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_MSG)
|
||||
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_MSG)
|
||||
|
||||
/*-
|
||||
* ProtectedPart ::= SEQUENCE {
|
||||
@@ -586,4 +678,48 @@ DECLARE_ASN1_FUNCTIONS(CMP_PROTECTEDPART)
|
||||
* }
|
||||
*/
|
||||
|
||||
#endif /* !defined OSSL_HEADER_CMP_INT_H */
|
||||
/*
|
||||
* functions
|
||||
*/
|
||||
|
||||
/* from cmp_asn.c */
|
||||
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
|
||||
|
||||
/* from cmp_util.c */
|
||||
const char *ossl_cmp_log_parse_metadata(const char *buf,
|
||||
OSSL_CMP_severity *level, char **func,
|
||||
char **file, int *line);
|
||||
/* workaround for 4096 bytes limitation of ERR_print_errors_cb() */
|
||||
void ossl_cmp_add_error_txt(const char *separator, const char *txt);
|
||||
# define ossl_cmp_add_error_data(txt) ossl_cmp_add_error_txt(" : ", txt)
|
||||
# define ossl_cmp_add_error_line(txt) ossl_cmp_add_error_txt("\n", txt)
|
||||
/* functions manipulating lists of certificates etc could be generally useful */
|
||||
int ossl_cmp_sk_X509_add1_cert (STACK_OF(X509) *sk, X509 *cert,
|
||||
int no_dup, int prepend);
|
||||
int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
|
||||
int no_self_signed, int no_dups, int prepend);
|
||||
int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
|
||||
int only_self_signed);
|
||||
STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
|
||||
int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
|
||||
const ASN1_OCTET_STRING *src);
|
||||
int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
|
||||
const unsigned char *bytes, int len);
|
||||
STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert);
|
||||
|
||||
/* from cmp_ctx.c */
|
||||
int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert);
|
||||
int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status);
|
||||
int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
|
||||
OSSL_CMP_PKIFREETEXT *text);
|
||||
int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info);
|
||||
int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert);
|
||||
int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs);
|
||||
int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
|
||||
STACK_OF(X509) *extraCertsIn);
|
||||
int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
|
||||
const ASN1_OCTET_STRING *nonce);
|
||||
|
||||
# define OSSL_CMP_TRANSACTIONID_LENGTH 16
|
||||
|
||||
#endif /* !defined OSSL_CRYPTO_CMP_LOCAL_H */
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright 2007-2019 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 <string.h>
|
||||
#include <openssl/cmp_util.h>
|
||||
#include "cmp_local.h" /* just for decls of internal functions defined here */
|
||||
#include <openssl/cmperr.h>
|
||||
#include <openssl/err.h> /* should be implied by cmperr.h */
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
/*
|
||||
* use trace API for CMP-specific logging, prefixed by "CMP " and severity
|
||||
*/
|
||||
|
||||
int OSSL_CMP_log_open(void) /* is designed to be idempotent */
|
||||
{
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
BIO *bio = BIO_new_fp(stdout, BIO_NOCLOSE);
|
||||
|
||||
if (bio != NULL && OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP, bio))
|
||||
return 1;
|
||||
BIO_free(bio);
|
||||
#endif
|
||||
CMPerr(0, CMP_R_NO_STDIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OSSL_CMP_log_close(void) /* is designed to be idempotent */
|
||||
{
|
||||
(void)OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP, NULL);
|
||||
}
|
||||
|
||||
/* return >= 0 if level contains logging level, possibly preceded by "CMP " */
|
||||
#define max_level_len 5 /* = max length of the below strings, e.g., "EMERG" */
|
||||
static OSSL_CMP_severity parse_level(const char *level)
|
||||
{
|
||||
const char *end_level = strchr(level, ':');
|
||||
int len;
|
||||
char level_copy[max_level_len + 1];
|
||||
|
||||
if (end_level == NULL)
|
||||
return -1;
|
||||
|
||||
if (strncmp(level, OSSL_CMP_LOG_PREFIX,
|
||||
strlen(OSSL_CMP_LOG_PREFIX)) == 0)
|
||||
level += strlen(OSSL_CMP_LOG_PREFIX);
|
||||
len = end_level - level;
|
||||
if (len > max_level_len)
|
||||
return -1;
|
||||
OPENSSL_strlcpy(level_copy, level, len + 1);
|
||||
return
|
||||
strcmp(level_copy, "EMERG") == 0 ? OSSL_CMP_LOG_EMERG :
|
||||
strcmp(level_copy, "ALERT") == 0 ? OSSL_CMP_LOG_ALERT :
|
||||
strcmp(level_copy, "CRIT") == 0 ? OSSL_CMP_LOG_CRIT :
|
||||
strcmp(level_copy, "ERROR") == 0 ? OSSL_CMP_LOG_ERR :
|
||||
strcmp(level_copy, "WARN") == 0 ? OSSL_CMP_LOG_WARNING :
|
||||
strcmp(level_copy, "NOTE") == 0 ? OSSL_CMP_LOG_NOTICE :
|
||||
strcmp(level_copy, "INFO") == 0 ? OSSL_CMP_LOG_INFO :
|
||||
strcmp(level_copy, "DEBUG") == 0 ? OSSL_CMP_LOG_DEBUG :
|
||||
-1;
|
||||
}
|
||||
|
||||
const char *ossl_cmp_log_parse_metadata(const char *buf,
|
||||
OSSL_CMP_severity *level, char **func, char **file, int *line)
|
||||
{
|
||||
const char *p_func = buf;
|
||||
const char *p_file = buf == NULL ? NULL : strchr(buf, ':');
|
||||
const char *p_level = buf;
|
||||
const char *msg = buf;
|
||||
|
||||
*level = -1;
|
||||
*func = NULL;
|
||||
*file = NULL;
|
||||
*line = 0;
|
||||
|
||||
if (p_file != NULL) {
|
||||
const char *p_line = strchr(++p_file, ':');
|
||||
|
||||
if ((*level = parse_level(buf)) < 0 && p_line != NULL) {
|
||||
/* check if buf contains location info and logging level */
|
||||
char *p_level_tmp = (char *)p_level;
|
||||
const long line_number = strtol(++p_line, &p_level_tmp, 10);
|
||||
|
||||
p_level = p_level_tmp;
|
||||
if (p_level > p_line && *(p_level++) == ':') {
|
||||
if ((*level = parse_level(p_level)) >= 0) {
|
||||
*func = OPENSSL_strndup(p_func, p_file - 1 - p_func);
|
||||
*file = OPENSSL_strndup(p_file, p_line - 1 - p_file);
|
||||
/* no real problem if OPENSSL_strndup() returns NULL */
|
||||
*line = (int)line_number;
|
||||
msg = strchr(p_level, ':') + 1;
|
||||
if (*msg == ' ')
|
||||
msg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* auxiliary function for incrementally reporting texts via the error queue
|
||||
*/
|
||||
static void put_error(int lib, const char *func, int reason,
|
||||
const char *file, int line)
|
||||
{
|
||||
ERR_new();
|
||||
ERR_set_debug(file, line, func);
|
||||
ERR_set_error(lib, reason, NULL /* no data here, so fmt is NULL */);
|
||||
}
|
||||
|
||||
#define ERR_print_errors_cb_LIMIT 4096 /* size of char buf[] variable there */
|
||||
#define TYPICAL_MAX_OUTPUT_BEFORE_DATA 100
|
||||
#define MAX_DATA_LEN (ERR_print_errors_cb_LIMIT-TYPICAL_MAX_OUTPUT_BEFORE_DATA)
|
||||
void ossl_cmp_add_error_txt(const char *separator, const char *txt)
|
||||
{
|
||||
const char *file = NULL;
|
||||
int line;
|
||||
const char *func = NULL;
|
||||
const char *data = NULL;
|
||||
int flags;
|
||||
unsigned long err = ERR_peek_last_error();
|
||||
|
||||
if (separator == NULL)
|
||||
separator = "";
|
||||
if (err == 0)
|
||||
put_error(ERR_LIB_CMP, NULL, 0, "", 0);
|
||||
|
||||
do {
|
||||
size_t available_len, data_len;
|
||||
const char *curr = txt, *next = txt;
|
||||
char *tmp;
|
||||
|
||||
ERR_peek_last_error_all(&file, &line, &func, &data, &flags);
|
||||
if ((flags & ERR_TXT_STRING) == 0) {
|
||||
data = "";
|
||||
separator = "";
|
||||
}
|
||||
data_len = strlen(data);
|
||||
|
||||
/* workaround for limit of ERR_print_errors_cb() */
|
||||
if (data_len >= MAX_DATA_LEN
|
||||
|| strlen(separator) >= (size_t)(MAX_DATA_LEN - data_len))
|
||||
available_len = 0;
|
||||
else
|
||||
available_len = MAX_DATA_LEN - data_len - strlen(separator) - 1;
|
||||
/* MAX_DATA_LEN > available_len >= 0 */
|
||||
|
||||
if (separator[0] == '\0') {
|
||||
const size_t len_next = strlen(next);
|
||||
|
||||
if (len_next <= available_len) {
|
||||
next += len_next;
|
||||
curr = NULL; /* no need to split */
|
||||
}
|
||||
else {
|
||||
next += available_len;
|
||||
curr = next; /* will split at this point */
|
||||
}
|
||||
} else {
|
||||
while (*next != '\0' && (size_t)(next - txt) <= available_len) {
|
||||
curr = next;
|
||||
next = strstr(curr, separator);
|
||||
if (next != NULL)
|
||||
next += strlen(separator);
|
||||
else
|
||||
next = curr + strlen(curr);
|
||||
}
|
||||
if ((size_t)(next - txt) <= available_len)
|
||||
curr = NULL; /* the above loop implies *next == '\0' */
|
||||
}
|
||||
if (curr != NULL) {
|
||||
/* split error msg at curr since error data would get too long */
|
||||
if (curr != txt) {
|
||||
tmp = OPENSSL_strndup(txt, curr - txt);
|
||||
if (tmp == NULL)
|
||||
return;
|
||||
ERR_add_error_data(2, separator, tmp);
|
||||
OPENSSL_free(tmp);
|
||||
}
|
||||
put_error(ERR_LIB_CMP, func, err, file, line);
|
||||
txt = curr;
|
||||
} else {
|
||||
ERR_add_error_data(2, separator, txt);
|
||||
txt = next; /* finished */
|
||||
}
|
||||
} while (*txt != '\0');
|
||||
}
|
||||
|
||||
/* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */
|
||||
void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn)
|
||||
{
|
||||
unsigned long err;
|
||||
char msg[ERR_print_errors_cb_LIMIT];
|
||||
const char *file = NULL, *func = NULL, *data = NULL;
|
||||
int line, flags;
|
||||
|
||||
if (log_fn == NULL) {
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
ERR_print_errors_fp(stderr);
|
||||
#else
|
||||
/* CMPerr(0, CMP_R_NO_STDIO) makes no sense during error printing */
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
while ((err = ERR_get_error_all(&file, &line, &func, &data, &flags)) != 0) {
|
||||
char component[128];
|
||||
const char *func_ = func != NULL && *func != '\0' ? func : "<unknown>";
|
||||
|
||||
if (!(flags & ERR_TXT_STRING))
|
||||
data = NULL;
|
||||
#ifdef OSSL_CMP_PRINT_LIBINFO
|
||||
BIO_snprintf(component, sizeof(component), "OpenSSL:%s:%s",
|
||||
ERR_lib_error_string(err), func_);
|
||||
#else
|
||||
BIO_snprintf(component, sizeof(component), "%s",func_);
|
||||
#endif
|
||||
BIO_snprintf(msg, sizeof(msg), "%s%s%s", ERR_reason_error_string(err),
|
||||
data == NULL ? "" : " : ", data == NULL ? "" : data);
|
||||
if (log_fn(component, file, line, OSSL_CMP_LOG_ERR, msg) <= 0)
|
||||
break; /* abort outputting the error report */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* functions manipulating lists of certificates etc.
|
||||
* these functions could be generally useful.
|
||||
*/
|
||||
|
||||
int ossl_cmp_sk_X509_add1_cert(STACK_OF(X509) *sk, X509 *cert,
|
||||
int no_dup, int prepend)
|
||||
{
|
||||
if (sk == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
if (no_dup) {
|
||||
/*
|
||||
* not using sk_X509_set_cmp_func() and sk_X509_find()
|
||||
* because this re-orders the certs on the stack
|
||||
*/
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sk_X509_num(sk); i++) {
|
||||
if (X509_cmp(sk_X509_value(sk, i), cert) == 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!X509_up_ref(cert))
|
||||
return 0;
|
||||
if (!sk_X509_insert(sk, cert, prepend ? 0 : -1)) {
|
||||
X509_free(cert);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
|
||||
int no_self_signed, int no_dups, int prepend)
|
||||
/* compiler would allow 'const' for the list of certs, yet they are up-ref'ed */
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sk == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sk_X509_num(certs); i++) { /* certs may be NULL */
|
||||
X509 *cert = sk_X509_value(certs, i);
|
||||
|
||||
if (!no_self_signed || X509_check_issued(cert, cert) != X509_V_OK) {
|
||||
if (!ossl_cmp_sk_X509_add1_cert(sk, cert, no_dups, prepend))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
|
||||
int only_self_signed)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (store == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
if (certs == NULL)
|
||||
return 1;
|
||||
for (i = 0; i < sk_X509_num(certs); i++) {
|
||||
X509 *cert = sk_X509_value(certs, i);
|
||||
|
||||
if (!only_self_signed || X509_check_issued(cert, cert) == X509_V_OK)
|
||||
if (!X509_STORE_add_cert(store, cert)) /* ups cert ref counter */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store)
|
||||
{
|
||||
int i;
|
||||
STACK_OF(X509) *sk;
|
||||
STACK_OF(X509_OBJECT) *objs;
|
||||
|
||||
if (store == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
if ((sk = sk_X509_new_null()) == NULL)
|
||||
return NULL;
|
||||
objs = X509_STORE_get0_objects(store);
|
||||
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||
X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
|
||||
|
||||
if (cert != NULL) {
|
||||
if (!sk_X509_push(sk, cert))
|
||||
goto err;
|
||||
if (!X509_up_ref(cert)) {
|
||||
(void)sk_X509_pop(sk);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sk;
|
||||
|
||||
err:
|
||||
sk_X509_pop_free(sk, X509_free);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Builds up the certificate chain of certs as high up as possible using
|
||||
* the given list of certs containing all possible intermediate certificates and
|
||||
* optionally the (possible) trust anchor(s). See also ssl_add_cert_chain().
|
||||
*
|
||||
* Intended use of this function is to find all the certificates above the trust
|
||||
* anchor needed to verify an EE's own certificate. Those are supposed to be
|
||||
* included in the ExtraCerts field of every first sent message of a transaction
|
||||
* when MSG_SIG_ALG is utilized.
|
||||
*
|
||||
* NOTE: This allocates a stack and increments the reference count of each cert,
|
||||
* so when not needed any more the stack and all its elements should be freed.
|
||||
* NOTE: in case there is more than one possibility for the chain,
|
||||
* OpenSSL seems to take the first one, check X509_verify_cert() for details.
|
||||
*
|
||||
* returns a pointer to a stack of (up_ref'ed) X509 certificates containing:
|
||||
* - the EE certificate given in the function arguments (cert)
|
||||
* - all intermediate certificates up the chain toward the trust anchor
|
||||
* whereas the (self-signed) trust anchor is not included
|
||||
* returns NULL on error
|
||||
*/
|
||||
STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert)
|
||||
{
|
||||
STACK_OF(X509) *chain = NULL, *result = NULL;
|
||||
X509_STORE *store = X509_STORE_new();
|
||||
X509_STORE_CTX *csc = NULL;
|
||||
|
||||
if (certs == NULL || cert == NULL || store == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
csc = X509_STORE_CTX_new();
|
||||
if (csc == NULL)
|
||||
goto err;
|
||||
|
||||
if (!ossl_cmp_X509_STORE_add1_certs(store, certs, 0)
|
||||
|| !X509_STORE_CTX_init(csc, store, cert, NULL))
|
||||
goto err;
|
||||
|
||||
(void)ERR_set_mark();
|
||||
/*
|
||||
* ignore return value as it would fail without trust anchor given in store
|
||||
*/
|
||||
(void)X509_verify_cert(csc);
|
||||
|
||||
/* don't leave any new errors in the queue */
|
||||
(void)ERR_pop_to_mark();
|
||||
|
||||
chain = X509_STORE_CTX_get0_chain(csc);
|
||||
|
||||
/* result list to store the up_ref'ed not self-signed certificates */
|
||||
if ((result = sk_X509_new_null()) == NULL)
|
||||
goto err;
|
||||
if (!ossl_cmp_sk_X509_add1_certs(result, chain, 1 /* no self-signed */,
|
||||
1 /* no duplicates */, 0)) {
|
||||
sk_X509_free(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
err:
|
||||
X509_STORE_free(store);
|
||||
X509_STORE_CTX_free(csc);
|
||||
return result;
|
||||
}
|
||||
|
||||
int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
|
||||
const ASN1_OCTET_STRING *src)
|
||||
{
|
||||
if (tgt == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
if (*tgt == src) /* self-assignment */
|
||||
return 1;
|
||||
ASN1_OCTET_STRING_free(*tgt);
|
||||
|
||||
if (src != NULL) {
|
||||
if ((*tgt = ASN1_OCTET_STRING_dup(src)) == NULL)
|
||||
return 0;
|
||||
} else {
|
||||
*tgt = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
|
||||
const unsigned char *bytes, int len)
|
||||
{
|
||||
ASN1_OCTET_STRING *new = NULL;
|
||||
|
||||
if (tgt == NULL) {
|
||||
CMPerr(0, CMP_R_NULL_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
if (bytes != NULL) {
|
||||
if ((new = ASN1_OCTET_STRING_new()) == NULL
|
||||
|| !(ASN1_OCTET_STRING_set(new, bytes, len))) {
|
||||
ASN1_OCTET_STRING_free(new);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ASN1_OCTET_STRING_free(*tgt);
|
||||
*tgt = new;
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user