Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/agc-netpgp-standalone]: src/crypto/external/bsd/netpgp/dist/src/libverif...



details:   https://anonhg.NetBSD.org/src/rev/c57d959250c9
branches:  agc-netpgp-standalone
changeset: 777822:c57d959250c9
user:      agc <agc%NetBSD.org@localhost>
date:      Wed Oct 24 02:27:25 2012 +0000

description:
various improvements in netpgpverify:

+ store the revocation code in the signature

+ attempt to be bug compatible with gpg - if a signature on a text
document does not match the first time, try again, this time trimming
trailing white space (' ' and '\t' characters) from the text document.
this makes the verification work the same as gpg.  this behavior is
not activated for binary documents.  i have absolutely no idea why
this is done in the first place; christoph badura thinks it may be to
do with original pgp compatibility.  this and the stripping of the
trailing \r\n on text document digest calculation make no sense to me.

+ only compare the leading Q bits (i.e.  the length of the DSA Q
value) when verifying a DSA signature, per RFC 4880.  helps with
sha256 digests and smaller keys.

+ calculate the displayed size of DSA keys a bit differently, no functional
difference.

diffstat:

 crypto/external/bsd/netpgp/dist/src/libverify/libverify.c |  110 ++++++++-----
 crypto/external/bsd/netpgp/dist/src/libverify/pgpsum.c    |   14 +-
 crypto/external/bsd/netpgp/dist/src/libverify/verify.h    |    1 +
 3 files changed, 79 insertions(+), 46 deletions(-)

diffs (245 lines):

diff -r 0206f6b08cde -r c57d959250c9 crypto/external/bsd/netpgp/dist/src/libverify/libverify.c
--- a/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c Wed Oct 24 02:18:56 2012 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c Wed Oct 24 02:27:25 2012 +0000
@@ -713,10 +713,10 @@
 read_sig_subpackets(pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
 {
        pgpv_sigsubpkt_t         subpkt;
-       const int        is_subpkt = 0;
-       unsigned         lenlen;
-       unsigned         i;
-       uint8_t         *start;
+       const int                is_subpkt = 0;
+       unsigned                 lenlen;
+       unsigned                 i;
+       uint8_t                 *start;
 
        start = p;
        for (i = 0 ; (unsigned)(p - start) < sigpkt->subslen ; i++) {
@@ -784,6 +784,7 @@
                        sigpkt->sig.features = (char *)(void *)p;
                        break;
                case SUBPKT_REVOCATION_REASON:
+                       sigpkt->sig.revoked = *p++ + 1;
                        sigpkt->sig.why_revoked = (char *)(void *)p;
                        break;
                default:
@@ -1326,16 +1327,7 @@
                return pubkey->bn[RSA_N].bits;
        case PUBKEY_DSA:
        case PUBKEY_ECDSA:
-               switch(BITS_TO_BYTES(pubkey->bn[DSA_Q].bits)) {
-               case 20:
-                       return 1024;
-               case 28:
-                       return 2048;
-               case 32:
-                       return 3072;
-               default:
-                       return 0;
-               }
+               return BITS_TO_BYTES(pubkey->bn[DSA_Q].bits) * 64;
        case PUBKEY_ELGAMAL_ENCRYPT:
        case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN:
                return pubkey->bn[ELGAMAL_P].bits;
@@ -1356,6 +1348,7 @@
        if (pubkey->expiry) {
                cc += fmt_time(&s[cc], size - cc, " [Expiry ", pubkey->birth + pubkey->expiry, "]", 0);
        }
+       /* XXX - revoked? */
        cc += snprintf(&s[cc], size - cc, "\n");
        cc += fmt_fingerprint(&s[cc], size - cc, &pubkey->fingerprint, "fingerprint: ");
        return cc;
@@ -1451,18 +1444,23 @@
        return memcmp(&decrypted[i + prefixlen], calculated, calclen) == 0;
 }
 
+#define BAD_BIGNUM(s, k)       \
+       (BN_is_zero((s)->bn) || BN_is_negative((s)->bn) || BN_cmp((s)->bn, (k)->bn) >= 0)
+
 #ifndef DSA_MAX_MODULUS_BITS
 #define DSA_MAX_MODULUS_BITS      10000
 #endif
 
 /* verify DSA signature */
 static int
-verify_dsa_verify(uint8_t *calculated, unsigned calclen, pgpv_bignum_t *sig, pgpv_pubkey_t *pubkey)
+verify_dsa_sig(uint8_t *calculated, unsigned calclen, pgpv_bignum_t *sig, pgpv_pubkey_t *pubkey)
 {
        unsigned          qbits;
        BIGNUM           *M;
        BIGNUM           *W;
        BIGNUM           *t1;
+       uint8_t           calcnum[128];
+       uint8_t           signum[128];
        int               ret;
 
        if (pubkey[DSA_P].bn == NULL || pubkey[DSA_Q].bn == NULL || pubkey[DSA_G].bn == NULL) {
@@ -1489,8 +1487,8 @@
        }
        ret = 0;
        if ((M = BN_new()) == NULL || (W = BN_new()) == NULL || (t1 = BN_new()) == NULL ||
-           BN_is_zero(sig[DSA_R].bn) || BN_is_negative(sig[DSA_R].bn) || BN_cmp(sig[DSA_R].bn, pubkey->bn[DSA_Q].bn) >= 0 ||
-           BN_is_zero(sig[DSA_S].bn) || BN_is_negative(sig[DSA_S].bn) || BN_cmp(sig[DSA_S].bn, pubkey->bn[DSA_Q].bn) >= 0 ||
+           BAD_BIGNUM(&sig[DSA_R], &pubkey->bn[DSA_Q]) ||
+           BAD_BIGNUM(&sig[DSA_S], &pubkey->bn[DSA_Q]) ||
            BN_mod_inverse(W, sig[DSA_S].bn, pubkey->bn[DSA_Q].bn, NULL) == NULL) {
                goto done;
        }
@@ -1506,7 +1504,10 @@
            !BN_div(NULL, t1, t1, pubkey->bn[DSA_Q].bn, NULL)) {
                goto done;
        }
-       ret = (BN_cmp(t1, sig[DSA_R].bn) == 0);
+       /* only compare the first q bits */
+       BN_bn2bin(t1, calcnum);
+       BN_bn2bin(sig[DSA_R].bn, signum);
+       ret = memcmp(calcnum, signum, BITS_TO_BYTES(qbits)) == 0;
 done:
        if (M) {
                BN_free(M);
@@ -1946,6 +1947,54 @@
        return 1;
 }
 
+/* match the calculated signature against the oen in the signature packet */
+static int
+match_sig(pgpv_cursor_t *cursor, pgpv_signature_t *signature, pgpv_pubkey_t *pubkey, uint8_t *data, size_t size)
+{
+       unsigned        calclen;
+       uint8_t         calculated[64];
+       int             match;
+
+       calclen = pgpv_digest_memory(calculated, sizeof(calculated),
+               data, size,
+               get_ref(&signature->hashstart), signature->hashlen,
+               (signature->type == SIGTYPE_TEXT) ? 't' : 'b');
+       if (ALG_IS_RSA(signature->keyalg)) {
+               match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
+       } else if (ALG_IS_DSA(signature->keyalg)) {
+               match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
+       } else {
+               snprintf(cursor->why, sizeof(cursor->why), "Signature type %u not recognised", signature->keyalg);
+               return 0;
+       }
+       if (!match && signature->type == SIGTYPE_TEXT) {
+               /* second try for cleartext data, ignoring trailing whitespace */
+               calclen = pgpv_digest_memory(calculated, sizeof(calculated),
+                       data, size,
+                       get_ref(&signature->hashstart), signature->hashlen, 'w');
+               if (ALG_IS_RSA(signature->keyalg)) {
+                       match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
+               } else if (ALG_IS_DSA(signature->keyalg)) {
+                       match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
+               }
+       }
+       if (!match) {
+               snprintf(cursor->why, sizeof(cursor->why), "Signature on data did not match");
+               return 0;
+       }
+       if (valid_dates(signature, pubkey, cursor->why, sizeof(cursor->why)) > 0) {
+               return 0;
+       }
+       if (key_expired(pubkey, cursor->why, sizeof(cursor->why))) {
+               return 0;
+       }
+       if (signature->revoked) {
+               snprintf(cursor->why, sizeof(cursor->why), "Signature was revoked");
+               return 0;
+       }
+       return 1;
+}
+
 /************************************************************************/
 /* start of exported functions */
 /************************************************************************/
@@ -2018,8 +2067,6 @@
        pgpv_litdata_t          *litdata;
        pgpv_pubkey_t           *pubkey;
        unsigned                 primary;
-       unsigned                 calclen;
-       uint8_t                  calculated[64];
        uint8_t                 *data;
        size_t                   pkt;
        size_t                   insize;
@@ -2077,28 +2124,7 @@
        cursor->sigtime = signature->birth;
        /* calc hash on data packet */
        data = get_literal_data(cursor, litdata, &insize);
-       calclen = pgpv_digest_memory(calculated, sizeof(calculated),
-               data, insize,
-               get_ref(&signature->hashstart), signature->hashlen,
-               (signature->type == SIGTYPE_TEXT));
-       if (ALG_IS_RSA(signature->keyalg)) {
-               if (!rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey)) {
-                       snprintf(cursor->why, sizeof(cursor->why), "Signature on data did not match");
-                       return 0;
-               }
-       } else if (ALG_IS_DSA(signature->keyalg)) {
-               if (!verify_dsa_verify(calculated, calclen, signature->bn, pubkey)) {
-                       snprintf(cursor->why, sizeof(cursor->why), "Signature on data did not match");
-                       return 0;
-               }
-       } else {
-               snprintf(cursor->why, sizeof(cursor->why), "Signature type %u not recognised", signature->keyalg);
-               return 0;
-       }
-       if (valid_dates(signature, pubkey, cursor->why, sizeof(cursor->why)) > 0) {
-               return 0;
-       }
-       if (key_expired(pubkey, cursor->why, sizeof(cursor->why))) {
+       if (!match_sig(cursor, signature, pubkey, data, insize)) {
                return 0;
        }
        ARRAY_APPEND(cursor->datacookies, pkt);
diff -r 0206f6b08cde -r c57d959250c9 crypto/external/bsd/netpgp/dist/src/libverify/pgpsum.c
--- a/crypto/external/bsd/netpgp/dist/src/libverify/pgpsum.c    Wed Oct 24 02:18:56 2012 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/libverify/pgpsum.c    Wed Oct 24 02:27:25 2012 +0000
@@ -39,16 +39,22 @@
 
 /* add the ascii armor line endings (except for last line) */
 static size_t
-don_armor(digest_t *hash, uint8_t *in, size_t insize)
+don_armor(digest_t *hash, uint8_t *in, size_t insize, int doarmor)
 {
        uint8_t *from;
+       uint8_t *newp;
        uint8_t *p;
        uint8_t  dos_line_end[2];
 
        dos_line_end[0] = '\r';
        dos_line_end[1] = '\n';
        for (from = in ; (p = memchr(from, '\n', insize - (size_t)(from - in))) != NULL ; from = p + 1) {
-               digest_update(hash, from, (size_t)(p - from));
+               for (newp = p ; doarmor == 'w' && newp > from ; --newp) {
+                       if (*(newp - 1) != ' ' && *(newp - 1) != '\t') {
+                               break;
+                       }
+               }
+               digest_update(hash, from, (size_t)(newp - from));
                digest_update(hash, dos_line_end, sizeof(dos_line_end));
        }
        digest_update(hash, from, insize - (size_t)(from - in));
@@ -118,9 +124,9 @@
        writefile(mem, cc);
 #endif
        digest_init(&hash, hashalg);
-       if (doarmor && !already_armored(mem, cc)) {
+       if (strchr("tw", doarmor) != NULL && !already_armored(mem, cc)) {
                /* this took me ages to find - something causes gpg to truncate its input */
-               don_armor(&hash, mem, cc - 1);
+               don_armor(&hash, mem, cc - 1, doarmor);
        } else {
                digest_update(&hash, mem, cc);
        }
diff -r 0206f6b08cde -r c57d959250c9 crypto/external/bsd/netpgp/dist/src/libverify/verify.h
--- a/crypto/external/bsd/netpgp/dist/src/libverify/verify.h    Wed Oct 24 02:18:56 2012 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/libverify/verify.h    Wed Oct 24 02:27:25 2012 +0000
@@ -133,6 +133,7 @@
        uint8_t          pref_compress_alg;
        uint8_t          notation;
        uint8_t          type_key;
+       uint8_t          revoked;               /* subtract 1 to get real reason, 0 == not revoked */
 } pgpv_signature_t;
 
 /* a signature packet */



Home | Main Index | Thread Index | Old Index