Projects
Kolab:3.4:Updates
httpd
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
apache2.dsc
Changed
@@ -2,7 +2,7 @@ Source: apache2 Binary: apache2.2-common, apache2.2-bin, apache2-mpm-worker, apache2-mpm-prefork, apache2-mpm-event, apache2-mpm-itk, apache2-utils, apache2-suexec, apache2-suexec-custom, apache2, apache2-doc, apache2-prefork-dev, apache2-threaded-dev, apache2-dbg Architecture: any all -Version: 2.2.22-13.2+deb7u4 +Version: 2.2.22-13.2+deb7u5 Maintainer: Debian Apache Maintainers <debian-apache@lists.debian.org> Uploaders: Stefan Fritsch <sf@debian.org>, Steinar H. Gunderson <sesse@debian.org>, Arno Töll <arno@debian.org> Homepage: http://httpd.apache.org/
View file
debian.changelog
Changed
@@ -1,3 +1,25 @@ +apache2 (2.2.22-13.2+deb7u5) wheezy; urgency=medium + + * Non-maintainer upload. + * Merge patches from Debian 2.2.22-13+deb7u5. + + -- Christoph Erhardt <kolab@sicherha.de> Wed, 05 Aug 2015 10:10:27 +0200 + +apache2 (2.2.22-13+deb7u5) wheezy-security; urgency=medium + + * CVE-2015-3183: Fix request smuggling via chunked transfer encoding. + Backported by Marc Deslauriers. + * Don't limit default DH parameters to 1024 bits. Closes: #780398 + This may cause problems with some Java based clients. A work-around is to + configure these client not to use DHE key exchange but use ECDHE or RSA + instead. + A server-side work-around that limits the DH parameters to 1024 bits for + all clients is described at + http://httpd.apache.org/docs/trunk/ssl/ssl_faq.html#javadh . + * Backport support for adding DH parameters to the SSLCertificateFile. + + -- Stefan Fritsch <sf@debian.org> Sat, 01 Aug 2015 22:08:57 +0200 + apache2 (2.2.22-13.2+deb7u4) wheezy; urgency=medium * Non-maintainer upload.
View file
debian.tar.gz/README.Debian
Changed
@@ -13,6 +13,7 @@ SSL workaround for MSIE ECC keys and ECDH ciphers Session ticket key life-time and forward secrecy + DH parameters Suexec @@ -261,6 +262,17 @@ increasing the frequency of graceful restarts by changing the log rotation in /etc/logrotate.d/apache2 from weekly to daily. +DH parameters +------------- + +The package in Debian has support for Diffie-Hellman (DH) parameters larger +than 1024 bit and for custom DH parameters backported from Apache 2.2.30. +This may cause connection failures with java clients that only support 1024 +bit DH parameters. A work-around is to configure these client not to use DHE +key exchange but use ECDHE or RSA instead. A server-side work-around that +limits the DH parameters to 1024 bits for all clients is described at +http://httpd.apache.org/docs/trunk/ssl/ssl_faq.html#javadh + Suexec ======
View file
debian.tar.gz/patches/CVE-2015-3183.patch
Added
@@ -0,0 +1,801 @@ +Description: fix request smuggling via chunked transfer encoding +Origin: backport, http://svn.apache.org/viewvc?view=revision&revision=1687338 +Origin: backport, http://svn.apache.org/viewvc?view=revision&revision=1687339 +Origin: backport, http://svn.apache.org/viewvc?view=revision&revision=1688936 +Origin: backport, http://svn.apache.org/viewvc?view=revision&revision=1689522 + +Index: apache2-2.2.22/modules/http/http_filters.c +=================================================================== +--- apache2-2.2.22.orig/modules/http/http_filters.c 2015-07-24 09:33:00.000000000 -0400 ++++ apache2-2.2.22/modules/http/http_filters.c 2015-07-24 13:06:08.276786883 -0400 +@@ -56,27 +56,33 @@ + #include <unistd.h> + #endif + +-#define INVALID_CHAR -2 +- +-static long get_chunk_size(char *); +- +-typedef struct http_filter_ctx { ++typedef struct http_filter_ctx ++{ + apr_off_t remaining; + apr_off_t limit; + apr_off_t limit_used; +- enum { +- BODY_NONE, +- BODY_LENGTH, +- BODY_CHUNK, +- BODY_CHUNK_PART ++ apr_int32_t chunk_used; ++ apr_int32_t chunk_bws; ++ apr_int32_t chunkbits; ++ enum ++ { ++ BODY_NONE, /* streamed data */ ++ BODY_LENGTH, /* data constrained by content length */ ++ BODY_CHUNK, /* chunk expected */ ++ BODY_CHUNK_PART, /* chunk digits */ ++ BODY_CHUNK_EXT, /* chunk extension */ ++ BODY_CHUNK_CR, /* got space(s) after digits, expect [CR]LF or ext */ ++ BODY_CHUNK_LF, /* got CR after digits or ext, expect LF */ ++ BODY_CHUNK_DATA, /* data constrained by chunked encoding */ ++ BODY_CHUNK_END, /* chunked data terminating CRLF */ ++ BODY_CHUNK_END_LF, /* got CR after data, expect LF */ ++ BODY_CHUNK_TRAILER /* trailers */ + } state; +- int eos_sent; +- char chunk_ln[32]; +- char *pos; +- apr_off_t linesize; ++ unsigned int eos_sent :1; + apr_bucket_brigade *bb; + } http_ctx_t; + ++/* bail out if some error in the HTTP input filter happens */ + static apr_status_t bail_out_on_error(http_ctx_t *ctx, + ap_filter_t *f, + int http_error) +@@ -92,119 +98,162 @@ + e = apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, e); + ctx->eos_sent = 1; ++ /* If chunked encoding / content-length are corrupt, we may treat parts ++ * of this request's body as the next one's headers. ++ * To be safe, disable keep-alive. ++ */ ++ f->r->connection->keepalive = AP_CONN_CLOSE; + return ap_pass_brigade(f->r->output_filters, bb); + } + +-static apr_status_t get_remaining_chunk_line(http_ctx_t *ctx, +- apr_bucket_brigade *b, +- int linelimit) ++/** ++ * Parse a chunk line with optional extension, detect overflow. ++ * There are two error cases: ++ * 1) If the conversion would require too many bits, APR_EGENERAL is returned. ++ * 2) If the conversion used the correct number of bits, but an overflow ++ * caused only the sign bit to flip, then APR_ENOSPC is returned. ++ * In general, any negative number can be considered an overflow error. ++ */ ++static apr_status_t parse_chunk_size(http_ctx_t *ctx, const char *buffer, ++ apr_size_t len, int linelimit) + { +- apr_status_t rv; +- apr_off_t brigade_length; +- apr_bucket *e; +- const char *lineend; +- apr_size_t len; ++ apr_size_t i = 0; + +- /* +- * As the brigade b should have been requested in mode AP_MODE_GETLINE +- * all buckets in this brigade are already some type of memory +- * buckets (due to the needed scanning for LF in mode AP_MODE_GETLINE) +- * or META buckets. +- */ +- rv = apr_brigade_length(b, 0, &brigade_length); +- if (rv != APR_SUCCESS) { +- return rv; +- } +- /* Sanity check. Should never happen. See above. */ +- if (brigade_length == -1) { +- return APR_EGENERAL; +- } +- if (!brigade_length) { +- return APR_EAGAIN; +- } +- ctx->linesize += brigade_length; +- if (ctx->linesize > linelimit) { +- return APR_ENOSPC; +- } +- /* +- * As all buckets are already some type of memory buckets or META buckets +- * (see above), we only need to check the last byte in the last data bucket. +- */ +- for (e = APR_BRIGADE_LAST(b); +- e != APR_BRIGADE_SENTINEL(b); +- e = APR_BUCKET_PREV(e)) { ++ while (i < len) { ++ char c = buffer[i]; ++ ++ ap_xlate_proto_from_ascii(&c, 1); + +- if (APR_BUCKET_IS_METADATA(e)) { ++ /* handle CRLF after the chunk */ ++ if (ctx->state == BODY_CHUNK_END ++ || ctx->state == BODY_CHUNK_END_LF) { ++ if (c == LF) { ++ ctx->state = BODY_CHUNK; ++ } ++ else if (c == CR && ctx->state == BODY_CHUNK_END) { ++ ctx->state = BODY_CHUNK_END_LF; ++ } ++ else { ++ /* ++ * LF expected. ++ */ ++ return APR_EINVAL; ++ } ++ i++; + continue; + } +- rv = apr_bucket_read(e, &lineend, &len, APR_BLOCK_READ); +- if (rv != APR_SUCCESS) { +- return rv; ++ ++ /* handle start of the chunk */ ++ if (ctx->state == BODY_CHUNK) { ++ if (!apr_isxdigit(c)) { ++ /* ++ * Detect invalid character at beginning. This also works for ++ * empty chunk size lines. ++ */ ++ return APR_EINVAL; ++ } ++ else { ++ ctx->state = BODY_CHUNK_PART; ++ } ++ ctx->remaining = 0; ++ ctx->chunkbits = sizeof(apr_off_t) * 8; ++ ctx->chunk_used = 0; ++ ctx->chunk_bws = 0; + } +- if (len > 0) { +- break; /* we got the data we want */ ++ ++ if (c == LF) { ++ if (ctx->remaining) { ++ ctx->state = BODY_CHUNK_DATA; ++ } ++ else { ++ ctx->state = BODY_CHUNK_TRAILER; ++ } + } +- /* If we got a zero-length data bucket, we try the next one */ +- } +- /* We had no data in this brigade */ +- if (!len || e == APR_BRIGADE_SENTINEL(b)) { +- return APR_EAGAIN; +- } +- if (lineend[len - 1] != APR_ASCII_LF) { +- return APR_EAGAIN; +- } +- /* Line is complete. So reset ctx->linesize for next round. */ +- ctx->linesize = 0; +- return APR_SUCCESS; +-} ++ else if (ctx->state == BODY_CHUNK_LF) { ++ /* ++ * LF expected. ++ */ ++ return APR_EINVAL; ++ } ++ else if (c == CR) { ++ ctx->state = BODY_CHUNK_LF; ++ } ++ else if (c == ';') { ++ ctx->state = BODY_CHUNK_EXT; ++ } ++ else if (ctx->state == BODY_CHUNK_EXT) { ++ /* ++ * Control chars (but tabs) are invalid. ++ */ ++ if (c != '\t' && apr_iscntrl(c)) { ++ return APR_EINVAL; ++ } ++ } ++ else if (c == ' ' || c == '\t') { ++ /* Be lenient up to 10 BWS (term from rfc7230 - 3.2.3). ++ */ ++ ctx->state = BODY_CHUNK_CR; ++ if (++ctx->chunk_bws > 10) { ++ return APR_EINVAL; ++ } ++ } ++ else if (ctx->state == BODY_CHUNK_CR) { ++ /* ++ * ';', CR or LF expected. ++ */ ++ return APR_EINVAL; ++ } ++ else if (ctx->state == BODY_CHUNK_PART) { ++ int xvalue; + +-static apr_status_t get_chunk_line(http_ctx_t *ctx, apr_bucket_brigade *b, +- int linelimit) +-{ +- apr_size_t len; +- int tmp_len; +- apr_status_t rv; ++ /* ignore leading zeros */ ++ if (!ctx->remaining && c == '0') { ++ i++; ++ continue; ++ } + +- tmp_len = sizeof(ctx->chunk_ln) - (ctx->pos - ctx->chunk_ln) - 1; +- /* Saveguard ourselves against underflows */ +- if (tmp_len < 0) { +- len = 0; +- } +- else { +- len = (apr_size_t) tmp_len; +- } +- /* +- * Check if there is space left in ctx->chunk_ln. If not, then either +- * the chunk size is insane or we have chunk-extensions. Ignore both +- * by discarding the remaining part of the line via +- * get_remaining_chunk_line. Only bail out if the line is too long. +- */ +- if (len > 0) { +- rv = apr_brigade_flatten(b, ctx->pos, &len); +- if (rv != APR_SUCCESS) { +- return rv; +- } +- ctx->pos += len; +- ctx->linesize += len; +- *(ctx->pos) = '\0'; +- /* +- * Check if we really got a full line. If yes the +- * last char in the just read buffer must be LF. +- * If not advance the buffer and return APR_EAGAIN. +- * We do not start processing until we have the +- * full line. +- */ +- if (ctx->pos[-1] != APR_ASCII_LF) { +- /* Check if the remaining data in the brigade has the LF */ +- return get_remaining_chunk_line(ctx, b, linelimit); ++ ctx->chunkbits -= 4; ++ if (ctx->chunkbits < 0) { ++ /* overflow */ ++ return APR_ENOSPC; ++ } ++ ++ if (c >= '0' && c <= '9') { ++ xvalue = c - '0'; ++ } ++ else if (c >= 'A' && c <= 'F') { ++ xvalue = c - 'A' + 0xa; ++ } ++ else if (c >= 'a' && c <= 'f') { ++ xvalue = c - 'a' + 0xa; ++ } ++ else { ++ /* bogus character */ ++ return APR_EINVAL; ++ } ++ ++ ctx->remaining = (ctx->remaining << 4) | xvalue; ++ if (ctx->remaining < 0) { ++ /* overflow */ ++ return APR_ENOSPC; ++ } + } +- /* Line is complete. So reset ctx->pos for next round. */ +- ctx->pos = ctx->chunk_ln; +- return APR_SUCCESS; ++ else { ++ /* Should not happen */ ++ return APR_EGENERAL; ++ } ++ ++ i++; ++ } ++ ++ /* sanity check */ ++ ctx->chunk_used += len; ++ if (ctx->chunk_used < 0 || ctx->chunk_used > linelimit) { ++ return APR_ENOSPC; + } +- return get_remaining_chunk_line(ctx, b, linelimit); +-} + ++ return APR_SUCCESS; ++} + + static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f, + apr_bucket_brigade *b, int merge) +@@ -218,7 +267,6 @@ + r->status = HTTP_OK; + r->headers_in = r->trailers_in; + apr_table_clear(r->headers_in); +- ctx->state = BODY_NONE; + ap_get_mime_headers(r); + + if(r->status == HTTP_OK) { +@@ -262,9 +310,9 @@ + apr_bucket *e; + http_ctx_t *ctx = f->ctx; + apr_status_t rv; +- apr_off_t totalread; + int http_error = HTTP_REQUEST_ENTITY_TOO_LARGE; + apr_bucket_brigade *bb; ++ int again; + + conf = (core_server_config *) + ap_get_module_config(f->r->server->module_config, &core_module); +@@ -278,7 +326,6 @@ + const char *tenc, *lenp; + f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx)); + ctx->state = BODY_NONE; +- ctx->pos = ctx->chunk_ln; + ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); + bb = ctx->bb; + +@@ -308,7 +355,7 @@ + */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, + "Unknown Transfer-Encoding: %s", tenc); +- return bail_out_on_error(ctx, f, HTTP_NOT_IMPLEMENTED); ++ return bail_out_on_error(ctx, f, HTTP_BAD_REQUEST); + } + else { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, f->r, +@@ -332,7 +379,7 @@ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, + "Invalid Content-Length"); + +- return bail_out_on_error(ctx, f, HTTP_REQUEST_ENTITY_TOO_LARGE); ++ return bail_out_on_error(ctx, f, HTTP_BAD_REQUEST); + } + + /* If we have a limit in effect and we know the C-L ahead of +@@ -374,7 +421,8 @@ + if (!ap_is_HTTP_SUCCESS(f->r->status)) { + ctx->state = BODY_NONE; + ctx->eos_sent = 1; +- } else { ++ } ++ else { + char *tmp; + int len; + +@@ -396,276 +444,199 @@ + ap_pass_brigade(f->c->output_filters, bb); + } + } ++ } + +- /* We can't read the chunk until after sending 100 if required. */ +- if (ctx->state == BODY_CHUNK) { +- apr_brigade_cleanup(bb); ++ /* sanity check in case we're read twice */ ++ if (ctx->eos_sent) { ++ e = apr_bucket_eos_create(f->c->bucket_alloc); ++ APR_BRIGADE_INSERT_TAIL(b, e); ++ return APR_SUCCESS; ++ } ++ ++ do { ++ apr_brigade_cleanup(b); ++ again = 0; /* until further notice */ ++ ++ /* read and handle the brigade */ ++ switch (ctx->state) { ++ case BODY_CHUNK: ++ case BODY_CHUNK_PART: ++ case BODY_CHUNK_EXT: ++ case BODY_CHUNK_CR: ++ case BODY_CHUNK_LF: ++ case BODY_CHUNK_END: ++ case BODY_CHUNK_END_LF: { + +- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, +- block, 0); ++ rv = ap_get_brigade(f->next, b, AP_MODE_GETLINE, block, 0); + + /* for timeout */ +- if (block == APR_NONBLOCK_READ && +- ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) || +- (APR_STATUS_IS_EAGAIN(rv)) )) { +- ctx->state = BODY_CHUNK_PART; ++ if (block == APR_NONBLOCK_READ ++ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b)) ++ || (APR_STATUS_IS_EAGAIN(rv)))) { + return APR_EAGAIN; + } + +- if (rv == APR_SUCCESS) { +- rv = get_chunk_line(ctx, bb, f->r->server->limit_req_line); +- if (APR_STATUS_IS_EAGAIN(rv)) { +- apr_brigade_cleanup(bb); +- ctx->state = BODY_CHUNK_PART; +- return rv; +- } +- if (rv == APR_SUCCESS) { +- ctx->remaining = get_chunk_size(ctx->chunk_ln); +- if (ctx->remaining == INVALID_CHAR) { +- rv = APR_EGENERAL; +- http_error = HTTP_SERVICE_UNAVAILABLE; +- } +- } ++ if (rv == APR_EOF) { ++ return APR_INCOMPLETE; + } +- apr_brigade_cleanup(bb); + +- /* Detect chunksize error (such as overflow) */ +- if (rv != APR_SUCCESS || ctx->remaining < 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "Error reading first chunk %s ", +- (ctx->remaining < 0) ? "(overflow)" : ""); +- ctx->remaining = 0; /* Reset it in case we have to +- * come back here later */ +- if (APR_STATUS_IS_TIMEUP(rv)) { +- http_error = HTTP_REQUEST_TIME_OUT; +- } +- return bail_out_on_error(ctx, f, http_error); ++ if (rv != APR_SUCCESS) { ++ return rv; + } + +- if (!ctx->remaining) { +- return read_chunked_trailers(ctx, f, b, +- conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE); +- } +- } +- } +- else { +- bb = ctx->bb; +- } ++ e = APR_BRIGADE_FIRST(b); ++ while (e != APR_BRIGADE_SENTINEL(b)) { ++ const char *buffer; ++ apr_size_t len; + +- if (ctx->eos_sent) { +- e = apr_bucket_eos_create(f->c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(b, e); +- return APR_SUCCESS; +- } ++ if (!APR_BUCKET_IS_METADATA(e)) { ++ int parsing = 0; + +- if (!ctx->remaining) { +- switch (ctx->state) { +- case BODY_NONE: +- break; +- case BODY_LENGTH: +- e = apr_bucket_eos_create(f->c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(b, e); +- ctx->eos_sent = 1; +- return APR_SUCCESS; +- case BODY_CHUNK: +- case BODY_CHUNK_PART: +- { +- apr_brigade_cleanup(bb); ++ rv = apr_bucket_read(e, &buffer, &len, APR_BLOCK_READ); + +- /* We need to read the CRLF after the chunk. */ +- if (ctx->state == BODY_CHUNK) { +- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, +- block, 0); +- if (block == APR_NONBLOCK_READ && +- ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) || +- (APR_STATUS_IS_EAGAIN(rv)) )) { +- return APR_EAGAIN; ++ if (rv == APR_SUCCESS) { ++ parsing = 1; ++ rv = parse_chunk_size(ctx, buffer, len, ++ f->r->server->limit_req_fieldsize); + } +- /* If we get an error, then leave */ + if (rv != APR_SUCCESS) { +- return rv; +- } +- /* +- * We really don't care whats on this line. If it is RFC +- * compliant it should be only \r\n. If there is more +- * before we just ignore it as long as we do not get over +- * the limit for request lines. +- */ +- rv = get_remaining_chunk_line(ctx, bb, +- f->r->server->limit_req_line); +- apr_brigade_cleanup(bb); +- if (APR_STATUS_IS_EAGAIN(rv)) { +- return rv; +- } +- } else { +- rv = APR_SUCCESS; +- } +- +- if (rv == APR_SUCCESS) { +- /* Read the real chunk line. */ +- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, +- block, 0); +- /* Test timeout */ +- if (block == APR_NONBLOCK_READ && +- ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) || +- (APR_STATUS_IS_EAGAIN(rv)) )) { +- ctx->state = BODY_CHUNK_PART; +- return APR_EAGAIN; +- } +- ctx->state = BODY_CHUNK; +- if (rv == APR_SUCCESS) { +- rv = get_chunk_line(ctx, bb, f->r->server->limit_req_line); +- if (APR_STATUS_IS_EAGAIN(rv)) { +- ctx->state = BODY_CHUNK_PART; +- apr_brigade_cleanup(bb); +- return rv; +- } +- if (rv == APR_SUCCESS) { +- ctx->remaining = get_chunk_size(ctx->chunk_ln); +- if (ctx->remaining == INVALID_CHAR) { +- rv = APR_EGENERAL; +- http_error = HTTP_SERVICE_UNAVAILABLE; ++ ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r, ++ "Error reading/parsing chunk %s ", ++ (APR_ENOSPC == rv) ? "(overflow)" : ""); ++ if (parsing) { ++ if (rv != APR_ENOSPC) { ++ http_error = HTTP_BAD_REQUEST; + } ++ return bail_out_on_error(ctx, f, http_error); + } ++ return rv; + } +- apr_brigade_cleanup(bb); + } + +- /* Detect chunksize error (such as overflow) */ +- if (rv != APR_SUCCESS || ctx->remaining < 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "Error reading chunk %s ", +- (ctx->remaining < 0) ? "(overflow)" : ""); +- ctx->remaining = 0; /* Reset it in case we have to +- * come back here later */ +- if (APR_STATUS_IS_TIMEUP(rv)) { +- http_error = HTTP_REQUEST_TIME_OUT; +- } +- return bail_out_on_error(ctx, f, http_error); +- } ++ apr_bucket_delete(e); ++ e = APR_BRIGADE_FIRST(b); ++ } ++ again = 1; /* come around again */ + +- if (!ctx->remaining) { +- return read_chunked_trailers(ctx, f, b, ++ if (ctx->state == BODY_CHUNK_TRAILER) { ++ /* Treat UNSET as DISABLE - trailers aren't merged by default */ ++ return read_chunked_trailers(ctx, f, b, + conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE); +- } + } +- break; +- } +- } + +- /* Ensure that the caller can not go over our boundary point. */ +- if (ctx->state == BODY_LENGTH || ctx->state == BODY_CHUNK) { +- if (ctx->remaining < readbytes) { +- readbytes = ctx->remaining; ++ break; + } +- AP_DEBUG_ASSERT(readbytes > 0); +- } ++ case BODY_NONE: ++ case BODY_LENGTH: ++ case BODY_CHUNK_DATA: { + +- rv = ap_get_brigade(f->next, b, mode, block, readbytes); ++ /* Ensure that the caller can not go over our boundary point. */ ++ if (ctx->state != BODY_NONE && ctx->remaining < readbytes) { ++ readbytes = ctx->remaining; ++ } ++ if (readbytes > 0) { ++ apr_off_t totalread; ++ ++ rv = ap_get_brigade(f->next, b, mode, block, readbytes); ++ ++ /* for timeout */ ++ if (block == APR_NONBLOCK_READ ++ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b)) ++ || (APR_STATUS_IS_EAGAIN(rv)))) { ++ return APR_EAGAIN; ++ } + +- if (rv != APR_SUCCESS) { +- return rv; +- } ++ if (rv == APR_EOF && ctx->state != BODY_NONE ++ && ctx->remaining > 0) { ++ return APR_INCOMPLETE; ++ } + +- /* How many bytes did we just read? */ +- apr_brigade_length(b, 0, &totalread); ++ if (rv != APR_SUCCESS) { ++ return rv; ++ } + +- /* If this happens, we have a bucket of unknown length. Die because +- * it means our assumptions have changed. */ +- AP_DEBUG_ASSERT(totalread >= 0); +- +- if (ctx->state != BODY_NONE) { +- ctx->remaining -= totalread; +- if (ctx->remaining > 0) { +- e = APR_BRIGADE_LAST(b); +- if (APR_BUCKET_IS_EOS(e)) +- return APR_EOF; +- } +- } ++ /* How many bytes did we just read? */ ++ apr_brigade_length(b, 0, &totalread); + +- /* If we have no more bytes remaining on a C-L request, +- * save the callter a roundtrip to discover EOS. +- */ +- if (ctx->state == BODY_LENGTH && ctx->remaining == 0) { +- e = apr_bucket_eos_create(f->c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(b, e); +- } ++ /* If this happens, we have a bucket of unknown length. Die because ++ * it means our assumptions have changed. */ ++ AP_DEBUG_ASSERT(totalread >= 0); ++ ++ if (ctx->state != BODY_NONE) { ++ ctx->remaining -= totalread; ++ if (ctx->remaining > 0) { ++ e = APR_BRIGADE_LAST(b); ++ if (APR_BUCKET_IS_EOS(e)) { ++ apr_bucket_delete(e); ++ return APR_INCOMPLETE; ++ } ++ } ++ else if (ctx->state == BODY_CHUNK_DATA) { ++ /* next chunk please */ ++ ctx->state = BODY_CHUNK_END; ++ ctx->chunk_used = 0; ++ } ++ } + +- /* We have a limit in effect. */ +- if (ctx->limit) { +- /* FIXME: Note that we might get slightly confused on chunked inputs +- * as we'd need to compensate for the chunk lengths which may not +- * really count. This seems to be up for interpretation. */ +- ctx->limit_used += totalread; +- if (ctx->limit < ctx->limit_used) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, +- "Read content-length of %" APR_OFF_T_FMT +- " is larger than the configured limit" +- " of %" APR_OFF_T_FMT, ctx->limit_used, ctx->limit); +- apr_brigade_cleanup(bb); +- e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL, +- f->r->pool, +- f->c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(bb, e); +- e = apr_bucket_eos_create(f->c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(bb, e); +- ctx->eos_sent = 1; +- return ap_pass_brigade(f->r->output_filters, bb); +- } +- } ++ /* We have a limit in effect. */ ++ if (ctx->limit) { ++ /* FIXME: Note that we might get slightly confused on ++ * chunked inputs as we'd need to compensate for the chunk ++ * lengths which may not really count. This seems to be up ++ * for interpretation. ++ */ ++ ctx->limit_used += totalread; ++ if (ctx->limit < ctx->limit_used) { ++ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, ++ "Read content length of " ++ "%" APR_OFF_T_FMT " is larger than the " ++ "configured limit of %" APR_OFF_T_FMT, ++ ctx->limit_used, ctx->limit); ++ return bail_out_on_error(ctx, f, ++ HTTP_REQUEST_ENTITY_TOO_LARGE); ++ } ++ } ++ } + +- return APR_SUCCESS; +-} ++ /* If we have no more bytes remaining on a C-L request, ++ * save the caller a round trip to discover EOS. ++ */ ++ if (ctx->state == BODY_LENGTH && ctx->remaining == 0) { ++ e = apr_bucket_eos_create(f->c->bucket_alloc); ++ APR_BRIGADE_INSERT_TAIL(b, e); ++ ctx->eos_sent = 1; ++ } + +-/** +- * Parse a chunk extension, detect overflow. +- * There are two error cases: +- * 1) If the conversion would require too many bits, a -1 is returned. +- * 2) If the conversion used the correct number of bits, but an overflow +- * caused only the sign bit to flip, then that negative number is +- * returned. +- * In general, any negative number can be considered an overflow error. +- */ +-static long get_chunk_size(char *b) +-{ +- long chunksize = 0; +- size_t chunkbits = sizeof(long) * 8; ++ break; ++ } ++ case BODY_CHUNK_TRAILER: { + +- ap_xlate_proto_from_ascii(b, strlen(b)); ++ rv = ap_get_brigade(f->next, b, mode, block, readbytes); + +- if (!apr_isxdigit(*b)) { +- /* +- * Detect invalid character at beginning. This also works for empty +- * chunk size lines. +- */ +- return INVALID_CHAR; +- } +- /* Skip leading zeros */ +- while (*b == '0') { +- ++b; +- } ++ /* for timeout */ ++ if (block == APR_NONBLOCK_READ ++ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b)) ++ || (APR_STATUS_IS_EAGAIN(rv)))) { ++ return APR_EAGAIN; ++ } + +- while (apr_isxdigit(*b) && (chunkbits > 0)) { +- int xvalue = 0; ++ if (rv != APR_SUCCESS) { ++ return rv; ++ } + +- if (*b >= '0' && *b <= '9') { +- xvalue = *b - '0'; ++ break; + } +- else if (*b >= 'A' && *b <= 'F') { +- xvalue = *b - 'A' + 0xa; ++ default: { ++ /* Should not happen */ ++ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, ++ "Unexpected body state (%i)", (int)ctx->state); ++ return APR_EGENERAL; + } +- else if (*b >= 'a' && *b <= 'f') { +- xvalue = *b - 'a' + 0xa; + } + +- chunksize = (chunksize << 4) | xvalue; +- chunkbits -= 4; +- ++b; +- } +- if (apr_isxdigit(*b) && (chunkbits <= 0)) { +- /* overflow */ +- return -1; +- } ++ } while (again); + +- return chunksize; ++ return APR_SUCCESS; + } + + typedef struct header_struct {
View file
debian.tar.gz/patches/DH-SSLCertificateFile.patch
Added
@@ -0,0 +1,1373 @@ +# DP: backport support for adding DH parameters to the SSLCertificateFile + +--- a/docs/manual/mod/mod_ssl.html.en ++++ b/docs/manual/mod/mod_ssl.html.en +@@ -388,12 +388,47 @@ SSLCertificateChainFile /usr/local/apach + <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_ssl</td></tr> + </table> + <p> +-This directive points to the PEM-encoded Certificate file for the server and +-optionally also to the corresponding RSA or DSA Private Key file for it +-(contained in the same file). If the contained Private Key is encrypted the +-Pass Phrase dialog is forced at startup time. This directive can be used up to +-two times (referencing different filenames) when both a RSA and a DSA based +-server certificate is used in parallel.</p> ++This directive points to a file with certificate data in PEM format. ++At a minimum, the file must include an end-entity (leaf) certificate. ++The directive can be used up to three times (referencing different filenames) ++when an RSA, a DSA, and an ECC based server certificate is used in parallel. ++</p> ++ ++<p> ++Custom DH parameters and an EC curve name for ephemeral keys, ++can be added to end of the first file configured using ++<code class="directive"><a href="#sslcertificatefile">SSLCertificateFile</a></code>. ++Such parameters can be generated using the commands ++<code>openssl dhparam</code> and <code>openssl ecparam</code>. ++The parameters can be added as-is to the end of the first ++certificate file. Only the first file can be used for custom ++parameters, as they are applied independently of the authentication ++algorithm type. ++</p> ++ ++<p> ++Finally the the end-entity certificate's private key can also be ++added to the certificate file instead of using a separate ++<code class="directive"><a href="#sslcertificatekeyfile">SSLCertificateKeyFile</a></code> ++directive. This practice is highly discouraged. If the private ++key is encrypted, the pass phrase dialog is forced at startup time. ++</p> ++ ++<div class="note"> ++<h3>DH parameter interoperability with primes > 1024 bit</h3> ++<p> ++Beginning with version 2.2.30, mod_ssl makes use of ++standardized DH parameters with prime lengths of 2048, 3072, 4096, 6144 and ++8192 bits (from <a href="http://www.ietf.org/rfc/rfc3526.txt">RFC 3526</a>), ++and hands them out to clients based on the length of the certificate's RSA/DSA ++key. ++With Java-based clients in particular (Java 7 or earlier), this may lead ++to handshake failures - see this ++<a href="../ssl/ssl_faq.html#javadh">FAQ answer</a> for working around ++such issues. ++</p> ++</div> ++ + <div class="example"><h3>Example</h3><p><code> + SSLCertificateFile /usr/local/apache2/conf/ssl.crt/server.crt + </code></p></div> +@@ -409,18 +444,22 @@ SSLCertificateFile /usr/local/apache2/co + <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_ssl</td></tr> + </table> + <p> +-This directive points to the PEM-encoded Private Key file for the +-server. If the Private Key is not combined with the Certificate in the +-<code class="directive">SSLCertificateFile</code>, use this additional directive to +-point to the file with the stand-alone Private Key. When +-<code class="directive">SSLCertificateFile</code> is used and the file +-contains both the Certificate and the Private Key this directive need +-not be used. But we strongly discourage this practice. Instead we +-recommend you to separate the Certificate and the Private Key. If the +-contained Private Key is encrypted, the Pass Phrase dialog is forced +-at startup time. This directive can be used up to two times +-(referencing different filenames) when both a RSA and a DSA based +-private key is used in parallel.</p> ++This directive points to the PEM-encoded private key file for the ++server. If the contained private key is encrypted, the pass phrase ++dialog is forced at startup time.</p> ++ ++<p> ++The directive can be used up to three times (referencing different filenames) ++when an RSA, a DSA, and an ECC based private key is used in parallel. For each ++<code class="directive"><a href="#sslcertificatekeyfile">SSLCertificateKeyFile</a></code> ++directive, there must be a matching <code class="directive">SSLCertificateFile</code> ++directive.</p> ++ ++<p> ++The private key may also be combined with the certificate in the file given by ++<code class="directive"><a href="#sslcertificatefile">SSLCertificateFile</a></code>, but this practice ++is highly discouraged.</p> ++ + <div class="example"><h3>Example</h3><p><code> + SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/server.key + </code></p></div> +@@ -1886,6 +1925,6 @@ SSLVerifyDepth 10 + <div class="bottomlang"> + <p><span>Available Languages: </span><a href="../en/mod/mod_ssl.html" title="English"> en </a></p> + </div><div id="footer"> +-<p class="apache">Copyright 2012 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p> ++<p class="apache">Copyright 2015 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p> + <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div> + </body></html> +\ No newline at end of file +--- a/docs/manual/ssl/ssl_faq.html.en ++++ b/docs/manual/ssl/ssl_faq.html.en +@@ -675,6 +675,7 @@ HTTPS to an Apache+mod_ssl server with M + <li><a href="#nn">Why do I get I/O errors, or the message "Netscape has + encountered bad data from the server", when connecting via + HTTPS to an Apache+mod_ssl server with Netscape Navigator?</a></li> ++<li><a href="#javadh">Why do I get handshake failures with Java-based clients when using a certificate with more than 1024 bits?</a></li> + </ul> + + <h3><a name="random" id="random">Why do I get lots of random SSL protocol +@@ -907,6 +908,40 @@ HTTPS to an Apache+mod_ssl server with N + implementation is correct, so when you encounter I/O errors with Netscape + Navigator it is usually caused by the configured certificates.</p> + ++ ++<h3><a name="javadh" id="javadh">Why do I get handshake failures with Java-based clients when using a certificate with more than 1024 bits?</a></h3> ++ <p>Beginning with version 2.2.30, ++ <code class="module"><a href="../mod/mod_ssl.html">mod_ssl</a></code> will use DH parameters which include primes ++ with lengths of more than 1024 bits. Java 7 and earlier limit their ++ support for DH prime sizes to a maximum of 1024 bits, however.</p> ++ ++ <p>If your Java-based client aborts with exceptions such as ++ <code>java.lang.RuntimeException: Could not generate DH keypair</code> and ++ <code>java.security.InvalidAlgorithmParameterException: Prime size must be ++ multiple of 64, and can only range from 512 to 1024 (inclusive)</code>, ++ and httpd logs <code>tlsv1 alert internal error (SSL alert number 80)</code> ++ (at <code class="directive"><a href="../mod/core.html#loglevel">LogLevel</a></code> <code>info</code> ++ or higher), you can either rearrange mod_ssl's cipher list with ++ <code class="directive"><a href="../mod/mod_ssl.html#sslciphersuite">SSLCipherSuite</a></code> ++ (possibly in conjunction with <code class="directive"><a href="../mod/mod_ssl.html#sslhonorcipherorder">SSLHonorCipherOrder</a></code>), ++ or you can use custom DH parameters with a 1024-bit prime, which ++ will always have precedence over any of the built-in DH parameters.</p> ++ ++ <p>To generate custom DH parameters, use the <code>openssl dhparam 1024</code> ++ command. Alternatively, you can use the following standard 1024-bit DH ++ parameters from <a href="http://www.ietf.org/rfc/rfc2409.txt">RFC 2409</a>, ++ section 6.2:</p> ++ <div class="example"><pre>-----BEGIN DH PARAMETERS----- ++MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR ++Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL ++/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC ++-----END DH PARAMETERS-----</pre></div> ++ <p>Add the custom parameters including the "BEGIN DH PARAMETERS" and ++ "END DH PARAMETERS" lines to the end of the first certificate file ++ you have configured using the ++ <code class="directive"><a href="../mod/mod_ssl.html#sslcertificatefile">SSLCertificateFile</a></code> directive.</p> ++ ++ + </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> + <div class="section"> + <h2><a name="support" id="support">mod_ssl Support</a></h2> +@@ -1054,6 +1089,6 @@ the reason for my core dump?</a></h3> + <div class="bottomlang"> + <p><span>Available Languages: </span><a href="../en/ssl/ssl_faq.html" title="English"> en </a></p> + </div><div id="footer"> +-<p class="apache">Copyright 2012 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p> ++<p class="apache">Copyright 2015 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p> + <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div> + </body></html> +\ No newline at end of file +--- a/modules/ssl/mod_ssl.c ++++ b/modules/ssl/mod_ssl.c +@@ -422,15 +422,6 @@ int ssl_init_ssl_connection(conn_rec *c) + + sslconn->ssl = ssl; + +- /* +- * Configure callbacks for SSL connection +- */ +- SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA); +- SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH); +-#ifndef OPENSSL_NO_EC +- SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH); +-#endif +- + SSL_set_verify_result(ssl, X509_V_OK); + + ssl_io_filter_init(c, ssl); +--- a/modules/ssl/ssl_engine_config.c ++++ b/modules/ssl/ssl_engine_config.c +@@ -76,8 +76,6 @@ SSLModConfigRec *ssl_config_global_creat + mc->szCryptoDevice = NULL; + #endif + +- memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys)); +- + apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY, + apr_pool_cleanup_null, + pool); +--- a/modules/ssl/ssl_engine_dh.c ++++ b/modules/ssl/ssl_engine_dh.c +@@ -41,21 +41,9 @@ + ** 0e:3e:30:06:80:a3:03:0c:6e:4c:37:57:d0:8f:70: + ** e6:aa:87:10:33 + ** generator: 2 (0x2) +-** Diffie-Hellman-Parameters: (1024 bit) +-** prime: +-** 00:d6:7d:e4:40:cb:bb:dc:19:36:d6:93:d3:4a:fd: +-** 0a:d5:0c:84:d2:39:a4:5f:52:0b:b8:81:74:cb:98: +-** bc:e9:51:84:9f:91:2e:63:9c:72:fb:13:b4:b4:d7: +-** 17:7e:16:d5:5a:c1:79:ba:42:0b:2a:29:fe:32:4a: +-** 46:7a:63:5e:81:ff:59:01:37:7b:ed:dc:fd:33:16: +-** 8a:46:1a:ad:3b:72:da:e8:86:00:78:04:5b:07:a7: +-** db:ca:78:74:08:7d:15:10:ea:9f:cc:9d:dd:33:05: +-** 07:dd:62:db:88:ae:aa:74:7d:e0:f4:d6:e2:bd:68: +-** b0:e7:39:3e:0f:24:21:8e:b3 +-** generator: 2 (0x2) + */ + +-static unsigned char dh512_p[] = { ++static const unsigned char dh512_p[] = { + 0x9F, 0xDB, 0x8B, 0x8A, 0x00, 0x45, 0x44, 0xF0, 0x04, 0x5F, 0x17, 0x37, + 0xD0, 0xBA, 0x2E, 0x0B, 0x27, 0x4C, 0xDF, 0x1A, 0x9F, 0x58, 0x82, 0x18, + 0xFB, 0x43, 0x53, 0x16, 0xA1, 0x6E, 0x37, 0x41, 0x71, 0xFD, 0x19, 0xD8, +@@ -63,7 +51,7 @@ static unsigned char dh512_p[] = { + 0x80, 0xA3, 0x03, 0x0C, 0x6E, 0x4C, 0x37, 0x57, 0xD0, 0x8F, 0x70, 0xE6, + 0xAA, 0x87, 0x10, 0x33, + }; +-static unsigned char dh512_g[] = { ++static const unsigned char dh512_g[] = { + 0x02, + }; + +@@ -73,7 +61,23 @@ static DH *get_dh512(void) + dh512_g, sizeof(dh512_g)); + } + +-static unsigned char dh1024_p[] = { ++#if 0 /* Legacy (replaced by RFC2409's below) */ ++/* ++** Diffie-Hellman-Parameters: (1024 bit) ++** prime: ++** 00:d6:7d:e4:40:cb:bb:dc:19:36:d6:93:d3:4a:fd: ++** 0a:d5:0c:84:d2:39:a4:5f:52:0b:b8:81:74:cb:98: ++** bc:e9:51:84:9f:91:2e:63:9c:72:fb:13:b4:b4:d7: ++** 17:7e:16:d5:5a:c1:79:ba:42:0b:2a:29:fe:32:4a: ++** 46:7a:63:5e:81:ff:59:01:37:7b:ed:dc:fd:33:16: ++** 8a:46:1a:ad:3b:72:da:e8:86:00:78:04:5b:07:a7: ++** db:ca:78:74:08:7d:15:10:ea:9f:cc:9d:dd:33:05: ++** 07:dd:62:db:88:ae:aa:74:7d:e0:f4:d6:e2:bd:68: ++** b0:e7:39:3e:0f:24:21:8e:b3 ++** generator: 2 (0x2) ++*/ ++ ++static const unsigned char dh1024_p[] = { + 0xD6, 0x7D, 0xE4, 0x40, 0xCB, 0xBB, 0xDC, 0x19, 0x36, 0xD6, 0x93, 0xD3, + 0x4A, 0xFD, 0x0A, 0xD5, 0x0C, 0x84, 0xD2, 0x39, 0xA4, 0x5F, 0x52, 0x0B, + 0xB8, 0x81, 0x74, 0xCB, 0x98, 0xBC, 0xE9, 0x51, 0x84, 0x9F, 0x91, 0x2E, +@@ -86,7 +90,7 @@ static unsigned char dh1024_p[] = { + 0x88, 0xAE, 0xAA, 0x74, 0x7D, 0xE0, 0xF4, 0xD6, 0xE2, 0xBD, 0x68, 0xB0, + 0xE7, 0x39, 0x3E, 0x0F, 0x24, 0x21, 0x8E, 0xB3, + }; +-static unsigned char dh1024_g[] = { ++static const unsigned char dh1024_g[] = { + 0x02, + }; + +@@ -95,23 +99,581 @@ static DH *get_dh1024(void) + return modssl_dh_configure(dh1024_p, sizeof(dh1024_p), + dh1024_g, sizeof(dh1024_g)); + } ++#endif + + /* ----END GENERATED SECTION---------- */ + ++/* ++ * "Second Oakley Default Group" from RFC2409, section 6.2. ++ * ++ * The prime is: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }. ++ * ++ * RFC2409 specifies a generator of 2. ++ */ ++static const unsigned char dh1024_p[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, ++ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, ++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, ++ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, ++ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, ++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, ++ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, ++ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, ++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, ++ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, ++ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, ++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, ++ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, ++ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++}; ++static const unsigned char dh1024_g[] = { ++ 0x02, ++}; ++ ++static DH *get_dh1024(void) ++{ ++ return modssl_dh_configure(dh1024_p, sizeof(dh1024_p), ++ dh1024_g, sizeof(dh1024_g)); ++} ++ ++/* ++ * "2048-bit MODP Group" from RFC3526, Section 3. ++ * ++ * The prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } ++ * ++ * RFC3526 specifies a generator of 2. ++ */ ++static const unsigned char dh2048_p[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, ++ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, ++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, ++ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, ++ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, ++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, ++ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, ++ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, ++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, ++ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, ++ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, ++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, ++ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, ++ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, ++ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, ++ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, ++ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, ++ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, ++ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, ++ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, ++ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, ++ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, ++ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, ++ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, ++ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, ++ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, ++ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, ++ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, ++ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, ++ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++}; ++static const unsigned char dh2048_g[] = { ++ 0x02, ++}; ++ ++static DH *get_dh2048(void) ++{ ++ return modssl_dh_configure(dh2048_p, sizeof(dh2048_p), ++ dh2048_g, sizeof(dh2048_g)); ++} ++ ++/* ++ * "3072-bit MODP Group" from RFC3526, Section 4. ++ * ++ * The prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } ++ * ++ * RFC3526 specifies a generator of 2. ++ */ ++static const unsigned char dh3072_p[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, ++ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, ++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, ++ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, ++ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, ++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, ++ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, ++ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, ++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, ++ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, ++ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, ++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, ++ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, ++ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, ++ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, ++ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, ++ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, ++ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, ++ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, ++ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, ++ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, ++ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, ++ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, ++ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, ++ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, ++ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, ++ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, ++ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, ++ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, ++ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, ++ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, ++ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, ++ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, ++ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, ++ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, ++ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, ++ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, ++ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, ++ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, ++ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, ++ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, ++ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, ++ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, ++ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, ++ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, ++ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++}; ++static const unsigned char dh3072_g[] = { ++ 0x02, ++}; ++ ++static DH *get_dh3072(void) ++{ ++ return modssl_dh_configure(dh3072_p, sizeof(dh3072_p), ++ dh3072_g, sizeof(dh3072_g)); ++} ++ ++/* ++ * "4096-bit MODP Group" from RFC3526, Section 5. ++ * ++ * The prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } ++ * ++ * RFC3526 specifies a generator of 2. ++ */ ++static const unsigned char dh4096_p[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, ++ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, ++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, ++ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, ++ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, ++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, ++ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, ++ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, ++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, ++ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, ++ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, ++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, ++ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, ++ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, ++ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, ++ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, ++ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, ++ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, ++ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, ++ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, ++ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, ++ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, ++ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, ++ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, ++ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, ++ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, ++ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, ++ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, ++ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, ++ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, ++ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, ++ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, ++ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, ++ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, ++ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, ++ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, ++ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, ++ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, ++ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, ++ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, ++ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, ++ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, ++ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, ++ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, ++ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, ++ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, ++ 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, ++ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, ++ 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, ++ 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, ++ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, ++ 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, ++ 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, ++ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, ++ 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, ++ 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, ++ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, ++ 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, ++ 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, ++ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, ++ 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, ++ 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++}; ++static const unsigned char dh4096_g[] = { ++ 0x02, ++}; ++ ++static DH *get_dh4096(void) ++{ ++ return modssl_dh_configure(dh4096_p, sizeof(dh4096_p), ++ dh4096_g, sizeof(dh4096_g)); ++} ++ ++/* ++ * "6144-bit MODP Group" from RFC3526, Section 6. ++ * ++ * The prime is: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } ++ * ++ * RFC3526 specifies a generator of 2. ++ */ ++static const unsigned char dh6144_p[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, ++ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, ++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, ++ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, ++ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, ++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, ++ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, ++ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, ++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, ++ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, ++ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, ++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, ++ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, ++ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, ++ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, ++ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, ++ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, ++ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, ++ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, ++ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, ++ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, ++ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, ++ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, ++ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, ++ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, ++ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, ++ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, ++ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, ++ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, ++ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, ++ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, ++ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, ++ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, ++ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, ++ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, ++ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, ++ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, ++ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, ++ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, ++ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, ++ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, ++ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, ++ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, ++ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, ++ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, ++ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, ++ 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, ++ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, ++ 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, ++ 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, ++ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, ++ 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, ++ 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, ++ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, ++ 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, ++ 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, ++ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, ++ 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, ++ 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, ++ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, ++ 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, ++ 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, ++ 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, ++ 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, ++ 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, ++ 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, ++ 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, ++ 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, ++ 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, ++ 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, ++ 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, ++ 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, ++ 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, ++ 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, ++ 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, ++ 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, ++ 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, ++ 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, ++ 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, ++ 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, ++ 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, ++ 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, ++ 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, ++ 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, ++ 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, ++ 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, ++ 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, ++ 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, ++ 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, ++ 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, ++ 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, ++ 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, ++ 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, ++ 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++}; ++static const unsigned char dh6144_g[] = { ++ 0x02, ++}; ++ ++static DH *get_dh6144(void) ++{ ++ return modssl_dh_configure(dh6144_p, sizeof(dh6144_p), ++ dh6144_g, sizeof(dh6144_g)); ++} ++ ++/* ++ * "8192-bit MODP Group" from RFC3526, Section 7. ++ * ++ * The prime is: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } ++ * ++ * RFC3526 specifies a generator of 2. ++ */ ++static const unsigned char dh8192_p[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, ++ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, ++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, ++ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, ++ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, ++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, ++ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, ++ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, ++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, ++ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, ++ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, ++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, ++ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, ++ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, ++ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, ++ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, ++ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, ++ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, ++ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, ++ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, ++ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, ++ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, ++ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, ++ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, ++ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, ++ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, ++ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, ++ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, ++ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, ++ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, ++ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, ++ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, ++ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, ++ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, ++ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, ++ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, ++ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, ++ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, ++ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, ++ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, ++ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, ++ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, ++ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, ++ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, ++ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, ++ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, ++ 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, ++ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, ++ 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, ++ 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, ++ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, ++ 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, ++ 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, ++ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, ++ 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, ++ 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, ++ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, ++ 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, ++ 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, ++ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, ++ 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, ++ 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, ++ 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, ++ 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, ++ 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, ++ 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, ++ 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, ++ 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, ++ 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, ++ 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, ++ 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, ++ 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, ++ 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, ++ 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, ++ 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, ++ 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, ++ 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, ++ 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, ++ 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, ++ 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, ++ 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, ++ 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, ++ 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, ++ 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, ++ 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, ++ 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, ++ 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, ++ 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, ++ 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, ++ 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, ++ 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, ++ 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, ++ 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, ++ 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, ++ 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, ++ 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, ++ 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, ++ 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, ++ 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, ++ 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, ++ 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, ++ 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, ++ 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, ++ 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, ++ 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, ++ 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, ++ 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, ++ 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, ++ 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, ++ 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, ++ 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, ++ 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, ++ 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, ++ 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, ++ 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, ++ 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, ++ 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, ++ 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, ++ 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, ++ 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, ++ 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, ++ 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, ++ 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, ++ 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, ++ 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, ++ 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++}; ++static const unsigned char dh8192_g[] = { ++ 0x02, ++}; ++ ++static DH *get_dh8192(void) ++{ ++ return modssl_dh_configure(dh8192_p, sizeof(dh8192_p), ++ dh8192_g, sizeof(dh8192_g)); ++} ++ ++/* Storage and initialization for DH parameters. */ ++static struct dhparam { ++ DH *(*const make)(void); /* function to generate... */ ++ DH *dh; /* ...this, used for keys.... */ ++ const unsigned int min; /* ...of length >= this. */ ++} dhparams[] = { ++ { get_dh8192, NULL, 6145 }, ++ { get_dh6144, NULL, 4097 }, ++ { get_dh4096, NULL, 3073 }, ++ { get_dh3072, NULL, 2049 }, ++ { get_dh2048, NULL, 1025 }, ++ { get_dh1024, NULL, 513 }, ++ { get_dh512, NULL, 0 } ++}; ++ ++int ssl_dh_InitParams(server_rec *s) ++{ ++ unsigned n; ++ ++ for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++) { ++ const unsigned int bits = ++ dhparams[n].min ? (dhparams[n].min - 1) * 2 : 512; ++#ifdef HAVE_FIPS ++ if (bits < 1024 && FIPS_mode()) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "Init: Skipping generating temporary " ++ "%u bit DH parameters in FIPS mode", bits); ++ continue; ++ } ++#endif ++ dhparams[n].dh = dhparams[n].make(); ++ if (!dhparams[n].dh) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, ++ "Init: Failed to generate temporary " ++ "%u bit DH parameters", bits); ++ return !OK; ++ } ++ } ++ return OK; ++} ++ ++void ssl_dh_FreeParams(void) ++{ ++ unsigned n; ++ ++ /* DH_free() is a noop for a NULL parameter, so these are harmless ++ * in the (unexpected) case where these variables are already ++ * NULL. */ ++ for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++) { ++ DH_free(dhparams[n].dh); ++ dhparams[n].dh = NULL; ++ } ++} ++ ++/* Hand out the same DH structure though once generated as we leak ++ * memory otherwise and freeing the structure up after use would be ++ * hard to track and in fact is not needed at all as it is safe to ++ * use the same parameters over and over again security wise (in ++ * contrast to the keys itself) and code safe as the returned structure ++ * is duplicated by OpenSSL anyway. Hence no modification happens ++ * to our copy. */ + DH *ssl_dh_GetTmpParam(int nKeyLen) + { +- DH *dh; ++ unsigned n; ++ ++ for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++) ++ if (nKeyLen >= dhparams[n].min) ++ return dhparams[n].dh; + +- if (nKeyLen == 512) +- dh = get_dh512(); +- else if (nKeyLen == 1024) +- dh = get_dh1024(); +- else +- dh = get_dh1024(); +- return dh; ++ return NULL; /* impossible to reach. */ + } + +-DH *ssl_dh_GetParamFromFile(char *file) ++DH *ssl_dh_GetParamFromFile(const char *file) + { + DH *dh = NULL; + BIO *bio; +@@ -127,6 +689,20 @@ DH *ssl_dh_GetParamFromFile(char *file) + return (dh); + } + ++#ifndef OPENSSL_NO_EC ++EC_GROUP *ssl_ec_GetParamFromFile(const char *file) ++{ ++ EC_GROUP *group = NULL; ++ BIO *bio; ++ ++ if ((bio = BIO_new_file(file, "r")) == NULL) ++ return NULL; ++ group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL); ++ BIO_free(bio); ++ return (group); ++} ++#endif ++ + /* + =cut + ## +--- a/modules/ssl/ssl_engine_init.c ++++ b/modules/ssl/ssl_engine_init.c +@@ -53,160 +53,6 @@ static void ssl_add_version_components(a + + + /* +- * Handle the Temporary RSA Keys and DH Params +- */ +- +-#define MODSSL_TMP_KEY_FREE(mc, type, idx) \ +- if (mc->pTmpKeys[idx]) { \ +- type##_free((type *)mc->pTmpKeys[idx]); \ +- mc->pTmpKeys[idx] = NULL; \ +- } +- +-#define MODSSL_TMP_KEYS_FREE(mc, type) \ +- MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_512); \ +- MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_1024) +- +-static void ssl_tmp_keys_free(server_rec *s) +-{ +- SSLModConfigRec *mc = myModConfig(s); +- +- MODSSL_TMP_KEYS_FREE(mc, RSA); +- MODSSL_TMP_KEYS_FREE(mc, DH); +-#ifndef OPENSSL_NO_EC +- MODSSL_TMP_KEY_FREE(mc, EC_KEY, SSL_TMP_KEY_EC_256); +-#endif +-} +- +-static int ssl_tmp_key_init_rsa(server_rec *s, +- int bits, int idx) +-{ +- SSLModConfigRec *mc = myModConfig(s); +- +-#ifdef HAVE_FIPS +- +- if (FIPS_mode() && bits < 1024) { +- mc->pTmpKeys[idx] = NULL; +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "Init: Skipping generating temporary " +- "%d bit RSA private key in FIPS mode", bits); +- return OK; +- } +- +-#endif +- +- if (!(mc->pTmpKeys[idx] = +- RSA_generate_key(bits, RSA_F4, NULL, NULL))) +- { +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "Init: Failed to generate temporary " +- "%d bit RSA private key", bits); +- ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); +- return !OK; +- } +- +- return OK; +-} +- +-static int ssl_tmp_key_init_dh(server_rec *s, +- int bits, int idx) +-{ +- SSLModConfigRec *mc = myModConfig(s); +- +-#ifdef HAVE_FIPS +- +- if (FIPS_mode() && bits < 1024) { +- mc->pTmpKeys[idx] = NULL; +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "Init: Skipping generating temporary " +- "%d bit DH parameters in FIPS mode", bits); +- return OK; +- } +- +-#endif +- +- if (!(mc->pTmpKeys[idx] = +- ssl_dh_GetTmpParam(bits))) +- { +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "Init: Failed to generate temporary " +- "%d bit DH parameters", bits); +- return !OK; +- } +- +- return OK; +-} +- +-#ifndef OPENSSL_NO_EC +-static int ssl_tmp_key_init_ec(server_rec *s, +- int bits, int idx) +-{ +- SSLModConfigRec *mc = myModConfig(s); +- EC_KEY *ecdh = NULL; +- +- /* XXX: Are there any FIPS constraints we should enforce? */ +- +- if (bits != 256) { +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "Init: Failed to generate temporary " +- "%d bit EC parameters, only 256 bits supported", bits); +- return !OK; +- } +- +- if ((ecdh = EC_KEY_new()) == NULL || +- EC_KEY_set_group(ecdh, EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) != 1) +- { +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "Init: Failed to generate temporary " +- "%d bit EC parameters", bits); +- return !OK; +- } +- +- mc->pTmpKeys[idx] = ecdh; +- return OK; +-} +- +-#define MODSSL_TMP_KEY_INIT_EC(s, bits) \ +- ssl_tmp_key_init_ec(s, bits, SSL_TMP_KEY_EC_##bits) +- +-#endif +- +-#define MODSSL_TMP_KEY_INIT_RSA(s, bits) \ +- ssl_tmp_key_init_rsa(s, bits, SSL_TMP_KEY_RSA_##bits) +- +-#define MODSSL_TMP_KEY_INIT_DH(s, bits) \ +- ssl_tmp_key_init_dh(s, bits, SSL_TMP_KEY_DH_##bits) +- +-static int ssl_tmp_keys_init(server_rec *s) +-{ +- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, +- "Init: Generating temporary RSA private keys (512/1024 bits)"); +- +- if (MODSSL_TMP_KEY_INIT_RSA(s, 512) || +- MODSSL_TMP_KEY_INIT_RSA(s, 1024)) { +- return !OK; +- } +- +- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, +- "Init: Generating temporary DH parameters (512/1024 bits)"); +- +- if (MODSSL_TMP_KEY_INIT_DH(s, 512) || +- MODSSL_TMP_KEY_INIT_DH(s, 1024)) { +- return !OK; +- } +- +-#ifndef OPENSSL_NO_EC +- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, +- "Init: Generating temporary EC parameters (256 bits)"); +- +- if (MODSSL_TMP_KEY_INIT_EC(s, 256)) { +- return !OK; +- } +-#endif +- +- return OK; +-} +- +-/* + * Per-module initialization + */ + int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, +@@ -335,7 +181,7 @@ int ssl_init_Module(apr_pool_t *p, apr_p + */ + ssl_pphrase_Handle(base_server, ptemp); + +- if (ssl_tmp_keys_init(base_server)) { ++ if (ssl_dh_InitParams(base_server)) { + return !OK; + } + +@@ -606,6 +452,9 @@ static void ssl_init_ctx_protocol(server + * Configure additional context ingredients + */ + SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); ++#ifndef OPENSSL_NO_EC ++ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); ++#endif + + #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + /* +@@ -646,11 +495,7 @@ static void ssl_init_ctx_callbacks(serve + { + SSL_CTX *ctx = mctx->ssl_ctx; + +- SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA); + SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH); +-#ifndef OPENSSL_NO_EC +- SSL_CTX_set_tmp_ecdh_callback(ctx,ssl_callback_TmpECDH); +-#endif + + SSL_CTX_set_info_callback(ctx, ssl_callback_Info); + } +@@ -1040,10 +885,14 @@ static void ssl_init_server_certs(server + const char *rsa_id, *dsa_id; + #ifndef OPENSSL_NO_EC + const char *ecc_id; ++ EC_GROUP *ecparams; ++ int nid; ++ EC_KEY *eckey = NULL; + #endif + const char *vhost_id = mctx->sc->vhost_id; + int i; + int have_rsa, have_dsa; ++ DH *dhparams; + #ifndef OPENSSL_NO_EC + int have_ecc; + #endif +@@ -1098,6 +947,46 @@ static void ssl_init_server_certs(server + #endif + ssl_die(); + } ++ ++ /* ++ * Try to read DH parameters from the (first) SSLCertificateFile ++ */ ++ if ((mctx->pks->cert_files[0] != NULL) && ++ (dhparams = ssl_dh_GetParamFromFile(mctx->pks->cert_files[0]))) { ++ SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams); ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "Custom DH parameters (%d bits) for %s loaded from %s", ++ BN_num_bits(dhparams->p), vhost_id, ++ mctx->pks->cert_files[0]); ++ } ++ ++#ifndef OPENSSL_NO_EC ++ /* ++ * Similarly, try to read the ECDH curve name from SSLCertificateFile... ++ */ ++ if ((mctx->pks->cert_files[0] != NULL) && ++ (ecparams = ssl_ec_GetParamFromFile(mctx->pks->cert_files[0])) && ++ (nid = EC_GROUP_get_curve_name(ecparams)) && ++ (eckey = EC_KEY_new_by_curve_name(nid))) { ++ SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey); ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "ECDH curve %s for %s specified in %s", ++ OBJ_nid2sn(nid), vhost_id, mctx->pks->cert_files[0]); ++ } ++ /* ++ * ...otherwise, enable auto curve selection (OpenSSL 1.0.2 and later) ++ * or configure NIST P-256 (required to enable ECDHE for earlier versions) ++ */ ++ else { ++#if defined(SSL_CTX_set_ecdh_auto) ++ SSL_CTX_set_ecdh_auto(mctx->ssl_ctx, 1); ++#else ++ eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ++ SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey); ++#endif ++ } ++ EC_KEY_free(eckey); ++#endif + } + + static void ssl_init_proxy_certs(server_rec *s, +@@ -1468,7 +1357,7 @@ apr_status_t ssl_init_ModuleKill(void *d + /* + * Destroy the temporary keys and params + */ +- ssl_tmp_keys_free(base_server); ++ ssl_dh_FreeParams(); + + /* + * Free the non-pool allocated structures +--- a/modules/ssl/ssl_engine_kernel.c ++++ b/modules/ssl/ssl_engine_kernel.c +@@ -1196,117 +1196,48 @@ int ssl_hook_Fixup(request_rec *r) + */ + + /* +- * Handle out temporary RSA private keys on demand +- * +- * The background of this as the TLSv1 standard explains it: +- * +- * | D.1. Temporary RSA keys +- * | +- * | US Export restrictions limit RSA keys used for encryption to 512 +- * | bits, but do not place any limit on lengths of RSA keys used for +- * | signing operations. Certificates often need to be larger than 512 +- * | bits, since 512-bit RSA keys are not secure enough for high-value +- * | transactions or for applications requiring long-term security. Some +- * | certificates are also designated signing-only, in which case they +- * | cannot be used for key exchange. +- * | +- * | When the public key in the certificate cannot be used for encryption, +- * | the server signs a temporary RSA key, which is then exchanged. In +- * | exportable applications, the temporary RSA key should be the maximum +- * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are +- * | relatively insecure, they should be changed often. For typical +- * | electronic commerce applications, it is suggested that keys be +- * | changed daily or every 500 transactions, and more often if possible. +- * | Note that while it is acceptable to use the same temporary key for +- * | multiple transactions, it must be signed each time it is used. +- * | +- * | RSA key generation is a time-consuming process. In many cases, a +- * | low-priority process can be assigned the task of key generation. +- * | Whenever a new key is completed, the existing temporary key can be +- * | replaced with the new one. +- * +- * XXX: base on comment above, if thread support is enabled, +- * we should spawn a low-priority thread to generate new keys +- * on the fly. +- * +- * So we generated 512 and 1024 bit temporary keys on startup +- * which we now just hand out on demand.... +- */ +- +-RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int keylen) +-{ +- conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); +- SSLModConfigRec *mc = myModConfigFromConn(c); +- int idx; +- +- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, +- "handing out temporary %d bit RSA key", keylen); +- +- /* doesn't matter if export flag is on, +- * we won't be asked for keylen > 512 in that case. +- * if we are asked for a keylen > 1024, it is too expensive +- * to generate on the fly. +- * XXX: any reason not to generate 2048 bit keys at startup? +- */ +- +- switch (keylen) { +- case 512: +- idx = SSL_TMP_KEY_RSA_512; +- break; +- +- case 1024: +- default: +- idx = SSL_TMP_KEY_RSA_1024; +- } +- +- return (RSA *)mc->pTmpKeys[idx]; +-} +- +-/* + * Hand out the already generated DH parameters... ++ * Based on the authentication strength. + */ + DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen) + { + conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); +- SSLModConfigRec *mc = myModConfigFromConn(c); +- int idx; ++ EVP_PKEY *pkey; ++ int type; + + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, +- "handing out temporary %d bit DH key", keylen); +- +- switch (keylen) { +- case 512: +- idx = SSL_TMP_KEY_DH_512; +- break; +- +- case 1024: +- default: +- idx = SSL_TMP_KEY_DH_1024; +- } ++ "handing out built-in DH parameters for %d-bit " ++ "authenticated connection", keylen); + +- return (DH *)mc->pTmpKeys[idx]; +-} +- +-#ifndef OPENSSL_NO_EC +-EC_KEY *ssl_callback_TmpECDH(SSL *ssl, int export, int keylen) +-{ +- conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); +- SSLModConfigRec *mc = myModConfigFromConn(c); +- int idx; +- +- /* XXX Uses 256-bit key for now. TODO: support other sizes. */ +- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, +- "handing out temporary 256 bit ECC key"); ++#ifdef SSL_CERT_SET_SERVER ++ /* ++ * When multiple certs/keys are configured for the SSL_CTX: make sure ++ * that we get the private key which is indeed used for the current ++ * SSL connection (available in OpenSSL 1.0.2 or later only) ++ */ ++ SSL_set_current_cert(ssl, SSL_CERT_SET_SERVER); ++#endif ++ pkey = SSL_get_privatekey(ssl); ++ type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE; + +- switch (keylen) { +- case 256: +- default: +- idx = SSL_TMP_KEY_EC_256; ++ /* ++ * OpenSSL will call us with either keylen == 512 or keylen == 1024 ++ * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h). ++ * Adjust the DH parameter length according to the size of the ++ * RSA/DSA private key used for the current connection, and always ++ * use at least 1024-bit parameters. ++ * Note: This may cause interoperability issues with implementations ++ * which limit their DH support to 1024 bit - e.g. Java 7 and earlier. ++ * In this case, SSLCertificateFile can be used to specify fixed ++ * 1024-bit DH parameters (with the effect that OpenSSL skips this ++ * callback). ++ */ ++ if ((type == EVP_PKEY_RSA) || (type == EVP_PKEY_DSA)) { ++ keylen = EVP_PKEY_bits(pkey); + } + +- return (EC_KEY *)mc->pTmpKeys[idx]; ++ return ssl_dh_GetTmpParam(keylen); + } +-#endif + + /* + * This OpenSSL callback function is called when OpenSSL +--- a/modules/ssl/ssl_private.h ++++ b/modules/ssl/ssl_private.h +@@ -207,22 +207,6 @@ typedef int ssl_algo_t; + #define SSL_AIDX_MAX (2) + #endif + +- +-/** +- * Define IDs for the temporary RSA keys and DH params +- */ +- +-#define SSL_TMP_KEY_RSA_512 (0) +-#define SSL_TMP_KEY_RSA_1024 (1) +-#define SSL_TMP_KEY_DH_512 (2) +-#define SSL_TMP_KEY_DH_1024 (3) +-#ifndef OPENSSL_NO_EC +-#define SSL_TMP_KEY_EC_256 (4) +-#define SSL_TMP_KEY_MAX (5) +-#else +-#define SSL_TMP_KEY_MAX (4) +-#endif +- + /** + * Define the SSL options + */ +@@ -422,7 +406,6 @@ typedef struct { + apr_global_mutex_t *pMutex; + apr_array_header_t *aRandSeed; + apr_hash_t *tVHostKeys; +- void *pTmpKeys[SSL_TMP_KEY_MAX]; + apr_hash_t *tPublicCert; + apr_hash_t *tPrivateKey; + #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) +@@ -624,11 +607,7 @@ int ssl_hook_Upgrade(request_re + void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s); + + /** OpenSSL callbacks */ +-RSA *ssl_callback_TmpRSA(SSL *, int, int); + DH *ssl_callback_TmpDH(SSL *, int, int); +-#ifndef OPENSSL_NO_EC +-EC_KEY *ssl_callback_TmpECDH(SSL *, int, int); +-#endif + int ssl_callback_SSLVerify(int, X509_STORE_CTX *); + int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, conn_rec *); + int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP_PKEY **pkey); +@@ -703,8 +682,13 @@ int ssl_init_ssl_connection(con + void ssl_pphrase_Handle(server_rec *, apr_pool_t *); + + /** Diffie-Hellman Parameter Support */ +-DH *ssl_dh_GetTmpParam(int); +-DH *ssl_dh_GetParamFromFile(char *); ++DH *ssl_dh_GetTmpParam(int); ++DH *ssl_dh_GetParamFromFile(const char *); ++#ifndef OPENSSL_NO_EC ++EC_GROUP *ssl_ec_GetParamFromFile(const char *); ++#endif ++int ssl_dh_InitParams(server_rec *); ++void ssl_dh_FreeParams(void); + + unsigned char *ssl_asn1_table_set(apr_hash_t *table, + const char *key, +--- a/modules/ssl/ssl_util_ssl.c ++++ b/modules/ssl/ssl_util_ssl.c +@@ -550,8 +550,8 @@ int modssl_session_get_time(SSL_SESSION + #define SSLC_VERSION_NUMBER 0x0000 + #endif + +-DH *modssl_dh_configure(unsigned char *p, int plen, +- unsigned char *g, int glen) ++DH *modssl_dh_configure(const unsigned char *p, int plen, ++ const unsigned char *g, int glen) + { + DH *dh; + +--- a/modules/ssl/ssl_util_ssl.h ++++ b/modules/ssl/ssl_util_ssl.h +@@ -94,8 +94,8 @@ char *SSL_SESSION_id2sz(unsigned c + /** util functions for OpenSSL+sslc compat */ + int modssl_session_get_time(SSL_SESSION *session); + +-DH *modssl_dh_configure(unsigned char *p, int plen, +- unsigned char *g, int glen); ++DH *modssl_dh_configure(const unsigned char *p, int plen, ++ const unsigned char *g, int glen); + + #endif /* __SSL_UTIL_SSL_H__ */ + /** @} */
View file
debian.tar.gz/patches/series
Changed
@@ -48,3 +48,5 @@ CVE-2013-5704_trailers.patch SNI_case_insensitve.diff mod_ssl_SSL_CLIENT_S_DN_UID.diff +DH-SSLCertificateFile.patch +CVE-2015-3183.patch
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.