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