1/*++ 2/* NAME 3/* tls_dh 4/* SUMMARY 5/* Diffie-Hellman parameter support 6/* SYNOPSIS 7/* #define TLS_INTERNAL 8/* #include <tls.h> 9/* 10/* void tls_set_dh_from_file(path, bits) 11/* const char *path; 12/* int bits; 13/* 14/* int tls_set_eecdh_curve(server_ctx, grade) 15/* SSL_CTX *server_ctx; 16/* const char *grade; 17/* 18/* DH *tls_tmp_dh_cb(ssl, export, keylength) 19/* SSL *ssl; /* unused */ 20/* int export; 21/* int keylength; 22/* DESCRIPTION 23/* This module maintains parameters for Diffie-Hellman key generation. 24/* 25/* tls_tmp_dh_cb() is a call-back routine for the 26/* SSL_CTX_set_tmp_dh_callback() function. 27/* 28/* tls_set_dh_from_file() overrides compiled-in DH parameters 29/* with those specified in the named files. The file format 30/* is as expected by the PEM_read_DHparams() routine. The 31/* "bits" argument must be 512 or 1024. 32/* 33/* tls_set_eecdh_curve() enables ephemeral Elliptic-Curve DH 34/* key exchange algorithms by instantiating in the server SSL 35/* context a suitable curve (corresponding to the specified 36/* EECDH security grade) from the set of named curves in RFC 37/* 4492 Section 5.1.1. Errors generate warnings, but do not 38/* disable TLS, rather we continue without EECDH. A zero 39/* result indicates that the grade is invalid or the corresponding 40/* curve could not be used. 41/* DIAGNOSTICS 42/* In case of error, tls_set_dh_from_file() logs a warning and 43/* ignores the request. 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#include <stdio.h> 71 72/* Utility library. */ 73 74#include <msg.h> 75 76 /* 77 * Global library 78 */ 79#include <mail_params.h> 80 81/* TLS library. */ 82 83#define TLS_INTERNAL 84#include <tls.h> 85 86/* Application-specific. */ 87 88 /* 89 * Compiled-in EDH primes (the compiled-in generator is always 2). These are 90 * used when no parameters are explicitly loaded from a site-specific file. 91 * 92 * 512-bit parameters are used for export ciphers, and 1024-bit parameters are 93 * used for non-export ciphers. An ~80-bit strong EDH key exchange is really 94 * too weak to protect 128+ bit keys, but larger DH primes are 95 * computationally expensive. When greater security is required, use EECDH. 96 */ 97 98 /* 99 * Generated via "openssl dhparam -2 -noout -C 512 2>/dev/null" TODO: 100 * generate at compile-time. 101 */ 102static unsigned char dh512_p[] = { 103 0x88, 0x3F, 0x00, 0xAF, 0xFC, 0x0C, 0x8A, 0xB8, 0x35, 0xCD, 0xE5, 0xC2, 104 0x0F, 0x55, 0xDF, 0x06, 0x3F, 0x16, 0x07, 0xBF, 0xCE, 0x13, 0x35, 0xE4, 105 0x1C, 0x1E, 0x03, 0xF3, 0xAB, 0x17, 0xF6, 0x63, 0x50, 0x63, 0x67, 0x3E, 106 0x10, 0xD7, 0x3E, 0xB4, 0xEB, 0x46, 0x8C, 0x40, 0x50, 0xE6, 0x91, 0xA5, 107 0x6E, 0x01, 0x45, 0xDE, 0xC9, 0xB1, 0x1F, 0x64, 0x54, 0xFA, 0xD9, 0xAB, 108 0x4F, 0x70, 0xBA, 0x5B, 109}; 110 111 /* 112 * Generated via "openssl dhparam -2 -noout -C 1024 2>/dev/null" TODO: 113 * generate at compile-time. 114 */ 115static unsigned char dh1024_p[] = { 116 0xB0, 0xFE, 0xB4, 0xCF, 0xD4, 0x55, 0x07, 0xE7, 0xCC, 0x88, 0x59, 0x0D, 117 0x17, 0x26, 0xC5, 0x0C, 0xA5, 0x4A, 0x92, 0x23, 0x81, 0x78, 0xDA, 0x88, 118 0xAA, 0x4C, 0x13, 0x06, 0xBF, 0x5D, 0x2F, 0x9E, 0xBC, 0x96, 0xB8, 0x51, 119 0x00, 0x9D, 0x0C, 0x0D, 0x75, 0xAD, 0xFD, 0x3B, 0xB1, 0x7E, 0x71, 0x4F, 120 0x3F, 0x91, 0x54, 0x14, 0x44, 0xB8, 0x30, 0x25, 0x1C, 0xEB, 0xDF, 0x72, 121 0x9C, 0x4C, 0xF1, 0x89, 0x0D, 0x68, 0x3F, 0x94, 0x8E, 0xA4, 0xFB, 0x76, 122 0x89, 0x18, 0xB2, 0x91, 0x16, 0x90, 0x01, 0x99, 0x66, 0x8C, 0x53, 0x81, 123 0x4E, 0x27, 0x3D, 0x99, 0xE7, 0x5A, 0x7A, 0xAF, 0xD5, 0xEC, 0xE2, 0x7E, 124 0xFA, 0xED, 0x01, 0x18, 0xC2, 0x78, 0x25, 0x59, 0x06, 0x5C, 0x39, 0xF6, 125 0xCD, 0x49, 0x54, 0xAF, 0xC1, 0xB1, 0xEA, 0x4A, 0xF9, 0x53, 0xD0, 0xDF, 126 0x6D, 0xAF, 0xD4, 0x93, 0xE7, 0xBA, 0xAE, 0x9B, 127}; 128 129 /* 130 * Cached results. 131 */ 132static DH *dh_1024 = 0; 133static DH *dh_512 = 0; 134 135/* tls_set_dh_from_file - set Diffie-Hellman parameters from file */ 136 137void tls_set_dh_from_file(const char *path, int bits) 138{ 139 FILE *paramfile; 140 DH **dhPtr; 141 142 switch (bits) { 143 case 512: 144 dhPtr = &dh_512; 145 break; 146 case 1024: 147 dhPtr = &dh_1024; 148 break; 149 default: 150 msg_panic("Invalid DH parameters size %d, file %s", bits, path); 151 } 152 153 if ((paramfile = fopen(path, "r")) != 0) { 154 if ((*dhPtr = PEM_read_DHparams(paramfile, 0, 0, 0)) == 0) { 155 msg_warn("cannot load %d-bit DH parameters from file %s" 156 " -- using compiled-in defaults", bits, path); 157 tls_print_errors(); 158 } 159 (void) fclose(paramfile); /* 200411 */ 160 } else { 161 msg_warn("cannot load %d-bit DH parameters from file %s: %m" 162 " -- using compiled-in defaults", bits, path); 163 } 164} 165 166/* tls_get_dh - get compiled-in DH parameters */ 167 168static DH *tls_get_dh(const unsigned char *p, int plen) 169{ 170 DH *dh; 171 static unsigned char g[] = {0x02,}; 172 173 /* Use the compiled-in parameters. */ 174 if ((dh = DH_new()) == 0) { 175 msg_warn("cannot create DH parameter set: %m"); /* 200411 */ 176 return (0); 177 } 178 dh->p = BN_bin2bn(p, plen, (BIGNUM *) 0); 179 dh->g = BN_bin2bn(g, 1, (BIGNUM *) 0); 180 if ((dh->p == 0) || (dh->g == 0)) { 181 msg_warn("cannot load compiled-in DH parameters"); /* 200411 */ 182 DH_free(dh); /* 200411 */ 183 return (0); 184 } 185 return (dh); 186} 187 188/* tls_tmp_dh_cb - call-back for Diffie-Hellman parameters */ 189 190DH *tls_tmp_dh_cb(SSL *unused_ssl, int export, int keylength) 191{ 192 DH *dh_tmp; 193 194 if (export && keylength == 512) { /* 40-bit export cipher */ 195 if (dh_512 == 0) 196 dh_512 = tls_get_dh(dh512_p, (int) sizeof(dh512_p)); 197 dh_tmp = dh_512; 198 } else { /* ADH, DHE-RSA or DSA */ 199 if (dh_1024 == 0) 200 dh_1024 = tls_get_dh(dh1024_p, (int) sizeof(dh1024_p)); 201 dh_tmp = dh_1024; 202 } 203 return (dh_tmp); 204} 205 206int tls_set_eecdh_curve(SSL_CTX *server_ctx, const char *grade) 207{ 208#if OPENSSL_VERSION_NUMBER >= 0x1000000fL && !defined(OPENSSL_NO_ECDH) 209 int nid; 210 EC_KEY *ecdh; 211 const char *curve; 212 int g; 213 214#define TLS_EECDH_INVALID 0 215#define TLS_EECDH_NONE 1 216#define TLS_EECDH_STRONG 2 217#define TLS_EECDH_ULTRA 3 218 static NAME_CODE eecdh_table[] = { 219 "none", TLS_EECDH_NONE, 220 "strong", TLS_EECDH_STRONG, 221 "ultra", TLS_EECDH_ULTRA, 222 0, TLS_EECDH_INVALID, 223 }; 224 225 switch (g = name_code(eecdh_table, NAME_CODE_FLAG_NONE, grade)) { 226 default: 227 msg_panic("Invalid eecdh grade code: %d", g); 228 case TLS_EECDH_INVALID: 229 msg_warn("Invalid TLS eecdh grade \"%s\": EECDH disabled", grade); 230 return (0); 231 case TLS_EECDH_NONE: 232 return (1); 233 case TLS_EECDH_STRONG: 234 curve = var_tls_eecdh_strong; 235 break; 236 case TLS_EECDH_ULTRA: 237 curve = var_tls_eecdh_ultra; 238 break; 239 } 240 241 /* 242 * Elliptic-Curve Diffie-Hellman parameters are either "named curves" 243 * from RFC 4492 section 5.1.1, or explicitly described curves over 244 * binary fields. OpenSSL only supports the "named curves", which provide 245 * maximum interoperability. The recommended curve for 128-bit 246 * work-factor key exchange is "prime256v1" a.k.a. "secp256r1" from 247 * Section 2.7 of http://www.secg.org/download/aid-386/sec2_final.pdf 248 */ 249 250 if ((nid = OBJ_sn2nid(curve)) == NID_undef) { 251 msg_warn("unknown curve \"%s\": disabling EECDH support", curve); 252 return (0); 253 } 254 ERR_clear_error(); 255 if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0 256 || SSL_CTX_set_tmp_ecdh(server_ctx, ecdh) == 0) { 257 msg_warn("unable to use curve \"%s\": disabling EECDH support", curve); 258 tls_print_errors(); 259 return (0); 260 } 261#endif 262 return (1); 263} 264 265#ifdef TEST 266 267int main(int unused_argc, char **unused_argv) 268{ 269 tls_tmp_dh_cb(0, 1, 512); 270 tls_tmp_dh_cb(0, 1, 1024); 271 tls_tmp_dh_cb(0, 1, 2048); 272 tls_tmp_dh_cb(0, 0, 512); 273 return (0); 274} 275 276#endif 277 278#endif 279