summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/gost/gostr341001.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/gost/gostr341001.c')
-rw-r--r--src/lib/libcrypto/gost/gostr341001.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/src/lib/libcrypto/gost/gostr341001.c b/src/lib/libcrypto/gost/gostr341001.c
new file mode 100644
index 0000000000..3c314765f7
--- /dev/null
+++ b/src/lib/libcrypto/gost/gostr341001.c
@@ -0,0 +1,321 @@
1/* $OpenBSD: gostr341001.c,v 1.1 2014/11/09 19:17:13 miod Exp $ */
2/*
3 * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4 * Copyright (c) 2005-2006 Cryptocom LTD
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. All advertising materials mentioning features or use of this
19 * software must display the following acknowledgment:
20 * "This product includes software developed by the OpenSSL Project
21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22 *
23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24 * endorse or promote products derived from this software without
25 * prior written permission. For written permission, please contact
26 * openssl-core@openssl.org.
27 *
28 * 5. Products derived from this software may not be called "OpenSSL"
29 * nor may "OpenSSL" appear in their names without prior written
30 * permission of the OpenSSL Project.
31 *
32 * 6. Redistributions of any form whatsoever must retain the following
33 * acknowledgment:
34 * "This product includes software developed by the OpenSSL Project
35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48 * OF THE POSSIBILITY OF SUCH DAMAGE.
49 * ====================================================================
50 */
51
52#include <string.h>
53
54#include <openssl/opensslconf.h>
55
56#ifndef OPENSSL_NO_GOST
57#include <openssl/err.h>
58#include <openssl/gost.h>
59#include "gost_locl.h"
60
61/* Convert little-endian byte array into bignum */
62BIGNUM *GOST_le2bn(const unsigned char * buf, size_t len, BIGNUM * bn)
63{
64 unsigned char temp[64];
65 int i;
66 if (len > 64)
67 return NULL;
68
69 for (i = 0; i < len; i++) {
70 temp[len - 1 - i] = buf[i];
71 }
72
73 return BN_bin2bn(temp, len, bn);
74}
75
76int GOST_bn2le(BIGNUM * bn, unsigned char * buf, int len)
77{
78 unsigned char temp[64];
79 int i, bytes;
80
81 bytes = BN_num_bytes(bn);
82 if (len > 64 || bytes > len)
83 return 0;
84
85 BN_bn2bin(bn, temp);
86
87 for (i = 0; i < bytes; i++) {
88 buf[bytes - 1 - i] = temp[i];
89 }
90
91 memset(buf + bytes, 0, len - bytes);
92
93 return 1;
94}
95
96
97int gost2001_compute_public(GOST_KEY * ec)
98{
99 const EC_GROUP *group = GOST_KEY_get0_group(ec);
100 EC_POINT *pub_key = NULL;
101 const BIGNUM *priv_key = NULL;
102 BN_CTX *ctx = NULL;
103 int ok = 0;
104
105 if (!group) {
106 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,
107 GOST_R_KEY_IS_NOT_INITIALIZED);
108 return 0;
109 }
110 ctx = BN_CTX_new();
111 BN_CTX_start(ctx);
112 if (!(priv_key = GOST_KEY_get0_private_key(ec))) {
113 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
114 goto err;
115 }
116
117 pub_key = EC_POINT_new(group);
118 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) {
119 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
120 goto err;
121 }
122 if (!GOST_KEY_set_public_key(ec, pub_key)) {
123 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
124 goto err;
125 }
126 ok = 256;
127err:
128 BN_CTX_end(ctx);
129 EC_POINT_free(pub_key);
130 BN_CTX_free(ctx);
131 return ok;
132}
133
134ECDSA_SIG *gost2001_do_sign(BIGNUM * md, GOST_KEY * eckey)
135{
136 ECDSA_SIG *newsig = NULL;
137 BIGNUM *order = NULL;
138 const EC_GROUP *group;
139 const BIGNUM *priv_key;
140 BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k =
141 NULL, *e = NULL;
142 EC_POINT *C = NULL;
143 BN_CTX *ctx = BN_CTX_new();
144 BN_CTX_start(ctx);
145 newsig = ECDSA_SIG_new();
146 if (!newsig) {
147 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
148 goto err;
149 }
150 s = newsig->s;
151 r = newsig->r;
152 group = GOST_KEY_get0_group(eckey);
153 order = BN_CTX_get(ctx);
154 EC_GROUP_get_order(group, order, ctx);
155 priv_key = GOST_KEY_get0_private_key(eckey);
156 e = BN_CTX_get(ctx);
157 BN_mod(e, md, order, ctx);
158 if (BN_is_zero(e)) {
159 BN_one(e);
160 }
161 k = BN_CTX_get(ctx);
162 X = BN_CTX_get(ctx);
163 C = EC_POINT_new(group);
164 do {
165 do {
166 if (!BN_rand_range(k, order)) {
167 GOSTerr(GOST_F_GOST2001_DO_SIGN,
168 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
169 ECDSA_SIG_free(newsig);
170 newsig = NULL;
171 goto err;
172 }
173 /* We do not want timing information to leak the length of k,
174 * so we compute G*k using an equivalent scalar of fixed
175 * bit-length. */
176 if (!BN_add(k, k, order))
177 goto err;
178 if (BN_num_bits(k) <= BN_num_bits(order))
179 if (!BN_add(k, k, order))
180 goto err;
181
182 if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) {
183 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
184 ECDSA_SIG_free(newsig);
185 newsig = NULL;
186 goto err;
187 }
188 if (!EC_POINT_get_affine_coordinates_GFp
189 (group, C, X, NULL, ctx)) {
190 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
191 ECDSA_SIG_free(newsig);
192 newsig = NULL;
193 goto err;
194 }
195 BN_nnmod(r, X, order, ctx);
196 }
197 while (BN_is_zero(r));
198 /* s = (r*priv_key+k*e) mod order */
199 if (!tmp)
200 tmp = BN_CTX_get(ctx);
201 BN_mod_mul(tmp, priv_key, r, order, ctx);
202 if (!tmp2)
203 tmp2 = BN_CTX_get(ctx);
204 BN_mod_mul(tmp2, k, e, order, ctx);
205 BN_mod_add(s, tmp, tmp2, order, ctx);
206 }
207 while (BN_is_zero(s));
208
209err:
210 BN_CTX_end(ctx);
211 BN_CTX_free(ctx);
212 EC_POINT_free(C);
213 BN_free(md);
214 return newsig;
215}
216
217int gost2001_do_verify(BIGNUM * md, ECDSA_SIG * sig, GOST_KEY * ec)
218{
219 BN_CTX *ctx = BN_CTX_new();
220 const EC_GROUP *group = GOST_KEY_get0_group(ec);
221 BIGNUM *order;
222 BIGNUM *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = NULL;
223 BIGNUM *X = NULL, *tmp = NULL;
224 EC_POINT *C = NULL;
225 const EC_POINT *pub_key = NULL;
226 int ok = 0;
227
228 BN_CTX_start(ctx);
229 order = BN_CTX_get(ctx);
230 e = BN_CTX_get(ctx);
231 z1 = BN_CTX_get(ctx);
232 z2 = BN_CTX_get(ctx);
233 tmp = BN_CTX_get(ctx);
234 X = BN_CTX_get(ctx);
235 R = BN_CTX_get(ctx);
236 v = BN_CTX_get(ctx);
237
238 EC_GROUP_get_order(group, order, ctx);
239 pub_key = GOST_KEY_get0_public_key(ec);
240 if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
241 (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) {
242 GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
243 goto err;
244
245 }
246
247 BN_mod(e, md, order, ctx);
248 if (BN_is_zero(e))
249 BN_one(e);
250 v = BN_mod_inverse(v, e, order, ctx);
251 BN_mod_mul(z1, sig->s, v, order, ctx);
252 BN_sub(tmp, order, sig->r);
253 BN_mod_mul(z2, tmp, v, order, ctx);
254 C = EC_POINT_new(group);
255 if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) {
256 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
257 goto err;
258 }
259 if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
260 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
261 goto err;
262 }
263 BN_mod(R, X, order, ctx);
264 if (BN_cmp(R, sig->r) != 0) {
265 GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH);
266 } else {
267 ok = 1;
268 }
269 err:
270 EC_POINT_free(C);
271 BN_CTX_end(ctx);
272 BN_CTX_free(ctx);
273 return ok;
274}
275
276
277/* Implementation of CryptoPro VKO 34.10-2001 algorithm */
278void VKO_compute_key(BIGNUM * X, BIGNUM * Y,
279 const GOST_KEY * pkey, GOST_KEY * priv_key,
280 const BIGNUM * ukm)
281{
282 BIGNUM *p = NULL, *order = NULL;
283 const BIGNUM *key = GOST_KEY_get0_private_key(priv_key);
284 const EC_POINT *pub_key = GOST_KEY_get0_public_key(pkey);
285 EC_POINT *pnt = EC_POINT_new(GOST_KEY_get0_group(priv_key));
286 BN_CTX *ctx = BN_CTX_new();
287
288 BN_CTX_start(ctx);
289 p = BN_CTX_get(ctx);
290 order = BN_CTX_get(ctx);
291 EC_GROUP_get_order(GOST_KEY_get0_group(priv_key), order, ctx);
292 BN_mod_mul(p, key, ukm, order, ctx);
293 EC_POINT_mul(GOST_KEY_get0_group(priv_key), pnt, NULL, pub_key, p, ctx);
294 EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(priv_key),
295 pnt, X, Y, ctx);
296 BN_CTX_end(ctx);
297 BN_CTX_free(ctx);
298 EC_POINT_free(pnt);
299}
300
301int gost2001_keygen(GOST_KEY * ec)
302{
303 BIGNUM *order = BN_new(), *d = BN_new();
304 const EC_GROUP *group = GOST_KEY_get0_group(ec);
305 EC_GROUP_get_order(group, order, NULL);
306
307 do {
308 if (!BN_rand_range(d, order)) {
309 GOSTerr(GOST_F_GOST2001_KEYGEN,
310 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
311 BN_free(d);
312 BN_free(order);
313 return 0;
314 }
315 } while (BN_is_zero(d));
316 GOST_KEY_set_private_key(ec, d);
317 BN_free(d);
318 BN_free(order);
319 return gost2001_compute_public(ec);
320}
321#endif