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/>.
27 #include "app-common.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
36 app_help_count_bits (const unsigned char *a
, size_t len
)
38 unsigned int n
= len
* 8;
44 for (; len
&& !*a
; len
--, a
++, n
-=8)
48 for (i
=7; i
&& !(*a
& (1<<i
)); i
--)
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
59 app_help_get_keygrip_string (ksba_cert_t cert
, char *hexkeygrip
)
65 unsigned char array
[20];
67 p
= ksba_cert_get_public_key (cert
);
69 return gpg_error (GPG_ERR_BUG
);
70 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
72 return gpg_error (GPG_ERR_INV_SEXP
);
73 err
= gcry_sexp_sscan (&s_pkey
, NULL
, (char*)p
, n
);
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
);
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.
100 app_help_read_length_of_cert (int slot
, int fid
, size_t *r_certoff
)
103 unsigned char *buffer
;
104 const unsigned char *p
;
106 int class, tag
, constructed
, ndef
;
107 size_t resultlen
, objlen
, hdrlen
;
109 err
= iso7816_select_file (slot
, fid
, 0, NULL
, NULL
);
112 log_info ("error selecting FID 0x%04X: %s\n", fid
, gpg_strerror (err
));
116 err
= iso7816_read_binary (slot
, 0, 32, &buffer
, &buflen
);
119 log_info ("error reading certificate from FID 0x%04X: %s\n",
120 fid
, gpg_strerror (err
));
124 if (!buflen
|| *buffer
== 0xff)
126 log_info ("no certificate contained in FID 0x%04X\n", fid
);
133 err
= parse_ber_header (&p
, &n
, &class, &tag
, &constructed
,
134 &ndef
, &objlen
, &hdrlen
);
137 log_info ("error parsing certificate in FID 0x%04X: %s\n",
138 fid
, gpg_strerror (err
));
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
);
152 resultlen
= objlen
+ hdrlen
;
155 /* The callers want the offset to the actual certificate. */
158 err
= parse_ber_header (&p
, &n
, &class, &tag
, &constructed
,
159 &ndef
, &objlen
, &hdrlen
);
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
)
172 return 0; /* That should never happen. */