Module Name:    src
Committed By:   agc
Date:           Sat Oct 20 10:16:31 UTC 2012

Modified Files:
        src/crypto/external/bsd/netpgp/dist/src/libverify 
[agc-netpgp-standalone]:
            libverify.c

Log Message:
add preliminary support for DSA signatures to libnetpgpverify(3) and
netpgpverify(1)


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.2 -r1.1.2.3 \
    src/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c
diff -u src/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c:1.1.2.2 src/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c:1.1.2.3
--- src/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c:1.1.2.2	Sat Oct 20 05:55:42 2012
+++ src/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c	Sat Oct 20 10:16:31 2012
@@ -122,8 +122,8 @@
 
 /* signature mpi indices in bignumber array */
 #define RSA_SIG				0
-#define DSA_SIG_R			0
-#define DSA_SIG_S			1
+#define DSA_R				0
+#define DSA_S				1
 #define ELGAMAL_SIG_R			0
 #define ELGAMAL_SIG_S			1
 
@@ -392,6 +392,8 @@ fmt_mpi(char *s, size_t size, pgpv_bignu
 			 ((alg) == PUBKEY_RSA_ENCRYPT) ||		\
 			 ((alg) == PUBKEY_RSA_SIGN))
 
+#define ALG_IS_DSA(alg)	((alg) == PUBKEY_DSA)
+
 /* format key mpis into memory */
 static unsigned
 fmt_key_mpis(pgpv_pubkey_t *pubkey, uint8_t *buf, size_t size)
@@ -678,8 +680,8 @@ read_signature_mpis(pgpv_sigpkt_t *sigpk
 	case PUBKEY_DSA:
 	case PUBKEY_ECDSA:
 	case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN: /* deprecated */
-		if (!get_mpi(&sigpkt->sig.bn[DSA_SIG_R], p, pktlen, &off) ||
-		    !get_mpi(&sigpkt->sig.bn[DSA_SIG_S], &p[off], pktlen, &off)) {
+		if (!get_mpi(&sigpkt->sig.bn[DSA_R], p, pktlen, &off) ||
+		    !get_mpi(&sigpkt->sig.bn[DSA_S], &p[off], pktlen, &off)) {
 			printf("sigpkt->version %d, dsa/elgamal sig weird\n", sigpkt->sig.version);
 			return 0;
 		}
@@ -1449,6 +1451,74 @@ rsa_verify(uint8_t *calculated, unsigned
 	return memcmp(&decrypted[i + prefixlen], calculated, calclen) == 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)
+{
+	unsigned	  qbits;
+	BIGNUM		 *M;
+	BIGNUM		 *W;
+	BIGNUM		 *t1;
+	int		  ret;
+
+	if (sig[DSA_P].bn == NULL || sig[DSA_Q].bn == NULL || sig[DSA_G].bn == NULL) {
+		return 0;
+	}
+	M = W = t1 = NULL;
+	qbits = pubkey->bn[DSA_Q].bits;
+	switch(qbits) {
+	case 160:
+	case 224:
+	case 256:
+		break;
+	default:
+		printf("dsa: bad # of Q bits\n");
+		return 0;
+	}
+	if (pubkey->bn[DSA_Q].bits > DSA_MAX_MODULUS_BITS) {
+		printf("dsa: p too large\n");
+		return 0;
+	}
+	/* no love for SHA512? */
+	if (calclen > SHA256_DIGEST_LENGTH) {
+		printf("dsa: digest too long\n");
+		return 0;
+	}
+	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 ||
+	    BN_mod_inverse(W, sig[DSA_S].bn, pubkey->bn[DSA_Q].bn, NULL) != MP_OKAY) {
+		goto err;
+	}
+	if (calclen > qbits / 8) {
+		calclen = qbits / 8;
+	}
+	if (BN_bin2bn(calculated, (int)calclen, M) == NULL ||
+	    !BN_mod_mul(M, M, W, pubkey->bn[DSA_Q].bn, NULL) ||
+	    !BN_mod_mul(W, sig[DSA_R].bn, W, pubkey->bn[DSA_Q].bn, NULL) ||
+	    !BN_mod_exp(pubkey->bn[DSA_P].bn, t1, pubkey->bn[DSA_G].bn, M, NULL) ||
+	    !BN_div(NULL, M, t1, pubkey->bn[DSA_Q].bn, NULL)) {
+		goto err;
+	}
+	ret = (BN_cmp(M, sig[DSA_R].bn) == 0);
+err:
+	if (M) {
+		BN_free(M);
+	}
+	if (W) {
+		BN_free(W);
+	}
+	if (t1) {
+		BN_free(t1);
+	}
+	return ret;
+}
+
 #define TIME_SNPRINTF(_cc, _buf, _size, _fmt, _val)	do {		\
 	time_t	 _t;							\
 	char	*_s;							\
@@ -2017,18 +2087,24 @@ pgpv_verify(pgpv_cursor_t *cursor, pgpv_
 			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))) {
+	} 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;
 		}
-		ARRAY_APPEND(cursor->datacookies, pkt);
-		ARRAY_APPEND(cursor->found, primary);
-		return 1;
+	} else {
+		snprintf(cursor->why, sizeof(cursor->why), "Signature type %u not recognised", signature->keyalg);
+		return 0;
 	}
-	snprintf(cursor->why, sizeof(cursor->why), "Signature not RSA");
-	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;
+	}
+	ARRAY_APPEND(cursor->datacookies, (unsigned)pkt);
+	ARRAY_APPEND(cursor->found, primary);
+	return 1;
 }
 
 /* set up the pubkey keyring */

Reply via email to