summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/gost/gostr341001_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/gost/gostr341001_key.c')
-rw-r--r--src/lib/libcrypto/gost/gostr341001_key.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/src/lib/libcrypto/gost/gostr341001_key.c b/src/lib/libcrypto/gost/gostr341001_key.c
new file mode 100644
index 0000000000..9c7f52b769
--- /dev/null
+++ b/src/lib/libcrypto/gost/gostr341001_key.c
@@ -0,0 +1,306 @@
1/* $OpenBSD: gostr341001_key.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 <openssl/opensslconf.h>
53
54#ifndef OPENSSL_NO_GOST
55#include <openssl/err.h>
56#include <openssl/gost.h>
57#include <openssl/objects.h>
58#include "gost_locl.h"
59
60struct gost_key_st {
61 EC_GROUP *group;
62
63 EC_POINT *pub_key;
64 BIGNUM *priv_key;
65
66 int references;
67
68 int digest_nid;
69};
70
71GOST_KEY * GOST_KEY_new(void)
72{
73 GOST_KEY *ret;
74
75 ret = malloc(sizeof(GOST_KEY));
76 if (ret == NULL) {
77 GOSTerr(GOST_F_GOST_KEY_NEW, ERR_R_MALLOC_FAILURE);
78 return (NULL);
79 }
80 ret->group = NULL;
81 ret->pub_key = NULL;
82 ret->priv_key = NULL;
83 ret->references = 1;
84 ret->digest_nid = NID_undef;
85 return (ret);
86}
87
88void GOST_KEY_free(GOST_KEY * r)
89{
90 int i;
91
92 if (r == NULL)
93 return;
94
95 i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC);
96 if (i > 0)
97 return;
98
99 EC_GROUP_free(r->group);
100 EC_POINT_free(r->pub_key);
101 BN_clear_free(r->priv_key);
102
103 OPENSSL_cleanse((void *) r, sizeof(GOST_KEY));
104
105 free(r);
106}
107
108int GOST_KEY_check_key(const GOST_KEY * key)
109{
110 int ok = 0;
111 BN_CTX *ctx = NULL;
112 BIGNUM *order = NULL;
113 EC_POINT *point = NULL;
114
115 if (!key || !key->group || !key->pub_key) {
116 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
117 return 0;
118 }
119 if (EC_POINT_is_at_infinity(key->group, key->pub_key)) {
120 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
121 goto err;
122 }
123 if ((ctx = BN_CTX_new()) == NULL)
124 goto err;
125 if ((point = EC_POINT_new(key->group)) == NULL)
126 goto err;
127
128 /* testing whether the pub_key is on the elliptic curve */
129 if (!EC_POINT_is_on_curve(key->group, key->pub_key, ctx)) {
130 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
131 goto err;
132 }
133 /* testing whether pub_key * order is the point at infinity */
134 if ((order = BN_new()) == NULL)
135 goto err;
136 if (!EC_GROUP_get_order(key->group, order, ctx)) {
137 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
138 goto err;
139 }
140 if (!EC_POINT_mul(key->group, point, NULL, key->pub_key, order, ctx)) {
141 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB);
142 goto err;
143 }
144 if (!EC_POINT_is_at_infinity(key->group, point)) {
145 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
146 goto err;
147 }
148 /*
149 * in case the priv_key is present : check if generator * priv_key ==
150 * pub_key
151 */
152 if (key->priv_key) {
153 if (BN_cmp(key->priv_key, order) >= 0) {
154 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
155 goto err;
156 }
157 if (!EC_POINT_mul(key->group, point, key->priv_key,
158 NULL, NULL, ctx)) {
159 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, ERR_R_EC_LIB);
160 goto err;
161 }
162 if (EC_POINT_cmp(key->group, point, key->pub_key,
163 ctx) != 0) {
164 GOSTerr(GOST_F_GOST_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
165 goto err;
166 }
167 }
168 ok = 1;
169err:
170 BN_free(order);
171 BN_CTX_free(ctx);
172 EC_POINT_free(point);
173 return (ok);
174}
175
176int GOST_KEY_set_public_key_affine_coordinates(GOST_KEY * key, BIGNUM * x, BIGNUM * y)
177{
178 BN_CTX *ctx = NULL;
179 BIGNUM *tx, *ty;
180 EC_POINT *point = NULL;
181 int ok = 0;
182
183 if (!key || !key->group || !x || !y) {
184 GOSTerr(GOST_F_GOST_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
185 ERR_R_PASSED_NULL_PARAMETER);
186 return 0;
187 }
188 ctx = BN_CTX_new();
189 if (!ctx)
190 goto err;
191
192 point = EC_POINT_new(key->group);
193
194 if (!point)
195 goto err;
196
197 tx = BN_CTX_get(ctx);
198 ty = BN_CTX_get(ctx);
199 if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
200 x, y, ctx))
201 goto err;
202 if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
203 tx, ty, ctx))
204 goto err;
205 /*
206 * Check if retrieved coordinates match originals: if not values are
207 * out of range.
208 */
209 if (BN_cmp(x, tx) || BN_cmp(y, ty)) {
210 GOSTerr(GOST_F_GOST_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
211 EC_R_COORDINATES_OUT_OF_RANGE);
212 goto err;
213 }
214 if (!GOST_KEY_set_public_key(key, point))
215 goto err;
216
217 if (GOST_KEY_check_key(key) == 0)
218 goto err;
219
220 ok = 1;
221
222err:
223 BN_CTX_free(ctx);
224 EC_POINT_free(point);
225 return ok;
226
227}
228
229const EC_GROUP * GOST_KEY_get0_group(const GOST_KEY * key)
230{
231 return key->group;
232}
233
234int GOST_KEY_set_group(GOST_KEY * key, const EC_GROUP * group)
235{
236 EC_GROUP_free(key->group);
237 key->group = EC_GROUP_dup(group);
238 return (key->group == NULL) ? 0 : 1;
239}
240
241const BIGNUM * GOST_KEY_get0_private_key(const GOST_KEY * key)
242{
243 return key->priv_key;
244}
245
246int GOST_KEY_set_private_key(GOST_KEY * key, const BIGNUM * priv_key)
247{
248 BN_clear_free(key->priv_key);
249 key->priv_key = BN_dup(priv_key);
250 return (key->priv_key == NULL) ? 0 : 1;
251}
252
253const EC_POINT *
254GOST_KEY_get0_public_key(const GOST_KEY * key)
255{
256 return key->pub_key;
257}
258
259int GOST_KEY_set_public_key(GOST_KEY * key, const EC_POINT * pub_key)
260{
261 EC_POINT_free(key->pub_key);
262 key->pub_key = EC_POINT_dup(pub_key, key->group);
263 return (key->pub_key == NULL) ? 0 : 1;
264}
265
266int GOST_KEY_get_digest(const GOST_KEY * key)
267{
268 return key->digest_nid;
269}
270int GOST_KEY_set_digest(GOST_KEY * key, int digest_nid)
271{
272 if (digest_nid == NID_id_GostR3411_94_CryptoProParamSet ||
273 digest_nid == NID_id_tc26_gost3411_2012_256 ||
274 digest_nid == NID_id_tc26_gost3411_2012_512) {
275 key->digest_nid = digest_nid;
276 return 1;
277 }
278
279 return 0;
280}
281
282size_t GOST_KEY_get_size(const GOST_KEY * r)
283{
284 int i;
285 BIGNUM *order = NULL;
286 const EC_GROUP *group;
287
288 if (r == NULL)
289 return 0;
290 group = GOST_KEY_get0_group(r);
291 if (group == NULL)
292 return 0;
293
294 if ((order = BN_new()) == NULL)
295 return 0;
296
297 if (!EC_GROUP_get_order(group,order,NULL)) {
298 BN_clear_free(order);
299 return 0;
300 }
301
302 i = BN_num_bytes(order);
303 BN_clear_free(order);
304 return (i);
305}
306#endif