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