2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* This file contains the code the Certificate Type TLS extension.
24 * This extension is currently gnutls specific.
27 #include "gnutls_int.h"
28 #include "gnutls_errors.h"
29 #include "gnutls_num.h"
31 #include <gnutls_state.h>
32 #include <gnutls_num.h>
33 #include <algorithms.h>
35 /* Maps record size to numbers according to the
39 static int _gnutls_supported_ecc_recv_params (gnutls_session_t session
,
42 static int _gnutls_supported_ecc_send_params (gnutls_session_t session
,
43 gnutls_buffer_st
* extdata
);
45 static int _gnutls_supported_ecc_pf_recv_params (gnutls_session_t session
,
48 static int _gnutls_supported_ecc_pf_send_params (gnutls_session_t session
,
49 gnutls_buffer_st
* extdata
);
51 extension_entry_st ext_mod_supported_ecc
= {
52 .name
= "SUPPORTED ECC",
53 .type
= GNUTLS_EXTENSION_SUPPORTED_ECC
,
54 .parse_type
= GNUTLS_EXT_TLS
,
56 .recv_func
= _gnutls_supported_ecc_recv_params
,
57 .send_func
= _gnutls_supported_ecc_send_params
,
63 extension_entry_st ext_mod_supported_ecc_pf
= {
64 .name
= "SUPPORTED ECC POINT FORMATS",
65 .type
= GNUTLS_EXTENSION_SUPPORTED_ECC_PF
,
66 .parse_type
= GNUTLS_EXT_TLS
,
68 .recv_func
= _gnutls_supported_ecc_pf_recv_params
,
69 .send_func
= _gnutls_supported_ecc_pf_send_params
,
76 * In case of a server: if a SUPPORTED_ECC extension type is received then it stores
77 * into the session security parameters the new value. The server may use gnutls_session_certificate_type_get(),
80 * In case of a client: If a supported_eccs have been specified then we send the extension.
84 _gnutls_supported_ecc_recv_params (gnutls_session_t session
,
85 const uint8_t * data
, size_t _data_size
)
87 int new_type
= -1, ret
, i
;
88 ssize_t data_size
= _data_size
;
90 const uint8_t* p
= data
;
92 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
94 /* A client shouldn't receive this extension */
95 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION
);
98 { /* SERVER SIDE - we must check if the sent supported ecc type is the right one
101 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION
);
103 DECR_LEN (data_size
, 2);
104 len
= _gnutls_read_uint16(p
);
107 DECR_LEN (data_size
, len
);
109 for (i
= 0; i
< len
; i
+=2)
111 new_type
= _gnutls_tls_id_to_ecc_curve (_gnutls_read_uint16(&p
[i
]));
115 /* Check if we support this supported_ecc */
117 _gnutls_session_supports_ecc_curve (session
, new_type
)) < 0)
129 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER
;
133 _gnutls_session_supports_ecc_curve (session
, new_type
)) < 0)
135 /* The peer has requested unsupported ecc
136 * types. Instead of failing, procceed normally.
137 * (the ciphersuite selection would fail, or a
138 * non certificate ciphersuite will be selected).
140 return gnutls_assert_val(0);
143 _gnutls_session_ecc_curve_set (session
, new_type
);
150 /* returns data_size or a negative number on failure
153 _gnutls_supported_ecc_send_params (gnutls_session_t session
, gnutls_buffer_st
* extdata
)
159 /* this extension is only being sent on client side */
160 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
163 if (session
->internals
.priorities
.supported_ecc
.algorithms
> 0)
166 len
= session
->internals
.priorities
.supported_ecc
.algorithms
;
170 ret
= _gnutls_buffer_append_prefix(extdata
, 16, len
*2);
172 return gnutls_assert_val(ret
);
174 for (i
= 0; i
< len
; i
++)
177 _gnutls_ecc_curve_get_tls_id (session
->internals
.priorities
.
178 supported_ecc
.priority
[i
]);
179 ret
= _gnutls_buffer_append_prefix(extdata
, 16, p
);
181 return gnutls_assert_val(ret
);
192 * In case of a server: if a SUPPORTED_ECC extension type is received then it stores
193 * into the session security parameters the new value. The server may use gnutls_session_certificate_type_get(),
196 * In case of a client: If a supported_eccs have been specified then we send the extension.
200 _gnutls_supported_ecc_pf_recv_params (gnutls_session_t session
,
201 const uint8_t * data
, size_t _data_size
)
204 int uncompressed
= 0;
205 int data_size
= _data_size
;
207 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
210 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION
);
213 DECR_LEN (data_size
, len
+1);
216 if (data
[i
] == 0) /* uncompressed */
219 if (uncompressed
== 0)
220 return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM
);
224 /* only sanity check here. We only support uncompressed points
225 * and a client must support it thus nothing to check.
228 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION
);
234 /* returns data_size or a negative number on failure
237 _gnutls_supported_ecc_pf_send_params (gnutls_session_t session
, gnutls_buffer_st
* extdata
)
239 const uint8_t p
[2] = {0x01, 0x00}; /* only support uncompressed point format */
241 if (session
->security_parameters
.entity
== GNUTLS_SERVER
&& !_gnutls_session_is_ecc(session
))
244 if (session
->internals
.priorities
.supported_ecc
.algorithms
> 0)
246 _gnutls_buffer_append_data(extdata
, p
, 2);
253 /* Returns 0 if the given ECC curve is allowed in the current
254 * session. A negative error value is returned otherwise.
257 _gnutls_session_supports_ecc_curve (gnutls_session_t session
, unsigned int ecc_type
)
261 if (session
->internals
.priorities
.supported_ecc
.algorithms
> 0)
263 for (i
= 0; i
< session
->internals
.priorities
.supported_ecc
.algorithms
; i
++)
265 if (session
->internals
.priorities
.supported_ecc
.priority
[i
] == ecc_type
)
270 return GNUTLS_E_ECC_UNSUPPORTED_CURVE
;