We have reached a state where we are able to import certs and
[gnupg.git] / sm / certcheck.c
1 /* certcheck.c - check one certificate
2  *      Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29
30 #include <gcrypt.h>
31 #include <ksba.h>
32
33 #include "gpgsm.h"
34 #include "keydb.h"
35 #include "i18n.h"
36
37 static int
38 do_encode_md (GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
39               const byte *asn, size_t asnlen, GCRY_MPI *r_val)
40 {
41   int nframe = (nbits+7) / 8;
42   byte *frame;
43   int i, n;
44   
45   if ( len + asnlen + 4  > nframe )
46     {
47       log_error ("can't encode a %d bit MD into a %d bits frame\n",
48                  (int)(len*8), (int)nbits);
49       return GPGSM_Internal_Error;
50     }
51   
52   /* We encode the MD in this way:
53    *
54    *       0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
55    *
56    * PAD consists of FF bytes.
57    */
58   frame = xtrymalloc (nframe);
59   if (!frame)
60     return GPGSM_Out_Of_Core;
61   n = 0;
62   frame[n++] = 0;
63   frame[n++] = 1; /* block type */
64   i = nframe - len - asnlen -3 ;
65   assert ( i > 1 );
66   memset ( frame+n, 0xff, i ); n += i;
67   frame[n++] = 0;
68   memcpy ( frame+n, asn, asnlen ); n += asnlen;
69   memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
70   assert ( n == nframe );
71   gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, &nframe);
72   xfree (frame);
73   return 0;
74 }
75
76
77 /*
78   Check the signature on CERT using the ISSUER-CERT.  This function
79   does only test the cryptographic signature and nothing else.  It is
80   assumed that the ISSUER_CERT is valid. */
81 int
82 gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert)
83 {
84   /* OID for MD5 as defined in PKCS#1 (rfc2313) */
85   static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 (md5) */
86   { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
87     0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
88   };
89
90   GCRY_MD_HD md;
91   int rc, algo;
92   GCRY_MPI frame;
93   char *p;
94   GCRY_SEXP s_sig, s_hash, s_pkey;
95
96   algo = ksba_cert_get_digest_algo (cert);
97   md = gcry_md_open (algo, 0);
98   if (!md)
99     {
100       log_error ("md_open failed: %s\n", gcry_strerror (-1));
101       return GPGSM_General_Error;
102     }
103
104   rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
105   if (rc)
106     {
107       log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
108       gcry_md_close (md);
109       return map_ksba_err (rc);
110     }
111   gcry_md_final (md);
112
113   p = ksba_cert_get_sig_val (cert); /* fixme: check p*/
114   if (DBG_X509)
115     log_debug ("signature: %s\n", p);
116
117   rc = gcry_sexp_sscan ( &s_sig, NULL, p, strlen(p));
118   if (rc)
119     {
120       log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
121       return map_gcry_err (rc);
122     }
123   /*gcry_sexp_dump (s_sig);*/
124
125
126   /* FIXME: need to map the algo to the ASN OID - we assume a fixed
127      one for now */
128   rc = do_encode_md (md, algo, 16, 2048, asn, DIM(asn), &frame);
129   if (rc)
130     {
131       /* fixme: clean up some things */
132       return rc;
133     }
134   /* put hash into the S-Exp s_hash */
135   if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
136     BUG ();
137   /*fputs ("hash:\n", stderr); gcry_sexp_dump (s_hash);*/
138
139   p = ksba_cert_get_public_key (issuer_cert);
140   if (DBG_X509)
141     log_debug ("issuer public key: %s\n", p);
142
143   rc = gcry_sexp_sscan ( &s_pkey, NULL, p, strlen(p));
144   if (rc)
145     {
146       log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
147       return map_gcry_err (rc);
148     }
149   /*gcry_sexp_dump (s_pkey);*/
150   
151   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
152   if (DBG_CRYPTO)
153       log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
154   return map_gcry_err (rc);
155 }
156