Line | Count | Source |
1 | | /* keyid.c - key ID and fingerprint handling |
2 | | * Copyright (C) 1998, 1999, 2000, 2001, 2003, |
3 | | * 2004, 2006, 2010 Free Software Foundation, Inc. |
4 | | * Copyright (C) 2014 Werner Koch |
5 | | * Copyright (C) 2016, 2023 g10 Code GmbH |
6 | | * |
7 | | * This file is part of GnuPG. |
8 | | * |
9 | | * GnuPG is free software; you can redistribute it and/or modify |
10 | | * it under the terms of the GNU General Public License as published by |
11 | | * the Free Software Foundation; either version 3 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * GnuPG is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU General Public License |
20 | | * along with this program; if not, see <https://www.gnu.org/licenses/>. |
21 | | * SPDX-License-Identifier: GPL-3.0-or-later |
22 | | */ |
23 | | |
24 | | #include <config.h> |
25 | | #include <stdio.h> |
26 | | #include <stdlib.h> |
27 | | #include <string.h> |
28 | | #include <errno.h> |
29 | | #include <time.h> |
30 | | |
31 | | #include "gpg.h" |
32 | | #include "../common/util.h" |
33 | | #include "main.h" |
34 | | #include "packet.h" |
35 | | #include "options.h" |
36 | | #include "keydb.h" |
37 | | #include "../common/i18n.h" |
38 | | #include "rmd160.h" |
39 | | #include "../common/host2net.h" |
40 | | |
41 | | |
42 | 0 | #define KEYID_STR_SIZE 19 |
43 | | |
44 | | #ifdef HAVE_UNSIGNED_TIME_T |
45 | | # define IS_INVALID_TIME_T(a) ((a) == (time_t)(-1)) |
46 | | #else |
47 | | /* Error or 32 bit time_t and value after 2038-01-19. */ |
48 | 0 | # define IS_INVALID_TIME_T(a) ((a) < 0) |
49 | | #endif |
50 | | |
51 | | |
52 | | /* Return a letter describing the public key algorithms. */ |
53 | | int |
54 | | pubkey_letter( int algo ) |
55 | 0 | { |
56 | 0 | switch (algo) |
57 | 0 | { |
58 | 0 | case PUBKEY_ALGO_RSA: return 'R' ; |
59 | 0 | case PUBKEY_ALGO_RSA_E: return 'r' ; |
60 | 0 | case PUBKEY_ALGO_RSA_S: return 's' ; |
61 | 0 | case PUBKEY_ALGO_ELGAMAL_E: return 'g' ; |
62 | 0 | case PUBKEY_ALGO_ELGAMAL: return 'G' ; |
63 | 0 | case PUBKEY_ALGO_DSA: return 'D' ; |
64 | 0 | case PUBKEY_ALGO_ECDH: return 'e' ; /* ECC DH (encrypt only) */ |
65 | 0 | case PUBKEY_ALGO_ECDSA: return 'E' ; /* ECC DSA (sign only) */ |
66 | 0 | case PUBKEY_ALGO_EDDSA: return 'E' ; /* ECC EdDSA (sign only) */ |
67 | 0 | default: return '?'; |
68 | 0 | } |
69 | 0 | } |
70 | | |
71 | | /* Return a string describing the public key algorithm and the |
72 | | keysize. For elliptic curves the function prints the name of the |
73 | | curve because the keysize is a property of the curve. The string |
74 | | is copied to the supplied buffer up a length of BUFSIZE-1. |
75 | | Examples for the output are: |
76 | | |
77 | | "rsa3072" - RSA with 3072 bit |
78 | | "elg1024" - Elgamal with 1024 bit |
79 | | "ed25519" - EdDSA using the curve Ed25519. |
80 | | "cv25519" - ECDH using the curve X25519. |
81 | | "ky768_cv448 - Kyber-768 with X448 as second algo. |
82 | | "ky1024_bp512 - Kyber-1024 with BrainpoolP256r1 as second algo. |
83 | | "E_1.2.3.4" - ECC using the unsupported curve with OID "1.2.3.4". |
84 | | "unknown_N" - Unknown OpenPGP algorithm N. |
85 | | "E_1.3.6.1.4.1.11591.2.12242973" ECC with a bogus OID. |
86 | | |
87 | | Note that with Kyber we use "bp" as abbreviation for BrainpoolP and |
88 | | ignore the final r1 part. |
89 | | |
90 | | If the option --legacy-list-mode is active, the output use the |
91 | | legacy format: |
92 | | |
93 | | "3072R" - RSA with 3072 bit |
94 | | "1024g" - Elgamal with 1024 bit |
95 | | "256E" - ECDSA using a curve with 256 bit |
96 | | |
97 | | The macro PUBKEY_STRING_SIZE may be used to allocate a buffer with |
98 | | a suitable size. Note that a more general version of this function |
99 | | exists as get_keyalgo_string. However, that has no special |
100 | | treatment for the old and unsupported Elgamal which we here print as |
101 | | xxxNNNN. */ |
102 | | char * |
103 | | pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize) |
104 | 0 | { |
105 | 0 | const char *prefix = NULL; |
106 | 0 | int dual = 0; |
107 | 0 | char *curve; |
108 | 0 | const char *name; |
109 | |
|
110 | 0 | if (opt.legacy_list_mode) |
111 | 0 | { |
112 | 0 | snprintf (buffer, bufsize, "%4u%c", |
113 | 0 | nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo)); |
114 | 0 | return buffer; |
115 | 0 | } |
116 | | |
117 | 0 | switch (pk->pubkey_algo) |
118 | 0 | { |
119 | 0 | case PUBKEY_ALGO_RSA: |
120 | 0 | case PUBKEY_ALGO_RSA_E: |
121 | 0 | case PUBKEY_ALGO_RSA_S: prefix = "rsa"; break; |
122 | 0 | case PUBKEY_ALGO_ELGAMAL_E: prefix = "elg"; break; |
123 | 0 | case PUBKEY_ALGO_DSA: prefix = "dsa"; break; |
124 | 0 | case PUBKEY_ALGO_ELGAMAL: prefix = "xxx"; break; |
125 | 0 | case PUBKEY_ALGO_ECDH: |
126 | 0 | case PUBKEY_ALGO_ECDSA: |
127 | 0 | case PUBKEY_ALGO_EDDSA: prefix = ""; break; |
128 | 0 | case PUBKEY_ALGO_KYBER: prefix = "ky"; dual = 1; break; |
129 | 0 | case PUBKEY_ALGO_DIL3_25519: prefix = "dil3"; break; |
130 | 0 | case PUBKEY_ALGO_DIL5_448: prefix = "dil5"; break; |
131 | 0 | case PUBKEY_ALGO_SPHINX_SHA2: prefix = "sphinx_sha2"; break; |
132 | 0 | } |
133 | | |
134 | | |
135 | 0 | if (prefix && *prefix) |
136 | 0 | { |
137 | 0 | if (dual) |
138 | 0 | { |
139 | 0 | curve = openpgp_oid_to_str (pk->pkey[0]); |
140 | | /* Note that we prefer the abbreviated name of the curve. */ |
141 | 0 | name = openpgp_oid_to_curve (curve, 2); |
142 | 0 | if (!name) |
143 | 0 | name = "unknown"; |
144 | |
|
145 | 0 | snprintf (buffer, bufsize, "%s%u_%s", |
146 | 0 | prefix, nbits_from_pk (pk), name); |
147 | 0 | xfree (curve); |
148 | 0 | } |
149 | 0 | else |
150 | 0 | snprintf (buffer, bufsize, "%s%u", prefix, nbits_from_pk (pk)); |
151 | 0 | } |
152 | 0 | else if (prefix) |
153 | 0 | { |
154 | 0 | curve = openpgp_oid_to_str (pk->pkey[0]); |
155 | 0 | name = openpgp_oid_to_curve (curve, 0); |
156 | |
|
157 | 0 | if (name) |
158 | 0 | snprintf (buffer, bufsize, "%s", name); |
159 | 0 | else if (curve) |
160 | 0 | snprintf (buffer, bufsize, "E_%s", curve); |
161 | 0 | else |
162 | 0 | snprintf (buffer, bufsize, "E_error"); |
163 | 0 | xfree (curve); |
164 | 0 | } |
165 | 0 | else |
166 | 0 | snprintf (buffer, bufsize, "unknown_%u", (unsigned int)pk->pubkey_algo); |
167 | |
|
168 | 0 | return buffer; |
169 | 0 | } |
170 | | |
171 | | |
172 | | /* Helper for compare_pubkey_string. This skips leading spaces, |
173 | | * commas and optional condition operators and returns a pointer to |
174 | | * the first non-space character or NULL in case of an error. The |
175 | | * length of a prefix consisting of letters is then returned ar PFXLEN |
176 | | * and the value of the number (e.g. 384 for "brainpoolP384r1") at |
177 | | * NUMBER. R_LENGTH receives the entire length of the algorithm name |
178 | | * which is terminated by a space, nul, or a comma. If R_CONDITION is |
179 | | * not NULL, 0 is stored for a leading "=", 1 for a ">", 2 for a ">=", |
180 | | * -1 for a "<", and -2 for a "<=". If R_CONDITION is NULL no |
181 | | * condition prefix is allowed. */ |
182 | | static const char * |
183 | | parse_one_algo_string (const char *str, size_t *pfxlen, unsigned int *number, |
184 | | size_t *r_length, int *r_condition) |
185 | 0 | { |
186 | 0 | int condition = 0; |
187 | 0 | const char *result; |
188 | |
|
189 | 0 | while (spacep (str) || *str ==',') |
190 | 0 | str++; |
191 | 0 | if (!r_condition) |
192 | 0 | ; |
193 | 0 | else if (*str == '>' && str[1] == '=') |
194 | 0 | condition = 2, str += 2; |
195 | 0 | else if (*str == '>' ) |
196 | 0 | condition = 1, str += 1; |
197 | 0 | else if (*str == '<' && str[1] == '=') |
198 | 0 | condition = -2, str += 2; |
199 | 0 | else if (*str == '<') |
200 | 0 | condition = -1, str += 1; |
201 | 0 | else if (*str == '=') /* Default. */ |
202 | 0 | str += 1; |
203 | |
|
204 | 0 | if (!alphap (str)) |
205 | 0 | return NULL; /* Error. */ |
206 | | |
207 | 0 | *pfxlen = 1; |
208 | 0 | for (result = str++; alphap (str); str++) |
209 | 0 | ++*pfxlen; |
210 | 0 | while (*str == '-' || *str == '+') |
211 | 0 | str++; |
212 | 0 | *number = atoi (str); |
213 | 0 | while (*str && !spacep (str) && *str != ',') |
214 | 0 | str++; |
215 | |
|
216 | 0 | *r_length = str - result; |
217 | 0 | if (r_condition) |
218 | 0 | *r_condition = condition; |
219 | 0 | return result; |
220 | 0 | } |
221 | | |
222 | | |
223 | | /* Return an extra algo strength offset to handle peculiarities like |
224 | | * ed448 > ed25519. */ |
225 | | static size_t |
226 | | extra_algo_strength_offset (const char *string) |
227 | 0 | { |
228 | 0 | if (!string || !*string) |
229 | 0 | return 0; |
230 | 0 | if (!ascii_strcasecmp (string, "ed448")) |
231 | 0 | return 50000; /* (ed)50448 is larger (ed)25519. */ |
232 | 0 | if (!ascii_strcasecmp (string, "cv448")) |
233 | 0 | return 50000; /* (cv)50448 is larger (cv)25519. */ |
234 | 0 | return 0; |
235 | 0 | } |
236 | | |
237 | | |
238 | | |
239 | | /* Helper for compare_pubkey_string. If BPARSED is set to 0 on |
240 | | * return, an error in ASTR or BSTR was found and further checks are |
241 | | * not possible. */ |
242 | | static int |
243 | | compare_pubkey_string_part (const char *astr, const char *bstr_arg, |
244 | | size_t *bparsed) |
245 | 0 | { |
246 | 0 | const char *bstr = bstr_arg; |
247 | 0 | size_t alen, apfxlen, blen, bpfxlen; |
248 | 0 | unsigned int anumber, bnumber; |
249 | 0 | int condition; |
250 | |
|
251 | 0 | *bparsed = 0; |
252 | 0 | astr = parse_one_algo_string (astr, &apfxlen, &anumber, &alen, &condition); |
253 | 0 | if (!astr) |
254 | 0 | return 0; /* Invalid algorithm name. */ |
255 | 0 | anumber += extra_algo_strength_offset (astr); |
256 | 0 | bstr = parse_one_algo_string (bstr, &bpfxlen, &bnumber, &blen, &condition); |
257 | 0 | if (!bstr) |
258 | 0 | return 0; /* Invalid algorithm name. */ |
259 | 0 | bnumber += extra_algo_strength_offset (bstr); |
260 | 0 | *bparsed = blen + (bstr - bstr_arg); |
261 | 0 | if (apfxlen != bpfxlen || ascii_strncasecmp (astr, bstr, apfxlen)) |
262 | 0 | return 0; /* false. */ |
263 | 0 | switch (condition) |
264 | 0 | { |
265 | 0 | case 2: return anumber >= bnumber; |
266 | 0 | case 1: return anumber > bnumber; |
267 | 0 | case -1: return anumber < bnumber; |
268 | 0 | case -2: return anumber <= bnumber; |
269 | 0 | } |
270 | | |
271 | 0 | return alen == blen && !ascii_strncasecmp (astr, bstr, alen); |
272 | 0 | } |
273 | | |
274 | | |
275 | | /* Check whether ASTR matches the constraints given by BSTR. ASTR may |
276 | | * be any algo string like "rsa2048", "ed25519" and BSTR may be a |
277 | | * constraint which is in the simplest case just another algo string. |
278 | | * BSTR may have more that one string in which case they are comma |
279 | | * separated and any match will return true. It is possible to prefix |
280 | | * BSTR with ">", ">=", "<=", or "<". That prefix operator is applied |
281 | | * to the number part of the algorithm, i.e. the first sequence of |
282 | | * digits found before end-of-string or a comma. Examples: |
283 | | * |
284 | | * | ASTR | BSTR | result | |
285 | | * |----------+----------------------+--------| |
286 | | * | rsa2048 | rsa2048 | true | |
287 | | * | rsa2048 | >=rsa2048 | true | |
288 | | * | rsa2048 | >rsa2048 | false | |
289 | | * | ed25519 | >rsa1024 | false | |
290 | | * | ed25519 | ed25519 | true | |
291 | | * | nistp384 | >nistp256 | true | |
292 | | * | nistp521 | >=rsa3072, >nistp384 | true | |
293 | | */ |
294 | | int |
295 | | compare_pubkey_string (const char *astr, const char *bstr) |
296 | 0 | { |
297 | 0 | size_t bparsed; |
298 | 0 | int result; |
299 | |
|
300 | 0 | while (*bstr) |
301 | 0 | { |
302 | 0 | result = compare_pubkey_string_part (astr, bstr, &bparsed); |
303 | 0 | if (result) |
304 | 0 | return 1; |
305 | 0 | if (!bparsed) |
306 | 0 | return 0; /* Syntax error in ASTR or BSTR. */ |
307 | 0 | bstr += bparsed; |
308 | 0 | } |
309 | | |
310 | 0 | return 0; |
311 | 0 | } |
312 | | |
313 | | |
314 | | |
315 | | /* Hash a public key and allow to specify the to be used format. |
316 | | * Note that if the v5 format is requested for a v4 key, a 0x04 as |
317 | | * version is hashed instead of the 0x05. */ |
318 | | static void |
319 | | do_hash_public_key (gcry_md_hd_t md, PKT_public_key *pk, int use_v5) |
320 | 0 | { |
321 | 0 | unsigned int n; |
322 | 0 | unsigned int nn[PUBKEY_MAX_NPKEY]; |
323 | 0 | byte *pp[PUBKEY_MAX_NPKEY]; |
324 | 0 | int i; |
325 | 0 | unsigned int nbits; |
326 | 0 | size_t nbytes; |
327 | 0 | int npkey = pubkey_get_npkey (pk->pubkey_algo); |
328 | |
|
329 | 0 | n = use_v5? 10 : 6; |
330 | | /* FIXME: We can avoid the extra malloc by calling only the first |
331 | | mpi_print here which computes the required length and calling the |
332 | | real mpi_print only at the end. The speed advantage would only be |
333 | | for ECC (opaque MPIs) or if we could implement an mpi_print |
334 | | variant with a callback handler to do the hashing. */ |
335 | 0 | if (npkey==0 && pk->pkey[0] |
336 | 0 | && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE)) |
337 | 0 | { |
338 | 0 | pp[0] = gcry_mpi_get_opaque (pk->pkey[0], &nbits); |
339 | 0 | nn[0] = (nbits+7)/8; |
340 | 0 | n+=nn[0]; |
341 | 0 | } |
342 | 0 | else |
343 | 0 | { |
344 | 0 | for (i=0; i < npkey; i++ ) |
345 | 0 | { |
346 | 0 | if (!pk->pkey[i]) |
347 | 0 | { |
348 | | /* This case may only happen if the parsing of the MPI |
349 | | failed but the key was anyway created. May happen |
350 | | during "gpg KEYFILE". */ |
351 | 0 | pp[i] = NULL; |
352 | 0 | nn[i] = 0; |
353 | 0 | } |
354 | 0 | else if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2) |
355 | 0 | { |
356 | | /* Ugly: We need to re-construct the wire format of the |
357 | | * key parameter. It would be easier to use a second |
358 | | * index for pp and nn which we could bump independent of |
359 | | * i. */ |
360 | 0 | const char *p; |
361 | |
|
362 | 0 | p = gcry_mpi_get_opaque (pk->pkey[i], &nbits); |
363 | 0 | nn[i] = (nbits+7)/8; |
364 | 0 | pp[i] = xmalloc (4 + nn[i] + 1); |
365 | 0 | if (p) |
366 | 0 | { |
367 | 0 | pp[i][0] = nn[i] >> 24; |
368 | 0 | pp[i][1] = nn[i] >> 16; |
369 | 0 | pp[i][2] = nn[i] >> 8; |
370 | 0 | pp[i][3] = nn[i]; |
371 | 0 | memcpy (pp[i] + 4 , p, nn[i]); |
372 | 0 | nn[i] += 4; |
373 | 0 | } |
374 | 0 | else |
375 | 0 | pp[i] = NULL; |
376 | 0 | n += nn[i]; |
377 | 0 | } |
378 | 0 | else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE)) |
379 | 0 | { |
380 | 0 | const char *p; |
381 | 0 | int is_sos = 0; |
382 | |
|
383 | 0 | if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_USER2)) |
384 | 0 | is_sos = 2; |
385 | |
|
386 | 0 | p = gcry_mpi_get_opaque (pk->pkey[i], &nbits); |
387 | 0 | pp[i] = xmalloc ((nbits+7)/8 + is_sos); |
388 | 0 | if (p) |
389 | 0 | memcpy (pp[i] + is_sos, p, (nbits+7)/8); |
390 | 0 | else |
391 | 0 | pp[i] = NULL; |
392 | 0 | if (is_sos) |
393 | 0 | { |
394 | 0 | if (*p) |
395 | 0 | { |
396 | 0 | nbits = ((nbits + 7) / 8) * 8; |
397 | |
|
398 | 0 | if (nbits >= 8 && !(*p & 0x80)) |
399 | 0 | if (--nbits >= 7 && !(*p & 0x40)) |
400 | 0 | if (--nbits >= 6 && !(*p & 0x20)) |
401 | 0 | if (--nbits >= 5 && !(*p & 0x10)) |
402 | 0 | if (--nbits >= 4 && !(*p & 0x08)) |
403 | 0 | if (--nbits >= 3 && !(*p & 0x04)) |
404 | 0 | if (--nbits >= 2 && !(*p & 0x02)) |
405 | 0 | if (--nbits >= 1 && !(*p & 0x01)) |
406 | 0 | --nbits; |
407 | 0 | } |
408 | |
|
409 | 0 | pp[i][0] = (nbits >> 8); |
410 | 0 | pp[i][1] = nbits; |
411 | 0 | } |
412 | 0 | nn[i] = (nbits+7)/8 + is_sos; |
413 | 0 | n += nn[i]; |
414 | 0 | } |
415 | 0 | else |
416 | 0 | { |
417 | 0 | if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, |
418 | 0 | &nbytes, pk->pkey[i])) |
419 | 0 | BUG (); |
420 | 0 | pp[i] = xmalloc (nbytes); |
421 | 0 | if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes, |
422 | 0 | &nbytes, pk->pkey[i])) |
423 | 0 | BUG (); |
424 | 0 | nn[i] = nbytes; |
425 | 0 | n += nn[i]; |
426 | 0 | } |
427 | 0 | } |
428 | 0 | } |
429 | | |
430 | 0 | if (use_v5) |
431 | 0 | { |
432 | 0 | gcry_md_putc ( md, 0x9a ); /* ctb */ |
433 | 0 | gcry_md_putc ( md, n >> 24 ); /* 4 byte length header (upper bits) */ |
434 | 0 | gcry_md_putc ( md, n >> 16 ); |
435 | 0 | } |
436 | 0 | else |
437 | 0 | { |
438 | 0 | gcry_md_putc ( md, 0x99 ); /* ctb */ |
439 | 0 | } |
440 | 0 | gcry_md_putc ( md, n >> 8 ); /* lower bits of the length header. */ |
441 | 0 | gcry_md_putc ( md, n ); |
442 | 0 | gcry_md_putc ( md, pk->version ); |
443 | 0 | gcry_md_putc ( md, pk->timestamp >> 24 ); |
444 | 0 | gcry_md_putc ( md, pk->timestamp >> 16 ); |
445 | 0 | gcry_md_putc ( md, pk->timestamp >> 8 ); |
446 | 0 | gcry_md_putc ( md, pk->timestamp ); |
447 | |
|
448 | 0 | gcry_md_putc ( md, pk->pubkey_algo ); |
449 | |
|
450 | 0 | if (use_v5) /* Hash the 32 bit length */ |
451 | 0 | { |
452 | 0 | n -= 10; |
453 | 0 | gcry_md_putc ( md, n >> 24 ); |
454 | 0 | gcry_md_putc ( md, n >> 16 ); |
455 | 0 | gcry_md_putc ( md, n >> 8 ); |
456 | 0 | gcry_md_putc ( md, n ); |
457 | 0 | } |
458 | |
|
459 | 0 | if(npkey==0 && pk->pkey[0] |
460 | 0 | && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE)) |
461 | 0 | { |
462 | 0 | if (pp[0]) |
463 | 0 | gcry_md_write (md, pp[0], nn[0]); |
464 | 0 | } |
465 | 0 | else |
466 | 0 | { |
467 | 0 | for(i=0; i < npkey; i++ ) |
468 | 0 | { |
469 | 0 | if (pp[i]) |
470 | 0 | gcry_md_write ( md, pp[i], nn[i] ); |
471 | 0 | xfree(pp[i]); |
472 | 0 | } |
473 | 0 | } |
474 | 0 | } |
475 | | |
476 | | |
477 | | /* Hash a public key. This function is useful for v4 and v5 |
478 | | * fingerprints and for v3 or v4 key signing. */ |
479 | | void |
480 | | hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) |
481 | 0 | { |
482 | 0 | do_hash_public_key (md, pk, (pk->version == 5)); |
483 | 0 | } |
484 | | |
485 | | |
486 | | /* fixme: Check whether we can replace this function or if not |
487 | | describe why we need it. */ |
488 | | u32 |
489 | | v3_keyid (gcry_mpi_t a, u32 *ki) |
490 | 0 | { |
491 | 0 | byte *buffer, *p; |
492 | 0 | size_t nbytes; |
493 | |
|
494 | 0 | if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nbytes, a )) |
495 | 0 | BUG (); |
496 | | /* fixme: allocate it on the stack */ |
497 | 0 | buffer = xmalloc (nbytes); |
498 | 0 | if (gcry_mpi_print( GCRYMPI_FMT_USG, buffer, nbytes, NULL, a )) |
499 | 0 | BUG (); |
500 | 0 | if (nbytes < 8) /* oops */ |
501 | 0 | ki[0] = ki[1] = 0; |
502 | 0 | else |
503 | 0 | { |
504 | 0 | p = buffer + nbytes - 8; |
505 | 0 | ki[0] = buf32_to_u32 (p); |
506 | 0 | p += 4; |
507 | 0 | ki[1] = buf32_to_u32 (p); |
508 | 0 | } |
509 | 0 | xfree (buffer); |
510 | 0 | return ki[1]; |
511 | 0 | } |
512 | | |
513 | | |
514 | | /* Return PK's keyid. The memory is owned by PK. */ |
515 | | u32 * |
516 | | pk_keyid (PKT_public_key *pk) |
517 | 0 | { |
518 | 0 | keyid_from_pk (pk, NULL); |
519 | | |
520 | | /* Uncomment this for help tracking down bugs related to keyid or |
521 | | main_keyid not being set correctly. */ |
522 | | #if 0 |
523 | | if (! (pk->main_keyid[0] || pk->main_keyid[1])) |
524 | | log_bug ("pk->main_keyid not set!\n"); |
525 | | if (keyid_cmp (pk->keyid, pk->main_keyid) == 0 |
526 | | && ! pk->flags.primary) |
527 | | log_bug ("keyid and main_keyid are the same, but primary flag not set!\n"); |
528 | | if (keyid_cmp (pk->keyid, pk->main_keyid) != 0 |
529 | | && pk->flags.primary) |
530 | | log_bug ("keyid and main_keyid are different, but primary flag set!\n"); |
531 | | #endif |
532 | |
|
533 | 0 | return pk->keyid; |
534 | 0 | } |
535 | | |
536 | | /* Return the keyid of the primary key associated with PK. The memory |
537 | | is owned by PK. */ |
538 | | u32 * |
539 | | pk_main_keyid (PKT_public_key *pk) |
540 | 0 | { |
541 | | /* Uncomment this for help tracking down bugs related to keyid or |
542 | | main_keyid not being set correctly. */ |
543 | | #if 0 |
544 | | if (! (pk->main_keyid[0] || pk->main_keyid[1])) |
545 | | log_bug ("pk->main_keyid not set!\n"); |
546 | | #endif |
547 | |
|
548 | 0 | return pk->main_keyid; |
549 | 0 | } |
550 | | |
551 | | /* Copy the keyid in SRC to DEST and return DEST. */ |
552 | | u32 * |
553 | | keyid_copy (u32 *dest, const u32 *src) |
554 | 0 | { |
555 | 0 | dest[0] = src[0]; |
556 | 0 | dest[1] = src[1]; |
557 | 0 | return dest; |
558 | 0 | } |
559 | | |
560 | | char * |
561 | | format_keyid (u32 *keyid, int format, char *buffer, int len) |
562 | 67.8k | { |
563 | 67.8k | if (! buffer) |
564 | 0 | { |
565 | 0 | len = KEYID_STR_SIZE; |
566 | 0 | buffer = xtrymalloc (len); |
567 | 0 | if (!buffer) |
568 | 0 | return NULL; |
569 | 0 | } |
570 | | |
571 | 67.8k | if (format == KF_DEFAULT) |
572 | 0 | format = opt.keyid_format; |
573 | 67.8k | if (format == KF_DEFAULT) |
574 | 0 | format = KF_NONE; |
575 | | |
576 | 67.8k | switch (format) |
577 | 67.8k | { |
578 | 0 | case KF_NONE: |
579 | 0 | if (len) |
580 | 0 | *buffer = 0; |
581 | 0 | break; |
582 | | |
583 | 0 | case KF_SHORT: |
584 | 0 | snprintf (buffer, len, "%08lX", (ulong)keyid[1]); |
585 | 0 | break; |
586 | | |
587 | 67.8k | case KF_LONG: |
588 | 67.8k | snprintf (buffer, len, "%08lX%08lX", (ulong)keyid[0], (ulong)keyid[1]); |
589 | 67.8k | break; |
590 | | |
591 | 0 | case KF_0xSHORT: |
592 | 0 | snprintf (buffer, len, "0x%08lX", (ulong)keyid[1]); |
593 | 0 | break; |
594 | | |
595 | 0 | case KF_0xLONG: |
596 | 0 | snprintf (buffer, len, "0x%08lX%08lX", (ulong)keyid[0],(ulong)keyid[1]); |
597 | 0 | break; |
598 | | |
599 | 0 | default: |
600 | 0 | BUG(); |
601 | 67.8k | } |
602 | | |
603 | 67.8k | return buffer; |
604 | 67.8k | } |
605 | | |
606 | | size_t |
607 | | keystrlen(void) |
608 | 67.8k | { |
609 | 67.8k | int format = opt.keyid_format; |
610 | 67.8k | if (format == KF_DEFAULT) |
611 | 67.8k | format = KF_NONE; |
612 | | |
613 | 67.8k | switch(format) |
614 | 67.8k | { |
615 | 67.8k | case KF_NONE: |
616 | 67.8k | return 0; |
617 | | |
618 | 0 | case KF_SHORT: |
619 | 0 | return 8; |
620 | | |
621 | 0 | case KF_LONG: |
622 | 0 | return 16; |
623 | | |
624 | 0 | case KF_0xSHORT: |
625 | 0 | return 10; |
626 | | |
627 | 0 | case KF_0xLONG: |
628 | 0 | return 18; |
629 | | |
630 | 0 | default: |
631 | 0 | BUG(); |
632 | 67.8k | } |
633 | 67.8k | } |
634 | | |
635 | | |
636 | | const char * |
637 | | keystr (u32 *keyid) |
638 | 67.8k | { |
639 | 67.8k | static char keyid_str[KEYID_STR_SIZE]; |
640 | 67.8k | int format = opt.keyid_format; |
641 | | |
642 | 67.8k | if (format == KF_DEFAULT) |
643 | 67.8k | format = KF_NONE; |
644 | 67.8k | if (format == KF_NONE) |
645 | 67.8k | format = KF_LONG; |
646 | | |
647 | 67.8k | return format_keyid (keyid, format, keyid_str, sizeof (keyid_str)); |
648 | 67.8k | } |
649 | | |
650 | | /* This function returns the key id of the main and possible the |
651 | | * subkey as one string. It is used by error messages. */ |
652 | | const char * |
653 | | keystr_with_sub (u32 *main_kid, u32 *sub_kid) |
654 | 0 | { |
655 | 0 | static char buffer[KEYID_STR_SIZE+1+KEYID_STR_SIZE]; |
656 | 0 | char *p; |
657 | 0 | int format = opt.keyid_format; |
658 | |
|
659 | 0 | if (format == KF_NONE) |
660 | 0 | format = KF_LONG; |
661 | |
|
662 | 0 | format_keyid (main_kid, format, buffer, KEYID_STR_SIZE); |
663 | 0 | if (sub_kid) |
664 | 0 | { |
665 | 0 | p = buffer + strlen (buffer); |
666 | 0 | *p++ = '/'; |
667 | 0 | format_keyid (sub_kid, format, p, KEYID_STR_SIZE); |
668 | 0 | } |
669 | 0 | return buffer; |
670 | 0 | } |
671 | | |
672 | | |
673 | | const char * |
674 | | keystr_from_pk(PKT_public_key *pk) |
675 | 0 | { |
676 | 0 | keyid_from_pk(pk,NULL); |
677 | |
|
678 | 0 | return keystr(pk->keyid); |
679 | 0 | } |
680 | | |
681 | | |
682 | | const char * |
683 | | keystr_from_pk_with_sub (PKT_public_key *main_pk, PKT_public_key *sub_pk) |
684 | 0 | { |
685 | 0 | keyid_from_pk (main_pk, NULL); |
686 | 0 | if (sub_pk) |
687 | 0 | keyid_from_pk (sub_pk, NULL); |
688 | |
|
689 | 0 | return keystr_with_sub (main_pk->keyid, sub_pk? sub_pk->keyid:NULL); |
690 | 0 | } |
691 | | |
692 | | |
693 | | /* Return PK's key id as a string using the default format. PK owns |
694 | | the storage. */ |
695 | | const char * |
696 | | pk_keyid_str (PKT_public_key *pk) |
697 | 0 | { |
698 | 0 | return keystr (pk_keyid (pk)); |
699 | 0 | } |
700 | | |
701 | | |
702 | | const char * |
703 | | keystr_from_desc(KEYDB_SEARCH_DESC *desc) |
704 | 0 | { |
705 | 0 | switch(desc->mode) |
706 | 0 | { |
707 | 0 | case KEYDB_SEARCH_MODE_LONG_KID: |
708 | 0 | case KEYDB_SEARCH_MODE_SHORT_KID: |
709 | 0 | return keystr(desc->u.kid); |
710 | | |
711 | 0 | case KEYDB_SEARCH_MODE_FPR: |
712 | 0 | { |
713 | 0 | u32 keyid[2]; |
714 | |
|
715 | 0 | if (desc->fprlen == 32) |
716 | 0 | { |
717 | 0 | keyid[0] = buf32_to_u32 (desc->u.fpr); |
718 | 0 | keyid[1] = buf32_to_u32 (desc->u.fpr+4); |
719 | 0 | } |
720 | 0 | else if (desc->fprlen == 20) |
721 | 0 | { |
722 | 0 | keyid[0] = buf32_to_u32 (desc->u.fpr+12); |
723 | 0 | keyid[1] = buf32_to_u32 (desc->u.fpr+16); |
724 | 0 | } |
725 | 0 | else if (desc->fprlen == 16) |
726 | 0 | return "?v3 fpr?"; |
727 | 0 | else /* oops */ |
728 | 0 | return "?vx fpr?"; |
729 | 0 | return keystr(keyid); |
730 | 0 | } |
731 | | |
732 | 0 | default: |
733 | 0 | BUG(); |
734 | 0 | } |
735 | 0 | } |
736 | | |
737 | | |
738 | | /* Compute the fingerprint and keyid and store it in PK. */ |
739 | | static void |
740 | | compute_fingerprint (PKT_public_key *pk) |
741 | 0 | { |
742 | 0 | const byte *dp; |
743 | 0 | gcry_md_hd_t md; |
744 | 0 | size_t len; |
745 | |
|
746 | 0 | if (gcry_md_open (&md, pk->version == 5 ? GCRY_MD_SHA256 : GCRY_MD_SHA1, 0)) |
747 | 0 | BUG (); |
748 | 0 | hash_public_key (md, pk); |
749 | 0 | gcry_md_final (md); |
750 | 0 | dp = gcry_md_read (md, 0); |
751 | 0 | len = gcry_md_get_algo_dlen (gcry_md_get_algo (md)); |
752 | 0 | log_assert (len <= MAX_FINGERPRINT_LEN); |
753 | 0 | memcpy (pk->fpr, dp, len); |
754 | 0 | pk->fprlen = len; |
755 | 0 | if (pk->version == 5) |
756 | 0 | { |
757 | 0 | pk->keyid[0] = buf32_to_u32 (dp); |
758 | 0 | pk->keyid[1] = buf32_to_u32 (dp+4); |
759 | 0 | } |
760 | 0 | else |
761 | 0 | { |
762 | 0 | pk->keyid[0] = buf32_to_u32 (dp+12); |
763 | 0 | pk->keyid[1] = buf32_to_u32 (dp+16); |
764 | 0 | } |
765 | 0 | gcry_md_close( md); |
766 | 0 | } |
767 | | |
768 | | |
769 | | /* |
770 | | * Get the keyid from the public key PK and store it at KEYID unless |
771 | | * this is NULL. Returns the 32 bit short keyid. |
772 | | */ |
773 | | u32 |
774 | | keyid_from_pk (PKT_public_key *pk, u32 *keyid) |
775 | 0 | { |
776 | 0 | u32 dummy_keyid[2]; |
777 | |
|
778 | 0 | if (!keyid) |
779 | 0 | keyid = dummy_keyid; |
780 | |
|
781 | 0 | if (!pk->fprlen) |
782 | 0 | compute_fingerprint (pk); |
783 | |
|
784 | 0 | keyid[0] = pk->keyid[0]; |
785 | 0 | keyid[1] = pk->keyid[1]; |
786 | |
|
787 | 0 | if (pk->fprlen == 32) |
788 | 0 | return keyid[0]; |
789 | 0 | else |
790 | 0 | return keyid[1]; |
791 | 0 | } |
792 | | |
793 | | |
794 | | /* |
795 | | * Get the keyid from the fingerprint. This function is simple for |
796 | | * most keys, but has to do a key lookup for old v3 keys where the |
797 | | * keyid is not part of the fingerprint. |
798 | | */ |
799 | | u32 |
800 | | keyid_from_fingerprint (ctrl_t ctrl, const byte *fpr, size_t fprlen, u32 *keyid) |
801 | 0 | { |
802 | 0 | u32 dummy_keyid[2]; |
803 | |
|
804 | 0 | if( !keyid ) |
805 | 0 | keyid = dummy_keyid; |
806 | |
|
807 | 0 | if (fprlen != 20 && fprlen != 32) |
808 | 0 | { |
809 | | /* This is special as we have to lookup the key first. */ |
810 | 0 | PKT_public_key pk; |
811 | 0 | int rc; |
812 | |
|
813 | 0 | memset (&pk, 0, sizeof pk); |
814 | 0 | rc = get_pubkey_byfpr (ctrl, &pk, NULL, fpr, fprlen); |
815 | 0 | if( rc ) |
816 | 0 | { |
817 | 0 | log_printhex (fpr, fprlen, |
818 | 0 | "Oops: keyid_from_fingerprint: no pubkey; fpr:"); |
819 | 0 | keyid[0] = 0; |
820 | 0 | keyid[1] = 0; |
821 | 0 | } |
822 | 0 | else |
823 | 0 | keyid_from_pk (&pk, keyid); |
824 | 0 | } |
825 | 0 | else |
826 | 0 | { |
827 | 0 | const byte *dp = fpr; |
828 | 0 | if (fprlen == 20) /* v4 key */ |
829 | 0 | { |
830 | 0 | keyid[0] = buf32_to_u32 (dp+12); |
831 | 0 | keyid[1] = buf32_to_u32 (dp+16); |
832 | 0 | } |
833 | 0 | else /* v5 key */ |
834 | 0 | { |
835 | 0 | keyid[0] = buf32_to_u32 (dp); |
836 | 0 | keyid[1] = buf32_to_u32 (dp+4); |
837 | 0 | } |
838 | 0 | } |
839 | |
|
840 | 0 | return keyid[1]; |
841 | 0 | } |
842 | | |
843 | | |
844 | | u32 |
845 | | keyid_from_sig (PKT_signature *sig, u32 *keyid) |
846 | 0 | { |
847 | 0 | if( keyid ) |
848 | 0 | { |
849 | 0 | keyid[0] = sig->keyid[0]; |
850 | 0 | keyid[1] = sig->keyid[1]; |
851 | 0 | } |
852 | 0 | return sig->keyid[1]; /*FIXME:shortkeyid*/ |
853 | 0 | } |
854 | | |
855 | | |
856 | | byte * |
857 | | namehash_from_uid (PKT_user_id *uid) |
858 | 0 | { |
859 | 0 | if (!uid->namehash) |
860 | 0 | { |
861 | 0 | uid->namehash = xmalloc (20); |
862 | |
|
863 | 0 | if (uid->attrib_data) |
864 | 0 | rmd160_hash_buffer (uid->namehash, uid->attrib_data, uid->attrib_len); |
865 | 0 | else |
866 | 0 | rmd160_hash_buffer (uid->namehash, uid->name, uid->len); |
867 | 0 | } |
868 | |
|
869 | 0 | return uid->namehash; |
870 | 0 | } |
871 | | |
872 | | |
873 | | /* |
874 | | * Return the number of bits used in PK. For Kyber we return the |
875 | | * octet count of the Kyber part and not of the ECC (thus likely |
876 | | * values are 768 or 1024). Note that this function may be called |
877 | | * with only pubkey_algo and pkey[] correctly set. |
878 | | */ |
879 | | unsigned int |
880 | | nbits_from_pk (PKT_public_key *pk) |
881 | 0 | { |
882 | 0 | if (pk->pubkey_algo == PUBKEY_ALGO_KYBER) |
883 | 0 | { |
884 | 0 | unsigned int nbits; |
885 | 0 | if (!gcry_mpi_get_opaque (pk->pkey[2], &nbits)) |
886 | 0 | return 0; |
887 | 0 | switch (nbits/8) |
888 | 0 | { |
889 | 0 | case 800: nbits = 512; break; |
890 | 0 | case 1184: nbits = 768; break; |
891 | 0 | case 1568: nbits = 1024; break; |
892 | 0 | default: nbits = 0; break; /* Unknown version. */ |
893 | 0 | } |
894 | 0 | return nbits; |
895 | 0 | } |
896 | 0 | else |
897 | 0 | return pubkey_nbits (pk->pubkey_algo, pk->pkey); |
898 | 0 | } |
899 | | |
900 | | |
901 | | /* Convert an UTC TIMESTAMP into an UTC yyyy-mm-dd string. Return |
902 | | * that string. The caller should pass a buffer with at least a size |
903 | | * of MK_DATESTR_SIZE. */ |
904 | | char * |
905 | | mk_datestr (char *buffer, size_t bufsize, u32 timestamp) |
906 | 0 | { |
907 | 0 | time_t atime = timestamp; |
908 | 0 | struct tm *tp; |
909 | |
|
910 | 0 | if (IS_INVALID_TIME_T (atime)) |
911 | 0 | strcpy (buffer, "????" "-??" "-??"); /* Mark this as invalid. */ |
912 | 0 | else |
913 | 0 | { |
914 | 0 | tp = gmtime (&atime); |
915 | 0 | snprintf (buffer, bufsize, "%04d-%02d-%02d", |
916 | 0 | 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); |
917 | 0 | } |
918 | 0 | return buffer; |
919 | 0 | } |
920 | | |
921 | | |
922 | | /* |
923 | | * return a string with the creation date of the pk |
924 | | * Note: this is alloced in a static buffer. |
925 | | * Format is: yyyy-mm-dd |
926 | | */ |
927 | | const char * |
928 | | dateonlystr_from_pk (PKT_public_key *pk) |
929 | 0 | { |
930 | 0 | static char buffer[MK_DATESTR_SIZE]; |
931 | |
|
932 | 0 | return mk_datestr (buffer, sizeof buffer, pk->timestamp); |
933 | 0 | } |
934 | | |
935 | | |
936 | | /* Same as dateonlystr_from_pk but with a global option a full iso |
937 | | * timestamp is returned. In this case it shares a static buffer with |
938 | | * isotimestamp(). */ |
939 | | const char * |
940 | | datestr_from_pk (PKT_public_key *pk) |
941 | 0 | { |
942 | 0 | if (opt.flags.full_timestrings) |
943 | 0 | return isotimestamp (pk->timestamp); |
944 | 0 | else |
945 | 0 | return dateonlystr_from_pk (pk); |
946 | 0 | } |
947 | | |
948 | | |
949 | | const char * |
950 | | dateonlystr_from_sig (PKT_signature *sig ) |
951 | 0 | { |
952 | 0 | static char buffer[MK_DATESTR_SIZE]; |
953 | |
|
954 | 0 | return mk_datestr (buffer, sizeof buffer, sig->timestamp); |
955 | 0 | } |
956 | | |
957 | | const char * |
958 | | datestr_from_sig (PKT_signature *sig ) |
959 | 0 | { |
960 | 0 | if (opt.flags.full_timestrings) |
961 | 0 | return isotimestamp (sig->timestamp); |
962 | 0 | else |
963 | 0 | return dateonlystr_from_sig (sig); |
964 | 0 | } |
965 | | |
966 | | |
967 | | const char * |
968 | | expirestr_from_pk (PKT_public_key *pk) |
969 | 0 | { |
970 | 0 | static char buffer[MK_DATESTR_SIZE]; |
971 | |
|
972 | 0 | if (!pk->expiredate) |
973 | 0 | return _("never "); |
974 | | |
975 | 0 | if (opt.flags.full_timestrings) |
976 | 0 | return isotimestamp (pk->expiredate); |
977 | | |
978 | 0 | return mk_datestr (buffer, sizeof buffer, pk->expiredate); |
979 | 0 | } |
980 | | |
981 | | |
982 | | const char * |
983 | | expirestr_from_sig (PKT_signature *sig) |
984 | 0 | { |
985 | 0 | static char buffer[MK_DATESTR_SIZE]; |
986 | |
|
987 | 0 | if (!sig->expiredate) |
988 | 0 | return _("never "); |
989 | | |
990 | 0 | if (opt.flags.full_timestrings) |
991 | 0 | return isotimestamp (sig->expiredate); |
992 | | |
993 | 0 | return mk_datestr (buffer, sizeof buffer, sig->expiredate); |
994 | 0 | } |
995 | | |
996 | | |
997 | | const char * |
998 | | revokestr_from_pk( PKT_public_key *pk ) |
999 | 0 | { |
1000 | 0 | static char buffer[MK_DATESTR_SIZE]; |
1001 | |
|
1002 | 0 | if(!pk->revoked.date) |
1003 | 0 | return _("never "); |
1004 | | |
1005 | 0 | if (opt.flags.full_timestrings) |
1006 | 0 | return isotimestamp (pk->revoked.date); |
1007 | | |
1008 | 0 | return mk_datestr (buffer, sizeof buffer, pk->revoked.date); |
1009 | 0 | } |
1010 | | |
1011 | | |
1012 | | const char * |
1013 | | usagestr_from_pk (PKT_public_key *pk, int fill) |
1014 | 0 | { |
1015 | 0 | static char buffer[10]; |
1016 | 0 | int i = 0; |
1017 | 0 | unsigned int use = pk->pubkey_usage; |
1018 | |
|
1019 | 0 | if ( use & PUBKEY_USAGE_SIG ) |
1020 | 0 | buffer[i++] = 'S'; |
1021 | |
|
1022 | 0 | if ( use & PUBKEY_USAGE_CERT ) |
1023 | 0 | buffer[i++] = 'C'; |
1024 | |
|
1025 | 0 | if ( use & PUBKEY_USAGE_ENC ) |
1026 | 0 | buffer[i++] = 'E'; |
1027 | |
|
1028 | 0 | if ( (use & PUBKEY_USAGE_AUTH) ) |
1029 | 0 | buffer[i++] = 'A'; |
1030 | |
|
1031 | 0 | if ( (use & PUBKEY_USAGE_RENC) ) |
1032 | 0 | buffer[i++] = 'R'; |
1033 | 0 | if ( (use & PUBKEY_USAGE_TIME) ) |
1034 | 0 | buffer[i++] = 'T'; |
1035 | 0 | if ( (use & PUBKEY_USAGE_GROUP) ) |
1036 | 0 | buffer[i++] = 'G'; |
1037 | |
|
1038 | 0 | while (fill && i < 4) |
1039 | 0 | buffer[i++] = ' '; |
1040 | |
|
1041 | 0 | buffer[i] = 0; |
1042 | 0 | return buffer; |
1043 | 0 | } |
1044 | | |
1045 | | |
1046 | | const char * |
1047 | | colon_strtime (u32 t) |
1048 | 0 | { |
1049 | 0 | static char buf[20]; |
1050 | |
|
1051 | 0 | if (!t) |
1052 | 0 | return ""; |
1053 | 0 | snprintf (buf, sizeof buf, "%lu", (ulong)t); |
1054 | 0 | return buf; |
1055 | 0 | } |
1056 | | |
1057 | | const char * |
1058 | | colon_datestr_from_pk (PKT_public_key *pk) |
1059 | 0 | { |
1060 | 0 | static char buf[20]; |
1061 | |
|
1062 | 0 | snprintf (buf, sizeof buf, "%lu", (ulong)pk->timestamp); |
1063 | 0 | return buf; |
1064 | 0 | } |
1065 | | |
1066 | | |
1067 | | const char * |
1068 | | colon_datestr_from_sig (PKT_signature *sig) |
1069 | 0 | { |
1070 | 0 | static char buf[20]; |
1071 | |
|
1072 | 0 | snprintf (buf, sizeof buf, "%lu", (ulong)sig->timestamp); |
1073 | 0 | return buf; |
1074 | 0 | } |
1075 | | |
1076 | | const char * |
1077 | | colon_expirestr_from_sig (PKT_signature *sig) |
1078 | 0 | { |
1079 | 0 | static char buf[20]; |
1080 | |
|
1081 | 0 | if (!sig->expiredate) |
1082 | 0 | return ""; |
1083 | | |
1084 | 0 | snprintf (buf, sizeof buf,"%lu", (ulong)sig->expiredate); |
1085 | 0 | return buf; |
1086 | 0 | } |
1087 | | |
1088 | | |
1089 | | |
1090 | | /* |
1091 | | * Return a byte array with the fingerprint for the given PK/SK |
1092 | | * The length of the array is returned in ret_len. Caller must free |
1093 | | * the array or provide an array of length MAX_FINGERPRINT_LEN. |
1094 | | */ |
1095 | | byte * |
1096 | | fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) |
1097 | 0 | { |
1098 | 0 | if (!pk->fprlen) |
1099 | 0 | compute_fingerprint (pk); |
1100 | |
|
1101 | 0 | if (!array) |
1102 | 0 | array = xmalloc (pk->fprlen); |
1103 | 0 | memcpy (array, pk->fpr, pk->fprlen); |
1104 | |
|
1105 | 0 | if (ret_len) |
1106 | 0 | *ret_len = pk->fprlen; |
1107 | 0 | return array; |
1108 | 0 | } |
1109 | | |
1110 | | |
1111 | | /* |
1112 | | * Return a byte array with the fingerprint for the given PK/SK The |
1113 | | * length of the array is returned in ret_len. Caller must free the |
1114 | | * array or provide an array of length MAX_FINGERPRINT_LEN. This |
1115 | | * version creates a v5 fingerprint even for v4 keys. |
1116 | | */ |
1117 | | byte * |
1118 | | v5_fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) |
1119 | 0 | { |
1120 | 0 | const byte *dp; |
1121 | 0 | gcry_md_hd_t md; |
1122 | |
|
1123 | 0 | if (pk->version == 5) |
1124 | 0 | return fingerprint_from_pk (pk, array, ret_len); |
1125 | | |
1126 | 0 | if (gcry_md_open (&md, GCRY_MD_SHA256, 0)) |
1127 | 0 | BUG (); |
1128 | 0 | do_hash_public_key (md, pk, 1); |
1129 | 0 | gcry_md_final (md); |
1130 | 0 | dp = gcry_md_read (md, 0); |
1131 | 0 | if (!array) |
1132 | 0 | array = xmalloc (32); |
1133 | 0 | memcpy (array, dp, 32); |
1134 | 0 | gcry_md_close (md); |
1135 | |
|
1136 | 0 | if (ret_len) |
1137 | 0 | *ret_len = 32; |
1138 | 0 | return array; |
1139 | 0 | } |
1140 | | |
1141 | | |
1142 | | /* |
1143 | | * This is the core of fpr20_from_pk which directly takes a |
1144 | | * fingerprint and its length instead of the public key. See below |
1145 | | * for details. |
1146 | | */ |
1147 | | void |
1148 | | fpr20_from_fpr (const byte *fpr, unsigned int fprlen, byte array[20]) |
1149 | 0 | { |
1150 | 0 | if (fprlen >= 32) /* v5 fingerprint (or larger) */ |
1151 | 0 | { |
1152 | 0 | memcpy (array + 0, fpr + 20, 4); |
1153 | 0 | memcpy (array + 4, fpr + 24, 4); |
1154 | 0 | memcpy (array + 8, fpr + 28, 4); |
1155 | 0 | memcpy (array + 12, fpr + 0, 4); /* kid[0] */ |
1156 | 0 | memcpy (array + 16, fpr + 4, 4); /* kid[1] */ |
1157 | 0 | } |
1158 | 0 | else if (fprlen == 20) /* v4 fingerprint */ |
1159 | 0 | memcpy (array, fpr, 20); |
1160 | 0 | else /* v3 or too short: fill up with zeroes. */ |
1161 | 0 | { |
1162 | 0 | memset (array, 0, 20); |
1163 | 0 | memcpy (array, fpr, fprlen); |
1164 | 0 | } |
1165 | 0 | } |
1166 | | |
1167 | | |
1168 | | /* |
1169 | | * Get FPR20 for the given PK/SK into ARRAY. |
1170 | | * |
1171 | | * FPR20 is special form of fingerprint of length 20 for the record of |
1172 | | * trustdb. For v4key, having fingerprint with SHA-1, FPR20 is the |
1173 | | * same one. For v5key, FPR20 is constructed from its fingerprint |
1174 | | * with SHA-2, so that its kid of last 8-byte can be as same as |
1175 | | * kid of v5key fingerprint. |
1176 | | * |
1177 | | */ |
1178 | | void |
1179 | | fpr20_from_pk (PKT_public_key *pk, byte array[20]) |
1180 | 0 | { |
1181 | 0 | if (!pk->fprlen) |
1182 | 0 | compute_fingerprint (pk); |
1183 | |
|
1184 | 0 | fpr20_from_fpr (pk->fpr, pk->fprlen, array); |
1185 | 0 | } |
1186 | | |
1187 | | |
1188 | | /* Return an allocated buffer with the fingerprint of PK formatted as |
1189 | | * a plain hexstring. If BUFFER is NULL the result is a malloc'd |
1190 | | * string. If BUFFER is not NULL the result will be copied into this |
1191 | | * buffer. In the latter case BUFLEN describes the length of the |
1192 | | * buffer; if this is too short the function terminates the process. |
1193 | | * Returns a malloc'ed string or BUFFER. A suitable length for BUFFER |
1194 | | * is (2*MAX_FINGERPRINT_LEN + 1). */ |
1195 | | char * |
1196 | | hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen) |
1197 | 0 | { |
1198 | 0 | if (!pk->fprlen) |
1199 | 0 | compute_fingerprint (pk); |
1200 | |
|
1201 | 0 | if (!buffer) |
1202 | 0 | { |
1203 | 0 | buffer = xtrymalloc (2 * pk->fprlen + 1); |
1204 | 0 | if (!buffer) |
1205 | 0 | return NULL; |
1206 | 0 | } |
1207 | 0 | else if (buflen < 2 * pk->fprlen + 1) |
1208 | 0 | log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen); |
1209 | | |
1210 | 0 | bin2hex (pk->fpr, pk->fprlen, buffer); |
1211 | 0 | return buffer; |
1212 | 0 | } |
1213 | | |
1214 | | |
1215 | | /* Same as hexfingerprint but returns a v5 fingerprint also for a v4 |
1216 | | * key. */ |
1217 | | char * |
1218 | | v5hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen) |
1219 | 0 | { |
1220 | 0 | char fprbuf[32]; |
1221 | |
|
1222 | 0 | if (pk->version == 5) |
1223 | 0 | return hexfingerprint (pk, buffer, buflen); |
1224 | | |
1225 | 0 | if (!buffer) |
1226 | 0 | { |
1227 | 0 | buffer = xtrymalloc (2 * 32 + 1); |
1228 | 0 | if (!buffer) |
1229 | 0 | return NULL; |
1230 | 0 | } |
1231 | 0 | else if (buflen < 2 * 32 + 1) |
1232 | 0 | log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen); |
1233 | | |
1234 | 0 | v5_fingerprint_from_pk (pk, fprbuf, NULL); |
1235 | 0 | return bin2hex (fprbuf, 32, buffer); |
1236 | 0 | } |
1237 | | |
1238 | | |
1239 | | /* Pretty print a hex fingerprint. If BUFFER is NULL the result is a |
1240 | | malloc'd string. If BUFFER is not NULL the result will be copied |
1241 | | into this buffer. In the latter case BUFLEN describes the length |
1242 | | of the buffer; if this is too short the function terminates the |
1243 | | process. Returns a malloc'ed string or BUFFER. A suitable length |
1244 | | for BUFFER is (MAX_FORMATTED_FINGERPRINT_LEN + 1). */ |
1245 | | char * |
1246 | | format_hexfingerprint (const char *fingerprint, char *buffer, size_t buflen) |
1247 | 0 | { |
1248 | 0 | int hexlen = strlen (fingerprint); |
1249 | 0 | int space; |
1250 | 0 | int i, j; |
1251 | |
|
1252 | 0 | if (hexlen == 40) /* v4 fingerprint */ |
1253 | 0 | { |
1254 | 0 | space = (/* The characters and the NUL. */ |
1255 | 0 | 40 + 1 |
1256 | | /* After every fourth character, we add a space (except |
1257 | | the last). */ |
1258 | 0 | + 40 / 4 - 1 |
1259 | | /* Half way through we add a second space. */ |
1260 | 0 | + 1); |
1261 | 0 | } |
1262 | 0 | else if (hexlen == 64 || hexlen == 50) /* v5 fingerprint */ |
1263 | 0 | { |
1264 | | /* The v5 fingerprint is commonly printed truncated to 25 |
1265 | | * octets. We accept the truncated as well as the full hex |
1266 | | * version here and format it like this: |
1267 | | * 19347 BC987 24640 25F99 DF3EC 2E000 0ED98 84892 E1F7B 3EA4C |
1268 | | */ |
1269 | 0 | hexlen = 50; |
1270 | 0 | space = 10 * 5 + 9 + 1; |
1271 | 0 | } |
1272 | 0 | else /* Other fingerprint versions - print as is. */ |
1273 | 0 | { |
1274 | | /* We truncated here so that we do not need to provide a buffer |
1275 | | * of a length which is in reality never used. */ |
1276 | 0 | if (hexlen > MAX_FORMATTED_FINGERPRINT_LEN - 1) |
1277 | 0 | hexlen = MAX_FORMATTED_FINGERPRINT_LEN - 1; |
1278 | 0 | space = hexlen + 1; |
1279 | 0 | } |
1280 | |
|
1281 | 0 | if (!buffer) |
1282 | 0 | buffer = xmalloc (space); |
1283 | 0 | else if (buflen < space) |
1284 | 0 | log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen); |
1285 | | |
1286 | 0 | if (hexlen == 40) /* v4 fingerprint */ |
1287 | 0 | { |
1288 | 0 | for (i = 0, j = 0; i < 40; i ++) |
1289 | 0 | { |
1290 | 0 | if (i && !(i % 4)) |
1291 | 0 | buffer[j ++] = ' '; |
1292 | 0 | if (i == 40 / 2) |
1293 | 0 | buffer[j ++] = ' '; |
1294 | |
|
1295 | 0 | buffer[j ++] = fingerprint[i]; |
1296 | 0 | } |
1297 | 0 | buffer[j ++] = 0; |
1298 | 0 | log_assert (j == space); |
1299 | 0 | } |
1300 | 0 | else if (hexlen == 50) /* v5 fingerprint */ |
1301 | 0 | { |
1302 | 0 | for (i=j=0; i < 50; i++) |
1303 | 0 | { |
1304 | 0 | if (i && !(i % 5)) |
1305 | 0 | buffer[j++] = ' '; |
1306 | 0 | buffer[j++] = fingerprint[i]; |
1307 | 0 | } |
1308 | 0 | buffer[j++] = 0; |
1309 | 0 | log_assert (j == space); |
1310 | 0 | } |
1311 | 0 | else |
1312 | 0 | { |
1313 | 0 | mem2str (buffer, fingerprint, space); |
1314 | 0 | } |
1315 | | |
1316 | 0 | return buffer; |
1317 | 0 | } |
1318 | | |
1319 | | |
1320 | | |
1321 | | /* Return the so called KEYGRIP which is the SHA-1 hash of the public |
1322 | | * key parameters expressed as an canonical encoded S-Exp. ARRAY must |
1323 | | * be 20 bytes long. Returns 0 on success or an error code. If |
1324 | | * GET_SECOND Is one and PK has dual algorithm, the keygrip of the |
1325 | | * second algorithm is return; GPG_ERR_FALSE is returned if the algo |
1326 | | * is not a dual algorithm. */ |
1327 | | gpg_error_t |
1328 | | keygrip_from_pk (PKT_public_key *pk, unsigned char *array, int get_second) |
1329 | 0 | { |
1330 | 0 | gpg_error_t err; |
1331 | 0 | gcry_sexp_t s_pkey; |
1332 | |
|
1333 | 0 | if (DBG_PACKET) |
1334 | 0 | log_debug ("get_keygrip for public key%s\n", get_second?" (second)":""); |
1335 | |
|
1336 | 0 | if (get_second && pk->pubkey_algo != PUBKEY_ALGO_KYBER) |
1337 | 0 | return gpg_error (GPG_ERR_FALSE); |
1338 | | |
1339 | 0 | switch (pk->pubkey_algo) |
1340 | 0 | { |
1341 | 0 | case GCRY_PK_DSA: |
1342 | 0 | err = gcry_sexp_build (&s_pkey, NULL, |
1343 | 0 | "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", |
1344 | 0 | pk->pkey[0], pk->pkey[1], |
1345 | 0 | pk->pkey[2], pk->pkey[3]); |
1346 | 0 | break; |
1347 | | |
1348 | 0 | case GCRY_PK_ELG: |
1349 | 0 | case GCRY_PK_ELG_E: |
1350 | 0 | err = gcry_sexp_build (&s_pkey, NULL, |
1351 | 0 | "(public-key(elg(p%m)(g%m)(y%m)))", |
1352 | 0 | pk->pkey[0], pk->pkey[1], pk->pkey[2]); |
1353 | 0 | break; |
1354 | | |
1355 | 0 | case GCRY_PK_RSA: |
1356 | 0 | case GCRY_PK_RSA_S: |
1357 | 0 | case GCRY_PK_RSA_E: |
1358 | 0 | err = gcry_sexp_build (&s_pkey, NULL, |
1359 | 0 | "(public-key(rsa(n%m)(e%m)))", |
1360 | 0 | pk->pkey[0], pk->pkey[1]); |
1361 | 0 | break; |
1362 | | |
1363 | 0 | case PUBKEY_ALGO_EDDSA: |
1364 | 0 | case PUBKEY_ALGO_ECDSA: |
1365 | 0 | case PUBKEY_ALGO_ECDH: |
1366 | 0 | { |
1367 | 0 | char *curve = openpgp_oid_to_str (pk->pkey[0]); |
1368 | 0 | if (!curve) |
1369 | 0 | err = gpg_error_from_syserror (); |
1370 | 0 | else |
1371 | 0 | { |
1372 | 0 | err = gcry_sexp_build (&s_pkey, NULL, |
1373 | 0 | pk->pubkey_algo == PUBKEY_ALGO_EDDSA? |
1374 | 0 | "(public-key(ecc(curve%s)(flags eddsa)(q%m)))": |
1375 | 0 | (pk->pubkey_algo == PUBKEY_ALGO_ECDH |
1376 | 0 | && openpgp_oid_is_cv25519 (pk->pkey[0]))? |
1377 | 0 | "(public-key(ecc(curve%s)(flags djb-tweak)(q%m)))": |
1378 | 0 | "(public-key(ecc(curve%s)(q%m)))", |
1379 | 0 | curve, pk->pkey[1]); |
1380 | 0 | xfree (curve); |
1381 | 0 | } |
1382 | 0 | } |
1383 | 0 | break; |
1384 | | |
1385 | 0 | case PUBKEY_ALGO_KYBER: |
1386 | 0 | if (get_second) |
1387 | 0 | { |
1388 | 0 | char tmpname[15]; |
1389 | |
|
1390 | 0 | snprintf (tmpname, sizeof tmpname, "kyber%u", nbits_from_pk (pk)); |
1391 | 0 | err = gcry_sexp_build (&s_pkey, NULL, |
1392 | 0 | "(public-key(%s(p%m)))", |
1393 | 0 | tmpname, pk->pkey[2]); |
1394 | 0 | } |
1395 | 0 | else |
1396 | 0 | { |
1397 | 0 | char *curve = openpgp_oid_to_str (pk->pkey[0]); |
1398 | 0 | if (!curve) |
1399 | 0 | err = gpg_error_from_syserror (); |
1400 | 0 | else |
1401 | 0 | { |
1402 | 0 | err = gcry_sexp_build (&s_pkey, NULL, |
1403 | 0 | openpgp_oid_is_cv25519 (pk->pkey[0]) |
1404 | 0 | ? "(public-key(ecc(curve%s)(flags djb-tweak)(q%m)))" |
1405 | 0 | : "(public-key(ecc(curve%s)(q%m)))", |
1406 | 0 | curve, pk->pkey[1]); |
1407 | 0 | xfree (curve); |
1408 | 0 | } |
1409 | 0 | } |
1410 | 0 | break; |
1411 | | |
1412 | 0 | default: |
1413 | 0 | err = gpg_error (GPG_ERR_PUBKEY_ALGO); |
1414 | 0 | break; |
1415 | 0 | } |
1416 | | |
1417 | 0 | if (err) |
1418 | 0 | return err; |
1419 | | |
1420 | 0 | if (!gcry_pk_get_keygrip (s_pkey, array)) |
1421 | 0 | { |
1422 | 0 | char *hexfpr; |
1423 | |
|
1424 | 0 | hexfpr = hexfingerprint (pk, NULL, 0); |
1425 | 0 | log_info ("error computing keygrip (fpr=%s)\n", hexfpr); |
1426 | 0 | xfree (hexfpr); |
1427 | |
|
1428 | 0 | memset (array, 0, 20); |
1429 | 0 | err = gpg_error (GPG_ERR_GENERAL); |
1430 | 0 | } |
1431 | 0 | else |
1432 | 0 | { |
1433 | 0 | if (DBG_PACKET) |
1434 | 0 | log_printhex (array, 20, "keygrip="); |
1435 | | /* FIXME: Save the keygrip in PK. */ |
1436 | 0 | } |
1437 | 0 | gcry_sexp_release (s_pkey); |
1438 | |
|
1439 | 0 | return err; |
1440 | 0 | } |
1441 | | |
1442 | | |
1443 | | /* Store an allocated buffer with the keygrip of PK encoded as a |
1444 | | * hexstring at r_GRIP. Returns 0 on success. For dual algorithms |
1445 | | * the keygrips are delimited by a comma. */ |
1446 | | gpg_error_t |
1447 | | hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip) |
1448 | 0 | { |
1449 | 0 | gpg_error_t err; |
1450 | 0 | char *buf; |
1451 | 0 | unsigned char grip[KEYGRIP_LEN]; |
1452 | 0 | unsigned char grip2[KEYGRIP_LEN]; |
1453 | |
|
1454 | 0 | *r_grip = NULL; |
1455 | 0 | err = keygrip_from_pk (pk, grip, 0); |
1456 | 0 | if (!err) |
1457 | 0 | { |
1458 | 0 | if (pk->pubkey_algo == PUBKEY_ALGO_KYBER) |
1459 | 0 | { |
1460 | 0 | err = keygrip_from_pk (pk, grip2, 1); |
1461 | 0 | if (err) |
1462 | 0 | goto leave; |
1463 | 0 | buf = xtrymalloc (2 * KEYGRIP_LEN * 2 + 1 + 1); |
1464 | 0 | } |
1465 | 0 | else |
1466 | 0 | buf = xtrymalloc (KEYGRIP_LEN * 2 + 1); |
1467 | | |
1468 | 0 | if (!buf) |
1469 | 0 | { |
1470 | 0 | err = gpg_error_from_syserror (); |
1471 | 0 | goto leave; |
1472 | 0 | } |
1473 | | |
1474 | 0 | bin2hex (grip, KEYGRIP_LEN, buf); |
1475 | 0 | if (pk->pubkey_algo == PUBKEY_ALGO_KYBER) |
1476 | 0 | { |
1477 | 0 | buf[2*KEYGRIP_LEN] = ','; |
1478 | 0 | bin2hex (grip2, KEYGRIP_LEN, buf+2*KEYGRIP_LEN+1); |
1479 | 0 | } |
1480 | 0 | *r_grip = buf; |
1481 | 0 | } |
1482 | 0 | leave: |
1483 | 0 | return err; |
1484 | 0 | } |
1485 | | |
1486 | | |
1487 | | /* Return a hexfied malloced string of the ECDH parameters for an ECDH |
1488 | | * key from the public key PK. Returns NULL on error. */ |
1489 | | char * |
1490 | | ecdh_param_str_from_pk (PKT_public_key *pk) |
1491 | 0 | { |
1492 | 0 | const unsigned char *s; |
1493 | 0 | unsigned int n; |
1494 | |
|
1495 | 0 | if (!pk |
1496 | 0 | || pk->pubkey_algo != PUBKEY_ALGO_ECDH |
1497 | 0 | || !gcry_mpi_get_flag (pk->pkey[2], GCRYMPI_FLAG_OPAQUE) |
1498 | 0 | || !(s = gcry_mpi_get_opaque (pk->pkey[2], &n)) || !n) |
1499 | 0 | { |
1500 | 0 | gpg_err_set_errno (EINVAL); |
1501 | 0 | return NULL; /* Invalid parameter */ |
1502 | 0 | } |
1503 | | |
1504 | 0 | n = (n+7)/8; |
1505 | | return bin2hex (s, n, NULL); |
1506 | 0 | } |