3 * OpenPGP MPI functions using OpenSSL BIGNUM code.
5 * Copyright (c) 2005 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * contrib/pgcrypto/pgp-mpi-openssl.c
33 #include <openssl/bn.h>
41 BIGNUM
*bn
= BN_bin2bn(n
->data
, n
->bytes
, NULL
);
45 if (BN_num_bits(bn
) != n
->bits
)
47 px_debug("mpi_to_bn: bignum conversion failed: mpi=%d, bn=%d",
48 n
->bits
, BN_num_bits(bn
));
61 res
= pgp_mpi_alloc(BN_num_bits(bn
), &n
);
65 if (BN_num_bytes(bn
) != n
->bytes
)
67 px_debug("bn_to_mpi: bignum conversion failed: bn=%d, mpi=%d",
68 BN_num_bytes(bn
), n
->bytes
);
72 BN_bn2bin(bn
, n
->data
);
77 * Decide the number of bits in the random component k
79 * It should be in the same range as p for signing (which
80 * is deprecated), but can be much smaller for encrypting.
82 * Until I research it further, I just mimic gpg behaviour.
83 * It has a special mapping table, for values <= 5120,
84 * above that it uses 'arbitrary high number'. Following
85 * algorithm hovers 10-70 bits above gpg values. And for
86 * larger p, it uses gpg's algorithm.
88 * The point is - if k gets large, encryption will be
89 * really slow. It does not matter for decryption.
92 decide_k_bits(int p_bits
)
95 return p_bits
/ 10 + 160;
97 return (p_bits
/ 8 + 200) * 3 / 2;
101 pgp_elgamal_encrypt(PGP_PubKey
*pk
, PGP_MPI
*_m
,
102 PGP_MPI
**c1_p
, PGP_MPI
**c2_p
)
104 int res
= PXE_PGP_MATH_FAILED
;
106 BIGNUM
*m
= mpi_to_bn(_m
);
107 BIGNUM
*p
= mpi_to_bn(pk
->pub
.elg
.p
);
108 BIGNUM
*g
= mpi_to_bn(pk
->pub
.elg
.g
);
109 BIGNUM
*y
= mpi_to_bn(pk
->pub
.elg
.y
);
110 BIGNUM
*k
= BN_new();
111 BIGNUM
*yk
= BN_new();
112 BIGNUM
*c1
= BN_new();
113 BIGNUM
*c2
= BN_new();
114 BN_CTX
*tmp
= BN_CTX_new();
116 if (!m
|| !p
|| !g
|| !y
|| !k
|| !yk
|| !c1
|| !c2
|| !tmp
)
122 k_bits
= decide_k_bits(BN_num_bits(p
));
123 if (!BN_rand(k
, k_bits
, 0, 0))
127 * c1 = g^k c2 = m * y^k
129 if (!BN_mod_exp(c1
, g
, k
, p
, tmp
))
131 if (!BN_mod_exp(yk
, y
, k
, p
, tmp
))
133 if (!BN_mod_mul(c2
, m
, yk
, p
, tmp
))
137 *c1_p
= bn_to_mpi(c1
);
138 *c2_p
= bn_to_mpi(c2
);
164 pgp_elgamal_decrypt(PGP_PubKey
*pk
, PGP_MPI
*_c1
, PGP_MPI
*_c2
,
167 int res
= PXE_PGP_MATH_FAILED
;
168 BIGNUM
*c1
= mpi_to_bn(_c1
);
169 BIGNUM
*c2
= mpi_to_bn(_c2
);
170 BIGNUM
*p
= mpi_to_bn(pk
->pub
.elg
.p
);
171 BIGNUM
*x
= mpi_to_bn(pk
->sec
.elg
.x
);
172 BIGNUM
*c1x
= BN_new();
173 BIGNUM
*div
= BN_new();
174 BIGNUM
*m
= BN_new();
175 BN_CTX
*tmp
= BN_CTX_new();
177 if (!c1
|| !c2
|| !p
|| !x
|| !c1x
|| !div
|| !m
|| !tmp
)
183 if (!BN_mod_exp(c1x
, c1
, x
, p
, tmp
))
185 if (!BN_mod_inverse(div
, c1x
, p
, tmp
))
187 if (!BN_mod_mul(m
, c2
, div
, p
, tmp
))
191 *msg_p
= bn_to_mpi(m
);
215 pgp_rsa_encrypt(PGP_PubKey
*pk
, PGP_MPI
*_m
, PGP_MPI
**c_p
)
217 int res
= PXE_PGP_MATH_FAILED
;
218 BIGNUM
*m
= mpi_to_bn(_m
);
219 BIGNUM
*e
= mpi_to_bn(pk
->pub
.rsa
.e
);
220 BIGNUM
*n
= mpi_to_bn(pk
->pub
.rsa
.n
);
221 BIGNUM
*c
= BN_new();
222 BN_CTX
*tmp
= BN_CTX_new();
224 if (!m
|| !e
|| !n
|| !c
|| !tmp
)
230 if (!BN_mod_exp(c
, m
, e
, n
, tmp
))
251 pgp_rsa_decrypt(PGP_PubKey
*pk
, PGP_MPI
*_c
, PGP_MPI
**m_p
)
253 int res
= PXE_PGP_MATH_FAILED
;
254 BIGNUM
*c
= mpi_to_bn(_c
);
255 BIGNUM
*d
= mpi_to_bn(pk
->sec
.rsa
.d
);
256 BIGNUM
*n
= mpi_to_bn(pk
->pub
.rsa
.n
);
257 BIGNUM
*m
= BN_new();
258 BN_CTX
*tmp
= BN_CTX_new();
260 if (!m
|| !d
|| !n
|| !c
|| !tmp
)
266 if (!BN_mod_exp(m
, c
, d
, n
, tmp
))