CMP: add support for genm/genp messages with id-it-caCerts

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/19231)
This commit is contained in:
Dr. David von Oheimb 2021-12-03 18:17:50 +01:00 committed by Dr. David von Oheimb
parent 985429f4f4
commit d477484d33
18 changed files with 409 additions and 43 deletions

View File

@ -277,7 +277,7 @@ const OPTIONS cmp_options[] = {
OPT_SECTION("Generic message"),
{"cmd", OPT_CMD, 's', "CMP request to send: ir/cr/kur/p10cr/rr/genm"},
{"infotype", OPT_INFOTYPE, 's',
"InfoType name for requesting specific info in genm, e.g. 'signKeyPairTypes'"},
"InfoType name for requesting specific info in genm, e.g. 'caCerts'"},
{"geninfo", OPT_GENINFO, 's',
"generalInfo integer values to place in request PKIHeader with given OID"},
{OPT_MORE_STR, 0, 0,
@ -395,7 +395,7 @@ const OPTIONS cmp_options[] = {
{"extracertsout", OPT_EXTRACERTSOUT, 's',
"File to save extra certificates received in the extraCerts field"},
{"cacertsout", OPT_CACERTSOUT, 's',
"File to save CA certificates received in the caPubs field of 'ip' messages"},
"File to save CA certs received in caPubs field or genp with id-it-caCerts"},
OPT_SECTION("Client authentication"),
{"ref", OPT_REF, 's',
@ -1615,6 +1615,8 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
CMP_warn1("-days %s", msg);
if (opt_popo != OSSL_CRMF_POPO_NONE - 1)
CMP_warn1("-popo %s", msg);
if (opt_out_trusted != NULL)
CMP_warn1("-out_trusted %s", msg);
} else if (opt_newkey != NULL) {
const char *file = opt_newkey;
const int format = opt_keyform;
@ -1873,8 +1875,9 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
}
goto set_path;
}
if (!OSSL_HTTP_parse_url(opt_server, &use_ssl, NULL /* user */, &host, &port,
&portnum, &path, NULL /* q */, NULL /* frag */)) {
if (!OSSL_HTTP_parse_url(opt_server, &use_ssl, NULL /* user */,
&host, &port, &portnum,
&path, NULL /* q */, NULL /* frag */)) {
CMP_err1("cannot parse -server URL: %s", opt_server);
goto err;
}
@ -1909,7 +1912,12 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
if (!transform_opts())
goto err;
if (opt_infotype_s != NULL) {
if (opt_infotype_s == NULL) {
if (opt_cmd == CMP_GENM)
CMP_warn("no -infotype option given for genm");
} else if (opt_cmd != CMP_GENM) {
CMP_warn("-infotype option is ignored for commands other than 'genm'");
} else {
char id_buf[100] = "id-it-";
strncat(id_buf, opt_infotype_s, sizeof(id_buf) - strlen(id_buf) - 1);
@ -2136,9 +2144,8 @@ static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs)
if (i2t_ASN1_OBJECT(name, sizeof(name), type) <= 0) {
CMP_err1("error parsing type of ITAV #%d from genp", i);
ret = 0;
}
else {
CMP_info2("ITAV #%d from genp type=%s", i, name);
} else {
CMP_info2("ITAV #%d from genp infoType=%s", i, name);
}
}
return ret;
@ -2829,6 +2836,56 @@ static void print_status(void)
OPENSSL_free(buf);
}
static int do_genm(OSSL_CMP_CTX *ctx)
{
if (opt_infotype == NID_id_it_caCerts) {
STACK_OF(X509) *cacerts = NULL;
if (opt_cacertsout == NULL) {
CMP_err("Missing -cacertsout option for -infotype caCerts");
return 0;
}
if (!OSSL_CMP_get_caCerts(ctx, &cacerts))
return 0;
/* could check authorization of sender/origin at this point */
if (cacerts == NULL) {
CMP_warn("no CA certificates provided by server");
} else if (save_free_certs(cacerts, opt_cacertsout, "CA") < 0) {
CMP_err1("Failed to store CA certficates from genp in %s",
opt_cacertsout);
return 0;
}
return 1;
} else {
OSSL_CMP_ITAV *req;
STACK_OF(OSSL_CMP_ITAV) *itavs;
if (opt_infotype != NID_undef) {
CMP_warn1("No specific support for -infotype %s available",
opt_infotype_s);
req = OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL);
if (req == NULL || !OSSL_CMP_CTX_push0_genm_ITAV(ctx, req)) {
CMP_err1("Failed to create genm for -infotype %s",
opt_infotype_s);
return 0;
}
}
if ((itavs = OSSL_CMP_exec_GENM_ses(ctx)) != NULL) {
int res = print_itavs(itavs);
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
return res;
}
if (OSSL_CMP_CTX_get_status(ctx) != OSSL_CMP_PKISTATUS_request)
CMP_err("Did not receive response on genm or genp is not valid");
return 0;
}
}
int cmp_main(int argc, char **argv)
{
char *configfile = NULL;
@ -3041,26 +3098,7 @@ int cmp_main(int argc, char **argv)
ret = OSSL_CMP_exec_RR_ses(cmp_ctx);
break;
case CMP_GENM:
{
STACK_OF(OSSL_CMP_ITAV) *itavs;
if (opt_infotype != NID_undef) {
OSSL_CMP_ITAV *itav =
OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL);
if (itav == NULL)
goto err;
OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav);
}
if ((itavs = OSSL_CMP_exec_GENM_ses(cmp_ctx)) != NULL) {
ret = print_itavs(itavs);
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
} else {
CMP_err("could not obtain ITAVs from genp");
}
break;
}
ret = do_genm(cmp_ctx);
default:
break;
}

View File

@ -21,7 +21,7 @@ typedef struct
X509 *refCert; /* cert to expect for oldCertID in kur/rr msg */
X509 *certOut; /* certificate to be returned in cp/ip/kup msg */
STACK_OF(X509) *chainOut; /* chain of certOut to add to extraCerts field */
STACK_OF(X509) *caPubsOut; /* certs to return in caPubs field of ip msg */
STACK_OF(X509) *caPubsOut; /* used in caPubs of ip and in caCerts of genp */
OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
int sendError; /* send error response on given request type */
OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */
@ -30,7 +30,6 @@ typedef struct
int checkAfterTime; /* time the client should wait between polling */
} mock_srv_ctx;
static void mock_srv_ctx_free(mock_srv_ctx *ctx)
{
if (ctx == NULL)
@ -332,6 +331,21 @@ static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
if (sk_OSSL_CMP_ITAV_num(in) == 1) {
OSSL_CMP_ITAV *req = sk_OSSL_CMP_ITAV_value(in, 0), *rsp;
ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(req);
if (OBJ_obj2nid(obj) == NID_id_it_caCerts) {
if ((*out = sk_OSSL_CMP_ITAV_new_reserve(NULL, 1)) == NULL)
return 0;
if ((rsp = OSSL_CMP_ITAV_new_caCerts(ctx->caPubsOut)) == NULL) {
sk_OSSL_CMP_ITAV_free(*out);
return 0;
}
(void)sk_OSSL_CMP_ITAV_push(*out, rsp);
return 1;
}
}
*out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup,
OSSL_CMP_ITAV_free);

View File

@ -1,4 +1,4 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \
cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \
cmp_server.c cmp_client.c cmp_http.c
cmp_server.c cmp_client.c cmp_genm.c cmp_http.c

View File

@ -114,10 +114,11 @@ ASN1_ADB(OSSL_CMP_ITAV) = {
ADB_ENTRY(NID_id_it_suppLangTags,
ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.suppLangTagsValue,
ASN1_UTF8STRING)),
ADB_ENTRY(NID_id_it_caCerts,
ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.caCerts, X509)),
} ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
&infotypeandvalue_default_tt, NULL);
ASN1_SEQUENCE(OSSL_CMP_ITAV) = {
ASN1_SIMPLE(OSSL_CMP_ITAV, infoType, ASN1_OBJECT),
ASN1_ADB_OBJECT(OSSL_CMP_ITAV)
@ -183,6 +184,37 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
return 0;
}
OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts)
{
OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new();
if (itav == NULL)
return NULL;
if (sk_X509_num(caCerts) > 0
&& (itav->infoValue.caCerts =
sk_X509_deep_copy(caCerts, X509_dup, X509_free)) == NULL) {
OSSL_CMP_ITAV_free(itav);
return NULL;
}
itav->infoType = OBJ_nid2obj(NID_id_it_caCerts);
return itav;
}
int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out)
{
if (itav == NULL || out == NULL) {
ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (OBJ_obj2nid(itav->infoType) != NID_id_it_caCerts) {
ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
*out = sk_X509_num(itav->infoValue.caCerts) > 0
? itav->infoValue.caCerts : NULL;
return 1;
}
/* get ASN.1 encoded integer, return -1 on error */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
{

View File

@ -84,7 +84,9 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"failure obtaining random"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
"fail info out of range"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GETTING_GENP), "getting genp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_GENP), "invalid genp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CERTID), "missing certid"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),
@ -139,6 +141,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED),
"transactionid unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNCLEAN_CTX), "unclean ctx"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
"unexpected pkistatus"},

179
crypto/cmp/cmp_genm.c Normal file
View File

@ -0,0 +1,179 @@
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Siemens AG 2022
*
* 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 "cmp_local.h"
#include <openssl/cmp_util.h>
static const X509_VERIFY_PARAM *get0_trustedStore_vpm(const OSSL_CMP_CTX *ctx)
{
const X509_STORE *ts = OSSL_CMP_CTX_get0_trustedStore(ctx);
return ts == NULL ? NULL : X509_STORE_get0_param(ts);
}
static void cert_msg(const char *func, const char *file, int lineno,
OSSL_CMP_severity level, OSSL_CMP_CTX *ctx,
const char *source, X509 *cert, const char *msg)
{
char *subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
ossl_cmp_print_log(level, ctx, func, file, lineno,
level == OSSL_CMP_LOG_WARNING ? "WARN" : "ERR",
"certificate from '%s' with subject '%s' %s",
source, subj, msg);
OPENSSL_free(subj);
}
/* use |type_CA| -1 (no CA type check) or 0 (must be EE) or 1 (must be CA) */
static int ossl_X509_check(OSSL_CMP_CTX *ctx, const char *source, X509 *cert,
int type_CA, const X509_VERIFY_PARAM *vpm)
{
uint32_t ex_flags = X509_get_extension_flags(cert);
int res = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
X509_get0_notAfter(cert));
int ret = res == 0;
OSSL_CMP_severity level =
vpm == NULL ? OSSL_CMP_LOG_WARNING : OSSL_CMP_LOG_ERR;
if (!ret)
cert_msg(OPENSSL_FUNC, OPENSSL_FILE, OPENSSL_LINE, level, ctx,
source, cert, res > 0 ? "has expired" : "not yet valid");
if (type_CA >= 0 && (ex_flags & EXFLAG_V1) == 0) {
int is_CA = (ex_flags & EXFLAG_CA) != 0;
if ((type_CA != 0) != is_CA) {
cert_msg(OPENSSL_FUNC, OPENSSL_FILE, OPENSSL_LINE, level, ctx,
source, cert,
is_CA ? "is not an EE cert" : "is not a CA cert");
ret = 0;
}
}
return ret;
}
static int ossl_X509_check_all(OSSL_CMP_CTX *ctx, const char *source,
STACK_OF(X509) *certs,
int type_CA, const X509_VERIFY_PARAM *vpm)
{
int i;
int ret = 1;
for (i = 0; i < sk_X509_num(certs /* may be NULL */); i++)
ret = ossl_X509_check(ctx, source,
sk_X509_value(certs, i), type_CA, vpm)
&& ret; /* Having 'ret' after the '&&', all certs are checked. */
return ret;
}
static OSSL_CMP_ITAV *get_genm_itav(OSSL_CMP_CTX *ctx,
OSSL_CMP_ITAV *req, /* gets consumed */
int expected, const char *desc)
{
STACK_OF(OSSL_CMP_ITAV) *itavs = NULL;
int i, n;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
goto err;
}
if (OSSL_CMP_CTX_get_status(ctx) != OSSL_CMP_PKISTATUS_unspecified) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_UNCLEAN_CTX,
"client context in unsuitable state; should call CMPclient_reinit() before");
goto err;
}
if (!OSSL_CMP_CTX_push0_genm_ITAV(ctx, req))
goto err;
req = NULL;
itavs = OSSL_CMP_exec_GENM_ses(ctx);
if (itavs == NULL) {
if (OSSL_CMP_CTX_get_status(ctx) != OSSL_CMP_PKISTATUS_request)
ERR_raise_data(ERR_LIB_CMP, CMP_R_GETTING_GENP,
"with infoType %s", desc);
return NULL;
}
if ((n = sk_OSSL_CMP_ITAV_num(itavs)) <= 0) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_GENP,
"response on genm requesting infoType %s does not include suitable value", desc);
sk_OSSL_CMP_ITAV_free(itavs);
return NULL;
}
if (n > 1)
ossl_cmp_log2(WARN, ctx,
"response on genm contains %d ITAVs; will use the first ITAV with infoType id-it-%s",
n, desc);
for (i = 0; i < n; i++) {
OSSL_CMP_ITAV *itav = sk_OSSL_CMP_ITAV_shift(itavs);
ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(itav);
char name[128] = "genp contains InfoType '";
size_t offset = strlen(name);
if (OBJ_obj2nid(obj) == expected) {
for (i++; i < n; i++)
OSSL_CMP_ITAV_free(sk_OSSL_CMP_ITAV_shift(itavs));
sk_OSSL_CMP_ITAV_free(itavs);
return itav;
}
if (OBJ_obj2txt(name + offset, sizeof(name) - offset, obj, 0) < 0)
strcat(name, "<unknown>");
ossl_cmp_log2(WARN, ctx, "%s' while expecting 'id-it-%s'", name, desc);
OSSL_CMP_ITAV_free(itav);
}
ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_GENP,
"could not find any ITAV for %s", desc);
err:
sk_OSSL_CMP_ITAV_free(itavs);
OSSL_CMP_ITAV_free(req);
return NULL;
}
int OSSL_CMP_get_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out)
{
OSSL_CMP_ITAV *req, *itav;
STACK_OF(X509) *certs = NULL;
int ret = 0;
if (out == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
*out = NULL;
if ((req = OSSL_CMP_ITAV_new_caCerts(NULL)) == NULL)
return 0;
if ((itav = get_genm_itav(ctx, req, NID_id_it_caCerts, "caCerts")) == NULL)
return 0;
if (!OSSL_CMP_ITAV_get0_caCerts(itav, &certs))
goto end;
ret = 1;
if (certs == NULL) /* no CA certificate available */
goto end;
if (!ossl_X509_check_all(ctx, "genp", certs, 1 /* CA */,
get0_trustedStore_vpm(ctx))) {
ret = 0;
goto end;
}
*out = sk_X509_new_reserve(NULL, sk_X509_num(certs));
if (!X509_add_certs(*out, certs,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP)) {
sk_X509_pop_free(*out, X509_free);
*out = NULL;
ret = 0;
}
end:
OSSL_CMP_ITAV_free(itav);
return ret;
}

View File

@ -247,6 +247,8 @@ struct ossl_cmp_itav_st {
OSSL_CMP_MSGS *origPKIMessage;
/* NID_id_it_suppLangTags - Supported Language Tags */
STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
/* NID_id_it_caCerts - CA Certificates */
STACK_OF(X509) *caCerts;
/* this is to be used for so far undeclared objects */
ASN1_TYPE *other;
} infoValue;

View File

@ -672,7 +672,7 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
}
/*
* Creates a new General Message/Response with an empty itav stack
* Creates a new General Message/Response with a copy of the given itav stack
* returns a pointer to the PKIMessage on success, NULL on error
*/
static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,

View File

@ -231,7 +231,9 @@ CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain
CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
CMP_R_FAIL_INFO_OUT_OF_RANGE:129:fail info out of range
CMP_R_GETTING_GENP:192:getting genp
CMP_R_INVALID_ARGS:100:invalid args
CMP_R_INVALID_GENP:193:invalid genp
CMP_R_INVALID_OPTION:174:invalid option
CMP_R_MISSING_CERTID:165:missing certid
CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\
@ -268,6 +270,7 @@ CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg
CMP_R_TOTAL_TIMEOUT:184:total timeout
CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
CMP_R_TRANSFER_ERROR:159:transfer error
CMP_R_UNCLEAN_CTX:191:unclean ctx
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
CMP_R_UNEXPECTED_PVNO:153:unexpected pvno

View File

@ -1591,6 +1591,10 @@ DEPEND[html/man3/OSSL_CMP_HDR_get0_transactionID.html]=man3/OSSL_CMP_HDR_get0_tr
GENERATE[html/man3/OSSL_CMP_HDR_get0_transactionID.html]=man3/OSSL_CMP_HDR_get0_transactionID.pod
DEPEND[man/man3/OSSL_CMP_HDR_get0_transactionID.3]=man3/OSSL_CMP_HDR_get0_transactionID.pod
GENERATE[man/man3/OSSL_CMP_HDR_get0_transactionID.3]=man3/OSSL_CMP_HDR_get0_transactionID.pod
DEPEND[html/man3/OSSL_CMP_ITAV_new_caCerts.html]=man3/OSSL_CMP_ITAV_new_caCerts.pod
GENERATE[html/man3/OSSL_CMP_ITAV_new_caCerts.html]=man3/OSSL_CMP_ITAV_new_caCerts.pod
DEPEND[man/man3/OSSL_CMP_ITAV_new_caCerts.3]=man3/OSSL_CMP_ITAV_new_caCerts.pod
GENERATE[man/man3/OSSL_CMP_ITAV_new_caCerts.3]=man3/OSSL_CMP_ITAV_new_caCerts.pod
DEPEND[html/man3/OSSL_CMP_ITAV_set0.html]=man3/OSSL_CMP_ITAV_set0.pod
GENERATE[html/man3/OSSL_CMP_ITAV_set0.html]=man3/OSSL_CMP_ITAV_set0.pod
DEPEND[man/man3/OSSL_CMP_ITAV_set0.3]=man3/OSSL_CMP_ITAV_set0.pod
@ -3289,6 +3293,7 @@ html/man3/OSSL_ALGORITHM.html \
html/man3/OSSL_CALLBACK.html \
html/man3/OSSL_CMP_CTX_new.html \
html/man3/OSSL_CMP_HDR_get0_transactionID.html \
html/man3/OSSL_CMP_ITAV_new_caCerts.html \
html/man3/OSSL_CMP_ITAV_set0.html \
html/man3/OSSL_CMP_MSG_get0_header.html \
html/man3/OSSL_CMP_MSG_http_perform.html \
@ -3924,6 +3929,7 @@ man/man3/OSSL_ALGORITHM.3 \
man/man3/OSSL_CALLBACK.3 \
man/man3/OSSL_CMP_CTX_new.3 \
man/man3/OSSL_CMP_HDR_get0_transactionID.3 \
man/man3/OSSL_CMP_ITAV_new_caCerts.3 \
man/man3/OSSL_CMP_ITAV_set0.3 \
man/man3/OSSL_CMP_MSG_get0_header.3 \
man/man3/OSSL_CMP_MSG_http_perform.3 \

View File

@ -45,16 +45,17 @@ ossl_cmp_mock_srv_set1_refCert() sets the reference certificate to be expected
for rr messages and for any oldCertID included in kur messages.
ossl_cmp_mock_srv_set1_certOut() sets the certificate to be returned in
cp/ip/kup.
cp/ip/kup messages.
Note that on each certificate request the mock server does not produce
a fresh certificate but just returns the same pre-existing certificate.
ossl_cmp_mock_srv_set1_chainOut() sets the certificate chain to be added to
the extraCerts in a cp/ip/kup.
the extraCerts in a cp/ip/kup message.
It should be useful for the validation of the certificate given via
ossl_cmp_mock_srv_set1_certOut().
ossl_cmp_mock_srv_set1_caPubsOut() sets the caPubs to be returned in an ip.
ossl_cmp_mock_srv_set1_caPubsOut() sets the caPubs to be returned in an ip msg
and the list of certificates to be returned in a genp of infoType caCerts.
ossl_cmp_mock_srv_set_statusInfo() sets the status info to be returned.

View File

@ -236,6 +236,7 @@ ITAV B<infoType>s is printed to stdout.
Set InfoType name to use for requesting specific info in B<genm>,
e.g., C<signKeyPairTypes>.
So far, there is specific support for C<caCerts>.
=item B<-geninfo> I<OID:int:N>
@ -655,7 +656,8 @@ field of the last received response message that is not a pollRep nor PKIConf.
=item B<-cacertsout> I<filename>
The file where to save the list of CA certificates contained in the caPubs field
if a positive certificate response (i.e., IP, CP, or KUP) message was received.
if a positive certificate response (i.e., IP, CP, or KUP) message was received
or contained in a general response (genp) message with infoType C<caCerts>.
=back

View File

@ -0,0 +1,59 @@
=pod
=head1 NAME
OSSL_CMP_ITAV_new_caCerts,
OSSL_CMP_ITAV_get0_caCerts
- CMP utility functions for handling specific genm and genp messages
=head1 SYNOPSIS
#include <openssl/cmp.h>
OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts);
int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out);
=head1 DESCRIPTION
ITAV is short for InfoTypeAndValue.
OSSL_CMP_ITAV_new_caCerts() creates an B<OSSL_CMP_ITAV> structure of type
B<caCerts> and fills it with a copy of the provided list of certificates.
The I<caCerts> argument may be NULL or contain any number of certificates.
OSSL_CMP_ITAV_get0_caCerts() requires that I<itav> has type B<caCerts>.
It assigns NULL to I<*out> if there are no CA certificates in I<itav>, otherwise
the internal pointer of type B<STACK_OF(X509)> with the certificates present.
=head1 NOTES
CMP is defined in RFC 4210.
=head1 RETURN VALUES
OSSL_CMP_ITAV_new_caCerts()
returns a pointer to the new ITAV structure on success, or NULL on error.
OSSL_CMP_ITAV_get0_caCerts()
returns 1 on success, 0 on error.
=head1 SEE ALSO
L<OSSL_CMP_ITAV_create(3)> and L<OSSL_CMP_ITAV_get0_type(3)>
=head1 HISTORY
OSSL_CMP_ITAV_new_caCerts() and
OSSL_CMP_ITAV_get0_rootCaCert()
were added in OpenSSL 3.2.
=head1 COPYRIGHT
Copyright 2022 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
L<https://www.openssl.org/source/license.html>.
=cut

View File

@ -13,7 +13,8 @@ OSSL_CMP_P10CR,
OSSL_CMP_KUR,
OSSL_CMP_try_certreq,
OSSL_CMP_exec_RR_ses,
OSSL_CMP_exec_GENM_ses
OSSL_CMP_exec_GENM_ses,
OSSL_CMP_get_caCerts
- functions implementing CMP client transactions
=head1 SYNOPSIS
@ -34,6 +35,7 @@ OSSL_CMP_exec_GENM_ses
const OSSL_CRMF_MSG *crm, int *checkAfter);
int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
int OSSL_CMP_get_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out);
=head1 DESCRIPTION
@ -115,6 +117,12 @@ and returns the list of B<ITAV>s received in the GENP message.
This can be used, for instance, to poll for CRLs or CA Key Updates.
See RFC 4210 section 5.3.19 and appendix E.5 for details.
OSSL_CMP_get_caCerts() uses a genm/gemp message exchange with infoType caCerts
to obtain a list of CA certificates from the CMP server referenced by I<ctx>.
On success it assigns to I<*out> the list of certificates received,
which must be freed by the caller.
NULL means that no CA certificate is available at the server.
=head1 NOTES
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
@ -138,7 +146,8 @@ In the latter case L<OSSL_CMP_CTX_get0_newCert(3)> yields NULL
and the output parameter I<checkAfter> has been used to
assign the received value unless I<checkAfter> is NULL.
OSSL_CMP_exec_RR_ses() returns 1 on success, 0 on error.
OSSL_CMP_exec_RR_ses() and OSSL_CMP_get_caCerts()
return 1 on success, 0 on error.
OSSL_CMP_exec_GENM_ses() returns NULL on error,
otherwise a pointer to the sequence of B<ITAV> received, which may be empty.
@ -161,6 +170,8 @@ L<OSSL_CMP_MSG_http_perform(3)>
The OpenSSL CMP support was added in OpenSSL 3.0.
OSSL_CMP_get_caCerts() was added in OpenSSL 3.2.
=head1 COPYRIGHT
Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.

View File

@ -140,7 +140,6 @@ extern "C" {
# if OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN > INT_MAX
# error CMP_PKIFAILUREINFO_MAX bit pattern does not fit in type int
# endif
typedef ASN1_BIT_STRING OSSL_CMP_PKIFAILUREINFO;
# define OSSL_CMP_CTX_FAILINFO_badAlg (1 << 0)
@ -206,8 +205,8 @@ typedef ASN1_BIT_STRING OSSL_CMP_PKIFAILUREINFO;
# define OSSL_CMP_PKISTATUS_revocationWarning 4
# define OSSL_CMP_PKISTATUS_revocationNotification 5
# define OSSL_CMP_PKISTATUS_keyUpdateWarning 6
typedef ASN1_INTEGER OSSL_CMP_PKISTATUS;
DECLARE_ASN1_ITEM(OSSL_CMP_PKISTATUS)
# define OSSL_CMP_CERTORENCCERT_CERTIFICATE 0
@ -261,6 +260,10 @@ ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav);
int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
OSSL_CMP_ITAV *itav);
void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav);
OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts);
int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out);
void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
/* from cmp_ctx.c */
@ -317,9 +320,9 @@ void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_set1_srvCert(OSSL_CMP_CTX *ctx, X509 *cert);
int OSSL_CMP_CTX_set1_expected_sender(OSSL_CMP_CTX *ctx, const X509_NAME *name);
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store);
#define OSSL_CMP_CTX_set0_trusted OSSL_CMP_CTX_set0_trustedStore
# define OSSL_CMP_CTX_set0_trusted OSSL_CMP_CTX_set0_trustedStore
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx);
#define OSSL_CMP_CTX_get0_trusted OSSL_CMP_CTX_get0_trustedStore
# define OSSL_CMP_CTX_get0_trusted OSSL_CMP_CTX_get0_trustedStore
int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs);
STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx);
/* client authentication: */
@ -478,6 +481,9 @@ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
/* from cmp_genm.c */
int OSSL_CMP_get_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out);
# ifdef __cplusplus
}
# endif

View File

@ -59,7 +59,9 @@
# define CMP_R_FAILED_EXTRACTING_PUBKEY 141
# define CMP_R_FAILURE_OBTAINING_RANDOM 110
# define CMP_R_FAIL_INFO_OUT_OF_RANGE 129
# define CMP_R_GETTING_GENP 192
# define CMP_R_INVALID_ARGS 100
# define CMP_R_INVALID_GENP 193
# define CMP_R_INVALID_OPTION 174
# define CMP_R_MISSING_CERTID 165
# define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION 130
@ -94,6 +96,7 @@
# define CMP_R_TOTAL_TIMEOUT 184
# define CMP_R_TRANSACTIONID_UNMATCHED 152
# define CMP_R_TRANSFER_ERROR 159
# define CMP_R_UNCLEAN_CTX 191
# define CMP_R_UNEXPECTED_PKIBODY 133
# define CMP_R_UNEXPECTED_PKISTATUS 185
# define CMP_R_UNEXPECTED_PVNO 153

View File

@ -44,8 +44,12 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty
0,revreason out of integer range, -section,, -cmd,rr,,BLANK,,,BLANK,,, -oldcert,_RESULT_DIR/test.cert.pem, -revreason,010000000000000000000
,,,,,,,,,,,,,,,,,
1,ir + infotype, -section,, -cmd,ir,,BLANK,,, -infotype,signKeyPairTypes,,BLANK,,BLANK,
1,genm without -infotype, -section,, -cmd,genm,,BLANK,,, BLANK,,,BLANK,,BLANK,
0,genm with missing infotype value, -section,, -cmd,genm,,BLANK,,, -infotype,,,BLANK,,BLANK,
0,genm with invalid infotype value, -section,, -cmd,genm,,BLANK,,, -infotype,asdf,,BLANK,,BLANK,
1,genm with infotype signKeyPairTypes, -section,, -cmd,genm,,BLANK,,, -infotype,signKeyPairTypes,,BLANK,,BLANK,
0,genm with infotype caCerts but missing -cacertsout, -section,, -cmd,genm,,BLANK,,, -infotype,caCerts,,BLANK,,BLANK,
1,genm with infotype caCerts, -section,, -cmd,genm,, -cacertsout,_RESULT_DIR/test.cacerts.pem,, -infotype,caCerts,,BLANK,,BLANK,
,,,,,,,,,,,,,,,,,,,,,,
1,geninfo, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int:987,BLANK,,BLANK,
0,geninfo missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,,,,,

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -5445,6 +5445,9 @@ BN_signed_bn2native ? 3_2_0 EXIST::FUNCTION:
ASYNC_set_mem_functions ? 3_2_0 EXIST::FUNCTION:
ASYNC_get_mem_functions ? 3_2_0 EXIST::FUNCTION:
BIO_ADDR_dup ? 3_2_0 EXIST::FUNCTION:SOCK
OSSL_CMP_ITAV_new_caCerts ? 3_2_0 EXIST::FUNCTION:CMP
OSSL_CMP_ITAV_get0_caCerts ? 3_2_0 EXIST::FUNCTION:CMP
OSSL_CMP_get_caCerts ? 3_2_0 EXIST::FUNCTION:CMP
OSSL_CMP_CTX_get0_libctx ? 3_2_0 EXIST::FUNCTION:CMP
OSSL_CMP_CTX_get0_propq ? 3_2_0 EXIST::FUNCTION:CMP
OSSL_CMP_CTX_reset_geninfo_ITAVs ? 3_0_8 EXIST::FUNCTION:CMP