2 * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright Nokia 2007-2019
4 * Copyright Siemens AG 2015-2019
6 * Licensed under the Apache License 2.0 (the "License"). You may not use
7 * this file except in compliance with the License. You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
12 /* CMP functions for PKIMessage construction */
14 #include "cmp_local.h"
16 /* explicit #includes not strictly needed since implied by the above: */
17 #include <openssl/asn1t.h>
18 #include <openssl/cmp.h>
19 #include <openssl/crmf.h>
20 #include <openssl/err.h>
21 #include <openssl/x509.h>
22 #include "crypto/x509.h" /* for x509_set0_libctx() */
24 OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg)
27 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
33 const char *ossl_cmp_bodytype_to_string(int type)
35 static const char *type_names[] = {
36 "IR", "IP", "CR", "CP", "P10CR",
37 "POPDECC", "POPDECR", "KUR", "KUP",
38 "KRR", "KRP", "RR", "RP", "CCR", "CCP",
39 "CKUANN", "CANN", "RANN", "CRLANN", "PKICONF", "NESTED",
40 "GENM", "GENP", "ERROR", "CERTCONF", "POLLREQ", "POLLREP",
43 if (type < 0 || type > OSSL_CMP_PKIBODY_TYPE_MAX)
44 return "illegal body type";
45 return type_names[type];
48 int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type)
50 if (!ossl_assert(msg != NULL && msg->body != NULL))
53 msg->body->type = type;
57 int ossl_cmp_msg_get_bodytype(const OSSL_CMP_MSG *msg)
59 if (!ossl_assert(msg != NULL && msg->body != NULL))
62 return msg->body->type;
65 /* Add an extension to the referenced extension stack, which may be NULL */
66 static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
71 if (!ossl_assert(pexts != NULL)) /* pointer to var must not be NULL */
74 if ((ext = X509V3_EXT_i2d(nid, crit, ex)) == NULL)
77 res = X509v3_add_ext(pexts, ext, 0) != NULL;
78 X509_EXTENSION_free(ext);
82 /* Add a CRL revocation reason code to extension stack, which may be NULL */
83 static int add_crl_reason_extension(X509_EXTENSIONS **pexts, int reason_code)
85 ASN1_ENUMERATED *val = ASN1_ENUMERATED_new();
88 if (val != NULL && ASN1_ENUMERATED_set(val, reason_code))
89 res = add1_extension(pexts, NID_crl_reason, 0 /* non-critical */, val);
90 ASN1_ENUMERATED_free(val);
94 OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype)
96 OSSL_CMP_MSG *msg = NULL;
98 if (!ossl_assert(ctx != NULL))
101 if ((msg = OSSL_CMP_MSG_new()) == NULL)
103 if (!ossl_cmp_hdr_init(ctx, msg->header)
104 || !ossl_cmp_msg_set_bodytype(msg, bodytype))
106 if (ctx->geninfo_ITAVs != NULL
107 && !ossl_cmp_hdr_generalInfo_push1_items(msg->header,
112 case OSSL_CMP_PKIBODY_IR:
113 case OSSL_CMP_PKIBODY_CR:
114 case OSSL_CMP_PKIBODY_KUR:
115 if ((msg->body->value.ir = OSSL_CRMF_MSGS_new()) == NULL)
119 case OSSL_CMP_PKIBODY_P10CR:
120 if (ctx->p10CSR == NULL) {
121 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_P10CSR);
124 if ((msg->body->value.p10cr = X509_REQ_dup(ctx->p10CSR)) == NULL)
128 case OSSL_CMP_PKIBODY_IP:
129 case OSSL_CMP_PKIBODY_CP:
130 case OSSL_CMP_PKIBODY_KUP:
131 if ((msg->body->value.ip = OSSL_CMP_CERTREPMESSAGE_new()) == NULL)
135 case OSSL_CMP_PKIBODY_RR:
136 if ((msg->body->value.rr = sk_OSSL_CMP_REVDETAILS_new_null()) == NULL)
139 case OSSL_CMP_PKIBODY_RP:
140 if ((msg->body->value.rp = OSSL_CMP_REVREPCONTENT_new()) == NULL)
144 case OSSL_CMP_PKIBODY_CERTCONF:
145 if ((msg->body->value.certConf =
146 sk_OSSL_CMP_CERTSTATUS_new_null()) == NULL)
149 case OSSL_CMP_PKIBODY_PKICONF:
150 if ((msg->body->value.pkiconf = ASN1_TYPE_new()) == NULL)
152 ASN1_TYPE_set(msg->body->value.pkiconf, V_ASN1_NULL, NULL);
155 case OSSL_CMP_PKIBODY_POLLREQ:
156 if ((msg->body->value.pollReq = sk_OSSL_CMP_POLLREQ_new_null()) == NULL)
159 case OSSL_CMP_PKIBODY_POLLREP:
160 if ((msg->body->value.pollRep = sk_OSSL_CMP_POLLREP_new_null()) == NULL)
164 case OSSL_CMP_PKIBODY_GENM:
165 case OSSL_CMP_PKIBODY_GENP:
166 if ((msg->body->value.genm = sk_OSSL_CMP_ITAV_new_null()) == NULL)
170 case OSSL_CMP_PKIBODY_ERROR:
171 if ((msg->body->value.error = OSSL_CMP_ERRORMSGCONTENT_new()) == NULL)
176 ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
181 OSSL_CMP_MSG_free(msg);
185 #define HAS_SAN(ctx) \
186 (sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \
187 || OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1)
189 static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
192 if (ctx->subjectName != NULL)
193 return ctx->subjectName;
195 if (refcert != NULL && (for_KUR || !HAS_SAN(ctx)))
197 * For KUR, copy subjectName from reference certificate.
198 * For IR or CR, do the same only if there is no subjectAltName.
200 return X509_get_subject_name(refcert);
204 OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
206 OSSL_CRMF_MSG *crm = NULL;
207 X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->cert;
208 /* refcert defaults to current client cert */
209 EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
210 STACK_OF(GENERAL_NAME) *default_sans = NULL;
211 const X509_NAME *subject = determine_subj(ctx, refcert, for_KUR);
212 const X509_NAME *issuer = ctx->issuer != NULL || refcert == NULL
213 ? ctx->issuer : X509_get_issuer_name(refcert);
214 int crit = ctx->setSubjectAltNameCritical || subject == NULL;
215 /* RFC5280: subjectAltName MUST be critical if subject is null */
216 X509_EXTENSIONS *exts = NULL;
219 rkey = ctx->pkey; /* default is independent of ctx->oldCert */
221 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
222 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
226 if (for_KUR && refcert == NULL) {
227 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
230 if ((crm = OSSL_CRMF_MSG_new()) == NULL)
232 if (!OSSL_CRMF_MSG_set_certReqId(crm, rid)
234 * fill certTemplate, corresponding to CertificationRequestInfo
235 * of PKCS#10. The rkey param cannot be NULL so far -
236 * it could be NULL if centralized key creation was supported
238 || !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
239 subject, issuer, NULL /* serial */))
241 if (ctx->days != 0) {
242 time_t now = time(NULL);
243 ASN1_TIME *notBefore = ASN1_TIME_adj(NULL, now, 0, 0);
244 ASN1_TIME *notAfter = ASN1_TIME_adj(NULL, now, ctx->days, 0);
246 if (notBefore == NULL
248 || !OSSL_CRMF_MSG_set0_validity(crm, notBefore, notAfter)) {
249 ASN1_TIME_free(notBefore);
250 ASN1_TIME_free(notAfter);
256 if (refcert != NULL && !ctx->SubjectAltName_nodefault)
257 default_sans = X509V3_get_d2i(X509_get0_extensions(refcert),
258 NID_subject_alt_name, NULL, NULL);
259 /* exts are copied from ctx to allow reuse */
260 if (ctx->reqExtensions != NULL) {
261 exts = sk_X509_EXTENSION_deep_copy(ctx->reqExtensions,
263 X509_EXTENSION_free);
267 if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0
268 && !add1_extension(&exts, NID_subject_alt_name,
269 crit, ctx->subjectAltNames))
271 if (!HAS_SAN(ctx) && default_sans != NULL
272 && !add1_extension(&exts, NID_subject_alt_name, crit, default_sans))
274 if (ctx->policies != NULL
275 && !add1_extension(&exts, NID_certificate_policies,
276 ctx->setPoliciesCritical, ctx->policies))
278 if (!OSSL_CRMF_MSG_set0_extensions(crm, exts))
281 /* end fill certTemplate, now set any controls */
283 /* for KUR, set OldCertId according to D.6 */
285 OSSL_CRMF_CERTID *cid =
286 OSSL_CRMF_CERTID_gen(X509_get_issuer_name(refcert),
287 X509_get0_serialNumber(refcert));
292 ret = OSSL_CRMF_MSG_set1_regCtrl_oldCertID(crm, cid);
293 OSSL_CRMF_CERTID_free(cid);
301 OSSL_CRMF_MSG_free(crm);
305 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
306 sk_GENERAL_NAME_pop_free(default_sans, GENERAL_NAME_free);
310 OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type,
311 const OSSL_CRMF_MSG *crm)
314 OSSL_CRMF_MSG *local_crm = NULL;
316 if (!ossl_assert(ctx != NULL))
319 if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR
320 && type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) {
321 ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
325 if ((msg = ossl_cmp_msg_create(ctx, type)) == NULL)
329 if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
333 /* For P10CR the content has already been set in OSSL_CMP_MSG_create */
334 if (type != OSSL_CMP_PKIBODY_P10CR) {
335 EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
338 * privkey is NULL in case ctx->newPkey does not include a private key.
339 * We then may try to use ctx->pkey as fallback/default, but only
340 * if ctx-> newPkey does not include a (non-matching) public key:
342 if (privkey == NULL && OSSL_CMP_CTX_get0_newPkey(ctx, 0) == NULL)
343 privkey = ctx->pkey; /* default is independent of ctx->oldCert */
344 if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
345 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
349 local_crm = OSSL_CMP_CTX_setup_CRM(ctx,
350 type == OSSL_CMP_PKIBODY_KUR,
352 if (local_crm == NULL
353 || !OSSL_CRMF_MSG_create_popo(ctx->popoMethod, local_crm,
354 privkey, ctx->digest,
355 ctx->libctx, ctx->propq))
358 if ((local_crm = OSSL_CRMF_MSG_dup(crm)) == NULL)
362 /* value.ir is same for cr and kur */
363 if (!sk_OSSL_CRMF_MSG_push(msg->body->value.ir, local_crm))
366 /* TODO: here optional 2nd certreqmsg could be pushed to the stack */
369 if (!ossl_cmp_msg_protect(ctx, msg))
375 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREQ);
376 OSSL_CRMF_MSG_free(local_crm);
377 OSSL_CMP_MSG_free(msg);
381 OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
382 int certReqId, OSSL_CMP_PKISI *si,
383 X509 *cert, STACK_OF(X509) *chain,
384 STACK_OF(X509) *caPubs, int encrypted,
385 int unprotectedErrors)
387 OSSL_CMP_MSG *msg = NULL;
388 OSSL_CMP_CERTREPMESSAGE *repMsg = NULL;
389 OSSL_CMP_CERTRESPONSE *resp = NULL;
392 if (!ossl_assert(ctx != NULL && si != NULL))
395 if ((msg = ossl_cmp_msg_create(ctx, bodytype)) == NULL)
397 repMsg = msg->body->value.ip; /* value.ip is same for cp and kup */
400 if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
404 if ((resp = OSSL_CMP_CERTRESPONSE_new()) == NULL)
406 OSSL_CMP_PKISI_free(resp->status);
407 if ((resp->status = OSSL_CMP_PKISI_dup(si)) == NULL
408 || !ASN1_INTEGER_set(resp->certReqId, certReqId))
411 status = ossl_cmp_pkisi_get_status(resp->status);
412 if (status != OSSL_CMP_PKISTATUS_rejection
413 && status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) {
415 ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
419 if ((resp->certifiedKeyPair = OSSL_CMP_CERTIFIEDKEYPAIR_new())
422 resp->certifiedKeyPair->certOrEncCert->type =
423 OSSL_CMP_CERTORENCCERT_CERTIFICATE;
424 if (!X509_up_ref(cert))
426 resp->certifiedKeyPair->certOrEncCert->value.certificate = cert;
429 if (!sk_OSSL_CMP_CERTRESPONSE_push(repMsg->response, resp))
432 /* TODO: here optional 2nd certrep could be pushed to the stack */
434 if (bodytype == OSSL_CMP_PKIBODY_IP && caPubs != NULL
435 && (repMsg->caPubs = X509_chain_up_ref(caPubs)) == NULL)
437 if (sk_X509_num(chain) > 0) {
438 msg->extraCerts = sk_X509_new_reserve(NULL, sk_X509_num(chain));
439 if (msg->extraCerts == NULL
440 || !X509_add_certs(msg->extraCerts, chain,
441 X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
445 if (!unprotectedErrors
446 || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
447 if (!ossl_cmp_msg_protect(ctx, msg))
453 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP);
454 OSSL_CMP_CERTRESPONSE_free(resp);
455 OSSL_CMP_MSG_free(msg);
459 OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
461 OSSL_CMP_MSG *msg = NULL;
462 OSSL_CMP_REVDETAILS *rd;
464 if (!ossl_assert(ctx != NULL && ctx->oldCert != NULL))
467 if ((rd = OSSL_CMP_REVDETAILS_new()) == NULL)
470 /* Fill the template from the contents of the certificate to be revoked */
471 if (!OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
472 NULL /* pubkey would be redundant */,
473 NULL /* subject would be redundant */,
474 X509_get_issuer_name(ctx->oldCert),
475 X509_get0_serialNumber(ctx->oldCert)))
478 /* revocation reason code is optional */
479 if (ctx->revocationReason != CRL_REASON_NONE
480 && !add_crl_reason_extension(&rd->crlEntryDetails,
481 ctx->revocationReason))
484 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RR)) == NULL)
487 if (!sk_OSSL_CMP_REVDETAILS_push(msg->body->value.rr, rd))
492 * TODO: the Revocation Passphrase according to section 5.3.19.9 could be
493 * set here if set in ctx
496 if (!ossl_cmp_msg_protect(ctx, msg))
502 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR);
503 OSSL_CMP_MSG_free(msg);
504 OSSL_CMP_REVDETAILS_free(rd);
508 OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
509 OSSL_CRMF_CERTID *cid, int unprot_err)
511 OSSL_CMP_REVREPCONTENT *rep = NULL;
512 OSSL_CMP_PKISI *si1 = NULL;
513 OSSL_CRMF_CERTID *cid_copy = NULL;
514 OSSL_CMP_MSG *msg = NULL;
516 if (!ossl_assert(ctx != NULL && si != NULL && cid != NULL))
519 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RP)) == NULL)
521 rep = msg->body->value.rp;
523 if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL)
526 if (!sk_OSSL_CMP_PKISI_push(rep->status, si1)) {
527 OSSL_CMP_PKISI_free(si1);
531 if ((rep->revCerts = sk_OSSL_CRMF_CERTID_new_null()) == NULL)
533 if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL)
535 if (!sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) {
536 OSSL_CRMF_CERTID_free(cid_copy);
541 || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
542 if (!ossl_cmp_msg_protect(ctx, msg))
548 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP);
549 OSSL_CMP_MSG_free(msg);
553 OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx)
557 if (!ossl_assert(ctx != NULL))
560 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_PKICONF)) == NULL)
562 if (ossl_cmp_msg_protect(ctx, msg))
566 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
567 OSSL_CMP_MSG_free(msg);
571 int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav)
575 if (!ossl_assert(msg != NULL && itav != NULL))
578 bodytype = ossl_cmp_msg_get_bodytype(msg);
579 if (bodytype != OSSL_CMP_PKIBODY_GENM
580 && bodytype != OSSL_CMP_PKIBODY_GENP) {
581 ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
585 /* value.genp has the same structure, so this works for genp as well */
586 return OSSL_CMP_ITAV_push0_stack_item(&msg->body->value.genm, itav);
589 int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
590 const STACK_OF(OSSL_CMP_ITAV) *itavs)
593 OSSL_CMP_ITAV *itav = NULL;
595 if (!ossl_assert(msg != NULL))
598 for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
599 itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i));
601 || !ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
602 OSSL_CMP_ITAV_free(itav);
610 * Creates a new General Message/Response with an empty itav stack
611 * returns a pointer to the PKIMessage on success, NULL on error
613 static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
614 const STACK_OF(OSSL_CMP_ITAV) *itavs,
615 int body_type, int err_code)
617 OSSL_CMP_MSG *msg = NULL;
619 if (!ossl_assert(ctx != NULL))
622 if ((msg = ossl_cmp_msg_create(ctx, body_type)) == NULL)
625 if (ctx->genm_ITAVs != NULL
626 && !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs))
629 if (!ossl_cmp_msg_protect(ctx, msg))
635 ERR_raise(ERR_LIB_CMP, err_code);
636 OSSL_CMP_MSG_free(msg);
640 OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx)
642 return gen_new(ctx, ctx->genm_ITAVs,
643 OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
646 OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
647 const STACK_OF(OSSL_CMP_ITAV) *itavs)
649 return gen_new(ctx, itavs,
650 OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
653 OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
655 const char *details, int unprotected)
657 OSSL_CMP_MSG *msg = NULL;
658 OSSL_CMP_PKIFREETEXT *ft;
660 if (!ossl_assert(ctx != NULL && si != NULL))
663 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_ERROR)) == NULL)
666 OSSL_CMP_PKISI_free(msg->body->value.error->pKIStatusInfo);
667 if ((msg->body->value.error->pKIStatusInfo = OSSL_CMP_PKISI_dup(si))
670 if (errorCode >= 0) {
671 if ((msg->body->value.error->errorCode = ASN1_INTEGER_new()) == NULL)
673 if (!ASN1_INTEGER_set(msg->body->value.error->errorCode, errorCode))
676 if (details != NULL) {
677 if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL)
679 msg->body->value.error->errorDetails = ft;
680 if (!ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details))
684 if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
689 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_ERROR);
690 OSSL_CMP_MSG_free(msg);
695 * Set the certHash field of a OSSL_CMP_CERTSTATUS structure.
696 * This is used in the certConf message, for example,
697 * to confirm that the certificate was received successfully.
699 int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
700 ASN1_OCTET_STRING *hash)
702 if (!ossl_assert(certStatus != NULL))
704 ASN1_OCTET_STRING_free(certStatus->certHash);
705 certStatus->certHash = hash;
710 * TODO: handle potential 2nd certificate when signing and encrypting
711 * certificates have been requested/received
713 OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
716 OSSL_CMP_MSG *msg = NULL;
717 OSSL_CMP_CERTSTATUS *certStatus = NULL;
718 ASN1_OCTET_STRING *certHash = NULL;
719 OSSL_CMP_PKISI *sinfo;
721 if (!ossl_assert(ctx != NULL && ctx->newCert != NULL))
724 if ((unsigned)fail_info > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
725 ERR_raise(ERR_LIB_CMP, CMP_R_FAIL_INFO_OUT_OF_RANGE);
729 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_CERTCONF)) == NULL)
732 if ((certStatus = OSSL_CMP_CERTSTATUS_new()) == NULL)
734 /* consume certStatus into msg right away so it gets deallocated with msg */
735 if (!sk_OSSL_CMP_CERTSTATUS_push(msg->body->value.certConf, certStatus))
737 /* set the ID of the certReq */
738 if (!ASN1_INTEGER_set(certStatus->certReqId, OSSL_CMP_CERTREQID))
741 * the hash of the certificate, using the same hash algorithm
742 * as is used to create and verify the certificate signature
744 if ((certHash = X509_digest_sig(ctx->newCert)) == NULL)
747 if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
751 * For any particular CertStatus, omission of the statusInfo field
752 * indicates ACCEPTANCE of the specified certificate. Alternatively,
753 * explicit status details (with respect to acceptance or rejection) MAY
754 * be provided in the statusInfo field, perhaps for auditing purposes at
757 sinfo = fail_info != 0 ?
758 OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
759 OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
762 certStatus->statusInfo = sinfo;
764 if (!ossl_cmp_msg_protect(ctx, msg))
770 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTCONF);
771 OSSL_CMP_MSG_free(msg);
772 ASN1_OCTET_STRING_free(certHash);
776 OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid)
778 OSSL_CMP_MSG *msg = NULL;
779 OSSL_CMP_POLLREQ *preq = NULL;
781 if (!ossl_assert(ctx != NULL))
784 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREQ)) == NULL)
787 /* TODO: support multiple cert request IDs to poll */
788 if ((preq = OSSL_CMP_POLLREQ_new()) == NULL
789 || !ASN1_INTEGER_set(preq->certReqId, crid)
790 || !sk_OSSL_CMP_POLLREQ_push(msg->body->value.pollReq, preq))
794 if (!ossl_cmp_msg_protect(ctx, msg))
800 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREQ);
801 OSSL_CMP_POLLREQ_free(preq);
802 OSSL_CMP_MSG_free(msg);
806 OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
810 OSSL_CMP_POLLREP *prep;
812 if (!ossl_assert(ctx != NULL))
815 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREP)) == NULL)
817 if ((prep = OSSL_CMP_POLLREP_new()) == NULL)
819 if (!sk_OSSL_CMP_POLLREP_push(msg->body->value.pollRep, prep))
821 if (!ASN1_INTEGER_set(prep->certReqId, crid))
823 if (!ASN1_INTEGER_set_int64(prep->checkAfter, poll_after))
826 if (!ossl_cmp_msg_protect(ctx, msg))
831 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP);
832 OSSL_CMP_MSG_free(msg);
837 * returns the status field of the RevRepContent with the given
838 * request/sequence id inside a revocation response.
839 * RevRepContent has the revocation statuses in same order as they were sent in
841 * returns NULL on error
844 ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
846 OSSL_CMP_PKISI *status;
848 if (!ossl_assert(rrep != NULL))
851 if ((status = sk_OSSL_CMP_PKISI_value(rrep->status, rsid)) != NULL)
854 ERR_raise(ERR_LIB_CMP, CMP_R_PKISTATUSINFO_NOT_FOUND);
859 * returns the CertId field in the revCerts part of the RevRepContent
860 * with the given request/sequence id inside a revocation response.
861 * RevRepContent has the CertIds in same order as they were sent in
863 * returns NULL on error
866 ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
868 OSSL_CRMF_CERTID *cid = NULL;
870 if (!ossl_assert(rrep != NULL))
873 if ((cid = sk_OSSL_CRMF_CERTID_value(rrep->revCerts, rsid)) != NULL)
876 ERR_raise(ERR_LIB_CMP, CMP_R_CERTID_NOT_FOUND);
880 static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
887 trid = ossl_cmp_asn1_get_int(certReqId);
890 ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
897 * returns a pointer to the PollResponse with the given CertReqId
898 * (or the first one in case -1) inside a PollRepContent
899 * returns NULL on error or if no suitable PollResponse available
902 ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
905 OSSL_CMP_POLLREP *pollRep = NULL;
908 if (!ossl_assert(prc != NULL))
911 for (i = 0; i < sk_OSSL_CMP_POLLREP_num(prc); i++) {
912 pollRep = sk_OSSL_CMP_POLLREP_value(prc, i);
913 if (suitable_rid(pollRep->certReqId, rid))
917 ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
918 "expected certReqId = %d", rid);
923 * returns a pointer to the CertResponse with the given CertReqId
924 * (or the first one in case -1) inside a CertRepMessage
925 * returns NULL on error or if no suitable CertResponse available
927 OSSL_CMP_CERTRESPONSE *
928 ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
931 OSSL_CMP_CERTRESPONSE *crep = NULL;
934 if (!ossl_assert(crm != NULL && crm->response != NULL))
937 for (i = 0; i < sk_OSSL_CMP_CERTRESPONSE_num(crm->response); i++) {
938 crep = sk_OSSL_CMP_CERTRESPONSE_value(crm->response, i);
939 if (suitable_rid(crep->certReqId, rid))
943 ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
944 "expected certReqId = %d", rid);
949 * Retrieve the newly enrolled certificate from the given certResponse crep.
950 * In case of indirect POPO uses the libctx and propq from ctx and private key.
951 * Returns a pointer to a copy of the found certificate, or NULL if not found.
953 X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
954 const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
956 OSSL_CMP_CERTORENCCERT *coec;
959 if (!ossl_assert(crep != NULL && ctx != NULL))
962 if (crep->certifiedKeyPair
963 && (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
964 switch (coec->type) {
965 case OSSL_CMP_CERTORENCCERT_CERTIFICATE:
966 crt = X509_dup(coec->value.certificate);
968 case OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT:
969 /* cert encrypted for indirect PoP; RFC 4210, 5.2.8.2 */
971 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
975 OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(coec->value.encryptedCert,
976 ctx->libctx, ctx->propq,
980 ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE);
985 ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
987 (void)x509_set0_libctx(crt, ctx->libctx, ctx->propq);
991 int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
993 if (ctx == NULL || msg == NULL) {
994 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
997 if (!ossl_cmp_hdr_set_transactionID(ctx, msg->header))
999 return msg->header->protectionAlg == NULL
1000 || ossl_cmp_msg_protect(ctx, msg);
1003 OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file)
1005 OSSL_CMP_MSG *msg = NULL;
1009 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
1013 if ((bio = BIO_new_file(file, "rb")) == NULL)
1015 msg = d2i_OSSL_CMP_MSG_bio(bio, NULL);
1020 int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg)
1025 if (file == NULL || msg == NULL) {
1026 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
1030 bio = BIO_new_file(file, "wb");
1033 res = i2d_OSSL_CMP_MSG_bio(bio, msg);
1038 OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg)
1040 return ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new,
1041 d2i_OSSL_CMP_MSG, bio, msg);
1044 int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
1046 return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);