1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland 28*5c51f124SMoriah Waterland /* 29*5c51f124SMoriah Waterland * Module: security.c 30*5c51f124SMoriah Waterland * Description: 31*5c51f124SMoriah Waterland * Module for handling certificates and various 32*5c51f124SMoriah Waterland * utilities to access their data. 33*5c51f124SMoriah Waterland */ 34*5c51f124SMoriah Waterland 35*5c51f124SMoriah Waterland #include <stdio.h> 36*5c51f124SMoriah Waterland #include <string.h> 37*5c51f124SMoriah Waterland #include <errno.h> 38*5c51f124SMoriah Waterland #include <ctype.h> 39*5c51f124SMoriah Waterland #include <sys/types.h> 40*5c51f124SMoriah Waterland #include <sys/stat.h> 41*5c51f124SMoriah Waterland #include <limits.h> 42*5c51f124SMoriah Waterland #include <pkgstrct.h> 43*5c51f124SMoriah Waterland #include <pkginfo.h> 44*5c51f124SMoriah Waterland #include <locale.h> 45*5c51f124SMoriah Waterland #include <libintl.h> 46*5c51f124SMoriah Waterland #include <unistd.h> 47*5c51f124SMoriah Waterland #include <stdlib.h> 48*5c51f124SMoriah Waterland 49*5c51f124SMoriah Waterland #include <openssl/bio.h> 50*5c51f124SMoriah Waterland #include <openssl/pkcs12.h> 51*5c51f124SMoriah Waterland #include <openssl/pkcs7.h> 52*5c51f124SMoriah Waterland #include <openssl/x509.h> 53*5c51f124SMoriah Waterland #include <openssl/err.h> 54*5c51f124SMoriah Waterland #include <openssl/ssl.h> 55*5c51f124SMoriah Waterland #include "pkgerr.h" 56*5c51f124SMoriah Waterland #include "pkglib.h" 57*5c51f124SMoriah Waterland #include "pkglibmsgs.h" 58*5c51f124SMoriah Waterland #include "pkglocale.h" 59*5c51f124SMoriah Waterland #include "p12lib.h" 60*5c51f124SMoriah Waterland 61*5c51f124SMoriah Waterland /* length of allowable passwords */ 62*5c51f124SMoriah Waterland #define MAX_PASSLEN 128 63*5c51f124SMoriah Waterland 64*5c51f124SMoriah Waterland /* 65*5c51f124SMoriah Waterland * Name: init_security 66*5c51f124SMoriah Waterland * Description: Initializes structures, libraries, for security operations 67*5c51f124SMoriah Waterland * Arguments: none 68*5c51f124SMoriah Waterland * Returns: 0 if we couldn't initialize, non-zero otherwise 69*5c51f124SMoriah Waterland */ 70*5c51f124SMoriah Waterland void 71*5c51f124SMoriah Waterland sec_init(void) 72*5c51f124SMoriah Waterland { 73*5c51f124SMoriah Waterland OpenSSL_add_all_algorithms(); 74*5c51f124SMoriah Waterland SSL_load_error_strings(); 75*5c51f124SMoriah Waterland ERR_load_SUNW_strings(); 76*5c51f124SMoriah Waterland (void) SSL_library_init(); 77*5c51f124SMoriah Waterland } 78*5c51f124SMoriah Waterland 79*5c51f124SMoriah Waterland /* 80*5c51f124SMoriah Waterland * get_cert_chain - Builds a chain of certificates, from a given 81*5c51f124SMoriah Waterland * user certificate to a trusted certificate. 82*5c51f124SMoriah Waterland * 83*5c51f124SMoriah Waterland * Arguments: 84*5c51f124SMoriah Waterland * err - Error object to add errors to 85*5c51f124SMoriah Waterland * cert - User cert to start with 86*5c51f124SMoriah Waterland * cas - Trusted certs to use as trust anchors 87*5c51f124SMoriah Waterland * chain - The resulting chain of certs (in the form of an 88*5c51f124SMoriah Waterland * ordered set) is placed here. 89*5c51f124SMoriah Waterland * 90*5c51f124SMoriah Waterland * Returns: 91*5c51f124SMoriah Waterland * 0 - Success - chain is stored in 'chain'. 92*5c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err 93*5c51f124SMoriah Waterland */ 94*5c51f124SMoriah Waterland int 95*5c51f124SMoriah Waterland get_cert_chain(PKG_ERR *err, X509 *cert, STACK_OF(X509) *clcerts, 96*5c51f124SMoriah Waterland STACK_OF(X509) *cas, STACK_OF(X509) **chain) 97*5c51f124SMoriah Waterland { 98*5c51f124SMoriah Waterland X509_STORE_CTX *store_ctx = NULL; 99*5c51f124SMoriah Waterland X509_STORE *ca_store = NULL; 100*5c51f124SMoriah Waterland X509 *ca_cert = NULL; 101*5c51f124SMoriah Waterland int i; 102*5c51f124SMoriah Waterland int ret = 0; 103*5c51f124SMoriah Waterland 104*5c51f124SMoriah Waterland if ((ca_store = X509_STORE_new()) == NULL) { 105*5c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, 106*5c51f124SMoriah Waterland gettext(ERR_MEM)); 107*5c51f124SMoriah Waterland ret = 1; 108*5c51f124SMoriah Waterland goto cleanup; 109*5c51f124SMoriah Waterland } 110*5c51f124SMoriah Waterland 111*5c51f124SMoriah Waterland /* add all ca certs into the store */ 112*5c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(cas); i++) { 113*5c51f124SMoriah Waterland /* LINTED pointer cast may result in improper alignment */ 114*5c51f124SMoriah Waterland ca_cert = sk_X509_value(cas, i); 115*5c51f124SMoriah Waterland if (X509_STORE_add_cert(ca_store, ca_cert) == 0) { 116*5c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 117*5c51f124SMoriah Waterland ret = 1; 118*5c51f124SMoriah Waterland goto cleanup; 119*5c51f124SMoriah Waterland } 120*5c51f124SMoriah Waterland } 121*5c51f124SMoriah Waterland 122*5c51f124SMoriah Waterland /* initialize context object used during the chain resolution */ 123*5c51f124SMoriah Waterland 124*5c51f124SMoriah Waterland if ((store_ctx = X509_STORE_CTX_new()) == NULL) { 125*5c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 126*5c51f124SMoriah Waterland ret = 1; 127*5c51f124SMoriah Waterland goto cleanup; 128*5c51f124SMoriah Waterland } 129*5c51f124SMoriah Waterland 130*5c51f124SMoriah Waterland (void) X509_STORE_CTX_init(store_ctx, ca_store, cert, clcerts); 131*5c51f124SMoriah Waterland /* attempt to verify the cert, which builds the cert chain */ 132*5c51f124SMoriah Waterland if (X509_verify_cert(store_ctx) <= 0) { 133*5c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CHAIN, 134*5c51f124SMoriah Waterland gettext(ERR_CERTCHAIN), 135*5c51f124SMoriah Waterland get_subject_display_name(cert), 136*5c51f124SMoriah Waterland X509_verify_cert_error_string(store_ctx->error)); 137*5c51f124SMoriah Waterland ret = 1; 138*5c51f124SMoriah Waterland goto cleanup; 139*5c51f124SMoriah Waterland } 140*5c51f124SMoriah Waterland *chain = X509_STORE_CTX_get1_chain(store_ctx); 141*5c51f124SMoriah Waterland 142*5c51f124SMoriah Waterland cleanup: 143*5c51f124SMoriah Waterland if (ca_store != NULL) 144*5c51f124SMoriah Waterland (void) X509_STORE_free(ca_store); 145*5c51f124SMoriah Waterland if (store_ctx != NULL) { 146*5c51f124SMoriah Waterland (void) X509_STORE_CTX_cleanup(store_ctx); 147*5c51f124SMoriah Waterland (void) X509_STORE_CTX_free(store_ctx); 148*5c51f124SMoriah Waterland } 149*5c51f124SMoriah Waterland 150*5c51f124SMoriah Waterland return (ret); 151*5c51f124SMoriah Waterland } 152*5c51f124SMoriah Waterland 153*5c51f124SMoriah Waterland /* 154*5c51f124SMoriah Waterland * Name: get_subject_name 155*5c51f124SMoriah Waterland * Description: Retrieves a name used for identifying a certificate's subject. 156*5c51f124SMoriah Waterland * 157*5c51f124SMoriah Waterland * Arguments: cert - The certificate to get the name from 158*5c51f124SMoriah Waterland * 159*5c51f124SMoriah Waterland * Returns : A static buffer containing the common name (CN) of the 160*5c51f124SMoriah Waterland * subject of the cert. 161*5c51f124SMoriah Waterland * 162*5c51f124SMoriah Waterland * if the CN is not available, returns a string with the entire 163*5c51f124SMoriah Waterland * X509 distinguished name. 164*5c51f124SMoriah Waterland */ 165*5c51f124SMoriah Waterland char 166*5c51f124SMoriah Waterland *get_subject_display_name(X509 *cert) 167*5c51f124SMoriah Waterland { 168*5c51f124SMoriah Waterland 169*5c51f124SMoriah Waterland X509_NAME *xname; 170*5c51f124SMoriah Waterland static char sname[ATTR_MAX]; 171*5c51f124SMoriah Waterland 172*5c51f124SMoriah Waterland xname = X509_get_subject_name(cert); 173*5c51f124SMoriah Waterland if (X509_NAME_get_text_by_NID(xname, 174*5c51f124SMoriah Waterland NID_commonName, sname, 175*5c51f124SMoriah Waterland ATTR_MAX) <= 0) { 176*5c51f124SMoriah Waterland (void) strncpy(sname, 177*5c51f124SMoriah Waterland X509_NAME_oneline(xname, 178*5c51f124SMoriah Waterland NULL, 0), ATTR_MAX); 179*5c51f124SMoriah Waterland sname[ATTR_MAX - 1] = '\0'; 180*5c51f124SMoriah Waterland } 181*5c51f124SMoriah Waterland return (sname); 182*5c51f124SMoriah Waterland } 183*5c51f124SMoriah Waterland 184*5c51f124SMoriah Waterland /* 185*5c51f124SMoriah Waterland * Name: get_display_name 186*5c51f124SMoriah Waterland * Description: Retrieves a name used for identifying a certificate's issuer. 187*5c51f124SMoriah Waterland * 188*5c51f124SMoriah Waterland * Arguments: cert - The certificate to get the name from 189*5c51f124SMoriah Waterland * 190*5c51f124SMoriah Waterland * Returns : A static buffer containing the common name (CN) 191*5c51f124SMoriah Waterland * of the issuer of the cert. 192*5c51f124SMoriah Waterland * 193*5c51f124SMoriah Waterland * if the CN is not available, returns a string with the entire 194*5c51f124SMoriah Waterland * X509 distinguished name. 195*5c51f124SMoriah Waterland */ 196*5c51f124SMoriah Waterland char 197*5c51f124SMoriah Waterland *get_issuer_display_name(X509 *cert) 198*5c51f124SMoriah Waterland { 199*5c51f124SMoriah Waterland 200*5c51f124SMoriah Waterland X509_NAME *xname; 201*5c51f124SMoriah Waterland static char sname[ATTR_MAX]; 202*5c51f124SMoriah Waterland 203*5c51f124SMoriah Waterland xname = X509_get_issuer_name(cert); 204*5c51f124SMoriah Waterland if (X509_NAME_get_text_by_NID(xname, 205*5c51f124SMoriah Waterland NID_commonName, sname, 206*5c51f124SMoriah Waterland ATTR_MAX) <= 0) { 207*5c51f124SMoriah Waterland (void) strncpy(sname, 208*5c51f124SMoriah Waterland X509_NAME_oneline(xname, 209*5c51f124SMoriah Waterland NULL, 0), ATTR_MAX); 210*5c51f124SMoriah Waterland sname[ATTR_MAX - 1] = '\0'; 211*5c51f124SMoriah Waterland } 212*5c51f124SMoriah Waterland return (sname); 213*5c51f124SMoriah Waterland } 214*5c51f124SMoriah Waterland 215*5c51f124SMoriah Waterland 216*5c51f124SMoriah Waterland /* 217*5c51f124SMoriah Waterland * Name: get_serial_num 218*5c51f124SMoriah Waterland * Description: Retrieves the serial number of an X509 cert 219*5c51f124SMoriah Waterland * 220*5c51f124SMoriah Waterland * Arguments: cert - The certificate to get the data from 221*5c51f124SMoriah Waterland * 222*5c51f124SMoriah Waterland * Returns : A static buffer containing the serial number 223*5c51f124SMoriah Waterland * of the cert 224*5c51f124SMoriah Waterland * 225*5c51f124SMoriah Waterland * if the SN is not available, returns NULL 226*5c51f124SMoriah Waterland */ 227*5c51f124SMoriah Waterland char 228*5c51f124SMoriah Waterland *get_serial_num(X509 *cert) 229*5c51f124SMoriah Waterland { 230*5c51f124SMoriah Waterland static char sn_str[ATTR_MAX]; 231*5c51f124SMoriah Waterland ASN1_INTEGER *sn; 232*5c51f124SMoriah Waterland 233*5c51f124SMoriah Waterland if ((sn = X509_get_serialNumber(cert)) != 0) { 234*5c51f124SMoriah Waterland return (NULL); 235*5c51f124SMoriah Waterland } else { 236*5c51f124SMoriah Waterland (void) snprintf(sn_str, ATTR_MAX, "%ld", 237*5c51f124SMoriah Waterland ASN1_INTEGER_get(sn)); 238*5c51f124SMoriah Waterland } 239*5c51f124SMoriah Waterland 240*5c51f124SMoriah Waterland return (sn_str); 241*5c51f124SMoriah Waterland } 242*5c51f124SMoriah Waterland 243*5c51f124SMoriah Waterland /* 244*5c51f124SMoriah Waterland * Name: get_fingerprint 245*5c51f124SMoriah Waterland * Description: Generates a fingerprint string given 246*5c51f124SMoriah Waterland * a digest algorithm with which to calculate 247*5c51f124SMoriah Waterland * the fingerprint 248*5c51f124SMoriah Waterland * 249*5c51f124SMoriah Waterland * Arguments: cert - The certificate to get the data from 250*5c51f124SMoriah Waterland * Arguments: alg - The algorithm to use to calculate the fingerprint 251*5c51f124SMoriah Waterland * 252*5c51f124SMoriah Waterland * Returns : A static buffer containing the digest 253*5c51f124SMoriah Waterland * NULL if cert is NULL, or digest cannot be calculated 254*5c51f124SMoriah Waterland */ 255*5c51f124SMoriah Waterland char 256*5c51f124SMoriah Waterland *get_fingerprint(X509 *cert, const EVP_MD *alg) 257*5c51f124SMoriah Waterland { 258*5c51f124SMoriah Waterland static char fp_str[ATTR_MAX]; 259*5c51f124SMoriah Waterland char tmp[ATTR_MAX] = ""; 260*5c51f124SMoriah Waterland unsigned int n; 261*5c51f124SMoriah Waterland unsigned char md[EVP_MAX_MD_SIZE]; 262*5c51f124SMoriah Waterland int i; 263*5c51f124SMoriah Waterland 264*5c51f124SMoriah Waterland if (!X509_digest(cert, alg, md, &n)) { 265*5c51f124SMoriah Waterland return (NULL); 266*5c51f124SMoriah Waterland } 267*5c51f124SMoriah Waterland 268*5c51f124SMoriah Waterland /* start with empty string */ 269*5c51f124SMoriah Waterland fp_str[0] = '\0'; 270*5c51f124SMoriah Waterland 271*5c51f124SMoriah Waterland for (i = 0; i < (int)n; i++) { 272*5c51f124SMoriah Waterland /* form a byte of the fingerprint */ 273*5c51f124SMoriah Waterland (void) snprintf(tmp, ATTR_MAX, "%02X:", md[i]); 274*5c51f124SMoriah Waterland /* cat it onto the end of the result */ 275*5c51f124SMoriah Waterland (void) strlcat(fp_str, tmp, ATTR_MAX); 276*5c51f124SMoriah Waterland } 277*5c51f124SMoriah Waterland 278*5c51f124SMoriah Waterland /* nuke trailing ':' */ 279*5c51f124SMoriah Waterland fp_str[strlen(fp_str) - 1] = '\0'; 280*5c51f124SMoriah Waterland 281*5c51f124SMoriah Waterland return (fp_str); 282*5c51f124SMoriah Waterland } 283