]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/crmf/crmf_lib.c
11351e33d1651ae414a37bee7b6963c41696532b
[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 char name[80] = "";
373
374 if (ps == NULL || cr == NULL || pkey == NULL) {
375 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
376 return 0;
377 }
378 if (ps->poposkInput != NULL) {
379 /* We do not support cases 1+2 defined in RFC 4211, section 4.1 */
380 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPOSKINPUT_NOT_SUPPORTED);
381 return 0;
382 }
383
384 if (EVP_PKEY_get_default_digest_name(pkey, name, sizeof(name)) > 0
385 && strcmp(name, "UNDEF") == 0) /* at least for Ed25519, Ed448 */
386 digest = NULL;
387
388 return ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
389 ps->algorithmIdentifier, NULL, ps->signature, cr,
390 NULL, pkey, digest, libctx, propq);
391 }
392
393
394 int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
395 EVP_PKEY *pkey, const EVP_MD *digest,
396 OSSL_LIB_CTX *libctx, const char *propq)
397 {
398 OSSL_CRMF_POPO *pp = NULL;
399 ASN1_INTEGER *tag = NULL;
400
401 if (crm == NULL || (meth == OSSL_CRMF_POPO_SIGNATURE && pkey == NULL)) {
402 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
403 return 0;
404 }
405
406 if (meth == OSSL_CRMF_POPO_NONE)
407 goto end;
408 if ((pp = OSSL_CRMF_POPO_new()) == NULL)
409 goto err;
410 pp->type = meth;
411
412 switch (meth) {
413 case OSSL_CRMF_POPO_RAVERIFIED:
414 if ((pp->value.raVerified = ASN1_NULL_new()) == NULL)
415 goto err;
416 break;
417
418 case OSSL_CRMF_POPO_SIGNATURE:
419 {
420 OSSL_CRMF_POPOSIGNINGKEY *ps = OSSL_CRMF_POPOSIGNINGKEY_new();
421
422 if (ps == NULL)
423 goto err;
424 if (!create_popo_signature(ps, crm->certReq, pkey, digest,
425 libctx, propq)) {
426 OSSL_CRMF_POPOSIGNINGKEY_free(ps);
427 goto err;
428 }
429 pp->value.signature = ps;
430 }
431 break;
432
433 case OSSL_CRMF_POPO_KEYENC:
434 if ((pp->value.keyEncipherment = OSSL_CRMF_POPOPRIVKEY_new()) == NULL)
435 goto err;
436 tag = ASN1_INTEGER_new();
437 pp->value.keyEncipherment->type =
438 OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE;
439 pp->value.keyEncipherment->value.subsequentMessage = tag;
440 if (tag == NULL
441 || !ASN1_INTEGER_set(tag, OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT))
442 goto err;
443 break;
444
445 default:
446 ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO);
447 goto err;
448 }
449
450 end:
451 OSSL_CRMF_POPO_free(crm->popo);
452 crm->popo = pp;
453
454 return 1;
455 err:
456 OSSL_CRMF_POPO_free(pp);
457 return 0;
458 }
459
460 /* verifies the Proof-of-Possession of the request with the given rid in reqs */
461 int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
462 int rid, int acceptRAVerified,
463 OSSL_LIB_CTX *libctx, const char *propq)
464 {
465 OSSL_CRMF_MSG *req = NULL;
466 X509_PUBKEY *pubkey = NULL;
467 OSSL_CRMF_POPOSIGNINGKEY *sig = NULL;
468 const ASN1_ITEM *it;
469 void *asn;
470
471 if (reqs == NULL || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL) {
472 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
473 return 0;
474 }
475
476 if (req->popo == NULL) {
477 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING);
478 return 0;
479 }
480
481 switch (req->popo->type) {
482 case OSSL_CRMF_POPO_RAVERIFIED:
483 if (!acceptRAVerified) {
484 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED);
485 return 0;
486 }
487 break;
488 case OSSL_CRMF_POPO_SIGNATURE:
489 pubkey = req->certReq->certTemplate->publicKey;
490 if (pubkey == NULL) {
491 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
492 return 0;
493 }
494 sig = req->popo->value.signature;
495 if (sig->poposkInput != NULL) {
496 /*
497 * According to RFC 4211: publicKey contains a copy of
498 * the public key from the certificate template. This MUST be
499 * exactly the same value as contained in the certificate template.
500 */
501 if (sig->poposkInput->publicKey == NULL) {
502 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY);
503 return 0;
504 }
505 if (X509_PUBKEY_eq(pubkey, sig->poposkInput->publicKey) != 1) {
506 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY);
507 return 0;
508 }
509 it = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT);
510 asn = sig->poposkInput;
511 } else {
512 if (req->certReq->certTemplate->subject == NULL) {
513 ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_MISSING_SUBJECT);
514 return 0;
515 }
516 it = ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST);
517 asn = req->certReq;
518 }
519 if (ASN1_item_verify_ex(it, sig->algorithmIdentifier, sig->signature,
520 asn, NULL, X509_PUBKEY_get0(pubkey), libctx,
521 propq) < 1)
522 return 0;
523 break;
524 case OSSL_CRMF_POPO_KEYENC:
525 case OSSL_CRMF_POPO_KEYAGREE:
526 default:
527 ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_POPO_METHOD);
528 return 0;
529 }
530 return 1;
531 }
532
533 /* retrieves the serialNumber of the given cert template or NULL on error */
534 const ASN1_INTEGER
535 *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl)
536 {
537 return tmpl != NULL ? tmpl->serialNumber : NULL;
538 }
539
540 const X509_NAME
541 *OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl)
542 {
543 return tmpl != NULL ? tmpl->subject : NULL;
544 }
545
546 /* retrieves the issuer name of the given cert template or NULL on error */
547 const X509_NAME
548 *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl)
549 {
550 return tmpl != NULL ? tmpl->issuer : NULL;
551 }
552
553 X509_EXTENSIONS
554 *OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl)
555 {
556 return tmpl != NULL ? tmpl->extensions : NULL;
557 }
558
559 /* retrieves the issuer name of the given CertId or NULL on error */
560 const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid)
561 {
562 return cid != NULL && cid->issuer->type == GEN_DIRNAME ?
563 cid->issuer->d.directoryName : NULL;
564 }
565
566 /* retrieves the serialNumber of the given CertId or NULL on error */
567 const ASN1_INTEGER *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid)
568 {
569 return cid != NULL ? cid->serialNumber : NULL;
570 }
571
572 /*-
573 * fill in certificate template.
574 * Any value argument that is NULL will leave the respective field unchanged.
575 */
576 int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
577 EVP_PKEY *pubkey,
578 const X509_NAME *subject,
579 const X509_NAME *issuer,
580 const ASN1_INTEGER *serial)
581 {
582 if (tmpl == NULL) {
583 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
584 return 0;
585 }
586 if (subject != NULL && !X509_NAME_set((X509_NAME **)&tmpl->subject, subject))
587 return 0;
588 if (issuer != NULL && !X509_NAME_set((X509_NAME **)&tmpl->issuer, issuer))
589 return 0;
590 if (serial != NULL) {
591 ASN1_INTEGER_free(tmpl->serialNumber);
592 if ((tmpl->serialNumber = ASN1_INTEGER_dup(serial)) == NULL)
593 return 0;
594 }
595 if (pubkey != NULL && !X509_PUBKEY_set(&tmpl->publicKey, pubkey))
596 return 0;
597 return 1;
598 }
599
600
601 /*-
602 * Decrypts the certificate in the given encryptedValue using private key pkey.
603 * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2.
604 *
605 * returns a pointer to the decrypted certificate
606 * returns NULL on error or if no certificate available
607 */
608 X509
609 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
610 OSSL_LIB_CTX *libctx, const char *propq,
611 EVP_PKEY *pkey)
612 {
613 X509 *cert = NULL; /* decrypted certificate */
614 EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */
615 unsigned char *ek = NULL; /* decrypted symmetric encryption key */
616 size_t eksize = 0; /* size of decrypted symmetric encryption key */
617 EVP_CIPHER *cipher = NULL; /* used cipher */
618 int cikeysize = 0; /* key size from cipher */
619 unsigned char *iv = NULL; /* initial vector for symmetric encryption */
620 unsigned char *outbuf = NULL; /* decryption output buffer */
621 const unsigned char *p = NULL; /* needed for decoding ASN1 */
622 int n, outlen = 0;
623 EVP_PKEY_CTX *pkctx = NULL; /* private key context */
624 char name[OSSL_MAX_NAME_SIZE];
625
626 if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL
627 || ecert->encValue == NULL || pkey == NULL) {
628 ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
629 return NULL;
630 }
631
632 /* select symmetric cipher based on algorithm given in message */
633 OBJ_obj2txt(name, sizeof(name), ecert->symmAlg->algorithm, 0);
634
635 (void)ERR_set_mark();
636 cipher = EVP_CIPHER_fetch(NULL, name, NULL);
637
638 if (cipher == NULL)
639 cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name);
640
641 if (cipher == NULL) {
642 (void)ERR_clear_last_mark();
643 ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER);
644 goto end;
645 }
646 (void)ERR_pop_to_mark();
647
648 cikeysize = EVP_CIPHER_get_key_length(cipher);
649 /* first the symmetric key needs to be decrypted */
650 pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
651 if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx)) {
652 ASN1_BIT_STRING *encKey = ecert->encSymmKey;
653 size_t failure;
654 int retval;
655
656 if (EVP_PKEY_decrypt(pkctx, NULL, &eksize,
657 encKey->data, encKey->length) <= 0
658 || (ek = OPENSSL_malloc(eksize)) == NULL)
659 goto end;
660 retval = EVP_PKEY_decrypt(pkctx, ek, &eksize,
661 encKey->data, encKey->length);
662 ERR_clear_error(); /* error state may have sensitive information */
663 failure = ~constant_time_is_zero_s(constant_time_msb(retval)
664 | constant_time_is_zero(retval));
665 failure |= ~constant_time_eq_s(eksize, (size_t)cikeysize);
666 if (failure) {
667 ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
668 goto end;
669 }
670 } else {
671 goto end;
672 }
673 if ((iv = OPENSSL_malloc(EVP_CIPHER_get_iv_length(cipher))) == NULL)
674 goto end;
675 if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv,
676 EVP_CIPHER_get_iv_length(cipher))
677 != EVP_CIPHER_get_iv_length(cipher)) {
678 ERR_raise(ERR_LIB_CRMF, CRMF_R_MALFORMED_IV);
679 goto end;
680 }
681
682 /*
683 * d2i_X509 changes the given pointer, so use p for decoding the message and
684 * keep the original pointer in outbuf so the memory can be freed later
685 */
686 if ((p = outbuf = OPENSSL_malloc(ecert->encValue->length +
687 EVP_CIPHER_get_block_size(cipher))) == NULL
688 || (evp_ctx = EVP_CIPHER_CTX_new()) == NULL)
689 goto end;
690 EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
691
692 if (!EVP_DecryptInit(evp_ctx, cipher, ek, iv)
693 || !EVP_DecryptUpdate(evp_ctx, outbuf, &outlen,
694 ecert->encValue->data,
695 ecert->encValue->length)
696 || !EVP_DecryptFinal(evp_ctx, outbuf + outlen, &n)) {
697 ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE);
698 goto end;
699 }
700 outlen += n;
701
702 /* convert decrypted certificate from DER to internal ASN.1 structure */
703 if ((cert = X509_new_ex(libctx, propq)) == NULL)
704 goto end;
705 if (d2i_X509(&cert, &p, outlen) == NULL)
706 ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE);
707 end:
708 EVP_PKEY_CTX_free(pkctx);
709 OPENSSL_free(outbuf);
710 EVP_CIPHER_CTX_free(evp_ctx);
711 EVP_CIPHER_free(cipher);
712 OPENSSL_clear_free(ek, eksize);
713 OPENSSL_free(iv);
714 return cert;
715 }