15c51f124SMoriah Waterland /* 25c51f124SMoriah Waterland * CDDL HEADER START 35c51f124SMoriah Waterland * 45c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 55c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 65c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 75c51f124SMoriah Waterland * 85c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 105c51f124SMoriah Waterland * See the License for the specific language governing permissions 115c51f124SMoriah Waterland * and limitations under the License. 125c51f124SMoriah Waterland * 135c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 145c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 165c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 175c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 185c51f124SMoriah Waterland * 195c51f124SMoriah Waterland * CDDL HEADER END 205c51f124SMoriah Waterland */ 215c51f124SMoriah Waterland 225c51f124SMoriah Waterland /* 235c51f124SMoriah Waterland * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 245c51f124SMoriah Waterland * Use is subject to license terms. 255c51f124SMoriah Waterland */ 265c51f124SMoriah Waterland 275c51f124SMoriah Waterland 285c51f124SMoriah Waterland /* 295c51f124SMoriah Waterland * Module: security.c 305c51f124SMoriah Waterland * Description: 315c51f124SMoriah Waterland * Module for handling certificates and various 325c51f124SMoriah Waterland * utilities to access their data. 335c51f124SMoriah Waterland */ 345c51f124SMoriah Waterland 355c51f124SMoriah Waterland #include <stdio.h> 365c51f124SMoriah Waterland #include <string.h> 375c51f124SMoriah Waterland #include <errno.h> 385c51f124SMoriah Waterland #include <ctype.h> 395c51f124SMoriah Waterland #include <sys/types.h> 405c51f124SMoriah Waterland #include <sys/stat.h> 415c51f124SMoriah Waterland #include <limits.h> 425c51f124SMoriah Waterland #include <pkgstrct.h> 435c51f124SMoriah Waterland #include <pkginfo.h> 445c51f124SMoriah Waterland #include <locale.h> 455c51f124SMoriah Waterland #include <libintl.h> 465c51f124SMoriah Waterland #include <unistd.h> 475c51f124SMoriah Waterland #include <stdlib.h> 485c51f124SMoriah Waterland 495c51f124SMoriah Waterland #include <openssl/bio.h> 505c51f124SMoriah Waterland #include <openssl/pkcs12.h> 515c51f124SMoriah Waterland #include <openssl/pkcs7.h> 525c51f124SMoriah Waterland #include <openssl/x509.h> 535c51f124SMoriah Waterland #include <openssl/err.h> 545c51f124SMoriah Waterland #include <openssl/ssl.h> 555c51f124SMoriah Waterland #include "pkgerr.h" 565c51f124SMoriah Waterland #include "pkglib.h" 575c51f124SMoriah Waterland #include "pkglibmsgs.h" 585c51f124SMoriah Waterland #include "pkglocale.h" 595c51f124SMoriah Waterland #include "p12lib.h" 605c51f124SMoriah Waterland 615c51f124SMoriah Waterland /* length of allowable passwords */ 625c51f124SMoriah Waterland #define MAX_PASSLEN 128 635c51f124SMoriah Waterland 645c51f124SMoriah Waterland /* 655c51f124SMoriah Waterland * Name: init_security 665c51f124SMoriah Waterland * Description: Initializes structures, libraries, for security operations 675c51f124SMoriah Waterland * Arguments: none 685c51f124SMoriah Waterland * Returns: 0 if we couldn't initialize, non-zero otherwise 695c51f124SMoriah Waterland */ 705c51f124SMoriah Waterland void 715c51f124SMoriah Waterland sec_init(void) 725c51f124SMoriah Waterland { 735c51f124SMoriah Waterland OpenSSL_add_all_algorithms(); 745c51f124SMoriah Waterland SSL_load_error_strings(); 755c51f124SMoriah Waterland ERR_load_SUNW_strings(); 765c51f124SMoriah Waterland (void) SSL_library_init(); 775c51f124SMoriah Waterland } 785c51f124SMoriah Waterland 795c51f124SMoriah Waterland /* 805c51f124SMoriah Waterland * get_cert_chain - Builds a chain of certificates, from a given 815c51f124SMoriah Waterland * user certificate to a trusted certificate. 825c51f124SMoriah Waterland * 835c51f124SMoriah Waterland * Arguments: 845c51f124SMoriah Waterland * err - Error object to add errors to 855c51f124SMoriah Waterland * cert - User cert to start with 865c51f124SMoriah Waterland * cas - Trusted certs to use as trust anchors 875c51f124SMoriah Waterland * chain - The resulting chain of certs (in the form of an 885c51f124SMoriah Waterland * ordered set) is placed here. 895c51f124SMoriah Waterland * 905c51f124SMoriah Waterland * Returns: 915c51f124SMoriah Waterland * 0 - Success - chain is stored in 'chain'. 925c51f124SMoriah Waterland * non-zero - Failure, errors recorded in err 935c51f124SMoriah Waterland */ 945c51f124SMoriah Waterland int 955c51f124SMoriah Waterland get_cert_chain(PKG_ERR *err, X509 *cert, STACK_OF(X509) *clcerts, 965c51f124SMoriah Waterland STACK_OF(X509) *cas, STACK_OF(X509) **chain) 975c51f124SMoriah Waterland { 985c51f124SMoriah Waterland X509_STORE_CTX *store_ctx = NULL; 995c51f124SMoriah Waterland X509_STORE *ca_store = NULL; 1005c51f124SMoriah Waterland X509 *ca_cert = NULL; 1015c51f124SMoriah Waterland int i; 1025c51f124SMoriah Waterland int ret = 0; 1035c51f124SMoriah Waterland 1045c51f124SMoriah Waterland if ((ca_store = X509_STORE_new()) == NULL) { 1055c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, 1065c51f124SMoriah Waterland gettext(ERR_MEM)); 1075c51f124SMoriah Waterland ret = 1; 1085c51f124SMoriah Waterland goto cleanup; 1095c51f124SMoriah Waterland } 1105c51f124SMoriah Waterland 1115c51f124SMoriah Waterland /* add all ca certs into the store */ 1125c51f124SMoriah Waterland for (i = 0; i < sk_X509_num(cas); i++) { 113*d7141854SRobert Mustacchi /* LINTED pointer cast may result in improper alignment */ 1145c51f124SMoriah Waterland ca_cert = sk_X509_value(cas, i); 1155c51f124SMoriah Waterland if (X509_STORE_add_cert(ca_store, ca_cert) == 0) { 1165c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 1175c51f124SMoriah Waterland ret = 1; 1185c51f124SMoriah Waterland goto cleanup; 1195c51f124SMoriah Waterland } 1205c51f124SMoriah Waterland } 1215c51f124SMoriah Waterland 1225c51f124SMoriah Waterland /* initialize context object used during the chain resolution */ 1235c51f124SMoriah Waterland 1245c51f124SMoriah Waterland if ((store_ctx = X509_STORE_CTX_new()) == NULL) { 1255c51f124SMoriah Waterland pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 1265c51f124SMoriah Waterland ret = 1; 1275c51f124SMoriah Waterland goto cleanup; 1285c51f124SMoriah Waterland } 1295c51f124SMoriah Waterland 1305c51f124SMoriah Waterland (void) X509_STORE_CTX_init(store_ctx, ca_store, cert, clcerts); 1315c51f124SMoriah Waterland /* attempt to verify the cert, which builds the cert chain */ 1325c51f124SMoriah Waterland if (X509_verify_cert(store_ctx) <= 0) { 1335c51f124SMoriah Waterland pkgerr_add(err, PKGERR_CHAIN, 1345c51f124SMoriah Waterland gettext(ERR_CERTCHAIN), 1355c51f124SMoriah Waterland get_subject_display_name(cert), 1365c51f124SMoriah Waterland X509_verify_cert_error_string(store_ctx->error)); 1375c51f124SMoriah Waterland ret = 1; 1385c51f124SMoriah Waterland goto cleanup; 1395c51f124SMoriah Waterland } 1405c51f124SMoriah Waterland *chain = X509_STORE_CTX_get1_chain(store_ctx); 1415c51f124SMoriah Waterland 1425c51f124SMoriah Waterland cleanup: 1435c51f124SMoriah Waterland if (ca_store != NULL) 1445c51f124SMoriah Waterland (void) X509_STORE_free(ca_store); 1455c51f124SMoriah Waterland if (store_ctx != NULL) { 1465c51f124SMoriah Waterland (void) X509_STORE_CTX_cleanup(store_ctx); 1475c51f124SMoriah Waterland (void) X509_STORE_CTX_free(store_ctx); 1485c51f124SMoriah Waterland } 1495c51f124SMoriah Waterland 1505c51f124SMoriah Waterland return (ret); 1515c51f124SMoriah Waterland } 1525c51f124SMoriah Waterland 1535c51f124SMoriah Waterland /* 1545c51f124SMoriah Waterland * Name: get_subject_name 1555c51f124SMoriah Waterland * Description: Retrieves a name used for identifying a certificate's subject. 1565c51f124SMoriah Waterland * 1575c51f124SMoriah Waterland * Arguments: cert - The certificate to get the name from 1585c51f124SMoriah Waterland * 1595c51f124SMoriah Waterland * Returns : A static buffer containing the common name (CN) of the 1605c51f124SMoriah Waterland * subject of the cert. 1615c51f124SMoriah Waterland * 1625c51f124SMoriah Waterland * if the CN is not available, returns a string with the entire 1635c51f124SMoriah Waterland * X509 distinguished name. 1645c51f124SMoriah Waterland */ 1655c51f124SMoriah Waterland char 1665c51f124SMoriah Waterland *get_subject_display_name(X509 *cert) 1675c51f124SMoriah Waterland { 1685c51f124SMoriah Waterland 1695c51f124SMoriah Waterland X509_NAME *xname; 1705c51f124SMoriah Waterland static char sname[ATTR_MAX]; 1715c51f124SMoriah Waterland 1725c51f124SMoriah Waterland xname = X509_get_subject_name(cert); 1735c51f124SMoriah Waterland if (X509_NAME_get_text_by_NID(xname, 1745c51f124SMoriah Waterland NID_commonName, sname, 1755c51f124SMoriah Waterland ATTR_MAX) <= 0) { 1765c51f124SMoriah Waterland (void) strncpy(sname, 177*d7141854SRobert Mustacchi X509_NAME_oneline(xname, 178*d7141854SRobert Mustacchi NULL, 0), ATTR_MAX); 1795c51f124SMoriah Waterland sname[ATTR_MAX - 1] = '\0'; 1805c51f124SMoriah Waterland } 1815c51f124SMoriah Waterland return (sname); 1825c51f124SMoriah Waterland } 1835c51f124SMoriah Waterland 1845c51f124SMoriah Waterland /* 1855c51f124SMoriah Waterland * Name: get_display_name 1865c51f124SMoriah Waterland * Description: Retrieves a name used for identifying a certificate's issuer. 1875c51f124SMoriah Waterland * 1885c51f124SMoriah Waterland * Arguments: cert - The certificate to get the name from 1895c51f124SMoriah Waterland * 1905c51f124SMoriah Waterland * Returns : A static buffer containing the common name (CN) 1915c51f124SMoriah Waterland * of the issuer of the cert. 1925c51f124SMoriah Waterland * 1935c51f124SMoriah Waterland * if the CN is not available, returns a string with the entire 1945c51f124SMoriah Waterland * X509 distinguished name. 1955c51f124SMoriah Waterland */ 1965c51f124SMoriah Waterland char 1975c51f124SMoriah Waterland *get_issuer_display_name(X509 *cert) 1985c51f124SMoriah Waterland { 1995c51f124SMoriah Waterland 2005c51f124SMoriah Waterland X509_NAME *xname; 2015c51f124SMoriah Waterland static char sname[ATTR_MAX]; 2025c51f124SMoriah Waterland 2035c51f124SMoriah Waterland xname = X509_get_issuer_name(cert); 2045c51f124SMoriah Waterland if (X509_NAME_get_text_by_NID(xname, 2055c51f124SMoriah Waterland NID_commonName, sname, 2065c51f124SMoriah Waterland ATTR_MAX) <= 0) { 2075c51f124SMoriah Waterland (void) strncpy(sname, 208*d7141854SRobert Mustacchi X509_NAME_oneline(xname, 209*d7141854SRobert Mustacchi NULL, 0), ATTR_MAX); 2105c51f124SMoriah Waterland sname[ATTR_MAX - 1] = '\0'; 2115c51f124SMoriah Waterland } 2125c51f124SMoriah Waterland return (sname); 2135c51f124SMoriah Waterland } 2145c51f124SMoriah Waterland 2155c51f124SMoriah Waterland 2165c51f124SMoriah Waterland /* 2175c51f124SMoriah Waterland * Name: get_serial_num 2185c51f124SMoriah Waterland * Description: Retrieves the serial number of an X509 cert 2195c51f124SMoriah Waterland * 2205c51f124SMoriah Waterland * Arguments: cert - The certificate to get the data from 2215c51f124SMoriah Waterland * 2225c51f124SMoriah Waterland * Returns : A static buffer containing the serial number 2235c51f124SMoriah Waterland * of the cert 2245c51f124SMoriah Waterland * 2255c51f124SMoriah Waterland * if the SN is not available, returns NULL 2265c51f124SMoriah Waterland */ 2275c51f124SMoriah Waterland char 2285c51f124SMoriah Waterland *get_serial_num(X509 *cert) 2295c51f124SMoriah Waterland { 2305c51f124SMoriah Waterland static char sn_str[ATTR_MAX]; 2315c51f124SMoriah Waterland ASN1_INTEGER *sn; 2325c51f124SMoriah Waterland 2335c51f124SMoriah Waterland if ((sn = X509_get_serialNumber(cert)) != 0) { 2345c51f124SMoriah Waterland return (NULL); 2355c51f124SMoriah Waterland } else { 2365c51f124SMoriah Waterland (void) snprintf(sn_str, ATTR_MAX, "%ld", 2375c51f124SMoriah Waterland ASN1_INTEGER_get(sn)); 2385c51f124SMoriah Waterland } 2395c51f124SMoriah Waterland 2405c51f124SMoriah Waterland return (sn_str); 2415c51f124SMoriah Waterland } 2425c51f124SMoriah Waterland 2435c51f124SMoriah Waterland /* 2445c51f124SMoriah Waterland * Name: get_fingerprint 2455c51f124SMoriah Waterland * Description: Generates a fingerprint string given 2465c51f124SMoriah Waterland * a digest algorithm with which to calculate 2475c51f124SMoriah Waterland * the fingerprint 2485c51f124SMoriah Waterland * 2495c51f124SMoriah Waterland * Arguments: cert - The certificate to get the data from 2505c51f124SMoriah Waterland * Arguments: alg - The algorithm to use to calculate the fingerprint 2515c51f124SMoriah Waterland * 2525c51f124SMoriah Waterland * Returns : A static buffer containing the digest 2535c51f124SMoriah Waterland * NULL if cert is NULL, or digest cannot be calculated 2545c51f124SMoriah Waterland */ 2555c51f124SMoriah Waterland char 2565c51f124SMoriah Waterland *get_fingerprint(X509 *cert, const EVP_MD *alg) 2575c51f124SMoriah Waterland { 2585c51f124SMoriah Waterland static char fp_str[ATTR_MAX]; 2595c51f124SMoriah Waterland char tmp[ATTR_MAX] = ""; 2605c51f124SMoriah Waterland unsigned int n; 2615c51f124SMoriah Waterland unsigned char md[EVP_MAX_MD_SIZE]; 2625c51f124SMoriah Waterland int i; 2635c51f124SMoriah Waterland 2645c51f124SMoriah Waterland if (!X509_digest(cert, alg, md, &n)) { 2655c51f124SMoriah Waterland return (NULL); 2665c51f124SMoriah Waterland } 2675c51f124SMoriah Waterland 2685c51f124SMoriah Waterland /* start with empty string */ 2695c51f124SMoriah Waterland fp_str[0] = '\0'; 2705c51f124SMoriah Waterland 2715c51f124SMoriah Waterland for (i = 0; i < (int)n; i++) { 2725c51f124SMoriah Waterland /* form a byte of the fingerprint */ 2735c51f124SMoriah Waterland (void) snprintf(tmp, ATTR_MAX, "%02X:", md[i]); 2745c51f124SMoriah Waterland /* cat it onto the end of the result */ 2755c51f124SMoriah Waterland (void) strlcat(fp_str, tmp, ATTR_MAX); 2765c51f124SMoriah Waterland } 2775c51f124SMoriah Waterland 2785c51f124SMoriah Waterland /* nuke trailing ':' */ 2795c51f124SMoriah Waterland fp_str[strlen(fp_str) - 1] = '\0'; 2805c51f124SMoriah Waterland 2815c51f124SMoriah Waterland return (fp_str); 2825c51f124SMoriah Waterland } 283