15c51f124SMoriah Waterland /* 25c51f124SMoriah Waterland * ==================================================================== 35c51f124SMoriah Waterland * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 45c51f124SMoriah Waterland * 55c51f124SMoriah Waterland * Redistribution and use in source and binary forms, with or without 65c51f124SMoriah Waterland * modification, are permitted provided that the following conditions 75c51f124SMoriah Waterland * are met: 85c51f124SMoriah Waterland * 95c51f124SMoriah Waterland * 1. Redistributions of source code must retain the above copyright 105c51f124SMoriah Waterland * notice, this list of conditions and the following disclaimer. 115c51f124SMoriah Waterland * 125c51f124SMoriah Waterland * 2. Redistributions in binary form must reproduce the above copyright 135c51f124SMoriah Waterland * notice, this list of conditions and the following disclaimer in 145c51f124SMoriah Waterland * the documentation and/or other materials provided with the 155c51f124SMoriah Waterland * distribution. 165c51f124SMoriah Waterland * 175c51f124SMoriah Waterland * 3. All advertising materials mentioning features or use of this 185c51f124SMoriah Waterland * software must display the following acknowledgment: 195c51f124SMoriah Waterland * "This product includes software developed by the OpenSSL Project 205c51f124SMoriah Waterland * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 215c51f124SMoriah Waterland * 225c51f124SMoriah Waterland * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 235c51f124SMoriah Waterland * endorse or promote products derived from this software without 245c51f124SMoriah Waterland * prior written permission. For written permission, please contact 255c51f124SMoriah Waterland * licensing@OpenSSL.org. 265c51f124SMoriah Waterland * 275c51f124SMoriah Waterland * 5. Products derived from this software may not be called "OpenSSL" 285c51f124SMoriah Waterland * nor may "OpenSSL" appear in their names without prior written 295c51f124SMoriah Waterland * permission of the OpenSSL Project. 305c51f124SMoriah Waterland * 315c51f124SMoriah Waterland * 6. Redistributions of any form whatsoever must retain the following 325c51f124SMoriah Waterland * acknowledgment: 335c51f124SMoriah Waterland * "This product includes software developed by the OpenSSL Project 345c51f124SMoriah Waterland * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 355c51f124SMoriah Waterland * 365c51f124SMoriah Waterland * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 375c51f124SMoriah Waterland * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 385c51f124SMoriah Waterland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 395c51f124SMoriah Waterland * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 405c51f124SMoriah Waterland * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 415c51f124SMoriah Waterland * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 425c51f124SMoriah Waterland * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 435c51f124SMoriah Waterland * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 445c51f124SMoriah Waterland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 455c51f124SMoriah Waterland * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 465c51f124SMoriah Waterland * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 475c51f124SMoriah Waterland * OF THE POSSIBILITY OF SUCH DAMAGE. 485c51f124SMoriah Waterland * ==================================================================== 495c51f124SMoriah Waterland * 505c51f124SMoriah Waterland * This product includes cryptographic software written by Eric Young 515c51f124SMoriah Waterland * (eay@cryptsoft.com). This product includes software written by Tim 525c51f124SMoriah Waterland * Hudson (tjh@cryptsoft.com). 535c51f124SMoriah Waterland * 545c51f124SMoriah Waterland */ 555c51f124SMoriah Waterland 565c51f124SMoriah Waterland /* 575c51f124SMoriah Waterland * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 585c51f124SMoriah Waterland * Use is subject to license terms. 595c51f124SMoriah Waterland */ 605c51f124SMoriah Waterland 61*70f9559bSTheo Schlossnagle /* 62*70f9559bSTheo Schlossnagle * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved. 63*70f9559bSTheo Schlossnagle */ 64*70f9559bSTheo Schlossnagle 655c51f124SMoriah Waterland 665c51f124SMoriah Waterland #include <strings.h> 675c51f124SMoriah Waterland #include <stdlib.h> 685c51f124SMoriah Waterland #include <assert.h> 695c51f124SMoriah Waterland 705c51f124SMoriah Waterland #include <openssl/crypto.h> 715c51f124SMoriah Waterland #include <openssl/err.h> 725c51f124SMoriah Waterland #include <openssl/x509.h> 735c51f124SMoriah Waterland #include <openssl/pem.h> 745c51f124SMoriah Waterland 755c51f124SMoriah Waterland #include <openssl/pkcs12.h> 765c51f124SMoriah Waterland #include "p12lib.h" 775c51f124SMoriah Waterland 785c51f124SMoriah Waterland /* 795c51f124SMoriah Waterland * OpenSSL provides a framework for pushing error codes onto a stack. 805c51f124SMoriah Waterland * When an error occurs, the consumer may use the framework to 815c51f124SMoriah Waterland * pop the errors off the stack and provide a trace of where the 825c51f124SMoriah Waterland * errors occurred. 835c51f124SMoriah Waterland * 845c51f124SMoriah Waterland * Our PKCS12 code plugs into this framework by calling 855c51f124SMoriah Waterland * ERR_load_SUNW_strings(). To push an error (which by the way, consists 865c51f124SMoriah Waterland * of a function code and an error code) onto the stack our PKCS12 code 875c51f124SMoriah Waterland * calls SUNWerr(). 885c51f124SMoriah Waterland * 895c51f124SMoriah Waterland * Consumers of our PKCS12 code can then call the OpenSSL error routines 905c51f124SMoriah Waterland * when an error occurs and retrieve the stack of errors. 915c51f124SMoriah Waterland */ 925c51f124SMoriah Waterland 935c51f124SMoriah Waterland #ifndef OPENSSL_NO_ERR 945c51f124SMoriah Waterland 955c51f124SMoriah Waterland /* Function codes and their matching strings */ 965c51f124SMoriah Waterland static ERR_STRING_DATA SUNW_str_functs[] = { 975c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_USE_X509CERT, 0), "sunw_use_x509cert" }, 985c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_USE_PKEY, 0), "sunw_use_pkey" }, 995c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_USE_TASTORE, 0), "sunw_use_tastore" }, 1005c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_USE_CERTFILE, 0), "sunw_p12_use_certfile" }, 1015c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_USE_KEYFILE, 0), "sunw_p12_use_keyfile" }, 1025c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_USE_TRUSTFILE, 0), "sunw_p12_use_trustfile" }, 1035c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_READ_FILE, 0), "p12_read_file" }, 1045c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_DOPARSE, 0), "p12_doparse" }, 1055c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_PKCS12_PARSE, 0), "sunw_PKCS12_parse" }, 1065c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_PKCS12_CONTENTS, 0), "sunw_PKCS12_contents" }, 1075c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_PARSE_ONE_BAG, 0), "parse_one_bag" }, 1085c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_PKCS12_CREATE, 0), "sunw_PKCS12_create" }, 1095c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_SPLIT_CERTS, 0), "sunw_split_certs" }, 1105c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_FIND_LOCALKEYID, 0), "sunw_find_localkeyid" }, 1115c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_SET_LOCALKEYID, 0), "sunw_set_localkeyid" }, 1125c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_GET_LOCALKEYID, 0), "sunw_get_localkeyid" }, 1135c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_SET_FNAME, 0), "sunw_set_fname" }, 1145c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_GET_PKEY_FNAME, 0), "sunw_get_pkey_fname" }, 1155c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_APPEND_KEYS, 0), "sunw_append_keys" }, 1165c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_PEM_CONTENTS, 0), "sunw_PEM_contents" }, 1175c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_PEM_INFO, 0), "pem_info" }, 1185c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_ASC2BMPSTRING, 0), "asc2bmpstring" }, 1195c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_UTF82ASCSTR, 0), "utf82ascstr" }, 1205c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_FINDATTR, 0), "findattr" }, 1215c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_TYPE2ATTRIB, 0), "type2attrib" }, 1225c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_MOVE_CERTS, 0), "move_certs" }, 1235c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_FIND_FNAME, 0), "sunw_find_fname" }, 1245c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_PARSE_OUTER, 0), "parse_outer" }, 1255c51f124SMoriah Waterland { ERR_PACK(0, SUNW_F_CHECKFILE, 0), "checkfile" }, 1265c51f124SMoriah Waterland { 0, NULL } 1275c51f124SMoriah Waterland }; 1285c51f124SMoriah Waterland 1295c51f124SMoriah Waterland /* Error codes and their matching strings */ 1305c51f124SMoriah Waterland static ERR_STRING_DATA SUNW_str_reasons[] = { 1315c51f124SMoriah Waterland { SUNW_R_INVALID_ARG, "invalid argument" }, 1325c51f124SMoriah Waterland { SUNW_R_MEMORY_FAILURE, "memory failure" }, 1335c51f124SMoriah Waterland { SUNW_R_MAC_VERIFY_FAILURE, "mac verify failure" }, 1345c51f124SMoriah Waterland { SUNW_R_MAC_CREATE_FAILURE, "mac create failure" }, 1355c51f124SMoriah Waterland { SUNW_R_BAD_FILETYPE, "bad file type" }, 1365c51f124SMoriah Waterland { SUNW_R_BAD_PKEY, "bad or missing private key" }, 1375c51f124SMoriah Waterland { SUNW_R_BAD_PKEYTYPE, "unsupported key type" }, 1385c51f124SMoriah Waterland { SUNW_R_PKEY_READ_ERR, "unable to read private key" }, 1395c51f124SMoriah Waterland { SUNW_R_NO_TRUST_ANCHOR, "no trust anchors found" }, 1405c51f124SMoriah Waterland { SUNW_R_READ_TRUST_ERR, "unable to read trust anchor" }, 1415c51f124SMoriah Waterland { SUNW_R_ADD_TRUST_ERR, "unable to add trust anchor" }, 1425c51f124SMoriah Waterland { SUNW_R_PKCS12_PARSE_ERR, "PKCS12 parse error" }, 1435c51f124SMoriah Waterland { SUNW_R_PKCS12_CREATE_ERR, "PKCS12 create error" }, 1445c51f124SMoriah Waterland { SUNW_R_BAD_CERTTYPE, "unsupported certificate type" }, 1455c51f124SMoriah Waterland { SUNW_R_PARSE_CERT_ERR, "error parsing PKCS12 certificate" }, 1465c51f124SMoriah Waterland { SUNW_R_PARSE_BAG_ERR, "error parsing PKCS12 bag" }, 1475c51f124SMoriah Waterland { SUNW_R_MAKE_BAG_ERR, "error making PKCS12 bag" }, 1485c51f124SMoriah Waterland { SUNW_R_BAD_LKID, "bad localKeyID format" }, 1495c51f124SMoriah Waterland { SUNW_R_SET_LKID_ERR, "error setting localKeyID" }, 1505c51f124SMoriah Waterland { SUNW_R_BAD_FNAME, "bad friendlyName format" }, 1515c51f124SMoriah Waterland { SUNW_R_SET_FNAME_ERR, "error setting friendlyName" }, 1525c51f124SMoriah Waterland { SUNW_R_BAD_TRUST, "bad or missing trust anchor" }, 1535c51f124SMoriah Waterland { SUNW_R_BAD_BAGTYPE, "unsupported bag type" }, 1545c51f124SMoriah Waterland { SUNW_R_CERT_ERR, "certificate error" }, 1555c51f124SMoriah Waterland { SUNW_R_PKEY_ERR, "private key error" }, 1565c51f124SMoriah Waterland { SUNW_R_READ_ERR, "error reading file" }, 1575c51f124SMoriah Waterland { SUNW_R_ADD_ATTR_ERR, "error adding attribute" }, 1585c51f124SMoriah Waterland { SUNW_R_STR_CONVERT_ERR, "error converting string" }, 1595c51f124SMoriah Waterland { SUNW_R_PKCS12_EMPTY_ERR, "empty PKCS12 structure" }, 1605c51f124SMoriah Waterland { SUNW_R_PASSWORD_ERR, "bad password" }, 1615c51f124SMoriah Waterland { 0, NULL } 1625c51f124SMoriah Waterland }; 1635c51f124SMoriah Waterland 1645c51f124SMoriah Waterland /* 1655c51f124SMoriah Waterland * The library name that our module will be known as. This name 1665c51f124SMoriah Waterland * may be retrieved via OpenSSLs error APIs. 1675c51f124SMoriah Waterland */ 1685c51f124SMoriah Waterland static ERR_STRING_DATA SUNW_lib_name[] = { 1695c51f124SMoriah Waterland { 0, SUNW_LIB_NAME }, 1705c51f124SMoriah Waterland { 0, NULL } 1715c51f124SMoriah Waterland }; 1725c51f124SMoriah Waterland #endif 1735c51f124SMoriah Waterland 1745c51f124SMoriah Waterland /* 1755c51f124SMoriah Waterland * The value of this variable (initialized by a call to 1765c51f124SMoriah Waterland * ERR_load_SUNW_strings()) is what identifies our errors 1775c51f124SMoriah Waterland * to OpenSSL as being ours. 1785c51f124SMoriah Waterland */ 1795c51f124SMoriah Waterland static int SUNW_lib_error_code = 0; 1805c51f124SMoriah Waterland 1815c51f124SMoriah Waterland /* local routines */ 1825c51f124SMoriah Waterland static int parse_pkcs12(PKCS12 *, const char *, int, char *, int, char *, 1835c51f124SMoriah Waterland EVP_PKEY **, X509 **, STACK_OF(X509) **); 1845c51f124SMoriah Waterland static int pem_info(FILE *, pem_password_cb, void *, 1855c51f124SMoriah Waterland STACK_OF(EVP_PKEY) **, STACK_OF(X509) **); 1865c51f124SMoriah Waterland 1875c51f124SMoriah Waterland static int parse_outer(PKCS12 *, const char *, STACK_OF(EVP_PKEY) *, 1885c51f124SMoriah Waterland STACK_OF(X509) *); 1895c51f124SMoriah Waterland 1905c51f124SMoriah Waterland static int parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *, const char *, 1915c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *, STACK_OF(X509) *); 1925c51f124SMoriah Waterland 1935c51f124SMoriah Waterland static int parse_one_bag(PKCS12_SAFEBAG *, const char *, 1945c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *, STACK_OF(X509) *); 1955c51f124SMoriah Waterland 1965c51f124SMoriah Waterland static X509_ATTRIBUTE *type2attrib(ASN1_TYPE *, int); 1975c51f124SMoriah Waterland static ASN1_TYPE *attrib2type(X509_ATTRIBUTE *); 1985c51f124SMoriah Waterland static uchar_t *utf82ascstr(ASN1_UTF8STRING *); 1995c51f124SMoriah Waterland static ASN1_BMPSTRING *asc2bmpstring(const char *, int); 2005c51f124SMoriah Waterland static int find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *, int); 2015c51f124SMoriah Waterland static int find_attr(int, ASN1_STRING *, STACK_OF(EVP_PKEY) *, 2025c51f124SMoriah Waterland EVP_PKEY **, STACK_OF(X509) *, X509 **); 2035c51f124SMoriah Waterland 2045c51f124SMoriah Waterland static chk_errs_t check_time(chk_actions_t, X509 *); 2055c51f124SMoriah Waterland static int get_key_cert(int, STACK_OF(EVP_PKEY) *, EVP_PKEY **, 2065c51f124SMoriah Waterland STACK_OF(X509) *, X509 **cert); 2075c51f124SMoriah Waterland static int move_certs(STACK_OF(X509) *, STACK_OF(X509) *); 2085c51f124SMoriah Waterland static int sunw_append_keys(STACK_OF(EVP_PKEY) *, 2095c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *); 2105c51f124SMoriah Waterland static int set_results(STACK_OF(EVP_PKEY) **, 2115c51f124SMoriah Waterland STACK_OF(EVP_PKEY) **, STACK_OF(X509) **, STACK_OF(X509) **, 2125c51f124SMoriah Waterland STACK_OF(X509) **, STACK_OF(X509) **, 2135c51f124SMoriah Waterland STACK_OF(EVP_PKEY) **, STACK_OF(EVP_PKEY) **); 2145c51f124SMoriah Waterland 2155c51f124SMoriah Waterland /* 2165c51f124SMoriah Waterland * ---------------------------------------------------------------------------- 2175c51f124SMoriah Waterland * Public routines 2185c51f124SMoriah Waterland * ---------------------------------------------------------------------------- 2195c51f124SMoriah Waterland */ 2205c51f124SMoriah Waterland 2215c51f124SMoriah Waterland /* 2225c51f124SMoriah Waterland * sunw_PKCS12_parse - Parse a PKCS12 structure and break it into its parts. 2235c51f124SMoriah Waterland * 2245c51f124SMoriah Waterland * Parse and decrypt a PKCS#12 structure returning user key, user cert and/or 2255c51f124SMoriah Waterland * other (CA) certs. Note either ca should be NULL, *ca should be NULL, 2265c51f124SMoriah Waterland * or it should point to a valid STACK_OF(X509) structure. pkey and cert can 2275c51f124SMoriah Waterland * be passed uninitialized. 2285c51f124SMoriah Waterland * 2295c51f124SMoriah Waterland * Arguments: 2305c51f124SMoriah Waterland * p12 - Structure with pkcs12 info to be parsed 2315c51f124SMoriah Waterland * pass - Pass phrase for the private key (possibly empty) or NULL if 2325c51f124SMoriah Waterland * there is none. 2335c51f124SMoriah Waterland * matchty - Info about which certs/keys to return if many are in the file. 2345c51f124SMoriah Waterland * keyid - If private key localkeyids friendlynames are to match a 2355c51f124SMoriah Waterland * predetermined value, the value to match. This value should 2365c51f124SMoriah Waterland * be an octet string. 2375c51f124SMoriah Waterland * keyid_len- Length of the keyid byte string. 2385c51f124SMoriah Waterland * name_str - If friendlynames are to match a predetermined value, the value 2395c51f124SMoriah Waterland * to match. This value should be a NULL terminated string. 2405c51f124SMoriah Waterland * pkey - Points to location pointing to the private key returned. 2415c51f124SMoriah Waterland * cert - Points to locaiton which points to the client cert returned 2425c51f124SMoriah Waterland * ca - Points to location that points to a stack of 'certificate 2435c51f124SMoriah Waterland * authority' certs/trust anchors. 2445c51f124SMoriah Waterland * 2455c51f124SMoriah Waterland * Match based on the value of 'matchty' and the contents of 'keyid' 2465c51f124SMoriah Waterland * and/or 'name_str', as appropriate. Go through the lists of certs and 2475c51f124SMoriah Waterland * private keys which were taken from the pkcs12 structure, looking for 2485c51f124SMoriah Waterland * matches of the requested type. This function only searches the lists of 2495c51f124SMoriah Waterland * matching private keys and client certificates. Kinds of matches allowed, 2505c51f124SMoriah Waterland * and the order in which they will be checked, are: 2515c51f124SMoriah Waterland * 2525c51f124SMoriah Waterland * 1) Find the key and/or cert whose localkeyid attributes matches 2535c51f124SMoriah Waterland * 'keyid'. 2545c51f124SMoriah Waterland * 2) Find the key and/or cert whose friendlyname attributes matches 2555c51f124SMoriah Waterland * 'name_str' 2565c51f124SMoriah Waterland * 3) Return the first matching key/cert pair found. 2575c51f124SMoriah Waterland * 4) Return the last matching key/cert pair found. 2585c51f124SMoriah Waterland * 5) Return whatever cert and/or key are available, even unmatching. 2595c51f124SMoriah Waterland * 2605c51f124SMoriah Waterland * Append to the CA list, the certs which do not have matching private 2615c51f124SMoriah Waterland * keys and which were not selected. 2625c51f124SMoriah Waterland * 2635c51f124SMoriah Waterland * If none of the bits are set, no client certs or private keys will be 2645c51f124SMoriah Waterland * returned. CA (aka trust anchor) certs can be. 2655c51f124SMoriah Waterland * 2665c51f124SMoriah Waterland * Notes: If #3 is selected, then #4 will never occur. CA certs will be 2675c51f124SMoriah Waterland * selected after a cert/key pairs are isolated. 2685c51f124SMoriah Waterland * 2695c51f124SMoriah Waterland * Returns: 2705c51f124SMoriah Waterland * < 0 - An error returned. Call ERR_get_error() to get errors information. 2715c51f124SMoriah Waterland * Where possible, memory has been freed. 2725c51f124SMoriah Waterland * >= 0 - Objects were found and returned. Which objects are indicated by 2735c51f124SMoriah Waterland * which bits are set (FOUND_PKEY, FOUND_CERT, FOUND_CA_CERTS). 2745c51f124SMoriah Waterland */ 2755c51f124SMoriah Waterland int 2765c51f124SMoriah Waterland sunw_PKCS12_parse(PKCS12 *p12, const char *pass, int matchty, char *keyid, 2775c51f124SMoriah Waterland int keyid_len, char *name_str, EVP_PKEY **pkey, X509 **cert, 2785c51f124SMoriah Waterland STACK_OF(X509) **ca) 2795c51f124SMoriah Waterland { 2805c51f124SMoriah Waterland boolean_t ca_supplied; 2815c51f124SMoriah Waterland int retval = -1; 2825c51f124SMoriah Waterland 2835c51f124SMoriah Waterland /* If NULL PKCS12 structure, this is an error */ 2845c51f124SMoriah Waterland if (p12 == NULL) { 2855c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG); 2865c51f124SMoriah Waterland return (-1); 2875c51f124SMoriah Waterland } 2885c51f124SMoriah Waterland 2895c51f124SMoriah Waterland /* Set up arguments.... These will be allocated if needed */ 2905c51f124SMoriah Waterland if (pkey) 2915c51f124SMoriah Waterland *pkey = NULL; 2925c51f124SMoriah Waterland if (cert) 2935c51f124SMoriah Waterland *cert = NULL; 2945c51f124SMoriah Waterland 2955c51f124SMoriah Waterland /* 2965c51f124SMoriah Waterland * If there is already a ca list, use it. Otherwise, allocate one 2975c51f124SMoriah Waterland * and free is later if an error occurs or whatever.) 2985c51f124SMoriah Waterland */ 2995c51f124SMoriah Waterland ca_supplied = (ca != NULL && *ca != NULL); 3005c51f124SMoriah Waterland if (ca != NULL && *ca == NULL) { 3015c51f124SMoriah Waterland if ((*ca = sk_X509_new_null()) == NULL) { 3025c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MEMORY_FAILURE); 3035c51f124SMoriah Waterland return (-1); 3045c51f124SMoriah Waterland } 3055c51f124SMoriah Waterland } 3065c51f124SMoriah Waterland 3075c51f124SMoriah Waterland /* 3085c51f124SMoriah Waterland * If password is zero length or NULL then try verifying both cases 3095c51f124SMoriah Waterland * to determine which password is correct. The reason for this is that 3105c51f124SMoriah Waterland * under PKCS#12 password based encryption no password and a zero 3115c51f124SMoriah Waterland * length password are two different things. If the password has a 3125c51f124SMoriah Waterland * non-zero length and is not NULL then call PKCS12_verify_mac() with 3135c51f124SMoriah Waterland * a length of '-1' and let it use strlen() to figure out the length 3145c51f124SMoriah Waterland * of the password. 3155c51f124SMoriah Waterland */ 3165c51f124SMoriah Waterland /* Check the mac */ 3175c51f124SMoriah Waterland if (pass == NULL || *pass == '\0') { 3185c51f124SMoriah Waterland if (PKCS12_verify_mac(p12, NULL, 0)) 3195c51f124SMoriah Waterland pass = NULL; 3205c51f124SMoriah Waterland else if (PKCS12_verify_mac(p12, "", 0)) 3215c51f124SMoriah Waterland pass = ""; 3225c51f124SMoriah Waterland else { 3235c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_PARSE, 3245c51f124SMoriah Waterland SUNW_R_MAC_VERIFY_FAILURE); 3255c51f124SMoriah Waterland goto err; 3265c51f124SMoriah Waterland } 3275c51f124SMoriah Waterland } else if (PKCS12_verify_mac(p12, pass, -1) == 0) { 3285c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_MAC_VERIFY_FAILURE); 3295c51f124SMoriah Waterland goto err; 3305c51f124SMoriah Waterland } 3315c51f124SMoriah Waterland 3325c51f124SMoriah Waterland retval = parse_pkcs12(p12, pass, matchty, keyid, keyid_len, 3335c51f124SMoriah Waterland name_str, pkey, cert, ca); 3345c51f124SMoriah Waterland if (retval < 0) { 3355c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_PKCS12_PARSE_ERR); 3365c51f124SMoriah Waterland goto err; 3375c51f124SMoriah Waterland } 3385c51f124SMoriah Waterland return (retval); 3395c51f124SMoriah Waterland 3405c51f124SMoriah Waterland err: 3415c51f124SMoriah Waterland if (pkey && *pkey) { 3425c51f124SMoriah Waterland sunw_evp_pkey_free(*pkey); 3435c51f124SMoriah Waterland } 3445c51f124SMoriah Waterland if (cert && *cert) 3455c51f124SMoriah Waterland X509_free(*cert); 3465c51f124SMoriah Waterland if (ca_supplied == B_FALSE && ca != NULL) 3475c51f124SMoriah Waterland sk_X509_pop_free(*ca, X509_free); 3485c51f124SMoriah Waterland 3495c51f124SMoriah Waterland return (-1); 3505c51f124SMoriah Waterland 3515c51f124SMoriah Waterland } 3525c51f124SMoriah Waterland 3535c51f124SMoriah Waterland 3545c51f124SMoriah Waterland /* 3555c51f124SMoriah Waterland * sunw_PEM_contents() parses a PEM file and returns component parts found 3565c51f124SMoriah Waterland * 3575c51f124SMoriah Waterland * Parse and decrypt a PEM file, returning any user keys and certs. 3585c51f124SMoriah Waterland * 3595c51f124SMoriah Waterland * There are some limits to this function. It will ignore the following: 3605c51f124SMoriah Waterland * - certificates identified by "TRUSTED CERTIFICATE" 3615c51f124SMoriah Waterland * - CERTIFICATE REQUEST and NEW CERTIFICATE REQUEST records. 3625c51f124SMoriah Waterland * - X509 CRL 3635c51f124SMoriah Waterland * - DH PARAMETERS 3645c51f124SMoriah Waterland * - DSA PARAMETERS 3655c51f124SMoriah Waterland * - Any PUBLIC KEY 3665c51f124SMoriah Waterland * - PKCS7 3675c51f124SMoriah Waterland * - PRIVATE KEY or ENCRYPTED PRIVATE KEY (PKCS 8) 3685c51f124SMoriah Waterland * 3695c51f124SMoriah Waterland * Arguments: 3705c51f124SMoriah Waterland * fp - File pointer for file containing PEM data. 3715c51f124SMoriah Waterland * pass - Pass phrase for the private key or NULL if there is none. 3725c51f124SMoriah Waterland * pkeys - Points to address of a stack of private keys to return. 3735c51f124SMoriah Waterland * certs - Points to address of a stack of client certs to return. 3745c51f124SMoriah Waterland * 3755c51f124SMoriah Waterland * The pointers to stacks should either be NULL or their contents should 3765c51f124SMoriah Waterland * either be NULL or should point to a valid STACK_OF(X509) structure. 3775c51f124SMoriah Waterland * If the stacks contain information, corresponding information from the 3785c51f124SMoriah Waterland * file will be appended to the original contents. 3795c51f124SMoriah Waterland * 3805c51f124SMoriah Waterland * Note: Client certs and and their matching private keys will be in any 3815c51f124SMoriah Waterland * order. 3825c51f124SMoriah Waterland * 3835c51f124SMoriah Waterland * Certs which have no matching private key are assumed to be ca certs. 3845c51f124SMoriah Waterland * 3855c51f124SMoriah Waterland * Returns: 3865c51f124SMoriah Waterland * < 0 - An error returned. Call ERR_get_error() to get errors information. 3875c51f124SMoriah Waterland * Where possible, memory has been freed. 3885c51f124SMoriah Waterland * >= 0 - Objects were found and returned. Which objects are indicated by 3895c51f124SMoriah Waterland * which bits are set (FOUND_PKEY, FOUND_CERT) 3905c51f124SMoriah Waterland */ 3915c51f124SMoriah Waterland int sunw_PEM_contents(FILE *fp, pem_password_cb *cb, void *userdata, 3925c51f124SMoriah Waterland STACK_OF(EVP_PKEY) **pkey, STACK_OF(X509) **certs) 3935c51f124SMoriah Waterland { 3945c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *work_kl = NULL; 3955c51f124SMoriah Waterland STACK_OF(X509) *work_ca = NULL; 3965c51f124SMoriah Waterland int retval = -1; 3975c51f124SMoriah Waterland 3985c51f124SMoriah Waterland /* 3995c51f124SMoriah Waterland * Allocate the working stacks for private key and for the 4005c51f124SMoriah Waterland * ca certs. 4015c51f124SMoriah Waterland */ 4025c51f124SMoriah Waterland if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) { 4035c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE); 4045c51f124SMoriah Waterland goto cleanup; 4055c51f124SMoriah Waterland } 4065c51f124SMoriah Waterland 4075c51f124SMoriah Waterland if ((work_ca = sk_X509_new_null()) == NULL) { 4085c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_CONTENTS, SUNW_R_MEMORY_FAILURE); 4095c51f124SMoriah Waterland goto cleanup; 4105c51f124SMoriah Waterland } 4115c51f124SMoriah Waterland 4125c51f124SMoriah Waterland /* Error strings are set within the following. */ 4135c51f124SMoriah Waterland if (pem_info(fp, cb, userdata, &work_kl, &work_ca) <= 0) { 4145c51f124SMoriah Waterland goto cleanup; 4155c51f124SMoriah Waterland } 4165c51f124SMoriah Waterland 4175c51f124SMoriah Waterland /* on error, set_results() returns an error on the stack */ 4185c51f124SMoriah Waterland retval = set_results(pkey, &work_kl, certs, &work_ca, NULL, NULL, NULL, 4195c51f124SMoriah Waterland NULL); 4205c51f124SMoriah Waterland cleanup: 4215c51f124SMoriah Waterland if (work_kl != NULL) { 4225c51f124SMoriah Waterland sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free); 4235c51f124SMoriah Waterland } 4245c51f124SMoriah Waterland if (work_ca != NULL) 4255c51f124SMoriah Waterland sk_X509_pop_free(work_ca, X509_free); 4265c51f124SMoriah Waterland 4275c51f124SMoriah Waterland return (retval); 4285c51f124SMoriah Waterland } 4295c51f124SMoriah Waterland 4305c51f124SMoriah Waterland 4315c51f124SMoriah Waterland /* 4325c51f124SMoriah Waterland * sunw_PKCS12_contents() parses a pkcs#12 structure and returns component 4335c51f124SMoriah Waterland * parts found, without evaluation. 4345c51f124SMoriah Waterland * 4355c51f124SMoriah Waterland * Parse and decrypt a PKCS#12 structure returning any user keys and/or 4365c51f124SMoriah Waterland * various certs. Note these should either be NULL, *whatever should 4375c51f124SMoriah Waterland * be NULL, or it should point to a valid STACK_OF(X509) structure. 4385c51f124SMoriah Waterland * 4395c51f124SMoriah Waterland * Arguments: 4405c51f124SMoriah Waterland * p12 - Structure with pkcs12 info to be parsed 4415c51f124SMoriah Waterland * pass - Pass phrase for the private key and entire pkcs12 wad (possibly 4425c51f124SMoriah Waterland * empty) or NULL if there is none. 4435c51f124SMoriah Waterland * pkeys - Points to address of a stack of private keys to return. 4445c51f124SMoriah Waterland * certs - Points to address of a stack of client certs return. 4455c51f124SMoriah Waterland * 4465c51f124SMoriah Waterland * Note: The certs and keys being returned are in random order. 4475c51f124SMoriah Waterland * 4485c51f124SMoriah Waterland * Returns: 4495c51f124SMoriah Waterland * < 0 - An error returned. Call ERR_get_error() to get errors information. 4505c51f124SMoriah Waterland * Where possible, memory has been freed. 4515c51f124SMoriah Waterland * >= 0 - Objects were found and returned. Which objects are indicated by 4525c51f124SMoriah Waterland * which bits are set (FOUND_PKEY or FOUND_CERT) 4535c51f124SMoriah Waterland */ 4545c51f124SMoriah Waterland int 4555c51f124SMoriah Waterland sunw_PKCS12_contents(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) **pkey, 4565c51f124SMoriah Waterland STACK_OF(X509) **certs) 4575c51f124SMoriah Waterland { 4585c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *work_kl = NULL; 4595c51f124SMoriah Waterland STACK_OF(X509) *work_ca = NULL; 4605c51f124SMoriah Waterland int retval = -1; 4615c51f124SMoriah Waterland 4625c51f124SMoriah Waterland /* 4635c51f124SMoriah Waterland * Allocate the working stacks for private key and for the 4645c51f124SMoriah Waterland * ca certs. 4655c51f124SMoriah Waterland */ 4665c51f124SMoriah Waterland if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) { 4675c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE); 4685c51f124SMoriah Waterland goto cleanup; 4695c51f124SMoriah Waterland } 4705c51f124SMoriah Waterland 4715c51f124SMoriah Waterland if ((work_ca = sk_X509_new_null()) == NULL) { 4725c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CONTENTS, SUNW_R_MEMORY_FAILURE); 4735c51f124SMoriah Waterland goto cleanup; 4745c51f124SMoriah Waterland } 4755c51f124SMoriah Waterland 4765c51f124SMoriah Waterland if (parse_outer(p12, pass, work_kl, work_ca) == 0) { 4775c51f124SMoriah Waterland /* 4785c51f124SMoriah Waterland * Error already on stack 4795c51f124SMoriah Waterland */ 4805c51f124SMoriah Waterland goto cleanup; 4815c51f124SMoriah Waterland } 4825c51f124SMoriah Waterland 4835c51f124SMoriah Waterland /* on error, set_results() returns an error on the stack */ 4845c51f124SMoriah Waterland retval = set_results(pkey, &work_kl, certs, &work_ca, NULL, 4855c51f124SMoriah Waterland NULL, NULL, NULL); 4865c51f124SMoriah Waterland 4875c51f124SMoriah Waterland cleanup: 4885c51f124SMoriah Waterland if (work_kl != NULL) { 4895c51f124SMoriah Waterland sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free); 4905c51f124SMoriah Waterland } 4915c51f124SMoriah Waterland 4925c51f124SMoriah Waterland return (retval); 4935c51f124SMoriah Waterland } 4945c51f124SMoriah Waterland 4955c51f124SMoriah Waterland 4965c51f124SMoriah Waterland 4975c51f124SMoriah Waterland /* 4985c51f124SMoriah Waterland * sunw_split_certs() - Given a list of certs and a list of private keys, 4995c51f124SMoriah Waterland * moves certs which match one of the keys to a different stack. 5005c51f124SMoriah Waterland * 5015c51f124SMoriah Waterland * Arguments: 5025c51f124SMoriah Waterland * allkeys - Points to a stack of private keys to search. 5035c51f124SMoriah Waterland * allcerts - Points to a stack of certs to be searched. 5045c51f124SMoriah Waterland * keycerts - Points to address of a stack of certs with matching private 5055c51f124SMoriah Waterland * keys. They are moved from 'allcerts'. This may not be NULL 5065c51f124SMoriah Waterland * when called. If *keycerts is NULL upon entry, a new stack will 5075c51f124SMoriah Waterland * be allocated. Otherwise, it must be a valid STACK_OF(509). 5085c51f124SMoriah Waterland * nocerts - Points to address of a stack for keys which have no matching 5095c51f124SMoriah Waterland * certs. Keys are moved from 'allkeys' here when they have no 5105c51f124SMoriah Waterland * matching certs. If this is NULL, matchless keys will be 5115c51f124SMoriah Waterland * discarded. 5125c51f124SMoriah Waterland * 5135c51f124SMoriah Waterland * Notes: If an error occurs while moving certs, the cert being move may be 5145c51f124SMoriah Waterland * lost. 'keycerts' may only contain part of the matching certs. The number 5155c51f124SMoriah Waterland * of certs successfully moved can be found by checking sk_X509_num(keycerts). 5165c51f124SMoriah Waterland * 5175c51f124SMoriah Waterland * If there is a key which does not have a matching cert, it is moved to 5185c51f124SMoriah Waterland * the list nocerts. 5195c51f124SMoriah Waterland * 5205c51f124SMoriah Waterland * If all certs are removed from 'certs' and/or 'pkeys', it will be the 5215c51f124SMoriah Waterland * caller's responsibility to free the empty stacks. 5225c51f124SMoriah Waterland * 5235c51f124SMoriah Waterland * Returns: 5245c51f124SMoriah Waterland * < 0 - An error returned. Call ERR_get_error() to get errors information. 5255c51f124SMoriah Waterland * Where possible, memory has been freed. 5265c51f124SMoriah Waterland * >= 0 - The number of certs moved from 'cert' to 'pkcerts'. 5275c51f124SMoriah Waterland */ 5285c51f124SMoriah Waterland int 5295c51f124SMoriah Waterland sunw_split_certs(STACK_OF(EVP_PKEY) *allkeys, STACK_OF(X509) *allcerts, 5305c51f124SMoriah Waterland STACK_OF(X509) **keycerts, STACK_OF(EVP_PKEY) **nocerts) 5315c51f124SMoriah Waterland { 5325c51f124SMoriah Waterland STACK_OF(X509) *matching; 5335c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *nomatch; 5345c51f124SMoriah Waterland EVP_PKEY *tmpkey; 5355c51f124SMoriah Waterland X509 *tmpcert; 5365c51f124SMoriah Waterland int count = 0; 5375c51f124SMoriah Waterland int found; 5385c51f124SMoriah Waterland int res; 5395c51f124SMoriah Waterland int i; 5405c51f124SMoriah Waterland int k; 5415c51f124SMoriah Waterland 5425c51f124SMoriah Waterland *keycerts = NULL; 5435c51f124SMoriah Waterland if (nocerts != NULL) 5445c51f124SMoriah Waterland *nocerts = NULL; 5455c51f124SMoriah Waterland nomatch = NULL; 5465c51f124SMoriah Waterland 5475c51f124SMoriah Waterland if ((matching = sk_X509_new_null()) == NULL) { 5485c51f124SMoriah Waterland SUNWerr(SUNW_F_SPLIT_CERTS, SUNW_R_MEMORY_FAILURE); 5495c51f124SMoriah Waterland return (-1); 5505c51f124SMoriah Waterland } 5515c51f124SMoriah Waterland *keycerts = matching; 5525c51f124SMoriah Waterland 5535c51f124SMoriah Waterland k = 0; 5545c51f124SMoriah Waterland while (k < sk_EVP_PKEY_num(allkeys)) { 5555c51f124SMoriah Waterland found = 0; 5565c51f124SMoriah Waterland tmpkey = sk_EVP_PKEY_value(allkeys, k); 5575c51f124SMoriah Waterland 5585c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(allcerts); i++) { 5595c51f124SMoriah Waterland tmpcert = sk_X509_value(allcerts, i); 5605c51f124SMoriah Waterland res = X509_check_private_key(tmpcert, tmpkey); 5615c51f124SMoriah Waterland if (res != 0) { 5625c51f124SMoriah Waterland count++; 5635c51f124SMoriah Waterland found = 1; 5645c51f124SMoriah Waterland tmpcert = sk_X509_delete(allcerts, i); 5655c51f124SMoriah Waterland if (sk_X509_push(matching, tmpcert) == 0) { 5665c51f124SMoriah Waterland X509_free(tmpcert); 5675c51f124SMoriah Waterland SUNWerr(SUNW_F_SPLIT_CERTS, 5685c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 5695c51f124SMoriah Waterland return (-1); 5705c51f124SMoriah Waterland } 5715c51f124SMoriah Waterland break; 5725c51f124SMoriah Waterland } 5735c51f124SMoriah Waterland } 5745c51f124SMoriah Waterland if (found != 0) { 5755c51f124SMoriah Waterland /* 5765c51f124SMoriah Waterland * Found a match - keep the key & check out the next 5775c51f124SMoriah Waterland * one. 5785c51f124SMoriah Waterland */ 5795c51f124SMoriah Waterland k++; 5805c51f124SMoriah Waterland } else { 5815c51f124SMoriah Waterland /* 5825c51f124SMoriah Waterland * No cert matching this key. Move the key if 5835c51f124SMoriah Waterland * possible or discard it. Don't increment the 5845c51f124SMoriah Waterland * index. 5855c51f124SMoriah Waterland */ 5865c51f124SMoriah Waterland if (nocerts == NULL) { 5875c51f124SMoriah Waterland tmpkey = sk_EVP_PKEY_delete(allkeys, k); 5885c51f124SMoriah Waterland sunw_evp_pkey_free(tmpkey); 5895c51f124SMoriah Waterland } else { 5905c51f124SMoriah Waterland if (*nocerts == NULL) { 5915c51f124SMoriah Waterland nomatch = sk_EVP_PKEY_new_null(); 5925c51f124SMoriah Waterland if (nomatch == NULL) { 5935c51f124SMoriah Waterland SUNWerr(SUNW_F_SPLIT_CERTS, 5945c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 5955c51f124SMoriah Waterland return (-1); 5965c51f124SMoriah Waterland } 5975c51f124SMoriah Waterland *nocerts = nomatch; 5985c51f124SMoriah Waterland } 5995c51f124SMoriah Waterland tmpkey = sk_EVP_PKEY_delete(allkeys, k); 6005c51f124SMoriah Waterland if (sk_EVP_PKEY_push(nomatch, tmpkey) == 0) { 6015c51f124SMoriah Waterland sunw_evp_pkey_free(tmpkey); 6025c51f124SMoriah Waterland SUNWerr(SUNW_F_SPLIT_CERTS, 6035c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 6045c51f124SMoriah Waterland return (-1); 6055c51f124SMoriah Waterland } 6065c51f124SMoriah Waterland } 6075c51f124SMoriah Waterland } 6085c51f124SMoriah Waterland } 6095c51f124SMoriah Waterland 6105c51f124SMoriah Waterland return (count); 6115c51f124SMoriah Waterland } 6125c51f124SMoriah Waterland 6135c51f124SMoriah Waterland /* 6145c51f124SMoriah Waterland * sunw_PKCS12_create() creates a pkcs#12 structure and given component parts. 6155c51f124SMoriah Waterland * 6165c51f124SMoriah Waterland * Given one or more of user private key, user cert and/or other (CA) certs, 6175c51f124SMoriah Waterland * return an encrypted PKCS12 structure containing them. 6185c51f124SMoriah Waterland * 6195c51f124SMoriah Waterland * Arguments: 6205c51f124SMoriah Waterland * pass - Pass phrase for the pkcs12 structure and private key (possibly 6215c51f124SMoriah Waterland * empty) or NULL if there is none. It will be used to encrypt 6225c51f124SMoriah Waterland * both the private key(s) and as the pass phrase for the whole 6235c51f124SMoriah Waterland * pkcs12 wad. 6245c51f124SMoriah Waterland * pkeys - Points to stack of private keys. 6255c51f124SMoriah Waterland * certs - Points to stack of client (public ke) certs 6265c51f124SMoriah Waterland * cacerts - Points to stack of 'certificate authority' certs (or trust 6275c51f124SMoriah Waterland * anchors). 6285c51f124SMoriah Waterland * 6295c51f124SMoriah Waterland * Note that any of these may be NULL. 6305c51f124SMoriah Waterland * 6315c51f124SMoriah Waterland * Returns: 6325c51f124SMoriah Waterland * NULL - An error occurred. 6335c51f124SMoriah Waterland * != NULL - Address of PKCS12 structure. The user is responsible for 6345c51f124SMoriah Waterland * freeing the memory when done. 6355c51f124SMoriah Waterland */ 6365c51f124SMoriah Waterland PKCS12 * 6375c51f124SMoriah Waterland sunw_PKCS12_create(const char *pass, STACK_OF(EVP_PKEY) *pkeys, 6385c51f124SMoriah Waterland STACK_OF(X509) *certs, STACK_OF(X509) *cacerts) 6395c51f124SMoriah Waterland { 6405c51f124SMoriah Waterland int nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC; 6415c51f124SMoriah Waterland int nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 6425c51f124SMoriah Waterland STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 6435c51f124SMoriah Waterland STACK_OF(PKCS7) *safes = NULL; 6445c51f124SMoriah Waterland PKCS12_SAFEBAG *bag = NULL; 6455c51f124SMoriah Waterland PKCS8_PRIV_KEY_INFO *p8 = NULL; 6465c51f124SMoriah Waterland EVP_PKEY *pkey = NULL; 6475c51f124SMoriah Waterland PKCS12 *ret_p12 = NULL; 6485c51f124SMoriah Waterland PKCS12 *p12 = NULL; 6495c51f124SMoriah Waterland PKCS7 *authsafe = NULL; 6505c51f124SMoriah Waterland X509 *cert = NULL; 6515c51f124SMoriah Waterland uchar_t *str = NULL; 6525c51f124SMoriah Waterland int certs_there = 0; 6535c51f124SMoriah Waterland int keys_there = 0; 6545c51f124SMoriah Waterland int len; 6555c51f124SMoriah Waterland int i; 6565c51f124SMoriah Waterland 6575c51f124SMoriah Waterland if ((safes = sk_PKCS7_new_null()) == NULL) { 6585c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 6595c51f124SMoriah Waterland return (NULL); 6605c51f124SMoriah Waterland } 6615c51f124SMoriah Waterland 6625c51f124SMoriah Waterland if ((bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) { 6635c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 6645c51f124SMoriah Waterland goto err_ret; 6655c51f124SMoriah Waterland } 6665c51f124SMoriah Waterland 6675c51f124SMoriah Waterland if (certs != NULL && sk_X509_num(certs) > 0) { 6685c51f124SMoriah Waterland 6695c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(certs); i++) { 6705c51f124SMoriah Waterland cert = sk_X509_value(certs, i); 6715c51f124SMoriah Waterland 6725c51f124SMoriah Waterland /* Add user certificate */ 6735c51f124SMoriah Waterland if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) { 6745c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR); 6755c51f124SMoriah Waterland goto err_ret; 6765c51f124SMoriah Waterland } 6775c51f124SMoriah Waterland if (cert->aux != NULL && cert->aux->alias != NULL && 6785c51f124SMoriah Waterland cert->aux->alias->type == V_ASN1_UTF8STRING) { 6795c51f124SMoriah Waterland str = utf82ascstr(cert->aux->alias); 6805c51f124SMoriah Waterland if (str == NULL) { 6815c51f124SMoriah Waterland /* 6825c51f124SMoriah Waterland * Error already on stack 6835c51f124SMoriah Waterland */ 6845c51f124SMoriah Waterland goto err_ret; 6855c51f124SMoriah Waterland } 6865c51f124SMoriah Waterland if (PKCS12_add_friendlyname_asc(bag, 6875c51f124SMoriah Waterland (char const *) str, 6885c51f124SMoriah Waterland strlen((char const *) str)) == 0) { 6895c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 6905c51f124SMoriah Waterland SUNW_R_ADD_ATTR_ERR); 6915c51f124SMoriah Waterland goto err_ret; 6925c51f124SMoriah Waterland } 6935c51f124SMoriah Waterland } 6945c51f124SMoriah Waterland if (cert->aux != NULL && cert->aux->keyid != NULL && 6955c51f124SMoriah Waterland cert->aux->keyid->type == V_ASN1_OCTET_STRING) { 6965c51f124SMoriah Waterland str = cert->aux->keyid->data; 6975c51f124SMoriah Waterland len = cert->aux->keyid->length; 6985c51f124SMoriah Waterland 6995c51f124SMoriah Waterland if (str != NULL && 7005c51f124SMoriah Waterland PKCS12_add_localkeyid(bag, str, len) == 0) { 7015c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 7025c51f124SMoriah Waterland SUNW_R_ADD_ATTR_ERR); 7035c51f124SMoriah Waterland goto err_ret; 7045c51f124SMoriah Waterland } 7055c51f124SMoriah Waterland } 7065c51f124SMoriah Waterland if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) { 7075c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 7085c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 7095c51f124SMoriah Waterland goto err_ret; 7105c51f124SMoriah Waterland } 7115c51f124SMoriah Waterland certs_there++; 7125c51f124SMoriah Waterland bag = NULL; 7135c51f124SMoriah Waterland } 7145c51f124SMoriah Waterland } 7155c51f124SMoriah Waterland 7165c51f124SMoriah Waterland if (cacerts != NULL && sk_X509_num(cacerts) > 0) { 7175c51f124SMoriah Waterland 7185c51f124SMoriah Waterland /* Put all certs in structure */ 7195c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(cacerts); i++) { 7205c51f124SMoriah Waterland cert = sk_X509_value(cacerts, i); 7215c51f124SMoriah Waterland if ((bag = M_PKCS12_x5092certbag(cert)) == NULL) { 7225c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR); 7235c51f124SMoriah Waterland goto err_ret; 7245c51f124SMoriah Waterland } 7255c51f124SMoriah Waterland 7265c51f124SMoriah Waterland if (cert->aux != NULL && cert->aux->alias != NULL && 7275c51f124SMoriah Waterland cert->aux->alias->type == V_ASN1_UTF8STRING) { 7285c51f124SMoriah Waterland str = utf82ascstr(cert->aux->alias); 7295c51f124SMoriah Waterland if (str == NULL) { 7305c51f124SMoriah Waterland /* 7315c51f124SMoriah Waterland * Error already on stack 7325c51f124SMoriah Waterland */ 7335c51f124SMoriah Waterland goto err_ret; 7345c51f124SMoriah Waterland } 7355c51f124SMoriah Waterland if (PKCS12_add_friendlyname_asc( 7365c51f124SMoriah Waterland bag, (char const *) str, 7375c51f124SMoriah Waterland strlen((char const *) str)) == 0) { 7385c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 7395c51f124SMoriah Waterland SUNW_R_ADD_ATTR_ERR); 7405c51f124SMoriah Waterland goto err_ret; 7415c51f124SMoriah Waterland } 7425c51f124SMoriah Waterland } 7435c51f124SMoriah Waterland if (cert->aux != NULL && cert->aux->keyid != NULL && 7445c51f124SMoriah Waterland cert->aux->keyid->type == V_ASN1_OCTET_STRING) { 7455c51f124SMoriah Waterland str = cert->aux->keyid->data; 7465c51f124SMoriah Waterland len = cert->aux->keyid->length; 7475c51f124SMoriah Waterland 7485c51f124SMoriah Waterland if (str != NULL && 7495c51f124SMoriah Waterland PKCS12_add_localkeyid(bag, str, len) == 0) { 7505c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 7515c51f124SMoriah Waterland SUNW_R_ADD_ATTR_ERR); 7525c51f124SMoriah Waterland goto err_ret; 7535c51f124SMoriah Waterland } 7545c51f124SMoriah Waterland } 7555c51f124SMoriah Waterland if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) { 7565c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 7575c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 7585c51f124SMoriah Waterland goto err_ret; 7595c51f124SMoriah Waterland } 7605c51f124SMoriah Waterland certs_there++; 7615c51f124SMoriah Waterland bag = NULL; 7625c51f124SMoriah Waterland } 7635c51f124SMoriah Waterland } 7645c51f124SMoriah Waterland 7655c51f124SMoriah Waterland if (certs != NULL || cacerts != NULL && certs_there) { 7665c51f124SMoriah Waterland /* Turn certbags into encrypted authsafe */ 7675c51f124SMoriah Waterland authsafe = PKCS12_pack_p7encdata(nid_cert, pass, -1, 7685c51f124SMoriah Waterland NULL, 0, PKCS12_DEFAULT_ITER, bags); 7695c51f124SMoriah Waterland if (authsafe == NULL) { 7705c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_CERT_ERR); 7715c51f124SMoriah Waterland goto err_ret; 7725c51f124SMoriah Waterland } 7735c51f124SMoriah Waterland sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 7745c51f124SMoriah Waterland bags = NULL; 7755c51f124SMoriah Waterland 7765c51f124SMoriah Waterland if (sk_PKCS7_push(safes, authsafe) == 0) { 7775c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 7785c51f124SMoriah Waterland goto err_ret; 7795c51f124SMoriah Waterland } 7805c51f124SMoriah Waterland authsafe = NULL; 7815c51f124SMoriah Waterland } 7825c51f124SMoriah Waterland 7835c51f124SMoriah Waterland if (pkeys != NULL && sk_EVP_PKEY_num(pkeys) > 0) { 7845c51f124SMoriah Waterland 7855c51f124SMoriah Waterland if (bags == NULL && 7865c51f124SMoriah Waterland (bags = sk_PKCS12_SAFEBAG_new_null()) == NULL) { 7875c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MEMORY_FAILURE); 7885c51f124SMoriah Waterland goto err_ret; 7895c51f124SMoriah Waterland } 7905c51f124SMoriah Waterland 7915c51f124SMoriah Waterland for (i = 0; i < sk_EVP_PKEY_num(pkeys); i++) { 7925c51f124SMoriah Waterland 7935c51f124SMoriah Waterland pkey = sk_EVP_PKEY_value(pkeys, i); 7945c51f124SMoriah Waterland 7955c51f124SMoriah Waterland /* Make a shrouded key bag */ 7965c51f124SMoriah Waterland if ((p8 = EVP_PKEY2PKCS8(pkey)) == NULL) { 7975c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKEY_ERR); 7985c51f124SMoriah Waterland goto err_ret; 7995c51f124SMoriah Waterland } 8005c51f124SMoriah Waterland 8015c51f124SMoriah Waterland bag = PKCS12_MAKE_SHKEYBAG(nid_key, pass, -1, NULL, 0, 8025c51f124SMoriah Waterland PKCS12_DEFAULT_ITER, p8); 8035c51f124SMoriah Waterland if (bag == NULL) { 8045c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 8055c51f124SMoriah Waterland SUNW_R_MAKE_BAG_ERR); 8065c51f124SMoriah Waterland goto err_ret; 8075c51f124SMoriah Waterland } 8085c51f124SMoriah Waterland PKCS8_PRIV_KEY_INFO_free(p8); 8095c51f124SMoriah Waterland p8 = NULL; 8105c51f124SMoriah Waterland 8115c51f124SMoriah Waterland len = sunw_get_pkey_fname(GETDO_COPY, pkey, 8125c51f124SMoriah Waterland (char **)&str); 8135c51f124SMoriah Waterland if (str != NULL) { 8145c51f124SMoriah Waterland if (PKCS12_add_friendlyname_asc(bag, 8155c51f124SMoriah Waterland (const char *)str, len) == 0) { 8165c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 8175c51f124SMoriah Waterland SUNW_R_ADD_ATTR_ERR); 8185c51f124SMoriah Waterland goto err_ret; 8195c51f124SMoriah Waterland } 8205c51f124SMoriah Waterland } 8215c51f124SMoriah Waterland str = NULL; 8225c51f124SMoriah Waterland 8235c51f124SMoriah Waterland len = sunw_get_pkey_localkeyid(GETDO_COPY, pkey, 8245c51f124SMoriah Waterland (char **)&str, &len); 8255c51f124SMoriah Waterland if (str != NULL) { 8265c51f124SMoriah Waterland if (PKCS12_add_localkeyid(bag, str, len) == 0) { 8275c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 8285c51f124SMoriah Waterland SUNW_R_ADD_ATTR_ERR); 8295c51f124SMoriah Waterland goto err_ret; 8305c51f124SMoriah Waterland } 8315c51f124SMoriah Waterland } 8325c51f124SMoriah Waterland str = NULL; 8335c51f124SMoriah Waterland 8345c51f124SMoriah Waterland if (sk_PKCS12_SAFEBAG_push(bags, bag) == 0) { 8355c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 8365c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 8375c51f124SMoriah Waterland goto err_ret; 8385c51f124SMoriah Waterland } 8395c51f124SMoriah Waterland keys_there++; 8405c51f124SMoriah Waterland bag = NULL; 8415c51f124SMoriah Waterland } 8425c51f124SMoriah Waterland 8435c51f124SMoriah Waterland if (keys_there) { 8445c51f124SMoriah Waterland /* Turn into unencrypted authsafe */ 8455c51f124SMoriah Waterland authsafe = PKCS12_pack_p7data(bags); 8465c51f124SMoriah Waterland if (authsafe == NULL) { 8475c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 8485c51f124SMoriah Waterland SUNW_R_PKCS12_CREATE_ERR); 8495c51f124SMoriah Waterland goto err_ret; 8505c51f124SMoriah Waterland } 8515c51f124SMoriah Waterland sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 8525c51f124SMoriah Waterland bags = NULL; 8535c51f124SMoriah Waterland 8545c51f124SMoriah Waterland if (sk_PKCS7_push(safes, authsafe) == 0) { 8555c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, 8565c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 8575c51f124SMoriah Waterland } 8585c51f124SMoriah Waterland authsafe = NULL; 8595c51f124SMoriah Waterland } 8605c51f124SMoriah Waterland } 8615c51f124SMoriah Waterland 8625c51f124SMoriah Waterland if (certs_there == 0 && keys_there == 0) { 8635c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_EMPTY_ERR); 8645c51f124SMoriah Waterland goto err_ret; 8655c51f124SMoriah Waterland } 8665c51f124SMoriah Waterland 8675c51f124SMoriah Waterland if ((p12 = PKCS12_init(NID_pkcs7_data)) == NULL) { 8685c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR); 8695c51f124SMoriah Waterland goto err_ret; 8705c51f124SMoriah Waterland } 8715c51f124SMoriah Waterland 8725c51f124SMoriah Waterland /* 8735c51f124SMoriah Waterland * Note that safes is copied by the following. Therefore, it needs 8745c51f124SMoriah Waterland * to be freed whether or not the following succeeds. 8755c51f124SMoriah Waterland */ 8765c51f124SMoriah Waterland if (M_PKCS12_pack_authsafes(p12, safes) == 0) { 8775c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_PKCS12_CREATE_ERR); 8785c51f124SMoriah Waterland goto err_ret; 8795c51f124SMoriah Waterland } 8805c51f124SMoriah Waterland if (PKCS12_set_mac(p12, pass, -1, NULL, 0, 2048, NULL) == 0) { 8815c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_CREATE, SUNW_R_MAC_CREATE_FAILURE); 8825c51f124SMoriah Waterland goto err_ret; 8835c51f124SMoriah Waterland } 8845c51f124SMoriah Waterland 8855c51f124SMoriah Waterland ret_p12 = p12; 8865c51f124SMoriah Waterland p12 = NULL; 8875c51f124SMoriah Waterland 8885c51f124SMoriah Waterland /* Fallthrough is intentional */ 8895c51f124SMoriah Waterland 8905c51f124SMoriah Waterland err_ret: 8915c51f124SMoriah Waterland 8925c51f124SMoriah Waterland if (str != NULL) 8935c51f124SMoriah Waterland free(str); 8945c51f124SMoriah Waterland 8955c51f124SMoriah Waterland if (p8 != NULL) 8965c51f124SMoriah Waterland PKCS8_PRIV_KEY_INFO_free(p8); 8975c51f124SMoriah Waterland 8985c51f124SMoriah Waterland if (bag != NULL) 8995c51f124SMoriah Waterland PKCS12_SAFEBAG_free(bag); 9005c51f124SMoriah Waterland if (bags != NULL) 9015c51f124SMoriah Waterland sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 9025c51f124SMoriah Waterland if (authsafe != NULL) 9035c51f124SMoriah Waterland PKCS7_free(authsafe); 9045c51f124SMoriah Waterland if (safes != NULL) 9055c51f124SMoriah Waterland sk_PKCS7_pop_free(safes, PKCS7_free); 9065c51f124SMoriah Waterland if (p12 != NULL) 9075c51f124SMoriah Waterland PKCS12_free(p12); 9085c51f124SMoriah Waterland 9095c51f124SMoriah Waterland return (ret_p12); 9105c51f124SMoriah Waterland } 9115c51f124SMoriah Waterland 9125c51f124SMoriah Waterland /* 9135c51f124SMoriah Waterland * sunw_evp_pkey_free() Given an EVP_PKEY structure, free any attributes 9145c51f124SMoriah Waterland * that are attached. Then free the EVP_PKEY itself. 9155c51f124SMoriah Waterland * 9165c51f124SMoriah Waterland * This is a replacement for EVP_PKEY_free() for the sunw stuff. 9175c51f124SMoriah Waterland * It should be used in places where EVP_PKEY_free would be used, 9185c51f124SMoriah Waterland * including calls to sk_EVP_PKEY_pop_free(). 9195c51f124SMoriah Waterland * 9205c51f124SMoriah Waterland * Arguments: 9215c51f124SMoriah Waterland * pkey - Entry which potentially has attributes to be freed. 9225c51f124SMoriah Waterland * 9235c51f124SMoriah Waterland * Returns: 9245c51f124SMoriah Waterland * None. 9255c51f124SMoriah Waterland */ 9265c51f124SMoriah Waterland void 9275c51f124SMoriah Waterland sunw_evp_pkey_free(EVP_PKEY *pkey) 9285c51f124SMoriah Waterland { 9295c51f124SMoriah Waterland if (pkey != NULL) { 9305c51f124SMoriah Waterland if (pkey->attributes != NULL) { 9315c51f124SMoriah Waterland sk_X509_ATTRIBUTE_pop_free(pkey->attributes, 9325c51f124SMoriah Waterland X509_ATTRIBUTE_free); 9335c51f124SMoriah Waterland pkey->attributes = NULL; 9345c51f124SMoriah Waterland } 9355c51f124SMoriah Waterland EVP_PKEY_free(pkey); 9365c51f124SMoriah Waterland } 9375c51f124SMoriah Waterland } 9385c51f124SMoriah Waterland 9395c51f124SMoriah Waterland /* 9405c51f124SMoriah Waterland * sunw_set_localkeyid() sets the localkeyid in a cert, a private key or 9415c51f124SMoriah Waterland * both. Any existing localkeyid will be discarded. 9425c51f124SMoriah Waterland * 9435c51f124SMoriah Waterland * Arguments: 9445c51f124SMoriah Waterland * keyid_str- A byte string with the localkeyid to set 9455c51f124SMoriah Waterland * keyid_len- Length of the keyid byte string. 9465c51f124SMoriah Waterland * pkey - Points to a private key to set the keyidstr in. 9475c51f124SMoriah Waterland * cert - Points to a cert to set the keyidstr in. 9485c51f124SMoriah Waterland * 9495c51f124SMoriah Waterland * Note that setting a keyid into a cert which will not be written out as 9505c51f124SMoriah Waterland * a PKCS12 cert is pointless since it will be lost. 9515c51f124SMoriah Waterland * 9525c51f124SMoriah Waterland * Returns: 9535c51f124SMoriah Waterland * 0 - Success. 9545c51f124SMoriah Waterland * < 0 - An error occurred. It was probably an error in allocating 9555c51f124SMoriah Waterland * memory. The error will be set in the error stack. Call 9565c51f124SMoriah Waterland * ERR_get_error() to get specific information. 9575c51f124SMoriah Waterland */ 9585c51f124SMoriah Waterland int 9595c51f124SMoriah Waterland sunw_set_localkeyid(const char *keyid_str, int keyid_len, EVP_PKEY *pkey, 9605c51f124SMoriah Waterland X509 *cert) 9615c51f124SMoriah Waterland { 9625c51f124SMoriah Waterland X509_ATTRIBUTE *attr = NULL; 9635c51f124SMoriah Waterland ASN1_STRING *str = NULL; 9645c51f124SMoriah Waterland ASN1_TYPE *keyid = NULL; 9655c51f124SMoriah Waterland int retval = -1; 9665c51f124SMoriah Waterland int i; 9675c51f124SMoriah Waterland 9685c51f124SMoriah Waterland if (cert != NULL) { 9695c51f124SMoriah Waterland if (X509_keyid_set1(cert, (uchar_t *)keyid_str, keyid_len) 9705c51f124SMoriah Waterland == 0) { 9715c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_SET_LKID_ERR); 9725c51f124SMoriah Waterland goto cleanup; 9735c51f124SMoriah Waterland } 9745c51f124SMoriah Waterland } 9755c51f124SMoriah Waterland if (pkey != NULL) { 9765c51f124SMoriah Waterland str = (ASN1_STRING *)M_ASN1_OCTET_STRING_new(); 9775c51f124SMoriah Waterland if (str == NULL || 9785c51f124SMoriah Waterland M_ASN1_OCTET_STRING_set(str, keyid_str, keyid_len) == 0 || 9795c51f124SMoriah Waterland (keyid = ASN1_TYPE_new()) == NULL) { 9805c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE); 9815c51f124SMoriah Waterland goto cleanup; 9825c51f124SMoriah Waterland } 9835c51f124SMoriah Waterland 9845c51f124SMoriah Waterland ASN1_TYPE_set(keyid, V_ASN1_OCTET_STRING, str); 9855c51f124SMoriah Waterland str = NULL; 9865c51f124SMoriah Waterland 9875c51f124SMoriah Waterland attr = type2attrib(keyid, NID_localKeyID); 9885c51f124SMoriah Waterland if (attr == NULL) { 9895c51f124SMoriah Waterland /* 9905c51f124SMoriah Waterland * Error already on stack 9915c51f124SMoriah Waterland */ 9925c51f124SMoriah Waterland goto cleanup; 9935c51f124SMoriah Waterland } 9945c51f124SMoriah Waterland keyid = NULL; 9955c51f124SMoriah Waterland 9965c51f124SMoriah Waterland if (pkey->attributes == NULL) { 9975c51f124SMoriah Waterland pkey->attributes = sk_X509_ATTRIBUTE_new_null(); 9985c51f124SMoriah Waterland if (pkey->attributes == NULL) { 9995c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_LOCALKEYID, 10005c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 10015c51f124SMoriah Waterland goto cleanup; 10025c51f124SMoriah Waterland } 10035c51f124SMoriah Waterland } else { 10045c51f124SMoriah Waterland i = find_attr_by_nid(pkey->attributes, NID_localKeyID); 10055c51f124SMoriah Waterland if (i >= 0) 10065c51f124SMoriah Waterland sk_X509_ATTRIBUTE_delete(pkey->attributes, i); 10075c51f124SMoriah Waterland } 10085c51f124SMoriah Waterland if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) { 10095c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_LOCALKEYID, SUNW_R_MEMORY_FAILURE); 10105c51f124SMoriah Waterland goto cleanup; 10115c51f124SMoriah Waterland } 10125c51f124SMoriah Waterland attr = NULL; 10135c51f124SMoriah Waterland } 10145c51f124SMoriah Waterland retval = 0; 10155c51f124SMoriah Waterland 10165c51f124SMoriah Waterland cleanup: 10175c51f124SMoriah Waterland if (str != NULL) 10185c51f124SMoriah Waterland ASN1_STRING_free(str); 10195c51f124SMoriah Waterland if (keyid != NULL) 10205c51f124SMoriah Waterland ASN1_TYPE_free(keyid); 10215c51f124SMoriah Waterland if (attr != NULL) 10225c51f124SMoriah Waterland X509_ATTRIBUTE_free(attr); 10235c51f124SMoriah Waterland 10245c51f124SMoriah Waterland return (retval); 10255c51f124SMoriah Waterland } 10265c51f124SMoriah Waterland 10275c51f124SMoriah Waterland /* 10285c51f124SMoriah Waterland * sunw_get_pkey_localkeyid() gets the localkeyid from a private key. It can 10295c51f124SMoriah Waterland * optionally remove the value found. 10305c51f124SMoriah Waterland * 10315c51f124SMoriah Waterland * Arguments: 10325c51f124SMoriah Waterland * dowhat - What to do with the attributes (remove them or copy them). 10335c51f124SMoriah Waterland * pkey - Points to a private key to set the keyidstr in. 10345c51f124SMoriah Waterland * keyid_str- Points to a location which will receive the pointer to 10355c51f124SMoriah Waterland * a byte string containing the binary localkeyid. Note that 10365c51f124SMoriah Waterland * this is a copy, and the caller must free it. 10375c51f124SMoriah Waterland * keyid_len- Length of keyid_str. 10385c51f124SMoriah Waterland * 10395c51f124SMoriah Waterland * Returns: 10405c51f124SMoriah Waterland * >= 0 - The number of characters in the keyid returned. 10415c51f124SMoriah Waterland * < 0 - An error occurred. It was probably an error in allocating 10425c51f124SMoriah Waterland * memory. The error will be set in the error stack. Call 10435c51f124SMoriah Waterland * ERR_get_error() to get specific information. 10445c51f124SMoriah Waterland */ 10455c51f124SMoriah Waterland int 10465c51f124SMoriah Waterland sunw_get_pkey_localkeyid(getdo_actions_t dowhat, EVP_PKEY *pkey, 10475c51f124SMoriah Waterland char **keyid_str, int *keyid_len) 10485c51f124SMoriah Waterland { 10495c51f124SMoriah Waterland X509_ATTRIBUTE *attr = NULL; 10505c51f124SMoriah Waterland ASN1_OCTET_STRING *str = NULL; 10515c51f124SMoriah Waterland ASN1_TYPE *ty = NULL; 10525c51f124SMoriah Waterland int len = 0; 10535c51f124SMoriah Waterland int i; 10545c51f124SMoriah Waterland 10555c51f124SMoriah Waterland if (keyid_str != NULL) 10565c51f124SMoriah Waterland *keyid_str = NULL; 10575c51f124SMoriah Waterland if (keyid_len != NULL) 10585c51f124SMoriah Waterland *keyid_len = 0; 10595c51f124SMoriah Waterland 10605c51f124SMoriah Waterland if (pkey == NULL || pkey->attributes == NULL) { 10615c51f124SMoriah Waterland return (0); 10625c51f124SMoriah Waterland } 10635c51f124SMoriah Waterland 10645c51f124SMoriah Waterland if ((i = find_attr_by_nid(pkey->attributes, NID_localKeyID)) < 0) { 10655c51f124SMoriah Waterland return (0); 10665c51f124SMoriah Waterland } 10675c51f124SMoriah Waterland attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i); 10685c51f124SMoriah Waterland 10695c51f124SMoriah Waterland if ((ty = attrib2type(attr)) == NULL || 10705c51f124SMoriah Waterland ty->type != V_ASN1_OCTET_STRING) { 10715c51f124SMoriah Waterland return (0); 10725c51f124SMoriah Waterland } 10735c51f124SMoriah Waterland 10745c51f124SMoriah Waterland if (dowhat == GETDO_DEL) { 10755c51f124SMoriah Waterland attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i); 10765c51f124SMoriah Waterland if (attr != NULL) 10775c51f124SMoriah Waterland X509_ATTRIBUTE_free(attr); 10785c51f124SMoriah Waterland return (0); 10795c51f124SMoriah Waterland } 10805c51f124SMoriah Waterland 10815c51f124SMoriah Waterland str = ty->value.octet_string; 10825c51f124SMoriah Waterland len = str->length; 10835c51f124SMoriah Waterland if ((*keyid_str = malloc(len)) == NULL) { 10845c51f124SMoriah Waterland SUNWerr(SUNW_F_GET_LOCALKEYID, SUNW_R_MEMORY_FAILURE); 10855c51f124SMoriah Waterland return (-1); 10865c51f124SMoriah Waterland } 10875c51f124SMoriah Waterland 10885c51f124SMoriah Waterland (void) memcpy(*keyid_str, str->data, len); 10895c51f124SMoriah Waterland *keyid_len = len; 10905c51f124SMoriah Waterland 10915c51f124SMoriah Waterland return (len); 10925c51f124SMoriah Waterland } 10935c51f124SMoriah Waterland 10945c51f124SMoriah Waterland /* 10955c51f124SMoriah Waterland * sunw_get_pkey_fname() gets the friendlyName from a private key. It can 10965c51f124SMoriah Waterland * optionally remove the value found. 10975c51f124SMoriah Waterland * 10985c51f124SMoriah Waterland * Arguments: 10995c51f124SMoriah Waterland * dowhat - What to do with the attributes (remove them or copy them). 11005c51f124SMoriah Waterland * pkey - Points to a private key to get the frientlyname from 11015c51f124SMoriah Waterland * fname - Points to a location which will receive the pointer to a 11025c51f124SMoriah Waterland * byte string with the ASCII friendlyname 11035c51f124SMoriah Waterland * 11045c51f124SMoriah Waterland * Returns: 11055c51f124SMoriah Waterland * >= 0 - The number of characters in the frienlyname returned. 11065c51f124SMoriah Waterland * < 0 - An error occurred. It was probably an error in allocating 11075c51f124SMoriah Waterland * memory. The error will be set in the error stack. Call 11085c51f124SMoriah Waterland * ERR_get_error() to get specific information. 11095c51f124SMoriah Waterland */ 11105c51f124SMoriah Waterland int 11115c51f124SMoriah Waterland sunw_get_pkey_fname(getdo_actions_t dowhat, EVP_PKEY *pkey, char **fname) 11125c51f124SMoriah Waterland { 11135c51f124SMoriah Waterland X509_ATTRIBUTE *attr = NULL; 11145c51f124SMoriah Waterland ASN1_BMPSTRING *str = NULL; 11155c51f124SMoriah Waterland ASN1_TYPE *ty = NULL; 11165c51f124SMoriah Waterland int len = 0; 11175c51f124SMoriah Waterland int i; 11185c51f124SMoriah Waterland 11195c51f124SMoriah Waterland if (fname != NULL) 11205c51f124SMoriah Waterland *fname = NULL; 11215c51f124SMoriah Waterland 11225c51f124SMoriah Waterland if (pkey == NULL || pkey->attributes == NULL) { 11235c51f124SMoriah Waterland return (0); 11245c51f124SMoriah Waterland } 11255c51f124SMoriah Waterland 11265c51f124SMoriah Waterland if ((i = find_attr_by_nid(pkey->attributes, NID_friendlyName)) < 0) { 11275c51f124SMoriah Waterland return (0); 11285c51f124SMoriah Waterland } 11295c51f124SMoriah Waterland attr = sk_X509_ATTRIBUTE_value(pkey->attributes, i); 11305c51f124SMoriah Waterland 11315c51f124SMoriah Waterland if ((ty = attrib2type(attr)) == NULL || 11325c51f124SMoriah Waterland ty->type != V_ASN1_BMPSTRING) { 11335c51f124SMoriah Waterland return (0); 11345c51f124SMoriah Waterland } 11355c51f124SMoriah Waterland 11365c51f124SMoriah Waterland if (dowhat == GETDO_DEL) { 11375c51f124SMoriah Waterland attr = sk_X509_ATTRIBUTE_delete(pkey->attributes, i); 11385c51f124SMoriah Waterland if (attr != NULL) 11395c51f124SMoriah Waterland X509_ATTRIBUTE_free(attr); 11405c51f124SMoriah Waterland return (0); 11415c51f124SMoriah Waterland } 11425c51f124SMoriah Waterland 11435c51f124SMoriah Waterland str = ty->value.bmpstring; 1144*70f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L 11455c51f124SMoriah Waterland *fname = uni2asc(str->data, str->length); 1146*70f9559bSTheo Schlossnagle #else 1147*70f9559bSTheo Schlossnagle *fname = OPENSSL_uni2asc(str->data, str->length); 1148*70f9559bSTheo Schlossnagle #endif 11495c51f124SMoriah Waterland if (*fname == NULL) { 11505c51f124SMoriah Waterland SUNWerr(SUNW_F_GET_PKEY_FNAME, SUNW_R_MEMORY_FAILURE); 11515c51f124SMoriah Waterland return (-1); 11525c51f124SMoriah Waterland } 11535c51f124SMoriah Waterland 11545c51f124SMoriah Waterland len = strlen(*fname); 11555c51f124SMoriah Waterland 11565c51f124SMoriah Waterland return (len); 11575c51f124SMoriah Waterland } 11585c51f124SMoriah Waterland 11595c51f124SMoriah Waterland /* 11605c51f124SMoriah Waterland * sunw_find_localkeyid() searches stacks of certs and private keys, 11615c51f124SMoriah Waterland * and returns the first matching cert/private key found. 11625c51f124SMoriah Waterland * 11635c51f124SMoriah Waterland * Look for a keyid in a stack of certs. if 'certs' is NULL and 'pkeys' is 11645c51f124SMoriah Waterland * not NULL, search the list of private keys. Move the matching cert to 11655c51f124SMoriah Waterland * 'matching_cert' and its matching private key to 'matching_pkey'. If no 11665c51f124SMoriah Waterland * cert or keys match, no match occurred. 11675c51f124SMoriah Waterland * 11685c51f124SMoriah Waterland * Arguments: 11695c51f124SMoriah Waterland * keyid_str- A byte string with the localkeyid to match 11705c51f124SMoriah Waterland * keyid_len- Length of the keyid byte string. 11715c51f124SMoriah Waterland * pkeys - Points to a stack of private keys which match the certs. 11725c51f124SMoriah Waterland * This may be NULL, in which case no keys are returned. 11735c51f124SMoriah Waterland * certs - Points to a stack of certs to search. If NULL, search the 11745c51f124SMoriah Waterland * stack of keys instead. 11755c51f124SMoriah Waterland * matching_pkey 11765c51f124SMoriah Waterland * - Pointer to receive address of first matching pkey found. 11775c51f124SMoriah Waterland * 'matching_pkey' must not be NULL; '*matching_pkey' will be 11785c51f124SMoriah Waterland * reset. 11795c51f124SMoriah Waterland * matching_cert 11805c51f124SMoriah Waterland * - Pointer to receive address of first matching cert found. 11815c51f124SMoriah Waterland * 'matching_cert' must not be NULL; '*matching_cert' will be 11825c51f124SMoriah Waterland * reset. 11835c51f124SMoriah Waterland * 11845c51f124SMoriah Waterland * Returns: 11855c51f124SMoriah Waterland * < 0 - An error returned. Call ERR_get_error() to get errors information. 11865c51f124SMoriah Waterland * Where possible, memory has been freed. 11875c51f124SMoriah Waterland * >= 0 - Objects were found and returned. Which objects are indicated by 11885c51f124SMoriah Waterland * which bits are set (FOUND_PKEY and/or FOUND_CERT). 11895c51f124SMoriah Waterland */ 11905c51f124SMoriah Waterland int 11915c51f124SMoriah Waterland sunw_find_localkeyid(char *keyid_str, int len, STACK_OF(EVP_PKEY) *pkeys, 11925c51f124SMoriah Waterland STACK_OF(X509) *certs, EVP_PKEY **matching_pkey, X509 **matching_cert) 11935c51f124SMoriah Waterland { 11945c51f124SMoriah Waterland ASN1_STRING *cmpstr = NULL; 11955c51f124SMoriah Waterland EVP_PKEY *tmp_pkey = NULL; 11965c51f124SMoriah Waterland X509 *tmp_cert = NULL; 11975c51f124SMoriah Waterland int retval = 0; 11985c51f124SMoriah Waterland 11995c51f124SMoriah Waterland /* If NULL arguments, this is an error */ 12005c51f124SMoriah Waterland if (keyid_str == NULL || 12015c51f124SMoriah Waterland (pkeys == NULL || certs == NULL) || 12025c51f124SMoriah Waterland (pkeys != NULL && matching_pkey == NULL) || 12035c51f124SMoriah Waterland (certs != NULL && matching_cert == NULL)) { 12045c51f124SMoriah Waterland SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_INVALID_ARG); 12055c51f124SMoriah Waterland return (-1); 12065c51f124SMoriah Waterland } 12075c51f124SMoriah Waterland 12085c51f124SMoriah Waterland if (matching_pkey != NULL) 12095c51f124SMoriah Waterland *matching_pkey = NULL; 12105c51f124SMoriah Waterland if (matching_cert != NULL) 12115c51f124SMoriah Waterland *matching_cert = NULL; 12125c51f124SMoriah Waterland 12135c51f124SMoriah Waterland cmpstr = (ASN1_STRING *)M_ASN1_OCTET_STRING_new(); 12145c51f124SMoriah Waterland if (cmpstr == NULL || 12155c51f124SMoriah Waterland M_ASN1_OCTET_STRING_set(cmpstr, keyid_str, len) == 0) { 12165c51f124SMoriah Waterland SUNWerr(SUNW_F_FIND_LOCALKEYID, SUNW_R_MEMORY_FAILURE); 12175c51f124SMoriah Waterland return (-1); 12185c51f124SMoriah Waterland } 12195c51f124SMoriah Waterland 12205c51f124SMoriah Waterland retval = find_attr(NID_localKeyID, cmpstr, pkeys, &tmp_pkey, certs, 12215c51f124SMoriah Waterland &tmp_cert); 12225c51f124SMoriah Waterland if (retval == 0) { 12235c51f124SMoriah Waterland ASN1_STRING_free(cmpstr); 12245c51f124SMoriah Waterland return (retval); 12255c51f124SMoriah Waterland } 12265c51f124SMoriah Waterland 12275c51f124SMoriah Waterland if (matching_pkey != NULL) 12285c51f124SMoriah Waterland *matching_pkey = tmp_pkey; 12295c51f124SMoriah Waterland if (matching_cert != NULL) 12305c51f124SMoriah Waterland *matching_cert = tmp_cert; 12315c51f124SMoriah Waterland 12325c51f124SMoriah Waterland return (retval); 12335c51f124SMoriah Waterland } 12345c51f124SMoriah Waterland 12355c51f124SMoriah Waterland /* 12365c51f124SMoriah Waterland * sunw_find_fname() searches stacks of certs and private keys for one with 12375c51f124SMoriah Waterland * a matching friendlyname and returns the first matching cert/private 12385c51f124SMoriah Waterland * key found. 12395c51f124SMoriah Waterland * 12405c51f124SMoriah Waterland * Look for a friendlyname in a stack of certs. if 'certs' is NULL and 'pkeys' 12415c51f124SMoriah Waterland * is not NULL, search the list of private keys. Move the matching cert to 12425c51f124SMoriah Waterland * 'matching_cert' and its matching private key to 'matching_pkey'. If no 12435c51f124SMoriah Waterland * cert or keys match, no match occurred. 12445c51f124SMoriah Waterland * 12455c51f124SMoriah Waterland * Arguments: 12465c51f124SMoriah Waterland * fname - Friendlyname to find (NULL-terminated ASCII string). 12475c51f124SMoriah Waterland * pkeys - Points to a stack of private keys which match the certs. 12485c51f124SMoriah Waterland * This may be NULL, in which case no keys are returned. 12495c51f124SMoriah Waterland * certs - Points to a stack of certs to search. If NULL, search the 12505c51f124SMoriah Waterland * stack of keys instead. 12515c51f124SMoriah Waterland * matching_pkey 12525c51f124SMoriah Waterland * - Pointer to receive address of first matching pkey found. 12535c51f124SMoriah Waterland * matching_cert 12545c51f124SMoriah Waterland * - Pointer to receive address of first matching cert found. 12555c51f124SMoriah Waterland * 12565c51f124SMoriah Waterland * Returns: 12575c51f124SMoriah Waterland * < 0 - An error returned. Call ERR_get_error() to get errors information. 12585c51f124SMoriah Waterland * Where possible, memory has been freed. 12595c51f124SMoriah Waterland * >= 0 - Objects were found and returned. Which objects are indicated by 12605c51f124SMoriah Waterland * which bits are set (FOUND_PKEY and/or FOUND_CERT). 12615c51f124SMoriah Waterland */ 12625c51f124SMoriah Waterland int 12635c51f124SMoriah Waterland sunw_find_fname(char *fname, STACK_OF(EVP_PKEY) *pkeys, STACK_OF(X509) *certs, 12645c51f124SMoriah Waterland EVP_PKEY **matching_pkey, X509 ** matching_cert) 12655c51f124SMoriah Waterland { 12665c51f124SMoriah Waterland ASN1_STRING *cmpstr = NULL; 12675c51f124SMoriah Waterland EVP_PKEY *tmp_pkey = NULL; 12685c51f124SMoriah Waterland X509 *tmp_cert = NULL; 12695c51f124SMoriah Waterland int retval = 0; 12705c51f124SMoriah Waterland 12715c51f124SMoriah Waterland /* If NULL arguments, this is an error */ 12725c51f124SMoriah Waterland if (fname == NULL || 12735c51f124SMoriah Waterland (pkeys == NULL && certs == NULL) || 12745c51f124SMoriah Waterland (pkeys != NULL && matching_pkey == NULL) || 12755c51f124SMoriah Waterland (certs != NULL && matching_cert == NULL)) { 12765c51f124SMoriah Waterland SUNWerr(SUNW_F_FIND_FNAME, SUNW_R_INVALID_ARG); 12775c51f124SMoriah Waterland return (-1); 12785c51f124SMoriah Waterland } 12795c51f124SMoriah Waterland 12805c51f124SMoriah Waterland if (matching_pkey != NULL) 12815c51f124SMoriah Waterland *matching_pkey = NULL; 12825c51f124SMoriah Waterland if (matching_cert != NULL) 12835c51f124SMoriah Waterland *matching_cert = NULL; 12845c51f124SMoriah Waterland 12855c51f124SMoriah Waterland cmpstr = (ASN1_STRING *)asc2bmpstring(fname, strlen(fname)); 12865c51f124SMoriah Waterland if (cmpstr == NULL) { 12875c51f124SMoriah Waterland /* 12885c51f124SMoriah Waterland * Error already on stack 12895c51f124SMoriah Waterland */ 12905c51f124SMoriah Waterland return (-1); 12915c51f124SMoriah Waterland } 12925c51f124SMoriah Waterland 12935c51f124SMoriah Waterland retval = find_attr(NID_friendlyName, cmpstr, pkeys, &tmp_pkey, certs, 12945c51f124SMoriah Waterland &tmp_cert); 12955c51f124SMoriah Waterland if (retval == 0) { 12965c51f124SMoriah Waterland ASN1_STRING_free(cmpstr); 12975c51f124SMoriah Waterland return (retval); 12985c51f124SMoriah Waterland } 12995c51f124SMoriah Waterland 13005c51f124SMoriah Waterland if (matching_pkey != NULL) 13015c51f124SMoriah Waterland *matching_pkey = tmp_pkey; 13025c51f124SMoriah Waterland if (matching_cert != NULL) 13035c51f124SMoriah Waterland *matching_cert = tmp_cert; 13045c51f124SMoriah Waterland 13055c51f124SMoriah Waterland return (retval); 13065c51f124SMoriah Waterland } 13075c51f124SMoriah Waterland 13085c51f124SMoriah Waterland /* 13095c51f124SMoriah Waterland * sunw_get_cert_fname() gets the fiendlyname from a cert. It can 13105c51f124SMoriah Waterland * optionally remove the value found. 13115c51f124SMoriah Waterland * 13125c51f124SMoriah Waterland * Arguments: 13135c51f124SMoriah Waterland * dowhat - What to do with the attributes (remove them or copy them). 13145c51f124SMoriah Waterland * cert - Points to a cert to get the friendlyName from. 13155c51f124SMoriah Waterland * fname - Points to a location which will receive the pointer to a 13165c51f124SMoriah Waterland * byte string with the ASCII friendlyname 13175c51f124SMoriah Waterland * 13185c51f124SMoriah Waterland * Returns: 13195c51f124SMoriah Waterland * >= 0 - The number of characters in the friendlyname returned. 13205c51f124SMoriah Waterland * < 0 - An error occurred. It was probably an error in allocating 13215c51f124SMoriah Waterland * memory. The error will be set in the error stack. Call 13225c51f124SMoriah Waterland * ERR_get_error() to get specific information. 13235c51f124SMoriah Waterland */ 13245c51f124SMoriah Waterland int 13255c51f124SMoriah Waterland sunw_get_cert_fname(getdo_actions_t dowhat, X509 *cert, char **fname) 13265c51f124SMoriah Waterland { 13275c51f124SMoriah Waterland int len; 13285c51f124SMoriah Waterland 13295c51f124SMoriah Waterland if (fname != NULL) 13305c51f124SMoriah Waterland *fname = NULL; 13315c51f124SMoriah Waterland 13325c51f124SMoriah Waterland if (cert == NULL || cert->aux == NULL || cert->aux->alias == NULL) { 13335c51f124SMoriah Waterland return (0); 13345c51f124SMoriah Waterland } 13355c51f124SMoriah Waterland 13365c51f124SMoriah Waterland if (dowhat == GETDO_DEL) { 13375c51f124SMoriah Waterland /* Delete the entry */ 13385c51f124SMoriah Waterland ASN1_UTF8STRING_free(cert->aux->alias); 13395c51f124SMoriah Waterland cert->aux->alias = NULL; 13405c51f124SMoriah Waterland return (0); 13415c51f124SMoriah Waterland } 13425c51f124SMoriah Waterland 13435c51f124SMoriah Waterland *((uchar_t **)fname) = utf82ascstr(cert->aux->alias); 13445c51f124SMoriah Waterland if (*fname == NULL) { 13455c51f124SMoriah Waterland /* 13465c51f124SMoriah Waterland * Error already on stack 13475c51f124SMoriah Waterland */ 13485c51f124SMoriah Waterland return (-1); 13495c51f124SMoriah Waterland } 13505c51f124SMoriah Waterland 13515c51f124SMoriah Waterland len = strlen(*fname); 13525c51f124SMoriah Waterland 13535c51f124SMoriah Waterland return (len); 13545c51f124SMoriah Waterland } 13555c51f124SMoriah Waterland 13565c51f124SMoriah Waterland /* 13575c51f124SMoriah Waterland * sunw_set_fname() sets the friendlyName in a cert, a private key or 13585c51f124SMoriah Waterland * both. Any existing friendlyname will be discarded. 13595c51f124SMoriah Waterland * 13605c51f124SMoriah Waterland * Arguments: 13615c51f124SMoriah Waterland * ascname - An ASCII string with the friendlyName to set 13625c51f124SMoriah Waterland * pkey - Points to a private key to set the fname in. 13635c51f124SMoriah Waterland * cert - Points to a cert to set the fname in. 13645c51f124SMoriah Waterland * 13655c51f124SMoriah Waterland * Note that setting a friendlyName into a cert which will not be written out 13665c51f124SMoriah Waterland * as a PKCS12 cert is pointless since it will be lost. 13675c51f124SMoriah Waterland * 13685c51f124SMoriah Waterland * Returns: 13695c51f124SMoriah Waterland * 0 - Success. 13705c51f124SMoriah Waterland * <0 - An error occurred. It was probably an error in allocating 13715c51f124SMoriah Waterland * memory. The error will be set in the error stack. Call 13725c51f124SMoriah Waterland * ERR_get_error() to get specific information. 13735c51f124SMoriah Waterland */ 13745c51f124SMoriah Waterland int 13755c51f124SMoriah Waterland sunw_set_fname(const char *ascname, EVP_PKEY *pkey, X509 *cert) 13765c51f124SMoriah Waterland { 13775c51f124SMoriah Waterland X509_ATTRIBUTE *attr = NULL; 13785c51f124SMoriah Waterland ASN1_BMPSTRING *str = NULL; 13795c51f124SMoriah Waterland ASN1_TYPE *fname = NULL; 13805c51f124SMoriah Waterland unsigned char *data = NULL; 13815c51f124SMoriah Waterland int retval = -1; 13825c51f124SMoriah Waterland int len; 13835c51f124SMoriah Waterland int i; 13845c51f124SMoriah Waterland 13855c51f124SMoriah Waterland str = asc2bmpstring(ascname, strlen(ascname)); 13865c51f124SMoriah Waterland if (str == NULL) { 13875c51f124SMoriah Waterland /* 13885c51f124SMoriah Waterland * Error already on stack 13895c51f124SMoriah Waterland */ 13905c51f124SMoriah Waterland return (-1); 13915c51f124SMoriah Waterland } 13925c51f124SMoriah Waterland 13935c51f124SMoriah Waterland if (cert != NULL) { 13945c51f124SMoriah Waterland if (cert->aux != NULL && cert->aux->alias != NULL) { 13955c51f124SMoriah Waterland ASN1_UTF8STRING_free(cert->aux->alias); 13965c51f124SMoriah Waterland } 13975c51f124SMoriah Waterland 13985c51f124SMoriah Waterland len = ASN1_STRING_to_UTF8(&data, str); 13995c51f124SMoriah Waterland i = -23; 14005c51f124SMoriah Waterland if (len <= 0 || (i = X509_alias_set1(cert, data, len)) == 0) { 14015c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_FNAME, SUNW_R_SET_FNAME_ERR); 14025c51f124SMoriah Waterland goto cleanup; 14035c51f124SMoriah Waterland } 14045c51f124SMoriah Waterland } 14055c51f124SMoriah Waterland if (pkey != NULL) { 14065c51f124SMoriah Waterland if ((fname = ASN1_TYPE_new()) == NULL) { 14075c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE); 14085c51f124SMoriah Waterland goto cleanup; 14095c51f124SMoriah Waterland } 14105c51f124SMoriah Waterland 14115c51f124SMoriah Waterland ASN1_TYPE_set(fname, V_ASN1_BMPSTRING, str); 14125c51f124SMoriah Waterland str = NULL; 14135c51f124SMoriah Waterland 14145c51f124SMoriah Waterland attr = type2attrib(fname, NID_friendlyName); 14155c51f124SMoriah Waterland if (attr == NULL) { 14165c51f124SMoriah Waterland /* 14175c51f124SMoriah Waterland * Error already on stack 14185c51f124SMoriah Waterland */ 14195c51f124SMoriah Waterland goto cleanup; 14205c51f124SMoriah Waterland } 14215c51f124SMoriah Waterland fname = NULL; 14225c51f124SMoriah Waterland 14235c51f124SMoriah Waterland if (pkey->attributes == NULL) { 14245c51f124SMoriah Waterland pkey->attributes = sk_X509_ATTRIBUTE_new_null(); 14255c51f124SMoriah Waterland if (pkey->attributes == NULL) { 14265c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_FNAME, 14275c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 14285c51f124SMoriah Waterland goto cleanup; 14295c51f124SMoriah Waterland } 14305c51f124SMoriah Waterland } else if ((i = find_attr_by_nid(pkey->attributes, 14315c51f124SMoriah Waterland NID_friendlyName)) >= 0) { 14325c51f124SMoriah Waterland (void) sk_X509_ATTRIBUTE_delete(pkey->attributes, i); 14335c51f124SMoriah Waterland } 14345c51f124SMoriah Waterland 14355c51f124SMoriah Waterland if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) { 14365c51f124SMoriah Waterland SUNWerr(SUNW_F_SET_FNAME, SUNW_R_MEMORY_FAILURE); 14375c51f124SMoriah Waterland goto cleanup; 14385c51f124SMoriah Waterland } 14395c51f124SMoriah Waterland 14405c51f124SMoriah Waterland attr = NULL; 14415c51f124SMoriah Waterland } 14425c51f124SMoriah Waterland retval = 0; 14435c51f124SMoriah Waterland 14445c51f124SMoriah Waterland cleanup: 14455c51f124SMoriah Waterland if (data != NULL) 14465c51f124SMoriah Waterland OPENSSL_free(data); 14475c51f124SMoriah Waterland if (str != NULL) 14485c51f124SMoriah Waterland ASN1_BMPSTRING_free(str); 14495c51f124SMoriah Waterland if (fname != NULL) 14505c51f124SMoriah Waterland ASN1_TYPE_free(fname); 14515c51f124SMoriah Waterland if (attr != NULL) 14525c51f124SMoriah Waterland X509_ATTRIBUTE_free(attr); 14535c51f124SMoriah Waterland 14545c51f124SMoriah Waterland return (retval); 14555c51f124SMoriah Waterland } 14565c51f124SMoriah Waterland 14575c51f124SMoriah Waterland /* 14585c51f124SMoriah Waterland * sunw_check_keys() compares the public key in the certificate and a 14595c51f124SMoriah Waterland * private key to ensure that they match. 14605c51f124SMoriah Waterland * 14615c51f124SMoriah Waterland * Arguments: 14625c51f124SMoriah Waterland * cert - Points to a certificate. 14635c51f124SMoriah Waterland * pkey - Points to a private key. 14645c51f124SMoriah Waterland * 14655c51f124SMoriah Waterland * Returns: 14665c51f124SMoriah Waterland * == 0 - These do not match. 14675c51f124SMoriah Waterland * != 0 - The cert's public key and the private key match. 14685c51f124SMoriah Waterland */ 14695c51f124SMoriah Waterland int 14705c51f124SMoriah Waterland sunw_check_keys(X509 *cert, EVP_PKEY *pkey) 14715c51f124SMoriah Waterland { 14725c51f124SMoriah Waterland int retval = 0; 14735c51f124SMoriah Waterland 14745c51f124SMoriah Waterland if (pkey != NULL && cert != NULL) 14755c51f124SMoriah Waterland retval = X509_check_private_key(cert, pkey); 14765c51f124SMoriah Waterland 14775c51f124SMoriah Waterland return (retval); 14785c51f124SMoriah Waterland } 14795c51f124SMoriah Waterland 14805c51f124SMoriah Waterland /* 14815c51f124SMoriah Waterland * sunw_check_cert_times() compares the time fields in a certificate 14825c51f124SMoriah Waterland * 14835c51f124SMoriah Waterland * Compare the 'not before' and the 'not after' times in the cert 14845c51f124SMoriah Waterland * to the current time. Return the results of the comparison (bad time formats, 14855c51f124SMoriah Waterland * cert not yet in force, cert expired or in range) 14865c51f124SMoriah Waterland * 14875c51f124SMoriah Waterland * Arguments: 14885c51f124SMoriah Waterland * dowhat - what field(s) to check. 14895c51f124SMoriah Waterland * cert - Points to a cert to check 14905c51f124SMoriah Waterland * 14915c51f124SMoriah Waterland * Returns: 14925c51f124SMoriah Waterland * Results of the comparison. 14935c51f124SMoriah Waterland */ 14945c51f124SMoriah Waterland chk_errs_t 14955c51f124SMoriah Waterland sunw_check_cert_times(chk_actions_t chkwhat, X509 *cert) 14965c51f124SMoriah Waterland { 14975c51f124SMoriah Waterland return (check_time(chkwhat, cert)); 14985c51f124SMoriah Waterland } 14995c51f124SMoriah Waterland 15005c51f124SMoriah Waterland /* 15015c51f124SMoriah Waterland * ---------------------------------------------------------------------------- 15025c51f124SMoriah Waterland * Local routines 15035c51f124SMoriah Waterland * ---------------------------------------------------------------------------- 15045c51f124SMoriah Waterland */ 15055c51f124SMoriah Waterland 15065c51f124SMoriah Waterland 15075c51f124SMoriah Waterland /* 15085c51f124SMoriah Waterland * parse_pkcs12 - Oversee parsing of the pkcs12 structure. Get it 15095c51f124SMoriah Waterland * parsed. After that either return what's found directly, or 15105c51f124SMoriah Waterland * do any required matching. 15115c51f124SMoriah Waterland * 15125c51f124SMoriah Waterland * Arguments: 15135c51f124SMoriah Waterland * p12 - Structure with pkcs12 info to be parsed 15145c51f124SMoriah Waterland * pass - Pass phrase for the private key (possibly empty) or NULL if 15155c51f124SMoriah Waterland * there is none. 15165c51f124SMoriah Waterland * matchty - Info about which certs/keys to return if many are in the file. 15175c51f124SMoriah Waterland * keyid - If private key localkeyids friendlynames are to match a 15185c51f124SMoriah Waterland * predetermined value, the value to match. This value should 15195c51f124SMoriah Waterland * be an octet string. 15205c51f124SMoriah Waterland * keyid_len- Length of the keyid byte string. 15215c51f124SMoriah Waterland * name_str - If friendlynames are to match a predetermined value, the value 15225c51f124SMoriah Waterland * to match. This value should be a NULL terminated string. 15235c51f124SMoriah Waterland * pkey - Points to location pointing to the private key returned. 15245c51f124SMoriah Waterland * cert - Points to locaiton which points to the client cert returned 15255c51f124SMoriah Waterland * ca - Points to location that points to a stack of 'certificate 15265c51f124SMoriah Waterland * authority' certs/trust anchors. 15275c51f124SMoriah Waterland * 15285c51f124SMoriah Waterland * Note about error codes: This function is an internal function, and the 15295c51f124SMoriah Waterland * place where it is called sets error codes. Therefore only set an error 15305c51f124SMoriah Waterland * code if it is something that is unique or if the function which detected 15315c51f124SMoriah Waterland * the error doesn't set one. 15325c51f124SMoriah Waterland * 15335c51f124SMoriah Waterland * Returns: 15345c51f124SMoriah Waterland * == -1 - An error occurred. Call ERR_get_error() to get error information. 15355c51f124SMoriah Waterland * Where possible, memory has been freed. 15365c51f124SMoriah Waterland * == 0 - No matching returns were found. 15375c51f124SMoriah Waterland * > 0 - This is the aithmetic 'or' of the FOUND_* bits that indicate which 15385c51f124SMoriah Waterland * of the requested entries were found. 15395c51f124SMoriah Waterland */ 15405c51f124SMoriah Waterland static int 15415c51f124SMoriah Waterland parse_pkcs12(PKCS12 *p12, const char *pass, int matchty, char *keyid, 15425c51f124SMoriah Waterland int kstr_len, char *name_str, EVP_PKEY **pkey, X509 **cert, 15435c51f124SMoriah Waterland STACK_OF(X509) **ca) 15445c51f124SMoriah Waterland { 15455c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *work_kl = NULL; /* Head for private key list */ 15465c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *nocerts = NULL; /* Head for alt. key list */ 15475c51f124SMoriah Waterland STACK_OF(X509) *work_ca = NULL; /* Head for cert list */ 15485c51f124SMoriah Waterland STACK_OF(X509) *work_cl = NULL; 15495c51f124SMoriah Waterland int retval = 0; 15505c51f124SMoriah Waterland int n; 15515c51f124SMoriah Waterland 15525c51f124SMoriah Waterland retval = sunw_PKCS12_contents(p12, pass, &work_kl, &work_ca); 15535c51f124SMoriah Waterland if (retval < 0) { 15545c51f124SMoriah Waterland goto cleanup; 15555c51f124SMoriah Waterland } else if (retval == 0) { 15565c51f124SMoriah Waterland /* 15575c51f124SMoriah Waterland * Not really an error here - its just that nothing was found. 15585c51f124SMoriah Waterland */ 15595c51f124SMoriah Waterland goto cleanup; 15605c51f124SMoriah Waterland } 15615c51f124SMoriah Waterland 15625c51f124SMoriah Waterland if (sk_EVP_PKEY_num(work_kl) > 0) { 15635c51f124SMoriah Waterland 15645c51f124SMoriah Waterland if (sunw_split_certs(work_kl, work_ca, &work_cl, &nocerts) 15655c51f124SMoriah Waterland < 0) { 15665c51f124SMoriah Waterland goto cleanup; 15675c51f124SMoriah Waterland } 15685c51f124SMoriah Waterland } 15695c51f124SMoriah Waterland 15705c51f124SMoriah Waterland /* 15715c51f124SMoriah Waterland * Go through the lists of certs and private keys which were 15725c51f124SMoriah Waterland * returned, looking for matches of the appropriate type. Do these 15735c51f124SMoriah Waterland * in the order described above. 15745c51f124SMoriah Waterland */ 15755c51f124SMoriah Waterland if ((matchty & DO_FIND_KEYID) != 0) { 15765c51f124SMoriah Waterland 15775c51f124SMoriah Waterland if (keyid == NULL) { 15785c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG); 15795c51f124SMoriah Waterland retval = -1; 15805c51f124SMoriah Waterland goto cleanup; 15815c51f124SMoriah Waterland } 15825c51f124SMoriah Waterland 15835c51f124SMoriah Waterland /* See if string matches localkeyid's */ 15845c51f124SMoriah Waterland retval = sunw_find_localkeyid(keyid, kstr_len, 15855c51f124SMoriah Waterland work_kl, work_cl, pkey, cert); 15865c51f124SMoriah Waterland if (retval != 0) { 15875c51f124SMoriah Waterland if (retval == -1) 15885c51f124SMoriah Waterland goto cleanup; 15895c51f124SMoriah Waterland else 15905c51f124SMoriah Waterland goto last_part; 15915c51f124SMoriah Waterland } 15925c51f124SMoriah Waterland } 15935c51f124SMoriah Waterland if ((matchty & DO_FIND_FN) != 0) { 15945c51f124SMoriah Waterland 15955c51f124SMoriah Waterland if (name_str == NULL) { 15965c51f124SMoriah Waterland SUNWerr(SUNW_F_PKCS12_PARSE, SUNW_R_INVALID_ARG); 15975c51f124SMoriah Waterland retval = -1; 15985c51f124SMoriah Waterland goto cleanup; 15995c51f124SMoriah Waterland } 16005c51f124SMoriah Waterland 16015c51f124SMoriah Waterland /* See if string matches friendly names */ 16025c51f124SMoriah Waterland retval = sunw_find_fname(name_str, work_kl, work_cl, 16035c51f124SMoriah Waterland pkey, cert); 16045c51f124SMoriah Waterland if (retval != 0) { 16055c51f124SMoriah Waterland if (retval == -1) 16065c51f124SMoriah Waterland goto cleanup; 16075c51f124SMoriah Waterland else 16085c51f124SMoriah Waterland goto last_part; 16095c51f124SMoriah Waterland } 16105c51f124SMoriah Waterland } 16115c51f124SMoriah Waterland 16125c51f124SMoriah Waterland if (matchty & DO_FIRST_PAIR) { 16135c51f124SMoriah Waterland 16145c51f124SMoriah Waterland /* Find the first cert and private key and return them */ 16155c51f124SMoriah Waterland retval = get_key_cert(0, work_kl, pkey, work_cl, cert); 16165c51f124SMoriah Waterland if (retval != 0) { 16175c51f124SMoriah Waterland if (retval == -1) 16185c51f124SMoriah Waterland goto cleanup; 16195c51f124SMoriah Waterland else 16205c51f124SMoriah Waterland goto last_part; 16215c51f124SMoriah Waterland } 16225c51f124SMoriah Waterland } 16235c51f124SMoriah Waterland 16245c51f124SMoriah Waterland if (matchty & DO_LAST_PAIR) { 16255c51f124SMoriah Waterland 16265c51f124SMoriah Waterland /* 16275c51f124SMoriah Waterland * Find the last matching cert and private key and return 16285c51f124SMoriah Waterland * them. Since keys which don't have matching client certs 16295c51f124SMoriah Waterland * are at the end of the list of keys, use the number of 16305c51f124SMoriah Waterland * client certs to compute the position of the last private 16315c51f124SMoriah Waterland * key which matches a client cert. 16325c51f124SMoriah Waterland */ 16335c51f124SMoriah Waterland n = sk_X509_num(work_cl) - 1; 16345c51f124SMoriah Waterland retval = get_key_cert(n, work_kl, pkey, work_cl, cert); 16355c51f124SMoriah Waterland if (retval != 0) { 16365c51f124SMoriah Waterland if (retval == -1) 16375c51f124SMoriah Waterland goto cleanup; 16385c51f124SMoriah Waterland else 16395c51f124SMoriah Waterland goto last_part; 16405c51f124SMoriah Waterland } 16415c51f124SMoriah Waterland } 16425c51f124SMoriah Waterland 16435c51f124SMoriah Waterland if (matchty & DO_UNMATCHING) { 16445c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *tmpk; 16455c51f124SMoriah Waterland STACK_OF(X509) *tmpc; 16465c51f124SMoriah Waterland 16475c51f124SMoriah Waterland /* Find the first cert and private key and return them */ 16485c51f124SMoriah Waterland tmpc = work_cl; 16495c51f124SMoriah Waterland if (work_cl == NULL || sk_X509_num(work_cl) == 0) 16505c51f124SMoriah Waterland tmpc = work_ca; 16515c51f124SMoriah Waterland tmpk = work_kl; 16525c51f124SMoriah Waterland if (work_kl == NULL || sk_EVP_PKEY_num(work_kl) == 0) 16535c51f124SMoriah Waterland tmpk = nocerts; 16545c51f124SMoriah Waterland retval = get_key_cert(0, tmpk, pkey, tmpc, cert); 16555c51f124SMoriah Waterland if (retval != 0) { 16565c51f124SMoriah Waterland if (retval == -1) 16575c51f124SMoriah Waterland goto cleanup; 16585c51f124SMoriah Waterland else 16595c51f124SMoriah Waterland goto last_part; 16605c51f124SMoriah Waterland } 16615c51f124SMoriah Waterland } 16625c51f124SMoriah Waterland 16635c51f124SMoriah Waterland last_part: 16645c51f124SMoriah Waterland /* If no errors, terminate normally */ 16655c51f124SMoriah Waterland if (retval != -1) 16665c51f124SMoriah Waterland retval |= set_results(NULL, NULL, NULL, NULL, ca, &work_ca, 16675c51f124SMoriah Waterland NULL, NULL); 16685c51f124SMoriah Waterland if (retval >= 0) { 16695c51f124SMoriah Waterland goto clean_part; 16705c51f124SMoriah Waterland } 16715c51f124SMoriah Waterland 16725c51f124SMoriah Waterland /* Fallthrough is intentional in error cases. */ 16735c51f124SMoriah Waterland cleanup: 16745c51f124SMoriah Waterland if (pkey != NULL && *pkey != NULL) { 16755c51f124SMoriah Waterland sunw_evp_pkey_free(*pkey); 16765c51f124SMoriah Waterland *pkey = NULL; 16775c51f124SMoriah Waterland } 16785c51f124SMoriah Waterland if (cert != NULL && *cert != NULL) { 16795c51f124SMoriah Waterland X509_free(*cert); 16805c51f124SMoriah Waterland *cert = NULL; 16815c51f124SMoriah Waterland } 16825c51f124SMoriah Waterland 16835c51f124SMoriah Waterland clean_part: 16845c51f124SMoriah Waterland 16855c51f124SMoriah Waterland if (work_kl != NULL) { 16865c51f124SMoriah Waterland sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free); 16875c51f124SMoriah Waterland } 16885c51f124SMoriah Waterland if (work_ca != NULL) 16895c51f124SMoriah Waterland sk_X509_pop_free(work_ca, X509_free); 16905c51f124SMoriah Waterland if (work_cl != NULL) 16915c51f124SMoriah Waterland sk_X509_pop_free(work_cl, X509_free); 16925c51f124SMoriah Waterland 16935c51f124SMoriah Waterland return (retval); 16945c51f124SMoriah Waterland } 16955c51f124SMoriah Waterland 16965c51f124SMoriah Waterland /* 16975c51f124SMoriah Waterland * parse_outer - Unpack the outer PKCS#12 structure and go through the 16985c51f124SMoriah Waterland * individual bags. Return stacks of certs, private keys found and 16995c51f124SMoriah Waterland * CA certs found. 17005c51f124SMoriah Waterland * 17015c51f124SMoriah Waterland * Note about error codes: This function is an internal function, and the 17025c51f124SMoriah Waterland * place where it is called sets error codes. 17035c51f124SMoriah Waterland * 17045c51f124SMoriah Waterland * Returns: 17055c51f124SMoriah Waterland * 0 - An error returned. Call ERR_get_error() to get errors information. 17065c51f124SMoriah Waterland * Where possible, memory has been freed. 17075c51f124SMoriah Waterland * 1 - PKCS12 data object was parsed and lists of certs and private keys 17085c51f124SMoriah Waterland * were returned. 17095c51f124SMoriah Waterland */ 17105c51f124SMoriah Waterland static int 17115c51f124SMoriah Waterland parse_outer(PKCS12 *p12, const char *pass, STACK_OF(EVP_PKEY) *kl, 17125c51f124SMoriah Waterland STACK_OF(X509) *cl) 17135c51f124SMoriah Waterland { 17145c51f124SMoriah Waterland STACK_OF(PKCS12_SAFEBAG) *bags; 17155c51f124SMoriah Waterland STACK_OF(PKCS7) *asafes; 17165c51f124SMoriah Waterland int i, bagnid; 17175c51f124SMoriah Waterland PKCS7 *p7; 17185c51f124SMoriah Waterland 17195c51f124SMoriah Waterland if ((asafes = M_PKCS12_unpack_authsafes(p12)) == NULL) 17205c51f124SMoriah Waterland return (0); 17215c51f124SMoriah Waterland 17225c51f124SMoriah Waterland for (i = 0; i < sk_PKCS7_num(asafes); i++) { 17235c51f124SMoriah Waterland p7 = sk_PKCS7_value(asafes, i); 17245c51f124SMoriah Waterland bagnid = OBJ_obj2nid(p7->type); 17255c51f124SMoriah Waterland if (bagnid == NID_pkcs7_data) { 17265c51f124SMoriah Waterland bags = M_PKCS12_unpack_p7data(p7); 17275c51f124SMoriah Waterland } else if (bagnid == NID_pkcs7_encrypted) { 17285c51f124SMoriah Waterland /* 17295c51f124SMoriah Waterland * A length of '-1' means strlen() can be used 17305c51f124SMoriah Waterland * to determine the password length. 17315c51f124SMoriah Waterland */ 17325c51f124SMoriah Waterland bags = M_PKCS12_unpack_p7encdata(p7, pass, -1); 17335c51f124SMoriah Waterland } else { 17345c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_BAD_BAGTYPE); 17355c51f124SMoriah Waterland return (0); 17365c51f124SMoriah Waterland } 17375c51f124SMoriah Waterland 17385c51f124SMoriah Waterland if (bags == NULL) { 17395c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_OUTER, SUNW_R_PARSE_BAG_ERR); 17405c51f124SMoriah Waterland sk_PKCS7_pop_free(asafes, PKCS7_free); 17415c51f124SMoriah Waterland return (0); 17425c51f124SMoriah Waterland } 17435c51f124SMoriah Waterland if (parse_all_bags(bags, pass, kl, cl) == 0) { 17445c51f124SMoriah Waterland sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 17455c51f124SMoriah Waterland sk_PKCS7_pop_free(asafes, PKCS7_free); 17465c51f124SMoriah Waterland return (0); 17475c51f124SMoriah Waterland } 17485c51f124SMoriah Waterland } 17495c51f124SMoriah Waterland 17505c51f124SMoriah Waterland return (1); 17515c51f124SMoriah Waterland } 17525c51f124SMoriah Waterland 17535c51f124SMoriah Waterland /* 17545c51f124SMoriah Waterland * parse_all_bags - go through the stack of bags, parsing each. 17555c51f124SMoriah Waterland * 17565c51f124SMoriah Waterland * Note about error codes: This function is an internal function, and the 17575c51f124SMoriah Waterland * place where it is called sets error codes. 17585c51f124SMoriah Waterland * 17595c51f124SMoriah Waterland * Returns: 17605c51f124SMoriah Waterland * 0 - An error returned. Call ERR_get_error() to get errors information. 17615c51f124SMoriah Waterland * Where possible, memory has been freed. 17625c51f124SMoriah Waterland * 1 - Stack of safebags was parsed and lists of certs and private keys 17635c51f124SMoriah Waterland * were returned. 17645c51f124SMoriah Waterland */ 17655c51f124SMoriah Waterland static int 17665c51f124SMoriah Waterland parse_all_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, 17675c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *kl, STACK_OF(X509) *cl) 17685c51f124SMoriah Waterland { 17695c51f124SMoriah Waterland int i; 17705c51f124SMoriah Waterland for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 17715c51f124SMoriah Waterland if (parse_one_bag(sk_PKCS12_SAFEBAG_value(bags, i), 17725c51f124SMoriah Waterland pass, kl, cl) == 0) 17735c51f124SMoriah Waterland return (0); 17745c51f124SMoriah Waterland } 17755c51f124SMoriah Waterland return (1); 17765c51f124SMoriah Waterland } 17775c51f124SMoriah Waterland 17785c51f124SMoriah Waterland /* 17795c51f124SMoriah Waterland * parse_one_bag - Parse an individual bag 17805c51f124SMoriah Waterland * 17815c51f124SMoriah Waterland * i = parse_one_bag(bag, pass, kl, cl); 17825c51f124SMoriah Waterland * 17835c51f124SMoriah Waterland * Arguments: 17845c51f124SMoriah Waterland * bag - pkcs12 safebag to parse. 17855c51f124SMoriah Waterland * pass - password for use in decryption of shrouded keybag 17865c51f124SMoriah Waterland * kl - Stack of private keys found so far. New private keys will 17875c51f124SMoriah Waterland * be added here if found. 17885c51f124SMoriah Waterland * cl - Stack of certs found so far. New certificates will be 17895c51f124SMoriah Waterland * added here if found. 17905c51f124SMoriah Waterland * 17915c51f124SMoriah Waterland * Returns: 17925c51f124SMoriah Waterland * 0 - An error returned. Call ERR_get_error() to get errors information. 17935c51f124SMoriah Waterland * Where possible, memory has been freed. 17945c51f124SMoriah Waterland * 1 - one safebag was parsed. If it contained a cert or private key, it 17955c51f124SMoriah Waterland * was added to the stack of certs or private keys found, respectively. 17965c51f124SMoriah Waterland * localKeyId or friendlyName attributes are returned with the 17975c51f124SMoriah Waterland * private key or certificate. 17985c51f124SMoriah Waterland */ 17995c51f124SMoriah Waterland static int 18005c51f124SMoriah Waterland parse_one_bag(PKCS12_SAFEBAG *bag, const char *pass, STACK_OF(EVP_PKEY) *kl, 18015c51f124SMoriah Waterland STACK_OF(X509) *cl) 18025c51f124SMoriah Waterland { 18035c51f124SMoriah Waterland X509_ATTRIBUTE *attr = NULL; 18045c51f124SMoriah Waterland ASN1_TYPE *keyid = NULL; 18055c51f124SMoriah Waterland ASN1_TYPE *fname = NULL; 18065c51f124SMoriah Waterland PKCS8_PRIV_KEY_INFO *p8; 18075c51f124SMoriah Waterland EVP_PKEY *pkey = NULL; 18085c51f124SMoriah Waterland X509 *x509 = NULL; 18095c51f124SMoriah Waterland uchar_t *data = NULL; 18105c51f124SMoriah Waterland char *str = NULL; 18115c51f124SMoriah Waterland int retval = 1; 18125c51f124SMoriah Waterland 18135c51f124SMoriah Waterland keyid = PKCS12_get_attr(bag, NID_localKeyID); 18145c51f124SMoriah Waterland fname = PKCS12_get_attr(bag, NID_friendlyName); 18155c51f124SMoriah Waterland 18165c51f124SMoriah Waterland switch (M_PKCS12_bag_type(bag)) { 18175c51f124SMoriah Waterland case NID_keyBag: 18185c51f124SMoriah Waterland if ((pkey = EVP_PKCS82PKEY(bag->value.keybag)) == NULL) { 18195c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR); 18205c51f124SMoriah Waterland retval = 0; 18215c51f124SMoriah Waterland break; 18225c51f124SMoriah Waterland } 18235c51f124SMoriah Waterland break; 18245c51f124SMoriah Waterland 18255c51f124SMoriah Waterland case NID_pkcs8ShroudedKeyBag: 18265c51f124SMoriah Waterland /* 18275c51f124SMoriah Waterland * A length of '-1' means strlen() can be used 18285c51f124SMoriah Waterland * to determine the password length. 18295c51f124SMoriah Waterland */ 18305c51f124SMoriah Waterland if ((p8 = M_PKCS12_decrypt_skey(bag, pass, -1)) == NULL) { 18315c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR); 18325c51f124SMoriah Waterland retval = 0; 18335c51f124SMoriah Waterland break; 18345c51f124SMoriah Waterland } 18355c51f124SMoriah Waterland pkey = EVP_PKCS82PKEY(p8); 18365c51f124SMoriah Waterland PKCS8_PRIV_KEY_INFO_free(p8); 18375c51f124SMoriah Waterland if (pkey == NULL) { 18385c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_PARSE_BAG_ERR); 18395c51f124SMoriah Waterland retval = 0; 18405c51f124SMoriah Waterland } 18415c51f124SMoriah Waterland break; 18425c51f124SMoriah Waterland 18435c51f124SMoriah Waterland case NID_certBag: 18445c51f124SMoriah Waterland if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) { 18455c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_CERTTYPE); 18465c51f124SMoriah Waterland break; 18475c51f124SMoriah Waterland } 18485c51f124SMoriah Waterland if ((x509 = M_PKCS12_certbag2x509(bag)) == NULL) { 18495c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 18505c51f124SMoriah Waterland SUNW_R_PARSE_CERT_ERR); 18515c51f124SMoriah Waterland retval = 0; 18525c51f124SMoriah Waterland break; 18535c51f124SMoriah Waterland } 18545c51f124SMoriah Waterland 18555c51f124SMoriah Waterland if (keyid != NULL) { 18565c51f124SMoriah Waterland if (keyid->type != V_ASN1_OCTET_STRING) { 18575c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 18585c51f124SMoriah Waterland SUNW_R_BAD_LKID); 18595c51f124SMoriah Waterland retval = 0; 18605c51f124SMoriah Waterland break; 18615c51f124SMoriah Waterland } 18625c51f124SMoriah Waterland if (X509_keyid_set1(x509, 18635c51f124SMoriah Waterland keyid->value.octet_string->data, 18645c51f124SMoriah Waterland keyid->value.octet_string->length) == 0) { 18655c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 18665c51f124SMoriah Waterland SUNW_R_SET_LKID_ERR); 18675c51f124SMoriah Waterland retval = 0; 18685c51f124SMoriah Waterland break; 18695c51f124SMoriah Waterland } 18705c51f124SMoriah Waterland } 18715c51f124SMoriah Waterland 18725c51f124SMoriah Waterland if (fname != NULL) { 18735c51f124SMoriah Waterland ASN1_STRING *tmpstr = NULL; 18745c51f124SMoriah Waterland int len; 18755c51f124SMoriah Waterland 18765c51f124SMoriah Waterland if (fname->type != V_ASN1_BMPSTRING) { 18775c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 18785c51f124SMoriah Waterland SUNW_R_BAD_FNAME); 18795c51f124SMoriah Waterland retval = 0; 18805c51f124SMoriah Waterland break; 18815c51f124SMoriah Waterland } 18825c51f124SMoriah Waterland 18835c51f124SMoriah Waterland tmpstr = fname->value.asn1_string; 18845c51f124SMoriah Waterland len = ASN1_STRING_to_UTF8(&data, tmpstr); 18855c51f124SMoriah Waterland if (len < 0) { 18865c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 18875c51f124SMoriah Waterland SUNW_R_SET_FNAME_ERR); 18885c51f124SMoriah Waterland retval = 0; 18895c51f124SMoriah Waterland break; 18905c51f124SMoriah Waterland } 18915c51f124SMoriah Waterland 18925c51f124SMoriah Waterland if (X509_alias_set1(x509, data, len) == 0) { 18935c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 18945c51f124SMoriah Waterland SUNW_R_SET_FNAME_ERR); 18955c51f124SMoriah Waterland retval = 0; 18965c51f124SMoriah Waterland break; 18975c51f124SMoriah Waterland } 18985c51f124SMoriah Waterland } 18995c51f124SMoriah Waterland 19005c51f124SMoriah Waterland if (sk_X509_push(cl, x509) == 0) { 19015c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_MEMORY_FAILURE); 19025c51f124SMoriah Waterland retval = 0; 19035c51f124SMoriah Waterland break; 19045c51f124SMoriah Waterland } 19055c51f124SMoriah Waterland x509 = NULL; 19065c51f124SMoriah Waterland break; 19075c51f124SMoriah Waterland 19085c51f124SMoriah Waterland case NID_safeContentsBag: 19095c51f124SMoriah Waterland if (keyid != NULL) 19105c51f124SMoriah Waterland ASN1_TYPE_free(keyid); 19115c51f124SMoriah Waterland if (fname != NULL) 19125c51f124SMoriah Waterland ASN1_TYPE_free(fname); 19135c51f124SMoriah Waterland if (parse_all_bags(bag->value.safes, pass, kl, cl) == 0) { 19145c51f124SMoriah Waterland /* 19155c51f124SMoriah Waterland * Error already on stack 19165c51f124SMoriah Waterland */ 19175c51f124SMoriah Waterland return (0); 19185c51f124SMoriah Waterland } 19195c51f124SMoriah Waterland return (1); 19205c51f124SMoriah Waterland 19215c51f124SMoriah Waterland default: 19225c51f124SMoriah Waterland if (keyid != NULL) 19235c51f124SMoriah Waterland ASN1_TYPE_free(keyid); 19245c51f124SMoriah Waterland if (fname != NULL) 19255c51f124SMoriah Waterland ASN1_TYPE_free(fname); 19265c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, SUNW_R_BAD_BAGTYPE); 19275c51f124SMoriah Waterland return (0); 19285c51f124SMoriah Waterland } 19295c51f124SMoriah Waterland 19305c51f124SMoriah Waterland 19315c51f124SMoriah Waterland if (pkey != NULL) { 19325c51f124SMoriah Waterland if (retval != 0 && (keyid != NULL || fname != NULL) && 19335c51f124SMoriah Waterland pkey->attributes == NULL) { 19345c51f124SMoriah Waterland pkey->attributes = sk_X509_ATTRIBUTE_new_null(); 19355c51f124SMoriah Waterland if (pkey->attributes == NULL) { 19365c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 19375c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 19385c51f124SMoriah Waterland retval = 0; 19395c51f124SMoriah Waterland } 19405c51f124SMoriah Waterland } 19415c51f124SMoriah Waterland 19425c51f124SMoriah Waterland if (retval != 0 && keyid != NULL) { 19435c51f124SMoriah Waterland attr = type2attrib(keyid, NID_localKeyID); 19445c51f124SMoriah Waterland if (attr == NULL) 19455c51f124SMoriah Waterland /* 19465c51f124SMoriah Waterland * Error already on stack 19475c51f124SMoriah Waterland */ 19485c51f124SMoriah Waterland retval = 0; 19495c51f124SMoriah Waterland else { 19505c51f124SMoriah Waterland keyid = NULL; 19515c51f124SMoriah Waterland if (sk_X509_ATTRIBUTE_push(pkey->attributes, 19525c51f124SMoriah Waterland attr) == 0) { 19535c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 19545c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 19555c51f124SMoriah Waterland retval = 0; 19565c51f124SMoriah Waterland } else { 19575c51f124SMoriah Waterland attr = NULL; 19585c51f124SMoriah Waterland } 19595c51f124SMoriah Waterland } 19605c51f124SMoriah Waterland } 19615c51f124SMoriah Waterland 19625c51f124SMoriah Waterland if (retval != 0 && fname != NULL) { 19635c51f124SMoriah Waterland attr = type2attrib(fname, NID_friendlyName); 19645c51f124SMoriah Waterland if (attr == NULL) { 19655c51f124SMoriah Waterland /* 19665c51f124SMoriah Waterland * Error already on stack 19675c51f124SMoriah Waterland */ 19685c51f124SMoriah Waterland retval = 0; 19695c51f124SMoriah Waterland } else { 19705c51f124SMoriah Waterland fname = NULL; 19715c51f124SMoriah Waterland if (sk_X509_ATTRIBUTE_push(pkey->attributes, 19725c51f124SMoriah Waterland attr) == 0) { 19735c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 19745c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 19755c51f124SMoriah Waterland retval = 0; 19765c51f124SMoriah Waterland } else { 19775c51f124SMoriah Waterland attr = NULL; 19785c51f124SMoriah Waterland } 19795c51f124SMoriah Waterland } 19805c51f124SMoriah Waterland } 19815c51f124SMoriah Waterland 19825c51f124SMoriah Waterland /* Save the private key */ 19835c51f124SMoriah Waterland if (retval != 0) { 19845c51f124SMoriah Waterland if (sk_EVP_PKEY_push(kl, pkey) == 0) { 19855c51f124SMoriah Waterland SUNWerr(SUNW_F_PARSE_ONE_BAG, 19865c51f124SMoriah Waterland SUNW_R_MEMORY_FAILURE); 19875c51f124SMoriah Waterland retval = 0; 19885c51f124SMoriah Waterland } else { 19895c51f124SMoriah Waterland pkey = NULL; 19905c51f124SMoriah Waterland } 19915c51f124SMoriah Waterland } 19925c51f124SMoriah Waterland } 19935c51f124SMoriah Waterland 19945c51f124SMoriah Waterland if (pkey != NULL) { 19955c51f124SMoriah Waterland sunw_evp_pkey_free(pkey); 19965c51f124SMoriah Waterland } 19975c51f124SMoriah Waterland 19985c51f124SMoriah Waterland if (x509 != NULL) 19995c51f124SMoriah Waterland X509_free(x509); 20005c51f124SMoriah Waterland 20015c51f124SMoriah Waterland if (keyid != NULL) 20025c51f124SMoriah Waterland ASN1_TYPE_free(keyid); 20035c51f124SMoriah Waterland 20045c51f124SMoriah Waterland if (fname != NULL) 20055c51f124SMoriah Waterland ASN1_TYPE_free(fname); 20065c51f124SMoriah Waterland 20075c51f124SMoriah Waterland if (attr != NULL) 20085c51f124SMoriah Waterland X509_ATTRIBUTE_free(attr); 20095c51f124SMoriah Waterland 20105c51f124SMoriah Waterland if (data != NULL) 20115c51f124SMoriah Waterland OPENSSL_free(data); 20125c51f124SMoriah Waterland 20135c51f124SMoriah Waterland if (str != NULL) 20145c51f124SMoriah Waterland OPENSSL_free(str); 20155c51f124SMoriah Waterland 20165c51f124SMoriah Waterland return (retval); 20175c51f124SMoriah Waterland } 20185c51f124SMoriah Waterland 20195c51f124SMoriah Waterland /* 20205c51f124SMoriah Waterland * This function uses the only function that reads PEM files, regardless of 20215c51f124SMoriah Waterland * the kinds of information included (private keys, public keys, cert requests, 20225c51f124SMoriah Waterland * certs). Other interfaces that read files require that the application 20235c51f124SMoriah Waterland * specifically know what kinds of things to read next, and call different 20245c51f124SMoriah Waterland * interfaces for the different kinds of entities. 20255c51f124SMoriah Waterland * 20265c51f124SMoriah Waterland * There is only one aspect of this function that's a bit problematic. 20275c51f124SMoriah Waterland * If it finds an encrypted private key, it does not decrypt it. It returns 20285c51f124SMoriah Waterland * the encrypted data and other information needed to decrypt it. The caller 20295c51f124SMoriah Waterland * must do the decryption. This function does the decoding. 20305c51f124SMoriah Waterland */ 20315c51f124SMoriah Waterland static int 20325c51f124SMoriah Waterland pem_info(FILE *fp, pem_password_cb cb, void *userdata, 20335c51f124SMoriah Waterland STACK_OF(EVP_PKEY) **pkeys, STACK_OF(X509) **certs) 20345c51f124SMoriah Waterland { 20355c51f124SMoriah Waterland STACK_OF(X509_INFO) *info; 20365c51f124SMoriah Waterland STACK_OF(EVP_PKEY) *work_kl; 20375c51f124SMoriah Waterland STACK_OF(X509) *work_cl; 20385c51f124SMoriah Waterland X509_INFO *x; 20395c51f124SMoriah Waterland int retval = 0; 20405c51f124SMoriah Waterland int i; 20415c51f124SMoriah Waterland 20425c51f124SMoriah Waterland info = PEM_X509_INFO_read(fp, NULL, cb, userdata); 20435c51f124SMoriah Waterland if (info == NULL) { 20445c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, SUNW_R_READ_ERR); 20455c51f124SMoriah Waterland return (-1); 20465c51f124SMoriah Waterland } 20475c51f124SMoriah Waterland 20485c51f124SMoriah Waterland /* 20495c51f124SMoriah Waterland * Allocate the working stacks for private key(s) and for the cert(s). 20505c51f124SMoriah Waterland */ 20515c51f124SMoriah Waterland if ((work_kl = sk_EVP_PKEY_new_null()) == NULL) { 20525c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE); 20535c51f124SMoriah Waterland retval = -1; 20545c51f124SMoriah Waterland goto cleanup; 20555c51f124SMoriah Waterland } 20565c51f124SMoriah Waterland 20575c51f124SMoriah Waterland if ((work_cl = sk_X509_new_null()) == NULL) { 20585c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, SUNW_R_MEMORY_FAILURE); 20595c51f124SMoriah Waterland retval = -1; 20605c51f124SMoriah Waterland goto cleanup; 20615c51f124SMoriah Waterland } 20625c51f124SMoriah Waterland 20635c51f124SMoriah Waterland /* 20645c51f124SMoriah Waterland * Go through the entries in the info structure. 20655c51f124SMoriah Waterland */ 20665c51f124SMoriah Waterland for (i = 0; i < sk_X509_INFO_num(info); i++) { 20675c51f124SMoriah Waterland x = sk_X509_INFO_value(info, i); 20685c51f124SMoriah Waterland if (x->x509) { 20695c51f124SMoriah Waterland if (sk_X509_push(work_cl, x->x509) == 0) { 20705c51f124SMoriah Waterland retval = -1; 20715c51f124SMoriah Waterland break; 20725c51f124SMoriah Waterland } 20735c51f124SMoriah Waterland x->x509 = NULL; 20745c51f124SMoriah Waterland } 20755c51f124SMoriah Waterland if (x->x_pkey != NULL && x->x_pkey->dec_pkey != NULL && 20765c51f124SMoriah Waterland (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA || 20775c51f124SMoriah Waterland x->x_pkey->dec_pkey->type == EVP_PKEY_DSA)) { 20785c51f124SMoriah Waterland const uchar_t *p; 20795c51f124SMoriah Waterland 20805c51f124SMoriah Waterland /* 20815c51f124SMoriah Waterland * If the key was encrypted, PEM_X509_INFO_read does 20825c51f124SMoriah Waterland * not decrypt it. If that is the case, the 'enc_pkey' 20835c51f124SMoriah Waterland * field is set to point to the unencrypted key data. 20845c51f124SMoriah Waterland * Go through the additional steps to decode it before 20855c51f124SMoriah Waterland * going on. 20865c51f124SMoriah Waterland */ 20875c51f124SMoriah Waterland if (x->x_pkey->enc_pkey != NULL) { 20885c51f124SMoriah Waterland 20895c51f124SMoriah Waterland if (PEM_do_header(&x->enc_cipher, 20905c51f124SMoriah Waterland (uchar_t *)x->enc_data, 20915c51f124SMoriah Waterland (long *)&x->enc_len, 20925c51f124SMoriah Waterland cb, userdata) == 0) { 20935c51f124SMoriah Waterland if (ERR_GET_REASON(ERR_peek_error()) == 20945c51f124SMoriah Waterland PEM_R_BAD_PASSWORD_READ) { 20955c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, 20965c51f124SMoriah Waterland SUNW_R_PASSWORD_ERR); 20975c51f124SMoriah Waterland } else { 20985c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, 20995c51f124SMoriah Waterland SUNW_R_PKEY_READ_ERR); 21005c51f124SMoriah Waterland } 21015c51f124SMoriah Waterland retval = -1; 21025c51f124SMoriah Waterland break; 21035c51f124SMoriah Waterland } 21045c51f124SMoriah Waterland if (x->x_pkey->dec_pkey->type == EVP_PKEY_RSA) { 21055c51f124SMoriah Waterland RSA **pp; 21065c51f124SMoriah Waterland 21075c51f124SMoriah Waterland pp = &(x->x_pkey->dec_pkey->pkey.rsa); 21085c51f124SMoriah Waterland p = (uchar_t *)x->enc_data; 21095c51f124SMoriah Waterland if (d2i_RSAPrivateKey(pp, &p, 21105c51f124SMoriah Waterland x->enc_len) == NULL) { 21115c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, 21125c51f124SMoriah Waterland SUNW_R_PKEY_READ_ERR); 21135c51f124SMoriah Waterland retval = -1; 21145c51f124SMoriah Waterland break; 21155c51f124SMoriah Waterland } 21165c51f124SMoriah Waterland } else { 21175c51f124SMoriah Waterland DSA **pp; 21185c51f124SMoriah Waterland 21195c51f124SMoriah Waterland pp = &(x->x_pkey->dec_pkey->pkey.dsa); 21205c51f124SMoriah Waterland p = (uchar_t *)x->enc_data; 21215c51f124SMoriah Waterland if (d2i_DSAPrivateKey(pp, &p, 21225c51f124SMoriah Waterland x->enc_len) == NULL) { 21235c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, 21245c51f124SMoriah Waterland SUNW_R_PKEY_READ_ERR); 21255c51f124SMoriah Waterland retval = -1; 21265c51f124SMoriah Waterland break; 21275c51f124SMoriah Waterland } 21285c51f124SMoriah Waterland } 21295c51f124SMoriah Waterland } 21305c51f124SMoriah Waterland 21315c51f124SMoriah Waterland /* Save the key. */ 21325c51f124SMoriah Waterland retval = sk_EVP_PKEY_push(work_kl, x->x_pkey->dec_pkey); 21335c51f124SMoriah Waterland if (retval == 0) { 21345c51f124SMoriah Waterland retval = -1; 21355c51f124SMoriah Waterland break; 21365c51f124SMoriah Waterland } 21375c51f124SMoriah Waterland x->x_pkey->dec_pkey = NULL; 21385c51f124SMoriah Waterland } else if (x->x_pkey != NULL) { 21395c51f124SMoriah Waterland SUNWerr(SUNW_F_PEM_INFO, SUNW_R_BAD_PKEYTYPE); 21405c51f124SMoriah Waterland retval = -1; 21415c51f124SMoriah Waterland break; 21425c51f124SMoriah Waterland } 21435c51f124SMoriah Waterland } 21445c51f124SMoriah Waterland if (retval == -1) 21455c51f124SMoriah Waterland goto cleanup; 21465c51f124SMoriah Waterland 21475c51f124SMoriah Waterland /* If error occurs, then error already on stack */ 21485c51f124SMoriah Waterland retval = set_results(pkeys, &work_kl, certs, &work_cl, NULL, NULL, 21495c51f124SMoriah Waterland NULL, NULL); 21505c51f124SMoriah Waterland 21515c51f124SMoriah Waterland cleanup: 21525c51f124SMoriah Waterland if (work_kl != NULL) { 21535c51f124SMoriah Waterland sk_EVP_PKEY_pop_free(work_kl, sunw_evp_pkey_free); 21545c51f124SMoriah Waterland } 21555c51f124SMoriah Waterland if (work_cl != NULL) 21565c51f124SMoriah Waterland sk_X509_pop_free(work_cl, X509_free); 21575c51f124SMoriah Waterland 21585c51f124SMoriah Waterland sk_X509_INFO_pop_free(info, X509_INFO_free); 21595c51f124SMoriah Waterland 21605c51f124SMoriah Waterland return (retval); 21615c51f124SMoriah Waterland } 21625c51f124SMoriah Waterland 21635c51f124SMoriah Waterland /* 21645c51f124SMoriah Waterland * sunw_append_keys - Given two stacks of private keys, remove the keys from 21655c51f124SMoriah Waterland * the second stack and append them to the first. Both stacks must exist 21665c51f124SMoriah Waterland * at time of call. 21675c51f124SMoriah Waterland * 21685c51f124SMoriah Waterland * Arguments: 21695c51f124SMoriah Waterland * dst - the stack to receive the keys from 'src' 21705c51f124SMoriah Waterland * src - the stack whose keys are to be moved. 21715c51f124SMoriah Waterland * 21725c51f124SMoriah Waterland * Returns: 21735c51f124SMoriah Waterland * -1 - An error occurred. The error status is set. 21745c51f124SMoriah Waterland * >= 0 - The number of keys that were copied. 21755c51f124SMoriah Waterland */ 21765c51f124SMoriah Waterland static int 21775c51f124SMoriah Waterland sunw_append_keys(STACK_OF(EVP_PKEY) *dst, STACK_OF(EVP_PKEY) *src) 21785c51f124SMoriah Waterland { 21795c51f124SMoriah Waterland EVP_PKEY *tmpk; 21805c51f124SMoriah Waterland int count = 0; 21815c51f124SMoriah Waterland 21825c51f124SMoriah Waterland while (sk_EVP_PKEY_num(src) > 0) { 21835c51f124SMoriah Waterland tmpk = sk_EVP_PKEY_delete(src, 0); 21845c51f124SMoriah Waterland if (sk_EVP_PKEY_push(dst, tmpk) == 0) { 21855c51f124SMoriah Waterland sunw_evp_pkey_free(tmpk); 21865c51f124SMoriah Waterland SUNWerr(SUNW_F_APPEND_KEYS, SUNW_R_MEMORY_FAILURE); 21875c51f124SMoriah Waterland return (-1); 21885c51f124SMoriah Waterland } 21895c51f124SMoriah Waterland count ++; 21905c51f124SMoriah Waterland } 21915c51f124SMoriah Waterland 21925c51f124SMoriah Waterland return (count); 21935c51f124SMoriah Waterland } 21945c51f124SMoriah Waterland 21955c51f124SMoriah Waterland /* 21965c51f124SMoriah Waterland * move_certs - Given two stacks of certs, remove the certs from 21975c51f124SMoriah Waterland * the second stack and append them to the first. 21985c51f124SMoriah Waterland * 21995c51f124SMoriah Waterland * Arguments: 22005c51f124SMoriah Waterland * dst - the stack to receive the certs from 'src' 22015c51f124SMoriah Waterland * src - the stack whose certs are to be moved. 22025c51f124SMoriah Waterland * 22035c51f124SMoriah Waterland * Returns: 22045c51f124SMoriah Waterland * -1 - An error occurred. The error status is set. 22055c51f124SMoriah Waterland * >= 0 - The number of certs that were copied. 22065c51f124SMoriah Waterland */ 22075c51f124SMoriah Waterland static int 22085c51f124SMoriah Waterland move_certs(STACK_OF(X509) *dst, STACK_OF(X509) *src) 22095c51f124SMoriah Waterland { 22105c51f124SMoriah Waterland X509 *tmpc; 22115c51f124SMoriah Waterland int count = 0; 22125c51f124SMoriah Waterland 22135c51f124SMoriah Waterland while (sk_X509_num(src) > 0) { 22145c51f124SMoriah Waterland tmpc = sk_X509_delete(src, 0); 22155c51f124SMoriah Waterland if (sk_X509_push(dst, tmpc) == 0) { 22165c51f124SMoriah Waterland X509_free(tmpc); 22175c51f124SMoriah Waterland SUNWerr(SUNW_F_MOVE_CERTS, SUNW_R_MEMORY_FAILURE); 22185c51f124SMoriah Waterland return (-1); 22195c51f124SMoriah Waterland } 22205c51f124SMoriah Waterland count++; 22215c51f124SMoriah Waterland } 22225c51f124SMoriah Waterland 22235c51f124SMoriah Waterland return (count); 22245c51f124SMoriah Waterland } 22255c51f124SMoriah Waterland 22265c51f124SMoriah Waterland /* 22275c51f124SMoriah Waterland * get_key_cert - Get a cert and its matching key from the stacks of certs 22285c51f124SMoriah Waterland * and keys. They are removed from the stacks. 22295c51f124SMoriah Waterland * 22305c51f124SMoriah Waterland * Arguments: 22315c51f124SMoriah Waterland * n - Offset of the entries to return. 22325c51f124SMoriah Waterland * kl - Points to a stack of private keys that matches the list of 22335c51f124SMoriah Waterland * certs below. 22345c51f124SMoriah Waterland * pkey - Points at location where the address of the matching private 22355c51f124SMoriah Waterland * key will be stored. 22365c51f124SMoriah Waterland * cl - Points to a stack of client certs with matching private keys. 22375c51f124SMoriah Waterland * cert - Points to locaiton where the address of the matching client cert 22385c51f124SMoriah Waterland * will be returned 22395c51f124SMoriah Waterland * 22405c51f124SMoriah Waterland * The assumption is that the stacks of keys and certs contain key/cert pairs, 22415c51f124SMoriah Waterland * with entries in the same order and hence at the same offset. Provided 22425c51f124SMoriah Waterland * the key and cert selected match, each will be removed from its stack and 22435c51f124SMoriah Waterland * returned. 22445c51f124SMoriah Waterland * 22455c51f124SMoriah Waterland * A stack of certs can be passed in without a stack of private keys, and vise 22465c51f124SMoriah Waterland * versa. In that case, the indicated key/cert will be returned. 22475c51f124SMoriah Waterland * 22485c51f124SMoriah Waterland * Returns: 22495c51f124SMoriah Waterland * 0 - No matches were found. 22505c51f124SMoriah Waterland * > 0 - Bits set based on FOUND_* definitions, indicating what is returned. 22515c51f124SMoriah Waterland * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT). 22525c51f124SMoriah Waterland */ 22535c51f124SMoriah Waterland static int 22545c51f124SMoriah Waterland get_key_cert(int n, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, STACK_OF(X509) *cl, 22555c51f124SMoriah Waterland X509 **cert) 22565c51f124SMoriah Waterland { 22575c51f124SMoriah Waterland int retval = 0; 22585c51f124SMoriah Waterland int nk; 22595c51f124SMoriah Waterland int nc; 22605c51f124SMoriah Waterland 22615c51f124SMoriah Waterland nk = (kl != NULL) ? sk_EVP_PKEY_num(kl) : 0; 22625c51f124SMoriah Waterland nc = (cl != NULL) ? sk_X509_num(cl) : 0; 22635c51f124SMoriah Waterland 22645c51f124SMoriah Waterland if (pkey != NULL && *pkey == NULL) { 22655c51f124SMoriah Waterland if (nk > 0 && n >= 0 || n < nk) { 22665c51f124SMoriah Waterland *pkey = sk_EVP_PKEY_delete(kl, n); 22675c51f124SMoriah Waterland if (*pkey != NULL) 22685c51f124SMoriah Waterland retval |= FOUND_PKEY; 22695c51f124SMoriah Waterland } 22705c51f124SMoriah Waterland } 22715c51f124SMoriah Waterland 22725c51f124SMoriah Waterland if (cert != NULL && *cert == NULL) { 22735c51f124SMoriah Waterland if (nc > 0 && n >= 0 && n < nc) { 22745c51f124SMoriah Waterland *cert = sk_X509_delete(cl, n); 22755c51f124SMoriah Waterland if (*cert != NULL) 22765c51f124SMoriah Waterland retval |= FOUND_CERT; 22775c51f124SMoriah Waterland } 22785c51f124SMoriah Waterland } 22795c51f124SMoriah Waterland 22805c51f124SMoriah Waterland return (retval); 22815c51f124SMoriah Waterland } 22825c51f124SMoriah Waterland 22835c51f124SMoriah Waterland 22845c51f124SMoriah Waterland /* 22855c51f124SMoriah Waterland * asc2bmpstring - Convert a regular C ASCII string to an ASn1_STRING in 22865c51f124SMoriah Waterland * ASN1_BMPSTRING format. 22875c51f124SMoriah Waterland * 22885c51f124SMoriah Waterland * Arguments: 22895c51f124SMoriah Waterland * str - String to be convered. 22905c51f124SMoriah Waterland * len - Length of the string. 22915c51f124SMoriah Waterland * 22925c51f124SMoriah Waterland * Returns: 22935c51f124SMoriah Waterland * == NULL - An error occurred. Error information (accessible by 22945c51f124SMoriah Waterland * ERR_get_error()) is set. 22955c51f124SMoriah Waterland * != NULL - Points to an ASN1_BMPSTRING structure with the converted 22965c51f124SMoriah Waterland * string as a value. 22975c51f124SMoriah Waterland */ 22985c51f124SMoriah Waterland static ASN1_BMPSTRING * 22995c51f124SMoriah Waterland asc2bmpstring(const char *str, int len) 23005c51f124SMoriah Waterland { 23015c51f124SMoriah Waterland ASN1_BMPSTRING *bmp = NULL; 23025c51f124SMoriah Waterland uchar_t *uni = NULL; 23035c51f124SMoriah Waterland int unilen; 23045c51f124SMoriah Waterland 23055c51f124SMoriah Waterland /* Convert the character to the bmp format. */ 2306*70f9559bSTheo Schlossnagle #if OPENSSL_VERSION_NUMBER < 0x10000000L 23075c51f124SMoriah Waterland if (asc2uni(str, len, &uni, &unilen) == 0) { 2308*70f9559bSTheo Schlossnagle #else 2309*70f9559bSTheo Schlossnagle if (OPENSSL_asc2uni(str, len, &uni, &unilen) == 0) { 2310*70f9559bSTheo Schlossnagle #endif 23115c51f124SMoriah Waterland SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE); 23125c51f124SMoriah Waterland return (NULL); 23135c51f124SMoriah Waterland } 23145c51f124SMoriah Waterland 23155c51f124SMoriah Waterland /* 23165c51f124SMoriah Waterland * Adjust for possible pair of NULL bytes at the end because 23175c51f124SMoriah Waterland * asc2uni() returns a doubly null terminated string. 23185c51f124SMoriah Waterland */ 23195c51f124SMoriah Waterland if (uni[unilen - 1] == '\0' && uni[unilen - 2] == '\0') 23205c51f124SMoriah Waterland unilen -= 2; 23215c51f124SMoriah Waterland 23225c51f124SMoriah Waterland /* Construct comparison string with correct format */ 23235c51f124SMoriah Waterland bmp = M_ASN1_BMPSTRING_new(); 23245c51f124SMoriah Waterland if (bmp == NULL) { 23255c51f124SMoriah Waterland SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE); 23265c51f124SMoriah Waterland OPENSSL_free(uni); 23275c51f124SMoriah Waterland return (NULL); 23285c51f124SMoriah Waterland } 23295c51f124SMoriah Waterland 23305c51f124SMoriah Waterland bmp->data = uni; 23315c51f124SMoriah Waterland bmp->length = unilen; 23325c51f124SMoriah Waterland 23335c51f124SMoriah Waterland return (bmp); 23345c51f124SMoriah Waterland } 23355c51f124SMoriah Waterland 23365c51f124SMoriah Waterland /* 23375c51f124SMoriah Waterland * utf82ascstr - Convert a UTF8STRING string to a regular C ASCII string. 23385c51f124SMoriah Waterland * This goes through an intermediate step with a ASN1_STRING type of 23395c51f124SMoriah Waterland * IA5STRING (International Alphabet 5, which is the same as ASCII). 23405c51f124SMoriah Waterland * 23415c51f124SMoriah Waterland * Arguments: 23425c51f124SMoriah Waterland * str - UTF8STRING to be converted. 23435c51f124SMoriah Waterland * 23445c51f124SMoriah Waterland * Returns: 23455c51f124SMoriah Waterland * == NULL - An error occurred. Error information (accessible by 23465c51f124SMoriah Waterland * ERR_get_error()) is set. 23475c51f124SMoriah Waterland * != NULL - Points to a NULL-termianted ASCII string. The caller must 23485c51f124SMoriah Waterland * free it. 23495c51f124SMoriah Waterland */ 23505c51f124SMoriah Waterland static uchar_t * 23515c51f124SMoriah Waterland utf82ascstr(ASN1_UTF8STRING *ustr) 23525c51f124SMoriah Waterland { 23535c51f124SMoriah Waterland ASN1_STRING tmpstr; 23545c51f124SMoriah Waterland ASN1_STRING *astr = &tmpstr; 23555c51f124SMoriah Waterland uchar_t *retstr = NULL; 23565c51f124SMoriah Waterland int mbflag; 23575c51f124SMoriah Waterland int ret; 23585c51f124SMoriah Waterland 23595c51f124SMoriah Waterland if (ustr == NULL || ustr->type != V_ASN1_UTF8STRING) { 23605c51f124SMoriah Waterland SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_INVALID_ARG); 23615c51f124SMoriah Waterland return (NULL); 23625c51f124SMoriah Waterland } 23635c51f124SMoriah Waterland 23645c51f124SMoriah Waterland mbflag = MBSTRING_ASC; 23655c51f124SMoriah Waterland tmpstr.data = NULL; 23665c51f124SMoriah Waterland tmpstr.length = 0; 23675c51f124SMoriah Waterland 23685c51f124SMoriah Waterland ret = ASN1_mbstring_copy(&astr, ustr->data, ustr->length, mbflag, 23695c51f124SMoriah Waterland B_ASN1_IA5STRING); 23705c51f124SMoriah Waterland if (ret < 0) { 23715c51f124SMoriah Waterland SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_STR_CONVERT_ERR); 23725c51f124SMoriah Waterland return (NULL); 23735c51f124SMoriah Waterland } 23745c51f124SMoriah Waterland 23755c51f124SMoriah Waterland retstr = OPENSSL_malloc(astr->length + 1); 23765c51f124SMoriah Waterland if (retstr == NULL) { 23775c51f124SMoriah Waterland SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_MEMORY_FAILURE); 23785c51f124SMoriah Waterland return (NULL); 23795c51f124SMoriah Waterland } 23805c51f124SMoriah Waterland 23815c51f124SMoriah Waterland (void) memcpy(retstr, astr->data, astr->length); 23825c51f124SMoriah Waterland retstr[astr->length] = '\0'; 23835c51f124SMoriah Waterland OPENSSL_free(astr->data); 23845c51f124SMoriah Waterland 23855c51f124SMoriah Waterland return (retstr); 23865c51f124SMoriah Waterland } 23875c51f124SMoriah Waterland 23885c51f124SMoriah Waterland 23895c51f124SMoriah Waterland /* 23905c51f124SMoriah Waterland * type2attrib - Given a ASN1_TYPE, return a X509_ATTRIBUTE of the type 23915c51f124SMoriah Waterland * specified by the given NID. 23925c51f124SMoriah Waterland * 23935c51f124SMoriah Waterland * Arguments: 23945c51f124SMoriah Waterland * ty - Type structure to be made into an attribute 23955c51f124SMoriah Waterland * nid - NID of the attribute 23965c51f124SMoriah Waterland * 23975c51f124SMoriah Waterland * Returns: 23985c51f124SMoriah Waterland * NULL An error occurred. 23995c51f124SMoriah Waterland * != NULL An X509_ATTRIBUTE structure. 24005c51f124SMoriah Waterland */ 24015c51f124SMoriah Waterland X509_ATTRIBUTE * 24025c51f124SMoriah Waterland type2attrib(ASN1_TYPE *ty, int nid) 24035c51f124SMoriah Waterland { 24045c51f124SMoriah Waterland X509_ATTRIBUTE *a; 24055c51f124SMoriah Waterland 24065c51f124SMoriah Waterland if ((a = X509_ATTRIBUTE_new()) == NULL || 24075c51f124SMoriah Waterland (a->value.set = sk_ASN1_TYPE_new_null()) == NULL || 24085c51f124SMoriah Waterland sk_ASN1_TYPE_push(a->value.set, ty) == 0) { 24095c51f124SMoriah Waterland if (a != NULL) 24105c51f124SMoriah Waterland X509_ATTRIBUTE_free(a); 24115c51f124SMoriah Waterland SUNWerr(SUNW_F_TYPE2ATTRIB, SUNW_R_MEMORY_FAILURE); 24125c51f124SMoriah Waterland return (NULL); 24135c51f124SMoriah Waterland } 24145c51f124SMoriah Waterland a->single = 0; 24155c51f124SMoriah Waterland a->object = OBJ_nid2obj(nid); 24165c51f124SMoriah Waterland 24175c51f124SMoriah Waterland return (a); 24185c51f124SMoriah Waterland } 24195c51f124SMoriah Waterland 24205c51f124SMoriah Waterland /* 24215c51f124SMoriah Waterland * attrib2type - Given a X509_ATTRIBUTE, return pointer to the ASN1_TYPE 24225c51f124SMoriah Waterland * component 24235c51f124SMoriah Waterland * 24245c51f124SMoriah Waterland * Arguments: 24255c51f124SMoriah Waterland * attr - Attribute structure containing a type. 24265c51f124SMoriah Waterland * 24275c51f124SMoriah Waterland * Returns: 24285c51f124SMoriah Waterland * NULL An error occurred. 24295c51f124SMoriah Waterland * != NULL An ASN1_TYPE structure. 24305c51f124SMoriah Waterland */ 24315c51f124SMoriah Waterland static ASN1_TYPE * 24325c51f124SMoriah Waterland attrib2type(X509_ATTRIBUTE *attr) 24335c51f124SMoriah Waterland { 24345c51f124SMoriah Waterland ASN1_TYPE *ty = NULL; 24355c51f124SMoriah Waterland 24365c51f124SMoriah Waterland if (attr == NULL || attr->single == 1) 24375c51f124SMoriah Waterland return (NULL); 24385c51f124SMoriah Waterland 24395c51f124SMoriah Waterland if (sk_ASN1_TYPE_num(attr->value.set) > 0) 24405c51f124SMoriah Waterland ty = sk_ASN1_TYPE_value(attr->value.set, 0); 24415c51f124SMoriah Waterland 24425c51f124SMoriah Waterland return (ty); 24435c51f124SMoriah Waterland } 24445c51f124SMoriah Waterland 24455c51f124SMoriah Waterland /* 24465c51f124SMoriah Waterland * find_attr_by_nid - Given a ASN1_TYPE, return the offset of a X509_ATTRIBUTE 24475c51f124SMoriah Waterland * of the type specified by the given NID. 24485c51f124SMoriah Waterland * 24495c51f124SMoriah Waterland * Arguments: 24505c51f124SMoriah Waterland * attrs - Stack of attributes to search 24515c51f124SMoriah Waterland * nid - NID of the attribute being searched for 24525c51f124SMoriah Waterland * 24535c51f124SMoriah Waterland * Returns: 24545c51f124SMoriah Waterland * -1 None found 24555c51f124SMoriah Waterland * != -1 Offset of the matching attribute. 24565c51f124SMoriah Waterland */ 24575c51f124SMoriah Waterland static int 24585c51f124SMoriah Waterland find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *attrs, int nid) 24595c51f124SMoriah Waterland { 24605c51f124SMoriah Waterland X509_ATTRIBUTE *a; 24615c51f124SMoriah Waterland int i; 24625c51f124SMoriah Waterland 24635c51f124SMoriah Waterland if (attrs == NULL) 24645c51f124SMoriah Waterland return (-1); 24655c51f124SMoriah Waterland 24665c51f124SMoriah Waterland for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) { 24675c51f124SMoriah Waterland a = sk_X509_ATTRIBUTE_value(attrs, i); 24685c51f124SMoriah Waterland if (OBJ_obj2nid(a->object) == nid) 24695c51f124SMoriah Waterland return (i); 24705c51f124SMoriah Waterland } 24715c51f124SMoriah Waterland return (-1); 24725c51f124SMoriah Waterland } 24735c51f124SMoriah Waterland 24745c51f124SMoriah Waterland /* 24755c51f124SMoriah Waterland * Called by our PKCS12 code to read our function and error codes 24765c51f124SMoriah Waterland * into memory so that the OpenSSL framework can retrieve them. 24775c51f124SMoriah Waterland */ 24785c51f124SMoriah Waterland void 24795c51f124SMoriah Waterland ERR_load_SUNW_strings(void) 24805c51f124SMoriah Waterland { 24815c51f124SMoriah Waterland assert(SUNW_lib_error_code == 0); 24825c51f124SMoriah Waterland #ifndef OPENSSL_NO_ERR 24835c51f124SMoriah Waterland /* 24845c51f124SMoriah Waterland * Have OpenSSL provide us with a unique ID. 24855c51f124SMoriah Waterland */ 24865c51f124SMoriah Waterland SUNW_lib_error_code = ERR_get_next_error_library(); 24875c51f124SMoriah Waterland 24885c51f124SMoriah Waterland ERR_load_strings(SUNW_lib_error_code, SUNW_str_functs); 24895c51f124SMoriah Waterland ERR_load_strings(SUNW_lib_error_code, SUNW_str_reasons); 24905c51f124SMoriah Waterland 24915c51f124SMoriah Waterland SUNW_lib_name->error = ERR_PACK(SUNW_lib_error_code, 0, 0); 24925c51f124SMoriah Waterland ERR_load_strings(0, SUNW_lib_name); 24935c51f124SMoriah Waterland #endif 24945c51f124SMoriah Waterland } 24955c51f124SMoriah Waterland 24965c51f124SMoriah Waterland /* 24975c51f124SMoriah Waterland * The SUNWerr macro resolves to this routine. So when we need 24985c51f124SMoriah Waterland * to push an error, this routine does it for us. Notice that 24995c51f124SMoriah Waterland * the SUNWerr macro provides a filename and line #. 25005c51f124SMoriah Waterland */ 25015c51f124SMoriah Waterland void 25025c51f124SMoriah Waterland ERR_SUNW_error(int function, int reason, char *file, int line) 25035c51f124SMoriah Waterland { 25045c51f124SMoriah Waterland assert(SUNW_lib_error_code != 0); 25055c51f124SMoriah Waterland #ifndef OPENSSL_NO_ERR 25065c51f124SMoriah Waterland ERR_PUT_error(SUNW_lib_error_code, function, reason, file, line); 25075c51f124SMoriah Waterland #endif 25085c51f124SMoriah Waterland } 25095c51f124SMoriah Waterland 25105c51f124SMoriah Waterland /* 25115c51f124SMoriah Waterland * check_time - Given an indication of the which time(s) to check, check 25125c51f124SMoriah Waterland * that time or those times against the current time and return the 25135c51f124SMoriah Waterland * relationship. 25145c51f124SMoriah Waterland * 25155c51f124SMoriah Waterland * Arguments: 25165c51f124SMoriah Waterland * chkwhat - What kind of check to do. 25175c51f124SMoriah Waterland * cert - The cert to check. 25185c51f124SMoriah Waterland * 25195c51f124SMoriah Waterland * Returns: 25205c51f124SMoriah Waterland * CHKERR_* values. 25215c51f124SMoriah Waterland */ 25225c51f124SMoriah Waterland static chk_errs_t 25235c51f124SMoriah Waterland check_time(chk_actions_t chkwhat, X509 *cert) 25245c51f124SMoriah Waterland { 25255c51f124SMoriah Waterland int i; 25265c51f124SMoriah Waterland 25275c51f124SMoriah Waterland if (chkwhat == CHK_NOT_BEFORE || chkwhat == CHK_BOTH) { 25285c51f124SMoriah Waterland i = X509_cmp_time(X509_get_notBefore(cert), NULL); 25295c51f124SMoriah Waterland if (i == 0) 25305c51f124SMoriah Waterland return (CHKERR_TIME_BEFORE_BAD); 25315c51f124SMoriah Waterland if (i > 0) 25325c51f124SMoriah Waterland return (CHKERR_TIME_IS_BEFORE); 25335c51f124SMoriah Waterland 25345c51f124SMoriah Waterland /* The current time is after the 'not before' time */ 25355c51f124SMoriah Waterland } 25365c51f124SMoriah Waterland 25375c51f124SMoriah Waterland if (chkwhat == CHK_NOT_AFTER || chkwhat == CHK_BOTH) { 25385c51f124SMoriah Waterland i = X509_cmp_time(X509_get_notAfter(cert), NULL); 25395c51f124SMoriah Waterland if (i == 0) 25405c51f124SMoriah Waterland return (CHKERR_TIME_AFTER_BAD); 25415c51f124SMoriah Waterland if (i < 0) 25425c51f124SMoriah Waterland return (CHKERR_TIME_HAS_EXPIRED); 25435c51f124SMoriah Waterland } 25445c51f124SMoriah Waterland 25455c51f124SMoriah Waterland return (CHKERR_TIME_OK); 25465c51f124SMoriah Waterland } 25475c51f124SMoriah Waterland 25485c51f124SMoriah Waterland /* 25495c51f124SMoriah Waterland * find_attr - Look for a given attribute of the type associated with the NID. 25505c51f124SMoriah Waterland * 25515c51f124SMoriah Waterland * Arguments: 25525c51f124SMoriah Waterland * nid - NID for the attribute to be found (either NID_friendlyName or 25535c51f124SMoriah Waterland * NID_locakKeyId) 25545c51f124SMoriah Waterland * str - ASN1_STRING-type structure containing the value to be found, 25555c51f124SMoriah Waterland * FriendlyName expects a ASN1_BMPSTRING and localKeyID uses a 25565c51f124SMoriah Waterland * ASN1_STRING. 25575c51f124SMoriah Waterland * kl - Points to a stack of private keys. 25585c51f124SMoriah Waterland * pkey - Points at a location where the address of the matching private 25595c51f124SMoriah Waterland * key will be stored. 25605c51f124SMoriah Waterland * cl - Points to a stack of client certs with matching private keys. 25615c51f124SMoriah Waterland * cert - Points to locaiton where the address of the matching client cert 25625c51f124SMoriah Waterland * will be returned 25635c51f124SMoriah Waterland * 25645c51f124SMoriah Waterland * This function is designed to process lists of certs and private keys. 25655c51f124SMoriah Waterland * This is made complex because these the attributes are stored differently 25665c51f124SMoriah Waterland * for certs and for keys. For certs, only a few attributes are retained. 25675c51f124SMoriah Waterland * FriendlyName is stored in the aux structure, under the name 'alias'. 25685c51f124SMoriah Waterland * LocalKeyId is also stored in the aux structure, under the name 'keyid'. 25695c51f124SMoriah Waterland * A pkey structure has a stack of attributes. 25705c51f124SMoriah Waterland * 25715c51f124SMoriah Waterland * The basic approach is: 25725c51f124SMoriah Waterland * - If there there is no stack of certs but a stack of private keys exists, 25735c51f124SMoriah Waterland * search the stack of keys for a match. Alternately, if there is a stack 25745c51f124SMoriah Waterland * of certs and no private keys, search the certs. 25755c51f124SMoriah Waterland * 25765c51f124SMoriah Waterland * - If there are both certs and keys, assume that the matching certs and 25775c51f124SMoriah Waterland * keys are in their respective stacks, with matching entries in the same 25785c51f124SMoriah Waterland * order. Search for the name or keyid in the stack of certs. If it is 25795c51f124SMoriah Waterland * not found, then this function returns 0 (nothing found). 25805c51f124SMoriah Waterland * 25815c51f124SMoriah Waterland * - Once a cert is found, verify that the key actually matches by 25825c51f124SMoriah Waterland * comparing the private key with the public key (in the cert). 25835c51f124SMoriah Waterland * If they don't match, return an error. 25845c51f124SMoriah Waterland * 25855c51f124SMoriah Waterland * A pointer to cert and/or pkey which matches the name or keyid is stored 25865c51f124SMoriah Waterland * in the return arguments. 25875c51f124SMoriah Waterland * 25885c51f124SMoriah Waterland * Returns: 25895c51f124SMoriah Waterland * 0 - No matches were found. 25905c51f124SMoriah Waterland * > 0 - Bits set based on FOUND_* definitions, indicating what was found. 25915c51f124SMoriah Waterland * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT). 25925c51f124SMoriah Waterland */ 25935c51f124SMoriah Waterland static int 25945c51f124SMoriah Waterland find_attr(int nid, ASN1_STRING *str, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, 25955c51f124SMoriah Waterland STACK_OF(X509) *cl, X509 **cert) 25965c51f124SMoriah Waterland { 25975c51f124SMoriah Waterland ASN1_UTF8STRING *ustr = NULL; 25985c51f124SMoriah Waterland ASN1_STRING *s; 25995c51f124SMoriah Waterland ASN1_TYPE *t; 26005c51f124SMoriah Waterland EVP_PKEY *p; 26015c51f124SMoriah Waterland uchar_t *fname = NULL; 26025c51f124SMoriah Waterland X509 *x; 26035c51f124SMoriah Waterland int found = 0; 26045c51f124SMoriah Waterland int chkcerts; 26055c51f124SMoriah Waterland int len; 26065c51f124SMoriah Waterland int res; 26075c51f124SMoriah Waterland int c = -1; 26085c51f124SMoriah Waterland int k = -1; 26095c51f124SMoriah Waterland 26105c51f124SMoriah Waterland chkcerts = (cert != NULL || pkey != NULL) && cl != NULL; 26115c51f124SMoriah Waterland if (chkcerts && nid == NID_friendlyName && 26125c51f124SMoriah Waterland str->type == V_ASN1_BMPSTRING) { 26135c51f124SMoriah Waterland ustr = ASN1_UTF8STRING_new(); 26145c51f124SMoriah Waterland if (ustr == NULL) { 26155c51f124SMoriah Waterland SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE); 26165c51f124SMoriah Waterland return (0); 26175c51f124SMoriah Waterland } 26185c51f124SMoriah Waterland len = ASN1_STRING_to_UTF8(&fname, str); 26195c51f124SMoriah Waterland if (fname == NULL) { 26205c51f124SMoriah Waterland ASN1_UTF8STRING_free(ustr); 26215c51f124SMoriah Waterland SUNWerr(SUNW_F_FINDATTR, SUNW_R_STR_CONVERT_ERR); 26225c51f124SMoriah Waterland return (0); 26235c51f124SMoriah Waterland } 26245c51f124SMoriah Waterland 26255c51f124SMoriah Waterland if (ASN1_STRING_set(ustr, fname, len) == 0) { 26265c51f124SMoriah Waterland ASN1_UTF8STRING_free(ustr); 26275c51f124SMoriah Waterland OPENSSL_free(fname); 26285c51f124SMoriah Waterland SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE); 26295c51f124SMoriah Waterland return (0); 26305c51f124SMoriah Waterland } 26315c51f124SMoriah Waterland } 26325c51f124SMoriah Waterland 26335c51f124SMoriah Waterland if (chkcerts) { 26345c51f124SMoriah Waterland for (c = 0; c < sk_X509_num(cl); c++) { 26355c51f124SMoriah Waterland res = -1; 26365c51f124SMoriah Waterland x = sk_X509_value(cl, c); 26375c51f124SMoriah Waterland if (nid == NID_friendlyName && ustr != NULL) { 26385c51f124SMoriah Waterland if (x->aux == NULL || x->aux->alias == NULL) 26395c51f124SMoriah Waterland continue; 26405c51f124SMoriah Waterland s = x->aux->alias; 26415c51f124SMoriah Waterland if (s != NULL && s->type == ustr->type && 26425c51f124SMoriah Waterland s->data != NULL) { 26435c51f124SMoriah Waterland res = ASN1_STRING_cmp(s, ustr); 26445c51f124SMoriah Waterland } 26455c51f124SMoriah Waterland } else { 26465c51f124SMoriah Waterland if (x->aux == NULL || x->aux->keyid == NULL) 26475c51f124SMoriah Waterland continue; 26485c51f124SMoriah Waterland s = x->aux->keyid; 26495c51f124SMoriah Waterland if (s != NULL && s->type == str->type && 26505c51f124SMoriah Waterland s->data != NULL) { 26515c51f124SMoriah Waterland res = ASN1_STRING_cmp(s, str); 26525c51f124SMoriah Waterland } 26535c51f124SMoriah Waterland } 26545c51f124SMoriah Waterland if (res == 0) { 26555c51f124SMoriah Waterland if (cert != NULL) 26565c51f124SMoriah Waterland *cert = sk_X509_delete(cl, c); 26575c51f124SMoriah Waterland found = FOUND_CERT; 26585c51f124SMoriah Waterland break; 26595c51f124SMoriah Waterland } 26605c51f124SMoriah Waterland } 26615c51f124SMoriah Waterland if (ustr != NULL) { 26625c51f124SMoriah Waterland ASN1_UTF8STRING_free(ustr); 26635c51f124SMoriah Waterland OPENSSL_free(fname); 26645c51f124SMoriah Waterland } 26655c51f124SMoriah Waterland } 26665c51f124SMoriah Waterland 26675c51f124SMoriah Waterland if (pkey != NULL && kl != NULL) { 26685c51f124SMoriah Waterland /* 26695c51f124SMoriah Waterland * Looking for pkey to match a cert? If so, assume that 26705c51f124SMoriah Waterland * lists of certs and their matching pkeys are in the same 26715c51f124SMoriah Waterland * order. Call X509_check_private_key() to verify this 26725c51f124SMoriah Waterland * assumption. 26735c51f124SMoriah Waterland */ 26745c51f124SMoriah Waterland if (found != 0 && cert != NULL) { 26755c51f124SMoriah Waterland k = c; 26765c51f124SMoriah Waterland p = sk_EVP_PKEY_value(kl, k); 26775c51f124SMoriah Waterland if (X509_check_private_key(x, p) != 0) { 26785c51f124SMoriah Waterland if (pkey != NULL) 26795c51f124SMoriah Waterland *pkey = sk_EVP_PKEY_delete(kl, k); 26805c51f124SMoriah Waterland found |= FOUND_PKEY; 26815c51f124SMoriah Waterland } 26825c51f124SMoriah Waterland } else if (cert == NULL) { 26835c51f124SMoriah Waterland for (k = 0; k < sk_EVP_PKEY_num(kl); k++) { 26845c51f124SMoriah Waterland p = sk_EVP_PKEY_value(kl, k); 26855c51f124SMoriah Waterland if (p == NULL || p->attributes == NULL) 26865c51f124SMoriah Waterland continue; 26875c51f124SMoriah Waterland 26885c51f124SMoriah Waterland t = PKCS12_get_attr_gen(p->attributes, nid); 26895c51f124SMoriah Waterland if (t != NULL || ASN1_STRING_cmp(str, 26905c51f124SMoriah Waterland t->value.asn1_string) == 0) 26915c51f124SMoriah Waterland continue; 26925c51f124SMoriah Waterland 26935c51f124SMoriah Waterland found |= FOUND_PKEY; 26945c51f124SMoriah Waterland if (pkey != NULL) 26955c51f124SMoriah Waterland *pkey = sk_EVP_PKEY_delete(kl, k); 26965c51f124SMoriah Waterland break; 26975c51f124SMoriah Waterland } 26985c51f124SMoriah Waterland } 26995c51f124SMoriah Waterland } 27005c51f124SMoriah Waterland 27015c51f124SMoriah Waterland return (found); 27025c51f124SMoriah Waterland } 27035c51f124SMoriah Waterland 27045c51f124SMoriah Waterland /* 27055c51f124SMoriah Waterland * set_results - Given two pointers to stacks of private keys, certs or CA 27065c51f124SMoriah Waterland * CA certs, either copy the second stack to the first, or append the 27075c51f124SMoriah Waterland * contents of the second to the first. 27085c51f124SMoriah Waterland * 27095c51f124SMoriah Waterland * Arguments: 27105c51f124SMoriah Waterland * pkeys - Points to stack of pkeys 27115c51f124SMoriah Waterland * work_kl - Points to working stack of pkeys 27125c51f124SMoriah Waterland * certs - Points to stack of certs 27135c51f124SMoriah Waterland * work_cl - Points to working stack of certs 27145c51f124SMoriah Waterland * cacerts - Points to stack of CA certs 27155c51f124SMoriah Waterland * work_ca - Points to working stack of CA certs 27165c51f124SMoriah Waterland * xtrakeys - Points to stack of unmatcned pkeys 27175c51f124SMoriah Waterland * work_xl - Points to working stack of unmatcned pkeys 27185c51f124SMoriah Waterland * 27195c51f124SMoriah Waterland * The arguments are in pairs. The first of each pair points to a stack 27205c51f124SMoriah Waterland * of keys or certs. The second of the pair points at a 'working stack' 27215c51f124SMoriah Waterland * of the same type of entities. Actions taken are as follows: 27225c51f124SMoriah Waterland * 27235c51f124SMoriah Waterland * - If either the first or second argument is NULL, or if there are no 27245c51f124SMoriah Waterland * members in the second stack, there is nothing to do. 27255c51f124SMoriah Waterland * - If the first argument points to a pointer which is NULL, then there 27265c51f124SMoriah Waterland * is no existing stack for the first argument. Copy the stack pointer 27275c51f124SMoriah Waterland * from the second argument to the first argument and NULL out the stack 27285c51f124SMoriah Waterland * pointer for the second. 27295c51f124SMoriah Waterland * - Otherwise, go through the elements of the second stack, removing each 27305c51f124SMoriah Waterland * and adding it to the first stack. 27315c51f124SMoriah Waterland * 27325c51f124SMoriah Waterland * Returns: 27335c51f124SMoriah Waterland * == -1 - An error occurred. Call ERR_get_error() to get error information. 27345c51f124SMoriah Waterland * == 0 - No matching returns were found. 27355c51f124SMoriah Waterland * > 0 - This is the arithmetic 'or' of the FOUND_* bits that indicate which 27365c51f124SMoriah Waterland * of the requested entries were manipulated. 27375c51f124SMoriah Waterland */ 27385c51f124SMoriah Waterland static int 27395c51f124SMoriah Waterland set_results(STACK_OF(EVP_PKEY) **pkeys, STACK_OF(EVP_PKEY) **work_kl, 27405c51f124SMoriah Waterland STACK_OF(X509) **certs, STACK_OF(X509) **work_cl, 27415c51f124SMoriah Waterland STACK_OF(X509) **cacerts, STACK_OF(X509) **work_ca, 27425c51f124SMoriah Waterland STACK_OF(EVP_PKEY) **xtrakeys, STACK_OF(EVP_PKEY) **work_xl) 27435c51f124SMoriah Waterland { 27445c51f124SMoriah Waterland int retval = 0; 27455c51f124SMoriah Waterland 27465c51f124SMoriah Waterland if (pkeys != NULL && work_kl != NULL && *work_kl != NULL && 27475c51f124SMoriah Waterland sk_EVP_PKEY_num(*work_kl) > 0) { 27485c51f124SMoriah Waterland if (*pkeys == NULL) { 27495c51f124SMoriah Waterland *pkeys = *work_kl; 27505c51f124SMoriah Waterland *work_kl = NULL; 27515c51f124SMoriah Waterland } else { 27525c51f124SMoriah Waterland if (sunw_append_keys(*pkeys, *work_kl) < 0) { 27535c51f124SMoriah Waterland return (-1); 27545c51f124SMoriah Waterland } 27555c51f124SMoriah Waterland } 27565c51f124SMoriah Waterland retval |= FOUND_PKEY; 27575c51f124SMoriah Waterland } 27585c51f124SMoriah Waterland if (certs != NULL && work_cl != NULL && *work_cl != NULL && 27595c51f124SMoriah Waterland sk_X509_num(*work_cl) > 0) { 27605c51f124SMoriah Waterland if (*certs == NULL) { 27615c51f124SMoriah Waterland *certs = *work_cl; 27625c51f124SMoriah Waterland *work_cl = NULL; 27635c51f124SMoriah Waterland } else { 27645c51f124SMoriah Waterland if (move_certs(*certs, *work_cl) < 0) { 27655c51f124SMoriah Waterland return (-1); 27665c51f124SMoriah Waterland } 27675c51f124SMoriah Waterland } 27685c51f124SMoriah Waterland retval |= FOUND_CERT; 27695c51f124SMoriah Waterland } 27705c51f124SMoriah Waterland 27715c51f124SMoriah Waterland if (cacerts != NULL && work_ca != NULL && *work_ca != NULL && 27725c51f124SMoriah Waterland sk_X509_num(*work_ca) > 0) { 27735c51f124SMoriah Waterland if (*cacerts == NULL) { 27745c51f124SMoriah Waterland *cacerts = *work_ca; 27755c51f124SMoriah Waterland *work_ca = NULL; 27765c51f124SMoriah Waterland } else { 27775c51f124SMoriah Waterland if (move_certs(*cacerts, *work_ca) < 0) { 27785c51f124SMoriah Waterland return (-1); 27795c51f124SMoriah Waterland } 27805c51f124SMoriah Waterland } 27815c51f124SMoriah Waterland retval |= FOUND_CA_CERTS; 27825c51f124SMoriah Waterland } 27835c51f124SMoriah Waterland 27845c51f124SMoriah Waterland if (xtrakeys != NULL && work_xl != NULL && *work_xl != NULL && 27855c51f124SMoriah Waterland sk_EVP_PKEY_num(*work_xl) > 0) { 27865c51f124SMoriah Waterland if (*xtrakeys == NULL) { 27875c51f124SMoriah Waterland *xtrakeys = *work_xl; 27885c51f124SMoriah Waterland *work_xl = NULL; 27895c51f124SMoriah Waterland } else { 27905c51f124SMoriah Waterland if (sunw_append_keys(*xtrakeys, *work_xl) < 0) { 27915c51f124SMoriah Waterland return (-1); 27925c51f124SMoriah Waterland } 27935c51f124SMoriah Waterland } 27945c51f124SMoriah Waterland retval |= FOUND_XPKEY; 27955c51f124SMoriah Waterland } 27965c51f124SMoriah Waterland 27975c51f124SMoriah Waterland return (retval); 27985c51f124SMoriah Waterland } 2799