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/e0c07b54952d
branches:  agc-netpgp-standalone
changeset: 777815:e0c07b54952d
user:      agc <agc%NetBSD.org@localhost>
date:      Sat Oct 20 10:16:31 2012 +0000

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

diffstat:

 crypto/external/bsd/netpgp/dist/src/libverify/libverify.c |  102 ++++++++++++-
 1 files changed, 89 insertions(+), 13 deletions(-)

diffs (143 lines):

diff -r 127863e468f0 -r e0c07b54952d crypto/external/bsd/netpgp/dist/src/libverify/libverify.c
--- a/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c Sat Oct 20 06:01:57 2012 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/libverify/libverify.c Sat Oct 20 10:16:31 2012 +0000
@@ -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 @@
                         ((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 @@
        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 @@
        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 @@
                        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;
+       }
+       if (valid_dates(signature, pubkey, cursor->why, sizeof(cursor->why)) > 0) {
+               return 0;
        }
-       snprintf(cursor->why, sizeof(cursor->why), "Signature not RSA");
-       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 */



Home | Main Index | Thread Index | Old Index