rpm  5.4.15
rpmgc.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmiotypes.h>
8 #include <rpmmacro.h>
9 #include <rpmlog.h> /* XXX should crypto wrappers use rpmlog? */
10 
11 #define _RPMGC_INTERNAL
12 #if defined(WITH_GCRYPT)
13 #define _RPMPGP_INTERNAL
14 #include <rpmgc.h>
15 #endif
16 
17 #include "debug.h"
18 
19 #if defined(WITH_GCRYPT)
20 
21 /*@access pgpDig @*/
22 /*@access pgpDigParams @*/
23 
24 /*@-redecl@*/
25 /*@unchecked@*/
26 extern int _pgp_debug;
27 
28 /*@unchecked@*/
29 extern int _pgp_print;
30 /*@=redecl@*/
31 
32 /*@unchecked@*/
33 static int _rpmgc_debug;
34 
35 #define SPEW(_t, _rc, _dig) \
36  { if ((_t) || _rpmgc_debug || _pgp_debug < 0) \
37  fprintf(stderr, "<-- %s(%p) %s\t%s/%s\n", __FUNCTION__, (_dig), \
38  ((_rc) ? "OK" : "BAD"), (_dig)->pubkey_algoN, (_dig)->hash_algoN); \
39  }
40 
46 static
47 unsigned char nibble(char c)
48  /*@*/
49 {
50  if (c >= '0' && c <= '9')
51  return (unsigned char) (c - '0');
52  if (c >= 'A' && c <= 'F')
53  return (unsigned char)((int)(c - 'A') + 10);
54  if (c >= 'a' && c <= 'f')
55  return (unsigned char)((int)(c - 'a') + 10);
56  return (unsigned char) '\0';
57 }
58 
59 /*==============================================================*/
60 #ifdef UNUSED
61 /* Swiped (and largely rewritten) from LGPL gnupg/common/openpgp-oid.c */
62 
63 /* Helper for openpgp_oid_from_str. */
64 static size_t
65 make_flagged_int(unsigned long value, unsigned char * b, size_t nb)
66 {
67  int more = 0;
68  int shift;
69 
70  /* fixme: figure out the number of bits in an ulong and start with
71  that value as shift (after making it a multiple of 7) a more
72  straigtforward implementation is to do it in reverse order using
73  a temporary buffer - saves a lot of compares */
74  for (more = 0, shift = 28; shift > 0; shift -= 7) {
75  if (more || value >= (1UL << shift)) {
76  b[nb++] = 0x80 | (value >> shift);
77  value -= (value >> shift) << shift;
78  more = 1;
79  }
80  }
81  b[nb++] = value;
82  return nb;
83 }
84 
85 /*
86  * Convert the OID given in dotted decimal form in STRING to an DER
87  * encoding and store it as an opaque value at R_MPI. The format of
88  * the DER encoded is not a regular ASN.1 object but the modified
89  * format as used by OpenPGP for the ECC curve description. On error
90  * the function returns and error code an NULL is stored at R_BUG.
91  * Note that scanning STRING stops at the first white space
92  * character.
93  */
94 static
95 int openpgp_oid_from_str(const char * s, gcry_mpi_t * r_mpi)
96 {
97  const char * se = s;
98  size_t ns = (s ? strlen(s) : 0);
99  unsigned char * b = xmalloc(ns + 2 + 1);
100  size_t nb = 1; /* count the length byte */
101  const char *endp;
102  unsigned long val;
103  unsigned long val1 = 0;
104  int arcno = 0;
105  int rc = -1; /* assume failure */
106 
107  *r_mpi = NULL;
108 
109  if (s == NULL || s[0] == '\0')
110  goto exit;
111 
112  do {
113  arcno++;
114  val = strtoul(se, (char **) &endp, 10);
115  if (!xisdigit(*se) || !(*endp == '.' || *endp == '\0'))
116  goto exit;
117 
118  if (*endp == '.')
119  se = endp + 1;
120 
121  switch (arcno) {
122  case 1:
123  if (val > 2) /* Not allowed. */
124  goto exit;
125  val1 = val;
126  break;
127  case 2: /* Combine the 1st 2 arcs into octet. */
128  if (val1 < 2) {
129  if (val > 39)
130  goto exit;
131  b[nb++] = val1 * 40 + val;
132  } else {
133  val += 80;
134  nb = make_flagged_int(val, b, nb);
135  }
136  break;
137  default:
138  nb = make_flagged_int(val, b, nb);
139  break;
140  }
141  } while (*endp == '.');
142 
143  if (arcno == 1 || nb < 2 || nb > 254) /* Can't encode 1st arc. */
144  goto exit;
145 
146  *b = nb - 1;
147  *r_mpi = gcry_mpi_set_opaque(NULL, b, nb * 8);
148  if (*r_mpi) /* Success? */
149  rc = 0;
150 
151 exit:
152  if (rc)
153  b = _free(b);
154  return rc;
155 }
156 
157 /*
158  * Return a malloced string represenation of the OID in the opaque MPI
159  * A. In case of an error NULL is returned and ERRNO is set.
160  */
161 static
162 char *openpgp_oid_to_str(gcry_mpi_t a)
163 {
164  unsigned int nbits = 0;
165  const unsigned char * b = (a && gcry_mpi_get_flag(a, GCRYMPI_FLAG_OPAQUE))
166  ? gcry_mpi_get_opaque(a, &nbits)
167  : NULL;
168  size_t nb = (nbits + 7) / 8;
169  /* 2 chars in prefix, (3+1) decimalchars/byte, trailing NUL, skip length */
170  size_t nt = (2 + ((nb ? nb-1 : 0) * (3+1)) + 1);
171  char *t = xmalloc(nt);
172  char *te = t;
173  size_t ix = 0;
174  unsigned long valmask = (unsigned long) 0xfe << (8 * (sizeof(valmask) - 1));
175  unsigned long val;
176 
177  *te = '\0';
178 
179  /* Check oid consistency, skipping the length byte. */
180  if (b == NULL || nb == 0 || *b++ != --nb)
181  goto invalid;
182 
183  /* Add the prefix and decode the 1st byte */
184  if (b[ix] < 40)
185  te += sprintf(te, "0.%d", b[ix]);
186  else if (b[ix] < 80)
187  te += sprintf(te, "1.%d", b[ix] - 40);
188  else {
189  val = b[ix] & 0x7f;
190  while ((b[ix] & 0x80) && ++ix < nb) {
191  if ((val & valmask))
192  goto overflow;
193  val <<= 7;
194  val |= b[ix] & 0x7f;
195  }
196  val -= 80;
197  te += sprintf(te, "2.%lu", val);
198  }
199  *te = '\0';
200 
201  /* Append the (dotted) oid integers */
202  for (ix++; ix < nb; ix++) {
203  val = b[ix] & 0x7f;
204  while ((b[ix] & 0x80) && ++ix < nb) {
205  if ((val & valmask))
206  goto overflow;
207  val <<= 7;
208  val |= b[ix] & 0x7f;
209  }
210  te += sprintf(te, ".%lu", val);
211  }
212  *te = '\0';
213  goto exit;
214 
215 overflow:
216  /*
217  * Return a special OID (gnu.gnupg.badoid) to indicate the error
218  * case. The OID is broken and thus we return one which can't do
219  * any harm. Formally this does not need to be a bad OID but an OID
220  * with an arc that can't be represented in a 32 bit word is more
221  * than likely corrupt.
222  */
223  t = _free(t);
224  t = xstrdup("1.3.6.1.4.1.11591.2.12242973");
225  goto exit;
226 
227 invalid:
228  errno = EINVAL;
229  t = _free(t);
230  goto exit;
231 
232 exit:
233  return t;
234 }
235 #endif /* UNUSED */
236 
237 /*==============================================================*/
238 
239 static void fail(const char *format, ...)
240 {
241  va_list arg_ptr;
242 
243  va_start(arg_ptr, format);
244  vfprintf(stderr, format, arg_ptr);
245  va_end(arg_ptr);
247 }
248 
249 static
250 void rpmgcDump(const char * msg, gcry_sexp_t sexp)
251  /*@*/
252 {
253  if (_rpmgc_debug || _pgp_debug) {
254  size_t nb = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
255  char * buf = (char *) alloca(nb+1);
256 
257  nb = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buf, nb);
258  buf[nb] = '\0';
259  fprintf(stderr, "========== %s:\n%s", msg, buf);
260  }
261  return;
262 }
263 
264 static
265 gcry_error_t rpmgcErr(rpmgc gc, const char * msg, gcry_error_t err)
266  /*@*/
267 {
268  /* XXX Don't spew on expected failures ... */
269  if (err && gcry_err_code(err) != gc->badok)
270  fprintf (stderr, "rpmgc: %s(0x%0x): %s/%s\n",
271  msg, (unsigned)err, gcry_strsource(err), gcry_strerror(err));
272  return err;
273 }
274 
275 static
276 int rpmgcSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
277  /*@modifies dig @*/
278 {
279  rpmgc gc = (rpmgc) dig->impl;
280  gcry_error_t err;
281  const char * hash_algo_name = NULL;
282  int rc = 1; /* assume error */
283  int xx;
284 pgpDigParams pubp = pgpGetPubkey(dig);
285 dig->pubkey_algoN = pgpPubkeyAlgo2Name(pubp->pubkey_algo);
286 dig->hash_algoN = pgpHashAlgo2Name(sigp->hash_algo);
287 
288  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
289 
290  switch (sigp->hash_algo) {
291  case PGPHASHALGO_MD5:
292  hash_algo_name = "md5";
293  break;
294  case PGPHASHALGO_SHA1:
295  hash_algo_name = "sha1";
296  break;
298  hash_algo_name = "ripemd160"; /* XXX FIXME: RPM != GCRYPT name */
299  break;
300  case PGPHASHALGO_MD2:
301  hash_algo_name = "md2";
302  break;
304  hash_algo_name = "tiger";
305  break;
307 #ifdef NOTYET
308  hash_algo_name = "haval";
309 #endif
310  break;
311  case PGPHASHALGO_SHA256:
312  hash_algo_name = "sha256";
313  break;
314  case PGPHASHALGO_SHA384:
315  hash_algo_name = "sha384";
316  break;
317  case PGPHASHALGO_SHA512:
318  hash_algo_name = "sha512";
319  break;
320  case PGPHASHALGO_SHA224:
321  hash_algo_name = "sha224";
322  break;
323  default:
324  break;
325  }
326  if (hash_algo_name == NULL)
327  goto exit;
328 
329  /* Set RSA hash. */
330  err = rpmgcErr(gc, "RSA c",
331  gcry_sexp_build(&gc->hash, NULL,
332  "(data (flags pkcs1) (hash %s %b))", hash_algo_name, gc->digestlen, gc->digest) );
333 if (_pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
334 
335  /* Compare leading 16 bits of digest for quick check. */
336  rc = memcmp(gc->digest, sigp->signhash16, sizeof(sigp->signhash16));
337 
338  /* XXX FIXME: avoid spurious "BAD" error msg while signing. */
339  if (rc && sigp->signhash16[0] == 0 && sigp->signhash16[1] == 0)
340  rc = 0;
341 
342 exit:
343 SPEW(0, !rc, dig);
344  return rc;
345 }
346 
347 static
348 int rpmgcSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
349  /*@modifies dig @*/
350 {
351  rpmgc gc = (rpmgc) dig->impl;
352  gcry_error_t err;
353  int rc;
354  int xx;
355 pgpDigParams pubp = pgpGetPubkey(dig);
356 dig->pubkey_algoN = pgpPubkeyAlgo2Name(pubp->pubkey_algo);
357 dig->hash_algoN = pgpHashAlgo2Name(sigp->hash_algo);
358 
359 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
360  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
361 
362  /* Set DSA hash. */
363 /*@-moduncon -noeffectuncon @*/
364  { gcry_mpi_t c = NULL;
365  /* XXX FIXME: Truncate to qbits (if necessary) */
366  unsigned int dlen =
367  (gc->digestlen > gc->qbits/8 ? gc->qbits/8 : gc->digestlen);
368  err = rpmgcErr(gc, "DSA c",
369  gcry_mpi_scan(&c, GCRYMPI_FMT_USG, gc->digest, dlen, NULL));
370  err = rpmgcErr(gc, "DSA gc->hash",
371  gcry_sexp_build(&gc->hash, NULL,
372  "(data (flags raw) (value %m))", c) );
373  gcry_mpi_release(c);
374 if (_pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
375  }
376 /*@=moduncon =noeffectuncon @*/
377 
378  /* Compare leading 16 bits of digest for quick check. */
379  rc = memcmp(gc->digest, sigp->signhash16, sizeof(sigp->signhash16));
380 
381  /* XXX FIXME: avoid spurious "BAD" error msg while signing. */
382  if (rc && sigp->signhash16[0] == 0 && sigp->signhash16[1] == 0)
383  rc = 0;
384 
385 SPEW(0, !rc, dig);
386  return rc;
387 }
388 
389 static
390 int rpmgcSetELG(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
391  /*@*/
392 {
393  rpmgc gc = (rpmgc) dig->impl;
394  gcry_error_t err;
395  int rc = 0; /* XXX always fail. */
396  int xx;
397 pgpDigParams pubp = pgpGetPubkey(dig);
398 dig->pubkey_algoN = pgpPubkeyAlgo2Name(pubp->pubkey_algo);
399 dig->hash_algoN = pgpHashAlgo2Name(sigp->hash_algo);
400 
401 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
402  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
403 
404  /* Set ELG hash. */
405 /*@-moduncon -noeffectuncon @*/
406  { gcry_mpi_t c = NULL;
407  /* XXX truncate to 160 bits for DSA2? */
408  err = rpmgcErr(gc, "ELG c",
409  gcry_mpi_scan(&c, GCRYMPI_FMT_USG, gc->digest, 160/8, NULL));
410  err = rpmgcErr(gc, "ELG gc->hash",
411  gcry_sexp_build(&gc->hash, NULL,
412  "(data (flags raw) (value %m))", c) );
413  gcry_mpi_release(c);
414 if (1 || _pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
415  }
416 /*@=moduncon =noeffectuncon @*/
417 
418  /* Compare leading 16 bits of digest for quick check. */
419  rc = memcmp(gc->digest, sigp->signhash16, sizeof(sigp->signhash16));
420 
421  /* XXX FIXME: avoid spurious "BAD" error msg while signing. */
422  if (rc && sigp->signhash16[0] == 0 && sigp->signhash16[1] == 0)
423  rc = 0;
424 
425 SPEW(0, !rc, dig);
426  return rc;
427 }
428 
429 static
430 int rpmgcSetECDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
431  /*@*/
432 {
433  rpmgc gc = (rpmgc) dig->impl;
434  int rc = 1; /* assume failure. */
435  gpg_error_t err;
436  int xx;
437 pgpDigParams pubp = pgpGetPubkey(dig);
438 dig->pubkey_algoN = pgpPubkeyAlgo2Name(pubp->pubkey_algo);
439 dig->hash_algoN = pgpHashAlgo2Name(sigp->hash_algo);
440 
441 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
442 gc->digest = _free(gc->digest);
443 gc->digestlen = 0;
444  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
445 
446  /* Set ECDSA hash. */
447  { gcry_mpi_t c = NULL;
448  err = rpmgcErr(gc, "ECDSA c",
449  gcry_mpi_scan(&c, GCRYMPI_FMT_USG, gc->digest, gc->digestlen, NULL));
450 if (gc->hash) {
451  gcry_sexp_release(gc->hash); gc->hash = NULL;
452 }
453  err = rpmgcErr(gc, "ECDSA gc->hash",
454  gcry_sexp_build(&gc->hash, NULL,
455  "(data (flags raw) (value %m))", c) );
456  gcry_mpi_release(c);
457 if (_pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
458  }
459 
460  /* Compare leading 16 bits of digest for quick check. */
461  rc = memcmp(gc->digest, sigp->signhash16, sizeof(sigp->signhash16));
462 
463  /* XXX FIXME: avoid spurious "BAD" error msg while signing. */
464  if (rc && sigp->signhash16[0] == 0 && sigp->signhash16[1] == 0)
465  rc = 0;
466 
467 SPEW(0, !rc, dig);
468  return rc;
469 }
470 
471 static int rpmgcErrChk(pgpDig dig, const char * msg, int rc, unsigned expected)
472 {
473 rpmgc gc = (rpmgc) dig->impl;
474  /* Was the return code the expected result? */
475  rc = (gcry_err_code(gc->err) != expected);
476  if (rc)
477  fail("%s failed: %s\n", msg, gpg_strerror(gc->err));
478 /* XXX FIXME: pgpImplStrerror */
479  return rc; /* XXX 0 on success */
480 }
481 
482 static int rpmgcAvailable(rpmgc gc, int algo, int rc)
483 {
484  /* Permit non-certified algo's if not in FIPS mode. */
485  if (rc && !gc->in_fips_mode)
486  rc = 0;
487 #ifdef NOTNOW
488  if (rc)
489  rpmlog(RPMLOG_INFO," algorithm %d not available in fips mode\n", algo);
490 #else
491 /* XXX FIXME: refactor back into trsa.c */
492  if (rc)
493  fprintf(stderr," algorithm %d not available in fips mode\n", algo);
494 #endif
495  return rc; /* XXX 0 on success */
496 }
497 
498 static int rpmgcAvailableCipher(pgpDig dig, int algo)
499 {
500  rpmgc gc = (rpmgc) dig->impl;
501  return rpmgcAvailable(gc, algo, gcry_cipher_test_algo(algo));
502 }
503 
504 static int rpmgcAvailableDigest(pgpDig dig, int algo)
505 {
506  rpmgc gc = (rpmgc) dig->impl;
507  int rc = 0; /* assume available */
508  rc = rpmgcAvailable(gc, algo,
509  (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
510  return rc;
511 }
512 
513 static int rpmgcAvailablePubkey(pgpDig dig, int algo)
514 {
515  rpmgc gc = (rpmgc) dig->impl;
516  int rc = 0; /* assume available */
517  rc = rpmgcAvailable(gc, algo, gcry_pk_test_algo(algo));
518  return rc;
519 }
520 
521 static
522 int rpmgcVerify(pgpDig dig)
523 {
524  rpmgc gc = (rpmgc) dig->impl;
525  int rc;
526 pgpDigParams pubp = pgpGetPubkey(dig);
527 pgpDigParams sigp = pgpGetSignature(dig);
528 dig->pubkey_algoN = pgpPubkeyAlgo2Name(pubp->pubkey_algo);
529 dig->hash_algoN = pgpHashAlgo2Name(sigp->hash_algo);
530 
531  if (gc->sig == NULL) {
532  pgpDigParams pubp = pgpGetPubkey(dig);
533  switch (pubp->pubkey_algo) {
534  case PGPPUBKEYALGO_RSA:
535 assert(gc->c);
536  gc->err = rpmgcErr(gc, "RSA gc->sig",
537  gcry_sexp_build(&gc->sig, NULL,
538  "(sig-val (RSA (s %m)))", gc->c) );
539  break;
540  case PGPPUBKEYALGO_DSA:
541 assert(gc->r);
542 assert(gc->s);
543  gc->err = rpmgcErr(gc, "DSA gc->sig",
544  gcry_sexp_build(&gc->sig, NULL,
545  "(sig-val (DSA (r %m) (s %m)))", gc->r, gc->s) );
546  break;
547  case PGPPUBKEYALGO_ELGAMAL: /* XXX FIXME: untested. */
548 assert(gc->r);
549 assert(gc->s);
550  gc->err = rpmgcErr(gc, "ELG gc->sig",
551  gcry_sexp_build(&gc->sig, NULL,
552  "(sig-val (ELG (r %m) (s %m)))", gc->r, gc->s) );
553  break;
554  case PGPPUBKEYALGO_ECDSA: /* XXX FIXME */
555 assert(gc->r);
556 assert(gc->s);
557  gc->err = rpmgcErr(gc, "ECDSA gc->sig",
558  gcry_sexp_build(&gc->sig, NULL,
559  "(sig-val (ECDSA (r %m) (s %m)))", gc->r, gc->s) );
560  break;
561  default:
562 assert(0);
563  break;
564  }
565 if (_pgp_debug < 0)
566 rpmgcDump("gc->sig", gc->sig);
567  }
568 
569  if (gc->pub_key == NULL) {
570  pgpDigParams pubp = pgpGetPubkey(dig);
571  switch (pubp->pubkey_algo) {
572  case PGPPUBKEYALGO_RSA:
573 assert(gc->n);
574 assert(gc->e);
575 /* gc->d priv_key */
576 /* gc->p priv_key optional */
577 /* gc->q priv_key optional */
578 /* gc->u priv_key optional */
579  gc->err = rpmgcErr(gc, "RSA gc->pub_key",
580  gcry_sexp_build(&gc->pub_key, NULL,
581  "(public-key (RSA (n %m) (e %m)))", gc->n, gc->e) );
582  break;
583  case PGPPUBKEYALGO_DSA:
584 assert(gc->p);
585 assert(gc->q);
586 assert(gc->g);
587 assert(gc->y);
588 /* gc->x priv_key */
589  gc->err = rpmgcErr(gc, "DSA gc->pub_key",
590  gcry_sexp_build(&gc->pub_key, NULL,
591  "(public-key (DSA (p %m) (q %m) (g %m) (y %m)))",
592  gc->p, gc->q, gc->g, gc->y) );
593  break;
594  case PGPPUBKEYALGO_ELGAMAL: /* XXX FIXME: untested. */
595 assert(gc->p);
596 assert(gc->g);
597 assert(gc->y);
598 /* gc->x priv_key */
599  gc->err = rpmgcErr(gc, "ELG gc->pub_key",
600  gcry_sexp_build(&gc->pub_key, NULL,
601  "(public-key (ELG (p %m) (g %m) (y %m)))",
602  gc->p, gc->g, gc->y) );
603  break;
604  case PGPPUBKEYALGO_ECDSA: /* XXX FIXME */
605 /* gc->p curve */
606 /* gc->a curve */
607 /* gc->b curve */
608 /* gc->g curve */
609 /* gc->n curve */
610 assert(gc->q);
611 /* gc->d priv_key */
612 assert(gc->curve);
613  { char *t = rpmExpand("(public-key (ECDSA (curve \"", gc->curve,"\")",
614  "(q %%m)))", NULL);
615  gc->err = rpmgcErr(gc, "ECDSA gc->pub_key",
616  gcry_sexp_build(&gc->pub_key, NULL, t, gc->q));
617  t = _free(t);
618  } break;
619  default:
620 assert(0);
621  break;
622  }
623 if (_pgp_debug < 0)
624 rpmgcDump("gc->pub_key", gc->pub_key);
625  }
626 
627  /* Verify the signature. */
628  gc->err = rpmgcErr(gc, "gcry_pk_verify",
629  gcry_pk_verify (gc->sig, gc->hash, gc->pub_key));
630 
631  rc = (gc->err == 0);
632 
633 SPEW(0, rc, dig);
634  return rc; /* XXX 1 on success */
635 }
636 
637 static
638 int rpmgcSign(pgpDig dig)
639 {
640  rpmgc gc = (rpmgc) dig->impl;
641  int rc;
642 pgpDigParams pubp = pgpGetPubkey(dig);
643 pgpDigParams sigp = pgpGetSignature(dig);
644 dig->pubkey_algoN = pgpPubkeyAlgo2Name(pubp->pubkey_algo);
645 dig->hash_algoN = pgpHashAlgo2Name(sigp->hash_algo);
646 
647  /* Sign the hash. */
648  gc->err = rpmgcErr(gc, "gcry_pk_sign",
649  gcry_pk_sign (&gc->sig, gc->hash, gc->sec_key));
650 
651  rc = (gc->err == 0);
652 
653 SPEW(!rc, rc, dig);
654  return rc; /* XXX 1 on success */
655 }
656 
657 static
658 int rpmgcGenerate(pgpDig dig)
659  /*@*/
660 {
661  rpmgc gc = (rpmgc) dig->impl;
662  int rc;
663 pgpDigParams pubp = pgpGetPubkey(dig);
664 pgpDigParams sigp = pgpGetSignature(dig);
665 assert(pubp->pubkey_algo);
666 assert(sigp->hash_algo);
667 
668 /* XXX FIXME: gc->{key_spec,key_pair} could be local. */
669  switch (pubp->pubkey_algo) {
670  case PGPPUBKEYALGO_RSA:
671 if (gc->nbits == 0) gc->nbits = 2048; /* XXX FIXME */
672  gc->err = rpmgcErr(gc, "gc->key_spec",
673  gcry_sexp_build(&gc->key_spec, NULL,
674  gc->in_fips_mode
675  ? "(genkey (RSA (nbits %d)))"
676  : "(genkey (RSA (nbits %d)(transient-key)))",
677  gc->nbits));
678  break;
679  case PGPPUBKEYALGO_DSA:
680  /* XXX Set the no. of qbits based on the digest being used. */
681  if (gc->qbits == 0)
682  switch (sigp->hash_algo) {
683  default: /* XXX default */
684  case PGPHASHALGO_SHA1: gc->qbits = 160; break;
685  case PGPHASHALGO_SHA224: gc->qbits = 224; break;
686  case PGPHASHALGO_SHA256: gc->qbits = 256; break;
687  case PGPHASHALGO_SHA384: gc->qbits = 384; break;
688  case PGPHASHALGO_SHA512: gc->qbits = 512; break;
689  }
690 assert(gc->qbits);
691 
692  /* XXX Set the no. of nbits for non-truncated digest in use. */
693  if (gc->nbits == 0)
694  switch (gc->qbits) {
695  default: /* XXX default */
696  case 160: gc->nbits = 1024; break;
697  case 224: gc->nbits = 2048; break;
698  case 256: gc->nbits = 3072; break;
699 #ifdef PAINFUL
700  case 384: gc->nbits = 7680; break;
701  case 512: gc->nbits = 15360; break;
702 #else /* XXX FIXME: truncated DSA2 no workie. */
703  case 384: gc->nbits = 2048; break;
704  case 512: gc->nbits = 2048; break;
705 #endif
706  }
707 assert(gc->nbits);
708  gc->err = rpmgcErr(gc, "gc->key_spec",
709  gcry_sexp_build(&gc->key_spec, NULL,
710  gc->in_fips_mode
711  ? "(genkey (DSA (nbits %d)))"
712  : "(genkey (DSA (nbits %d)(transient-key)))",
713  gc->nbits));
714  break;
715  case PGPPUBKEYALGO_ELGAMAL: /* XXX FIXME: untested. */
716 if (gc->nbits == 0) gc->nbits = 1024; /* XXX FIXME */
717  gc->err = rpmgcErr(gc, "gc->key_spec",
718  gcry_sexp_build(&gc->key_spec, NULL,
719  gc->in_fips_mode
720  ? "(genkey (ELG (nbits %d)))"
721  : "(genkey (ELG (nbits %d)(transient-key)))",
722  gc->nbits));
723  break;
724  case PGPPUBKEYALGO_ECDSA:
725  /* XXX Set the no. of bits based on the digest being used. */
726  if (gc->nbits == 0)
727  switch (sigp->hash_algo) {
728  case PGPHASHALGO_TIGER192: gc->nbits = 192; break;
729  case PGPHASHALGO_SHA224: gc->nbits = 224; break;
730  default: /* XXX default */
731  case PGPHASHALGO_SHA256: gc->nbits = 256; break;
732  case PGPHASHALGO_SHA384: gc->nbits = 384; break;
733  case PGPHASHALGO_SHA512: gc->nbits = 521; break;
734  }
735 assert(gc->nbits);
736  if (gc->curve == NULL)
737  switch (gc->nbits) {
738  case 192: gc->curve = xstrdup("NIST P-192"); break;
739  case 224: gc->curve = xstrdup("NIST P-224"); break;
740  default: /* default */
741  gc->nbits = 256;
742  /*@fallthrough@*/
743  case 256: gc->curve = xstrdup("NIST P-256"); break;
744  case 384: gc->curve = xstrdup("NIST P-384"); break;
745  case 521: gc->curve = xstrdup("NIST P-521"); break;
746  }
747 assert(gc->curve);
748 
749 #ifdef DYING
750  gc->err = rpmgcErr(gc, "gc->key_spec",
751  gcry_sexp_build(&gc->key_spec, NULL,
752  gc->in_fips_mode
753  ? "(genkey (ECDSA (nbits %d)))"
754  : "(genkey (ECDSA (nbits %d)(transient-key)))",
755  gc->nbits));
756 #else
757  /* XXX gcry_sexp_build %s format is fubar in libgcrypt-1.5.3 ?!? */
758  { char * t = rpmExpand("(genkey (ECDSA (curve \"", gc->curve, "\")",
759  gc->in_fips_mode ? "" : "(transient-key)",
760  "))", NULL);
761  gc->err = rpmgcErr(gc, "gc->key_spec",
762  gcry_sexp_build(&gc->key_spec, NULL, t));
763  t = _free(t);
764  }
765 #endif
766  break;
767  default:
768 assert(0);
769  break;
770  }
771  if (gc->err)
772  goto exit;
773 if ((_rpmgc_debug || _pgp_debug < 0) && gc->key_spec) rpmgcDump("gc->key_spec", gc->key_spec);
774 
775  /* Generate the key pair. */
776  gc->err = rpmgcErr(gc, "gc->key_pair",
777  gcry_pk_genkey(&gc->key_pair, gc->key_spec));
778  if (gc->err)
779  goto exit;
780 if ((_rpmgc_debug || _pgp_debug < 0) && gc->key_pair) rpmgcDump("gc->key_pair", gc->key_pair);
781 
782  /* Split key_pair into sec_key/pub_key. */
783  gc->pub_key = gcry_sexp_find_token(gc->key_pair, "public-key", 0);
784  if (gc->pub_key == NULL)
785 /* XXX FIXME: refactor errmsg here. */
786  goto exit;
787 if ((_rpmgc_debug || _pgp_debug < 0) && gc->pub_key) rpmgcDump("gc->pub_key", gc->pub_key);
788 
789  gc->sec_key = gcry_sexp_find_token(gc->key_pair, "private-key", 0);
790  if (gc->sec_key == NULL)
791 /* XXX FIXME: refactor errmsg here. */
792  goto exit;
793 if ((_rpmgc_debug || _pgp_debug < 0) && gc->sec_key) rpmgcDump("gc->sec_key", gc->sec_key);
794 
795 exit:
796 
797  rc = (gc->err == 0 && gc->pub_key && gc->sec_key);
798 
799 if (gc->key_spec) {
800  gcry_sexp_release(gc->key_spec);
801  gc->key_spec = NULL;
802 }
803 if (gc->key_pair) {
804  gcry_sexp_release(gc->key_pair);
805  gc->key_pair = NULL;
806 }
807 
808 SPEW(!rc, rc, dig);
809  return rc; /* XXX 1 on success */
810 }
811 
812 /*@-globuse -mustmod @*/
813 static
814 int rpmgcMpiItem(/*@unused@*/ const char * pre, pgpDig dig, int itemno,
815  const rpmuint8_t * p,
816  /*@unused@*/ /*@null@*/ const rpmuint8_t * pend)
817  /*@globals fileSystem @*/
818  /*@modifies dig, fileSystem @*/
819 {
820  rpmgc gc = (rpmgc) dig->impl;
821  unsigned int nb = (pend >= p ? (pend - p) : 0);
822  unsigned int mbits = (((8 * (nb - 2)) + 0x1f) & ~0x1f);
823  const char * mpiname = "";
824  gcry_mpi_t * mpip = NULL;
825  size_t nscan = 0;
826  int rc = 0;
827 
828  switch (itemno) {
829  default:
830 assert(0);
831  case 10: /* RSA m**d */
832  gc->nbits = mbits;
833  mpiname = "RSA m**d"; mpip = &gc->c;
834  break;
835  case 20: /* DSA r */
836  gc->qbits = mbits;
837  mpiname = "DSA r"; mpip = &gc->r;
838  break;
839  case 21: /* DSA s */
840 assert(mbits == gc->qbits);
841  mpiname = "DSA s"; mpip = &gc->s;
842  break;
843  case 30: /* RSA n */
844  gc->nbits = mbits;
845  mpiname = "RSA n"; mpip = &gc->n;
846  break;
847  case 31: /* RSA e */
848  mpiname = "RSA e"; mpip = &gc->e;
849  break;
850  case 40: /* DSA p */
851  gc->nbits = mbits;
852  mpiname = "DSA p"; mpip = &gc->p;
853  break;
854  case 41: /* DSA q */
855  gc->qbits = mbits;
856  mpiname = "DSA q"; mpip = &gc->q;
857  break;
858  case 42: /* DSA g */
859 assert(mbits == gc->nbits);
860  mpiname = "DSA g"; mpip = &gc->g;
861  break;
862  case 43: /* DSA y */
863 assert(mbits == gc->nbits);
864  mpiname = "DSA y"; mpip = &gc->y;
865  break;
866  case 50: /* ECDSA r */
867  gc->qbits = mbits;
868  mpiname = "ECDSA r"; mpip = &gc->r;
869  break;
870  case 51: /* ECDSA s */
871 assert(mbits == gc->qbits);
872  mpiname = "ECDSA s"; mpip = &gc->s;
873  break;
874  case 60: /* ECDSA curve OID */
875  { const char * s = xstrdup(pgpHexStr(p, nb));
876  if (!strcasecmp(s, "2a8648ce3d030101"))
877  gc->nbits = 192;
878  else if (!strcasecmp(s, "2b81040021"))
879  gc->nbits = 224;
880  else if (!strcasecmp(s, "2a8648ce3d030107"))
881  gc->nbits = 256;
882  else if (!strcasecmp(s, "2b81040022"))
883  gc->nbits = 384;
884  else if (!strcasecmp(s, "2b81040023"))
885  gc->nbits = 521;
886  else
887  gc->nbits = 256; /* XXX FIXME default? */
888  s = _free(s);
889  }
890 assert(gc->nbits > 0);
891  switch (gc->nbits) {
892  case 192: gc->curve = xstrdup("NIST P-192"); break;
893  case 224: gc->curve = xstrdup("NIST P-224"); break;
894  default: /* default */
895  gc->nbits = 256;
896  /*@fallthrough@*/
897  case 256: gc->curve = xstrdup("NIST P-256"); break;
898  case 384: gc->curve = xstrdup("NIST P-384"); break;
899  case 521: gc->curve = xstrdup("NIST P-521"); break;
900  }
901 assert(gc->curve != NULL);
902  goto exit; /* XXX early exit */
903  break;
904  case 61: /* ECDSA Q */
905  mpiname = "ECDSA Q"; mpip = &gc->q;
906  break;
907  }
908 
909  if (mpip == NULL)
910  goto exit;
911 
912 /*@-moduncon -noeffectuncon @*/
913  if (itemno != 60) {
914  nb = pgpMpiLen(p);
915  gc->err = rpmgcErr(gc, mpiname,
916  gcry_mpi_scan(mpip, GCRYMPI_FMT_PGP, p, nb, &nscan) );
917 /*@=moduncon =noeffectuncon @*/
918 assert(nb == nscan);
919  }
920 
921  if (_pgp_debug < 0)
922  { unsigned nbits = gcry_mpi_get_nbits(*mpip);
923  unsigned char * hex = NULL;
924  size_t nhex = 0;
925  gc->err = rpmgcErr(gc, "MPI print",
926  gcry_mpi_aprint(GCRYMPI_FMT_HEX, &hex, &nhex, *mpip) );
927  fprintf(stderr, "*** %s\t%5d:%s\n", mpiname, (int)nbits, hex);
928  hex = _free(hex);
929  }
930 
931 exit:
932  return rc;
933 }
934 /*@=globuse =mustmod @*/
935 
936 /*@-mustmod@*/
937 static
938 void rpmgcClean(void * impl)
939  /*@modifies impl @*/
940 {
941  rpmgc gc = (rpmgc) impl;
942 /*@-moduncon -noeffectuncon @*/
943  if (gc != NULL) {
944  gc->nbits = 0;
945  gc->err = 0;
946  gc->badok = 0;
947  gc->digest = _free(gc->digest);
948  gc->digestlen = 0;
949 
950 assert(gc->key_spec == NULL);
951  if (gc->key_spec)
952  gcry_sexp_release(gc->key_spec);
953  gc->key_spec = NULL;
954 assert(gc->key_pair == NULL);
955  if (gc->key_pair)
956  gcry_sexp_release(gc->key_pair);
957  gc->key_pair = NULL;
958  if (gc->pub_key)
959  gcry_sexp_release(gc->pub_key);
960  gc->pub_key = NULL;
961  if (gc->sec_key)
962  gcry_sexp_release(gc->sec_key);
963  gc->sec_key = NULL;
964  if (gc->hash)
965  gcry_sexp_release(gc->hash);
966  gc->hash = NULL;
967  if (gc->sig)
968  gcry_sexp_release(gc->sig);
969  gc->sig = NULL;
970 
971  if (gc->c)
972  gcry_mpi_release(gc->c);
973  gc->c = NULL;
974  if (gc->p)
975  gcry_mpi_release(gc->p);
976  gc->p = NULL;
977  if (gc->q)
978  gcry_mpi_release(gc->q);
979  gc->q = NULL;
980  if (gc->g)
981  gcry_mpi_release(gc->g);
982  gc->g = NULL;
983  if (gc->y)
984  gcry_mpi_release(gc->y);
985  gc->y = NULL;
986 
987  if (gc->r)
988  gcry_mpi_release(gc->r);
989  gc->r = NULL;
990  if (gc->s)
991  gcry_mpi_release(gc->s);
992  gc->s = NULL;
993  if (gc->n)
994  gcry_mpi_release(gc->n);
995  gc->n = NULL;
996  if (gc->e)
997  gcry_mpi_release(gc->e);
998  gc->e = NULL;
999  if (gc->a) /* XXX unused */
1000  gcry_mpi_release(gc->a);
1001  gc->a = NULL;
1002  if (gc->b) /* XXX unused */
1003  gcry_mpi_release(gc->b);
1004  gc->b = NULL;
1005 
1006  gc->oid = _free(gc->oid);
1007  gc->curve = _free(gc->curve);
1008 
1009  }
1010 /*@=moduncon =noeffectuncon @*/
1011 }
1012 /*@=mustmod@*/
1013 
1014 /*@unchecked@*/
1015 static int rpmgc_initialized;
1016 
1017 static /*@null@*/
1018 void * rpmgcFree(/*@only@*/ void * impl)
1019  /*@globals rpmgc_initialized @*/
1020  /*@modifies impl, rpmgc_initialized @*/
1021 {
1022 
1023  rpmgcClean(impl);
1024 
1025  /* XXX if (gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) */
1026  if (--rpmgc_initialized == 0) {
1027  rpmgc gc = (rpmgc) impl;
1028 
1029  if (_pgp_debug < 0) {
1030  gc->err = rpmgcErr(gc, "CLEAR_DEBUG_FLAGS",
1031  gcry_control(GCRYCTL_CLEAR_DEBUG_FLAGS, 3));
1032  gc->err = rpmgcErr(gc, "SET_VERBOSITY",
1033  gcry_control(GCRYCTL_SET_VERBOSITY, 0) );
1034  }
1035 
1036 #ifdef NOTYET
1037  /* XXX useful output only w standard PRNG, nothing w fips/system */
1038  rpmlog(RPMLOG_DEBUG, D_("---------- libgcrypt %s statistics:\n"), GCRYPT_VERSION);
1039  gc->err = rpmgcErr(gc, "DUMP_RANDOM_STATS",
1040  gcry_control(GCRYCTL_DUMP_RANDOM_STATS) );
1041  gc->err = rpmgcErr(gc, "DUMP_MEMORY_STATS",
1042  gcry_control(GCRYCTL_DUMP_MEMORY_STATS) );
1043  gc->err = rpmgcErr(gc, "DUMP_SECMEM_STATS",
1044  gcry_control(GCRYCTL_DUMP_MEMORY_STATS) );
1045  rpmlog(RPMLOG_DEBUG, D_("----------\n"));
1046 #endif
1047  }
1048 
1049  impl = _free(impl);
1050 
1051  return NULL;
1052 }
1053 
1054 #ifdef REFERENCE
1055  _p The argument provided in the call to gcry_set_progress_handler.
1056  what A string identifying the type of the progress output.
1057  The following values for what are defined:
1058  need_entropy -- Not enough entropy is available.
1059  total holds the number of required bytes.
1060  wait_dev_random -- Waiting to re-open a random device.
1061  total gives the number of seconds until the next try.
1062  primegen -- Values for printchar:
1063  \n Prime generated.
1064  ! Need to refresh the pool of prime numbers.
1065  <,> Number of bits adjusted.
1066  ^ Searching for a generator.
1067  . Fermat test on 10 candidates failed.
1068  : Restart with a new random value.
1069  + Rabin Miller test passed.
1070 #endif
1071 static void rpmgcProgress(void * _p, const char * what,
1072  int printchar, int current, int total)
1073 {
1074  int msglvl = RPMLOG_DEBUG; /* XXX RPMLOG_INFO? */
1075  /* XXX use fprintf for interactive feedback? */
1076  if (!strcmp(what, "need_entropy"))
1077  rpmlog(msglvl, D_("Waiting for %d bytes of entropy ...\n"), total);
1078  else if (!strcmp(what, "wait_dev_random"))
1079  rpmlog(msglvl, D_("Waiting on random device re-open in %d secs ...\n"), total);
1080 #ifdef NOTYET /* XXX noisy/surprising context if inline continuation */
1081  else if (!strcmp(what, "primegen"))
1082  rpmlog("%c", printchar);
1083 #endif
1084 }
1085 
1086 static int lvl2log(int lvl)
1087 {
1088  switch (lvl) {
1089  default:
1090  case GCRY_LOG_CONT: /* FIXME: (Continue the last log line.) */
1091  case GCRY_LOG_INFO: lvl = RPMLOG_DEBUG; break;
1092  case GCRY_LOG_WARN: lvl = RPMLOG_WARNING; break;
1093  case GCRY_LOG_ERROR: lvl = RPMLOG_ERR; break;
1094  case GCRY_LOG_FATAL: lvl = RPMLOG_CRIT; break;
1095  case GCRY_LOG_BUG: lvl = RPMLOG_ALERT; break;
1096  case GCRY_LOG_DEBUG: lvl = RPMLOG_DEBUG; break;
1097  }
1098  return lvl;
1099 }
1100 
1101 static void rpmgcFatal(void * opaque, int lvl, const char * msg)
1102 {
1103  rpmlog(lvl2log(lvl), msg);
1104 }
1105 
1106 static void rpmgcLog(void * opaque, int lvl, const char * fmt, va_list ap)
1107 {
1108  (void)opaque;
1109  vrpmlog(lvl2log(lvl), fmt, ap);
1110 }
1111 
1112 static
1113 void * rpmgcInit(void)
1114  /*@globals rpmgc_initialized @*/
1115  /*@modifies rpmgc_initialized @*/
1116 {
1117  rpmgc gc = (rpmgc) xcalloc(1, sizeof(*gc));
1118 
1119  if (rpmgc_initialized++ == 0) {
1120 
1121  /* XXX Ensure initialization is exactly once */
1122  /* XXX TODO: make FIPS mode configurable */
1123  if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
1124  rpmlog(RPMLOG_DEBUG, "---------- libgcrypt %s configuration:\n", GCRYPT_VERSION);
1125  gc->err = rpmgcErr(gc, "SET_ENFORCED_FIPS_FLAG",
1126  gcry_control(GCRYCTL_SET_ENFORCED_FIPS_FLAG) );
1127  gc->err = rpmgcErr(gc, "FORCE_FIPS_MODE",
1128  gcry_control(GCRYCTL_FORCE_FIPS_MODE) );
1129  }
1130 
1131  gcry_set_progress_handler((gcry_handler_progress_t)rpmgcProgress, NULL);
1132  /* XXX gcry_set_allocation_handler */
1133  gcry_set_fatalerror_handler((gcry_handler_error_t)rpmgcFatal, NULL);
1134  gcry_set_log_handler((gcry_handler_log_t)rpmgcLog, NULL);
1135 
1136  if (_pgp_debug < 0) {
1137  gc->err = rpmgcErr(gc, "SET_VERBOSITY",
1138  gcry_control(GCRYCTL_SET_VERBOSITY, 3) );
1139  gc->err = rpmgcErr(gc, "SET_DEBUG_FLAGS",
1140  gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 3) );
1141  }
1142 
1143  /* XXX Ensure initialization is exactly once */
1144  if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
1145  gc->err = rpmgcErr(gc, "GCRYPT_VERSION",
1146  gcry_check_version (GCRYPT_VERSION) == 0 );
1147 
1148  gc->err = rpmgcErr(gc, "DISABLE_PRIV_DROP",
1149  gcry_control(GCRYCTL_DISABLE_PRIV_DROP) );
1150  gc->err = rpmgcErr(gc, "USE_SECURE_RNDPOOL",
1151  gcry_control(GCRYCTL_USE_SECURE_RNDPOOL) );
1152 
1153  gc->err = rpmgcErr(gc, "SUSPEND_SECMEM_WARN",
1154  gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN) );
1155  gc->err = rpmgcErr(gc, "INIT_SECMEM",
1156  gcry_control(GCRYCTL_INIT_SECMEM, 16384) );
1157  gc->err = rpmgcErr(gc, "RESUME_SECMEM_WARN",
1158  gcry_control(GCRYCTL_RESUME_SECMEM_WARN) );
1159  gc->err = rpmgcErr(gc, "DISABLE_SECMEM_WARN",
1160  gcry_control(GCRYCTL_DISABLE_SECMEM_WARN) );
1161 
1162 #ifdef NOTYET /* XXX no reason to override libgcrypt defaults yet */
1163  gc->err = rpmgcErr(gc, "SET_PREFERRED_RNG_TYPE",
1164  gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM) );
1165 #endif
1166 
1167  gc->err = rpmgcErr(gc, "INITIALIZATION_FINISHED",
1168  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0) );
1169 
1170  gc->err = rpmgcErr(gc, "PRINT_CONFIG",
1171  gcry_control (GCRYCTL_PRINT_CONFIG, NULL) );
1172  rpmlog(RPMLOG_DEBUG, "----------\n");
1173  }
1174  }
1175 
1176  return (void *) gc;
1177 }
1178 
1179 struct pgpImplVecs_s rpmgcImplVecs = {
1180  "Gcrypt " GCRYPT_VERSION,
1181  rpmgcSetRSA,
1182  rpmgcSetDSA,
1183  rpmgcSetELG,
1184  rpmgcSetECDSA,
1185 
1186  rpmgcErrChk,
1187  rpmgcAvailableCipher, rpmgcAvailableDigest, rpmgcAvailablePubkey,
1188  rpmgcVerify, rpmgcSign, rpmgcGenerate,
1189 
1190  rpmgcMpiItem, rpmgcClean,
1191  rpmgcFree, rpmgcInit
1192 };
1193 
1194 int rpmgcExportPubkey(pgpDig dig)
1195 {
1196  uint8_t pkt[8192];
1197  uint8_t * be = pkt;
1198  size_t pktlen;
1199  time_t now = time(NULL);
1200  uint32_t bt = now;
1201  size_t nb;
1202  size_t nw;
1203  pgpDigParams pubp = pgpGetPubkey(dig);
1204  rpmgc gc = (rpmgc) dig->impl;
1205  int rc = 0; /* assume failure */
1206  int xx;
1207 
1208  *be++ = 0x80 | (PGPTAG_PUBLIC_KEY << 2) | 0x01;
1209  be += 2;
1210 
1211  *be++ = 0x04;
1212  *be++ = (bt >> 24);
1213  *be++ = (bt >> 16);
1214  *be++ = (bt >> 8);
1215  *be++ = (bt );
1216  *be++ = pubp->pubkey_algo;
1217 
1218  switch (pubp->pubkey_algo) {
1219  default:
1220 assert(0);
1221  break;
1222  case PGPPUBKEYALGO_RSA:
1223 if (gc->pub_key) rpmgcDump(__FUNCTION__, gc->pub_key);
1224 assert(gc->pub_key);
1225 xx = gcry_sexp_extract_param (gc->pub_key, NULL, "+n +e", &gc->n, &gc->e, NULL);
1226 assert(gc->n);
1227 assert(gc->e);
1228  nb = sizeof(pkt) - (be - pkt);
1229  nw = 0;
1230  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->n);
1231  be += nw;
1232 
1233  nb = sizeof(pkt) - (be - pkt);
1234  nw = 0;
1235  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->e);
1236  be += nw;
1237  break;
1238  case PGPPUBKEYALGO_DSA:
1239 if (gc->pub_key) rpmgcDump(__FUNCTION__, gc->pub_key);
1240 assert(gc->pub_key);
1241 xx = gcry_sexp_extract_param (gc->pub_key, NULL, "+p +q +g +y", &gc->p, &gc->q, &gc->g, &gc->y, NULL);
1242 assert(gc->p);
1243 assert(gc->q);
1244 assert(gc->g);
1245 assert(gc->y);
1246  nb = sizeof(pkt) - (be - pkt);
1247  nw = 0;
1248  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->p);
1249  be += nw;
1250 
1251  nb = sizeof(pkt) - (be - pkt);
1252  nw = 0;
1253  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->q);
1254  be += nw;
1255 
1256  nb = sizeof(pkt) - (be - pkt);
1257  nw = 0;
1258  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->g);
1259  be += nw;
1260 
1261  nb = sizeof(pkt) - (be - pkt);
1262  nw = 0;
1263  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->y);
1264  be += nw;
1265  break;
1266  case PGPPUBKEYALGO_ECDSA:
1267 if (gc->pub_key) rpmgcDump(__FUNCTION__, gc->pub_key);
1268 assert(gc->pub_key);
1269  /* OID */
1270  { const char * s;
1271  size_t ns;
1272  size_t i;
1273  switch (gc->nbits) {
1274  case 192: s = "2a8648ce3d030101"; break;
1275  case 224: s = "2b81040021"; break;
1276  default: /* XXX FIXME: default? */
1277  case 256: s = "2a8648ce3d030107"; break;
1278  case 384: s = "2b81040022"; break;
1279  case 512: /* XXX sanity */
1280  case 521: s = "2b81040023"; break;
1281  }
1282  ns = strlen(s);
1283  *be++ = ns/2;
1284  for (i = 0; i < ns; i += 2)
1285  *be++ = (nibble(s[i]) << 4) | (nibble(s[i+1]));
1286  }
1287 
1288  /* Q */
1289 assert(gc->pub_key);
1290 xx = gcry_sexp_extract_param (gc->pub_key, NULL, "+q", &gc->q, NULL);
1291 assert(gc->q);
1292  nb = sizeof(pkt) - (be - pkt);
1293  nw = 0;
1294  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->q);
1295  be += nw;
1296  break;
1297  }
1298 
1299  pktlen = (be - pkt);
1300  nb = pktlen - 3;
1301  pkt[1] = (nb >> 8);
1302  pkt[2] = (nb );
1303 
1304  xx = pgpPubkeyFingerprint(pkt, pktlen, pubp->signid);
1305 
1306  dig->pub = memcpy(xmalloc(pktlen), pkt, pktlen);
1307  dig->publen = pktlen;
1308  rc = 1;
1309 
1310 SPEW(!rc, rc, dig);
1311  return rc;
1312 }
1313 
1314 int rpmgcExportSignature(pgpDig dig, /*@only@*/ DIGEST_CTX ctx)
1315 {
1316  uint8_t pkt[8192];
1317  uint8_t * be = pkt;
1318  uint8_t * h;
1319  size_t pktlen;
1320  time_t now = time(NULL);
1321  uint32_t bt;
1322  size_t nb;
1323  size_t nw;
1324  pgpDigParams pubp = pgpGetPubkey(dig);
1325  pgpDigParams sigp = pgpGetSignature(dig);
1326  int rc = 0; /* assume failure */
1327  rpmgc gc = (rpmgc) dig->impl;
1328  int xx;
1329 
1330  sigp->tag = PGPTAG_SIGNATURE;
1331  *be++ = 0x80 | (sigp->tag << 2) | 0x01;
1332  be += 2; /* pktlen */
1333 
1334  sigp->hash = be;
1335  *be++ = sigp->version = 0x04; /* version */
1336  *be++ = sigp->sigtype = PGPSIGTYPE_BINARY; /* sigtype */
1337  *be++ = sigp->pubkey_algo = pubp->pubkey_algo; /* pubkey_algo */
1338  *be++ = sigp->hash_algo; /* hash_algo */
1339 
1340  be += 2; /* skip hashd length */
1341  h = (uint8_t *) be;
1342 
1343  *be++ = 1 + 4; /* signature creation time */
1345  bt = now;
1346  *be++ = sigp->time[0] = (bt >> 24);
1347  *be++ = sigp->time[1] = (bt >> 16);
1348  *be++ = sigp->time[2] = (bt >> 8);
1349  *be++ = sigp->time[3] = (bt );
1350 
1351  *be++ = 1 + 4; /* signature expiration time */
1353  bt = 30 * 24 * 60 * 60; /* XXX 30 days from creation */
1354  *be++ = sigp->expire[0] = (bt >> 24);
1355  *be++ = sigp->expire[1] = (bt >> 16);
1356  *be++ = sigp->expire[2] = (bt >> 8);
1357  *be++ = sigp->expire[3] = (bt );
1358 
1359 /* key expiration time (only on a self-signature) */
1360 
1361  *be++ = 1 + 1; /* exportable certification */
1363  *be++ = 0;
1364 
1365  *be++ = 1 + 1; /* revocable */
1366  *be++ = PGPSUBTYPE_REVOCABLE;
1367  *be++ = 0;
1368 
1369 /* notation data */
1370 
1371  sigp->hashlen = (be - h); /* set hashed length */
1372  h[-2] = (sigp->hashlen >> 8);
1373  h[-1] = (sigp->hashlen );
1374  sigp->hashlen += sizeof(struct pgpPktSigV4_s);
1375 
1376  if (sigp->hash != NULL)
1377  xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1378 
1379  if (sigp->version == (rpmuint8_t) 4) {
1380  uint8_t trailer[6];
1381  trailer[0] = sigp->version;
1382  trailer[1] = (rpmuint8_t)0xff;
1383  trailer[2] = (sigp->hashlen >> 24);
1384  trailer[3] = (sigp->hashlen >> 16);
1385  trailer[4] = (sigp->hashlen >> 8);
1386  trailer[5] = (sigp->hashlen );
1387  xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1388  }
1389 
1390  sigp->signhash16[0] = 0x00;
1391  sigp->signhash16[1] = 0x00;
1392  switch (pubp->pubkey_algo) {
1393  default:
1394 assert(0);
1395  break;
1396  case PGPPUBKEYALGO_RSA:
1397  xx = pgpImplSetRSA(ctx, dig, sigp); /* XXX signhash16 check fails */
1398  break;
1399  case PGPPUBKEYALGO_DSA:
1400  xx = pgpImplSetDSA(ctx, dig, sigp); /* XXX signhash16 check fails */
1401  break;
1402  case PGPPUBKEYALGO_ECDSA:
1403  xx = pgpImplSetECDSA(ctx, dig, sigp); /* XXX signhash16 check fails */
1404  break;
1405  }
1406  h = (uint8_t *) gc->digest;
1407  sigp->signhash16[0] = h[0];
1408  sigp->signhash16[1] = h[1];
1409 
1410  /* XXX pgpImplVec forces "--usecrypto foo" to also be used */
1411  xx = pgpImplSign(dig);
1412 assert(xx == 1);
1413 
1414  be += 2; /* skip unhashed length. */
1415  h = be;
1416 
1417  *be++ = 1 + 8; /* issuer key ID */
1418  *be++ = PGPSUBTYPE_ISSUER_KEYID;
1419  *be++ = pubp->signid[0];
1420  *be++ = pubp->signid[1];
1421  *be++ = pubp->signid[2];
1422  *be++ = pubp->signid[3];
1423  *be++ = pubp->signid[4];
1424  *be++ = pubp->signid[5];
1425  *be++ = pubp->signid[6];
1426  *be++ = pubp->signid[7];
1427 
1428  bt = (be - h); /* set unhashed length */
1429  h[-2] = (bt >> 8);
1430  h[-1] = (bt );
1431 
1432  *be++ = sigp->signhash16[0]; /* signhash16 */
1433  *be++ = sigp->signhash16[1];
1434 
1435  switch (pubp->pubkey_algo) {
1436  default:
1437 assert(0);
1438  break;
1439  case PGPPUBKEYALGO_RSA:
1440 if (gc->sig) rpmgcDump(__FUNCTION__, gc->sig);
1441 assert(gc->sig);
1442 xx = gcry_sexp_extract_param (gc->sig, NULL, "+s", &gc->c, NULL);
1443 assert(gc->c);
1444  nb = sizeof(pkt) - (be - pkt);
1445  nw = 0;
1446  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->c);
1447  be += nw;
1448  break;
1449  case PGPPUBKEYALGO_DSA:
1450 if (gc->sig) rpmgcDump(__FUNCTION__, gc->sig);
1451 assert(gc->sig);
1452 xx = gcry_sexp_extract_param (gc->sig, NULL, "+r +s", &gc->r, &gc->s, NULL);
1453 assert(gc->r);
1454 assert(gc->s);
1455  nb = sizeof(pkt) - (be - pkt);
1456  nw = 0;
1457  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->r);
1458  be += nw;
1459 
1460  nb = sizeof(pkt) - (be - pkt);
1461  nw = 0;
1462  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, 1024, &nw, gc->s);
1463  be += nw;
1464  break;
1465  case PGPPUBKEYALGO_ECDSA:
1466 if (gc->sig) rpmgcDump(__FUNCTION__, gc->sig);
1467 assert(gc->sig);
1468 xx = gcry_sexp_extract_param (gc->sig, NULL, "+r +s", &gc->r, &gc->s, NULL);
1469 assert(gc->r);
1470 assert(gc->s);
1471  nb = sizeof(pkt) - (be - pkt);
1472  nw = 0;
1473  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, nb, &nw, gc->r);
1474  be += nw;
1475 
1476  nb = sizeof(pkt) - (be - pkt);
1477  nw = 0;
1478  xx = gcry_mpi_print(GCRYMPI_FMT_PGP, be, 1024, &nw, gc->s);
1479  be += nw;
1480  break;
1481  }
1482 
1483  pktlen = (be - pkt); /* packet length */
1484  nb = pktlen - 3;
1485  pkt[1] = (nb >> 8);
1486  pkt[2] = (nb );
1487 
1488  dig->sig = memcpy(xmalloc(pktlen), pkt, pktlen);
1489  dig->siglen = pktlen;
1490  rc = 1;
1491 
1492 SPEW(!rc, rc, dig);
1493  return rc;
1494 }
1495 
1496 #endif /* WITH_GCRYPT */
const bson * b
Definition: bson.h:280
pgpDigParams pgpGetPubkey(pgpDig dig)
Return OpenPGP pubkey parameters.
Definition: rpmpgp.c:1397
struct rpmgc_s * rpmgc
Definition: rpmgc.h:22
void * next
Definition: rpmiotypes.h:47
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
struct pgpDigParams_s * pgpDigParams
Definition: rpmiotypes.h:101
int rpmgcExportSignature(pgpDig dig, DIGEST_CTX ctx)
const char int time
Definition: bson.h:1005
static unsigned char nibble(char c)
Convert hex to binary nibble.
Definition: pack.c:628
int errno
5.2.3.
Definition: rpmpgp.h:376
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
static int pgpImplSign(pgpDig dig)
Definition: rpmpgp.h:1867
const char * pgpPubkeyAlgo2Name(uint32_t algo)
Definition: rpmpgp.c:1193
static int pgpImplSetDSA(DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
Definition: rpmpgp.h:1785
char * alloca()
Yet Another syslog(3) API clone.
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:986
void vrpmlog(unsigned code, const char *fmt, va_list ap)
Same as _rpmlog with stdarg argument list.
Definition: rpmlog.c:204
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
mongo_error_t err
Definition: mongo.h:922
#define SPEW(_list)
Definition: rpmns.c:45
pgpHashAlgo rpmDigestAlgo(DIGEST_CTX ctx)
Return digest algorithm identifier.
Definition: digest.c:191
pgpDigParams pgpGetSignature(pgpDig dig)
Return OpenPGP signature parameters.
Definition: rpmpgp.c:1392
int _pgp_error_count
Definition: rpmpgp.c:48
#define fail(_err)
Definition: yarn.c:199
Digest private data.
Definition: digest.c:130
struct pgpDig_s * pgpDig
Definition: rpmiotypes.h:97
static int pgpImplSetECDSA(DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
Definition: rpmpgp.h:1803
int rpmgcExportPubkey(pgpDig dig)
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3238
static int pgpImplSetRSA(DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
Definition: rpmpgp.h:1776
static void output(int indent, int *offset, const char *fmt,...)
Definition: rpmmtree.c:2497
static unsigned int pgpMpiLen(const rpmuint8_t *p)
Return no.
Definition: rpmpgp.h:1087
const char const int i
Definition: bson.h:778
static int xisdigit(int c)
Definition: rpmiotypes.h:546
int pgpPubkeyFingerprint(const rpmuint8_t *pkt, size_t pktlen, rpmuint8_t *keyid)
Print/parse an OpenPGP subtype packet.
Definition: rpmpgp.c:1029
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
const bson * in
Definition: bson.h:746
pgpImplVecs_t rpmgcImplVecs
Implementation specific parameter storage.
#define until(a)
Definition: yarn.c:292
const char char type
Definition: bson.h:908
const char * pgpHashAlgo2Name(uint32_t algo)
Definition: rpmpgp.c:1188
int rpmDigestFinal(DIGEST_CTX ctx, void *datap, size_t *lenp, int asAscii)
Return digest and destroy context.
Definition: digest.c:1000
#define xmalloc
Definition: system.h:32
static cptr_t current[2]
Definition: rpmrc.c:128
#define D_(Text)
Definition: system.h:526
static char * pgpHexStr(const rpmuint8_t *p, size_t plen)
Return hex formatted representation of bytes.
Definition: rpmpgp.h:1124
int _pgp_print
Definition: rpmpgp.c:45
int _pgp_debug
Definition: rpmpgp.c:42
const char * ns
Definition: mongo.h:326