mirror of https://github.com/openssl/openssl
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:
parent
985429f4f4
commit
d477484d33
94
apps/cmp.c
94
apps/cmp.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue