Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openssl: auto DHE, ECDHE #4412

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 17 additions & 23 deletions pkgs/racket-doc/openssl/openssl.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -686,42 +686,36 @@ collection for testing purposes where the peer identifies itself using
@deftogether[[
@defproc[(ssl-server-context-enable-dhe!
[context ssl-server-context?]
[dh-param (or/c path-string? bytes?) ssl-dh4096-param-bytes])
[ignored (or/c path-string? bytes?) ssl-dh4096-param-bytes])
void?]
@defproc[(ssl-server-context-enable-ecdhe!
[context ssl-server-context?]
[curve-name symbol? 'secp521r1])
[ignored symbol? 'ignored])
void?]
]]{

Enables cipher suites that provide
@hyperlink["http://en.wikipedia.org/wiki/Forward_secrecy"]{perfect
forward secrecy} via ephemeral Diffie-Hellman (DHE) or ephemeral
elliptic-curve Diffie-Hellman (ECDHE) key exchange, respectively.

For DHE, the @racket[dh-param] must be a path to a @filepath{.pem}
file containing DH parameters or the content of such a file as a byte
string.

For ECDHE, the @racket[curve-name] must be one of the following
symbols naming a standard elliptic curve:
@(add-between
(map (lambda (s) (racket '@#,(racketvalfont (symbol->string s))))
'(sect163k1 sect163r1 sect163r2 sect193r1 sect193r2 sect233k1 sect233r1
sect239k1 sect283k1 sect283r1 sect409k1 sect409r1 sect571k1 sect571r1
secp160k1 secp160r1 secp160r2 secp192k1 secp224k1 secp224r1 secp256k1
secp384r1 secp521r1 prime192v prime256v))
", ").
@bold{Deprecated.} These procedures have no effect; they are provided for
backwards compatibility only.

Ciphers supporting
@hyperlink["http://en.wikipedia.org/wiki/Forward_secrecy"]{perfect forward
secrecy} via ephemeral Diffie-Hellman (DHE) or ephemeral elliptic-curve
Diffie-Hellman (ECDHE) key exchange are enabled by default, with automatic
selection of key-exchange groups. Customization of the groups (DH parameters
and EC curves) is no longer supported.

@history[#:changed "7.7.0.4" @elem{Allow a byte string as the @racket[dh-param]
argument to @racket[ssl-server-context-enable-dhe!].}]}
argument to @racket[ssl-server-context-enable-dhe!].}
#:changed "8.6.0.4" @elem{Deprecated, changed to have no effect.}]}

@defthing[ssl-dh4096-param-bytes bytes?]{

Byte string describing 4096-bit Diffie-Hellman parameters in @filepath{.pem} format.
@bold{Deprecated.} Defined as @racket[#""], provided for backwards compatibility
only. See @racket[ssl-server-context-enable-dhe!].

@history[#:changed "7.7.0.4" @elem{Added as a replacement for
@racketidfont{ssl-dh4096-param-path}.}]}
@racketidfont{ssl-dh4096-param-path}.}
#:changed "8.6.0.4" @elem{Deprecated, redefined to empty byte string.}]}

@defproc[(ssl-set-server-name-identification-callback!
[context ssl-server-context?]
Expand Down
27 changes: 13 additions & 14 deletions pkgs/racket-test/tests/openssl/test-ephemeral.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,26 @@

(cond
[(memq 'tls12 (supported-server-protocols))
;; Test DHE ciphers (note: cipher spec is "EDH", contrary to openssl ciphers docs)
(test-ephemeral (lambda (server-ctx)
(ssl-server-context-enable-dhe! server-ctx ssl-dh4096-param-bytes))
"AES+EDH")
(test-case "test DHE ciphers"
;; note: cipher spec is "EDH", contrary to openssl ciphers docs
(test-ephemeral (lambda (server-ctx)
(ssl-server-context-enable-dhe! server-ctx ssl-dh4096-param-bytes))
"AES+EDH"))
(test-case "test ECDHE ciphers"
(test-ephemeral (lambda (server-ctx)
(ssl-server-context-enable-ecdhe! server-ctx 'secp521r1))
"ECDHE-RSA-AES128-SHA256"))

;; Test ECDHE ciphers
(test-ephemeral (lambda (server-ctx)
(ssl-server-context-enable-ecdhe! server-ctx 'secp521r1))
"ECDHE-RSA-AES128-SHA256")

;; Sanity check for DHE: connection fails when enable! not called
;; These used to be sanity checks for DHE and ECDHE, where the connection
;; fails when `enable!` is not called. But calling `enable!` is no longer
;; necessary.
#;
(check-exn
#rx"connect failed"
(lambda ()
;; for DrDr, suppress accept error printing
(parameterize ((current-error-port (open-output-string)))
(test-ephemeral void "AES+EDH"))))

;; This used to be a sanity check for ECDHE, where the connection
;; fails when `enable!` is not called. But calling `enable!` is
;; apparently no longer necessary.
#;
(check-exn
#rx"connect failed"
Expand Down
18 changes: 0 additions & 18 deletions racket/collects/openssl/dh4096.pem

This file was deleted.

94 changes: 25 additions & 69 deletions racket/collects/openssl/mzssl.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -56,35 +56,6 @@ TO DO:
(define (alpn-protocol-bytes/c v)
(and (bytes? v) (< 0 (bytes-length v) 256)))

(define curve-nid-alist
'((sect163k1 . 721)
(sect163r1 . 722)
(sect163r2 . 723)
(sect193r1 . 724)
(sect193r2 . 725)
(sect233k1 . 726)
(sect233r1 . 727)
(sect239k1 . 728)
(sect283k1 . 729)
(sect283r1 . 730)
(sect409k1 . 731)
(sect409r1 . 732)
(sect571k1 . 733)
(sect571r1 . 734)
(secp160k1 . 708)
(secp160r1 . 709)
(secp160r2 . 710)
(secp192k1 . 711)
(secp224k1 . 712)
(secp224r1 . 713)
(secp256k1 . 714)
(secp384r1 . 715)
(secp521r1 . 716)
(prime192v1 . 409)
(prime256v1 . 415)))

(define curve/c (apply or/c (map car curve-nid-alist)))

(define verify-source/c
(or/c path-string?
(list/c 'directory path-string?)
Expand Down Expand Up @@ -112,9 +83,9 @@ TO DO:
#:certificate-chain (or/c path-string? #f))
ssl-server-context?)]
[ssl-server-context-enable-dhe!
(->* (ssl-server-context?) ((or/c path-string? bytes?)) void?)]
(->* (ssl-server-context?) ((or/c 'auto path-string? bytes?)) void?)]
[ssl-server-context-enable-ecdhe!
(->* (ssl-server-context?) (curve/c) void?)]
(->* (ssl-server-context?) (symbol?) void?)]
[ssl-client-context?
(c-> any/c boolean?)]
[ssl-server-context?
Expand Down Expand Up @@ -305,15 +276,7 @@ TO DO:
[else
(x509-root-sources)])))

(define ssl-dh4096-param-bytes
(include/reader "dh4096.pem" (lambda (src port)
(let loop ([accum '()])
(define bstr (read-bytes 4096 port))
(if (eof-object? bstr)
(if (null? accum)
eof
(datum->syntax #'here (apply bytes-append (reverse accum))))
(loop (cons bstr accum)))))))
(define ssl-dh4096-param-bytes #"")

;; Make this bigger than 4096 to accommodate at least
;; 4096 of unencrypted data
Expand Down Expand Up @@ -492,6 +455,19 @@ TO DO:
(unless (and (= 1 (SSL_CTX_set_min_proto_version ctx min-proto))
(= 1 (SSL_CTX_set_max_proto_version ctx max-proto)))
(error who "failed setting min/max protocol versions: ~e" protocol-symbol))))
(unless client?
;; Always enable DHE and ECDHE support (only needed for server contexts).
(cond [v1.1.0/later?
;; DHE supports automatic selection of DH params:
(SSL_CTX_set_dh_auto ctx 1)
;; and ECDHE automatic curve selection is enabled by default.
(void)]
[else
;; In v1.0.2, DHE requires explicitly setting the group; this is the
;; best built-in available in v1.0.2:
(SSL_CTX_set_tmp_dh ctx (DH_get_2048_256))
;; and ECDHE supports automatic curve selection, but must be enabled:
(SSL_CTX_set_ecdh_auto ctx 1)]))
ctx)

(define (encrypt->method who e client?)
Expand Down Expand Up @@ -572,37 +548,17 @@ TO DO:
(define (ssl-seal-context! mzctx)
(set-ssl-context-sealed?! mzctx #t))

(define (ssl-server-context-enable-ecdhe! context [name 'secp521r1])
(define (symbol->nid name)
(cond [(assq name curve-nid-alist)
=> cdr]
[else
(error 'ssl-server-context-enable-ecdhe!
"bad curve name\n curve name: ~e" name)]))
(define ctx (extract-ctx 'ssl-server-context-enable-ecdhe! #t context))
(define key (EC_KEY_new_by_curve_name (symbol->nid name)))
(check-valid key 'ssl-server-context-enable-ecdhe! "enabling ECDHE")
(unless (= 1 (SSL_CTX_ctrl ctx SSL_CTRL_SET_TMP_ECDH 0 key))
(error 'ssl-server-context-enable-ecdhe! "enabling ECDHE"))
(SSL_CTX_ctrl ctx SSL_CTRL_OPTIONS SSL_OP_SINGLE_ECDH_USE #f)
(define (ssl-server-context-enable-ecdhe! context [name #f])
;; No longer necessary, ECDHE enabled in auto mode in (server) context
;; construction. Can customize with SSL_set1_groups[_list], but generally
;; unnecessary, so currently unsupported.
(void))

(define (ssl-server-context-enable-dhe! context [ssl-dh4096-param ssl-dh4096-param-bytes])
(define params (if (bytes? ssl-dh4096-param)
ssl-dh4096-param
(call-with-input-file* ssl-dh4096-param port->bytes)))
(define params-bio (BIO_new_mem_buf params (bytes-length params)))
(check-valid params-bio 'ssl-server-context-enable-dhe! "loading Diffie-Hellman parameters")
(with-failure
(lambda ()
(BIO_free params-bio))
(define ctx (extract-ctx 'ssl-server-context-enable-dhe! #t context))
(define dh (PEM_read_bio_DHparams params-bio #f #f #f))
(check-valid dh 'ssl-server-context-enable-dhe! "loading Diffie-Hellman parameters")
(unless (= 1 (SSL_CTX_ctrl ctx SSL_CTRL_SET_TMP_DH 0 dh))
(error 'ssl-server-context-enable-dhe! "failed to enable DHE"))
(SSL_CTX_ctrl ctx SSL_CTRL_OPTIONS SSL_OP_SINGLE_DH_USE #f)
(void)))
(define (ssl-server-context-enable-dhe! context [params 'auto])
;; No effect. DHE enabled in auto mode in (server) context construction.
(unless (eq? params 'auto)
(log-openssl-warning "ssl-server-context-enable-dhe!: ignoring given DH parameters"))
(void))

(define (ssl-load-... who load-it ssl-context-or-listener pathname
#:try? [try? #f])
Expand Down
28 changes: 16 additions & 12 deletions racket/collects/openssl/private/ffi.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
(define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53)
(define SSL_CTRL_SET_TLSEXT_HOSTNAME 55)
(define SSL_CTRL_SET_TMP_DH 3)
(define SSL_CTRL_SET_TMP_ECDH 4)
(define SSL_CTRL_SET_ECDH_AUTO 94)
(define SSL_CTRL_SET_DH_AUTO 118)
(define SSL_CTRL_GET_EXTMS_SUPPORT 122)
(define SSL_CTRL_SET_MIN_PROTO_VERSION 123)
(define SSL_CTRL_SET_MAX_PROTO_VERSION 124)
Expand All @@ -70,9 +71,6 @@
(define SSL_OP_NO_TLSv1_2 #x08000000)
(define SSL_OP_NO_TLSv1_1 #x10000000)

(define SSL_OP_SINGLE_ECDH_USE #x00080000)
(define SSL_OP_SINGLE_DH_USE #x00100000)

(define TLSEXT_NAMETYPE_host_name 0)

(define SSL_TLSEXT_ERR_OK 0)
Expand Down Expand Up @@ -146,12 +144,6 @@
(define-ssl TLS_server_method (_fun -> _SSL_METHOD*)
#:fail (lambda () SSLv23_server_method)))

(define-crypto DH_free (_fun _DH* -> _void) #:wrap (deallocator))
(define-crypto EC_KEY_free (_fun _EC_KEY* -> _void) #:wrap (deallocator))

(define-crypto EC_KEY_new_by_curve_name (_fun _int -> _EC_KEY*)
#:wrap (allocator EC_KEY_free))

(define-crypto BIO_s_mem (_fun -> _BIO_METHOD*))
(define-crypto BIO_new (_fun _BIO_METHOD* -> _BIO*/null))
(define-crypto BIO_new_mem_buf (_fun _pointer _int -> _BIO*))
Expand Down Expand Up @@ -248,9 +240,14 @@
(define-ssl SSL_library_init (_fun -> _void) #:fail (lambda () void))
(define-ssl SSL_load_error_strings (_fun -> _void) #:fail (lambda () void)))

(begin ;; deprecated in v3.0.0
(define-crypto DH_free (_fun _DH* -> _void) #:wrap (deallocator))
(define-crypto DH_get_2048_256 (_fun -> _DH*) #:fail (lambda () (lambda () #f))
#:wrap (allocator DH_free))
(define (SSL_CTX_set_tmp_dh ctx dh)
(SSL_CTX_ctrl ctx SSL_CTRL_SET_TMP_DH 0 dh)))

(define-crypto GENERAL_NAME_free _fpointer)
(define-crypto PEM_read_bio_DHparams (_fun _BIO* _pointer _pointer _pointer -> _DH*)
#:wrap (allocator DH_free))
(define-crypto ASN1_STRING_length (_fun _ASN1_STRING* -> _int))
(define-crypto ASN1_STRING_data (_fun _ASN1_STRING* -> _pointer))
(define-crypto X509_NAME_get_index_by_NID (_fun _X509_NAME* _int _int -> _int))
Expand Down Expand Up @@ -380,3 +377,10 @@
(define (SSL_set_tlsext_host_name s hostname)
(SSL_ctrl/bytes s SSL_CTRL_SET_TLSEXT_HOSTNAME
TLSEXT_NAMETYPE_host_name (string->bytes/latin-1 hostname)))

(define (SSL_CTX_set_ecdh_auto ctx onoff)
;; no-op since v1.1.0
(SSL_CTX_ctrl ctx SSL_CTRL_SET_ECDH_AUTO onoff #f))

(define (SSL_CTX_set_dh_auto ctx onoff)
(SSL_CTX_ctrl ctx SSL_CTRL_SET_DH_AUTO onoff #f))