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
143 fingerprint. If R_HIGH is not NULL the next 4 bytes are stored
146 gpgsm_get_short_fingerprint (ksba_cert_t cert
, unsigned long *r_high
)
148 unsigned char digest
[20];
150 gpgsm_get_fingerprint (cert
, GCRY_MD_SHA1
, digest
, NULL
);
152 *r_high
= ((digest
[12]<<24)|(digest
[13]<<16)|(digest
[14]<< 8)|digest
[15]);
153 return ((digest
[16]<<24)|(digest
[17]<<16)|(digest
[18]<< 8)|digest
[19]);
157 /* Return the so called KEYGRIP which is the SHA-1 hash of the public
158 key parameters expressed as an canoncial encoded S-Exp. ARRAY must
159 be 20 bytes long. Returns ARRAY or a newly allocated buffer if ARRAY was
160 given as NULL. May return NULL on error. */
162 gpgsm_get_keygrip (ksba_cert_t cert
, unsigned char *array
)
169 p
= ksba_cert_get_public_key (cert
);
171 return NULL
; /* oops */
174 log_debug ("get_keygrip for public key\n");
175 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
178 log_error ("libksba did not return a proper S-Exp\n");
181 rc
= gcry_sexp_sscan ( &s_pkey
, NULL
, (char*)p
, n
);
185 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc
));
188 array
= gcry_pk_get_keygrip (s_pkey
, array
);
189 gcry_sexp_release (s_pkey
);
192 rc
= gpg_error (GPG_ERR_GENERAL
);
193 log_error ("can't calculate keygrip\n");
197 log_printhex ("keygrip=", array
, 20);
202 /* Return an allocated buffer with the keygrip of CERT encoded as a
203 hexstring. NULL is returned in case of error. */
205 gpgsm_get_keygrip_hexstring (ksba_cert_t cert
)
207 unsigned char grip
[20];
210 if (!gpgsm_get_keygrip (cert
, grip
))
212 buf
= xtrymalloc (20*2+1);
214 bin2hex (grip
, 20, buf
);
219 /* Return the PK algorithm used by CERT as well as the length in bits
220 of the public key at NBITS. */
222 gpgsm_get_key_algo_info (ksba_cert_t cert
, unsigned int *nbits
)
235 p
= ksba_cert_get_public_key (cert
);
238 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
244 rc
= gcry_sexp_sscan (&s_pkey
, NULL
, (char *)p
, n
);
250 *nbits
= gcry_pk_get_nbits (s_pkey
);
252 /* Breaking the algorithm out of the S-exp is a bit of a challenge ... */
253 l1
= gcry_sexp_find_token (s_pkey
, "public-key", 0);
256 gcry_sexp_release (s_pkey
);
259 l2
= gcry_sexp_cadr (l1
);
260 gcry_sexp_release (l1
);
262 name
= gcry_sexp_nth_data (l1
, 0, &n
);
265 if (n
> sizeof namebuf
-1)
266 n
= sizeof namebuf
-1;
267 memcpy (namebuf
, name
, n
);
272 gcry_sexp_release (l1
);
273 gcry_sexp_release (s_pkey
);
274 return gcry_pk_map_name (namebuf
);
280 /* For certain purposes we need a certificate id which has an upper
281 limit of the size. We use the hash of the issuer name and the
282 serial number for this. In most cases the serial number is not
283 that large and the resulting string can be passed on an assuan
284 command line. Everything is hexencoded with the serialnumber
285 delimited from the hash by a dot.
287 The caller must free the string.
290 gpgsm_get_certid (ksba_cert_t cert
)
295 unsigned char hash
[20];
300 p
= ksba_cert_get_issuer (cert
, 0);
302 return NULL
; /* Ooops: No issuer */
303 gcry_md_hash_buffer (GCRY_MD_SHA1
, hash
, p
, strlen (p
));
306 serial
= ksba_cert_get_serial (cert
);
308 return NULL
; /* oops: no serial number */
312 log_error ("Ooops: invalid serial number\n");
317 n
= strtoul (p
, &endp
, 10);
321 log_error ("Ooops: invalid serial number (no colon)\n");
327 certid
= xtrymalloc ( 40 + 1 + n
*2 + 1);
331 return NULL
; /* out of core */
334 for (i
=0, endp
= certid
; i
< 20; i
++, endp
+= 2 )
335 sprintf (endp
, "%02X", hash
[i
]);
337 for (i
=0; i
< n
; i
++, endp
+= 2)
338 sprintf (endp
, "%02X", ((unsigned char*)p
)[i
]);