]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_ameth.c
New Gost CMS support, KARI/KTRI parsing
[openssl-gost/engine.git] / gost_ameth.c
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 #ifndef OPENSSL_NO_CMS
17 # include <openssl/cms.h>
18 #endif
19 #include "gost_lcl.h"
20 #include "e_gost_err.h"
21
22 #define PK_WRAP_PARAM "LEGACY_PK_WRAP"
23
24 /*
25  * Pack bignum into byte buffer of given size, filling all leading bytes by
26  * zeros
27  */
28 int store_bignum(const BIGNUM *bn, unsigned char *buf, int len)
29 {
30     int bytes = BN_num_bytes(bn);
31
32     if (bytes > len)
33         return 0;
34     memset(buf, 0, len);
35     BN_bn2bin(bn, buf + len - bytes);
36     return 1;
37 }
38
39 static int pkey_bits_gost(const EVP_PKEY *pk)
40 {
41     if (!pk)
42         return -1;
43
44     switch (EVP_PKEY_base_id(pk)) {
45     case NID_id_GostR3410_2001:
46     case NID_id_GostR3410_2012_256:
47         return 256;
48     case NID_id_GostR3410_2012_512:
49         return 512;
50     }
51
52     return -1;
53 }
54
55 static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
56 {
57     ASN1_STRING *params = ASN1_STRING_new();
58     GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
59     int pkey_param_nid = NID_undef;
60     void *key_ptr = EVP_PKEY_get0((EVP_PKEY *)key);
61     int result = 0;
62
63     if (!params || !gkp) {
64         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
65         goto err;
66     }
67     switch (EVP_PKEY_base_id(key)) {
68     case NID_id_GostR3410_2012_256:
69         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
70         switch (pkey_param_nid) {
71             case NID_id_GostR3410_2001_TestParamSet:
72             case NID_id_GostR3410_2001_CryptoPro_A_ParamSet:
73             case NID_id_GostR3410_2001_CryptoPro_B_ParamSet:
74             case NID_id_GostR3410_2001_CryptoPro_C_ParamSet:
75             case NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet:
76             case NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet:
77                 gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_256);
78         }
79         break;
80     case NID_id_GostR3410_2012_512:
81         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
82         switch (pkey_param_nid) {
83             case NID_id_tc26_gost_3410_2012_512_paramSetTest:
84             case NID_id_tc26_gost_3410_2012_512_paramSetA:
85             case NID_id_tc26_gost_3410_2012_512_paramSetB:
86                 gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_512);
87         }
88         break;
89     case NID_id_GostR3410_2001:
90         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
91         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
92         break;
93     }
94
95     if (pkey_param_nid == NID_undef) {
96         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, GOST_R_INVALID_PARAMSET);
97         goto err;
98     }
99
100     gkp->key_params = OBJ_nid2obj(pkey_param_nid);
101     /*
102      * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
103      */
104     params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
105     if (params->length <= 0) {
106         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
107         goto err;
108     }
109     params->type = V_ASN1_SEQUENCE;
110     result = 1;
111  err:
112     if (gkp)
113         GOST_KEY_PARAMS_free(gkp);
114     if (result == 0) {          /* if error */
115         if (params)
116             ASN1_STRING_free(params);
117         return NULL;
118     }
119     return params;
120 }
121
122 static int gost_decode_nid_params(EVP_PKEY *pkey, int pkey_nid, int param_nid)
123 {
124     void *key_ptr = EVP_PKEY_get0(pkey);
125
126     switch (pkey_nid) {
127     case NID_id_GostR3410_2012_256:
128     case NID_id_GostR3410_2012_512:
129     case NID_id_GostR3410_2001:
130         if (!key_ptr) {
131             key_ptr = EC_KEY_new();
132             if (!EVP_PKEY_assign(pkey, pkey_nid, key_ptr)) {
133                 EC_KEY_free(key_ptr);
134                 break;
135             }
136         }
137         return fill_GOST_EC_params(key_ptr, param_nid);
138     }
139
140     return 0;
141 }
142
143 /*
144  * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
145  * NID and parameters
146  */
147 static int decode_gost_algor_params(EVP_PKEY *pkey,
148                                     const X509_ALGOR *palg)
149 {
150     const ASN1_OBJECT *palg_obj = NULL;
151     int ptype = V_ASN1_UNDEF;
152     int pkey_nid = NID_undef, param_nid = NID_undef;
153     ASN1_STRING *pval = NULL;
154     const unsigned char *p;
155     GOST_KEY_PARAMS *gkp = NULL;
156
157     if (!pkey || !palg)
158         return 0;
159     X509_ALGOR_get0(&palg_obj, &ptype, (const void **)&pval, palg);
160     if (ptype != V_ASN1_SEQUENCE) {
161         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
162                 GOST_R_BAD_KEY_PARAMETERS_FORMAT);
163         return 0;
164     }
165     p = pval->data;
166     pkey_nid = OBJ_obj2nid(palg_obj);
167
168     gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length);
169     if (!gkp) {
170         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
171                 GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
172         return 0;
173     }
174     param_nid = OBJ_obj2nid(gkp->key_params);
175     GOST_KEY_PARAMS_free(gkp);
176     if (!EVP_PKEY_set_type(pkey, pkey_nid)) {
177         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
178         return 0;
179     }
180     return gost_decode_nid_params(pkey, pkey_nid, param_nid);
181 }
182
183 static int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
184 {
185     switch (EVP_PKEY_base_id(pkey)) {
186     case NID_id_GostR3410_2012_512:
187     case NID_id_GostR3410_2012_256:
188     case NID_id_GostR3410_2001:
189         {
190             EC_KEY *ec = EVP_PKEY_get0(pkey);
191             if (!ec) {
192                 ec = EC_KEY_new();
193                 EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), ec);
194             }
195             if (!EC_KEY_set_private_key(ec, priv))
196                 return 0;
197             if (!EVP_PKEY_missing_parameters(pkey))
198                 return gost_ec_compute_public(ec);
199             break;
200         }
201     default:
202         return 0;
203     }
204     return 1;
205 }
206
207 BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
208 {
209     switch (EVP_PKEY_base_id(pkey)) {
210     case NID_id_GostR3410_2012_512:
211     case NID_id_GostR3410_2012_256:
212     case NID_id_GostR3410_2001:
213         {
214             EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
215             if (ec)
216                 return (BIGNUM *)EC_KEY_get0_private_key(ec);
217             break;
218         }
219     }
220     return NULL;
221 }
222
223 /*
224  * GOST CMS processing functions
225  */
226 /* FIXME reaarange declarations */
227 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub);
228
229 static int gost_cms_set_kari_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
230 {
231         int ret = 0;
232         X509_ALGOR *alg;
233         ASN1_OCTET_STRING *ukm;
234
235         /* Deal with originator */
236         X509_ALGOR *pubalg = NULL;
237         ASN1_BIT_STRING *pubkey = NULL;
238
239         EVP_PKEY *peer_key = NULL;
240         X509_PUBKEY *tmp   = NULL;
241
242         int nid;
243         unsigned char shared_key[64];
244         size_t shared_key_size = 64;
245         const EVP_CIPHER *cipher = NULL;
246
247         if (CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm) == 0)
248                 goto err;
249
250         if (CMS_RecipientInfo_kari_get0_orig_id(ri, &pubalg, &pubkey, NULL, NULL, NULL) == 0)
251                   goto err;
252
253         nid = OBJ_obj2nid(alg->algorithm);
254         if (alg->parameter->type != V_ASN1_SEQUENCE)
255                   goto err;
256
257         switch (nid) {
258                 case NID_kuznyechik_kexp15:
259                 case NID_magma_kexp15:
260                         cipher = EVP_get_cipherbynid(nid);
261                         break;
262         }
263
264         if (cipher == NULL) {
265                         GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_CIPHER_NOT_FOUND);
266                   goto err;
267   }
268
269         if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_SET_IV,
270                 ASN1_STRING_length(ukm), (void *)ASN1_STRING_get0_data(ukm)) <= 0)
271                         goto err;
272
273         if (pubkey != NULL && pubalg != NULL) {
274                 const ASN1_OBJECT *paobj = NULL;
275                 int ptype = 0;
276                 const void *param = NULL;
277
278                 peer_key = EVP_PKEY_new();
279                 tmp = X509_PUBKEY_new();
280
281                 if ((peer_key == NULL) || (tmp == NULL)) {
282                         GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, ERR_R_MALLOC_FAILURE);
283                         goto err;
284                 }
285
286                 X509_ALGOR_get0(&paobj, &ptype, &param, pubalg);
287
288                 if (X509_PUBKEY_set0_param(tmp, (ASN1_OBJECT *)paobj,
289                         ptype, (void *)param,
290                         (unsigned char *)ASN1_STRING_get0_data(pubkey),
291                         ASN1_STRING_length(pubkey) ) == 0) {
292                                 GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_PUBLIC_KEY_UNDEFINED);
293                                 goto err;
294                 }
295
296                 if (pub_decode_gost_ec(peer_key, tmp) <= 0) {
297                                 GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_ERROR_DECODING_PUBLIC_KEY);
298                                 goto err;
299                 }
300
301                 if (EVP_PKEY_derive_set_peer(pctx, peer_key) <= 0) {
302                                 GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_ERROR_SETTING_PEER_KEY);
303                                 goto err;
304                 }
305         }
306
307         if (EVP_PKEY_derive(pctx, shared_key, &shared_key_size) <= 0) {
308                 GOSTerr(GOST_F_GOST_CMS_SET_KARI_SHARED_INFO, GOST_R_ERROR_COMPUTING_SHARED_KEY);
309                 goto err;
310         }
311
312         EVP_CIPHER_CTX_set_flags(CMS_RecipientInfo_kari_get0_ctx(ri), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
313         if (EVP_DecryptInit_ex(CMS_RecipientInfo_kari_get0_ctx(ri), cipher, NULL,
314                 shared_key, ukm->data+24) == 0)
315                         goto err;
316
317         ret = 1;
318 err:
319         EVP_PKEY_free(peer_key);
320         if (ret == 0) {
321                 X509_PUBKEY_free(tmp);
322         }
323
324         return ret;
325 }
326
327 static int gost_cms_set_ktri_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
328 {
329         X509_ALGOR *alg;
330         struct gost_pmeth_data *gctx = EVP_PKEY_CTX_get_data(pctx);
331
332         CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg);
333
334         switch (OBJ_obj2nid(alg->algorithm)) {
335                 case NID_kuznyechik_kexp15:
336                         gctx->cipher_nid = NID_kuznyechik_ctr;
337                         break;
338
339                 case NID_magma_kexp15:
340                         gctx->cipher_nid = NID_magma_ctr;
341                         break;
342
343                 case NID_id_GostR3410_2012_256:
344                 case NID_id_GostR3410_2012_512:
345                         gctx->cipher_nid = NID_id_Gost28147_89;
346                         break;
347
348                 default:
349                         GOSTerr(GOST_F_GOST_CMS_SET_KTRI_SHARED_INFO, GOST_R_UNSUPPORTED_RECIPIENT_INFO);
350                         return 0;
351         }
352
353         return 1;
354 }
355
356 static int gost_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
357 {
358         switch(CMS_RecipientInfo_type(ri)) {
359                 case CMS_RECIPINFO_AGREE:
360                         return gost_cms_set_kari_shared_info(pctx, ri);
361                 break;
362                 case CMS_RECIPINFO_TRANS:
363                         return gost_cms_set_ktri_shared_info(pctx, ri);
364                 break;
365         }
366
367         GOSTerr(GOST_F_GOST_CMS_SET_SHARED_INFO, GOST_R_UNSUPPORTED_RECIPIENT_INFO);
368         return 0;
369 }
370 /*
371  * Control function
372  */
373 static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
374 {
375     int nid = EVP_PKEY_base_id(pkey), md_nid = NID_undef;
376     X509_ALGOR *alg1 = NULL, *alg2 = NULL;
377
378     switch (nid) {
379     case NID_id_GostR3410_2012_512:
380         md_nid = NID_id_GostR3411_2012_512;
381         break;
382     case NID_id_GostR3410_2012_256:
383         md_nid = NID_id_GostR3411_2012_256;
384         break;
385     case NID_id_GostR3410_2001:
386     case NID_id_GostR3410_94:
387         md_nid = NID_id_GostR3411_94;
388         break;
389     default:
390         return -1;
391     }
392
393     switch (op) {
394     case ASN1_PKEY_CTRL_PKCS7_SIGN:
395         if (arg1 == 0) {
396             PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *)arg2, NULL,
397                                         &alg1, &alg2);
398             X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid), V_ASN1_NULL, 0);
399             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
400         }
401         return 1;
402 #ifndef OPENSSL_NO_CMS
403     case ASN1_PKEY_CTRL_CMS_SIGN:
404         if (arg1 == 0) {
405             CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2, NULL, NULL,
406                                      &alg1, &alg2);
407             X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid), V_ASN1_NULL, 0);
408             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
409         }
410         return 1;
411 #endif
412     case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
413         if (arg1 == 0) { /* Encryption */
414             ASN1_STRING *params = encode_gost_algor_params(pkey);
415             if (!params) {
416                 return -1;
417             }
418             PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg1);
419             X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
420                             V_ASN1_SEQUENCE, params);
421                                 }
422         return 1;
423 #ifndef OPENSSL_NO_CMS
424     case ASN1_PKEY_CTRL_CMS_ENVELOPE:
425         if (arg1 == 0) {
426             ASN1_STRING *params = encode_gost_algor_params(pkey);
427             if (!params) {
428                 return -1;
429             }
430             CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
431                                              NULL, &alg1);
432             X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
433                             V_ASN1_SEQUENCE, params);
434         } else {
435           EVP_PKEY_CTX *pctx;
436           CMS_RecipientInfo *ri = arg2;
437           pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
438           if (!pctx)
439               return 0;
440           return gost_cms_set_shared_info(pctx, ri);
441         }
442         return 1;
443 #ifdef ASN1_PKEY_CTRL_CMS_RI_TYPE
444   case ASN1_PKEY_CTRL_CMS_RI_TYPE:
445         *(int *)arg2 = CMS_RECIPINFO_TRANS;
446         return 1;
447         case ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED:
448                         if (arg1 == CMS_RECIPINFO_AGREE || arg1 == CMS_RECIPINFO_TRANS)
449                                 return 1;
450                         else
451                                 return 0;
452                         break;
453 #endif
454 #endif
455     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
456         *(int *)arg2 = md_nid;
457         return 2;
458     }
459
460     return -2;
461 }
462
463 /* --------------------- free functions * ------------------------------*/
464 static void pkey_free_gost_ec(EVP_PKEY *key)
465 {
466     EC_KEY_free((EC_KEY *)EVP_PKEY_get0(key));
467 }
468
469 /* ------------------ private key functions  -----------------------------*/
470
471 static BIGNUM *unmask_priv_key(EVP_PKEY *pk,
472                                const unsigned char *buf, int len, int num_masks)
473 {
474     BIGNUM *pknum_masked = NULL, *q = NULL;
475     const EC_KEY *key_ptr = (pk) ? EVP_PKEY_get0(pk) : NULL;
476     const EC_GROUP *group = (key_ptr) ? EC_KEY_get0_group(key_ptr) : NULL;
477
478     pknum_masked = BN_lebin2bn(buf, len, BN_secure_new());
479     if (!pknum_masked)
480         return NULL;
481
482     if (num_masks > 0) {
483         /*
484          * XXX Remove sign by gost94
485          */
486         const unsigned char *p = buf + num_masks * len;
487
488         q = BN_new();
489         if (!q || !group || EC_GROUP_get_order(group, q, NULL) <= 0) {
490             BN_free(pknum_masked);
491             pknum_masked = NULL;
492             goto end;
493         }
494
495         for (; p != buf; p -= len) {
496             BIGNUM *mask = BN_lebin2bn(p, len, BN_secure_new());
497             BN_CTX *ctx = BN_CTX_secure_new();
498
499             BN_mod_mul(pknum_masked, pknum_masked, mask, q, ctx);
500
501             BN_CTX_free(ctx);
502             BN_free(mask);
503         }
504     }
505
506  end:
507     if (q)
508         BN_free(q);
509     return pknum_masked;
510 }
511
512 static int priv_decode_gost(EVP_PKEY *pk,
513                             const PKCS8_PRIV_KEY_INFO *p8inf)
514 {
515     const unsigned char *pkey_buf = NULL, *p = NULL;
516     int priv_len = 0;
517     BIGNUM *pk_num = NULL;
518     int ret = 0;
519     const X509_ALGOR *palg = NULL;
520     const ASN1_OBJECT *palg_obj = NULL;
521     ASN1_INTEGER *priv_key = NULL;
522     int expected_key_len;
523
524     if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
525         return 0;
526     p = pkey_buf;
527     if (!decode_gost_algor_params(pk, palg)) {
528         return 0;
529     }
530
531     expected_key_len = pkey_bits_gost(pk) > 0 ? pkey_bits_gost(pk) / 8 : 0;
532     if (expected_key_len == 0) {
533         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
534         return 0;
535     }
536
537     if (priv_len % expected_key_len == 0) {
538         /* Key is not wrapped but masked */
539         pk_num = unmask_priv_key(pk, pkey_buf, expected_key_len,
540                                  priv_len / expected_key_len - 1);
541     } else if (V_ASN1_OCTET_STRING == *p) {
542         /* New format - Little endian octet string */
543         ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
544         if (!s || ((s->length != 32) && (s->length != 64))) {
545             ASN1_STRING_free(s);
546             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
547             return 0;
548         }
549         pk_num = BN_lebin2bn(s->data, s->length, BN_secure_new());
550         ASN1_STRING_free(s);
551     } else if (V_ASN1_INTEGER == *p) {
552         priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
553         if (!priv_key) {
554             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
555             return 0;
556         }
557         pk_num = ASN1_INTEGER_to_BN(priv_key, BN_secure_new());
558         ASN1_INTEGER_free(priv_key);
559     } else if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == *p) {
560         MASKED_GOST_KEY *mgk = d2i_MASKED_GOST_KEY(NULL, &p, priv_len);
561
562         if (!mgk) {
563             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
564             return 0;
565         }
566
567         priv_len = mgk->masked_priv_key->length;
568         if (priv_len % expected_key_len) {
569             MASKED_GOST_KEY_free(mgk);
570             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
571             return 0;
572         }
573
574         pk_num = unmask_priv_key(pk, mgk->masked_priv_key->data,
575                                  expected_key_len,
576                                  priv_len / expected_key_len - 1);
577         MASKED_GOST_KEY_free(mgk);
578     } else {
579         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
580         return 0;
581     }
582
583     if (pk_num == NULL) {
584         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
585         return 0;
586     }
587
588     ret = gost_set_priv_key(pk, pk_num);
589     BN_free(pk_num);
590     return ret;
591 }
592
593 /* ----------------------------------------------------------------------*/
594 static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
595 {
596     ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
597     ASN1_STRING *params = NULL;
598     unsigned char *buf = NULL;
599     int key_len = pkey_bits_gost(pk), i = 0;
600     /* unmasked private key */
601     const char *pk_format = get_gost_engine_param(GOST_PARAM_PK_FORMAT);
602
603     key_len = (key_len < 0) ? 0 : key_len / 8;
604     if (key_len == 0 || !(buf = OPENSSL_secure_malloc(key_len))) {
605         return 0;
606     }
607
608     if (!store_bignum(gost_get0_priv_key(pk), buf, key_len)) {
609         OPENSSL_secure_free(buf);
610         return 0;
611     }
612
613     params = encode_gost_algor_params(pk);
614     if (!params) {
615         OPENSSL_secure_free(buf);
616         return 0;
617     }
618
619     /* Convert buf to Little-endian */
620     for (i = 0; i < key_len / 2; i++) {
621         unsigned char tmp = buf[i];
622         buf[i] = buf[key_len - 1 - i];
623         buf[key_len - 1 - i] = tmp;
624     }
625
626     if (pk_format != NULL && strcmp(pk_format, PK_WRAP_PARAM) == 0) {
627         ASN1_STRING *octet = ASN1_STRING_new();
628         int priv_len = 0;
629         unsigned char *priv_buf = NULL;
630         if (!octet || !ASN1_OCTET_STRING_set(octet, buf, key_len)) {
631             ASN1_STRING_free(octet);
632             ASN1_STRING_free(params);
633             OPENSSL_secure_free(buf);
634             return 0;
635         }
636         priv_len = i2d_ASN1_OCTET_STRING(octet, &priv_buf);
637         ASN1_STRING_free(octet);
638         OPENSSL_secure_free(buf);
639
640         return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
641                                priv_buf, priv_len);
642     }
643
644     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
645                            buf, key_len);
646 }
647
648 /* --------- printing keys --------------------------------*/
649 static int print_gost_priv(BIO *out, const EVP_PKEY *pkey, int indent)
650 {
651     BIGNUM *key;
652
653     if (!BIO_indent(out, indent, 128))
654         return 0;
655     BIO_printf(out, "Private key: ");
656     key = gost_get0_priv_key(pkey);
657     if (!key)
658         BIO_printf(out, "<undefined>");
659     else
660         BN_print(out, key);
661     BIO_printf(out, "\n");
662
663     return 1;
664 }
665
666 static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent)
667 {
668     BN_CTX *ctx;
669     BIGNUM *X, *Y;
670     const EC_POINT *pubkey;
671     const EC_GROUP *group;
672     EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey);
673     int ok = 0;
674
675     ctx = BN_CTX_new();
676     if (!ctx) {
677         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE);
678         return 0;
679     }
680
681     BN_CTX_start(ctx);
682     X = BN_CTX_get(ctx);
683     Y = BN_CTX_get(ctx);
684     pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL;
685     group = (key) ? EC_KEY_get0_group(key) : NULL;
686     if (!pubkey || !group)
687         goto err;
688
689     if (!EC_POINT_get_affine_coordinates(group, pubkey, X, Y, ctx)) {
690         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB);
691         goto err;
692     }
693     if (!BIO_indent(out, indent, 128))
694         goto err;
695     BIO_printf(out, "Public key:\n");
696     if (!BIO_indent(out, indent + 3, 128))
697         goto err;
698     BIO_printf(out, "X:");
699     BN_print(out, X);
700     BIO_printf(out, "\n");
701     if (!BIO_indent(out, indent + 3, 128))
702         goto err;
703     BIO_printf(out, "Y:");
704     BN_print(out, Y);
705     BIO_printf(out, "\n");
706     ok = 1;
707  err:
708     BN_CTX_end(ctx);
709     BN_CTX_free(ctx);
710
711     return ok;
712 }
713
714 static int print_gost_ec_param(BIO *out, const EVP_PKEY *pkey, int indent)
715 {
716     EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
717     const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
718     int param_nid;
719
720     if (!group)
721         return 0;
722
723     param_nid = EC_GROUP_get_curve_name(group);
724     if (!BIO_indent(out, indent, 128))
725         return 0;
726     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
727
728     return 1;
729 }
730
731 static int print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
732                          ASN1_PCTX *pctx, int type)
733 {
734     if (type == 2) {
735         if (print_gost_priv(out, pkey, indent) == 0)
736             return 0;
737     }
738     if (type >= 1) {
739         if (print_gost_ec_pub(out, pkey, indent) == 0)
740             return 0;
741     }
742
743     return print_gost_ec_param(out, pkey, indent);
744 }
745
746 static int param_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
747                                ASN1_PCTX *pctx)
748 {
749     return print_gost_ec(out, pkey, indent, pctx, 0);
750 }
751
752 static int pub_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
753                              ASN1_PCTX *pctx)
754 {
755     return print_gost_ec(out, pkey, indent, pctx, 1);
756 }
757
758 static int priv_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
759                               ASN1_PCTX *pctx)
760 {
761     return print_gost_ec(out, pkey, indent, pctx, 2);
762 }
763
764 /* ---------------------------------------------------------------------*/
765 static int param_missing_gost_ec(const EVP_PKEY *pk)
766 {
767     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
768     if (!ec)
769         return 1;
770     if (!EC_KEY_get0_group(ec))
771         return 1;
772     return 0;
773 }
774
775 static int param_copy_gost_ec(EVP_PKEY *to, const EVP_PKEY *from)
776 {
777     EC_KEY *eto = EVP_PKEY_get0(to);
778     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
779     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
780         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS);
781         return 0;
782     }
783     if (!efrom) {
784         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING);
785         return 0;
786     }
787     if (!eto) {
788         eto = EC_KEY_new();
789         if (!eto) {
790             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE);
791             return 0;
792         }
793         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
794             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
795             EC_KEY_free(eto);
796             return 0;
797         }
798     }
799     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
800         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
801         return 0;
802     }
803     if (EC_KEY_get0_private_key(eto)) {
804         return gost_ec_compute_public(eto);
805     }
806     return 1;
807 }
808
809 static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
810 {
811     const EC_GROUP *group_a, *group_b;
812     EC_KEY *ec_a = EVP_PKEY_get0((EVP_PKEY *)a);
813     EC_KEY *ec_b = EVP_PKEY_get0((EVP_PKEY *)b);
814     if (!ec_a || !ec_b)
815         return 0;
816
817     group_a = EC_KEY_get0_group(ec_a);
818     group_b = EC_KEY_get0_group(ec_b);
819     if (!group_a || !group_b)
820         return 0;
821
822     if (EC_GROUP_get_curve_name(group_a) == EC_GROUP_get_curve_name(group_b)) {
823         return 1;
824     }
825     return 0;
826 }
827
828 /* ---------- Public key functions * --------------------------------------*/
829 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
830 {
831     X509_ALGOR *palg = NULL;
832     const unsigned char *pubkey_buf = NULL;
833     unsigned char *databuf;
834     ASN1_OBJECT *palgobj = NULL;
835     int pub_len;
836     EC_POINT *pub_key;
837     BIGNUM *X, *Y;
838     ASN1_OCTET_STRING *octet = NULL;
839     size_t len;
840     const EC_GROUP *group;
841
842     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
843         return 0;
844     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
845     if (!decode_gost_algor_params(pk, palg))
846         return 0;
847     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
848     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
849     if (!octet) {
850         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
851         return 0;
852     }
853     databuf = OPENSSL_malloc(octet->length);
854     if (databuf == NULL) {
855         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
856         ASN1_OCTET_STRING_free(octet);
857         return 0;
858     }
859
860     BUF_reverse(databuf, octet->data, octet->length);
861     len = octet->length / 2;
862     ASN1_OCTET_STRING_free(octet);
863
864     Y = BN_bin2bn(databuf, len, NULL);
865     X = BN_bin2bn(databuf + len, len, NULL);
866     OPENSSL_free(databuf);
867     pub_key = EC_POINT_new(group);
868     if (!EC_POINT_set_affine_coordinates(group, pub_key, X, Y, NULL)) {
869         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
870         EC_POINT_free(pub_key);
871         BN_free(X);
872         BN_free(Y);
873         return 0;
874     }
875     BN_free(X);
876     BN_free(Y);
877     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
878         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
879         EC_POINT_free(pub_key);
880         return 0;
881     }
882     EC_POINT_free(pub_key);
883     return 1;
884
885 }
886
887 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
888 {
889     ASN1_OBJECT *algobj;
890     ASN1_OCTET_STRING *octet = NULL;
891     void *pval;
892     unsigned char *buf = NULL, *databuf = NULL;
893     int data_len, ret = -1;
894     const EC_POINT *pub_key;
895     BIGNUM *X = NULL, *Y = NULL, *order;
896     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
897     int ptype = V_ASN1_SEQUENCE;
898     ASN1_STRING *params;
899
900     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
901
902     params = encode_gost_algor_params(pk);
903     pval = params;
904
905     order = BN_new();
906     if (!order) {
907         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
908         goto err;
909     }
910     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
911     pub_key = EC_KEY_get0_public_key(ec);
912     if (!pub_key) {
913         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
914         goto err;
915     }
916     X = BN_new();
917     Y = BN_new();
918     if (!X || !Y) {
919         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
920         goto err;
921     }
922     if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
923                                              pub_key, X, Y, NULL)) {
924         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
925         goto err;
926     }
927     data_len = 2 * BN_num_bytes(order);
928     databuf = OPENSSL_zalloc(data_len);
929     if (databuf == NULL) {
930         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
931         goto err;
932     }
933
934     store_bignum(X, databuf + data_len / 2, data_len / 2);
935     store_bignum(Y, databuf, data_len / 2);
936
937     BUF_reverse(databuf, NULL, data_len);
938
939     octet = ASN1_OCTET_STRING_new();
940     if (octet == NULL) {
941         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
942         goto err;
943     }
944
945     if (0 == ASN1_STRING_set(octet, databuf, data_len)) {
946         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
947         goto err;
948     }
949
950     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
951  err:
952     ASN1_BIT_STRING_free(octet);
953     if (X)
954         BN_free(X);
955     if (Y)
956         BN_free(Y);
957     if (order)
958         BN_free(order);
959     if (databuf)
960         OPENSSL_free(databuf);
961
962     if (ret < 0)
963         return 0;
964     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
965 }
966
967 static int pub_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
968 {
969     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
970     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
971     const EC_POINT *ka, *kb;
972     if (!ea || !eb)
973         return 0;
974     ka = EC_KEY_get0_public_key(ea);
975     kb = EC_KEY_get0_public_key(eb);
976     if (!ka || !kb)
977         return 0;
978     return (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
979 }
980
981 static int pkey_size_gost(const EVP_PKEY *pk)
982 {
983     if (!pk)
984         return -1;
985
986     switch (EVP_PKEY_base_id(pk)) {
987     case NID_id_GostR3410_94:
988     case NID_id_GostR3410_2001:
989     case NID_id_GostR3410_2012_256:
990         return 64;
991     case NID_id_GostR3410_2012_512:
992         return 128;
993     }
994
995     return -1;
996 }
997
998 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
999 static void mackey_free_gost(EVP_PKEY *pk)
1000 {
1001     OPENSSL_free(EVP_PKEY_get0(pk));
1002 }
1003
1004 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1005 {
1006     switch (op) {
1007     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1008         if (arg2) {
1009             *(int *)arg2 = NID_id_Gost28147_89_MAC;
1010             return 2;
1011         }
1012     }
1013     return -2;
1014 }
1015
1016 static int mac_ctrl_gost_12(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1017 {
1018     switch (op) {
1019     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1020         if (arg2) {
1021             *(int *)arg2 = NID_gost_mac_12;
1022             return 2;
1023         }
1024     }
1025     return -2;
1026 }
1027
1028 static int mac_ctrl_magma(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1029 {
1030     switch (op) {
1031     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1032         if (arg2) {
1033             *(int *)arg2 = NID_magma_mac;
1034             return 2;
1035         }
1036     }
1037     return -2;
1038 }
1039
1040 static int mac_ctrl_grasshopper(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1041 {
1042     switch (op) {
1043     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1044         if (arg2) {
1045             *(int *)arg2 = NID_grasshopper_mac;
1046             return 2;
1047         }
1048     }
1049     return -2;
1050 }
1051
1052 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
1053 {
1054     int nid =
1055         EC_GROUP_get_curve_name(EC_KEY_get0_group
1056                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
1057     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
1058 }
1059
1060 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
1061                                  int derlen)
1062 {
1063     ASN1_OBJECT *obj = NULL;
1064     int nid;
1065     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
1066         return 0;
1067     }
1068     nid = OBJ_obj2nid(obj);
1069     ASN1_OBJECT_free(obj);
1070
1071     return gost_decode_nid_params(pkey, NID_id_GostR3410_2001, nid);
1072 }
1073
1074 /* ----------------------------------------------------------------------*/
1075 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
1076                         const char *pemstr, const char *info)
1077 {
1078     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
1079     if (!*ameth)
1080         return 0;
1081     switch (nid) {
1082     case NID_id_GostR3410_2001:
1083         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
1084         EVP_PKEY_asn1_set_private(*ameth,
1085                                   priv_decode_gost, priv_encode_gost,
1086                                   priv_print_gost_ec);
1087
1088         EVP_PKEY_asn1_set_param(*ameth,
1089                                 gost2001_param_decode, gost2001_param_encode,
1090                                 param_missing_gost_ec, param_copy_gost_ec,
1091                                 param_cmp_gost_ec, param_print_gost_ec);
1092         EVP_PKEY_asn1_set_public(*ameth,
1093                                  pub_decode_gost_ec, pub_encode_gost_ec,
1094                                  pub_cmp_gost_ec, pub_print_gost_ec,
1095                                  pkey_size_gost, pkey_bits_gost);
1096
1097         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
1098         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
1099         break;
1100     case NID_id_GostR3410_2012_256:
1101     case NID_id_GostR3410_2012_512:
1102         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
1103         EVP_PKEY_asn1_set_private(*ameth,
1104                                   priv_decode_gost, priv_encode_gost,
1105                                   priv_print_gost_ec);
1106
1107         EVP_PKEY_asn1_set_param(*ameth,
1108                                 NULL, NULL,
1109                                 param_missing_gost_ec, param_copy_gost_ec,
1110                                 param_cmp_gost_ec, NULL);
1111
1112         EVP_PKEY_asn1_set_public(*ameth,
1113                                  pub_decode_gost_ec, pub_encode_gost_ec,
1114                                  pub_cmp_gost_ec, pub_print_gost_ec,
1115                                  pkey_size_gost, pkey_bits_gost);
1116
1117         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
1118         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
1119         break;
1120     case NID_id_Gost28147_89_MAC:
1121         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1122         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
1123         break;
1124     case NID_gost_mac_12:
1125         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1126         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost_12);
1127         break;
1128     case NID_magma_mac:
1129         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1130         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_magma);
1131         break;
1132     case NID_grasshopper_mac:
1133         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1134         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_grasshopper);
1135         break;
1136     }
1137     return 1;
1138 }