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
22 #include <gnutls_int.h>
23 #include <gnutls_errors.h>
25 #include <auth_cert.h>
26 #include <gnutls_cert.h>
27 #include <x509_asn1.h>
29 #include <gnutls_datum.h>
30 #include <gnutls_mpi.h>
31 #include <gnutls_privkey.h>
32 #include <gnutls_global.h>
33 #include <gnutls_pk.h>
35 #include <gnutls_str.h>
37 /* returns DER tbsCertificate
39 static gnutls_datum
_gnutls_get_tbs( gnutls_cert
* cert
) {
41 gnutls_datum ret
= {NULL
, 0};
46 if (asn1_create_structure( _gnutls_get_pkix(), "PKIX1.Certificate", &c2
, "certificate")!=ASN_OK
) {
51 result
= asn1_get_der( c2
, cert
->raw
.data
, cert
->raw
.size
);
52 if (result
!= ASN_OK
) {
54 asn1_delete_structure(c2
);
58 result
= asn1_get_start_end_der( c2
, cert
->raw
.data
, cert
->raw
.size
,
59 "certificate.tbsCertificate", &start
, &end
);
60 asn1_delete_structure(c2
);
62 if (result
!= ASN_OK
) {
67 len
= end
- start
+ 1;
68 str
= &cert
->raw
.data
[start
];
70 if (gnutls_set_datum( &ret
, str
, len
) < 0) {
79 /* we use DER here -- FIXME: use BER
81 static int _gnutls_get_ber_digest_info( const gnutls_datum
*info
, MACAlgorithm
*hash
, opaque
* digest
, int *digest_size
) {
87 if ((result
=asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.DigestInfo", &dinfo
, "digest_info"))!=ASN_OK
) {
89 return _gnutls_asn2err(result
);
92 result
= asn1_get_der( dinfo
, info
->data
, info
->size
);
93 if (result
!= ASN_OK
) {
95 asn1_delete_structure(dinfo
);
96 return _gnutls_asn2err(result
);
101 asn1_read_value( dinfo
, "digest_info.digestAlgorithm.algorithm", str
, &len
);
102 if (result
!= ASN_OK
) {
104 asn1_delete_structure(dinfo
);
105 return _gnutls_asn2err(result
);
110 if ( strcmp(str
, "1 2 840 113549 2 5")==0) { /* MD5 */
111 *hash
= GNUTLS_MAC_MD5
;
113 if ( strcmp(str
, "1 3 14 3 2 26")==0) { /* SHA1 ID */
114 *hash
= GNUTLS_MAC_SHA
;
119 _gnutls_x509_log( "X509_SIG: HASH OID: %s\n", str
);
122 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
126 asn1_read_value( dinfo
, "digest_info.digest", digest
, digest_size
);
127 if (result
!= ASN_OK
) {
129 asn1_delete_structure(dinfo
);
130 return _gnutls_asn2err(result
);
133 asn1_delete_structure(dinfo
);
138 /* if hash==MD5 then we do RSA-MD5
139 * if hash==SHA then we do RSA-SHA
140 * params[0] is modulus
141 * params[1] is public key
144 _pkcs1_rsa_verify_sig( const gnutls_datum
* signature
, gnutls_datum
* text
, GNUTLS_MPI
*params
, int params_len
)
148 opaque digest
[MAX_HASH_SIZE
], md
[MAX_HASH_SIZE
];
150 GNUTLS_HASH_HANDLE hd
;
151 gnutls_datum decrypted
;
153 if ( (ret
=_gnutls_pkcs1_rsa_decrypt( &decrypted
, *signature
, params
, params_len
, 1)) < 0) {
158 /* decrypted is a BER encoded data of type DigestInfo
161 digest_size
= sizeof(digest
);
162 if ( (ret
= _gnutls_get_ber_digest_info( &decrypted
, &hash
, digest
, &digest_size
)) != 0) {
164 gnutls_sfree_datum( &decrypted
);
168 gnutls_sfree_datum( &decrypted
);
170 if (digest_size
!= _gnutls_hash_get_algo_len(hash
)) {
172 return GNUTLS_E_ASN1_GENERIC_ERROR
;
175 hd
= _gnutls_hash_init( hash
);
176 _gnutls_hash( hd
, text
->data
, text
->size
);
177 _gnutls_hash_deinit( hd
, md
);
179 if (memcmp( md
, digest
, digest_size
)!=0) {
181 return GNUTLS_E_PK_SIGNATURE_FAILED
;
187 /* verifies if the certificate is properly signed.
188 * returns 0 on success.
190 CertificateStatus
gnutls_x509_verify_signature(gnutls_cert
* cert
, gnutls_cert
* issuer
) {
191 gnutls_datum signature
;
194 signature
.data
= cert
->signature
.data
;
195 signature
.size
= cert
->signature
.size
;
197 tbs
= _gnutls_get_tbs( cert
);
198 if (tbs
.data
==NULL
) {
200 return GNUTLS_CERT_INVALID
;
203 _gnutls_x509_log("X509_VERIFY: CERT[%s]\n", GET_CN(cert
->raw
));
204 _gnutls_x509_log("X509_VERIFY: ISSUER[%s]\n", GET_CN(issuer
->raw
));
206 switch( issuer
->subject_pk_algorithm
) {
209 if (_pkcs1_rsa_verify_sig( &signature
, &tbs
, issuer
->params
, issuer
->params_size
)!=0) {
211 gnutls_free_datum( &tbs
);
212 return GNUTLS_CERT_INVALID
;
215 gnutls_free_datum(&tbs
);
220 if (_gnutls_dsa_verify( &tbs
, &signature
, issuer
->params
, issuer
->params_size
)!=0) {
222 gnutls_free_datum( &tbs
);
223 return GNUTLS_CERT_INVALID
;
226 gnutls_free_datum(&tbs
);
232 gnutls_free_datum(&tbs
);
234 _gnutls_x509_log( "X509_SIG: PK: %d\n", issuer
->subject_pk_algorithm
);
237 return GNUTLS_CERT_INVALID
;