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