Line data Source code
1 : /*
2 : * Copyright (C) 2017-2019 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 : #include "gnutls_int.h"
24 : #include "errors.h"
25 : #include <auth/cert.h>
26 : #include <algorithms.h>
27 : #include <ext/signature.h>
28 : #include <abstract_int.h>
29 : #include "tls13-sig.h"
30 : #include "tls-sig.h"
31 : #include "hash_int.h"
32 :
33 : #undef PREFIX_SIZE
34 : #define PREFIX_SIZE 64
35 : #if PREFIX_SIZE < MAX_HASH_SIZE
36 : /* we assume later that prefix is sufficient to store hash output */
37 : # error Need to modify code
38 : #endif
39 :
40 : int
41 568 : _gnutls13_handshake_verify_data(gnutls_session_t session,
42 : unsigned verify_flags,
43 : gnutls_pcert_st *cert,
44 : const gnutls_datum_t *context,
45 : const gnutls_datum_t *signature,
46 : const gnutls_sign_entry_st *se)
47 : {
48 568 : int ret;
49 568 : const version_entry_st *ver = get_version(session);
50 568 : gnutls_buffer_st buf;
51 568 : uint8_t prefix[PREFIX_SIZE];
52 568 : unsigned key_usage = 0;
53 568 : gnutls_datum_t p;
54 :
55 568 : _gnutls_handshake_log
56 : ("HSK[%p]: verifying TLS 1.3 handshake data using %s\n", session,
57 : se->name);
58 :
59 568 : ret =
60 568 : _gnutls_pubkey_compatible_with_sig(session,
61 : cert->pubkey, ver,
62 : se->id);
63 568 : if (ret < 0)
64 0 : return gnutls_assert_val(ret);
65 :
66 1136 : if (unlikely(sign_supports_cert_pk_algorithm(se, cert->pubkey->params.algo) == 0)) {
67 0 : _gnutls_handshake_log("HSK[%p]: certificate of %s cannot be combined with %s sig\n",
68 : session, gnutls_pk_get_name(cert->pubkey->params.algo), se->name);
69 0 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
70 : }
71 :
72 568 : ret =
73 568 : _gnutls_session_sign_algo_enabled(session, se->id);
74 568 : if (ret < 0)
75 0 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
76 :
77 568 : if ((se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0) /* explicitly prohibited */
78 0 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
79 :
80 568 : gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
81 :
82 568 : ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
83 568 : if (ret < 0)
84 2 : return gnutls_assert_val(ret);
85 :
86 566 : _gnutls_buffer_init(&buf);
87 :
88 566 : memset(prefix, 0x20, sizeof(prefix));
89 566 : ret = _gnutls_buffer_append_data(&buf, prefix, sizeof(prefix));
90 566 : if (ret < 0) {
91 0 : gnutls_assert();
92 0 : goto cleanup;
93 : }
94 :
95 566 : ret = _gnutls_buffer_append_data(&buf, context->data, context->size);
96 566 : if (ret < 0) {
97 0 : gnutls_assert();
98 0 : goto cleanup;
99 : }
100 :
101 566 : ret = _gnutls_buffer_append_data(&buf, "\x00", 1);
102 566 : if (ret < 0) {
103 0 : gnutls_assert();
104 0 : goto cleanup;
105 : }
106 :
107 566 : ret = gnutls_hash_fast(MAC_TO_DIG(session->security_parameters.prf->id),
108 566 : session->internals.handshake_hash_buffer.data,
109 566 : session->internals.handshake_hash_buffer_prev_len,
110 : prefix);
111 566 : if (ret < 0) {
112 0 : gnutls_assert();
113 0 : goto cleanup;
114 : }
115 :
116 566 : ret = _gnutls_buffer_append_data(&buf, prefix, session->security_parameters.prf->output_size);
117 566 : if (ret < 0) {
118 0 : gnutls_assert();
119 0 : goto cleanup;
120 : }
121 :
122 566 : p.data = buf.data;
123 566 : p.size = buf.length;
124 :
125 : /* Here we intentionally enable flag GNUTLS_VERIFY_ALLOW_BROKEN
126 : * because we have checked whether the currently used signature
127 : * algorithm is allowed in the session. */
128 566 : ret = gnutls_pubkey_verify_data2(cert->pubkey, se->id,
129 : verify_flags|GNUTLS_VERIFY_ALLOW_BROKEN,
130 : &p, signature);
131 566 : if (ret < 0) {
132 0 : gnutls_assert();
133 0 : goto cleanup;
134 : }
135 :
136 : ret = 0;
137 566 : cleanup:
138 566 : _gnutls_buffer_clear(&buf);
139 :
140 566 : return ret;
141 : }
142 :
143 : int
144 3760 : _gnutls13_handshake_sign_data(gnutls_session_t session,
145 : gnutls_pcert_st * cert, gnutls_privkey_t pkey,
146 : const gnutls_datum_t *context,
147 : gnutls_datum_t * signature,
148 : const gnutls_sign_entry_st *se)
149 : {
150 3760 : gnutls_datum_t p;
151 3760 : int ret;
152 3760 : gnutls_buffer_st buf;
153 3760 : uint8_t tmp[MAX_HASH_SIZE];
154 :
155 3760 : if (unlikely(se == NULL || (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0))
156 0 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
157 :
158 7520 : if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) == 0))
159 0 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
160 :
161 : /* when we reach here we know we have a signing certificate */
162 3760 : _gnutls_handshake_log
163 : ("HSK[%p]: signing TLS 1.3 handshake data: using %s and PRF: %s\n", session, se->name,
164 : session->security_parameters.prf->name);
165 :
166 3760 : _gnutls_buffer_init(&buf);
167 :
168 3760 : ret = _gnutls_buffer_resize(&buf, PREFIX_SIZE);
169 3760 : if (ret < 0) {
170 0 : gnutls_assert();
171 0 : goto cleanup;
172 : }
173 :
174 3760 : memset(buf.data, 0x20, PREFIX_SIZE);
175 3760 : buf.length += PREFIX_SIZE;
176 :
177 3760 : ret = _gnutls_buffer_append_data(&buf, context->data, context->size);
178 3760 : if (ret < 0) {
179 0 : gnutls_assert();
180 0 : goto cleanup;
181 : }
182 :
183 3760 : ret = _gnutls_buffer_append_data(&buf, "\x00", 1);
184 3760 : if (ret < 0) {
185 0 : gnutls_assert();
186 0 : goto cleanup;
187 : }
188 :
189 3760 : ret = gnutls_hash_fast(MAC_TO_DIG(session->security_parameters.prf->id),
190 3760 : session->internals.handshake_hash_buffer.data,
191 : session->internals.handshake_hash_buffer.length,
192 : tmp);
193 3760 : if (ret < 0) {
194 0 : gnutls_assert();
195 0 : goto cleanup;
196 : }
197 :
198 3760 : ret = _gnutls_buffer_append_data(&buf, tmp, session->security_parameters.prf->output_size);
199 3760 : if (ret < 0) {
200 0 : gnutls_assert();
201 0 : goto cleanup;
202 : }
203 :
204 3760 : p.data = buf.data;
205 3760 : p.size = buf.length;
206 :
207 3760 : ret = gnutls_privkey_sign_data2(pkey, se->id, 0, &p, signature);
208 3760 : if (ret < 0) {
209 0 : gnutls_assert();
210 0 : goto cleanup;
211 : }
212 :
213 : ret = 0;
214 3760 : cleanup:
215 3760 : _gnutls_buffer_clear(&buf);
216 :
217 3760 : return ret;
218 :
219 : }
|