Line data Source code
1 : /*
2 : * Copyright (C) 2002-2016 Free Software Foundation, Inc.
3 : * Copyright (C) 2015-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 Signature Algorithms TLS extension.
25 : * This extension is currently gnutls specific.
26 : */
27 :
28 : #include "gnutls_int.h"
29 : #include "errors.h"
30 : #include "num.h"
31 : #include <gnutls/gnutls.h>
32 : #include <ext/signature.h>
33 : #include <state.h>
34 : #include <num.h>
35 : #include <algorithms.h>
36 : #include <abstract_int.h>
37 :
38 : /*
39 : * Some (all SChannel) clients fail to send proper SigAlgs due to Micro$oft crazyness.
40 : * Patch the extension for them.
41 : */
42 : #ifdef ENABLE_GOST
43 : #define GOST_SIG_FIXUP_SCHANNEL
44 : #endif
45 :
46 : static int _gnutls_signature_algorithm_recv_params(gnutls_session_t
47 : session,
48 : const uint8_t * data,
49 : size_t data_size);
50 : static int _gnutls_signature_algorithm_send_params(gnutls_session_t
51 : session,
52 : gnutls_buffer_st * extdata);
53 : static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv);
54 : static int signature_algorithms_pack(gnutls_ext_priv_data_t epriv,
55 : gnutls_buffer_st * ps);
56 : static int signature_algorithms_unpack(gnutls_buffer_st * ps,
57 : gnutls_ext_priv_data_t * _priv);
58 :
59 : const hello_ext_entry_st ext_mod_sig = {
60 : .name = "Signature Algorithms",
61 : .tls_id = 13,
62 : .gid = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
63 : .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO,
64 : .client_parse_point = GNUTLS_EXT_TLS,
65 : .server_parse_point = GNUTLS_EXT_TLS,
66 : .recv_func = _gnutls_signature_algorithm_recv_params,
67 : .send_func = _gnutls_signature_algorithm_send_params,
68 : .pack_func = signature_algorithms_pack,
69 : .unpack_func = signature_algorithms_unpack,
70 : .deinit_func = signature_algorithms_deinit_data,
71 : .cannot_be_overriden = 1
72 : };
73 :
74 : typedef struct {
75 : /* TLS 1.2 signature algorithms */
76 : gnutls_sign_algorithm_t sign_algorithms[MAX_ALGOS];
77 : uint16_t sign_algorithms_size;
78 : } sig_ext_st;
79 :
80 : /* generates a SignatureAndHashAlgorithm structure with length as prefix
81 : * by using the setup priorities.
82 : */
83 : int
84 6314 : _gnutls_sign_algorithm_write_params(gnutls_session_t session,
85 : gnutls_buffer_st * extdata)
86 : {
87 6314 : uint8_t *p;
88 6314 : unsigned int len, i;
89 6314 : const sign_algorithm_st *aid, *prev = NULL;
90 6314 : uint8_t buffer[MAX_ALGOS*2];
91 :
92 6314 : p = buffer;
93 6314 : len = 0;
94 :
95 : /* This generates a list of TLS signature algorithms. It has
96 : * limited duplicate detection, and does not add twice the same
97 : * AID */
98 :
99 121870 : for (i=0;i<session->internals.priorities->sigalg.size;i++) {
100 115556 : aid = &session->internals.priorities->sigalg.entry[i]->aid;
101 :
102 115556 : if (HAVE_UNKNOWN_SIGAID(aid))
103 0 : continue;
104 :
105 115556 : if (prev && prev->id[0] == aid->id[0] && prev->id[1] == aid->id[1])
106 12390 : continue;
107 :
108 : /* Ignore non-GOST sign types for CertReq */
109 103166 : if (session->security_parameters.cs &&
110 49129 : _gnutls_kx_is_vko_gost(session->security_parameters.cs->kx_algorithm) &&
111 546 : !_sign_is_gost(session->internals.priorities->sigalg.entry[i]))
112 494 : continue;
113 :
114 102672 : _gnutls_handshake_log
115 : ("EXT[%p]: sent signature algo (%d.%d) %s\n", session,
116 : (int)aid->id[0], (int)aid->id[1],
117 : session->internals.priorities->sigalg.entry[i]->name);
118 :
119 102672 : len += 2;
120 102672 : if (unlikely(len >= sizeof(buffer))) {
121 : len -= 2;
122 : break;
123 : }
124 :
125 102672 : *p = aid->id[0];
126 102672 : p++;
127 102672 : *p = aid->id[1];
128 102672 : p++;
129 102672 : prev = aid;
130 : }
131 :
132 6314 : return _gnutls_buffer_append_data_prefix(extdata, 16, buffer, len);
133 : }
134 :
135 :
136 : /* Parses the Signature Algorithm structure and stores data into
137 : * session->security_parameters.extensions.
138 : */
139 : int
140 13950 : _gnutls_sign_algorithm_parse_data(gnutls_session_t session,
141 : const uint8_t * data, size_t data_size)
142 : {
143 13950 : unsigned int sig, i;
144 13950 : sig_ext_st *priv;
145 13950 : gnutls_ext_priv_data_t epriv;
146 13950 : const version_entry_st *ver = get_version(session);
147 :
148 13950 : if (data_size == 0 || data_size % 2 != 0)
149 9 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
150 :
151 13944 : if (ver == NULL) { /* assume TLS 1.2 semantics */
152 0 : ver = version_to_entry(GNUTLS_TLS1_2);
153 0 : if (unlikely(ver == NULL)) {
154 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
155 : }
156 : }
157 :
158 13944 : priv = gnutls_calloc(1, sizeof(*priv));
159 13944 : if (priv == NULL) {
160 0 : gnutls_assert();
161 0 : return GNUTLS_E_MEMORY_ERROR;
162 : }
163 :
164 284017 : for (i = 0; i < data_size; i += 2) {
165 270076 : uint8_t id[2];
166 :
167 270076 : id[0] = data[i];
168 270076 : id[1] = data[i + 1];
169 :
170 270076 : sig = _gnutls_tls_aid_to_sign(id[0], id[1], ver);
171 :
172 270076 : _gnutls_handshake_log
173 : ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session,
174 : (int)id[0], (int)id[1],
175 : gnutls_sign_get_name(sig));
176 :
177 270076 : if (sig != GNUTLS_SIGN_UNKNOWN) {
178 139817 : if (priv->sign_algorithms_size == MAX_ALGOS)
179 : break;
180 139814 : priv->sign_algorithms[priv->
181 139814 : sign_algorithms_size++] = sig;
182 : }
183 : }
184 :
185 13944 : epriv = priv;
186 13944 : _gnutls_hello_ext_set_priv(session,
187 : GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
188 : epriv);
189 :
190 13944 : return 0;
191 : }
192 :
193 : /*
194 : * In case of a server: if a SIGNATURE_ALGORITHMS extension type is
195 : * received then it stores into the session security parameters the
196 : * new value.
197 : *
198 : * In case of a client: If a signature_algorithms have been specified
199 : * then it is an error;
200 : */
201 :
202 : static int
203 13825 : _gnutls_signature_algorithm_recv_params(gnutls_session_t session,
204 : const uint8_t * data,
205 : size_t data_size)
206 : {
207 13825 : int ret;
208 :
209 13825 : if (session->security_parameters.entity == GNUTLS_CLIENT) {
210 : /* nothing for now */
211 0 : gnutls_assert();
212 : /* Although TLS 1.2 mandates that we must not accept reply
213 : * to this message, there are good reasons to just ignore it. Check
214 : * https://www.ietf.org/mail-archive/web/tls/current/msg03880.html
215 : */
216 : /* return GNUTLS_E_UNEXPECTED_PACKET; */
217 : } else {
218 : /* SERVER SIDE
219 : */
220 13825 : if (data_size >= 2) {
221 13822 : uint16_t len;
222 :
223 13822 : DECR_LEN(data_size, 2);
224 13822 : len = _gnutls_read_uint16(data);
225 13822 : DECR_LEN(data_size, len);
226 :
227 13465 : if (data_size > 0)
228 19 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
229 :
230 13454 : ret =
231 13454 : _gnutls_sign_algorithm_parse_data(session,
232 : data + 2,
233 : len);
234 13454 : if (ret < 0) {
235 6 : gnutls_assert();
236 6 : return ret;
237 : }
238 : } else {
239 3 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
240 : }
241 : }
242 :
243 : return 0;
244 : }
245 :
246 : /* returns data_size or a negative number on failure
247 : */
248 : static int
249 3784 : _gnutls_signature_algorithm_send_params(gnutls_session_t session,
250 : gnutls_buffer_st * extdata)
251 : {
252 3784 : int ret;
253 3784 : size_t init_length = extdata->length;
254 3784 : const version_entry_st *ver = get_version(session);
255 :
256 3784 : if (unlikely(ver == NULL))
257 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
258 :
259 : /* this function sends the client extension data */
260 3784 : if (session->security_parameters.entity == GNUTLS_CLIENT
261 3784 : && _gnutls_version_has_selectable_sighash(ver)) {
262 3476 : if (session->internals.priorities->sigalg.size > 0) {
263 3476 : ret =
264 3476 : _gnutls_sign_algorithm_write_params(session, extdata);
265 3476 : if (ret < 0)
266 0 : return gnutls_assert_val(ret);
267 :
268 3476 : return extdata->length - init_length;
269 : }
270 : }
271 :
272 : /* if we are here it means we don't send the extension */
273 : return 0;
274 : }
275 :
276 : #ifdef GOST_SIG_FIXUP_SCHANNEL
277 : static bool
278 37 : is_gost_sig_present(sig_ext_st *priv)
279 : {
280 37 : unsigned i;
281 37 : const gnutls_sign_entry_st *se;
282 :
283 599 : for (i = 0; i < priv->sign_algorithms_size; i++) {
284 597 : se = _gnutls_sign_to_entry(priv->sign_algorithms[i]);
285 597 : if (se != NULL && _sign_is_gost(se))
286 : return true;
287 : }
288 :
289 : return false;
290 : }
291 : #endif
292 :
293 : /* Returns a requested by the peer signature algorithm that
294 : * matches the given certificate's public key algorithm.
295 : *
296 : * When the @client_cert flag is not set, then this function will
297 : * also check whether the signature algorithm is allowed to be
298 : * used in that session. Otherwise GNUTLS_SIGN_UNKNOWN is
299 : * returned.
300 : */
301 : gnutls_sign_algorithm_t
302 12624 : _gnutls_session_get_sign_algo(gnutls_session_t session,
303 : gnutls_pcert_st * cert,
304 : gnutls_privkey_t privkey,
305 : unsigned client_cert,
306 : gnutls_kx_algorithm_t kx_algorithm)
307 : {
308 12624 : unsigned i;
309 12624 : int ret;
310 12624 : const version_entry_st *ver = get_version(session);
311 12624 : sig_ext_st *priv;
312 12624 : gnutls_ext_priv_data_t epriv;
313 12624 : unsigned int cert_algo;
314 12624 : const gnutls_sign_entry_st *se;
315 :
316 12624 : if (unlikely(ver == NULL))
317 0 : return gnutls_assert_val(GNUTLS_SIGN_UNKNOWN);
318 :
319 12624 : cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
320 :
321 12624 : ret =
322 12624 : _gnutls_hello_ext_get_priv(session,
323 : GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
324 : &epriv);
325 12624 : if (ret < 0)
326 : priv = NULL;
327 : else
328 12010 : priv = epriv;
329 :
330 : #ifdef GOST_SIG_FIXUP_SCHANNEL
331 : /*
332 : * Some (all SChannel) clients fail to send proper SigAlgs due to Micro$oft crazyness.
333 : * If we are negotiating GOST KX (because we have received GOST
334 : * ciphersuites) and if we have received no GOST SignatureAlgorithms,
335 : * assume that the client could not send them and continue negotiation
336 : * as if correct algorithm was sent.
337 : */
338 12624 : if (_gnutls_kx_is_vko_gost(kx_algorithm) &&
339 37 : (!priv ||
340 37 : !is_gost_sig_present(priv) ||
341 35 : !_gnutls_version_has_selectable_sighash(ver))) {
342 2 : gnutls_digest_algorithm_t dig;
343 :
344 2 : _gnutls_handshake_log("EXT[%p]: GOST KX, but no GOST SigAlgs received, patching up.", session);
345 :
346 2 : if (cert_algo == GNUTLS_PK_GOST_01)
347 : dig = GNUTLS_DIG_GOSTR_94;
348 2 : else if (cert_algo == GNUTLS_PK_GOST_12_256)
349 : dig = GNUTLS_DIG_STREEBOG_256;
350 1 : else if (cert_algo == GNUTLS_PK_GOST_12_512)
351 : dig = GNUTLS_DIG_STREEBOG_512;
352 : else
353 0 : dig = GNUTLS_DIG_SHA1;
354 :
355 2 : ret = gnutls_pk_to_sign(cert_algo, dig);
356 :
357 2 : if (!client_cert && _gnutls_session_sign_algo_enabled(session, ret) < 0)
358 0 : goto fail;
359 2 : return ret;
360 : }
361 : #endif
362 :
363 12622 : if (!priv || !_gnutls_version_has_selectable_sighash(ver)) {
364 : /* none set, allow SHA-1 only */
365 614 : ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1);
366 :
367 614 : if (!client_cert && _gnutls_session_sign_algo_enabled(session, ret) < 0)
368 20 : goto fail;
369 594 : return ret;
370 : }
371 :
372 :
373 :
374 30755 : for (i = 0; i < priv->sign_algorithms_size; i++) {
375 28234 : se = _gnutls_sign_to_entry(priv->sign_algorithms[i]);
376 28234 : if (se == NULL)
377 0 : continue;
378 :
379 28234 : _gnutls_handshake_log("checking cert compat with %s\n", se->name);
380 :
381 28234 : if (_gnutls_privkey_compatible_with_sig(privkey, priv->sign_algorithms[i]) == 0)
382 9631 : continue;
383 :
384 37350 : if (sign_supports_cert_pk_algorithm(se, cert_algo) != 0) {
385 10771 : if (_gnutls_pubkey_compatible_with_sig
386 : (session, cert->pubkey, ver, se->id) < 0)
387 68 : continue;
388 :
389 10703 : if (_gnutls_session_sign_algo_enabled
390 : (session, se->id) < 0)
391 1216 : continue;
392 :
393 9487 : return se->id;
394 : }
395 : }
396 :
397 : /* When having a legacy client certificate which can only be signed
398 : * using algorithms we don't always enable by default (e.g., DSA-SHA1),
399 : * continue and sign with it. */
400 2521 : if (client_cert) {
401 1 : _gnutls_audit_log(session, "No shared signature schemes with peer for client certificate (%s). Is the certificate a legacy one?\n",
402 : gnutls_pk_get_name(cert_algo));
403 : }
404 :
405 2520 : fail:
406 : return GNUTLS_SIGN_UNKNOWN;
407 : }
408 :
409 : /* Check if the given signature algorithm is supported.
410 : * This means that it is enabled by the priority functions,
411 : * and in case of a server a matching certificate exists.
412 : */
413 : int
414 13756 : _gnutls_session_sign_algo_enabled(gnutls_session_t session,
415 : gnutls_sign_algorithm_t sig)
416 : {
417 13756 : unsigned i;
418 13756 : const version_entry_st *ver = get_version(session);
419 :
420 13756 : if (unlikely(ver == NULL))
421 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
422 :
423 13756 : if (!_gnutls_version_has_selectable_sighash(ver)) {
424 : return 0;
425 : }
426 :
427 13676 : if (ver->tls13_sem) {
428 : /* disallow RSA, DSA, and SHA1 */
429 9534 : const gnutls_sign_entry_st *se;
430 :
431 9534 : se = _gnutls_sign_to_entry(sig);
432 9534 : if (se == NULL || (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0) {
433 1231 : gnutls_assert();
434 1231 : goto disallowed;
435 : }
436 : }
437 :
438 40372 : for (i = 0; i < session->internals.priorities->sigalg.size; i++) {
439 40367 : if (session->internals.priorities->sigalg.entry[i]->id == sig) {
440 : return 0; /* ok */
441 : }
442 : }
443 :
444 5 : disallowed:
445 1236 : _gnutls_handshake_log("Signature algorithm %s is not enabled\n", gnutls_sign_algorithm_get_name(sig));
446 : return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
447 : }
448 :
449 15070 : static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv)
450 : {
451 15070 : gnutls_free(priv);
452 15070 : }
453 :
454 : static int
455 4084 : signature_algorithms_pack(gnutls_ext_priv_data_t epriv,
456 : gnutls_buffer_st * ps)
457 : {
458 4084 : sig_ext_st *priv = epriv;
459 4084 : int ret, i;
460 :
461 4084 : BUFFER_APPEND_NUM(ps, priv->sign_algorithms_size);
462 62505 : for (i = 0; i < priv->sign_algorithms_size; i++) {
463 58421 : BUFFER_APPEND_NUM(ps, priv->sign_algorithms[i]);
464 : }
465 : return 0;
466 : }
467 :
468 : static int
469 1170 : signature_algorithms_unpack(gnutls_buffer_st * ps,
470 : gnutls_ext_priv_data_t * _priv)
471 : {
472 1170 : sig_ext_st *priv;
473 1170 : int i, ret;
474 1170 : gnutls_ext_priv_data_t epriv;
475 :
476 1170 : priv = gnutls_calloc(1, sizeof(*priv));
477 1170 : if (priv == NULL) {
478 0 : gnutls_assert();
479 0 : return GNUTLS_E_MEMORY_ERROR;
480 : }
481 :
482 1170 : BUFFER_POP_NUM(ps, priv->sign_algorithms_size);
483 19916 : for (i = 0; i < priv->sign_algorithms_size; i++) {
484 18746 : BUFFER_POP_NUM(ps, priv->sign_algorithms[i]);
485 : }
486 :
487 1170 : epriv = priv;
488 1170 : *_priv = epriv;
489 :
490 1170 : return 0;
491 :
492 0 : error:
493 0 : gnutls_free(priv);
494 0 : return ret;
495 : }
496 :
497 :
498 :
499 : /**
500 : * gnutls_sign_algorithm_get_requested:
501 : * @session: is a #gnutls_session_t type.
502 : * @indx: is an index of the signature algorithm to return
503 : * @algo: the returned certificate type will be stored there
504 : *
505 : * Returns the signature algorithm specified by index that was
506 : * requested by the peer. If the specified index has no data available
507 : * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If
508 : * the negotiated TLS version does not support signature algorithms
509 : * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
510 : * for the first index. The first index is 0.
511 : *
512 : * This function is useful in the certificate callback functions
513 : * to assist in selecting the correct certificate.
514 : *
515 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
516 : * an error code is returned.
517 : *
518 : * Since: 2.10.0
519 : **/
520 : int
521 0 : gnutls_sign_algorithm_get_requested(gnutls_session_t session,
522 : size_t indx,
523 : gnutls_sign_algorithm_t * algo)
524 : {
525 0 : const version_entry_st *ver = get_version(session);
526 0 : sig_ext_st *priv;
527 0 : gnutls_ext_priv_data_t epriv;
528 0 : int ret;
529 :
530 0 : if (unlikely(ver == NULL))
531 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
532 :
533 0 : ret =
534 0 : _gnutls_hello_ext_get_priv(session,
535 : GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
536 : &epriv);
537 0 : if (ret < 0) {
538 0 : gnutls_assert();
539 0 : return ret;
540 : }
541 0 : priv = epriv;
542 :
543 0 : if (!_gnutls_version_has_selectable_sighash(ver)
544 0 : || priv->sign_algorithms_size == 0) {
545 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
546 : }
547 :
548 0 : if (indx < priv->sign_algorithms_size) {
549 0 : *algo = priv->sign_algorithms[indx];
550 0 : return 0;
551 : } else
552 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
553 : }
554 :
555 : /**
556 : * gnutls_sign_algorithm_get:
557 : * @session: is a #gnutls_session_t type.
558 : *
559 : * Returns the signature algorithm that is (or will be) used in this
560 : * session by the server to sign data. This function should be
561 : * used only with TLS 1.2 or later.
562 : *
563 : * Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN.
564 : *
565 : * Since: 3.1.1
566 : **/
567 24522 : int gnutls_sign_algorithm_get(gnutls_session_t session)
568 : {
569 24522 : return session->security_parameters.server_sign_algo;
570 : }
571 :
572 : /**
573 : * gnutls_sign_algorithm_get_client:
574 : * @session: is a #gnutls_session_t type.
575 : *
576 : * Returns the signature algorithm that is (or will be) used in this
577 : * session by the client to sign data. This function should be
578 : * used only with TLS 1.2 or later.
579 : *
580 : * Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN.
581 : *
582 : * Since: 3.1.11
583 : **/
584 6419 : int gnutls_sign_algorithm_get_client(gnutls_session_t session)
585 : {
586 6419 : return session->security_parameters.client_sign_algo;
587 : }
|