Age Owner TLA Line data Source code
1 : /*
2 : * pgp-mpi-openssl.c
3 : * OpenPGP MPI functions using OpenSSL BIGNUM code.
4 : *
5 : * Copyright (c) 2005 Marko Kreen
6 : * All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
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.
16 : *
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
27 : * SUCH DAMAGE.
28 : *
29 : * contrib/pgcrypto/pgp-mpi-openssl.c
30 : */
31 : #include "postgres.h"
32 :
33 : #include <openssl/bn.h>
34 :
35 : #include "pgp.h"
36 : #include "px.h"
37 :
38 : static BIGNUM *
5050 bruce 39 CBC 71 : mpi_to_bn(PGP_MPI *n)
40 : {
6385 41 71 : BIGNUM *bn = BN_bin2bn(n->data, n->bytes, NULL);
42 :
6482 43 71 : if (!bn)
6482 bruce 44 UBC 0 : return NULL;
6482 bruce 45 CBC 71 : if (BN_num_bits(bn) != n->bits)
46 : {
6482 bruce 47 UBC 0 : px_debug("mpi_to_bn: bignum conversion failed: mpi=%d, bn=%d",
48 : n->bits, BN_num_bits(bn));
49 0 : BN_clear_free(bn);
50 0 : return NULL;
51 : }
6482 bruce 52 CBC 71 : return bn;
53 : }
54 :
55 : static PGP_MPI *
56 24 : bn_to_mpi(BIGNUM *bn)
57 : {
58 : int res;
59 : PGP_MPI *n;
60 :
61 24 : res = pgp_mpi_alloc(BN_num_bits(bn), &n);
62 24 : if (res < 0)
6482 bruce 63 UBC 0 : return NULL;
64 :
6482 bruce 65 CBC 24 : if (BN_num_bytes(bn) != n->bytes)
66 : {
6482 bruce 67 UBC 0 : px_debug("bn_to_mpi: bignum conversion failed: bn=%d, mpi=%d",
6385 68 0 : BN_num_bytes(bn), n->bytes);
6482 69 0 : pgp_mpi_free(n);
70 0 : return NULL;
71 : }
6482 bruce 72 CBC 24 : BN_bn2bin(bn, n->data);
73 24 : return n;
74 : }
75 :
76 : /*
77 : * Decide the number of bits in the random component k
78 : *
79 : * It should be in the same range as p for signing (which
80 : * is deprecated), but can be much smaller for encrypting.
81 : *
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.
87 : *
88 : * The point is - if k gets large, encryption will be
89 : * really slow. It does not matter for decryption.
90 : */
91 : static int
92 5 : decide_k_bits(int p_bits)
93 : {
94 5 : if (p_bits <= 5120)
95 5 : return p_bits / 10 + 160;
96 : else
6482 bruce 97 UBC 0 : return (p_bits / 8 + 200) * 3 / 2;
98 : }
99 :
100 : int
5050 bruce 101 CBC 5 : pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *_m,
102 : PGP_MPI **c1_p, PGP_MPI **c2_p)
103 : {
6385 104 5 : int res = PXE_PGP_MATH_FAILED;
105 : int k_bits;
106 5 : BIGNUM *m = mpi_to_bn(_m);
107 5 : BIGNUM *p = mpi_to_bn(pk->pub.elg.p);
108 5 : BIGNUM *g = mpi_to_bn(pk->pub.elg.g);
109 5 : BIGNUM *y = mpi_to_bn(pk->pub.elg.y);
110 5 : BIGNUM *k = BN_new();
111 5 : BIGNUM *yk = BN_new();
112 5 : BIGNUM *c1 = BN_new();
113 5 : BIGNUM *c2 = BN_new();
114 5 : BN_CTX *tmp = BN_CTX_new();
115 :
6482 116 5 : if (!m || !p || !g || !y || !k || !yk || !c1 || !c2 || !tmp)
6482 bruce 117 UBC 0 : goto err;
118 :
119 : /*
120 : * generate k
121 : */
6482 bruce 122 CBC 5 : k_bits = decide_k_bits(BN_num_bits(p));
6448 123 5 : if (!BN_rand(k, k_bits, 0, 0))
6482 bruce 124 UBC 0 : goto err;
125 :
126 : /*
127 : * c1 = g^k c2 = m * y^k
128 : */
6482 bruce 129 CBC 5 : if (!BN_mod_exp(c1, g, k, p, tmp))
6482 bruce 130 UBC 0 : goto err;
6482 bruce 131 CBC 5 : if (!BN_mod_exp(yk, y, k, p, tmp))
6482 bruce 132 UBC 0 : goto err;
6482 bruce 133 CBC 5 : if (!BN_mod_mul(c2, m, yk, p, tmp))
6482 bruce 134 UBC 0 : goto err;
135 :
136 : /* result */
6482 bruce 137 CBC 5 : *c1_p = bn_to_mpi(c1);
138 5 : *c2_p = bn_to_mpi(c2);
139 5 : if (*c1_p && *c2_p)
140 5 : res = 0;
6482 bruce 141 UBC 0 : err:
6385 bruce 142 CBC 5 : if (tmp)
143 5 : BN_CTX_free(tmp);
144 5 : if (c2)
145 5 : BN_clear_free(c2);
146 5 : if (c1)
147 5 : BN_clear_free(c1);
148 5 : if (yk)
149 5 : BN_clear_free(yk);
150 5 : if (k)
151 5 : BN_clear_free(k);
152 5 : if (y)
153 5 : BN_clear_free(y);
154 5 : if (g)
155 5 : BN_clear_free(g);
156 5 : if (p)
157 5 : BN_clear_free(p);
158 5 : if (m)
159 5 : BN_clear_free(m);
6482 160 5 : return res;
161 : }
162 :
163 : int
5050 164 9 : pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_MPI *_c1, PGP_MPI *_c2,
165 : PGP_MPI **msg_p)
166 : {
6385 167 9 : int res = PXE_PGP_MATH_FAILED;
168 9 : BIGNUM *c1 = mpi_to_bn(_c1);
169 9 : BIGNUM *c2 = mpi_to_bn(_c2);
170 9 : BIGNUM *p = mpi_to_bn(pk->pub.elg.p);
171 9 : BIGNUM *x = mpi_to_bn(pk->sec.elg.x);
172 9 : BIGNUM *c1x = BN_new();
173 9 : BIGNUM *div = BN_new();
174 9 : BIGNUM *m = BN_new();
175 9 : BN_CTX *tmp = BN_CTX_new();
176 :
6482 177 9 : if (!c1 || !c2 || !p || !x || !c1x || !div || !m || !tmp)
6482 bruce 178 UBC 0 : goto err;
179 :
180 : /*
181 : * m = c2 / (c1^x)
182 : */
6482 bruce 183 CBC 9 : if (!BN_mod_exp(c1x, c1, x, p, tmp))
6482 bruce 184 UBC 0 : goto err;
6482 bruce 185 CBC 9 : if (!BN_mod_inverse(div, c1x, p, tmp))
6482 bruce 186 UBC 0 : goto err;
6482 bruce 187 CBC 9 : if (!BN_mod_mul(m, c2, div, p, tmp))
6482 bruce 188 UBC 0 : goto err;
189 :
190 : /* result */
6482 bruce 191 CBC 9 : *msg_p = bn_to_mpi(m);
192 9 : if (*msg_p)
193 9 : res = 0;
6482 bruce 194 UBC 0 : err:
6385 bruce 195 CBC 9 : if (tmp)
196 9 : BN_CTX_free(tmp);
197 9 : if (m)
198 9 : BN_clear_free(m);
199 9 : if (div)
200 9 : BN_clear_free(div);
201 9 : if (c1x)
202 9 : BN_clear_free(c1x);
203 9 : if (x)
204 9 : BN_clear_free(x);
205 9 : if (p)
206 9 : BN_clear_free(p);
207 9 : if (c2)
208 9 : BN_clear_free(c2);
209 9 : if (c1)
210 9 : BN_clear_free(c1);
6482 211 9 : return res;
212 : }
213 :
214 : int
5050 215 1 : pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *_m, PGP_MPI **c_p)
216 : {
6385 217 1 : int res = PXE_PGP_MATH_FAILED;
218 1 : BIGNUM *m = mpi_to_bn(_m);
219 1 : BIGNUM *e = mpi_to_bn(pk->pub.rsa.e);
220 1 : BIGNUM *n = mpi_to_bn(pk->pub.rsa.n);
221 1 : BIGNUM *c = BN_new();
222 1 : BN_CTX *tmp = BN_CTX_new();
223 :
6448 224 1 : if (!m || !e || !n || !c || !tmp)
6448 bruce 225 UBC 0 : goto err;
226 :
227 : /*
228 : * c = m ^ e
229 : */
6448 bruce 230 CBC 1 : if (!BN_mod_exp(c, m, e, n, tmp))
6448 bruce 231 UBC 0 : goto err;
232 :
6448 bruce 233 CBC 1 : *c_p = bn_to_mpi(c);
234 1 : if (*c_p)
235 1 : res = 0;
6448 bruce 236 UBC 0 : err:
6385 bruce 237 CBC 1 : if (tmp)
238 1 : BN_CTX_free(tmp);
239 1 : if (c)
240 1 : BN_clear_free(c);
241 1 : if (n)
242 1 : BN_clear_free(n);
243 1 : if (e)
244 1 : BN_clear_free(e);
245 1 : if (m)
246 1 : BN_clear_free(m);
6448 247 1 : return res;
248 : }
249 :
250 : int
5050 251 4 : pgp_rsa_decrypt(PGP_PubKey *pk, PGP_MPI *_c, PGP_MPI **m_p)
252 : {
6385 253 4 : int res = PXE_PGP_MATH_FAILED;
254 4 : BIGNUM *c = mpi_to_bn(_c);
255 4 : BIGNUM *d = mpi_to_bn(pk->sec.rsa.d);
256 4 : BIGNUM *n = mpi_to_bn(pk->pub.rsa.n);
257 4 : BIGNUM *m = BN_new();
258 4 : BN_CTX *tmp = BN_CTX_new();
259 :
6448 260 4 : if (!m || !d || !n || !c || !tmp)
6448 bruce 261 UBC 0 : goto err;
262 :
263 : /*
264 : * m = c ^ d
265 : */
6448 bruce 266 CBC 4 : if (!BN_mod_exp(m, c, d, n, tmp))
6448 bruce 267 UBC 0 : goto err;
268 :
6448 bruce 269 CBC 4 : *m_p = bn_to_mpi(m);
270 4 : if (*m_p)
271 4 : res = 0;
6448 bruce 272 UBC 0 : err:
6385 bruce 273 CBC 4 : if (tmp)
274 4 : BN_CTX_free(tmp);
275 4 : if (m)
276 4 : BN_clear_free(m);
277 4 : if (n)
278 4 : BN_clear_free(n);
279 4 : if (d)
280 4 : BN_clear_free(d);
281 4 : if (c)
282 4 : BN_clear_free(c);
6448 283 4 : return res;
284 : }
|