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>" 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>" % 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 %
This commit is contained in:
parent
3ca57ae182
commit
37d8b79b30
@ -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
|
||||
|
||||
|
65
crypto/external/bsd/netpgp/dist/src/lib/create.c
vendored
65
crypto/external/bsd/netpgp/dist/src/lib/create.c
vendored
@ -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 @@ encode_m_buf(const uint8_t *M, size_t mLen, const __ops_pubkey_t * pubkey,
|
||||
/* 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(const __ops_key_t *key, const char *ciphername)
|
||||
"__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 @@ __ops_create_pk_sesskey(const __ops_key_t *key, const char *ciphername)
|
||||
(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 @@ __ops_create_pk_sesskey(const __ops_key_t *key, const char *ciphername)
|
||||
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 @@ __ops_write_pk_sesskey(__ops_output_t *output, __ops_pk_sesskey_t *pksk)
|
||||
;
|
||||
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");
|
||||
|
41
crypto/external/bsd/netpgp/dist/src/lib/crypto.c
vendored
41
crypto/external/bsd/netpgp/dist/src/lib/crypto.c
vendored
@ -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 @@ __ops_rsa_encrypt_mpi(const uint8_t *encoded_m_buf,
|
||||
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)
|
||||
{
|
||||
|
@ -129,6 +129,8 @@ int __ops_rsa_private_encrypt(uint8_t *, const uint8_t *, size_t,
|
||||
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 @@ int __ops_decrypt_decode_mpi(uint8_t *, unsigned, const BIGNUM *,
|
||||
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;
|
||||
|
@ -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 @@ openssl_read_pem_seckey(const char *f, __ops_key_t *key, const char *type, int v
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* c1 = g^k c2 = m * y^k
|
||||
*/
|
||||
if (!BN_mod_exp(c1, g, k, p, tmp)) {
|
||||
goto done;
|
||||
}
|
||||
if (!BN_mod_exp(yk, y, k, p, tmp)) {
|
||||
goto done;
|
||||
}
|
||||
if (!BN_mod_mul(c2, m, yk, p, tmp)) {
|
||||
goto done;
|
||||
}
|
||||
/* result */
|
||||
BN_bn2bin(c1, g_to_k);
|
||||
ret = BN_num_bytes(c1); /* c1 = g^k */
|
||||
BN_bn2bin(c2, encm);
|
||||
ret += BN_num_bytes(c2); /* c2 = m * y^k */
|
||||
done:
|
||||
if (tmp) {
|
||||
BN_CTX_free(tmp);
|
||||
}
|
||||
if (c2) {
|
||||
BN_clear_free(c2);
|
||||
}
|
||||
if (c1) {
|
||||
BN_clear_free(c1);
|
||||
}
|
||||
if (yk) {
|
||||
BN_clear_free(yk);
|
||||
}
|
||||
if (k) {
|
||||
BN_clear_free(k);
|
||||
}
|
||||
if (g) {
|
||||
BN_clear_free(g);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
__ops_elgamal_private_decrypt(uint8_t *out,
|
||||
const uint8_t *in,
|
||||
|
Loading…
Reference in New Issue
Block a user