Push signature verification down to librpmio
authorPanu Matilainen <pmatilai@redhat.com>
Wed, 25 Mar 2009 13:16:59 +0000 (15:16 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 25 Mar 2009 13:16:59 +0000 (15:16 +0200)
- new pgpVerifySig() call to perform the lowlevel verify, use for
  verifying DSA/RSA signatures
- librpm is now free of NSS specifics (apart from what still leaks through
  including rpmio/digest.h), remove linkage

lib/Makefile.am
lib/signature.c
rpmio/rpmpgp.c
rpmio/rpmpgp.h

index 5b65695..8d317f2 100644 (file)
@@ -43,7 +43,6 @@ librpm_la_LDFLAGS = -version-info 0:0:0
 
 librpm_la_LIBADD = \
        $(top_builddir)/rpmio/librpmio.la \
-       @WITH_NSS_LIB@ \
        @WITH_POPT_LIB@ \
        @WITH_SELINUX_LIB@ \
        @WITH_SQLITE3_LIB@ \
index e00fe5e..2fd09f6 100644 (file)
@@ -1046,49 +1046,6 @@ exit:
     return res;
 }
 
-/* lower level verification bits for RSA+DSA signatures */
-static rpmRC verifyPGPSig(pgpDigParams sigp,
-                       SECKEYPublicKey *key, SECItem *sig, SECOidTag sigalg,
-                       DIGEST_CTX hashctx)
-{      
-    DIGEST_CTX ctx = rpmDigestDup(hashctx);
-    uint8_t *hash = NULL;
-    size_t hashlen = 0;
-    rpmRC res = RPMRC_FAIL; /* assume failure */
-    int xx;
-
-    if (sigp == NULL || ctx == NULL)
-       goto exit;
-
-    if (sigp->hash != NULL)
-       xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
-
-    if (sigp->version == 4) {
-       /* V4 trailer is six octets long (rfc4880) */
-       uint8_t trailer[6];
-       uint32_t nb = sigp->hashlen;
-       nb = htonl(nb);
-       trailer[0] = sigp->version;
-       trailer[1] = 0xff;
-       memcpy(trailer+2, &nb, 4);
-       xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
-    }
-
-    xx = rpmDigestFinal(ctx, (void **)&hash, &hashlen, 0);
-
-    /* Compare leading 16 bits of digest for quick check. */
-    if (memcmp(hash, sigp->signhash16, 2) == 0) {
-       SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
-       if (VFY_VerifyDigest(&digest, key, sig, sigalg, NULL) == SECSuccess) {
-           res = RPMRC_OK;
-       }
-    }
-
-exit:
-    free(hash);
-    return res;
-}
-
 /**
  * Verify RSA signature.
  * @param keyring      pubkey keyring
@@ -1101,7 +1058,6 @@ verifyRSASignature(rpmKeyring keyring, rpmtd sigtd, pgpDig dig, char ** msg,
                DIGEST_CTX hashctx)
 {
     pgpDigParams sigp = dig ? &dig->signature : NULL;
-    SECOidTag sigalg = SEC_OID_UNKNOWN;
     rpmRC res = RPMRC_FAIL; /* assume failure */
     const char *hdr = (sigtd->tag == RPMSIGTAG_RSA) ? _("Header ") : "";
     const char *signame = _("Unknown");;
@@ -1118,27 +1074,21 @@ verifyRSASignature(rpmKeyring keyring, rpmtd sigtd, pgpDig dig, char ** msg,
     switch (sigp->hash_algo) {
     case PGPHASHALGO_MD5:
        signame = "RSA/MD5";
-       sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
        break;
     case PGPHASHALGO_SHA1:
        signame = "RSA/SHA1";
-       sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
        break;
     case PGPHASHALGO_MD2:
        signame = "RSA/MD2";
-       sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
        break;
     case PGPHASHALGO_SHA256:
        signame = "RSA/SHA256";
-       sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
        break;
     case PGPHASHALGO_SHA384:
        signame = "RSA/SHA384";
-       sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
        break;
     case PGPHASHALGO_SHA512:
        signame = "RSA/SHA512";
-       sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
        break;
     /* fallthrough for unsupported / unknown types */
     case PGPHASHALGO_TIGER192:
@@ -1149,7 +1099,7 @@ verifyRSASignature(rpmKeyring keyring, rpmtd sigtd, pgpDig dig, char ** msg,
     }
 
     /* Verify the desired signature match. */
-    if (sigp->pubkey_algo != PGPPUBKEYALGO_RSA || sigalg == SEC_OID_UNKNOWN ||
+    if (sigp->pubkey_algo != PGPPUBKEYALGO_RSA ||
                        (!(sigtd->tag == RPMSIGTAG_RSA || 
                           sigtd->tag == RPMSIGTAG_PGP || 
                           sigtd->tag == RPMSIGTAG_PGP5))) {
@@ -1159,7 +1109,7 @@ verifyRSASignature(rpmKeyring keyring, rpmtd sigtd, pgpDig dig, char ** msg,
     /* Retrieve the matching public key and verify. */
     res = rpmKeyringLookup(keyring, dig);
     if (res == RPMRC_OK) {
-       res = verifyPGPSig(sigp, dig->keydata, dig->sigdata, sigalg, hashctx);
+       res = pgpVerifySig(dig, hashctx);
     }
 
 exit:
@@ -1208,9 +1158,7 @@ verifyDSASignature(rpmKeyring keyring, rpmtd sigtd, pgpDig dig, char ** msg,
     /* Retrieve the matching public key and verify. */
     res = rpmKeyringLookup(keyring, dig);
     if (res == RPMRC_OK) {
-       /* XXX TODO: handle other algorithm types too */
-       SECOidTag sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
-       res = verifyPGPSig(sigp, dig->keydata, dig->sigdata, sigalg, hashctx);
+       res = pgpVerifySig(dig, hashctx);
     }
 
 exit:
index 2cb10a5..4e216bd 100644 (file)
@@ -1283,6 +1283,82 @@ int pgpPrtPkts(const uint8_t * pkts, size_t pktlen, pgpDig dig, int printing)
     return 0;
 }
 
+static SECOidTag getSigAlg(pgpDigParams sigp)
+{
+    SECOidTag sigalg = SEC_OID_UNKNOWN;
+    if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA) {
+       /* assume SHA1 for now, NSS doesn't have SECOID's for other types */
+       sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+    } else if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA) {
+       switch (sigp->hash_algo) {
+       case PGPHASHALGO_MD5:
+           sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+           break;
+       case PGPHASHALGO_MD2:
+           sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
+           break;
+       case PGPHASHALGO_SHA1:
+           sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+           break;
+       case PGPHASHALGO_SHA256:
+           sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+           break;
+       case PGPHASHALGO_SHA384:
+            sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
+           break;
+       case PGPHASHALGO_SHA512:
+           sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+           break;
+       default:
+           break;
+       }
+    }
+    return sigalg;
+}
+
+rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx)
+{
+    DIGEST_CTX ctx = rpmDigestDup(hashctx);
+    uint8_t *hash = NULL;
+    size_t hashlen = 0;
+    rpmRC res = RPMRC_FAIL; /* assume failure */
+    pgpDigParams sigp = dig ? &dig->signature : NULL;
+
+    if (sigp == NULL || ctx == NULL)
+       goto exit;
+
+    if (sigp->hash != NULL)
+       rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
+
+    if (sigp->version == 4) {
+       /* V4 trailer is six octets long (rfc4880) */
+       uint8_t trailer[6];
+       uint32_t nb = sigp->hashlen;
+       nb = htonl(nb);
+       trailer[0] = sigp->version;
+       trailer[1] = 0xff;
+       memcpy(trailer+2, &nb, 4);
+       rpmDigestUpdate(ctx, trailer, sizeof(trailer));
+    }
+
+    rpmDigestFinal(ctx, (void **)&hash, &hashlen, 0);
+
+    /* Compare leading 16 bits of digest for quick check. */
+    if (hash && memcmp(hash, sigp->signhash16, 2) == 0) {
+       SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
+       /* XXX VFY_VerifyDigest() is deprecated in NSS 3.12 */ 
+       if (VFY_VerifyDigest(&digest, dig->keydata, dig->sigdata, 
+                            getSigAlg(sigp), NULL) == SECSuccess) {
+           res = RPMRC_OK;
+       }
+    }
+
+exit:
+    free(hash);
+    return res;
+
+}
+
 pgpArmor pgpReadPkts(const char * fn, uint8_t ** pkt, size_t * pktlen)
 {
     uint8_t * b = NULL;
index c3d6097..0789b45 100644 (file)
@@ -1041,6 +1041,14 @@ void pgpCleanDig(pgpDig dig);
 pgpDig pgpFreeDig(pgpDig dig);
 
 /** \ingroup rpmpgp
+ * Verify a PGP signature.
+ * @param dig          container
+ * @param hashctx      digest context
+ * @return             RPMRC_OK on success 
+ */
+rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx);
+
+/** \ingroup rpmpgp
  * Perform cryptography initialization.
  * It must be called before any cryptography can be used within rpm.
  * It's not normally necessary to call it directly as it's called in