1 /*
2 * CDDL HEADER START
3 *
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.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
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.
26 *
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.
34 *
35 * These functions use the sunw_PKCS12_parse to read the certs.
36 *
37 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
38 * Use is subject to license terms.
39 */
40
41 #pragma ident "%Z%%M% %I% %E% SMI"
42
43 #include <stdio.h>
44 #include <strings.h>
45 #include <stdlib.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
48
49 #include <openssl/crypto.h>
50 #include <openssl/err.h>
51 #include <openssl/x509.h>
52 #include <openssl/ssl.h>
53
54 #include <openssl/pkcs12.h>
55 #include <p12access.h>
56 #include <p12err.h>
57
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 *);
63
64 /*
65 * sunw_use_x509cert - pass an x509 client certificate to ssl
66 *
67 * Arguments:
68 * ctx - SSL's context structure
69 * cert - Certificate to pass in x509 format
70 *
71 * Returns:
72 * <=0 - Error occurred. Check the error stack for specifics.
73 * >0 - Success. Cert was successfully added.
74 */
75 static int
sunw_use_x509cert(SSL_CTX * ctx,X509 * cert)76 sunw_use_x509cert(SSL_CTX *ctx, X509 *cert)
77 {
78 ERR_clear_error();
79
80 if (ctx == NULL || cert == NULL) {
81 SUNWerr(SUNW_F_USE_X509CERT, SUNW_R_INVALID_ARG);
82 return (-1);
83 }
84
85 if (SSL_CTX_use_certificate(ctx, cert) != 1) {
86 SUNWerr(SUNW_F_USE_X509CERT, SUNW_R_CERT_ERR);
87 return (-1);
88 }
89 return (1);
90 }
91
92 /*
93 * sunw_use_pkey - pass an EVP_PKEY private key to ssl
94 *
95 * Arguments:
96 * ctx - SSL's context structure
97 * pkey - EVP_PKEY formatted private key
98 *
99 * Returns:
100 * <=0 - Error occurred. Check the error stack for specifics.
101 * >0 - Success.
102 */
103 static int
sunw_use_pkey(SSL_CTX * ctx,EVP_PKEY * pkey)104 sunw_use_pkey(SSL_CTX *ctx, EVP_PKEY *pkey)
105 {
106 ERR_clear_error();
107 if (ctx == NULL || pkey == NULL) {
108 SUNWerr(SUNW_F_USE_PKEY, SUNW_R_INVALID_ARG);
109 return (-1);
110 }
111
112 if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
113 SUNWerr(SUNW_F_USE_PKEY, SUNW_R_PKEY_ERR);
114 return (-1);
115 }
116
117 return (1);
118 }
119
120 /*
121 * sunw_use_tastore - take a stack of X509 certs and add them to the
122 * SSL store of trust anchors (aka CA certs).
123 *
124 * This function takes the certs in the stack and passes them into
125 * SSL for addition to the cache of TA certs.
126 *
127 * Arguments:
128 * ctx - SSL's context structure
129 * ta_certs - Stack of certs to add to the list of SSL trust anchors.
130 *
131 * Returns:
132 * <=0 - Error occurred. Check the error stack for specifics.
133 * >0 - Success. Certs were successfully added.
134 */
135 static int
sunw_use_tastore(SSL_CTX * ctx,STACK_OF (X509)* ta_certs)136 sunw_use_tastore(SSL_CTX *ctx, STACK_OF(X509) *ta_certs)
137 {
138 X509 *tmp;
139 int ret = -1;
140 int i;
141
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);
146 }
147
148 if (sk_X509_num(ta_certs) == 0) {
149 SUNWerr(SUNW_F_USE_TASTORE, SUNW_R_NO_TRUST_ANCHOR);
150 return (-1);
151 }
152
153 for (i = 0; i < sk_X509_num(ta_certs); i++) {
154 tmp = sk_X509_value(ta_certs, i);
155
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;
162 }
163 SUNWerr(SUNW_F_USE_TASTORE, SUNW_R_ADD_TRUST_ERR);
164 return (-1);
165 } else if (ret < 0) {
166 break;
167 }
168 }
169
170 if (ret < 0) {
171 SUNWerr(SUNW_F_USE_TASTORE, SUNW_R_ADD_TRUST_ERR);
172 }
173
174 return (ret);
175 }
176
177 /*
178 * sunw_p12_use_certfile - read a client certificate from a pkcs12 file and
179 * pass it in to SSL.
180 *
181 * Read in the certificate in pkcs12-formated file. Use the provided
182 * passphrase to decrypt it. Pass the cert to SSL.
183 *
184 * Arguments:
185 * ctx - SSL's context structure
186 * filename - Name of file with the client certificate.
187 * passwd - Passphrase for pkcs12 data.
188 *
189 * Returns:
190 * <=0 - Error occurred. Check the error stack for specifics.
191 * >0 - Success. Cert was successfully added.
192 */
193 int
sunw_p12_use_certfile(SSL_CTX * ctx,char * filename,char * passwd)194 sunw_p12_use_certfile(SSL_CTX *ctx, char *filename, char *passwd)
195 {
196 PKCS12 *p12 = NULL;
197 X509 *cert = NULL;
198 int ret = -1;
199
200 ERR_clear_error();
201 if (ctx == NULL || filename == NULL) {
202 SUNWerr(SUNW_F_USE_CERTFILE, SUNW_R_INVALID_ARG);
203 return (-1);
204 }
205
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) {
212 /*
213 * Error already on stack
214 */
215 ret = -1;
216 }
217 }
218 }
219
220 if (p12 != NULL)
221 PKCS12_free(p12);
222
223 if (ret == -1 && cert != NULL) {
224 X509_free(cert);
225 cert = NULL;
226 }
227
228 return (ret);
229 }
230
231 /*
232 * sunw_p12_use_keyfile - read a RSA private key from a pkcs12 file and pass
233 * it in to SSL.
234 *
235 * Read in the RSA private key in pkcs12 format. Use the provided
236 * passphrase to decrypt it. Pass the cert to SSL.
237 *
238 * Arguments:
239 * ctx - SSL's context structure
240 * filename - Name of file with private key.
241 * passwd - Passphrase for pkcs12 data.
242 *
243 * Returns:
244 * <=0 - Error occurred. Check the error stack for specifics.
245 * >0 - Success. Key was successfully added.
246 */
247 int
sunw_p12_use_keyfile(SSL_CTX * ctx,char * filename,char * passwd)248 sunw_p12_use_keyfile(SSL_CTX *ctx, char *filename, char *passwd)
249 {
250 EVP_PKEY *pkey = NULL;
251 PKCS12 *p12 = NULL;
252 int ret = -1;
253
254 ERR_clear_error();
255 if (ctx == NULL || filename == NULL) {
256 SUNWerr(SUNW_F_USE_KEYFILE, SUNW_R_INVALID_ARG);
257 return (-1);
258 }
259
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) {
266 /*
267 * Error already on stack
268 */
269 ret = -1;
270 }
271 } else {
272 SUNWerr(SUNW_F_USE_KEYFILE, SUNW_R_BAD_PKEY);
273 }
274 } else {
275 SUNWerr(SUNW_F_USE_KEYFILE, SUNW_R_PKEY_READ_ERR);
276 }
277
278 if (p12 != NULL)
279 PKCS12_free(p12);
280
281 if (ret == -1 && pkey != NULL) {
282 sunw_evp_pkey_free(pkey);
283 pkey = NULL;
284 }
285
286 return (ret);
287 }
288
289 /*
290 * sunw_p12_use_trustfile - read a list of trustanchors from a pkcs12 file and
291 * pass the stack in to SSL.
292 *
293 * Read in the trust anchors from pkcs12-formated file. Use the provided
294 * passphrase to decrypt it. Pass the cert to SSL.
295 *
296 * Arguments:
297 * ctx - SSL's context structure
298 * filename - Name of file with the certificates.
299 * passwd - Passphrase for pkcs12 data.
300 *
301 * Returns:
302 * <=0 - Error occurred. Check the error stack for specifics.
303 * >0 - Success. Trust anchors were successfully added.
304 */
305 int
sunw_p12_use_trustfile(SSL_CTX * ctx,char * filename,char * passwd)306 sunw_p12_use_trustfile(SSL_CTX *ctx, char *filename, char *passwd)
307 {
308 PKCS12 *p12 = NULL;
309 STACK_OF(X509) *ta_sk = NULL;
310 int ret = -1;
311
312 ERR_clear_error();
313 if (ctx == NULL || filename == NULL) {
314 SUNWerr(SUNW_F_USE_TRUSTFILE, SUNW_R_INVALID_ARG);
315 return (-1);
316 }
317
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;
327 }
328 } else {
329 SUNWerr(SUNW_F_USE_TRUSTFILE, SUNW_R_READ_TRUST_ERR);
330 }
331
332 if (p12 != NULL)
333 PKCS12_free(p12);
334
335 if (ta_sk != NULL)
336 sk_X509_pop_free(ta_sk, X509_free);
337
338 return (ret);
339 }
340
341 /*
342 * p12_read_file - read a pkcs12 file and get its contents. Return the
343 * pkcs12 structures.
344 *
345 * Arguments:
346 * filename - Name of file with the client certificate.
347 *
348 *
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.
353 */
354 static PKCS12 *
p12_read_file(char * filename)355 p12_read_file(char *filename)
356 {
357 PKCS12 *p12 = NULL;
358 FILE *fp = NULL;
359 int ret = 0;
360
361 ERR_clear_error();
362 if (checkfile(filename) == -1) {
363 /*
364 * Error already on stack
365 */
366 return (NULL);
367 }
368
369 if ((fp = fopen(filename, "r")) == 0) {
370 SYSerr(SYS_F_FOPEN, errno);
371 return (NULL);
372 }
373
374 p12 = d2i_PKCS12_fp(fp, NULL);
375 if (p12 == NULL) {
376 SUNWerr(SUNW_F_READ_FILE, SUNW_R_READ_ERR);
377 ret = -1;
378 }
379
380 if (fp != NULL)
381 (void) fclose(fp);
382
383 if (ret == -1 && p12 != NULL) {
384 PKCS12_free(p12);
385 p12 = NULL;
386 }
387
388 return (p12);
389 }
390
391 /*
392 * p12_doparse - Given a pkcs12 structure, check the passphrase and then
393 * parse it.
394 *
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
403 *
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.)
408 */
409 static int
p12_doparse(PKCS12 * p12,char * passwd,int matchty,EVP_PKEY ** pkey,X509 ** cert,STACK_OF (X509)** ca)410 p12_doparse(PKCS12 *p12, char *passwd, int matchty,
411 EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
412 {
413 int ret = 0;
414
415 ERR_clear_error();
416
417 /*
418 * Check passphrase (including null one).
419 */
420 if (check_password(p12, passwd) == 0) {
421 SUNWerr(SUNW_F_DOPARSE, SUNW_R_MAC_VERIFY_FAILURE);
422 return (-1);
423 }
424
425 ret = sunw_PKCS12_parse(p12, passwd, matchty, NULL, 0, NULL,
426 pkey, cert, ca);
427 if (ret <= 0) {
428 /*
429 * Error already on stack
430 */
431 return (-1);
432 }
433
434 return (ret);
435 }
436
437 /*
438 * checkfile - given a file name, verify that the file exists and is
439 * readable.
440 */
441 /* ARGSUSED */
442 static int
checkfile(char * filename)443 checkfile(char *filename)
444 {
445 #ifndef _BOOT
446 struct stat sbuf;
447
448 if (access(filename, R_OK) == -1 || stat(filename, &sbuf) == -1) {
449 SYSerr(SYS_F_FOPEN, errno);
450 return (-1);
451 }
452
453 if (!S_ISREG(sbuf.st_mode)) {
454 SUNWerr(SUNW_F_CHECKFILE, SUNW_R_BAD_FILETYPE);
455 return (-1);
456 }
457 #endif
458 return (0);
459 }
460
461 /*
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.
464 *
465 * Arguments:
466 * pass - password to check
467 *
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.
472 */
473 static int
check_password(PKCS12 * p12,char * pass)474 check_password(PKCS12 *p12, char *pass)
475 {
476 int ret = 1;
477
478 /*
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().
485 */
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;
493 }
494
495 return (ret);
496 }
497