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, (int)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 pgp_elgamal_encrypt(PGP_PubKey * pk, PGP_MPI * _m, PGP_MPI ** c1_p, PGP_MPI ** c2_p) { int res = PXE_PGP_MATH_FAILED; int k_bits; BIGNUM *m = mpi_to_bn(_m); BIGNUM *p = mpi_to_bn(pk->pub.elg.p); BIGNUM *g = mpi_to_bn(pk->pub.elg.g); BIGNUM *y = mpi_to_bn(pk->pub.elg.y); BIGNUM *k = BN_new(); BIGNUM *yk = BN_new(); BIGNUM *c1 = BN_new(); BIGNUM *c2 = BN_new(); BN_CTX *tmp = BN_CTX_new(); if (!m || !p || !g || !y || !k || !yk || !c1 || !c2 || !tmp) goto err; /* * generate k */ k_bits = decide_k_bits(BN_num_bits(p)); if (!BN_rand(k, k_bits, 0, 0)) goto err; /* * c1 = g^k c2 = m * y^k */ if (!BN_mod_exp(c1, g, k, p, tmp)) goto err; if (!BN_mod_exp(yk, y, k, p, tmp)) goto err; if (!BN_mod_mul(c2, m, yk, p, tmp)) goto err; /* result */ *c1_p = bn_to_mpi(c1); *c2_p = bn_to_mpi(c2); if (*c1_p && *c2_p) res = 0; err: 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 (y) BN_clear_free(y); if (g) BN_clear_free(g); if (p) BN_clear_free(p); if (m) BN_clear_free(m); return res; }