]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/crmf/crmf_lib.c
CMP: Add missing getter functions to CRMF API and CMP API
[thirdparty/openssl.git] / crypto / crmf / crmf_lib.c
1 /*-
2 * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright Nokia 2007-2018
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 * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb.
12 */
13
14 /*
15 * This file contains the functions that handle the individual items inside
16 * the CRMF structures
17 */
18
19 /*
20 * NAMING
21 *
22 * The 0 functions use the supplied structure pointer directly in the parent and
23 * it will be freed up when the parent is freed.
24 *
25 * The 1 functions use a copy of the supplied structure pointer (or in some
26 * cases increases its link count) in the parent and so both should be freed up.
27 */
28
29 #include <openssl/asn1t.h>
30
31 #include "crmf_local.h"
32 #include "internal/constant_time.h"
33 #include "internal/sizes.h"
34
35 /* explicit #includes not strictly needed since implied by the above: */
36 #include <openssl/crmf.h>
37 #include <openssl/err.h>
38 #include <openssl/evp.h>
39
40 /*-
41 * atyp = Attribute Type
42 * valt = Value Type
43 * ctrlinf = "regCtrl" or "regInfo"
44 */
45 #define IMPLEMENT_CRMF_CTRL_FUNC(atyp, valt, ctrlinf) \
46 valt *OSSL_CRMF_MSG_get0_##ctrlinf##_##atyp(const OSSL_CRMF_MSG *msg) \
47 { \
48 int i; \
49 STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *controls; \
50 OSSL_CRMF_ATTRIBUTETYPEANDVALUE *atav = NULL; \
51 \
52 if (msg == NULL || msg->certReq == NULL) \
53 return NULL; \
54 controls = msg->certReq->controls; \
55 for (i = 0; i < sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_num(controls); i++) { \
56 atav = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_value(controls, i); \
57 if (OBJ_obj2nid(atav->type) == NID_id_##ctrlinf##_##atyp) \
58 return atav->value.atyp; \
59 } \
60 return NULL; \
61 } \
62 \
63 int OSSL_CRMF_MSG_set1_##ctrlinf##_##atyp(OSSL_CRMF_MSG *msg, const valt *in) \
64 { \
65 OSSL_CRMF_ATTRIBUTETYPEANDVALUE *atav = NULL; \
66 \
67 if (msg == NULL || in == NULL) \
68 goto err; \
69 if ((atav = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new()) == NULL) \
70 goto err; \
71 if ((atav->type = OBJ_nid2obj(NID_id_##ctrlinf##_##atyp)) == NULL) \
72 goto err; \
73 if ((atav->value.atyp = valt##_dup(in)) == NULL) \
74 goto err; \
75 if (!OSSL_CRMF_MSG_push0_##ctrlinf(msg, atav)) \
76 goto err; \
77 return 1; \
78 err: \
79 OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(atav); \
80 return 0; \
81 }
82
83
84 /*-
85 * Pushes the given control attribute into the controls stack of a CertRequest
86 * (section 6)
87 * returns 1 on success, 0 on error
88 */
89 static int OSSL_CRMF_MSG_push0_regCtrl(OSSL_CRMF_MSG *crm,
90 OSSL_CRMF_ATTRIBUTETYPEANDVALUE *ctrl)
91 {
92 int new = 0;
93
94 if (crm == NULL || crm->certReq == NULL || ctrl == NULL) {
95 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
96 return 0;
97 }
98
99 if (crm->certReq->controls == NULL) {
100 crm->certReq->controls = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null();
101 if (crm->certReq->controls == NULL)
102 goto err;
103 new = 1;
104 }
105 if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->certReq->controls, ctrl))
106 goto err;
107
108 return 1;
109 err:
110 if (new != 0) {
111 sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(crm->certReq->controls);
112 crm->certReq->controls = NULL;
113 }
114 return 0;
115 }
116
117 /* id-regCtrl-regToken Control (section 6.1) */
118 IMPLEMENT_CRMF_CTRL_FUNC(regToken, ASN1_STRING, regCtrl)
119
120 /* id-regCtrl-authenticator Control (section 6.2) */
121 #define ASN1_UTF8STRING_dup ASN1_STRING_dup
122 IMPLEMENT_CRMF_CTRL_FUNC(authenticator, ASN1_UTF8STRING, regCtrl)
123
124 int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
125 int method, GENERAL_NAME *nm)
126 {
127 if (spi == NULL
128 || method < OSSL_CRMF_PUB_METHOD_DONTCARE
129 || method > OSSL_CRMF_PUB_METHOD_LDAP) {
130 ERR_raise(ERR_LIB_CRMF, ERR_R_PASSED_INVALID_ARGUMENT);
131 return 0;
132 }
133
134 if (!ASN1_INTEGER_set(spi->pubMethod, method))
135 return 0;
136 GENERAL_NAME_free(spi->pubLocation);
137 spi->pubLocation = nm;
138 return 1;
139 }
140
141 int
142 OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
143 OSSL_CRMF_SINGLEPUBINFO *spi)
144 {
145 if (pi == NULL || spi == NULL) {
146 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
147 return 0;
148 }
149 if (pi->pubInfos == NULL)
150 pi->pubInfos = sk_OSSL_CRMF_SINGLEPUBINFO_new_null();
151 if (pi->pubInfos == NULL)
152 return 0;
153
154 return sk_OSSL_CRMF_SINGLEPUBINFO_push(pi->pubInfos, spi);
155 }
156
157 int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
158 int action)
159 {
160 if (pi == NULL
161 || action < OSSL_CRMF_PUB_ACTION_DONTPUBLISH
162 || action > OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH) {
163 ERR_raise(ERR_LIB_CRMF, ERR_R_PASSED_INVALID_ARGUMENT);
164 return 0;
165 }
166
167 return ASN1_INTEGER_set(pi->action, action);
168 }
169
170 /* id-regCtrl-pkiPublicationInfo Control (section 6.3) */
171 IMPLEMENT_CRMF_CTRL_FUNC(pkiPublicationInfo, OSSL_CRMF_PKIPUBLICATIONINFO,
172 regCtrl)
173
174 /* id-regCtrl-oldCertID Control (section 6.5) from the given */
175 IMPLEMENT_CRMF_CTRL_FUNC(oldCertID, OSSL_CRMF_CERTID, regCtrl)
176
177 OSSL_CRMF_CERTID *OSSL_CRMF_CERTID_gen(const X509_NAME *issuer,
178 const ASN1_INTEGER *serial)
179 {
180 OSSL_CRMF_CERTID *cid = NULL;
181
182 if (issuer == NULL || serial == NULL) {
183 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
184 return NULL;
185 }
186
187 if ((cid = OSSL_CRMF_CERTID_new()) == NULL)
188 goto err;
189
190 if (!X509_NAME_set(&cid->issuer->d.directoryName, issuer))
191 goto err;
192 cid->issuer->type = GEN_DIRNAME;
193
194 ASN1_INTEGER_free(cid->serialNumber);
195 if ((cid->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
196 goto err;
197
198 return cid;
199
200 err:
201 OSSL_CRMF_CERTID_free(cid);
202 return NULL;
203 }
204
205 /*
206 * id-regCtrl-protocolEncrKey Control (section 6.6)
207 */
208 IMPLEMENT_CRMF_CTRL_FUNC(protocolEncrKey, X509_PUBKEY, regCtrl)
209
210 /*-
211 * Pushes the attribute given in regInfo in to the CertReqMsg->regInfo stack.
212 * (section 7)
213 * returns 1 on success, 0 on error
214 */
215 static int OSSL_CRMF_MSG_push0_regInfo(OSSL_CRMF_MSG *crm,
216 OSSL_CRMF_ATTRIBUTETYPEANDVALUE *ri)
217 {
218 STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *info = NULL;
219
220 if (crm == NULL || ri == NULL) {
221 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
222 return 0;
223 }
224
225 if (crm->regInfo == NULL)
226 crm->regInfo = info = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null();
227 if (crm->regInfo == NULL)
228 goto err;
229 if (!sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(crm->regInfo, ri))
230 goto err;
231 return 1;
232
233 err:
234 if (info != NULL)
235 crm->regInfo = NULL;
236 sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(info);
237 return 0;
238 }
239
240 /* id-regInfo-utf8Pairs to regInfo (section 7.1) */
241 IMPLEMENT_CRMF_CTRL_FUNC(utf8Pairs, ASN1_UTF8STRING, regInfo)
242
243 /* id-regInfo-certReq to regInfo (section 7.2) */
244 IMPLEMENT_CRMF_CTRL_FUNC(certReq, OSSL_CRMF_CERTREQUEST, regInfo)
245
246
247 /* retrieves the certificate template of crm */
248 OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm)
249 {
250 if (crm == NULL || crm->certReq == NULL) {
251 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
252 return NULL;
253 }
254 return crm->certReq->certTemplate;
255 }
256
257
258 int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm,
259 ASN1_TIME *notBefore, ASN1_TIME *notAfter)
260 {
261 OSSL_CRMF_OPTIONALVALIDITY *vld;
262 OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
263
264 if (tmpl == NULL) { /* also crm == NULL implies this */
265 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
266 return 0;
267 }
268
269 if ((vld = OSSL_CRMF_OPTIONALVALIDITY_new()) == NULL)
270 return 0;
271 vld->notBefore = notBefore;
272 vld->notAfter = notAfter;
273 tmpl->validity = vld;
274 return 1;
275 }
276
277
278 int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid)
279 {
280 if (crm == NULL || crm->certReq == NULL || crm->certReq->certReqId == NULL) {
281 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
282 return 0;
283 }
284
285 return ASN1_INTEGER_set(crm->certReq->certReqId, rid);
286 }
287
288 /* get ASN.1 encoded integer, return -1 on error */
289 static int crmf_asn1_get_int(const ASN1_INTEGER *a)
290 {
291 int64_t res;
292
293 if (!ASN1_INTEGER_get_int64(&res, a)) {
294 ERR_raise(ERR_LIB_CRMF, ASN1_R_INVALID_NUMBER);
295 return -1;
296 }
297 if (res < INT_MIN) {
298 ERR_raise(ERR_LIB_CRMF, ASN1_R_TOO_SMALL);
299 return -1;
300 }
301 if (res > INT_MAX) {
302 ERR_raise(ERR_LIB_CRMF, ASN1_R_TOO_LARGE);
303 return -1;
304 }
305 return (int)res;
306 }
307
308 int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm)
309 {
310 if (crm == NULL || /* not really needed: */ crm->certReq == NULL) {
311 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
312 return -1;
313 }
314 return crmf_asn1_get_int(crm->certReq->certReqId);
315 }
316
317
318 int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm,
319 X509_EXTENSIONS *exts)
320 {
321 OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
322
323 if (tmpl == NULL) { /* also crm == NULL implies this */
324 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
325 return 0;
326 }
327
328 if (sk_X509_EXTENSION_num(exts) == 0) {
329 sk_X509_EXTENSION_free(exts);
330 exts = NULL; /* do not include empty extensions list */
331 }
332
333 sk_X509_EXTENSION_pop_free(tmpl->extensions, X509_EXTENSION_free);
334 tmpl->extensions = exts;
335 return 1;
336 }
337
338
339 int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm,
340 X509_EXTENSION *ext)
341 {
342 int new = 0;
343 OSSL_CRMF_CERTTEMPLATE *tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
344
345 if (tmpl == NULL || ext == NULL) { /* also crm == NULL implies this */
346 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
347 return 0;
348 }
349
350 if (tmpl->extensions == NULL) {
351 if ((tmpl->extensions = sk_X509_EXTENSION_new_null()) == NULL)
352 goto err;
353 new = 1;
354 }
355
356 if (!sk_X509_EXTENSION_push(tmpl->extensions, ext))
357 goto err;
358 return 1;
359 err:
360 if (new != 0) {
361 sk_X509_EXTENSION_free(tmpl->extensions);
362 tmpl->extensions = NULL;
363 }
364 return 0;
365 }
366
367 static int create_popo_signature(OSSL_CRMF_POPOSIGNINGKEY *ps,
368 const OSSL_CRMF_CERTREQUEST *cr,
369 EVP_PKEY *pkey, const EVP_MD *digest,
370 OSSL_LIB_CTX *libctx, const char *propq)
371 {
372 if (ps == NULL || cr == NULL || pkey == NULL) {
373 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
374 return 0;
375 }
376 if (ps->poposkInput != NULL) {
377 /* We do not support cases 1+2 defined in RFC 4211, section 4.1 */
378 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPOSKINPUT_NOT_SUPPORTED);
379 return 0;
380 }
381
382 return ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
383 ps->algorithmIdentifier, NULL, ps->signature, cr,
384 NULL, pkey, digest, libctx, propq);
385 }
386
387
388 int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
389 EVP_PKEY *pkey, const EVP_MD *digest,
390 OSSL_LIB_CTX *libctx, const char *propq)
391 {
392 OSSL_CRMF_POPO *pp = NULL;
393 ASN1_INTEGER *tag = NULL;
394
395 if (crm == NULL || (meth == OSSL_CRMF_POPO_SIGNATURE && pkey == NULL)) {
396 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
397 return 0;
398 }
399
400 if (meth == OSSL_CRMF_POPO_NONE)
401 goto end;
402 if ((pp = OSSL_CRMF_POPO_new()) == NULL)
403 goto err;
404 pp->type = meth;
405
406 switch (meth) {
407 case OSSL_CRMF_POPO_RAVERIFIED:
408 if ((pp->value.raVerified = ASN1_NULL_new()) == NULL)
409 goto err;
410 break;
411
412 case OSSL_CRMF_POPO_SIGNATURE:
413 {
414 OSSL_CRMF_POPOSIGNINGKEY *ps = OSSL_CRMF_POPOSIGNINGKEY_new();
415
416 if (ps == NULL)
417 goto err;
418 if (!create_popo_signature(ps, crm->certReq, pkey, digest,
419 libctx, propq)) {
420 OSSL_CRMF_POPOSIGNINGKEY_free(ps);
421 goto err;
422 }
423 pp->value.signature = ps;
424 }
425 break;
426
427 case OSSL_CRMF_POPO_KEYENC:
428 if ((pp->value.keyEncipherment = OSSL_CRMF_POPOPRIVKEY_new()) == NULL)
429 goto err;
430 tag = ASN1_INTEGER_new();
431 pp->value.keyEncipherment->type =
432 OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE;
433 pp->value.keyEncipherment->value.subsequentMessage = tag;
434 if (tag == NULL
435 || !ASN1_INTEGER_set(tag, OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT))
436 goto err;
437 break;
438
439 default:
440 ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO);
441 goto err;
442 }
443
444 end:
445 OSSL_CRMF_POPO_free(crm->popo);
446 crm->popo = pp;
447
448 return 1;
449 err:
450 OSSL_CRMF_POPO_free(pp);
451 return 0;
452 }
453
454 /* verifies the Proof-of-Possession of the request with the given rid in reqs */
455 int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
456 int rid, int acceptRAVerified,
457 OSSL_LIB_CTX *libctx, const char *propq)
458 {
459 OSSL_CRMF_MSG *req = NULL;
460 X509_PUBKEY *pubkey = NULL;
461 OSSL_CRMF_POPOSIGNINGKEY *sig = NULL;
462 const ASN1_ITEM *it;
463 void *asn;
464
465 if (reqs == NULL || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL) {
466 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
467 return 0;
468 }
469
470 if (req->popo == NULL) {
471 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING);
472 return 0;
473 }
474
475 switch (req->popo->type) {
476 case OSSL_CRMF_POPO_RAVERIFIED:
477 if (!acceptRAVerified) {
478 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED);
479 return 0;
480 }
481 break;
482 case OSSL_CRMF_POPO_SIGNATURE:
483 pubkey = req->certReq->certTemplate->publicKey;
484 if (pubkey == NULL) {
485 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
486 return 0;
487 }
488 sig = req->popo->value.signature;
489 if (sig->poposkInput != NULL) {
490 /*
491 * According to RFC 4211: publicKey contains a copy of
492 * the public key from the certificate template. This MUST be
493 * exactly the same value as contained in the certificate template.
494 */
495 if (sig->poposkInput->publicKey == NULL) {
496 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
497 return 0;
498 }
499 if (X509_PUBKEY_eq(pubkey, sig->poposkInput->publicKey) != 1) {
500 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY);
501 return 0;
502 }
503 it = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT);
504 asn = sig->poposkInput;
505 } else {
506 if (req->certReq->certTemplate->subject == NULL) {
507 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_SUBJECT);
508 return 0;
509 }
510 it = ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST);
511 asn = req->certReq;
512 }
513 if (ASN1_item_verify_ex(it, sig->algorithmIdentifier, sig->signature,
514 asn, NULL, X509_PUBKEY_get0(pubkey), libctx,
515 propq) < 1)
516 return 0;
517 break;
518 case OSSL_CRMF_POPO_KEYENC:
519 case OSSL_CRMF_POPO_KEYAGREE:
520 default:
521 ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_POPO_METHOD);
522 return 0;
523 }
524 return 1;
525 }
526
527 /* retrieves the serialNumber of the given cert template or NULL on error */
528 ASN1_INTEGER
529 *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl)
530 {
531 return tmpl != NULL ? tmpl->serialNumber : NULL;
532 }
533
534 const X509_NAME
535 *OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl)
536 {
537 return tmpl != NULL ? tmpl->subject : NULL;
538 }
539
540 /* retrieves the issuer name of the given cert template or NULL on error */
541 const X509_NAME
542 *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl)
543 {
544 return tmpl != NULL ? tmpl->issuer : NULL;
545 }
546
547 X509_EXTENSIONS
548 *OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl)
549 {
550 return tmpl != NULL ? tmpl->extensions : NULL;
551 }
552
553 /* retrieves the issuer name of the given CertId or NULL on error */
554 const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid)
555 {
556 return cid != NULL && cid->issuer->type == GEN_DIRNAME ?
557 cid->issuer->d.directoryName : NULL;
558 }
559
560 /* retrieves the serialNumber of the given CertId or NULL on error */
561 ASN1_INTEGER *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid)
562 {
563 return cid != NULL ? cid->serialNumber : NULL;
564 }
565
566 /*-
567 * fill in certificate template.
568 * Any value argument that is NULL will leave the respective field unchanged.
569 */
570 int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
571 EVP_PKEY *pubkey,
572 const X509_NAME *subject,
573 const X509_NAME *issuer,
574 const ASN1_INTEGER *serial)
575 {
576 if (tmpl == NULL) {
577 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
578 return 0;
579 }
580 if (subject != NULL && !X509_NAME_set((X509_NAME **)&tmpl->subject, subject))
581 return 0;
582 if (issuer != NULL && !X509_NAME_set((X509_NAME **)&tmpl->issuer, issuer))
583 return 0;
584 if (serial != NULL) {
585 ASN1_INTEGER_free(tmpl->serialNumber);
586 if ((tmpl->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
587 return 0;
588 }
589 if (pubkey != NULL && !X509_PUBKEY_set(&tmpl->publicKey, pubkey))
590 return 0;
591 return 1;
592 }
593
594
595 /*-
596 * Decrypts the certificate in the given encryptedValue using private key pkey.
597 * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2.
598 *
599 * returns a pointer to the decrypted certificate
600 * returns NULL on error or if no certificate available
601 */
602 X509
603 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
604 OSSL_LIB_CTX *libctx, const char *propq,
605 EVP_PKEY *pkey)
606 {
607 X509 *cert = NULL; /* decrypted certificate */
608 EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */
609 unsigned char *ek = NULL; /* decrypted symmetric encryption key */
610 size_t eksize = 0; /* size of decrypted symmetric encryption key */
611 EVP_CIPHER *cipher = NULL; /* used cipher */
612 int cikeysize = 0; /* key size from cipher */
613 unsigned char *iv = NULL; /* initial vector for symmetric encryption */
614 unsigned char *outbuf = NULL; /* decryption output buffer */
615 const unsigned char *p = NULL; /* needed for decoding ASN1 */
616 int n, outlen = 0;
617 EVP_PKEY_CTX *pkctx = NULL; /* private key context */
618 char name[OSSL_MAX_NAME_SIZE];
619
620 if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL
621 || ecert->encValue == NULL || pkey == NULL) {
622 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
623 return NULL;
624 }
625
626 /* select symmetric cipher based on algorithm given in message */
627 OBJ_obj2txt(name, sizeof(name), ecert->symmAlg->algorithm, 0);
628
629 (void)ERR_set_mark();
630 cipher = EVP_CIPHER_fetch(NULL, name, NULL);
631
632 if (cipher == NULL)
633 cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name);
634
635 if (cipher == NULL) {
636 (void)ERR_clear_last_mark();
637 ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER);
638 goto end;
639 }
640 (void)ERR_pop_to_mark();
641
642 cikeysize = EVP_CIPHER_get_key_length(cipher);
643 /* first the symmetric key needs to be decrypted */
644 pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
645 if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx)) {
646 ASN1_BIT_STRING *encKey = ecert->encSymmKey;
647 size_t failure;
648 int retval;
649
650 if (EVP_PKEY_decrypt(pkctx, NULL, &eksize,
651 encKey->data, encKey->length) <= 0
652 || (ek = OPENSSL_malloc(eksize)) == NULL)
653 goto end;
654 retval = EVP_PKEY_decrypt(pkctx, ek, &eksize,
655 encKey->data, encKey->length);
656 ERR_clear_error(); /* error state may have sensitive information */
657 failure = ~constant_time_is_zero_s(constant_time_msb(retval)
658 | constant_time_is_zero(retval));
659 failure |= ~constant_time_eq_s(eksize, (size_t)cikeysize);
660 if (failure) {
661 ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
662 goto end;
663 }
664 } else {
665 goto end;
666 }
667 if ((iv = OPENSSL_malloc(EVP_CIPHER_get_iv_length(cipher))) == NULL)
668 goto end;
669 if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv,
670 EVP_CIPHER_get_iv_length(cipher))
671 != EVP_CIPHER_get_iv_length(cipher)) {
672 ERR_raise(ERR_LIB_CRMF, CRMF_R_MALFORMED_IV);
673 goto end;
674 }
675
676 /*
677 * d2i_X509 changes the given pointer, so use p for decoding the message and
678 * keep the original pointer in outbuf so the memory can be freed later
679 */
680 if ((p = outbuf = OPENSSL_malloc(ecert->encValue->length +
681 EVP_CIPHER_get_block_size(cipher))) == NULL
682 || (evp_ctx = EVP_CIPHER_CTX_new()) == NULL)
683 goto end;
684 EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
685
686 if (!EVP_DecryptInit(evp_ctx, cipher, ek, iv)
687 || !EVP_DecryptUpdate(evp_ctx, outbuf, &outlen,
688 ecert->encValue->data,
689 ecert->encValue->length)
690 || !EVP_DecryptFinal(evp_ctx, outbuf + outlen, &n)) {
691 ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE);
692 goto end;
693 }
694 outlen += n;
695
696 /* convert decrypted certificate from DER to internal ASN.1 structure */
697 if ((cert = X509_new_ex(libctx, propq)) == NULL)
698 goto end;
699 if (d2i_X509(&cert, &p, outlen) == NULL)
700 ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE);
701 end:
702 EVP_PKEY_CTX_free(pkctx);
703 OPENSSL_free(outbuf);
704 EVP_CIPHER_CTX_free(evp_ctx);
705 EVP_CIPHER_free(cipher);
706 OPENSSL_clear_free(ek, eksize);
707 OPENSSL_free(iv);
708 return cert;
709 }