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