Make gpg-pubkey headers properly verifiable
authorPanu Matilainen <pmatilai@redhat.com>
Thu, 24 Nov 2011 09:39:36 +0000 (11:39 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Thu, 24 Nov 2011 09:58:44 +0000 (11:58 +0200)
- The pubkey headers have been rpm v3 all the way until now, whoops :)
  Pull the actual key part of the header into immutable region and
  stomp a sha1 digest on the result, allowing a (much) better
  verification on loading. This part inspired by stumbling on a
  related discussion on rpm5.org mailing list so credits where...
- Since we only insert either literally constant data or data retrieved
  from the actual key into the immutable part of the header, the
  calculated digest is constant for a given key regardless of where
  and when it was imported. This gives some added verification and/or
  cross-checking possibilities (eg was the imported key exactly the
  same as what shipped etc)

lib/rpmts.c

index 356b291..111879b 100644 (file)
@@ -419,8 +419,26 @@ static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp)
     headerPutUint32(h, RPMTAG_BUILDTIME, &keytime, 1);
     headerPutString(h, RPMTAG_SOURCERPM, "(none)");
 
-    *hdrp = headerLink(h);
-    rc = 0;
+    /* Reload the lot to immutable region and stomp sha1 digest on it */
+    h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
+    if (h != NULL) {
+       char *sha1 = NULL;
+       const void *blob = headerUnload(h);
+       size_t blen = headerSizeof(h, HEADER_MAGIC_NO);
+
+       /* XXX FIXME: bah, this code is repeated in way too many places */
+       DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
+       rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic));
+       rpmDigestUpdate(ctx, blob, blen);
+       rpmDigestFinal(ctx, (void **)&sha1, NULL, 1);
+
+       if (sha1) {
+           headerPutString(h, RPMTAG_SHA1HEADER, sha1);
+           *hdrp = headerLink(h);
+           rc = 0;
+       }
+       free(sha1);
+    }
 
 exit:
     headerFree(h);