1*9781SMoriah.Waterland@Sun.COM /*
2*9781SMoriah.Waterland@Sun.COM * ====================================================================
3*9781SMoriah.Waterland@Sun.COM * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
4*9781SMoriah.Waterland@Sun.COM *
5*9781SMoriah.Waterland@Sun.COM * Redistribution and use in source and binary forms, with or without
6*9781SMoriah.Waterland@Sun.COM * modification, are permitted provided that the following conditions
7*9781SMoriah.Waterland@Sun.COM * are met:
8*9781SMoriah.Waterland@Sun.COM *
9*9781SMoriah.Waterland@Sun.COM * 1. Redistributions of source code must retain the above copyright
10*9781SMoriah.Waterland@Sun.COM * notice, this list of conditions and the following disclaimer.
11*9781SMoriah.Waterland@Sun.COM *
12*9781SMoriah.Waterland@Sun.COM * 2. Redistributions in binary form must reproduce the above copyright
13*9781SMoriah.Waterland@Sun.COM * notice, this list of conditions and the following disclaimer in
14*9781SMoriah.Waterland@Sun.COM * the documentation and/or other materials provided with the
15*9781SMoriah.Waterland@Sun.COM * distribution.
16*9781SMoriah.Waterland@Sun.COM *
17*9781SMoriah.Waterland@Sun.COM * 3. All advertising materials mentioning features or use of this
18*9781SMoriah.Waterland@Sun.COM * software must display the following acknowledgment:
19*9781SMoriah.Waterland@Sun.COM * "This product includes software developed by the OpenSSL Project
20*9781SMoriah.Waterland@Sun.COM * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21*9781SMoriah.Waterland@Sun.COM *
22*9781SMoriah.Waterland@Sun.COM * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23*9781SMoriah.Waterland@Sun.COM * endorse or promote products derived from this software without
24*9781SMoriah.Waterland@Sun.COM * prior written permission. For written permission, please contact
25*9781SMoriah.Waterland@Sun.COM * licensing@OpenSSL.org.
26*9781SMoriah.Waterland@Sun.COM *
27*9781SMoriah.Waterland@Sun.COM * 5. Products derived from this software may not be called "OpenSSL"
28*9781SMoriah.Waterland@Sun.COM * nor may "OpenSSL" appear in their names without prior written
29*9781SMoriah.Waterland@Sun.COM * permission of the OpenSSL Project.
30*9781SMoriah.Waterland@Sun.COM *
31*9781SMoriah.Waterland@Sun.COM * 6. Redistributions of any form whatsoever must retain the following
32*9781SMoriah.Waterland@Sun.COM * acknowledgment:
33*9781SMoriah.Waterland@Sun.COM * "This product includes software developed by the OpenSSL Project
34*9781SMoriah.Waterland@Sun.COM * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35*9781SMoriah.Waterland@Sun.COM *
36*9781SMoriah.Waterland@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37*9781SMoriah.Waterland@Sun.COM * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38*9781SMoriah.Waterland@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39*9781SMoriah.Waterland@Sun.COM * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40*9781SMoriah.Waterland@Sun.COM * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41*9781SMoriah.Waterland@Sun.COM * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42*9781SMoriah.Waterland@Sun.COM * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43*9781SMoriah.Waterland@Sun.COM * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44*9781SMoriah.Waterland@Sun.COM * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45*9781SMoriah.Waterland@Sun.COM * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46*9781SMoriah.Waterland@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47*9781SMoriah.Waterland@Sun.COM * OF THE POSSIBILITY OF SUCH DAMAGE.
48*9781SMoriah.Waterland@Sun.COM * ====================================================================
49*9781SMoriah.Waterland@Sun.COM *
50*9781SMoriah.Waterland@Sun.COM * This product includes cryptographic software written by Eric Young
51*9781SMoriah.Waterland@Sun.COM * (eay@cryptsoft.com). This product includes software written by Tim
52*9781SMoriah.Waterland@Sun.COM * Hudson (tjh@cryptsoft.com).
53*9781SMoriah.Waterland@Sun.COM *
54*9781SMoriah.Waterland@Sun.COM */
55*9781SMoriah.Waterland@Sun.COM
56*9781SMoriah.Waterland@Sun.COM /*
57*9781SMoriah.Waterland@Sun.COM * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
58*9781SMoriah.Waterland@Sun.COM * Use is subject to license terms.
59*9781SMoriah.Waterland@Sun.COM */
60*9781SMoriah.Waterland@Sun.COM
61*9781SMoriah.Waterland@Sun.COM
62*9781SMoriah.Waterland@Sun.COM #include <strings.h>
63*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
64*9781SMoriah.Waterland@Sun.COM #include <assert.h>
65*9781SMoriah.Waterland@Sun.COM
66*9781SMoriah.Waterland@Sun.COM #include <openssl/crypto.h>
67*9781SMoriah.Waterland@Sun.COM #include <openssl/err.h>
68*9781SMoriah.Waterland@Sun.COM #include <openssl/x509.h>
69*9781SMoriah.Waterland@Sun.COM #include <openssl/pem.h>
70*9781SMoriah.Waterland@Sun.COM
71*9781SMoriah.Waterland@Sun.COM #include <openssl/pkcs12.h>
72*9781SMoriah.Waterland@Sun.COM #include "p12lib.h"
73*9781SMoriah.Waterland@Sun.COM
74*9781SMoriah.Waterland@Sun.COM /*
75*9781SMoriah.Waterland@Sun.COM * OpenSSL provides a framework for pushing error codes onto a stack.
76*9781SMoriah.Waterland@Sun.COM * When an error occurs, the consumer may use the framework to
77*9781SMoriah.Waterland@Sun.COM * pop the errors off the stack and provide a trace of where the
78*9781SMoriah.Waterland@Sun.COM * errors occurred.
79*9781SMoriah.Waterland@Sun.COM *
80*9781SMoriah.Waterland@Sun.COM * Our PKCS12 code plugs into this framework by calling
81*9781SMoriah.Waterland@Sun.COM * ERR_load_SUNW_strings(). To push an error (which by the way, consists
82*9781SMoriah.Waterland@Sun.COM * of a function code and an error code) onto the stack our PKCS12 code
83*9781SMoriah.Waterland@Sun.COM * calls SUNWerr().
84*9781SMoriah.Waterland@Sun.COM *
85*9781SMoriah.Waterland@Sun.COM * Consumers of our PKCS12 code can then call the OpenSSL error routines
86*9781SMoriah.Waterland@Sun.COM * when an error occurs and retrieve the stack of errors.
87*9781SMoriah.Waterland@Sun.COM */
88*9781SMoriah.Waterland@Sun.COM
89*9781SMoriah.Waterland@Sun.COM #ifndef OPENSSL_NO_ERR
90*9781SMoriah.Waterland@Sun.COM
91*9781SMoriah.Waterland@Sun.COM /* Function codes and their matching strings */
92*9781SMoriah.Waterland@Sun.COM static ERR_STRING_DATA SUNW_str_functs[] = {
93*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_USE_X509CERT, 0), "sunw_use_x509cert" },
94*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_USE_PKEY, 0), "sunw_use_pkey" },
95*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_USE_TASTORE, 0), "sunw_use_tastore" },
96*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_USE_CERTFILE, 0), "sunw_p12_use_certfile" },
97*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_USE_KEYFILE, 0), "sunw_p12_use_keyfile" },
98*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_USE_TRUSTFILE, 0), "sunw_p12_use_trustfile" },
99*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_READ_FILE, 0), "p12_read_file" },
100*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_DOPARSE, 0), "p12_doparse" },
101*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_PKCS12_PARSE, 0), "sunw_PKCS12_parse" },
102*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_PKCS12_CONTENTS, 0), "sunw_PKCS12_contents" },
103*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_PARSE_ONE_BAG, 0), "parse_one_bag" },
104*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_PKCS12_CREATE, 0), "sunw_PKCS12_create" },
105*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_SPLIT_CERTS, 0), "sunw_split_certs" },
106*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_FIND_LOCALKEYID, 0), "sunw_find_localkeyid" },
107*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_SET_LOCALKEYID, 0), "sunw_set_localkeyid" },
108*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_GET_LOCALKEYID, 0), "sunw_get_localkeyid" },
109*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_SET_FNAME, 0), "sunw_set_fname" },
110*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_GET_PKEY_FNAME, 0), "sunw_get_pkey_fname" },
111*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_APPEND_KEYS, 0), "sunw_append_keys" },
112*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_PEM_CONTENTS, 0), "sunw_PEM_contents" },
113*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_PEM_INFO, 0), "pem_info" },
114*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_ASC2BMPSTRING, 0), "asc2bmpstring" },
115*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_UTF82ASCSTR, 0), "utf82ascstr" },
116*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_FINDATTR, 0), "findattr" },
117*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_TYPE2ATTRIB, 0), "type2attrib" },
118*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_MOVE_CERTS, 0), "move_certs" },
119*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_FIND_FNAME, 0), "sunw_find_fname" },
120*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_PARSE_OUTER, 0), "parse_outer" },
121*9781SMoriah.Waterland@Sun.COM { ERR_PACK(0, SUNW_F_CHECKFILE, 0), "checkfile" },
122*9781SMoriah.Waterland@Sun.COM { 0, NULL }
123*9781SMoriah.Waterland@Sun.COM };
124*9781SMoriah.Waterland@Sun.COM
125*9781SMoriah.Waterland@Sun.COM /* Error codes and their matching strings */
126*9781SMoriah.Waterland@Sun.COM static ERR_STRING_DATA SUNW_str_reasons[] = {
127*9781SMoriah.Waterland@Sun.COM { SUNW_R_INVALID_ARG, "invalid argument" },
128*9781SMoriah.Waterland@Sun.COM { SUNW_R_MEMORY_FAILURE, "memory failure" },
129*9781SMoriah.Waterland@Sun.COM { SUNW_R_MAC_VERIFY_FAILURE, "mac verify failure" },
130*9781SMoriah.Waterland@Sun.COM { SUNW_R_MAC_CREATE_FAILURE, "mac create failure" },
131*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_FILETYPE, "bad file type" },
132*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_PKEY, "bad or missing private key" },
133*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_PKEYTYPE, "unsupported key type" },
134*9781SMoriah.Waterland@Sun.COM { SUNW_R_PKEY_READ_ERR, "unable to read private key" },
135*9781SMoriah.Waterland@Sun.COM { SUNW_R_NO_TRUST_ANCHOR, "no trust anchors found" },
136*9781SMoriah.Waterland@Sun.COM { SUNW_R_READ_TRUST_ERR, "unable to read trust anchor" },
137*9781SMoriah.Waterland@Sun.COM { SUNW_R_ADD_TRUST_ERR, "unable to add trust anchor" },
138*9781SMoriah.Waterland@Sun.COM { SUNW_R_PKCS12_PARSE_ERR, "PKCS12 parse error" },
139*9781SMoriah.Waterland@Sun.COM { SUNW_R_PKCS12_CREATE_ERR, "PKCS12 create error" },
140*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_CERTTYPE, "unsupported certificate type" },
141*9781SMoriah.Waterland@Sun.COM { SUNW_R_PARSE_CERT_ERR, "error parsing PKCS12 certificate" },
142*9781SMoriah.Waterland@Sun.COM { SUNW_R_PARSE_BAG_ERR, "error parsing PKCS12 bag" },
143*9781SMoriah.Waterland@Sun.COM { SUNW_R_MAKE_BAG_ERR, "error making PKCS12 bag" },
144*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_LKID, "bad localKeyID format" },
145*9781SMoriah.Waterland@Sun.COM { SUNW_R_SET_LKID_ERR, "error setting localKeyID" },
146*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_FNAME, "bad friendlyName format" },
147*9781SMoriah.Waterland@Sun.COM { SUNW_R_SET_FNAME_ERR, "error setting friendlyName" },
148*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_TRUST, "bad or missing trust anchor" },
149*9781SMoriah.Waterland@Sun.COM { SUNW_R_BAD_BAGTYPE, "unsupported bag type" },
150*9781SMoriah.Waterland@Sun.COM { SUNW_R_CERT_ERR, "certificate error" },
151*9781SMoriah.Waterland@Sun.COM { SUNW_R_PKEY_ERR, "private key error" },
152*9781SMoriah.Waterland@Sun.COM { SUNW_R_READ_ERR, "error reading file" },
153*9781SMoriah.Waterland@Sun.COM { SUNW_R_ADD_ATTR_ERR, "error adding attribute" },
154*9781SMoriah.Waterland@Sun.COM { SUNW_R_STR_CONVERT_ERR, "error converting string" },
155*9781SMoriah.Waterland@Sun.COM { SUNW_R_PKCS12_EMPTY_ERR, "empty PKCS12 structure" },
156*9781SMoriah.Waterland@Sun.COM { SUNW_R_PASSWORD_ERR, "bad password" },
157*9781SMoriah.Waterland@Sun.COM { 0, NULL }
158*9781SMoriah.Waterland@Sun.COM };
159*9781SMoriah.Waterland@Sun.COM
160*9781SMoriah.Waterland@Sun.COM /*
161*9781SMoriah.Waterland@Sun.COM * The library name that our module will be known as. This name
162*9781SMoriah.Waterland@Sun.COM * may be retrieved via OpenSSLs error APIs.
163*9781SMoriah.Waterland@Sun.COM */
164*9781SMoriah.Waterland@Sun.COM static ERR_STRING_DATA SUNW_lib_name[] = {
165*9781SMoriah.Waterland@Sun.COM { 0, SUNW_LIB_NAME },
166*9781SMoriah.Waterland@Sun.COM { 0, NULL }
167*9781SMoriah.Waterland@Sun.COM };
168*9781SMoriah.Waterland@Sun.COM #endif
169*9781SMoriah.Waterland@Sun.COM
170*9781SMoriah.Waterland@Sun.COM /*
171*9781SMoriah.Waterland@Sun.COM * The value of this variable (initialized by a call to
172*9781SMoriah.Waterland@Sun.COM * ERR_load_SUNW_strings()) is what identifies our errors
173*9781SMoriah.Waterland@Sun.COM * to OpenSSL as being ours.
174*9781SMoriah.Waterland@Sun.COM */
175*9781SMoriah.Waterland@Sun.COM static int SUNW_lib_error_code = 0;
176*9781SMoriah.Waterland@Sun.COM
177*9781SMoriah.Waterland@Sun.COM /* local routines */
178*9781SMoriah.Waterland@Sun.COM static int parse_pkcs12(PKCS12 *, const char *, int, char *, int, char *,
179*9781SMoriah.Waterland@Sun.COM EVP_PKEY **, X509 **, STACK_OF(X509) **);
180*9781SMoriah.Waterland@Sun.COM static int pem_info(FILE *, pem_password_cb, void *,
181*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) **, STACK_OF(X509) **);
182*9781SMoriah.Waterland@Sun.COM
183*9781SMoriah.Waterland@Sun.COM static int parse_outer(PKCS12 *, const char *, STACK_OF(EVP_PKEY) *,
184*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *);
185*9781SMoriah.Waterland@Sun.COM
186*9781SMoriah.Waterland@Sun.COM static int parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *, const char *,
187*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
188*9781SMoriah.Waterland@Sun.COM
189*9781SMoriah.Waterland@Sun.COM static int parse_one_bag(PKCS12_SAFEBAG *, const char *,
190*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
191*9781SMoriah.Waterland@Sun.COM
192*9781SMoriah.Waterland@Sun.COM static X509_ATTRIBUTE *type2attrib(ASN1_TYPE *, int);
193*9781SMoriah.Waterland@Sun.COM static ASN1_TYPE *attrib2type(X509_ATTRIBUTE *);
194*9781SMoriah.Waterland@Sun.COM static uchar_t *utf82ascstr(ASN1_UTF8STRING *);
195*9781SMoriah.Waterland@Sun.COM static ASN1_BMPSTRING *asc2bmpstring(const char *, int);
196*9781SMoriah.Waterland@Sun.COM static int find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *, int);
197*9781SMoriah.Waterland@Sun.COM static int find_attr(int, ASN1_STRING *, STACK_OF(EVP_PKEY) *,
198*9781SMoriah.Waterland@Sun.COM EVP_PKEY **, STACK_OF(X509) *, X509 **);
199*9781SMoriah.Waterland@Sun.COM
200*9781SMoriah.Waterland@Sun.COM static chk_errs_t check_time(chk_actions_t, X509 *);
201*9781SMoriah.Waterland@Sun.COM static int get_key_cert(int, STACK_OF(EVP_PKEY) *, EVP_PKEY **,
202*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *, X509 **cert);
203*9781SMoriah.Waterland@Sun.COM static int move_certs(STACK_OF(X509) *, STACK_OF(X509) *);
204*9781SMoriah.Waterland@Sun.COM static int sunw_append_keys(STACK_OF(EVP_PKEY) *,
205*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *);
206*9781SMoriah.Waterland@Sun.COM static int set_results(STACK_OF(EVP_PKEY) **,
207*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) **, STACK_OF(X509) **, STACK_OF(X509) **,
208*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) **, STACK_OF(X509) **,
209*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) **, STACK_OF(EVP_PKEY) **);
210*9781SMoriah.Waterland@Sun.COM
211*9781SMoriah.Waterland@Sun.COM /*
212*9781SMoriah.Waterland@Sun.COM * ----------------------------------------------------------------------------
213*9781SMoriah.Waterland@Sun.COM * Public routines
214*9781SMoriah.Waterland@Sun.COM * ----------------------------------------------------------------------------
215*9781SMoriah.Waterland@Sun.COM */
216*9781SMoriah.Waterland@Sun.COM
217*9781SMoriah.Waterland@Sun.COM /*
218*9781SMoriah.Waterland@Sun.COM * sunw_PKCS12_parse - Parse a PKCS12 structure and break it into its parts.
219*9781SMoriah.Waterland@Sun.COM *
220*9781SMoriah.Waterland@Sun.COM * Parse and decrypt a PKCS#12 structure returning user key, user cert and/or
221*9781SMoriah.Waterland@Sun.COM * other (CA) certs. Note either ca should be NULL, *ca should be NULL,
222*9781SMoriah.Waterland@Sun.COM * or it should point to a valid STACK_OF(X509) structure. pkey and cert can
223*9781SMoriah.Waterland@Sun.COM * be passed uninitialized.
224*9781SMoriah.Waterland@Sun.COM *
225*9781SMoriah.Waterland@Sun.COM * Arguments:
226*9781SMoriah.Waterland@Sun.COM * p12 - Structure with pkcs12 info to be parsed
227*9781SMoriah.Waterland@Sun.COM * pass - Pass phrase for the private key (possibly empty) or NULL if
228*9781SMoriah.Waterland@Sun.COM * there is none.
229*9781SMoriah.Waterland@Sun.COM * matchty - Info about which certs/keys to return if many are in the file.
230*9781SMoriah.Waterland@Sun.COM * keyid - If private key localkeyids friendlynames are to match a
231*9781SMoriah.Waterland@Sun.COM * predetermined value, the value to match. This value should
232*9781SMoriah.Waterland@Sun.COM * be an octet string.
233*9781SMoriah.Waterland@Sun.COM * keyid_len- Length of the keyid byte string.
234*9781SMoriah.Waterland@Sun.COM * name_str - If friendlynames are to match a predetermined value, the value
235*9781SMoriah.Waterland@Sun.COM * to match. This value should be a NULL terminated string.
236*9781SMoriah.Waterland@Sun.COM * pkey - Points to location pointing to the private key returned.
237*9781SMoriah.Waterland@Sun.COM * cert - Points to locaiton which points to the client cert returned
238*9781SMoriah.Waterland@Sun.COM * ca - Points to location that points to a stack of 'certificate
239*9781SMoriah.Waterland@Sun.COM * authority' certs/trust anchors.
240*9781SMoriah.Waterland@Sun.COM *
241*9781SMoriah.Waterland@Sun.COM * Match based on the value of 'matchty' and the contents of 'keyid'
242*9781SMoriah.Waterland@Sun.COM * and/or 'name_str', as appropriate. Go through the lists of certs and
243*9781SMoriah.Waterland@Sun.COM * private keys which were taken from the pkcs12 structure, looking for
244*9781SMoriah.Waterland@Sun.COM * matches of the requested type. This function only searches the lists of
245*9781SMoriah.Waterland@Sun.COM * matching private keys and client certificates. Kinds of matches allowed,
246*9781SMoriah.Waterland@Sun.COM * and the order in which they will be checked, are:
247*9781SMoriah.Waterland@Sun.COM *
248*9781SMoriah.Waterland@Sun.COM * 1) Find the key and/or cert whose localkeyid attributes matches
249*9781SMoriah.Waterland@Sun.COM * 'keyid'.
250*9781SMoriah.Waterland@Sun.COM * 2) Find the key and/or cert whose friendlyname attributes matches
251*9781SMoriah.Waterland@Sun.COM * 'name_str'
252*9781SMoriah.Waterland@Sun.COM * 3) Return the first matching key/cert pair found.
253*9781SMoriah.Waterland@Sun.COM * 4) Return the last matching key/cert pair found.
254*9781SMoriah.Waterland@Sun.COM * 5) Return whatever cert and/or key are available, even unmatching.
255*9781SMoriah.Waterland@Sun.COM *
256*9781SMoriah.Waterland@Sun.COM * Append to the CA list, the certs which do not have matching private
257*9781SMoriah.Waterland@Sun.COM * keys and which were not selected.
258*9781SMoriah.Waterland@Sun.COM *
259*9781SMoriah.Waterland@Sun.COM * If none of the bits are set, no client certs or private keys will be
260*9781SMoriah.Waterland@Sun.COM * returned. CA (aka trust anchor) certs can be.
261*9781SMoriah.Waterland@Sun.COM *
262*9781SMoriah.Waterland@Sun.COM * Notes: If #3 is selected, then #4 will never occur. CA certs will be
263*9781SMoriah.Waterland@Sun.COM * selected after a cert/key pairs are isolated.
264*9781SMoriah.Waterland@Sun.COM *
265*9781SMoriah.Waterland@Sun.COM * Returns:
266*9781SMoriah.Waterland@Sun.COM * < 0 - An error returned. Call ERR_get_error() to get errors information.
267*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
268*9781SMoriah.Waterland@Sun.COM * >= 0 - Objects were found and returned. Which objects are indicated by
269*9781SMoriah.Waterland@Sun.COM * which bits are set (FOUND_PKEY, FOUND_CERT, FOUND_CA_CERTS).
270*9781SMoriah.Waterland@Sun.COM */
271*9781SMoriah.Waterland@Sun.COM int
sunw_PKCS12_parse(PKCS12 * p12,const char * pass,int matchty,char * keyid,int keyid_len,char * name_str,EVP_PKEY ** pkey,X509 ** cert,STACK_OF (X509)** ca)272*9781SMoriah.Waterland@Sun.COM sunw_PKCS12_parse(PKCS12 *p12, const char *pass, int matchty, char *keyid,
273*9781SMoriah.Waterland@Sun.COM int keyid_len, char *name_str, EVP_PKEY **pkey, X509 **cert,
274*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) **ca)
275*9781SMoriah.Waterland@Sun.COM {
276*9781SMoriah.Waterland@Sun.COM boolean_t ca_supplied;
277*9781SMoriah.Waterland@Sun.COM int retval = -1;
278*9781SMoriah.Waterland@Sun.COM
279*9781SMoriah.Waterland@Sun.COM /* If NULL PKCS12 structure, this is an error */
280*9781SMoriah.Waterland@Sun.COM if (p12 == NULL) {
281*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
282*9781SMoriah.Waterland@Sun.COM return (-1);
283*9781SMoriah.Waterland@Sun.COM }
284*9781SMoriah.Waterland@Sun.COM
285*9781SMoriah.Waterland@Sun.COM /* Set up arguments.... These will be allocated if needed */
286*9781SMoriah.Waterland@Sun.COM if (pkey)
287*9781SMoriah.Waterland@Sun.COM *pkey = NULL;
288*9781SMoriah.Waterland@Sun.COM if (cert)
289*9781SMoriah.Waterland@Sun.COM *cert = NULL;
290*9781SMoriah.Waterland@Sun.COM
291*9781SMoriah.Waterland@Sun.COM /*
292*9781SMoriah.Waterland@Sun.COM * If there is already a ca list, use it. Otherwise, allocate one
293*9781SMoriah.Waterland@Sun.COM * and free is later if an error occurs or whatever.)
294*9781SMoriah.Waterland@Sun.COM */
295*9781SMoriah.Waterland@Sun.COM ca_supplied = (ca != NULL && *ca != NULL);
296*9781SMoriah.Waterland@Sun.COM if (ca != NULL && *ca == NULL) {
297*9781SMoriah.Waterland@Sun.COM if ((*ca = sk_X509_new_null()) == NULL) {
298*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MEMORY_FAILURE);
299*9781SMoriah.Waterland@Sun.COM return (-1);
300*9781SMoriah.Waterland@Sun.COM }
301*9781SMoriah.Waterland@Sun.COM }
302*9781SMoriah.Waterland@Sun.COM
303*9781SMoriah.Waterland@Sun.COM /*
304*9781SMoriah.Waterland@Sun.COM * If password is zero length or NULL then try verifying both cases
305*9781SMoriah.Waterland@Sun.COM * to determine which password is correct. The reason for this is that
306*9781SMoriah.Waterland@Sun.COM * under PKCS#12 password based encryption no password and a zero
307*9781SMoriah.Waterland@Sun.COM * length password are two different things. If the password has a
308*9781SMoriah.Waterland@Sun.COM * non-zero length and is not NULL then call PKCS12_verify_mac() with
309*9781SMoriah.Waterland@Sun.COM * a length of '-1' and let it use strlen() to figure out the length
310*9781SMoriah.Waterland@Sun.COM * of the password.
311*9781SMoriah.Waterland@Sun.COM */
312*9781SMoriah.Waterland@Sun.COM /* Check the mac */
313*9781SMoriah.Waterland@Sun.COM if (pass == NULL || *pass == '\0') {
314*9781SMoriah.Waterland@Sun.COM if (PKCS12_verify_mac(p12, NULL, 0))
315*9781SMoriah.Waterland@Sun.COM pass = NULL;
316*9781SMoriah.Waterland@Sun.COM else if (PKCS12_verify_mac(p12, "", 0))
317*9781SMoriah.Waterland@Sun.COM pass = "";
318*9781SMoriah.Waterland@Sun.COM else {
319*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_PARSE,
320*9781SMoriah.Waterland@Sun.COM SUNW_R_MAC_VERIFY_FAILURE);
321*9781SMoriah.Waterland@Sun.COM goto err;
322*9781SMoriah.Waterland@Sun.COM }
323*9781SMoriah.Waterland@Sun.COM } else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
324*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MAC_VERIFY_FAILURE);
325*9781SMoriah.Waterland@Sun.COM goto err;
326*9781SMoriah.Waterland@Sun.COM }
327*9781SMoriah.Waterland@Sun.COM
328*9781SMoriah.Waterland@Sun.COM retval = parse_pkcs12(p12, pass, matchty, keyid, keyid_len,
329*9781SMoriah.Waterland@Sun.COM name_str, pkey, cert, ca);
330*9781SMoriah.Waterland@Sun.COM if (retval < 0) {
331*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_PKCS12_PARSE_ERR);
332*9781SMoriah.Waterland@Sun.COM goto err;
333*9781SMoriah.Waterland@Sun.COM }
334*9781SMoriah.Waterland@Sun.COM return (retval);
335*9781SMoriah.Waterland@Sun.COM
336*9781SMoriah.Waterland@Sun.COM err:
337*9781SMoriah.Waterland@Sun.COM if (pkey && *pkey) {
338*9781SMoriah.Waterland@Sun.COM sunw_evp_pkey_free(*pkey);
339*9781SMoriah.Waterland@Sun.COM }
340*9781SMoriah.Waterland@Sun.COM if (cert && *cert)
341*9781SMoriah.Waterland@Sun.COM X509_free(*cert);
342*9781SMoriah.Waterland@Sun.COM if (ca_supplied == B_FALSE && ca != NULL)
343*9781SMoriah.Waterland@Sun.COM sk_X509_pop_free(*ca, X509_free);
344*9781SMoriah.Waterland@Sun.COM
345*9781SMoriah.Waterland@Sun.COM return (-1);
346*9781SMoriah.Waterland@Sun.COM
347*9781SMoriah.Waterland@Sun.COM }
348*9781SMoriah.Waterland@Sun.COM
349*9781SMoriah.Waterland@Sun.COM
350*9781SMoriah.Waterland@Sun.COM /*
351*9781SMoriah.Waterland@Sun.COM * sunw_PEM_contents() parses a PEM file and returns component parts found
352*9781SMoriah.Waterland@Sun.COM *
353*9781SMoriah.Waterland@Sun.COM * Parse and decrypt a PEM file, returning any user keys and certs.
354*9781SMoriah.Waterland@Sun.COM *
355*9781SMoriah.Waterland@Sun.COM * There are some limits to this function. It will ignore the following:
356*9781SMoriah.Waterland@Sun.COM * - certificates identified by "TRUSTED CERTIFICATE"
357*9781SMoriah.Waterland@Sun.COM * - CERTIFICATE REQUEST and NEW CERTIFICATE REQUEST records.
358*9781SMoriah.Waterland@Sun.COM * - X509 CRL
359*9781SMoriah.Waterland@Sun.COM * - DH PARAMETERS
360*9781SMoriah.Waterland@Sun.COM * - DSA PARAMETERS
361*9781SMoriah.Waterland@Sun.COM * - Any PUBLIC KEY
362*9781SMoriah.Waterland@Sun.COM * - PKCS7
363*9781SMoriah.Waterland@Sun.COM * - PRIVATE KEY or ENCRYPTED PRIVATE KEY (PKCS 8)
364*9781SMoriah.Waterland@Sun.COM *
365*9781SMoriah.Waterland@Sun.COM * Arguments:
366*9781SMoriah.Waterland@Sun.COM * fp - File pointer for file containing PEM data.
367*9781SMoriah.Waterland@Sun.COM * pass - Pass phrase for the private key or NULL if there is none.
368*9781SMoriah.Waterland@Sun.COM * pkeys - Points to address of a stack of private keys to return.
369*9781SMoriah.Waterland@Sun.COM * certs - Points to address of a stack of client certs to return.
370*9781SMoriah.Waterland@Sun.COM *
371*9781SMoriah.Waterland@Sun.COM * The pointers to stacks should either be NULL or their contents should
372*9781SMoriah.Waterland@Sun.COM * either be NULL or should point to a valid STACK_OF(X509) structure.
373*9781SMoriah.Waterland@Sun.COM * If the stacks contain information, corresponding information from the
374*9781SMoriah.Waterland@Sun.COM * file will be appended to the original contents.
375*9781SMoriah.Waterland@Sun.COM *
376*9781SMoriah.Waterland@Sun.COM * Note: Client certs and and their matching private keys will be in any
377*9781SMoriah.Waterland@Sun.COM * order.
378*9781SMoriah.Waterland@Sun.COM *
379*9781SMoriah.Waterland@Sun.COM * Certs which have no matching private key are assumed to be ca certs.
380*9781SMoriah.Waterland@Sun.COM *
381*9781SMoriah.Waterland@Sun.COM * Returns:
382*9781SMoriah.Waterland@Sun.COM * < 0 - An error returned. Call ERR_get_error() to get errors information.
383*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
384*9781SMoriah.Waterland@Sun.COM * >= 0 - Objects were found and returned. Which objects are indicated by
385*9781SMoriah.Waterland@Sun.COM * which bits are set (FOUND_PKEY, FOUND_CERT)
386*9781SMoriah.Waterland@Sun.COM */
sunw_PEM_contents(FILE * fp,pem_password_cb * cb,void * userdata,STACK_OF (EVP_PKEY)** pkey,STACK_OF (X509)** certs)387*9781SMoriah.Waterland@Sun.COM int sunw_PEM_contents(FILE *fp, pem_password_cb *cb, void *userdata,
388*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) **pkey, STACK_OF(X509) **certs)
389*9781SMoriah.Waterland@Sun.COM {
390*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *work_kl = NULL;
391*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *work_ca = NULL;
392*9781SMoriah.Waterland@Sun.COM int retval = -1;
393*9781SMoriah.Waterland@Sun.COM
394*9781SMoriah.Waterland@Sun.COM /*
395*9781SMoriah.Waterland@Sun.COM * Allocate the working stacks for private key and for the
396*9781SMoriah.Waterland@Sun.COM * ca certs.
397*9781SMoriah.Waterland@Sun.COM */
398*9781SMoriah.Waterland@Sun.COM if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
399*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE);
400*9781SMoriah.Waterland@Sun.COM goto cleanup;
401*9781SMoriah.Waterland@Sun.COM }
402*9781SMoriah.Waterland@Sun.COM
403*9781SMoriah.Waterland@Sun.COM if ((work_ca = sk_X509_new_null()) == NULL) {
404*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE);
405*9781SMoriah.Waterland@Sun.COM goto cleanup;
406*9781SMoriah.Waterland@Sun.COM }
407*9781SMoriah.Waterland@Sun.COM
408*9781SMoriah.Waterland@Sun.COM /* Error strings are set within the following. */
409*9781SMoriah.Waterland@Sun.COM if (pem_info(fp, cb, userdata, &work_kl, &work_ca) <= 0) {
410*9781SMoriah.Waterland@Sun.COM goto cleanup;
411*9781SMoriah.Waterland@Sun.COM }
412*9781SMoriah.Waterland@Sun.COM
413*9781SMoriah.Waterland@Sun.COM /* on error, set_results() returns an error on the stack */
414*9781SMoriah.Waterland@Sun.COM retval = set_results(pkey, &work_kl, certs, &work_ca, NULL, NULL, NULL,
415*9781SMoriah.Waterland@Sun.COM NULL);
416*9781SMoriah.Waterland@Sun.COM cleanup:
417*9781SMoriah.Waterland@Sun.COM if (work_kl != NULL) {
418*9781SMoriah.Waterland@Sun.COM sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
419*9781SMoriah.Waterland@Sun.COM }
420*9781SMoriah.Waterland@Sun.COM if (work_ca != NULL)
421*9781SMoriah.Waterland@Sun.COM sk_X509_pop_free(work_ca, X509_free);
422*9781SMoriah.Waterland@Sun.COM
423*9781SMoriah.Waterland@Sun.COM return (retval);
424*9781SMoriah.Waterland@Sun.COM }
425*9781SMoriah.Waterland@Sun.COM
426*9781SMoriah.Waterland@Sun.COM
427*9781SMoriah.Waterland@Sun.COM /*
428*9781SMoriah.Waterland@Sun.COM * sunw_PKCS12_contents() parses a pkcs#12 structure and returns component
429*9781SMoriah.Waterland@Sun.COM * parts found, without evaluation.
430*9781SMoriah.Waterland@Sun.COM *
431*9781SMoriah.Waterland@Sun.COM * Parse and decrypt a PKCS#12 structure returning any user keys and/or
432*9781SMoriah.Waterland@Sun.COM * various certs. Note these should either be NULL, *whatever should
433*9781SMoriah.Waterland@Sun.COM * be NULL, or it should point to a valid STACK_OF(X509) structure.
434*9781SMoriah.Waterland@Sun.COM *
435*9781SMoriah.Waterland@Sun.COM * Arguments:
436*9781SMoriah.Waterland@Sun.COM * p12 - Structure with pkcs12 info to be parsed
437*9781SMoriah.Waterland@Sun.COM * pass - Pass phrase for the private key and entire pkcs12 wad (possibly
438*9781SMoriah.Waterland@Sun.COM * empty) or NULL if there is none.
439*9781SMoriah.Waterland@Sun.COM * pkeys - Points to address of a stack of private keys to return.
440*9781SMoriah.Waterland@Sun.COM * certs - Points to address of a stack of client certs return.
441*9781SMoriah.Waterland@Sun.COM *
442*9781SMoriah.Waterland@Sun.COM * Note: The certs and keys being returned are in random order.
443*9781SMoriah.Waterland@Sun.COM *
444*9781SMoriah.Waterland@Sun.COM * Returns:
445*9781SMoriah.Waterland@Sun.COM * < 0 - An error returned. Call ERR_get_error() to get errors information.
446*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
447*9781SMoriah.Waterland@Sun.COM * >= 0 - Objects were found and returned. Which objects are indicated by
448*9781SMoriah.Waterland@Sun.COM * which bits are set (FOUND_PKEY or FOUND_CERT)
449*9781SMoriah.Waterland@Sun.COM */
450*9781SMoriah.Waterland@Sun.COM int
sunw_PKCS12_contents(PKCS12 * p12,const char * pass,STACK_OF (EVP_PKEY)** pkey,STACK_OF (X509)** certs)451*9781SMoriah.Waterland@Sun.COM sunw_PKCS12_contents(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) **pkey,
452*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) **certs)
453*9781SMoriah.Waterland@Sun.COM {
454*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *work_kl = NULL;
455*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *work_ca = NULL;
456*9781SMoriah.Waterland@Sun.COM int retval = -1;
457*9781SMoriah.Waterland@Sun.COM
458*9781SMoriah.Waterland@Sun.COM /*
459*9781SMoriah.Waterland@Sun.COM * Allocate the working stacks for private key and for the
460*9781SMoriah.Waterland@Sun.COM * ca certs.
461*9781SMoriah.Waterland@Sun.COM */
462*9781SMoriah.Waterland@Sun.COM if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
463*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE);
464*9781SMoriah.Waterland@Sun.COM goto cleanup;
465*9781SMoriah.Waterland@Sun.COM }
466*9781SMoriah.Waterland@Sun.COM
467*9781SMoriah.Waterland@Sun.COM if ((work_ca = sk_X509_new_null()) == NULL) {
468*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE);
469*9781SMoriah.Waterland@Sun.COM goto cleanup;
470*9781SMoriah.Waterland@Sun.COM }
471*9781SMoriah.Waterland@Sun.COM
472*9781SMoriah.Waterland@Sun.COM if (parse_outer(p12, pass, work_kl, work_ca) == 0) {
473*9781SMoriah.Waterland@Sun.COM /*
474*9781SMoriah.Waterland@Sun.COM * Error already on stack
475*9781SMoriah.Waterland@Sun.COM */
476*9781SMoriah.Waterland@Sun.COM goto cleanup;
477*9781SMoriah.Waterland@Sun.COM }
478*9781SMoriah.Waterland@Sun.COM
479*9781SMoriah.Waterland@Sun.COM /* on error, set_results() returns an error on the stack */
480*9781SMoriah.Waterland@Sun.COM retval = set_results(pkey, &work_kl, certs, &work_ca, NULL,
481*9781SMoriah.Waterland@Sun.COM NULL, NULL, NULL);
482*9781SMoriah.Waterland@Sun.COM
483*9781SMoriah.Waterland@Sun.COM cleanup:
484*9781SMoriah.Waterland@Sun.COM if (work_kl != NULL) {
485*9781SMoriah.Waterland@Sun.COM sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
486*9781SMoriah.Waterland@Sun.COM }
487*9781SMoriah.Waterland@Sun.COM
488*9781SMoriah.Waterland@Sun.COM return (retval);
489*9781SMoriah.Waterland@Sun.COM }
490*9781SMoriah.Waterland@Sun.COM
491*9781SMoriah.Waterland@Sun.COM
492*9781SMoriah.Waterland@Sun.COM
493*9781SMoriah.Waterland@Sun.COM /*
494*9781SMoriah.Waterland@Sun.COM * sunw_split_certs() - Given a list of certs and a list of private keys,
495*9781SMoriah.Waterland@Sun.COM * moves certs which match one of the keys to a different stack.
496*9781SMoriah.Waterland@Sun.COM *
497*9781SMoriah.Waterland@Sun.COM * Arguments:
498*9781SMoriah.Waterland@Sun.COM * allkeys - Points to a stack of private keys to search.
499*9781SMoriah.Waterland@Sun.COM * allcerts - Points to a stack of certs to be searched.
500*9781SMoriah.Waterland@Sun.COM * keycerts - Points to address of a stack of certs with matching private
501*9781SMoriah.Waterland@Sun.COM * keys. They are moved from 'allcerts'. This may not be NULL
502*9781SMoriah.Waterland@Sun.COM * when called. If *keycerts is NULL upon entry, a new stack will
503*9781SMoriah.Waterland@Sun.COM * be allocated. Otherwise, it must be a valid STACK_OF(509).
504*9781SMoriah.Waterland@Sun.COM * nocerts - Points to address of a stack for keys which have no matching
505*9781SMoriah.Waterland@Sun.COM * certs. Keys are moved from 'allkeys' here when they have no
506*9781SMoriah.Waterland@Sun.COM * matching certs. If this is NULL, matchless keys will be
507*9781SMoriah.Waterland@Sun.COM * discarded.
508*9781SMoriah.Waterland@Sun.COM *
509*9781SMoriah.Waterland@Sun.COM * Notes: If an error occurs while moving certs, the cert being move may be
510*9781SMoriah.Waterland@Sun.COM * lost. 'keycerts' may only contain part of the matching certs. The number
511*9781SMoriah.Waterland@Sun.COM * of certs successfully moved can be found by checking sk_X509_num(keycerts).
512*9781SMoriah.Waterland@Sun.COM *
513*9781SMoriah.Waterland@Sun.COM * If there is a key which does not have a matching cert, it is moved to
514*9781SMoriah.Waterland@Sun.COM * the list nocerts.
515*9781SMoriah.Waterland@Sun.COM *
516*9781SMoriah.Waterland@Sun.COM * If all certs are removed from 'certs' and/or 'pkeys', it will be the
517*9781SMoriah.Waterland@Sun.COM * caller's responsibility to free the empty stacks.
518*9781SMoriah.Waterland@Sun.COM *
519*9781SMoriah.Waterland@Sun.COM * Returns:
520*9781SMoriah.Waterland@Sun.COM * < 0 - An error returned. Call ERR_get_error() to get errors information.
521*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
522*9781SMoriah.Waterland@Sun.COM * >= 0 - The number of certs moved from 'cert' to 'pkcerts'.
523*9781SMoriah.Waterland@Sun.COM */
524*9781SMoriah.Waterland@Sun.COM int
sunw_split_certs(STACK_OF (EVP_PKEY)* allkeys,STACK_OF (X509)* allcerts,STACK_OF (X509)** keycerts,STACK_OF (EVP_PKEY)** nocerts)525*9781SMoriah.Waterland@Sun.COM sunw_split_certs(STACK_OF(EVP_PKEY) *allkeys, STACK_OF(X509) *allcerts,
526*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) **keycerts, STACK_OF(EVP_PKEY) **nocerts)
527*9781SMoriah.Waterland@Sun.COM {
528*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *matching;
529*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *nomatch;
530*9781SMoriah.Waterland@Sun.COM EVP_PKEY *tmpkey;
531*9781SMoriah.Waterland@Sun.COM X509 *tmpcert;
532*9781SMoriah.Waterland@Sun.COM int count = 0;
533*9781SMoriah.Waterland@Sun.COM int found;
534*9781SMoriah.Waterland@Sun.COM int res;
535*9781SMoriah.Waterland@Sun.COM int i;
536*9781SMoriah.Waterland@Sun.COM int k;
537*9781SMoriah.Waterland@Sun.COM
538*9781SMoriah.Waterland@Sun.COM *keycerts = NULL;
539*9781SMoriah.Waterland@Sun.COM if (nocerts != NULL)
540*9781SMoriah.Waterland@Sun.COM *nocerts = NULL;
541*9781SMoriah.Waterland@Sun.COM nomatch = NULL;
542*9781SMoriah.Waterland@Sun.COM
543*9781SMoriah.Waterland@Sun.COM if ((matching = sk_X509_new_null()) == NULL) {
544*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SPLIT_CERTS, SUNW_R_MEMORY_FAILURE);
545*9781SMoriah.Waterland@Sun.COM return (-1);
546*9781SMoriah.Waterland@Sun.COM }
547*9781SMoriah.Waterland@Sun.COM *keycerts = matching;
548*9781SMoriah.Waterland@Sun.COM
549*9781SMoriah.Waterland@Sun.COM k = 0;
550*9781SMoriah.Waterland@Sun.COM while (k < sk_EVP_PKEY_num(allkeys)) {
551*9781SMoriah.Waterland@Sun.COM found = 0;
552*9781SMoriah.Waterland@Sun.COM tmpkey = sk_EVP_PKEY_value(allkeys, k);
553*9781SMoriah.Waterland@Sun.COM
554*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_X509_num(allcerts); i++) {
555*9781SMoriah.Waterland@Sun.COM tmpcert = sk_X509_value(allcerts, i);
556*9781SMoriah.Waterland@Sun.COM res = X509_check_private_key(tmpcert, tmpkey);
557*9781SMoriah.Waterland@Sun.COM if (res != 0) {
558*9781SMoriah.Waterland@Sun.COM count++;
559*9781SMoriah.Waterland@Sun.COM found = 1;
560*9781SMoriah.Waterland@Sun.COM tmpcert = sk_X509_delete(allcerts, i);
561*9781SMoriah.Waterland@Sun.COM if (sk_X509_push(matching, tmpcert) == 0) {
562*9781SMoriah.Waterland@Sun.COM X509_free(tmpcert);
563*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SPLIT_CERTS,
564*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
565*9781SMoriah.Waterland@Sun.COM return (-1);
566*9781SMoriah.Waterland@Sun.COM }
567*9781SMoriah.Waterland@Sun.COM break;
568*9781SMoriah.Waterland@Sun.COM }
569*9781SMoriah.Waterland@Sun.COM }
570*9781SMoriah.Waterland@Sun.COM if (found != 0) {
571*9781SMoriah.Waterland@Sun.COM /*
572*9781SMoriah.Waterland@Sun.COM * Found a match - keep the key & check out the next
573*9781SMoriah.Waterland@Sun.COM * one.
574*9781SMoriah.Waterland@Sun.COM */
575*9781SMoriah.Waterland@Sun.COM k++;
576*9781SMoriah.Waterland@Sun.COM } else {
577*9781SMoriah.Waterland@Sun.COM /*
578*9781SMoriah.Waterland@Sun.COM * No cert matching this key. Move the key if
579*9781SMoriah.Waterland@Sun.COM * possible or discard it. Don't increment the
580*9781SMoriah.Waterland@Sun.COM * index.
581*9781SMoriah.Waterland@Sun.COM */
582*9781SMoriah.Waterland@Sun.COM if (nocerts == NULL) {
583*9781SMoriah.Waterland@Sun.COM tmpkey = sk_EVP_PKEY_delete(allkeys, k);
584*9781SMoriah.Waterland@Sun.COM sunw_evp_pkey_free(tmpkey);
585*9781SMoriah.Waterland@Sun.COM } else {
586*9781SMoriah.Waterland@Sun.COM if (*nocerts == NULL) {
587*9781SMoriah.Waterland@Sun.COM nomatch = sk_EVP_PKEY_new_null();
588*9781SMoriah.Waterland@Sun.COM if (nomatch == NULL) {
589*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SPLIT_CERTS,
590*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
591*9781SMoriah.Waterland@Sun.COM return (-1);
592*9781SMoriah.Waterland@Sun.COM }
593*9781SMoriah.Waterland@Sun.COM *nocerts = nomatch;
594*9781SMoriah.Waterland@Sun.COM }
595*9781SMoriah.Waterland@Sun.COM tmpkey = sk_EVP_PKEY_delete(allkeys, k);
596*9781SMoriah.Waterland@Sun.COM if (sk_EVP_PKEY_push(nomatch, tmpkey) == 0) {
597*9781SMoriah.Waterland@Sun.COM sunw_evp_pkey_free(tmpkey);
598*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SPLIT_CERTS,
599*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
600*9781SMoriah.Waterland@Sun.COM return (-1);
601*9781SMoriah.Waterland@Sun.COM }
602*9781SMoriah.Waterland@Sun.COM }
603*9781SMoriah.Waterland@Sun.COM }
604*9781SMoriah.Waterland@Sun.COM }
605*9781SMoriah.Waterland@Sun.COM
606*9781SMoriah.Waterland@Sun.COM return (count);
607*9781SMoriah.Waterland@Sun.COM }
608*9781SMoriah.Waterland@Sun.COM
609*9781SMoriah.Waterland@Sun.COM /*
610*9781SMoriah.Waterland@Sun.COM * sunw_PKCS12_create() creates a pkcs#12 structure and given component parts.
611*9781SMoriah.Waterland@Sun.COM *
612*9781SMoriah.Waterland@Sun.COM * Given one or more of user private key, user cert and/or other (CA) certs,
613*9781SMoriah.Waterland@Sun.COM * return an encrypted PKCS12 structure containing them.
614*9781SMoriah.Waterland@Sun.COM *
615*9781SMoriah.Waterland@Sun.COM * Arguments:
616*9781SMoriah.Waterland@Sun.COM * pass - Pass phrase for the pkcs12 structure and private key (possibly
617*9781SMoriah.Waterland@Sun.COM * empty) or NULL if there is none. It will be used to encrypt
618*9781SMoriah.Waterland@Sun.COM * both the private key(s) and as the pass phrase for the whole
619*9781SMoriah.Waterland@Sun.COM * pkcs12 wad.
620*9781SMoriah.Waterland@Sun.COM * pkeys - Points to stack of private keys.
621*9781SMoriah.Waterland@Sun.COM * certs - Points to stack of client (public ke) certs
622*9781SMoriah.Waterland@Sun.COM * cacerts - Points to stack of 'certificate authority' certs (or trust
623*9781SMoriah.Waterland@Sun.COM * anchors).
624*9781SMoriah.Waterland@Sun.COM *
625*9781SMoriah.Waterland@Sun.COM * Note that any of these may be NULL.
626*9781SMoriah.Waterland@Sun.COM *
627*9781SMoriah.Waterland@Sun.COM * Returns:
628*9781SMoriah.Waterland@Sun.COM * NULL - An error occurred.
629*9781SMoriah.Waterland@Sun.COM * != NULL - Address of PKCS12 structure. The user is responsible for
630*9781SMoriah.Waterland@Sun.COM * freeing the memory when done.
631*9781SMoriah.Waterland@Sun.COM */
632*9781SMoriah.Waterland@Sun.COM PKCS12 *
sunw_PKCS12_create(const char * pass,STACK_OF (EVP_PKEY)* pkeys,STACK_OF (X509)* certs,STACK_OF (X509)* cacerts)633*9781SMoriah.Waterland@Sun.COM sunw_PKCS12_create(const char *pass, STACK_OF(EVP_PKEY) *pkeys,
634*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *certs, STACK_OF(X509) *cacerts)
635*9781SMoriah.Waterland@Sun.COM {
636*9781SMoriah.Waterland@Sun.COM int nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
637*9781SMoriah.Waterland@Sun.COM int nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
638*9781SMoriah.Waterland@Sun.COM STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
639*9781SMoriah.Waterland@Sun.COM STACK_OF(PKCS7) *safes = NULL;
640*9781SMoriah.Waterland@Sun.COM PKCS12_SAFEBAG *bag = NULL;
641*9781SMoriah.Waterland@Sun.COM PKCS8_PRIV_KEY_INFO *p8 = NULL;
642*9781SMoriah.Waterland@Sun.COM EVP_PKEY *pkey = NULL;
643*9781SMoriah.Waterland@Sun.COM PKCS12 *ret_p12 = NULL;
644*9781SMoriah.Waterland@Sun.COM PKCS12 *p12 = NULL;
645*9781SMoriah.Waterland@Sun.COM PKCS7 *authsafe = NULL;
646*9781SMoriah.Waterland@Sun.COM X509 *cert = NULL;
647*9781SMoriah.Waterland@Sun.COM uchar_t *str = NULL;
648*9781SMoriah.Waterland@Sun.COM int certs_there = 0;
649*9781SMoriah.Waterland@Sun.COM int keys_there = 0;
650*9781SMoriah.Waterland@Sun.COM int len;
651*9781SMoriah.Waterland@Sun.COM int i;
652*9781SMoriah.Waterland@Sun.COM
653*9781SMoriah.Waterland@Sun.COM if ((safes = sk_PKCS7_new_null()) == NULL) {
654*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
655*9781SMoriah.Waterland@Sun.COM return (NULL);
656*9781SMoriah.Waterland@Sun.COM }
657*9781SMoriah.Waterland@Sun.COM
658*9781SMoriah.Waterland@Sun.COM if ((bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) {
659*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
660*9781SMoriah.Waterland@Sun.COM goto err_ret;
661*9781SMoriah.Waterland@Sun.COM }
662*9781SMoriah.Waterland@Sun.COM
663*9781SMoriah.Waterland@Sun.COM if (certs != NULL && sk_X509_num(certs) > 0) {
664*9781SMoriah.Waterland@Sun.COM
665*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_X509_num(certs); i++) {
666*9781SMoriah.Waterland@Sun.COM cert = sk_X509_value(certs, i);
667*9781SMoriah.Waterland@Sun.COM
668*9781SMoriah.Waterland@Sun.COM /* Add user certificate */
669*9781SMoriah.Waterland@Sun.COM if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) {
670*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
671*9781SMoriah.Waterland@Sun.COM goto err_ret;
672*9781SMoriah.Waterland@Sun.COM }
673*9781SMoriah.Waterland@Sun.COM if (cert->aux != NULL && cert->aux->alias != NULL &&
674*9781SMoriah.Waterland@Sun.COM cert->aux->alias->type == V_ASN1_UTF8STRING) {
675*9781SMoriah.Waterland@Sun.COM str = utf82ascstr(cert->aux->alias);
676*9781SMoriah.Waterland@Sun.COM if (str == NULL) {
677*9781SMoriah.Waterland@Sun.COM /*
678*9781SMoriah.Waterland@Sun.COM * Error already on stack
679*9781SMoriah.Waterland@Sun.COM */
680*9781SMoriah.Waterland@Sun.COM goto err_ret;
681*9781SMoriah.Waterland@Sun.COM }
682*9781SMoriah.Waterland@Sun.COM if (PKCS12_add_friendlyname_asc(bag,
683*9781SMoriah.Waterland@Sun.COM (char const *) str,
684*9781SMoriah.Waterland@Sun.COM strlen((char const *) str)) == 0) {
685*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
686*9781SMoriah.Waterland@Sun.COM SUNW_R_ADD_ATTR_ERR);
687*9781SMoriah.Waterland@Sun.COM goto err_ret;
688*9781SMoriah.Waterland@Sun.COM }
689*9781SMoriah.Waterland@Sun.COM }
690*9781SMoriah.Waterland@Sun.COM if (cert->aux != NULL && cert->aux->keyid != NULL &&
691*9781SMoriah.Waterland@Sun.COM cert->aux->keyid->type == V_ASN1_OCTET_STRING) {
692*9781SMoriah.Waterland@Sun.COM str = cert->aux->keyid->data;
693*9781SMoriah.Waterland@Sun.COM len = cert->aux->keyid->length;
694*9781SMoriah.Waterland@Sun.COM
695*9781SMoriah.Waterland@Sun.COM if (str != NULL &&
696*9781SMoriah.Waterland@Sun.COM PKCS12_add_localkeyid(bag, str, len) == 0) {
697*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
698*9781SMoriah.Waterland@Sun.COM SUNW_R_ADD_ATTR_ERR);
699*9781SMoriah.Waterland@Sun.COM goto err_ret;
700*9781SMoriah.Waterland@Sun.COM }
701*9781SMoriah.Waterland@Sun.COM }
702*9781SMoriah.Waterland@Sun.COM if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
703*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
704*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
705*9781SMoriah.Waterland@Sun.COM goto err_ret;
706*9781SMoriah.Waterland@Sun.COM }
707*9781SMoriah.Waterland@Sun.COM certs_there++;
708*9781SMoriah.Waterland@Sun.COM bag = NULL;
709*9781SMoriah.Waterland@Sun.COM }
710*9781SMoriah.Waterland@Sun.COM }
711*9781SMoriah.Waterland@Sun.COM
712*9781SMoriah.Waterland@Sun.COM if (cacerts != NULL && sk_X509_num(cacerts) > 0) {
713*9781SMoriah.Waterland@Sun.COM
714*9781SMoriah.Waterland@Sun.COM /* Put all certs in structure */
715*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_X509_num(cacerts); i++) {
716*9781SMoriah.Waterland@Sun.COM cert = sk_X509_value(cacerts, i);
717*9781SMoriah.Waterland@Sun.COM if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) {
718*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
719*9781SMoriah.Waterland@Sun.COM goto err_ret;
720*9781SMoriah.Waterland@Sun.COM }
721*9781SMoriah.Waterland@Sun.COM
722*9781SMoriah.Waterland@Sun.COM if (cert->aux != NULL && cert->aux->alias != NULL &&
723*9781SMoriah.Waterland@Sun.COM cert->aux->alias->type == V_ASN1_UTF8STRING) {
724*9781SMoriah.Waterland@Sun.COM str = utf82ascstr(cert->aux->alias);
725*9781SMoriah.Waterland@Sun.COM if (str == NULL) {
726*9781SMoriah.Waterland@Sun.COM /*
727*9781SMoriah.Waterland@Sun.COM * Error already on stack
728*9781SMoriah.Waterland@Sun.COM */
729*9781SMoriah.Waterland@Sun.COM goto err_ret;
730*9781SMoriah.Waterland@Sun.COM }
731*9781SMoriah.Waterland@Sun.COM if (PKCS12_add_friendlyname_asc(
732*9781SMoriah.Waterland@Sun.COM bag, (char const *) str,
733*9781SMoriah.Waterland@Sun.COM strlen((char const *) str)) == 0) {
734*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
735*9781SMoriah.Waterland@Sun.COM SUNW_R_ADD_ATTR_ERR);
736*9781SMoriah.Waterland@Sun.COM goto err_ret;
737*9781SMoriah.Waterland@Sun.COM }
738*9781SMoriah.Waterland@Sun.COM }
739*9781SMoriah.Waterland@Sun.COM if (cert->aux != NULL && cert->aux->keyid != NULL &&
740*9781SMoriah.Waterland@Sun.COM cert->aux->keyid->type == V_ASN1_OCTET_STRING) {
741*9781SMoriah.Waterland@Sun.COM str = cert->aux->keyid->data;
742*9781SMoriah.Waterland@Sun.COM len = cert->aux->keyid->length;
743*9781SMoriah.Waterland@Sun.COM
744*9781SMoriah.Waterland@Sun.COM if (str != NULL &&
745*9781SMoriah.Waterland@Sun.COM PKCS12_add_localkeyid(bag, str, len) == 0) {
746*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
747*9781SMoriah.Waterland@Sun.COM SUNW_R_ADD_ATTR_ERR);
748*9781SMoriah.Waterland@Sun.COM goto err_ret;
749*9781SMoriah.Waterland@Sun.COM }
750*9781SMoriah.Waterland@Sun.COM }
751*9781SMoriah.Waterland@Sun.COM if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
752*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
753*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
754*9781SMoriah.Waterland@Sun.COM goto err_ret;
755*9781SMoriah.Waterland@Sun.COM }
756*9781SMoriah.Waterland@Sun.COM certs_there++;
757*9781SMoriah.Waterland@Sun.COM bag = NULL;
758*9781SMoriah.Waterland@Sun.COM }
759*9781SMoriah.Waterland@Sun.COM }
760*9781SMoriah.Waterland@Sun.COM
761*9781SMoriah.Waterland@Sun.COM if (certs != NULL || cacerts != NULL && certs_there) {
762*9781SMoriah.Waterland@Sun.COM /* Turn certbags into encrypted authsafe */
763*9781SMoriah.Waterland@Sun.COM authsafe = PKCS12_pack_p7encdata(nid_cert, pass, -1,
764*9781SMoriah.Waterland@Sun.COM NULL, 0, PKCS12_DEFAULT_ITER, bags);
765*9781SMoriah.Waterland@Sun.COM if (authsafe == NULL) {
766*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR);
767*9781SMoriah.Waterland@Sun.COM goto err_ret;
768*9781SMoriah.Waterland@Sun.COM }
769*9781SMoriah.Waterland@Sun.COM sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
770*9781SMoriah.Waterland@Sun.COM bags = NULL;
771*9781SMoriah.Waterland@Sun.COM
772*9781SMoriah.Waterland@Sun.COM if (sk_PKCS7_push(safes, authsafe) == 0) {
773*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
774*9781SMoriah.Waterland@Sun.COM goto err_ret;
775*9781SMoriah.Waterland@Sun.COM }
776*9781SMoriah.Waterland@Sun.COM authsafe = NULL;
777*9781SMoriah.Waterland@Sun.COM }
778*9781SMoriah.Waterland@Sun.COM
779*9781SMoriah.Waterland@Sun.COM if (pkeys != NULL && sk_EVP_PKEY_num(pkeys) > 0) {
780*9781SMoriah.Waterland@Sun.COM
781*9781SMoriah.Waterland@Sun.COM if (bags == NULL &&
782*9781SMoriah.Waterland@Sun.COM (bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) {
783*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE);
784*9781SMoriah.Waterland@Sun.COM goto err_ret;
785*9781SMoriah.Waterland@Sun.COM }
786*9781SMoriah.Waterland@Sun.COM
787*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_EVP_PKEY_num(pkeys); i++) {
788*9781SMoriah.Waterland@Sun.COM
789*9781SMoriah.Waterland@Sun.COM pkey = sk_EVP_PKEY_value(pkeys, i);
790*9781SMoriah.Waterland@Sun.COM
791*9781SMoriah.Waterland@Sun.COM /* Make a shrouded key bag */
792*9781SMoriah.Waterland@Sun.COM if ((p8 = EVP_PKEY2PKCS8(pkey)) == NULL) {
793*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKEY_ERR);
794*9781SMoriah.Waterland@Sun.COM goto err_ret;
795*9781SMoriah.Waterland@Sun.COM }
796*9781SMoriah.Waterland@Sun.COM
797*9781SMoriah.Waterland@Sun.COM bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0,
798*9781SMoriah.Waterland@Sun.COM PKCS12_DEFAULT_ITER, p8);
799*9781SMoriah.Waterland@Sun.COM if (bag == NULL) {
800*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
801*9781SMoriah.Waterland@Sun.COM SUNW_R_MAKE_BAG_ERR);
802*9781SMoriah.Waterland@Sun.COM goto err_ret;
803*9781SMoriah.Waterland@Sun.COM }
804*9781SMoriah.Waterland@Sun.COM PKCS8_PRIV_KEY_INFO_free(p8);
805*9781SMoriah.Waterland@Sun.COM p8 = NULL;
806*9781SMoriah.Waterland@Sun.COM
807*9781SMoriah.Waterland@Sun.COM len = sunw_get_pkey_fname(GETDO_COPY, pkey,
808*9781SMoriah.Waterland@Sun.COM (char **)&str);
809*9781SMoriah.Waterland@Sun.COM if (str != NULL) {
810*9781SMoriah.Waterland@Sun.COM if (PKCS12_add_friendlyname_asc(bag,
811*9781SMoriah.Waterland@Sun.COM (const char *)str, len) == 0) {
812*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
813*9781SMoriah.Waterland@Sun.COM SUNW_R_ADD_ATTR_ERR);
814*9781SMoriah.Waterland@Sun.COM goto err_ret;
815*9781SMoriah.Waterland@Sun.COM }
816*9781SMoriah.Waterland@Sun.COM }
817*9781SMoriah.Waterland@Sun.COM str = NULL;
818*9781SMoriah.Waterland@Sun.COM
819*9781SMoriah.Waterland@Sun.COM len = sunw_get_pkey_localkeyid(GETDO_COPY, pkey,
820*9781SMoriah.Waterland@Sun.COM (char **)&str, &len);
821*9781SMoriah.Waterland@Sun.COM if (str != NULL) {
822*9781SMoriah.Waterland@Sun.COM if (PKCS12_add_localkeyid(bag, str, len) == 0) {
823*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
824*9781SMoriah.Waterland@Sun.COM SUNW_R_ADD_ATTR_ERR);
825*9781SMoriah.Waterland@Sun.COM goto err_ret;
826*9781SMoriah.Waterland@Sun.COM }
827*9781SMoriah.Waterland@Sun.COM }
828*9781SMoriah.Waterland@Sun.COM str = NULL;
829*9781SMoriah.Waterland@Sun.COM
830*9781SMoriah.Waterland@Sun.COM if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) {
831*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
832*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
833*9781SMoriah.Waterland@Sun.COM goto err_ret;
834*9781SMoriah.Waterland@Sun.COM }
835*9781SMoriah.Waterland@Sun.COM keys_there++;
836*9781SMoriah.Waterland@Sun.COM bag = NULL;
837*9781SMoriah.Waterland@Sun.COM }
838*9781SMoriah.Waterland@Sun.COM
839*9781SMoriah.Waterland@Sun.COM if (keys_there) {
840*9781SMoriah.Waterland@Sun.COM /* Turn into unencrypted authsafe */
841*9781SMoriah.Waterland@Sun.COM authsafe = PKCS12_pack_p7data(bags);
842*9781SMoriah.Waterland@Sun.COM if (authsafe == NULL) {
843*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
844*9781SMoriah.Waterland@Sun.COM SUNW_R_PKCS12_CREATE_ERR);
845*9781SMoriah.Waterland@Sun.COM goto err_ret;
846*9781SMoriah.Waterland@Sun.COM }
847*9781SMoriah.Waterland@Sun.COM sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
848*9781SMoriah.Waterland@Sun.COM bags = NULL;
849*9781SMoriah.Waterland@Sun.COM
850*9781SMoriah.Waterland@Sun.COM if (sk_PKCS7_push(safes, authsafe) == 0) {
851*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE,
852*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
853*9781SMoriah.Waterland@Sun.COM }
854*9781SMoriah.Waterland@Sun.COM authsafe = NULL;
855*9781SMoriah.Waterland@Sun.COM }
856*9781SMoriah.Waterland@Sun.COM }
857*9781SMoriah.Waterland@Sun.COM
858*9781SMoriah.Waterland@Sun.COM if (certs_there == 0 && keys_there == 0) {
859*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_EMPTY_ERR);
860*9781SMoriah.Waterland@Sun.COM goto err_ret;
861*9781SMoriah.Waterland@Sun.COM }
862*9781SMoriah.Waterland@Sun.COM
863*9781SMoriah.Waterland@Sun.COM if ((p12 = PKCS12_init(NID_pkcs7_data)) == NULL) {
864*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR);
865*9781SMoriah.Waterland@Sun.COM goto err_ret;
866*9781SMoriah.Waterland@Sun.COM }
867*9781SMoriah.Waterland@Sun.COM
868*9781SMoriah.Waterland@Sun.COM /*
869*9781SMoriah.Waterland@Sun.COM * Note that safes is copied by the following. Therefore, it needs
870*9781SMoriah.Waterland@Sun.COM * to be freed whether or not the following succeeds.
871*9781SMoriah.Waterland@Sun.COM */
872*9781SMoriah.Waterland@Sun.COM if (M_PKCS12_pack_authsafes(p12, safes) == 0) {
873*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR);
874*9781SMoriah.Waterland@Sun.COM goto err_ret;
875*9781SMoriah.Waterland@Sun.COM }
876*9781SMoriah.Waterland@Sun.COM if (PKCS12_set_mac(p12, pass, -1, NULL, 0, 2048, NULL) == 0) {
877*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MAC_CREATE_FAILURE);
878*9781SMoriah.Waterland@Sun.COM goto err_ret;
879*9781SMoriah.Waterland@Sun.COM }
880*9781SMoriah.Waterland@Sun.COM
881*9781SMoriah.Waterland@Sun.COM ret_p12 = p12;
882*9781SMoriah.Waterland@Sun.COM p12 = NULL;
883*9781SMoriah.Waterland@Sun.COM
884*9781SMoriah.Waterland@Sun.COM /* Fallthrough is intentional */
885*9781SMoriah.Waterland@Sun.COM
886*9781SMoriah.Waterland@Sun.COM err_ret:
887*9781SMoriah.Waterland@Sun.COM
888*9781SMoriah.Waterland@Sun.COM if (str != NULL)
889*9781SMoriah.Waterland@Sun.COM free(str);
890*9781SMoriah.Waterland@Sun.COM
891*9781SMoriah.Waterland@Sun.COM if (p8 != NULL)
892*9781SMoriah.Waterland@Sun.COM PKCS8_PRIV_KEY_INFO_free(p8);
893*9781SMoriah.Waterland@Sun.COM
894*9781SMoriah.Waterland@Sun.COM if (bag != NULL)
895*9781SMoriah.Waterland@Sun.COM PKCS12_SAFEBAG_free(bag);
896*9781SMoriah.Waterland@Sun.COM if (bags != NULL)
897*9781SMoriah.Waterland@Sun.COM sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
898*9781SMoriah.Waterland@Sun.COM if (authsafe != NULL)
899*9781SMoriah.Waterland@Sun.COM PKCS7_free(authsafe);
900*9781SMoriah.Waterland@Sun.COM if (safes != NULL)
901*9781SMoriah.Waterland@Sun.COM sk_PKCS7_pop_free(safes, PKCS7_free);
902*9781SMoriah.Waterland@Sun.COM if (p12 != NULL)
903*9781SMoriah.Waterland@Sun.COM PKCS12_free(p12);
904*9781SMoriah.Waterland@Sun.COM
905*9781SMoriah.Waterland@Sun.COM return (ret_p12);
906*9781SMoriah.Waterland@Sun.COM }
907*9781SMoriah.Waterland@Sun.COM
908*9781SMoriah.Waterland@Sun.COM /*
909*9781SMoriah.Waterland@Sun.COM * sunw_evp_pkey_free() Given an EVP_PKEY structure, free any attributes
910*9781SMoriah.Waterland@Sun.COM * that are attached. Then free the EVP_PKEY itself.
911*9781SMoriah.Waterland@Sun.COM *
912*9781SMoriah.Waterland@Sun.COM * This is a replacement for EVP_PKEY_free() for the sunw stuff.
913*9781SMoriah.Waterland@Sun.COM * It should be used in places where EVP_PKEY_free would be used,
914*9781SMoriah.Waterland@Sun.COM * including calls to sk_EVP_PKEY_pop_free().
915*9781SMoriah.Waterland@Sun.COM *
916*9781SMoriah.Waterland@Sun.COM * Arguments:
917*9781SMoriah.Waterland@Sun.COM * pkey - Entry which potentially has attributes to be freed.
918*9781SMoriah.Waterland@Sun.COM *
919*9781SMoriah.Waterland@Sun.COM * Returns:
920*9781SMoriah.Waterland@Sun.COM * None.
921*9781SMoriah.Waterland@Sun.COM */
922*9781SMoriah.Waterland@Sun.COM void
sunw_evp_pkey_free(EVP_PKEY * pkey)923*9781SMoriah.Waterland@Sun.COM sunw_evp_pkey_free(EVP_PKEY *pkey)
924*9781SMoriah.Waterland@Sun.COM {
925*9781SMoriah.Waterland@Sun.COM if (pkey != NULL) {
926*9781SMoriah.Waterland@Sun.COM if (pkey->attributes != NULL) {
927*9781SMoriah.Waterland@Sun.COM sk_X509_ATTRIBUTE_pop_free(pkey->attributes,
928*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE_free);
929*9781SMoriah.Waterland@Sun.COM pkey->attributes = NULL;
930*9781SMoriah.Waterland@Sun.COM }
931*9781SMoriah.Waterland@Sun.COM EVP_PKEY_free(pkey);
932*9781SMoriah.Waterland@Sun.COM }
933*9781SMoriah.Waterland@Sun.COM }
934*9781SMoriah.Waterland@Sun.COM
935*9781SMoriah.Waterland@Sun.COM /*
936*9781SMoriah.Waterland@Sun.COM * sunw_set_localkeyid() sets the localkeyid in a cert, a private key or
937*9781SMoriah.Waterland@Sun.COM * both. Any existing localkeyid will be discarded.
938*9781SMoriah.Waterland@Sun.COM *
939*9781SMoriah.Waterland@Sun.COM * Arguments:
940*9781SMoriah.Waterland@Sun.COM * keyid_str- A byte string with the localkeyid to set
941*9781SMoriah.Waterland@Sun.COM * keyid_len- Length of the keyid byte string.
942*9781SMoriah.Waterland@Sun.COM * pkey - Points to a private key to set the keyidstr in.
943*9781SMoriah.Waterland@Sun.COM * cert - Points to a cert to set the keyidstr in.
944*9781SMoriah.Waterland@Sun.COM *
945*9781SMoriah.Waterland@Sun.COM * Note that setting a keyid into a cert which will not be written out as
946*9781SMoriah.Waterland@Sun.COM * a PKCS12 cert is pointless since it will be lost.
947*9781SMoriah.Waterland@Sun.COM *
948*9781SMoriah.Waterland@Sun.COM * Returns:
949*9781SMoriah.Waterland@Sun.COM * 0 - Success.
950*9781SMoriah.Waterland@Sun.COM * < 0 - An error occurred. It was probably an error in allocating
951*9781SMoriah.Waterland@Sun.COM * memory. The error will be set in the error stack. Call
952*9781SMoriah.Waterland@Sun.COM * ERR_get_error() to get specific information.
953*9781SMoriah.Waterland@Sun.COM */
954*9781SMoriah.Waterland@Sun.COM int
sunw_set_localkeyid(const char * keyid_str,int keyid_len,EVP_PKEY * pkey,X509 * cert)955*9781SMoriah.Waterland@Sun.COM sunw_set_localkeyid(const char *keyid_str, int keyid_len, EVP_PKEY *pkey,
956*9781SMoriah.Waterland@Sun.COM X509 *cert)
957*9781SMoriah.Waterland@Sun.COM {
958*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *attr = NULL;
959*9781SMoriah.Waterland@Sun.COM ASN1_STRING *str = NULL;
960*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *keyid = NULL;
961*9781SMoriah.Waterland@Sun.COM int retval = -1;
962*9781SMoriah.Waterland@Sun.COM int i;
963*9781SMoriah.Waterland@Sun.COM
964*9781SMoriah.Waterland@Sun.COM if (cert != NULL) {
965*9781SMoriah.Waterland@Sun.COM if (X509_keyid_set1(cert, (uchar_t *)keyid_str, keyid_len)
966*9781SMoriah.Waterland@Sun.COM == 0) {
967*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_SET_LKID_ERR);
968*9781SMoriah.Waterland@Sun.COM goto cleanup;
969*9781SMoriah.Waterland@Sun.COM }
970*9781SMoriah.Waterland@Sun.COM }
971*9781SMoriah.Waterland@Sun.COM if (pkey != NULL) {
972*9781SMoriah.Waterland@Sun.COM str = (ASN1_STRING *)M_ASN1_OCTET_STRING_new();
973*9781SMoriah.Waterland@Sun.COM if (str == NULL ||
974*9781SMoriah.Waterland@Sun.COM M_ASN1_OCTET_STRING_set(str, keyid_str, keyid_len) == 0 ||
975*9781SMoriah.Waterland@Sun.COM (keyid = ASN1_TYPE_new()) == NULL) {
976*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
977*9781SMoriah.Waterland@Sun.COM goto cleanup;
978*9781SMoriah.Waterland@Sun.COM }
979*9781SMoriah.Waterland@Sun.COM
980*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_set(keyid, V_ASN1_OCTET_STRING, str);
981*9781SMoriah.Waterland@Sun.COM str = NULL;
982*9781SMoriah.Waterland@Sun.COM
983*9781SMoriah.Waterland@Sun.COM attr = type2attrib(keyid, NID_localKeyID);
984*9781SMoriah.Waterland@Sun.COM if (attr == NULL) {
985*9781SMoriah.Waterland@Sun.COM /*
986*9781SMoriah.Waterland@Sun.COM * Error already on stack
987*9781SMoriah.Waterland@Sun.COM */
988*9781SMoriah.Waterland@Sun.COM goto cleanup;
989*9781SMoriah.Waterland@Sun.COM }
990*9781SMoriah.Waterland@Sun.COM keyid = NULL;
991*9781SMoriah.Waterland@Sun.COM
992*9781SMoriah.Waterland@Sun.COM if (pkey->attributes == NULL) {
993*9781SMoriah.Waterland@Sun.COM pkey->attributes = sk_X509_ATTRIBUTE_new_null();
994*9781SMoriah.Waterland@Sun.COM if (pkey->attributes == NULL) {
995*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_LOCALKEYID,
996*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
997*9781SMoriah.Waterland@Sun.COM goto cleanup;
998*9781SMoriah.Waterland@Sun.COM }
999*9781SMoriah.Waterland@Sun.COM } else {
1000*9781SMoriah.Waterland@Sun.COM i = find_attr_by_nid(pkey->attributes, NID_localKeyID);
1001*9781SMoriah.Waterland@Sun.COM if (i >= 0)
1002*9781SMoriah.Waterland@Sun.COM sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1003*9781SMoriah.Waterland@Sun.COM }
1004*9781SMoriah.Waterland@Sun.COM if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) {
1005*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
1006*9781SMoriah.Waterland@Sun.COM goto cleanup;
1007*9781SMoriah.Waterland@Sun.COM }
1008*9781SMoriah.Waterland@Sun.COM attr = NULL;
1009*9781SMoriah.Waterland@Sun.COM }
1010*9781SMoriah.Waterland@Sun.COM retval = 0;
1011*9781SMoriah.Waterland@Sun.COM
1012*9781SMoriah.Waterland@Sun.COM cleanup:
1013*9781SMoriah.Waterland@Sun.COM if (str != NULL)
1014*9781SMoriah.Waterland@Sun.COM ASN1_STRING_free(str);
1015*9781SMoriah.Waterland@Sun.COM if (keyid != NULL)
1016*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(keyid);
1017*9781SMoriah.Waterland@Sun.COM if (attr != NULL)
1018*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE_free(attr);
1019*9781SMoriah.Waterland@Sun.COM
1020*9781SMoriah.Waterland@Sun.COM return (retval);
1021*9781SMoriah.Waterland@Sun.COM }
1022*9781SMoriah.Waterland@Sun.COM
1023*9781SMoriah.Waterland@Sun.COM /*
1024*9781SMoriah.Waterland@Sun.COM * sunw_get_pkey_localkeyid() gets the localkeyid from a private key. It can
1025*9781SMoriah.Waterland@Sun.COM * optionally remove the value found.
1026*9781SMoriah.Waterland@Sun.COM *
1027*9781SMoriah.Waterland@Sun.COM * Arguments:
1028*9781SMoriah.Waterland@Sun.COM * dowhat - What to do with the attributes (remove them or copy them).
1029*9781SMoriah.Waterland@Sun.COM * pkey - Points to a private key to set the keyidstr in.
1030*9781SMoriah.Waterland@Sun.COM * keyid_str- Points to a location which will receive the pointer to
1031*9781SMoriah.Waterland@Sun.COM * a byte string containing the binary localkeyid. Note that
1032*9781SMoriah.Waterland@Sun.COM * this is a copy, and the caller must free it.
1033*9781SMoriah.Waterland@Sun.COM * keyid_len- Length of keyid_str.
1034*9781SMoriah.Waterland@Sun.COM *
1035*9781SMoriah.Waterland@Sun.COM * Returns:
1036*9781SMoriah.Waterland@Sun.COM * >= 0 - The number of characters in the keyid returned.
1037*9781SMoriah.Waterland@Sun.COM * < 0 - An error occurred. It was probably an error in allocating
1038*9781SMoriah.Waterland@Sun.COM * memory. The error will be set in the error stack. Call
1039*9781SMoriah.Waterland@Sun.COM * ERR_get_error() to get specific information.
1040*9781SMoriah.Waterland@Sun.COM */
1041*9781SMoriah.Waterland@Sun.COM int
sunw_get_pkey_localkeyid(getdo_actions_t dowhat,EVP_PKEY * pkey,char ** keyid_str,int * keyid_len)1042*9781SMoriah.Waterland@Sun.COM sunw_get_pkey_localkeyid(getdo_actions_t dowhat, EVP_PKEY *pkey,
1043*9781SMoriah.Waterland@Sun.COM char **keyid_str, int *keyid_len)
1044*9781SMoriah.Waterland@Sun.COM {
1045*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *attr = NULL;
1046*9781SMoriah.Waterland@Sun.COM ASN1_OCTET_STRING *str = NULL;
1047*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *ty = NULL;
1048*9781SMoriah.Waterland@Sun.COM int len = 0;
1049*9781SMoriah.Waterland@Sun.COM int i;
1050*9781SMoriah.Waterland@Sun.COM
1051*9781SMoriah.Waterland@Sun.COM if (keyid_str != NULL)
1052*9781SMoriah.Waterland@Sun.COM *keyid_str = NULL;
1053*9781SMoriah.Waterland@Sun.COM if (keyid_len != NULL)
1054*9781SMoriah.Waterland@Sun.COM *keyid_len = 0;
1055*9781SMoriah.Waterland@Sun.COM
1056*9781SMoriah.Waterland@Sun.COM if (pkey == NULL || pkey->attributes == NULL) {
1057*9781SMoriah.Waterland@Sun.COM return (0);
1058*9781SMoriah.Waterland@Sun.COM }
1059*9781SMoriah.Waterland@Sun.COM
1060*9781SMoriah.Waterland@Sun.COM if ((i = find_attr_by_nid(pkey->attributes, NID_localKeyID)) < 0) {
1061*9781SMoriah.Waterland@Sun.COM return (0);
1062*9781SMoriah.Waterland@Sun.COM }
1063*9781SMoriah.Waterland@Sun.COM attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
1064*9781SMoriah.Waterland@Sun.COM
1065*9781SMoriah.Waterland@Sun.COM if ((ty = attrib2type(attr)) == NULL ||
1066*9781SMoriah.Waterland@Sun.COM ty->type != V_ASN1_OCTET_STRING) {
1067*9781SMoriah.Waterland@Sun.COM return (0);
1068*9781SMoriah.Waterland@Sun.COM }
1069*9781SMoriah.Waterland@Sun.COM
1070*9781SMoriah.Waterland@Sun.COM if (dowhat == GETDO_DEL) {
1071*9781SMoriah.Waterland@Sun.COM attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1072*9781SMoriah.Waterland@Sun.COM if (attr != NULL)
1073*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE_free(attr);
1074*9781SMoriah.Waterland@Sun.COM return (0);
1075*9781SMoriah.Waterland@Sun.COM }
1076*9781SMoriah.Waterland@Sun.COM
1077*9781SMoriah.Waterland@Sun.COM str = ty->value.octet_string;
1078*9781SMoriah.Waterland@Sun.COM len = str->length;
1079*9781SMoriah.Waterland@Sun.COM if ((*keyid_str = malloc(len)) == NULL) {
1080*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_GET_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
1081*9781SMoriah.Waterland@Sun.COM return (-1);
1082*9781SMoriah.Waterland@Sun.COM }
1083*9781SMoriah.Waterland@Sun.COM
1084*9781SMoriah.Waterland@Sun.COM (void) memcpy(*keyid_str, str->data, len);
1085*9781SMoriah.Waterland@Sun.COM *keyid_len = len;
1086*9781SMoriah.Waterland@Sun.COM
1087*9781SMoriah.Waterland@Sun.COM return (len);
1088*9781SMoriah.Waterland@Sun.COM }
1089*9781SMoriah.Waterland@Sun.COM
1090*9781SMoriah.Waterland@Sun.COM /*
1091*9781SMoriah.Waterland@Sun.COM * sunw_get_pkey_fname() gets the friendlyName from a private key. It can
1092*9781SMoriah.Waterland@Sun.COM * optionally remove the value found.
1093*9781SMoriah.Waterland@Sun.COM *
1094*9781SMoriah.Waterland@Sun.COM * Arguments:
1095*9781SMoriah.Waterland@Sun.COM * dowhat - What to do with the attributes (remove them or copy them).
1096*9781SMoriah.Waterland@Sun.COM * pkey - Points to a private key to get the frientlyname from
1097*9781SMoriah.Waterland@Sun.COM * fname - Points to a location which will receive the pointer to a
1098*9781SMoriah.Waterland@Sun.COM * byte string with the ASCII friendlyname
1099*9781SMoriah.Waterland@Sun.COM *
1100*9781SMoriah.Waterland@Sun.COM * Returns:
1101*9781SMoriah.Waterland@Sun.COM * >= 0 - The number of characters in the frienlyname returned.
1102*9781SMoriah.Waterland@Sun.COM * < 0 - An error occurred. It was probably an error in allocating
1103*9781SMoriah.Waterland@Sun.COM * memory. The error will be set in the error stack. Call
1104*9781SMoriah.Waterland@Sun.COM * ERR_get_error() to get specific information.
1105*9781SMoriah.Waterland@Sun.COM */
1106*9781SMoriah.Waterland@Sun.COM int
sunw_get_pkey_fname(getdo_actions_t dowhat,EVP_PKEY * pkey,char ** fname)1107*9781SMoriah.Waterland@Sun.COM sunw_get_pkey_fname(getdo_actions_t dowhat, EVP_PKEY *pkey, char **fname)
1108*9781SMoriah.Waterland@Sun.COM {
1109*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *attr = NULL;
1110*9781SMoriah.Waterland@Sun.COM ASN1_BMPSTRING *str = NULL;
1111*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *ty = NULL;
1112*9781SMoriah.Waterland@Sun.COM int len = 0;
1113*9781SMoriah.Waterland@Sun.COM int i;
1114*9781SMoriah.Waterland@Sun.COM
1115*9781SMoriah.Waterland@Sun.COM if (fname != NULL)
1116*9781SMoriah.Waterland@Sun.COM *fname = NULL;
1117*9781SMoriah.Waterland@Sun.COM
1118*9781SMoriah.Waterland@Sun.COM if (pkey == NULL || pkey->attributes == NULL) {
1119*9781SMoriah.Waterland@Sun.COM return (0);
1120*9781SMoriah.Waterland@Sun.COM }
1121*9781SMoriah.Waterland@Sun.COM
1122*9781SMoriah.Waterland@Sun.COM if ((i = find_attr_by_nid(pkey->attributes, NID_friendlyName)) < 0) {
1123*9781SMoriah.Waterland@Sun.COM return (0);
1124*9781SMoriah.Waterland@Sun.COM }
1125*9781SMoriah.Waterland@Sun.COM attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
1126*9781SMoriah.Waterland@Sun.COM
1127*9781SMoriah.Waterland@Sun.COM if ((ty = attrib2type(attr)) == NULL ||
1128*9781SMoriah.Waterland@Sun.COM ty->type != V_ASN1_BMPSTRING) {
1129*9781SMoriah.Waterland@Sun.COM return (0);
1130*9781SMoriah.Waterland@Sun.COM }
1131*9781SMoriah.Waterland@Sun.COM
1132*9781SMoriah.Waterland@Sun.COM if (dowhat == GETDO_DEL) {
1133*9781SMoriah.Waterland@Sun.COM attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1134*9781SMoriah.Waterland@Sun.COM if (attr != NULL)
1135*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE_free(attr);
1136*9781SMoriah.Waterland@Sun.COM return (0);
1137*9781SMoriah.Waterland@Sun.COM }
1138*9781SMoriah.Waterland@Sun.COM
1139*9781SMoriah.Waterland@Sun.COM str = ty->value.bmpstring;
1140*9781SMoriah.Waterland@Sun.COM *fname = uni2asc(str->data, str->length);
1141*9781SMoriah.Waterland@Sun.COM if (*fname == NULL) {
1142*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_GET_PKEY_FNAME, SUNW_R_MEMORY_FAILURE);
1143*9781SMoriah.Waterland@Sun.COM return (-1);
1144*9781SMoriah.Waterland@Sun.COM }
1145*9781SMoriah.Waterland@Sun.COM
1146*9781SMoriah.Waterland@Sun.COM len = strlen(*fname);
1147*9781SMoriah.Waterland@Sun.COM
1148*9781SMoriah.Waterland@Sun.COM return (len);
1149*9781SMoriah.Waterland@Sun.COM }
1150*9781SMoriah.Waterland@Sun.COM
1151*9781SMoriah.Waterland@Sun.COM /*
1152*9781SMoriah.Waterland@Sun.COM * sunw_find_localkeyid() searches stacks of certs and private keys,
1153*9781SMoriah.Waterland@Sun.COM * and returns the first matching cert/private key found.
1154*9781SMoriah.Waterland@Sun.COM *
1155*9781SMoriah.Waterland@Sun.COM * Look for a keyid in a stack of certs. if 'certs' is NULL and 'pkeys' is
1156*9781SMoriah.Waterland@Sun.COM * not NULL, search the list of private keys. Move the matching cert to
1157*9781SMoriah.Waterland@Sun.COM * 'matching_cert' and its matching private key to 'matching_pkey'. If no
1158*9781SMoriah.Waterland@Sun.COM * cert or keys match, no match occurred.
1159*9781SMoriah.Waterland@Sun.COM *
1160*9781SMoriah.Waterland@Sun.COM * Arguments:
1161*9781SMoriah.Waterland@Sun.COM * keyid_str- A byte string with the localkeyid to match
1162*9781SMoriah.Waterland@Sun.COM * keyid_len- Length of the keyid byte string.
1163*9781SMoriah.Waterland@Sun.COM * pkeys - Points to a stack of private keys which match the certs.
1164*9781SMoriah.Waterland@Sun.COM * This may be NULL, in which case no keys are returned.
1165*9781SMoriah.Waterland@Sun.COM * certs - Points to a stack of certs to search. If NULL, search the
1166*9781SMoriah.Waterland@Sun.COM * stack of keys instead.
1167*9781SMoriah.Waterland@Sun.COM * matching_pkey
1168*9781SMoriah.Waterland@Sun.COM * - Pointer to receive address of first matching pkey found.
1169*9781SMoriah.Waterland@Sun.COM * 'matching_pkey' must not be NULL; '*matching_pkey' will be
1170*9781SMoriah.Waterland@Sun.COM * reset.
1171*9781SMoriah.Waterland@Sun.COM * matching_cert
1172*9781SMoriah.Waterland@Sun.COM * - Pointer to receive address of first matching cert found.
1173*9781SMoriah.Waterland@Sun.COM * 'matching_cert' must not be NULL; '*matching_cert' will be
1174*9781SMoriah.Waterland@Sun.COM * reset.
1175*9781SMoriah.Waterland@Sun.COM *
1176*9781SMoriah.Waterland@Sun.COM * Returns:
1177*9781SMoriah.Waterland@Sun.COM * < 0 - An error returned. Call ERR_get_error() to get errors information.
1178*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
1179*9781SMoriah.Waterland@Sun.COM * >= 0 - Objects were found and returned. Which objects are indicated by
1180*9781SMoriah.Waterland@Sun.COM * which bits are set (FOUND_PKEY and/or FOUND_CERT).
1181*9781SMoriah.Waterland@Sun.COM */
1182*9781SMoriah.Waterland@Sun.COM int
sunw_find_localkeyid(char * keyid_str,int len,STACK_OF (EVP_PKEY)* pkeys,STACK_OF (X509)* certs,EVP_PKEY ** matching_pkey,X509 ** matching_cert)1183*9781SMoriah.Waterland@Sun.COM sunw_find_localkeyid(char *keyid_str, int len, STACK_OF(EVP_PKEY) *pkeys,
1184*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *certs, EVP_PKEY **matching_pkey, X509 **matching_cert)
1185*9781SMoriah.Waterland@Sun.COM {
1186*9781SMoriah.Waterland@Sun.COM ASN1_STRING *cmpstr = NULL;
1187*9781SMoriah.Waterland@Sun.COM EVP_PKEY *tmp_pkey = NULL;
1188*9781SMoriah.Waterland@Sun.COM X509 *tmp_cert = NULL;
1189*9781SMoriah.Waterland@Sun.COM int retval = 0;
1190*9781SMoriah.Waterland@Sun.COM
1191*9781SMoriah.Waterland@Sun.COM /* If NULL arguments, this is an error */
1192*9781SMoriah.Waterland@Sun.COM if (keyid_str == NULL ||
1193*9781SMoriah.Waterland@Sun.COM (pkeys == NULL || certs == NULL) ||
1194*9781SMoriah.Waterland@Sun.COM (pkeys != NULL && matching_pkey == NULL) ||
1195*9781SMoriah.Waterland@Sun.COM (certs != NULL && matching_cert == NULL)) {
1196*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_INVALID_ARG);
1197*9781SMoriah.Waterland@Sun.COM return (-1);
1198*9781SMoriah.Waterland@Sun.COM }
1199*9781SMoriah.Waterland@Sun.COM
1200*9781SMoriah.Waterland@Sun.COM if (matching_pkey != NULL)
1201*9781SMoriah.Waterland@Sun.COM *matching_pkey = NULL;
1202*9781SMoriah.Waterland@Sun.COM if (matching_cert != NULL)
1203*9781SMoriah.Waterland@Sun.COM *matching_cert = NULL;
1204*9781SMoriah.Waterland@Sun.COM
1205*9781SMoriah.Waterland@Sun.COM cmpstr = (ASN1_STRING *)M_ASN1_OCTET_STRING_new();
1206*9781SMoriah.Waterland@Sun.COM if (cmpstr == NULL ||
1207*9781SMoriah.Waterland@Sun.COM M_ASN1_OCTET_STRING_set(cmpstr, keyid_str, len) == 0) {
1208*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_MEMORY_FAILURE);
1209*9781SMoriah.Waterland@Sun.COM return (-1);
1210*9781SMoriah.Waterland@Sun.COM }
1211*9781SMoriah.Waterland@Sun.COM
1212*9781SMoriah.Waterland@Sun.COM retval = find_attr(NID_localKeyID, cmpstr, pkeys, &tmp_pkey, certs,
1213*9781SMoriah.Waterland@Sun.COM &tmp_cert);
1214*9781SMoriah.Waterland@Sun.COM if (retval == 0) {
1215*9781SMoriah.Waterland@Sun.COM ASN1_STRING_free(cmpstr);
1216*9781SMoriah.Waterland@Sun.COM return (retval);
1217*9781SMoriah.Waterland@Sun.COM }
1218*9781SMoriah.Waterland@Sun.COM
1219*9781SMoriah.Waterland@Sun.COM if (matching_pkey != NULL)
1220*9781SMoriah.Waterland@Sun.COM *matching_pkey = tmp_pkey;
1221*9781SMoriah.Waterland@Sun.COM if (matching_cert != NULL)
1222*9781SMoriah.Waterland@Sun.COM *matching_cert = tmp_cert;
1223*9781SMoriah.Waterland@Sun.COM
1224*9781SMoriah.Waterland@Sun.COM return (retval);
1225*9781SMoriah.Waterland@Sun.COM }
1226*9781SMoriah.Waterland@Sun.COM
1227*9781SMoriah.Waterland@Sun.COM /*
1228*9781SMoriah.Waterland@Sun.COM * sunw_find_fname() searches stacks of certs and private keys for one with
1229*9781SMoriah.Waterland@Sun.COM * a matching friendlyname and returns the first matching cert/private
1230*9781SMoriah.Waterland@Sun.COM * key found.
1231*9781SMoriah.Waterland@Sun.COM *
1232*9781SMoriah.Waterland@Sun.COM * Look for a friendlyname in a stack of certs. if 'certs' is NULL and 'pkeys'
1233*9781SMoriah.Waterland@Sun.COM * is not NULL, search the list of private keys. Move the matching cert to
1234*9781SMoriah.Waterland@Sun.COM * 'matching_cert' and its matching private key to 'matching_pkey'. If no
1235*9781SMoriah.Waterland@Sun.COM * cert or keys match, no match occurred.
1236*9781SMoriah.Waterland@Sun.COM *
1237*9781SMoriah.Waterland@Sun.COM * Arguments:
1238*9781SMoriah.Waterland@Sun.COM * fname - Friendlyname to find (NULL-terminated ASCII string).
1239*9781SMoriah.Waterland@Sun.COM * pkeys - Points to a stack of private keys which match the certs.
1240*9781SMoriah.Waterland@Sun.COM * This may be NULL, in which case no keys are returned.
1241*9781SMoriah.Waterland@Sun.COM * certs - Points to a stack of certs to search. If NULL, search the
1242*9781SMoriah.Waterland@Sun.COM * stack of keys instead.
1243*9781SMoriah.Waterland@Sun.COM * matching_pkey
1244*9781SMoriah.Waterland@Sun.COM * - Pointer to receive address of first matching pkey found.
1245*9781SMoriah.Waterland@Sun.COM * matching_cert
1246*9781SMoriah.Waterland@Sun.COM * - Pointer to receive address of first matching cert found.
1247*9781SMoriah.Waterland@Sun.COM *
1248*9781SMoriah.Waterland@Sun.COM * Returns:
1249*9781SMoriah.Waterland@Sun.COM * < 0 - An error returned. Call ERR_get_error() to get errors information.
1250*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
1251*9781SMoriah.Waterland@Sun.COM * >= 0 - Objects were found and returned. Which objects are indicated by
1252*9781SMoriah.Waterland@Sun.COM * which bits are set (FOUND_PKEY and/or FOUND_CERT).
1253*9781SMoriah.Waterland@Sun.COM */
1254*9781SMoriah.Waterland@Sun.COM int
sunw_find_fname(char * fname,STACK_OF (EVP_PKEY)* pkeys,STACK_OF (X509)* certs,EVP_PKEY ** matching_pkey,X509 ** matching_cert)1255*9781SMoriah.Waterland@Sun.COM sunw_find_fname(char *fname, STACK_OF(EVP_PKEY) *pkeys, STACK_OF(X509) *certs,
1256*9781SMoriah.Waterland@Sun.COM EVP_PKEY **matching_pkey, X509 ** matching_cert)
1257*9781SMoriah.Waterland@Sun.COM {
1258*9781SMoriah.Waterland@Sun.COM ASN1_STRING *cmpstr = NULL;
1259*9781SMoriah.Waterland@Sun.COM EVP_PKEY *tmp_pkey = NULL;
1260*9781SMoriah.Waterland@Sun.COM X509 *tmp_cert = NULL;
1261*9781SMoriah.Waterland@Sun.COM int retval = 0;
1262*9781SMoriah.Waterland@Sun.COM
1263*9781SMoriah.Waterland@Sun.COM /* If NULL arguments, this is an error */
1264*9781SMoriah.Waterland@Sun.COM if (fname == NULL ||
1265*9781SMoriah.Waterland@Sun.COM (pkeys == NULL && certs == NULL) ||
1266*9781SMoriah.Waterland@Sun.COM (pkeys != NULL && matching_pkey == NULL) ||
1267*9781SMoriah.Waterland@Sun.COM (certs != NULL && matching_cert == NULL)) {
1268*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_FIND_FNAME, SUNW_R_INVALID_ARG);
1269*9781SMoriah.Waterland@Sun.COM return (-1);
1270*9781SMoriah.Waterland@Sun.COM }
1271*9781SMoriah.Waterland@Sun.COM
1272*9781SMoriah.Waterland@Sun.COM if (matching_pkey != NULL)
1273*9781SMoriah.Waterland@Sun.COM *matching_pkey = NULL;
1274*9781SMoriah.Waterland@Sun.COM if (matching_cert != NULL)
1275*9781SMoriah.Waterland@Sun.COM *matching_cert = NULL;
1276*9781SMoriah.Waterland@Sun.COM
1277*9781SMoriah.Waterland@Sun.COM cmpstr = (ASN1_STRING *)asc2bmpstring(fname, strlen(fname));
1278*9781SMoriah.Waterland@Sun.COM if (cmpstr == NULL) {
1279*9781SMoriah.Waterland@Sun.COM /*
1280*9781SMoriah.Waterland@Sun.COM * Error already on stack
1281*9781SMoriah.Waterland@Sun.COM */
1282*9781SMoriah.Waterland@Sun.COM return (-1);
1283*9781SMoriah.Waterland@Sun.COM }
1284*9781SMoriah.Waterland@Sun.COM
1285*9781SMoriah.Waterland@Sun.COM retval = find_attr(NID_friendlyName, cmpstr, pkeys, &tmp_pkey, certs,
1286*9781SMoriah.Waterland@Sun.COM &tmp_cert);
1287*9781SMoriah.Waterland@Sun.COM if (retval == 0) {
1288*9781SMoriah.Waterland@Sun.COM ASN1_STRING_free(cmpstr);
1289*9781SMoriah.Waterland@Sun.COM return (retval);
1290*9781SMoriah.Waterland@Sun.COM }
1291*9781SMoriah.Waterland@Sun.COM
1292*9781SMoriah.Waterland@Sun.COM if (matching_pkey != NULL)
1293*9781SMoriah.Waterland@Sun.COM *matching_pkey = tmp_pkey;
1294*9781SMoriah.Waterland@Sun.COM if (matching_cert != NULL)
1295*9781SMoriah.Waterland@Sun.COM *matching_cert = tmp_cert;
1296*9781SMoriah.Waterland@Sun.COM
1297*9781SMoriah.Waterland@Sun.COM return (retval);
1298*9781SMoriah.Waterland@Sun.COM }
1299*9781SMoriah.Waterland@Sun.COM
1300*9781SMoriah.Waterland@Sun.COM /*
1301*9781SMoriah.Waterland@Sun.COM * sunw_get_cert_fname() gets the fiendlyname from a cert. It can
1302*9781SMoriah.Waterland@Sun.COM * optionally remove the value found.
1303*9781SMoriah.Waterland@Sun.COM *
1304*9781SMoriah.Waterland@Sun.COM * Arguments:
1305*9781SMoriah.Waterland@Sun.COM * dowhat - What to do with the attributes (remove them or copy them).
1306*9781SMoriah.Waterland@Sun.COM * cert - Points to a cert to get the friendlyName from.
1307*9781SMoriah.Waterland@Sun.COM * fname - Points to a location which will receive the pointer to a
1308*9781SMoriah.Waterland@Sun.COM * byte string with the ASCII friendlyname
1309*9781SMoriah.Waterland@Sun.COM *
1310*9781SMoriah.Waterland@Sun.COM * Returns:
1311*9781SMoriah.Waterland@Sun.COM * >= 0 - The number of characters in the friendlyname returned.
1312*9781SMoriah.Waterland@Sun.COM * < 0 - An error occurred. It was probably an error in allocating
1313*9781SMoriah.Waterland@Sun.COM * memory. The error will be set in the error stack. Call
1314*9781SMoriah.Waterland@Sun.COM * ERR_get_error() to get specific information.
1315*9781SMoriah.Waterland@Sun.COM */
1316*9781SMoriah.Waterland@Sun.COM int
sunw_get_cert_fname(getdo_actions_t dowhat,X509 * cert,char ** fname)1317*9781SMoriah.Waterland@Sun.COM sunw_get_cert_fname(getdo_actions_t dowhat, X509 *cert, char **fname)
1318*9781SMoriah.Waterland@Sun.COM {
1319*9781SMoriah.Waterland@Sun.COM int len;
1320*9781SMoriah.Waterland@Sun.COM
1321*9781SMoriah.Waterland@Sun.COM if (fname != NULL)
1322*9781SMoriah.Waterland@Sun.COM *fname = NULL;
1323*9781SMoriah.Waterland@Sun.COM
1324*9781SMoriah.Waterland@Sun.COM if (cert == NULL || cert->aux == NULL || cert->aux->alias == NULL) {
1325*9781SMoriah.Waterland@Sun.COM return (0);
1326*9781SMoriah.Waterland@Sun.COM }
1327*9781SMoriah.Waterland@Sun.COM
1328*9781SMoriah.Waterland@Sun.COM if (dowhat == GETDO_DEL) {
1329*9781SMoriah.Waterland@Sun.COM /* Delete the entry */
1330*9781SMoriah.Waterland@Sun.COM ASN1_UTF8STRING_free(cert->aux->alias);
1331*9781SMoriah.Waterland@Sun.COM cert->aux->alias = NULL;
1332*9781SMoriah.Waterland@Sun.COM return (0);
1333*9781SMoriah.Waterland@Sun.COM }
1334*9781SMoriah.Waterland@Sun.COM
1335*9781SMoriah.Waterland@Sun.COM *((uchar_t **)fname) = utf82ascstr(cert->aux->alias);
1336*9781SMoriah.Waterland@Sun.COM if (*fname == NULL) {
1337*9781SMoriah.Waterland@Sun.COM /*
1338*9781SMoriah.Waterland@Sun.COM * Error already on stack
1339*9781SMoriah.Waterland@Sun.COM */
1340*9781SMoriah.Waterland@Sun.COM return (-1);
1341*9781SMoriah.Waterland@Sun.COM }
1342*9781SMoriah.Waterland@Sun.COM
1343*9781SMoriah.Waterland@Sun.COM len = strlen(*fname);
1344*9781SMoriah.Waterland@Sun.COM
1345*9781SMoriah.Waterland@Sun.COM return (len);
1346*9781SMoriah.Waterland@Sun.COM }
1347*9781SMoriah.Waterland@Sun.COM
1348*9781SMoriah.Waterland@Sun.COM /*
1349*9781SMoriah.Waterland@Sun.COM * sunw_set_fname() sets the friendlyName in a cert, a private key or
1350*9781SMoriah.Waterland@Sun.COM * both. Any existing friendlyname will be discarded.
1351*9781SMoriah.Waterland@Sun.COM *
1352*9781SMoriah.Waterland@Sun.COM * Arguments:
1353*9781SMoriah.Waterland@Sun.COM * ascname - An ASCII string with the friendlyName to set
1354*9781SMoriah.Waterland@Sun.COM * pkey - Points to a private key to set the fname in.
1355*9781SMoriah.Waterland@Sun.COM * cert - Points to a cert to set the fname in.
1356*9781SMoriah.Waterland@Sun.COM *
1357*9781SMoriah.Waterland@Sun.COM * Note that setting a friendlyName into a cert which will not be written out
1358*9781SMoriah.Waterland@Sun.COM * as a PKCS12 cert is pointless since it will be lost.
1359*9781SMoriah.Waterland@Sun.COM *
1360*9781SMoriah.Waterland@Sun.COM * Returns:
1361*9781SMoriah.Waterland@Sun.COM * 0 - Success.
1362*9781SMoriah.Waterland@Sun.COM * <0 - An error occurred. It was probably an error in allocating
1363*9781SMoriah.Waterland@Sun.COM * memory. The error will be set in the error stack. Call
1364*9781SMoriah.Waterland@Sun.COM * ERR_get_error() to get specific information.
1365*9781SMoriah.Waterland@Sun.COM */
1366*9781SMoriah.Waterland@Sun.COM int
sunw_set_fname(const char * ascname,EVP_PKEY * pkey,X509 * cert)1367*9781SMoriah.Waterland@Sun.COM sunw_set_fname(const char *ascname, EVP_PKEY *pkey, X509 *cert)
1368*9781SMoriah.Waterland@Sun.COM {
1369*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *attr = NULL;
1370*9781SMoriah.Waterland@Sun.COM ASN1_BMPSTRING *str = NULL;
1371*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *fname = NULL;
1372*9781SMoriah.Waterland@Sun.COM unsigned char *data = NULL;
1373*9781SMoriah.Waterland@Sun.COM int retval = -1;
1374*9781SMoriah.Waterland@Sun.COM int len;
1375*9781SMoriah.Waterland@Sun.COM int i;
1376*9781SMoriah.Waterland@Sun.COM
1377*9781SMoriah.Waterland@Sun.COM str = asc2bmpstring(ascname, strlen(ascname));
1378*9781SMoriah.Waterland@Sun.COM if (str == NULL) {
1379*9781SMoriah.Waterland@Sun.COM /*
1380*9781SMoriah.Waterland@Sun.COM * Error already on stack
1381*9781SMoriah.Waterland@Sun.COM */
1382*9781SMoriah.Waterland@Sun.COM return (-1);
1383*9781SMoriah.Waterland@Sun.COM }
1384*9781SMoriah.Waterland@Sun.COM
1385*9781SMoriah.Waterland@Sun.COM if (cert != NULL) {
1386*9781SMoriah.Waterland@Sun.COM if (cert->aux != NULL && cert->aux->alias != NULL) {
1387*9781SMoriah.Waterland@Sun.COM ASN1_UTF8STRING_free(cert->aux->alias);
1388*9781SMoriah.Waterland@Sun.COM }
1389*9781SMoriah.Waterland@Sun.COM
1390*9781SMoriah.Waterland@Sun.COM len = ASN1_STRING_to_UTF8(&data, str);
1391*9781SMoriah.Waterland@Sun.COM i = -23;
1392*9781SMoriah.Waterland@Sun.COM if (len <= 0 || (i = X509_alias_set1(cert, data, len)) == 0) {
1393*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_FNAME, SUNW_R_SET_FNAME_ERR);
1394*9781SMoriah.Waterland@Sun.COM goto cleanup;
1395*9781SMoriah.Waterland@Sun.COM }
1396*9781SMoriah.Waterland@Sun.COM }
1397*9781SMoriah.Waterland@Sun.COM if (pkey != NULL) {
1398*9781SMoriah.Waterland@Sun.COM if ((fname = ASN1_TYPE_new()) == NULL) {
1399*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE);
1400*9781SMoriah.Waterland@Sun.COM goto cleanup;
1401*9781SMoriah.Waterland@Sun.COM }
1402*9781SMoriah.Waterland@Sun.COM
1403*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_set(fname, V_ASN1_BMPSTRING, str);
1404*9781SMoriah.Waterland@Sun.COM str = NULL;
1405*9781SMoriah.Waterland@Sun.COM
1406*9781SMoriah.Waterland@Sun.COM attr = type2attrib(fname, NID_friendlyName);
1407*9781SMoriah.Waterland@Sun.COM if (attr == NULL) {
1408*9781SMoriah.Waterland@Sun.COM /*
1409*9781SMoriah.Waterland@Sun.COM * Error already on stack
1410*9781SMoriah.Waterland@Sun.COM */
1411*9781SMoriah.Waterland@Sun.COM goto cleanup;
1412*9781SMoriah.Waterland@Sun.COM }
1413*9781SMoriah.Waterland@Sun.COM fname = NULL;
1414*9781SMoriah.Waterland@Sun.COM
1415*9781SMoriah.Waterland@Sun.COM if (pkey->attributes == NULL) {
1416*9781SMoriah.Waterland@Sun.COM pkey->attributes = sk_X509_ATTRIBUTE_new_null();
1417*9781SMoriah.Waterland@Sun.COM if (pkey->attributes == NULL) {
1418*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_FNAME,
1419*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
1420*9781SMoriah.Waterland@Sun.COM goto cleanup;
1421*9781SMoriah.Waterland@Sun.COM }
1422*9781SMoriah.Waterland@Sun.COM } else if ((i = find_attr_by_nid(pkey->attributes,
1423*9781SMoriah.Waterland@Sun.COM NID_friendlyName)) >= 0) {
1424*9781SMoriah.Waterland@Sun.COM (void) sk_X509_ATTRIBUTE_delete(pkey->attributes, i);
1425*9781SMoriah.Waterland@Sun.COM }
1426*9781SMoriah.Waterland@Sun.COM
1427*9781SMoriah.Waterland@Sun.COM if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) {
1428*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE);
1429*9781SMoriah.Waterland@Sun.COM goto cleanup;
1430*9781SMoriah.Waterland@Sun.COM }
1431*9781SMoriah.Waterland@Sun.COM
1432*9781SMoriah.Waterland@Sun.COM attr = NULL;
1433*9781SMoriah.Waterland@Sun.COM }
1434*9781SMoriah.Waterland@Sun.COM retval = 0;
1435*9781SMoriah.Waterland@Sun.COM
1436*9781SMoriah.Waterland@Sun.COM cleanup:
1437*9781SMoriah.Waterland@Sun.COM if (data != NULL)
1438*9781SMoriah.Waterland@Sun.COM OPENSSL_free(data);
1439*9781SMoriah.Waterland@Sun.COM if (str != NULL)
1440*9781SMoriah.Waterland@Sun.COM ASN1_BMPSTRING_free(str);
1441*9781SMoriah.Waterland@Sun.COM if (fname != NULL)
1442*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(fname);
1443*9781SMoriah.Waterland@Sun.COM if (attr != NULL)
1444*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE_free(attr);
1445*9781SMoriah.Waterland@Sun.COM
1446*9781SMoriah.Waterland@Sun.COM return (retval);
1447*9781SMoriah.Waterland@Sun.COM }
1448*9781SMoriah.Waterland@Sun.COM
1449*9781SMoriah.Waterland@Sun.COM /*
1450*9781SMoriah.Waterland@Sun.COM * sunw_check_keys() compares the public key in the certificate and a
1451*9781SMoriah.Waterland@Sun.COM * private key to ensure that they match.
1452*9781SMoriah.Waterland@Sun.COM *
1453*9781SMoriah.Waterland@Sun.COM * Arguments:
1454*9781SMoriah.Waterland@Sun.COM * cert - Points to a certificate.
1455*9781SMoriah.Waterland@Sun.COM * pkey - Points to a private key.
1456*9781SMoriah.Waterland@Sun.COM *
1457*9781SMoriah.Waterland@Sun.COM * Returns:
1458*9781SMoriah.Waterland@Sun.COM * == 0 - These do not match.
1459*9781SMoriah.Waterland@Sun.COM * != 0 - The cert's public key and the private key match.
1460*9781SMoriah.Waterland@Sun.COM */
1461*9781SMoriah.Waterland@Sun.COM int
sunw_check_keys(X509 * cert,EVP_PKEY * pkey)1462*9781SMoriah.Waterland@Sun.COM sunw_check_keys(X509 *cert, EVP_PKEY *pkey)
1463*9781SMoriah.Waterland@Sun.COM {
1464*9781SMoriah.Waterland@Sun.COM int retval = 0;
1465*9781SMoriah.Waterland@Sun.COM
1466*9781SMoriah.Waterland@Sun.COM if (pkey != NULL && cert != NULL)
1467*9781SMoriah.Waterland@Sun.COM retval = X509_check_private_key(cert, pkey);
1468*9781SMoriah.Waterland@Sun.COM
1469*9781SMoriah.Waterland@Sun.COM return (retval);
1470*9781SMoriah.Waterland@Sun.COM }
1471*9781SMoriah.Waterland@Sun.COM
1472*9781SMoriah.Waterland@Sun.COM /*
1473*9781SMoriah.Waterland@Sun.COM * sunw_check_cert_times() compares the time fields in a certificate
1474*9781SMoriah.Waterland@Sun.COM *
1475*9781SMoriah.Waterland@Sun.COM * Compare the 'not before' and the 'not after' times in the cert
1476*9781SMoriah.Waterland@Sun.COM * to the current time. Return the results of the comparison (bad time formats,
1477*9781SMoriah.Waterland@Sun.COM * cert not yet in force, cert expired or in range)
1478*9781SMoriah.Waterland@Sun.COM *
1479*9781SMoriah.Waterland@Sun.COM * Arguments:
1480*9781SMoriah.Waterland@Sun.COM * dowhat - what field(s) to check.
1481*9781SMoriah.Waterland@Sun.COM * cert - Points to a cert to check
1482*9781SMoriah.Waterland@Sun.COM *
1483*9781SMoriah.Waterland@Sun.COM * Returns:
1484*9781SMoriah.Waterland@Sun.COM * Results of the comparison.
1485*9781SMoriah.Waterland@Sun.COM */
1486*9781SMoriah.Waterland@Sun.COM chk_errs_t
sunw_check_cert_times(chk_actions_t chkwhat,X509 * cert)1487*9781SMoriah.Waterland@Sun.COM sunw_check_cert_times(chk_actions_t chkwhat, X509 *cert)
1488*9781SMoriah.Waterland@Sun.COM {
1489*9781SMoriah.Waterland@Sun.COM return (check_time(chkwhat, cert));
1490*9781SMoriah.Waterland@Sun.COM }
1491*9781SMoriah.Waterland@Sun.COM
1492*9781SMoriah.Waterland@Sun.COM /*
1493*9781SMoriah.Waterland@Sun.COM * ----------------------------------------------------------------------------
1494*9781SMoriah.Waterland@Sun.COM * Local routines
1495*9781SMoriah.Waterland@Sun.COM * ----------------------------------------------------------------------------
1496*9781SMoriah.Waterland@Sun.COM */
1497*9781SMoriah.Waterland@Sun.COM
1498*9781SMoriah.Waterland@Sun.COM
1499*9781SMoriah.Waterland@Sun.COM /*
1500*9781SMoriah.Waterland@Sun.COM * parse_pkcs12 - Oversee parsing of the pkcs12 structure. Get it
1501*9781SMoriah.Waterland@Sun.COM * parsed. After that either return what's found directly, or
1502*9781SMoriah.Waterland@Sun.COM * do any required matching.
1503*9781SMoriah.Waterland@Sun.COM *
1504*9781SMoriah.Waterland@Sun.COM * Arguments:
1505*9781SMoriah.Waterland@Sun.COM * p12 - Structure with pkcs12 info to be parsed
1506*9781SMoriah.Waterland@Sun.COM * pass - Pass phrase for the private key (possibly empty) or NULL if
1507*9781SMoriah.Waterland@Sun.COM * there is none.
1508*9781SMoriah.Waterland@Sun.COM * matchty - Info about which certs/keys to return if many are in the file.
1509*9781SMoriah.Waterland@Sun.COM * keyid - If private key localkeyids friendlynames are to match a
1510*9781SMoriah.Waterland@Sun.COM * predetermined value, the value to match. This value should
1511*9781SMoriah.Waterland@Sun.COM * be an octet string.
1512*9781SMoriah.Waterland@Sun.COM * keyid_len- Length of the keyid byte string.
1513*9781SMoriah.Waterland@Sun.COM * name_str - If friendlynames are to match a predetermined value, the value
1514*9781SMoriah.Waterland@Sun.COM * to match. This value should be a NULL terminated string.
1515*9781SMoriah.Waterland@Sun.COM * pkey - Points to location pointing to the private key returned.
1516*9781SMoriah.Waterland@Sun.COM * cert - Points to locaiton which points to the client cert returned
1517*9781SMoriah.Waterland@Sun.COM * ca - Points to location that points to a stack of 'certificate
1518*9781SMoriah.Waterland@Sun.COM * authority' certs/trust anchors.
1519*9781SMoriah.Waterland@Sun.COM *
1520*9781SMoriah.Waterland@Sun.COM * Note about error codes: This function is an internal function, and the
1521*9781SMoriah.Waterland@Sun.COM * place where it is called sets error codes. Therefore only set an error
1522*9781SMoriah.Waterland@Sun.COM * code if it is something that is unique or if the function which detected
1523*9781SMoriah.Waterland@Sun.COM * the error doesn't set one.
1524*9781SMoriah.Waterland@Sun.COM *
1525*9781SMoriah.Waterland@Sun.COM * Returns:
1526*9781SMoriah.Waterland@Sun.COM * == -1 - An error occurred. Call ERR_get_error() to get error information.
1527*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
1528*9781SMoriah.Waterland@Sun.COM * == 0 - No matching returns were found.
1529*9781SMoriah.Waterland@Sun.COM * > 0 - This is the aithmetic 'or' of the FOUND_* bits that indicate which
1530*9781SMoriah.Waterland@Sun.COM * of the requested entries were found.
1531*9781SMoriah.Waterland@Sun.COM */
1532*9781SMoriah.Waterland@Sun.COM static int
parse_pkcs12(PKCS12 * p12,const char * pass,int matchty,char * keyid,int kstr_len,char * name_str,EVP_PKEY ** pkey,X509 ** cert,STACK_OF (X509)** ca)1533*9781SMoriah.Waterland@Sun.COM parse_pkcs12(PKCS12 *p12, const char *pass, int matchty, char *keyid,
1534*9781SMoriah.Waterland@Sun.COM int kstr_len, char *name_str, EVP_PKEY **pkey, X509 **cert,
1535*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) **ca)
1536*9781SMoriah.Waterland@Sun.COM {
1537*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *work_kl = NULL; /* Head for private key list */
1538*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *nocerts = NULL; /* Head for alt. key list */
1539*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *work_ca = NULL; /* Head for cert list */
1540*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *work_cl = NULL;
1541*9781SMoriah.Waterland@Sun.COM int retval = 0;
1542*9781SMoriah.Waterland@Sun.COM int n;
1543*9781SMoriah.Waterland@Sun.COM
1544*9781SMoriah.Waterland@Sun.COM retval = sunw_PKCS12_contents(p12, pass, &work_kl, &work_ca);
1545*9781SMoriah.Waterland@Sun.COM if (retval < 0) {
1546*9781SMoriah.Waterland@Sun.COM goto cleanup;
1547*9781SMoriah.Waterland@Sun.COM } else if (retval == 0) {
1548*9781SMoriah.Waterland@Sun.COM /*
1549*9781SMoriah.Waterland@Sun.COM * Not really an error here - its just that nothing was found.
1550*9781SMoriah.Waterland@Sun.COM */
1551*9781SMoriah.Waterland@Sun.COM goto cleanup;
1552*9781SMoriah.Waterland@Sun.COM }
1553*9781SMoriah.Waterland@Sun.COM
1554*9781SMoriah.Waterland@Sun.COM if (sk_EVP_PKEY_num(work_kl) > 0) {
1555*9781SMoriah.Waterland@Sun.COM
1556*9781SMoriah.Waterland@Sun.COM if (sunw_split_certs(work_kl, work_ca, &work_cl, &nocerts)
1557*9781SMoriah.Waterland@Sun.COM < 0) {
1558*9781SMoriah.Waterland@Sun.COM goto cleanup;
1559*9781SMoriah.Waterland@Sun.COM }
1560*9781SMoriah.Waterland@Sun.COM }
1561*9781SMoriah.Waterland@Sun.COM
1562*9781SMoriah.Waterland@Sun.COM /*
1563*9781SMoriah.Waterland@Sun.COM * Go through the lists of certs and private keys which were
1564*9781SMoriah.Waterland@Sun.COM * returned, looking for matches of the appropriate type. Do these
1565*9781SMoriah.Waterland@Sun.COM * in the order described above.
1566*9781SMoriah.Waterland@Sun.COM */
1567*9781SMoriah.Waterland@Sun.COM if ((matchty & DO_FIND_KEYID) != 0) {
1568*9781SMoriah.Waterland@Sun.COM
1569*9781SMoriah.Waterland@Sun.COM if (keyid == NULL) {
1570*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
1571*9781SMoriah.Waterland@Sun.COM retval = -1;
1572*9781SMoriah.Waterland@Sun.COM goto cleanup;
1573*9781SMoriah.Waterland@Sun.COM }
1574*9781SMoriah.Waterland@Sun.COM
1575*9781SMoriah.Waterland@Sun.COM /* See if string matches localkeyid's */
1576*9781SMoriah.Waterland@Sun.COM retval = sunw_find_localkeyid(keyid, kstr_len,
1577*9781SMoriah.Waterland@Sun.COM work_kl, work_cl, pkey, cert);
1578*9781SMoriah.Waterland@Sun.COM if (retval != 0) {
1579*9781SMoriah.Waterland@Sun.COM if (retval == -1)
1580*9781SMoriah.Waterland@Sun.COM goto cleanup;
1581*9781SMoriah.Waterland@Sun.COM else
1582*9781SMoriah.Waterland@Sun.COM goto last_part;
1583*9781SMoriah.Waterland@Sun.COM }
1584*9781SMoriah.Waterland@Sun.COM }
1585*9781SMoriah.Waterland@Sun.COM if ((matchty & DO_FIND_FN) != 0) {
1586*9781SMoriah.Waterland@Sun.COM
1587*9781SMoriah.Waterland@Sun.COM if (name_str == NULL) {
1588*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG);
1589*9781SMoriah.Waterland@Sun.COM retval = -1;
1590*9781SMoriah.Waterland@Sun.COM goto cleanup;
1591*9781SMoriah.Waterland@Sun.COM }
1592*9781SMoriah.Waterland@Sun.COM
1593*9781SMoriah.Waterland@Sun.COM /* See if string matches friendly names */
1594*9781SMoriah.Waterland@Sun.COM retval = sunw_find_fname(name_str, work_kl, work_cl,
1595*9781SMoriah.Waterland@Sun.COM pkey, cert);
1596*9781SMoriah.Waterland@Sun.COM if (retval != 0) {
1597*9781SMoriah.Waterland@Sun.COM if (retval == -1)
1598*9781SMoriah.Waterland@Sun.COM goto cleanup;
1599*9781SMoriah.Waterland@Sun.COM else
1600*9781SMoriah.Waterland@Sun.COM goto last_part;
1601*9781SMoriah.Waterland@Sun.COM }
1602*9781SMoriah.Waterland@Sun.COM }
1603*9781SMoriah.Waterland@Sun.COM
1604*9781SMoriah.Waterland@Sun.COM if (matchty & DO_FIRST_PAIR) {
1605*9781SMoriah.Waterland@Sun.COM
1606*9781SMoriah.Waterland@Sun.COM /* Find the first cert and private key and return them */
1607*9781SMoriah.Waterland@Sun.COM retval = get_key_cert(0, work_kl, pkey, work_cl, cert);
1608*9781SMoriah.Waterland@Sun.COM if (retval != 0) {
1609*9781SMoriah.Waterland@Sun.COM if (retval == -1)
1610*9781SMoriah.Waterland@Sun.COM goto cleanup;
1611*9781SMoriah.Waterland@Sun.COM else
1612*9781SMoriah.Waterland@Sun.COM goto last_part;
1613*9781SMoriah.Waterland@Sun.COM }
1614*9781SMoriah.Waterland@Sun.COM }
1615*9781SMoriah.Waterland@Sun.COM
1616*9781SMoriah.Waterland@Sun.COM if (matchty & DO_LAST_PAIR) {
1617*9781SMoriah.Waterland@Sun.COM
1618*9781SMoriah.Waterland@Sun.COM /*
1619*9781SMoriah.Waterland@Sun.COM * Find the last matching cert and private key and return
1620*9781SMoriah.Waterland@Sun.COM * them. Since keys which don't have matching client certs
1621*9781SMoriah.Waterland@Sun.COM * are at the end of the list of keys, use the number of
1622*9781SMoriah.Waterland@Sun.COM * client certs to compute the position of the last private
1623*9781SMoriah.Waterland@Sun.COM * key which matches a client cert.
1624*9781SMoriah.Waterland@Sun.COM */
1625*9781SMoriah.Waterland@Sun.COM n = sk_X509_num(work_cl) - 1;
1626*9781SMoriah.Waterland@Sun.COM retval = get_key_cert(n, work_kl, pkey, work_cl, cert);
1627*9781SMoriah.Waterland@Sun.COM if (retval != 0) {
1628*9781SMoriah.Waterland@Sun.COM if (retval == -1)
1629*9781SMoriah.Waterland@Sun.COM goto cleanup;
1630*9781SMoriah.Waterland@Sun.COM else
1631*9781SMoriah.Waterland@Sun.COM goto last_part;
1632*9781SMoriah.Waterland@Sun.COM }
1633*9781SMoriah.Waterland@Sun.COM }
1634*9781SMoriah.Waterland@Sun.COM
1635*9781SMoriah.Waterland@Sun.COM if (matchty & DO_UNMATCHING) {
1636*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *tmpk;
1637*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *tmpc;
1638*9781SMoriah.Waterland@Sun.COM
1639*9781SMoriah.Waterland@Sun.COM /* Find the first cert and private key and return them */
1640*9781SMoriah.Waterland@Sun.COM tmpc = work_cl;
1641*9781SMoriah.Waterland@Sun.COM if (work_cl == NULL || sk_X509_num(work_cl) == 0)
1642*9781SMoriah.Waterland@Sun.COM tmpc = work_ca;
1643*9781SMoriah.Waterland@Sun.COM tmpk = work_kl;
1644*9781SMoriah.Waterland@Sun.COM if (work_kl == NULL || sk_EVP_PKEY_num(work_kl) == 0)
1645*9781SMoriah.Waterland@Sun.COM tmpk = nocerts;
1646*9781SMoriah.Waterland@Sun.COM retval = get_key_cert(0, tmpk, pkey, tmpc, cert);
1647*9781SMoriah.Waterland@Sun.COM if (retval != 0) {
1648*9781SMoriah.Waterland@Sun.COM if (retval == -1)
1649*9781SMoriah.Waterland@Sun.COM goto cleanup;
1650*9781SMoriah.Waterland@Sun.COM else
1651*9781SMoriah.Waterland@Sun.COM goto last_part;
1652*9781SMoriah.Waterland@Sun.COM }
1653*9781SMoriah.Waterland@Sun.COM }
1654*9781SMoriah.Waterland@Sun.COM
1655*9781SMoriah.Waterland@Sun.COM last_part:
1656*9781SMoriah.Waterland@Sun.COM /* If no errors, terminate normally */
1657*9781SMoriah.Waterland@Sun.COM if (retval != -1)
1658*9781SMoriah.Waterland@Sun.COM retval |= set_results(NULL, NULL, NULL, NULL, ca, &work_ca,
1659*9781SMoriah.Waterland@Sun.COM NULL, NULL);
1660*9781SMoriah.Waterland@Sun.COM if (retval >= 0) {
1661*9781SMoriah.Waterland@Sun.COM goto clean_part;
1662*9781SMoriah.Waterland@Sun.COM }
1663*9781SMoriah.Waterland@Sun.COM
1664*9781SMoriah.Waterland@Sun.COM /* Fallthrough is intentional in error cases. */
1665*9781SMoriah.Waterland@Sun.COM cleanup:
1666*9781SMoriah.Waterland@Sun.COM if (pkey != NULL && *pkey != NULL) {
1667*9781SMoriah.Waterland@Sun.COM sunw_evp_pkey_free(*pkey);
1668*9781SMoriah.Waterland@Sun.COM *pkey = NULL;
1669*9781SMoriah.Waterland@Sun.COM }
1670*9781SMoriah.Waterland@Sun.COM if (cert != NULL && *cert != NULL) {
1671*9781SMoriah.Waterland@Sun.COM X509_free(*cert);
1672*9781SMoriah.Waterland@Sun.COM *cert = NULL;
1673*9781SMoriah.Waterland@Sun.COM }
1674*9781SMoriah.Waterland@Sun.COM
1675*9781SMoriah.Waterland@Sun.COM clean_part:
1676*9781SMoriah.Waterland@Sun.COM
1677*9781SMoriah.Waterland@Sun.COM if (work_kl != NULL) {
1678*9781SMoriah.Waterland@Sun.COM sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
1679*9781SMoriah.Waterland@Sun.COM }
1680*9781SMoriah.Waterland@Sun.COM if (work_ca != NULL)
1681*9781SMoriah.Waterland@Sun.COM sk_X509_pop_free(work_ca, X509_free);
1682*9781SMoriah.Waterland@Sun.COM if (work_cl != NULL)
1683*9781SMoriah.Waterland@Sun.COM sk_X509_pop_free(work_cl, X509_free);
1684*9781SMoriah.Waterland@Sun.COM
1685*9781SMoriah.Waterland@Sun.COM return (retval);
1686*9781SMoriah.Waterland@Sun.COM }
1687*9781SMoriah.Waterland@Sun.COM
1688*9781SMoriah.Waterland@Sun.COM /*
1689*9781SMoriah.Waterland@Sun.COM * parse_outer - Unpack the outer PKCS#12 structure and go through the
1690*9781SMoriah.Waterland@Sun.COM * individual bags. Return stacks of certs, private keys found and
1691*9781SMoriah.Waterland@Sun.COM * CA certs found.
1692*9781SMoriah.Waterland@Sun.COM *
1693*9781SMoriah.Waterland@Sun.COM * Note about error codes: This function is an internal function, and the
1694*9781SMoriah.Waterland@Sun.COM * place where it is called sets error codes.
1695*9781SMoriah.Waterland@Sun.COM *
1696*9781SMoriah.Waterland@Sun.COM * Returns:
1697*9781SMoriah.Waterland@Sun.COM * 0 - An error returned. Call ERR_get_error() to get errors information.
1698*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
1699*9781SMoriah.Waterland@Sun.COM * 1 - PKCS12 data object was parsed and lists of certs and private keys
1700*9781SMoriah.Waterland@Sun.COM * were returned.
1701*9781SMoriah.Waterland@Sun.COM */
1702*9781SMoriah.Waterland@Sun.COM static int
parse_outer(PKCS12 * p12,const char * pass,STACK_OF (EVP_PKEY)* kl,STACK_OF (X509)* cl)1703*9781SMoriah.Waterland@Sun.COM parse_outer(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) *kl,
1704*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *cl)
1705*9781SMoriah.Waterland@Sun.COM {
1706*9781SMoriah.Waterland@Sun.COM STACK_OF(PKCS12_SAFEBAG) *bags;
1707*9781SMoriah.Waterland@Sun.COM STACK_OF(PKCS7) *asafes;
1708*9781SMoriah.Waterland@Sun.COM int i, bagnid;
1709*9781SMoriah.Waterland@Sun.COM PKCS7 *p7;
1710*9781SMoriah.Waterland@Sun.COM
1711*9781SMoriah.Waterland@Sun.COM if ((asafes = M_PKCS12_unpack_authsafes(p12)) == NULL)
1712*9781SMoriah.Waterland@Sun.COM return (0);
1713*9781SMoriah.Waterland@Sun.COM
1714*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_PKCS7_num(asafes); i++) {
1715*9781SMoriah.Waterland@Sun.COM p7 = sk_PKCS7_value(asafes, i);
1716*9781SMoriah.Waterland@Sun.COM bagnid = OBJ_obj2nid(p7->type);
1717*9781SMoriah.Waterland@Sun.COM if (bagnid == NID_pkcs7_data) {
1718*9781SMoriah.Waterland@Sun.COM bags = M_PKCS12_unpack_p7data(p7);
1719*9781SMoriah.Waterland@Sun.COM } else if (bagnid == NID_pkcs7_encrypted) {
1720*9781SMoriah.Waterland@Sun.COM /*
1721*9781SMoriah.Waterland@Sun.COM * A length of '-1' means strlen() can be used
1722*9781SMoriah.Waterland@Sun.COM * to determine the password length.
1723*9781SMoriah.Waterland@Sun.COM */
1724*9781SMoriah.Waterland@Sun.COM bags = M_PKCS12_unpack_p7encdata(p7, pass, -1);
1725*9781SMoriah.Waterland@Sun.COM } else {
1726*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_BAD_BAGTYPE);
1727*9781SMoriah.Waterland@Sun.COM return (0);
1728*9781SMoriah.Waterland@Sun.COM }
1729*9781SMoriah.Waterland@Sun.COM
1730*9781SMoriah.Waterland@Sun.COM if (bags == NULL) {
1731*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_PARSE_BAG_ERR);
1732*9781SMoriah.Waterland@Sun.COM sk_PKCS7_pop_free(asafes, PKCS7_free);
1733*9781SMoriah.Waterland@Sun.COM return (0);
1734*9781SMoriah.Waterland@Sun.COM }
1735*9781SMoriah.Waterland@Sun.COM if (parse_all_bags(bags, pass, kl, cl) == 0) {
1736*9781SMoriah.Waterland@Sun.COM sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
1737*9781SMoriah.Waterland@Sun.COM sk_PKCS7_pop_free(asafes, PKCS7_free);
1738*9781SMoriah.Waterland@Sun.COM return (0);
1739*9781SMoriah.Waterland@Sun.COM }
1740*9781SMoriah.Waterland@Sun.COM }
1741*9781SMoriah.Waterland@Sun.COM
1742*9781SMoriah.Waterland@Sun.COM return (1);
1743*9781SMoriah.Waterland@Sun.COM }
1744*9781SMoriah.Waterland@Sun.COM
1745*9781SMoriah.Waterland@Sun.COM /*
1746*9781SMoriah.Waterland@Sun.COM * parse_all_bags - go through the stack of bags, parsing each.
1747*9781SMoriah.Waterland@Sun.COM *
1748*9781SMoriah.Waterland@Sun.COM * Note about error codes: This function is an internal function, and the
1749*9781SMoriah.Waterland@Sun.COM * place where it is called sets error codes.
1750*9781SMoriah.Waterland@Sun.COM *
1751*9781SMoriah.Waterland@Sun.COM * Returns:
1752*9781SMoriah.Waterland@Sun.COM * 0 - An error returned. Call ERR_get_error() to get errors information.
1753*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
1754*9781SMoriah.Waterland@Sun.COM * 1 - Stack of safebags was parsed and lists of certs and private keys
1755*9781SMoriah.Waterland@Sun.COM * were returned.
1756*9781SMoriah.Waterland@Sun.COM */
1757*9781SMoriah.Waterland@Sun.COM static int
parse_all_bags(STACK_OF (PKCS12_SAFEBAG)* bags,const char * pass,STACK_OF (EVP_PKEY)* kl,STACK_OF (X509)* cl)1758*9781SMoriah.Waterland@Sun.COM parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
1759*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *kl, STACK_OF(X509) *cl)
1760*9781SMoriah.Waterland@Sun.COM {
1761*9781SMoriah.Waterland@Sun.COM int i;
1762*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
1763*9781SMoriah.Waterland@Sun.COM if (parse_one_bag(sk_PKCS12_SAFEBAG_value(bags, i),
1764*9781SMoriah.Waterland@Sun.COM pass, kl, cl) == 0)
1765*9781SMoriah.Waterland@Sun.COM return (0);
1766*9781SMoriah.Waterland@Sun.COM }
1767*9781SMoriah.Waterland@Sun.COM return (1);
1768*9781SMoriah.Waterland@Sun.COM }
1769*9781SMoriah.Waterland@Sun.COM
1770*9781SMoriah.Waterland@Sun.COM /*
1771*9781SMoriah.Waterland@Sun.COM * parse_one_bag - Parse an individual bag
1772*9781SMoriah.Waterland@Sun.COM *
1773*9781SMoriah.Waterland@Sun.COM * i = parse_one_bag(bag, pass, kl, cl);
1774*9781SMoriah.Waterland@Sun.COM *
1775*9781SMoriah.Waterland@Sun.COM * Arguments:
1776*9781SMoriah.Waterland@Sun.COM * bag - pkcs12 safebag to parse.
1777*9781SMoriah.Waterland@Sun.COM * pass - password for use in decryption of shrouded keybag
1778*9781SMoriah.Waterland@Sun.COM * kl - Stack of private keys found so far. New private keys will
1779*9781SMoriah.Waterland@Sun.COM * be added here if found.
1780*9781SMoriah.Waterland@Sun.COM * cl - Stack of certs found so far. New certificates will be
1781*9781SMoriah.Waterland@Sun.COM * added here if found.
1782*9781SMoriah.Waterland@Sun.COM *
1783*9781SMoriah.Waterland@Sun.COM * Returns:
1784*9781SMoriah.Waterland@Sun.COM * 0 - An error returned. Call ERR_get_error() to get errors information.
1785*9781SMoriah.Waterland@Sun.COM * Where possible, memory has been freed.
1786*9781SMoriah.Waterland@Sun.COM * 1 - one safebag was parsed. If it contained a cert or private key, it
1787*9781SMoriah.Waterland@Sun.COM * was added to the stack of certs or private keys found, respectively.
1788*9781SMoriah.Waterland@Sun.COM * localKeyId or friendlyName attributes are returned with the
1789*9781SMoriah.Waterland@Sun.COM * private key or certificate.
1790*9781SMoriah.Waterland@Sun.COM */
1791*9781SMoriah.Waterland@Sun.COM static int
parse_one_bag(PKCS12_SAFEBAG * bag,const char * pass,STACK_OF (EVP_PKEY)* kl,STACK_OF (X509)* cl)1792*9781SMoriah.Waterland@Sun.COM parse_one_bag(PKCS12_SAFEBAG *bag, const char *pass, STACK_OF(EVP_PKEY) *kl,
1793*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *cl)
1794*9781SMoriah.Waterland@Sun.COM {
1795*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *attr = NULL;
1796*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *keyid = NULL;
1797*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *fname = NULL;
1798*9781SMoriah.Waterland@Sun.COM PKCS8_PRIV_KEY_INFO *p8;
1799*9781SMoriah.Waterland@Sun.COM EVP_PKEY *pkey = NULL;
1800*9781SMoriah.Waterland@Sun.COM X509 *x509 = NULL;
1801*9781SMoriah.Waterland@Sun.COM uchar_t *data = NULL;
1802*9781SMoriah.Waterland@Sun.COM char *str = NULL;
1803*9781SMoriah.Waterland@Sun.COM int retval = 1;
1804*9781SMoriah.Waterland@Sun.COM
1805*9781SMoriah.Waterland@Sun.COM keyid = PKCS12_get_attr(bag, NID_localKeyID);
1806*9781SMoriah.Waterland@Sun.COM fname = PKCS12_get_attr(bag, NID_friendlyName);
1807*9781SMoriah.Waterland@Sun.COM
1808*9781SMoriah.Waterland@Sun.COM switch (M_PKCS12_bag_type(bag)) {
1809*9781SMoriah.Waterland@Sun.COM case NID_keyBag:
1810*9781SMoriah.Waterland@Sun.COM if ((pkey = EVP_PKCS82PKEY(bag->value.keybag)) == NULL) {
1811*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
1812*9781SMoriah.Waterland@Sun.COM retval = 0;
1813*9781SMoriah.Waterland@Sun.COM break;
1814*9781SMoriah.Waterland@Sun.COM }
1815*9781SMoriah.Waterland@Sun.COM break;
1816*9781SMoriah.Waterland@Sun.COM
1817*9781SMoriah.Waterland@Sun.COM case NID_pkcs8ShroudedKeyBag:
1818*9781SMoriah.Waterland@Sun.COM /*
1819*9781SMoriah.Waterland@Sun.COM * A length of '-1' means strlen() can be used
1820*9781SMoriah.Waterland@Sun.COM * to determine the password length.
1821*9781SMoriah.Waterland@Sun.COM */
1822*9781SMoriah.Waterland@Sun.COM if ((p8 = M_PKCS12_decrypt_skey(bag, pass, -1)) == NULL) {
1823*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
1824*9781SMoriah.Waterland@Sun.COM retval = 0;
1825*9781SMoriah.Waterland@Sun.COM break;
1826*9781SMoriah.Waterland@Sun.COM }
1827*9781SMoriah.Waterland@Sun.COM pkey = EVP_PKCS82PKEY(p8);
1828*9781SMoriah.Waterland@Sun.COM PKCS8_PRIV_KEY_INFO_free(p8);
1829*9781SMoriah.Waterland@Sun.COM if (pkey == NULL) {
1830*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR);
1831*9781SMoriah.Waterland@Sun.COM retval = 0;
1832*9781SMoriah.Waterland@Sun.COM }
1833*9781SMoriah.Waterland@Sun.COM break;
1834*9781SMoriah.Waterland@Sun.COM
1835*9781SMoriah.Waterland@Sun.COM case NID_certBag:
1836*9781SMoriah.Waterland@Sun.COM if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) {
1837*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_CERTTYPE);
1838*9781SMoriah.Waterland@Sun.COM break;
1839*9781SMoriah.Waterland@Sun.COM }
1840*9781SMoriah.Waterland@Sun.COM if ((x509 = M_PKCS12_certbag2x509(bag)) == NULL) {
1841*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1842*9781SMoriah.Waterland@Sun.COM SUNW_R_PARSE_CERT_ERR);
1843*9781SMoriah.Waterland@Sun.COM retval = 0;
1844*9781SMoriah.Waterland@Sun.COM break;
1845*9781SMoriah.Waterland@Sun.COM }
1846*9781SMoriah.Waterland@Sun.COM
1847*9781SMoriah.Waterland@Sun.COM if (keyid != NULL) {
1848*9781SMoriah.Waterland@Sun.COM if (keyid->type != V_ASN1_OCTET_STRING) {
1849*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1850*9781SMoriah.Waterland@Sun.COM SUNW_R_BAD_LKID);
1851*9781SMoriah.Waterland@Sun.COM retval = 0;
1852*9781SMoriah.Waterland@Sun.COM break;
1853*9781SMoriah.Waterland@Sun.COM }
1854*9781SMoriah.Waterland@Sun.COM if (X509_keyid_set1(x509,
1855*9781SMoriah.Waterland@Sun.COM keyid->value.octet_string->data,
1856*9781SMoriah.Waterland@Sun.COM keyid->value.octet_string->length) == 0) {
1857*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1858*9781SMoriah.Waterland@Sun.COM SUNW_R_SET_LKID_ERR);
1859*9781SMoriah.Waterland@Sun.COM retval = 0;
1860*9781SMoriah.Waterland@Sun.COM break;
1861*9781SMoriah.Waterland@Sun.COM }
1862*9781SMoriah.Waterland@Sun.COM }
1863*9781SMoriah.Waterland@Sun.COM
1864*9781SMoriah.Waterland@Sun.COM if (fname != NULL) {
1865*9781SMoriah.Waterland@Sun.COM ASN1_STRING *tmpstr = NULL;
1866*9781SMoriah.Waterland@Sun.COM int len;
1867*9781SMoriah.Waterland@Sun.COM
1868*9781SMoriah.Waterland@Sun.COM if (fname->type != V_ASN1_BMPSTRING) {
1869*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1870*9781SMoriah.Waterland@Sun.COM SUNW_R_BAD_FNAME);
1871*9781SMoriah.Waterland@Sun.COM retval = 0;
1872*9781SMoriah.Waterland@Sun.COM break;
1873*9781SMoriah.Waterland@Sun.COM }
1874*9781SMoriah.Waterland@Sun.COM
1875*9781SMoriah.Waterland@Sun.COM tmpstr = fname->value.asn1_string;
1876*9781SMoriah.Waterland@Sun.COM len = ASN1_STRING_to_UTF8(&data, tmpstr);
1877*9781SMoriah.Waterland@Sun.COM if (len < 0) {
1878*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1879*9781SMoriah.Waterland@Sun.COM SUNW_R_SET_FNAME_ERR);
1880*9781SMoriah.Waterland@Sun.COM retval = 0;
1881*9781SMoriah.Waterland@Sun.COM break;
1882*9781SMoriah.Waterland@Sun.COM }
1883*9781SMoriah.Waterland@Sun.COM
1884*9781SMoriah.Waterland@Sun.COM if (X509_alias_set1(x509, data, len) == 0) {
1885*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1886*9781SMoriah.Waterland@Sun.COM SUNW_R_SET_FNAME_ERR);
1887*9781SMoriah.Waterland@Sun.COM retval = 0;
1888*9781SMoriah.Waterland@Sun.COM break;
1889*9781SMoriah.Waterland@Sun.COM }
1890*9781SMoriah.Waterland@Sun.COM }
1891*9781SMoriah.Waterland@Sun.COM
1892*9781SMoriah.Waterland@Sun.COM if (sk_X509_push(cl, x509) == 0) {
1893*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_MEMORY_FAILURE);
1894*9781SMoriah.Waterland@Sun.COM retval = 0;
1895*9781SMoriah.Waterland@Sun.COM break;
1896*9781SMoriah.Waterland@Sun.COM }
1897*9781SMoriah.Waterland@Sun.COM x509 = NULL;
1898*9781SMoriah.Waterland@Sun.COM break;
1899*9781SMoriah.Waterland@Sun.COM
1900*9781SMoriah.Waterland@Sun.COM case NID_safeContentsBag:
1901*9781SMoriah.Waterland@Sun.COM if (keyid != NULL)
1902*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(keyid);
1903*9781SMoriah.Waterland@Sun.COM if (fname != NULL)
1904*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(fname);
1905*9781SMoriah.Waterland@Sun.COM if (parse_all_bags(bag->value.safes, pass, kl, cl) == 0) {
1906*9781SMoriah.Waterland@Sun.COM /*
1907*9781SMoriah.Waterland@Sun.COM * Error already on stack
1908*9781SMoriah.Waterland@Sun.COM */
1909*9781SMoriah.Waterland@Sun.COM return (0);
1910*9781SMoriah.Waterland@Sun.COM }
1911*9781SMoriah.Waterland@Sun.COM return (1);
1912*9781SMoriah.Waterland@Sun.COM
1913*9781SMoriah.Waterland@Sun.COM default:
1914*9781SMoriah.Waterland@Sun.COM if (keyid != NULL)
1915*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(keyid);
1916*9781SMoriah.Waterland@Sun.COM if (fname != NULL)
1917*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(fname);
1918*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_BAGTYPE);
1919*9781SMoriah.Waterland@Sun.COM return (0);
1920*9781SMoriah.Waterland@Sun.COM }
1921*9781SMoriah.Waterland@Sun.COM
1922*9781SMoriah.Waterland@Sun.COM
1923*9781SMoriah.Waterland@Sun.COM if (pkey != NULL) {
1924*9781SMoriah.Waterland@Sun.COM if (retval != 0 && (keyid != NULL || fname != NULL) &&
1925*9781SMoriah.Waterland@Sun.COM pkey->attributes == NULL) {
1926*9781SMoriah.Waterland@Sun.COM pkey->attributes = sk_X509_ATTRIBUTE_new_null();
1927*9781SMoriah.Waterland@Sun.COM if (pkey->attributes == NULL) {
1928*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1929*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
1930*9781SMoriah.Waterland@Sun.COM retval = 0;
1931*9781SMoriah.Waterland@Sun.COM }
1932*9781SMoriah.Waterland@Sun.COM }
1933*9781SMoriah.Waterland@Sun.COM
1934*9781SMoriah.Waterland@Sun.COM if (retval != 0 && keyid != NULL) {
1935*9781SMoriah.Waterland@Sun.COM attr = type2attrib(keyid, NID_localKeyID);
1936*9781SMoriah.Waterland@Sun.COM if (attr == NULL)
1937*9781SMoriah.Waterland@Sun.COM /*
1938*9781SMoriah.Waterland@Sun.COM * Error already on stack
1939*9781SMoriah.Waterland@Sun.COM */
1940*9781SMoriah.Waterland@Sun.COM retval = 0;
1941*9781SMoriah.Waterland@Sun.COM else {
1942*9781SMoriah.Waterland@Sun.COM keyid = NULL;
1943*9781SMoriah.Waterland@Sun.COM if (sk_X509_ATTRIBUTE_push(pkey->attributes,
1944*9781SMoriah.Waterland@Sun.COM attr) == 0) {
1945*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1946*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
1947*9781SMoriah.Waterland@Sun.COM retval = 0;
1948*9781SMoriah.Waterland@Sun.COM } else {
1949*9781SMoriah.Waterland@Sun.COM attr = NULL;
1950*9781SMoriah.Waterland@Sun.COM }
1951*9781SMoriah.Waterland@Sun.COM }
1952*9781SMoriah.Waterland@Sun.COM }
1953*9781SMoriah.Waterland@Sun.COM
1954*9781SMoriah.Waterland@Sun.COM if (retval != 0 && fname != NULL) {
1955*9781SMoriah.Waterland@Sun.COM attr = type2attrib(fname, NID_friendlyName);
1956*9781SMoriah.Waterland@Sun.COM if (attr == NULL) {
1957*9781SMoriah.Waterland@Sun.COM /*
1958*9781SMoriah.Waterland@Sun.COM * Error already on stack
1959*9781SMoriah.Waterland@Sun.COM */
1960*9781SMoriah.Waterland@Sun.COM retval = 0;
1961*9781SMoriah.Waterland@Sun.COM } else {
1962*9781SMoriah.Waterland@Sun.COM fname = NULL;
1963*9781SMoriah.Waterland@Sun.COM if (sk_X509_ATTRIBUTE_push(pkey->attributes,
1964*9781SMoriah.Waterland@Sun.COM attr) == 0) {
1965*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1966*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
1967*9781SMoriah.Waterland@Sun.COM retval = 0;
1968*9781SMoriah.Waterland@Sun.COM } else {
1969*9781SMoriah.Waterland@Sun.COM attr = NULL;
1970*9781SMoriah.Waterland@Sun.COM }
1971*9781SMoriah.Waterland@Sun.COM }
1972*9781SMoriah.Waterland@Sun.COM }
1973*9781SMoriah.Waterland@Sun.COM
1974*9781SMoriah.Waterland@Sun.COM /* Save the private key */
1975*9781SMoriah.Waterland@Sun.COM if (retval != 0) {
1976*9781SMoriah.Waterland@Sun.COM if (sk_EVP_PKEY_push(kl, pkey) == 0) {
1977*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PARSE_ONE_BAG,
1978*9781SMoriah.Waterland@Sun.COM SUNW_R_MEMORY_FAILURE);
1979*9781SMoriah.Waterland@Sun.COM retval = 0;
1980*9781SMoriah.Waterland@Sun.COM } else {
1981*9781SMoriah.Waterland@Sun.COM pkey = NULL;
1982*9781SMoriah.Waterland@Sun.COM }
1983*9781SMoriah.Waterland@Sun.COM }
1984*9781SMoriah.Waterland@Sun.COM }
1985*9781SMoriah.Waterland@Sun.COM
1986*9781SMoriah.Waterland@Sun.COM if (pkey != NULL) {
1987*9781SMoriah.Waterland@Sun.COM sunw_evp_pkey_free(pkey);
1988*9781SMoriah.Waterland@Sun.COM }
1989*9781SMoriah.Waterland@Sun.COM
1990*9781SMoriah.Waterland@Sun.COM if (x509 != NULL)
1991*9781SMoriah.Waterland@Sun.COM X509_free(x509);
1992*9781SMoriah.Waterland@Sun.COM
1993*9781SMoriah.Waterland@Sun.COM if (keyid != NULL)
1994*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(keyid);
1995*9781SMoriah.Waterland@Sun.COM
1996*9781SMoriah.Waterland@Sun.COM if (fname != NULL)
1997*9781SMoriah.Waterland@Sun.COM ASN1_TYPE_free(fname);
1998*9781SMoriah.Waterland@Sun.COM
1999*9781SMoriah.Waterland@Sun.COM if (attr != NULL)
2000*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE_free(attr);
2001*9781SMoriah.Waterland@Sun.COM
2002*9781SMoriah.Waterland@Sun.COM if (data != NULL)
2003*9781SMoriah.Waterland@Sun.COM OPENSSL_free(data);
2004*9781SMoriah.Waterland@Sun.COM
2005*9781SMoriah.Waterland@Sun.COM if (str != NULL)
2006*9781SMoriah.Waterland@Sun.COM OPENSSL_free(str);
2007*9781SMoriah.Waterland@Sun.COM
2008*9781SMoriah.Waterland@Sun.COM return (retval);
2009*9781SMoriah.Waterland@Sun.COM }
2010*9781SMoriah.Waterland@Sun.COM
2011*9781SMoriah.Waterland@Sun.COM /*
2012*9781SMoriah.Waterland@Sun.COM * This function uses the only function that reads PEM files, regardless of
2013*9781SMoriah.Waterland@Sun.COM * the kinds of information included (private keys, public keys, cert requests,
2014*9781SMoriah.Waterland@Sun.COM * certs). Other interfaces that read files require that the application
2015*9781SMoriah.Waterland@Sun.COM * specifically know what kinds of things to read next, and call different
2016*9781SMoriah.Waterland@Sun.COM * interfaces for the different kinds of entities.
2017*9781SMoriah.Waterland@Sun.COM *
2018*9781SMoriah.Waterland@Sun.COM * There is only one aspect of this function that's a bit problematic.
2019*9781SMoriah.Waterland@Sun.COM * If it finds an encrypted private key, it does not decrypt it. It returns
2020*9781SMoriah.Waterland@Sun.COM * the encrypted data and other information needed to decrypt it. The caller
2021*9781SMoriah.Waterland@Sun.COM * must do the decryption. This function does the decoding.
2022*9781SMoriah.Waterland@Sun.COM */
2023*9781SMoriah.Waterland@Sun.COM static int
pem_info(FILE * fp,pem_password_cb cb,void * userdata,STACK_OF (EVP_PKEY)** pkeys,STACK_OF (X509)** certs)2024*9781SMoriah.Waterland@Sun.COM pem_info(FILE *fp, pem_password_cb cb, void *userdata,
2025*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) **pkeys, STACK_OF(X509) **certs)
2026*9781SMoriah.Waterland@Sun.COM {
2027*9781SMoriah.Waterland@Sun.COM STACK_OF(X509_INFO) *info;
2028*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) *work_kl;
2029*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *work_cl;
2030*9781SMoriah.Waterland@Sun.COM X509_INFO *x;
2031*9781SMoriah.Waterland@Sun.COM int retval = 0;
2032*9781SMoriah.Waterland@Sun.COM int i;
2033*9781SMoriah.Waterland@Sun.COM
2034*9781SMoriah.Waterland@Sun.COM info = PEM_X509_INFO_read(fp, NULL, cb, userdata);
2035*9781SMoriah.Waterland@Sun.COM if (info == NULL) {
2036*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO, SUNW_R_READ_ERR);
2037*9781SMoriah.Waterland@Sun.COM return (-1);
2038*9781SMoriah.Waterland@Sun.COM }
2039*9781SMoriah.Waterland@Sun.COM
2040*9781SMoriah.Waterland@Sun.COM /*
2041*9781SMoriah.Waterland@Sun.COM * Allocate the working stacks for private key(s) and for the cert(s).
2042*9781SMoriah.Waterland@Sun.COM */
2043*9781SMoriah.Waterland@Sun.COM if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) {
2044*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE);
2045*9781SMoriah.Waterland@Sun.COM retval = -1;
2046*9781SMoriah.Waterland@Sun.COM goto cleanup;
2047*9781SMoriah.Waterland@Sun.COM }
2048*9781SMoriah.Waterland@Sun.COM
2049*9781SMoriah.Waterland@Sun.COM if ((work_cl = sk_X509_new_null()) == NULL) {
2050*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE);
2051*9781SMoriah.Waterland@Sun.COM retval = -1;
2052*9781SMoriah.Waterland@Sun.COM goto cleanup;
2053*9781SMoriah.Waterland@Sun.COM }
2054*9781SMoriah.Waterland@Sun.COM
2055*9781SMoriah.Waterland@Sun.COM /*
2056*9781SMoriah.Waterland@Sun.COM * Go through the entries in the info structure.
2057*9781SMoriah.Waterland@Sun.COM */
2058*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_X509_INFO_num(info); i++) {
2059*9781SMoriah.Waterland@Sun.COM x = sk_X509_INFO_value(info, i);
2060*9781SMoriah.Waterland@Sun.COM if (x->x509) {
2061*9781SMoriah.Waterland@Sun.COM if (sk_X509_push(work_cl, x->x509) == 0) {
2062*9781SMoriah.Waterland@Sun.COM retval = -1;
2063*9781SMoriah.Waterland@Sun.COM break;
2064*9781SMoriah.Waterland@Sun.COM }
2065*9781SMoriah.Waterland@Sun.COM x->x509 = NULL;
2066*9781SMoriah.Waterland@Sun.COM }
2067*9781SMoriah.Waterland@Sun.COM if (x->x_pkey != NULL && x->x_pkey->dec_pkey != NULL &&
2068*9781SMoriah.Waterland@Sun.COM (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA ||
2069*9781SMoriah.Waterland@Sun.COM x->x_pkey->dec_pkey->type == EVP_PKEY_DSA)) {
2070*9781SMoriah.Waterland@Sun.COM const uchar_t *p;
2071*9781SMoriah.Waterland@Sun.COM
2072*9781SMoriah.Waterland@Sun.COM /*
2073*9781SMoriah.Waterland@Sun.COM * If the key was encrypted, PEM_X509_INFO_read does
2074*9781SMoriah.Waterland@Sun.COM * not decrypt it. If that is the case, the 'enc_pkey'
2075*9781SMoriah.Waterland@Sun.COM * field is set to point to the unencrypted key data.
2076*9781SMoriah.Waterland@Sun.COM * Go through the additional steps to decode it before
2077*9781SMoriah.Waterland@Sun.COM * going on.
2078*9781SMoriah.Waterland@Sun.COM */
2079*9781SMoriah.Waterland@Sun.COM if (x->x_pkey->enc_pkey != NULL) {
2080*9781SMoriah.Waterland@Sun.COM
2081*9781SMoriah.Waterland@Sun.COM if (PEM_do_header(&x->enc_cipher,
2082*9781SMoriah.Waterland@Sun.COM (uchar_t *)x->enc_data,
2083*9781SMoriah.Waterland@Sun.COM (long *)&x->enc_len,
2084*9781SMoriah.Waterland@Sun.COM cb, userdata) == 0) {
2085*9781SMoriah.Waterland@Sun.COM if (ERR_GET_REASON(ERR_peek_error()) ==
2086*9781SMoriah.Waterland@Sun.COM PEM_R_BAD_PASSWORD_READ) {
2087*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO,
2088*9781SMoriah.Waterland@Sun.COM SUNW_R_PASSWORD_ERR);
2089*9781SMoriah.Waterland@Sun.COM } else {
2090*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO,
2091*9781SMoriah.Waterland@Sun.COM SUNW_R_PKEY_READ_ERR);
2092*9781SMoriah.Waterland@Sun.COM }
2093*9781SMoriah.Waterland@Sun.COM retval = -1;
2094*9781SMoriah.Waterland@Sun.COM break;
2095*9781SMoriah.Waterland@Sun.COM }
2096*9781SMoriah.Waterland@Sun.COM if (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA) {
2097*9781SMoriah.Waterland@Sun.COM RSA **pp;
2098*9781SMoriah.Waterland@Sun.COM
2099*9781SMoriah.Waterland@Sun.COM pp = &(x->x_pkey->dec_pkey->pkey.rsa);
2100*9781SMoriah.Waterland@Sun.COM p = (uchar_t *)x->enc_data;
2101*9781SMoriah.Waterland@Sun.COM if (d2i_RSAPrivateKey(pp, &p,
2102*9781SMoriah.Waterland@Sun.COM x->enc_len) == NULL) {
2103*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO,
2104*9781SMoriah.Waterland@Sun.COM SUNW_R_PKEY_READ_ERR);
2105*9781SMoriah.Waterland@Sun.COM retval = -1;
2106*9781SMoriah.Waterland@Sun.COM break;
2107*9781SMoriah.Waterland@Sun.COM }
2108*9781SMoriah.Waterland@Sun.COM } else {
2109*9781SMoriah.Waterland@Sun.COM DSA **pp;
2110*9781SMoriah.Waterland@Sun.COM
2111*9781SMoriah.Waterland@Sun.COM pp = &(x->x_pkey->dec_pkey->pkey.dsa);
2112*9781SMoriah.Waterland@Sun.COM p = (uchar_t *)x->enc_data;
2113*9781SMoriah.Waterland@Sun.COM if (d2i_DSAPrivateKey(pp, &p,
2114*9781SMoriah.Waterland@Sun.COM x->enc_len) == NULL) {
2115*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO,
2116*9781SMoriah.Waterland@Sun.COM SUNW_R_PKEY_READ_ERR);
2117*9781SMoriah.Waterland@Sun.COM retval = -1;
2118*9781SMoriah.Waterland@Sun.COM break;
2119*9781SMoriah.Waterland@Sun.COM }
2120*9781SMoriah.Waterland@Sun.COM }
2121*9781SMoriah.Waterland@Sun.COM }
2122*9781SMoriah.Waterland@Sun.COM
2123*9781SMoriah.Waterland@Sun.COM /* Save the key. */
2124*9781SMoriah.Waterland@Sun.COM retval = sk_EVP_PKEY_push(work_kl, x->x_pkey->dec_pkey);
2125*9781SMoriah.Waterland@Sun.COM if (retval == 0) {
2126*9781SMoriah.Waterland@Sun.COM retval = -1;
2127*9781SMoriah.Waterland@Sun.COM break;
2128*9781SMoriah.Waterland@Sun.COM }
2129*9781SMoriah.Waterland@Sun.COM x->x_pkey->dec_pkey = NULL;
2130*9781SMoriah.Waterland@Sun.COM } else if (x->x_pkey != NULL) {
2131*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_PEM_INFO, SUNW_R_BAD_PKEYTYPE);
2132*9781SMoriah.Waterland@Sun.COM retval = -1;
2133*9781SMoriah.Waterland@Sun.COM break;
2134*9781SMoriah.Waterland@Sun.COM }
2135*9781SMoriah.Waterland@Sun.COM }
2136*9781SMoriah.Waterland@Sun.COM if (retval == -1)
2137*9781SMoriah.Waterland@Sun.COM goto cleanup;
2138*9781SMoriah.Waterland@Sun.COM
2139*9781SMoriah.Waterland@Sun.COM /* If error occurs, then error already on stack */
2140*9781SMoriah.Waterland@Sun.COM retval = set_results(pkeys, &work_kl, certs, &work_cl, NULL, NULL,
2141*9781SMoriah.Waterland@Sun.COM NULL, NULL);
2142*9781SMoriah.Waterland@Sun.COM
2143*9781SMoriah.Waterland@Sun.COM cleanup:
2144*9781SMoriah.Waterland@Sun.COM if (work_kl != NULL) {
2145*9781SMoriah.Waterland@Sun.COM sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free);
2146*9781SMoriah.Waterland@Sun.COM }
2147*9781SMoriah.Waterland@Sun.COM if (work_cl != NULL)
2148*9781SMoriah.Waterland@Sun.COM sk_X509_pop_free(work_cl, X509_free);
2149*9781SMoriah.Waterland@Sun.COM
2150*9781SMoriah.Waterland@Sun.COM sk_X509_INFO_pop_free(info, X509_INFO_free);
2151*9781SMoriah.Waterland@Sun.COM
2152*9781SMoriah.Waterland@Sun.COM return (retval);
2153*9781SMoriah.Waterland@Sun.COM }
2154*9781SMoriah.Waterland@Sun.COM
2155*9781SMoriah.Waterland@Sun.COM /*
2156*9781SMoriah.Waterland@Sun.COM * sunw_append_keys - Given two stacks of private keys, remove the keys from
2157*9781SMoriah.Waterland@Sun.COM * the second stack and append them to the first. Both stacks must exist
2158*9781SMoriah.Waterland@Sun.COM * at time of call.
2159*9781SMoriah.Waterland@Sun.COM *
2160*9781SMoriah.Waterland@Sun.COM * Arguments:
2161*9781SMoriah.Waterland@Sun.COM * dst - the stack to receive the keys from 'src'
2162*9781SMoriah.Waterland@Sun.COM * src - the stack whose keys are to be moved.
2163*9781SMoriah.Waterland@Sun.COM *
2164*9781SMoriah.Waterland@Sun.COM * Returns:
2165*9781SMoriah.Waterland@Sun.COM * -1 - An error occurred. The error status is set.
2166*9781SMoriah.Waterland@Sun.COM * >= 0 - The number of keys that were copied.
2167*9781SMoriah.Waterland@Sun.COM */
2168*9781SMoriah.Waterland@Sun.COM static int
sunw_append_keys(STACK_OF (EVP_PKEY)* dst,STACK_OF (EVP_PKEY)* src)2169*9781SMoriah.Waterland@Sun.COM sunw_append_keys(STACK_OF(EVP_PKEY) *dst, STACK_OF(EVP_PKEY) *src)
2170*9781SMoriah.Waterland@Sun.COM {
2171*9781SMoriah.Waterland@Sun.COM EVP_PKEY *tmpk;
2172*9781SMoriah.Waterland@Sun.COM int count = 0;
2173*9781SMoriah.Waterland@Sun.COM
2174*9781SMoriah.Waterland@Sun.COM while (sk_EVP_PKEY_num(src) > 0) {
2175*9781SMoriah.Waterland@Sun.COM tmpk = sk_EVP_PKEY_delete(src, 0);
2176*9781SMoriah.Waterland@Sun.COM if (sk_EVP_PKEY_push(dst, tmpk) == 0) {
2177*9781SMoriah.Waterland@Sun.COM sunw_evp_pkey_free(tmpk);
2178*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_APPEND_KEYS, SUNW_R_MEMORY_FAILURE);
2179*9781SMoriah.Waterland@Sun.COM return (-1);
2180*9781SMoriah.Waterland@Sun.COM }
2181*9781SMoriah.Waterland@Sun.COM count ++;
2182*9781SMoriah.Waterland@Sun.COM }
2183*9781SMoriah.Waterland@Sun.COM
2184*9781SMoriah.Waterland@Sun.COM return (count);
2185*9781SMoriah.Waterland@Sun.COM }
2186*9781SMoriah.Waterland@Sun.COM
2187*9781SMoriah.Waterland@Sun.COM /*
2188*9781SMoriah.Waterland@Sun.COM * move_certs - Given two stacks of certs, remove the certs from
2189*9781SMoriah.Waterland@Sun.COM * the second stack and append them to the first.
2190*9781SMoriah.Waterland@Sun.COM *
2191*9781SMoriah.Waterland@Sun.COM * Arguments:
2192*9781SMoriah.Waterland@Sun.COM * dst - the stack to receive the certs from 'src'
2193*9781SMoriah.Waterland@Sun.COM * src - the stack whose certs are to be moved.
2194*9781SMoriah.Waterland@Sun.COM *
2195*9781SMoriah.Waterland@Sun.COM * Returns:
2196*9781SMoriah.Waterland@Sun.COM * -1 - An error occurred. The error status is set.
2197*9781SMoriah.Waterland@Sun.COM * >= 0 - The number of certs that were copied.
2198*9781SMoriah.Waterland@Sun.COM */
2199*9781SMoriah.Waterland@Sun.COM static int
move_certs(STACK_OF (X509)* dst,STACK_OF (X509)* src)2200*9781SMoriah.Waterland@Sun.COM move_certs(STACK_OF(X509) *dst, STACK_OF(X509) *src)
2201*9781SMoriah.Waterland@Sun.COM {
2202*9781SMoriah.Waterland@Sun.COM X509 *tmpc;
2203*9781SMoriah.Waterland@Sun.COM int count = 0;
2204*9781SMoriah.Waterland@Sun.COM
2205*9781SMoriah.Waterland@Sun.COM while (sk_X509_num(src) > 0) {
2206*9781SMoriah.Waterland@Sun.COM tmpc = sk_X509_delete(src, 0);
2207*9781SMoriah.Waterland@Sun.COM if (sk_X509_push(dst, tmpc) == 0) {
2208*9781SMoriah.Waterland@Sun.COM X509_free(tmpc);
2209*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_MOVE_CERTS, SUNW_R_MEMORY_FAILURE);
2210*9781SMoriah.Waterland@Sun.COM return (-1);
2211*9781SMoriah.Waterland@Sun.COM }
2212*9781SMoriah.Waterland@Sun.COM count++;
2213*9781SMoriah.Waterland@Sun.COM }
2214*9781SMoriah.Waterland@Sun.COM
2215*9781SMoriah.Waterland@Sun.COM return (count);
2216*9781SMoriah.Waterland@Sun.COM }
2217*9781SMoriah.Waterland@Sun.COM
2218*9781SMoriah.Waterland@Sun.COM /*
2219*9781SMoriah.Waterland@Sun.COM * get_key_cert - Get a cert and its matching key from the stacks of certs
2220*9781SMoriah.Waterland@Sun.COM * and keys. They are removed from the stacks.
2221*9781SMoriah.Waterland@Sun.COM *
2222*9781SMoriah.Waterland@Sun.COM * Arguments:
2223*9781SMoriah.Waterland@Sun.COM * n - Offset of the entries to return.
2224*9781SMoriah.Waterland@Sun.COM * kl - Points to a stack of private keys that matches the list of
2225*9781SMoriah.Waterland@Sun.COM * certs below.
2226*9781SMoriah.Waterland@Sun.COM * pkey - Points at location where the address of the matching private
2227*9781SMoriah.Waterland@Sun.COM * key will be stored.
2228*9781SMoriah.Waterland@Sun.COM * cl - Points to a stack of client certs with matching private keys.
2229*9781SMoriah.Waterland@Sun.COM * cert - Points to locaiton where the address of the matching client cert
2230*9781SMoriah.Waterland@Sun.COM * will be returned
2231*9781SMoriah.Waterland@Sun.COM *
2232*9781SMoriah.Waterland@Sun.COM * The assumption is that the stacks of keys and certs contain key/cert pairs,
2233*9781SMoriah.Waterland@Sun.COM * with entries in the same order and hence at the same offset. Provided
2234*9781SMoriah.Waterland@Sun.COM * the key and cert selected match, each will be removed from its stack and
2235*9781SMoriah.Waterland@Sun.COM * returned.
2236*9781SMoriah.Waterland@Sun.COM *
2237*9781SMoriah.Waterland@Sun.COM * A stack of certs can be passed in without a stack of private keys, and vise
2238*9781SMoriah.Waterland@Sun.COM * versa. In that case, the indicated key/cert will be returned.
2239*9781SMoriah.Waterland@Sun.COM *
2240*9781SMoriah.Waterland@Sun.COM * Returns:
2241*9781SMoriah.Waterland@Sun.COM * 0 - No matches were found.
2242*9781SMoriah.Waterland@Sun.COM * > 0 - Bits set based on FOUND_* definitions, indicating what is returned.
2243*9781SMoriah.Waterland@Sun.COM * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
2244*9781SMoriah.Waterland@Sun.COM */
2245*9781SMoriah.Waterland@Sun.COM static int
get_key_cert(int n,STACK_OF (EVP_PKEY)* kl,EVP_PKEY ** pkey,STACK_OF (X509)* cl,X509 ** cert)2246*9781SMoriah.Waterland@Sun.COM get_key_cert(int n, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, STACK_OF(X509) *cl,
2247*9781SMoriah.Waterland@Sun.COM X509 **cert)
2248*9781SMoriah.Waterland@Sun.COM {
2249*9781SMoriah.Waterland@Sun.COM int retval = 0;
2250*9781SMoriah.Waterland@Sun.COM int nk;
2251*9781SMoriah.Waterland@Sun.COM int nc;
2252*9781SMoriah.Waterland@Sun.COM
2253*9781SMoriah.Waterland@Sun.COM nk = (kl != NULL) ? sk_EVP_PKEY_num(kl) : 0;
2254*9781SMoriah.Waterland@Sun.COM nc = (cl != NULL) ? sk_X509_num(cl) : 0;
2255*9781SMoriah.Waterland@Sun.COM
2256*9781SMoriah.Waterland@Sun.COM if (pkey != NULL && *pkey == NULL) {
2257*9781SMoriah.Waterland@Sun.COM if (nk > 0 && n >= 0 || n < nk) {
2258*9781SMoriah.Waterland@Sun.COM *pkey = sk_EVP_PKEY_delete(kl, n);
2259*9781SMoriah.Waterland@Sun.COM if (*pkey != NULL)
2260*9781SMoriah.Waterland@Sun.COM retval |= FOUND_PKEY;
2261*9781SMoriah.Waterland@Sun.COM }
2262*9781SMoriah.Waterland@Sun.COM }
2263*9781SMoriah.Waterland@Sun.COM
2264*9781SMoriah.Waterland@Sun.COM if (cert != NULL && *cert == NULL) {
2265*9781SMoriah.Waterland@Sun.COM if (nc > 0 && n >= 0 && n < nc) {
2266*9781SMoriah.Waterland@Sun.COM *cert = sk_X509_delete(cl, n);
2267*9781SMoriah.Waterland@Sun.COM if (*cert != NULL)
2268*9781SMoriah.Waterland@Sun.COM retval |= FOUND_CERT;
2269*9781SMoriah.Waterland@Sun.COM }
2270*9781SMoriah.Waterland@Sun.COM }
2271*9781SMoriah.Waterland@Sun.COM
2272*9781SMoriah.Waterland@Sun.COM return (retval);
2273*9781SMoriah.Waterland@Sun.COM }
2274*9781SMoriah.Waterland@Sun.COM
2275*9781SMoriah.Waterland@Sun.COM
2276*9781SMoriah.Waterland@Sun.COM /*
2277*9781SMoriah.Waterland@Sun.COM * asc2bmpstring - Convert a regular C ASCII string to an ASn1_STRING in
2278*9781SMoriah.Waterland@Sun.COM * ASN1_BMPSTRING format.
2279*9781SMoriah.Waterland@Sun.COM *
2280*9781SMoriah.Waterland@Sun.COM * Arguments:
2281*9781SMoriah.Waterland@Sun.COM * str - String to be convered.
2282*9781SMoriah.Waterland@Sun.COM * len - Length of the string.
2283*9781SMoriah.Waterland@Sun.COM *
2284*9781SMoriah.Waterland@Sun.COM * Returns:
2285*9781SMoriah.Waterland@Sun.COM * == NULL - An error occurred. Error information (accessible by
2286*9781SMoriah.Waterland@Sun.COM * ERR_get_error()) is set.
2287*9781SMoriah.Waterland@Sun.COM * != NULL - Points to an ASN1_BMPSTRING structure with the converted
2288*9781SMoriah.Waterland@Sun.COM * string as a value.
2289*9781SMoriah.Waterland@Sun.COM */
2290*9781SMoriah.Waterland@Sun.COM static ASN1_BMPSTRING *
asc2bmpstring(const char * str,int len)2291*9781SMoriah.Waterland@Sun.COM asc2bmpstring(const char *str, int len)
2292*9781SMoriah.Waterland@Sun.COM {
2293*9781SMoriah.Waterland@Sun.COM ASN1_BMPSTRING *bmp = NULL;
2294*9781SMoriah.Waterland@Sun.COM uchar_t *uni = NULL;
2295*9781SMoriah.Waterland@Sun.COM int unilen;
2296*9781SMoriah.Waterland@Sun.COM
2297*9781SMoriah.Waterland@Sun.COM /* Convert the character to the bmp format. */
2298*9781SMoriah.Waterland@Sun.COM if (asc2uni(str, len, &uni, &unilen) == 0) {
2299*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
2300*9781SMoriah.Waterland@Sun.COM return (NULL);
2301*9781SMoriah.Waterland@Sun.COM }
2302*9781SMoriah.Waterland@Sun.COM
2303*9781SMoriah.Waterland@Sun.COM /*
2304*9781SMoriah.Waterland@Sun.COM * Adjust for possible pair of NULL bytes at the end because
2305*9781SMoriah.Waterland@Sun.COM * asc2uni() returns a doubly null terminated string.
2306*9781SMoriah.Waterland@Sun.COM */
2307*9781SMoriah.Waterland@Sun.COM if (uni[unilen - 1] == '\0' && uni[unilen - 2] == '\0')
2308*9781SMoriah.Waterland@Sun.COM unilen -= 2;
2309*9781SMoriah.Waterland@Sun.COM
2310*9781SMoriah.Waterland@Sun.COM /* Construct comparison string with correct format */
2311*9781SMoriah.Waterland@Sun.COM bmp = M_ASN1_BMPSTRING_new();
2312*9781SMoriah.Waterland@Sun.COM if (bmp == NULL) {
2313*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE);
2314*9781SMoriah.Waterland@Sun.COM OPENSSL_free(uni);
2315*9781SMoriah.Waterland@Sun.COM return (NULL);
2316*9781SMoriah.Waterland@Sun.COM }
2317*9781SMoriah.Waterland@Sun.COM
2318*9781SMoriah.Waterland@Sun.COM bmp->data = uni;
2319*9781SMoriah.Waterland@Sun.COM bmp->length = unilen;
2320*9781SMoriah.Waterland@Sun.COM
2321*9781SMoriah.Waterland@Sun.COM return (bmp);
2322*9781SMoriah.Waterland@Sun.COM }
2323*9781SMoriah.Waterland@Sun.COM
2324*9781SMoriah.Waterland@Sun.COM /*
2325*9781SMoriah.Waterland@Sun.COM * utf82ascstr - Convert a UTF8STRING string to a regular C ASCII string.
2326*9781SMoriah.Waterland@Sun.COM * This goes through an intermediate step with a ASN1_STRING type of
2327*9781SMoriah.Waterland@Sun.COM * IA5STRING (International Alphabet 5, which is the same as ASCII).
2328*9781SMoriah.Waterland@Sun.COM *
2329*9781SMoriah.Waterland@Sun.COM * Arguments:
2330*9781SMoriah.Waterland@Sun.COM * str - UTF8STRING to be converted.
2331*9781SMoriah.Waterland@Sun.COM *
2332*9781SMoriah.Waterland@Sun.COM * Returns:
2333*9781SMoriah.Waterland@Sun.COM * == NULL - An error occurred. Error information (accessible by
2334*9781SMoriah.Waterland@Sun.COM * ERR_get_error()) is set.
2335*9781SMoriah.Waterland@Sun.COM * != NULL - Points to a NULL-termianted ASCII string. The caller must
2336*9781SMoriah.Waterland@Sun.COM * free it.
2337*9781SMoriah.Waterland@Sun.COM */
2338*9781SMoriah.Waterland@Sun.COM static uchar_t *
utf82ascstr(ASN1_UTF8STRING * ustr)2339*9781SMoriah.Waterland@Sun.COM utf82ascstr(ASN1_UTF8STRING *ustr)
2340*9781SMoriah.Waterland@Sun.COM {
2341*9781SMoriah.Waterland@Sun.COM ASN1_STRING tmpstr;
2342*9781SMoriah.Waterland@Sun.COM ASN1_STRING *astr = &tmpstr;
2343*9781SMoriah.Waterland@Sun.COM uchar_t *retstr = NULL;
2344*9781SMoriah.Waterland@Sun.COM int mbflag;
2345*9781SMoriah.Waterland@Sun.COM int ret;
2346*9781SMoriah.Waterland@Sun.COM
2347*9781SMoriah.Waterland@Sun.COM if (ustr == NULL || ustr->type != V_ASN1_UTF8STRING) {
2348*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_INVALID_ARG);
2349*9781SMoriah.Waterland@Sun.COM return (NULL);
2350*9781SMoriah.Waterland@Sun.COM }
2351*9781SMoriah.Waterland@Sun.COM
2352*9781SMoriah.Waterland@Sun.COM mbflag = MBSTRING_ASC;
2353*9781SMoriah.Waterland@Sun.COM tmpstr.data = NULL;
2354*9781SMoriah.Waterland@Sun.COM tmpstr.length = 0;
2355*9781SMoriah.Waterland@Sun.COM
2356*9781SMoriah.Waterland@Sun.COM ret = ASN1_mbstring_copy(&astr, ustr->data, ustr->length, mbflag,
2357*9781SMoriah.Waterland@Sun.COM B_ASN1_IA5STRING);
2358*9781SMoriah.Waterland@Sun.COM if (ret < 0) {
2359*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_STR_CONVERT_ERR);
2360*9781SMoriah.Waterland@Sun.COM return (NULL);
2361*9781SMoriah.Waterland@Sun.COM }
2362*9781SMoriah.Waterland@Sun.COM
2363*9781SMoriah.Waterland@Sun.COM retstr = OPENSSL_malloc(astr->length + 1);
2364*9781SMoriah.Waterland@Sun.COM if (retstr == NULL) {
2365*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_MEMORY_FAILURE);
2366*9781SMoriah.Waterland@Sun.COM return (NULL);
2367*9781SMoriah.Waterland@Sun.COM }
2368*9781SMoriah.Waterland@Sun.COM
2369*9781SMoriah.Waterland@Sun.COM (void) memcpy(retstr, astr->data, astr->length);
2370*9781SMoriah.Waterland@Sun.COM retstr[astr->length] = '\0';
2371*9781SMoriah.Waterland@Sun.COM OPENSSL_free(astr->data);
2372*9781SMoriah.Waterland@Sun.COM
2373*9781SMoriah.Waterland@Sun.COM return (retstr);
2374*9781SMoriah.Waterland@Sun.COM }
2375*9781SMoriah.Waterland@Sun.COM
2376*9781SMoriah.Waterland@Sun.COM
2377*9781SMoriah.Waterland@Sun.COM /*
2378*9781SMoriah.Waterland@Sun.COM * type2attrib - Given a ASN1_TYPE, return a X509_ATTRIBUTE of the type
2379*9781SMoriah.Waterland@Sun.COM * specified by the given NID.
2380*9781SMoriah.Waterland@Sun.COM *
2381*9781SMoriah.Waterland@Sun.COM * Arguments:
2382*9781SMoriah.Waterland@Sun.COM * ty - Type structure to be made into an attribute
2383*9781SMoriah.Waterland@Sun.COM * nid - NID of the attribute
2384*9781SMoriah.Waterland@Sun.COM *
2385*9781SMoriah.Waterland@Sun.COM * Returns:
2386*9781SMoriah.Waterland@Sun.COM * NULL An error occurred.
2387*9781SMoriah.Waterland@Sun.COM * != NULL An X509_ATTRIBUTE structure.
2388*9781SMoriah.Waterland@Sun.COM */
2389*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *
type2attrib(ASN1_TYPE * ty,int nid)2390*9781SMoriah.Waterland@Sun.COM type2attrib(ASN1_TYPE *ty, int nid)
2391*9781SMoriah.Waterland@Sun.COM {
2392*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *a;
2393*9781SMoriah.Waterland@Sun.COM
2394*9781SMoriah.Waterland@Sun.COM if ((a = X509_ATTRIBUTE_new()) == NULL ||
2395*9781SMoriah.Waterland@Sun.COM (a->value.set = sk_ASN1_TYPE_new_null()) == NULL ||
2396*9781SMoriah.Waterland@Sun.COM sk_ASN1_TYPE_push(a->value.set, ty) == 0) {
2397*9781SMoriah.Waterland@Sun.COM if (a != NULL)
2398*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE_free(a);
2399*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_TYPE2ATTRIB, SUNW_R_MEMORY_FAILURE);
2400*9781SMoriah.Waterland@Sun.COM return (NULL);
2401*9781SMoriah.Waterland@Sun.COM }
2402*9781SMoriah.Waterland@Sun.COM a->single = 0;
2403*9781SMoriah.Waterland@Sun.COM a->object = OBJ_nid2obj(nid);
2404*9781SMoriah.Waterland@Sun.COM
2405*9781SMoriah.Waterland@Sun.COM return (a);
2406*9781SMoriah.Waterland@Sun.COM }
2407*9781SMoriah.Waterland@Sun.COM
2408*9781SMoriah.Waterland@Sun.COM /*
2409*9781SMoriah.Waterland@Sun.COM * attrib2type - Given a X509_ATTRIBUTE, return pointer to the ASN1_TYPE
2410*9781SMoriah.Waterland@Sun.COM * component
2411*9781SMoriah.Waterland@Sun.COM *
2412*9781SMoriah.Waterland@Sun.COM * Arguments:
2413*9781SMoriah.Waterland@Sun.COM * attr - Attribute structure containing a type.
2414*9781SMoriah.Waterland@Sun.COM *
2415*9781SMoriah.Waterland@Sun.COM * Returns:
2416*9781SMoriah.Waterland@Sun.COM * NULL An error occurred.
2417*9781SMoriah.Waterland@Sun.COM * != NULL An ASN1_TYPE structure.
2418*9781SMoriah.Waterland@Sun.COM */
2419*9781SMoriah.Waterland@Sun.COM static ASN1_TYPE *
attrib2type(X509_ATTRIBUTE * attr)2420*9781SMoriah.Waterland@Sun.COM attrib2type(X509_ATTRIBUTE *attr)
2421*9781SMoriah.Waterland@Sun.COM {
2422*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *ty = NULL;
2423*9781SMoriah.Waterland@Sun.COM
2424*9781SMoriah.Waterland@Sun.COM if (attr == NULL || attr->single == 1)
2425*9781SMoriah.Waterland@Sun.COM return (NULL);
2426*9781SMoriah.Waterland@Sun.COM
2427*9781SMoriah.Waterland@Sun.COM if (sk_ASN1_TYPE_num(attr->value.set) > 0)
2428*9781SMoriah.Waterland@Sun.COM ty = sk_ASN1_TYPE_value(attr->value.set, 0);
2429*9781SMoriah.Waterland@Sun.COM
2430*9781SMoriah.Waterland@Sun.COM return (ty);
2431*9781SMoriah.Waterland@Sun.COM }
2432*9781SMoriah.Waterland@Sun.COM
2433*9781SMoriah.Waterland@Sun.COM /*
2434*9781SMoriah.Waterland@Sun.COM * find_attr_by_nid - Given a ASN1_TYPE, return the offset of a X509_ATTRIBUTE
2435*9781SMoriah.Waterland@Sun.COM * of the type specified by the given NID.
2436*9781SMoriah.Waterland@Sun.COM *
2437*9781SMoriah.Waterland@Sun.COM * Arguments:
2438*9781SMoriah.Waterland@Sun.COM * attrs - Stack of attributes to search
2439*9781SMoriah.Waterland@Sun.COM * nid - NID of the attribute being searched for
2440*9781SMoriah.Waterland@Sun.COM *
2441*9781SMoriah.Waterland@Sun.COM * Returns:
2442*9781SMoriah.Waterland@Sun.COM * -1 None found
2443*9781SMoriah.Waterland@Sun.COM * != -1 Offset of the matching attribute.
2444*9781SMoriah.Waterland@Sun.COM */
2445*9781SMoriah.Waterland@Sun.COM static int
find_attr_by_nid(STACK_OF (X509_ATTRIBUTE)* attrs,int nid)2446*9781SMoriah.Waterland@Sun.COM find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
2447*9781SMoriah.Waterland@Sun.COM {
2448*9781SMoriah.Waterland@Sun.COM X509_ATTRIBUTE *a;
2449*9781SMoriah.Waterland@Sun.COM int i;
2450*9781SMoriah.Waterland@Sun.COM
2451*9781SMoriah.Waterland@Sun.COM if (attrs == NULL)
2452*9781SMoriah.Waterland@Sun.COM return (-1);
2453*9781SMoriah.Waterland@Sun.COM
2454*9781SMoriah.Waterland@Sun.COM for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
2455*9781SMoriah.Waterland@Sun.COM a = sk_X509_ATTRIBUTE_value(attrs, i);
2456*9781SMoriah.Waterland@Sun.COM if (OBJ_obj2nid(a->object) == nid)
2457*9781SMoriah.Waterland@Sun.COM return (i);
2458*9781SMoriah.Waterland@Sun.COM }
2459*9781SMoriah.Waterland@Sun.COM return (-1);
2460*9781SMoriah.Waterland@Sun.COM }
2461*9781SMoriah.Waterland@Sun.COM
2462*9781SMoriah.Waterland@Sun.COM /*
2463*9781SMoriah.Waterland@Sun.COM * Called by our PKCS12 code to read our function and error codes
2464*9781SMoriah.Waterland@Sun.COM * into memory so that the OpenSSL framework can retrieve them.
2465*9781SMoriah.Waterland@Sun.COM */
2466*9781SMoriah.Waterland@Sun.COM void
ERR_load_SUNW_strings(void)2467*9781SMoriah.Waterland@Sun.COM ERR_load_SUNW_strings(void)
2468*9781SMoriah.Waterland@Sun.COM {
2469*9781SMoriah.Waterland@Sun.COM assert(SUNW_lib_error_code == 0);
2470*9781SMoriah.Waterland@Sun.COM #ifndef OPENSSL_NO_ERR
2471*9781SMoriah.Waterland@Sun.COM /*
2472*9781SMoriah.Waterland@Sun.COM * Have OpenSSL provide us with a unique ID.
2473*9781SMoriah.Waterland@Sun.COM */
2474*9781SMoriah.Waterland@Sun.COM SUNW_lib_error_code = ERR_get_next_error_library();
2475*9781SMoriah.Waterland@Sun.COM
2476*9781SMoriah.Waterland@Sun.COM ERR_load_strings(SUNW_lib_error_code, SUNW_str_functs);
2477*9781SMoriah.Waterland@Sun.COM ERR_load_strings(SUNW_lib_error_code, SUNW_str_reasons);
2478*9781SMoriah.Waterland@Sun.COM
2479*9781SMoriah.Waterland@Sun.COM SUNW_lib_name->error = ERR_PACK(SUNW_lib_error_code, 0, 0);
2480*9781SMoriah.Waterland@Sun.COM ERR_load_strings(0, SUNW_lib_name);
2481*9781SMoriah.Waterland@Sun.COM #endif
2482*9781SMoriah.Waterland@Sun.COM }
2483*9781SMoriah.Waterland@Sun.COM
2484*9781SMoriah.Waterland@Sun.COM /*
2485*9781SMoriah.Waterland@Sun.COM * The SUNWerr macro resolves to this routine. So when we need
2486*9781SMoriah.Waterland@Sun.COM * to push an error, this routine does it for us. Notice that
2487*9781SMoriah.Waterland@Sun.COM * the SUNWerr macro provides a filename and line #.
2488*9781SMoriah.Waterland@Sun.COM */
2489*9781SMoriah.Waterland@Sun.COM void
ERR_SUNW_error(int function,int reason,char * file,int line)2490*9781SMoriah.Waterland@Sun.COM ERR_SUNW_error(int function, int reason, char *file, int line)
2491*9781SMoriah.Waterland@Sun.COM {
2492*9781SMoriah.Waterland@Sun.COM assert(SUNW_lib_error_code != 0);
2493*9781SMoriah.Waterland@Sun.COM #ifndef OPENSSL_NO_ERR
2494*9781SMoriah.Waterland@Sun.COM ERR_PUT_error(SUNW_lib_error_code, function, reason, file, line);
2495*9781SMoriah.Waterland@Sun.COM #endif
2496*9781SMoriah.Waterland@Sun.COM }
2497*9781SMoriah.Waterland@Sun.COM
2498*9781SMoriah.Waterland@Sun.COM /*
2499*9781SMoriah.Waterland@Sun.COM * check_time - Given an indication of the which time(s) to check, check
2500*9781SMoriah.Waterland@Sun.COM * that time or those times against the current time and return the
2501*9781SMoriah.Waterland@Sun.COM * relationship.
2502*9781SMoriah.Waterland@Sun.COM *
2503*9781SMoriah.Waterland@Sun.COM * Arguments:
2504*9781SMoriah.Waterland@Sun.COM * chkwhat - What kind of check to do.
2505*9781SMoriah.Waterland@Sun.COM * cert - The cert to check.
2506*9781SMoriah.Waterland@Sun.COM *
2507*9781SMoriah.Waterland@Sun.COM * Returns:
2508*9781SMoriah.Waterland@Sun.COM * CHKERR_* values.
2509*9781SMoriah.Waterland@Sun.COM */
2510*9781SMoriah.Waterland@Sun.COM static chk_errs_t
check_time(chk_actions_t chkwhat,X509 * cert)2511*9781SMoriah.Waterland@Sun.COM check_time(chk_actions_t chkwhat, X509 *cert)
2512*9781SMoriah.Waterland@Sun.COM {
2513*9781SMoriah.Waterland@Sun.COM int i;
2514*9781SMoriah.Waterland@Sun.COM
2515*9781SMoriah.Waterland@Sun.COM if (chkwhat == CHK_NOT_BEFORE || chkwhat == CHK_BOTH) {
2516*9781SMoriah.Waterland@Sun.COM i = X509_cmp_time(X509_get_notBefore(cert), NULL);
2517*9781SMoriah.Waterland@Sun.COM if (i == 0)
2518*9781SMoriah.Waterland@Sun.COM return (CHKERR_TIME_BEFORE_BAD);
2519*9781SMoriah.Waterland@Sun.COM if (i > 0)
2520*9781SMoriah.Waterland@Sun.COM return (CHKERR_TIME_IS_BEFORE);
2521*9781SMoriah.Waterland@Sun.COM
2522*9781SMoriah.Waterland@Sun.COM /* The current time is after the 'not before' time */
2523*9781SMoriah.Waterland@Sun.COM }
2524*9781SMoriah.Waterland@Sun.COM
2525*9781SMoriah.Waterland@Sun.COM if (chkwhat == CHK_NOT_AFTER || chkwhat == CHK_BOTH) {
2526*9781SMoriah.Waterland@Sun.COM i = X509_cmp_time(X509_get_notAfter(cert), NULL);
2527*9781SMoriah.Waterland@Sun.COM if (i == 0)
2528*9781SMoriah.Waterland@Sun.COM return (CHKERR_TIME_AFTER_BAD);
2529*9781SMoriah.Waterland@Sun.COM if (i < 0)
2530*9781SMoriah.Waterland@Sun.COM return (CHKERR_TIME_HAS_EXPIRED);
2531*9781SMoriah.Waterland@Sun.COM }
2532*9781SMoriah.Waterland@Sun.COM
2533*9781SMoriah.Waterland@Sun.COM return (CHKERR_TIME_OK);
2534*9781SMoriah.Waterland@Sun.COM }
2535*9781SMoriah.Waterland@Sun.COM
2536*9781SMoriah.Waterland@Sun.COM /*
2537*9781SMoriah.Waterland@Sun.COM * find_attr - Look for a given attribute of the type associated with the NID.
2538*9781SMoriah.Waterland@Sun.COM *
2539*9781SMoriah.Waterland@Sun.COM * Arguments:
2540*9781SMoriah.Waterland@Sun.COM * nid - NID for the attribute to be found (either NID_friendlyName or
2541*9781SMoriah.Waterland@Sun.COM * NID_locakKeyId)
2542*9781SMoriah.Waterland@Sun.COM * str - ASN1_STRING-type structure containing the value to be found,
2543*9781SMoriah.Waterland@Sun.COM * FriendlyName expects a ASN1_BMPSTRING and localKeyID uses a
2544*9781SMoriah.Waterland@Sun.COM * ASN1_STRING.
2545*9781SMoriah.Waterland@Sun.COM * kl - Points to a stack of private keys.
2546*9781SMoriah.Waterland@Sun.COM * pkey - Points at a location where the address of the matching private
2547*9781SMoriah.Waterland@Sun.COM * key will be stored.
2548*9781SMoriah.Waterland@Sun.COM * cl - Points to a stack of client certs with matching private keys.
2549*9781SMoriah.Waterland@Sun.COM * cert - Points to locaiton where the address of the matching client cert
2550*9781SMoriah.Waterland@Sun.COM * will be returned
2551*9781SMoriah.Waterland@Sun.COM *
2552*9781SMoriah.Waterland@Sun.COM * This function is designed to process lists of certs and private keys.
2553*9781SMoriah.Waterland@Sun.COM * This is made complex because these the attributes are stored differently
2554*9781SMoriah.Waterland@Sun.COM * for certs and for keys. For certs, only a few attributes are retained.
2555*9781SMoriah.Waterland@Sun.COM * FriendlyName is stored in the aux structure, under the name 'alias'.
2556*9781SMoriah.Waterland@Sun.COM * LocalKeyId is also stored in the aux structure, under the name 'keyid'.
2557*9781SMoriah.Waterland@Sun.COM * A pkey structure has a stack of attributes.
2558*9781SMoriah.Waterland@Sun.COM *
2559*9781SMoriah.Waterland@Sun.COM * The basic approach is:
2560*9781SMoriah.Waterland@Sun.COM * - If there there is no stack of certs but a stack of private keys exists,
2561*9781SMoriah.Waterland@Sun.COM * search the stack of keys for a match. Alternately, if there is a stack
2562*9781SMoriah.Waterland@Sun.COM * of certs and no private keys, search the certs.
2563*9781SMoriah.Waterland@Sun.COM *
2564*9781SMoriah.Waterland@Sun.COM * - If there are both certs and keys, assume that the matching certs and
2565*9781SMoriah.Waterland@Sun.COM * keys are in their respective stacks, with matching entries in the same
2566*9781SMoriah.Waterland@Sun.COM * order. Search for the name or keyid in the stack of certs. If it is
2567*9781SMoriah.Waterland@Sun.COM * not found, then this function returns 0 (nothing found).
2568*9781SMoriah.Waterland@Sun.COM *
2569*9781SMoriah.Waterland@Sun.COM * - Once a cert is found, verify that the key actually matches by
2570*9781SMoriah.Waterland@Sun.COM * comparing the private key with the public key (in the cert).
2571*9781SMoriah.Waterland@Sun.COM * If they don't match, return an error.
2572*9781SMoriah.Waterland@Sun.COM *
2573*9781SMoriah.Waterland@Sun.COM * A pointer to cert and/or pkey which matches the name or keyid is stored
2574*9781SMoriah.Waterland@Sun.COM * in the return arguments.
2575*9781SMoriah.Waterland@Sun.COM *
2576*9781SMoriah.Waterland@Sun.COM * Returns:
2577*9781SMoriah.Waterland@Sun.COM * 0 - No matches were found.
2578*9781SMoriah.Waterland@Sun.COM * > 0 - Bits set based on FOUND_* definitions, indicating what was found.
2579*9781SMoriah.Waterland@Sun.COM * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT).
2580*9781SMoriah.Waterland@Sun.COM */
2581*9781SMoriah.Waterland@Sun.COM static int
find_attr(int nid,ASN1_STRING * str,STACK_OF (EVP_PKEY)* kl,EVP_PKEY ** pkey,STACK_OF (X509)* cl,X509 ** cert)2582*9781SMoriah.Waterland@Sun.COM find_attr(int nid, ASN1_STRING *str, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey,
2583*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) *cl, X509 **cert)
2584*9781SMoriah.Waterland@Sun.COM {
2585*9781SMoriah.Waterland@Sun.COM ASN1_UTF8STRING *ustr = NULL;
2586*9781SMoriah.Waterland@Sun.COM ASN1_STRING *s;
2587*9781SMoriah.Waterland@Sun.COM ASN1_TYPE *t;
2588*9781SMoriah.Waterland@Sun.COM EVP_PKEY *p;
2589*9781SMoriah.Waterland@Sun.COM uchar_t *fname = NULL;
2590*9781SMoriah.Waterland@Sun.COM X509 *x;
2591*9781SMoriah.Waterland@Sun.COM int found = 0;
2592*9781SMoriah.Waterland@Sun.COM int chkcerts;
2593*9781SMoriah.Waterland@Sun.COM int len;
2594*9781SMoriah.Waterland@Sun.COM int res;
2595*9781SMoriah.Waterland@Sun.COM int c = -1;
2596*9781SMoriah.Waterland@Sun.COM int k = -1;
2597*9781SMoriah.Waterland@Sun.COM
2598*9781SMoriah.Waterland@Sun.COM chkcerts = (cert != NULL || pkey != NULL) && cl != NULL;
2599*9781SMoriah.Waterland@Sun.COM if (chkcerts && nid == NID_friendlyName &&
2600*9781SMoriah.Waterland@Sun.COM str->type == V_ASN1_BMPSTRING) {
2601*9781SMoriah.Waterland@Sun.COM ustr = ASN1_UTF8STRING_new();
2602*9781SMoriah.Waterland@Sun.COM if (ustr == NULL) {
2603*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
2604*9781SMoriah.Waterland@Sun.COM return (0);
2605*9781SMoriah.Waterland@Sun.COM }
2606*9781SMoriah.Waterland@Sun.COM len = ASN1_STRING_to_UTF8(&fname, str);
2607*9781SMoriah.Waterland@Sun.COM if (fname == NULL) {
2608*9781SMoriah.Waterland@Sun.COM ASN1_UTF8STRING_free(ustr);
2609*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_FINDATTR, SUNW_R_STR_CONVERT_ERR);
2610*9781SMoriah.Waterland@Sun.COM return (0);
2611*9781SMoriah.Waterland@Sun.COM }
2612*9781SMoriah.Waterland@Sun.COM
2613*9781SMoriah.Waterland@Sun.COM if (ASN1_STRING_set(ustr, fname, len) == 0) {
2614*9781SMoriah.Waterland@Sun.COM ASN1_UTF8STRING_free(ustr);
2615*9781SMoriah.Waterland@Sun.COM OPENSSL_free(fname);
2616*9781SMoriah.Waterland@Sun.COM SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE);
2617*9781SMoriah.Waterland@Sun.COM return (0);
2618*9781SMoriah.Waterland@Sun.COM }
2619*9781SMoriah.Waterland@Sun.COM }
2620*9781SMoriah.Waterland@Sun.COM
2621*9781SMoriah.Waterland@Sun.COM if (chkcerts) {
2622*9781SMoriah.Waterland@Sun.COM for (c = 0; c < sk_X509_num(cl); c++) {
2623*9781SMoriah.Waterland@Sun.COM res = -1;
2624*9781SMoriah.Waterland@Sun.COM x = sk_X509_value(cl, c);
2625*9781SMoriah.Waterland@Sun.COM if (nid == NID_friendlyName && ustr != NULL) {
2626*9781SMoriah.Waterland@Sun.COM if (x->aux == NULL || x->aux->alias == NULL)
2627*9781SMoriah.Waterland@Sun.COM continue;
2628*9781SMoriah.Waterland@Sun.COM s = x->aux->alias;
2629*9781SMoriah.Waterland@Sun.COM if (s != NULL && s->type == ustr->type &&
2630*9781SMoriah.Waterland@Sun.COM s->data != NULL) {
2631*9781SMoriah.Waterland@Sun.COM res = ASN1_STRING_cmp(s, ustr);
2632*9781SMoriah.Waterland@Sun.COM }
2633*9781SMoriah.Waterland@Sun.COM } else {
2634*9781SMoriah.Waterland@Sun.COM if (x->aux == NULL || x->aux->keyid == NULL)
2635*9781SMoriah.Waterland@Sun.COM continue;
2636*9781SMoriah.Waterland@Sun.COM s = x->aux->keyid;
2637*9781SMoriah.Waterland@Sun.COM if (s != NULL && s->type == str->type &&
2638*9781SMoriah.Waterland@Sun.COM s->data != NULL) {
2639*9781SMoriah.Waterland@Sun.COM res = ASN1_STRING_cmp(s, str);
2640*9781SMoriah.Waterland@Sun.COM }
2641*9781SMoriah.Waterland@Sun.COM }
2642*9781SMoriah.Waterland@Sun.COM if (res == 0) {
2643*9781SMoriah.Waterland@Sun.COM if (cert != NULL)
2644*9781SMoriah.Waterland@Sun.COM *cert = sk_X509_delete(cl, c);
2645*9781SMoriah.Waterland@Sun.COM found = FOUND_CERT;
2646*9781SMoriah.Waterland@Sun.COM break;
2647*9781SMoriah.Waterland@Sun.COM }
2648*9781SMoriah.Waterland@Sun.COM }
2649*9781SMoriah.Waterland@Sun.COM if (ustr != NULL) {
2650*9781SMoriah.Waterland@Sun.COM ASN1_UTF8STRING_free(ustr);
2651*9781SMoriah.Waterland@Sun.COM OPENSSL_free(fname);
2652*9781SMoriah.Waterland@Sun.COM }
2653*9781SMoriah.Waterland@Sun.COM }
2654*9781SMoriah.Waterland@Sun.COM
2655*9781SMoriah.Waterland@Sun.COM if (pkey != NULL && kl != NULL) {
2656*9781SMoriah.Waterland@Sun.COM /*
2657*9781SMoriah.Waterland@Sun.COM * Looking for pkey to match a cert? If so, assume that
2658*9781SMoriah.Waterland@Sun.COM * lists of certs and their matching pkeys are in the same
2659*9781SMoriah.Waterland@Sun.COM * order. Call X509_check_private_key() to verify this
2660*9781SMoriah.Waterland@Sun.COM * assumption.
2661*9781SMoriah.Waterland@Sun.COM */
2662*9781SMoriah.Waterland@Sun.COM if (found != 0 && cert != NULL) {
2663*9781SMoriah.Waterland@Sun.COM k = c;
2664*9781SMoriah.Waterland@Sun.COM p = sk_EVP_PKEY_value(kl, k);
2665*9781SMoriah.Waterland@Sun.COM if (X509_check_private_key(x, p) != 0) {
2666*9781SMoriah.Waterland@Sun.COM if (pkey != NULL)
2667*9781SMoriah.Waterland@Sun.COM *pkey = sk_EVP_PKEY_delete(kl, k);
2668*9781SMoriah.Waterland@Sun.COM found |= FOUND_PKEY;
2669*9781SMoriah.Waterland@Sun.COM }
2670*9781SMoriah.Waterland@Sun.COM } else if (cert == NULL) {
2671*9781SMoriah.Waterland@Sun.COM for (k = 0; k < sk_EVP_PKEY_num(kl); k++) {
2672*9781SMoriah.Waterland@Sun.COM p = sk_EVP_PKEY_value(kl, k);
2673*9781SMoriah.Waterland@Sun.COM if (p == NULL || p->attributes == NULL)
2674*9781SMoriah.Waterland@Sun.COM continue;
2675*9781SMoriah.Waterland@Sun.COM
2676*9781SMoriah.Waterland@Sun.COM t = PKCS12_get_attr_gen(p->attributes, nid);
2677*9781SMoriah.Waterland@Sun.COM if (t != NULL || ASN1_STRING_cmp(str,
2678*9781SMoriah.Waterland@Sun.COM t->value.asn1_string) == 0)
2679*9781SMoriah.Waterland@Sun.COM continue;
2680*9781SMoriah.Waterland@Sun.COM
2681*9781SMoriah.Waterland@Sun.COM found |= FOUND_PKEY;
2682*9781SMoriah.Waterland@Sun.COM if (pkey != NULL)
2683*9781SMoriah.Waterland@Sun.COM *pkey = sk_EVP_PKEY_delete(kl, k);
2684*9781SMoriah.Waterland@Sun.COM break;
2685*9781SMoriah.Waterland@Sun.COM }
2686*9781SMoriah.Waterland@Sun.COM }
2687*9781SMoriah.Waterland@Sun.COM }
2688*9781SMoriah.Waterland@Sun.COM
2689*9781SMoriah.Waterland@Sun.COM return (found);
2690*9781SMoriah.Waterland@Sun.COM }
2691*9781SMoriah.Waterland@Sun.COM
2692*9781SMoriah.Waterland@Sun.COM /*
2693*9781SMoriah.Waterland@Sun.COM * set_results - Given two pointers to stacks of private keys, certs or CA
2694*9781SMoriah.Waterland@Sun.COM * CA certs, either copy the second stack to the first, or append the
2695*9781SMoriah.Waterland@Sun.COM * contents of the second to the first.
2696*9781SMoriah.Waterland@Sun.COM *
2697*9781SMoriah.Waterland@Sun.COM * Arguments:
2698*9781SMoriah.Waterland@Sun.COM * pkeys - Points to stack of pkeys
2699*9781SMoriah.Waterland@Sun.COM * work_kl - Points to working stack of pkeys
2700*9781SMoriah.Waterland@Sun.COM * certs - Points to stack of certs
2701*9781SMoriah.Waterland@Sun.COM * work_cl - Points to working stack of certs
2702*9781SMoriah.Waterland@Sun.COM * cacerts - Points to stack of CA certs
2703*9781SMoriah.Waterland@Sun.COM * work_ca - Points to working stack of CA certs
2704*9781SMoriah.Waterland@Sun.COM * xtrakeys - Points to stack of unmatcned pkeys
2705*9781SMoriah.Waterland@Sun.COM * work_xl - Points to working stack of unmatcned pkeys
2706*9781SMoriah.Waterland@Sun.COM *
2707*9781SMoriah.Waterland@Sun.COM * The arguments are in pairs. The first of each pair points to a stack
2708*9781SMoriah.Waterland@Sun.COM * of keys or certs. The second of the pair points at a 'working stack'
2709*9781SMoriah.Waterland@Sun.COM * of the same type of entities. Actions taken are as follows:
2710*9781SMoriah.Waterland@Sun.COM *
2711*9781SMoriah.Waterland@Sun.COM * - If either the first or second argument is NULL, or if there are no
2712*9781SMoriah.Waterland@Sun.COM * members in the second stack, there is nothing to do.
2713*9781SMoriah.Waterland@Sun.COM * - If the first argument points to a pointer which is NULL, then there
2714*9781SMoriah.Waterland@Sun.COM * is no existing stack for the first argument. Copy the stack pointer
2715*9781SMoriah.Waterland@Sun.COM * from the second argument to the first argument and NULL out the stack
2716*9781SMoriah.Waterland@Sun.COM * pointer for the second.
2717*9781SMoriah.Waterland@Sun.COM * - Otherwise, go through the elements of the second stack, removing each
2718*9781SMoriah.Waterland@Sun.COM * and adding it to the first stack.
2719*9781SMoriah.Waterland@Sun.COM *
2720*9781SMoriah.Waterland@Sun.COM * Returns:
2721*9781SMoriah.Waterland@Sun.COM * == -1 - An error occurred. Call ERR_get_error() to get error information.
2722*9781SMoriah.Waterland@Sun.COM * == 0 - No matching returns were found.
2723*9781SMoriah.Waterland@Sun.COM * > 0 - This is the arithmetic 'or' of the FOUND_* bits that indicate which
2724*9781SMoriah.Waterland@Sun.COM * of the requested entries were manipulated.
2725*9781SMoriah.Waterland@Sun.COM */
2726*9781SMoriah.Waterland@Sun.COM static int
set_results(STACK_OF (EVP_PKEY)** pkeys,STACK_OF (EVP_PKEY)** work_kl,STACK_OF (X509)** certs,STACK_OF (X509)** work_cl,STACK_OF (X509)** cacerts,STACK_OF (X509)** work_ca,STACK_OF (EVP_PKEY)** xtrakeys,STACK_OF (EVP_PKEY)** work_xl)2727*9781SMoriah.Waterland@Sun.COM set_results(STACK_OF(EVP_PKEY) **pkeys, STACK_OF(EVP_PKEY) **work_kl,
2728*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) **certs, STACK_OF(X509) **work_cl,
2729*9781SMoriah.Waterland@Sun.COM STACK_OF(X509) **cacerts, STACK_OF(X509) **work_ca,
2730*9781SMoriah.Waterland@Sun.COM STACK_OF(EVP_PKEY) **xtrakeys, STACK_OF(EVP_PKEY) **work_xl)
2731*9781SMoriah.Waterland@Sun.COM {
2732*9781SMoriah.Waterland@Sun.COM int retval = 0;
2733*9781SMoriah.Waterland@Sun.COM
2734*9781SMoriah.Waterland@Sun.COM if (pkeys != NULL && work_kl != NULL && *work_kl != NULL &&
2735*9781SMoriah.Waterland@Sun.COM sk_EVP_PKEY_num(*work_kl) > 0) {
2736*9781SMoriah.Waterland@Sun.COM if (*pkeys == NULL) {
2737*9781SMoriah.Waterland@Sun.COM *pkeys = *work_kl;
2738*9781SMoriah.Waterland@Sun.COM *work_kl = NULL;
2739*9781SMoriah.Waterland@Sun.COM } else {
2740*9781SMoriah.Waterland@Sun.COM if (sunw_append_keys(*pkeys, *work_kl) < 0) {
2741*9781SMoriah.Waterland@Sun.COM return (-1);
2742*9781SMoriah.Waterland@Sun.COM }
2743*9781SMoriah.Waterland@Sun.COM }
2744*9781SMoriah.Waterland@Sun.COM retval |= FOUND_PKEY;
2745*9781SMoriah.Waterland@Sun.COM }
2746*9781SMoriah.Waterland@Sun.COM if (certs != NULL && work_cl != NULL && *work_cl != NULL &&
2747*9781SMoriah.Waterland@Sun.COM sk_X509_num(*work_cl) > 0) {
2748*9781SMoriah.Waterland@Sun.COM if (*certs == NULL) {
2749*9781SMoriah.Waterland@Sun.COM *certs = *work_cl;
2750*9781SMoriah.Waterland@Sun.COM *work_cl = NULL;
2751*9781SMoriah.Waterland@Sun.COM } else {
2752*9781SMoriah.Waterland@Sun.COM if (move_certs(*certs, *work_cl) < 0) {
2753*9781SMoriah.Waterland@Sun.COM return (-1);
2754*9781SMoriah.Waterland@Sun.COM }
2755*9781SMoriah.Waterland@Sun.COM }
2756*9781SMoriah.Waterland@Sun.COM retval |= FOUND_CERT;
2757*9781SMoriah.Waterland@Sun.COM }
2758*9781SMoriah.Waterland@Sun.COM
2759*9781SMoriah.Waterland@Sun.COM if (cacerts != NULL && work_ca != NULL && *work_ca != NULL &&
2760*9781SMoriah.Waterland@Sun.COM sk_X509_num(*work_ca) > 0) {
2761*9781SMoriah.Waterland@Sun.COM if (*cacerts == NULL) {
2762*9781SMoriah.Waterland@Sun.COM *cacerts = *work_ca;
2763*9781SMoriah.Waterland@Sun.COM *work_ca = NULL;
2764*9781SMoriah.Waterland@Sun.COM } else {
2765*9781SMoriah.Waterland@Sun.COM if (move_certs(*cacerts, *work_ca) < 0) {
2766*9781SMoriah.Waterland@Sun.COM return (-1);
2767*9781SMoriah.Waterland@Sun.COM }
2768*9781SMoriah.Waterland@Sun.COM }
2769*9781SMoriah.Waterland@Sun.COM retval |= FOUND_CA_CERTS;
2770*9781SMoriah.Waterland@Sun.COM }
2771*9781SMoriah.Waterland@Sun.COM
2772*9781SMoriah.Waterland@Sun.COM if (xtrakeys != NULL && work_xl != NULL && *work_xl != NULL &&
2773*9781SMoriah.Waterland@Sun.COM sk_EVP_PKEY_num(*work_xl) > 0) {
2774*9781SMoriah.Waterland@Sun.COM if (*xtrakeys == NULL) {
2775*9781SMoriah.Waterland@Sun.COM *xtrakeys = *work_xl;
2776*9781SMoriah.Waterland@Sun.COM *work_xl = NULL;
2777*9781SMoriah.Waterland@Sun.COM } else {
2778*9781SMoriah.Waterland@Sun.COM if (sunw_append_keys(*xtrakeys, *work_xl) < 0) {
2779*9781SMoriah.Waterland@Sun.COM return (-1);
2780*9781SMoriah.Waterland@Sun.COM }
2781*9781SMoriah.Waterland@Sun.COM }
2782*9781SMoriah.Waterland@Sun.COM retval |= FOUND_XPKEY;
2783*9781SMoriah.Waterland@Sun.COM }
2784*9781SMoriah.Waterland@Sun.COM
2785*9781SMoriah.Waterland@Sun.COM return (retval);
2786*9781SMoriah.Waterland@Sun.COM }
2787