1 /*
2  * Copyright (C) 2015-2016 Red Hat, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
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 2.1 of
11  * the License, or (at your option) any later version.
12  *
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.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>
20  *
21  */
22 
23 /* Functions that relate to the TLS handshake procedure.
24  */
25 
26 #include "gnutls_int.h"
27 #include "errors.h"
28 #include "debug.h"
29 #include "handshake.h"
30 #include <auth/cert.h>
31 #include "constate.h"
32 #include <record.h>
33 #include <state.h>
34 #include <ext/safe_renegotiation.h>
35 #include <auth/anon.h>		/* for gnutls_anon_server_credentials_t */
36 #include <auth/psk.h>		/* for gnutls_psk_server_credentials_t */
37 #ifdef ENABLE_SRP
38 # include <auth/srp_kx.h>
39 #endif
40 
_gnutls_check_id_for_change(gnutls_session_t session)41 int _gnutls_check_id_for_change(gnutls_session_t session)
42 {
43 	int cred_type;
44 
45 	/* This checks in PSK and SRP ciphersuites that the username remained the
46 	 * same on a rehandshake. */
47 	if (session->internals.flags & GNUTLS_ALLOW_ID_CHANGE)
48 		return 0;
49 
50 	cred_type = gnutls_auth_get_type(session);
51 	if (cred_type == GNUTLS_CRD_PSK || cred_type == GNUTLS_CRD_SRP) {
52 		const char *username = NULL;
53 		int username_length;
54 
55 		if (cred_type == GNUTLS_CRD_PSK) {
56 			psk_auth_info_t ai;
57 
58 			ai = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
59 			if (ai == NULL)
60 				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
61 
62 			username = ai->username;
63 			username_length = ai->username_len;
64 #ifdef ENABLE_SRP
65 		} else {
66 			srp_server_auth_info_t ai = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
67 			if (ai == NULL)
68 				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
69 
70 			username = ai->username;
71 			username_length = strlen(ai->username);
72 #endif
73 		}
74 
75 		if (username == NULL)
76 			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
77 
78 		if (session->internals.saved_username_size != -1) {
79 			if (session->internals.saved_username_size == username_length &&
80 			    strncmp(session->internals.saved_username, username, username_length) != 0) {
81 				_gnutls_debug_log("Session's PSK username changed during rehandshake; aborting!\n");
82 				return gnutls_assert_val(GNUTLS_E_SESSION_USER_ID_CHANGED);
83 			}
84 		} else {
85 			memcpy(session->internals.saved_username, username, username_length);
86 			session->internals.saved_username[username_length] = 0;
87 			session->internals.saved_username_size = username_length;
88 		}
89 	}
90 
91 	return 0;
92 }
93 
_gnutls_check_if_cert_hash_is_same(gnutls_session_t session,gnutls_certificate_credentials_t cred)94 int _gnutls_check_if_cert_hash_is_same(gnutls_session_t session, gnutls_certificate_credentials_t cred)
95 {
96 	cert_auth_info_t ai;
97 	char tmp[32];
98 	int ret;
99 
100 	if (session->internals.flags & GNUTLS_ALLOW_ID_CHANGE)
101 		return 0;
102 
103 	ai = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
104 	if (ai == NULL || ai->ncerts == 0)
105 		return 0;
106 
107 	ret = gnutls_hash_fast(GNUTLS_DIG_SHA256,
108 			       ai->raw_certificate_list[0].data,
109 			       ai->raw_certificate_list[0].size,
110 			       tmp);
111 	if (ret < 0)
112 		return gnutls_assert_val(ret);
113 
114 	if (session->internals.cert_hash_set) {
115 		if (memcmp(tmp, session->internals.cert_hash, 32) != 0) {
116 			_gnutls_debug_log("Session certificate changed during rehandshake; aborting!\n");
117 			return gnutls_assert_val(GNUTLS_E_SESSION_USER_ID_CHANGED);
118 		}
119 	} else {
120 		memcpy(session->internals.cert_hash, tmp, 32);
121 		session->internals.cert_hash_set = 1;
122 	}
123 
124 	return 0;
125 }
126