# HG changeset patch # User Paul Aurich # Date 1290312251 28800 # Node ID 8c61b29d87ecf6c25f17b1f4e2c79b0472bf097d # Parent 3e0325d39a61ee7c311d5bd89288187a4f7a482c context: support for diffie-hellman key exchange diff -r 3e0325d39a61 -r 8c61b29d87ec src/context.c --- a/src/context.c Sun Nov 07 17:12:33 2010 -0800 +++ b/src/context.c Sat Nov 20 20:04:11 2010 -0800 @@ -19,6 +19,46 @@ }; typedef struct ssl_option_s ssl_option_t; +/* The export DH key */ +static DH *dh_512 = NULL; +/* The larger key (builtin is 2048, caller may specify larger) */ +static DH *dh_larger = NULL; + +/* Generated via "openssl dhparam -2 -noout -C 512 2>/dev/null" */ +static unsigned char dh512_p[] = { + 0xE4,0x3F,0x75,0x82,0xAD,0x0B,0x28,0xC7,0xEF,0xCE,0xBC,0x3B, + 0x14,0xBB,0xA6,0xF4,0xA2,0xE9,0xA6,0x59,0xCF,0x97,0x1C,0x86, + 0x43,0x3B,0x92,0x4A,0x6B,0x15,0x4B,0x0C,0xAC,0x8F,0xFA,0x43, + 0xE2,0xA8,0xC3,0x3B,0x7B,0x51,0x1B,0x46,0x21,0xBF,0x8C,0x06, + 0x6C,0xB1,0x49,0x75,0xC7,0xAC,0x47,0x1D,0x9D,0x64,0xD5,0x99, + 0x33,0x86,0xAD,0xEB, +}; + +/* Generated via "openssl dhparam -2 -noout -C 2048 2>/dev/null" */ +static unsigned char dh2048_p[] = { + 0x9B,0xF4,0xC5,0x57,0x81,0x8F,0xCF,0x31,0x78,0x95,0x04,0xCD, + 0xEA,0xCC,0x30,0xEA,0xF7,0xCA,0x76,0xC8,0x8F,0x91,0xEA,0x0E, + 0x44,0x8D,0xE2,0x63,0x19,0x3B,0x4D,0x04,0xC8,0x7D,0x0D,0xFF, + 0x3D,0x52,0x76,0x02,0xF3,0xCA,0x1C,0x44,0xAF,0x0E,0xA9,0x59, + 0x02,0x40,0x75,0xD6,0xED,0x35,0x4D,0x11,0x5B,0x2B,0x73,0x23, + 0xE5,0x53,0x0B,0x1F,0xB0,0x47,0xC4,0x7F,0x95,0x5D,0xB0,0xD5, + 0xF3,0xD3,0xAB,0x5F,0x28,0x2B,0xEC,0x2C,0x15,0x0B,0x1B,0x0C, + 0xD4,0xBE,0x24,0x2F,0xC5,0x07,0x3C,0xE4,0xC5,0xE6,0x16,0x42, + 0x4C,0x31,0x04,0xBB,0x80,0x96,0xFF,0x64,0x50,0xA4,0xA5,0xB5, + 0xF5,0x3A,0xBA,0x57,0xE4,0xE6,0xC2,0x23,0x0A,0xB6,0x27,0xC4, + 0x06,0x01,0x1E,0x98,0x20,0x09,0xC8,0xB7,0x90,0x09,0x86,0x06, + 0xAA,0x85,0xE7,0x02,0xC8,0xC6,0xD9,0x1D,0xAB,0x17,0xEE,0x78, + 0x73,0x78,0x88,0x7F,0xA7,0xF2,0x34,0xA7,0xDD,0x02,0x16,0x36, + 0x0D,0x77,0x16,0x3E,0x95,0xAE,0x02,0xEE,0x36,0x37,0xD5,0x61, + 0x5D,0xFE,0xC6,0x0B,0xDF,0xCE,0xB9,0x26,0x31,0x6F,0x34,0x92, + 0xBB,0xBB,0x91,0x29,0x77,0x62,0x1D,0x75,0xA0,0x51,0x8D,0x31, + 0x4C,0x64,0x4E,0xBF,0xDC,0xE8,0x67,0x17,0x90,0x6A,0x80,0xE9, + 0xD7,0xD8,0x56,0x4E,0x85,0x21,0x9C,0xFB,0xE6,0x1B,0xD8,0x05, + 0xFD,0x13,0x77,0x00,0x96,0x2D,0x0C,0x2A,0x95,0x1A,0x08,0x82, + 0x2E,0xB3,0xE2,0xFC,0xE8,0xA6,0xF1,0x16,0x37,0x57,0x82,0xD6, + 0xF5,0xAB,0xA9,0x43,0x8F,0x33,0xB0,0x57,0x38,0x6E,0x61,0xD4, + 0xDD,0xE0,0x1C,0xCB, +}; static ssl_option_t ssl_options[] = { /* OpenSSL 0.9.7 and 0.9.8 */ @@ -143,6 +183,38 @@ return 0; } +static DH *get_dh(const unsigned char *p, int len) +{ + DH *dh = NULL; + static unsigned char g[] = { 0x02 }; + + if ((dh = DH_new()) == NULL) return NULL; + dh->p = BN_bin2bn(p, len, NULL); + dh->g = BN_bin2bn(g, sizeof(g), NULL); + if (dh->p == NULL || dh->g == NULL) { + DH_free(dh); + return NULL; + } + + return dh; +} + +/** + * DH parameter callback + */ +static DH *dh_param_cb(SSL *ssl, int is_export, int keylength) +{ + /* Logic in postfix and dovecot, but we're using a 2048-bit group... */ + if (is_export && keylength == 512) { + if (dh_512 == NULL) { dh_512 = get_dh(dh512_p, sizeof(dh512_p)); } + return dh_512; + } else { + if (dh_larger == NULL) { dh_larger = get_dh(dh2048_p, sizeof(dh2048_p)); } + return dh_larger; + } +} + + /*------------------------------ Lua Functions -------------------------------*/ /** @@ -174,6 +246,11 @@ ctx->mode = MD_CTX_INVALID; /* No session support */ SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF); + /* + * Support ephemeral diffie-hellman key exchange. This is only needed + * for server mode, but clearer to put it here rather than set_mode. + */ + SSL_CTX_set_tmp_dh_callback(ctx->context, dh_param_cb); luaL_getmetatable(L, "SSL:Context"); lua_setmetatable(L, -2); return 1; @@ -248,6 +325,41 @@ } /** + * Load a DH params files. This is a global LuaSec thing. + */ +static int load_dhparams(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + FILE *paramfile; + DH *dh; + + paramfile = fopen(filename, "r"); + if (!paramfile) { + lua_pushboolean(L, 0); + lua_pushfstring(L, "error reading dh param file %s: %s", filename, + strerror(errno)); + return 2; + } + + dh = PEM_read_DHparams(paramfile, NULL, NULL, NULL); + fclose(paramfile); + if (!dh) { + lua_pushboolean(L, 0); + lua_pushfstring(L, "error loading dh param file %s: %s", filename, + ERR_reason_error_string(ERR_get_error())); + return 2; + } + + if (dh_larger) + DH_free(dh_larger); + + dh_larger = dh; + + lua_pushboolean(L, 1); + return 1; +} + +/** * Set the cipher list. */ static int set_cipher(lua_State *L) @@ -369,6 +481,7 @@ {"setoptions", set_options}, {"setmode", set_mode}, {"rawcontext", raw_ctx}, + {"loaddhparams", load_dhparams}, {NULL, NULL} }; diff -r 3e0325d39a61 -r 8c61b29d87ec src/ssl.lua --- a/src/ssl.lua Sun Nov 07 17:12:33 2010 -0800 +++ b/src/ssl.lua Sat Nov 20 20:04:11 2010 -0800 @@ -18,6 +18,7 @@ -- Export functions rawconnection = core.rawconnection rawcontext = context.rawcontext +loaddhparams = context.loaddhparams cert_from_pem = x509.cert_from_pem