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