1 /*	$NetBSD: tls_certkey.c,v 1.1.1.3 2010/11/27 10:35:45 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	tls_certkey 3
6 /* SUMMARY
7 /*	public key certificate and private key loader
8 /* SYNOPSIS
9 /*	#define TLS_INTERNAL
10 /*	#include <tls.h>
11 /*
12 /*	int	tls_set_ca_certificate_info(ctx, CAfile, CApath)
13 /*	SSL_CTX	*ctx;
14 /*	const char *CAfile;
15 /*	const char *CApath;
16 /*
17 /*	int	tls_set_my_certificate_key_info(ctx, cert_file, key_file,
18 /*						dcert_file, dkey_file,
19 /*						eccert_file, eckey_file)
20 /*	SSL_CTX	*ctx;
21 /*	const char *cert_file;
22 /*	const char *key_file;
23 /*	const char *dcert_file;
24 /*	const char *dkey_file;
25 /*	const char *eccert_file;
26 /*	const char *eckey_file;
27 /* DESCRIPTION
28 /*	OpenSSL supports two options to specify CA certificates:
29 /*	either one file CAfile that contains all CA certificates,
30 /*	or a directory CApath with separate files for each
31 /*	individual CA, with symbolic links named after the hash
32 /*	values of the certificates. The second option is not
33 /*	convenient with a chrooted process.
34 /*
35 /*	tls_set_ca_certificate_info() loads the CA certificate
36 /*	information for the specified TLS server or client context.
37 /*	The result is -1 on failure, 0 on success.
38 /*
39 /*	tls_set_my_certificate_key_info() loads the public key
40 /*	certificates and private keys for the specified TLS server
41 /*	or client context. Up to 3 pairs of key pairs (RSA, DSA and
42 /*	ECDSA) may be specified; each certificate and key pair must
43 /*	match.  The result is -1 on failure, 0 on success.
44 /* LICENSE
45 /* .ad
46 /* .fi
47 /*	This software is free. You can do with it whatever you want.
48 /*	The original author kindly requests that you acknowledge
49 /*	the use of his software.
50 /* AUTHOR(S)
51 /*	Originally written by:
52 /*	Lutz Jaenicke
53 /*	BTU Cottbus
54 /*	Allgemeine Elektrotechnik
55 /*	Universitaetsplatz 3-4
56 /*	D-03044 Cottbus, Germany
57 /*
58 /*	Updated by:
59 /*	Wietse Venema
60 /*	IBM T.J. Watson Research
61 /*	P.O. Box 704
62 /*	Yorktown Heights, NY 10598, USA
63 /*--*/
64 
65 /* System library. */
66 
67 #include <sys_defs.h>
68 
69 #ifdef USE_TLS
70 
71 /* Utility library. */
72 
73 #include <msg.h>
74 
75 /* Global library. */
76 
77 #include <mail_params.h>
78 
79 /* TLS library. */
80 
81 #define TLS_INTERNAL
82 #include <tls.h>
83 
84 /* tls_set_ca_certificate_info - load certificate authority certificates */
85 
86 int     tls_set_ca_certificate_info(SSL_CTX *ctx, const char *CAfile,
87 				            const char *CApath)
88 {
89     if (*CAfile == 0)
90 	CAfile = 0;
91     if (*CApath == 0)
92 	CApath = 0;
93     if (CAfile || CApath) {
94 	if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
95 	    msg_info("cannot load Certificate Authority data: "
96 		     "disabling TLS support");
97 	    tls_print_errors();
98 	    return (-1);
99 	}
100 	if (var_tls_append_def_CA && !SSL_CTX_set_default_verify_paths(ctx)) {
101 	    msg_info("cannot set certificate verification paths: "
102 		     "disabling TLS support");
103 	    tls_print_errors();
104 	    return (-1);
105 	}
106     }
107     return (0);
108 }
109 
110 /* set_cert_stuff - specify certificate and key information */
111 
112 static int set_cert_stuff(SSL_CTX *ctx, const char *cert_type,
113 			          const char *cert_file,
114 			          const char *key_file)
115 {
116 
117     /*
118      * We need both the private key (in key_file) and the public key
119      * certificate (in cert_file). Both may specify the same file.
120      *
121      * Code adapted from OpenSSL apps/s_cb.c.
122      */
123     ERR_clear_error();
124     if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) {
125 	msg_warn("cannot get %s certificate from file %s: "
126 		 "disabling TLS support", cert_type, cert_file);
127 	tls_print_errors();
128 	return (0);
129     }
130     if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
131 	msg_warn("cannot get %s private key from file %s: "
132 		 "disabling TLS support", cert_type, key_file);
133 	tls_print_errors();
134 	return (0);
135     }
136 
137     /*
138      * Sanity check.
139      */
140     if (!SSL_CTX_check_private_key(ctx)) {
141 	msg_warn("%s private key in %s does not match public key in %s: "
142 		 "disabling TLS support", cert_type, key_file, cert_file);
143 	return (0);
144     }
145     return (1);
146 }
147 
148 /* tls_set_my_certificate_key_info - load client or server certificates/keys */
149 
150 int     tls_set_my_certificate_key_info(SSL_CTX *ctx,
151 					        const char *cert_file,
152 					        const char *key_file,
153 					        const char *dcert_file,
154 					        const char *dkey_file,
155 					        const char *eccert_file,
156 					        const char *eckey_file)
157 {
158 
159     /*
160      * Lack of certificates is fine so long as we are prepared to use
161      * anonymous ciphers.
162      */
163     if (*cert_file && !set_cert_stuff(ctx, "RSA", cert_file, key_file))
164 	return (-1);			/* logged */
165     if (*dcert_file && !set_cert_stuff(ctx, "DSA", dcert_file, dkey_file))
166 	return (-1);				/* logged */
167 #if OPENSSL_VERSION_NUMBER >= 0x1000000fL && !defined(OPENSSL_NO_ECDH)
168     if (*eccert_file && !set_cert_stuff(ctx, "ECDSA", eccert_file, eckey_file))
169 	return (-1);				/* logged */
170 #else
171     if (*eccert_file)
172 	msg_warn("ECDSA not supported. Ignoring ECDSA certificate file \"%s\"",
173 		 eccert_file);
174 #endif
175     return (0);
176 }
177 
178 #endif
179