Line data Source code
1 : /*
2 : * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3 : * Copyright (C) 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 : /* The certificate authentication functions which are needed in the handshake,
25 : * and are common to RSA and DHE key exchange, are in this file.
26 : */
27 :
28 : #include "gnutls_int.h"
29 : #include "auth.h"
30 : #include "errors.h"
31 : #include <auth/cert.h>
32 : #include "dh.h"
33 : #include "num.h"
34 : #include "libtasn1.h"
35 : #include "datum.h"
36 : #include "ext/signature.h"
37 : #include <pk.h>
38 : #include <algorithms.h>
39 : #include <global.h>
40 : #include <record.h>
41 : #include <tls-sig.h>
42 : #include <state.h>
43 : #include <pk.h>
44 : #include <x509.h>
45 : #include <x509/verify-high.h>
46 : #include <gnutls/abstract.h>
47 : #include "abstract_int.h"
48 : #include "debug.h"
49 :
50 : static void
51 : selected_certs_set(gnutls_session_t session,
52 : gnutls_pcert_st * certs, int ncerts,
53 : gnutls_ocsp_data_st *ocsp, unsigned nocsp,
54 : gnutls_privkey_t key, int need_free,
55 : gnutls_status_request_ocsp_func ocsp_func,
56 : void *ocsp_func_ptr);
57 :
58 : #define MAX_CLIENT_SIGN_ALGOS 5
59 : #define CERTTYPE_SIZE (MAX_CLIENT_SIGN_ALGOS+1)
60 : typedef enum CertificateSigType { RSA_SIGN = 1, DSA_SIGN = 2, ECDSA_SIGN = 64,
61 : #ifdef ENABLE_GOST
62 : GOSTR34102012_256_SIGN = 67,
63 : GOSTR34102012_512_SIGN = 68
64 : #endif
65 : } CertificateSigType;
66 :
67 : /* Moves data from an internal certificate struct (gnutls_pcert_st) to
68 : * another internal certificate struct (cert_auth_info_t), and deinitializes
69 : * the former.
70 : */
71 1964 : int _gnutls_pcert_to_auth_info(cert_auth_info_t info, gnutls_pcert_st * certs, size_t ncerts)
72 : {
73 1964 : size_t i, j;
74 :
75 1964 : if (info->raw_certificate_list != NULL) {
76 268 : for (j = 0; j < info->ncerts; j++)
77 352 : _gnutls_free_datum(&info->raw_certificate_list[j]);
78 92 : gnutls_free(info->raw_certificate_list);
79 : }
80 :
81 1964 : if (ncerts == 0) {
82 0 : info->raw_certificate_list = NULL;
83 0 : info->ncerts = 0;
84 0 : return 0;
85 : }
86 :
87 3928 : info->raw_certificate_list =
88 1964 : gnutls_calloc(ncerts, sizeof(gnutls_datum_t));
89 1964 : if (info->raw_certificate_list == NULL) {
90 0 : gnutls_assert();
91 0 : return GNUTLS_E_MEMORY_ERROR;
92 : }
93 :
94 1964 : info->cert_type = certs[0].type;
95 1964 : info->ncerts = ncerts;
96 :
97 4537 : for (i = 0; i < ncerts; i++) {
98 2573 : info->raw_certificate_list[i].data = certs[i].cert.data;
99 2573 : info->raw_certificate_list[i].size = certs[i].cert.size;
100 2573 : certs[i].cert.data = NULL;
101 2573 : gnutls_pcert_deinit(&certs[i]);
102 : }
103 1964 : gnutls_free(certs);
104 :
105 1964 : return 0;
106 : }
107 :
108 : /* returns 0 if the algo_to-check exists in the pk_algos list,
109 : * -1 otherwise.
110 : */
111 : inline static int
112 5 : check_pk_algo_in_list(const gnutls_pk_algorithm_t *
113 : pk_algos, int pk_algos_length,
114 : gnutls_pk_algorithm_t algo_to_check)
115 : {
116 5 : int i;
117 6 : for (i = 0; i < pk_algos_length; i++) {
118 14 : if (algo_to_check == pk_algos[i]) {
119 : return 0;
120 : }
121 : }
122 : return -1;
123 : }
124 :
125 : /* Returns the issuer's Distinguished name in odn, of the certificate
126 : * specified in cert.
127 : */
128 16 : static int cert_get_issuer_dn(gnutls_pcert_st * cert, gnutls_datum_t * odn)
129 : {
130 16 : ASN1_TYPE dn;
131 16 : int len, result;
132 16 : int start, end;
133 :
134 16 : if ((result = asn1_create_element
135 : (_gnutls_get_pkix(), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS) {
136 0 : gnutls_assert();
137 0 : return _gnutls_asn2err(result);
138 : }
139 :
140 16 : result = asn1_der_decoding(&dn, cert->cert.data, cert->cert.size, NULL);
141 16 : if (result != ASN1_SUCCESS) {
142 : /* couldn't decode DER */
143 0 : gnutls_assert();
144 0 : asn1_delete_structure(&dn);
145 0 : return _gnutls_asn2err(result);
146 : }
147 :
148 16 : result =
149 32 : asn1_der_decoding_startEnd(dn, cert->cert.data,
150 16 : cert->cert.size,
151 : "tbsCertificate.issuer", &start, &end);
152 :
153 16 : if (result != ASN1_SUCCESS) {
154 : /* couldn't decode DER */
155 0 : gnutls_assert();
156 0 : asn1_delete_structure(&dn);
157 0 : return _gnutls_asn2err(result);
158 : }
159 16 : asn1_delete_structure(&dn);
160 :
161 16 : len = end - start + 1;
162 :
163 16 : odn->size = len;
164 16 : odn->data = &cert->cert.data[start];
165 :
166 16 : return 0;
167 : }
168 :
169 : /* Locates the most appropriate x509 certificate using the
170 : * given DN. If indx == -1 then no certificate was found.
171 : *
172 : * That is to guess which certificate to use, based on the
173 : * CAs and sign algorithms supported by the peer server.
174 : */
175 : static int
176 338 : find_x509_client_cert(gnutls_session_t session,
177 : const gnutls_certificate_credentials_t cred,
178 : const uint8_t * _data, size_t _data_size,
179 : const gnutls_pk_algorithm_t * pk_algos,
180 : int pk_algos_length, int *indx)
181 : {
182 338 : unsigned size;
183 338 : gnutls_datum_t odn = { NULL, 0 }, asked_dn;
184 338 : const uint8_t *data = _data;
185 338 : ssize_t data_size = _data_size;
186 338 : unsigned i, j;
187 338 : int result, cert_pk;
188 338 : unsigned key_usage;
189 :
190 338 : *indx = -1;
191 :
192 : /* If peer doesn't send any issuers and we have a single certificate
193 : * then send that one.
194 : */
195 338 : if (cred->ncerts == 1 &&
196 : (data_size == 0
197 12 : || (session->internals.flags & GNUTLS_FORCE_CLIENT_CERT))) {
198 76 : if (cred->certs[0].cert_list[0].type == GNUTLS_CRT_X509) {
199 :
200 75 : key_usage = get_key_usage(session, cred->certs[0].cert_list[0].pubkey);
201 :
202 : /* For client certificates we require signatures */
203 75 : result = _gnutls_check_key_usage_for_sig(session, key_usage, 1);
204 75 : if (result < 0) {
205 1 : _gnutls_debug_log("Client certificate is not suitable for signing\n");
206 1 : return gnutls_assert_val(result);
207 : }
208 :
209 74 : *indx = 0;
210 74 : return 0;
211 : }
212 : }
213 :
214 903 : do {
215 903 : DECR_LENGTH_RET(data_size, 2, 0);
216 657 : size = _gnutls_read_uint16(data);
217 657 : DECR_LENGTH_RET(data_size, size, 0);
218 645 : data += 2;
219 :
220 645 : asked_dn.data = (void*)data;
221 645 : asked_dn.size = size;
222 645 : _gnutls_dn_log("Peer requested CA", &asked_dn);
223 :
224 650 : for (i = 0; i < cred->ncerts; i++) {
225 21 : for (j = 0; j < cred->certs[i].cert_list_length; j++) {
226 32 : if ((result =
227 16 : cert_get_issuer_dn(&cred->certs
228 16 : [i].cert_list
229 16 : [j], &odn)) < 0) {
230 0 : gnutls_assert();
231 0 : return result;
232 : }
233 :
234 16 : if (odn.size == 0 || odn.size != asked_dn.size)
235 11 : continue;
236 :
237 5 : key_usage = get_key_usage(session, cred->certs[i].cert_list[0].pubkey);
238 :
239 : /* For client certificates we require signatures */
240 5 : if (_gnutls_check_key_usage_for_sig(session, key_usage, 1) < 0) {
241 0 : _gnutls_debug_log("Client certificate is not suitable for signing\n");
242 0 : continue;
243 : }
244 :
245 : /* If the DN matches and
246 : * the *_SIGN algorithm matches
247 : * the cert is our cert!
248 : */
249 5 : cert_pk =
250 10 : gnutls_pubkey_get_pk_algorithm(cred->certs
251 5 : [i].cert_list
252 : [0].pubkey,
253 : NULL);
254 :
255 5 : if ((memcmp(odn.data, asked_dn.data, asked_dn.size) == 0) &&
256 10 : (check_pk_algo_in_list
257 : (pk_algos, pk_algos_length,
258 : cert_pk) == 0)) {
259 5 : *indx = i;
260 5 : break;
261 : }
262 : }
263 10 : if (*indx != -1)
264 : break;
265 : }
266 :
267 645 : if (*indx != -1)
268 : break;
269 :
270 : /* move to next record */
271 640 : data += size;
272 : }
273 640 : while (1);
274 :
275 : return 0;
276 :
277 : }
278 :
279 :
280 : /* Locates the first raw public-key.
281 : * Currently it only makes sense to associate one raw pubkey per session.
282 : * Associating more raw pubkeys with a session has no use because we
283 : * don't know how to select the correct one.
284 : */
285 : static int
286 9 : find_rawpk_client_cert(gnutls_session_t session,
287 : const gnutls_certificate_credentials_t cred,
288 : const gnutls_pk_algorithm_t* pk_algos,
289 : int pk_algos_length, int* indx)
290 : {
291 9 : unsigned i;
292 9 : int ret;
293 9 : gnutls_pk_algorithm_t pk;
294 :
295 9 : *indx = -1;
296 :
297 9 : for (i = 0; i < cred->ncerts; i++) {
298 : /* We know that our list length will be 1, therefore we can
299 : * ignore the rest.
300 : */
301 9 : if (cred->certs[i].cert_list_length == 1 && cred->certs[i].cert_list[0].type == GNUTLS_CRT_RAWPK) {
302 9 : pk = gnutls_pubkey_get_pk_algorithm(cred->certs[i].cert_list[0].pubkey, NULL);
303 :
304 : /* For client certificates we require signatures */
305 18 : ret = _gnutls_check_key_usage_for_sig(session, get_key_usage(session, cred->certs[i].cert_list[0].pubkey), 1);
306 9 : if (ret < 0) {
307 : /* we return an error instead of skipping so that the user is notified about
308 : * the key incompatibility */
309 1 : _gnutls_debug_log("Client certificate is not suitable for signing\n");
310 1 : return gnutls_assert_val(ret);
311 : }
312 :
313 : /* Check whether the public-key algorithm of our credential is in
314 : * the list with supported public-key algorithms and whether the
315 : * cert type matches. */
316 16 : if ((check_pk_algo_in_list(pk_algos, pk_algos_length, pk) == 0)) {
317 : // We found a compatible credential
318 8 : *indx = i;
319 8 : break;
320 : }
321 : }
322 : }
323 :
324 : return 0;
325 : }
326 :
327 :
328 : /* Returns the number of issuers in the server's
329 : * certificate request packet.
330 : */
331 : static int
332 215 : get_issuers_num(gnutls_session_t session, const uint8_t * data, ssize_t data_size)
333 : {
334 215 : int issuers_dn_len = 0;
335 215 : unsigned size;
336 :
337 : /* Count the number of the given issuers;
338 : * This is used to allocate the issuers_dn without
339 : * using realloc().
340 : */
341 :
342 215 : if (data_size == 0 || data == NULL)
343 : return 0;
344 :
345 166 : while (data_size > 0) {
346 : /* This works like DECR_LEN()
347 : */
348 84 : DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
349 84 : size = _gnutls_read_uint16(data);
350 :
351 84 : DECR_LENGTH_RET(data_size, size, GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
352 :
353 84 : data += 2;
354 :
355 84 : if (size > 0) {
356 84 : issuers_dn_len++;
357 84 : data += size;
358 : }
359 : }
360 :
361 : return issuers_dn_len;
362 : }
363 :
364 : /* Returns the issuers in the server's certificate request
365 : * packet.
366 : */
367 : static int
368 82 : get_issuers(gnutls_session_t session,
369 : gnutls_datum_t * issuers_dn, int issuers_len,
370 : const uint8_t * data, size_t data_size)
371 : {
372 82 : int i;
373 82 : unsigned size;
374 :
375 82 : if (get_certificate_type(session, GNUTLS_CTYPE_CLIENT) != GNUTLS_CRT_X509)
376 : return 0;
377 :
378 : /* put the requested DNs to req_dn, only in case
379 : * of X509 certificates.
380 : */
381 82 : if (issuers_len > 0) {
382 :
383 166 : for (i = 0; i < issuers_len; i++) {
384 : /* The checks here for the buffer boundaries
385 : * are not needed since the buffer has been
386 : * parsed above.
387 : */
388 84 : data_size -= 2;
389 :
390 84 : size = _gnutls_read_uint16(data);
391 :
392 84 : data += 2;
393 :
394 84 : issuers_dn[i].data = (void*)data;
395 84 : issuers_dn[i].size = size;
396 :
397 84 : _gnutls_dn_log("Peer requested CA", &issuers_dn[i]);
398 :
399 84 : data += size;
400 : }
401 : }
402 :
403 : return 0;
404 : }
405 :
406 : /* Calls the client or server certificate get callback.
407 : */
408 : static int
409 233 : call_get_cert_callback(gnutls_session_t session,
410 : const gnutls_datum_t * issuers_dn,
411 : int issuers_dn_length,
412 : gnutls_pk_algorithm_t * pk_algos, int pk_algos_length)
413 : {
414 233 : gnutls_privkey_t local_key = NULL;
415 233 : int ret = GNUTLS_E_INTERNAL_ERROR;
416 233 : gnutls_certificate_type_t type;
417 233 : gnutls_certificate_credentials_t cred;
418 233 : gnutls_pcert_st *pcert = NULL;
419 233 : gnutls_ocsp_data_st *ocsp = NULL;
420 233 : unsigned int ocsp_length = 0;
421 233 : unsigned int pcert_length = 0;
422 :
423 233 : cred = (gnutls_certificate_credentials_t)
424 233 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
425 233 : if (cred == NULL) {
426 0 : gnutls_assert();
427 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
428 : }
429 :
430 : /* Correctly set the certificate type for ourselves */
431 233 : type = get_certificate_type(session, GNUTLS_CTYPE_OURS);
432 :
433 : /* Check whether a callback is set and call it */
434 233 : if (cred->get_cert_callback3) {
435 233 : struct gnutls_cert_retr_st info;
436 233 : unsigned int flags = 0;
437 :
438 233 : memset(&info, 0, sizeof(info));
439 233 : info.req_ca_rdn = issuers_dn;
440 233 : info.nreqs = issuers_dn_length;
441 233 : info.pk_algos = pk_algos;
442 233 : info.pk_algos_length = pk_algos_length;
443 233 : info.cred = cred;
444 :
445 : /* we avoid all allocations and transformations */
446 233 : ret =
447 233 : cred->get_cert_callback3(session, &info,
448 : &pcert, &pcert_length,
449 : &ocsp, &ocsp_length,
450 : &local_key, &flags);
451 233 : if (ret < 0)
452 0 : return gnutls_assert_val(GNUTLS_E_USER_ERROR);
453 :
454 233 : if (pcert_length > 0 && type != pcert[0].type)
455 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
456 :
457 233 : if (pcert_length == 0) {
458 126 : pcert = NULL;
459 126 : local_key = NULL;
460 : }
461 :
462 233 : selected_certs_set(session, pcert, pcert_length,
463 : ocsp, ocsp_length,
464 233 : local_key, (flags&GNUTLS_CERT_RETR_DEINIT_ALL)?1:0,
465 : cred->glob_ocsp_func, cred->glob_ocsp_func_ptr);
466 :
467 233 : return 0;
468 : } else {
469 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
470 : }
471 : }
472 :
473 : /* Finds the appropriate certificate depending on the cA Distinguished name
474 : * advertized by the server. If none matches then returns 0 and -1 as index.
475 : * In case of an error a negative error code, is returned.
476 : *
477 : * 20020128: added ability to select a certificate depending on the SIGN
478 : * algorithm (only in automatic mode).
479 : */
480 : int
481 566 : _gnutls_select_client_cert(gnutls_session_t session,
482 : const uint8_t * _data, size_t _data_size,
483 : gnutls_pk_algorithm_t * pk_algos, int pk_algos_length)
484 : {
485 566 : int result;
486 566 : int indx = -1;
487 566 : gnutls_certificate_credentials_t cred;
488 566 : const uint8_t *data = _data;
489 566 : ssize_t data_size = _data_size;
490 566 : int issuers_dn_length;
491 566 : gnutls_datum_t *issuers_dn = NULL;
492 566 : gnutls_certificate_type_t cert_type;
493 :
494 566 : cred = (gnutls_certificate_credentials_t)
495 566 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
496 566 : if (cred == NULL) {
497 0 : gnutls_assert();
498 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
499 : }
500 :
501 566 : cert_type = get_certificate_type(session, GNUTLS_CTYPE_CLIENT);
502 :
503 566 : if (cred->get_cert_callback3 != NULL) {
504 :
505 : /* use a callback to get certificate
506 : */
507 219 : if (cert_type == GNUTLS_CRT_X509) {
508 215 : issuers_dn_length =
509 215 : get_issuers_num(session, data, data_size);
510 215 : if (issuers_dn_length < 0) {
511 0 : gnutls_assert();
512 0 : return issuers_dn_length;
513 : }
514 :
515 215 : if (issuers_dn_length > 0) {
516 82 : issuers_dn =
517 82 : gnutls_malloc(sizeof(gnutls_datum_t) *
518 : issuers_dn_length);
519 82 : if (issuers_dn == NULL) {
520 0 : gnutls_assert();
521 0 : return GNUTLS_E_MEMORY_ERROR;
522 : }
523 :
524 82 : result =
525 82 : get_issuers(session, issuers_dn,
526 : issuers_dn_length, data,
527 : data_size);
528 82 : if (result < 0) {
529 0 : gnutls_assert();
530 0 : goto cleanup;
531 : }
532 : }
533 : } else {
534 : issuers_dn_length = 0;
535 : }
536 :
537 219 : result =
538 219 : call_get_cert_callback(session, issuers_dn,
539 : issuers_dn_length, pk_algos,
540 : pk_algos_length);
541 219 : goto cleanup;
542 :
543 : } else {
544 : /* If we have no callbacks, try to guess.
545 : */
546 347 : switch (cert_type) {
547 338 : case GNUTLS_CRT_X509:
548 338 : result = find_x509_client_cert(session, cred, _data,
549 : _data_size, pk_algos,
550 : pk_algos_length, &indx);
551 338 : break;
552 9 : case GNUTLS_CRT_RAWPK:
553 9 : result = find_rawpk_client_cert(session, cred,
554 : pk_algos, pk_algos_length, &indx);
555 9 : break;
556 : default:
557 : result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
558 : break;
559 : }
560 :
561 347 : if (result < 0) {
562 2 : return gnutls_assert_val(result);
563 : }
564 :
565 345 : if (indx >= 0) {
566 87 : selected_certs_set(session,
567 : &cred->certs[indx].
568 : cert_list[0],
569 87 : cred->certs[indx].
570 : cert_list_length,
571 87 : cred->certs[indx].ocsp_data,
572 : cred->certs[indx].ocsp_data_length,
573 87 : cred->certs[indx].pkey, 0,
574 : NULL, NULL);
575 : } else {
576 258 : selected_certs_set(session, NULL, 0, NULL, 0,
577 : NULL, 0, NULL, NULL);
578 : }
579 :
580 : result = 0;
581 : }
582 :
583 564 : cleanup:
584 564 : gnutls_free(issuers_dn);
585 564 : return result;
586 :
587 : }
588 :
589 : /* Generate certificate message
590 : */
591 7724 : static int gen_x509_crt(gnutls_session_t session, gnutls_buffer_st * data)
592 : {
593 7724 : int ret, i;
594 7724 : gnutls_pcert_st *apr_cert_list;
595 7724 : gnutls_privkey_t apr_pkey;
596 7724 : int apr_cert_list_length;
597 7724 : unsigned init_pos = data->length;
598 :
599 : /* find the appropriate certificate
600 : */
601 15448 : if ((ret =
602 7724 : _gnutls_get_selected_cert(session, &apr_cert_list,
603 : &apr_cert_list_length, &apr_pkey)) < 0) {
604 0 : gnutls_assert();
605 0 : return ret;
606 : }
607 :
608 : ret = 3;
609 16102 : for (i = 0; i < apr_cert_list_length; i++) {
610 8378 : ret += apr_cert_list[i].cert.size + 3;
611 : /* hold size
612 : * for uint24 */
613 : }
614 :
615 : /* if no certificates were found then send:
616 : * 0B 00 00 03 00 00 00 // Certificate with no certs
617 : * instead of:
618 : * 0B 00 00 00 // empty certificate handshake
619 : *
620 : * ( the above is the whole handshake message, not
621 : * the one produced here )
622 : */
623 :
624 7724 : ret = _gnutls_buffer_append_prefix(data, 24, ret - 3);
625 7724 : if (ret < 0)
626 0 : return gnutls_assert_val(ret);
627 :
628 16102 : for (i = 0; i < apr_cert_list_length; i++) {
629 8378 : ret =
630 16756 : _gnutls_buffer_append_data_prefix(data, 24,
631 : apr_cert_list[i].
632 8378 : cert.data,
633 8378 : apr_cert_list[i].
634 8378 : cert.size);
635 8378 : if (ret < 0)
636 0 : return gnutls_assert_val(ret);
637 : }
638 :
639 7724 : return data->length - init_pos;
640 : }
641 :
642 :
643 : /* Generates a Raw Public Key certificate message that holds only the
644 : * SubjectPublicKeyInfo part of a regular certificate message.
645 : *
646 : * Returns the number of bytes sent or a negative error code.
647 : */
648 : int
649 20 : _gnutls_gen_rawpk_crt(gnutls_session_t session, gnutls_buffer_st* data)
650 : {
651 20 : int ret;
652 20 : gnutls_pcert_st *apr_cert_list;
653 20 : gnutls_privkey_t apr_pkey;
654 20 : int apr_cert_list_length;
655 :
656 20 : if((ret = _gnutls_get_selected_cert(session, &apr_cert_list,
657 : &apr_cert_list_length, &apr_pkey)) < 0) {
658 0 : return gnutls_assert_val(ret);
659 : }
660 :
661 : /* Since we are transmitting a raw public key with no additional
662 : * certificate credentials attached to it, it doesn't make sense to
663 : * have more than one certificate set (i.e. to have a certificate chain).
664 : */
665 20 : assert(apr_cert_list_length <= 1);
666 :
667 : /* Write our certificate containing only the SubjectPublicKeyInfo to
668 : * the output buffer. We always have exactly one certificate that
669 : * contains our raw public key. Our message looks like:
670 : * <length++certificate> where
671 : * length = 3 bytes (or 24 bits) and
672 : * certificate = length bytes.
673 : */
674 20 : if (apr_cert_list_length == 0) {
675 0 : ret = _gnutls_buffer_append_prefix(data, 24, 0);
676 : } else {
677 20 : ret = _gnutls_buffer_append_data_prefix(data, 24,
678 20 : apr_cert_list[0].cert.data,
679 20 : apr_cert_list[0].cert.size);
680 : }
681 :
682 :
683 20 : if (ret < 0) return gnutls_assert_val(ret);
684 :
685 20 : return data->length;
686 : }
687 :
688 :
689 : int
690 396 : _gnutls_gen_cert_client_crt(gnutls_session_t session, gnutls_buffer_st * data)
691 : {
692 396 : gnutls_certificate_type_t cert_type;
693 :
694 : // Retrieve the (negotiated) certificate type for the client
695 396 : cert_type = get_certificate_type(session, GNUTLS_CTYPE_CLIENT);
696 :
697 396 : switch (cert_type) {
698 392 : case GNUTLS_CRT_X509:
699 392 : return gen_x509_crt(session, data);
700 4 : case GNUTLS_CRT_RAWPK:
701 4 : return _gnutls_gen_rawpk_crt(session, data);
702 : default:
703 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
704 : }
705 : }
706 :
707 : int
708 7348 : _gnutls_gen_cert_server_crt(gnutls_session_t session, gnutls_buffer_st * data)
709 : {
710 7348 : gnutls_certificate_type_t cert_type;
711 :
712 : // Retrieve the (negotiated) certificate type for the server
713 7348 : cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
714 :
715 7348 : switch (cert_type) {
716 7332 : case GNUTLS_CRT_X509:
717 7332 : return gen_x509_crt(session, data);
718 16 : case GNUTLS_CRT_RAWPK:
719 16 : return _gnutls_gen_rawpk_crt(session, data);
720 : default:
721 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
722 : }
723 : }
724 :
725 : static
726 1965 : int check_pk_compat(gnutls_session_t session, gnutls_pubkey_t pubkey)
727 : {
728 1965 : unsigned cert_pk;
729 1965 : unsigned kx;
730 :
731 1965 : if (session->security_parameters.entity != GNUTLS_CLIENT)
732 : return 0;
733 :
734 1214 : cert_pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
735 1214 : if (cert_pk == GNUTLS_PK_UNKNOWN) {
736 0 : gnutls_assert();
737 0 : return GNUTLS_E_CERTIFICATE_ERROR;
738 : }
739 :
740 1214 : kx = session->security_parameters.cs->kx_algorithm;
741 :
742 2428 : if (_gnutls_map_kx_get_cred(kx, 1) == GNUTLS_CRD_CERTIFICATE &&
743 1214 : !_gnutls_kx_supports_pk(kx, cert_pk)) {
744 1 : gnutls_assert();
745 1 : return GNUTLS_E_CERTIFICATE_ERROR;
746 : }
747 :
748 : return 0;
749 : }
750 :
751 : /* Process server certificate
752 : */
753 : #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) gnutls_pcert_deinit(&peer_certificate_list[x])
754 : static int
755 4158 : _gnutls_proc_x509_crt(gnutls_session_t session,
756 : uint8_t * data, size_t data_size)
757 : {
758 4158 : int size, len, ret;
759 4158 : uint8_t *p = data;
760 4158 : cert_auth_info_t info;
761 4158 : gnutls_certificate_credentials_t cred;
762 4158 : ssize_t dsize = data_size;
763 4158 : int i;
764 4158 : gnutls_pcert_st *peer_certificate_list;
765 4158 : size_t peer_certificate_list_size = 0, j, x;
766 4158 : gnutls_datum_t tmp;
767 :
768 4158 : cred = (gnutls_certificate_credentials_t)
769 4158 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
770 4158 : if (cred == NULL) {
771 0 : gnutls_assert();
772 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
773 : }
774 :
775 8316 : if ((ret =
776 4158 : _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE,
777 : sizeof(cert_auth_info_st), 1)) < 0) {
778 0 : gnutls_assert();
779 0 : return ret;
780 : }
781 :
782 4158 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
783 :
784 4158 : if (data == NULL || data_size == 0) {
785 1 : gnutls_assert();
786 : /* no certificate was sent */
787 1 : return GNUTLS_E_NO_CERTIFICATE_FOUND;
788 : }
789 :
790 4157 : DECR_LEN(dsize, 3);
791 4157 : size = _gnutls_read_uint24(p);
792 4157 : p += 3;
793 :
794 : /* ensure no discrepancy in data */
795 4157 : if (size != dsize)
796 1683 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
797 :
798 : /* some implementations send 0B 00 00 06 00 00 03 00 00 00
799 : * instead of just 0B 00 00 03 00 00 00 as an empty certificate message.
800 : */
801 3315 : if (size == 0 || (size == 3 && memcmp(p, "\x00\x00\x00", 3) == 0)) {
802 305 : gnutls_assert();
803 : /* no certificate was sent */
804 305 : return GNUTLS_E_NO_CERTIFICATE_FOUND;
805 : }
806 :
807 3010 : i = dsize;
808 6688 : while (i > 0) {
809 4488 : DECR_LEN(dsize, 3);
810 4466 : len = _gnutls_read_uint24(p);
811 4466 : p += 3;
812 4466 : DECR_LEN(dsize, len);
813 3678 : peer_certificate_list_size++;
814 3678 : p += len;
815 3678 : i -= len + 3;
816 : }
817 :
818 2200 : if (dsize != 0)
819 0 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
820 :
821 2200 : if (peer_certificate_list_size == 0) {
822 0 : gnutls_assert();
823 0 : return GNUTLS_E_NO_CERTIFICATE_FOUND;
824 : }
825 :
826 : /* Ok we now allocate the memory to hold the
827 : * certificate list
828 : */
829 :
830 2200 : peer_certificate_list =
831 2200 : gnutls_calloc(1,
832 : sizeof(gnutls_pcert_st) *
833 : (peer_certificate_list_size));
834 2200 : if (peer_certificate_list == NULL) {
835 0 : gnutls_assert();
836 0 : return GNUTLS_E_MEMORY_ERROR;
837 : }
838 :
839 : p = data + 3;
840 :
841 : /* Now we start parsing the list (again).
842 : * We don't use DECR_LEN since the list has
843 : * been parsed before.
844 : */
845 :
846 4778 : for (j = 0; j < peer_certificate_list_size; j++) {
847 2833 : len = _gnutls_read_uint24(p);
848 2833 : p += 3;
849 :
850 2833 : tmp.size = len;
851 2833 : tmp.data = p;
852 :
853 2833 : ret =
854 5666 : gnutls_pcert_import_x509_raw(&peer_certificate_list
855 2833 : [j], &tmp,
856 : GNUTLS_X509_FMT_DER, 0);
857 2833 : if (ret < 0) {
858 255 : gnutls_assert();
859 255 : peer_certificate_list_size = j;
860 255 : ret = GNUTLS_E_CERTIFICATE_ERROR;
861 255 : goto cleanup;
862 : }
863 :
864 2578 : p += len;
865 : }
866 :
867 1945 : ret = check_pk_compat(session, peer_certificate_list[0].pubkey);
868 1945 : if (ret < 0) {
869 1 : gnutls_assert();
870 1 : goto cleanup;
871 : }
872 :
873 1944 : ret =
874 1944 : _gnutls_pcert_to_auth_info(info,
875 : peer_certificate_list,
876 : peer_certificate_list_size);
877 1944 : if (ret < 0) {
878 0 : gnutls_assert();
879 0 : goto cleanup;
880 : }
881 :
882 : return 0;
883 :
884 256 : cleanup:
885 281 : CLEAR_CERTS;
886 256 : gnutls_free(peer_certificate_list);
887 256 : return ret;
888 :
889 : }
890 :
891 :
892 20 : int _gnutls_proc_rawpk_crt(gnutls_session_t session,
893 : uint8_t * data, size_t data_size)
894 : {
895 20 : int cert_size, ret;
896 20 : cert_auth_info_t info;
897 20 : gnutls_pcert_st* peer_certificate;
898 20 : gnutls_datum_t tmp_cert;
899 :
900 20 : uint8_t *p = data;
901 20 : ssize_t dsize = data_size;
902 :
903 : /* We assume data != null and data_size > 0 because
904 : * the caller checks this for us. */
905 :
906 : /* Read the length of our certificate. We always have exactly
907 : * one certificate that contains our raw public key. Our message
908 : * looks like:
909 : * <length++certificate> where
910 : * length = 3 bytes and
911 : * certificate = length bytes.
912 : */
913 20 : DECR_LEN(dsize, 3);
914 20 : cert_size = _gnutls_read_uint24(p);
915 20 : p += 3;
916 :
917 : /* Ensure no discrepancy in data */
918 20 : if (cert_size != dsize)
919 0 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
920 :
921 :
922 20 : if (cert_size == 0) {
923 : // No certificate was sent. This is not OK.
924 0 : return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
925 : }
926 :
927 20 : DECR_LEN_FINAL(dsize, cert_size);
928 :
929 : /* We are now going to read our certificate and store it into
930 : * the authentication info structure.
931 : */
932 20 : tmp_cert.size = cert_size;
933 20 : tmp_cert.data = p;
934 :
935 20 : peer_certificate = gnutls_calloc(1, sizeof(*peer_certificate));
936 20 : if (peer_certificate == NULL) {
937 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
938 : }
939 :
940 : // Import our raw certificate holding only a raw public key into this pcert
941 20 : ret = gnutls_pcert_import_rawpk_raw(peer_certificate, &tmp_cert, GNUTLS_X509_FMT_DER, 0, 0);
942 20 : if (ret < 0) {
943 0 : gnutls_assert();
944 0 : goto cleanup;
945 : }
946 :
947 : // Check whether the PK algo is compatible with the negotiated KX
948 20 : ret = check_pk_compat(session, peer_certificate->pubkey);
949 20 : if (ret < 0) {
950 0 : gnutls_assert();
951 0 : goto cleanup;
952 : }
953 :
954 20 : ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE,
955 : sizeof(cert_auth_info_st), 1);
956 20 : if (ret < 0) {
957 0 : gnutls_assert();
958 0 : goto cleanup;
959 : }
960 :
961 20 : info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
962 :
963 : /* Copy our imported certificate into the auth info structure
964 : * and free our temporary cert storage peer_certificate.
965 : */
966 20 : ret = _gnutls_pcert_to_auth_info(info, peer_certificate, 1);
967 20 : if (ret < 0) {
968 0 : gnutls_assert();
969 0 : goto cleanup;
970 : }
971 :
972 : return GNUTLS_E_SUCCESS;
973 :
974 0 : cleanup:
975 0 : if (peer_certificate != NULL) {
976 0 : gnutls_pcert_deinit(peer_certificate);
977 0 : gnutls_free(peer_certificate);
978 : }
979 :
980 0 : return ret;
981 : }
982 :
983 :
984 4179 : int _gnutls_proc_crt(gnutls_session_t session, uint8_t * data, size_t data_size)
985 : {
986 4179 : gnutls_certificate_credentials_t cred;
987 4179 : gnutls_certificate_type_t cert_type;
988 :
989 4179 : cred =
990 4179 : (gnutls_certificate_credentials_t) _gnutls_get_cred(session,
991 : GNUTLS_CRD_CERTIFICATE);
992 4179 : if (cred == NULL) {
993 1 : gnutls_assert();
994 1 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
995 : }
996 :
997 : /* Determine what certificate type we need to process.
998 : * We need to process the certificate of the peer. */
999 4178 : cert_type = get_certificate_type(session, GNUTLS_CTYPE_PEERS);
1000 :
1001 4178 : switch (cert_type) {
1002 4158 : case GNUTLS_CRT_X509:
1003 4158 : return _gnutls_proc_x509_crt(session, data, data_size);
1004 20 : case GNUTLS_CRT_RAWPK:
1005 20 : return _gnutls_proc_rawpk_crt(session, data, data_size);
1006 : default:
1007 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1008 : }
1009 : }
1010 :
1011 : /* Checks if we support the given signature algorithm
1012 : * (RSA or DSA). Returns the corresponding gnutls_pk_algorithm_t
1013 : * if true;
1014 : */
1015 1963 : inline static int _gnutls_check_supported_sign_algo(CertificateSigType algo)
1016 : {
1017 1963 : switch (algo) {
1018 : case RSA_SIGN:
1019 : return GNUTLS_PK_RSA;
1020 : case DSA_SIGN:
1021 399 : return GNUTLS_PK_DSA;
1022 : case ECDSA_SIGN:
1023 405 : return GNUTLS_PK_EC;
1024 : #ifdef ENABLE_GOST
1025 : case GOSTR34102012_256_SIGN:
1026 26 : return GNUTLS_PK_GOST_12_256;
1027 : case GOSTR34102012_512_SIGN:
1028 26 : return GNUTLS_PK_GOST_12_512;
1029 : #endif
1030 : }
1031 :
1032 : return -1;
1033 : }
1034 :
1035 : int
1036 424 : _gnutls_proc_cert_cert_req(gnutls_session_t session, uint8_t * data,
1037 : size_t data_size)
1038 : {
1039 424 : int size, ret;
1040 424 : uint8_t *p;
1041 424 : gnutls_certificate_credentials_t cred;
1042 424 : ssize_t dsize;
1043 424 : int i;
1044 424 : gnutls_pk_algorithm_t pk_algos[MAX_CLIENT_SIGN_ALGOS];
1045 424 : int pk_algos_length;
1046 424 : const version_entry_st *ver = get_version(session);
1047 :
1048 424 : if (unlikely(ver == NULL))
1049 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1050 :
1051 424 : cred = (gnutls_certificate_credentials_t)
1052 424 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
1053 424 : if (cred == NULL) {
1054 0 : gnutls_assert();
1055 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1056 : }
1057 :
1058 848 : if ((ret =
1059 424 : _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE,
1060 : sizeof(cert_auth_info_st), 0)) < 0) {
1061 0 : gnutls_assert();
1062 0 : return ret;
1063 : }
1064 :
1065 424 : p = data;
1066 424 : dsize = data_size;
1067 :
1068 424 : DECR_LEN(dsize, 1);
1069 424 : size = p[0];
1070 424 : p++;
1071 : /* check if the sign algorithm is supported.
1072 : */
1073 424 : pk_algos_length = 0;
1074 2387 : for (i = 0; i < size; i++, p++) {
1075 1969 : DECR_LEN(dsize, 1);
1076 3223 : if ((ret = _gnutls_check_supported_sign_algo(*p)) > 0) {
1077 1260 : if (pk_algos_length < MAX_CLIENT_SIGN_ALGOS) {
1078 1191 : pk_algos[pk_algos_length++] = ret;
1079 : }
1080 : }
1081 : }
1082 :
1083 418 : if (pk_algos_length == 0) {
1084 0 : gnutls_assert();
1085 0 : return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
1086 : }
1087 :
1088 418 : if (_gnutls_version_has_selectable_sighash(ver)) {
1089 : /* read supported hashes */
1090 343 : int hash_num;
1091 343 : DECR_LEN(dsize, 2);
1092 343 : hash_num = _gnutls_read_uint16(p);
1093 343 : p += 2;
1094 343 : DECR_LEN(dsize, hash_num);
1095 :
1096 343 : ret = _gnutls_sign_algorithm_parse_data(session, p, hash_num);
1097 343 : if (ret < 0) {
1098 0 : gnutls_assert();
1099 0 : return ret;
1100 : }
1101 :
1102 343 : p += hash_num;
1103 : }
1104 :
1105 : /* read the certificate authorities */
1106 418 : DECR_LEN(dsize, 2);
1107 417 : size = _gnutls_read_uint16(p);
1108 417 : p += 2;
1109 :
1110 417 : DECR_LEN_FINAL(dsize, size);
1111 :
1112 : /* We should reply with a certificate message,
1113 : * even if we have no certificate to send.
1114 : */
1115 413 : session->internals.hsk_flags |= HSK_CRT_ASKED;
1116 :
1117 : /* now we ask the user to tell which one
1118 : * he wants to use.
1119 : */
1120 826 : if ((ret =
1121 413 : _gnutls_select_client_cert(session, p, size, pk_algos,
1122 : pk_algos_length)) < 0) {
1123 2 : gnutls_assert();
1124 2 : return ret;
1125 : }
1126 :
1127 : return 0;
1128 : }
1129 :
1130 : int
1131 396 : _gnutls_gen_cert_client_crt_vrfy(gnutls_session_t session,
1132 : gnutls_buffer_st * data)
1133 : {
1134 396 : int ret;
1135 396 : gnutls_pcert_st *apr_cert_list;
1136 396 : gnutls_privkey_t apr_pkey;
1137 396 : int apr_cert_list_length;
1138 396 : gnutls_datum_t signature = { NULL, 0 };
1139 396 : gnutls_sign_algorithm_t sign_algo;
1140 396 : const version_entry_st *ver = get_version(session);
1141 396 : unsigned init_pos = data->length;
1142 :
1143 396 : if (unlikely(ver == NULL))
1144 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1145 :
1146 : /* find the appropriate certificate */
1147 792 : if ((ret =
1148 396 : _gnutls_get_selected_cert(session, &apr_cert_list,
1149 : &apr_cert_list_length, &apr_pkey)) < 0) {
1150 0 : gnutls_assert();
1151 0 : return ret;
1152 : }
1153 :
1154 396 : if (apr_cert_list_length > 0) {
1155 262 : if ((ret =
1156 131 : _gnutls_handshake_sign_crt_vrfy(session,
1157 : &apr_cert_list[0],
1158 : apr_pkey,
1159 : &signature)) < 0) {
1160 3 : gnutls_assert();
1161 3 : return ret;
1162 : }
1163 128 : sign_algo = ret;
1164 : } else {
1165 : return 0;
1166 : }
1167 :
1168 128 : if (_gnutls_version_has_selectable_sighash(ver)) {
1169 72 : const sign_algorithm_st *aid;
1170 72 : uint8_t p[2];
1171 : /* error checking is not needed here since we have used those algorithms */
1172 72 : aid = _gnutls_sign_to_tls_aid(sign_algo);
1173 72 : if (aid == NULL)
1174 0 : return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM);
1175 :
1176 72 : p[0] = aid->id[0];
1177 72 : p[1] = aid->id[1];
1178 72 : ret = _gnutls_buffer_append_data(data, p, 2);
1179 72 : if (ret < 0) {
1180 0 : gnutls_assert();
1181 0 : goto cleanup;
1182 : }
1183 : }
1184 :
1185 128 : ret =
1186 256 : _gnutls_buffer_append_data_prefix(data, 16, signature.data,
1187 128 : signature.size);
1188 128 : if (ret < 0) {
1189 0 : gnutls_assert();
1190 0 : goto cleanup;
1191 : }
1192 :
1193 128 : ret = data->length - init_pos;
1194 :
1195 128 : cleanup:
1196 128 : _gnutls_free_datum(&signature);
1197 128 : return ret;
1198 : }
1199 :
1200 : int
1201 750 : _gnutls_proc_cert_client_crt_vrfy(gnutls_session_t session,
1202 : uint8_t * data, size_t data_size)
1203 : {
1204 750 : int size, ret;
1205 750 : ssize_t dsize = data_size;
1206 750 : uint8_t *pdata = data;
1207 750 : gnutls_datum_t sig;
1208 750 : cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
1209 750 : gnutls_pcert_st peer_cert;
1210 750 : gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
1211 750 : const version_entry_st *ver = get_version(session);
1212 750 : gnutls_certificate_credentials_t cred;
1213 750 : unsigned vflags;
1214 :
1215 750 : if (unlikely(info == NULL || info->ncerts == 0 || ver == NULL)) {
1216 0 : gnutls_assert();
1217 : /* we need this in order to get peer's certificate */
1218 0 : return GNUTLS_E_INTERNAL_ERROR;
1219 : }
1220 :
1221 750 : cred = (gnutls_certificate_credentials_t)
1222 750 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
1223 750 : if (cred == NULL) {
1224 0 : gnutls_assert();
1225 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1226 : }
1227 :
1228 750 : vflags = cred->verify_flags | session->internals.additional_verify_flags;
1229 :
1230 750 : if (_gnutls_version_has_selectable_sighash(ver)) {
1231 670 : DECR_LEN(dsize, 2);
1232 :
1233 668 : sign_algo = _gnutls_tls_aid_to_sign(pdata[0], pdata[1], ver);
1234 668 : if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
1235 1 : gnutls_assert();
1236 1 : return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
1237 : }
1238 667 : pdata += 2;
1239 : }
1240 :
1241 747 : ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
1242 747 : if (ret < 0)
1243 0 : return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
1244 :
1245 747 : DECR_LEN(dsize, 2);
1246 745 : size = _gnutls_read_uint16(pdata);
1247 745 : pdata += 2;
1248 :
1249 1002 : DECR_LEN_FINAL(dsize, size);
1250 :
1251 488 : sig.data = pdata;
1252 488 : sig.size = size;
1253 :
1254 488 : ret = _gnutls_get_auth_info_pcert(&peer_cert,
1255 : session->security_parameters.
1256 : client_ctype, info);
1257 :
1258 488 : if (ret < 0) {
1259 0 : gnutls_assert();
1260 0 : return ret;
1261 : }
1262 :
1263 976 : if ((ret =
1264 488 : _gnutls_handshake_verify_crt_vrfy(session, vflags, &peer_cert, &sig,
1265 : sign_algo)) < 0) {
1266 235 : gnutls_assert();
1267 235 : gnutls_pcert_deinit(&peer_cert);
1268 235 : return ret;
1269 : }
1270 253 : gnutls_pcert_deinit(&peer_cert);
1271 :
1272 253 : return 0;
1273 : }
1274 :
1275 : int
1276 2708 : _gnutls_gen_cert_server_cert_req(gnutls_session_t session,
1277 : gnutls_buffer_st * data)
1278 : {
1279 2708 : gnutls_certificate_credentials_t cred;
1280 2708 : int ret, i;
1281 2708 : uint8_t tmp_data[CERTTYPE_SIZE];
1282 2708 : const version_entry_st *ver = get_version(session);
1283 2708 : unsigned init_pos = data->length;
1284 :
1285 2708 : if (unlikely(ver == NULL))
1286 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1287 :
1288 : /* Now we need to generate the RDN sequence. This is
1289 : * already in the CERTIFICATE_CRED structure, to improve
1290 : * performance.
1291 : */
1292 :
1293 2708 : cred = (gnutls_certificate_credentials_t)
1294 2708 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
1295 2708 : if (cred == NULL) {
1296 0 : gnutls_assert();
1297 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1298 : }
1299 :
1300 2708 : i = 1;
1301 : #ifdef ENABLE_GOST
1302 2708 : if (_gnutls_kx_is_vko_gost(session->security_parameters.cs->kx_algorithm)) {
1303 26 : tmp_data[i++] = GOSTR34102012_256_SIGN;
1304 26 : tmp_data[i++] = GOSTR34102012_512_SIGN;
1305 : } else
1306 : #endif
1307 : {
1308 2682 : tmp_data[i++] = RSA_SIGN;
1309 2682 : tmp_data[i++] = DSA_SIGN;
1310 2682 : tmp_data[i++] = ECDSA_SIGN;
1311 : }
1312 2708 : tmp_data[0] = i - 1;
1313 :
1314 2708 : ret = _gnutls_buffer_append_data(data, tmp_data, i);
1315 2708 : if (ret < 0)
1316 0 : return gnutls_assert_val(ret);
1317 :
1318 2708 : if (_gnutls_version_has_selectable_sighash(ver)) {
1319 2589 : ret =
1320 2589 : _gnutls_sign_algorithm_write_params(session, data);
1321 2589 : if (ret < 0) {
1322 0 : gnutls_assert();
1323 0 : return ret;
1324 : }
1325 : }
1326 :
1327 2708 : if (session->security_parameters.client_ctype == GNUTLS_CRT_X509 &&
1328 2703 : session->internals.ignore_rdn_sequence == 0) {
1329 :
1330 2703 : ret =
1331 5406 : _gnutls_buffer_append_data_prefix(data, 16,
1332 : cred->
1333 2703 : tlist->x509_rdn_sequence.
1334 : data,
1335 2703 : cred->
1336 2703 : tlist->x509_rdn_sequence.
1337 : size);
1338 2703 : if (ret < 0)
1339 0 : return gnutls_assert_val(ret);
1340 : } else {
1341 5 : ret = _gnutls_buffer_append_prefix(data, 16, 0);
1342 5 : if (ret < 0)
1343 0 : return gnutls_assert_val(ret);
1344 : }
1345 :
1346 2708 : return data->length - init_pos;
1347 : }
1348 :
1349 : /* This function will return the appropriate certificate to use.
1350 : * Fills in the apr_cert_list, apr_cert_list_length and apr_pkey.
1351 : * The return value is a negative error code on error.
1352 : *
1353 : * It is normal to return 0 with no certificates in client side.
1354 : *
1355 : */
1356 : int
1357 20051 : _gnutls_get_selected_cert(gnutls_session_t session,
1358 : gnutls_pcert_st ** apr_cert_list,
1359 : int *apr_cert_list_length,
1360 : gnutls_privkey_t * apr_pkey)
1361 : {
1362 20051 : if (session->security_parameters.entity == GNUTLS_SERVER) {
1363 :
1364 18482 : *apr_cert_list = session->internals.selected_cert_list;
1365 18482 : *apr_pkey = session->internals.selected_key;
1366 18482 : *apr_cert_list_length =
1367 18482 : session->internals.selected_cert_list_length;
1368 :
1369 18482 : if (*apr_cert_list_length == 0 || *apr_cert_list == NULL) {
1370 0 : gnutls_assert();
1371 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1372 : }
1373 :
1374 : } else { /* CLIENT SIDE */
1375 : /* _gnutls_select_client_cert() must have been called before.
1376 : */
1377 1569 : *apr_cert_list = session->internals.selected_cert_list;
1378 1569 : *apr_cert_list_length =
1379 1569 : session->internals.selected_cert_list_length;
1380 1569 : *apr_pkey = session->internals.selected_key;
1381 :
1382 : }
1383 :
1384 : return 0;
1385 : }
1386 :
1387 :
1388 35127 : void _gnutls_selected_certs_deinit(gnutls_session_t session)
1389 : {
1390 35127 : if (session->internals.selected_need_free != 0) {
1391 : int i;
1392 :
1393 24 : for (i = 0;
1394 24 : i < session->internals.selected_cert_list_length; i++) {
1395 16 : gnutls_pcert_deinit(&session->internals.
1396 16 : selected_cert_list[i]);
1397 : }
1398 8 : gnutls_free(session->internals.selected_cert_list);
1399 :
1400 8 : for (i = 0;
1401 8 : i < session->internals.selected_ocsp_length; i++) {
1402 0 : _gnutls_free_datum(&session->internals.
1403 0 : selected_ocsp[i].response);
1404 : }
1405 8 : gnutls_free(session->internals.selected_ocsp);
1406 :
1407 8 : gnutls_privkey_deinit(session->internals.selected_key);
1408 : }
1409 35127 : session->internals.selected_ocsp_func = NULL;
1410 :
1411 35127 : session->internals.selected_cert_list = NULL;
1412 35127 : session->internals.selected_cert_list_length = 0;
1413 :
1414 35127 : session->internals.selected_key = NULL;
1415 :
1416 35127 : return;
1417 : }
1418 :
1419 : static void
1420 11902 : selected_certs_set(gnutls_session_t session,
1421 : gnutls_pcert_st * certs, int ncerts,
1422 : gnutls_ocsp_data_st *ocsp, unsigned nocsp,
1423 : gnutls_privkey_t key, int need_free,
1424 : gnutls_status_request_ocsp_func ocsp_func,
1425 : void *ocsp_func_ptr)
1426 : {
1427 11902 : _gnutls_selected_certs_deinit(session);
1428 :
1429 11902 : session->internals.selected_cert_list = certs;
1430 11902 : session->internals.selected_cert_list_length = ncerts;
1431 :
1432 11902 : session->internals.selected_ocsp = ocsp;
1433 11902 : session->internals.selected_ocsp_length = nocsp;
1434 :
1435 11902 : session->internals.selected_key = key;
1436 11902 : session->internals.selected_need_free = need_free;
1437 :
1438 11902 : session->internals.selected_ocsp_func = ocsp_func;
1439 11902 : session->internals.selected_ocsp_func_ptr = ocsp_func_ptr;
1440 11902 : }
1441 :
1442 16899 : static void get_server_name(gnutls_session_t session, uint8_t * name,
1443 : size_t max_name_size)
1444 : {
1445 16899 : int ret, i;
1446 16899 : size_t max_name;
1447 16899 : unsigned int type;
1448 :
1449 16899 : ret = 0;
1450 32003 : for (i = 0; !(ret < 0); i++) {
1451 16899 : max_name = max_name_size;
1452 16899 : ret =
1453 16899 : gnutls_server_name_get(session, name, &max_name, &type, i);
1454 16899 : if (ret >= 0 && type == GNUTLS_NAME_DNS)
1455 : return;
1456 : }
1457 :
1458 15104 : name[0] = 0;
1459 :
1460 15104 : return;
1461 : }
1462 :
1463 : /* Checks the compatibility of the pubkey in the certificate with the
1464 : * ciphersuite and selects a signature algorithm (if required by the
1465 : * ciphersuite and TLS version) appropriate for the certificate. If none
1466 : * can be selected returns an error.
1467 : *
1468 : * IMPORTANT
1469 : * Currently this function is only called from _gnutls_select_server_cert,
1470 : * i.e. it is only called at the server. We therefore retrieve the
1471 : * negotiated server certificate type within this function.
1472 : * If, in the future, this routine is called at the client then we
1473 : * need to adapt the implementation accordingly.
1474 : */
1475 : static
1476 23053 : int cert_select_sign_algorithm(gnutls_session_t session,
1477 : gnutls_pcert_st * cert,
1478 : gnutls_privkey_t pkey,
1479 : const gnutls_cipher_suite_entry_st *cs)
1480 : {
1481 23053 : gnutls_pubkey_t pubkey = cert->pubkey;
1482 23053 : gnutls_certificate_type_t cert_type = cert->type;
1483 23053 : unsigned pk = pubkey->params.algo;
1484 23053 : unsigned key_usage;
1485 23053 : gnutls_sign_algorithm_t algo;
1486 23053 : const version_entry_st *ver = get_version(session);
1487 23053 : gnutls_certificate_type_t ctype;
1488 :
1489 23053 : assert(IS_SERVER(session));
1490 :
1491 : /* Retrieve the server certificate type */
1492 23053 : ctype = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
1493 :
1494 23053 : if (ctype != cert_type) {
1495 14 : return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1496 : }
1497 :
1498 23039 : key_usage = get_key_usage(session, pubkey);
1499 :
1500 : /* In TLS1.3 we support only signatures; ensure the selected key supports them */
1501 23039 : if (ver->tls13_sem && _gnutls_check_key_usage_for_sig(session, key_usage, 1) < 0)
1502 28 : return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1503 :
1504 23011 : if (!ver->tls13_sem && !_gnutls_kx_supports_pk_usage(cs->kx_algorithm, pk, key_usage)) {
1505 9472 : return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1506 : }
1507 :
1508 13877 : if (!ver->tls13_sem && _gnutls_kx_encipher_type(cs->kx_algorithm) != CIPHER_SIGN)
1509 : return 0;
1510 :
1511 10218 : if (!_gnutls_version_has_selectable_sighash(ver)) {
1512 : /* For SSL3.0 and TLS1.0 we lie as we cannot express md5-sha1 as
1513 : * signature algorithm. */
1514 1460 : algo = gnutls_pk_to_sign(cert->pubkey->params.algo, GNUTLS_DIG_SHA1);
1515 1460 : gnutls_sign_algorithm_set_server(session, algo);
1516 1460 : return 0;
1517 : }
1518 :
1519 8758 : algo = _gnutls_session_get_sign_algo(session, cert, pkey, 0, cs->kx_algorithm);
1520 8758 : if (algo == GNUTLS_SIGN_UNKNOWN)
1521 2630 : return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
1522 :
1523 6219 : gnutls_sign_algorithm_set_server(session, algo);
1524 6219 : _gnutls_handshake_log("Selected signature algorithm: %s\n", gnutls_sign_algorithm_get_name(algo));
1525 :
1526 : return 0;
1527 : }
1528 :
1529 : /* finds the most appropriate certificate in the cert list.
1530 : * The 'appropriate' is defined by the user.
1531 : *
1532 : * requested_algo holds the parameters required by the peer (RSA, DSA
1533 : * or -1 for any).
1534 : *
1535 : * Returns 0 on success and a negative error code on error. The
1536 : * selected certificate will be in session->internals.selected_*.
1537 : *
1538 : */
1539 : int
1540 16969 : _gnutls_select_server_cert(gnutls_session_t session, const gnutls_cipher_suite_entry_st *cs)
1541 : {
1542 16969 : unsigned i, j;
1543 16969 : int idx, ret;
1544 16969 : gnutls_certificate_credentials_t cred;
1545 16969 : char server_name[MAX_CN];
1546 :
1547 16969 : cred = (gnutls_certificate_credentials_t)
1548 16969 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
1549 16969 : if (cred == NULL) {
1550 29 : gnutls_assert(); /* we don't need to select a cert */
1551 29 : return 0;
1552 : }
1553 :
1554 : /* When a callback is set, we call it once to get the
1555 : * certificate and then check its compatibility with
1556 : * the ciphersuites.
1557 : */
1558 16940 : if (cred->get_cert_callback3) {
1559 41 : if (session->internals.selected_cert_list_length == 0) {
1560 14 : ret = call_get_cert_callback(session, NULL, 0, NULL, 0);
1561 14 : if (ret < 0)
1562 0 : return gnutls_assert_val(ret);
1563 :
1564 14 : if (session->internals.selected_cert_list_length == 0)
1565 0 : return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1566 :
1567 14 : _gnutls_debug_log("Selected (%s) cert\n",
1568 : gnutls_pk_get_name(session->internals.selected_cert_list[0].pubkey->params.algo));
1569 : }
1570 :
1571 41 : ret = cert_select_sign_algorithm(session,
1572 : &session->internals.selected_cert_list[0],
1573 : session->internals.selected_key,
1574 : cs);
1575 41 : if (ret < 0)
1576 27 : return gnutls_assert_val(ret);
1577 :
1578 : return 0;
1579 : }
1580 :
1581 : /* Otherwise... we check the compatibility of the ciphersuite
1582 : * with all the certificates available. */
1583 :
1584 16899 : get_server_name(session, (unsigned char *)server_name,
1585 : sizeof(server_name));
1586 :
1587 16899 : _gnutls_handshake_log ("HSK[%p]: Requested server name: '%s'\n",
1588 : session, server_name);
1589 16899 : idx = -1; /* default is use no certificate */
1590 :
1591 : /* find certificates that match the requested server_name
1592 : */
1593 :
1594 16899 : if (server_name[0] != 0) {
1595 4690 : for (j = 0; j < cred->ncerts; j++) {
1596 3277 : i = cred->sorted_cert_idx[j];
1597 :
1598 3277 : if (cred->certs[i].names != NULL
1599 6572 : && _gnutls_str_array_match(cred->certs[i].names,
1600 : server_name) != 0) {
1601 : /* if requested algorithms are also compatible select it */
1602 :
1603 1326 : ret = cert_select_sign_algorithm(session,
1604 : &cred->certs[i].cert_list[0],
1605 : cred->certs[i].pkey,
1606 : cs);
1607 1326 : if (ret >= 0) {
1608 382 : idx = i;
1609 382 : _gnutls_debug_log("Selected (%s) cert based on ciphersuite %x.%x: %s\n",
1610 : gnutls_pk_get_name(cred->certs[i].cert_list[0].pubkey->params.algo),
1611 : (unsigned)cs->id[0],
1612 : (unsigned)cs->id[1],
1613 : cs->name);
1614 : /* found */
1615 382 : goto finished;
1616 : }
1617 : }
1618 : }
1619 : }
1620 :
1621 : /* no name match */
1622 27261 : for (j = 0; j < cred->ncerts; j++) {
1623 21686 : i = cred->sorted_cert_idx[j];
1624 :
1625 21686 : _gnutls_handshake_log
1626 : ("HSK[%p]: checking compat of %s with certificate[%d] (%s/%s)\n",
1627 : session, cs->name, i,
1628 : gnutls_pk_get_name(cred->certs[i].cert_list[0].pubkey->
1629 : params.algo),
1630 : gnutls_certificate_type_get_name(cred->certs[i].
1631 : cert_list[0].type));
1632 :
1633 43372 : ret = cert_select_sign_algorithm(session,
1634 : &cred->certs[i].cert_list[0],
1635 21686 : cred->certs[i].pkey,
1636 : cs);
1637 21686 : if (ret >= 0) {
1638 10942 : idx = i;
1639 10942 : _gnutls_debug_log("Selected (%s) cert based on ciphersuite %x.%x: %s\n",
1640 : gnutls_pk_get_name(cred->certs[i].cert_list[0].pubkey->params.algo),
1641 : (unsigned)cs->id[0],
1642 : (unsigned)cs->id[1],
1643 : cs->name);
1644 : /* found */
1645 10942 : goto finished;
1646 : }
1647 : }
1648 :
1649 : /* store the certificate pointer for future use, in the handshake.
1650 : * (This will allow not calling this callback again.)
1651 : */
1652 5575 : finished:
1653 16899 : if (idx >= 0) {
1654 11324 : gnutls_status_request_ocsp_func ocsp_func = NULL;
1655 11324 : void *ocsp_ptr = NULL;
1656 11324 : gnutls_ocsp_data_st *ocsp = NULL;
1657 11324 : unsigned nocsp = 0;
1658 :
1659 11324 : if (cred->certs[idx].ocsp_data_length > 0) {
1660 25 : ocsp = &cred->certs[idx].ocsp_data[0];
1661 25 : nocsp = cred->certs[idx].ocsp_data_length;
1662 11299 : } else if (cred->glob_ocsp_func != NULL) {
1663 10 : ocsp_func = cred->glob_ocsp_func;
1664 10 : ocsp_ptr = cred->glob_ocsp_func_ptr;
1665 11289 : } else if (cred->certs[idx].ocsp_func != NULL) {
1666 6 : ocsp_func = cred->certs[idx].ocsp_func;
1667 6 : ocsp_ptr = cred->certs[idx].ocsp_func_ptr;
1668 : }
1669 :
1670 11324 : selected_certs_set(session,
1671 : &cred->certs[idx].cert_list[0],
1672 11324 : cred->certs[idx].cert_list_length,
1673 : ocsp, nocsp,
1674 : cred->certs[idx].pkey, 0,
1675 : ocsp_func,
1676 : ocsp_ptr);
1677 : } else {
1678 : /* Certificate does not support REQUESTED_ALGO. */
1679 5598 : return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
1680 : }
1681 :
1682 11324 : return 0;
1683 : }
1684 :
1685 3528 : int _gnutls_gen_dhe_signature(gnutls_session_t session,
1686 : gnutls_buffer_st * data, uint8_t * plain,
1687 : unsigned plain_size)
1688 : {
1689 3528 : gnutls_pcert_st *apr_cert_list;
1690 3528 : gnutls_privkey_t apr_pkey;
1691 3528 : int apr_cert_list_length;
1692 3528 : gnutls_datum_t signature = { NULL, 0 }, ddata;
1693 3528 : gnutls_sign_algorithm_t sign_algo;
1694 3528 : const version_entry_st *ver = get_version(session);
1695 3528 : int ret;
1696 :
1697 3528 : if (unlikely(ver == NULL))
1698 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1699 :
1700 3528 : ddata.data = plain;
1701 3528 : ddata.size = plain_size;
1702 :
1703 : /* find the appropriate certificate */
1704 7056 : if ((ret =
1705 3528 : _gnutls_get_selected_cert(session, &apr_cert_list,
1706 : &apr_cert_list_length, &apr_pkey)) < 0) {
1707 0 : gnutls_assert();
1708 0 : return ret;
1709 : }
1710 :
1711 3528 : if (apr_cert_list_length > 0) {
1712 7056 : if ((ret =
1713 3528 : _gnutls_handshake_sign_data(session,
1714 : &apr_cert_list[0],
1715 : apr_pkey, &ddata,
1716 : &signature, &sign_algo)) < 0) {
1717 1 : gnutls_assert();
1718 1 : goto cleanup;
1719 : }
1720 : } else {
1721 0 : gnutls_assert();
1722 0 : ret = 0; /* ANON-DH, do not put a signature - ILLEGAL! */
1723 0 : goto cleanup;
1724 : }
1725 :
1726 3527 : if (_gnutls_version_has_selectable_sighash(ver)) {
1727 2093 : const sign_algorithm_st *aid;
1728 2093 : uint8_t p[2];
1729 :
1730 2093 : if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
1731 0 : ret = GNUTLS_E_UNKNOWN_ALGORITHM;
1732 0 : goto cleanup;
1733 : }
1734 :
1735 2093 : aid = _gnutls_sign_to_tls_aid(sign_algo);
1736 2093 : if (aid == NULL) {
1737 0 : gnutls_assert();
1738 0 : ret = GNUTLS_E_UNKNOWN_ALGORITHM;
1739 0 : goto cleanup;
1740 : }
1741 :
1742 2093 : p[0] = aid->id[0];
1743 2093 : p[1] = aid->id[1];
1744 :
1745 2093 : ret = _gnutls_buffer_append_data(data, p, 2);
1746 2093 : if (ret < 0) {
1747 0 : gnutls_assert();
1748 0 : goto cleanup;
1749 : }
1750 : }
1751 :
1752 3527 : ret =
1753 7054 : _gnutls_buffer_append_data_prefix(data, 16, signature.data,
1754 3527 : signature.size);
1755 3527 : if (ret < 0) {
1756 0 : gnutls_assert();
1757 : }
1758 :
1759 : ret = 0;
1760 :
1761 3528 : cleanup:
1762 3528 : _gnutls_free_datum(&signature);
1763 3528 : return ret;
1764 : }
1765 :
1766 : int
1767 832 : _gnutls_proc_dhe_signature(gnutls_session_t session, uint8_t * data,
1768 : size_t _data_size, gnutls_datum_t * vparams)
1769 : {
1770 832 : int sigsize;
1771 832 : gnutls_datum_t signature;
1772 832 : int ret;
1773 832 : cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
1774 832 : ssize_t data_size = _data_size;
1775 832 : gnutls_pcert_st peer_cert;
1776 832 : gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
1777 832 : const version_entry_st *ver = get_version(session);
1778 832 : gnutls_certificate_credentials_t cred;
1779 832 : unsigned vflags;
1780 832 : gnutls_certificate_type_t cert_type;
1781 :
1782 832 : if (unlikely(info == NULL || info->ncerts == 0 || ver == NULL)) {
1783 0 : gnutls_assert();
1784 : /* we need this in order to get peer's certificate */
1785 0 : return GNUTLS_E_INTERNAL_ERROR;
1786 : }
1787 :
1788 832 : cred = (gnutls_certificate_credentials_t)
1789 832 : _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
1790 832 : if (cred == NULL) {
1791 0 : gnutls_assert();
1792 0 : return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1793 : }
1794 :
1795 832 : vflags = cred->verify_flags | session->internals.additional_verify_flags;
1796 :
1797 : /* VERIFY SIGNATURE */
1798 832 : if (_gnutls_version_has_selectable_sighash(ver)) {
1799 702 : uint8_t id[2];
1800 :
1801 702 : DECR_LEN(data_size, 1);
1802 701 : id[0] = *data++;
1803 701 : DECR_LEN(data_size, 1);
1804 701 : id[1] = *data++;
1805 :
1806 701 : sign_algo = _gnutls_tls_aid_to_sign(id[0], id[1], ver);
1807 701 : if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
1808 1 : _gnutls_debug_log("unknown signature %d.%d\n",
1809 : (int)id[0], (int)id[1]);
1810 1 : gnutls_assert();
1811 1 : return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
1812 : }
1813 : }
1814 830 : DECR_LEN(data_size, 2);
1815 830 : sigsize = _gnutls_read_uint16(data);
1816 830 : data += 2;
1817 :
1818 830 : DECR_LEN_FINAL(data_size, sigsize);
1819 829 : signature.data = data;
1820 829 : signature.size = sigsize;
1821 :
1822 : // Retrieve the negotiated certificate type
1823 829 : cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
1824 :
1825 1658 : if ((ret =
1826 829 : _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info)) < 0) {
1827 0 : gnutls_assert();
1828 0 : return ret;
1829 : }
1830 :
1831 829 : ret =
1832 829 : _gnutls_handshake_verify_data(session, vflags, &peer_cert, vparams,
1833 : &signature, sign_algo);
1834 :
1835 829 : gnutls_pcert_deinit(&peer_cert);
1836 829 : if (ret < 0) {
1837 31 : gnutls_assert();
1838 31 : return ret;
1839 : }
1840 :
1841 : return 0;
1842 : }
|