Mercurial > dovecot > core-2.2
diff src/lib-ssl-iostream/iostream-openssl-params.c @ 12616:bd23d4e10fa1
Added lib-ssl-iostream for handling SSL connections more easily.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 31 Jan 2011 18:40:27 +0200 |
parents | |
children | ba770cba5598 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-ssl-iostream/iostream-openssl-params.c Mon Jan 31 18:40:27 2011 +0200 @@ -0,0 +1,129 @@ +/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "buffer.h" +#include "iostream-openssl.h" + +/* 2 or 5. Haven't seen their difference explained anywhere, but 2 is the + default.. */ +#define DH_GENERATOR 2 + +static int dh_param_bitsizes[] = { 512, 1024 }; + +static int generate_dh_parameters(int bitsize, buffer_t *output) +{ + DH *dh; + unsigned char *p; + int len, len2; + + dh = DH_generate_parameters(bitsize, DH_GENERATOR, NULL, NULL); + if (dh == NULL) { + i_error("DH_generate_parameters(bits=%d, gen=%d) failed: %s", + bitsize, DH_GENERATOR, ssl_iostream_error()); + return -1; + } + + len = i2d_DHparams(dh, NULL); + if (len < 0) { + i_error("i2d_DHparams() failed: %s", ssl_iostream_error()); + DH_free(dh); + return -1; + } + + buffer_append(output, &bitsize, sizeof(bitsize)); + buffer_append(output, &len, sizeof(len)); + + p = buffer_append_space_unsafe(output, len); + len2 = i2d_DHparams(dh, &p); + i_assert(len == len2); + DH_free(dh); + return 0; +} + +int ssl_iostream_generate_params(buffer_t *output) +{ + unsigned int i; + + for (i = 0; i < N_ELEMENTS(dh_param_bitsizes); i++) { + if (generate_dh_parameters(dh_param_bitsizes[i], output) < 0) + return -1; + } + buffer_append_zero(output, sizeof(int)); + return 0; +} + +static int read_int(const unsigned char **data, const unsigned char *end) +{ + unsigned int len = end - *data; + int ret; + + if (len < sizeof(ret)) + return -1; + memcpy(&ret, *data, sizeof(ret)); + *data += sizeof(ret); + return ret; +} + +static int +read_dh_parameters_next(struct ssl_iostream_context *ctx, + const unsigned char **data, const unsigned char *end) +{ + const unsigned char *dbuf; + DH *dh; + int bits, len, ret = 1; + + /* get bit size. 0 ends the DH parameters list. */ + if ((bits = read_int(data, end)) <= 0) + return bits; + + /* get data size */ + if ((len = read_int(data, end)) <= 0 || end - *data < len) + return -1; + + dbuf = *data; + dh = d2i_DHparams(NULL, &dbuf, len); + *data += len; + + if (dh == NULL) + return -1; + + switch (bits) { + case 512: + ctx->dh_512 = dh; + break; + case 1024: + ctx->dh_1024 = dh; + break; + default: + ret = -1; + break; + } + return ret; +} + +int ssl_iostream_context_import_params(struct ssl_iostream_context *ctx, + const buffer_t *input) +{ + const unsigned char *data, *end; + int ret; + + ssl_iostream_context_free_params(ctx); + + data = input->data; + end = data + input->used; + while ((ret = read_dh_parameters_next(ctx, &data, end)) > 0) ; + + return ret < 0 || data != end ? -1 : 0; +} + +void ssl_iostream_context_free_params(struct ssl_iostream_context *ctx) +{ + if (ctx->dh_512 != NULL) { + DH_free(ctx->dh_512); + ctx->dh_512 = NULL; + } + if (ctx->dh_1024 != NULL) { + DH_free(ctx->dh_1024); + ctx->dh_1024 = NULL; + } +}