1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <stdio.h>
11e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
12e1051a39Sopenharmony_ci#include <openssl/pkcs12.h>
13e1051a39Sopenharmony_ci#include "p12_local.h"
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_1_1_0
16e1051a39Sopenharmony_ciASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid)
17e1051a39Sopenharmony_ci{
18e1051a39Sopenharmony_ci    return PKCS12_get_attr_gen(bag->attrib, attr_nid);
19e1051a39Sopenharmony_ci}
20e1051a39Sopenharmony_ci#endif
21e1051a39Sopenharmony_ci
22e1051a39Sopenharmony_ciconst ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag,
23e1051a39Sopenharmony_ci                                          int attr_nid)
24e1051a39Sopenharmony_ci{
25e1051a39Sopenharmony_ci    return PKCS12_get_attr_gen(bag->attrib, attr_nid);
26e1051a39Sopenharmony_ci}
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ciASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid)
29e1051a39Sopenharmony_ci{
30e1051a39Sopenharmony_ci    return PKCS12_get_attr_gen(PKCS8_pkey_get0_attrs(p8), attr_nid);
31e1051a39Sopenharmony_ci}
32e1051a39Sopenharmony_ci
33e1051a39Sopenharmony_ciconst PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag)
34e1051a39Sopenharmony_ci{
35e1051a39Sopenharmony_ci    if (PKCS12_SAFEBAG_get_nid(bag) != NID_keyBag)
36e1051a39Sopenharmony_ci        return NULL;
37e1051a39Sopenharmony_ci    return bag->value.keybag;
38e1051a39Sopenharmony_ci}
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ciconst X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag)
41e1051a39Sopenharmony_ci{
42e1051a39Sopenharmony_ci    if (OBJ_obj2nid(bag->type) != NID_pkcs8ShroudedKeyBag)
43e1051a39Sopenharmony_ci        return NULL;
44e1051a39Sopenharmony_ci    return bag->value.shkeybag;
45e1051a39Sopenharmony_ci}
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_ciconst STACK_OF(PKCS12_SAFEBAG) *
48e1051a39Sopenharmony_ciPKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag)
49e1051a39Sopenharmony_ci{
50e1051a39Sopenharmony_ci    if (OBJ_obj2nid(bag->type) != NID_safeContentsBag)
51e1051a39Sopenharmony_ci        return NULL;
52e1051a39Sopenharmony_ci    return bag->value.safes;
53e1051a39Sopenharmony_ci}
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ciconst ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag)
56e1051a39Sopenharmony_ci{
57e1051a39Sopenharmony_ci    return bag->type;
58e1051a39Sopenharmony_ci}
59e1051a39Sopenharmony_ci
60e1051a39Sopenharmony_ciint PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag)
61e1051a39Sopenharmony_ci{
62e1051a39Sopenharmony_ci    return OBJ_obj2nid(bag->type);
63e1051a39Sopenharmony_ci}
64e1051a39Sopenharmony_ci
65e1051a39Sopenharmony_ciint PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag)
66e1051a39Sopenharmony_ci{
67e1051a39Sopenharmony_ci    int btype = PKCS12_SAFEBAG_get_nid(bag);
68e1051a39Sopenharmony_ci
69e1051a39Sopenharmony_ci    if (btype != NID_certBag && btype != NID_crlBag && btype != NID_secretBag)
70e1051a39Sopenharmony_ci        return -1;
71e1051a39Sopenharmony_ci    return OBJ_obj2nid(bag->value.bag->type);
72e1051a39Sopenharmony_ci}
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_ciconst ASN1_OBJECT *PKCS12_SAFEBAG_get0_bag_type(const PKCS12_SAFEBAG *bag)
75e1051a39Sopenharmony_ci{
76e1051a39Sopenharmony_ci    return bag->value.bag->type;
77e1051a39Sopenharmony_ci}
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ciconst ASN1_TYPE *PKCS12_SAFEBAG_get0_bag_obj(const PKCS12_SAFEBAG *bag)
80e1051a39Sopenharmony_ci{
81e1051a39Sopenharmony_ci    return bag->value.bag->value.other;
82e1051a39Sopenharmony_ci}
83e1051a39Sopenharmony_ci
84e1051a39Sopenharmony_ciX509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag)
85e1051a39Sopenharmony_ci{
86e1051a39Sopenharmony_ci    if (PKCS12_SAFEBAG_get_nid(bag) != NID_certBag)
87e1051a39Sopenharmony_ci        return NULL;
88e1051a39Sopenharmony_ci    if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate)
89e1051a39Sopenharmony_ci        return NULL;
90e1051a39Sopenharmony_ci    return ASN1_item_unpack(bag->value.bag->value.octet,
91e1051a39Sopenharmony_ci                            ASN1_ITEM_rptr(X509));
92e1051a39Sopenharmony_ci}
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ciX509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag)
95e1051a39Sopenharmony_ci{
96e1051a39Sopenharmony_ci    if (PKCS12_SAFEBAG_get_nid(bag) != NID_crlBag)
97e1051a39Sopenharmony_ci        return NULL;
98e1051a39Sopenharmony_ci    if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Crl)
99e1051a39Sopenharmony_ci        return NULL;
100e1051a39Sopenharmony_ci    return ASN1_item_unpack(bag->value.bag->value.octet,
101e1051a39Sopenharmony_ci                            ASN1_ITEM_rptr(X509_CRL));
102e1051a39Sopenharmony_ci}
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509)
105e1051a39Sopenharmony_ci{
106e1051a39Sopenharmony_ci    return PKCS12_item_pack_safebag(x509, ASN1_ITEM_rptr(X509),
107e1051a39Sopenharmony_ci                                    NID_x509Certificate, NID_certBag);
108e1051a39Sopenharmony_ci}
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl)
111e1051a39Sopenharmony_ci{
112e1051a39Sopenharmony_ci    return PKCS12_item_pack_safebag(crl, ASN1_ITEM_rptr(X509_CRL),
113e1051a39Sopenharmony_ci                                    NID_x509Crl, NID_crlBag);
114e1051a39Sopenharmony_ci}
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_SAFEBAG_create_secret(int type, int vtype, const unsigned char *value, int len)
117e1051a39Sopenharmony_ci{
118e1051a39Sopenharmony_ci    PKCS12_BAGS *bag;
119e1051a39Sopenharmony_ci    PKCS12_SAFEBAG *safebag;
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ci    if ((bag = PKCS12_BAGS_new()) == NULL) {
122e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
123e1051a39Sopenharmony_ci        return NULL;
124e1051a39Sopenharmony_ci    }
125e1051a39Sopenharmony_ci    bag->type = OBJ_nid2obj(type);
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ci    switch(vtype) {
128e1051a39Sopenharmony_ci    case V_ASN1_OCTET_STRING:
129e1051a39Sopenharmony_ci        {
130e1051a39Sopenharmony_ci            ASN1_OCTET_STRING *strtmp = ASN1_OCTET_STRING_new();
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_ci            if (strtmp == NULL) {
133e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
134e1051a39Sopenharmony_ci                goto err;
135e1051a39Sopenharmony_ci            }
136e1051a39Sopenharmony_ci            /* Pack data into an octet string */
137e1051a39Sopenharmony_ci            if (!ASN1_OCTET_STRING_set(strtmp, value, len)) {
138e1051a39Sopenharmony_ci                ASN1_OCTET_STRING_free(strtmp);
139e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCODE_ERROR);
140e1051a39Sopenharmony_ci                goto err;
141e1051a39Sopenharmony_ci            }
142e1051a39Sopenharmony_ci            bag->value.other = ASN1_TYPE_new();
143e1051a39Sopenharmony_ci            if (bag->value.other == NULL) {
144e1051a39Sopenharmony_ci                ASN1_OCTET_STRING_free(strtmp);
145e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
146e1051a39Sopenharmony_ci                goto err;
147e1051a39Sopenharmony_ci            }
148e1051a39Sopenharmony_ci            ASN1_TYPE_set(bag->value.other, vtype, strtmp);
149e1051a39Sopenharmony_ci        }
150e1051a39Sopenharmony_ci        break;
151e1051a39Sopenharmony_ci
152e1051a39Sopenharmony_ci    default:
153e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_TYPE);
154e1051a39Sopenharmony_ci        goto err;
155e1051a39Sopenharmony_ci    }
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ci    if ((safebag = PKCS12_SAFEBAG_new()) == NULL) {
158e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
159e1051a39Sopenharmony_ci        goto err;
160e1051a39Sopenharmony_ci    }
161e1051a39Sopenharmony_ci    safebag->value.bag = bag;
162e1051a39Sopenharmony_ci    safebag->type = OBJ_nid2obj(NID_secretBag);
163e1051a39Sopenharmony_ci    return safebag;
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ci err:
166e1051a39Sopenharmony_ci    PKCS12_BAGS_free(bag);
167e1051a39Sopenharmony_ci    return NULL;
168e1051a39Sopenharmony_ci}
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ci/* Turn PKCS8 object into a keybag */
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8)
173e1051a39Sopenharmony_ci{
174e1051a39Sopenharmony_ci    PKCS12_SAFEBAG *bag = PKCS12_SAFEBAG_new();
175e1051a39Sopenharmony_ci
176e1051a39Sopenharmony_ci    if (bag == NULL) {
177e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
178e1051a39Sopenharmony_ci        return NULL;
179e1051a39Sopenharmony_ci    }
180e1051a39Sopenharmony_ci    bag->type = OBJ_nid2obj(NID_keyBag);
181e1051a39Sopenharmony_ci    bag->value.keybag = p8;
182e1051a39Sopenharmony_ci    return bag;
183e1051a39Sopenharmony_ci}
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci/* Turn PKCS8 object into a shrouded keybag */
186e1051a39Sopenharmony_ci
187e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8)
188e1051a39Sopenharmony_ci{
189e1051a39Sopenharmony_ci    PKCS12_SAFEBAG *bag = PKCS12_SAFEBAG_new();
190e1051a39Sopenharmony_ci
191e1051a39Sopenharmony_ci    /* Set up the safe bag */
192e1051a39Sopenharmony_ci    if (bag == NULL) {
193e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
194e1051a39Sopenharmony_ci        return NULL;
195e1051a39Sopenharmony_ci    }
196e1051a39Sopenharmony_ci    bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag);
197e1051a39Sopenharmony_ci    bag->value.shkeybag = p8;
198e1051a39Sopenharmony_ci    return bag;
199e1051a39Sopenharmony_ci}
200e1051a39Sopenharmony_ci
201e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(int pbe_nid,
202e1051a39Sopenharmony_ci                                                       const char *pass,
203e1051a39Sopenharmony_ci                                                       int passlen,
204e1051a39Sopenharmony_ci                                                       unsigned char *salt,
205e1051a39Sopenharmony_ci                                                       int saltlen, int iter,
206e1051a39Sopenharmony_ci                                                       PKCS8_PRIV_KEY_INFO *p8inf,
207e1051a39Sopenharmony_ci                                                       OSSL_LIB_CTX *ctx,
208e1051a39Sopenharmony_ci                                                       const char *propq)
209e1051a39Sopenharmony_ci{
210e1051a39Sopenharmony_ci    PKCS12_SAFEBAG *bag = NULL;
211e1051a39Sopenharmony_ci    const EVP_CIPHER *pbe_ciph = NULL;
212e1051a39Sopenharmony_ci    EVP_CIPHER *pbe_ciph_fetch = NULL;
213e1051a39Sopenharmony_ci    X509_SIG *p8;
214e1051a39Sopenharmony_ci
215e1051a39Sopenharmony_ci    ERR_set_mark();
216e1051a39Sopenharmony_ci    pbe_ciph = pbe_ciph_fetch = EVP_CIPHER_fetch(ctx, OBJ_nid2sn(pbe_nid), propq);
217e1051a39Sopenharmony_ci    if (pbe_ciph == NULL)
218e1051a39Sopenharmony_ci        pbe_ciph = EVP_get_cipherbynid(pbe_nid);
219e1051a39Sopenharmony_ci    ERR_pop_to_mark();
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ci    if (pbe_ciph != NULL)
222e1051a39Sopenharmony_ci        pbe_nid = -1;
223e1051a39Sopenharmony_ci
224e1051a39Sopenharmony_ci    p8 = PKCS8_encrypt_ex(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
225e1051a39Sopenharmony_ci                          p8inf, ctx, propq);
226e1051a39Sopenharmony_ci    if (p8 == NULL)
227e1051a39Sopenharmony_ci        goto err;
228e1051a39Sopenharmony_ci
229e1051a39Sopenharmony_ci    bag = PKCS12_SAFEBAG_create0_pkcs8(p8);
230e1051a39Sopenharmony_ci    if (bag == NULL)
231e1051a39Sopenharmony_ci        X509_SIG_free(p8);
232e1051a39Sopenharmony_ci
233e1051a39Sopenharmony_cierr:
234e1051a39Sopenharmony_ci    EVP_CIPHER_free(pbe_ciph_fetch);
235e1051a39Sopenharmony_ci    return bag;
236e1051a39Sopenharmony_ci}
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
239e1051a39Sopenharmony_ci                                                    const char *pass,
240e1051a39Sopenharmony_ci                                                    int passlen,
241e1051a39Sopenharmony_ci                                                    unsigned char *salt,
242e1051a39Sopenharmony_ci                                                    int saltlen, int iter,
243e1051a39Sopenharmony_ci                                                    PKCS8_PRIV_KEY_INFO *p8inf)
244e1051a39Sopenharmony_ci{
245e1051a39Sopenharmony_ci    return PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(pbe_nid, pass, passlen,
246e1051a39Sopenharmony_ci                                                  salt, saltlen, iter, p8inf,
247e1051a39Sopenharmony_ci                                                  NULL, NULL);
248e1051a39Sopenharmony_ci}
249