]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_ameth.c
Restoring gost89 CMS support in gost engine for OpenSSL 3.0
[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           *(int *)arg2 = 1;
450                                   return 1;
451       }
452                         else
453                                   return 0;
454                         break;
455 #endif
456 #endif
457     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
458         *(int *)arg2 = md_nid;
459         return 2;
460     }
461
462     return -2;
463 }
464
465 /* --------------------- free functions * ------------------------------*/
466 static void pkey_free_gost_ec(EVP_PKEY *key)
467 {
468     EC_KEY_free((EC_KEY *)EVP_PKEY_get0(key));
469 }
470
471 /* ------------------ private key functions  -----------------------------*/
472
473 static BIGNUM *unmask_priv_key(EVP_PKEY *pk,
474                                const unsigned char *buf, int len, int num_masks)
475 {
476     BIGNUM *pknum_masked = NULL, *q = NULL;
477     const EC_KEY *key_ptr = (pk) ? EVP_PKEY_get0(pk) : NULL;
478     const EC_GROUP *group = (key_ptr) ? EC_KEY_get0_group(key_ptr) : NULL;
479
480     pknum_masked = BN_lebin2bn(buf, len, BN_secure_new());
481     if (!pknum_masked)
482         return NULL;
483
484     if (num_masks > 0) {
485         /*
486          * XXX Remove sign by gost94
487          */
488         const unsigned char *p = buf + num_masks * len;
489
490         q = BN_new();
491         if (!q || !group || EC_GROUP_get_order(group, q, NULL) <= 0) {
492             BN_free(pknum_masked);
493             pknum_masked = NULL;
494             goto end;
495         }
496
497         for (; p != buf; p -= len) {
498             BIGNUM *mask = BN_lebin2bn(p, len, BN_secure_new());
499             BN_CTX *ctx = BN_CTX_secure_new();
500
501             BN_mod_mul(pknum_masked, pknum_masked, mask, q, ctx);
502
503             BN_CTX_free(ctx);
504             BN_free(mask);
505         }
506     }
507
508  end:
509     if (q)
510         BN_free(q);
511     return pknum_masked;
512 }
513
514 static int priv_decode_gost(EVP_PKEY *pk,
515                             const PKCS8_PRIV_KEY_INFO *p8inf)
516 {
517     const unsigned char *pkey_buf = NULL, *p = NULL;
518     int priv_len = 0;
519     BIGNUM *pk_num = NULL;
520     int ret = 0;
521     const X509_ALGOR *palg = NULL;
522     const ASN1_OBJECT *palg_obj = NULL;
523     ASN1_INTEGER *priv_key = NULL;
524     int expected_key_len;
525
526     if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
527         return 0;
528     p = pkey_buf;
529     if (!decode_gost_algor_params(pk, palg)) {
530         return 0;
531     }
532
533     expected_key_len = pkey_bits_gost(pk) > 0 ? pkey_bits_gost(pk) / 8 : 0;
534     if (expected_key_len == 0) {
535         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
536         return 0;
537     }
538
539     if (priv_len % expected_key_len == 0) {
540         /* Key is not wrapped but masked */
541         pk_num = unmask_priv_key(pk, pkey_buf, expected_key_len,
542                                  priv_len / expected_key_len - 1);
543     } else if (V_ASN1_OCTET_STRING == *p) {
544         /* New format - Little endian octet string */
545         ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
546         if (!s || ((s->length != 32) && (s->length != 64))) {
547             ASN1_STRING_free(s);
548             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
549             return 0;
550         }
551         pk_num = BN_lebin2bn(s->data, s->length, BN_secure_new());
552         ASN1_STRING_free(s);
553     } else if (V_ASN1_INTEGER == *p) {
554         priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
555         if (!priv_key) {
556             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
557             return 0;
558         }
559         pk_num = ASN1_INTEGER_to_BN(priv_key, BN_secure_new());
560         ASN1_INTEGER_free(priv_key);
561     } else if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == *p) {
562         MASKED_GOST_KEY *mgk = d2i_MASKED_GOST_KEY(NULL, &p, priv_len);
563
564         if (!mgk) {
565             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
566             return 0;
567         }
568
569         priv_len = mgk->masked_priv_key->length;
570         if (priv_len % expected_key_len) {
571             MASKED_GOST_KEY_free(mgk);
572             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
573             return 0;
574         }
575
576         pk_num = unmask_priv_key(pk, mgk->masked_priv_key->data,
577                                  expected_key_len,
578                                  priv_len / expected_key_len - 1);
579         MASKED_GOST_KEY_free(mgk);
580     } else {
581         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
582         return 0;
583     }
584
585     if (pk_num == NULL) {
586         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
587         return 0;
588     }
589
590     ret = gost_set_priv_key(pk, pk_num);
591     BN_free(pk_num);
592     return ret;
593 }
594
595 /* ----------------------------------------------------------------------*/
596 static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
597 {
598     ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
599     ASN1_STRING *params = NULL;
600     unsigned char *buf = NULL;
601     int key_len = pkey_bits_gost(pk), i = 0;
602     /* unmasked private key */
603     const char *pk_format = get_gost_engine_param(GOST_PARAM_PK_FORMAT);
604
605     key_len = (key_len < 0) ? 0 : key_len / 8;
606     if (key_len == 0 || !(buf = OPENSSL_secure_malloc(key_len))) {
607         return 0;
608     }
609
610     if (!store_bignum(gost_get0_priv_key(pk), buf, key_len)) {
611         OPENSSL_secure_free(buf);
612         return 0;
613     }
614
615     params = encode_gost_algor_params(pk);
616     if (!params) {
617         OPENSSL_secure_free(buf);
618         return 0;
619     }
620
621     /* Convert buf to Little-endian */
622     for (i = 0; i < key_len / 2; i++) {
623         unsigned char tmp = buf[i];
624         buf[i] = buf[key_len - 1 - i];
625         buf[key_len - 1 - i] = tmp;
626     }
627
628     if (pk_format != NULL && strcmp(pk_format, PK_WRAP_PARAM) == 0) {
629         ASN1_STRING *octet = ASN1_STRING_new();
630         int priv_len = 0;
631         unsigned char *priv_buf = NULL;
632         if (!octet || !ASN1_OCTET_STRING_set(octet, buf, key_len)) {
633             ASN1_STRING_free(octet);
634             ASN1_STRING_free(params);
635             OPENSSL_secure_free(buf);
636             return 0;
637         }
638         priv_len = i2d_ASN1_OCTET_STRING(octet, &priv_buf);
639         ASN1_STRING_free(octet);
640         OPENSSL_secure_free(buf);
641
642         return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
643                                priv_buf, priv_len);
644     }
645
646     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
647                            buf, key_len);
648 }
649
650 /* --------- printing keys --------------------------------*/
651 static int print_gost_priv(BIO *out, const EVP_PKEY *pkey, int indent)
652 {
653     BIGNUM *key;
654
655     if (!BIO_indent(out, indent, 128))
656         return 0;
657     BIO_printf(out, "Private key: ");
658     key = gost_get0_priv_key(pkey);
659     if (!key)
660         BIO_printf(out, "<undefined>");
661     else
662         BN_print(out, key);
663     BIO_printf(out, "\n");
664
665     return 1;
666 }
667
668 static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent)
669 {
670     BN_CTX *ctx;
671     BIGNUM *X, *Y;
672     const EC_POINT *pubkey;
673     const EC_GROUP *group;
674     EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey);
675     int ok = 0;
676
677     ctx = BN_CTX_new();
678     if (!ctx) {
679         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE);
680         return 0;
681     }
682
683     BN_CTX_start(ctx);
684     X = BN_CTX_get(ctx);
685     Y = BN_CTX_get(ctx);
686     pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL;
687     group = (key) ? EC_KEY_get0_group(key) : NULL;
688     if (!pubkey || !group)
689         goto err;
690
691     if (!EC_POINT_get_affine_coordinates(group, pubkey, X, Y, ctx)) {
692         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB);
693         goto err;
694     }
695     if (!BIO_indent(out, indent, 128))
696         goto err;
697     BIO_printf(out, "Public key:\n");
698     if (!BIO_indent(out, indent + 3, 128))
699         goto err;
700     BIO_printf(out, "X:");
701     BN_print(out, X);
702     BIO_printf(out, "\n");
703     if (!BIO_indent(out, indent + 3, 128))
704         goto err;
705     BIO_printf(out, "Y:");
706     BN_print(out, Y);
707     BIO_printf(out, "\n");
708     ok = 1;
709  err:
710     BN_CTX_end(ctx);
711     BN_CTX_free(ctx);
712
713     return ok;
714 }
715
716 static int print_gost_ec_param(BIO *out, const EVP_PKEY *pkey, int indent)
717 {
718     EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
719     const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
720     int param_nid;
721
722     if (!group)
723         return 0;
724
725     param_nid = EC_GROUP_get_curve_name(group);
726     if (!BIO_indent(out, indent, 128))
727         return 0;
728     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
729
730     return 1;
731 }
732
733 static int print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
734                          ASN1_PCTX *pctx, int type)
735 {
736     if (type == 2) {
737         if (print_gost_priv(out, pkey, indent) == 0)
738             return 0;
739     }
740     if (type >= 1) {
741         if (print_gost_ec_pub(out, pkey, indent) == 0)
742             return 0;
743     }
744
745     return print_gost_ec_param(out, pkey, indent);
746 }
747
748 static int param_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
749                                ASN1_PCTX *pctx)
750 {
751     return print_gost_ec(out, pkey, indent, pctx, 0);
752 }
753
754 static int pub_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
755                              ASN1_PCTX *pctx)
756 {
757     return print_gost_ec(out, pkey, indent, pctx, 1);
758 }
759
760 static int priv_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
761                               ASN1_PCTX *pctx)
762 {
763     return print_gost_ec(out, pkey, indent, pctx, 2);
764 }
765
766 /* ---------------------------------------------------------------------*/
767 static int param_missing_gost_ec(const EVP_PKEY *pk)
768 {
769     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
770     if (!ec)
771         return 1;
772     if (!EC_KEY_get0_group(ec))
773         return 1;
774     return 0;
775 }
776
777 static int param_copy_gost_ec(EVP_PKEY *to, const EVP_PKEY *from)
778 {
779     EC_KEY *eto = EVP_PKEY_get0(to);
780     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
781     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
782         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS);
783         return 0;
784     }
785     if (!efrom) {
786         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING);
787         return 0;
788     }
789     if (!eto) {
790         eto = EC_KEY_new();
791         if (!eto) {
792             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE);
793             return 0;
794         }
795         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
796             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
797             EC_KEY_free(eto);
798             return 0;
799         }
800     }
801     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
802         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
803         return 0;
804     }
805     if (EC_KEY_get0_private_key(eto)) {
806         return gost_ec_compute_public(eto);
807     }
808     return 1;
809 }
810
811 static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
812 {
813     const EC_GROUP *group_a, *group_b;
814     EC_KEY *ec_a = EVP_PKEY_get0((EVP_PKEY *)a);
815     EC_KEY *ec_b = EVP_PKEY_get0((EVP_PKEY *)b);
816     if (!ec_a || !ec_b)
817         return 0;
818
819     group_a = EC_KEY_get0_group(ec_a);
820     group_b = EC_KEY_get0_group(ec_b);
821     if (!group_a || !group_b)
822         return 0;
823
824     if (EC_GROUP_get_curve_name(group_a) == EC_GROUP_get_curve_name(group_b)) {
825         return 1;
826     }
827     return 0;
828 }
829
830 /* ---------- Public key functions * --------------------------------------*/
831 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
832 {
833     X509_ALGOR *palg = NULL;
834     const unsigned char *pubkey_buf = NULL;
835     unsigned char *databuf;
836     ASN1_OBJECT *palgobj = NULL;
837     int pub_len;
838     EC_POINT *pub_key;
839     BIGNUM *X, *Y;
840     ASN1_OCTET_STRING *octet = NULL;
841     size_t len;
842     const EC_GROUP *group;
843
844     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
845         return 0;
846     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
847     if (!decode_gost_algor_params(pk, palg))
848         return 0;
849     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
850     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
851     if (!octet) {
852         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
853         return 0;
854     }
855     databuf = OPENSSL_malloc(octet->length);
856     if (databuf == NULL) {
857         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
858         ASN1_OCTET_STRING_free(octet);
859         return 0;
860     }
861
862     BUF_reverse(databuf, octet->data, octet->length);
863     len = octet->length / 2;
864     ASN1_OCTET_STRING_free(octet);
865
866     Y = BN_bin2bn(databuf, len, NULL);
867     X = BN_bin2bn(databuf + len, len, NULL);
868     OPENSSL_free(databuf);
869     pub_key = EC_POINT_new(group);
870     if (!EC_POINT_set_affine_coordinates(group, pub_key, X, Y, NULL)) {
871         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
872         EC_POINT_free(pub_key);
873         BN_free(X);
874         BN_free(Y);
875         return 0;
876     }
877     BN_free(X);
878     BN_free(Y);
879     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
880         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
881         EC_POINT_free(pub_key);
882         return 0;
883     }
884     EC_POINT_free(pub_key);
885     return 1;
886
887 }
888
889 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
890 {
891     ASN1_OBJECT *algobj;
892     ASN1_OCTET_STRING *octet = NULL;
893     void *pval;
894     unsigned char *buf = NULL, *databuf = NULL;
895     int data_len, ret = -1;
896     const EC_POINT *pub_key;
897     BIGNUM *X = NULL, *Y = NULL, *order;
898     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
899     int ptype = V_ASN1_SEQUENCE;
900     ASN1_STRING *params;
901
902     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
903
904     params = encode_gost_algor_params(pk);
905     pval = params;
906
907     order = BN_new();
908     if (!order) {
909         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
910         goto err;
911     }
912     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
913     pub_key = EC_KEY_get0_public_key(ec);
914     if (!pub_key) {
915         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
916         goto err;
917     }
918     X = BN_new();
919     Y = BN_new();
920     if (!X || !Y) {
921         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
922         goto err;
923     }
924     if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
925                                              pub_key, X, Y, NULL)) {
926         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
927         goto err;
928     }
929     data_len = 2 * BN_num_bytes(order);
930     databuf = OPENSSL_zalloc(data_len);
931     if (databuf == NULL) {
932         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
933         goto err;
934     }
935
936     store_bignum(X, databuf + data_len / 2, data_len / 2);
937     store_bignum(Y, databuf, data_len / 2);
938
939     BUF_reverse(databuf, NULL, data_len);
940
941     octet = ASN1_OCTET_STRING_new();
942     if (octet == NULL) {
943         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
944         goto err;
945     }
946
947     if (0 == ASN1_STRING_set(octet, databuf, data_len)) {
948         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
949         goto err;
950     }
951
952     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
953  err:
954     ASN1_BIT_STRING_free(octet);
955     if (X)
956         BN_free(X);
957     if (Y)
958         BN_free(Y);
959     if (order)
960         BN_free(order);
961     if (databuf)
962         OPENSSL_free(databuf);
963
964     if (ret < 0)
965         return 0;
966     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
967 }
968
969 static int pub_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
970 {
971     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
972     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
973     const EC_POINT *ka, *kb;
974     if (!ea || !eb)
975         return 0;
976     ka = EC_KEY_get0_public_key(ea);
977     kb = EC_KEY_get0_public_key(eb);
978     if (!ka || !kb)
979         return 0;
980     return (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
981 }
982
983 static int pkey_size_gost(const EVP_PKEY *pk)
984 {
985     if (!pk)
986         return -1;
987
988     switch (EVP_PKEY_base_id(pk)) {
989     case NID_id_GostR3410_94:
990     case NID_id_GostR3410_2001:
991     case NID_id_GostR3410_2012_256:
992         return 64;
993     case NID_id_GostR3410_2012_512:
994         return 128;
995     }
996
997     return -1;
998 }
999
1000 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
1001 static void mackey_free_gost(EVP_PKEY *pk)
1002 {
1003     OPENSSL_free(EVP_PKEY_get0(pk));
1004 }
1005
1006 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1007 {
1008     switch (op) {
1009     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1010         if (arg2) {
1011             *(int *)arg2 = NID_id_Gost28147_89_MAC;
1012             return 2;
1013         }
1014     }
1015     return -2;
1016 }
1017
1018 static int mac_ctrl_gost_12(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1019 {
1020     switch (op) {
1021     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1022         if (arg2) {
1023             *(int *)arg2 = NID_gost_mac_12;
1024             return 2;
1025         }
1026     }
1027     return -2;
1028 }
1029
1030 static int mac_ctrl_magma(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1031 {
1032     switch (op) {
1033     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1034         if (arg2) {
1035             *(int *)arg2 = NID_magma_mac;
1036             return 2;
1037         }
1038     }
1039     return -2;
1040 }
1041
1042 static int mac_ctrl_grasshopper(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1043 {
1044     switch (op) {
1045     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1046         if (arg2) {
1047             *(int *)arg2 = NID_grasshopper_mac;
1048             return 2;
1049         }
1050     }
1051     return -2;
1052 }
1053
1054 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
1055 {
1056     int nid =
1057         EC_GROUP_get_curve_name(EC_KEY_get0_group
1058                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
1059     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
1060 }
1061
1062 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
1063                                  int derlen)
1064 {
1065     ASN1_OBJECT *obj = NULL;
1066     int nid;
1067     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
1068         return 0;
1069     }
1070     nid = OBJ_obj2nid(obj);
1071     ASN1_OBJECT_free(obj);
1072
1073     return gost_decode_nid_params(pkey, NID_id_GostR3410_2001, nid);
1074 }
1075
1076 /* ----------------------------------------------------------------------*/
1077 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
1078                         const char *pemstr, const char *info)
1079 {
1080     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
1081     if (!*ameth)
1082         return 0;
1083     switch (nid) {
1084     case NID_id_GostR3410_2001:
1085         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
1086         EVP_PKEY_asn1_set_private(*ameth,
1087                                   priv_decode_gost, priv_encode_gost,
1088                                   priv_print_gost_ec);
1089
1090         EVP_PKEY_asn1_set_param(*ameth,
1091                                 gost2001_param_decode, gost2001_param_encode,
1092                                 param_missing_gost_ec, param_copy_gost_ec,
1093                                 param_cmp_gost_ec, param_print_gost_ec);
1094         EVP_PKEY_asn1_set_public(*ameth,
1095                                  pub_decode_gost_ec, pub_encode_gost_ec,
1096                                  pub_cmp_gost_ec, pub_print_gost_ec,
1097                                  pkey_size_gost, pkey_bits_gost);
1098
1099         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
1100         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
1101         break;
1102     case NID_id_GostR3410_2012_256:
1103     case NID_id_GostR3410_2012_512:
1104         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
1105         EVP_PKEY_asn1_set_private(*ameth,
1106                                   priv_decode_gost, priv_encode_gost,
1107                                   priv_print_gost_ec);
1108
1109         EVP_PKEY_asn1_set_param(*ameth,
1110                                 NULL, NULL,
1111                                 param_missing_gost_ec, param_copy_gost_ec,
1112                                 param_cmp_gost_ec, NULL);
1113
1114         EVP_PKEY_asn1_set_public(*ameth,
1115                                  pub_decode_gost_ec, pub_encode_gost_ec,
1116                                  pub_cmp_gost_ec, pub_print_gost_ec,
1117                                  pkey_size_gost, pkey_bits_gost);
1118
1119         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
1120         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
1121         break;
1122     case NID_id_Gost28147_89_MAC:
1123         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1124         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
1125         break;
1126     case NID_gost_mac_12:
1127         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1128         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost_12);
1129         break;
1130     case NID_magma_mac:
1131         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1132         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_magma);
1133         break;
1134     case NID_grasshopper_mac:
1135         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1136         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_grasshopper);
1137         break;
1138     }
1139     return 1;
1140 }