~andersk/ubuntu/oneiric/openssl/spurious-reboot

« back to all changes in this revision

Viewing changes to engines/ccgost/gost_ameth.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2010-12-12 15:37:21 UTC
  • mto: (1.2.1 upstream) (11.2.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 55.
  • Revision ID: james.westby@ubuntu.com-20101212153721-mfw51stum5hwztpd
Tags: upstream-1.0.0c
ImportĀ upstreamĀ versionĀ 1.0.0c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************
 
2
 *                          gost_ameth.c                              *
 
3
 *             Copyright (c) 2005-2006 Cryptocom LTD                  *
 
4
 *         This file is distributed under the same license as OpenSSL *
 
5
 *                                                                    *
 
6
 *       Implementation of RFC 4490/4491 ASN1 method                  *
 
7
 *       for OpenSSL                                                  *
 
8
 *          Requires OpenSSL 0.9.9 for compilation                    *
 
9
 **********************************************************************/
 
10
#include <string.h>
 
11
#include <openssl/crypto.h>
 
12
#include <openssl/err.h>
 
13
#include <openssl/engine.h>
 
14
#include <openssl/evp.h>
 
15
#include <openssl/asn1.h>
 
16
#include "gost_params.h"
 
17
#include "gost_lcl.h"
 
18
#include "e_gost_err.h"
 
19
 
 
20
int gost94_nid_by_params(DSA *p) 
 
21
        {
 
22
        R3410_params *gost_params;
 
23
        BIGNUM *q=BN_new();
 
24
        for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++) 
 
25
                {
 
26
                BN_dec2bn(&q,gost_params->q);
 
27
                if (!BN_cmp(q,p->q)) 
 
28
                        {
 
29
                        BN_free(q);
 
30
                        return gost_params->nid;
 
31
                        }
 
32
                }       
 
33
        BN_free(q);
 
34
        return NID_undef;
 
35
        }
 
36
 
 
37
static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
 
38
        {
 
39
        ASN1_STRING *params = ASN1_STRING_new();
 
40
        GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
 
41
        int pkey_param_nid = NID_undef;
 
42
 
 
43
        if (!params || !gkp) 
 
44
                {
 
45
                GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
 
46
                        ERR_R_MALLOC_FAILURE);
 
47
                ASN1_STRING_free(params);
 
48
                params = NULL;
 
49
                goto err;
 
50
                }       
 
51
        switch (EVP_PKEY_base_id(key)) 
 
52
                {
 
53
                case NID_id_GostR3410_2001:
 
54
                        pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
 
55
                        break;
 
56
                case NID_id_GostR3410_94:
 
57
                        pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
 
58
                        if (pkey_param_nid == NID_undef) 
 
59
                                {
 
60
                                GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
 
61
                                        GOST_R_INVALID_GOST94_PARMSET);
 
62
                                ASN1_STRING_free(params);
 
63
                                params=NULL;
 
64
                                goto err;
 
65
                                }       
 
66
                        break;
 
67
                }       
 
68
        gkp->key_params = OBJ_nid2obj(pkey_param_nid);
 
69
        gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
 
70
        /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/
 
71
        params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
 
72
        if (params->length <=0 ) 
 
73
                {
 
74
                GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
 
75
                        ERR_R_MALLOC_FAILURE);
 
76
                ASN1_STRING_free(params);
 
77
                params = NULL;
 
78
                goto err;
 
79
                }
 
80
        params ->type = V_ASN1_SEQUENCE;
 
81
        err:
 
82
        GOST_KEY_PARAMS_free(gkp);
 
83
        return params;
 
84
        }
 
85
 
 
86
/* Parses GOST algorithm parameters from X509_ALGOR and
 
87
 * modifies pkey setting NID and parameters
 
88
 */
 
89
static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) 
 
90
        {
 
91
        ASN1_OBJECT *palg_obj =NULL;
 
92
        int ptype = V_ASN1_UNDEF;
 
93
        int pkey_nid = NID_undef,param_nid = NID_undef;
 
94
        void *_pval;
 
95
        ASN1_STRING *pval = NULL;
 
96
        const unsigned char  *p;
 
97
        GOST_KEY_PARAMS *gkp = NULL;
 
98
 
 
99
        X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
 
100
        pval = _pval;
 
101
        if (ptype != V_ASN1_SEQUENCE) 
 
102
                {
 
103
                GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
 
104
                        GOST_R_BAD_KEY_PARAMETERS_FORMAT);
 
105
                return 0;
 
106
                }       
 
107
        p=pval->data;
 
108
        pkey_nid = OBJ_obj2nid(palg_obj);
 
109
 
 
110
        gkp = d2i_GOST_KEY_PARAMS(NULL,&p,pval->length);
 
111
        if (!gkp) 
 
112
                {
 
113
                GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
 
114
                        GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
 
115
                return 0;
 
116
                }       
 
117
        param_nid = OBJ_obj2nid(gkp->key_params);
 
118
        GOST_KEY_PARAMS_free(gkp);
 
119
        EVP_PKEY_set_type(pkey,pkey_nid);
 
120
        switch (pkey_nid) 
 
121
                {
 
122
                case NID_id_GostR3410_94:
 
123
                {
 
124
                DSA *dsa= EVP_PKEY_get0(pkey);
 
125
                if (!dsa) 
 
126
                        {
 
127
                        dsa = DSA_new();
 
128
                        if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0;
 
129
                        }
 
130
                if (!fill_GOST94_params(dsa,param_nid)) return 0;
 
131
                break;
 
132
                }
 
133
                case NID_id_GostR3410_2001:
 
134
                {
 
135
                EC_KEY *ec = EVP_PKEY_get0(pkey);
 
136
                if (!ec) 
 
137
                        {
 
138
                        ec = EC_KEY_new();
 
139
                        if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
 
140
                        }
 
141
                if (!fill_GOST2001_params(ec,param_nid)) return 0;
 
142
                }
 
143
                }
 
144
 
 
145
        return 1;
 
146
        }
 
147
 
 
148
static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) 
 
149
        {
 
150
        switch (EVP_PKEY_base_id(pkey)) 
 
151
                {
 
152
                case NID_id_GostR3410_94:
 
153
                {
 
154
                DSA *dsa = EVP_PKEY_get0(pkey);
 
155
                if (!dsa) 
 
156
                        {
 
157
                        dsa = DSA_new();
 
158
                        EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa);
 
159
                        }       
 
160
                dsa->priv_key = BN_dup(priv);
 
161
                if (!EVP_PKEY_missing_parameters(pkey)) 
 
162
                        gost94_compute_public(dsa);
 
163
                break;
 
164
                }       
 
165
                case NID_id_GostR3410_2001:
 
166
                {
 
167
                EC_KEY *ec = EVP_PKEY_get0(pkey);
 
168
                if (!ec) 
 
169
                        {
 
170
                        ec = EC_KEY_new();
 
171
                        EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec);
 
172
                        }       
 
173
                if (!EC_KEY_set_private_key(ec,priv)) return 0;
 
174
                if (!EVP_PKEY_missing_parameters(pkey)) 
 
175
                        gost2001_compute_public(ec);
 
176
                break;
 
177
                }
 
178
                }
 
179
        return 1;               
 
180
        }
 
181
BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey) 
 
182
        {
 
183
        switch (EVP_PKEY_base_id(pkey)) 
 
184
                {
 
185
                case NID_id_GostR3410_94:
 
186
                {
 
187
                DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
 
188
                if (!dsa) 
 
189
                        {
 
190
                        return NULL;
 
191
                        }       
 
192
                if (!dsa->priv_key) return NULL;
 
193
                return dsa->priv_key;
 
194
                break;
 
195
                }       
 
196
                case NID_id_GostR3410_2001:
 
197
                {
 
198
                EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
 
199
                const BIGNUM* priv;
 
200
                if (!ec) 
 
201
                        {
 
202
                        return NULL;
 
203
                        }       
 
204
                if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
 
205
                return (BIGNUM *)priv;
 
206
                break;
 
207
                }
 
208
                }
 
209
        return NULL;            
 
210
        }
 
211
 
 
212
static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
 
213
        long arg1, void *arg2)
 
214
        {
 
215
        switch (op)
 
216
                {
 
217
                case ASN1_PKEY_CTRL_PKCS7_SIGN:
 
218
                        if (arg1 == 0) 
 
219
                                {
 
220
                                X509_ALGOR *alg1 = NULL, *alg2 = NULL;
 
221
                                int nid = EVP_PKEY_base_id(pkey);
 
222
                                PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2, 
 
223
                                        NULL, &alg1, &alg2);
 
224
                                X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
 
225
                                        V_ASN1_NULL, 0);
 
226
                                if (nid == NID_undef) 
 
227
                                        {
 
228
                                        return (-1);
 
229
                                        }
 
230
                                X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
 
231
                                }
 
232
                        return 1;
 
233
                case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
 
234
                        if (arg1 == 0)
 
235
                                {
 
236
                                X509_ALGOR *alg;
 
237
                                ASN1_STRING * params = encode_gost_algor_params(pkey);
 
238
                                if (!params) 
 
239
                                        {
 
240
                                        return -1;
 
241
                                        }
 
242
                                PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO*)arg2, &alg);
 
243
                                X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
 
244
                                        V_ASN1_SEQUENCE, params);
 
245
                                }
 
246
                        return 1;
 
247
                case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
 
248
                        *(int *)arg2 = NID_id_GostR3411_94;
 
249
                        return 2;
 
250
                }
 
251
        
 
252
        return -2;
 
253
        }
 
254
/*----------------------- free functions * ------------------------------*/
 
255
static void pkey_free_gost94(EVP_PKEY *key) 
 
256
        {
 
257
        if (key->pkey.dsa) 
 
258
                {
 
259
                DSA_free(key->pkey.dsa);
 
260
                }
 
261
        }
 
262
 
 
263
static void pkey_free_gost01(EVP_PKEY *key) 
 
264
        {
 
265
        if (key->pkey.ec) 
 
266
                {
 
267
                EC_KEY_free(key->pkey.ec);
 
268
                }
 
269
        }       
 
270
 
 
271
/* ------------------ private key functions  -----------------------------*/
 
272
static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) 
 
273
        {
 
274
        const unsigned char *pkey_buf = NULL,*p=NULL;
 
275
        int priv_len = 0;
 
276
        BIGNUM *pk_num=NULL;
 
277
        int ret =0;
 
278
        X509_ALGOR *palg =NULL;
 
279
        ASN1_OBJECT *palg_obj = NULL;
 
280
        ASN1_INTEGER *priv_key=NULL;
 
281
 
 
282
        if (!PKCS8_pkey_get0(&palg_obj,&pkey_buf,&priv_len,&palg,p8inf)) 
 
283
                return 0;
 
284
        p = pkey_buf;
 
285
        if (!decode_gost_algor_params(pk,palg)) 
 
286
                {
 
287
                return 0;
 
288
                }
 
289
        if (V_ASN1_OCTET_STRING == *p) 
 
290
                {
 
291
                /* New format - Little endian octet string */
 
292
                unsigned char rev_buf[32];
 
293
                int i;
 
294
                ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL,&p,priv_len);
 
295
                if (!s||s->length !=32) 
 
296
                        {
 
297
                        GOSTerr(GOST_F_PRIV_DECODE_GOST,
 
298
                                EVP_R_DECODE_ERROR);
 
299
                        return 0;       
 
300
                        }
 
301
                for (i=0;i<32;i++)
 
302
                        {
 
303
                        rev_buf[31-i]=s->data[i];
 
304
                        }
 
305
                ASN1_STRING_free(s);
 
306
                pk_num = getbnfrombuf(rev_buf,32);
 
307
                } 
 
308
        else
 
309
                {
 
310
                priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len);
 
311
                if (!priv_key) return 0;
 
312
                ret= ((pk_num =  ASN1_INTEGER_to_BN(priv_key, NULL))!=NULL) ;
 
313
                ASN1_INTEGER_free(priv_key);
 
314
                if (!ret)
 
315
                        {
 
316
                        GOSTerr(GOST_F_PRIV_DECODE_GOST,
 
317
                                EVP_R_DECODE_ERROR);
 
318
                        return 0;       
 
319
                        }
 
320
                }
 
321
 
 
322
        ret= gost_set_priv_key(pk,pk_num);
 
323
        BN_free(pk_num);
 
324
        return ret;
 
325
        }
 
326
 
 
327
/* ----------------------------------------------------------------------*/
 
328
static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
 
329
        {
 
330
        ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
 
331
        ASN1_STRING *params = encode_gost_algor_params(pk);
 
332
        unsigned char *priv_buf = NULL;
 
333
        int priv_len;
 
334
 
 
335
        ASN1_INTEGER *asn1key=NULL;
 
336
        if (!params) 
 
337
                {
 
338
                return 0;
 
339
                }
 
340
        asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk),NULL);
 
341
        priv_len = i2d_ASN1_INTEGER(asn1key,&priv_buf);
 
342
        ASN1_INTEGER_free(asn1key);
 
343
        return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params,
 
344
                priv_buf,priv_len);
 
345
        }
 
346
/* --------- printing keys --------------------------------*/
 
347
static int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent,
 
348
        ASN1_PCTX *pctx, int type) 
 
349
        {
 
350
        int param_nid = NID_undef;
 
351
 
 
352
        if (type == 2) 
 
353
                {
 
354
                BIGNUM *key;
 
355
 
 
356
                if (!BIO_indent(out,indent,128)) return 0;
 
357
                BIO_printf(out,"Private key: ");
 
358
                key = gost_get0_priv_key(pkey);
 
359
                if (!key) 
 
360
                        BIO_printf(out,"<undefined>");
 
361
                else 
 
362
                        BN_print(out,key);
 
363
                BIO_printf(out,"\n");
 
364
                }
 
365
        if (type >= 1)
 
366
                {
 
367
                BIGNUM *pubkey;
 
368
                
 
369
                pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
 
370
                BIO_indent(out,indent,128);
 
371
                BIO_printf(out,"Public key: ");
 
372
                BN_print(out,pubkey);
 
373
                BIO_printf(out,"\n");
 
374
        }       
 
375
 
 
376
        param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
 
377
        BIO_indent(out,indent,128);
 
378
        BIO_printf(out, "Parameter set: %s\n",OBJ_nid2ln(param_nid));
 
379
        return 1;
 
380
}
 
381
 
 
382
static int param_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
 
383
        ASN1_PCTX *pctx) 
 
384
        {
 
385
        return print_gost_94(out, pkey, indent, pctx,0);
 
386
        }
 
387
 
 
388
static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
 
389
        ASN1_PCTX *pctx)
 
390
        {
 
391
        return print_gost_94(out,pkey, indent, pctx,1);
 
392
        }
 
393
static int priv_print_gost94(BIO *out,const EVP_PKEY *pkey, int indent,
 
394
        ASN1_PCTX *pctx) 
 
395
        {
 
396
        return print_gost_94(out,pkey,indent,pctx,2);
 
397
        }
 
398
 
 
399
static int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent,
 
400
        ASN1_PCTX *pctx, int type)
 
401
        {
 
402
        int param_nid = NID_undef;
 
403
        if (type == 2) 
 
404
                {
 
405
                BIGNUM *key;
 
406
 
 
407
                if (!BIO_indent(out,indent,128)) return 0;
 
408
                BIO_printf(out,"Private key: ");
 
409
                key = gost_get0_priv_key(pkey);
 
410
                if (!key) 
 
411
                        BIO_printf(out,"<undefined)");
 
412
                else 
 
413
                        BN_print(out,key);
 
414
                BIO_printf(out,"\n");
 
415
                }
 
416
        if (type >= 1) 
 
417
                {
 
418
                BN_CTX *ctx = BN_CTX_new();
 
419
                BIGNUM *X,*Y;
 
420
                const EC_POINT *pubkey;
 
421
                const EC_GROUP *group;
 
422
 
 
423
                if (!ctx) 
 
424
                        {
 
425
                        GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_MALLOC_FAILURE);
 
426
                        return 0;
 
427
                        }
 
428
                BN_CTX_start(ctx);
 
429
                X = BN_CTX_get(ctx);
 
430
                Y = BN_CTX_get(ctx);
 
431
                pubkey = EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
 
432
                group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
 
433
                if (!EC_POINT_get_affine_coordinates_GFp(group,pubkey,X,Y,ctx)) 
 
434
                        {
 
435
                        GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_EC_LIB);
 
436
                        BN_CTX_free(ctx);
 
437
                        return 0;
 
438
                        }
 
439
                if (!BIO_indent(out,indent,128)) return 0;
 
440
                BIO_printf(out,"Public key:\n");
 
441
                if (!BIO_indent(out,indent+3,128)) return 0;
 
442
                BIO_printf(out,"X:");
 
443
                BN_print(out,X);
 
444
                BIO_printf(out,"\n");
 
445
                BIO_indent(out,indent+3,128);
 
446
                BIO_printf(out,"Y:");
 
447
                BN_print(out,Y);
 
448
                BIO_printf(out,"\n");
 
449
                BN_CTX_end(ctx);
 
450
                BN_CTX_free(ctx);
 
451
                }
 
452
 
 
453
        param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
 
454
        if (!BIO_indent(out,indent,128)) return 0;
 
455
        BIO_printf(out,"Parameter set: %s\n",OBJ_nid2ln(param_nid));
 
456
        return 1;
 
457
}
 
458
static int param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
 
459
        ASN1_PCTX *pctx) 
 
460
        {       
 
461
        return print_gost_01(out,pkey,indent,pctx,0);
 
462
        }
 
463
static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
 
464
        ASN1_PCTX *pctx)
 
465
        {
 
466
        return print_gost_01(out,pkey, indent, pctx,1);
 
467
        }
 
468
static int priv_print_gost01(BIO *out,const EVP_PKEY *pkey, int indent,
 
469
        ASN1_PCTX *pctx) 
 
470
        {
 
471
        return print_gost_01(out,pkey,indent,pctx,2);
 
472
        }
 
473
/* ---------------------------------------------------------------------*/
 
474
static int param_missing_gost94(const EVP_PKEY *pk) 
 
475
        {
 
476
        const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
 
477
        if (!dsa) return 1;
 
478
        if (!dsa->q) return 1;
 
479
        return 0;
 
480
        }
 
481
 
 
482
static int param_missing_gost01(const EVP_PKEY *pk) 
 
483
        {
 
484
        const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
 
485
        if (!ec) return 1;
 
486
        if (!EC_KEY_get0_group(ec)) return 1;
 
487
        return 0;
 
488
        }
 
489
 
 
490
static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from) 
 
491
        {
 
492
        const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
 
493
        DSA *dto = EVP_PKEY_get0(to);
 
494
        if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) 
 
495
                {
 
496
                GOSTerr(GOST_F_PARAM_COPY_GOST94,
 
497
                        GOST_R_INCOMPATIBLE_ALGORITHMS);
 
498
                return 0;
 
499
                }       
 
500
        if (!dfrom) 
 
501
                {
 
502
                GOSTerr(GOST_F_PARAM_COPY_GOST94,
 
503
                        GOST_R_KEY_PARAMETERS_MISSING);
 
504
                return 0;
 
505
                }       
 
506
        if (!dto) 
 
507
                {
 
508
                dto = DSA_new();
 
509
                EVP_PKEY_assign(to,EVP_PKEY_base_id(from),dto);
 
510
                }       
 
511
#define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);   
 
512
        COPYBIGNUM(dto,dfrom,p)
 
513
                COPYBIGNUM(dto,dfrom,q)
 
514
                COPYBIGNUM(dto,dfrom,g)
 
515
 
 
516
                if (dto->priv_key) 
 
517
                        gost94_compute_public(dto);
 
518
        return 1;       
 
519
        }
 
520
static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) 
 
521
        {
 
522
        EC_KEY *eto = EVP_PKEY_get0(to);
 
523
        const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
 
524
        if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) 
 
525
                {
 
526
                GOSTerr(GOST_F_PARAM_COPY_GOST01,
 
527
                        GOST_R_INCOMPATIBLE_ALGORITHMS);
 
528
                return 0;
 
529
                }       
 
530
        if (!efrom) 
 
531
                {
 
532
                GOSTerr(GOST_F_PARAM_COPY_GOST01,
 
533
                        GOST_R_KEY_PARAMETERS_MISSING);
 
534
                return 0;
 
535
                }       
 
536
        if (!eto) 
 
537
                {
 
538
                eto = EC_KEY_new();
 
539
                EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
 
540
                }       
 
541
        EC_KEY_set_group(eto,EC_KEY_get0_group(efrom));
 
542
        if (EC_KEY_get0_private_key(eto)) 
 
543
                {
 
544
                gost2001_compute_public(eto);
 
545
                }
 
546
        return 1;
 
547
        }
 
548
 
 
549
static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) 
 
550
        {
 
551
        const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
 
552
        const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
 
553
        if (!BN_cmp(da->q,db->q)) return 1;
 
554
        return 0;
 
555
        }
 
556
 
 
557
static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) 
 
558
        {
 
559
        if (EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a)))==
 
560
                EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b)))) 
 
561
                {
 
562
                return 1;
 
563
                }
 
564
        return 0;
 
565
 
 
566
        }
 
567
 
 
568
/* ---------- Public key functions * --------------------------------------*/
 
569
static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
 
570
        {
 
571
        X509_ALGOR *palg = NULL;
 
572
        const unsigned char *pubkey_buf = NULL;
 
573
        unsigned char *databuf;
 
574
        ASN1_OBJECT *palgobj = NULL;
 
575
        int pub_len,i,j;
 
576
        DSA *dsa;
 
577
        ASN1_OCTET_STRING *octet= NULL;
 
578
 
 
579
        if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
 
580
                        &palg, pub)) return 0;
 
581
        EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);  
 
582
        if (!decode_gost_algor_params(pk,palg)) return 0;
 
583
        octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
 
584
        if (!octet) 
 
585
                {
 
586
                GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE);
 
587
                return 0;
 
588
                }       
 
589
        databuf = OPENSSL_malloc(octet->length);
 
590
        for (i=0,j=octet->length-1;i<octet->length;i++,j--)
 
591
                {
 
592
                databuf[j]=octet->data[i];
 
593
                }       
 
594
        dsa = EVP_PKEY_get0(pk);
 
595
        dsa->pub_key=BN_bin2bn(databuf,octet->length,NULL);
 
596
        ASN1_OCTET_STRING_free(octet);
 
597
        OPENSSL_free(databuf);
 
598
        return 1;
 
599
 
 
600
        }
 
601
 
 
602
static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
 
603
        {
 
604
        ASN1_OBJECT *algobj = NULL;
 
605
        ASN1_OCTET_STRING *octet = NULL;
 
606
        void *pval = NULL;
 
607
        unsigned char *buf=NULL,*databuf,*sptr;
 
608
        int i,j,data_len,ret=0;
 
609
 
 
610
        int ptype = V_ASN1_UNDEF;
 
611
        DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
 
612
        algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
 
613
        if (pk->save_parameters) 
 
614
                {
 
615
                ASN1_STRING *params = encode_gost_algor_params(pk);
 
616
                pval = params;
 
617
                ptype = V_ASN1_SEQUENCE;
 
618
                }       
 
619
        data_len = BN_num_bytes(dsa->pub_key);
 
620
        databuf = OPENSSL_malloc(data_len);
 
621
        BN_bn2bin(dsa->pub_key,databuf);
 
622
        octet = ASN1_OCTET_STRING_new();
 
623
        ASN1_STRING_set(octet,NULL,data_len);
 
624
        sptr = ASN1_STRING_data(octet);
 
625
        for (i=0,j=data_len-1; i< data_len;i++,j--)
 
626
                {
 
627
                sptr[i]=databuf[j];
 
628
                }
 
629
        OPENSSL_free(databuf);
 
630
        ret = i2d_ASN1_OCTET_STRING(octet,&buf);
 
631
        ASN1_BIT_STRING_free(octet);
 
632
        if (ret <0)  return 0;
 
633
        return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
 
634
        }
 
635
 
 
636
static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
 
637
        {
 
638
        X509_ALGOR *palg = NULL;
 
639
        const unsigned char *pubkey_buf = NULL;
 
640
        unsigned char *databuf;
 
641
        ASN1_OBJECT *palgobj = NULL;
 
642
        int pub_len,i,j;
 
643
        EC_POINT *pub_key;
 
644
        BIGNUM *X,*Y;
 
645
        ASN1_OCTET_STRING *octet= NULL;
 
646
        int len;
 
647
        const EC_GROUP *group;
 
648
 
 
649
        if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
 
650
                        &palg, pub)) return 0;
 
651
        EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);  
 
652
        if (!decode_gost_algor_params(pk,palg)) return 0;
 
653
        group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
 
654
        octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
 
655
        if (!octet) 
 
656
                {
 
657
                GOSTerr(GOST_F_PUB_DECODE_GOST01,ERR_R_MALLOC_FAILURE);
 
658
                return 0;
 
659
                }       
 
660
        databuf = OPENSSL_malloc(octet->length);
 
661
        for (i=0,j=octet->length-1;i<octet->length;i++,j--)
 
662
                {
 
663
                databuf[j]=octet->data[i];
 
664
                }
 
665
        len=octet->length/2;
 
666
        ASN1_OCTET_STRING_free(octet);  
 
667
        
 
668
        Y= getbnfrombuf(databuf,len);
 
669
        X= getbnfrombuf(databuf+len,len);
 
670
        OPENSSL_free(databuf);
 
671
        pub_key = EC_POINT_new(group);
 
672
        if (!EC_POINT_set_affine_coordinates_GFp(group
 
673
                        ,pub_key,X,Y,NULL))
 
674
                {
 
675
                GOSTerr(GOST_F_PUB_DECODE_GOST01,
 
676
                        ERR_R_EC_LIB);
 
677
                EC_POINT_free(pub_key);
 
678
                BN_free(X);
 
679
                BN_free(Y);
 
680
                return 0;
 
681
                }       
 
682
        BN_free(X);
 
683
        BN_free(Y);
 
684
        if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk),pub_key))
 
685
                {
 
686
                GOSTerr(GOST_F_PUB_DECODE_GOST01,
 
687
                        ERR_R_EC_LIB);
 
688
                EC_POINT_free(pub_key);
 
689
                return 0;
 
690
                }       
 
691
        EC_POINT_free(pub_key);
 
692
        return 1;
 
693
 
 
694
        }
 
695
 
 
696
static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
 
697
        {
 
698
        ASN1_OBJECT *algobj = NULL;
 
699
        ASN1_OCTET_STRING *octet = NULL;
 
700
        void *pval = NULL;
 
701
        unsigned char *buf=NULL,*databuf,*sptr;
 
702
        int i,j,data_len,ret=0;
 
703
        const EC_POINT *pub_key;
 
704
        BIGNUM *X,*Y,*order;
 
705
        const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
 
706
        int ptype = V_ASN1_UNDEF;
 
707
 
 
708
        algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
 
709
        if (pk->save_parameters) 
 
710
                {
 
711
                ASN1_STRING *params = encode_gost_algor_params(pk);
 
712
                pval = params;
 
713
                ptype = V_ASN1_SEQUENCE;
 
714
                }
 
715
        order = BN_new();
 
716
        EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL);
 
717
        pub_key=EC_KEY_get0_public_key(ec);
 
718
        if (!pub_key) 
 
719
                {
 
720
                GOSTerr(GOST_F_PUB_ENCODE_GOST01,
 
721
                        GOST_R_PUBLIC_KEY_UNDEFINED);
 
722
                return 0;
 
723
                }       
 
724
        X=BN_new();
 
725
        Y=BN_new();
 
726
        EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
 
727
                pub_key,X,Y,NULL);
 
728
        data_len = 2*BN_num_bytes(order);
 
729
        BN_free(order);
 
730
        databuf = OPENSSL_malloc(data_len);
 
731
        memset(databuf,0,data_len);
 
732
        
 
733
        store_bignum(X,databuf+data_len/2,data_len/2);
 
734
        store_bignum(Y,databuf,data_len/2);
 
735
 
 
736
        BN_free(X);
 
737
        BN_free(Y);
 
738
        octet = ASN1_OCTET_STRING_new();
 
739
        ASN1_STRING_set(octet,NULL,data_len);
 
740
        sptr=ASN1_STRING_data(octet);
 
741
    for (i=0,j=data_len-1;i<data_len;i++,j--) 
 
742
                {
 
743
        sptr[i]=databuf[j];
 
744
                }
 
745
    OPENSSL_free(databuf);
 
746
        ret = i2d_ASN1_OCTET_STRING(octet,&buf);
 
747
        ASN1_BIT_STRING_free(octet);
 
748
        if (ret <0)  return 0;
 
749
        return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
 
750
        }
 
751
 
 
752
static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
 
753
        {
 
754
        const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
 
755
        const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
 
756
        if (da && db && da->pub_key && db->pub_key
 
757
                && !BN_cmp(da->pub_key,db->pub_key)) 
 
758
                {
 
759
                return 1;
 
760
                }               
 
761
        return 0;
 
762
        }
 
763
 
 
764
static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b)
 
765
        {
 
766
        const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
 
767
        const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
 
768
        const EC_POINT *ka,*kb;
 
769
        int ret=0;
 
770
        if (!ea || !eb) return 0;
 
771
        ka = EC_KEY_get0_public_key(ea);
 
772
        kb = EC_KEY_get0_public_key(eb);
 
773
        if (!ka || !kb) return 0;
 
774
        ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ;
 
775
        return ret;
 
776
        }
 
777
 
 
778
 
 
779
 
 
780
 
 
781
static int pkey_size_gost(const EVP_PKEY *pk)
 
782
        {
 
783
        return 64;
 
784
        }
 
785
 
 
786
static int pkey_bits_gost(const EVP_PKEY *pk)
 
787
        {
 
788
        return 256;
 
789
        }
 
790
/*------------------------ ASN1 METHOD for GOST MAC  -------------------*/
 
791
static void  mackey_free_gost(EVP_PKEY *pk)
 
792
        {
 
793
                if (pk->pkey.ptr) {
 
794
                        OPENSSL_free(pk->pkey.ptr);
 
795
                }       
 
796
        }
 
797
static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 
798
{
 
799
        switch (op)
 
800
                {
 
801
                case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
 
802
                        *(int *)arg2 = NID_id_Gost28147_89_MAC;
 
803
                        return 2;
 
804
                }
 
805
        return -2;
 
806
}       
 
807
 
 
808
static int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 
 
809
{
 
810
   int nid=gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
 
811
   return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
 
812
}
 
813
static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 
 
814
{
 
815
   int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
 
816
   return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
 
817
}
 
818
 
 
819
static int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
 
820
{
 
821
        ASN1_OBJECT *obj=NULL;
 
822
        DSA *dsa = EVP_PKEY_get0(pkey);
 
823
        int nid;
 
824
        if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
 
825
                return 0;
 
826
        }
 
827
        nid = OBJ_obj2nid(obj);
 
828
        ASN1_OBJECT_free(obj);
 
829
        if (!dsa) 
 
830
                {
 
831
                dsa=DSA_new();
 
832
                if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa)) return 0;
 
833
                }
 
834
        if (!fill_GOST94_params(dsa,nid)) return 0;
 
835
        return 1;
 
836
}       
 
837
 
 
838
static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
 
839
        ASN1_OBJECT *obj=NULL;
 
840
        int nid;
 
841
        EC_KEY *ec = EVP_PKEY_get0(pkey);
 
842
        if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
 
843
                return 0;
 
844
        }
 
845
        nid = OBJ_obj2nid(obj);
 
846
        ASN1_OBJECT_free(obj);
 
847
        if (!ec) 
 
848
                {
 
849
                ec = EC_KEY_new();
 
850
                if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec)) return 0;
 
851
                }       
 
852
        if (!fill_GOST2001_params(ec, nid)) return 0;
 
853
        return 1;
 
854
}       
 
855
 
 
856
 
 
857
 
 
858
 
 
859
 
 
860
/* ----------------------------------------------------------------------*/
 
861
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info) 
 
862
        {
 
863
        *ameth =        EVP_PKEY_asn1_new(nid, 
 
864
                ASN1_PKEY_SIGPARAM_NULL, pemstr, info); 
 
865
        if (!*ameth) return 0;
 
866
        switch (nid) 
 
867
                {
 
868
                case NID_id_GostR3410_94:
 
869
                        EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94);
 
870
                        EVP_PKEY_asn1_set_private (*ameth, 
 
871
                                priv_decode_gost, priv_encode_gost, 
 
872
                                priv_print_gost94);
 
873
 
 
874
                        EVP_PKEY_asn1_set_param (*ameth, 
 
875
                                gost94_param_decode, gost94_param_encode,
 
876
                                param_missing_gost94, param_copy_gost94, 
 
877
                                param_cmp_gost94,param_print_gost94 );
 
878
                        EVP_PKEY_asn1_set_public (*ameth,
 
879
                                pub_decode_gost94, pub_encode_gost94,
 
880
                                pub_cmp_gost94, pub_print_gost94,
 
881
                                pkey_size_gost, pkey_bits_gost);
 
882
        
 
883
                        EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
 
884
                        break;
 
885
                case NID_id_GostR3410_2001:
 
886
                        EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
 
887
                        EVP_PKEY_asn1_set_private (*ameth, 
 
888
                                priv_decode_gost, priv_encode_gost, 
 
889
                                priv_print_gost01);
 
890
 
 
891
                        EVP_PKEY_asn1_set_param (*ameth, 
 
892
                                gost2001_param_decode, gost2001_param_encode,
 
893
                                param_missing_gost01, param_copy_gost01, 
 
894
                                param_cmp_gost01, param_print_gost01);
 
895
                        EVP_PKEY_asn1_set_public (*ameth,
 
896
                                pub_decode_gost01, pub_encode_gost01,
 
897
                                pub_cmp_gost01, pub_print_gost01,
 
898
                                pkey_size_gost, pkey_bits_gost);
 
899
        
 
900
                        EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
 
901
                        break;
 
902
                case NID_id_Gost28147_89_MAC:
 
903
                        EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
 
904
                        EVP_PKEY_asn1_set_ctrl(*ameth,mac_ctrl_gost);   
 
905
                        break;
 
906
                }               
 
907
        return 1;
 
908
        }