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