1/*
2 * Copyright 1999-2023 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 "p12_local.h"
14
15static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
16                          PKCS12_SAFEBAG *bag);
17static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
18                                           X509 *cert,
19                                           const char *name,
20                                           int namelen,
21                                           unsigned char *keyid,
22                                           int keyidlen);
23
24static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
25{
26    int idx;
27    X509_ATTRIBUTE *attr;
28    idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1);
29    if (idx < 0)
30        return 1;
31    attr = EVP_PKEY_get_attr(pkey, idx);
32    if (!X509at_add1_attr(&bag->attrib, attr))
33        return 0;
34    return 1;
35}
36
37PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
38                         X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
39                         int iter, int mac_iter, int keytype,
40                         OSSL_LIB_CTX *ctx, const char *propq)
41{
42    PKCS12 *p12 = NULL;
43    STACK_OF(PKCS7) *safes = NULL;
44    STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
45    PKCS12_SAFEBAG *bag = NULL;
46    int i;
47    unsigned char keyid[EVP_MAX_MD_SIZE];
48    unsigned int keyidlen = 0;
49    int namelen = -1;
50    unsigned char *pkeyid = NULL;
51    int pkeyidlen = -1;
52
53    /* Set defaults */
54    if (nid_cert == NID_undef)
55        nid_cert = NID_aes_256_cbc;
56    if (nid_key == NID_undef)
57        nid_key = NID_aes_256_cbc;
58    if (!iter)
59        iter = PKCS12_DEFAULT_ITER;
60    if (!mac_iter)
61        mac_iter = PKCS12_DEFAULT_ITER;
62
63    if (pkey == NULL && cert == NULL && ca == NULL) {
64        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_ARGUMENT);
65        return NULL;
66    }
67
68    if (pkey && cert) {
69        if (!X509_check_private_key(cert, pkey))
70            return NULL;
71        if (!X509_digest(cert, EVP_sha1(), keyid, &keyidlen))
72            return NULL;
73    }
74
75    if (cert) {
76        if (name == NULL)
77            name = (char *)X509_alias_get0(cert, &namelen);
78        if (keyidlen > 0) {
79            pkeyid = keyid;
80            pkeyidlen = keyidlen;
81        } else {
82            pkeyid = X509_keyid_get0(cert, &pkeyidlen);
83        }
84
85        bag = pkcs12_add_cert_bag(&bags, cert, name, namelen, pkeyid, pkeyidlen);
86    }
87
88    /* Add all other certificates */
89    for (i = 0; i < sk_X509_num(ca); i++) {
90        if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
91            goto err;
92    }
93
94    if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass,
95                                    ctx, propq))
96        goto err;
97
98    sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
99    bags = NULL;
100
101    if (pkey) {
102        bag = PKCS12_add_key_ex(&bags, pkey, keytype, iter, nid_key, pass,
103                                ctx, propq);
104
105        if (!bag)
106            goto err;
107
108        if (!copy_bag_attr(bag, pkey, NID_ms_csp_name))
109            goto err;
110        if (!copy_bag_attr(bag, pkey, NID_LocalKeySet))
111            goto err;
112
113        if (name && !PKCS12_add_friendlyname(bag, name, -1))
114            goto err;
115        if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
116            goto err;
117    }
118
119    if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
120        goto err;
121
122    sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
123    bags = NULL;
124
125    p12 = PKCS12_add_safes_ex(safes, 0, ctx, propq);
126
127    if (p12 == NULL)
128        goto err;
129
130    sk_PKCS7_pop_free(safes, PKCS7_free);
131
132    safes = NULL;
133
134    if ((mac_iter != -1) &&
135        !PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL))
136        goto err;
137
138    return p12;
139
140 err:
141    PKCS12_free(p12);
142    sk_PKCS7_pop_free(safes, PKCS7_free);
143    sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
144    return NULL;
145
146}
147
148PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
149                      STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
150                      int mac_iter, int keytype)
151{
152    return PKCS12_create_ex(pass, name, pkey, cert, ca, nid_key, nid_cert,
153                            iter, mac_iter, keytype, NULL, NULL);
154}
155
156static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
157                                           X509 *cert,
158                                           const char *name,
159                                           int namelen,
160                                           unsigned char *keyid,
161                                           int keyidlen)
162{
163    PKCS12_SAFEBAG *bag = NULL;
164
165    /* Add user certificate */
166    if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL)
167        goto err;
168
169    if (name != NULL && !PKCS12_add_friendlyname(bag, name, namelen))
170        goto err;
171
172    if (keyid != NULL && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
173        goto err;
174
175    if (!pkcs12_add_bag(pbags, bag))
176        goto err;
177
178    return bag;
179
180 err:
181    PKCS12_SAFEBAG_free(bag);
182    return NULL;
183}
184
185PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
186{
187    char *name = NULL;
188    int namelen = -1;
189    unsigned char *keyid = NULL;
190    int keyidlen = -1;
191
192    /*
193     * Use friendlyName and localKeyID in certificate. (if present)
194     */
195    name = (char *)X509_alias_get0(cert, &namelen);
196    keyid = X509_keyid_get0(cert, &keyidlen);
197
198    return pkcs12_add_cert_bag(pbags, cert, name, namelen, keyid, keyidlen);
199}
200
201PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
202                                  EVP_PKEY *key, int key_usage, int iter,
203                                  int nid_key, const char *pass,
204                                  OSSL_LIB_CTX *ctx, const char *propq)
205{
206
207    PKCS12_SAFEBAG *bag = NULL;
208    PKCS8_PRIV_KEY_INFO *p8 = NULL;
209
210    /* Make a PKCS#8 structure */
211    if ((p8 = EVP_PKEY2PKCS8(key)) == NULL)
212        goto err;
213    if (key_usage && !PKCS8_add_keyusage(p8, key_usage))
214        goto err;
215    if (nid_key != -1) {
216        bag = PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(nid_key, pass, -1, NULL, 0,
217                                                     iter, p8, ctx, propq);
218        PKCS8_PRIV_KEY_INFO_free(p8);
219    } else
220        bag = PKCS12_SAFEBAG_create0_p8inf(p8);
221
222    if (!bag)
223        goto err;
224
225    if (!pkcs12_add_bag(pbags, bag))
226        goto err;
227
228    return bag;
229
230 err:
231    PKCS12_SAFEBAG_free(bag);
232    return NULL;
233
234}
235
236PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
237                               EVP_PKEY *key, int key_usage, int iter,
238                               int nid_key, const char *pass)
239{
240    return PKCS12_add_key_ex(pbags, key, key_usage, iter, nid_key, pass,
241                             NULL, NULL);
242}
243
244PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
245                                  int nid_type, const unsigned char *value, int len)
246{
247    PKCS12_SAFEBAG *bag = NULL;
248
249    /* Add secret, storing the value as an octet string */
250    if ((bag = PKCS12_SAFEBAG_create_secret(nid_type, V_ASN1_OCTET_STRING, value, len)) == NULL)
251        goto err;
252
253    if (!pkcs12_add_bag(pbags, bag))
254        goto err;
255
256    return bag;
257 err:
258    PKCS12_SAFEBAG_free(bag);
259    return NULL;
260}
261
262int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
263                       int nid_safe, int iter, const char *pass,
264                       OSSL_LIB_CTX *ctx, const char *propq)
265{
266    PKCS7 *p7 = NULL;
267    int free_safes = 0;
268
269    if (*psafes == NULL) {
270        *psafes = sk_PKCS7_new_null();
271        if (*psafes == NULL)
272            return 0;
273        free_safes = 1;
274    }
275
276    if (nid_safe == 0)
277#ifdef OPENSSL_NO_RC2
278        nid_safe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
279#else
280        nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC;
281#endif
282
283    if (nid_safe == -1)
284        p7 = PKCS12_pack_p7data(bags);
285    else
286        p7 = PKCS12_pack_p7encdata_ex(nid_safe, pass, -1, NULL, 0, iter, bags, ctx, propq);
287    if (p7 == NULL)
288        goto err;
289
290    if (!sk_PKCS7_push(*psafes, p7))
291        goto err;
292
293    return 1;
294
295 err:
296    if (free_safes) {
297        sk_PKCS7_free(*psafes);
298        *psafes = NULL;
299    }
300    PKCS7_free(p7);
301    return 0;
302}
303
304int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
305                    int nid_safe, int iter, const char *pass)
306{
307    return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL);
308}
309
310static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
311                          PKCS12_SAFEBAG *bag)
312{
313    int free_bags = 0;
314
315    if (pbags == NULL)
316        return 1;
317    if (*pbags == NULL) {
318        *pbags = sk_PKCS12_SAFEBAG_new_null();
319        if (*pbags == NULL)
320            return 0;
321        free_bags = 1;
322    }
323
324    if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) {
325        if (free_bags) {
326            sk_PKCS12_SAFEBAG_free(*pbags);
327            *pbags = NULL;
328        }
329        return 0;
330    }
331
332    return 1;
333
334}
335
336PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int nid_p7,
337                            OSSL_LIB_CTX *ctx, const char *propq)
338{
339    PKCS12 *p12;
340
341    if (nid_p7 <= 0)
342        nid_p7 = NID_pkcs7_data;
343    p12 = PKCS12_init_ex(nid_p7, ctx, propq);
344    if (p12 == NULL)
345        return NULL;
346
347    if (!PKCS12_pack_authsafes(p12, safes)) {
348        PKCS12_free(p12);
349        return NULL;
350    }
351
352    return p12;
353
354}
355
356PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
357{
358    return PKCS12_add_safes_ex(safes, nid_p7, NULL, NULL);
359}
360