/src/gnutls/lib/cert-cred.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-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 | | /* Some of the stuff needed for Certificate authentication is contained |
25 | | * in this file. |
26 | | */ |
27 | | |
28 | | #include "gnutls_int.h" |
29 | | #include "errors.h" |
30 | | #include <auth/cert.h> |
31 | | #include <datum.h> |
32 | | #include <mpi.h> |
33 | | #include <global.h> |
34 | | #include <algorithms.h> |
35 | | #include <dh.h> |
36 | | #include "str.h" |
37 | | #include <state.h> |
38 | | #include <auth.h> |
39 | | #include <x509.h> |
40 | | #include <str_array.h> |
41 | | #include <x509/verify-high.h> |
42 | | #include "x509/x509_int.h" |
43 | | #include "x509/common.h" |
44 | | #include "dh.h" |
45 | | #include "cert-cred.h" |
46 | | #include "intprops.h" |
47 | | |
48 | | /* |
49 | | * Adds a public/private key pair to a certificate credential |
50 | | */ |
51 | | int |
52 | | _gnutls_certificate_credential_append_keypair(gnutls_certificate_credentials_t |
53 | | res, gnutls_privkey_t key, |
54 | | gnutls_str_array_t names, |
55 | | gnutls_pcert_st * crt, int nr) |
56 | 0 | { |
57 | 0 | if (unlikely(INT_ADD_OVERFLOW(res->ncerts, 1))) { |
58 | 0 | return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); |
59 | 0 | } |
60 | | |
61 | 0 | res->sorted_cert_idx = _gnutls_reallocarray_fast(res->sorted_cert_idx, |
62 | 0 | res->ncerts + 1, |
63 | 0 | sizeof(unsigned int)); |
64 | 0 | if (res->sorted_cert_idx == NULL) |
65 | 0 | return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); |
66 | | |
67 | 0 | res->certs = _gnutls_reallocarray_fast(res->certs, |
68 | 0 | res->ncerts + 1, |
69 | 0 | sizeof(certs_st)); |
70 | 0 | if (res->certs == NULL) |
71 | 0 | return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); |
72 | | |
73 | 0 | memset(&res->certs[res->ncerts], 0, sizeof(res->certs[0])); |
74 | |
|
75 | 0 | res->certs[res->ncerts].cert_list = crt; |
76 | 0 | res->certs[res->ncerts].cert_list_length = nr; |
77 | 0 | res->certs[res->ncerts].names = names; |
78 | 0 | res->certs[res->ncerts].pkey = key; |
79 | |
|
80 | 0 | if (_gnutls13_sign_get_compatible_with_privkey(key)) |
81 | 0 | res->tls13_ok = 1; |
82 | | |
83 | | /* move RSA-PSS certificates before any RSA key. |
84 | | * Note that we cannot assume that any previous pointers |
85 | | * to sorted list are ok, due to the realloc in res->certs. */ |
86 | 0 | if (crt->pubkey->params.algo == GNUTLS_PK_RSA_PSS) { |
87 | 0 | unsigned i, ridx; |
88 | 0 | unsigned tmp; |
89 | |
|
90 | 0 | for (i = 0; i < res->ncerts; i++) { |
91 | 0 | ridx = res->sorted_cert_idx[i]; |
92 | |
|
93 | 0 | if (res->certs[ridx].cert_list->pubkey->params.algo == |
94 | 0 | GNUTLS_PK_RSA) { |
95 | 0 | tmp = ridx; |
96 | 0 | res->sorted_cert_idx[i] = res->ncerts; |
97 | 0 | res->sorted_cert_idx[res->ncerts] = tmp; |
98 | 0 | goto finish; |
99 | 0 | } |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | /* otherwise append it normally on the end */ |
104 | 0 | res->sorted_cert_idx[res->ncerts] = res->ncerts; |
105 | |
|
106 | 0 | finish: |
107 | 0 | return 0; |
108 | |
|
109 | 0 | } |
110 | | |
111 | | /** |
112 | | * gnutls_certificate_set_key: |
113 | | * @res: is a #gnutls_certificate_credentials_t type. |
114 | | * @names: is an array of DNS names belonging to the public-key (NULL if none) |
115 | | * @names_size: holds the size of the names list |
116 | | * @pcert_list: contains a certificate list (chain) or raw public-key |
117 | | * @pcert_list_size: holds the size of the certificate list |
118 | | * @key: is a #gnutls_privkey_t key corresponding to the first public-key in pcert_list |
119 | | * |
120 | | * This function sets a public/private key pair in the |
121 | | * gnutls_certificate_credentials_t type. The given public key may be encapsulated |
122 | | * in a certificate or can be given as a raw key. This function may be |
123 | | * called more than once, in case multiple key pairs exist for |
124 | | * the server. For clients that want to send more than their own end- |
125 | | * entity certificate (e.g., also an intermediate CA cert), the full |
126 | | * certificate chain must be provided in @pcert_list. |
127 | | * |
128 | | * Note that the @key will become part of the credentials structure and must |
129 | | * not be deallocated. It will be automatically deallocated when the @res structure |
130 | | * is deinitialized. |
131 | | * |
132 | | * If this function fails, the @res structure is at an undefined state and it must |
133 | | * not be reused to load other keys or certificates. |
134 | | * |
135 | | * Note that, this function by default returns zero on success and a negative value on error. |
136 | | * Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags() |
137 | | * it returns an index (greater or equal to zero). That index can be used for other functions to refer to the added key-pair. |
138 | | * |
139 | | * Since GnuTLS 3.6.6 this function also handles raw public keys. |
140 | | * |
141 | | * Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior). |
142 | | * |
143 | | * Since: 3.0 |
144 | | **/ |
145 | | int |
146 | | gnutls_certificate_set_key(gnutls_certificate_credentials_t res, |
147 | | const char **names, |
148 | | int names_size, |
149 | | gnutls_pcert_st * pcert_list, |
150 | | int pcert_list_size, gnutls_privkey_t key) |
151 | 0 | { |
152 | 0 | int ret, i; |
153 | 0 | gnutls_str_array_t str_names; |
154 | 0 | gnutls_pcert_st *new_pcert_list; |
155 | | |
156 | | /* Sanity checks */ |
157 | | // Check for a valid credential struct |
158 | 0 | if (res == NULL) { |
159 | 0 | return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); |
160 | 0 | } |
161 | | // A complete key pair must be given |
162 | 0 | if (pcert_list == NULL || key == NULL) { |
163 | 0 | return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); |
164 | 0 | } |
165 | | |
166 | | /* Process the names, if any */ |
167 | 0 | _gnutls_str_array_init(&str_names); |
168 | |
|
169 | 0 | if (names != NULL && names_size > 0) { |
170 | 0 | for (i = 0; i < names_size; i++) { |
171 | 0 | ret = |
172 | 0 | _gnutls_str_array_append_idna(&str_names, names[i], |
173 | 0 | strlen(names[i])); |
174 | 0 | if (ret < 0) { |
175 | 0 | ret = gnutls_assert_val(ret); |
176 | 0 | goto cleanup; |
177 | 0 | } |
178 | 0 | } |
179 | 0 | } else if (names == NULL && pcert_list[0].type == GNUTLS_CRT_X509) { |
180 | 0 | gnutls_x509_crt_t crt; |
181 | |
|
182 | 0 | ret = gnutls_x509_crt_init(&crt); |
183 | 0 | if (ret < 0) { |
184 | 0 | gnutls_assert(); |
185 | 0 | goto cleanup; |
186 | 0 | } |
187 | | |
188 | 0 | ret = |
189 | 0 | gnutls_x509_crt_import(crt, &pcert_list[0].cert, |
190 | 0 | GNUTLS_X509_FMT_DER); |
191 | 0 | if (ret < 0) { |
192 | 0 | gnutls_assert(); |
193 | 0 | gnutls_x509_crt_deinit(crt); |
194 | 0 | goto cleanup; |
195 | 0 | } |
196 | | |
197 | 0 | ret = _gnutls_get_x509_name(crt, &str_names); |
198 | 0 | gnutls_x509_crt_deinit(crt); |
199 | |
|
200 | 0 | if (ret < 0) { |
201 | 0 | gnutls_assert(); |
202 | 0 | goto cleanup; |
203 | 0 | } |
204 | 0 | } |
205 | | |
206 | 0 | if (res->pin.cb) |
207 | 0 | gnutls_privkey_set_pin_function(key, res->pin.cb, |
208 | 0 | res->pin.data); |
209 | |
|
210 | 0 | new_pcert_list = _gnutls_reallocarray(NULL, pcert_list_size, |
211 | 0 | sizeof(gnutls_pcert_st)); |
212 | 0 | if (new_pcert_list == NULL) { |
213 | 0 | return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); |
214 | 0 | } |
215 | 0 | memcpy(new_pcert_list, pcert_list, |
216 | 0 | sizeof(gnutls_pcert_st) * pcert_list_size); |
217 | |
|
218 | 0 | ret = |
219 | 0 | _gnutls_certificate_credential_append_keypair(res, key, str_names, |
220 | 0 | new_pcert_list, |
221 | 0 | pcert_list_size); |
222 | 0 | if (ret < 0) { |
223 | 0 | gnutls_assert(); |
224 | 0 | gnutls_free(new_pcert_list); |
225 | 0 | goto cleanup; |
226 | 0 | } |
227 | | |
228 | 0 | res->ncerts++; |
229 | | |
230 | | /* Unlike gnutls_certificate_set_x509_key, we deinitialize everything |
231 | | * local after a failure. That is because the caller is responsible for |
232 | | * freeing these values after a failure, and if we keep references we |
233 | | * lead to double freeing */ |
234 | 0 | if ((ret = _gnutls_check_key_cert_match(res)) < 0) { |
235 | 0 | gnutls_assert(); |
236 | 0 | gnutls_free(new_pcert_list); |
237 | 0 | res->ncerts--; |
238 | 0 | goto cleanup; |
239 | 0 | } |
240 | | |
241 | 0 | CRED_RET_SUCCESS(res); |
242 | |
|
243 | 0 | cleanup: |
244 | 0 | _gnutls_str_array_clear(&str_names); |
245 | 0 | return ret; |
246 | 0 | } |
247 | | |
248 | | /** |
249 | | * gnutls_certificate_free_keys: |
250 | | * @sc: is a #gnutls_certificate_credentials_t type. |
251 | | * |
252 | | * This function will delete all the keys and the certificates associated |
253 | | * with the given credentials. This function must not be called when a |
254 | | * TLS negotiation that uses the credentials is in progress. |
255 | | * |
256 | | **/ |
257 | | void gnutls_certificate_free_keys(gnutls_certificate_credentials_t sc) |
258 | 0 | { |
259 | 0 | unsigned i, j; |
260 | |
|
261 | 0 | for (i = 0; i < sc->ncerts; i++) { |
262 | 0 | for (j = 0; j < sc->certs[i].cert_list_length; j++) { |
263 | 0 | gnutls_pcert_deinit(&sc->certs[i].cert_list[j]); |
264 | 0 | } |
265 | 0 | gnutls_free(sc->certs[i].cert_list); |
266 | |
|
267 | 0 | for (j = 0; j < sc->certs[i].ocsp_data_length; j++) { |
268 | 0 | gnutls_free(sc->certs[i].ocsp_data[j].response.data); |
269 | 0 | } |
270 | 0 | _gnutls_str_array_clear(&sc->certs[i].names); |
271 | 0 | gnutls_privkey_deinit(sc->certs[i].pkey); |
272 | 0 | } |
273 | |
|
274 | 0 | gnutls_free(sc->certs); |
275 | 0 | gnutls_free(sc->sorted_cert_idx); |
276 | |
|
277 | 0 | sc->ncerts = 0; |
278 | 0 | } |
279 | | |
280 | | /** |
281 | | * gnutls_certificate_free_cas: |
282 | | * @sc: is a #gnutls_certificate_credentials_t type. |
283 | | * |
284 | | * This function was operational on very early versions of gnutls. |
285 | | * Due to internal refactorings and the fact that this was hardly ever |
286 | | * used, it is currently a no-op. |
287 | | * |
288 | | **/ |
289 | | void gnutls_certificate_free_cas(gnutls_certificate_credentials_t sc) |
290 | 0 | { |
291 | 0 | return; |
292 | 0 | } |
293 | | |
294 | | /** |
295 | | * gnutls_certificate_get_issuer: |
296 | | * @sc: is a #gnutls_certificate_credentials_t type. |
297 | | * @cert: is the certificate to find issuer for |
298 | | * @issuer: Will hold the issuer if any. Should be treated as constant. |
299 | | * @flags: Use zero or %GNUTLS_TL_GET_COPY |
300 | | * |
301 | | * This function will return the issuer of a given certificate. |
302 | | * If the flag %GNUTLS_TL_GET_COPY is specified a copy of the issuer |
303 | | * will be returned which must be freed using gnutls_x509_crt_deinit(). |
304 | | * In that case the provided @issuer must not be initialized. |
305 | | * |
306 | | * As with gnutls_x509_trust_list_get_issuer() this function requires |
307 | | * the %GNUTLS_TL_GET_COPY flag in order to operate with PKCS#11 trust |
308 | | * lists in a thread-safe way. |
309 | | * |
310 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
311 | | * negative error value. |
312 | | * |
313 | | * Since: 3.0 |
314 | | **/ |
315 | | int |
316 | | gnutls_certificate_get_issuer(gnutls_certificate_credentials_t sc, |
317 | | gnutls_x509_crt_t cert, |
318 | | gnutls_x509_crt_t * issuer, unsigned int flags) |
319 | 0 | { |
320 | 0 | return gnutls_x509_trust_list_get_issuer(sc->tlist, cert, issuer, |
321 | 0 | flags); |
322 | 0 | } |
323 | | |
324 | | /** |
325 | | * gnutls_certificate_get_crt_raw: |
326 | | * @sc: is a #gnutls_certificate_credentials_t type. |
327 | | * @idx1: the index of the certificate chain if multiple are present |
328 | | * @idx2: the index of the certificate in the chain. Zero gives the server's certificate. |
329 | | * @cert: Will hold the DER encoded certificate. |
330 | | * |
331 | | * This function will return the DER encoded certificate of the |
332 | | * server or any other certificate on its certificate chain (based on @idx2). |
333 | | * The returned data should be treated as constant and only accessible during the lifetime |
334 | | * of @sc. The @idx1 matches the value gnutls_certificate_set_x509_key() and friends |
335 | | * functions. |
336 | | * |
337 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
338 | | * negative error value. In case the indexes are out of bounds %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE |
339 | | * is returned. |
340 | | * |
341 | | * Since: 3.2.5 |
342 | | **/ |
343 | | int |
344 | | gnutls_certificate_get_crt_raw(gnutls_certificate_credentials_t sc, |
345 | | unsigned idx1, |
346 | | unsigned idx2, gnutls_datum_t * cert) |
347 | 0 | { |
348 | 0 | if (idx1 >= sc->ncerts) |
349 | 0 | return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); |
350 | | |
351 | 0 | if (idx2 >= sc->certs[idx1].cert_list_length) |
352 | 0 | return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); |
353 | | |
354 | 0 | cert->data = sc->certs[idx1].cert_list[idx2].cert.data; |
355 | 0 | cert->size = sc->certs[idx1].cert_list[idx2].cert.size; |
356 | |
|
357 | 0 | return 0; |
358 | 0 | } |
359 | | |
360 | | /** |
361 | | * gnutls_certificate_free_ca_names: |
362 | | * @sc: is a #gnutls_certificate_credentials_t type. |
363 | | * |
364 | | * This function will delete all the CA name in the given |
365 | | * credentials. Clients may call this to save some memory since in |
366 | | * client side the CA names are not used. Servers might want to use |
367 | | * this function if a large list of trusted CAs is present and |
368 | | * sending the names of it would just consume bandwidth without providing |
369 | | * information to client. |
370 | | * |
371 | | * CA names are used by servers to advertise the CAs they support to |
372 | | * clients. |
373 | | **/ |
374 | | void gnutls_certificate_free_ca_names(gnutls_certificate_credentials_t sc) |
375 | 0 | { |
376 | 0 | _gnutls_free_datum(&sc->tlist->x509_rdn_sequence); |
377 | 0 | } |
378 | | |
379 | | /** |
380 | | * gnutls_certificate_free_credentials: |
381 | | * @sc: is a #gnutls_certificate_credentials_t type. |
382 | | * |
383 | | * Free a gnutls_certificate_credentials_t structure. |
384 | | * |
385 | | * This function does not free any temporary parameters associated |
386 | | * with this structure (ie RSA and DH parameters are not freed by this |
387 | | * function). |
388 | | **/ |
389 | | void gnutls_certificate_free_credentials(gnutls_certificate_credentials_t sc) |
390 | 0 | { |
391 | | // Check for valid pointer and otherwise do nothing |
392 | 0 | if (sc == NULL) |
393 | 0 | return; |
394 | | |
395 | 0 | gnutls_x509_trust_list_deinit(sc->tlist, 1); |
396 | 0 | gnutls_certificate_free_keys(sc); |
397 | 0 | memset(sc->pin_tmp, 0, sizeof(sc->pin_tmp)); |
398 | |
|
399 | 0 | if (sc->deinit_dh_params) { |
400 | 0 | gnutls_dh_params_deinit(sc->dh_params); |
401 | 0 | } |
402 | |
|
403 | 0 | gnutls_free(sc); |
404 | 0 | } |
405 | | |
406 | | /** |
407 | | * gnutls_certificate_allocate_credentials: |
408 | | * @res: is a pointer to a #gnutls_certificate_credentials_t type. |
409 | | * |
410 | | * Allocate a gnutls_certificate_credentials_t structure. |
411 | | * |
412 | | * Returns: %GNUTLS_E_SUCCESS on success, or an error code. |
413 | | **/ |
414 | | int |
415 | | gnutls_certificate_allocate_credentials(gnutls_certificate_credentials_t * res) |
416 | 0 | { |
417 | 0 | int ret; |
418 | |
|
419 | 0 | *res = gnutls_calloc(1, sizeof(certificate_credentials_st)); |
420 | |
|
421 | 0 | if (*res == NULL) |
422 | 0 | return GNUTLS_E_MEMORY_ERROR; |
423 | | |
424 | 0 | ret = gnutls_x509_trust_list_init(&(*res)->tlist, 0); |
425 | 0 | if (ret < 0) { |
426 | 0 | gnutls_assert(); |
427 | 0 | gnutls_free(*res); |
428 | 0 | return GNUTLS_E_MEMORY_ERROR; |
429 | 0 | } |
430 | 0 | (*res)->verify_bits = DEFAULT_MAX_VERIFY_BITS; |
431 | 0 | (*res)->verify_depth = DEFAULT_MAX_VERIFY_DEPTH; |
432 | |
|
433 | 0 | return 0; |
434 | 0 | } |
435 | | |
436 | | /* converts the given x509 certificate list to gnutls_pcert_st* and allocates |
437 | | * space for them. |
438 | | */ |
439 | | static gnutls_pcert_st *alloc_and_load_x509_certs(gnutls_x509_crt_t * |
440 | | certs, unsigned ncerts) |
441 | 0 | { |
442 | 0 | gnutls_pcert_st *local_certs; |
443 | 0 | int ret = 0; |
444 | 0 | unsigned i, j; |
445 | |
|
446 | 0 | if (ncerts == 0) { |
447 | 0 | return NULL; |
448 | 0 | } |
449 | | |
450 | 0 | if (unlikely(certs == NULL)) { |
451 | 0 | gnutls_assert(); |
452 | 0 | return NULL; |
453 | 0 | } |
454 | | |
455 | 0 | local_certs = _gnutls_reallocarray(NULL, ncerts, |
456 | 0 | sizeof(gnutls_pcert_st)); |
457 | 0 | if (local_certs == NULL) { |
458 | 0 | gnutls_assert(); |
459 | 0 | return NULL; |
460 | 0 | } |
461 | | |
462 | 0 | for (i = 0; i < ncerts; i++) { |
463 | 0 | ret = gnutls_pcert_import_x509(&local_certs[i], certs[i], 0); |
464 | 0 | if (ret < 0) |
465 | 0 | break; |
466 | 0 | } |
467 | |
|
468 | 0 | if (ret < 0) { |
469 | 0 | gnutls_assert(); |
470 | 0 | for (j = 0; j < i; j++) { |
471 | 0 | gnutls_pcert_deinit(&local_certs[j]); |
472 | 0 | } |
473 | 0 | gnutls_free(local_certs); |
474 | 0 | return NULL; |
475 | 0 | } |
476 | | |
477 | 0 | return local_certs; |
478 | 0 | } |
479 | | |
480 | | /* converts the given x509 key to gnutls_privkey* and allocates |
481 | | * space for it. |
482 | | */ |
483 | | static gnutls_privkey_t |
484 | | alloc_and_load_x509_key(gnutls_x509_privkey_t key, int deinit) |
485 | 0 | { |
486 | 0 | gnutls_privkey_t local_key; |
487 | 0 | int ret = 0; |
488 | |
|
489 | 0 | if (key == NULL) |
490 | 0 | return NULL; |
491 | | |
492 | 0 | ret = gnutls_privkey_init(&local_key); |
493 | 0 | if (ret < 0) { |
494 | 0 | gnutls_assert(); |
495 | 0 | return NULL; |
496 | 0 | } |
497 | | |
498 | 0 | ret = |
499 | 0 | gnutls_privkey_import_x509(local_key, key, |
500 | 0 | deinit ? |
501 | 0 | GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE : 0); |
502 | 0 | if (ret < 0) { |
503 | 0 | gnutls_assert(); |
504 | 0 | gnutls_privkey_deinit(local_key); |
505 | 0 | return NULL; |
506 | 0 | } |
507 | | |
508 | 0 | return local_key; |
509 | 0 | } |
510 | | |
511 | | #ifdef ENABLE_PKCS11 |
512 | | |
513 | | /* converts the given raw key to gnutls_privkey* and allocates |
514 | | * space for it. |
515 | | */ |
516 | | static gnutls_privkey_t |
517 | | alloc_and_load_pkcs11_key(gnutls_pkcs11_privkey_t key, int deinit) |
518 | | { |
519 | | gnutls_privkey_t local_key; |
520 | | int ret = 0; |
521 | | |
522 | | if (key == NULL) |
523 | | return NULL; |
524 | | |
525 | | ret = gnutls_privkey_init(&local_key); |
526 | | if (ret < 0) { |
527 | | gnutls_assert(); |
528 | | return NULL; |
529 | | } |
530 | | |
531 | | ret = |
532 | | gnutls_privkey_import_pkcs11(local_key, key, |
533 | | deinit ? |
534 | | GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE |
535 | | : 0); |
536 | | if (ret < 0) { |
537 | | gnutls_assert(); |
538 | | gnutls_privkey_deinit(local_key); |
539 | | return NULL; |
540 | | } |
541 | | |
542 | | return local_key; |
543 | | } |
544 | | |
545 | | #endif |
546 | | |
547 | | /** |
548 | | * gnutls_certificate_server_set_request: |
549 | | * @session: is a #gnutls_session_t type. |
550 | | * @req: is one of GNUTLS_CERT_REQUEST, GNUTLS_CERT_REQUIRE, GNUTLS_CERT_IGNORE |
551 | | * |
552 | | * This function specifies if we (in case of a server) are going to |
553 | | * send a certificate request message to the client. If @req is |
554 | | * GNUTLS_CERT_REQUIRE then the server will return the %GNUTLS_E_NO_CERTIFICATE_FOUND |
555 | | * error if the peer does not provide a certificate. If you do not call this |
556 | | * function then the client will not be asked to send a certificate. Invoking |
557 | | * the function with @req GNUTLS_CERT_IGNORE has the same effect. |
558 | | **/ |
559 | | void |
560 | | gnutls_certificate_server_set_request(gnutls_session_t session, |
561 | | gnutls_certificate_request_t req) |
562 | 0 | { |
563 | 0 | session->internals.send_cert_req = req; |
564 | 0 | } |
565 | | |
566 | | static int call_legacy_cert_cb1(gnutls_session_t session, |
567 | | const struct gnutls_cert_retr_st *info, |
568 | | gnutls_pcert_st ** certs, |
569 | | unsigned int *pcert_length, |
570 | | gnutls_ocsp_data_st ** ocsp, |
571 | | unsigned int *ocsp_length, |
572 | | gnutls_privkey_t * privkey, unsigned int *flags) |
573 | 0 | { |
574 | 0 | gnutls_retr2_st st2; |
575 | 0 | gnutls_pcert_st *local_certs = NULL; |
576 | 0 | gnutls_privkey_t local_key = NULL; |
577 | 0 | unsigned i; |
578 | 0 | int ret; |
579 | |
|
580 | 0 | *ocsp_length = 0; |
581 | |
|
582 | 0 | memset(&st2, 0, sizeof(st2)); |
583 | |
|
584 | 0 | ret = |
585 | 0 | info->cred->legacy_cert_cb1(session, info->req_ca_rdn, info->nreqs, |
586 | 0 | info->pk_algos, info->pk_algos_length, |
587 | 0 | &st2); |
588 | 0 | if (ret < 0) |
589 | 0 | return gnutls_assert_val(ret); |
590 | | |
591 | 0 | if (st2.ncerts == 0) { |
592 | 0 | *pcert_length = 0; |
593 | 0 | *ocsp_length = 0; |
594 | 0 | *privkey = NULL; |
595 | 0 | return 0; |
596 | 0 | } |
597 | | |
598 | 0 | if (st2.cert_type != GNUTLS_CRT_X509) { |
599 | 0 | gnutls_assert(); |
600 | 0 | ret = GNUTLS_E_INVALID_REQUEST; |
601 | 0 | goto cleanup; |
602 | 0 | } |
603 | | |
604 | 0 | local_certs = alloc_and_load_x509_certs(st2.cert.x509, st2.ncerts); |
605 | 0 | if (local_certs == NULL) { |
606 | 0 | gnutls_assert(); |
607 | 0 | ret = GNUTLS_E_MEMORY_ERROR; |
608 | 0 | goto cleanup; |
609 | 0 | } |
610 | | |
611 | 0 | switch (st2.key_type) { |
612 | | #ifdef ENABLE_PKCS11 |
613 | | case GNUTLS_PRIVKEY_PKCS11: |
614 | | if (st2.key.pkcs11 != NULL) { |
615 | | local_key = |
616 | | alloc_and_load_pkcs11_key(st2.key.pkcs11, |
617 | | st2.deinit_all); |
618 | | if (local_key == NULL) { |
619 | | gnutls_assert(); |
620 | | ret = GNUTLS_E_INTERNAL_ERROR; |
621 | | goto cleanup; |
622 | | } |
623 | | } |
624 | | break; |
625 | | #endif |
626 | 0 | case GNUTLS_PRIVKEY_X509: |
627 | 0 | if (st2.key.x509 != NULL) { |
628 | 0 | local_key = |
629 | 0 | alloc_and_load_x509_key(st2.key.x509, |
630 | 0 | st2.deinit_all); |
631 | 0 | if (local_key == NULL) { |
632 | 0 | gnutls_assert(); |
633 | 0 | ret = GNUTLS_E_INTERNAL_ERROR; |
634 | 0 | goto cleanup; |
635 | 0 | } |
636 | 0 | } |
637 | 0 | break; |
638 | 0 | default: |
639 | 0 | gnutls_assert(); |
640 | 0 | ret = GNUTLS_E_INVALID_REQUEST; |
641 | 0 | goto cleanup; |
642 | 0 | } |
643 | | |
644 | 0 | *privkey = local_key; |
645 | 0 | *certs = local_certs; |
646 | 0 | *pcert_length = st2.ncerts; |
647 | | |
648 | | /* flag the caller to deinitialize our values */ |
649 | 0 | *flags |= GNUTLS_CERT_RETR_DEINIT_ALL; |
650 | |
|
651 | 0 | ret = 0; |
652 | |
|
653 | 0 | cleanup: |
654 | |
|
655 | 0 | if (st2.cert_type == GNUTLS_CRT_X509) { |
656 | 0 | if (st2.deinit_all) { |
657 | 0 | for (i = 0; i < st2.ncerts; i++) { |
658 | 0 | gnutls_x509_crt_deinit(st2.cert.x509[i]); |
659 | 0 | } |
660 | 0 | gnutls_free(st2.cert.x509); |
661 | 0 | } |
662 | 0 | } |
663 | |
|
664 | 0 | return ret; |
665 | |
|
666 | 0 | } |
667 | | |
668 | | /** |
669 | | * gnutls_certificate_set_retrieve_function: |
670 | | * @cred: is a #gnutls_certificate_credentials_t type. |
671 | | * @func: is the callback function |
672 | | * |
673 | | * This function sets a callback to be called in order to retrieve the |
674 | | * certificate to be used in the handshake. The callback will take control |
675 | | * only if a certificate is requested by the peer. You are advised |
676 | | * to use gnutls_certificate_set_retrieve_function2() because it |
677 | | * is much more efficient in the processing it requires from gnutls. |
678 | | * |
679 | | * The callback's function prototype is: |
680 | | * int (*callback)(gnutls_session_t, const gnutls_datum_t* req_ca_dn, int nreqs, |
681 | | * const gnutls_pk_algorithm_t* pk_algos, int pk_algos_length, gnutls_retr2_st* st); |
682 | | * |
683 | | * @req_ca_dn is only used in X.509 certificates. |
684 | | * Contains a list with the CA names that the server considers trusted. |
685 | | * This is a hint and typically the client should send a certificate that is signed |
686 | | * by one of these CAs. These names, when available, are DER encoded. To get a more |
687 | | * meaningful value use the function gnutls_x509_rdn_get(). |
688 | | * |
689 | | * @pk_algos contains a list with server's acceptable public key algorithms. |
690 | | * The certificate returned should support the server's given algorithms. |
691 | | * |
692 | | * @st should contain the certificates and private keys. |
693 | | * |
694 | | * If the callback function is provided then gnutls will call it, in the |
695 | | * handshake, after the certificate request message has been received. |
696 | | * |
697 | | * In server side pk_algos and req_ca_dn are NULL. |
698 | | * |
699 | | * The callback function should set the certificate list to be sent, |
700 | | * and return 0 on success. If no certificate was selected then the |
701 | | * number of certificates should be set to zero. The value (-1) |
702 | | * indicates error and the handshake will be terminated. If both certificates |
703 | | * are set in the credentials and a callback is available, the callback |
704 | | * takes predence. |
705 | | * |
706 | | * Since: 3.0 |
707 | | **/ |
708 | | void gnutls_certificate_set_retrieve_function |
709 | | (gnutls_certificate_credentials_t cred, |
710 | 0 | gnutls_certificate_retrieve_function * func) { |
711 | 0 | cred->legacy_cert_cb1 = func; |
712 | 0 | if (!func) |
713 | 0 | cred->get_cert_callback3 = NULL; |
714 | 0 | else |
715 | 0 | cred->get_cert_callback3 = call_legacy_cert_cb1; |
716 | 0 | } |
717 | | |
718 | | static int call_legacy_cert_cb2(gnutls_session_t session, |
719 | | const struct gnutls_cert_retr_st *info, |
720 | | gnutls_pcert_st ** certs, |
721 | | unsigned int *pcert_length, |
722 | | gnutls_ocsp_data_st ** ocsp, |
723 | | unsigned int *ocsp_length, |
724 | | gnutls_privkey_t * privkey, unsigned int *flags) |
725 | 0 | { |
726 | 0 | int ret; |
727 | 0 | *ocsp_length = 0; |
728 | | /* flags will be assumed to be zero */ |
729 | |
|
730 | 0 | ret = |
731 | 0 | info->cred->legacy_cert_cb2(session, info->req_ca_rdn, info->nreqs, |
732 | 0 | info->pk_algos, info->pk_algos_length, |
733 | 0 | certs, pcert_length, privkey); |
734 | 0 | if (ret < 0) { |
735 | 0 | gnutls_assert(); |
736 | 0 | } |
737 | 0 | return ret; |
738 | 0 | } |
739 | | |
740 | | /** |
741 | | * gnutls_certificate_set_retrieve_function2: |
742 | | * @cred: is a #gnutls_certificate_credentials_t type. |
743 | | * @func: is the callback function |
744 | | * |
745 | | * This function sets a callback to be called in order to retrieve the |
746 | | * certificate to be used in the handshake. The callback will take control |
747 | | * only if a certificate is requested by the peer. |
748 | | * |
749 | | * The callback's function prototype is: |
750 | | * int (*callback)(gnutls_session_t, const gnutls_datum_t* req_ca_dn, int nreqs, |
751 | | * const gnutls_pk_algorithm_t* pk_algos, int pk_algos_length, gnutls_pcert_st** pcert, |
752 | | * unsigned int *pcert_length, gnutls_privkey_t * pkey); |
753 | | * |
754 | | * @req_ca_dn is only used in X.509 certificates. |
755 | | * Contains a list with the CA names that the server considers trusted. |
756 | | * This is a hint and typically the client should send a certificate that is signed |
757 | | * by one of these CAs. These names, when available, are DER encoded. To get a more |
758 | | * meaningful value use the function gnutls_x509_rdn_get(). |
759 | | * |
760 | | * @pk_algos contains a list with server's acceptable public key algorithms. |
761 | | * The certificate returned should support the server's given algorithms. |
762 | | * |
763 | | * @pcert should contain a single certificate and public key or a list of them. |
764 | | * |
765 | | * @pcert_length is the size of the previous list. |
766 | | * |
767 | | * @pkey is the private key. |
768 | | * |
769 | | * If the callback function is provided then gnutls will call it, in the |
770 | | * handshake, after the certificate request message has been received. |
771 | | * All the provided by the callback values will not be released or |
772 | | * modified by gnutls. |
773 | | * |
774 | | * In server side pk_algos and req_ca_dn are NULL. |
775 | | * |
776 | | * The callback function should set the certificate list to be sent, |
777 | | * and return 0 on success. If no certificate was selected then the |
778 | | * number of certificates should be set to zero. The value (-1) |
779 | | * indicates error and the handshake will be terminated. If both certificates |
780 | | * are set in the credentials and a callback is available, the callback |
781 | | * takes predence. |
782 | | * |
783 | | * Since: 3.0 |
784 | | **/ |
785 | | void gnutls_certificate_set_retrieve_function2 |
786 | | (gnutls_certificate_credentials_t cred, |
787 | 0 | gnutls_certificate_retrieve_function2 * func) { |
788 | 0 | cred->legacy_cert_cb2 = func; |
789 | 0 | if (!func) |
790 | 0 | cred->get_cert_callback3 = NULL; |
791 | 0 | else |
792 | 0 | cred->get_cert_callback3 = call_legacy_cert_cb2; |
793 | 0 | } |
794 | | |
795 | | /** |
796 | | * gnutls_certificate_set_retrieve_function3: |
797 | | * @cred: is a #gnutls_certificate_credentials_t type. |
798 | | * @func: is the callback function |
799 | | * |
800 | | * This function sets a callback to be called in order to retrieve the |
801 | | * certificate and OCSP responses to be used in the handshake. @func will |
802 | | * be called only if the peer requests a certificate either during handshake |
803 | | * or during post-handshake authentication. |
804 | | * |
805 | | * The callback's function prototype is defined in `abstract.h': |
806 | | * |
807 | | * int gnutls_certificate_retrieve_function3( |
808 | | * gnutls_session_t, |
809 | | * const struct gnutls_cert_retr_st *info, |
810 | | * gnutls_pcert_st **certs, |
811 | | * unsigned int *certs_length, |
812 | | * gnutls_ocsp_data_st **ocsp, |
813 | | * unsigned int *ocsp_length, |
814 | | * gnutls_privkey_t *privkey, |
815 | | * unsigned int *flags); |
816 | | * |
817 | | * The info field of the callback contains: |
818 | | * @req_ca_dn which is a list with the CA names that the server considers trusted. |
819 | | * This is a hint and typically the client should send a certificate that is signed |
820 | | * by one of these CAs. These names, when available, are DER encoded. To get a more |
821 | | * meaningful value use the function gnutls_x509_rdn_get(). |
822 | | * @pk_algos contains a list with server's acceptable public key algorithms. |
823 | | * The certificate returned should support the server's given algorithms. |
824 | | * |
825 | | * The callback should fill-in the following values: |
826 | | * |
827 | | * @certs should contain an allocated list of certificates and public keys. |
828 | | * @certs_length is the size of the previous list. |
829 | | * @ocsp should contain an allocated list of OCSP responses. |
830 | | * @ocsp_length is the size of the previous list. |
831 | | * @privkey is the private key. |
832 | | * |
833 | | * If flags in the callback are set to %GNUTLS_CERT_RETR_DEINIT_ALL then |
834 | | * all provided values must be allocated using gnutls_malloc(), and will |
835 | | * be released by gnutls; otherwise they will not be touched by gnutls. |
836 | | * |
837 | | * The callback function should set the certificate and OCSP response |
838 | | * list to be sent, and return 0 on success. If no certificates are available, |
839 | | * the @certs_length and @ocsp_length should be set to zero. The return |
840 | | * value (-1) indicates error and the handshake will be terminated. If both |
841 | | * certificates are set in the credentials and a callback is available, the |
842 | | * callback takes predence. |
843 | | * |
844 | | * Raw public-keys: |
845 | | * In case raw public-keys are negotiated as certificate type, certificates |
846 | | * that would normally hold the public-key material are not available. In that case, |
847 | | * @certs contains an allocated list with only the public key. Since there is no |
848 | | * certificate, there is also no certificate status. Therefore, OCSP information |
849 | | * should not be set. |
850 | | * |
851 | | * Since: 3.6.3 |
852 | | **/ |
853 | | void gnutls_certificate_set_retrieve_function3 |
854 | | (gnutls_certificate_credentials_t cred, |
855 | 0 | gnutls_certificate_retrieve_function3 * func) { |
856 | 0 | cred->get_cert_callback3 = func; |
857 | 0 | } |
858 | | |
859 | | /** |
860 | | * gnutls_certificate_set_verify_function: |
861 | | * @cred: is a #gnutls_certificate_credentials_t type. |
862 | | * @func: is the callback function |
863 | | * |
864 | | * This function sets a callback to be called when peer's certificate |
865 | | * has been received in order to verify it on receipt rather than |
866 | | * doing after the handshake is completed. |
867 | | * |
868 | | * The callback's function prototype is: |
869 | | * int (*callback)(gnutls_session_t); |
870 | | * |
871 | | * If the callback function is provided then gnutls will call it, in the |
872 | | * handshake, just after the certificate message has been received. |
873 | | * To verify or obtain the certificate the gnutls_certificate_verify_peers2(), |
874 | | * gnutls_certificate_type_get(), gnutls_certificate_get_peers() functions |
875 | | * can be used. |
876 | | * |
877 | | * The callback function should return 0 for the handshake to continue |
878 | | * or non-zero to terminate. |
879 | | * |
880 | | * Since: 2.10.0 |
881 | | **/ |
882 | | void gnutls_certificate_set_verify_function |
883 | | (gnutls_certificate_credentials_t cred, |
884 | 0 | gnutls_certificate_verify_function * func) { |
885 | 0 | cred->verify_callback = func; |
886 | 0 | } |
887 | | |
888 | | /** |
889 | | * gnutls_x509_trust_list_set_getissuer_function: |
890 | | * @tlist: is a #gnutls_x509_trust_list_t type. |
891 | | * @func: is the callback function |
892 | | * |
893 | | * This function sets a callback to be called when the peer's certificate |
894 | | * chain is incomplete due a missing intermediate certificate. The callback |
895 | | * may provide the missing certificate for use during verification. |
896 | | * |
897 | | * The callback's function prototype is defined in gnutls/x509.h as: |
898 | | * |
899 | | * int (*callback)(gnutls_x509_trust_list_t list, |
900 | | * const gnutls_x509_crt_t cert, |
901 | | * gnutls_x509_crt_t **issuers, |
902 | | * unsigned int *issuers_size); |
903 | | * |
904 | | * If the callback function is provided then gnutls will call it during the |
905 | | * certificate verification procedure. The callback may wish to use |
906 | | * gnutls_x509_crt_get_authority_info_access() to get a URI from which |
907 | | * to attempt to download the missing issuer certificate, if available. |
908 | | * |
909 | | * On a successful call, the callback shall allocate the 'issuers' array with |
910 | | * gnutls_x509_crt_list_import2(). The ownership of both the array and the |
911 | | * elements is transferred to the caller and thus the application does not need |
912 | | * to maintain the memory after the call. |
913 | | * |
914 | | * The callback function should return 0 if the missing issuer certificate |
915 | | * for 'crt' was properly populated and added to the 'issuers', or non-zero |
916 | | * to continue the certificate list verification but with issuer as %NULL. |
917 | | * |
918 | | * Since: 3.7.0 |
919 | | **/ |
920 | | void gnutls_x509_trust_list_set_getissuer_function(gnutls_x509_trust_list_t |
921 | | tlist, |
922 | | gnutls_x509_trust_list_getissuer_function |
923 | | * func) |
924 | 0 | { |
925 | 0 | tlist->issuer_callback = func; |
926 | 0 | } |
927 | | |
928 | | /** |
929 | | * gnutls_x509_trust_list_set_ptr: |
930 | | * @tlist: is a #gnutls_x509_trust_list_t type. |
931 | | * @ptr: is the user pointer |
932 | | * |
933 | | * This function will set (associate) the user given pointer @ptr to |
934 | | * the tlist structure. This pointer can be accessed with |
935 | | * gnutls_x509_trust_list_get_ptr(). Useful in the callback function |
936 | | * gnutls_x509_trust_list_set_getissuer_function. |
937 | | * |
938 | | * Since: 3.7.0 |
939 | | **/ |
940 | | void gnutls_x509_trust_list_set_ptr(gnutls_x509_trust_list_t tlist, void *ptr) |
941 | 0 | { |
942 | 0 | tlist->usr_ptr = ptr; |
943 | 0 | } |
944 | | |
945 | | /** |
946 | | * gnutls_x509_trust_list_get_ptr: |
947 | | * @tlist: is a #gnutls_x509_trust_list_t type. |
948 | | * |
949 | | * Get user pointer for tlist. Useful in callback function |
950 | | * gnutls_x509_trust_list_set_getissuer_function. |
951 | | * This is the pointer set with gnutls_x509_trust_list_set_ptr(). |
952 | | * |
953 | | * Returns: the user given pointer from the tlist structure, or |
954 | | * %NULL if it was never set. |
955 | | * |
956 | | * Since: 3.7.0 |
957 | | **/ |
958 | | void *gnutls_x509_trust_list_get_ptr(gnutls_x509_trust_list_t tlist) |
959 | 0 | { |
960 | 0 | return tlist->usr_ptr; |
961 | 0 | } |
962 | | |
963 | | /** |
964 | | * gnutls_session_set_verify_output_function: |
965 | | * @session: is a #gnutls_x509_trust_list_t type. |
966 | | * @func: is the callback function |
967 | | * |
968 | | * This function sets a callback to be called when the peer's certificate |
969 | | * chain has to be verified and full path to the trusted root has to be |
970 | | * printed. |
971 | | * |
972 | | * The callback's function prototype is defined in `x509.h': |
973 | | * int (*callback)( |
974 | | * gnutls_x509_crt_t cert, |
975 | | * gnutls_x509_crt_t issuer, |
976 | | * gnutls_x509_crl_t crl, |
977 | | * unsigned int verification_output); |
978 | | * |
979 | | * If the callback function is provided then gnutls will call it, in the |
980 | | * certificate verification procedure. |
981 | | * To verify the certificate chain and print its path uptp the trusted root, |
982 | | * functions such as gnutls_certificate_verify_peers(), |
983 | | * gnutls_x509_trust_list_verify_crt(), and gnutls_x509_trust_list_verify_crt2() |
984 | | * can be used. The callback is set in _gnutls_verify_crt_status() and |
985 | | * _gnutls_pkcs11_verify_crt_status(). |
986 | | * |
987 | | * Since: 3.7.0 |
988 | | **/ |
989 | | void gnutls_session_set_verify_output_function(gnutls_session_t session, |
990 | | gnutls_verify_output_function * |
991 | | func) |
992 | 0 | { |
993 | 0 | session->internals.cert_output_callback = func; |
994 | 0 | } |
995 | | |
996 | 0 | #define TEST_TEXT "test text" |
997 | | /* returns error if the certificate has different algorithm than |
998 | | * the given key parameters. |
999 | | */ |
1000 | | int _gnutls_check_key_cert_match(gnutls_certificate_credentials_t res) |
1001 | 0 | { |
1002 | 0 | gnutls_datum_t test = { (void *)TEST_TEXT, sizeof(TEST_TEXT) - 1 }; |
1003 | 0 | gnutls_datum_t sig = { NULL, 0 }; |
1004 | 0 | gnutls_digest_algorithm_t dig; |
1005 | 0 | int pk, pk2, ret; |
1006 | 0 | unsigned sign_algo; |
1007 | |
|
1008 | 0 | if (res->flags & GNUTLS_CERTIFICATE_SKIP_KEY_CERT_MATCH) |
1009 | 0 | return 0; |
1010 | | |
1011 | 0 | pk = gnutls_pubkey_get_pk_algorithm(res->certs[res->ncerts - |
1012 | 0 | 1].cert_list[0].pubkey, |
1013 | 0 | NULL); |
1014 | 0 | pk2 = |
1015 | 0 | gnutls_privkey_get_pk_algorithm(res->certs[res->ncerts - 1].pkey, |
1016 | 0 | NULL); |
1017 | |
|
1018 | 0 | if (GNUTLS_PK_IS_RSA(pk) && GNUTLS_PK_IS_RSA(pk2)) { |
1019 | 0 | if (pk2 == GNUTLS_PK_RSA_PSS && pk == GNUTLS_PK_RSA) { |
1020 | 0 | _gnutls_debug_log |
1021 | 0 | ("you cannot mix an RSA-PSS key with an RSA certificate\n"); |
1022 | 0 | return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; |
1023 | 0 | } |
1024 | | |
1025 | 0 | if (pk2 == GNUTLS_PK_RSA_PSS || pk == GNUTLS_PK_RSA_PSS) |
1026 | 0 | pk = GNUTLS_PK_RSA_PSS; |
1027 | 0 | } else if (pk2 != pk) { |
1028 | 0 | gnutls_assert(); |
1029 | 0 | _gnutls_debug_log("key is %s, certificate is %s\n", |
1030 | 0 | gnutls_pk_get_name(pk2), |
1031 | 0 | gnutls_pk_get_name(pk)); |
1032 | 0 | return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; |
1033 | 0 | } |
1034 | | |
1035 | 0 | if (pk == GNUTLS_PK_GOST_01) |
1036 | 0 | dig = GNUTLS_DIG_GOSTR_94; |
1037 | 0 | else if (pk == GNUTLS_PK_GOST_12_256) |
1038 | 0 | dig = GNUTLS_DIG_STREEBOG_256; |
1039 | 0 | else if (pk == GNUTLS_PK_GOST_12_512) |
1040 | 0 | dig = GNUTLS_DIG_STREEBOG_512; |
1041 | 0 | else |
1042 | 0 | dig = GNUTLS_DIG_SHA256; |
1043 | |
|
1044 | 0 | sign_algo = gnutls_pk_to_sign(pk, dig); |
1045 | | |
1046 | | /* now check if keys really match. We use the sign/verify approach |
1047 | | * because we cannot always obtain the parameters from the abstract |
1048 | | * keys (e.g. PKCS #11). */ |
1049 | 0 | ret = gnutls_privkey_sign_data2(res->certs[res->ncerts - 1].pkey, |
1050 | 0 | sign_algo, 0, &test, &sig); |
1051 | 0 | if (ret < 0) { |
1052 | | /* for some reason we couldn't sign that. That shouldn't have |
1053 | | * happened, but since it did, report the issue and do not |
1054 | | * try the key matching test */ |
1055 | 0 | _gnutls_debug_log("%s: failed signing\n", __func__); |
1056 | 0 | goto finish; |
1057 | 0 | } |
1058 | | |
1059 | 0 | ret = |
1060 | 0 | gnutls_pubkey_verify_data2(res->certs[res->ncerts - 1]. |
1061 | 0 | cert_list[0].pubkey, sign_algo, |
1062 | 0 | GNUTLS_VERIFY_ALLOW_BROKEN, &test, &sig); |
1063 | |
|
1064 | 0 | gnutls_free(sig.data); |
1065 | |
|
1066 | 0 | if (ret < 0) |
1067 | 0 | return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH); |
1068 | | |
1069 | 0 | finish: |
1070 | 0 | return 0; |
1071 | 0 | } |
1072 | | |
1073 | | /** |
1074 | | * gnutls_certificate_verification_status_print: |
1075 | | * @status: The status flags to be printed |
1076 | | * @type: The certificate type |
1077 | | * @out: Newly allocated datum with (0) terminated string. |
1078 | | * @flags: should be zero |
1079 | | * |
1080 | | * This function will pretty print the status of a verification |
1081 | | * process -- eg. the one obtained by gnutls_certificate_verify_peers3(). |
1082 | | * |
1083 | | * The output @out needs to be deallocated using gnutls_free(). |
1084 | | * |
1085 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1086 | | * negative error value. |
1087 | | * |
1088 | | * Since: 3.1.4 |
1089 | | **/ |
1090 | | int |
1091 | | gnutls_certificate_verification_status_print(unsigned int status, |
1092 | | gnutls_certificate_type_t |
1093 | | type, gnutls_datum_t * out, |
1094 | | unsigned int flags) |
1095 | 0 | { |
1096 | 0 | gnutls_buffer_st str; |
1097 | |
|
1098 | 0 | _gnutls_buffer_init(&str); |
1099 | |
|
1100 | 0 | if (status == 0) |
1101 | 0 | _gnutls_buffer_append_str(&str, |
1102 | 0 | _("The certificate is trusted. ")); |
1103 | 0 | else |
1104 | 0 | _gnutls_buffer_append_str(&str, |
1105 | 0 | _ |
1106 | 0 | ("The certificate is NOT trusted. ")); |
1107 | |
|
1108 | 0 | if (type == GNUTLS_CRT_X509) { |
1109 | 0 | if (status & GNUTLS_CERT_REVOKED) |
1110 | 0 | _gnutls_buffer_append_str(&str, |
1111 | 0 | _ |
1112 | 0 | ("The certificate chain is revoked. ")); |
1113 | |
|
1114 | 0 | if (status & GNUTLS_CERT_MISMATCH) |
1115 | 0 | _gnutls_buffer_append_str(&str, |
1116 | 0 | _ |
1117 | 0 | ("The certificate doesn't match the local copy (TOFU). ")); |
1118 | |
|
1119 | 0 | if (status & GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED) |
1120 | 0 | _gnutls_buffer_append_str(&str, |
1121 | 0 | _ |
1122 | 0 | ("The revocation or OCSP data are old and have been superseded. ")); |
1123 | |
|
1124 | 0 | if (status & GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE) |
1125 | 0 | _gnutls_buffer_append_str(&str, |
1126 | 0 | _ |
1127 | 0 | ("The revocation or OCSP data are issued with a future date. ")); |
1128 | |
|
1129 | 0 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) |
1130 | 0 | _gnutls_buffer_append_str(&str, |
1131 | 0 | _ |
1132 | 0 | ("The certificate issuer is unknown. ")); |
1133 | |
|
1134 | 0 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) |
1135 | 0 | _gnutls_buffer_append_str(&str, |
1136 | 0 | _ |
1137 | 0 | ("The certificate issuer is not a CA. ")); |
1138 | 0 | } |
1139 | |
|
1140 | 0 | if (status & GNUTLS_CERT_INSECURE_ALGORITHM) |
1141 | 0 | _gnutls_buffer_append_str(&str, |
1142 | 0 | _ |
1143 | 0 | ("The certificate chain uses insecure algorithm. ")); |
1144 | |
|
1145 | 0 | if (status & GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE) |
1146 | 0 | _gnutls_buffer_append_str(&str, |
1147 | 0 | _ |
1148 | 0 | ("The certificate chain violates the signer's constraints. ")); |
1149 | |
|
1150 | 0 | if (status & GNUTLS_CERT_PURPOSE_MISMATCH) |
1151 | 0 | _gnutls_buffer_append_str(&str, |
1152 | 0 | _ |
1153 | 0 | ("The certificate chain does not match the intended purpose. ")); |
1154 | |
|
1155 | 0 | if (status & GNUTLS_CERT_NOT_ACTIVATED) |
1156 | 0 | _gnutls_buffer_append_str(&str, |
1157 | 0 | _ |
1158 | 0 | ("The certificate chain uses not yet valid certificate. ")); |
1159 | |
|
1160 | 0 | if (status & GNUTLS_CERT_EXPIRED) |
1161 | 0 | _gnutls_buffer_append_str(&str, |
1162 | 0 | _ |
1163 | 0 | ("The certificate chain uses expired certificate. ")); |
1164 | |
|
1165 | 0 | if (status & GNUTLS_CERT_SIGNATURE_FAILURE) |
1166 | 0 | _gnutls_buffer_append_str(&str, |
1167 | 0 | _ |
1168 | 0 | ("The signature in the certificate is invalid. ")); |
1169 | |
|
1170 | 0 | if (status & GNUTLS_CERT_UNEXPECTED_OWNER) |
1171 | 0 | _gnutls_buffer_append_str(&str, |
1172 | 0 | _ |
1173 | 0 | ("The name in the certificate does not match the expected. ")); |
1174 | |
|
1175 | 0 | if (status & GNUTLS_CERT_MISSING_OCSP_STATUS) |
1176 | 0 | _gnutls_buffer_append_str(&str, |
1177 | 0 | _ |
1178 | 0 | ("The certificate requires the server to include an OCSP status in its response, but the OCSP status is missing. ")); |
1179 | |
|
1180 | 0 | if (status & GNUTLS_CERT_INVALID_OCSP_STATUS) |
1181 | 0 | _gnutls_buffer_append_str(&str, |
1182 | 0 | _ |
1183 | 0 | ("The received OCSP status response is invalid. ")); |
1184 | |
|
1185 | 0 | if (status & GNUTLS_CERT_UNKNOWN_CRIT_EXTENSIONS) |
1186 | 0 | _gnutls_buffer_append_str(&str, |
1187 | 0 | _ |
1188 | 0 | ("The certificate contains an unknown critical extension. ")); |
1189 | |
|
1190 | 0 | return _gnutls_buffer_to_datum(&str, out, 1); |
1191 | 0 | } |
1192 | | |
1193 | | #if defined(ENABLE_DHE) || defined(ENABLE_ANON) |
1194 | | /** |
1195 | | * gnutls_certificate_set_dh_params: |
1196 | | * @res: is a gnutls_certificate_credentials_t type |
1197 | | * @dh_params: the Diffie-Hellman parameters. |
1198 | | * |
1199 | | * This function will set the Diffie-Hellman parameters for a |
1200 | | * certificate server to use. These parameters will be used in |
1201 | | * Ephemeral Diffie-Hellman cipher suites. Note that only a pointer |
1202 | | * to the parameters are stored in the certificate handle, so you |
1203 | | * must not deallocate the parameters before the certificate is deallocated. |
1204 | | * |
1205 | | * Deprecated: This function is unnecessary and discouraged on GnuTLS 3.6.0 |
1206 | | * or later. Since 3.6.0, DH parameters are negotiated |
1207 | | * following RFC7919. |
1208 | | * |
1209 | | **/ |
1210 | | void |
1211 | | gnutls_certificate_set_dh_params(gnutls_certificate_credentials_t res, |
1212 | | gnutls_dh_params_t dh_params) |
1213 | 0 | { |
1214 | 0 | if (res->deinit_dh_params) { |
1215 | 0 | res->deinit_dh_params = 0; |
1216 | 0 | gnutls_dh_params_deinit(res->dh_params); |
1217 | 0 | res->dh_params = NULL; |
1218 | 0 | } |
1219 | |
|
1220 | 0 | res->dh_params = dh_params; |
1221 | 0 | res->dh_sec_param = |
1222 | 0 | gnutls_pk_bits_to_sec_param(GNUTLS_PK_DH, |
1223 | 0 | _gnutls_mpi_get_nbits(dh_params->params |
1224 | 0 | [0])); |
1225 | 0 | } |
1226 | | |
1227 | | /** |
1228 | | * gnutls_certificate_set_known_dh_params: |
1229 | | * @res: is a gnutls_certificate_credentials_t type |
1230 | | * @sec_param: is an option of the %gnutls_sec_param_t enumeration |
1231 | | * |
1232 | | * This function will set the Diffie-Hellman parameters for a |
1233 | | * certificate server to use. These parameters will be used in |
1234 | | * Ephemeral Diffie-Hellman cipher suites and will be selected from |
1235 | | * the FFDHE set of RFC7919 according to the security level provided. |
1236 | | * |
1237 | | * Deprecated: This function is unnecessary and discouraged on GnuTLS 3.6.0 |
1238 | | * or later. Since 3.6.0, DH parameters are negotiated |
1239 | | * following RFC7919. |
1240 | | * |
1241 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1242 | | * negative error value. |
1243 | | * |
1244 | | * Since: 3.5.6 |
1245 | | **/ |
1246 | | int |
1247 | | gnutls_certificate_set_known_dh_params(gnutls_certificate_credentials_t res, |
1248 | | gnutls_sec_param_t sec_param) |
1249 | 0 | { |
1250 | 0 | res->dh_sec_param = sec_param; |
1251 | |
|
1252 | 0 | return 0; |
1253 | 0 | } |
1254 | | |
1255 | | #endif /* DH */ |