File: | lib/auth/cert.c |
Location: | line 1788, column 7 |
Description: | Value stored to 'size' is never read |
1 | /* |
2 | * Copyright (C) 2001-2012 Free Software Foundation, Inc. |
3 | * |
4 | * Author: Nikos Mavrogiannopoulos |
5 | * |
6 | * This file is part of GnuTLS. |
7 | * |
8 | * The GnuTLS is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public License |
10 | * as published by the Free Software Foundation; either version 3 of |
11 | * the License, or (at your option) any later version. |
12 | * |
13 | * This library is distributed in the hope that it will be useful, but |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Lesser General Public License |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
20 | * |
21 | */ |
22 | |
23 | /* The certificate authentication functions which are needed in the handshake, |
24 | * and are common to RSA and DHE key exchange, are in this file. |
25 | */ |
26 | |
27 | #include <gnutls_int.h> |
28 | #include "gnutls_auth.h" |
29 | #include "gnutls_errors.h" |
30 | #include <auth/cert.h> |
31 | #include "gnutls_dh.h" |
32 | #include "gnutls_num.h" |
33 | #include "libtasn1.h" |
34 | #include "gnutls_datum.h" |
35 | #include "ext/signature.h" |
36 | #include <gnutls_pk.h> |
37 | #include <algorithms.h> |
38 | #include <gnutls_global.h> |
39 | #include <gnutls_record.h> |
40 | #include <gnutls_sig.h> |
41 | #include <gnutls_state.h> |
42 | #include <gnutls_pk.h> |
43 | #include <gnutls_x509.h> |
44 | #include <gnutls/abstract.h> |
45 | #include "debug.h" |
46 | |
47 | #ifdef ENABLE_OPENPGP1 |
48 | #include "openpgp/gnutls_openpgp.h" |
49 | |
50 | static gnutls_privkey_t alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t |
51 | key, int deinit); |
52 | static gnutls_pcert_st *alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert); |
53 | |
54 | #endif |
55 | |
56 | static gnutls_pcert_st *alloc_and_load_x509_certs (gnutls_x509_crt_t * certs, |
57 | unsigned); |
58 | static gnutls_privkey_t alloc_and_load_x509_key (gnutls_x509_privkey_t key, |
59 | int deinit); |
60 | |
61 | #ifdef ENABLE_PKCS111 |
62 | static gnutls_privkey_t alloc_and_load_pkcs11_key (gnutls_pkcs11_privkey_t |
63 | key, int deinit); |
64 | #endif |
65 | |
66 | #define MAX_CLIENT_SIGN_ALGOS3 3 |
67 | #define CERTTYPE_SIZE(3 +1) (MAX_CLIENT_SIGN_ALGOS3+1) |
68 | typedef enum CertificateSigType |
69 | { RSA_SIGN = 1, DSA_SIGN = 2, ECDSA_SIGN = 64 |
70 | } CertificateSigType; |
71 | |
72 | /* Copies data from a internal certificate struct (gnutls_pcert_st) to |
73 | * exported certificate struct (cert_auth_info_t) |
74 | */ |
75 | static int |
76 | _gnutls_copy_certificate_auth_info (cert_auth_info_t info, gnutls_pcert_st * certs, size_t ncerts, int subkey_used, /* openpgp only */ |
77 | void *keyid) |
78 | { |
79 | /* Copy peer's information to auth_info_t |
80 | */ |
81 | int ret; |
82 | size_t i, j; |
83 | |
84 | if (info->raw_certificate_list != NULL((void*)0)) |
85 | { |
86 | for (j = 0; j < info->ncerts; j++) |
87 | _gnutls_free_datum (&info->raw_certificate_list[j])_gnutls_free_datum_m(&info->raw_certificate_list[j], gnutls_free ); |
88 | gnutls_free (info->raw_certificate_list); |
89 | } |
90 | |
91 | if (ncerts == 0) |
92 | { |
93 | info->raw_certificate_list = NULL((void*)0); |
94 | info->ncerts = 0; |
95 | return 0; |
96 | } |
97 | |
98 | info->raw_certificate_list = |
99 | gnutls_calloc (ncerts, sizeof (gnutls_datum_t)); |
100 | if (info->raw_certificate_list == NULL((void*)0)) |
101 | { |
102 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",102); } while(0);; |
103 | return GNUTLS_E_MEMORY_ERROR-25; |
104 | } |
105 | |
106 | for (i = 0; i < ncerts; i++) |
107 | { |
108 | if (certs[i].cert.size > 0) |
109 | { |
110 | ret = |
111 | _gnutls_set_datum (&info->raw_certificate_list[i],_gnutls_set_datum_m(&info->raw_certificate_list[i],certs [i].cert.data,certs[i].cert.size, gnutls_malloc) |
112 | certs[i].cert.data, certs[i].cert.size)_gnutls_set_datum_m(&info->raw_certificate_list[i],certs [i].cert.data,certs[i].cert.size, gnutls_malloc); |
113 | if (ret < 0) |
114 | { |
115 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",115); } while(0);; |
116 | goto clear; |
117 | } |
118 | } |
119 | } |
120 | info->ncerts = ncerts; |
121 | info->cert_type = certs[0].type; |
122 | |
123 | #ifdef ENABLE_OPENPGP1 |
124 | if (certs[0].type == GNUTLS_CRT_OPENPGP) |
125 | { |
126 | info->use_subkey = subkey_used; |
127 | if (keyid) |
128 | memcpy (info->subkey_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE8); |
129 | } |
130 | #endif |
131 | |
132 | return 0; |
133 | |
134 | clear: |
135 | |
136 | for (j = 0; j < i; j++) |
137 | _gnutls_free_datum (&info->raw_certificate_list[j])_gnutls_free_datum_m(&info->raw_certificate_list[j], gnutls_free ); |
138 | |
139 | gnutls_free (info->raw_certificate_list); |
140 | info->raw_certificate_list = NULL((void*)0); |
141 | |
142 | return ret; |
143 | } |
144 | |
145 | |
146 | |
147 | |
148 | /* returns 0 if the algo_to-check exists in the pk_algos list, |
149 | * -1 otherwise. |
150 | */ |
151 | inline static int |
152 | _gnutls_check_pk_algo_in_list (const gnutls_pk_algorithm_t * |
153 | pk_algos, int pk_algos_length, |
154 | gnutls_pk_algorithm_t algo_to_check) |
155 | { |
156 | int i; |
157 | for (i = 0; i < pk_algos_length; i++) |
158 | { |
159 | if (algo_to_check == pk_algos[i]) |
160 | { |
161 | return 0; |
162 | } |
163 | } |
164 | return -1; |
165 | } |
166 | |
167 | |
168 | /* Returns the issuer's Distinguished name in odn, of the certificate |
169 | * specified in cert. |
170 | */ |
171 | static int |
172 | _gnutls_cert_get_issuer_dn (gnutls_pcert_st * cert, gnutls_datum_t * odn) |
173 | { |
174 | ASN1_TYPE dn; |
175 | int len, result; |
176 | int start, end; |
177 | |
178 | if ((result = asn1_create_element |
179 | (_gnutls_get_pkix ()((ASN1_TYPE) _gnutls_pkix1_asn), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS0) |
180 | { |
181 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",181); } while(0);; |
182 | return _gnutls_asn2err (result); |
183 | } |
184 | |
185 | result = asn1_der_decoding (&dn, cert->cert.data, cert->cert.size, NULL((void*)0)); |
186 | if (result != ASN1_SUCCESS0) |
187 | { |
188 | /* couldn't decode DER */ |
189 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",189); } while(0);; |
190 | asn1_delete_structure (&dn); |
191 | return _gnutls_asn2err (result); |
192 | } |
193 | |
194 | result = asn1_der_decoding_startEnd (dn, cert->cert.data, cert->cert.size, |
195 | "tbsCertificate.issuer", &start, &end); |
196 | |
197 | if (result != ASN1_SUCCESS0) |
198 | { |
199 | /* couldn't decode DER */ |
200 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",200); } while(0);; |
201 | asn1_delete_structure (&dn); |
202 | return _gnutls_asn2err (result); |
203 | } |
204 | asn1_delete_structure (&dn); |
205 | |
206 | len = end - start + 1; |
207 | |
208 | odn->size = len; |
209 | odn->data = &cert->cert.data[start]; |
210 | |
211 | return 0; |
212 | } |
213 | |
214 | |
215 | /* Locates the most appropriate x509 certificate using the |
216 | * given DN. If indx == -1 then no certificate was found. |
217 | * |
218 | * That is to guess which certificate to use, based on the |
219 | * CAs and sign algorithms supported by the peer server. |
220 | */ |
221 | static int |
222 | _find_x509_cert (const gnutls_certificate_credentials_t cred, |
223 | opaque * _data, size_t _data_size, |
224 | const gnutls_pk_algorithm_t * pk_algos, |
225 | int pk_algos_length, int *indx) |
226 | { |
227 | unsigned size; |
228 | gnutls_datum_t odn = { NULL((void*)0), 0 }; |
229 | opaque *data = _data; |
230 | ssize_t data_size = _data_size; |
231 | unsigned i, j; |
232 | int result, cert_pk; |
233 | |
234 | *indx = -1; |
235 | |
236 | do |
237 | { |
238 | |
239 | DECR_LENGTH_RET (data_size, 2, 0)do { data_size-=2; if (data_size<0) {do { if (__builtin_expect ((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",239); } while(0);; return 0;} } while (0); |
240 | size = _gnutls_read_uint16 (data); |
241 | DECR_LENGTH_RET (data_size, size, 0)do { data_size-=size; if (data_size<0) {do { if (__builtin_expect ((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",241); } while(0);; return 0;} } while (0); |
242 | data += 2; |
243 | |
244 | for (i = 0; i < cred->ncerts; i++) |
245 | { |
246 | for (j = 0; j < cred->certs[i].cert_list_length; j++) |
247 | { |
248 | if ((result = |
249 | _gnutls_cert_get_issuer_dn (&cred->certs[i].cert_list[j], |
250 | &odn)) < 0) |
251 | { |
252 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",252); } while(0);; |
253 | return result; |
254 | } |
255 | |
256 | if (odn.size != size) |
257 | continue; |
258 | |
259 | /* If the DN matches and |
260 | * the *_SIGN algorithm matches |
261 | * the cert is our cert! |
262 | */ |
263 | cert_pk = |
264 | gnutls_pubkey_get_pk_algorithm (cred->certs[i].cert_list[0].pubkey, |
265 | NULL((void*)0)); |
266 | |
267 | if ((memcmp (odn.data, data, size) == 0) && |
268 | (_gnutls_check_pk_algo_in_list |
269 | (pk_algos, pk_algos_length, cert_pk) == 0)) |
270 | { |
271 | *indx = i; |
272 | break; |
273 | } |
274 | } |
275 | if (*indx != -1) |
276 | break; |
277 | } |
278 | |
279 | if (*indx != -1) |
280 | break; |
281 | |
282 | /* move to next record */ |
283 | data += size; |
284 | |
285 | } |
286 | while (1); |
287 | |
288 | return 0; |
289 | |
290 | } |
291 | |
292 | #ifdef ENABLE_OPENPGP1 |
293 | /* Locates the most appropriate openpgp cert |
294 | */ |
295 | static int |
296 | _find_openpgp_cert (const gnutls_certificate_credentials_t cred, |
297 | gnutls_pk_algorithm_t * pk_algos, |
298 | int pk_algos_length, int *indx) |
299 | { |
300 | unsigned i, j; |
301 | |
302 | *indx = -1; |
303 | |
304 | for (i = 0; i < cred->ncerts; i++) |
305 | { |
306 | for (j = 0; j < cred->certs[i].cert_list_length; j++) |
307 | { |
308 | |
309 | /* If the *_SIGN algorithm matches |
310 | * the cert is our cert! |
311 | */ |
312 | if ((_gnutls_check_pk_algo_in_list |
313 | (pk_algos, pk_algos_length, |
314 | gnutls_pubkey_get_pk_algorithm (cred->certs[i].cert_list[0].pubkey, |
315 | NULL((void*)0))) == 0) |
316 | && (cred->certs[i].cert_list[0].type == GNUTLS_CRT_OPENPGP)) |
317 | { |
318 | *indx = i; |
319 | break; |
320 | } |
321 | } |
322 | if (*indx != -1) |
323 | break; |
324 | } |
325 | |
326 | return 0; |
327 | } |
328 | #endif |
329 | |
330 | /* Returns the number of issuers in the server's |
331 | * certificate request packet. |
332 | */ |
333 | static int |
334 | get_issuers_num (gnutls_session_t session, opaque * data, ssize_t data_size) |
335 | { |
336 | int issuers_dn_len = 0, result; |
337 | unsigned size; |
338 | |
339 | /* Count the number of the given issuers; |
340 | * This is used to allocate the issuers_dn without |
341 | * using realloc(). |
342 | */ |
343 | |
344 | if (data_size == 0 || data == NULL((void*)0)) |
345 | return 0; |
346 | |
347 | if (data_size > 0) |
348 | do |
349 | { |
350 | /* This works like DECR_LEN() |
351 | */ |
352 | result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH-9; |
353 | DECR_LENGTH_COM (data_size, 2, goto error)do { data_size-=2; if (data_size<0) {do { if (__builtin_expect ((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",353); } while(0);; goto error;} } while (0); |
354 | size = _gnutls_read_uint16 (data); |
355 | |
356 | result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH-9; |
357 | DECR_LENGTH_COM (data_size, size, goto error)do { data_size-=size; if (data_size<0) {do { if (__builtin_expect ((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",357); } while(0);; goto error;} } while (0); |
358 | |
359 | data += 2; |
360 | |
361 | if (size > 0) |
362 | { |
363 | issuers_dn_len++; |
364 | data += size; |
365 | } |
366 | |
367 | if (data_size == 0) |
368 | break; |
369 | |
370 | } |
371 | while (1); |
372 | |
373 | return issuers_dn_len; |
374 | |
375 | error: |
376 | return result; |
377 | } |
378 | |
379 | /* Returns the issuers in the server's certificate request |
380 | * packet. |
381 | */ |
382 | static int |
383 | get_issuers (gnutls_session_t session, |
384 | gnutls_datum_t * issuers_dn, int issuers_len, |
385 | opaque * data, size_t data_size) |
386 | { |
387 | int i; |
388 | unsigned size; |
389 | |
390 | if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) |
391 | return 0; |
392 | |
393 | /* put the requested DNs to req_dn, only in case |
394 | * of X509 certificates. |
395 | */ |
396 | if (issuers_len > 0) |
397 | { |
398 | |
399 | for (i = 0; i < issuers_len; i++) |
400 | { |
401 | /* The checks here for the buffer boundaries |
402 | * are not needed since the buffer has been |
403 | * parsed above. |
404 | */ |
405 | data_size -= 2; |
406 | |
407 | size = _gnutls_read_uint16 (data); |
408 | |
409 | data += 2; |
410 | |
411 | issuers_dn[i].data = data; |
412 | issuers_dn[i].size = size; |
413 | |
414 | data += size; |
415 | } |
416 | } |
417 | |
418 | return 0; |
419 | } |
420 | |
421 | static void |
422 | st_to_st2 (gnutls_retr2_st * st2, gnutls_retr_st * st) |
423 | { |
424 | st2->cert_type = st->type; |
425 | if (st->type == GNUTLS_CRT_OPENPGP) |
426 | { |
427 | st2->key_type = GNUTLS_PRIVKEY_OPENPGP; |
428 | } |
429 | else |
430 | { |
431 | st2->key_type = GNUTLS_PRIVKEY_X509; |
432 | } |
433 | st2->ncerts = st->ncerts; |
434 | st2->deinit_all = st->deinit_all; |
435 | |
436 | switch (st2->cert_type) |
437 | { |
438 | case GNUTLS_CRT_OPENPGP: |
439 | st2->cert.pgp = st->cert.pgp; |
440 | st2->key.pgp = st->key.pgp; |
441 | break; |
442 | case GNUTLS_CRT_X509: |
443 | st2->cert.x509 = st->cert.x509; |
444 | st2->key.x509 = st->key.x509; |
445 | break; |
446 | default: |
447 | return; |
448 | } |
449 | |
450 | } |
451 | |
452 | /* Calls the client get callback. |
453 | */ |
454 | static int |
455 | call_get_cert_callback (gnutls_session_t session, |
456 | const gnutls_datum_t * issuers_dn, |
457 | int issuers_dn_length, |
458 | gnutls_pk_algorithm_t * pk_algos, int pk_algos_length) |
459 | { |
460 | unsigned i; |
461 | gnutls_pcert_st *local_certs = NULL((void*)0); |
462 | gnutls_privkey_t local_key = NULL((void*)0); |
463 | int ret = GNUTLS_E_INTERNAL_ERROR-59; |
464 | gnutls_certificate_type_t type = gnutls_certificate_type_get (session); |
465 | gnutls_certificate_credentials_t cred; |
466 | gnutls_retr2_st st2; |
467 | gnutls_pcert_st *pcert = NULL((void*)0); |
468 | unsigned int pcert_length = 0; |
469 | |
470 | cred = (gnutls_certificate_credentials_t) |
471 | _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL((void*)0)); |
472 | if (cred == NULL((void*)0)) |
473 | { |
474 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",474); } while(0);; |
475 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
476 | } |
477 | |
478 | memset (&st2, 0, sizeof (st2)); |
479 | |
480 | if (cred->get_cert_callback2) |
481 | { |
482 | /* we avoid all allocations and transformations */ |
483 | ret = cred->get_cert_callback2 (session, issuers_dn, issuers_dn_length, |
484 | pk_algos, pk_algos_length, |
485 | &pcert, &pcert_length, &local_key); |
486 | if (ret < 0) |
487 | return gnutls_assert_val (GNUTLS_E_USER_ERROR)gnutls_assert_val_int(-320, "cert.c", 487); |
488 | |
489 | if (pcert_length > 0 && type != pcert[0].type) |
490 | return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST)gnutls_assert_val_int(-50, "cert.c", 490); |
491 | |
492 | if (pcert_length == 0) |
493 | { |
494 | pcert = NULL((void*)0); |
495 | local_key = NULL((void*)0); |
496 | } |
497 | _gnutls_selected_certs_set (session, pcert, pcert_length, local_key, 0); |
498 | |
499 | return 0; |
500 | |
501 | } |
502 | else if (cred->get_cert_callback) |
503 | { |
504 | ret = cred->get_cert_callback (session, issuers_dn, issuers_dn_length, |
505 | pk_algos, pk_algos_length, &st2); |
506 | |
507 | } |
508 | else |
509 | { /* compatibility mode */ |
510 | gnutls_retr_st st; |
511 | memset (&st, 0, sizeof (st)); |
512 | if (session->security_parameters.entity == GNUTLS_SERVER1) |
513 | { |
514 | if (cred->server_get_cert_callback == NULL((void*)0)) |
515 | { |
516 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",516); } while(0);; |
517 | return GNUTLS_E_INTERNAL_ERROR-59; |
518 | } |
519 | ret = cred->server_get_cert_callback (session, &st); |
520 | if (ret >= 0) |
521 | st_to_st2 (&st2, &st); |
522 | } |
523 | else |
524 | { /* CLIENT */ |
525 | |
526 | if (cred->client_get_cert_callback == NULL((void*)0)) |
527 | { |
528 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",528); } while(0);; |
529 | return GNUTLS_E_INTERNAL_ERROR-59; |
530 | } |
531 | ret = cred->client_get_cert_callback (session, |
532 | issuers_dn, issuers_dn_length, |
533 | pk_algos, pk_algos_length, |
534 | &st); |
535 | if (ret >= 0) |
536 | st_to_st2 (&st2, &st); |
537 | } |
538 | } |
539 | |
540 | if (ret < 0) |
541 | { |
542 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",542); } while(0);; |
543 | return GNUTLS_E_USER_ERROR-320; |
544 | } |
545 | |
546 | if (st2.ncerts == 0) |
547 | return 0; /* no certificate was selected */ |
548 | |
549 | if (type != st2.cert_type) |
550 | { |
551 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",551); } while(0);; |
552 | ret = GNUTLS_E_INVALID_REQUEST-50; |
553 | goto cleanup; |
554 | } |
555 | |
556 | |
557 | if (type == GNUTLS_CRT_X509) |
558 | { |
559 | local_certs = alloc_and_load_x509_certs (st2.cert.x509, st2.ncerts); |
560 | } |
561 | else |
562 | { /* PGP */ |
563 | if (st2.ncerts > 1) |
564 | { |
565 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",565); } while(0);; |
566 | ret = GNUTLS_E_INVALID_REQUEST-50; |
567 | goto cleanup; |
568 | } |
569 | #ifdef ENABLE_OPENPGP1 |
570 | { |
571 | local_certs = alloc_and_load_pgp_certs (st2.cert.pgp); |
572 | } |
573 | #else |
574 | ret = GNUTLS_E_UNIMPLEMENTED_FEATURE-1250; |
575 | goto cleanup; |
576 | #endif |
577 | } |
578 | |
579 | if (local_certs == NULL((void*)0)) |
580 | { |
581 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",581); } while(0);; |
582 | ret = GNUTLS_E_MEMORY_ERROR-25; |
583 | goto cleanup; |
584 | } |
585 | |
586 | switch (st2.key_type) |
587 | { |
588 | case GNUTLS_PRIVKEY_OPENPGP: |
589 | #ifdef ENABLE_OPENPGP1 |
590 | if (st2.key.pgp != NULL((void*)0)) |
591 | { |
592 | local_key = alloc_and_load_pgp_key (st2.key.pgp, st2.deinit_all); |
593 | if (local_key == NULL((void*)0)) |
594 | { |
595 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",595); } while(0);; |
596 | ret = GNUTLS_E_INTERNAL_ERROR-59; |
597 | goto cleanup; |
598 | } |
599 | } |
600 | #endif |
601 | break; |
602 | case GNUTLS_PRIVKEY_PKCS11: |
603 | #ifdef ENABLE_PKCS111 |
604 | if (st2.key.pkcs11 != NULL((void*)0)) |
605 | { |
606 | local_key = |
607 | alloc_and_load_pkcs11_key (st2.key.pkcs11, st2.deinit_all); |
608 | if (local_key == NULL((void*)0)) |
609 | { |
610 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",610); } while(0);; |
611 | ret = GNUTLS_E_INTERNAL_ERROR-59; |
612 | goto cleanup; |
613 | } |
614 | } |
615 | #endif |
616 | break; |
617 | case GNUTLS_PRIVKEY_X509: |
618 | if (st2.key.x509 != NULL((void*)0)) |
619 | { |
620 | local_key = alloc_and_load_x509_key (st2.key.x509, st2.deinit_all); |
621 | if (local_key == NULL((void*)0)) |
622 | { |
623 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",623); } while(0);; |
624 | ret = GNUTLS_E_INTERNAL_ERROR-59; |
625 | goto cleanup; |
626 | } |
627 | } |
628 | break; |
629 | default: |
630 | gnutls_assert()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",630); } while(0);; |
631 | ret = GNUTLS_E_INVALID_REQUEST-50; |
632 | goto cleanup; |
633 | } |
634 | |
635 | _gnutls_selected_certs_set (session, local_certs, |
636 | (local_certs != NULL((void*)0)) ? st2.ncerts : 0, |
637 | local_key, 1); |
638 | |
639 | ret = 0; |
640 | |
641 | cleanup: |
642 | |
643 | if (st2.cert_type == GNUTLS_CRT_X509) |
644 | { |
645 | if (st2.deinit_all) |
646 | { |
647 | for (i = 0; i < st2.ncerts; i++) |
648 | { |
649 | gnutls_x509_crt_deinit (st2.cert.x509[i]); |
650 | } |
651 | gnutls_free(st2.cert.x509); |
652 | } |
653 | } |
654 | else |
655 | { |
656 | #ifdef ENABLE_OPENPGP1 |
657 | if (st2.deinit_all) |
658 | { |
659 | gnutls_openpgp_crt_deinit (st2.cert.pgp); |
660 | } |
661 | #endif |
662 | } |
663 | |
664 | if (ret < 0) |
665 | { |
666 | if (local_key != NULL((void*)0)) |
667 | gnutls_privkey_deinit (local_key); |
668 | } |
669 | |
670 | return ret; |
671 | } |
672 | |
673 | /* Finds the appropriate certificate depending on the cA Distinguished name |
674 | * advertized by the server. If none matches then returns 0 and -1 as index. |
675 | * In case of an error a negative error code, is returned. |
676 | * |
677 | * 20020128: added ability to select a certificate depending on the SIGN |
678 | * algorithm (only in automatic mode). |
679 | */ |
680 | static int |
681 | _select_client_cert (gnutls_session_t session, |
682 | opaque * _data, size_t _data_size, |
683 | gnutls_pk_algorithm_t * pk_algos, int pk_algos_length) |
684 | { |
685 | int result; |
686 | int indx = -1; |
687 | gnutls_certificate_credentials_t cred; |
688 | opaque *data = _data; |
689 | ssize_t data_size = _data_size; |
690 | int issuers_dn_length; |
691 | gnutls_datum_t *issuers_dn = NULL((void*)0); |
692 | |
693 | cred = (gnutls_certificate_credentials_t) |
694 | _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL((void*)0)); |
695 | if (cred == NULL((void*)0)) |
696 | { |
697 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",697); } while(0);; |
698 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
699 | } |
700 | |
701 | if (cred->client_get_cert_callback != NULL((void*)0) |
702 | || cred->get_cert_callback != NULL((void*)0) || cred->get_cert_callback2 != NULL((void*)0)) |
703 | { |
704 | |
705 | /* use a callback to get certificate |
706 | */ |
707 | if (session->security_parameters.cert_type != GNUTLS_CRT_X509) |
708 | issuers_dn_length = 0; |
709 | else |
710 | { |
711 | issuers_dn_length = get_issuers_num (session, data, data_size); |
712 | if (issuers_dn_length < 0) |
713 | { |
714 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",714); } while(0);; |
715 | return issuers_dn_length; |
716 | } |
717 | |
718 | if (issuers_dn_length > 0) |
719 | { |
720 | issuers_dn = |
721 | gnutls_malloc (sizeof (gnutls_datum_t) * issuers_dn_length); |
722 | if (issuers_dn == NULL((void*)0)) |
723 | { |
724 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",724); } while(0);; |
725 | return GNUTLS_E_MEMORY_ERROR-25; |
726 | } |
727 | |
728 | result = |
729 | get_issuers (session, issuers_dn, issuers_dn_length, |
730 | data, data_size); |
731 | if (result < 0) |
732 | { |
733 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",733); } while(0);; |
734 | goto cleanup; |
735 | } |
736 | } |
737 | } |
738 | |
739 | result = |
740 | call_get_cert_callback (session, issuers_dn, issuers_dn_length, |
741 | pk_algos, pk_algos_length); |
742 | goto cleanup; |
743 | |
744 | } |
745 | else |
746 | { |
747 | /* If we have no callbacks, try to guess. |
748 | */ |
749 | result = 0; |
750 | |
751 | if (session->security_parameters.cert_type == GNUTLS_CRT_X509) |
752 | result = |
753 | _find_x509_cert (cred, _data, _data_size, |
754 | pk_algos, pk_algos_length, &indx); |
755 | |
756 | #ifdef ENABLE_OPENPGP1 |
757 | if (session->security_parameters.cert_type == GNUTLS_CRT_OPENPGP) |
758 | result = _find_openpgp_cert (cred, pk_algos, pk_algos_length, &indx); |
759 | #endif |
760 | |
761 | if (result < 0) |
762 | { |
763 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",763); } while(0);; |
764 | return result; |
765 | } |
766 | |
767 | if (indx >= 0) |
768 | { |
769 | _gnutls_selected_certs_set (session, |
770 | &cred->certs[indx].cert_list[0], |
771 | cred->certs[indx].cert_list_length, |
772 | cred->pkey[indx], 0); |
773 | } |
774 | else |
775 | { |
776 | _gnutls_selected_certs_set (session, NULL((void*)0), 0, NULL((void*)0), 0); |
777 | } |
778 | |
779 | result = 0; |
780 | } |
781 | |
782 | cleanup: |
783 | gnutls_free (issuers_dn); |
784 | return result; |
785 | |
786 | } |
787 | |
788 | /* Generate client certificate |
789 | */ |
790 | |
791 | static int |
792 | _gnutls_gen_x509_crt (gnutls_session_t session, gnutls_buffer_st * data) |
793 | { |
794 | int ret, i; |
795 | gnutls_pcert_st *apr_cert_list; |
796 | gnutls_privkey_t apr_pkey; |
797 | int apr_cert_list_length; |
798 | |
799 | /* find the appropriate certificate |
800 | */ |
801 | if ((ret = |
802 | _gnutls_get_selected_cert (session, &apr_cert_list, |
803 | &apr_cert_list_length, &apr_pkey)) < 0) |
804 | { |
805 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",805); } while(0);; |
806 | return ret; |
807 | } |
808 | |
809 | ret = 3; |
810 | for (i = 0; i < apr_cert_list_length; i++) |
811 | { |
812 | ret += apr_cert_list[i].cert.size + 3; |
813 | /* hold size |
814 | * for uint24 */ |
815 | } |
816 | |
817 | /* if no certificates were found then send: |
818 | * 0B 00 00 03 00 00 00 // Certificate with no certs |
819 | * instead of: |
820 | * 0B 00 00 00 // empty certificate handshake |
821 | * |
822 | * ( the above is the whole handshake message, not |
823 | * the one produced here ) |
824 | */ |
825 | |
826 | ret = _gnutls_buffer_append_prefix (data, 24, ret - 3); |
827 | if (ret < 0) |
828 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 828); |
829 | |
830 | for (i = 0; i < apr_cert_list_length; i++) |
831 | { |
832 | ret = |
833 | _gnutls_buffer_append_data_prefix (data, 24, |
834 | apr_cert_list[i].cert.data, |
835 | apr_cert_list[i].cert.size); |
836 | if (ret < 0) |
837 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 837); |
838 | } |
839 | |
840 | return data->length; |
841 | } |
842 | |
843 | enum PGPKeyDescriptorType |
844 | { PGP_KEY_FINGERPRINT, PGP_KEY, PGP_KEY_SUBKEY, PGP_KEY_FINGERPRINT_SUBKEY }; |
845 | |
846 | #ifdef ENABLE_OPENPGP1 |
847 | static int |
848 | _gnutls_gen_openpgp_certificate (gnutls_session_t session, |
849 | gnutls_buffer_st * data) |
850 | { |
851 | int ret; |
852 | gnutls_pcert_st *apr_cert_list; |
853 | gnutls_privkey_t apr_pkey; |
854 | int apr_cert_list_length; |
855 | uint8_t type; |
856 | uint8_t fpr[20]; |
857 | size_t fpr_size; |
858 | unsigned int use_subkey = 0; |
859 | |
860 | /* find the appropriate certificate */ |
861 | if ((ret = |
862 | _gnutls_get_selected_cert (session, &apr_cert_list, |
863 | &apr_cert_list_length, &apr_pkey)) < 0) |
864 | { |
865 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",865); } while(0);; |
866 | return ret; |
867 | } |
868 | |
869 | ret = 3 + 1 + 3; |
870 | |
871 | |
872 | |
873 | if (apr_cert_list_length > 0) |
874 | { |
875 | fpr_size = sizeof (fpr); |
876 | ret = |
877 | gnutls_pubkey_get_openpgp_key_id (apr_cert_list[0].pubkey, 0, fpr, |
878 | &fpr_size, &use_subkey); |
879 | if (ret < 0) |
880 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 880); |
881 | |
882 | if (use_subkey != 0) |
883 | ret += 1 + fpr_size; /* for the keyid */ |
884 | |
885 | ret += apr_cert_list[0].cert.size; |
886 | } |
887 | |
888 | ret = _gnutls_buffer_append_prefix (data, 24, ret - 3); |
889 | if (ret < 0) |
890 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 890); |
891 | |
892 | |
893 | if (apr_cert_list_length > 0) |
894 | { |
895 | if (use_subkey != 0) |
896 | { |
897 | type = PGP_KEY_SUBKEY; |
898 | |
899 | ret = _gnutls_buffer_append_data (data, &type, 1); |
900 | if (ret < 0) |
901 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 901); |
902 | |
903 | ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size); |
904 | if (ret < 0) |
905 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 905); |
906 | } |
907 | else |
908 | { |
909 | type = PGP_KEY; |
910 | ret = _gnutls_buffer_append_data (data, &type, 1); |
911 | if (ret < 0) |
912 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 912); |
913 | } |
914 | |
915 | ret = |
916 | _gnutls_buffer_append_data_prefix (data, 24, |
917 | apr_cert_list[0].cert.data, |
918 | apr_cert_list[0].cert.size); |
919 | if (ret < 0) |
920 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 920); |
921 | } |
922 | else /* empty - no certificate */ |
923 | { |
924 | type = PGP_KEY; |
925 | |
926 | ret = _gnutls_buffer_append_data (data, &type, 1); |
927 | if (ret < 0) |
928 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 928); |
929 | |
930 | ret = _gnutls_buffer_append_prefix (data, 24, 0); |
931 | if (ret < 0) |
932 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 932); |
933 | } |
934 | |
935 | return data->length; |
936 | } |
937 | |
938 | static int |
939 | _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session, |
940 | gnutls_buffer_st * data) |
941 | { |
942 | int ret, packet_size; |
943 | uint8_t type, fpr[20]; |
944 | size_t fpr_size; |
945 | gnutls_pcert_st *apr_cert_list; |
946 | gnutls_privkey_t apr_pkey; |
947 | int apr_cert_list_length; |
948 | unsigned int use_subkey = 0; |
949 | |
950 | /* find the appropriate certificate */ |
951 | if ((ret = |
952 | _gnutls_get_selected_cert (session, &apr_cert_list, |
953 | &apr_cert_list_length, &apr_pkey)) < 0) |
954 | { |
955 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",955); } while(0);; |
956 | return ret; |
957 | } |
958 | |
959 | fpr_size = sizeof (fpr); |
960 | ret = |
961 | gnutls_pubkey_get_openpgp_key_id (apr_cert_list[0].pubkey, 0, fpr, |
962 | &fpr_size, &use_subkey); |
963 | if (ret < 0) |
964 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 964); |
965 | |
966 | packet_size = 3 + 1; |
967 | |
968 | if (use_subkey) |
969 | packet_size += 1 + fpr_size; /* for the keyid */ |
970 | |
971 | /* Only v4 fingerprints are sent |
972 | */ |
973 | if (apr_cert_list_length > 0) |
974 | packet_size += 20 + 1; |
975 | else /* empty certificate case */ |
976 | return _gnutls_gen_openpgp_certificate (session, data); |
977 | |
978 | ret = _gnutls_buffer_append_prefix (data, 24, packet_size - 3); |
979 | if (ret < 0) |
980 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 980); |
981 | |
982 | if (use_subkey) |
983 | { |
984 | type = PGP_KEY_FINGERPRINT_SUBKEY; |
985 | ret = _gnutls_buffer_append_data (data, &type, 1); |
986 | if (ret < 0) |
987 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 987); |
988 | |
989 | ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size); |
990 | if (ret < 0) |
991 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 991); |
992 | } |
993 | else |
994 | { |
995 | type = PGP_KEY_FINGERPRINT; /* key fingerprint */ |
996 | ret = _gnutls_buffer_append_data (data, &type, 1); |
997 | if (ret < 0) |
998 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 998); |
999 | } |
1000 | |
1001 | fpr_size = sizeof (fpr); |
1002 | if ((ret = |
1003 | _gnutls_openpgp_fingerprint (&apr_cert_list[0].cert, fpr, |
1004 | &fpr_size)) < 0) |
1005 | { |
1006 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1006); } while(0);; |
1007 | return ret; |
1008 | } |
1009 | |
1010 | ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size); |
1011 | if (ret < 0) |
1012 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 1012); |
1013 | |
1014 | return data->length; |
1015 | } |
1016 | #endif |
1017 | |
1018 | |
1019 | int |
1020 | _gnutls_gen_cert_client_certificate (gnutls_session_t session, |
1021 | gnutls_buffer_st * data) |
1022 | { |
1023 | switch (session->security_parameters.cert_type) |
1024 | { |
1025 | #ifdef ENABLE_OPENPGP1 |
1026 | case GNUTLS_CRT_OPENPGP: |
1027 | if (_gnutls_openpgp_send_fingerprint (session) == 0) |
1028 | return _gnutls_gen_openpgp_certificate (session, data); |
1029 | else |
1030 | return _gnutls_gen_openpgp_certificate_fpr (session, data); |
1031 | #endif |
1032 | case GNUTLS_CRT_X509: |
1033 | return _gnutls_gen_x509_crt (session, data); |
1034 | |
1035 | default: |
1036 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1036); } while(0);; |
1037 | return GNUTLS_E_INTERNAL_ERROR-59; |
1038 | } |
1039 | } |
1040 | |
1041 | int |
1042 | _gnutls_gen_cert_server_certificate (gnutls_session_t session, |
1043 | gnutls_buffer_st * data) |
1044 | { |
1045 | switch (session->security_parameters.cert_type) |
1046 | { |
1047 | #ifdef ENABLE_OPENPGP1 |
1048 | case GNUTLS_CRT_OPENPGP: |
1049 | return _gnutls_gen_openpgp_certificate (session, data); |
1050 | #endif |
1051 | case GNUTLS_CRT_X509: |
1052 | return _gnutls_gen_x509_crt (session, data); |
1053 | default: |
1054 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1054); } while(0);; |
1055 | return GNUTLS_E_INTERNAL_ERROR-59; |
1056 | } |
1057 | } |
1058 | |
1059 | /* Process server certificate |
1060 | */ |
1061 | |
1062 | #define CLEAR_CERTSfor(x=0;x<peer_certificate_list_size;x++) gnutls_pcert_deinit (&peer_certificate_list[x]) for(x=0;x<peer_certificate_list_size;x++) gnutls_pcert_deinit(&peer_certificate_list[x]) |
1063 | static int |
1064 | _gnutls_proc_x509_server_certificate (gnutls_session_t session, |
1065 | opaque * data, size_t data_size) |
1066 | { |
1067 | int size, len, ret; |
1068 | opaque *p = data; |
1069 | cert_auth_info_t info; |
1070 | gnutls_certificate_credentials_t cred; |
1071 | ssize_t dsize = data_size; |
1072 | int i; |
1073 | gnutls_pcert_st *peer_certificate_list; |
1074 | size_t peer_certificate_list_size = 0, j, x; |
1075 | gnutls_datum_t tmp; |
1076 | |
1077 | cred = (gnutls_certificate_credentials_t) |
1078 | _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL((void*)0)); |
1079 | if (cred == NULL((void*)0)) |
1080 | { |
1081 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1081); } while(0);; |
1082 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
1083 | } |
1084 | |
1085 | |
1086 | if ((ret = |
1087 | _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, |
1088 | sizeof (cert_auth_info_st), 1)) < 0) |
1089 | { |
1090 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1090); } while(0);; |
1091 | return ret; |
1092 | } |
1093 | |
1094 | info = _gnutls_get_auth_info (session); |
1095 | |
1096 | if (data == NULL((void*)0) || data_size == 0) |
1097 | { |
1098 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1098); } while(0);; |
1099 | /* no certificate was sent */ |
1100 | return GNUTLS_E_NO_CERTIFICATE_FOUND-49; |
1101 | } |
1102 | |
1103 | DECR_LEN (dsize, 3)do { dsize-=3; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1103 ); } while(0);; return -9;} } while (0); |
1104 | size = _gnutls_read_uint24 (p); |
1105 | p += 3; |
1106 | |
1107 | /* some implementations send 0B 00 00 06 00 00 03 00 00 00 |
1108 | * instead of just 0B 00 00 03 00 00 00 as an empty certificate message. |
1109 | */ |
1110 | if (size == 0 || size == 3) |
1111 | { |
1112 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1112); } while(0);; |
1113 | /* no certificate was sent */ |
1114 | return GNUTLS_E_NO_CERTIFICATE_FOUND-49; |
1115 | } |
1116 | |
1117 | i = dsize; |
1118 | while (i > 0) |
1119 | { |
1120 | DECR_LEN (dsize, 3)do { dsize-=3; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1120 ); } while(0);; return -9;} } while (0); |
1121 | len = _gnutls_read_uint24 (p); |
1122 | p += 3; |
1123 | DECR_LEN (dsize, len)do { dsize-=len; if (dsize<0) {do { if (__builtin_expect(( _gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",1123); } while(0);; return -9;} } while (0); |
1124 | peer_certificate_list_size++; |
1125 | p += len; |
1126 | i -= len + 3; |
1127 | } |
1128 | |
1129 | if (peer_certificate_list_size == 0) |
1130 | { |
1131 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1131); } while(0);; |
1132 | return GNUTLS_E_NO_CERTIFICATE_FOUND-49; |
1133 | } |
1134 | |
1135 | /* Ok we now allocate the memory to hold the |
1136 | * certificate list |
1137 | */ |
1138 | |
1139 | peer_certificate_list = |
1140 | gnutls_calloc (1, |
1141 | sizeof (gnutls_pcert_st) * (peer_certificate_list_size)); |
1142 | if (peer_certificate_list == NULL((void*)0)) |
1143 | { |
1144 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1144); } while(0);; |
1145 | return GNUTLS_E_MEMORY_ERROR-25; |
1146 | } |
1147 | |
1148 | p = data + 3; |
1149 | |
1150 | /* Now we start parsing the list (again). |
1151 | * We don't use DECR_LEN since the list has |
1152 | * been parsed before. |
1153 | */ |
1154 | |
1155 | for (j = 0; j < peer_certificate_list_size; j++) |
1156 | { |
1157 | len = _gnutls_read_uint24 (p); |
1158 | p += 3; |
1159 | |
1160 | tmp.size = len; |
1161 | tmp.data = p; |
1162 | |
1163 | ret = |
1164 | gnutls_pcert_import_x509_raw (&peer_certificate_list |
1165 | [j], &tmp, GNUTLS_X509_FMT_DER, 0); |
1166 | if (ret < 0) |
1167 | { |
1168 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1168); } while(0);; |
1169 | goto cleanup; |
1170 | } |
1171 | |
1172 | p += len; |
1173 | } |
1174 | |
1175 | |
1176 | if ((ret = |
1177 | _gnutls_copy_certificate_auth_info (info, |
1178 | peer_certificate_list, |
1179 | peer_certificate_list_size, 0, |
1180 | NULL((void*)0))) < 0) |
1181 | { |
1182 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1182); } while(0);; |
1183 | goto cleanup; |
1184 | } |
1185 | |
1186 | if ((ret = |
1187 | _gnutls_check_key_usage (&peer_certificate_list[0], |
1188 | gnutls_kx_get (session))) < 0) |
1189 | { |
1190 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1190); } while(0);; |
1191 | goto cleanup; |
1192 | } |
1193 | |
1194 | ret = 0; |
1195 | |
1196 | cleanup: |
1197 | CLEAR_CERTSfor(x=0;x<peer_certificate_list_size;x++) gnutls_pcert_deinit (&peer_certificate_list[x]); |
1198 | gnutls_free (peer_certificate_list); |
1199 | return ret; |
1200 | |
1201 | } |
1202 | |
1203 | #ifdef ENABLE_OPENPGP1 |
1204 | static int |
1205 | _gnutls_proc_openpgp_server_certificate (gnutls_session_t session, |
1206 | opaque * data, size_t data_size) |
1207 | { |
1208 | int size, ret, len; |
1209 | opaque *p = data; |
1210 | cert_auth_info_t info; |
1211 | gnutls_certificate_credentials_t cred; |
1212 | ssize_t dsize = data_size; |
1213 | int x, key_type; |
1214 | gnutls_pcert_st *peer_certificate_list = NULL((void*)0); |
1215 | int peer_certificate_list_size = 0; |
1216 | gnutls_datum_t tmp, akey = { NULL((void*)0), 0 }; |
1217 | uint8_t subkey_id[GNUTLS_OPENPGP_KEYID_SIZE8]; |
1218 | unsigned int subkey_id_set = 0; |
1219 | |
1220 | cred = (gnutls_certificate_credentials_t) |
1221 | _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL((void*)0)); |
1222 | if (cred == NULL((void*)0)) |
1223 | { |
1224 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1224); } while(0);; |
1225 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
1226 | } |
1227 | |
1228 | if ((ret = |
1229 | _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, |
1230 | sizeof (cert_auth_info_st), 1)) < 0) |
1231 | { |
1232 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1232); } while(0);; |
1233 | return ret; |
1234 | } |
1235 | |
1236 | info = _gnutls_get_auth_info (session); |
1237 | |
1238 | if (data == NULL((void*)0) || data_size == 0) |
1239 | { |
1240 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1240); } while(0);; |
1241 | return GNUTLS_E_NO_CERTIFICATE_FOUND-49; |
1242 | } |
1243 | |
1244 | DECR_LEN (dsize, 3)do { dsize-=3; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1244 ); } while(0);; return -9;} } while (0); |
1245 | size = _gnutls_read_uint24 (p); |
1246 | p += 3; |
1247 | |
1248 | if (size == 0) |
1249 | { |
1250 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1250); } while(0);; |
1251 | /* no certificate was sent */ |
1252 | return GNUTLS_E_NO_CERTIFICATE_FOUND-49; |
1253 | } |
1254 | |
1255 | /* Read PGPKeyDescriptor */ |
1256 | DECR_LEN (dsize, 1)do { dsize-=1; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1256 ); } while(0);; return -9;} } while (0); |
1257 | key_type = *p; |
1258 | p++; |
1259 | |
1260 | /* Try to read the keyid if present */ |
1261 | if (key_type == PGP_KEY_FINGERPRINT_SUBKEY || key_type == PGP_KEY_SUBKEY) |
1262 | { |
1263 | /* check size */ |
1264 | if (*p != GNUTLS_OPENPGP_KEYID_SIZE8) |
1265 | { |
1266 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1266); } while(0);; |
1267 | return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE-61; |
1268 | } |
1269 | |
1270 | DECR_LEN (dsize, 1)do { dsize-=1; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1270 ); } while(0);; return -9;} } while (0); |
1271 | p++; |
1272 | |
1273 | DECR_LEN (dsize, GNUTLS_OPENPGP_KEYID_SIZE)do { dsize-=8; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1273 ); } while(0);; return -9;} } while (0); |
1274 | memcpy (subkey_id, p, GNUTLS_OPENPGP_KEYID_SIZE8); |
1275 | p += GNUTLS_OPENPGP_KEYID_SIZE8; |
1276 | |
1277 | subkey_id_set = 1; |
1278 | |
1279 | } |
1280 | |
1281 | /* read the actual key or fingerprint */ |
1282 | if (key_type == PGP_KEY_FINGERPRINT |
1283 | || key_type == PGP_KEY_FINGERPRINT_SUBKEY) |
1284 | { /* the fingerprint */ |
1285 | |
1286 | DECR_LEN (dsize, 1)do { dsize-=1; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1286 ); } while(0);; return -9;} } while (0); |
1287 | len = (uint8_t) * p; |
1288 | p++; |
1289 | |
1290 | if (len != 20) |
1291 | { |
1292 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1292); } while(0);; |
1293 | return GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED-94; |
1294 | } |
1295 | |
1296 | DECR_LEN (dsize, 20)do { dsize-=20; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1296 ); } while(0);; return -9;} } while (0); |
1297 | |
1298 | /* request the actual key from our database, or |
1299 | * a key server or anything. |
1300 | */ |
1301 | if ((ret = |
1302 | _gnutls_openpgp_request_key (session, &akey, cred, p, 20)) < 0) |
1303 | { |
1304 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1304); } while(0);; |
1305 | return ret; |
1306 | } |
1307 | tmp = akey; |
1308 | peer_certificate_list_size++; |
1309 | |
1310 | } |
1311 | else if (key_type == PGP_KEY || key_type == PGP_KEY_SUBKEY) |
1312 | { /* the whole key */ |
1313 | |
1314 | /* Read the actual certificate */ |
1315 | DECR_LEN (dsize, 3)do { dsize-=3; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1315 ); } while(0);; return -9;} } while (0); |
1316 | len = _gnutls_read_uint24 (p); |
1317 | p += 3; |
1318 | |
1319 | if (len == 0) |
1320 | { |
1321 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1321); } while(0);; |
1322 | /* no certificate was sent */ |
1323 | return GNUTLS_E_NO_CERTIFICATE_FOUND-49; |
1324 | } |
1325 | |
1326 | DECR_LEN (dsize, len)do { dsize-=len; if (dsize<0) {do { if (__builtin_expect(( _gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",1326); } while(0);; return -9;} } while (0); |
1327 | peer_certificate_list_size++; |
1328 | |
1329 | tmp.size = len; |
1330 | tmp.data = p; |
1331 | |
1332 | } |
1333 | else |
1334 | { |
1335 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1335); } while(0);; |
1336 | return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE-61; |
1337 | } |
1338 | |
1339 | /* ok we now have the peer's key in tmp datum |
1340 | */ |
1341 | |
1342 | if (peer_certificate_list_size == 0) |
1343 | { |
1344 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1344); } while(0);; |
1345 | return GNUTLS_E_UNEXPECTED_PACKET_LENGTH-9; |
1346 | } |
1347 | |
1348 | peer_certificate_list = |
1349 | gnutls_calloc (1, |
1350 | sizeof (gnutls_pcert_st) * (peer_certificate_list_size)); |
1351 | if (peer_certificate_list == NULL((void*)0)) |
1352 | { |
1353 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1353); } while(0);; |
1354 | ret = GNUTLS_E_MEMORY_ERROR-25; |
1355 | goto cleanup; |
1356 | } |
1357 | |
1358 | ret = |
1359 | gnutls_pcert_import_openpgp_raw (&peer_certificate_list[0], |
1360 | &tmp, |
1361 | GNUTLS_OPENPGP_FMT_RAW, |
1362 | (subkey_id_set != 0) ? subkey_id : NULL((void*)0), |
1363 | 0); |
1364 | if (ret < 0) |
1365 | { |
1366 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1366); } while(0);; |
1367 | goto cleanup; |
1368 | } |
1369 | |
1370 | ret = |
1371 | _gnutls_copy_certificate_auth_info (info, |
1372 | peer_certificate_list, |
1373 | peer_certificate_list_size, |
1374 | subkey_id_set, |
1375 | (subkey_id_set != |
1376 | 0) ? subkey_id : NULL((void*)0)); |
1377 | if (ret < 0) |
1378 | { |
1379 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1379); } while(0);; |
1380 | goto cleanup; |
1381 | } |
1382 | |
1383 | if ((ret = |
1384 | _gnutls_check_key_usage (&peer_certificate_list[0], |
1385 | gnutls_kx_get (session))) < 0) |
1386 | { |
1387 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1387); } while(0);; |
1388 | goto cleanup; |
1389 | } |
1390 | |
1391 | ret = 0; |
1392 | |
1393 | cleanup: |
1394 | |
1395 | _gnutls_free_datum (&akey)_gnutls_free_datum_m(&akey, gnutls_free); |
1396 | CLEAR_CERTSfor(x=0;x<peer_certificate_list_size;x++) gnutls_pcert_deinit (&peer_certificate_list[x]); |
1397 | gnutls_free (peer_certificate_list); |
1398 | return ret; |
1399 | |
1400 | } |
1401 | #endif |
1402 | |
1403 | int |
1404 | _gnutls_proc_certificate (gnutls_session_t session, |
1405 | opaque * data, size_t data_size) |
1406 | { |
1407 | int ret; |
1408 | gnutls_certificate_credentials_t cred; |
1409 | |
1410 | cred = |
1411 | (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, |
1412 | GNUTLS_CRD_CERTIFICATE, |
1413 | NULL((void*)0)); |
1414 | if (cred == NULL((void*)0)) |
1415 | { |
1416 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1416); } while(0);; |
1417 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
1418 | } |
1419 | |
1420 | switch (session->security_parameters.cert_type) |
1421 | { |
1422 | #ifdef ENABLE_OPENPGP1 |
1423 | case GNUTLS_CRT_OPENPGP: |
1424 | ret = _gnutls_proc_openpgp_server_certificate (session, |
1425 | data, data_size); |
1426 | break; |
1427 | #endif |
1428 | case GNUTLS_CRT_X509: |
1429 | ret = _gnutls_proc_x509_server_certificate (session, data, data_size); |
1430 | break; |
1431 | default: |
1432 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1432); } while(0);; |
1433 | return GNUTLS_E_INTERNAL_ERROR-59; |
1434 | } |
1435 | |
1436 | if (ret == 0 && cred->verify_callback != NULL((void*)0)) |
1437 | { |
1438 | ret = cred->verify_callback (session); |
1439 | if (ret != 0) |
1440 | ret = GNUTLS_E_CERTIFICATE_ERROR-43; |
1441 | } |
1442 | |
1443 | return ret; |
1444 | } |
1445 | |
1446 | |
1447 | /* Checks if we support the given signature algorithm |
1448 | * (RSA or DSA). Returns the corresponding gnutls_pk_algorithm_t |
1449 | * if true; |
1450 | */ |
1451 | inline static int |
1452 | _gnutls_check_supported_sign_algo (CertificateSigType algo) |
1453 | { |
1454 | switch (algo) |
1455 | { |
1456 | case RSA_SIGN: |
1457 | return GNUTLS_PK_RSA; |
1458 | case DSA_SIGN: |
1459 | return GNUTLS_PK_DSA; |
1460 | case ECDSA_SIGN: |
1461 | return GNUTLS_PK_EC; |
1462 | } |
1463 | |
1464 | return -1; |
1465 | } |
1466 | |
1467 | int |
1468 | _gnutls_proc_cert_cert_req (gnutls_session_t session, opaque * data, |
1469 | size_t data_size) |
1470 | { |
1471 | int size, ret; |
1472 | opaque *p; |
1473 | gnutls_certificate_credentials_t cred; |
1474 | ssize_t dsize; |
1475 | int i; |
1476 | gnutls_pk_algorithm_t pk_algos[MAX_CLIENT_SIGN_ALGOS3]; |
1477 | int pk_algos_length; |
1478 | gnutls_protocol_t ver = gnutls_protocol_get_version_gnutls_protocol_get_version (session); |
1479 | |
1480 | cred = (gnutls_certificate_credentials_t) |
1481 | _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL((void*)0)); |
1482 | if (cred == NULL((void*)0)) |
1483 | { |
1484 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1484); } while(0);; |
1485 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
1486 | } |
1487 | |
1488 | if ((ret = |
1489 | _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, |
1490 | sizeof (cert_auth_info_st), 0)) < 0) |
1491 | { |
1492 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1492); } while(0);; |
1493 | return ret; |
1494 | } |
1495 | |
1496 | p = data; |
1497 | dsize = data_size; |
1498 | |
1499 | DECR_LEN (dsize, 1)do { dsize-=1; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1499 ); } while(0);; return -9;} } while (0); |
1500 | size = p[0]; |
1501 | p++; |
1502 | /* check if the sign algorithm is supported. |
1503 | */ |
1504 | pk_algos_length = 0; |
1505 | for (i = 0; i < size; i++, p++) |
1506 | { |
1507 | DECR_LEN (dsize, 1)do { dsize-=1; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1507 ); } while(0);; return -9;} } while (0); |
1508 | if ((ret = _gnutls_check_supported_sign_algo (*p)) > 0) |
1509 | { |
1510 | if (pk_algos_length < MAX_CLIENT_SIGN_ALGOS3) |
1511 | { |
1512 | pk_algos[pk_algos_length++] = ret; |
1513 | } |
1514 | } |
1515 | } |
1516 | |
1517 | if (pk_algos_length == 0) |
1518 | { |
1519 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1519); } while(0);; |
1520 | return GNUTLS_E_UNKNOWN_PK_ALGORITHM-80; |
1521 | } |
1522 | |
1523 | if (_gnutls_version_has_selectable_sighash (ver)) |
1524 | { |
1525 | /* read supported hashes */ |
1526 | int hash_num; |
1527 | DECR_LEN (dsize, 2)do { dsize-=2; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1527 ); } while(0);; return -9;} } while (0); |
1528 | hash_num = _gnutls_read_uint16 (p); |
1529 | p += 2; |
1530 | DECR_LEN (dsize, hash_num)do { dsize-=hash_num; if (dsize<0) {do { if (__builtin_expect ((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",1530); } while(0);; return -9;} } while (0); |
1531 | |
1532 | ret = _gnutls_sign_algorithm_parse_data (session, p, hash_num); |
1533 | if (ret < 0) |
1534 | { |
1535 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1535); } while(0);; |
1536 | return ret; |
1537 | } |
1538 | |
1539 | p += hash_num; |
1540 | } |
1541 | |
1542 | /* read the certificate authorities */ |
1543 | DECR_LEN (dsize, 2)do { dsize-=2; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1543 ); } while(0);; return -9;} } while (0); |
1544 | size = _gnutls_read_uint16 (p); |
1545 | p += 2; |
1546 | |
1547 | if (session->security_parameters.cert_type == GNUTLS_CRT_OPENPGP |
1548 | && size != 0) |
1549 | { |
1550 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1550); } while(0);; |
1551 | return GNUTLS_E_UNEXPECTED_PACKET_LENGTH-9; |
1552 | } |
1553 | |
1554 | DECR_LEN (dsize, size)do { dsize-=size; if (dsize<0) {do { if (__builtin_expect( (_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",1554); } while(0);; return -9;} } while (0); |
1555 | |
1556 | /* now we ask the user to tell which one |
1557 | * he wants to use. |
1558 | */ |
1559 | if ((ret = |
1560 | _select_client_cert (session, p, size, pk_algos, pk_algos_length)) < 0) |
1561 | { |
1562 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1562); } while(0);; |
1563 | return ret; |
1564 | } |
1565 | |
1566 | /* We should reply with a certificate message, |
1567 | * even if we have no certificate to send. |
1568 | */ |
1569 | session->key->certificate_requested = 1; |
1570 | |
1571 | return 0; |
1572 | } |
1573 | |
1574 | int |
1575 | _gnutls_gen_cert_client_cert_vrfy (gnutls_session_t session, |
1576 | gnutls_buffer_st * data) |
1577 | { |
1578 | int ret; |
1579 | gnutls_pcert_st *apr_cert_list; |
1580 | gnutls_privkey_t apr_pkey; |
1581 | int apr_cert_list_length; |
1582 | gnutls_datum_t signature = { NULL((void*)0), 0 }; |
1583 | int total_data; |
1584 | gnutls_sign_algorithm_t sign_algo; |
1585 | gnutls_protocol_t ver = gnutls_protocol_get_version_gnutls_protocol_get_version (session); |
1586 | |
1587 | /* find the appropriate certificate */ |
1588 | if ((ret = |
1589 | _gnutls_get_selected_cert (session, &apr_cert_list, |
1590 | &apr_cert_list_length, &apr_pkey)) < 0) |
1591 | { |
1592 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1592); } while(0);; |
1593 | return ret; |
1594 | } |
1595 | |
1596 | if (apr_cert_list_length > 0) |
1597 | { |
1598 | if ((ret = |
1599 | _gnutls_handshake_sign_cert_vrfy (session, |
1600 | &apr_cert_list[0], |
1601 | apr_pkey, &signature)) < 0) |
1602 | { |
1603 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1603); } while(0);; |
1604 | return ret; |
1605 | } |
1606 | sign_algo = ret; |
1607 | } |
1608 | else |
1609 | { |
1610 | return 0; |
1611 | } |
1612 | |
1613 | total_data = signature.size + 2; |
1614 | |
1615 | /* add hash and signature algorithms */ |
1616 | if (_gnutls_version_has_selectable_sighash (ver)) |
1617 | { |
1618 | total_data += 2; |
1619 | } |
1620 | |
1621 | if (_gnutls_version_has_selectable_sighash (ver)) |
1622 | { |
1623 | const sign_algorithm_st *aid; |
1624 | uint8_t p[2]; |
1625 | /* error checking is not needed here since we have used those algorithms */ |
1626 | aid = _gnutls_sign_to_tls_aid (sign_algo); |
1627 | if (aid == NULL((void*)0)) |
1628 | return gnutls_assert_val (GNUTLS_E_UNKNOWN_ALGORITHM)gnutls_assert_val_int(-105, "cert.c", 1628); |
1629 | |
1630 | p[0] = aid->hash_algorithm; |
1631 | p[1] = aid->sign_algorithm; |
1632 | ret = _gnutls_buffer_append_data (data, p, 2); |
1633 | if (ret < 0) |
1634 | { |
1635 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1635); } while(0);; |
1636 | goto cleanup; |
1637 | } |
1638 | } |
1639 | |
1640 | ret = |
1641 | _gnutls_buffer_append_data_prefix (data, 16, signature.data, |
1642 | signature.size); |
1643 | if (ret < 0) |
1644 | { |
1645 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1645); } while(0);; |
1646 | goto cleanup; |
1647 | } |
1648 | |
1649 | ret = data->length; |
1650 | |
1651 | cleanup: |
1652 | _gnutls_free_datum (&signature)_gnutls_free_datum_m(&signature, gnutls_free); |
1653 | return ret; |
1654 | } |
1655 | |
1656 | int |
1657 | _gnutls_proc_cert_client_cert_vrfy (gnutls_session_t session, |
1658 | opaque * data, size_t data_size) |
1659 | { |
1660 | int size, ret; |
1661 | ssize_t dsize = data_size; |
1662 | opaque *pdata = data; |
1663 | gnutls_datum_t sig; |
1664 | cert_auth_info_t info = _gnutls_get_auth_info (session); |
1665 | gnutls_pcert_st peer_cert; |
1666 | gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; |
1667 | gnutls_protocol_t ver = gnutls_protocol_get_version_gnutls_protocol_get_version (session); |
1668 | |
1669 | if (info == NULL((void*)0) || info->ncerts == 0) |
1670 | { |
1671 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1671); } while(0);; |
1672 | /* we need this in order to get peer's certificate */ |
1673 | return GNUTLS_E_INTERNAL_ERROR-59; |
1674 | } |
1675 | |
1676 | if (_gnutls_version_has_selectable_sighash (ver)) |
1677 | { |
1678 | sign_algorithm_st aid; |
1679 | |
1680 | DECR_LEN (dsize, 2)do { dsize-=2; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1680 ); } while(0);; return -9;} } while (0); |
1681 | aid.hash_algorithm = pdata[0]; |
1682 | aid.sign_algorithm = pdata[1]; |
1683 | |
1684 | sign_algo = _gnutls_tls_aid_to_sign (&aid); |
1685 | if (sign_algo == GNUTLS_SIGN_UNKNOWN) |
1686 | { |
1687 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1687); } while(0);; |
1688 | return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM-106; |
1689 | } |
1690 | pdata += 2; |
1691 | } |
1692 | |
1693 | ret = _gnutls_session_sign_algo_enabled (session, sign_algo); |
1694 | if (ret < 0) |
1695 | { |
1696 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1696); } while(0);; |
1697 | return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM-106; |
1698 | } |
1699 | |
1700 | DECR_LEN (dsize, 2)do { dsize-=2; if (dsize<0) {do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n", "cert.c",1700 ); } while(0);; return -9;} } while (0); |
1701 | size = _gnutls_read_uint16 (pdata); |
1702 | pdata += 2; |
1703 | |
1704 | DECR_LEN (dsize, size)do { dsize-=size; if (dsize<0) {do { if (__builtin_expect( (_gnutls_log_level >= 2), 0)) _gnutls_log( 2, "ASSERT: %s:%d\n" , "cert.c",1704); } while(0);; return -9;} } while (0); |
1705 | |
1706 | sig.data = pdata; |
1707 | sig.size = size; |
1708 | |
1709 | ret = _gnutls_get_auth_info_pcert (&peer_cert, |
1710 | session->security_parameters.cert_type, |
1711 | info); |
1712 | |
1713 | if (ret < 0) |
1714 | { |
1715 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1715); } while(0);; |
1716 | return ret; |
1717 | } |
1718 | |
1719 | if ((ret = |
1720 | _gnutls_handshake_verify_cert_vrfy (session, &peer_cert, &sig, |
1721 | sign_algo)) < 0) |
1722 | { |
1723 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1723); } while(0);; |
1724 | gnutls_pcert_deinit (&peer_cert); |
1725 | return ret; |
1726 | } |
1727 | gnutls_pcert_deinit (&peer_cert); |
1728 | |
1729 | return 0; |
1730 | } |
1731 | |
1732 | int |
1733 | _gnutls_gen_cert_server_cert_req (gnutls_session_t session, |
1734 | gnutls_buffer_st * data) |
1735 | { |
1736 | gnutls_certificate_credentials_t cred; |
1737 | int size, ret; |
1738 | uint8_t tmp_data[CERTTYPE_SIZE(3 +1)]; |
1739 | gnutls_protocol_t ver = gnutls_protocol_get_version_gnutls_protocol_get_version (session); |
1740 | |
1741 | /* Now we need to generate the RDN sequence. This is |
1742 | * already in the CERTIFICATE_CRED structure, to improve |
1743 | * performance. |
1744 | */ |
1745 | |
1746 | cred = (gnutls_certificate_credentials_t) |
1747 | _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL((void*)0)); |
1748 | if (cred == NULL((void*)0)) |
1749 | { |
1750 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1750); } while(0);; |
1751 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
1752 | } |
1753 | |
1754 | size = CERTTYPE_SIZE(3 +1) + 2; /* 2 for gnutls_certificate_type_t + 2 for size of rdn_seq |
1755 | */ |
1756 | |
1757 | if (session->security_parameters.cert_type == GNUTLS_CRT_X509 && |
1758 | session->internals.ignore_rdn_sequence == 0) |
1759 | size += cred->x509_rdn_sequence.size; |
1760 | |
1761 | if (_gnutls_version_has_selectable_sighash (ver)) |
1762 | /* Need two bytes to announce the number of supported hash |
1763 | functions (see below). */ |
1764 | size += MAX_SIGN_ALGO_SIZE(2 + 16 * 2); |
1765 | |
1766 | tmp_data[0] = CERTTYPE_SIZE(3 +1) - 1; |
1767 | tmp_data[1] = RSA_SIGN; |
1768 | tmp_data[2] = DSA_SIGN; |
1769 | tmp_data[3] = ECDSA_SIGN; /* only these for now */ |
1770 | |
1771 | ret = _gnutls_buffer_append_data (data, tmp_data, CERTTYPE_SIZE(3 +1)); |
1772 | if (ret < 0) |
1773 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 1773); |
1774 | |
1775 | if (_gnutls_version_has_selectable_sighash (ver)) |
1776 | { |
1777 | uint8_t p[MAX_SIGN_ALGO_SIZE(2 + 16 * 2)]; |
1778 | |
1779 | ret = |
1780 | _gnutls_sign_algorithm_write_params (session, p, MAX_SIGN_ALGO_SIZE(2 + 16 * 2)); |
1781 | if (ret < 0) |
1782 | { |
1783 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1783); } while(0);; |
1784 | return ret; |
1785 | } |
1786 | |
1787 | /* recalculate size */ |
1788 | size -= MAX_SIGN_ALGO_SIZE(2 + 16 * 2) + ret; |
Value stored to 'size' is never read | |
1789 | |
1790 | ret = _gnutls_buffer_append_data (data, p, ret); |
1791 | if (ret < 0) |
1792 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 1792); |
1793 | } |
1794 | |
1795 | if (session->security_parameters.cert_type == GNUTLS_CRT_X509 && |
1796 | session->internals.ignore_rdn_sequence == 0) |
1797 | { |
1798 | ret = |
1799 | _gnutls_buffer_append_data_prefix (data, 16, |
1800 | cred->x509_rdn_sequence.data, |
1801 | cred->x509_rdn_sequence.size); |
1802 | if (ret < 0) |
1803 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 1803); |
1804 | } |
1805 | else |
1806 | { |
1807 | ret = _gnutls_buffer_append_prefix (data, 16, 0); |
1808 | if (ret < 0) |
1809 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 1809); |
1810 | } |
1811 | |
1812 | return data->length; |
1813 | } |
1814 | |
1815 | |
1816 | /* This function will return the appropriate certificate to use. |
1817 | * Fills in the apr_cert_list, apr_cert_list_length and apr_pkey. |
1818 | * The return value is a negative error code on error. |
1819 | * |
1820 | * It is normal to return 0 with no certificates in client side. |
1821 | * |
1822 | */ |
1823 | int |
1824 | _gnutls_get_selected_cert (gnutls_session_t session, |
1825 | gnutls_pcert_st ** apr_cert_list, |
1826 | int *apr_cert_list_length, |
1827 | gnutls_privkey_t * apr_pkey) |
1828 | { |
1829 | if (session->security_parameters.entity == GNUTLS_SERVER1) |
1830 | { |
1831 | |
1832 | /* select_client_cert() has been called before. |
1833 | */ |
1834 | |
1835 | *apr_cert_list = session->internals.selected_cert_list; |
1836 | *apr_pkey = session->internals.selected_key; |
1837 | *apr_cert_list_length = session->internals.selected_cert_list_length; |
1838 | |
1839 | if (*apr_cert_list_length == 0 || *apr_cert_list == NULL((void*)0)) |
1840 | { |
1841 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1841); } while(0);; |
1842 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
1843 | } |
1844 | |
1845 | } |
1846 | else |
1847 | { /* CLIENT SIDE |
1848 | */ |
1849 | |
1850 | /* we have already decided which certificate |
1851 | * to send. |
1852 | */ |
1853 | *apr_cert_list = session->internals.selected_cert_list; |
1854 | *apr_cert_list_length = session->internals.selected_cert_list_length; |
1855 | *apr_pkey = session->internals.selected_key; |
1856 | |
1857 | } |
1858 | |
1859 | return 0; |
1860 | } |
1861 | |
1862 | /* converts the given x509 certificate list to gnutls_pcert_st* and allocates |
1863 | * space for them. |
1864 | */ |
1865 | static gnutls_pcert_st * |
1866 | alloc_and_load_x509_certs (gnutls_x509_crt_t * certs, unsigned ncerts) |
1867 | { |
1868 | gnutls_pcert_st *local_certs; |
1869 | int ret = 0; |
1870 | unsigned i, j; |
1871 | |
1872 | if (certs == NULL((void*)0)) |
1873 | return NULL((void*)0); |
1874 | |
1875 | local_certs = gnutls_malloc (sizeof (gnutls_pcert_st) * ncerts); |
1876 | if (local_certs == NULL((void*)0)) |
1877 | { |
1878 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1878); } while(0);; |
1879 | return NULL((void*)0); |
1880 | } |
1881 | |
1882 | for (i = 0; i < ncerts; i++) |
1883 | { |
1884 | ret = gnutls_pcert_import_x509 (&local_certs[i], certs[i], 0); |
1885 | if (ret < 0) |
1886 | break; |
1887 | } |
1888 | |
1889 | if (ret < 0) |
1890 | { |
1891 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1891); } while(0);; |
1892 | for (j = 0; j < i; j++) |
1893 | { |
1894 | gnutls_pcert_deinit (&local_certs[j]); |
1895 | } |
1896 | gnutls_free (local_certs); |
1897 | return NULL((void*)0); |
1898 | } |
1899 | |
1900 | return local_certs; |
1901 | } |
1902 | |
1903 | /* converts the given x509 key to gnutls_privkey* and allocates |
1904 | * space for it. |
1905 | */ |
1906 | static gnutls_privkey_t |
1907 | alloc_and_load_x509_key (gnutls_x509_privkey_t key, int deinit) |
1908 | { |
1909 | gnutls_privkey_t local_key; |
1910 | int ret = 0; |
1911 | |
1912 | if (key == NULL((void*)0)) |
1913 | return NULL((void*)0); |
1914 | |
1915 | ret = gnutls_privkey_init (&local_key); |
1916 | if (ret < 0) |
1917 | { |
1918 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1918); } while(0);; |
1919 | return NULL((void*)0); |
1920 | } |
1921 | |
1922 | ret = |
1923 | gnutls_privkey_import_x509 (local_key, key, |
1924 | deinit ? GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE(1<<0) : |
1925 | 0); |
1926 | if (ret < 0) |
1927 | { |
1928 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1928); } while(0);; |
1929 | gnutls_privkey_deinit (local_key); |
1930 | return NULL((void*)0); |
1931 | } |
1932 | |
1933 | return local_key; |
1934 | } |
1935 | |
1936 | /* converts the given pgp certificate to gnutls_cert* and allocates |
1937 | * space for them. |
1938 | */ |
1939 | #ifdef ENABLE_OPENPGP1 |
1940 | static gnutls_pcert_st * |
1941 | alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert) |
1942 | { |
1943 | gnutls_pcert_st *local_certs; |
1944 | int ret = 0; |
1945 | |
1946 | if (cert == NULL((void*)0)) |
1947 | return NULL((void*)0); |
1948 | |
1949 | local_certs = gnutls_malloc (sizeof (gnutls_pcert_st)); |
1950 | if (local_certs == NULL((void*)0)) |
1951 | { |
1952 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1952); } while(0);; |
1953 | return NULL((void*)0); |
1954 | } |
1955 | |
1956 | ret = gnutls_pcert_import_openpgp (local_certs, cert, 0); |
1957 | if (ret < 0) |
1958 | { |
1959 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1959); } while(0);; |
1960 | return NULL((void*)0); |
1961 | } |
1962 | |
1963 | if (ret < 0) |
1964 | { |
1965 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1965); } while(0);; |
1966 | gnutls_pcert_deinit (local_certs); |
1967 | gnutls_free (local_certs); |
1968 | return NULL((void*)0); |
1969 | } |
1970 | |
1971 | return local_certs; |
1972 | } |
1973 | |
1974 | /* converts the given raw key to gnutls_privkey* and allocates |
1975 | * space for it. |
1976 | */ |
1977 | static gnutls_privkey_t |
1978 | alloc_and_load_pgp_key (gnutls_openpgp_privkey_t key, int deinit) |
1979 | { |
1980 | gnutls_privkey_t local_key; |
1981 | int ret = 0; |
1982 | |
1983 | if (key == NULL((void*)0)) |
1984 | return NULL((void*)0); |
1985 | |
1986 | ret = gnutls_privkey_init (&local_key); |
1987 | if (ret < 0) |
1988 | { |
1989 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1989); } while(0);; |
1990 | return NULL((void*)0); |
1991 | } |
1992 | |
1993 | ret = |
1994 | gnutls_privkey_import_openpgp (local_key, key, |
1995 | deinit ? GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE(1<<0) |
1996 | : 0); |
1997 | if (ret < 0) |
1998 | { |
1999 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",1999); } while(0);; |
2000 | gnutls_privkey_deinit (local_key); |
2001 | return NULL((void*)0); |
2002 | } |
2003 | |
2004 | return local_key; |
2005 | } |
2006 | #endif |
2007 | |
2008 | #ifdef ENABLE_PKCS111 |
2009 | |
2010 | /* converts the given raw key to gnutls_privkey* and allocates |
2011 | * space for it. |
2012 | */ |
2013 | static gnutls_privkey_t |
2014 | alloc_and_load_pkcs11_key (gnutls_pkcs11_privkey_t key, int deinit) |
2015 | { |
2016 | gnutls_privkey_t local_key; |
2017 | int ret = 0; |
2018 | |
2019 | if (key == NULL((void*)0)) |
2020 | return NULL((void*)0); |
2021 | |
2022 | ret = gnutls_privkey_init (&local_key); |
2023 | if (ret < 0) |
2024 | { |
2025 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",2025); } while(0);; |
2026 | return NULL((void*)0); |
2027 | } |
2028 | |
2029 | ret = |
2030 | gnutls_privkey_import_pkcs11 (local_key, key, |
2031 | deinit ? GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE(1<<0) |
2032 | : 0); |
2033 | if (ret < 0) |
2034 | { |
2035 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",2035); } while(0);; |
2036 | gnutls_privkey_deinit (local_key); |
2037 | return NULL((void*)0); |
2038 | } |
2039 | |
2040 | return local_key; |
2041 | } |
2042 | |
2043 | #endif |
2044 | |
2045 | void |
2046 | _gnutls_selected_certs_deinit (gnutls_session_t session) |
2047 | { |
2048 | if (session->internals.selected_need_free != 0) |
2049 | { |
2050 | int i; |
2051 | |
2052 | for (i = 0; i < session->internals.selected_cert_list_length; i++) |
2053 | { |
2054 | gnutls_pcert_deinit (&session->internals.selected_cert_list[i]); |
2055 | } |
2056 | gnutls_free (session->internals.selected_cert_list); |
2057 | session->internals.selected_cert_list = NULL((void*)0); |
2058 | session->internals.selected_cert_list_length = 0; |
2059 | |
2060 | gnutls_privkey_deinit(session->internals.selected_key); |
2061 | session->internals.selected_key = NULL((void*)0); |
2062 | } |
2063 | |
2064 | return; |
2065 | } |
2066 | |
2067 | void |
2068 | _gnutls_selected_certs_set (gnutls_session_t session, |
2069 | gnutls_pcert_st * certs, int ncerts, |
2070 | gnutls_privkey_t key, int need_free) |
2071 | { |
2072 | _gnutls_selected_certs_deinit (session); |
2073 | |
2074 | session->internals.selected_cert_list = certs; |
2075 | session->internals.selected_cert_list_length = ncerts; |
2076 | session->internals.selected_key = key; |
2077 | session->internals.selected_need_free = need_free; |
2078 | |
2079 | } |
2080 | |
2081 | static void get_server_name(gnutls_session_t session, uint8_t* name, size_t max_name_size) |
2082 | { |
2083 | int ret, i; |
2084 | size_t max_name; |
2085 | unsigned int type; |
2086 | |
2087 | ret = 0; |
2088 | for (i=0; !(ret<0);i++) |
2089 | { |
2090 | max_name = max_name_size; |
2091 | ret = gnutls_server_name_get (session, name, &max_name, &type, i); |
2092 | if (ret >= 0 && type == GNUTLS_NAME_DNS) |
2093 | return; |
2094 | } |
2095 | |
2096 | name[0] = 0; |
2097 | |
2098 | return; |
2099 | } |
2100 | |
2101 | /* finds the most appropriate certificate in the cert list. |
2102 | * The 'appropriate' is defined by the user. |
2103 | * |
2104 | * requested_algo holds the parameters required by the peer (RSA, DSA |
2105 | * or -1 for any). |
2106 | * |
2107 | * Returns 0 on success and a negative error code on error. The |
2108 | * selected certificate will be in session->internals.selected_*. |
2109 | * |
2110 | */ |
2111 | int |
2112 | _gnutls_server_select_cert (gnutls_session_t session, |
2113 | gnutls_pk_algorithm_t * pk_algos, |
2114 | size_t pk_algos_size) |
2115 | { |
2116 | unsigned i, j; |
2117 | int idx, ret; |
2118 | gnutls_certificate_credentials_t cred; |
2119 | char server_name[MAX_CN256]; |
2120 | |
2121 | cred = (gnutls_certificate_credentials_t) |
2122 | _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL((void*)0)); |
2123 | if (cred == NULL((void*)0)) |
2124 | { |
2125 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",2125); } while(0);; |
2126 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
2127 | } |
2128 | |
2129 | /* If the callback which retrieves certificate has been set, |
2130 | * use it and leave. |
2131 | */ |
2132 | if (cred->server_get_cert_callback != NULL((void*)0) || cred->server_get_cert_callback |
2133 | || cred->get_cert_callback2) |
2134 | { |
2135 | ret = call_get_cert_callback (session, NULL((void*)0), 0, NULL((void*)0), 0); |
2136 | if (ret < 0) |
2137 | return gnutls_assert_val (ret)gnutls_assert_val_int(ret, "cert.c", 2137); |
2138 | return ret; |
2139 | } |
2140 | |
2141 | /* Otherwise... */ |
2142 | |
2143 | get_server_name(session, server_name, sizeof(server_name)); |
2144 | |
2145 | idx = -1; /* default is use no certificate */ |
2146 | |
2147 | /* find certificates that match the requested server_name |
2148 | */ |
2149 | |
2150 | if (server_name[0] != 0) |
2151 | { |
2152 | for (i = 0; i < cred->ncerts; i++) |
2153 | { |
2154 | if (cred->certs[i].names != NULL((void*)0) && _gnutls_str_array_match(cred->certs[i].names, server_name) != 0) |
2155 | { |
2156 | /* if requested algorithms are also compatible select it */ |
2157 | gnutls_pk_algorithmgnutls_pk_algorithm_t pk = |
2158 | gnutls_pubkey_get_pk_algorithm (cred->certs[i].cert_list[0].pubkey, |
2159 | NULL((void*)0)); |
2160 | |
2161 | _gnutls_handshake_log("HSK[%p]: Requested server name: '%s', ctype: %s (%d)", session, server_name,do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested server name: '%s', ctype: %s (%d)", session , server_name, gnutls_certificate_type_get_name (session-> security_parameters.cert_type), session->security_parameters .cert_type); } while(0) |
2162 | gnutls_certificate_type_get_name (session->security_parameters.cert_type),do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested server name: '%s', ctype: %s (%d)", session , server_name, gnutls_certificate_type_get_name (session-> security_parameters.cert_type), session->security_parameters .cert_type); } while(0) |
2163 | session->security_parameters.cert_type)do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested server name: '%s', ctype: %s (%d)", session , server_name, gnutls_certificate_type_get_name (session-> security_parameters.cert_type), session->security_parameters .cert_type); } while(0); |
2164 | |
2165 | if (session->security_parameters.cert_type == cred->certs[i].cert_list[0].type) |
2166 | { |
2167 | for (j = 0; j < pk_algos_size; j++) |
2168 | if (pk_algos[j] == pk) |
2169 | { |
2170 | idx = i; |
2171 | goto finished; |
2172 | } |
2173 | } |
2174 | } |
2175 | } |
2176 | } |
2177 | |
2178 | for (j = 0; j < pk_algos_size; j++) |
2179 | { |
2180 | _gnutls_handshake_logdo { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n" , session, gnutls_pk_get_name (pk_algos[j]), pk_algos[j], gnutls_certificate_type_get_name (session->security_parameters. cert_type), session->security_parameters .cert_type); } while(0) |
2181 | ("HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n",do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n" , session, gnutls_pk_get_name (pk_algos[j]), pk_algos[j], gnutls_certificate_type_get_name (session->security_parameters. cert_type), session->security_parameters .cert_type); } while(0) |
2182 | session, gnutls_pk_get_name (pk_algos[j]), pk_algos[j],do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n" , session, gnutls_pk_get_name (pk_algos[j]), pk_algos[j], gnutls_certificate_type_get_name (session->security_parameters. cert_type), session->security_parameters .cert_type); } while(0) |
2183 | gnutls_certificate_type_get_name (session->security_parameters.do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n" , session, gnutls_pk_get_name (pk_algos[j]), pk_algos[j], gnutls_certificate_type_get_name (session->security_parameters. cert_type), session->security_parameters .cert_type); } while(0) |
2184 | cert_type),do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n" , session, gnutls_pk_get_name (pk_algos[j]), pk_algos[j], gnutls_certificate_type_get_name (session->security_parameters. cert_type), session->security_parameters .cert_type); } while(0) |
2185 | session->security_parameters.cert_type)do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: Requested PK algorithm: %s (%d) -- ctype: %s (%d)\n" , session, gnutls_pk_get_name (pk_algos[j]), pk_algos[j], gnutls_certificate_type_get_name (session->security_parameters. cert_type), session->security_parameters .cert_type); } while(0); |
2186 | |
2187 | for (i = 0; i < cred->ncerts; i++) |
2188 | { |
2189 | gnutls_pk_algorithmgnutls_pk_algorithm_t pk = |
2190 | gnutls_pubkey_get_pk_algorithm (cred->certs[i].cert_list[0].pubkey, |
2191 | NULL((void*)0)); |
2192 | /* find one compatible certificate |
2193 | */ |
2194 | _gnutls_handshake_logdo { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: certificate[%d] PK algorithm: %s (%d) - ctype: %s (%d)\n" , session, i, gnutls_pk_get_name (pk), pk, gnutls_certificate_type_get_name (cred->certs[i].cert_list[0].type), cred->certs[i].cert_list [0].type); } while(0) |
2195 | ("HSK[%p]: certificate[%d] PK algorithm: %s (%d) - ctype: %s (%d)\n",do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: certificate[%d] PK algorithm: %s (%d) - ctype: %s (%d)\n" , session, i, gnutls_pk_get_name (pk), pk, gnutls_certificate_type_get_name (cred->certs[i].cert_list[0].type), cred->certs[i].cert_list [0].type); } while(0) |
2196 | session, i, gnutls_pk_get_name (pk), pk,do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: certificate[%d] PK algorithm: %s (%d) - ctype: %s (%d)\n" , session, i, gnutls_pk_get_name (pk), pk, gnutls_certificate_type_get_name (cred->certs[i].cert_list[0].type), cred->certs[i].cert_list [0].type); } while(0) |
2197 | gnutls_certificate_type_get_name (cred->certs[i].cert_list[0].type),do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: certificate[%d] PK algorithm: %s (%d) - ctype: %s (%d)\n" , session, i, gnutls_pk_get_name (pk), pk, gnutls_certificate_type_get_name (cred->certs[i].cert_list[0].type), cred->certs[i].cert_list [0].type); } while(0) |
2198 | cred->certs[i].cert_list[0].type)do { if (__builtin_expect((_gnutls_log_level >= 3), 0)) _gnutls_log ( 3, "HSK[%p]: certificate[%d] PK algorithm: %s (%d) - ctype: %s (%d)\n" , session, i, gnutls_pk_get_name (pk), pk, gnutls_certificate_type_get_name (cred->certs[i].cert_list[0].type), cred->certs[i].cert_list [0].type); } while(0); |
2199 | |
2200 | if (pk_algos[j] == pk) |
2201 | { |
2202 | /* if cert type matches |
2203 | */ |
2204 | /* *INDENT-OFF* */ |
2205 | if (session->security_parameters.cert_type == cred->certs[i].cert_list[0].type) |
2206 | { |
2207 | idx = i; |
2208 | goto finished; |
2209 | } |
2210 | /* *INDENT-ON* */ |
2211 | } |
2212 | } |
2213 | } |
2214 | |
2215 | /* store the certificate pointer for future use, in the handshake. |
2216 | * (This will allow not calling this callback again.) |
2217 | */ |
2218 | finished: |
2219 | if (idx >= 0) |
2220 | { |
2221 | _gnutls_selected_certs_set (session, |
2222 | &cred->certs[idx].cert_list[0], |
2223 | cred->certs[idx].cert_list_length, |
2224 | cred->pkey[idx], 0); |
2225 | } |
2226 | else |
2227 | { |
2228 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "cert.c",2228); } while(0);; |
2229 | /* Certificate does not support REQUESTED_ALGO. */ |
2230 | return GNUTLS_E_INSUFFICIENT_CREDENTIALS-32; |
2231 | } |
2232 | |
2233 | return 0; |
2234 | } |
2235 | |
2236 | /* Frees the rsa_info_st structure. |
2237 | */ |
2238 | void |
2239 | _gnutls_free_rsa_info (rsa_info_st * rsa) |
2240 | { |
2241 | _gnutls_free_datum (&rsa->modulus)_gnutls_free_datum_m(&rsa->modulus, gnutls_free); |
2242 | _gnutls_free_datum (&rsa->exponent)_gnutls_free_datum_m(&rsa->exponent, gnutls_free); |
2243 | } |