4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
31 * Module for handling certificates and various
32 * utilities to access their data.
39 #include <sys/types.h>
49 #include <openssl/bio.h>
50 #include <openssl/pkcs12.h>
51 #include <openssl/pkcs7.h>
52 #include <openssl/x509.h>
53 #include <openssl/err.h>
54 #include <openssl/ssl.h>
57 #include "pkglibmsgs.h"
58 #include "pkglocale.h"
61 /* length of allowable passwords */
62 #define MAX_PASSLEN 128
66 * Description: Initializes structures, libraries, for security operations
68 * Returns: 0 if we couldn't initialize, non-zero otherwise
73 OpenSSL_add_all_algorithms();
74 SSL_load_error_strings();
75 ERR_load_SUNW_strings();
76 (void) SSL_library_init();
80 * get_cert_chain - Builds a chain of certificates, from a given
81 * user certificate to a trusted certificate.
84 * err - Error object to add errors to
85 * cert - User cert to start with
86 * cas - Trusted certs to use as trust anchors
87 * chain - The resulting chain of certs (in the form of an
88 * ordered set) is placed here.
91 * 0 - Success - chain is stored in 'chain'.
92 * non-zero - Failure, errors recorded in err
95 get_cert_chain(PKG_ERR
*err
, X509
*cert
, STACK_OF(X509
) *clcerts
,
96 STACK_OF(X509
) *cas
, STACK_OF(X509
) **chain
)
98 X509_STORE_CTX
*store_ctx
= NULL
;
99 X509_STORE
*ca_store
= NULL
;
100 X509
*ca_cert
= NULL
;
104 if ((ca_store
= X509_STORE_new()) == NULL
) {
105 pkgerr_add(err
, PKGERR_NOMEM
,
111 /* add all ca certs into the store */
112 for (i
= 0; i
< sk_X509_num(cas
); i
++) {
113 ca_cert
= sk_X509_value(cas
, i
);
114 if (X509_STORE_add_cert(ca_store
, ca_cert
) == 0) {
115 pkgerr_add(err
, PKGERR_NOMEM
, gettext(ERR_MEM
));
121 /* initialize context object used during the chain resolution */
123 if ((store_ctx
= X509_STORE_CTX_new()) == NULL
) {
124 pkgerr_add(err
, PKGERR_NOMEM
, gettext(ERR_MEM
));
129 (void) X509_STORE_CTX_init(store_ctx
, ca_store
, cert
, clcerts
);
130 /* attempt to verify the cert, which builds the cert chain */
131 if (X509_verify_cert(store_ctx
) <= 0) {
132 pkgerr_add(err
, PKGERR_CHAIN
,
133 gettext(ERR_CERTCHAIN
),
134 get_subject_display_name(cert
),
135 X509_verify_cert_error_string(store_ctx
->error
));
139 *chain
= X509_STORE_CTX_get1_chain(store_ctx
);
142 if (ca_store
!= NULL
)
143 (void) X509_STORE_free(ca_store
);
144 if (store_ctx
!= NULL
) {
145 (void) X509_STORE_CTX_cleanup(store_ctx
);
146 (void) X509_STORE_CTX_free(store_ctx
);
153 * Name: get_subject_name
154 * Description: Retrieves a name used for identifying a certificate's subject.
156 * Arguments: cert - The certificate to get the name from
158 * Returns : A static buffer containing the common name (CN) of the
159 * subject of the cert.
161 * if the CN is not available, returns a string with the entire
162 * X509 distinguished name.
165 *get_subject_display_name(X509
*cert
)
169 static char sname
[ATTR_MAX
];
171 xname
= X509_get_subject_name(cert
);
172 if (X509_NAME_get_text_by_NID(xname
,
173 NID_commonName
, sname
,
175 (void) strncpy(sname
,
176 X509_NAME_oneline(xname
, NULL
, 0), ATTR_MAX
);
177 sname
[ATTR_MAX
- 1] = '\0';
183 * Name: get_display_name
184 * Description: Retrieves a name used for identifying a certificate's issuer.
186 * Arguments: cert - The certificate to get the name from
188 * Returns : A static buffer containing the common name (CN)
189 * of the issuer of the cert.
191 * if the CN is not available, returns a string with the entire
192 * X509 distinguished name.
195 *get_issuer_display_name(X509
*cert
)
199 static char sname
[ATTR_MAX
];
201 xname
= X509_get_issuer_name(cert
);
202 if (X509_NAME_get_text_by_NID(xname
,
203 NID_commonName
, sname
,
205 (void) strncpy(sname
,
206 X509_NAME_oneline(xname
, NULL
, 0), ATTR_MAX
);
207 sname
[ATTR_MAX
- 1] = '\0';
214 * Name: get_serial_num
215 * Description: Retrieves the serial number of an X509 cert
217 * Arguments: cert - The certificate to get the data from
219 * Returns : A static buffer containing the serial number
222 * if the SN is not available, returns NULL
225 *get_serial_num(X509
*cert
)
227 static char sn_str
[ATTR_MAX
];
230 if ((sn
= X509_get_serialNumber(cert
)) != 0) {
233 (void) snprintf(sn_str
, ATTR_MAX
, "%ld",
234 ASN1_INTEGER_get(sn
));
241 * Name: get_fingerprint
242 * Description: Generates a fingerprint string given
243 * a digest algorithm with which to calculate
246 * Arguments: cert - The certificate to get the data from
247 * Arguments: alg - The algorithm to use to calculate the fingerprint
249 * Returns : A static buffer containing the digest
250 * NULL if cert is NULL, or digest cannot be calculated
253 *get_fingerprint(X509
*cert
, const EVP_MD
*alg
)
255 static char fp_str
[ATTR_MAX
];
256 char tmp
[ATTR_MAX
] = "";
258 unsigned char md
[EVP_MAX_MD_SIZE
];
261 if (!X509_digest(cert
, alg
, md
, &n
)) {
265 /* start with empty string */
268 for (i
= 0; i
< (int)n
; i
++) {
269 /* form a byte of the fingerprint */
270 (void) snprintf(tmp
, ATTR_MAX
, "%02X:", md
[i
]);
271 /* cat it onto the end of the result */
272 (void) strlcat(fp_str
, tmp
, ATTR_MAX
);
275 /* nuke trailing ':' */
276 fp_str
[strlen(fp_str
) - 1] = '\0';