rpm  5.4.14
rpmgc.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmiotypes.h>
8 #include <rpmmacro.h>
9 #define _RPMGC_INTERNAL
10 #if defined(WITH_GCRYPT)
11 #define _RPMPGP_INTERNAL
12 #include <rpmgc.h>
13 #endif
14 
15 #include "debug.h"
16 
17 #if defined(WITH_GCRYPT)
18 
19 /*@access pgpDig @*/
20 /*@access pgpDigParams @*/
21 
22 /*@-redecl@*/
23 /*@unchecked@*/
24 extern int _pgp_debug;
25 
26 /*@unchecked@*/
27 extern int _pgp_print;
28 /*@=redecl@*/
29 
30 /*@unchecked@*/
31 static int _rpmgc_debug;
32 
33 #define SPEW(_t, _rc, _dig) \
34  { if ((_t) || _rpmgc_debug || _pgp_debug < 0) \
35  fprintf(stderr, "<-- %s(%p) %s\t%s\n", __FUNCTION__, (_dig), \
36  ((_rc) ? "OK" : "BAD"), (_dig)->pubkey_algoN); \
37  }
38 
39 /*==============================================================*/
40 /* Swiped (and largely rewritten) from LGPL gnupg/common/openpgp-oid.c */
41 
42 /* Helper for openpgp_oid_from_str. */
43 static size_t
44 make_flagged_int(unsigned long value, unsigned char * b, size_t nb)
45 {
46  int more = 0;
47  int shift;
48 
49  /* fixme: figure out the number of bits in an ulong and start with
50  that value as shift (after making it a multiple of 7) a more
51  straigtforward implementation is to do it in reverse order using
52  a temporary buffer - saves a lot of compares */
53  for (more = 0, shift = 28; shift > 0; shift -= 7) {
54  if (more || value >= (1UL << shift)) {
55  b[nb++] = 0x80 | (value >> shift);
56  value -= (value >> shift) << shift;
57  more = 1;
58  }
59  }
60  b[nb++] = value;
61  return nb;
62 }
63 
64 /*
65  * Convert the OID given in dotted decimal form in STRING to an DER
66  * encoding and store it as an opaque value at R_MPI. The format of
67  * the DER encoded is not a regular ASN.1 object but the modified
68  * format as used by OpenPGP for the ECC curve description. On error
69  * the function returns and error code an NULL is stored at R_BUG.
70  * Note that scanning STRING stops at the first white space
71  * character.
72  */
73 static
74 int openpgp_oid_from_str(const char * s, gcry_mpi_t * r_mpi)
75 {
76  const char * se = s;
77  size_t ns = (s ? strlen(s) : 0);
78  unsigned char * b = xmalloc(ns + 2 + 1);
79  size_t nb = 1; /* count the length byte */
80  const char *endp;
81  unsigned long val;
82  unsigned long val1 = 0;
83  int arcno = 0;
84  int rc = -1; /* assume failure */
85 
86  *r_mpi = NULL;
87 
88  if (s == NULL || s[0] == '\0')
89  goto exit;
90 
91  do {
92  arcno++;
93  val = strtoul(se, (char **) &endp, 10);
94  if (!xisdigit(*se) || !(*endp == '.' || *endp == '\0'))
95  goto exit;
96 
97  if (*endp == '.')
98  se = endp + 1;
99 
100  switch (arcno) {
101  case 1:
102  if (val > 2) /* Not allowed. */
103  goto exit;
104  val1 = val;
105  break;
106  case 2: /* Combine the 1st 2 arcs into octet. */
107  if (val1 < 2) {
108  if (val > 39)
109  goto exit;
110  b[nb++] = val1 * 40 + val;
111  } else {
112  val += 80;
113  nb = make_flagged_int(val, b, nb);
114  }
115  break;
116  default:
117  nb = make_flagged_int(val, b, nb);
118  break;
119  }
120  } while (*endp == '.');
121 
122  if (arcno == 1 || nb < 2 || nb > 254) /* Can't encode 1st arc. */
123  goto exit;
124 
125  *b = nb - 1;
126  *r_mpi = gcry_mpi_set_opaque(NULL, b, nb * 8);
127  if (*r_mpi) /* Success? */
128  rc = 0;
129 
130 exit:
131  if (rc)
132  b = _free(b);
133  return rc;
134 }
135 
136 /*
137  * Return a malloced string represenation of the OID in the opaque MPI
138  * A. In case of an error NULL is returned and ERRNO is set.
139  */
140 static
141 char *openpgp_oid_to_str(gcry_mpi_t a)
142 {
143  unsigned int nbits = 0;
144  const unsigned char * b = (a && gcry_mpi_get_flag(a, GCRYMPI_FLAG_OPAQUE))
145  ? gcry_mpi_get_opaque(a, &nbits)
146  : NULL;
147  size_t nb = (nbits + 7) / 8;
148  /* 2 chars in prefix, (3+1) decimalchars/byte, trailing NUL, skip length */
149  size_t nt = (2 + ((nb ? nb-1 : 0) * (3+1)) + 1);
150  char *t = xmalloc(nt);
151  char *te = t;
152  size_t ix = 0;
153  unsigned long valmask = (unsigned long) 0xfe << (8 * (sizeof(valmask) - 1));
154  unsigned long val;
155 
156  *te = '\0';
157 
158  /* Check oid consistency, skipping the length byte. */
159  if (b == NULL || nb == 0 || *b++ != --nb)
160  goto invalid;
161 
162  /* Add the prefix and decode the 1st byte */
163  if (b[ix] < 40)
164  te += sprintf(te, "0.%d", b[ix]);
165  else if (b[ix] < 80)
166  te += sprintf(te, "1.%d", b[ix] - 40);
167  else {
168  val = b[ix] & 0x7f;
169  while ((b[ix] & 0x80) && ++ix < nb) {
170  if ((val & valmask))
171  goto overflow;
172  val <<= 7;
173  val |= b[ix] & 0x7f;
174  }
175  val -= 80;
176  te += sprintf(te, "2.%lu", val);
177  }
178  *te = '\0';
179 
180  /* Append the (dotted) oid integers */
181  for (ix++; ix < nb; ix++) {
182  val = b[ix] & 0x7f;
183  while ((b[ix] & 0x80) && ++ix < nb) {
184  if ((val & valmask))
185  goto overflow;
186  val <<= 7;
187  val |= b[ix] & 0x7f;
188  }
189  te += sprintf(te, ".%lu", val);
190  }
191  *te = '\0';
192  goto exit;
193 
194 overflow:
195  /*
196  * Return a special OID (gnu.gnupg.badoid) to indicate the error
197  * case. The OID is broken and thus we return one which can't do
198  * any harm. Formally this does not need to be a bad OID but an OID
199  * with an arc that can't be represented in a 32 bit word is more
200  * than likely corrupt.
201  */
202  t = _free(t);
203  t = xstrdup("1.3.6.1.4.1.11591.2.12242973");
204  goto exit;
205 
206 invalid:
207  errno = EINVAL;
208  t = _free(t);
209  goto exit;
210 
211 exit:
212  return t;
213 }
214 
215 /*==============================================================*/
216 
217 static const char * rpmgcHashAlgo2Name(uint32_t algo)
218 {
219  return pgpValStr(pgpHashTbl, (rpmuint8_t)algo);
220 }
221 
222 static const char * rpmgcPubkeyAlgo2Name(uint32_t algo)
223 {
224  return pgpValStr(pgpPubkeyTbl, (rpmuint8_t)algo);
225 }
226 
227 static void fail(const char *format, ...)
228 {
229  va_list arg_ptr;
230 
231  va_start(arg_ptr, format);
232  vfprintf(stderr, format, arg_ptr);
233  va_end(arg_ptr);
235 }
236 
237 static
238 void rpmgcDump(const char * msg, gcry_sexp_t sexp)
239  /*@*/
240 {
241  if (_rpmgc_debug || _pgp_debug) {
242  size_t nb = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
243  char * buf = (char *) alloca(nb+1);
244 
245  nb = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buf, nb);
246  buf[nb] = '\0';
247  fprintf(stderr, "========== %s:\n%s", msg, buf);
248  }
249  return;
250 }
251 
252 static
253 gcry_error_t rpmgcErr(rpmgc gc, const char * msg, gcry_error_t err)
254  /*@*/
255 {
256  /* XXX Don't spew on expected failures ... */
257  if (err && gcry_err_code(err) != gc->badok)
258  fprintf (stderr, "rpmgc: %s(0x%0x): %s/%s\n",
259  msg, (unsigned)err, gcry_strsource(err), gcry_strerror(err));
260  return err;
261 }
262 
263 static
264 int rpmgcSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
265  /*@modifies dig @*/
266 {
267  rpmgc gc = (rpmgc) dig->impl;
268  gcry_error_t err;
269  const char * hash_algo_name = NULL;
270  int rc = 1; /* assume error */
271  int xx;
272 pgpDigParams pubp = pgpGetPubkey(dig);
273 dig->pubkey_algoN = rpmgcPubkeyAlgo2Name(pubp->pubkey_algo);
274 dig->hash_algoN = rpmgcHashAlgo2Name(sigp->hash_algo);
275 
276  switch (sigp->hash_algo) {
277  case PGPHASHALGO_MD5:
278  hash_algo_name = "md5";
279  break;
280  case PGPHASHALGO_SHA1:
281  hash_algo_name = "sha1";
282  break;
284  hash_algo_name = "ripemd160"; /* XXX FIXME: RPM != GCRYPT name */
285  break;
286  case PGPHASHALGO_MD2:
287  hash_algo_name = "md2";
288  break;
290  hash_algo_name = "tiger";
291  break;
293 #ifdef NOTYET
294  hash_algo_name = "haval";
295 #endif
296  break;
297  case PGPHASHALGO_SHA256:
298  hash_algo_name = "sha256";
299  break;
300  case PGPHASHALGO_SHA384:
301  hash_algo_name = "sha384";
302  break;
303  case PGPHASHALGO_SHA512:
304  hash_algo_name = "sha512";
305  break;
306  case PGPHASHALGO_SHA224:
307 #ifdef NOTYET
308  hash_algo_name = "sha224";
309 #endif
310  break;
311  default:
312  break;
313  }
314  if (hash_algo_name == NULL)
315  goto exit;
316 
317  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
318  ctx = NULL; /* XXX avoid double free */
319 
320  /* Set RSA hash. */
321  err = rpmgcErr(gc, "RSA c",
322  gcry_sexp_build(&gc->hash, NULL,
323  "(data (flags pkcs1) (hash %s %b))", hash_algo_name, gc->digestlen, gc->digest) );
324 if (_pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
325 
326  /* Compare leading 16 bits of digest for quick check. */
327  { const rpmuint8_t *s = (const rpmuint8_t *) gc->digest;
328  const rpmuint8_t *t = sigp->signhash16;
329  rc = memcmp(s, t, sizeof(sigp->signhash16));
330  }
331 
332 exit:
333  if (ctx) { /* XXX Free the context on error returns. */
334  xx = rpmDigestFinal(ctx, NULL, NULL, 0);
335  ctx = NULL;
336  }
337 SPEW(0, !rc, dig);
338  return rc;
339 }
340 
341 static
342 int rpmgcSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
343  /*@modifies dig @*/
344 {
345  rpmgc gc = (rpmgc) dig->impl;
346  gcry_error_t err;
347  int rc;
348  int xx;
349 pgpDigParams pubp = pgpGetPubkey(dig);
350 dig->pubkey_algoN = rpmgcPubkeyAlgo2Name(pubp->pubkey_algo);
351 dig->hash_algoN = rpmgcHashAlgo2Name(sigp->hash_algo);
352 
353 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
354  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
355 
356  /* Set DSA hash. */
357 /*@-moduncon -noeffectuncon @*/
358  { gcry_mpi_t c = NULL;
359  /* XXX truncate to 160 bits for DSA2? */
360  err = rpmgcErr(gc, "DSA c",
361  gcry_mpi_scan(&c, GCRYMPI_FMT_USG, gc->digest, 160/8, NULL));
362  err = rpmgcErr(gc, "DSA gc->hash",
363  gcry_sexp_build(&gc->hash, NULL,
364  "(data (flags raw) (value %m))", c) );
365  gcry_mpi_release(c);
366 if (_pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
367  }
368 /*@=moduncon =noeffectuncon @*/
369 
370  /* Compare leading 16 bits of digest for quick check. */
371  rc = memcmp(gc->digest, sigp->signhash16, sizeof(sigp->signhash16));
372 SPEW(0, !rc, dig);
373  return rc;
374 }
375 
376 static
377 int rpmgcSetELG(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
378  /*@*/
379 {
380  rpmgc gc = (rpmgc) dig->impl;
381  gcry_error_t err;
382  int rc = 0; /* XXX always fail. */
383  int xx;
384 pgpDigParams pubp = pgpGetPubkey(dig);
385 dig->pubkey_algoN = rpmgcPubkeyAlgo2Name(pubp->pubkey_algo);
386 dig->hash_algoN = rpmgcHashAlgo2Name(sigp->hash_algo);
387 
388 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
389  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
390 
391  /* Set ELG hash. */
392 /*@-moduncon -noeffectuncon @*/
393  { gcry_mpi_t c = NULL;
394  /* XXX truncate to 160 bits for DSA2? */
395  err = rpmgcErr(gc, "ELG c",
396  gcry_mpi_scan(&c, GCRYMPI_FMT_USG, gc->digest, 160/8, NULL));
397  err = rpmgcErr(gc, "ELG gc->hash",
398  gcry_sexp_build(&gc->hash, NULL,
399  "(data (flags raw) (value %m))", c) );
400  gcry_mpi_release(c);
401 if (1 || _pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
402  }
403 /*@=moduncon =noeffectuncon @*/
404 
405  /* Compare leading 16 bits of digest for quick check. */
406  rc = memcmp(gc->digest, sigp->signhash16, sizeof(sigp->signhash16));
407 
408 SPEW(0, !rc, dig);
409  return rc;
410 }
411 
412 static
413 int rpmgcSetECDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
414  /*@*/
415 {
416  rpmgc gc = (rpmgc) dig->impl;
417  int rc = 1; /* assume failure. */
418  gpg_error_t err;
419  int xx;
420 pgpDigParams pubp = pgpGetPubkey(dig);
421 dig->pubkey_algoN = rpmgcPubkeyAlgo2Name(pubp->pubkey_algo);
422 dig->hash_algoN = rpmgcHashAlgo2Name(sigp->hash_algo);
423 
424 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
425 gc->digest = _free(gc->digest);
426 gc->digestlen = 0;
427  xx = rpmDigestFinal(ctx, (void **)&gc->digest, &gc->digestlen, 0);
428 
429  /* Set ECDSA hash. */
430  { gcry_mpi_t c = NULL;
431  err = rpmgcErr(gc, "ECDSA c",
432  gcry_mpi_scan(&c, GCRYMPI_FMT_USG, gc->digest, gc->digestlen, NULL));
433 if (gc->hash) {
434  gcry_sexp_release(gc->hash); gc->hash = NULL;
435 }
436  err = rpmgcErr(gc, "ECDSA gc->hash",
437  gcry_sexp_build(&gc->hash, NULL,
438  "(data (flags raw) (value %m))", c) );
439  gcry_mpi_release(c);
440 if (_pgp_debug < 0) rpmgcDump("gc->hash", gc->hash);
441  }
442 
443  /* Compare leading 16 bits of digest for quick check. */
444  rc = memcmp(gc->digest, sigp->signhash16, sizeof(sigp->signhash16));
445 
446 SPEW(0, !rc, dig);
447  return rc;
448 }
449 
450 static int rpmgcErrChk(pgpDig dig, const char * msg, int rc, unsigned expected)
451 {
452 rpmgc gc = (rpmgc) dig->impl;
453  /* Was the return code the expected result? */
454  rc = (gcry_err_code(gc->err) != expected);
455  if (rc)
456  fail("%s failed: %s\n", msg, gpg_strerror(gc->err));
457 /* XXX FIXME: pgpImplStrerror */
458  return rc; /* XXX 0 on success */
459 }
460 
461 static int rpmgcAvailable(rpmgc gc, int algo, int rc)
462 {
463  /* Permit non-certified algo's if not in FIPS mode. */
464  if (rc && !gc->in_fips_mode)
465  rc = 0;
466 #ifdef NOTNOW
467  if (rc)
468  rpmlog(RPMLOG_INFO," algorithm %d not available in fips mode\n", algo);
469 #else
470 /* XXX FIXME: refactor back into trsa.c */
471  if (rc)
472  fprintf(stderr," algorithm %d not available in fips mode\n", algo);
473 #endif
474  return rc; /* XXX 0 on success */
475 }
476 
477 static int rpmgcAvailableCipher(pgpDig dig, int algo)
478 {
479  rpmgc gc = (rpmgc) dig->impl;
480  return rpmgcAvailable(gc, algo, gcry_cipher_test_algo(algo));
481 }
482 
483 static int rpmgcAvailableDigest(pgpDig dig, int algo)
484 {
485  rpmgc gc = (rpmgc) dig->impl;
486  int rc = 0; /* assume available */
487  rc = rpmgcAvailable(gc, algo,
488  (gcry_md_test_algo(algo) || algo == PGPHASHALGO_MD5));
489  return rc;
490 }
491 
492 static int rpmgcAvailablePubkey(pgpDig dig, int algo)
493 {
494  rpmgc gc = (rpmgc) dig->impl;
495  int rc = 0; /* assume available */
496  rc = rpmgcAvailable(gc, algo, gcry_pk_test_algo(algo));
497  return rc;
498 }
499 
500 static char * _curve_nist = "NIST P-256"; /* XXX FIXME */
501 static char * _curve_oid = "1.2.840.10045.3.1.7";/* XXX FIXME */
502 static char * _curve_x962 = "prime256v1"; /* XXX FIXME */
503 static char * _curve_secp = "secp256r1"; /* XXX FIXME */
504 
505 static
506 int rpmgcVerify(pgpDig dig)
507 {
508  rpmgc gc = (rpmgc) dig->impl;
509  int rc;
510 pgpDigParams pubp = pgpGetPubkey(dig);
511 pgpDigParams sigp = pgpGetSignature(dig);
512 dig->pubkey_algoN = rpmgcPubkeyAlgo2Name(pubp->pubkey_algo);
513 dig->hash_algoN = rpmgcHashAlgo2Name(sigp->hash_algo);
514 
515  if (gc->sig == NULL) {
516  pgpDigParams pubp = pgpGetPubkey(dig);
517  switch (pubp->pubkey_algo) {
518  case PGPPUBKEYALGO_RSA:
519 assert(gc->c);
520  gc->err = rpmgcErr(gc, "RSA gc->sig",
521  gcry_sexp_build(&gc->sig, NULL,
522  "(sig-val (RSA (s %m)))", gc->c) );
523  break;
524  case PGPPUBKEYALGO_DSA:
525 assert(gc->r);
526 assert(gc->s);
527  gc->err = rpmgcErr(gc, "DSA gc->sig",
528  gcry_sexp_build(&gc->sig, NULL,
529  "(sig-val (DSA (r %m) (s %m)))", gc->r, gc->s) );
530  break;
531  case PGPPUBKEYALGO_ELGAMAL: /* XXX FIXME: untested. */
532 assert(gc->r);
533 assert(gc->s);
534  gc->err = rpmgcErr(gc, "ELG gc->sig",
535  gcry_sexp_build(&gc->sig, NULL,
536  "(sig-val (ELG (r %m) (s %m)))", gc->r, gc->s) );
537  break;
538  case PGPPUBKEYALGO_ECDSA: /* XXX FIXME */
539 assert(gc->r);
540 assert(gc->s);
541  gc->err = rpmgcErr(gc, "ECDSA gc->sig",
542  gcry_sexp_build(&gc->sig, NULL,
543  "(sig-val (ECDSA (r %m) (s %m)))", gc->r, gc->s) );
544  break;
545  default:
546 assert(0);
547  break;
548  }
549 if (_pgp_debug < 0)
550 rpmgcDump("gc->sig", gc->sig);
551  }
552 
553  if (gc->pub_key == NULL) {
554  pgpDigParams pubp = pgpGetPubkey(dig);
555  switch (pubp->pubkey_algo) {
556  case PGPPUBKEYALGO_RSA:
557 assert(gc->n);
558 assert(gc->e);
559 /* gc->d priv_key */
560 /* gc->p priv_key optional */
561 /* gc->q priv_key optional */
562 /* gc->u priv_key optional */
563  gc->err = rpmgcErr(gc, "RSA gc->pub_key",
564  gcry_sexp_build(&gc->pub_key, NULL,
565  "(public-key (RSA (n %m) (e %m)))", gc->n, gc->e) );
566  break;
567  case PGPPUBKEYALGO_DSA:
568 assert(gc->p);
569 assert(gc->q);
570 assert(gc->g);
571 assert(gc->y);
572 /* gc->x priv_key */
573  gc->err = rpmgcErr(gc, "DSA gc->pub_key",
574  gcry_sexp_build(&gc->pub_key, NULL,
575  "(public-key (DSA (p %m) (q %m) (g %m) (y %m)))",
576  gc->p, gc->q, gc->g, gc->y) );
577  break;
578  case PGPPUBKEYALGO_ELGAMAL: /* XXX FIXME: untested. */
579 assert(gc->p);
580 assert(gc->g);
581 assert(gc->y);
582 /* gc->x priv_key */
583  gc->err = rpmgcErr(gc, "ELG gc->pub_key",
584  gcry_sexp_build(&gc->pub_key, NULL,
585  "(public-key (ELG (p %m) (g %m) (y %m)))",
586  gc->p, gc->g, gc->y) );
587  break;
588  case PGPPUBKEYALGO_ECDSA: /* XXX FIXME */
589 assert(gc->o);
590 /* gc->p curve */
591 /* gc->a curve */
592 /* gc->b curve */
593 /* gc->g curve */
594 /* gc->n curve */
595 assert(gc->q);
596 /* gc->d priv_key */
597  { unsigned int nbits = 0;
598  rpmuint8_t * b = gcry_mpi_get_opaque(gc->o, &nbits);
599  size_t nb = (nbits+7)/8;
600  char * t;
601 fprintf(stderr, "oid: %p[%u] %s\n", b, nbits, pgpHexStr(b, nb));
602  t = openpgp_oid_to_str(gc->o);
603 fprintf(stderr, "\t%s\n", t);
604  t = _free(t);
605  }
606  gc->err = rpmgcErr(gc, "ECDSA gc->pub_key",
607  gcry_sexp_build(&gc->pub_key, NULL,
608  "(public-key (ECDSA (curve \"%s\") (q %m))",
609  _curve_x962, gc->q) );
610  break;
611  default:
612 assert(0);
613  break;
614  }
615 if (_pgp_debug < 0)
616 rpmgcDump("gc->pub_key", gc->pub_key);
617  }
618 
619  /* Verify the signature. */
620  gc->err = rpmgcErr(gc, "gcry_pk_verify",
621  gcry_pk_verify (gc->sig, gc->hash, gc->pub_key));
622 
623  rc = (gc->err == 0);
624 
625 SPEW(0, rc, dig);
626  return rc; /* XXX 1 on success */
627 }
628 
629 static
630 int rpmgcSign(pgpDig dig)
631 {
632  rpmgc gc = (rpmgc) dig->impl;
633  int rc;
634 pgpDigParams pubp = pgpGetPubkey(dig);
635 pgpDigParams sigp = pgpGetSignature(dig);
636 dig->pubkey_algoN = rpmgcPubkeyAlgo2Name(pubp->pubkey_algo);
637 dig->hash_algoN = rpmgcHashAlgo2Name(sigp->hash_algo);
638 
639  /* Sign the hash. */
640  gc->err = rpmgcErr(gc, "gcry_pk_sign",
641  gcry_pk_sign (&gc->sig, gc->hash, gc->sec_key));
642 
643 if (_pgp_debug < 0 && gc->sig) rpmgcDump("gc->sig", gc->sig);
644 
645  rc = (gc->err == 0);
646 
647 SPEW(!rc, rc, dig);
648  return rc; /* XXX 1 on success */
649 }
650 
651 static
652 int rpmgcGenerate(pgpDig dig)
653  /*@*/
654 {
655  rpmgc gc = (rpmgc) dig->impl;
656  int rc;
657 pgpDigParams pubp = pgpGetPubkey(dig);
658 dig->pubkey_algoN = rpmgcPubkeyAlgo2Name(pubp->pubkey_algo);
659 
660 /* XXX FIXME: gc->{key_spec,key_pair} could be local. */
661 /* XXX FIXME: gc->qbits w DSA? curve w ECDSA? other params? */
662  switch (pubp->pubkey_algo) {
663  case PGPPUBKEYALGO_RSA:
664 if (gc->nbits == 0) gc->nbits = 1024; /* XXX FIXME */
665  gc->err = rpmgcErr(gc, "gc->key_spec",
666  gcry_sexp_build(&gc->key_spec, NULL,
667  gc->in_fips_mode
668  ? "(genkey (RSA (nbits %d)))"
669  : "(genkey (RSA (nbits %d)(transient-key)))",
670  gc->nbits));
671  break;
672  case PGPPUBKEYALGO_DSA:
673 if (gc->nbits == 0) gc->nbits = 1024; /* XXX FIXME */
674  gc->err = rpmgcErr(gc, "gc->key_spec",
675  gcry_sexp_build(&gc->key_spec, NULL,
676  gc->in_fips_mode
677  ? "(genkey (DSA (nbits %d)))"
678  : "(genkey (DSA (nbits %d)(transient-key)))",
679  gc->nbits));
680  break;
681  case PGPPUBKEYALGO_ELGAMAL: /* XXX FIXME: untested. */
682 if (gc->nbits == 0) gc->nbits = 1024; /* XXX FIXME */
683  gc->err = rpmgcErr(gc, "gc->key_spec",
684  gcry_sexp_build(&gc->key_spec, NULL,
685  gc->in_fips_mode
686  ? "(genkey (ELG (nbits %d)))"
687  : "(genkey (ELG (nbits %d)(transient-key)))",
688  gc->nbits));
689  break;
690  case PGPPUBKEYALGO_ECDSA:
691 if (gc->nbits == 0) gc->nbits = 256; /* XXX FIXME */
692 #ifdef DYING
693  gc->err = rpmgcErr(gc, "gc->key_spec",
694  gcry_sexp_build(&gc->key_spec, NULL,
695  gc->in_fips_mode
696  ? "(genkey (ECDSA (nbits %d)))"
697  : "(genkey (ECDSA (nbits %d)(transient-key)))",
698  gc->nbits));
699 #else
700  /* XXX gcry_sexp_build %s format is fubar in libgcrypt-1.5.3 ?!? */
701  { char * t = rpmExpand("(genkey (ECDSA (curve \"", _curve_nist, "\")",
702  gc->in_fips_mode ? "" : "(transient-key)",
703  "))", NULL);
704  gc->err = rpmgcErr(gc, "gc->key_spec",
705  gcry_sexp_build(&gc->key_spec, NULL, t));
706  t = _free(t);
707  }
708 #endif
709  break;
710  default:
711 assert(0);
712  break;
713  }
714  if (gc->err)
715  goto exit;
716 if ((_rpmgc_debug || _pgp_debug < 0) && gc->key_spec) rpmgcDump("gc->key_spec", gc->key_spec);
717 
718  /* Generate the key pair. */
719  gc->err = rpmgcErr(gc, "gc->key_pair",
720  gcry_pk_genkey(&gc->key_pair, gc->key_spec));
721  if (gc->err)
722  goto exit;
723 if ((_rpmgc_debug || _pgp_debug < 0) && gc->key_pair) rpmgcDump("gc->key_pair", gc->key_pair);
724 
725  gc->pub_key = gcry_sexp_find_token(gc->key_pair, "public-key", 0);
726  if (gc->pub_key == NULL)
727 /* XXX FIXME: refactor errmsg here. */
728  goto exit;
729 if ((_rpmgc_debug || _pgp_debug < 0) && gc->pub_key) rpmgcDump("gc->pub_key", gc->pub_key);
730 
731  gc->sec_key = gcry_sexp_find_token(gc->key_pair, "private-key", 0);
732  if (gc->sec_key == NULL)
733 /* XXX FIXME: refactor errmsg here. */
734  goto exit;
735 if ((_rpmgc_debug || _pgp_debug < 0) && gc->sec_key) rpmgcDump("gc->sec_key", gc->sec_key);
736 
737 exit:
738 
739  rc = (gc->err == 0 && gc->pub_key && gc->sec_key);
740 
741 #ifdef NOTYET
742 if (gc->key_spec) {
743  gcry_sexp_release(gc->key_spec);
744  gc->key_spec = NULL;
745 }
746 if (gc->key_pair) {
747  gcry_sexp_release(gc->key_pair);
748  gc->key_pair = NULL;
749 }
750 #endif
751 
752 SPEW(!rc, rc, dig);
753  return rc; /* XXX 1 on success */
754 }
755 
756 /*@-globuse -mustmod @*/
757 static
758 int rpmgcMpiItem(/*@unused@*/ const char * pre, pgpDig dig, int itemno,
759  const rpmuint8_t * p,
760  /*@unused@*/ /*@null@*/ const rpmuint8_t * pend)
761  /*@globals fileSystem @*/
762  /*@modifies dig, fileSystem @*/
763 {
764  rpmgc gc = (rpmgc) dig->impl;
765  size_t nb;
766  const char * mpiname = "";
767  gcry_mpi_t * mpip = NULL;
768  size_t nscan = 0;
769  int rc = 0;
770 
771  switch (itemno) {
772  default:
773 assert(0);
774  case 50: /* ECDSA r */
775  mpiname = "ECDSA r"; mpip = &gc->r;
776  break;
777  case 51: /* ECDSA s */
778  mpiname = "ECDSA s"; mpip = &gc->s;
779  break;
780  case 60: /* ECDSA curve OID */
781  mpiname = "ECDSA o"; mpip = &gc->o;
782  break;
783  case 61: /* ECDSA Q */
784  mpiname = "ECDSA Q"; mpip = &gc->q;
785  break;
786  case 10: /* RSA m**d */
787  mpiname = "RSA m**d"; mpip = &gc->c;
788  break;
789  case 20: /* DSA r */
790  mpiname = "DSA r"; mpip = &gc->r;
791  break;
792  case 21: /* DSA s */
793  mpiname = "DSA s"; mpip = &gc->s;
794  break;
795  case 30: /* RSA n */
796  mpiname = "RSA n"; mpip = &gc->n;
797  break;
798  case 31: /* RSA e */
799  mpiname = "RSA e"; mpip = &gc->e;
800  break;
801  case 40: /* DSA p */
802  mpiname = "DSA p"; mpip = &gc->p;
803  break;
804  case 41: /* DSA q */
805  mpiname = "DSA q"; mpip = &gc->q;
806  break;
807  case 42: /* DSA g */
808  mpiname = "DSA g"; mpip = &gc->g;
809  break;
810  case 43: /* DSA y */
811  mpiname = "DSA y"; mpip = &gc->y;
812  break;
813  }
814 
815  if (mpip == NULL)
816  goto exit;
817 
818 /*@-moduncon -noeffectuncon @*/
819  if (itemno == 60) {
820  nb = (pend >= p ? (pend - p) : 0);
821 assert(nb >= 2 && nb <= 254);
822  *mpip = gcry_mpi_set_opaque(*mpip, (void *)p, 8*nb);
823  } else {
824  nb = pgpMpiLen(p);
825  gc->err = rpmgcErr(gc, mpiname,
826  gcry_mpi_scan(mpip, GCRYMPI_FMT_PGP, p, nb, &nscan) );
827 /*@=moduncon =noeffectuncon @*/
828 assert(nb == nscan);
829  }
830 
831  if (_pgp_debug < 0)
832  { unsigned nbits = gcry_mpi_get_nbits(*mpip);
833  unsigned char * hex = NULL;
834  size_t nhex = 0;
835  gc->err = rpmgcErr(gc, "MPI print",
836  gcry_mpi_aprint(GCRYMPI_FMT_HEX, &hex, &nhex, *mpip) );
837  fprintf(stderr, "*** %s\t%5d:%s\n", mpiname, (int)nbits, hex);
838  hex = _free(hex);
839  }
840 
841 exit:
842  return rc;
843 }
844 /*@=globuse =mustmod @*/
845 
846 /*@-mustmod@*/
847 static
848 void rpmgcClean(void * impl)
849  /*@modifies impl @*/
850 {
851  rpmgc gc = (rpmgc) impl;
852 /*@-moduncon -noeffectuncon @*/
853  if (gc != NULL) {
854  gc->nbits = 0;
855  gc->err = 0;
856  gc->badok = 0;
857  gc->digest = _free(gc->digest);
858  gc->digestlen = 0;
859 
860  if (gc->key_spec) {
861  gcry_sexp_release(gc->key_spec);
862  gc->key_spec = NULL;
863  }
864  if (gc->key_pair) {
865  gcry_sexp_release(gc->key_pair);
866  gc->key_pair = NULL;
867  }
868  if (gc->pub_key) {
869  gcry_sexp_release(gc->pub_key);
870  gc->pub_key = NULL;
871  }
872  if (gc->sec_key) {
873  gcry_sexp_release(gc->sec_key);
874  gc->sec_key = NULL;
875  }
876  if (gc->hash) {
877  gcry_sexp_release(gc->hash);
878  gc->hash = NULL;
879  }
880  if (gc->sig) {
881  gcry_sexp_release(gc->sig);
882  gc->sig = NULL;
883  }
884 
885  if (gc->c) {
886  gcry_mpi_release(gc->c);
887  gc->c = NULL;
888  }
889  if (gc->p) {
890  gcry_mpi_release(gc->p);
891  gc->p = NULL;
892  }
893  if (gc->q) {
894  gcry_mpi_release(gc->q);
895  gc->q = NULL;
896  }
897  if (gc->g) {
898  gcry_mpi_release(gc->g);
899  gc->g = NULL;
900  }
901  if (gc->y) {
902  gcry_mpi_release(gc->y);
903  gc->y = NULL;
904  }
905 
906  if (gc->r) {
907  gcry_mpi_release(gc->r);
908  gc->r = NULL;
909  }
910  if (gc->s) {
911  gcry_mpi_release(gc->s);
912  gc->s = NULL;
913  }
914  if (gc->n) {
915  gcry_mpi_release(gc->n);
916  gc->n = NULL;
917  }
918  if (gc->e) {
919  gcry_mpi_release(gc->e);
920  gc->e = NULL;
921  }
922  if (gc->o) {
923  gcry_mpi_release(gc->o);
924  gc->o = NULL;
925  }
926  if (gc->a) { /* XXX unused */
927  gcry_mpi_release(gc->a);
928  gc->a = NULL;
929  }
930  if (gc->b) { /* XXX unused */
931  gcry_mpi_release(gc->b);
932  gc->b = NULL;
933  }
934 
935  gc->oid = _free(gc->oid);
936  gc->curve = _free(gc->curve);
937 
938  }
939 /*@=moduncon =noeffectuncon @*/
940 }
941 /*@=mustmod@*/
942 
943 /*@unchecked@*/
944 static int rpmgc_initialized;
945 
946 static /*@null@*/
947 void * rpmgcFree(/*@only@*/ void * impl)
948  /*@globals rpmgc_initialized @*/
949  /*@modifies impl, rpmgc_initialized @*/
950 {
951 
952  rpmgcClean(impl);
953 
954  if (--rpmgc_initialized == 0 && _pgp_debug < 0) {
955  rpmgc gc = (rpmgc) impl;
956  gc->err = rpmgcErr(gc, "CLEAR_DEBUG_FLAGS",
957  gcry_control(GCRYCTL_CLEAR_DEBUG_FLAGS, 3));
958  gc->err = rpmgcErr(gc, "SET_VERBOSITY",
959  gcry_control(GCRYCTL_SET_VERBOSITY, 0) );
960  }
961 
962  impl = _free(impl);
963 
964  return NULL;
965 }
966 
967 static
968 void * rpmgcInit(void)
969  /*@globals rpmgc_initialized @*/
970  /*@modifies rpmgc_initialized @*/
971 {
972  rpmgc gc = (rpmgc) xcalloc(1, sizeof(*gc));
973 
974  if (rpmgc_initialized++ == 0 && _pgp_debug < 0) {
975  gc->err = rpmgcErr(gc, "SET_VERBOSITY",
976  gcry_control(GCRYCTL_SET_VERBOSITY, 3) );
977  gc->err = rpmgcErr(gc, "SET_DEBUG_FLAGS",
978  gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 3) );
979  }
980 
981  return (void *) gc;
982 }
983 
984 struct pgpImplVecs_s rpmgcImplVecs = {
985  rpmgcSetRSA,
986  rpmgcSetDSA,
987  rpmgcSetELG,
988  rpmgcSetECDSA,
989 
990  rpmgcErrChk,
991  rpmgcAvailableCipher, rpmgcAvailableDigest, rpmgcAvailablePubkey,
992  rpmgcVerify, rpmgcSign, rpmgcGenerate,
993 
994  rpmgcMpiItem, rpmgcClean,
995  rpmgcFree, rpmgcInit
996 };
997 
998 #endif
999 
int xx
Definition: spec.c:744
format
Definition: hdrfmt.c:5560
DIGEST_CTX ctx
Definition: signature.c:785
rpmlog(RPMLOG_ERR,"%s\n", buf)
struct rpmgc_s * rpmgc
Definition: rpmgc.h:22
switch(opcode)
Definition: db3.c:896
return se
Definition: macro.c:897
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
static char *size_t nb
fgets(3) analogue that reads \ continuations.
Definition: macro.c:409
int rc
Definition: poptALL.c:670
int errno
long int value
Definition: rpmds.c:2712
struct pgpDig_s * pgpDig
Definition: rpmiotypes.h:86
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
sprintf(t," (%u)",(unsigned) dig->nbytes)
char * alloca()
goto exit
Definition: db3.c:1903
size_t ns
Definition: db3.c:1892
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
assert(key->size==sizeof(hdrNum))
struct pgpValTbl_s pgpHashTbl[]
Hash (string, value) pairs.
Definition: rpmpgp.c:143
int ix
Definition: rpmps-py.c:174
char * p
Definition: macro.c:413
static char * pgpHexStr(const rpmuint8_t *p, size_t plen)
Return hex formatted representation of bytes.
Definition: rpmpgp.h:1164
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
int _pgp_error_count
Definition: rpmpgp.c:35
pgpDigParams pgpGetSignature(pgpDig dig)
Return OpenPGP signature parameters.
Definition: rpmpgp.c:1226
Digest private data.
Definition: digest.c:127
pgpHashAlgo rpmDigestAlgo(DIGEST_CTX ctx)
Return digest algorithm identifier.
Definition: digest.c:188
return k val
Definition: rpmmtree.c:401
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3178
static const char *char c
Return text between pl and matching pr characters.
Definition: macro.c:470
const char * s
Definition: poptALL.c:734
static int xisdigit(int c)
Definition: rpmiotypes.h:437
char * t
Definition: rpmds.c:2716
static unsigned int pgpMpiLen(const rpmuint8_t *p)
Return no.
Definition: rpmpgp.h:1127
te
Definition: macro.c:552
const char * msg
Definition: rpmts-py.c:976
pgpImplVecs_t rpmgcImplVecs
Implementation specific parameter storage.
#define SPEW(_t, _rc, _dig)
Definition: rpmbc.c:25
struct pgpDigParams_s * pgpDigParams
Definition: rpmiotypes.h:90
return NULL
Definition: poptALL.c:613
static const char * pgpValStr(pgpValTbl vs, rpmuint8_t val)
Return string representation of am OpenPGP value.
Definition: rpmpgp.h:1199
char * buf
Parse (and execute) macro undefinition.
Definition: macro.c:703
char * b
Definition: macro.c:746
#define xmalloc
Definition: system.h:32
void rpmDigestFinal(rpmDigestDup(md5ctx),&md5sum,&md5len, 0)
int _pgp_print
Definition: rpmpgp.c:32
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
pgpDigParams sigp
Definition: signature.c:748
pgpDig dig
Definition: rpmts-py.c:979
int _pgp_debug
Definition: rpmpgp.c:29
pgpDigParams pgpGetPubkey(pgpDig dig)
Return OpenPGP pubkey parameters.
Definition: rpmpgp.c:1231
struct pgpValTbl_s pgpPubkeyTbl[]
Definition: rpmpgp.c:103