Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / tls / tls_dh.c
blob8b0a2dca536c7e5f00b65fecb756004ad5301b11
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* tls_dh
6 /* SUMMARY
7 /* Diffie-Hellman parameter support
8 /* SYNOPSIS
9 /* #define TLS_INTERNAL
10 /* #include <tls.h>
12 /* void tls_set_dh_from_file(path, bits)
13 /* const char *path;
14 /* int bits;
16 /* int tls_set_eecdh_curve(server_ctx, grade)
17 /* SSL_CTX *server_ctx;
18 /* const char *grade;
20 /* DH *tls_tmp_dh_cb(ssl, export, keylength)
21 /* SSL *ssl; /* unused */
22 /* int export;
23 /* int keylength;
24 /* DESCRIPTION
25 /* This module maintains parameters for Diffie-Hellman key generation.
27 /* tls_tmp_dh_cb() is a call-back routine for the
28 /* SSL_CTX_set_tmp_dh_callback() function.
30 /* tls_set_dh_from_file() overrides compiled-in DH parameters
31 /* with those specified in the named files. The file format
32 /* is as expected by the PEM_read_DHparams() routine. The
33 /* "bits" argument must be 512 or 1024.
35 /* tls_set_eecdh_curve() enables ephemeral Elliptic-Curve DH
36 /* key exchange algorithms by instantiating in the server SSL
37 /* context a suitable curve (corresponding to the specified
38 /* EECDH security grade) from the set of named curves in RFC
39 /* 4492 Section 5.1.1. Errors generate warnings, but do not
40 /* disable TLS, rather we continue without EECDH. A zero
41 /* result indicates that the grade is invalid or the corresponding
42 /* curve could not be used.
43 /* DIAGNOSTICS
44 /* In case of error, tls_set_dh_from_file() logs a warning and
45 /* ignores the request.
46 /* LICENSE
47 /* .ad
48 /* .fi
49 /* This software is free. You can do with it whatever you want.
50 /* The original author kindly requests that you acknowledge
51 /* the use of his software.
52 /* AUTHOR(S)
53 /* Originally written by:
54 /* Lutz Jaenicke
55 /* BTU Cottbus
56 /* Allgemeine Elektrotechnik
57 /* Universitaetsplatz 3-4
58 /* D-03044 Cottbus, Germany
60 /* Updated by:
61 /* Wietse Venema
62 /* IBM T.J. Watson Research
63 /* P.O. Box 704
64 /* Yorktown Heights, NY 10598, USA
65 /*--*/
67 /* System library. */
69 #include <sys_defs.h>
71 #ifdef USE_TLS
72 #include <stdio.h>
74 /* Utility library. */
76 #include <msg.h>
79 * Global library
81 #include <mail_params.h>
83 /* TLS library. */
85 #define TLS_INTERNAL
86 #include <tls.h>
88 /* Application-specific. */
91 * Compiled-in EDH primes (the compiled-in generator is always 2). These are
92 * used when no parameters are explicitly loaded from a site-specific file.
94 * 512-bit parameters are used for export ciphers, and 1024-bit parameters are
95 * used for non-export ciphers. An ~80-bit strong EDH key exchange is really
96 * too weak to protect 128+ bit keys, but larger DH primes are
97 * computationally expensive. When greater security is required, use EECDH.
101 * Generated via "openssl dhparam -2 -noout -C 512 2>/dev/null" TODO:
102 * generate at compile-time.
104 static unsigned char dh512_p[] = {
105 0x88, 0x3F, 0x00, 0xAF, 0xFC, 0x0C, 0x8A, 0xB8, 0x35, 0xCD, 0xE5, 0xC2,
106 0x0F, 0x55, 0xDF, 0x06, 0x3F, 0x16, 0x07, 0xBF, 0xCE, 0x13, 0x35, 0xE4,
107 0x1C, 0x1E, 0x03, 0xF3, 0xAB, 0x17, 0xF6, 0x63, 0x50, 0x63, 0x67, 0x3E,
108 0x10, 0xD7, 0x3E, 0xB4, 0xEB, 0x46, 0x8C, 0x40, 0x50, 0xE6, 0x91, 0xA5,
109 0x6E, 0x01, 0x45, 0xDE, 0xC9, 0xB1, 0x1F, 0x64, 0x54, 0xFA, 0xD9, 0xAB,
110 0x4F, 0x70, 0xBA, 0x5B,
114 * Generated via "openssl dhparam -2 -noout -C 1024 2>/dev/null" TODO:
115 * generate at compile-time.
117 static unsigned char dh1024_p[] = {
118 0xB0, 0xFE, 0xB4, 0xCF, 0xD4, 0x55, 0x07, 0xE7, 0xCC, 0x88, 0x59, 0x0D,
119 0x17, 0x26, 0xC5, 0x0C, 0xA5, 0x4A, 0x92, 0x23, 0x81, 0x78, 0xDA, 0x88,
120 0xAA, 0x4C, 0x13, 0x06, 0xBF, 0x5D, 0x2F, 0x9E, 0xBC, 0x96, 0xB8, 0x51,
121 0x00, 0x9D, 0x0C, 0x0D, 0x75, 0xAD, 0xFD, 0x3B, 0xB1, 0x7E, 0x71, 0x4F,
122 0x3F, 0x91, 0x54, 0x14, 0x44, 0xB8, 0x30, 0x25, 0x1C, 0xEB, 0xDF, 0x72,
123 0x9C, 0x4C, 0xF1, 0x89, 0x0D, 0x68, 0x3F, 0x94, 0x8E, 0xA4, 0xFB, 0x76,
124 0x89, 0x18, 0xB2, 0x91, 0x16, 0x90, 0x01, 0x99, 0x66, 0x8C, 0x53, 0x81,
125 0x4E, 0x27, 0x3D, 0x99, 0xE7, 0x5A, 0x7A, 0xAF, 0xD5, 0xEC, 0xE2, 0x7E,
126 0xFA, 0xED, 0x01, 0x18, 0xC2, 0x78, 0x25, 0x59, 0x06, 0x5C, 0x39, 0xF6,
127 0xCD, 0x49, 0x54, 0xAF, 0xC1, 0xB1, 0xEA, 0x4A, 0xF9, 0x53, 0xD0, 0xDF,
128 0x6D, 0xAF, 0xD4, 0x93, 0xE7, 0xBA, 0xAE, 0x9B,
132 * Cached results.
134 static DH *dh_1024 = 0;
135 static DH *dh_512 = 0;
137 /* tls_set_dh_from_file - set Diffie-Hellman parameters from file */
139 void tls_set_dh_from_file(const char *path, int bits)
141 FILE *paramfile;
142 DH **dhPtr;
144 switch (bits) {
145 case 512:
146 dhPtr = &dh_512;
147 break;
148 case 1024:
149 dhPtr = &dh_1024;
150 break;
151 default:
152 msg_panic("Invalid DH parameters size %d, file %s", bits, path);
155 if ((paramfile = fopen(path, "r")) != 0) {
156 if ((*dhPtr = PEM_read_DHparams(paramfile, 0, 0, 0)) == 0) {
157 msg_warn("cannot load %d-bit DH parameters from file %s"
158 " -- using compiled-in defaults", bits, path);
159 tls_print_errors();
161 (void) fclose(paramfile); /* 200411 */
162 } else {
163 msg_warn("cannot load %d-bit DH parameters from file %s: %m"
164 " -- using compiled-in defaults", bits, path);
168 /* tls_get_dh - get compiled-in DH parameters */
170 static DH *tls_get_dh(const unsigned char *p, int plen)
172 DH *dh;
173 static unsigned char g[] = {0x02,};
175 /* Use the compiled-in parameters. */
176 if ((dh = DH_new()) == 0) {
177 msg_warn("cannot create DH parameter set: %m"); /* 200411 */
178 return (0);
180 dh->p = BN_bin2bn(p, plen, (BIGNUM *) 0);
181 dh->g = BN_bin2bn(g, 1, (BIGNUM *) 0);
182 if ((dh->p == 0) || (dh->g == 0)) {
183 msg_warn("cannot load compiled-in DH parameters"); /* 200411 */
184 DH_free(dh); /* 200411 */
185 return (0);
187 return (dh);
190 /* tls_tmp_dh_cb - call-back for Diffie-Hellman parameters */
192 DH *tls_tmp_dh_cb(SSL *unused_ssl, int export, int keylength)
194 DH *dh_tmp;
196 if (export && keylength == 512) { /* 40-bit export cipher */
197 if (dh_512 == 0)
198 dh_512 = tls_get_dh(dh512_p, (int) sizeof(dh512_p));
199 dh_tmp = dh_512;
200 } else { /* ADH, DHE-RSA or DSA */
201 if (dh_1024 == 0)
202 dh_1024 = tls_get_dh(dh1024_p, (int) sizeof(dh1024_p));
203 dh_tmp = dh_1024;
205 return (dh_tmp);
208 int tls_set_eecdh_curve(SSL_CTX *server_ctx, const char *grade)
210 #if OPENSSL_VERSION_NUMBER >= 0x00909000 && !defined(OPENSSL_NO_ECDH)
211 int nid;
212 EC_KEY *ecdh;
213 const char *curve;
214 int g;
216 #define TLS_EECDH_INVALID 0
217 #define TLS_EECDH_NONE 1
218 #define TLS_EECDH_STRONG 2
219 #define TLS_EECDH_ULTRA 3
220 static NAME_CODE eecdh_table[] = {
221 "none", TLS_EECDH_NONE,
222 "strong", TLS_EECDH_STRONG,
223 "ultra", TLS_EECDH_ULTRA,
224 0, TLS_EECDH_INVALID,
227 switch (g = name_code(eecdh_table, NAME_CODE_FLAG_NONE, grade)) {
228 default:
229 msg_panic("Invalid eecdh grade code: %d", g);
230 case TLS_EECDH_INVALID:
231 msg_warn("Invalid TLS eecdh grade \"%s\": EECDH disabled", grade);
232 return (0);
233 case TLS_EECDH_NONE:
234 return (1);
235 case TLS_EECDH_STRONG:
236 curve = var_tls_eecdh_strong;
237 break;
238 case TLS_EECDH_ULTRA:
239 curve = var_tls_eecdh_ultra;
240 break;
244 * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
245 * from RFC 4492 section 5.1.1, or explicitly described curves over
246 * binary fields. OpenSSL only supports the "named curves", which provide
247 * maximum interoperability. The recommended curve for 128-bit
248 * work-factor key exchange is "prime256v1" a.k.a. "secp256r1" from
249 * Section 2.7 of http://www.secg.org/download/aid-386/sec2_final.pdf
252 if ((nid = OBJ_sn2nid(curve)) == NID_undef) {
253 msg_warn("unknown curve \"%s\": disabling EECDH support", curve);
254 return (0);
256 ERR_clear_error();
257 if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0
258 || SSL_CTX_set_tmp_ecdh(server_ctx, ecdh) == 0) {
259 msg_warn("unable to use curve \"%s\": disabling EECDH support", curve);
260 tls_print_errors();
261 return (0);
263 #endif
264 return (1);
267 #ifdef TEST
269 int main(int unused_argc, char **unused_argv)
271 tls_tmp_dh_cb(0, 1, 512);
272 tls_tmp_dh_cb(0, 1, 1024);
273 tls_tmp_dh_cb(0, 1, 2048);
274 tls_tmp_dh_cb(0, 0, 512);
275 return (0);
278 #endif
280 #endif