2 * Copyright (C) 2001,2002 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <gnutls_int.h>
22 #include "gnutls_auth_int.h"
23 #include "gnutls_errors.h"
24 #include <gnutls_cert.h>
25 #include <auth_cert.h>
26 #include "gnutls_dh.h"
27 #include "gnutls_num.h"
28 #include "x509_asn1.h"
30 #include "gnutls_datum.h"
31 #include <gnutls_random.h>
32 #include <gnutls_pk.h>
33 #include <gnutls_algorithms.h>
34 #include <gnutls_global.h>
35 #include <gnutls_record.h>
36 #include <x509_verify.h>
37 #include <gnutls_sig.h>
38 #include <x509_extensions.h>
39 #include <gnutls_state.h>
40 #include <gnutls_pk.h>
41 #include <gnutls_x509.h>
42 #include <gnutls_extra.h>
45 /* Copies data from a internal certificate struct (gnutls_cert) to
46 * exported certificate struct (CERTIFICATE_AUTH_INFO)
49 int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info
,
50 gnutls_cert
* cert
, int ncerts
)
52 /* Copy peer's information to AUTH_INFO
57 info
->raw_certificate_list
= NULL
;
62 info
->raw_certificate_list
=
63 gnutls_calloc(1, sizeof(gnutls_datum
) * ncerts
);
64 if (info
->raw_certificate_list
== NULL
) {
66 return GNUTLS_E_MEMORY_ERROR
;
69 for (i
= 0; i
< ncerts
; i
++) {
70 if (cert
->raw
.size
> 0) {
72 gnutls_set_datum(&info
->
73 raw_certificate_list
[i
],
82 info
->ncerts
= ncerts
;
88 for (j
= 0; j
< i
; j
++)
89 gnutls_free_datum(&info
->raw_certificate_list
[j
]);
91 gnutls_free(info
->raw_certificate_list
);
92 info
->raw_certificate_list
= NULL
;
98 /* Returns the issuer's Distinguished name in odn, of the certificate
101 int _gnutls_find_dn(gnutls_datum
* odn
, gnutls_cert
* cert
)
107 if ((result
=asn1_create_structure
108 (_gnutls_get_pkix(), "PKIX1.Certificate", &dn
,
111 return _gnutls_asn2err(result
);
114 result
= asn1_get_der(dn
, cert
->raw
.data
, cert
->raw
.size
);
115 if (result
!= ASN_OK
) {
116 /* couldn't decode DER */
118 asn1_delete_structure(dn
);
119 return _gnutls_asn2err(result
);
122 result
= asn1_get_start_end_der(dn
, cert
->raw
.data
, cert
->raw
.size
,
123 "dn.tbsCertificate.issuer", &start
,
126 if (result
!= ASN_OK
) {
127 /* couldn't decode DER */
129 asn1_delete_structure(dn
);
130 return _gnutls_asn2err(result
);
132 asn1_delete_structure(dn
);
134 len
= end
- start
+ 1;
137 odn
->data
= &cert
->raw
.data
[start
];
143 /* returns 0 if the algo_to-check exists in the pk_algos list,
147 static int _gnutls_check_pk_algo_in_list(PKAlgorithm
* pk_algos
,
149 PKAlgorithm algo_to_check
)
152 for (i
= 0; i
< pk_algos_length
; i
++) {
153 if (algo_to_check
== pk_algos
[i
]) {
160 /* Locates the most appropriate x509 certificate using the
161 * given DN. If indx == -1 then no certificate was found.
163 static int _find_x509_cert(const GNUTLS_CERTIFICATE_CREDENTIALS cred
,
164 opaque
* _data
, int _data_size
,
165 PKAlgorithm
* pk_algos
, int pk_algos_length
,
170 opaque
*data
= _data
;
171 int data_size
= _data_size
, i
, j
;
178 DECR_LENGTH_RET(data_size
, 2, 0);
179 size
= _gnutls_read_uint16(data
);
180 DECR_LENGTH_RET(data_size
, size
, 0);
183 for (i
= 0; i
< cred
->ncerts
; i
++) {
184 for (j
= 0; j
< cred
->cert_list_length
[i
]; j
++) {
186 _gnutls_find_dn(&odn
,
193 if (odn
.size
!= size
)
196 /* If the DN matches and
197 * the *_SIGN algorithm matches
198 * the cert is our cert!
200 if ((memcmp(odn
.data
,
202 (_gnutls_check_pk_algo_in_list
203 (pk_algos
, pk_algos_length
,
204 cred
->cert_list
[i
][0].
205 subject_pk_algorithm
) == 0)
206 && (cred
->cert_list
[i
][0].cert_type
==
219 /* move to next record */
231 /* Locates the most appropriate openpgp cert
233 static int _find_openpgp_cert(const GNUTLS_CERTIFICATE_CREDENTIALS cred
,
234 PKAlgorithm
* pk_algos
, int pk_algos_length
,
241 for (i
= 0; i
< cred
->ncerts
; i
++) {
242 for (j
= 0; j
< cred
->cert_list_length
[i
]; j
++) {
244 /* If the *_SIGN algorithm matches
245 * the cert is our cert!
247 if ((_gnutls_check_pk_algo_in_list
248 (pk_algos
, pk_algos_length
,
249 cred
->cert_list
[i
][0].
250 subject_pk_algorithm
) == 0)
251 && (cred
->cert_list
[i
][0].cert_type
==
252 GNUTLS_CRT_OPENPGP
)) {
264 /* Finds the appropriate certificate depending on the cA Distinguished name
265 * advertized by the server. If none matches then returns 0 and -1 as index.
266 * In case of an error a negative value, is returned.
268 * 20020128: added ability to select a certificate depending on the SIGN
269 * algorithm (only in automatic mode).
271 static int _gnutls_find_acceptable_client_cert(GNUTLS_STATE state
,
273 int _data_size
, int *ind
,
274 PKAlgorithm
* pk_algos
,
279 int i
, j
, try = 0, *ij_map
= NULL
;
280 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
281 opaque
*data
= _data
;
282 int data_size
= _data_size
;
285 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
289 return GNUTLS_E_INSUFICIENT_CRED
;
292 if (state
->gnutls_internals
.client_cert_callback
!= NULL
) {
293 /* if try>=0 then the client wants automatic
294 * choose of certificate, otherwise (-1), he
295 * will be prompted to choose one.
298 state
->gnutls_internals
.client_cert_callback(state
,
307 if (state
->security_parameters
.cert_type
==
310 _find_x509_cert(cred
, _data
, _data_size
,
311 pk_algos
, pk_algos_length
,
314 if (state
->security_parameters
.cert_type
==
317 _find_openpgp_cert(cred
, pk_algos
,
318 pk_algos_length
, &indx
);
330 if (indx
== -1 && state
->gnutls_internals
.client_cert_callback
!= NULL
&& cred
->ncerts
> 0) { /* use a callback to get certificate */
331 gnutls_datum
*my_certs
= NULL
;
332 gnutls_datum
*issuers_dn
= NULL
;
333 int issuers_dn_len
= 0;
334 opaque
* dataptr
= data
;
335 int dataptr_size
= data_size
;
337 /* Count the number of the given issuers;
338 * This is used to allocate the issuers_dn without
343 if (dataptr_size
<= 0)
345 size
= _gnutls_read_uint16(data
);
347 dataptr_size
-= size
;
348 if (dataptr_size
< 0)
357 if (dataptr_size
== 0)
364 gnutls_alloca(cred
->ncerts
* sizeof(gnutls_datum
));
365 if (my_certs
== NULL
)
368 /* put the requested DNs to req_dn, only in case
369 * of X509 certificates.
371 if (gnutls_cert_type_get(state
) == GNUTLS_CRT_X509
) {
373 data_size
= _data_size
;
375 issuers_dn
= gnutls_alloca( issuers_dn_len
* sizeof(gnutls_datum
));
376 if (issuers_dn
== NULL
)
379 for (i
=0;i
<issuers_dn_len
;i
++) {
380 /* The checks here for the buffer boundaries
381 * are not needed since the buffer has been
386 size
= _gnutls_read_uint16(data
);
390 issuers_dn
[i
].data
= data
;
391 issuers_dn
[i
].size
= size
;
397 } else { /* Other certificate types */
403 ij_map
= gnutls_alloca(sizeof(int) * cred
->ncerts
);
409 /* put our certificate's issuer and dn into cdn, idn
410 * Note that the certificates we provide to the callback
411 * are not all the certificates we have. Only the certificates
412 * that are requested by the server (CA matches - and sign
413 * algorithm matches), are provided.
415 for (j
= i
= 0; i
< cred
->ncerts
; i
++) {
416 if ((cred
->cert_list
[i
][0].cert_type
==
417 gnutls_cert_type_get(state
)) &&
418 (_gnutls_check_pk_algo_in_list(pk_algos
,
422 subject_pk_algorithm
)
424 /* Add a certificate ONLY if it is allowed
428 my_certs
[j
++] = cred
->cert_list
[i
][0].raw
;
433 state
->gnutls_internals
.client_cert_callback(state
,
439 /* the indx returned by the user is relative
440 * to the certificates we provided him.
441 * This will make it relative to the certificates
447 gnutls_afree(my_certs
);
448 gnutls_afree(ij_map
);
449 gnutls_afree(issuers_dn
);
456 /* Generate client certificate
459 int _gnutls_gen_x509_certificate(GNUTLS_STATE state
, opaque
** data
)
463 gnutls_cert
*apr_cert_list
;
464 gnutls_private_key
*apr_pkey
;
465 int apr_cert_list_length
;
467 /* find the appropriate certificate */
469 _gnutls_find_apr_cert(state
, &apr_cert_list
,
470 &apr_cert_list_length
,
477 for (i
= 0; i
< apr_cert_list_length
; i
++) {
478 ret
+= apr_cert_list
[i
].raw
.size
+ 3;
483 /* if no certificates were found then send:
484 * 0B 00 00 03 00 00 00 // Certificate with no certs
486 * 0B 00 00 00 // empty certificate handshake
488 * ( the above is the whole handshake message, not
489 * the one produced here )
492 (*data
) = gnutls_malloc(ret
);
497 return GNUTLS_E_MEMORY_ERROR
;
499 _gnutls_write_uint24(ret
- 3, pdata
);
501 for (i
= 0; i
< apr_cert_list_length
; i
++) {
502 _gnutls_write_datum24(pdata
, apr_cert_list
[i
].raw
);
503 pdata
+= (3 + apr_cert_list
[i
].raw
.size
);
509 enum PGPKeyDescriptorType
{ PGP_KEY_FINGERPRINT
, PGP_KEY
};
511 int _gnutls_gen_openpgp_certificate(GNUTLS_STATE state
,
516 gnutls_cert
*apr_cert_list
;
517 gnutls_private_key
*apr_pkey
;
518 int apr_cert_list_length
;
520 /* find the appropriate certificate */
522 _gnutls_find_apr_cert(state
, &apr_cert_list
,
523 &apr_cert_list_length
,
531 if (apr_cert_list_length
> 0)
532 ret
+= apr_cert_list
[0].raw
.size
;
534 (*data
) = gnutls_malloc(ret
);
539 return GNUTLS_E_MEMORY_ERROR
;
542 _gnutls_write_uint24(ret
- 3, pdata
);
545 *pdata
= PGP_KEY
; /* whole key */
548 if (apr_cert_list_length
> 0) {
549 _gnutls_write_datum24(pdata
, apr_cert_list
[0].raw
);
550 pdata
+= (3 + apr_cert_list
[0].raw
.size
);
551 } else /* empty - no certificate */
552 _gnutls_write_uint24(0, pdata
);
557 OPENPGP_FINGERPRINT _E_gnutls_openpgp_fingerprint
= NULL
;
558 OPENPGP_KEY_REQUEST _E_gnutls_openpgp_request_key
= NULL
;
559 extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert
;
561 int _gnutls_gen_openpgp_certificate_fpr(GNUTLS_STATE state
,
564 int ret
, fpr_size
, packet_size
;
566 gnutls_cert
*apr_cert_list
;
567 gnutls_private_key
*apr_pkey
;
568 int apr_cert_list_length
;
570 /* find the appropriate certificate */
572 _gnutls_find_apr_cert(state
, &apr_cert_list
,
573 &apr_cert_list_length
,
581 /* Only v4 fingerprints are sent
583 if (apr_cert_list_length
> 0 && apr_cert_list
[0].version
== 4)
584 packet_size
+= 20 + 1;
585 else /* empty certificate case */
586 return _gnutls_gen_openpgp_certificate(state
, data
);
588 (*data
) = gnutls_malloc(packet_size
);
593 return GNUTLS_E_MEMORY_ERROR
;
596 _gnutls_write_uint24(packet_size
- 3, pdata
);
599 *pdata
= PGP_KEY_FINGERPRINT
; /* key fingerprint */
607 if (_E_gnutls_openpgp_fingerprint
==NULL
) {
609 return GNUTLS_E_INVALID_REQUEST
;
612 if ( (ret
=_E_gnutls_openpgp_fingerprint( &apr_cert_list
[0].raw
, pdata
, &fpr_size
)) < 0) {
622 int _gnutls_gen_cert_client_certificate(GNUTLS_STATE state
, opaque
** data
)
624 switch (state
->security_parameters
.cert_type
) {
625 case GNUTLS_CRT_OPENPGP
:
626 if (_gnutls_openpgp_send_fingerprint(state
) == 0)
628 _gnutls_gen_openpgp_certificate(state
,
632 _gnutls_gen_openpgp_certificate_fpr
635 case GNUTLS_CRT_X509
:
636 return _gnutls_gen_x509_certificate(state
, data
);
640 return GNUTLS_E_UNKNOWN_ERROR
;
644 int _gnutls_gen_cert_server_certificate(GNUTLS_STATE state
, opaque
** data
)
646 switch (state
->security_parameters
.cert_type
) {
647 case GNUTLS_CRT_OPENPGP
:
648 return _gnutls_gen_openpgp_certificate(state
, data
);
649 case GNUTLS_CRT_X509
:
650 return _gnutls_gen_x509_certificate(state
, data
);
653 return GNUTLS_E_UNKNOWN_ERROR
;
657 /* Process server certificate
660 #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_free_cert(peer_certificate_list[x])
661 int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state
, opaque
* data
,
666 CERTIFICATE_AUTH_INFO info
;
667 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
668 int dsize
= data_size
;
670 gnutls_cert
*peer_certificate_list
;
671 int peer_certificate_list_size
= 0;
675 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
679 return GNUTLS_E_INSUFICIENT_CRED
;
684 _gnutls_auth_info_set(state
, GNUTLS_CRD_CERTIFICATE
,
685 sizeof(CERTIFICATE_AUTH_INFO_INT
), 1)) <
691 info
= _gnutls_get_auth_info(state
);
693 if (data
== NULL
|| data_size
== 0) {
695 /* no certificate was sent */
696 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
700 size
= _gnutls_read_uint24(p
);
705 /* no certificate was sent */
706 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
712 len
= _gnutls_read_uint24(p
);
714 DECR_LEN(dsize
, len
);
715 peer_certificate_list_size
++;
720 if (peer_certificate_list_size
== 0) {
722 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
725 /* Ok we now allocate the memory to hold the
729 peer_certificate_list
=
730 gnutls_alloca( sizeof(gnutls_cert
) *
731 (peer_certificate_list_size
));
733 if (peer_certificate_list
== NULL
) {
735 return GNUTLS_E_MEMORY_ERROR
;
737 memset( peer_certificate_list
, 0, sizeof(gnutls_cert
)*
738 peer_certificate_list_size
);
742 /* Now we start parsing the list (again).
743 * We don't use DECR_LEN since the list has
744 * been parsed before.
747 for (j
=0;j
<peer_certificate_list_size
;j
++) {
748 len
= _gnutls_read_uint24(p
);
755 _gnutls_x509_cert2gnutls_cert(&peer_certificate_list
759 gnutls_afree(peer_certificate_list
);
768 _gnutls_copy_certificate_auth_info(info
,
769 peer_certificate_list
,
770 peer_certificate_list_size
))
774 gnutls_afree(peer_certificate_list
);
779 _gnutls_check_x509_key_usage(&peer_certificate_list
[0],
780 gnutls_kx_get(state
)))
784 gnutls_afree(peer_certificate_list
);
789 gnutls_afree(peer_certificate_list
);
794 #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_free_cert(peer_certificate_list[x])
795 int _gnutls_proc_openpgp_server_certificate(GNUTLS_STATE state
,
796 opaque
* data
, int data_size
)
800 CERTIFICATE_AUTH_INFO info
;
801 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
802 int dsize
= data_size
;
804 gnutls_cert
*peer_certificate_list
;
805 int peer_certificate_list_size
= 0;
806 gnutls_datum tmp
, akey
= { NULL
, 0 };
809 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
813 return GNUTLS_E_INSUFICIENT_CRED
;
817 _gnutls_auth_info_set(state
, GNUTLS_CRD_CERTIFICATE
,
818 sizeof(CERTIFICATE_AUTH_INFO_INT
), 1)) <
824 info
= _gnutls_get_auth_info(state
);
826 if (data
== NULL
|| data_size
== 0) {
828 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
832 size
= _gnutls_read_uint24(p
);
837 /* no certificate was sent */
838 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
842 /* Read PGPKeyDescriptor */
844 if (*p
== PGP_KEY_FINGERPRINT
) { /* the fingerprint */
852 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
855 DECR_LEN( dsize
, 20);
857 /* request the actual key from our database, or
858 * a key server or anything.
860 if (_E_gnutls_openpgp_request_key
==NULL
) {
862 return GNUTLS_E_INVALID_REQUEST
;
864 if ( (ret
=_E_gnutls_openpgp_request_key( &akey
, cred
, p
, 20)) < 0) {
869 peer_certificate_list_size
++;
871 } else if (*p
== PGP_KEY
) { /* the whole key */
875 /* Read the actual certificate */
877 len
= _gnutls_read_uint24(p
);
882 /* no certificate was sent */
883 return GNUTLS_E_NO_CERTIFICATE_FOUND
;
886 DECR_LEN(dsize
, len
);
887 peer_certificate_list_size
++;
894 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
897 /* ok we now have the peer's key in tmp datum
900 if (peer_certificate_list_size
== 0) {
902 gnutls_free_datum( &akey
);
903 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
906 peer_certificate_list
=
907 gnutls_alloca( sizeof(gnutls_cert
) *
908 (peer_certificate_list_size
));
909 if (peer_certificate_list
== NULL
) {
911 return GNUTLS_E_MEMORY_ERROR
;
913 memset( peer_certificate_list
, 0, sizeof(gnutls_cert
)*
914 peer_certificate_list_size
);
916 if (_E_gnutls_openpgp_cert2gnutls_cert
==NULL
) {
918 gnutls_free_datum( &akey
);
920 gnutls_afree(peer_certificate_list
);
921 return GNUTLS_E_INVALID_REQUEST
;
925 _E_gnutls_openpgp_cert2gnutls_cert(&peer_certificate_list
[0],
928 gnutls_free_datum( &akey
);
930 gnutls_afree(peer_certificate_list
);
933 gnutls_free_datum( &akey
);
936 _gnutls_copy_certificate_auth_info(info
,
937 peer_certificate_list
,
938 peer_certificate_list_size
))
942 gnutls_afree(peer_certificate_list
);
947 _gnutls_check_x509_key_usage(&peer_certificate_list
[0],
948 gnutls_kx_get(state
)))
952 gnutls_afree(peer_certificate_list
);
957 gnutls_afree(peer_certificate_list
);
962 int _gnutls_proc_cert_server_certificate(GNUTLS_STATE state
, opaque
* data
,
965 switch (state
->security_parameters
.cert_type
) {
966 case GNUTLS_CRT_OPENPGP
:
967 return _gnutls_proc_openpgp_server_certificate(state
, data
,
969 case GNUTLS_CRT_X509
:
970 return _gnutls_proc_x509_server_certificate(state
, data
,
974 return GNUTLS_E_UNKNOWN_ERROR
;
978 #define MAX_SIGN_ALGOS 2
979 typedef enum CertificateSigType
{ RSA_SIGN
= 1, DSA_SIGN
980 } CertificateSigType
;
982 /* Checks if we support the given signature algorithm
983 * (RSA or DSA). Returns the corresponding PKAlgorithm
987 int _gnutls_check_supported_sign_algo(CertificateSigType algo
)
991 return GNUTLS_PK_RSA
;
993 return GNUTLS_PK_DSA
;
999 int _gnutls_proc_cert_cert_req(GNUTLS_STATE state
, opaque
* data
,
1004 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
1005 CERTIFICATE_AUTH_INFO info
;
1006 int dsize
= data_size
;
1008 PKAlgorithm pk_algos
[MAX_SIGN_ALGOS
];
1009 int pk_algos_length
;
1012 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
1016 return GNUTLS_E_INSUFICIENT_CRED
;
1020 _gnutls_auth_info_set(state
, GNUTLS_CRD_CERTIFICATE
,
1021 sizeof(CERTIFICATE_AUTH_INFO_INT
), 0)) <
1027 info
= _gnutls_get_auth_info(state
);
1032 /* check if the sign algorithm is supported.
1034 pk_algos_length
= j
= 0;
1035 for (i
= 0; i
< size
; i
++, p
++) {
1037 if ((ret
= _gnutls_check_supported_sign_algo(*p
)) > 0) {
1038 if (j
< MAX_SIGN_ALGOS
) {
1039 pk_algos
[j
++] = ret
;
1045 if (pk_algos_length
== 0) {
1047 return GNUTLS_E_UNKNOWN_KX_ALGORITHM
;
1050 if (state
->security_parameters
.cert_type
== GNUTLS_CRT_X509
) {
1052 size
= _gnutls_read_uint16(p
);
1059 DECR_LEN(dsize
, size
);
1061 /* now we ask the user to tell which one
1065 _gnutls_find_acceptable_client_cert(state
, p
, size
,
1067 pk_algos_length
)) < 0) {
1071 /* put the index of the client certificate to use
1073 state
->gnutls_internals
.selected_cert_index
= ind
;
1076 state
->gnutls_key
->certificate_requested
= 1;
1081 int _gnutls_gen_cert_client_cert_vrfy(GNUTLS_STATE state
, opaque
** data
)
1084 gnutls_cert
*apr_cert_list
;
1085 gnutls_private_key
*apr_pkey
;
1086 int apr_cert_list_length
, size
;
1087 gnutls_datum signature
;
1091 /* find the appropriate certificate */
1093 _gnutls_find_apr_cert(state
, &apr_cert_list
,
1094 &apr_cert_list_length
,
1100 if (apr_pkey
!= NULL
) {
1102 _gnutls_generate_sig_from_hdata(state
,
1114 *data
= gnutls_malloc(signature
.size
+ 2);
1115 if (*data
== NULL
) {
1116 gnutls_free_datum(&signature
);
1117 return GNUTLS_E_MEMORY_ERROR
;
1119 size
= signature
.size
;
1120 _gnutls_write_uint16(size
, *data
);
1122 memcpy(&(*data
)[2], signature
.data
, size
);
1124 gnutls_free_datum(&signature
);
1129 int _gnutls_proc_cert_client_cert_vrfy(GNUTLS_STATE state
, opaque
* data
,
1133 int dsize
= data_size
;
1134 opaque
*pdata
= data
;
1136 CERTIFICATE_AUTH_INFO info
= _gnutls_get_auth_info(state
);
1137 gnutls_cert peer_cert
;
1139 if (info
== NULL
|| info
->ncerts
== 0) {
1141 /* we need this in order to get peer's certificate */
1142 return GNUTLS_E_UNKNOWN_ERROR
;
1146 size
= _gnutls_read_uint16(pdata
);
1149 DECR_LEN(dsize
, size
);
1154 switch (state
->security_parameters
.cert_type
) {
1155 case GNUTLS_CRT_X509
:
1157 _gnutls_x509_cert2gnutls_cert(&peer_cert
,
1159 raw_certificate_list
[0]);
1161 case GNUTLS_CRT_OPENPGP
:
1162 if (_E_gnutls_openpgp_cert2gnutls_cert
==NULL
) {
1164 return GNUTLS_E_INVALID_REQUEST
;
1167 _E_gnutls_openpgp_cert2gnutls_cert(&peer_cert
,
1169 raw_certificate_list
1174 return GNUTLS_E_UNKNOWN_ERROR
;
1183 _gnutls_verify_sig_hdata(state
, &peer_cert
, &sig
,
1184 data_size
+ HANDSHAKE_HEADER_SIZE
)) <
1187 _gnutls_free_cert(peer_cert
);
1190 _gnutls_free_cert(peer_cert
);
1195 #define CERTTYPE_SIZE 3
1196 int _gnutls_gen_cert_server_cert_req(GNUTLS_STATE state
, opaque
** data
)
1198 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
1202 /* Now we need to generate the RDN sequence. This is
1203 * already in the CERTIFICATE_CRED structure, to improve
1208 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
1212 return GNUTLS_E_INSUFICIENT_CRED
;
1215 size
= CERTTYPE_SIZE
+ 2; /* 2 for CertificateType + 2 for size of rdn_seq
1218 if (state
->security_parameters
.cert_type
== GNUTLS_CRT_X509
)
1219 size
+= cred
->x509_rdn_sequence
.size
;
1221 (*data
) = gnutls_malloc(size
);
1224 if (pdata
== NULL
) {
1226 return GNUTLS_E_MEMORY_ERROR
;
1229 pdata
[0] = CERTTYPE_SIZE
- 1;
1231 pdata
[1] = RSA_SIGN
;
1232 pdata
[2] = DSA_SIGN
; /* only these for now */
1233 pdata
+= CERTTYPE_SIZE
;
1235 if (state
->security_parameters
.cert_type
== GNUTLS_CRT_X509
) {
1236 _gnutls_write_datum16(pdata
, cred
->x509_rdn_sequence
);
1237 pdata
+= cred
->x509_rdn_sequence
.size
+ 2;
1244 /* This function will return the appropriate certificate to use. The return
1245 * value depends on the side (client or server).
1247 int _gnutls_find_apr_cert(GNUTLS_STATE state
, gnutls_cert
** apr_cert_list
,
1248 int *apr_cert_list_length
,
1249 gnutls_private_key
** apr_pkey
)
1251 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
1255 _gnutls_get_kx_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
1260 *apr_cert_list
= NULL
;
1262 *apr_cert_list_length
= 0;
1263 return GNUTLS_E_INSUFICIENT_CRED
;
1266 if (state
->security_parameters
.entity
== GNUTLS_SERVER
) {
1268 if (cred
->ncerts
== 0) {
1269 *apr_cert_list
= NULL
;
1270 *apr_cert_list_length
= 0;
1272 gnutls_assert(); /* this is not allowed */
1273 return GNUTLS_E_INSUFICIENT_CRED
;
1275 /* find_cert_list_index() has been called before.
1277 ind
= state
->gnutls_internals
.selected_cert_index
;
1280 *apr_cert_list
= NULL
;
1281 *apr_cert_list_length
= 0;
1284 return GNUTLS_E_INSUFICIENT_CRED
;
1286 *apr_cert_list
= cred
->cert_list
[ind
];
1287 *apr_cert_list_length
=
1288 cred
->cert_list_length
[ind
];
1289 *apr_pkey
= &cred
->pkey
[ind
];
1292 } else { /* CLIENT SIDE */
1293 if (cred
->ncerts
== 0) {
1294 *apr_cert_list
= NULL
;
1295 *apr_cert_list_length
= 0;
1297 /* it is allowed not to have a certificate
1300 /* we had already decided which certificate
1303 ind
= state
->gnutls_internals
.selected_cert_index
;
1306 *apr_cert_list
= NULL
;
1307 *apr_cert_list_length
= 0;
1310 *apr_cert_list
= cred
->cert_list
[ind
];
1311 *apr_cert_list_length
=
1312 cred
->cert_list_length
[ind
];
1313 *apr_pkey
= &cred
->pkey
[ind
];
1322 /* finds the most appropriate certificate in the cert list.
1323 * The 'appropriate' is defined by the user.
1324 * (frontend to _gnutls_server_find_cert_index())
1326 const gnutls_cert
*_gnutls_server_find_cert(GNUTLS_STATE state
,
1327 PKAlgorithm requested_algo
)
1330 const GNUTLS_CERTIFICATE_CREDENTIALS x509_cred
;
1333 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
1336 if (x509_cred
== NULL
)
1339 i
= _gnutls_server_find_cert_list_index(state
,
1340 x509_cred
->cert_list
,
1347 return &x509_cred
->cert_list
[i
][0];
1350 /* finds the most appropriate certificate in the cert list.
1351 * The 'appropriate' is defined by the user.
1353 * requested_algo holds the parameters required by the peer (RSA, DSA
1356 int _gnutls_server_find_cert_list_index(GNUTLS_STATE state
,
1357 gnutls_cert
** cert_list
,
1358 int cert_list_length
,
1359 PKAlgorithm requested_algo
)
1361 int i
, index
= -1, j
;
1362 const GNUTLS_CERTIFICATE_CREDENTIALS cred
;
1363 int my_certs_length
;
1367 _gnutls_get_cred(state
->gnutls_key
, GNUTLS_CRD_CERTIFICATE
,
1371 return GNUTLS_E_INSUFICIENT_CRED
;
1374 index
= -1; /* default is use no certificate */
1376 for (i
= 0; i
< cred
->ncerts
; i
++) {
1377 /* find one compatible certificate */
1378 if (requested_algo
== -1 ||
1380 cred
->cert_list
[i
][0].subject_pk_algorithm
) {
1381 /* if cert type matches */
1382 if (state
->security_parameters
.cert_type
==
1383 cred
->cert_list
[i
][0].cert_type
) {
1391 if (state
->gnutls_internals
.server_cert_callback
!= NULL
&& cred
->ncerts
> 0) { /* use the callback to get certificate */
1392 gnutls_datum
*my_certs
= NULL
;
1395 gnutls_malloc(cred
->ncerts
* sizeof(gnutls_datum
));
1396 if (my_certs
== NULL
)
1398 my_certs_length
= cred
->ncerts
;
1400 /* put our certificate's issuer and dn into cdn, idn
1402 ij_map
= gnutls_malloc(sizeof(int) * cred
->ncerts
);
1405 for (i
= 0; i
< cred
->ncerts
; i
++) {
1406 /* Add compatible certificates */
1407 if (requested_algo
== -1 ||
1409 cred
->cert_list
[i
][0].subject_pk_algorithm
) {
1411 /* if cert type matches */
1412 if (state
->security_parameters
.cert_type
==
1413 cred
->cert_list
[i
][0].cert_type
) {
1417 cred
->cert_list
[i
][0].raw
;
1421 my_certs_length
= j
;
1424 state
->gnutls_internals
.server_cert_callback(state
,
1428 index
= ij_map
[index
];
1431 gnutls_free(my_certs
);
1432 gnutls_free(ij_map
);
1435 /* store the index for future use, in the handshake.
1436 * (This will allow not calling this callback again.)
1438 state
->gnutls_internals
.selected_cert_index
= index
;