1 /*
2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3 * Copyright (C) 2017 Red Hat, Inc.
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 /* This file contains the code for the Elliptic Curve Point Formats extension.
25 */
26
27 #include "ext/ec_point_formats.h"
28 #include "str.h"
29 #include "state.h"
30 #include <gnutls/gnutls.h>
31
32
33 static int _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
34 const uint8_t * data,
35 size_t data_size);
36 static int _gnutls_supported_ec_point_formats_send_params(gnutls_session_t session,
37 gnutls_buffer_st * extdata);
38
39
40 const hello_ext_entry_st ext_mod_supported_ec_point_formats = {
41 .name = "Supported EC Point Formats",
42 .tls_id = 11,
43 .gid = GNUTLS_EXTENSION_SUPPORTED_EC_POINT_FORMATS,
44 .client_parse_point = GNUTLS_EXT_TLS,
45 .server_parse_point = GNUTLS_EXT_TLS,
46 .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS |
47 GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
48 .recv_func = _gnutls_supported_ec_point_formats_recv_params,
49 .send_func = _gnutls_supported_ec_point_formats_send_params,
50 .pack_func = NULL,
51 .unpack_func = NULL,
52 .deinit_func = NULL
53 };
54
55
56 /* Receive point formats
57 */
58 static int
_gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,const uint8_t * data,size_t data_size)59 _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
60 const uint8_t * data,
61 size_t data_size)
62 {
63 size_t len, i;
64 int uncompressed = 0;
65
66 if (session->security_parameters.entity == GNUTLS_CLIENT) {
67 if (data_size < 1)
68 return
69 gnutls_assert_val
70 (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
71
72 len = data[0];
73 if (len < 1)
74 return
75 gnutls_assert_val
76 (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
77
78 DECR_LEN(data_size, len + 1);
79
80 for (i = 1; i <= len; i++)
81 if (data[i] == 0) { /* uncompressed */
82 uncompressed = 1;
83 break;
84 }
85
86 if (uncompressed == 0)
87 return
88 gnutls_assert_val
89 (GNUTLS_E_UNKNOWN_PK_ALGORITHM);
90 } else {
91 /* only sanity check here. We only support uncompressed points
92 * and a client must support it thus nothing to check.
93 */
94 if (data_size < 1)
95 return
96 gnutls_assert_val
97 (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
98 }
99
100 return 0;
101 }
102
103 /* returns data_size or a negative number on failure
104 */
105 static int
_gnutls_supported_ec_point_formats_send_params(gnutls_session_t session,gnutls_buffer_st * extdata)106 _gnutls_supported_ec_point_formats_send_params(gnutls_session_t session,
107 gnutls_buffer_st * extdata)
108 {
109 const uint8_t p[2] = { 0x01, 0x00 }; /* only support uncompressed point format */
110 int ret;
111
112 if (session->security_parameters.entity == GNUTLS_SERVER
113 && !_gnutls_session_is_ecc(session))
114 return 0;
115
116 if (session->internals.priorities->groups.size > 0) {
117 ret = _gnutls_buffer_append_data(extdata, p, 2);
118 if (ret < 0)
119 return gnutls_assert_val(ret);
120
121 return 2;
122 }
123 return 0;
124 }
125