diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2016-10-27 03:35:41 +0300 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2017-10-10 11:20:10 +0300 |
commit | 936edbc1835d7358a71d50dcadfda0f113aae43e (patch) | |
tree | 8ea3e24fba23b6a60e2fa4b994af222b3485c2d0 | |
parent | 4fd7d171207ddbab38a093722018859f7517a3a3 (diff) | |
download | gnutls-936edbc1835d7358a71d50dcadfda0f113aae43e.tar.gz |
Add CryptoPro extension used by CryptoPro CSP for old ciphersuites
Add extension (defined as TLSGostExtensionHashHMACSelect in
draft-chudov-cryptopro-cptls), required for interoperability with
CryptoPro CSP.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-rw-r--r-- | lib/ext/Makefile.am | 3 | ||||
-rw-r--r-- | lib/ext/cryptopro.c | 87 | ||||
-rw-r--r-- | lib/ext/cryptopro.h | 32 | ||||
-rw-r--r-- | lib/extensions.c | 4 | ||||
-rw-r--r-- | lib/extensions.h | 3 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 |
6 files changed, 128 insertions, 2 deletions
diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am index 698e41667e..2ffedd2ffb 100644 --- a/lib/ext/Makefile.am +++ b/lib/ext/Makefile.am @@ -40,7 +40,8 @@ libgnutls_ext_la_SOURCES = max_record.c \ session_ticket.h signature.h safe_renegotiation.h \ session_ticket.c srp.c ecc.c ecc.h heartbeat.c heartbeat.h \ status_request.h status_request.c dumbfw.c dumbfw.h \ - ext_master_secret.c ext_master_secret.h etm.h etm.c + ext_master_secret.c ext_master_secret.h etm.h etm.c \ + cryptopro.c if ENABLE_ALPN libgnutls_ext_la_SOURCES += alpn.c alpn.h diff --git a/lib/ext/cryptopro.c b/lib/ext/cryptopro.c new file mode 100644 index 0000000000..6baf561fb3 --- /dev/null +++ b/lib/ext/cryptopro.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016 Dmitry Eremin-Solenikov + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + */ +/* This file contains workaround for CryptoPro sending and receiving + * special extension when using older GOST cipher suites. + * + * Clients might expect to receive this extension from server. Thus we send it + * if client has asked for one and old ciphersuite is selected. + * + * Servers might (and will) send this extension if old ciphersuite is selected. + * Thus just ignore it on the client side. + * + * For data description, see TLSGostExtensionHashHMACSelect in + * https://tools.ietf.org/html/draft-chudov-cryptopro-cptls-04#appendix-A.1 + */ + +#include "gnutls_int.h" +#include <gnutls/gnutls.h> +#include <ext/cryptopro.h> + +#define GNUTLS_GOSTR341001_MAJOR 0x00 +#define GNUTLS_GOSTR341001_28147_MINOR 0x81 +#define GNUTLS_GOSTR341001_NULL_MINOR 0x83 + +static int +_gnutls_cryptopro_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size) +{ + /* Just ignore it, no use of that extension */ + + return 0; +} + +static const uint8_t cryptopro_server_data[] = { + 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, + 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, + 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, + 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17 +}; + +static int +_gnutls_cryptopro_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + if (session->security_parameters.entity == GNUTLS_SERVER) { + if (session->security_parameters.cs->id[0] == GNUTLS_GOSTR341001_MAJOR && + (session->security_parameters.cs->id[1] == GNUTLS_GOSTR341001_28147_MINOR || + session->security_parameters.cs->id[1] == GNUTLS_GOSTR341001_NULL_MINOR)) { + _gnutls_buffer_append_data(extdata, cryptopro_server_data, sizeof(cryptopro_server_data)); + return sizeof(cryptopro_server_data); + } + } else { + /* We might receive this extension even if we did not ask for it. + * CryptoPro/OpenSSL servers will send it if GOSTR341001 ciphersuite + * was selected. */ +#ifdef ENABLE_GOST + _gnutls_extension_list_add(session, &ext_mod_cryptopro, 0); +#endif + return 0; + } + return 0; +} + +const extension_entry_st ext_mod_cryptopro = { + .name = "CryptoPro", + .type = GNUTLS_EXTENSION_CRYPTOPRO, + .parse_type = GNUTLS_EXT_TLS, + + .recv_func = _gnutls_cryptopro_recv_params, + .send_func = _gnutls_cryptopro_send_params, +}; diff --git a/lib/ext/cryptopro.h b/lib/ext/cryptopro.h new file mode 100644 index 0000000000..a899672895 --- /dev/null +++ b/lib/ext/cryptopro.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* CryptoPro workaround extension + */ +#ifndef EXT_CRYPTOPRO_H +#define EXT_CRYPTOPRO_H + +#include <extensions.h> + +extern const extension_entry_st ext_mod_cryptopro; + +#endif diff --git a/lib/extensions.c b/lib/extensions.c index 2f889df3b8..40ca25d3d9 100644 --- a/lib/extensions.c +++ b/lib/extensions.c @@ -44,6 +44,7 @@ #include <ext/alpn.h> #include <ext/dumbfw.h> #include <ext/etm.h> +#include <ext/cryptopro.h> #include <num.h> static void @@ -79,6 +80,7 @@ static extension_entry_st const *extfunc[MAX_EXT_TYPES+1] = { #ifdef ENABLE_ALPN &ext_mod_alpn, #endif + &ext_mod_cryptopro, /* This must be the last extension registered. */ &ext_mod_dumbfw, @@ -161,7 +163,7 @@ _gnutls_extension_list_check(gnutls_session_t session, uint16_t type) * * Returns zero if failed, non-zero on success. */ -static unsigned _gnutls_extension_list_add(gnutls_session_t session, const struct extension_entry_st *e, unsigned check_dup) +unsigned _gnutls_extension_list_add(gnutls_session_t session, const struct extension_entry_st *e, unsigned check_dup) { unsigned i; diff --git a/lib/extensions.h b/lib/extensions.h index bc3154c180..1bb8b839cf 100644 --- a/lib/extensions.h +++ b/lib/extensions.h @@ -34,6 +34,9 @@ int _gnutls_gen_extensions(gnutls_session_t session, int _gnutls_ext_init(void); void _gnutls_ext_deinit(void); +unsigned _gnutls_extension_list_add(gnutls_session_t session, + const struct extension_entry_st *e, + unsigned check_dup); void _gnutls_extension_list_add_sr(gnutls_session_t session); int _gnutls_extension_list_check(gnutls_session_t session, uint16_t type); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 76e64083b2..bb40364c23 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -285,6 +285,7 @@ typedef enum extensions_t { GNUTLS_EXTENSION_ETM = 22, GNUTLS_EXTENSION_EXT_MASTER_SECRET = 23, GNUTLS_EXTENSION_SESSION_TICKET = 35, + GNUTLS_EXTENSION_CRYPTOPRO = 65000, /* aka: 0xfde8 */ GNUTLS_EXTENSION_SAFE_RENEGOTIATION = 65281 /* aka: 0xff01 */ } extensions_t; |