*** empty log message ***
[gnutls.git] / lib / x509_sig_check.c
blobb161962db81b9f3728a7d290bdf03be60097d731
1 /*
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>
24 #include <x509_b64.h>
25 #include <auth_cert.h>
26 #include <gnutls_cert.h>
27 #include <x509_asn1.h>
28 #include <x509_der.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>
34 #include <debug.h>
35 #include <gnutls_str.h>
37 /* returns DER tbsCertificate
39 static gnutls_datum _gnutls_get_tbs( gnutls_cert* cert) {
40 node_asn *c2;
41 gnutls_datum ret = {NULL, 0};
42 opaque *str;
43 int result, len;
44 int start, end;
46 if (asn1_create_structure( _gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate")!=ASN_OK) {
47 gnutls_assert();
48 return ret;
51 result = asn1_get_der( c2, cert->raw.data, cert->raw.size);
52 if (result != ASN_OK) {
53 gnutls_assert();
54 asn1_delete_structure(c2);
55 return ret;
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) {
63 gnutls_assert();
64 return ret;
67 len = end - start + 1;
68 str = &cert->raw.data[start];
70 if (gnutls_set_datum( &ret, str, len) < 0) {
71 gnutls_assert();
72 return ret;
75 return ret;
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) {
82 node_asn* dinfo;
83 int result;
84 opaque str[1024];
85 int len;
87 if ((result=asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.DigestInfo", &dinfo, "digest_info"))!=ASN_OK) {
88 gnutls_assert();
89 return _gnutls_asn2err(result);
92 result = asn1_get_der( dinfo, info->data, info->size);
93 if (result != ASN_OK) {
94 gnutls_assert();
95 asn1_delete_structure(dinfo);
96 return _gnutls_asn2err(result);
99 len = sizeof(str)-1;
100 result =
101 asn1_read_value( dinfo, "digest_info.digestAlgorithm.algorithm", str, &len);
102 if (result != ASN_OK) {
103 gnutls_assert();
104 asn1_delete_structure(dinfo);
105 return _gnutls_asn2err(result);
108 *hash = -1;
110 if ( strcmp(str, "1 2 840 113549 2 5")==0) { /* MD5 */
111 *hash = GNUTLS_MAC_MD5;
112 } else
113 if ( strcmp(str, "1 3 14 3 2 26")==0) { /* SHA1 ID */
114 *hash = GNUTLS_MAC_SHA;
117 if (*hash==-1) {
119 _gnutls_x509_log( "X509_SIG: HASH OID: %s\n", str);
121 gnutls_assert();
122 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
125 result =
126 asn1_read_value( dinfo, "digest_info.digest", digest, digest_size);
127 if (result != ASN_OK) {
128 gnutls_assert();
129 asn1_delete_structure(dinfo);
130 return _gnutls_asn2err(result);
133 asn1_delete_structure(dinfo);
135 return 0;
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
143 static int
144 _pkcs1_rsa_verify_sig( const gnutls_datum* signature, gnutls_datum* text, GNUTLS_MPI *params, int params_len)
146 MACAlgorithm hash;
147 int ret;
148 opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE];
149 int digest_size;
150 GNUTLS_HASH_HANDLE hd;
151 gnutls_datum decrypted;
153 if ( (ret=_gnutls_pkcs1_rsa_decrypt( &decrypted, *signature, params, params_len, 1)) < 0) {
154 gnutls_assert();
155 return ret;
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) {
163 gnutls_assert();
164 gnutls_sfree_datum( &decrypted);
165 return ret;
168 gnutls_sfree_datum( &decrypted);
170 if (digest_size != _gnutls_hash_get_algo_len(hash)) {
171 gnutls_assert();
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) {
180 gnutls_assert();
181 return GNUTLS_E_PK_SIGNATURE_FAILED;
184 return 0;
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;
192 gnutls_datum tbs;
194 signature.data = cert->signature.data;
195 signature.size = cert->signature.size;
197 tbs = _gnutls_get_tbs( cert);
198 if (tbs.data==NULL) {
199 gnutls_assert();
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) {
207 case GNUTLS_PK_RSA:
209 if (_pkcs1_rsa_verify_sig( &signature, &tbs, issuer->params, issuer->params_size)!=0) {
210 gnutls_assert();
211 gnutls_free_datum( &tbs);
212 return GNUTLS_CERT_INVALID;
215 gnutls_free_datum(&tbs);
216 return 0;
217 break;
219 case GNUTLS_PK_DSA:
220 if (_gnutls_dsa_verify( &tbs, &signature, issuer->params, issuer->params_size)!=0) {
221 gnutls_assert();
222 gnutls_free_datum( &tbs);
223 return GNUTLS_CERT_INVALID;
226 gnutls_free_datum(&tbs);
227 return 0;
228 break;
232 gnutls_free_datum(&tbs);
234 _gnutls_x509_log( "X509_SIG: PK: %d\n", issuer->subject_pk_algorithm);
236 gnutls_assert();
237 return GNUTLS_CERT_INVALID;