]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cmp/cmp_msg.c
CRYPTO: refactor ERR_raise()+ERR_add_error_data() to ERR_raise_data()
[thirdparty/openssl.git] / crypto / cmp / cmp_msg.c
CommitLineData
3dbc5156 1/*
33388b44 2 * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
3dbc5156
DDO
3 * Copyright Nokia 2007-2019
4 * Copyright Siemens AG 2015-2019
5 *
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
10 */
11
12/* CMP functions for PKIMessage construction */
13
14#include "cmp_local.h"
15
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>
cac30a69 22#include "crypto/x509.h" /* for x509_set0_libctx() */
3dbc5156
DDO
23
24OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg)
25{
26 if (msg == NULL) {
9311d0c4 27 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
3dbc5156
DDO
28 return NULL;
29 }
30 return msg->header;
31}
32
33const char *ossl_cmp_bodytype_to_string(int type)
34{
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",
41 };
42
43 if (type < 0 || type > OSSL_CMP_PKIBODY_TYPE_MAX)
44 return "illegal body type";
45 return type_names[type];
46}
47
48int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type)
49{
50 if (!ossl_assert(msg != NULL && msg->body != NULL))
51 return 0;
52
53 msg->body->type = type;
54 return 1;
55}
56
57int ossl_cmp_msg_get_bodytype(const OSSL_CMP_MSG *msg)
58{
59 if (!ossl_assert(msg != NULL && msg->body != NULL))
60 return -1;
61
62 return msg->body->type;
63}
64
65/* Add an extension to the referenced extension stack, which may be NULL */
66static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
67{
68 X509_EXTENSION *ext;
69 int res;
70
71 if (!ossl_assert(pexts != NULL)) /* pointer to var must not be NULL */
72 return 0;
73
74 if ((ext = X509V3_EXT_i2d(nid, crit, ex)) == NULL)
75 return 0;
76
77 res = X509v3_add_ext(pexts, ext, 0) != NULL;
78 X509_EXTENSION_free(ext);
79 return res;
80}
81
82/* Add a CRL revocation reason code to extension stack, which may be NULL */
83static int add_crl_reason_extension(X509_EXTENSIONS **pexts, int reason_code)
84{
85 ASN1_ENUMERATED *val = ASN1_ENUMERATED_new();
86 int res = 0;
87
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);
91 return res;
92}
93
94OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype)
95{
96 OSSL_CMP_MSG *msg = NULL;
97
98 if (!ossl_assert(ctx != NULL))
99 return NULL;
100
101 if ((msg = OSSL_CMP_MSG_new()) == NULL)
102 return NULL;
103 if (!ossl_cmp_hdr_init(ctx, msg->header)
104 || !ossl_cmp_msg_set_bodytype(msg, bodytype))
105 goto err;
106 if (ctx->geninfo_ITAVs != NULL
107 && !ossl_cmp_hdr_generalInfo_push1_items(msg->header,
108 ctx->geninfo_ITAVs))
109 goto err;
110
111 switch (bodytype) {
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)
116 goto err;
117 return msg;
118
119 case OSSL_CMP_PKIBODY_P10CR:
120 if (ctx->p10CSR == NULL) {
9311d0c4 121 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_P10CSR);
3dbc5156
DDO
122 goto err;
123 }
124 if ((msg->body->value.p10cr = X509_REQ_dup(ctx->p10CSR)) == NULL)
125 goto err;
126 return msg;
127
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)
132 goto err;
133 return msg;
134
135 case OSSL_CMP_PKIBODY_RR:
136 if ((msg->body->value.rr = sk_OSSL_CMP_REVDETAILS_new_null()) == NULL)
137 goto err;
138 return msg;
139 case OSSL_CMP_PKIBODY_RP:
140 if ((msg->body->value.rp = OSSL_CMP_REVREPCONTENT_new()) == NULL)
141 goto err;
142 return msg;
143
144 case OSSL_CMP_PKIBODY_CERTCONF:
145 if ((msg->body->value.certConf =
146 sk_OSSL_CMP_CERTSTATUS_new_null()) == NULL)
147 goto err;
148 return msg;
149 case OSSL_CMP_PKIBODY_PKICONF:
150 if ((msg->body->value.pkiconf = ASN1_TYPE_new()) == NULL)
151 goto err;
152 ASN1_TYPE_set(msg->body->value.pkiconf, V_ASN1_NULL, NULL);
153 return msg;
154
155 case OSSL_CMP_PKIBODY_POLLREQ:
156 if ((msg->body->value.pollReq = sk_OSSL_CMP_POLLREQ_new_null()) == NULL)
157 goto err;
158 return msg;
159 case OSSL_CMP_PKIBODY_POLLREP:
160 if ((msg->body->value.pollRep = sk_OSSL_CMP_POLLREP_new_null()) == NULL)
161 goto err;
162 return msg;
163
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)
167 goto err;
168 return msg;
169
170 case OSSL_CMP_PKIBODY_ERROR:
171 if ((msg->body->value.error = OSSL_CMP_ERRORMSGCONTENT_new()) == NULL)
172 goto err;
173 return msg;
174
175 default:
9311d0c4 176 ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
3dbc5156
DDO
177 goto err;
178 }
179
180 err:
181 OSSL_CMP_MSG_free(msg);
182 return NULL;
183}
184
185#define HAS_SAN(ctx) \
186 (sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \
187 || OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1)
188
8cc86b81 189static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
593d6554 190 int for_KUR)
3dbc5156
DDO
191{
192 if (ctx->subjectName != NULL)
193 return ctx->subjectName;
194
593d6554 195 if (refcert != NULL && (for_KUR || !HAS_SAN(ctx)))
3dbc5156
DDO
196 /*
197 * For KUR, copy subjectName from reference certificate.
198 * For IR or CR, do the same only if there is no subjectAltName.
199 */
200 return X509_get_subject_name(refcert);
201 return NULL;
202}
203
593d6554 204OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
3dbc5156
DDO
205{
206 OSSL_CRMF_MSG *crm = NULL;
63f1883d 207 X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->cert;
3dbc5156 208 /* refcert defaults to current client cert */
62dcd2aa 209 EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
3dbc5156 210 STACK_OF(GENERAL_NAME) *default_sans = NULL;
593d6554 211 const X509_NAME *subject = determine_subj(ctx, refcert, for_KUR);
d718521f
DDO
212 const X509_NAME *issuer = ctx->issuer != NULL || refcert == NULL
213 ? ctx->issuer : X509_get_issuer_name(refcert);
3dbc5156
DDO
214 int crit = ctx->setSubjectAltNameCritical || subject == NULL;
215 /* RFC5280: subjectAltName MUST be critical if subject is null */
216 X509_EXTENSIONS *exts = NULL;
217
62dcd2aa 218 if (rkey == NULL)
b27ff9b8 219 rkey = ctx->pkey; /* default is independent of ctx->oldCert */
e599d0ae
DDO
220 if (rkey == NULL) {
221#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
9311d0c4 222 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
e599d0ae
DDO
223 return NULL;
224#endif
225 }
593d6554 226 if (for_KUR && refcert == NULL) {
9311d0c4 227 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
3dbc5156
DDO
228 return NULL;
229 }
230 if ((crm = OSSL_CRMF_MSG_new()) == NULL)
231 return NULL;
232 if (!OSSL_CRMF_MSG_set_certReqId(crm, rid)
233 /*
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
237 */
238 || !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
d718521f 239 subject, issuer, NULL /* serial */))
3dbc5156
DDO
240 goto err;
241 if (ctx->days != 0) {
11baa470
DDO
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);
245
246 if (notBefore == NULL
247 || notAfter == NULL
248 || !OSSL_CRMF_MSG_set0_validity(crm, notBefore, notAfter)) {
249 ASN1_TIME_free(notBefore);
250 ASN1_TIME_free(notAfter);
3dbc5156 251 goto err;
11baa470 252 }
3dbc5156
DDO
253 }
254
255 /* extensions */
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,
262 X509_EXTENSION_dup,
263 X509_EXTENSION_free);
264 if (exts == NULL)
265 goto err;
266 }
267 if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0
268 && !add1_extension(&exts, NID_subject_alt_name,
269 crit, ctx->subjectAltNames))
270 goto err;
271 if (!HAS_SAN(ctx) && default_sans != NULL
272 && !add1_extension(&exts, NID_subject_alt_name, crit, default_sans))
273 goto err;
274 if (ctx->policies != NULL
275 && !add1_extension(&exts, NID_certificate_policies,
276 ctx->setPoliciesCritical, ctx->policies))
277 goto err;
278 if (!OSSL_CRMF_MSG_set0_extensions(crm, exts))
279 goto err;
280 exts = NULL;
281 /* end fill certTemplate, now set any controls */
282
283 /* for KUR, set OldCertId according to D.6 */
593d6554 284 if (for_KUR) {
3dbc5156
DDO
285 OSSL_CRMF_CERTID *cid =
286 OSSL_CRMF_CERTID_gen(X509_get_issuer_name(refcert),
1337a3a9 287 X509_get0_serialNumber(refcert));
3dbc5156
DDO
288 int ret;
289
290 if (cid == NULL)
291 goto err;
292 ret = OSSL_CRMF_MSG_set1_regCtrl_oldCertID(crm, cid);
293 OSSL_CRMF_CERTID_free(cid);
294 if (ret == 0)
295 goto err;
296 }
297
298 goto end;
299
300 err:
301 OSSL_CRMF_MSG_free(crm);
302 crm = NULL;
303
304 end:
305 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
306 sk_GENERAL_NAME_pop_free(default_sans, GENERAL_NAME_free);
307 return crm;
308}
309
299e0f1e
DDO
310OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type,
311 const OSSL_CRMF_MSG *crm)
3dbc5156 312{
3dbc5156 313 OSSL_CMP_MSG *msg;
299e0f1e 314 OSSL_CRMF_MSG *local_crm = NULL;
3dbc5156
DDO
315
316 if (!ossl_assert(ctx != NULL))
317 return NULL;
318
3dbc5156
DDO
319 if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR
320 && type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) {
9311d0c4 321 ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
3dbc5156
DDO
322 return NULL;
323 }
324
325 if ((msg = ossl_cmp_msg_create(ctx, type)) == NULL)
326 goto err;
327
328 /* header */
329 if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
330 goto err;
331
332 /* body */
333 /* For P10CR the content has already been set in OSSL_CMP_MSG_create */
334 if (type != OSSL_CMP_PKIBODY_P10CR) {
62dcd2aa
DDO
335 EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
336
337 if (privkey == NULL)
338 privkey = ctx->pkey; /* default is independent of ctx->oldCert */
3dbc5156 339 if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
9311d0c4 340 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
3dbc5156
DDO
341 goto err;
342 }
299e0f1e 343 if (crm == NULL) {
593d6554
DDO
344 local_crm = OSSL_CMP_CTX_setup_CRM(ctx,
345 type == OSSL_CMP_PKIBODY_KUR,
346 OSSL_CMP_CERTREQID);
347 if (local_crm == NULL
6d1f50b5
DDO
348 || !OSSL_CRMF_MSG_create_popo(ctx->popoMethod, local_crm,
349 privkey, ctx->digest,
350 ctx->libctx, ctx->propq))
299e0f1e
DDO
351 goto err;
352 } else {
353 if ((local_crm = OSSL_CRMF_MSG_dup(crm)) == NULL)
354 goto err;
355 }
356
357 /* value.ir is same for cr and kur */
358 if (!sk_OSSL_CRMF_MSG_push(msg->body->value.ir, local_crm))
3dbc5156 359 goto err;
299e0f1e 360 local_crm = NULL;
3dbc5156
DDO
361 /* TODO: here optional 2nd certreqmsg could be pushed to the stack */
362 }
363
364 if (!ossl_cmp_msg_protect(ctx, msg))
365 goto err;
366
367 return msg;
368
369 err:
9311d0c4 370 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREQ);
299e0f1e 371 OSSL_CRMF_MSG_free(local_crm);
3dbc5156
DDO
372 OSSL_CMP_MSG_free(msg);
373 return NULL;
374}
375
299e0f1e 376OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
3dbc5156
DDO
377 int certReqId, OSSL_CMP_PKISI *si,
378 X509 *cert, STACK_OF(X509) *chain,
379 STACK_OF(X509) *caPubs, int encrypted,
380 int unprotectedErrors)
381{
382 OSSL_CMP_MSG *msg = NULL;
383 OSSL_CMP_CERTREPMESSAGE *repMsg = NULL;
384 OSSL_CMP_CERTRESPONSE *resp = NULL;
385 int status = -1;
386
387 if (!ossl_assert(ctx != NULL && si != NULL))
388 return NULL;
389
390 if ((msg = ossl_cmp_msg_create(ctx, bodytype)) == NULL)
391 goto err;
392 repMsg = msg->body->value.ip; /* value.ip is same for cp and kup */
393
394 /* header */
395 if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
396 goto err;
397
398 /* body */
399 if ((resp = OSSL_CMP_CERTRESPONSE_new()) == NULL)
400 goto err;
401 OSSL_CMP_PKISI_free(resp->status);
402 if ((resp->status = OSSL_CMP_PKISI_dup(si)) == NULL
403 || !ASN1_INTEGER_set(resp->certReqId, certReqId))
404 goto err;
405
62dcd2aa 406 status = ossl_cmp_pkisi_get_status(resp->status);
3dbc5156
DDO
407 if (status != OSSL_CMP_PKISTATUS_rejection
408 && status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) {
409 if (encrypted) {
9311d0c4 410 ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
3dbc5156
DDO
411 goto err;
412 }
413
414 if ((resp->certifiedKeyPair = OSSL_CMP_CERTIFIEDKEYPAIR_new())
415 == NULL)
416 goto err;
417 resp->certifiedKeyPair->certOrEncCert->type =
418 OSSL_CMP_CERTORENCCERT_CERTIFICATE;
419 if (!X509_up_ref(cert))
420 goto err;
421 resp->certifiedKeyPair->certOrEncCert->value.certificate = cert;
422 }
423
424 if (!sk_OSSL_CMP_CERTRESPONSE_push(repMsg->response, resp))
425 goto err;
426 resp = NULL;
427 /* TODO: here optional 2nd certrep could be pushed to the stack */
428
429 if (bodytype == OSSL_CMP_PKIBODY_IP && caPubs != NULL
430 && (repMsg->caPubs = X509_chain_up_ref(caPubs)) == NULL)
431 goto err;
1a27fe4b
DDO
432 if (sk_X509_num(chain) > 0) {
433 msg->extraCerts = sk_X509_new_reserve(NULL, sk_X509_num(chain));
434 if (msg->extraCerts == NULL
eeccc237
DDO
435 || !X509_add_certs(msg->extraCerts, chain,
436 X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
d718521f 437 goto err;
1a27fe4b 438 }
3dbc5156
DDO
439
440 if (!unprotectedErrors
62dcd2aa 441 || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
3dbc5156
DDO
442 if (!ossl_cmp_msg_protect(ctx, msg))
443 goto err;
444
445 return msg;
446
447 err:
9311d0c4 448 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP);
3dbc5156
DDO
449 OSSL_CMP_CERTRESPONSE_free(resp);
450 OSSL_CMP_MSG_free(msg);
451 return NULL;
452}
453
454OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
455{
456 OSSL_CMP_MSG *msg = NULL;
457 OSSL_CMP_REVDETAILS *rd;
458
459 if (!ossl_assert(ctx != NULL && ctx->oldCert != NULL))
460 return NULL;
461
462 if ((rd = OSSL_CMP_REVDETAILS_new()) == NULL)
463 goto err;
464
465 /* Fill the template from the contents of the certificate to be revoked */
466 if (!OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
235595c4
DDO
467 NULL /* pubkey would be redundant */,
468 NULL /* subject would be redundant */,
3dbc5156 469 X509_get_issuer_name(ctx->oldCert),
1337a3a9 470 X509_get0_serialNumber(ctx->oldCert)))
3dbc5156
DDO
471 goto err;
472
473 /* revocation reason code is optional */
474 if (ctx->revocationReason != CRL_REASON_NONE
475 && !add_crl_reason_extension(&rd->crlEntryDetails,
476 ctx->revocationReason))
477 goto err;
478
479 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RR)) == NULL)
480 goto err;
481
482 if (!sk_OSSL_CMP_REVDETAILS_push(msg->body->value.rr, rd))
483 goto err;
484 rd = NULL;
485
486 /*
487 * TODO: the Revocation Passphrase according to section 5.3.19.9 could be
488 * set here if set in ctx
489 */
490
491 if (!ossl_cmp_msg_protect(ctx, msg))
492 goto err;
493
494 return msg;
495
496 err:
9311d0c4 497 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR);
3dbc5156
DDO
498 OSSL_CMP_MSG_free(msg);
499 OSSL_CMP_REVDETAILS_free(rd);
500 return NULL;
501}
502
503OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
504 OSSL_CRMF_CERTID *cid, int unprot_err)
505{
506 OSSL_CMP_REVREPCONTENT *rep = NULL;
507 OSSL_CMP_PKISI *si1 = NULL;
508 OSSL_CRMF_CERTID *cid_copy = NULL;
509 OSSL_CMP_MSG *msg = NULL;
510
511 if (!ossl_assert(ctx != NULL && si != NULL && cid != NULL))
512 return NULL;
513
514 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RP)) == NULL)
515 goto err;
516 rep = msg->body->value.rp;
517
518 if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL)
519 goto err;
520
521 if (!sk_OSSL_CMP_PKISI_push(rep->status, si1)) {
522 OSSL_CMP_PKISI_free(si1);
523 goto err;
524 }
525
526 if ((rep->revCerts = sk_OSSL_CRMF_CERTID_new_null()) == NULL)
527 goto err;
528 if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL)
529 goto err;
530 if (!sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) {
531 OSSL_CRMF_CERTID_free(cid_copy);
532 goto err;
533 }
534
535 if (!unprot_err
62dcd2aa 536 || ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
3dbc5156
DDO
537 if (!ossl_cmp_msg_protect(ctx, msg))
538 goto err;
539
540 return msg;
541
542 err:
9311d0c4 543 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP);
3dbc5156
DDO
544 OSSL_CMP_MSG_free(msg);
545 return NULL;
546}
547
548OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx)
549{
550 OSSL_CMP_MSG *msg;
551
552 if (!ossl_assert(ctx != NULL))
553 return NULL;
554
555 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_PKICONF)) == NULL)
556 goto err;
557 if (ossl_cmp_msg_protect(ctx, msg))
558 return msg;
559
560 err:
9311d0c4 561 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
3dbc5156
DDO
562 OSSL_CMP_MSG_free(msg);
563 return NULL;
564}
565
566int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav)
567{
568 int bodytype;
569
570 if (!ossl_assert(msg != NULL && itav != NULL))
571 return 0;
572
573 bodytype = ossl_cmp_msg_get_bodytype(msg);
574 if (bodytype != OSSL_CMP_PKIBODY_GENM
575 && bodytype != OSSL_CMP_PKIBODY_GENP) {
9311d0c4 576 ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
3dbc5156
DDO
577 return 0;
578 }
579
580 /* value.genp has the same structure, so this works for genp as well */
581 return OSSL_CMP_ITAV_push0_stack_item(&msg->body->value.genm, itav);
582}
583
584int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
62dcd2aa 585 const STACK_OF(OSSL_CMP_ITAV) *itavs)
3dbc5156
DDO
586{
587 int i;
588 OSSL_CMP_ITAV *itav = NULL;
589
590 if (!ossl_assert(msg != NULL))
591 return 0;
592
593 for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
143be474
DDO
594 itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i));
595 if (itav == NULL
596 || !ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
3dbc5156
DDO
597 OSSL_CMP_ITAV_free(itav);
598 return 0;
599 }
600 }
601 return 1;
602}
603
604/*
605 * Creates a new General Message/Response with an empty itav stack
606 * returns a pointer to the PKIMessage on success, NULL on error
607 */
62dcd2aa
DDO
608static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
609 const STACK_OF(OSSL_CMP_ITAV) *itavs,
610 int body_type, int err_code)
3dbc5156
DDO
611{
612 OSSL_CMP_MSG *msg = NULL;
613
614 if (!ossl_assert(ctx != NULL))
615 return NULL;
616
617 if ((msg = ossl_cmp_msg_create(ctx, body_type)) == NULL)
618 return NULL;
619
620 if (ctx->genm_ITAVs != NULL
62dcd2aa 621 && !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs))
3dbc5156
DDO
622 goto err;
623
624 if (!ossl_cmp_msg_protect(ctx, msg))
625 goto err;
626
627 return msg;
628
629 err:
9311d0c4 630 ERR_raise(ERR_LIB_CMP, err_code);
3dbc5156
DDO
631 OSSL_CMP_MSG_free(msg);
632 return NULL;
633}
634
635OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx)
636{
62dcd2aa
DDO
637 return gen_new(ctx, ctx->genm_ITAVs,
638 OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
3dbc5156
DDO
639}
640
62dcd2aa
DDO
641OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
642 const STACK_OF(OSSL_CMP_ITAV) *itavs)
3dbc5156 643{
62dcd2aa
DDO
644 return gen_new(ctx, itavs,
645 OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
3dbc5156
DDO
646}
647
648OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
649 int errorCode,
62dcd2aa 650 const char *details, int unprotected)
3dbc5156
DDO
651{
652 OSSL_CMP_MSG *msg = NULL;
62dcd2aa 653 OSSL_CMP_PKIFREETEXT *ft;
3dbc5156
DDO
654
655 if (!ossl_assert(ctx != NULL && si != NULL))
656 return NULL;
657
658 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_ERROR)) == NULL)
659 goto err;
660
661 OSSL_CMP_PKISI_free(msg->body->value.error->pKIStatusInfo);
662 if ((msg->body->value.error->pKIStatusInfo = OSSL_CMP_PKISI_dup(si))
663 == NULL)
664 goto err;
665 if (errorCode >= 0) {
666 if ((msg->body->value.error->errorCode = ASN1_INTEGER_new()) == NULL)
667 goto err;
668 if (!ASN1_INTEGER_set(msg->body->value.error->errorCode, errorCode))
669 goto err;
670 }
62dcd2aa
DDO
671 if (details != NULL) {
672 if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL)
673 goto err;
674 msg->body->value.error->errorDetails = ft;
675 if (!ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details))
3dbc5156 676 goto err;
62dcd2aa 677 }
3dbc5156
DDO
678
679 if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
680 goto err;
681 return msg;
682
683 err:
9311d0c4 684 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_ERROR);
3dbc5156
DDO
685 OSSL_CMP_MSG_free(msg);
686 return NULL;
687}
688
689/*
62dcd2aa
DDO
690 * Set the certHash field of a OSSL_CMP_CERTSTATUS structure.
691 * This is used in the certConf message, for example,
692 * to confirm that the certificate was received successfully.
3dbc5156 693 */
62dcd2aa
DDO
694int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
695 ASN1_OCTET_STRING *hash)
3dbc5156 696{
62dcd2aa 697 if (!ossl_assert(certStatus != NULL))
3dbc5156 698 return 0;
62dcd2aa
DDO
699 ASN1_OCTET_STRING_free(certStatus->certHash);
700 certStatus->certHash = hash;
3dbc5156 701 return 1;
3dbc5156
DDO
702}
703
704/*
705 * TODO: handle potential 2nd certificate when signing and encrypting
706 * certificates have been requested/received
707 */
708OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
709 const char *text)
710{
711 OSSL_CMP_MSG *msg = NULL;
712 OSSL_CMP_CERTSTATUS *certStatus = NULL;
62dcd2aa 713 ASN1_OCTET_STRING *certHash = NULL;
3dbc5156
DDO
714 OSSL_CMP_PKISI *sinfo;
715
716 if (!ossl_assert(ctx != NULL && ctx->newCert != NULL))
717 return NULL;
718
719 if ((unsigned)fail_info > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
9311d0c4 720 ERR_raise(ERR_LIB_CMP, CMP_R_FAIL_INFO_OUT_OF_RANGE);
3dbc5156
DDO
721 return NULL;
722 }
723
724 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_CERTCONF)) == NULL)
725 goto err;
726
727 if ((certStatus = OSSL_CMP_CERTSTATUS_new()) == NULL)
728 goto err;
729 /* consume certStatus into msg right away so it gets deallocated with msg */
730 if (!sk_OSSL_CMP_CERTSTATUS_push(msg->body->value.certConf, certStatus))
731 goto err;
732 /* set the ID of the certReq */
733 if (!ASN1_INTEGER_set(certStatus->certReqId, OSSL_CMP_CERTREQID))
734 goto err;
735 /*
736 * the hash of the certificate, using the same hash algorithm
737 * as is used to create and verify the certificate signature
738 */
44387c90 739 if ((certHash = X509_digest_sig(ctx->newCert)) == NULL)
62dcd2aa
DDO
740 goto err;
741
742 if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
3dbc5156 743 goto err;
62dcd2aa 744 certHash = NULL;
3dbc5156
DDO
745 /*
746 * For any particular CertStatus, omission of the statusInfo field
747 * indicates ACCEPTANCE of the specified certificate. Alternatively,
748 * explicit status details (with respect to acceptance or rejection) MAY
749 * be provided in the statusInfo field, perhaps for auditing purposes at
750 * the CA/RA.
751 */
752 sinfo = fail_info != 0 ?
62dcd2aa
DDO
753 OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
754 OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
3dbc5156
DDO
755 if (sinfo == NULL)
756 goto err;
757 certStatus->statusInfo = sinfo;
758
759 if (!ossl_cmp_msg_protect(ctx, msg))
760 goto err;
761
762 return msg;
763
764 err:
9311d0c4 765 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTCONF);
3dbc5156 766 OSSL_CMP_MSG_free(msg);
62dcd2aa 767 ASN1_OCTET_STRING_free(certHash);
3dbc5156
DDO
768 return NULL;
769}
770
771OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid)
772{
773 OSSL_CMP_MSG *msg = NULL;
774 OSSL_CMP_POLLREQ *preq = NULL;
775
776 if (!ossl_assert(ctx != NULL))
777 return NULL;
778
779 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREQ)) == NULL)
780 goto err;
781
782 /* TODO: support multiple cert request IDs to poll */
783 if ((preq = OSSL_CMP_POLLREQ_new()) == NULL
784 || !ASN1_INTEGER_set(preq->certReqId, crid)
785 || !sk_OSSL_CMP_POLLREQ_push(msg->body->value.pollReq, preq))
786 goto err;
787
788 preq = NULL;
789 if (!ossl_cmp_msg_protect(ctx, msg))
790 goto err;
791
792 return msg;
793
794 err:
9311d0c4 795 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREQ);
3dbc5156
DDO
796 OSSL_CMP_POLLREQ_free(preq);
797 OSSL_CMP_MSG_free(msg);
798 return NULL;
799}
800
801OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
802 int64_t poll_after)
803{
804 OSSL_CMP_MSG *msg;
805 OSSL_CMP_POLLREP *prep;
806
807 if (!ossl_assert(ctx != NULL))
808 return NULL;
809
810 if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREP)) == NULL)
811 goto err;
812 if ((prep = OSSL_CMP_POLLREP_new()) == NULL)
813 goto err;
814 if (!sk_OSSL_CMP_POLLREP_push(msg->body->value.pollRep, prep))
815 goto err;
816 if (!ASN1_INTEGER_set(prep->certReqId, crid))
817 goto err;
818 if (!ASN1_INTEGER_set_int64(prep->checkAfter, poll_after))
819 goto err;
820
821 if (!ossl_cmp_msg_protect(ctx, msg))
822 goto err;
823 return msg;
824
825 err:
9311d0c4 826 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP);
3dbc5156
DDO
827 OSSL_CMP_MSG_free(msg);
828 return NULL;
829}
830
831/*-
832 * returns the status field of the RevRepContent with the given
833 * request/sequence id inside a revocation response.
834 * RevRepContent has the revocation statuses in same order as they were sent in
835 * RevReqContent.
836 * returns NULL on error
837 */
838OSSL_CMP_PKISI *
62dcd2aa 839ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
3dbc5156
DDO
840{
841 OSSL_CMP_PKISI *status;
842
843 if (!ossl_assert(rrep != NULL))
844 return NULL;
845
846 if ((status = sk_OSSL_CMP_PKISI_value(rrep->status, rsid)) != NULL)
847 return status;
848
9311d0c4 849 ERR_raise(ERR_LIB_CMP, CMP_R_PKISTATUSINFO_NOT_FOUND);
3dbc5156
DDO
850 return NULL;
851}
852
853/*
854 * returns the CertId field in the revCerts part of the RevRepContent
855 * with the given request/sequence id inside a revocation response.
856 * RevRepContent has the CertIds in same order as they were sent in
857 * RevReqContent.
858 * returns NULL on error
859 */
860OSSL_CRMF_CERTID *
861ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
862{
863 OSSL_CRMF_CERTID *cid = NULL;
864
865 if (!ossl_assert(rrep != NULL))
866 return NULL;
867
868 if ((cid = sk_OSSL_CRMF_CERTID_value(rrep->revCerts, rsid)) != NULL)
869 return cid;
870
9311d0c4 871 ERR_raise(ERR_LIB_CMP, CMP_R_CERTID_NOT_FOUND);
3dbc5156
DDO
872 return NULL;
873}
874
875static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
876{
877 int trid;
878
879 if (rid == -1)
880 return 1;
881
882 trid = ossl_cmp_asn1_get_int(certReqId);
883
884 if (trid == -1) {
9311d0c4 885 ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
3dbc5156
DDO
886 return 0;
887 }
888 return rid == trid;
889}
890
3dbc5156
DDO
891/*
892 * returns a pointer to the PollResponse with the given CertReqId
893 * (or the first one in case -1) inside a PollRepContent
894 * returns NULL on error or if no suitable PollResponse available
895 */
896OSSL_CMP_POLLREP *
897ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
898 int rid)
899{
900 OSSL_CMP_POLLREP *pollRep = NULL;
901 int i;
902
903 if (!ossl_assert(prc != NULL))
904 return NULL;
905
906 for (i = 0; i < sk_OSSL_CMP_POLLREP_num(prc); i++) {
907 pollRep = sk_OSSL_CMP_POLLREP_value(prc, i);
908 if (suitable_rid(pollRep->certReqId, rid))
909 return pollRep;
910 }
911
a150f8e1
RL
912 ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
913 "expected certReqId = %d", rid);
3dbc5156
DDO
914 return NULL;
915}
916
917/*
918 * returns a pointer to the CertResponse with the given CertReqId
919 * (or the first one in case -1) inside a CertRepMessage
920 * returns NULL on error or if no suitable CertResponse available
921 */
922OSSL_CMP_CERTRESPONSE *
923ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
924 int rid)
925{
926 OSSL_CMP_CERTRESPONSE *crep = NULL;
927 int i;
928
929 if (!ossl_assert(crm != NULL && crm->response != NULL))
930 return NULL;
931
932 for (i = 0; i < sk_OSSL_CMP_CERTRESPONSE_num(crm->response); i++) {
933 crep = sk_OSSL_CMP_CERTRESPONSE_value(crm->response, i);
934 if (suitable_rid(crep->certReqId, rid))
935 return crep;
936 }
937
a150f8e1
RL
938 ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
939 "expected certReqId = %d", rid);
3dbc5156
DDO
940 return NULL;
941}
942
6d1f50b5
DDO
943/*-
944 * Retrieve the newly enrolled certificate from the given certResponse crep.
945 * In case of indirect POPO uses the libctx and propq from ctx and private key.
3dbc5156
DDO
946 * Returns a pointer to a copy of the found certificate, or NULL if not found.
947 */
6d1f50b5
DDO
948X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
949 const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
3dbc5156
DDO
950{
951 OSSL_CMP_CERTORENCCERT *coec;
952 X509 *crt = NULL;
953
6d1f50b5 954 if (!ossl_assert(crep != NULL && ctx != NULL))
3dbc5156
DDO
955 return NULL;
956
957 if (crep->certifiedKeyPair
958 && (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
959 switch (coec->type) {
960 case OSSL_CMP_CERTORENCCERT_CERTIFICATE:
961 crt = X509_dup(coec->value.certificate);
962 break;
963 case OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT:
964 /* cert encrypted for indirect PoP; RFC 4210, 5.2.8.2 */
6d1f50b5 965 if (pkey == NULL) {
9311d0c4 966 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
3dbc5156
DDO
967 return NULL;
968 }
969 crt =
970 OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(coec->value.encryptedCert,
6d1f50b5
DDO
971 ctx->libctx, ctx->propq,
972 pkey);
3dbc5156
DDO
973 break;
974 default:
9311d0c4 975 ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE);
3dbc5156
DDO
976 return NULL;
977 }
978 }
979 if (crt == NULL)
9311d0c4 980 ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
cac30a69
DDO
981 else
982 (void)x509_set0_libctx(crt, ctx->libctx, ctx->propq);
3dbc5156
DDO
983 return crt;
984}
985
143be474
DDO
986int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
987{
988 if (ctx == NULL || msg == NULL) {
9311d0c4 989 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
143be474
DDO
990 return 0;
991 }
992 if (!ossl_cmp_hdr_set_transactionID(ctx, msg->header))
993 return 0;
994 return msg->header->protectionAlg == NULL
995 || ossl_cmp_msg_protect(ctx, msg);
996}
997
fafa56a1 998OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file)
3dbc5156
DDO
999{
1000 OSSL_CMP_MSG *msg = NULL;
1001 BIO *bio = NULL;
1002
fafa56a1 1003 if (file == NULL) {
9311d0c4 1004 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
3dbc5156 1005 return NULL;
fafa56a1 1006 }
3dbc5156
DDO
1007
1008 if ((bio = BIO_new_file(file, "rb")) == NULL)
1009 return NULL;
ae8483d2 1010 msg = d2i_OSSL_CMP_MSG_bio(bio, NULL);
3dbc5156
DDO
1011 BIO_free(bio);
1012 return msg;
1013}
62dcd2aa 1014
1202de44
DDO
1015int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg)
1016{
1017 BIO *bio;
1018 int res;
1019
1020 if (file == NULL || msg == NULL) {
9311d0c4 1021 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
1202de44
DDO
1022 return -1;
1023 }
1024
1025 bio = BIO_new_file(file, "wb");
1026 if (bio == NULL)
1027 return -2;
1028 res = i2d_OSSL_CMP_MSG_bio(bio, msg);
1029 BIO_free(bio);
1030 return res;
1031}
1032
ae8483d2 1033OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg)
62dcd2aa
DDO
1034{
1035 return ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new,
1036 d2i_OSSL_CMP_MSG, bio, msg);
1037}
1038
ae8483d2 1039int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
62dcd2aa
DDO
1040{
1041 return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);
1042}