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 CMPerr(0, 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 CMPerr(0, 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 CMPerr(0, 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 int crit = ctx->setSubjectAltNameCritical || subject == NULL;
213 /* RFC5280: subjectAltName MUST be critical if subject is null */
214 X509_EXTENSIONS *exts = NULL;
217 rkey = ctx->pkey; /* default is independent of ctx->oldCert */
219 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
220 CMPerr(0, CMP_R_NULL_ARGUMENT);
224 if (for_KUR && refcert == NULL) {
225 CMPerr(0, CMP_R_MISSING_REFERENCE_CERT);
228 if ((crm = OSSL_CRMF_MSG_new()) == NULL)
230 if (!OSSL_CRMF_MSG_set_certReqId(crm, rid)
232 * fill certTemplate, corresponding to CertificationRequestInfo
233 * of PKCS#10. The rkey param cannot be NULL so far -
234 * it could be NULL if centralized key creation was supported
236 || !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
237 subject, ctx->issuer,
240 if (ctx->days != 0) {
241 time_t now = time(NULL);
242 ASN1_TIME *notBefore = ASN1_TIME_adj(NULL, now, 0, 0);
243 ASN1_TIME *notAfter = ASN1_TIME_adj(NULL, now, ctx->days, 0);
245 if (notBefore == NULL
247 || !OSSL_CRMF_MSG_set0_validity(crm, notBefore, notAfter)) {
248 ASN1_TIME_free(notBefore);
249 ASN1_TIME_free(notAfter);
255 if (refcert != NULL && !ctx->SubjectAltName_nodefault)
256 default_sans = X509V3_get_d2i(X509_get0_extensions(refcert),
257 NID_subject_alt_name, NULL, NULL);
258 /* exts are copied from ctx to allow reuse */
259 if (ctx->reqExtensions != NULL) {
260 exts = sk_X509_EXTENSION_deep_copy(ctx->reqExtensions,
262 X509_EXTENSION_free);
266 if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0
267 && !add1_extension(&exts, NID_subject_alt_name,
268 crit, ctx->subjectAltNames))
270 if (!HAS_SAN(ctx) && default_sans != NULL
271 && !add1_extension(&exts, NID_subject_alt_name, crit, default_sans))
273 if (ctx->policies != NULL
274 && !add1_extension(&exts, NID_certificate_policies,
275 ctx->setPoliciesCritical, ctx->policies))
277 if (!OSSL_CRMF_MSG_set0_extensions(crm, exts))
280 /* end fill certTemplate, now set any controls */
282 /* for KUR, set OldCertId according to D.6 */
284 OSSL_CRMF_CERTID *cid =
285 OSSL_CRMF_CERTID_gen(X509_get_issuer_name(refcert),
286 X509_get0_serialNumber(refcert));
291 ret = OSSL_CRMF_MSG_set1_regCtrl_oldCertID(crm, cid);
292 OSSL_CRMF_CERTID_free(cid);
300 OSSL_CRMF_MSG_free(crm);
304 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
305 sk_GENERAL_NAME_pop_free(default_sans, GENERAL_NAME_free);
309 OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type,
310 const OSSL_CRMF_MSG *crm)
313 OSSL_CRMF_MSG *local_crm = NULL;
315 if (!ossl_assert(ctx != NULL))
318 if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR
319 && type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) {
320 CMPerr(0, CMP_R_INVALID_ARGS);
324 if ((msg = ossl_cmp_msg_create(ctx, type)) == NULL)
328 if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
332 /* For P10CR the content has already been set in OSSL_CMP_MSG_create */
333 if (type != OSSL_CMP_PKIBODY_P10CR) {
334 EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
337 privkey = ctx->pkey; /* default is independent of ctx->oldCert */
338 if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
339 CMPerr(0, CMP_R_MISSING_PRIVATE_KEY);
343 local_crm = OSSL_CMP_CTX_setup_CRM(ctx,
344 type == OSSL_CMP_PKIBODY_KUR,
346 if (local_crm == NULL
347 || !OSSL_CRMF_MSG_create_popo(ctx->popoMethod, local_crm,
348 privkey, ctx->digest,
349 ctx->libctx, ctx->propq))
352 if ((local_crm = OSSL_CRMF_MSG_dup(crm)) == NULL)
356 /* value.ir is same for cr and kur */
357 if (!sk_OSSL_CRMF_MSG_push(msg->body->value.ir, local_crm))
360 /* TODO: here optional 2nd certreqmsg could be pushed to the stack */
363 if (!ossl_cmp_msg_protect(ctx, msg))
369 CMPerr(0, CMP_R_ERROR_CREATING_CERTREQ);
370 OSSL_CRMF_MSG_free(local_crm);
371 OSSL_CMP_MSG_free(msg);
375 OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
376 int certReqId, OSSL_CMP_PKISI *si,
377 X509 *cert, STACK_OF(X509) *chain,
378 STACK_OF(X509) *caPubs, int encrypted,
379 int unprotectedErrors)
381 OSSL_CMP_MSG *msg = NULL;
382 OSSL_CMP_CERTREPMESSAGE *repMsg = NULL;
383 OSSL_CMP_CERTRESPONSE *resp = NULL;
386 if (!ossl_assert(ctx != NULL && si != NULL))
389 if ((msg = ossl_cmp_msg_create(ctx, bodytype)) == NULL)
391 repMsg = msg->body->value.ip; /* value.ip is same for cp and kup */
394 if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
398 if ((resp = OSSL_CMP_CERTRESPONSE_new()) == NULL)
400 OSSL_CMP_PKISI_free(resp->status);
401 if ((resp->status = OSSL_CMP_PKISI_dup(si)) == NULL
402 || !ASN1_INTEGER_set(resp->certReqId, certReqId))
405 status = ossl_cmp_pkisi_get_status(resp->status);
406 if (status != OSSL_CMP_PKISTATUS_rejection
407 && status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) {
409 CMPerr(0, CMP_R_INVALID_ARGS);
413 if ((resp->certifiedKeyPair = OSSL_CMP_CERTIFIEDKEYPAIR_new())
416 resp->certifiedKeyPair->certOrEncCert->type =
417 OSSL_CMP_CERTORENCCERT_CERTIFICATE;
418 if (!X509_up_ref(cert))
420 resp->certifiedKeyPair->certOrEncCert->value.certificate = cert;
423 if (!sk_OSSL_CMP_CERTRESPONSE_push(repMsg->response, resp))
426 /* TODO: here optional 2nd certrep could be pushed to the stack */
428 if (bodytype == OSSL_CMP_PKIBODY_IP && caPubs != NULL
429 && (repMsg->caPubs = X509_chain_up_ref(caPubs)) == NULL)
431 if (sk_X509_num(chain) > 0) {
432 msg->extraCerts = sk_X509_new_reserve(NULL, sk_X509_num(chain));
433 if (msg->extraCerts == NULL
434 || !X509_add_certs(msg->extraCerts, chain,
435 X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
439 if (!unprotectedErrors
440 || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
441 if (!ossl_cmp_msg_protect(ctx, msg))
447 CMPerr(0, CMP_R_ERROR_CREATING_CERTREP);
448 OSSL_CMP_CERTRESPONSE_free(resp);
449 OSSL_CMP_MSG_free(msg);
453 OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
455 OSSL_CMP_MSG *msg = NULL;
456 OSSL_CMP_REVDETAILS *rd;
458 if (!ossl_assert(ctx != NULL && ctx->oldCert != NULL))
461 if ((rd = OSSL_CMP_REVDETAILS_new()) == NULL)
464 /* Fill the template from the contents of the certificate to be revoked */
465 if (!OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
466 NULL /* pubkey would be redundant */,
467 NULL /* subject would be redundant */,
468 X509_get_issuer_name(ctx->oldCert),
469 X509_get0_serialNumber(ctx->oldCert)))
472 /* revocation reason code is optional */
473 if (ctx->revocationReason != CRL_REASON_NONE
474 && !add_crl_reason_extension(&rd->crlEntryDetails,
475 ctx->revocationReason))
478 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RR)) == NULL)
481 if (!sk_OSSL_CMP_REVDETAILS_push(msg->body->value.rr, rd))
486 * TODO: the Revocation Passphrase according to section 5.3.19.9 could be
487 * set here if set in ctx
490 if (!ossl_cmp_msg_protect(ctx, msg))
496 CMPerr(0, CMP_R_ERROR_CREATING_RR);
497 OSSL_CMP_MSG_free(msg);
498 OSSL_CMP_REVDETAILS_free(rd);
502 OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
503 OSSL_CRMF_CERTID *cid, int unprot_err)
505 OSSL_CMP_REVREPCONTENT *rep = NULL;
506 OSSL_CMP_PKISI *si1 = NULL;
507 OSSL_CRMF_CERTID *cid_copy = NULL;
508 OSSL_CMP_MSG *msg = NULL;
510 if (!ossl_assert(ctx != NULL && si != NULL && cid != NULL))
513 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RP)) == NULL)
515 rep = msg->body->value.rp;
517 if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL)
520 if (!sk_OSSL_CMP_PKISI_push(rep->status, si1)) {
521 OSSL_CMP_PKISI_free(si1);
525 if ((rep->revCerts = sk_OSSL_CRMF_CERTID_new_null()) == NULL)
527 if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL)
529 if (!sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) {
530 OSSL_CRMF_CERTID_free(cid_copy);
535 || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
536 if (!ossl_cmp_msg_protect(ctx, msg))
542 CMPerr(0, CMP_R_ERROR_CREATING_RP);
543 OSSL_CMP_MSG_free(msg);
547 OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx)
551 if (!ossl_assert(ctx != NULL))
554 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_PKICONF)) == NULL)
556 if (ossl_cmp_msg_protect(ctx, msg))
560 CMPerr(0, CMP_R_ERROR_CREATING_PKICONF);
561 OSSL_CMP_MSG_free(msg);
565 int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav)
569 if (!ossl_assert(msg != NULL && itav != NULL))
572 bodytype = ossl_cmp_msg_get_bodytype(msg);
573 if (bodytype != OSSL_CMP_PKIBODY_GENM
574 && bodytype != OSSL_CMP_PKIBODY_GENP) {
575 CMPerr(0, CMP_R_INVALID_ARGS);
579 /* value.genp has the same structure, so this works for genp as well */
580 return OSSL_CMP_ITAV_push0_stack_item(&msg->body->value.genm, itav);
583 int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
584 const STACK_OF(OSSL_CMP_ITAV) *itavs)
587 OSSL_CMP_ITAV *itav = NULL;
589 if (!ossl_assert(msg != NULL))
592 for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
593 itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i));
595 || !ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
596 OSSL_CMP_ITAV_free(itav);
604 * Creates a new General Message/Response with an empty itav stack
605 * returns a pointer to the PKIMessage on success, NULL on error
607 static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
608 const STACK_OF(OSSL_CMP_ITAV) *itavs,
609 int body_type, int err_code)
611 OSSL_CMP_MSG *msg = NULL;
613 if (!ossl_assert(ctx != NULL))
616 if ((msg = ossl_cmp_msg_create(ctx, body_type)) == NULL)
619 if (ctx->genm_ITAVs != NULL
620 && !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs))
623 if (!ossl_cmp_msg_protect(ctx, msg))
630 OSSL_CMP_MSG_free(msg);
634 OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx)
636 return gen_new(ctx, ctx->genm_ITAVs,
637 OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
640 OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
641 const STACK_OF(OSSL_CMP_ITAV) *itavs)
643 return gen_new(ctx, itavs,
644 OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
647 OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
649 const char *details, int unprotected)
651 OSSL_CMP_MSG *msg = NULL;
652 OSSL_CMP_PKIFREETEXT *ft;
654 if (!ossl_assert(ctx != NULL && si != NULL))
657 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_ERROR)) == NULL)
660 OSSL_CMP_PKISI_free(msg->body->value.error->pKIStatusInfo);
661 if ((msg->body->value.error->pKIStatusInfo = OSSL_CMP_PKISI_dup(si))
664 if (errorCode >= 0) {
665 if ((msg->body->value.error->errorCode = ASN1_INTEGER_new()) == NULL)
667 if (!ASN1_INTEGER_set(msg->body->value.error->errorCode, errorCode))
670 if (details != NULL) {
671 if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL)
673 msg->body->value.error->errorDetails = ft;
674 if (!ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details))
678 if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
683 CMPerr(0, CMP_R_ERROR_CREATING_ERROR);
684 OSSL_CMP_MSG_free(msg);
689 * Set the certHash field of a OSSL_CMP_CERTSTATUS structure.
690 * This is used in the certConf message, for example,
691 * to confirm that the certificate was received successfully.
693 int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
694 ASN1_OCTET_STRING *hash)
696 if (!ossl_assert(certStatus != NULL))
698 ASN1_OCTET_STRING_free(certStatus->certHash);
699 certStatus->certHash = hash;
704 * TODO: handle potential 2nd certificate when signing and encrypting
705 * certificates have been requested/received
707 OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
710 OSSL_CMP_MSG *msg = NULL;
711 OSSL_CMP_CERTSTATUS *certStatus = NULL;
712 ASN1_OCTET_STRING *certHash = NULL;
713 OSSL_CMP_PKISI *sinfo;
715 if (!ossl_assert(ctx != NULL && ctx->newCert != NULL))
718 if ((unsigned)fail_info > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
719 CMPerr(0, CMP_R_FAIL_INFO_OUT_OF_RANGE);
723 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_CERTCONF)) == NULL)
726 if ((certStatus = OSSL_CMP_CERTSTATUS_new()) == NULL)
728 /* consume certStatus into msg right away so it gets deallocated with msg */
729 if (!sk_OSSL_CMP_CERTSTATUS_push(msg->body->value.certConf, certStatus))
731 /* set the ID of the certReq */
732 if (!ASN1_INTEGER_set(certStatus->certReqId, OSSL_CMP_CERTREQID))
735 * the hash of the certificate, using the same hash algorithm
736 * as is used to create and verify the certificate signature
738 if ((certHash = X509_digest_sig(ctx->newCert)) == NULL)
741 if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
745 * For any particular CertStatus, omission of the statusInfo field
746 * indicates ACCEPTANCE of the specified certificate. Alternatively,
747 * explicit status details (with respect to acceptance or rejection) MAY
748 * be provided in the statusInfo field, perhaps for auditing purposes at
751 sinfo = fail_info != 0 ?
752 OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
753 OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
756 certStatus->statusInfo = sinfo;
758 if (!ossl_cmp_msg_protect(ctx, msg))
764 CMPerr(0, CMP_R_ERROR_CREATING_CERTCONF);
765 OSSL_CMP_MSG_free(msg);
766 ASN1_OCTET_STRING_free(certHash);
770 OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid)
772 OSSL_CMP_MSG *msg = NULL;
773 OSSL_CMP_POLLREQ *preq = NULL;
775 if (!ossl_assert(ctx != NULL))
778 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREQ)) == NULL)
781 /* TODO: support multiple cert request IDs to poll */
782 if ((preq = OSSL_CMP_POLLREQ_new()) == NULL
783 || !ASN1_INTEGER_set(preq->certReqId, crid)
784 || !sk_OSSL_CMP_POLLREQ_push(msg->body->value.pollReq, preq))
788 if (!ossl_cmp_msg_protect(ctx, msg))
794 CMPerr(0, CMP_R_ERROR_CREATING_POLLREQ);
795 OSSL_CMP_POLLREQ_free(preq);
796 OSSL_CMP_MSG_free(msg);
800 OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
804 OSSL_CMP_POLLREP *prep;
806 if (!ossl_assert(ctx != NULL))
809 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREP)) == NULL)
811 if ((prep = OSSL_CMP_POLLREP_new()) == NULL)
813 if (!sk_OSSL_CMP_POLLREP_push(msg->body->value.pollRep, prep))
815 if (!ASN1_INTEGER_set(prep->certReqId, crid))
817 if (!ASN1_INTEGER_set_int64(prep->checkAfter, poll_after))
820 if (!ossl_cmp_msg_protect(ctx, msg))
825 CMPerr(0, CMP_R_ERROR_CREATING_POLLREP);
826 OSSL_CMP_MSG_free(msg);
831 * returns the status field of the RevRepContent with the given
832 * request/sequence id inside a revocation response.
833 * RevRepContent has the revocation statuses in same order as they were sent in
835 * returns NULL on error
838 ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
840 OSSL_CMP_PKISI *status;
842 if (!ossl_assert(rrep != NULL))
845 if ((status = sk_OSSL_CMP_PKISI_value(rrep->status, rsid)) != NULL)
848 CMPerr(0, CMP_R_PKISTATUSINFO_NOT_FOUND);
853 * returns the CertId field in the revCerts part of the RevRepContent
854 * with the given request/sequence id inside a revocation response.
855 * RevRepContent has the CertIds in same order as they were sent in
857 * returns NULL on error
860 ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
862 OSSL_CRMF_CERTID *cid = NULL;
864 if (!ossl_assert(rrep != NULL))
867 if ((cid = sk_OSSL_CRMF_CERTID_value(rrep->revCerts, rsid)) != NULL)
870 CMPerr(0, CMP_R_CERTID_NOT_FOUND);
874 static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
881 trid = ossl_cmp_asn1_get_int(certReqId);
884 CMPerr(0, CMP_R_BAD_REQUEST_ID);
890 static void add_expected_rid(int rid)
892 char str[DECIMAL_SIZE(rid) + 1];
894 BIO_snprintf(str, sizeof(str), "%d", rid);
895 ERR_add_error_data(2, "expected certReqId = ", str);
899 * returns a pointer to the PollResponse with the given CertReqId
900 * (or the first one in case -1) inside a PollRepContent
901 * returns NULL on error or if no suitable PollResponse available
904 ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
907 OSSL_CMP_POLLREP *pollRep = NULL;
910 if (!ossl_assert(prc != NULL))
913 for (i = 0; i < sk_OSSL_CMP_POLLREP_num(prc); i++) {
914 pollRep = sk_OSSL_CMP_POLLREP_value(prc, i);
915 if (suitable_rid(pollRep->certReqId, rid))
919 CMPerr(0, CMP_R_CERTRESPONSE_NOT_FOUND);
920 add_expected_rid(rid);
925 * returns a pointer to the CertResponse with the given CertReqId
926 * (or the first one in case -1) inside a CertRepMessage
927 * returns NULL on error or if no suitable CertResponse available
929 OSSL_CMP_CERTRESPONSE *
930 ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
933 OSSL_CMP_CERTRESPONSE *crep = NULL;
936 if (!ossl_assert(crm != NULL && crm->response != NULL))
939 for (i = 0; i < sk_OSSL_CMP_CERTRESPONSE_num(crm->response); i++) {
940 crep = sk_OSSL_CMP_CERTRESPONSE_value(crm->response, i);
941 if (suitable_rid(crep->certReqId, rid))
945 CMPerr(0, CMP_R_CERTRESPONSE_NOT_FOUND);
946 add_expected_rid(rid);
951 * Retrieve the newly enrolled certificate from the given certResponse crep.
952 * In case of indirect POPO uses the libctx and propq from ctx and private key.
953 * Returns a pointer to a copy of the found certificate, or NULL if not found.
955 X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
956 const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
958 OSSL_CMP_CERTORENCCERT *coec;
961 if (!ossl_assert(crep != NULL && ctx != NULL))
964 if (crep->certifiedKeyPair
965 && (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
966 switch (coec->type) {
967 case OSSL_CMP_CERTORENCCERT_CERTIFICATE:
968 crt = X509_dup(coec->value.certificate);
970 case OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT:
971 /* cert encrypted for indirect PoP; RFC 4210, 5.2.8.2 */
973 CMPerr(0, CMP_R_MISSING_PRIVATE_KEY);
977 OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(coec->value.encryptedCert,
978 ctx->libctx, ctx->propq,
982 CMPerr(0, CMP_R_UNKNOWN_CERT_TYPE);
987 CMPerr(0, CMP_R_CERTIFICATE_NOT_FOUND);
989 (void)x509_set0_libctx(crt, ctx->libctx, ctx->propq);
993 int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
995 if (ctx == NULL || msg == NULL) {
996 CMPerr(0, CMP_R_NULL_ARGUMENT);
999 if (!ossl_cmp_hdr_set_transactionID(ctx, msg->header))
1001 return msg->header->protectionAlg == NULL
1002 || ossl_cmp_msg_protect(ctx, msg);
1005 OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file)
1007 OSSL_CMP_MSG *msg = NULL;
1011 CMPerr(0, CMP_R_NULL_ARGUMENT);
1015 if ((bio = BIO_new_file(file, "rb")) == NULL)
1017 msg = d2i_OSSL_CMP_MSG_bio(bio, NULL);
1022 int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg)
1027 if (file == NULL || msg == NULL) {
1028 CMPerr(0, CMP_R_NULL_ARGUMENT);
1032 bio = BIO_new_file(file, "wb");
1035 res = i2d_OSSL_CMP_MSG_bio(bio, msg);
1040 OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg)
1042 return ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new,
1043 d2i_OSSL_CMP_MSG, bio, msg);
1046 int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
1048 return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);