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