8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / common / net / wanboot / p12access.c
blob53419dda420a70e177a6b9f1dabe3a97c3fa7dd6
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * This file includes interfaces to be used together with SSL to get PKCS#12
24 * certs and pass them to SSL. They replace similar functions for PEM,
25 * already provided for within SSL.
27 * The interfaces included here are:
28 * sunw_p12_use_certfile - gets the user's cert from a pkcs12 file & pass
29 * it to SSL.
30 * sunw_p12_use_keyfile - gets the RSA private key from a pkcs12 file and
31 * pass it to SSL
32 * sunw_p12_use_trustfile - read the pkcs12 trust anchor (aka certificate
33 * authority certs) file into memory and hand them off to SSL.
35 * These functions use the sunw_PKCS12_parse to read the certs.
37 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
38 * Use is subject to license terms.
41 #pragma ident "%Z%%M% %I% %E% SMI"
43 #include <stdio.h>
44 #include <strings.h>
45 #include <stdlib.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
49 #include <openssl/crypto.h>
50 #include <openssl/err.h>
51 #include <openssl/x509.h>
52 #include <openssl/ssl.h>
54 #include <openssl/pkcs12.h>
55 #include <p12access.h>
56 #include <p12err.h>
58 static PKCS12 *p12_read_file(char *);
59 static int p12_doparse(PKCS12 *, char *, int, EVP_PKEY **,
60 X509 **, STACK_OF(X509) **);
61 static int checkfile(char *);
62 static int check_password(PKCS12 *, char *);
65 * sunw_use_x509cert - pass an x509 client certificate to ssl
67 * Arguments:
68 * ctx - SSL's context structure
69 * cert - Certificate to pass in x509 format
71 * Returns:
72 * <=0 - Error occurred. Check the error stack for specifics.
73 * >0 - Success. Cert was successfully added.
75 static int
76 sunw_use_x509cert(SSL_CTX *ctx, X509 *cert)
78 ERR_clear_error();
80 if (ctx == NULL || cert == NULL) {
81 SUNWerr(SUNW_F_USE_X509CERT, SUNW_R_INVALID_ARG);
82 return (-1);
85 if (SSL_CTX_use_certificate(ctx, cert) != 1) {
86 SUNWerr(SUNW_F_USE_X509CERT, SUNW_R_CERT_ERR);
87 return (-1);
89 return (1);
93 * sunw_use_pkey - pass an EVP_PKEY private key to ssl
95 * Arguments:
96 * ctx - SSL's context structure
97 * pkey - EVP_PKEY formatted private key
99 * Returns:
100 * <=0 - Error occurred. Check the error stack for specifics.
101 * >0 - Success.
103 static int
104 sunw_use_pkey(SSL_CTX *ctx, EVP_PKEY *pkey)
106 ERR_clear_error();
107 if (ctx == NULL || pkey == NULL) {
108 SUNWerr(SUNW_F_USE_PKEY, SUNW_R_INVALID_ARG);
109 return (-1);
112 if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
113 SUNWerr(SUNW_F_USE_PKEY, SUNW_R_PKEY_ERR);
114 return (-1);
117 return (1);
121 * sunw_use_tastore - take a stack of X509 certs and add them to the
122 * SSL store of trust anchors (aka CA certs).
124 * This function takes the certs in the stack and passes them into
125 * SSL for addition to the cache of TA certs.
127 * Arguments:
128 * ctx - SSL's context structure
129 * ta_certs - Stack of certs to add to the list of SSL trust anchors.
131 * Returns:
132 * <=0 - Error occurred. Check the error stack for specifics.
133 * >0 - Success. Certs were successfully added.
135 static int
136 sunw_use_tastore(SSL_CTX *ctx, STACK_OF(X509) *ta_certs)
138 X509 *tmp;
139 int ret = -1;
140 int i;
142 ERR_clear_error();
143 if (ctx == NULL || ctx->cert_store == NULL || ta_certs == NULL) {
144 SUNWerr(SUNW_F_USE_TASTORE, SUNW_R_INVALID_ARG);
145 return (-1);
148 if (sk_X509_num(ta_certs) == 0) {
149 SUNWerr(SUNW_F_USE_TASTORE, SUNW_R_NO_TRUST_ANCHOR);
150 return (-1);
153 for (i = 0; i < sk_X509_num(ta_certs); i++) {
154 tmp = sk_X509_value(ta_certs, i);
156 ret = X509_STORE_add_cert(ctx->cert_store, tmp);
157 if (ret == 0) {
158 if (ERR_GET_REASON(ERR_peek_error()) ==
159 X509_R_CERT_ALREADY_IN_HASH_TABLE) {
160 ERR_clear_error();
161 continue;
163 SUNWerr(SUNW_F_USE_TASTORE, SUNW_R_ADD_TRUST_ERR);
164 return (-1);
165 } else if (ret < 0) {
166 break;
170 if (ret < 0) {
171 SUNWerr(SUNW_F_USE_TASTORE, SUNW_R_ADD_TRUST_ERR);
174 return (ret);
178 * sunw_p12_use_certfile - read a client certificate from a pkcs12 file and
179 * pass it in to SSL.
181 * Read in the certificate in pkcs12-formated file. Use the provided
182 * passphrase to decrypt it. Pass the cert to SSL.
184 * Arguments:
185 * ctx - SSL's context structure
186 * filename - Name of file with the client certificate.
187 * passwd - Passphrase for pkcs12 data.
189 * Returns:
190 * <=0 - Error occurred. Check the error stack for specifics.
191 * >0 - Success. Cert was successfully added.
194 sunw_p12_use_certfile(SSL_CTX *ctx, char *filename, char *passwd)
196 PKCS12 *p12 = NULL;
197 X509 *cert = NULL;
198 int ret = -1;
200 ERR_clear_error();
201 if (ctx == NULL || filename == NULL) {
202 SUNWerr(SUNW_F_USE_CERTFILE, SUNW_R_INVALID_ARG);
203 return (-1);
206 p12 = p12_read_file(filename);
207 if (p12 != NULL) {
208 ret = p12_doparse(p12, passwd, DO_UNMATCHING, NULL,
209 &cert, NULL);
210 if (ret > 0 && cert != NULL) {
211 if (sunw_use_x509cert(ctx, cert) == -1) {
213 * Error already on stack
215 ret = -1;
220 if (p12 != NULL)
221 PKCS12_free(p12);
223 if (ret == -1 && cert != NULL) {
224 X509_free(cert);
225 cert = NULL;
228 return (ret);
232 * sunw_p12_use_keyfile - read a RSA private key from a pkcs12 file and pass
233 * it in to SSL.
235 * Read in the RSA private key in pkcs12 format. Use the provided
236 * passphrase to decrypt it. Pass the cert to SSL.
238 * Arguments:
239 * ctx - SSL's context structure
240 * filename - Name of file with private key.
241 * passwd - Passphrase for pkcs12 data.
243 * Returns:
244 * <=0 - Error occurred. Check the error stack for specifics.
245 * >0 - Success. Key was successfully added.
248 sunw_p12_use_keyfile(SSL_CTX *ctx, char *filename, char *passwd)
250 EVP_PKEY *pkey = NULL;
251 PKCS12 *p12 = NULL;
252 int ret = -1;
254 ERR_clear_error();
255 if (ctx == NULL || filename == NULL) {
256 SUNWerr(SUNW_F_USE_KEYFILE, SUNW_R_INVALID_ARG);
257 return (-1);
260 p12 = p12_read_file(filename);
261 if (p12 != NULL) {
262 ret = p12_doparse(p12, passwd, DO_UNMATCHING, &pkey, NULL,
263 NULL);
264 if (ret > 0 && pkey != NULL) {
265 if (sunw_use_pkey(ctx, pkey) != 1) {
267 * Error already on stack
269 ret = -1;
271 } else {
272 SUNWerr(SUNW_F_USE_KEYFILE, SUNW_R_BAD_PKEY);
274 } else {
275 SUNWerr(SUNW_F_USE_KEYFILE, SUNW_R_PKEY_READ_ERR);
278 if (p12 != NULL)
279 PKCS12_free(p12);
281 if (ret == -1 && pkey != NULL) {
282 sunw_evp_pkey_free(pkey);
283 pkey = NULL;
286 return (ret);
290 * sunw_p12_use_trustfile - read a list of trustanchors from a pkcs12 file and
291 * pass the stack in to SSL.
293 * Read in the trust anchors from pkcs12-formated file. Use the provided
294 * passphrase to decrypt it. Pass the cert to SSL.
296 * Arguments:
297 * ctx - SSL's context structure
298 * filename - Name of file with the certificates.
299 * passwd - Passphrase for pkcs12 data.
301 * Returns:
302 * <=0 - Error occurred. Check the error stack for specifics.
303 * >0 - Success. Trust anchors were successfully added.
306 sunw_p12_use_trustfile(SSL_CTX *ctx, char *filename, char *passwd)
308 PKCS12 *p12 = NULL;
309 STACK_OF(X509) *ta_sk = NULL;
310 int ret = -1;
312 ERR_clear_error();
313 if (ctx == NULL || filename == NULL) {
314 SUNWerr(SUNW_F_USE_TRUSTFILE, SUNW_R_INVALID_ARG);
315 return (-1);
318 p12 = p12_read_file(filename);
319 if (p12 != NULL) {
320 ret = p12_doparse(p12, passwd, DO_NONE, NULL, NULL,
321 &ta_sk);
322 if (ret > 0 && ta_sk != NULL)
323 ret = sunw_use_tastore(ctx, ta_sk);
324 else {
325 SUNWerr(SUNW_F_USE_TRUSTFILE, SUNW_R_BAD_TRUST);
326 ret = -1;
328 } else {
329 SUNWerr(SUNW_F_USE_TRUSTFILE, SUNW_R_READ_TRUST_ERR);
332 if (p12 != NULL)
333 PKCS12_free(p12);
335 if (ta_sk != NULL)
336 sk_X509_pop_free(ta_sk, X509_free);
338 return (ret);
342 * p12_read_file - read a pkcs12 file and get its contents. Return the
343 * pkcs12 structures.
345 * Arguments:
346 * filename - Name of file with the client certificate.
349 * Returns:
350 * NULL - Error occurred. Check the error stack for specifics.
351 * != NULL - Success. The return value is the address of a pkcs12
352 * structure.
354 static PKCS12 *
355 p12_read_file(char *filename)
357 PKCS12 *p12 = NULL;
358 FILE *fp = NULL;
359 int ret = 0;
361 ERR_clear_error();
362 if (checkfile(filename) == -1) {
364 * Error already on stack
366 return (NULL);
369 if ((fp = fopen(filename, "r")) == 0) {
370 SYSerr(SYS_F_FOPEN, errno);
371 return (NULL);
374 p12 = d2i_PKCS12_fp(fp, NULL);
375 if (p12 == NULL) {
376 SUNWerr(SUNW_F_READ_FILE, SUNW_R_READ_ERR);
377 ret = -1;
380 if (fp != NULL)
381 (void) fclose(fp);
383 if (ret == -1 && p12 != NULL) {
384 PKCS12_free(p12);
385 p12 = NULL;
388 return (p12);
392 * p12_doparse - Given a pkcs12 structure, check the passphrase and then
393 * parse it.
395 * Arguments:
396 * p12 - Structure with pkcs12 data which has been read in
397 * passwd - Passphrase for pkcs12 data & key.
398 * matchty - How to decide which matching entry to take... See the
399 * DO_* definitions for valid values.
400 * pkey - Points at pointer to private key structure.
401 * cert - Points at pointer to client certificate structure
402 * ca - Points at pointer to list of CA certs
404 * Returns:
405 * <=0 - Error occurred. Check the error stack for specifics.
406 * >0 - Success. Bits set reflect the kind of information
407 * returned. (See the FOUND_* definitions.)
409 static int
410 p12_doparse(PKCS12 *p12, char *passwd, int matchty,
411 EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
413 int ret = 0;
415 ERR_clear_error();
418 * Check passphrase (including null one).
420 if (check_password(p12, passwd) == 0) {
421 SUNWerr(SUNW_F_DOPARSE, SUNW_R_MAC_VERIFY_FAILURE);
422 return (-1);
425 ret = sunw_PKCS12_parse(p12, passwd, matchty, NULL, 0, NULL,
426 pkey, cert, ca);
427 if (ret <= 0) {
429 * Error already on stack
431 return (-1);
434 return (ret);
438 * checkfile - given a file name, verify that the file exists and is
439 * readable.
441 /* ARGSUSED */
442 static int
443 checkfile(char *filename)
445 #ifndef _BOOT
446 struct stat sbuf;
448 if (access(filename, R_OK) == -1 || stat(filename, &sbuf) == -1) {
449 SYSerr(SYS_F_FOPEN, errno);
450 return (-1);
453 if (!S_ISREG(sbuf.st_mode)) {
454 SUNWerr(SUNW_F_CHECKFILE, SUNW_R_BAD_FILETYPE);
455 return (-1);
457 #endif
458 return (0);
462 * check_password - do various password checks to see if the current password
463 * will work or we need to prompt for a new one.
465 * Arguments:
466 * pass - password to check
468 * Returns:
469 * 1 - Password is OK.
470 * 0 - Password not valid. Error stack was set - use ERR_get_error() to
471 * to get the error.
473 static int
474 check_password(PKCS12 *p12, char *pass)
476 int ret = 1;
479 * If password is zero length or NULL then try verifying both cases
480 * to determine which password is correct. The reason for this is that
481 * under PKCS#12 password based encryption no password and a zero
482 * length password are two different things. Otherwise, calling
483 * PKCS12_verify_mac() with a length of -1 means that the length
484 * can be determined via strlen().
486 /* Check the mac */
487 if (pass == NULL || *pass == '\0') {
488 if (PKCS12_verify_mac(p12, NULL, 0) == 0 &&
489 PKCS12_verify_mac(p12, "", 0) == 0)
490 ret = 0;
491 } else if (PKCS12_verify_mac(p12, pass, -1) == 0) {
492 ret = 0;
495 return (ret);