agent/
[gnupg.git] / scd / app-help.c
blob3d9c605f6968fdecfbb2e5075d25477d61deead3
1 /* app-help.c - Application helper functions
2 * Copyright (C) 2004, 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include "scdaemon.h"
27 #include "app-common.h"
28 #include "iso7816.h"
29 #include "tlv.h"
32 /* Count the number of bits, assuming the A represents an unsigned big
33 integer of length LEN bytes. If A is NULL a length of 0 is
34 returned. */
35 unsigned int
36 app_help_count_bits (const unsigned char *a, size_t len)
38 unsigned int n = len * 8;
39 int i;
41 if (!a)
42 return 0;
44 for (; len && !*a; len--, a++, n -=8)
46 if (len)
48 for (i=7; i && !(*a & (1<<i)); i--)
49 n--;
51 return n;
55 /* Return the KEYGRIP for the certificate CERT as an hex encoded
56 string in the user provided buffer HEXKEYGRIP which must be of at
57 least 41 bytes. */
58 gpg_error_t
59 app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip)
61 gpg_error_t err;
62 gcry_sexp_t s_pkey;
63 ksba_sexp_t p;
64 size_t n;
65 unsigned char array[20];
67 p = ksba_cert_get_public_key (cert);
68 if (!p)
69 return gpg_error (GPG_ERR_BUG);
70 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
71 if (!n)
72 return gpg_error (GPG_ERR_INV_SEXP);
73 err = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
74 xfree (p);
75 if (err)
76 return err; /* Can't parse that S-expression. */
77 if (!gcry_pk_get_keygrip (s_pkey, array))
79 gcry_sexp_release (s_pkey);
80 return gpg_error (GPG_ERR_GENERAL); /* Failed to calculate the keygrip.*/
82 gcry_sexp_release (s_pkey);
84 bin2hex (array, 20, hexkeygrip);
86 return 0;
91 /* Given the SLOT and the File ID FID, return the length of the
92 certificate contained in that file. Returns 0 if the file does not
93 exists or does not contain a certificate. If R_CERTOFF is not
94 NULL, the length the header will be stored at this address; thus to
95 parse the X.509 certificate a read should start at that offset.
97 On success the file is still selected.
99 size_t
100 app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff)
102 gpg_error_t err;
103 unsigned char *buffer;
104 const unsigned char *p;
105 size_t buflen, n;
106 int class, tag, constructed, ndef;
107 size_t resultlen, objlen, hdrlen;
109 err = iso7816_select_file (slot, fid, 0, NULL, NULL);
110 if (err)
112 log_info ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
113 return 0;
116 err = iso7816_read_binary (slot, 0, 32, &buffer, &buflen);
117 if (err)
119 log_info ("error reading certificate from FID 0x%04X: %s\n",
120 fid, gpg_strerror (err));
121 return 0;
124 if (!buflen || *buffer == 0xff)
126 log_info ("no certificate contained in FID 0x%04X\n", fid);
127 xfree (buffer);
128 return 0;
131 p = buffer;
132 n = buflen;
133 err = parse_ber_header (&p, &n, &class, &tag, &constructed,
134 &ndef, &objlen, &hdrlen);
135 if (err)
137 log_info ("error parsing certificate in FID 0x%04X: %s\n",
138 fid, gpg_strerror (err));
139 xfree (buffer);
140 return 0;
143 /* All certificates should commence with a SEQUENCE except for the
144 special ROOT CA which are enclosed in a SET. */
145 if ( !(class == CLASS_UNIVERSAL && constructed
146 && (tag == TAG_SEQUENCE || tag == TAG_SET)))
148 log_info ("data at FID 0x%04X does not look like a certificate\n", fid);
149 return 0;
152 resultlen = objlen + hdrlen;
153 if (r_certoff)
155 /* The callers want the offset to the actual certificate. */
156 *r_certoff = hdrlen;
158 err = parse_ber_header (&p, &n, &class, &tag, &constructed,
159 &ndef, &objlen, &hdrlen);
160 if (err)
161 return 0;
163 if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
165 /* The certificate seems to be contained in a
166 userCertificate container. Assume the following sequence
167 is the certificate. */
168 *r_certoff += hdrlen + objlen;
169 if (*r_certoff > resultlen)
171 *r_certoff = 0;
172 return 0; /* That should never happen. */
175 else
176 *r_certoff = 0;
179 return resultlen;