summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2016-10-27 03:35:41 +0300
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2017-10-10 11:20:10 +0300
commit936edbc1835d7358a71d50dcadfda0f113aae43e (patch)
tree8ea3e24fba23b6a60e2fa4b994af222b3485c2d0
parent4fd7d171207ddbab38a093722018859f7517a3a3 (diff)
downloadgnutls-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.am3
-rw-r--r--lib/ext/cryptopro.c87
-rw-r--r--lib/ext/cryptopro.h32
-rw-r--r--lib/extensions.c4
-rw-r--r--lib/extensions.h3
-rw-r--r--lib/gnutls_int.h1
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;