3 * OpenPGP MPI functions.
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
42 mpz_t
*mp
= mp_int_alloc();
44 mp_int_init_size(mp
, 256);
49 mp_clear_free(mpz_t
* a
)
53 /* fixme: no clear? */
59 mp_px_rand(uint32 bits
, mpz_t
* res
)
62 unsigned bytes
= (bits
+ 7) / 8;
63 int last_bits
= bits
& 7;
66 buf
= px_alloc(bytes
);
67 err
= px_get_random_bytes(buf
, bytes
);
74 /* clear unnecessary bits and set last bit to one */
77 buf
[0] >>= 8 - last_bits
;
78 buf
[0] |= 1 << (last_bits
- 1);
83 mp_int_read_unsigned(res
, buf
, bytes
);
91 mp_modmul(mpz_t
* a
, mpz_t
* b
, mpz_t
* p
, mpz_t
* res
)
93 mpz_t
*tmp
= mp_new();
95 mp_int_mul(a
, b
, tmp
);
96 mp_int_mod(tmp
, p
, res
);
101 mpi_to_bn(PGP_MPI
* n
)
103 mpz_t
*bn
= mp_new();
105 mp_int_read_unsigned(bn
, n
->data
, n
->bytes
);
109 if (mp_int_count_bits(bn
) != n
->bits
)
111 px_debug("mpi_to_bn: bignum conversion failed: mpi=%d, bn=%d",
112 n
->bits
, mp_int_count_bits(bn
));
120 bn_to_mpi(mpz_t
* bn
)
126 res
= pgp_mpi_alloc(mp_int_count_bits(bn
), &n
);
130 bytes
= (mp_int_count_bits(bn
) + 7) / 8;
131 if (bytes
!= n
->bytes
)
133 px_debug("bn_to_mpi: bignum conversion failed: bn=%d, mpi=%d",
138 mp_int_to_unsigned(bn
, n
->data
, n
->bytes
);
143 * Decide the number of bits in the random componont k
145 * It should be in the same range as p for signing (which
146 * is deprecated), but can be much smaller for encrypting.
148 * Until I research it further, I just mimic gpg behaviour.
149 * It has a special mapping table, for values <= 5120,
150 * above that it uses 'arbitrary high number'. Following
151 * algorihm hovers 10-70 bits above gpg values. And for
152 * larger p, it uses gpg's algorihm.
154 * The point is - if k gets large, encryption will be
155 * really slow. It does not matter for decryption.
158 decide_k_bits(int p_bits
)
161 return p_bits
/ 10 + 160;
163 return (p_bits
/ 8 + 200) * 3 / 2;
167 pgp_elgamal_encrypt(PGP_PubKey
* pk
, PGP_MPI
* _m
,
168 PGP_MPI
** c1_p
, PGP_MPI
** c2_p
)
170 int res
= PXE_PGP_MATH_FAILED
;
172 mpz_t
*m
= mpi_to_bn(_m
);
173 mpz_t
*p
= mpi_to_bn(pk
->pub
.elg
.p
);
174 mpz_t
*g
= mpi_to_bn(pk
->pub
.elg
.g
);
175 mpz_t
*y
= mpi_to_bn(pk
->pub
.elg
.y
);
177 mpz_t
*yk
= mp_new();
178 mpz_t
*c1
= mp_new();
179 mpz_t
*c2
= mp_new();
181 if (!m
|| !p
|| !g
|| !y
|| !k
|| !yk
|| !c1
|| !c2
)
187 k_bits
= decide_k_bits(mp_int_count_bits(p
));
188 res
= mp_px_rand(k_bits
, k
);
193 * c1 = g^k c2 = m * y^k
195 mp_int_exptmod(g
, k
, p
, c1
);
196 mp_int_exptmod(y
, k
, p
, yk
);
197 mp_modmul(m
, yk
, p
, c2
);
200 *c1_p
= bn_to_mpi(c1
);
201 *c2_p
= bn_to_mpi(c2
);
217 pgp_elgamal_decrypt(PGP_PubKey
* pk
, PGP_MPI
* _c1
, PGP_MPI
* _c2
,
220 int res
= PXE_PGP_MATH_FAILED
;
221 mpz_t
*c1
= mpi_to_bn(_c1
);
222 mpz_t
*c2
= mpi_to_bn(_c2
);
223 mpz_t
*p
= mpi_to_bn(pk
->pub
.elg
.p
);
224 mpz_t
*x
= mpi_to_bn(pk
->sec
.elg
.x
);
225 mpz_t
*c1x
= mp_new();
226 mpz_t
*div
= mp_new();
229 if (!c1
|| !c2
|| !p
|| !x
|| !c1x
|| !div
|| !m
)
235 mp_int_exptmod(c1
, x
, p
, c1x
);
236 mp_int_invmod(c1x
, p
, div
);
237 mp_modmul(c2
, div
, p
, m
);
240 *msg_p
= bn_to_mpi(m
);
255 pgp_rsa_encrypt(PGP_PubKey
* pk
, PGP_MPI
* _m
, PGP_MPI
** c_p
)
257 int res
= PXE_PGP_MATH_FAILED
;
258 mpz_t
*m
= mpi_to_bn(_m
);
259 mpz_t
*e
= mpi_to_bn(pk
->pub
.rsa
.e
);
260 mpz_t
*n
= mpi_to_bn(pk
->pub
.rsa
.n
);
263 if (!m
|| !e
|| !n
|| !c
)
269 mp_int_exptmod(m
, e
, n
, c
);
283 pgp_rsa_decrypt(PGP_PubKey
* pk
, PGP_MPI
* _c
, PGP_MPI
** m_p
)
285 int res
= PXE_PGP_MATH_FAILED
;
286 mpz_t
*c
= mpi_to_bn(_c
);
287 mpz_t
*d
= mpi_to_bn(pk
->sec
.rsa
.d
);
288 mpz_t
*n
= mpi_to_bn(pk
->pub
.rsa
.n
);
291 if (!m
|| !d
|| !n
|| !c
)
297 mp_int_exptmod(c
, d
, n
, m
);