Add server option with-ephemeral-keys.
[gnupg.git] / sm / fingerprint.c
blobaddf562967e2a466e39ba5ce1699c112c6ffcd98
1 /* fingerprint.c - Get the fingerprint
2 * Copyright (C) 2001 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 <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <time.h>
27 #include <assert.h>
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <ksba.h>
34 /* Return the fingerprint of the certificate (we can't put this into
35 libksba because we need libgcrypt support). The caller must
36 provide an array of sufficient length or NULL so that the function
37 allocates the array. If r_len is not NULL, the length of the
38 digest is returned; well, this can also be done by using
39 gcry_md_get_algo_dlen(). If algo is 0, a SHA-1 will be used.
41 If there is a problem , the function does never return NULL but a
42 digest of all 0xff.
44 unsigned char *
45 gpgsm_get_fingerprint (ksba_cert_t cert, int algo,
46 unsigned char *array, int *r_len)
48 gcry_md_hd_t md;
49 int rc, len;
51 if (!algo)
52 algo = GCRY_MD_SHA1;
54 len = gcry_md_get_algo_dlen (algo);
55 assert (len);
56 if (!array)
57 array = xmalloc (len);
59 if (r_len)
60 *r_len = len;
62 /* Fist check whether we have cached the fingerprint. */
63 if (algo == GCRY_MD_SHA1)
65 size_t buflen;
67 assert (len >= 20);
68 if (!ksba_cert_get_user_data (cert, "sha1-fingerprint",
69 array, len, &buflen)
70 && buflen == 20)
71 return array;
74 /* No, need to compute it. */
75 rc = gcry_md_open (&md, algo, 0);
76 if (rc)
78 log_error ("md_open failed: %s\n", gpg_strerror (rc));
79 memset (array, 0xff, len); /* better return an invalid fpr than NULL */
80 return array;
83 rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
84 if (rc)
86 log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
87 gcry_md_close (md);
88 memset (array, 0xff, len); /* better return an invalid fpr than NULL */
89 return array;
91 gcry_md_final (md);
92 memcpy (array, gcry_md_read(md, algo), len );
93 gcry_md_close (md);
95 /* Cache an SHA-1 fingerprint. */
96 if ( algo == GCRY_MD_SHA1 )
97 ksba_cert_set_user_data (cert, "sha1-fingerprint", array, 20);
99 return array;
103 /* Return an allocated buffer with the formatted fingerprint */
104 char *
105 gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo)
107 unsigned char digest[MAX_DIGEST_LEN];
108 char *buf;
109 int len;
111 if (!algo)
112 algo = GCRY_MD_SHA1;
114 len = gcry_md_get_algo_dlen (algo);
115 assert (len <= MAX_DIGEST_LEN );
116 gpgsm_get_fingerprint (cert, algo, digest, NULL);
117 buf = xmalloc (len*3+1);
118 bin2hexcolon (digest, len, buf);
119 return buf;
122 /* Return an allocated buffer with the formatted fingerprint as one
123 large hexnumber */
124 char *
125 gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo)
127 unsigned char digest[MAX_DIGEST_LEN];
128 char *buf;
129 int len;
131 if (!algo)
132 algo = GCRY_MD_SHA1;
134 len = gcry_md_get_algo_dlen (algo);
135 assert (len <= MAX_DIGEST_LEN );
136 gpgsm_get_fingerprint (cert, algo, digest, NULL);
137 buf = xmalloc (len*2+1);
138 bin2hex (digest, len, buf);
139 return buf;
142 /* Return a certificate ID. These are the last 4 bytes of the SHA-1
143 fingerprint. */
144 unsigned long
145 gpgsm_get_short_fingerprint (ksba_cert_t cert)
147 unsigned char digest[20];
149 gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL);
150 return ((digest[16]<<24)|(digest[17]<<16)|(digest[18]<< 8)|digest[19]);
154 /* Return the so called KEYGRIP which is the SHA-1 hash of the public
155 key parameters expressed as an canoncial encoded S-Exp. ARRAY must
156 be 20 bytes long. Returns ARRAY or a newly allocated buffer if ARRAY was
157 given as NULL. May return NULL on error. */
158 unsigned char *
159 gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array)
161 gcry_sexp_t s_pkey;
162 int rc;
163 ksba_sexp_t p;
164 size_t n;
166 p = ksba_cert_get_public_key (cert);
167 if (!p)
168 return NULL; /* oops */
170 if (DBG_X509)
171 log_debug ("get_keygrip for public key\n");
172 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
173 if (!n)
175 log_error ("libksba did not return a proper S-Exp\n");
176 return NULL;
178 rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
179 xfree (p);
180 if (rc)
182 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
183 return NULL;
185 array = gcry_pk_get_keygrip (s_pkey, array);
186 gcry_sexp_release (s_pkey);
187 if (!array)
189 rc = gpg_error (GPG_ERR_GENERAL);
190 log_error ("can't calculate keygrip\n");
191 return NULL;
193 if (DBG_X509)
194 log_printhex ("keygrip=", array, 20);
196 return array;
199 /* Return an allocated buffer with the keygrip of CERT encoded as a
200 hexstring. NULL is returned in case of error. */
201 char *
202 gpgsm_get_keygrip_hexstring (ksba_cert_t cert)
204 unsigned char grip[20];
205 char *buf;
207 if (!gpgsm_get_keygrip (cert, grip))
208 return NULL;
209 buf = xtrymalloc (20*2+1);
210 if (buf)
211 bin2hex (grip, 20, buf);
212 return buf;
216 /* Return the PK algorithm used by CERT as well as the length in bits
217 of the public key at NBITS. */
219 gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits)
221 gcry_sexp_t s_pkey;
222 int rc;
223 ksba_sexp_t p;
224 size_t n;
225 gcry_sexp_t l1, l2;
226 const char *name;
227 char namebuf[128];
229 if (nbits)
230 *nbits = 0;
232 p = ksba_cert_get_public_key (cert);
233 if (!p)
234 return 0;
235 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
236 if (!n)
238 xfree (p);
239 return 0;
241 rc = gcry_sexp_sscan (&s_pkey, NULL, (char *)p, n);
242 xfree (p);
243 if (rc)
244 return 0;
246 if (nbits)
247 *nbits = gcry_pk_get_nbits (s_pkey);
249 /* Breaking the algorithm out of the S-exp is a bit of a challenge ... */
250 l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
251 if (!l1)
253 gcry_sexp_release (s_pkey);
254 return 0;
256 l2 = gcry_sexp_cadr (l1);
257 gcry_sexp_release (l1);
258 l1 = l2;
259 name = gcry_sexp_nth_data (l1, 0, &n);
260 if (name)
262 if (n > sizeof namebuf -1)
263 n = sizeof namebuf -1;
264 memcpy (namebuf, name, n);
265 namebuf[n] = 0;
267 else
268 *namebuf = 0;
269 gcry_sexp_release (l1);
270 gcry_sexp_release (s_pkey);
271 return gcry_pk_map_name (namebuf);
277 /* For certain purposes we need a certificate id which has an upper
278 limit of the size. We use the hash of the issuer name and the
279 serial number for this. In most cases the serial number is not
280 that large and the resulting string can be passed on an assuan
281 command line. Everything is hexencoded with the serialnumber
282 delimited from the hash by a dot.
284 The caller must free the string.
286 char *
287 gpgsm_get_certid (ksba_cert_t cert)
289 ksba_sexp_t serial;
290 char *p;
291 char *endp;
292 unsigned char hash[20];
293 unsigned long n;
294 char *certid;
295 int i;
297 p = ksba_cert_get_issuer (cert, 0);
298 if (!p)
299 return NULL; /* Ooops: No issuer */
300 gcry_md_hash_buffer (GCRY_MD_SHA1, hash, p, strlen (p));
301 xfree (p);
303 serial = ksba_cert_get_serial (cert);
304 if (!serial)
305 return NULL; /* oops: no serial number */
306 p = (char *)serial;
307 if (*p != '(')
309 log_error ("Ooops: invalid serial number\n");
310 xfree (serial);
311 return NULL;
313 p++;
314 n = strtoul (p, &endp, 10);
315 p = endp;
316 if (*p != ':')
318 log_error ("Ooops: invalid serial number (no colon)\n");
319 xfree (serial);
320 return NULL;
322 p++;
324 certid = xtrymalloc ( 40 + 1 + n*2 + 1);
325 if (!certid)
327 xfree (serial);
328 return NULL; /* out of core */
331 for (i=0, endp = certid; i < 20; i++, endp += 2 )
332 sprintf (endp, "%02X", hash[i]);
333 *endp++ = '.';
334 for (i=0; i < n; i++, endp += 2)
335 sprintf (endp, "%02X", ((unsigned char*)p)[i]);
336 *endp = 0;
338 xfree (serial);
339 return certid;