Coverage Report

Created: 2026-10-16 07:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/pkcs12/p12_kiss.c
Line
Count
Source
1
/*
2
 * Copyright 1999-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include <openssl/pkcs12.h>
13
#include <openssl/core_names.h>
14
#include "crypto/pkcs7/pk7_local.h"
15
#include "p12_local.h"
16
#include "crypto/x509.h" /* for ossl_x509_add_cert_new() */
17
18
/* Simplified PKCS#12 routines */
19
20
static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
21
    PKCS12_PARSE_CTX *ctx,
22
    OSSL_LIB_CTX *libctx, const char *propq);
23
24
static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
25
    int passlen, PKCS12_PARSE_CTX *ctx,
26
    OSSL_LIB_CTX *libctx, const char *propq);
27
28
static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
29
    PKCS12_PARSE_CTX *ctx,
30
    OSSL_LIB_CTX *libctx, const char *propq);
31
32
PKCS12_PARSE_CTX *PKCS12_PARSE_CTX_new(void)
33
0
{
34
0
    return OPENSSL_zalloc(sizeof(PKCS12_PARSE_CTX));
35
0
}
36
37
void PKCS12_PARSE_CTX_free(PKCS12_PARSE_CTX *ctx)
38
0
{
39
0
    OPENSSL_free(ctx);
40
0
}
41
42
void PKCS12_PARSE_CTX_set_pkey(PKCS12_PARSE_CTX *ctx, EVP_PKEY **pkey)
43
0
{
44
0
    ctx->pkey = pkey;
45
0
}
46
47
void PKCS12_PARSE_CTX_set_cert(PKCS12_PARSE_CTX *ctx, X509 **cert)
48
0
{
49
0
    ctx->cert = cert;
50
0
}
51
52
void PKCS12_PARSE_CTX_set_ca(PKCS12_PARSE_CTX *ctx, STACK_OF(X509) **ca)
53
0
{
54
0
    ctx->ca = ca;
55
0
}
56
57
void PKCS12_PARSE_CTX_set_skeys(PKCS12_PARSE_CTX *ctx, STACK_OF(EVP_SKEY) **skeys)
58
0
{
59
0
    ctx->skeys = skeys;
60
0
}
61
62
/*
63
 * Parse and decrypt a PKCS#12 structure returning user key, user cert,
64
 * other (CA) certs, and/or symmetric secret keys according to ctx settings.
65
 */
66
67
int PKCS12_parse_ex(PKCS12 *p12, const char *pass,
68
    PKCS12_PARSE_CTX *ctx,
69
    OSSL_LIB_CTX *libctx, const char *propq)
70
0
{
71
0
    X509 *x = NULL;
72
0
    STACK_OF(X509) *initial_ca = NULL;
73
0
    STACK_OF(EVP_SKEY) *initial_skeys = NULL;
74
0
    int initial_ca_count = 0;
75
0
    int initial_skeys_count = 0;
76
0
    int ca_added_count = 0;
77
0
    int skeys_added_count = 0;
78
79
0
    if (p12 == NULL) {
80
0
        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER);
81
0
        return 0;
82
0
    }
83
84
0
    if (ctx == NULL) {
85
0
        ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER);
86
0
        return 0;
87
0
    }
88
89
0
    initial_ca = ctx->ca != NULL ? *ctx->ca : NULL;
90
0
    initial_ca_count = initial_ca == NULL ? 0 : sk_X509_num(initial_ca);
91
0
    initial_skeys = ctx->skeys != NULL ? *ctx->skeys : NULL;
92
0
    initial_skeys_count = initial_skeys == NULL ? 0 : sk_EVP_SKEY_num(initial_skeys);
93
94
0
    if (ctx->pkey != NULL)
95
0
        *ctx->pkey = NULL;
96
0
    if (ctx->cert != NULL)
97
0
        *ctx->cert = NULL;
98
0
    ctx->ocerts = NULL;
99
100
    /* Check the mac */
101
0
    if (PKCS12_mac_present(p12)) {
102
        /*
103
         * If password is zero length or NULL then try verifying both cases to
104
         * determine which password is correct. The reason for this is that under
105
         * PKCS#12 password based encryption no password and a zero length
106
         * password are two different things...
107
         */
108
0
        if (pass == NULL || *pass == '\0') {
109
0
            if (ossl_pkcs12_verify_mac(p12, NULL, 0, libctx, propq))
110
0
                pass = NULL;
111
0
            else if (ossl_pkcs12_verify_mac(p12, "", 0, libctx, propq))
112
0
                pass = "";
113
0
            else {
114
0
                ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE);
115
0
                goto err;
116
0
            }
117
0
        } else if (!ossl_pkcs12_verify_mac(p12, pass, -1, libctx, propq)) {
118
0
            ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE);
119
0
            goto err;
120
0
        }
121
0
    } else if (pass == NULL || *pass == '\0') {
122
0
        pass = NULL;
123
0
    }
124
125
    /* If needed, allocate stack for other certificates */
126
0
    if ((ctx->cert != NULL || ctx->ca != NULL)
127
0
        && (ctx->ocerts = sk_X509_new_null()) == NULL) {
128
0
        ERR_raise(ERR_LIB_PKCS12, ERR_R_CRYPTO_LIB);
129
0
        goto err;
130
0
    }
131
132
0
    if (!parse_pk12(p12, pass, -1, ctx, libctx, propq)) {
133
0
        int err = ERR_peek_last_error();
134
135
0
        if (ERR_GET_LIB(err) != ERR_LIB_EVP
136
0
            && ERR_GET_REASON(err) != EVP_R_UNSUPPORTED_ALGORITHM)
137
0
            ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR);
138
0
        goto err;
139
0
    }
140
141
    /* Split the certs in ocerts over *cert and *ca as far as requested */
142
0
    while ((x = sk_X509_shift(ctx->ocerts)) != NULL) {
143
0
        if (ctx->pkey != NULL && *ctx->pkey != NULL
144
0
            && ctx->cert != NULL && *ctx->cert == NULL) {
145
0
            int match;
146
147
0
            ERR_set_mark();
148
0
            match = X509_check_private_key(x, *ctx->pkey);
149
0
            ERR_pop_to_mark();
150
0
            if (match) {
151
0
                *ctx->cert = x;
152
0
                continue;
153
0
            }
154
0
        }
155
156
0
        if (ctx->ca != NULL) {
157
0
            if (!ossl_x509_add_cert_new(ctx->ca, x, X509_ADD_FLAG_DEFAULT))
158
0
                goto err;
159
0
            continue;
160
0
        }
161
0
        X509_free(x);
162
0
    }
163
0
    sk_X509_free(ctx->ocerts);
164
0
    ctx->ocerts = NULL;
165
166
0
    return 1;
167
168
0
err:
169
0
    if (ctx->pkey != NULL) {
170
0
        EVP_PKEY_free(*ctx->pkey);
171
0
        *ctx->pkey = NULL;
172
0
    }
173
0
    if (ctx->cert != NULL) {
174
0
        X509_free(*ctx->cert);
175
0
        *ctx->cert = NULL;
176
0
    }
177
0
    skeys_added_count = ctx->skeys == NULL || *ctx->skeys == NULL ? 0 : sk_EVP_SKEY_num(*ctx->skeys) - initial_skeys_count;
178
0
    while (skeys_added_count > 0) {
179
0
        EVP_SKEY *t_skey = sk_EVP_SKEY_pop(*ctx->skeys);
180
0
        EVP_SKEY_free(t_skey);
181
0
        skeys_added_count--;
182
0
    }
183
184
0
    if (initial_skeys == NULL && ctx->skeys != NULL) {
185
0
        sk_EVP_SKEY_free(*ctx->skeys);
186
0
        *ctx->skeys = NULL;
187
0
    }
188
189
0
    ca_added_count = ctx->ca == NULL || *ctx->ca == NULL ? 0 : sk_X509_num(*ctx->ca) - initial_ca_count;
190
0
    while (ca_added_count > 0) {
191
0
        X509 *t_cert = sk_X509_pop(*ctx->ca);
192
0
        X509_free(t_cert);
193
0
        ca_added_count--;
194
0
    }
195
196
0
    if (initial_ca == NULL && ctx->ca != NULL) {
197
0
        sk_X509_free(*ctx->ca);
198
0
        *ctx->ca = NULL;
199
0
    }
200
201
0
    X509_free(x);
202
0
    OSSL_STACK_OF_X509_free(ctx->ocerts);
203
0
    ctx->ocerts = NULL;
204
0
    return 0;
205
0
}
206
207
int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
208
    STACK_OF(X509) **ca)
209
0
{
210
0
    PKCS12_PARSE_CTX *ctx;
211
0
    int ret;
212
213
0
    if (pkey != NULL)
214
0
        *pkey = NULL;
215
0
    if (cert != NULL)
216
0
        *cert = NULL;
217
218
0
    if (p12 == NULL) {
219
0
        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER);
220
0
        return 0;
221
0
    }
222
223
0
    ctx = PKCS12_PARSE_CTX_new();
224
0
    if (ctx == NULL)
225
0
        return 0;
226
227
0
    PKCS12_PARSE_CTX_set_pkey(ctx, pkey);
228
0
    PKCS12_PARSE_CTX_set_cert(ctx, cert);
229
0
    PKCS12_PARSE_CTX_set_ca(ctx, ca);
230
231
0
    ret = PKCS12_parse_ex(p12, pass, ctx, p12->authsafes->ctx.libctx, p12->authsafes->ctx.propq);
232
0
    PKCS12_PARSE_CTX_free(ctx);
233
0
    return ret;
234
0
}
235
236
/* Parse the outer PKCS#12 structure */
237
238
static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
239
    PKCS12_PARSE_CTX *ctx,
240
    OSSL_LIB_CTX *libctx, const char *propq)
241
0
{
242
0
    STACK_OF(PKCS7) *asafes;
243
0
    STACK_OF(PKCS12_SAFEBAG) *bags;
244
0
    int i, bagnid;
245
0
    PKCS7 *p7;
246
247
0
    if ((asafes = ossl_pkcs12_unpack_authsafes_ex(p12, libctx, propq)) == NULL)
248
0
        return 0;
249
0
    for (i = 0; i < sk_PKCS7_num(asafes); i++) {
250
0
        p7 = sk_PKCS7_value(asafes, i);
251
0
        bagnid = OBJ_obj2nid(p7->type);
252
0
        if (bagnid == NID_pkcs7_data) {
253
0
            bags = PKCS12_unpack_p7data(p7);
254
0
        } else if (bagnid == NID_pkcs7_encrypted) {
255
0
            bags = ossl_pkcs12_unpack_p7encdata_ex(p7, pass, passlen,
256
0
                libctx, propq);
257
0
        } else
258
0
            continue;
259
0
        if (!bags) {
260
0
            sk_PKCS7_pop_free(asafes, PKCS7_free);
261
0
            return 0;
262
0
        }
263
0
        if (!parse_bags(bags, pass, passlen, ctx, libctx, propq)) {
264
0
            sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
265
0
            sk_PKCS7_pop_free(asafes, PKCS7_free);
266
0
            return 0;
267
0
        }
268
0
        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
269
0
    }
270
0
    sk_PKCS7_pop_free(asafes, PKCS7_free);
271
0
    return 1;
272
0
}
273
274
static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
275
    int passlen, PKCS12_PARSE_CTX *ctx,
276
    OSSL_LIB_CTX *libctx, const char *propq)
277
0
{
278
0
    int i;
279
0
    for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
280
0
        if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i),
281
0
                pass, passlen, ctx,
282
0
                libctx, propq))
283
0
            return 0;
284
0
    }
285
0
    return 1;
286
0
}
287
288
static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
289
    PKCS12_PARSE_CTX *ctx,
290
    OSSL_LIB_CTX *libctx, const char *propq)
291
0
{
292
0
    PKCS8_PRIV_KEY_INFO *p8;
293
0
    X509 *x509;
294
0
    const ASN1_TYPE *attrib;
295
0
    ASN1_BMPSTRING *fname = NULL;
296
0
    ASN1_OCTET_STRING *lkid = NULL;
297
298
0
    if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) {
299
0
        if (attrib->type != V_ASN1_BMPSTRING)
300
0
            return 0;
301
0
        fname = attrib->value.bmpstring;
302
0
    }
303
304
0
    if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) {
305
0
        if (attrib->type != V_ASN1_OCTET_STRING)
306
0
            return 0;
307
0
        lkid = attrib->value.octet_string;
308
0
    }
309
310
0
    switch (PKCS12_SAFEBAG_get_nid(bag)) {
311
0
    case NID_keyBag:
312
0
        if (ctx->pkey == NULL || *ctx->pkey != NULL)
313
0
            return 1;
314
0
        *ctx->pkey = EVP_PKCS82PKEY_ex(PKCS12_SAFEBAG_get0_p8inf(bag),
315
0
            libctx, propq);
316
0
        if (*ctx->pkey == NULL)
317
0
            return 0;
318
0
        break;
319
320
0
    case NID_pkcs8ShroudedKeyBag:
321
0
        if (ctx->pkey == NULL || *ctx->pkey != NULL)
322
0
            return 1;
323
0
        if ((p8 = PKCS12_decrypt_skey_ex(bag, pass, passlen,
324
0
                 libctx, propq))
325
0
            == NULL)
326
0
            return 0;
327
0
        *ctx->pkey = EVP_PKCS82PKEY_ex(p8, libctx, propq);
328
0
        PKCS8_PRIV_KEY_INFO_free(p8);
329
0
        if (!(*ctx->pkey))
330
0
            return 0;
331
0
        break;
332
333
0
    case NID_certBag:
334
0
        if (ctx->ocerts == NULL
335
0
            || PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
336
0
            return 1;
337
0
        if ((x509 = PKCS12_SAFEBAG_get1_cert_ex(bag, libctx, propq)) == NULL)
338
0
            return 0;
339
0
        if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) {
340
0
            X509_free(x509);
341
0
            return 0;
342
0
        }
343
0
        if (fname) {
344
0
            int len, r;
345
0
            unsigned char *data;
346
347
0
            len = ASN1_STRING_to_UTF8(&data, fname);
348
0
            if (len >= 0) {
349
0
                r = X509_alias_set1(x509, data, len);
350
0
                OPENSSL_free(data);
351
0
                if (!r) {
352
0
                    X509_free(x509);
353
0
                    return 0;
354
0
                }
355
0
            }
356
0
        }
357
358
0
        if (!sk_X509_push(ctx->ocerts, x509)) {
359
0
            X509_free(x509);
360
0
            return 0;
361
0
        }
362
363
0
        break;
364
365
0
    case NID_secretBag:
366
0
        if (ctx->skeys == NULL)
367
0
            return 1;
368
0
        if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_pkcs8ShroudedKeyBag)
369
0
            return 1;
370
0
        {
371
0
            EVP_SKEY *skey;
372
0
            OSSL_PARAM extra[3];
373
0
            int nparams = 0;
374
0
            unsigned char *fname_utf8 = NULL;
375
0
            int fname_utf8_len = 0;
376
0
            PKCS8_PRIV_KEY_INFO *p8sb = PKCS12_decrypt_secretbag(bag, pass,
377
0
                passlen, libctx, propq);
378
379
0
            if (p8sb == NULL)
380
0
                return 0;
381
382
0
            if (fname) {
383
0
                fname_utf8_len = ASN1_STRING_to_UTF8(&fname_utf8, fname);
384
0
                if (fname_utf8_len >= 0)
385
0
                    extra[nparams++] = OSSL_PARAM_construct_utf8_string(
386
0
                        OSSL_SKEY_PARAM_ALIAS,
387
0
                        (char *)fname_utf8, (size_t)fname_utf8_len);
388
0
            }
389
0
            if (lkid)
390
0
                extra[nparams++] = OSSL_PARAM_construct_octet_string(
391
0
                    OSSL_SKEY_PARAM_LOCAL_KEYID,
392
0
                    lkid->data, (size_t)lkid->length);
393
0
            extra[nparams] = OSSL_PARAM_construct_end();
394
395
0
            skey = PKCS8_PRIV_KEY_INFO_get1_skey(p8sb, libctx, propq,
396
0
                extra, 1);
397
0
            PKCS8_PRIV_KEY_INFO_free(p8sb);
398
0
            OPENSSL_free(fname_utf8);
399
0
            if (skey == NULL) {
400
0
                ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR);
401
0
                return 0;
402
0
            }
403
0
            if (*ctx->skeys == NULL
404
0
                && (*ctx->skeys = sk_EVP_SKEY_new_null()) == NULL) {
405
0
                EVP_SKEY_free(skey);
406
0
                return 0;
407
0
            }
408
0
            if (!sk_EVP_SKEY_push(*ctx->skeys, skey)) {
409
0
                EVP_SKEY_free(skey);
410
0
                return 0;
411
0
            }
412
0
        }
413
0
        return 1;
414
415
0
    case NID_safeContentsBag:
416
0
        return parse_bags(PKCS12_SAFEBAG_get0_safes(bag), pass, passlen, ctx,
417
0
            libctx, propq);
418
419
0
    default:
420
0
        return 1;
421
0
    }
422
0
    return 1;
423
0
}