Line data Source code
1 : /*
2 : * Copyright (C) 2001-2015 Free Software Foundation, Inc.
3 : * Copyright (C) 2015 Nikos Mavrogiannopoulos
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 certificate authentication functions to be exported in the
25 : * API which did not fit elsewhere.
26 : */
27 :
28 : #include "gnutls_int.h"
29 : #include <auth/srp_kx.h>
30 : #include <auth/anon.h>
31 : #include <auth/cert.h>
32 : #include <auth/psk.h>
33 : #include "errors.h"
34 : #include <auth.h>
35 : #include <state.h>
36 : #include <datum.h>
37 : #include <algorithms.h>
38 :
39 : /* ANON & DHE */
40 :
41 : #if defined(ENABLE_DHE) || defined(ENABLE_ANON)
42 : /**
43 : * gnutls_dh_set_prime_bits:
44 : * @session: is a #gnutls_session_t type.
45 : * @bits: is the number of bits
46 : *
47 : * This function sets the number of bits, for use in a Diffie-Hellman
48 : * key exchange. This is used both in DH ephemeral and DH anonymous
49 : * cipher suites. This will set the minimum size of the prime that
50 : * will be used for the handshake.
51 : *
52 : * In the client side it sets the minimum accepted number of bits. If
53 : * a server sends a prime with less bits than that
54 : * %GNUTLS_E_DH_PRIME_UNACCEPTABLE will be returned by the handshake.
55 : *
56 : * Note that this function will warn via the audit log for value that
57 : * are believed to be weak.
58 : *
59 : * The function has no effect in server side.
60 : *
61 : * Note that since 3.1.7 this function is deprecated. The minimum
62 : * number of bits is set by the priority string level.
63 : * Also this function must be called after gnutls_priority_set_direct()
64 : * or the set value may be overridden by the selected priority options.
65 : *
66 : *
67 : **/
68 1974 : void gnutls_dh_set_prime_bits(gnutls_session_t session, unsigned int bits)
69 : {
70 1974 : if (bits < gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_WEAK)
71 0 : && bits != 0)
72 0 : _gnutls_audit_log(session,
73 : "Note that the security level of the Diffie-Hellman key exchange has been lowered to %u bits and this may allow decryption of the session data\n",
74 : bits);
75 1974 : session->internals.dh_prime_bits = bits;
76 1974 : }
77 :
78 :
79 : /**
80 : * gnutls_dh_get_group:
81 : * @session: is a gnutls session
82 : * @raw_gen: will hold the generator.
83 : * @raw_prime: will hold the prime.
84 : *
85 : * This function will return the group parameters used in the last
86 : * Diffie-Hellman key exchange with the peer. These are the prime and
87 : * the generator used. This function should be used for both
88 : * anonymous and ephemeral Diffie-Hellman. The output parameters must
89 : * be freed with gnutls_free().
90 : *
91 : * Note, that the prime and generator are exported as non-negative
92 : * integers and may include a leading zero byte.
93 : *
94 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
95 : * an error code is returned.
96 : **/
97 : int
98 1004 : gnutls_dh_get_group(gnutls_session_t session,
99 : gnutls_datum_t * raw_gen, gnutls_datum_t * raw_prime)
100 : {
101 1004 : dh_info_st *dh;
102 1004 : int ret;
103 1004 : anon_auth_info_t anon_info;
104 1004 : cert_auth_info_t cert_info;
105 1004 : psk_auth_info_t psk_info;
106 :
107 1004 : switch (gnutls_auth_get_type(session)) {
108 : case GNUTLS_CRD_ANON:
109 0 : anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
110 0 : if (anon_info == NULL)
111 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
112 0 : dh = &anon_info->dh;
113 0 : break;
114 : case GNUTLS_CRD_PSK:
115 2 : psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
116 2 : if (psk_info == NULL)
117 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
118 2 : dh = &psk_info->dh;
119 2 : break;
120 : case GNUTLS_CRD_CERTIFICATE:
121 1002 : cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
122 1002 : if (cert_info == NULL)
123 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
124 1002 : dh = &cert_info->dh;
125 1002 : break;
126 0 : default:
127 0 : gnutls_assert();
128 : return GNUTLS_E_INVALID_REQUEST;
129 : }
130 :
131 1004 : ret = _gnutls_set_datum(raw_prime, dh->prime.data, dh->prime.size);
132 1004 : if (ret < 0) {
133 0 : gnutls_assert();
134 0 : return ret;
135 : }
136 :
137 1004 : ret =
138 2008 : _gnutls_set_datum(raw_gen, dh->generator.data,
139 1004 : dh->generator.size);
140 1004 : if (ret < 0) {
141 0 : gnutls_assert();
142 0 : _gnutls_free_datum(raw_prime);
143 0 : return ret;
144 : }
145 :
146 : return 0;
147 : }
148 :
149 : /**
150 : * gnutls_dh_get_pubkey:
151 : * @session: is a gnutls session
152 : * @raw_key: will hold the public key.
153 : *
154 : * This function will return the peer's public key used in the last
155 : * Diffie-Hellman key exchange. This function should be used for both
156 : * anonymous and ephemeral Diffie-Hellman. The output parameters must
157 : * be freed with gnutls_free().
158 : *
159 : * Note, that public key is exported as non-negative
160 : * integer and may include a leading zero byte.
161 : *
162 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
163 : * an error code is returned.
164 : **/
165 : int
166 9 : gnutls_dh_get_pubkey(gnutls_session_t session, gnutls_datum_t * raw_key)
167 : {
168 9 : dh_info_st *dh;
169 9 : anon_auth_info_t anon_info;
170 9 : cert_auth_info_t cert_info;
171 9 : psk_auth_info_t psk_info;
172 :
173 9 : switch (gnutls_auth_get_type(session)) {
174 : case GNUTLS_CRD_ANON:
175 : {
176 0 : anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
177 0 : if (anon_info == NULL)
178 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
179 0 : dh = &anon_info->dh;
180 0 : break;
181 : }
182 : case GNUTLS_CRD_PSK:
183 : {
184 2 : psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
185 2 : if (psk_info == NULL)
186 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
187 2 : dh = &psk_info->dh;
188 2 : break;
189 : }
190 : case GNUTLS_CRD_CERTIFICATE:
191 : {
192 :
193 6 : cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
194 6 : if (cert_info == NULL)
195 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
196 6 : dh = &cert_info->dh;
197 6 : break;
198 : }
199 1 : default:
200 1 : gnutls_assert();
201 : return GNUTLS_E_INVALID_REQUEST;
202 : }
203 :
204 8 : return _gnutls_set_datum(raw_key, dh->public_key.data,
205 8 : dh->public_key.size);
206 : }
207 :
208 : /**
209 : * gnutls_dh_get_secret_bits:
210 : * @session: is a gnutls session
211 : *
212 : * This function will return the bits used in the last Diffie-Hellman
213 : * key exchange with the peer. Should be used for both anonymous and
214 : * ephemeral Diffie-Hellman.
215 : *
216 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
217 : * an error code is returned.
218 : **/
219 1004 : int gnutls_dh_get_secret_bits(gnutls_session_t session)
220 : {
221 1004 : switch (gnutls_auth_get_type(session)) {
222 : case GNUTLS_CRD_ANON:
223 : {
224 0 : anon_auth_info_t info;
225 :
226 0 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
227 0 : if (info == NULL)
228 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
229 0 : return info->dh.secret_bits;
230 : }
231 : case GNUTLS_CRD_PSK:
232 : {
233 2 : psk_auth_info_t info;
234 :
235 2 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
236 2 : if (info == NULL)
237 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
238 2 : return info->dh.secret_bits;
239 : }
240 : case GNUTLS_CRD_CERTIFICATE:
241 : {
242 1002 : cert_auth_info_t info;
243 :
244 1002 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
245 1002 : if (info == NULL)
246 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
247 :
248 1002 : return info->dh.secret_bits;
249 : }
250 0 : default:
251 0 : gnutls_assert();
252 : return GNUTLS_E_INVALID_REQUEST;
253 : }
254 : }
255 :
256 :
257 3044 : static int mpi_buf2bits(gnutls_datum_t * mpi_buf)
258 : {
259 3044 : bigint_t mpi;
260 3044 : int rc;
261 :
262 3044 : rc = _gnutls_mpi_init_scan_nz(&mpi, mpi_buf->data, mpi_buf->size);
263 3044 : if (rc) {
264 0 : gnutls_assert();
265 0 : return rc;
266 : }
267 :
268 3044 : rc = _gnutls_mpi_get_nbits(mpi);
269 3044 : _gnutls_mpi_release(&mpi);
270 :
271 : return rc;
272 : }
273 :
274 : /**
275 : * gnutls_dh_get_prime_bits:
276 : * @session: is a gnutls session
277 : *
278 : * This function will return the bits of the prime used in the last
279 : * Diffie-Hellman key exchange with the peer. Should be used for both
280 : * anonymous and ephemeral Diffie-Hellman. Note that some ciphers,
281 : * like RSA and DSA without DHE, do not use a Diffie-Hellman key
282 : * exchange, and then this function will return 0.
283 : *
284 : * Returns: The Diffie-Hellman bit strength is returned, or 0 if no
285 : * Diffie-Hellman key exchange was done, or a negative error code on
286 : * failure.
287 : **/
288 2385 : int gnutls_dh_get_prime_bits(gnutls_session_t session)
289 : {
290 2385 : dh_info_st *dh;
291 :
292 2385 : switch (gnutls_auth_get_type(session)) {
293 : case GNUTLS_CRD_ANON:
294 : {
295 0 : anon_auth_info_t info;
296 :
297 0 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
298 0 : if (info == NULL)
299 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
300 0 : dh = &info->dh;
301 0 : break;
302 : }
303 : case GNUTLS_CRD_PSK:
304 : {
305 2 : psk_auth_info_t info;
306 :
307 2 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
308 2 : if (info == NULL)
309 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
310 2 : dh = &info->dh;
311 2 : break;
312 : }
313 : case GNUTLS_CRD_CERTIFICATE:
314 : {
315 2042 : cert_auth_info_t info;
316 :
317 2042 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
318 2042 : if (info == NULL)
319 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
320 :
321 2042 : dh = &info->dh;
322 2042 : break;
323 : }
324 341 : default:
325 341 : gnutls_assert();
326 : return GNUTLS_E_INVALID_REQUEST;
327 : }
328 :
329 2044 : if(dh->prime.size == 0)
330 : return 0;
331 :
332 2044 : return mpi_buf2bits(&dh->prime);
333 : }
334 :
335 :
336 : /**
337 : * gnutls_dh_get_peers_public_bits:
338 : * @session: is a gnutls session
339 : *
340 : * Get the Diffie-Hellman public key bit size. Can be used for both
341 : * anonymous and ephemeral Diffie-Hellman.
342 : *
343 : * Returns: The public key bit size used in the last Diffie-Hellman
344 : * key exchange with the peer, or a negative error code in case of error.
345 : **/
346 1000 : int gnutls_dh_get_peers_public_bits(gnutls_session_t session)
347 : {
348 1000 : dh_info_st *dh;
349 :
350 1000 : switch (gnutls_auth_get_type(session)) {
351 : case GNUTLS_CRD_ANON:
352 : {
353 0 : anon_auth_info_t info;
354 :
355 0 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
356 0 : if (info == NULL)
357 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
358 :
359 0 : dh = &info->dh;
360 0 : break;
361 : }
362 : case GNUTLS_CRD_PSK:
363 : {
364 0 : psk_auth_info_t info;
365 :
366 0 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
367 0 : if (info == NULL)
368 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
369 :
370 0 : dh = &info->dh;
371 0 : break;
372 : }
373 : case GNUTLS_CRD_CERTIFICATE:
374 : {
375 1000 : cert_auth_info_t info;
376 :
377 1000 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
378 1000 : if (info == NULL)
379 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
380 :
381 1000 : dh = &info->dh;
382 1000 : break;
383 : }
384 0 : default:
385 0 : gnutls_assert();
386 : return GNUTLS_E_INVALID_REQUEST;
387 : }
388 :
389 1000 : return mpi_buf2bits(&dh->public_key);
390 : }
391 :
392 : #endif /* DH */
393 :
|