xref: /titanic_54/usr/src/lib/libpkg/common/security.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
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