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/>.
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
45 gpgsm_get_fingerprint (ksba_cert_t cert
, int algo
,
46 unsigned char *array
, int *r_len
)
54 len
= gcry_md_get_algo_dlen (algo
);
57 array
= xmalloc (len
);
62 /* Fist check whether we have cached the fingerprint. */
63 if (algo
== GCRY_MD_SHA1
)
68 if (!ksba_cert_get_user_data (cert
, "sha1-fingerprint",
74 /* No, need to compute it. */
75 rc
= gcry_md_open (&md
, algo
, 0);
78 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
79 memset (array
, 0xff, len
); /* better return an invalid fpr than NULL */
83 rc
= ksba_cert_hash (cert
, 0, HASH_FNC
, md
);
86 log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc
));
88 memset (array
, 0xff, len
); /* better return an invalid fpr than NULL */
92 memcpy (array
, gcry_md_read(md
, algo
), len
);
95 /* Cache an SHA-1 fingerprint. */
96 if ( algo
== GCRY_MD_SHA1
)
97 ksba_cert_set_user_data (cert
, "sha1-fingerprint", array
, 20);
103 /* Return an allocated buffer with the formatted fingerprint */
105 gpgsm_get_fingerprint_string (ksba_cert_t cert
, int algo
)
107 unsigned char digest
[MAX_DIGEST_LEN
];
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
);
122 /* Return an allocated buffer with the formatted fingerprint as one
125 gpgsm_get_fingerprint_hexstring (ksba_cert_t cert
, int algo
)
127 unsigned char digest
[MAX_DIGEST_LEN
];
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
);
142 /* Return a certificate ID. These are the last 4 bytes of the SHA-1
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. */
159 gpgsm_get_keygrip (ksba_cert_t cert
, unsigned char *array
)
166 p
= ksba_cert_get_public_key (cert
);
168 return NULL
; /* oops */
171 log_debug ("get_keygrip for public key\n");
172 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
175 log_error ("libksba did not return a proper S-Exp\n");
178 rc
= gcry_sexp_sscan ( &s_pkey
, NULL
, (char*)p
, n
);
182 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc
));
185 array
= gcry_pk_get_keygrip (s_pkey
, array
);
186 gcry_sexp_release (s_pkey
);
189 rc
= gpg_error (GPG_ERR_GENERAL
);
190 log_error ("can't calculate keygrip\n");
194 log_printhex ("keygrip=", array
, 20);
199 /* Return an allocated buffer with the keygrip of CERT encoded as a
200 hexstring. NULL is returned in case of error. */
202 gpgsm_get_keygrip_hexstring (ksba_cert_t cert
)
204 unsigned char grip
[20];
207 if (!gpgsm_get_keygrip (cert
, grip
))
209 buf
= xtrymalloc (20*2+1);
211 bin2hex (grip
, 20, 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
)
232 p
= ksba_cert_get_public_key (cert
);
235 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
241 rc
= gcry_sexp_sscan (&s_pkey
, NULL
, (char *)p
, n
);
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);
253 gcry_sexp_release (s_pkey
);
256 l2
= gcry_sexp_cadr (l1
);
257 gcry_sexp_release (l1
);
259 name
= gcry_sexp_nth_data (l1
, 0, &n
);
262 if (n
> sizeof namebuf
-1)
263 n
= sizeof namebuf
-1;
264 memcpy (namebuf
, name
, n
);
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.
287 gpgsm_get_certid (ksba_cert_t cert
)
292 unsigned char hash
[20];
297 p
= ksba_cert_get_issuer (cert
, 0);
299 return NULL
; /* Ooops: No issuer */
300 gcry_md_hash_buffer (GCRY_MD_SHA1
, hash
, p
, strlen (p
));
303 serial
= ksba_cert_get_serial (cert
);
305 return NULL
; /* oops: no serial number */
309 log_error ("Ooops: invalid serial number\n");
314 n
= strtoul (p
, &endp
, 10);
318 log_error ("Ooops: invalid serial number (no colon)\n");
324 certid
= xtrymalloc ( 40 + 1 + n
*2 + 1);
328 return NULL
; /* out of core */
331 for (i
=0, endp
= certid
; i
< 20; i
++, endp
+= 2 )
332 sprintf (endp
, "%02X", hash
[i
]);
334 for (i
=0; i
< n
; i
++, endp
+= 2)
335 sprintf (endp
, "%02X", ((unsigned char*)p
)[i
]);