summaryrefslogtreecommitdiff
path: root/lib/ext/ec_point_formats.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext/ec_point_formats.c')
-rw-r--r--lib/ext/ec_point_formats.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/ext/ec_point_formats.c b/lib/ext/ec_point_formats.c
new file mode 100644
index 0000000000..657eb6625d
--- /dev/null
+++ b/lib/ext/ec_point_formats.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2017 Red Hat, 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/>
+ *
+ */
+
+/* This file contains the code for the Elliptic Curve Point Formats extension.
+ */
+
+#include "ext/ec_point_formats.h"
+#include "str.h"
+#include "state.h"
+#include <gnutls/gnutls.h>
+
+
+static int _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
+ const uint8_t * data,
+ size_t data_size);
+static int _gnutls_supported_ec_point_formats_send_params(gnutls_session_t session,
+ gnutls_buffer_st * extdata);
+
+
+const hello_ext_entry_st ext_mod_supported_ec_point_formats = {
+ .name = "Supported EC Point Formats",
+ .tls_id = 11,
+ .gid = GNUTLS_EXTENSION_SUPPORTED_EC_POINT_FORMATS,
+ .parse_type = GNUTLS_EXT_TLS,
+ .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS |
+ GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ .recv_func = _gnutls_supported_ec_point_formats_recv_params,
+ .send_func = _gnutls_supported_ec_point_formats_send_params,
+ .pack_func = NULL,
+ .unpack_func = NULL,
+ .deinit_func = NULL
+};
+
+
+/* Receive point formats
+ */
+static int
+_gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
+ const uint8_t * data,
+ size_t _data_size)
+{
+ int len, i;
+ int uncompressed = 0;
+ int data_size = _data_size;
+
+ if (session->security_parameters.entity == GNUTLS_CLIENT) {
+ if (data_size < 1)
+ return
+ gnutls_assert_val
+ (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+
+ len = data[0];
+ if (len < 1)
+ return
+ gnutls_assert_val
+ (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+
+ DECR_LEN(data_size, len + 1);
+
+ for (i = 1; i <= len; i++)
+ if (data[i] == 0) { /* uncompressed */
+ uncompressed = 1;
+ break;
+ }
+
+ if (uncompressed == 0)
+ return
+ gnutls_assert_val
+ (GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+ } else {
+ /* only sanity check here. We only support uncompressed points
+ * and a client must support it thus nothing to check.
+ */
+ if (_data_size < 1)
+ return
+ gnutls_assert_val
+ (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+ }
+
+ return 0;
+}
+
+/* returns data_size or a negative number on failure
+ */
+static int
+_gnutls_supported_ec_point_formats_send_params(gnutls_session_t session,
+ gnutls_buffer_st * extdata)
+{
+ const uint8_t p[2] = { 0x01, 0x00 }; /* only support uncompressed point format */
+ int ret;
+
+ if (session->security_parameters.entity == GNUTLS_SERVER
+ && !_gnutls_session_is_ecc(session))
+ return 0;
+
+ if (session->internals.priorities->groups.size > 0) {
+ ret = _gnutls_buffer_append_data(extdata, p, 2);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 2;
+ }
+ return 0;
+}