1 /* $OpenBSD: gostr341001.c,v 1.3 2015/02/11 03:19:37 doug Exp $ */
3 * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4 * Copyright (c) 2005-2006 Cryptocom LTD
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * 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
15 * the documentation and/or other materials provided with the
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/)"
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.
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.
32 * 6. Redistributions of any form whatsoever must retain the following
34 * "This product includes software developed by the OpenSSL Project
35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
54 #include <openssl/opensslconf.h>
56 #ifndef OPENSSL_NO_GOST
57 #include <openssl/bn.h>
58 #include <openssl/err.h>
59 #include <openssl/gost.h>
60 #include "gost_locl.h"
62 /* Convert little-endian byte array into bignum */
64 GOST_le2bn(const unsigned char *buf
, size_t len
, BIGNUM
*bn
)
66 unsigned char temp
[64];
72 for (i
= 0; i
< len
; i
++) {
73 temp
[len
- 1 - i
] = buf
[i
];
76 return BN_bin2bn(temp
, len
, bn
);
80 GOST_bn2le(BIGNUM
*bn
, unsigned char *buf
, int len
)
82 unsigned char temp
[64];
85 bytes
= BN_num_bytes(bn
);
86 if (len
> 64 || bytes
> len
)
91 for (i
= 0; i
< bytes
; i
++) {
92 buf
[bytes
- 1 - i
] = temp
[i
];
95 memset(buf
+ bytes
, 0, len
- bytes
);
101 gost2001_compute_public(GOST_KEY
*ec
)
103 const EC_GROUP
*group
= GOST_KEY_get0_group(ec
);
104 EC_POINT
*pub_key
= NULL
;
105 const BIGNUM
*priv_key
= NULL
;
110 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
,
111 GOST_R_KEY_IS_NOT_INITIALIZED
);
116 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
,
117 ERR_R_MALLOC_FAILURE
);
121 if ((priv_key
= GOST_KEY_get0_private_key(ec
)) == NULL
)
124 pub_key
= EC_POINT_new(group
);
127 if (EC_POINT_mul(group
, pub_key
, priv_key
, NULL
, NULL
, ctx
) == 0)
129 if (GOST_KEY_set_public_key(ec
, pub_key
) == 0)
135 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
, ERR_R_EC_LIB
);
137 EC_POINT_free(pub_key
);
146 gost2001_do_sign(BIGNUM
*md
, GOST_KEY
*eckey
)
148 ECDSA_SIG
*newsig
= NULL
;
149 BIGNUM
*order
= NULL
;
150 const EC_GROUP
*group
;
151 const BIGNUM
*priv_key
;
152 BIGNUM
*r
= NULL
, *s
= NULL
, *X
= NULL
, *tmp
= NULL
, *tmp2
= NULL
, *k
=
155 BN_CTX
*ctx
= BN_CTX_new();
159 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_MALLOC_FAILURE
);
163 newsig
= ECDSA_SIG_new();
164 if (newsig
== NULL
) {
165 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_MALLOC_FAILURE
);
170 group
= GOST_KEY_get0_group(eckey
);
171 if ((order
= BN_CTX_get(ctx
)) == NULL
)
173 if (EC_GROUP_get_order(group
, order
, ctx
) == 0)
175 priv_key
= GOST_KEY_get0_private_key(eckey
);
176 if ((e
= BN_CTX_get(ctx
)) == NULL
)
178 if (BN_mod(e
, md
, order
, ctx
) == 0)
182 if ((k
= BN_CTX_get(ctx
)) == NULL
)
184 if ((X
= BN_CTX_get(ctx
)) == NULL
)
186 if ((C
= EC_POINT_new(group
)) == NULL
)
190 if (!BN_rand_range(k
, order
)) {
191 GOSTerr(GOST_F_GOST2001_DO_SIGN
,
192 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED
);
196 * We do not want timing information to leak the length
197 * of k, so we compute G*k using an equivalent scalar
198 * of fixed bit-length.
200 if (BN_add(k
, k
, order
) == 0)
202 if (BN_num_bits(k
) <= BN_num_bits(order
))
203 if (BN_add(k
, k
, order
) == 0)
206 if (EC_POINT_mul(group
, C
, k
, NULL
, NULL
, ctx
) == 0) {
207 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_EC_LIB
);
210 if (EC_POINT_get_affine_coordinates_GFp(group
, C
, X
,
212 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_EC_LIB
);
215 if (BN_nnmod(r
, X
, order
, ctx
) == 0)
217 } while (BN_is_zero(r
));
218 /* s = (r*priv_key+k*e) mod order */
220 if ((tmp
= BN_CTX_get(ctx
)) == NULL
)
223 if (BN_mod_mul(tmp
, priv_key
, r
, order
, ctx
) == 0)
226 if ((tmp2
= BN_CTX_get(ctx
)) == NULL
)
229 if (BN_mod_mul(tmp2
, k
, e
, order
, ctx
) == 0)
231 if (BN_mod_add(s
, tmp
, tmp2
, order
, ctx
) == 0)
233 } while (BN_is_zero(s
));
243 ECDSA_SIG_free(newsig
);
250 gost2001_do_verify(BIGNUM
*md
, ECDSA_SIG
*sig
, GOST_KEY
*ec
)
252 BN_CTX
*ctx
= BN_CTX_new();
253 const EC_GROUP
*group
= GOST_KEY_get0_group(ec
);
255 BIGNUM
*e
= NULL
, *R
= NULL
, *v
= NULL
, *z1
= NULL
, *z2
= NULL
;
256 BIGNUM
*X
= NULL
, *tmp
= NULL
;
258 const EC_POINT
*pub_key
= NULL
;
264 if ((order
= BN_CTX_get(ctx
)) == NULL
)
266 if ((e
= BN_CTX_get(ctx
)) == NULL
)
268 if ((z1
= BN_CTX_get(ctx
)) == NULL
)
270 if ((z2
= BN_CTX_get(ctx
)) == NULL
)
272 if ((tmp
= BN_CTX_get(ctx
)) == NULL
)
274 if ((X
= BN_CTX_get(ctx
)) == NULL
)
276 if ((R
= BN_CTX_get(ctx
)) == NULL
)
278 if ((v
= BN_CTX_get(ctx
)) == NULL
)
281 if (EC_GROUP_get_order(group
, order
, ctx
) == 0)
283 pub_key
= GOST_KEY_get0_public_key(ec
);
284 if (BN_is_zero(sig
->s
) || BN_is_zero(sig
->r
) ||
285 BN_cmp(sig
->s
, order
) >= 1 || BN_cmp(sig
->r
, order
) >= 1) {
286 GOSTerr(GOST_F_GOST2001_DO_VERIFY
,
287 GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q
);
291 if (BN_mod(e
, md
, order
, ctx
) == 0)
295 if ((v
= BN_mod_inverse(v
, e
, order
, ctx
)) == NULL
)
297 if (BN_mod_mul(z1
, sig
->s
, v
, order
, ctx
) == 0)
299 if (BN_sub(tmp
, order
, sig
->r
) == 0)
301 if (BN_mod_mul(z2
, tmp
, v
, order
, ctx
) == 0)
303 if ((C
= EC_POINT_new(group
)) == NULL
)
305 if (EC_POINT_mul(group
, C
, z1
, pub_key
, z2
, ctx
) == 0) {
306 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_EC_LIB
);
309 if (EC_POINT_get_affine_coordinates_GFp(group
, C
, X
, NULL
, ctx
) == 0) {
310 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_EC_LIB
);
313 if (BN_mod(R
, X
, order
, ctx
) == 0)
315 if (BN_cmp(R
, sig
->r
) != 0) {
316 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, GOST_R_SIGNATURE_MISMATCH
);
329 /* Implementation of CryptoPro VKO 34.10-2001 algorithm */
331 VKO_compute_key(BIGNUM
*X
, BIGNUM
*Y
, const GOST_KEY
*pkey
, GOST_KEY
*priv_key
,
334 BIGNUM
*p
= NULL
, *order
= NULL
;
335 const BIGNUM
*key
= GOST_KEY_get0_private_key(priv_key
);
336 const EC_GROUP
*group
= GOST_KEY_get0_group(priv_key
);
337 const EC_POINT
*pub_key
= GOST_KEY_get0_public_key(pkey
);
342 pnt
= EC_POINT_new(group
);
349 if ((p
= BN_CTX_get(ctx
)) == NULL
)
351 if ((order
= BN_CTX_get(ctx
)) == NULL
)
353 if (EC_GROUP_get_order(group
, order
, ctx
) == 0)
355 if (BN_mod_mul(p
, key
, ukm
, order
, ctx
) == 0)
357 if (EC_POINT_mul(group
, pnt
, NULL
, pub_key
, p
, ctx
) == 0)
359 if (EC_POINT_get_affine_coordinates_GFp(group
, pnt
, X
, Y
, ctx
) == 0)
373 gost2001_keygen(GOST_KEY
*ec
)
375 BIGNUM
*order
= BN_new(), *d
= BN_new();
376 const EC_GROUP
*group
= GOST_KEY_get0_group(ec
);
379 if (order
== NULL
|| d
== NULL
)
381 if (EC_GROUP_get_order(group
, order
, NULL
) == 0)
385 if (BN_rand_range(d
, order
) == 0) {
386 GOSTerr(GOST_F_GOST2001_KEYGEN
,
387 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED
);
390 } while (BN_is_zero(d
));
392 if (GOST_KEY_set_private_key(ec
, d
) == 0)
394 rc
= gost2001_compute_public(ec
);