1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * ==================================================================== 3*7c478bd9Sstevel@tonic-gate * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 6*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 7*7c478bd9Sstevel@tonic-gate * are met: 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 10*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 13*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 14*7c478bd9Sstevel@tonic-gate * the documentation and/or other materials provided with the 15*7c478bd9Sstevel@tonic-gate * distribution. 16*7c478bd9Sstevel@tonic-gate * 17*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 18*7c478bd9Sstevel@tonic-gate * software must display the following acknowledgment: 19*7c478bd9Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 20*7c478bd9Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 21*7c478bd9Sstevel@tonic-gate * 22*7c478bd9Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23*7c478bd9Sstevel@tonic-gate * endorse or promote products derived from this software without 24*7c478bd9Sstevel@tonic-gate * prior written permission. For written permission, please contact 25*7c478bd9Sstevel@tonic-gate * licensing@OpenSSL.org. 26*7c478bd9Sstevel@tonic-gate * 27*7c478bd9Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 28*7c478bd9Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 29*7c478bd9Sstevel@tonic-gate * permission of the OpenSSL Project. 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 32*7c478bd9Sstevel@tonic-gate * acknowledgment: 33*7c478bd9Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 34*7c478bd9Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37*7c478bd9Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39*7c478bd9Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40*7c478bd9Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41*7c478bd9Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42*7c478bd9Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43*7c478bd9Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45*7c478bd9Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46*7c478bd9Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47*7c478bd9Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 48*7c478bd9Sstevel@tonic-gate * ==================================================================== 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 51*7c478bd9Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 52*7c478bd9Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 53*7c478bd9Sstevel@tonic-gate * 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * Copyright 2002, 2003 Sun Microsystems, Inc. All rights reserved. 58*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 59*7c478bd9Sstevel@tonic-gate * 60*7c478bd9Sstevel@tonic-gate * All of the functions included here are internal to the pkcs12 functions 61*7c478bd9Sstevel@tonic-gate * in this library. None of these are exposed. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #include <stdio.h> 67*7c478bd9Sstevel@tonic-gate #include <string.h> 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #include <openssl/crypto.h> 70*7c478bd9Sstevel@tonic-gate #include <openssl/err.h> 71*7c478bd9Sstevel@tonic-gate #include <openssl/x509.h> 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #include <openssl/pkcs12.h> 74*7c478bd9Sstevel@tonic-gate #include <p12aux.h> 75*7c478bd9Sstevel@tonic-gate #include <auxutil.h> 76*7c478bd9Sstevel@tonic-gate #include <p12err.h> 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * asc2bmpstring - Convert a regular C ASCII string to an ASn1_STRING in 80*7c478bd9Sstevel@tonic-gate * ASN1_BMPSTRING format. 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * Arguments: 83*7c478bd9Sstevel@tonic-gate * str - String to be convered. 84*7c478bd9Sstevel@tonic-gate * len - Length of the string. 85*7c478bd9Sstevel@tonic-gate * 86*7c478bd9Sstevel@tonic-gate * Returns: 87*7c478bd9Sstevel@tonic-gate * == NULL - An error occurred. Error information (accessible by 88*7c478bd9Sstevel@tonic-gate * ERR_get_error()) is set. 89*7c478bd9Sstevel@tonic-gate * != NULL - Points to an ASN1_BMPSTRING structure with the converted 90*7c478bd9Sstevel@tonic-gate * string as a value. 91*7c478bd9Sstevel@tonic-gate */ 92*7c478bd9Sstevel@tonic-gate ASN1_BMPSTRING * 93*7c478bd9Sstevel@tonic-gate asc2bmpstring(const char *str, int len) 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate ASN1_BMPSTRING *bmp = NULL; 96*7c478bd9Sstevel@tonic-gate uchar_t *uni = NULL; 97*7c478bd9Sstevel@tonic-gate int unilen; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* Convert the character to the bmp format. */ 100*7c478bd9Sstevel@tonic-gate if (asc2uni(str, len, &uni, &unilen) == 0) { 101*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE); 102*7c478bd9Sstevel@tonic-gate return (NULL); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * Adjust for possible pair of NULL bytes at the end because 107*7c478bd9Sstevel@tonic-gate * asc2uni() returns a doubly null terminated string. 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate if (uni[unilen - 1] == '\0' && uni[unilen - 2] == '\0') 110*7c478bd9Sstevel@tonic-gate unilen -= 2; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* Construct comparison string with correct format */ 113*7c478bd9Sstevel@tonic-gate bmp = M_ASN1_BMPSTRING_new(); 114*7c478bd9Sstevel@tonic-gate if (bmp == NULL) { 115*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_ASC2BMPSTRING, SUNW_R_MEMORY_FAILURE); 116*7c478bd9Sstevel@tonic-gate OPENSSL_free(uni); 117*7c478bd9Sstevel@tonic-gate return (NULL); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate bmp->data = uni; 121*7c478bd9Sstevel@tonic-gate bmp->length = unilen; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate return (bmp); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * utf82ascstr - Convert a UTF8STRING string to a regular C ASCII string. 128*7c478bd9Sstevel@tonic-gate * This goes through an intermediate step with a ASN1_STRING type of 129*7c478bd9Sstevel@tonic-gate * IA5STRING (International Alphabet 5, which is the same as ASCII). 130*7c478bd9Sstevel@tonic-gate * 131*7c478bd9Sstevel@tonic-gate * Arguments: 132*7c478bd9Sstevel@tonic-gate * str - UTF8STRING to be converted. 133*7c478bd9Sstevel@tonic-gate * 134*7c478bd9Sstevel@tonic-gate * Returns: 135*7c478bd9Sstevel@tonic-gate * == NULL - An error occurred. Error information (accessible by 136*7c478bd9Sstevel@tonic-gate * ERR_get_error()) is set. 137*7c478bd9Sstevel@tonic-gate * != NULL - Points to a NULL-termianted ASCII string. The caller must 138*7c478bd9Sstevel@tonic-gate * free it. 139*7c478bd9Sstevel@tonic-gate */ 140*7c478bd9Sstevel@tonic-gate uchar_t * 141*7c478bd9Sstevel@tonic-gate utf82ascstr(ASN1_UTF8STRING *ustr) 142*7c478bd9Sstevel@tonic-gate { 143*7c478bd9Sstevel@tonic-gate ASN1_STRING tmpstr; 144*7c478bd9Sstevel@tonic-gate ASN1_STRING *astr = &tmpstr; 145*7c478bd9Sstevel@tonic-gate uchar_t *retstr = NULL; 146*7c478bd9Sstevel@tonic-gate int mbflag; 147*7c478bd9Sstevel@tonic-gate int ret; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate if (ustr == NULL || ustr->type != V_ASN1_UTF8STRING) { 150*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_INVALID_ARG); 151*7c478bd9Sstevel@tonic-gate return (NULL); 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate mbflag = MBSTRING_ASC; 155*7c478bd9Sstevel@tonic-gate tmpstr.data = NULL; 156*7c478bd9Sstevel@tonic-gate tmpstr.length = 0; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate ret = ASN1_mbstring_copy(&astr, ustr->data, ustr->length, mbflag, 159*7c478bd9Sstevel@tonic-gate B_ASN1_IA5STRING); 160*7c478bd9Sstevel@tonic-gate if (ret < 0) { 161*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_STR_CONVERT_ERR); 162*7c478bd9Sstevel@tonic-gate return (NULL); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate retstr = OPENSSL_malloc(astr->length + 1); 166*7c478bd9Sstevel@tonic-gate if (retstr == NULL) { 167*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_UTF82ASCSTR, SUNW_R_MEMORY_FAILURE); 168*7c478bd9Sstevel@tonic-gate return (NULL); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate (void) memcpy(retstr, astr->data, astr->length); 172*7c478bd9Sstevel@tonic-gate retstr[astr->length] = '\0'; 173*7c478bd9Sstevel@tonic-gate OPENSSL_free(astr->data); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate return (retstr); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate /* 179*7c478bd9Sstevel@tonic-gate * set_results - Given two pointers to stacks of private keys, certs or CA 180*7c478bd9Sstevel@tonic-gate * CA certs, either copy the second stack to the first, or append the 181*7c478bd9Sstevel@tonic-gate * contents of the second to the first. 182*7c478bd9Sstevel@tonic-gate * 183*7c478bd9Sstevel@tonic-gate * Arguments: 184*7c478bd9Sstevel@tonic-gate * pkeys - Points to stack of pkeys 185*7c478bd9Sstevel@tonic-gate * work_kl - Points to working stack of pkeys 186*7c478bd9Sstevel@tonic-gate * certs - Points to stack of certs 187*7c478bd9Sstevel@tonic-gate * work_cl - Points to working stack of certs 188*7c478bd9Sstevel@tonic-gate * cacerts - Points to stack of CA certs 189*7c478bd9Sstevel@tonic-gate * work_ca - Points to working stack of CA certs 190*7c478bd9Sstevel@tonic-gate * xtrakeys - Points to stack of unmatcned pkeys 191*7c478bd9Sstevel@tonic-gate * work_xl - Points to working stack of unmatcned pkeys 192*7c478bd9Sstevel@tonic-gate * 193*7c478bd9Sstevel@tonic-gate * The arguments are in pairs. The first of each pair points to a stack 194*7c478bd9Sstevel@tonic-gate * of keys or certs. The second of the pair points at a 'working stack' 195*7c478bd9Sstevel@tonic-gate * of the same type of entities. Actions taken are as follows: 196*7c478bd9Sstevel@tonic-gate * 197*7c478bd9Sstevel@tonic-gate * - If either the first or second argument is NULL, or if there are no 198*7c478bd9Sstevel@tonic-gate * members in the second stack, there is nothing to do. 199*7c478bd9Sstevel@tonic-gate * - If the first argument points to a pointer which is NULL, then there 200*7c478bd9Sstevel@tonic-gate * is no existing stack for the first argument. Copy the stack pointer 201*7c478bd9Sstevel@tonic-gate * from the second argument to the first argument and NULL out the stack 202*7c478bd9Sstevel@tonic-gate * pointer for the second. 203*7c478bd9Sstevel@tonic-gate * - Otherwise, go through the elements of the second stack, removing each 204*7c478bd9Sstevel@tonic-gate * and adding it to the first stack. 205*7c478bd9Sstevel@tonic-gate * 206*7c478bd9Sstevel@tonic-gate * Returns: 207*7c478bd9Sstevel@tonic-gate * == -1 - An error occurred. Call ERR_get_error() to get error information. 208*7c478bd9Sstevel@tonic-gate * == 0 - No matching returns were found. 209*7c478bd9Sstevel@tonic-gate * > 0 - This is the arithmetic 'or' of the FOUND_* bits that indicate which 210*7c478bd9Sstevel@tonic-gate * of the requested entries were manipulated. 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate int 213*7c478bd9Sstevel@tonic-gate set_results(STACK_OF(EVP_PKEY) **pkeys, STACK_OF(EVP_PKEY) **work_kl, 214*7c478bd9Sstevel@tonic-gate STACK_OF(X509) **certs, STACK_OF(X509) **work_cl, 215*7c478bd9Sstevel@tonic-gate STACK_OF(X509) **cacerts, STACK_OF(X509) **work_ca, 216*7c478bd9Sstevel@tonic-gate STACK_OF(EVP_PKEY) **xtrakeys, STACK_OF(EVP_PKEY) **work_xl) 217*7c478bd9Sstevel@tonic-gate { 218*7c478bd9Sstevel@tonic-gate int retval = 0; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if (pkeys != NULL && work_kl != NULL && *work_kl != NULL && 221*7c478bd9Sstevel@tonic-gate sk_EVP_PKEY_num(*work_kl) > 0) { 222*7c478bd9Sstevel@tonic-gate if (*pkeys == NULL) { 223*7c478bd9Sstevel@tonic-gate *pkeys = *work_kl; 224*7c478bd9Sstevel@tonic-gate *work_kl = NULL; 225*7c478bd9Sstevel@tonic-gate } else { 226*7c478bd9Sstevel@tonic-gate if (sunw_append_keys(*pkeys, *work_kl) < 0) { 227*7c478bd9Sstevel@tonic-gate return (-1); 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate retval |= FOUND_PKEY; 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate if (certs != NULL && work_cl != NULL && *work_cl != NULL && 233*7c478bd9Sstevel@tonic-gate sk_X509_num(*work_cl) > 0) { 234*7c478bd9Sstevel@tonic-gate if (*certs == NULL) { 235*7c478bd9Sstevel@tonic-gate *certs = *work_cl; 236*7c478bd9Sstevel@tonic-gate *work_cl = NULL; 237*7c478bd9Sstevel@tonic-gate } else { 238*7c478bd9Sstevel@tonic-gate if (move_certs(*certs, *work_cl) < 0) { 239*7c478bd9Sstevel@tonic-gate return (-1); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate retval |= FOUND_CERT; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (cacerts != NULL && work_ca != NULL && *work_ca != NULL && 246*7c478bd9Sstevel@tonic-gate sk_X509_num(*work_ca) > 0) { 247*7c478bd9Sstevel@tonic-gate if (*cacerts == NULL) { 248*7c478bd9Sstevel@tonic-gate *cacerts = *work_ca; 249*7c478bd9Sstevel@tonic-gate *work_ca = NULL; 250*7c478bd9Sstevel@tonic-gate } else { 251*7c478bd9Sstevel@tonic-gate if (move_certs(*cacerts, *work_ca) < 0) { 252*7c478bd9Sstevel@tonic-gate return (-1); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate retval |= FOUND_CA_CERTS; 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate if (xtrakeys != NULL && work_xl != NULL && *work_xl != NULL && 259*7c478bd9Sstevel@tonic-gate sk_EVP_PKEY_num(*work_xl) > 0) { 260*7c478bd9Sstevel@tonic-gate if (*xtrakeys == NULL) { 261*7c478bd9Sstevel@tonic-gate *xtrakeys = *work_xl; 262*7c478bd9Sstevel@tonic-gate *work_xl = NULL; 263*7c478bd9Sstevel@tonic-gate } else { 264*7c478bd9Sstevel@tonic-gate if (sunw_append_keys(*xtrakeys, *work_xl) < 0) { 265*7c478bd9Sstevel@tonic-gate return (-1); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate retval |= FOUND_XPKEY; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate return (retval); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * find_attr - Look for a given attribute of the type associated with the NID. 276*7c478bd9Sstevel@tonic-gate * 277*7c478bd9Sstevel@tonic-gate * Arguments: 278*7c478bd9Sstevel@tonic-gate * nid - NID for the attribute to be found (either NID_friendlyName or 279*7c478bd9Sstevel@tonic-gate * NID_locakKeyId) 280*7c478bd9Sstevel@tonic-gate * str - ASN1_STRING-type structure containing the value to be found, 281*7c478bd9Sstevel@tonic-gate * FriendlyName expects a ASN1_BMPSTRING and localKeyID uses a 282*7c478bd9Sstevel@tonic-gate * ASN1_STRING. 283*7c478bd9Sstevel@tonic-gate * kl - Points to a stack of private keys. 284*7c478bd9Sstevel@tonic-gate * pkey - Points at a location where the address of the matching private 285*7c478bd9Sstevel@tonic-gate * key will be stored. 286*7c478bd9Sstevel@tonic-gate * cl - Points to a stack of client certs with matching private keys. 287*7c478bd9Sstevel@tonic-gate * cert - Points to locaiton where the address of the matching client cert 288*7c478bd9Sstevel@tonic-gate * will be returned 289*7c478bd9Sstevel@tonic-gate * 290*7c478bd9Sstevel@tonic-gate * This function is designed to process lists of certs and private keys. 291*7c478bd9Sstevel@tonic-gate * This is made complex because these the attributes are stored differently 292*7c478bd9Sstevel@tonic-gate * for certs and for keys. For certs, only a few attributes are retained. 293*7c478bd9Sstevel@tonic-gate * FriendlyName is stored in the aux structure, under the name 'alias'. 294*7c478bd9Sstevel@tonic-gate * LocalKeyId is also stored in the aux structure, under the name 'keyid'. 295*7c478bd9Sstevel@tonic-gate * A pkey structure has a stack of attributes. 296*7c478bd9Sstevel@tonic-gate * 297*7c478bd9Sstevel@tonic-gate * The basic approach is: 298*7c478bd9Sstevel@tonic-gate * - If there there is no stack of certs but a stack of private keys exists, 299*7c478bd9Sstevel@tonic-gate * search the stack of keys for a match. Alternately, if there is a stack 300*7c478bd9Sstevel@tonic-gate * of certs and no private keys, search the certs. 301*7c478bd9Sstevel@tonic-gate * 302*7c478bd9Sstevel@tonic-gate * - If there are both certs and keys, assume that the matching certs and 303*7c478bd9Sstevel@tonic-gate * keys are in their respective stacks, with matching entries in the same 304*7c478bd9Sstevel@tonic-gate * order. Search for the name or keyid in the stack of certs. If it is 305*7c478bd9Sstevel@tonic-gate * not found, then this function returns 0 (nothing found). 306*7c478bd9Sstevel@tonic-gate * 307*7c478bd9Sstevel@tonic-gate * - Once a cert is found, verify that the key actually matches by 308*7c478bd9Sstevel@tonic-gate * comparing the private key with the public key (in the cert). 309*7c478bd9Sstevel@tonic-gate * If they don't match, return an error. 310*7c478bd9Sstevel@tonic-gate * 311*7c478bd9Sstevel@tonic-gate * A pointer to cert and/or pkey which matches the name or keyid is stored 312*7c478bd9Sstevel@tonic-gate * in the return arguments. 313*7c478bd9Sstevel@tonic-gate * 314*7c478bd9Sstevel@tonic-gate * Returns: 315*7c478bd9Sstevel@tonic-gate * 0 - No matches were found. 316*7c478bd9Sstevel@tonic-gate * > 0 - Bits set based on FOUND_* definitions, indicating what was found. 317*7c478bd9Sstevel@tonic-gate * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT). 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate int 320*7c478bd9Sstevel@tonic-gate find_attr(int nid, ASN1_STRING *str, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, 321*7c478bd9Sstevel@tonic-gate STACK_OF(X509) *cl, X509 **cert) 322*7c478bd9Sstevel@tonic-gate { 323*7c478bd9Sstevel@tonic-gate ASN1_UTF8STRING *ustr = NULL; 324*7c478bd9Sstevel@tonic-gate ASN1_STRING *s; 325*7c478bd9Sstevel@tonic-gate ASN1_TYPE *t; 326*7c478bd9Sstevel@tonic-gate EVP_PKEY *p; 327*7c478bd9Sstevel@tonic-gate uchar_t *fname = NULL; 328*7c478bd9Sstevel@tonic-gate X509 *x; 329*7c478bd9Sstevel@tonic-gate int found = 0; 330*7c478bd9Sstevel@tonic-gate int chkcerts; 331*7c478bd9Sstevel@tonic-gate int len; 332*7c478bd9Sstevel@tonic-gate int res; 333*7c478bd9Sstevel@tonic-gate int c = -1; 334*7c478bd9Sstevel@tonic-gate int k = -1; 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate chkcerts = (cert != NULL || pkey != NULL) && cl != NULL; 337*7c478bd9Sstevel@tonic-gate if (chkcerts && nid == NID_friendlyName && 338*7c478bd9Sstevel@tonic-gate str->type == V_ASN1_BMPSTRING) { 339*7c478bd9Sstevel@tonic-gate ustr = ASN1_UTF8STRING_new(); 340*7c478bd9Sstevel@tonic-gate if (ustr == NULL) { 341*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE); 342*7c478bd9Sstevel@tonic-gate return (0); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate len = ASN1_STRING_to_UTF8(&fname, str); 345*7c478bd9Sstevel@tonic-gate if (fname == NULL) { 346*7c478bd9Sstevel@tonic-gate ASN1_UTF8STRING_free(ustr); 347*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_FINDATTR, SUNW_R_STR_CONVERT_ERR); 348*7c478bd9Sstevel@tonic-gate return (0); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (ASN1_STRING_set(ustr, fname, len) == 0) { 352*7c478bd9Sstevel@tonic-gate ASN1_UTF8STRING_free(ustr); 353*7c478bd9Sstevel@tonic-gate OPENSSL_free(fname); 354*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_FINDATTR, SUNW_R_MEMORY_FAILURE); 355*7c478bd9Sstevel@tonic-gate return (0); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate if (chkcerts) { 360*7c478bd9Sstevel@tonic-gate for (c = 0; c < sk_X509_num(cl); c++) { 361*7c478bd9Sstevel@tonic-gate res = -1; 362*7c478bd9Sstevel@tonic-gate x = sk_X509_value(cl, c); 363*7c478bd9Sstevel@tonic-gate if (nid == NID_friendlyName && ustr != NULL) { 364*7c478bd9Sstevel@tonic-gate if (x->aux == NULL || x->aux->alias == NULL) 365*7c478bd9Sstevel@tonic-gate continue; 366*7c478bd9Sstevel@tonic-gate s = x->aux->alias; 367*7c478bd9Sstevel@tonic-gate if (s != NULL && s->type == ustr->type && 368*7c478bd9Sstevel@tonic-gate s->data != NULL) { 369*7c478bd9Sstevel@tonic-gate res = ASN1_STRING_cmp(s, ustr); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate } else { 372*7c478bd9Sstevel@tonic-gate if (x->aux == NULL || x->aux->keyid == NULL) 373*7c478bd9Sstevel@tonic-gate continue; 374*7c478bd9Sstevel@tonic-gate s = x->aux->keyid; 375*7c478bd9Sstevel@tonic-gate if (s != NULL && s->type == str->type && 376*7c478bd9Sstevel@tonic-gate s->data != NULL) { 377*7c478bd9Sstevel@tonic-gate res = ASN1_STRING_cmp(s, str); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate if (res == 0) { 381*7c478bd9Sstevel@tonic-gate if (cert != NULL) 382*7c478bd9Sstevel@tonic-gate *cert = sk_X509_delete(cl, c); 383*7c478bd9Sstevel@tonic-gate found = FOUND_CERT; 384*7c478bd9Sstevel@tonic-gate break; 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate if (ustr != NULL) { 388*7c478bd9Sstevel@tonic-gate ASN1_UTF8STRING_free(ustr); 389*7c478bd9Sstevel@tonic-gate OPENSSL_free(fname); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if (pkey != NULL && kl != NULL) { 394*7c478bd9Sstevel@tonic-gate /* 395*7c478bd9Sstevel@tonic-gate * Looking for pkey to match a cert? If so, assume that 396*7c478bd9Sstevel@tonic-gate * lists of certs and their matching pkeys are in the same 397*7c478bd9Sstevel@tonic-gate * order. Call X509_check_private_key() to verify this 398*7c478bd9Sstevel@tonic-gate * assumption. 399*7c478bd9Sstevel@tonic-gate */ 400*7c478bd9Sstevel@tonic-gate if (found != 0 && cert != NULL) { 401*7c478bd9Sstevel@tonic-gate k = c; 402*7c478bd9Sstevel@tonic-gate p = sk_EVP_PKEY_value(kl, k); 403*7c478bd9Sstevel@tonic-gate if (X509_check_private_key(x, p) != 0) { 404*7c478bd9Sstevel@tonic-gate if (pkey != NULL) 405*7c478bd9Sstevel@tonic-gate *pkey = sk_EVP_PKEY_delete(kl, k); 406*7c478bd9Sstevel@tonic-gate found |= FOUND_PKEY; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate } else if (cert == NULL) { 409*7c478bd9Sstevel@tonic-gate for (k = 0; k < sk_EVP_PKEY_num(kl); k++) { 410*7c478bd9Sstevel@tonic-gate p = sk_EVP_PKEY_value(kl, k); 411*7c478bd9Sstevel@tonic-gate if (p == NULL || p->attributes == NULL) 412*7c478bd9Sstevel@tonic-gate continue; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate t = PKCS12_get_attr_gen(p->attributes, nid); 415*7c478bd9Sstevel@tonic-gate if (t != NULL || ASN1_STRING_cmp(str, 416*7c478bd9Sstevel@tonic-gate t->value.asn1_string) == 0) 417*7c478bd9Sstevel@tonic-gate continue; 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate found |= FOUND_PKEY; 420*7c478bd9Sstevel@tonic-gate if (pkey != NULL) 421*7c478bd9Sstevel@tonic-gate *pkey = sk_EVP_PKEY_delete(kl, k); 422*7c478bd9Sstevel@tonic-gate break; 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate return (found); 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate * find_attr_by_nid - Given a ASN1_TYPE, return the offset of a X509_ATTRIBUTE 432*7c478bd9Sstevel@tonic-gate * of the type specified by the given NID. 433*7c478bd9Sstevel@tonic-gate * 434*7c478bd9Sstevel@tonic-gate * Arguments: 435*7c478bd9Sstevel@tonic-gate * attrs - Stack of attributes to search 436*7c478bd9Sstevel@tonic-gate * nid - NID of the attribute being searched for 437*7c478bd9Sstevel@tonic-gate * 438*7c478bd9Sstevel@tonic-gate * Returns: 439*7c478bd9Sstevel@tonic-gate * -1 None found 440*7c478bd9Sstevel@tonic-gate * != -1 Offset of the matching attribute. 441*7c478bd9Sstevel@tonic-gate */ 442*7c478bd9Sstevel@tonic-gate int 443*7c478bd9Sstevel@tonic-gate find_attr_by_nid(STACK_OF(X509_ATTRIBUTE) *attrs, int nid) 444*7c478bd9Sstevel@tonic-gate { 445*7c478bd9Sstevel@tonic-gate X509_ATTRIBUTE *a; 446*7c478bd9Sstevel@tonic-gate int i; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (attrs == NULL) 449*7c478bd9Sstevel@tonic-gate return (-1); 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) { 452*7c478bd9Sstevel@tonic-gate a = sk_X509_ATTRIBUTE_value(attrs, i); 453*7c478bd9Sstevel@tonic-gate if (OBJ_obj2nid(a->object) == nid) 454*7c478bd9Sstevel@tonic-gate return (i); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate return (-1); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate /* 460*7c478bd9Sstevel@tonic-gate * get_key_cert - Get a cert and its matching key from the stacks of certs 461*7c478bd9Sstevel@tonic-gate * and keys. They are removed from the stacks. 462*7c478bd9Sstevel@tonic-gate * 463*7c478bd9Sstevel@tonic-gate * Arguments: 464*7c478bd9Sstevel@tonic-gate * n - Offset of the entries to return. 465*7c478bd9Sstevel@tonic-gate * kl - Points to a stack of private keys that matches the list of 466*7c478bd9Sstevel@tonic-gate * certs below. 467*7c478bd9Sstevel@tonic-gate * pkey - Points at location where the address of the matching private 468*7c478bd9Sstevel@tonic-gate * key will be stored. 469*7c478bd9Sstevel@tonic-gate * cl - Points to a stack of client certs with matching private keys. 470*7c478bd9Sstevel@tonic-gate * cert - Points to locaiton where the address of the matching client cert 471*7c478bd9Sstevel@tonic-gate * will be returned 472*7c478bd9Sstevel@tonic-gate * 473*7c478bd9Sstevel@tonic-gate * The assumption is that the stacks of keys and certs contain key/cert pairs, 474*7c478bd9Sstevel@tonic-gate * with entries in the same order and hence at the same offset. Provided 475*7c478bd9Sstevel@tonic-gate * the key and cert selected match, each will be removed from its stack and 476*7c478bd9Sstevel@tonic-gate * returned. 477*7c478bd9Sstevel@tonic-gate * 478*7c478bd9Sstevel@tonic-gate * A stack of certs can be passed in without a stack of private keys, and vise 479*7c478bd9Sstevel@tonic-gate * versa. In that case, the indicated key/cert will be returned. 480*7c478bd9Sstevel@tonic-gate * 481*7c478bd9Sstevel@tonic-gate * Returns: 482*7c478bd9Sstevel@tonic-gate * 0 - No matches were found. 483*7c478bd9Sstevel@tonic-gate * > 0 - Bits set based on FOUND_* definitions, indicating what is returned. 484*7c478bd9Sstevel@tonic-gate * This can be FOUND_PKEY, FOUND_CERT or (FOUND_PKEY | FOUND_CERT). 485*7c478bd9Sstevel@tonic-gate */ 486*7c478bd9Sstevel@tonic-gate int 487*7c478bd9Sstevel@tonic-gate get_key_cert(int n, STACK_OF(EVP_PKEY) *kl, EVP_PKEY **pkey, STACK_OF(X509) *cl, 488*7c478bd9Sstevel@tonic-gate X509 **cert) 489*7c478bd9Sstevel@tonic-gate { 490*7c478bd9Sstevel@tonic-gate int retval = 0; 491*7c478bd9Sstevel@tonic-gate int nk; 492*7c478bd9Sstevel@tonic-gate int nc; 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate nk = (kl != NULL) ? sk_EVP_PKEY_num(kl) : 0; 495*7c478bd9Sstevel@tonic-gate nc = (cl != NULL) ? sk_X509_num(cl) : 0; 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate if (pkey != NULL && *pkey == NULL) { 498*7c478bd9Sstevel@tonic-gate if (nk > 0 && n >= 0 || n < nk) { 499*7c478bd9Sstevel@tonic-gate *pkey = sk_EVP_PKEY_delete(kl, n); 500*7c478bd9Sstevel@tonic-gate if (*pkey != NULL) 501*7c478bd9Sstevel@tonic-gate retval |= FOUND_PKEY; 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate if (cert != NULL && *cert == NULL) { 506*7c478bd9Sstevel@tonic-gate if (nc > 0 && n >= 0 && n < nc) { 507*7c478bd9Sstevel@tonic-gate *cert = sk_X509_delete(cl, n); 508*7c478bd9Sstevel@tonic-gate if (*cert != NULL) 509*7c478bd9Sstevel@tonic-gate retval |= FOUND_CERT; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate return (retval); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * type2attrib - Given a ASN1_TYPE, return a X509_ATTRIBUTE of the type 518*7c478bd9Sstevel@tonic-gate * specified by the given NID. 519*7c478bd9Sstevel@tonic-gate * 520*7c478bd9Sstevel@tonic-gate * Arguments: 521*7c478bd9Sstevel@tonic-gate * ty - Type structure to be made into an attribute 522*7c478bd9Sstevel@tonic-gate * nid - NID of the attribute 523*7c478bd9Sstevel@tonic-gate * 524*7c478bd9Sstevel@tonic-gate * Returns: 525*7c478bd9Sstevel@tonic-gate * NULL An error occurred. 526*7c478bd9Sstevel@tonic-gate * != NULL An X509_ATTRIBUTE structure. 527*7c478bd9Sstevel@tonic-gate */ 528*7c478bd9Sstevel@tonic-gate X509_ATTRIBUTE * 529*7c478bd9Sstevel@tonic-gate type2attrib(ASN1_TYPE *ty, int nid) 530*7c478bd9Sstevel@tonic-gate { 531*7c478bd9Sstevel@tonic-gate X509_ATTRIBUTE *a; 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate if ((a = X509_ATTRIBUTE_new()) == NULL || 534*7c478bd9Sstevel@tonic-gate (a->value.set = sk_ASN1_TYPE_new_null()) == NULL || 535*7c478bd9Sstevel@tonic-gate sk_ASN1_TYPE_push(a->value.set, ty) == 0) { 536*7c478bd9Sstevel@tonic-gate if (a != NULL) 537*7c478bd9Sstevel@tonic-gate X509_ATTRIBUTE_free(a); 538*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_TYPE2ATTRIB, SUNW_R_MEMORY_FAILURE); 539*7c478bd9Sstevel@tonic-gate return (NULL); 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate a->single = 0; 542*7c478bd9Sstevel@tonic-gate a->object = OBJ_nid2obj(nid); 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate return (a); 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate /* 548*7c478bd9Sstevel@tonic-gate * attrib2type - Given a X509_ATTRIBUTE, return pointer to the ASN1_TYPE 549*7c478bd9Sstevel@tonic-gate * component 550*7c478bd9Sstevel@tonic-gate * 551*7c478bd9Sstevel@tonic-gate * Arguments: 552*7c478bd9Sstevel@tonic-gate * attr - Attribute structure containing a type. 553*7c478bd9Sstevel@tonic-gate * 554*7c478bd9Sstevel@tonic-gate * Returns: 555*7c478bd9Sstevel@tonic-gate * NULL An error occurred. 556*7c478bd9Sstevel@tonic-gate * != NULL An ASN1_TYPE structure. 557*7c478bd9Sstevel@tonic-gate */ 558*7c478bd9Sstevel@tonic-gate ASN1_TYPE * 559*7c478bd9Sstevel@tonic-gate attrib2type(X509_ATTRIBUTE *attr) 560*7c478bd9Sstevel@tonic-gate { 561*7c478bd9Sstevel@tonic-gate ASN1_TYPE *ty = NULL; 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate if (attr == NULL || attr->single == 1) 564*7c478bd9Sstevel@tonic-gate return (NULL); 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate if (sk_ASN1_TYPE_num(attr->value.set) > 0) 567*7c478bd9Sstevel@tonic-gate ty = sk_ASN1_TYPE_value(attr->value.set, 0); 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate return (ty); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* 573*7c478bd9Sstevel@tonic-gate * move_certs - Given two stacks of certs, remove the certs from 574*7c478bd9Sstevel@tonic-gate * the second stack and append them to the first. 575*7c478bd9Sstevel@tonic-gate * 576*7c478bd9Sstevel@tonic-gate * Arguments: 577*7c478bd9Sstevel@tonic-gate * dst - the stack to receive the certs from 'src' 578*7c478bd9Sstevel@tonic-gate * src - the stack whose certs are to be moved. 579*7c478bd9Sstevel@tonic-gate * 580*7c478bd9Sstevel@tonic-gate * Returns: 581*7c478bd9Sstevel@tonic-gate * -1 - An error occurred. The error status is set. 582*7c478bd9Sstevel@tonic-gate * >= 0 - The number of certs that were copied. 583*7c478bd9Sstevel@tonic-gate */ 584*7c478bd9Sstevel@tonic-gate int 585*7c478bd9Sstevel@tonic-gate move_certs(STACK_OF(X509) *dst, STACK_OF(X509) *src) 586*7c478bd9Sstevel@tonic-gate { 587*7c478bd9Sstevel@tonic-gate X509 *tmpc; 588*7c478bd9Sstevel@tonic-gate int count = 0; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate while (sk_X509_num(src) > 0) { 591*7c478bd9Sstevel@tonic-gate tmpc = sk_X509_delete(src, 0); 592*7c478bd9Sstevel@tonic-gate if (sk_X509_push(dst, tmpc) == 0) { 593*7c478bd9Sstevel@tonic-gate X509_free(tmpc); 594*7c478bd9Sstevel@tonic-gate SUNWerr(SUNW_F_MOVE_CERTS, SUNW_R_MEMORY_FAILURE); 595*7c478bd9Sstevel@tonic-gate return (-1); 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate count++; 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate return (count); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate /* 604*7c478bd9Sstevel@tonic-gate * print_time - Given an ASN1_TIME, print one or both of the times. 605*7c478bd9Sstevel@tonic-gate * 606*7c478bd9Sstevel@tonic-gate * Arguments: 607*7c478bd9Sstevel@tonic-gate * fp - File to write to 608*7c478bd9Sstevel@tonic-gate * t - The time to format and print. 609*7c478bd9Sstevel@tonic-gate * 610*7c478bd9Sstevel@tonic-gate * Returns: 611*7c478bd9Sstevel@tonic-gate * 0 - Error occurred while opening or writing. 612*7c478bd9Sstevel@tonic-gate * > 0 - Success. 613*7c478bd9Sstevel@tonic-gate */ 614*7c478bd9Sstevel@tonic-gate int 615*7c478bd9Sstevel@tonic-gate print_time(FILE *fp, ASN1_TIME *t) 616*7c478bd9Sstevel@tonic-gate { 617*7c478bd9Sstevel@tonic-gate BIO *bp; 618*7c478bd9Sstevel@tonic-gate int ret = 1; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate if ((bp = BIO_new(BIO_s_file())) == NULL) { 621*7c478bd9Sstevel@tonic-gate return (0); 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate (void) BIO_set_fp(bp, fp, BIO_NOCLOSE); 625*7c478bd9Sstevel@tonic-gate ret = ASN1_TIME_print(bp, t); 626*7c478bd9Sstevel@tonic-gate (void) BIO_free(bp); 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate return (ret); 629*7c478bd9Sstevel@tonic-gate } 630