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 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 */ 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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