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