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