Source-Changes-HG archive

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

[src/trunk]: src/crypto/external/bsd/netpgp/dist/src/lib Add the ability to p...



details:   https://anonhg.NetBSD.org/src/rev/bb32028c5abb
branches:  trunk
changeset: 758528:bb32028c5abb
user:      agc <agc%NetBSD.org@localhost>
date:      Sun Nov 07 02:29:28 2010 +0000

description:
Add the ability to perform Elgamal encryption to netpgp.  Some of this
code is inspired by the (BSD-licensed) Elgamal crypto code in
Postgresql by Marko Kreen, but netpgp uses BIGNUM numbers instead of
MPIs, and its keys have a completely different structure, so much has
changed.

% cp config.h f
% netpgp -e f
netpgp: default key set to "d4a643c5"
% gpg -d f.gpg > f2

You need a passphrase to unlock the secret key for
user: "Alistair Crooks (DSA TEST KEY - DO NOT USE) <agc%netbsd.org@localhost>"
2048-bit ELG-E key, ID D727BC1E, created 2010-05-19 (main key ID D4A643C5)

gpg: encrypted with 2048-bit ELG-E key, ID D727BC1E, created 2010-05-19
      "Alistair Crooks (DSA TEST KEY - DO NOT USE) <agc%netbsd.org@localhost>"
% diff f f2
% ls -al f*
-rw-r--r--  1 agc  agc  5730 Nov  6 05:40 f
-rw-------  1 agc  agc  1727 Nov  6 05:40 f.gpg
-rw-r--r--  1 agc  agc  5730 Nov  6 05:41 f2
%

diffstat:

 crypto/external/bsd/netpgp/dist/src/lib/config.h.in      |   3 -
 crypto/external/bsd/netpgp/dist/src/lib/create.c         |  65 ++++++---
 crypto/external/bsd/netpgp/dist/src/lib/crypto.c         |  41 ++++++-
 crypto/external/bsd/netpgp/dist/src/lib/crypto.h         |   5 +
 crypto/external/bsd/netpgp/dist/src/lib/openssl_crypto.c |  99 +++++++++++++++-
 5 files changed, 186 insertions(+), 27 deletions(-)

diffs (truncated from 342 to 300 lines):

diff -r af0f0afef46a -r bb32028c5abb crypto/external/bsd/netpgp/dist/src/lib/config.h.in
--- a/crypto/external/bsd/netpgp/dist/src/lib/config.h.in       Sun Nov 07 01:12:22 2010 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/lib/config.h.in       Sun Nov 07 02:29:28 2010 +0000
@@ -12,9 +12,6 @@
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
-/* Define to 1 if you have the <dmalloc.h> header file. */
-#undef HAVE_DMALLOC_H
-
 /* Define to 1 if you have the <errno.h> header file. */
 #undef HAVE_ERRNO_H
 
diff -r af0f0afef46a -r bb32028c5abb crypto/external/bsd/netpgp/dist/src/lib/create.c
--- a/crypto/external/bsd/netpgp/dist/src/lib/create.c  Sun Nov 07 01:12:22 2010 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/lib/create.c  Sun Nov 07 02:29:28 2010 +0000
@@ -57,7 +57,7 @@
 
 #if defined(__NetBSD__)
 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
-__RCSID("$NetBSD: create.c,v 1.35 2010/11/04 15:38:45 agc Exp $");
+__RCSID("$NetBSD: create.c,v 1.36 2010/11/07 02:29:28 agc Exp $");
 #endif
 
 #include <sys/types.h>
@@ -881,41 +881,39 @@
        /* implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC */
        switch (pubkey->alg) {
        case OPS_PKA_RSA:
+               k = (unsigned)BN_num_bytes(pubkey->key.rsa.n);
+               if (mLen > k - 11) {
+                       (void) fprintf(stderr, "encode_m_buf: message too long\n");
+                       return 0;
+               }
                break;
        case OPS_PKA_DSA:
        case OPS_PKA_ELGAMAL:
-               (void) fprintf(stderr, "encode_m_buf: DSA/Elgamal encryption not implemented yet\n");
+               k = (unsigned)BN_num_bytes(pubkey->key.elgamal.p);
+               if (mLen > k - 11) {
+                       (void) fprintf(stderr, "encode_m_buf: message too long\n");
+                       return 0;
+               }
                break;
        default:
                (void) fprintf(stderr, "encode_m_buf: pubkey algorithm\n");
                return 0;
        }
-
-       k = (unsigned)BN_num_bytes(pubkey->key.rsa.n);
-       if (mLen > k - 11) {
-               (void) fprintf(stderr, "encode_m_buf: message too long\n");
-               return 0;
-       }
        /* these two bytes defined by RFC */
        EM[0] = 0x00;
        EM[1] = 0x02;
-
        /* add non-zero random bytes of length k - mLen -3 */
        for (i = 2; i < (k - mLen) - 1; ++i) {
                do {
                        __ops_random(EM + i, 1);
                } while (EM[i] == 0);
        }
-
        if (i < 8 + 2) {
                (void) fprintf(stderr, "encode_m_buf: bad i len\n");
                return 0;
        }
-
        EM[i++] = 0;
-
        (void) memcpy(EM + i, M, mLen);
-
        if (__ops_get_debug_level(__FILE__)) {
                hexdump(stderr, "Encoded Message:", EM, mLen);
        }
@@ -967,7 +965,18 @@
                        "__ops_create_pk_sesskey: can't allocate\n");
                return NULL;
        }
-       sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
+       switch(pubkey->alg) {
+       case OPS_PKA_RSA:
+               sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
+               break;
+       case OPS_PKA_DSA:
+       case OPS_PKA_ELGAMAL:
+               sz_encoded_m_buf = BN_num_bytes(pubkey->key.elgamal.p);
+               break;
+       default:
+               sz_encoded_m_buf = 0;
+               break;
+       }
        if ((encoded_m_buf = calloc(1, sz_encoded_m_buf)) == NULL) {
                (void) fprintf(stderr,
                        "__ops_create_pk_sesskey: can't allocate\n");
@@ -993,7 +1002,7 @@
        (void) memcpy(sesskey->key_id, id, sizeof(sesskey->key_id));
 
        if (__ops_get_debug_level(__FILE__)) {
-               hexdump(stderr, "Encrypting for RSA keyid", id, sizeof(sesskey->key_id));
+               hexdump(stderr, "Encrypting for keyid", id, sizeof(sesskey->key_id));
        }
        switch (pubkey->alg) {
        case OPS_PKA_RSA:
@@ -1041,11 +1050,14 @@
                break;
        case OPS_PKA_DSA:
        case OPS_PKA_ELGAMAL:
-               (void) fprintf(stderr, "DSA/Elgamal encryption not supported yet\n");
-               free(unencoded_m_buf);
-               free(encoded_m_buf);
-               free(sesskey);
-               return NULL;
+               if (!__ops_elgamal_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
+                               &sesskey->params)) {
+                       free(unencoded_m_buf);
+                       free(encoded_m_buf);
+                       free(sesskey);
+                       return NULL;
+               }
+               break;
        default:
                /* will not get here - for lint only */
                break;
@@ -1084,8 +1096,17 @@
                        ;
        case OPS_PKA_DSA:
        case OPS_PKA_ELGAMAL:
-               (void) fprintf(stderr, "__ops_write_pk_sesskey: DSA/Elgamal encryption not implemented yet\n");
-               return 0;
+               return __ops_write_ptag(output, OPS_PTAG_CT_PK_SESSION_KEY) &&
+                       __ops_write_length(output, (unsigned)(1 + 8 + 1 +
+                               BN_num_bytes(pksk->params.elgamal.g_to_k) + 2 +
+                               BN_num_bytes(pksk->params.elgamal.encrypted_m) + 2)) &&
+                       __ops_write_scalar(output, (unsigned)pksk->version, 1) &&
+                       __ops_write(output, pksk->key_id, 8) &&
+                       __ops_write_scalar(output, (unsigned)pksk->alg, 1) &&
+                       __ops_write_mpi(output, pksk->params.elgamal.g_to_k) &&
+                       __ops_write_mpi(output, pksk->params.elgamal.encrypted_m)
+                       /* ??   && __ops_write_scalar(output, 0, 2); */
+                       ;
        default:
                (void) fprintf(stderr,
                        "__ops_write_pk_sesskey: bad algorithm\n");
diff -r af0f0afef46a -r bb32028c5abb crypto/external/bsd/netpgp/dist/src/lib/crypto.c
--- a/crypto/external/bsd/netpgp/dist/src/lib/crypto.c  Sun Nov 07 01:12:22 2010 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/lib/crypto.c  Sun Nov 07 02:29:28 2010 +0000
@@ -54,7 +54,7 @@
 
 #if defined(__NetBSD__)
 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
-__RCSID("$NetBSD: crypto.c,v 1.29 2010/11/04 15:38:45 agc Exp $");
+__RCSID("$NetBSD: crypto.c,v 1.30 2010/11/07 02:29:28 agc Exp $");
 #endif
 
 #include <sys/types.h>
@@ -223,6 +223,45 @@
        return 1;
 }
 
+/**
+\ingroup Core_MPI
+\brief Elgamal-encrypt an MPI
+*/
+unsigned 
+__ops_elgamal_encrypt_mpi(const uint8_t *encoded_m_buf,
+                   const size_t sz_encoded_m_buf,
+                   const __ops_pubkey_t * pubkey,
+                   __ops_pk_sesskey_params_t * skp)
+{
+
+       uint8_t   encmpibuf[NETPGP_BUFSIZ];
+       uint8_t   g_to_k[NETPGP_BUFSIZ];
+       int             n;
+
+       if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.elgamal.p)) {
+               (void) fprintf(stderr, "sz_encoded_m_buf wrong\n");
+               return 0;
+       }
+
+       n = __ops_elgamal_public_encrypt(g_to_k, encmpibuf, encoded_m_buf,
+                               sz_encoded_m_buf, &pubkey->key.elgamal);
+       if (n == -1) {
+               (void) fprintf(stderr, "__ops_elgamal_public_encrypt failure\n");
+               return 0;
+       }
+
+       if (n <= 0)
+               return 0;
+
+       skp->elgamal.g_to_k = BN_bin2bn(g_to_k, n / 2, NULL);
+       skp->elgamal.encrypted_m = BN_bin2bn(encmpibuf, n / 2, NULL);
+
+       if (__ops_get_debug_level(__FILE__)) {
+               hexdump(stderr, "encrypted mpi", encmpibuf, 16);
+       }
+       return 1;
+}
+
 static __ops_cb_ret_t
 write_parsed_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
 {
diff -r af0f0afef46a -r bb32028c5abb crypto/external/bsd/netpgp/dist/src/lib/crypto.h
--- a/crypto/external/bsd/netpgp/dist/src/lib/crypto.h  Sun Nov 07 01:12:22 2010 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/lib/crypto.h  Sun Nov 07 02:29:28 2010 +0000
@@ -129,6 +129,8 @@
 int __ops_rsa_private_decrypt(uint8_t *, const uint8_t *, size_t,
                        const __ops_rsa_seckey_t *, const __ops_rsa_pubkey_t *);
 
+int __ops_elgamal_public_encrypt(uint8_t *, uint8_t *, const uint8_t *, size_t,
+                       const __ops_elgamal_pubkey_t *);
 int __ops_elgamal_private_decrypt(uint8_t *, const uint8_t *, size_t,
                        const __ops_elgamal_seckey_t *, const __ops_elgamal_pubkey_t *);
 
@@ -161,6 +163,9 @@
 unsigned __ops_rsa_encrypt_mpi(const uint8_t *, const size_t,
                        const __ops_pubkey_t *,
                        __ops_pk_sesskey_params_t *);
+unsigned __ops_elgamal_encrypt_mpi(const uint8_t *, const size_t,
+                       const __ops_pubkey_t *,
+                       __ops_pk_sesskey_params_t *);
 
 /* Encrypt everything that's written */
 struct __ops_key_data;
diff -r af0f0afef46a -r bb32028c5abb crypto/external/bsd/netpgp/dist/src/lib/openssl_crypto.c
--- a/crypto/external/bsd/netpgp/dist/src/lib/openssl_crypto.c  Sun Nov 07 01:12:22 2010 +0000
+++ b/crypto/external/bsd/netpgp/dist/src/lib/openssl_crypto.c  Sun Nov 07 02:29:28 2010 +0000
@@ -57,7 +57,7 @@
 
 #if defined(__NetBSD__)
 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
-__RCSID("$NetBSD: openssl_crypto.c,v 1.30 2010/11/04 06:45:28 agc Exp $");
+__RCSID("$NetBSD: openssl_crypto.c,v 1.31 2010/11/07 02:29:28 agc Exp $");
 #endif
 
 #ifdef HAVE_OPENSSL_DSA_H
@@ -878,6 +878,103 @@
        return ok;
 }
 
+/*
+ * Decide the number of bits in the random componont k
+ *
+ * It should be in the same range as p for signing (which
+ * is deprecated), but can be much smaller for encrypting.
+ *
+ * Until I research it further, I just mimic gpg behaviour.
+ * It has a special mapping table, for values <= 5120,
+ * above that it uses 'arbitrary high number'. Following
+ * algorihm hovers 10-70 bits above gpg values.  And for
+ * larger p, it uses gpg's algorihm.
+ *
+ * The point is - if k gets large, encryption will be
+ * really slow.  It does not matter for decryption.
+ */
+static int
+decide_k_bits(int p_bits)
+{
+       return (p_bits <= 5120) ? p_bits / 10 + 160 : (p_bits / 8 + 200) * 3 / 2;
+}
+
+int
+__ops_elgamal_public_encrypt(uint8_t *g_to_k, uint8_t *encm,
+                       const uint8_t *in,
+                       size_t size,
+                       const __ops_elgamal_pubkey_t *pubkey)
+{
+       int     ret = 0;
+       int     k_bits;
+       BIGNUM     *m;
+       BIGNUM     *p;
+       BIGNUM     *g;
+       BIGNUM     *y;
+       BIGNUM     *k;
+       BIGNUM     *yk;
+       BIGNUM     *c1;
+       BIGNUM     *c2;
+       BN_CTX     *tmp;
+
+       m = BN_bin2bn(in, size, NULL);
+       p = pubkey->p;
+       g = pubkey->g;
+       y = pubkey->y;
+       k = BN_new();
+       yk = BN_new();
+       c1 = BN_new();
+       c2 = BN_new();
+       tmp = BN_CTX_new();
+       if (!m || !p || !g || !y || !k || !yk || !c1 || !c2 || !tmp) {
+               goto done;
+       }
+       /*
+        * generate k
+        */
+       k_bits = decide_k_bits(BN_num_bits(p));
+       if (!BN_rand(k, k_bits, 0, 0)) {
+               goto done;
+       }



Home | Main Index | Thread Index | Old Index