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