Coverage Report

Created: 2025-12-31 06:58

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