xref: /titanic_41/usr/src/lib/libpkg/common/security.c (revision d7661440aeab0f2cc3a11393e2a4f614db544040)
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
sec_init(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
get_cert_chain(PKG_ERR * err,X509 * cert,STACK_OF (X509)* clcerts,STACK_OF (X509)* cas,STACK_OF (X509)** chain)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*d7661440SRobert 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
get_subject_display_name(X509 * cert)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*d7661440SRobert Mustacchi 		    X509_NAME_oneline(xname,
178*d7661440SRobert 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
get_issuer_display_name(X509 * cert)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*d7661440SRobert Mustacchi 		    X509_NAME_oneline(xname,
209*d7661440SRobert 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
get_serial_num(X509 * cert)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
get_fingerprint(X509 * cert,const EVP_MD * alg)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