0574d6eee4624db9ecc1ec0371fdaa9449fd5711
[openssl.git] / engines / ccgost / gost_pmeth.c
1 /**********************************************************************
2  *                          gost_pmeth.c                              *
3  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4  *         This file is distributed under the same license as OpenSSL *
5  *                                                                    *
6  *   Implementation of RFC 4357 (GOST R 34.10) Publick key method     *
7  *       for OpenSSL                                                  *
8  *          Requires OpenSSL 0.9.9 for compilation                    *
9  **********************************************************************/
10 #include <openssl/evp.h>
11 #include <openssl/objects.h>
12 #include <openssl/ec.h>
13 #include <openssl/err.h>
14 #include <openssl/x509v3.h>     /* For string_to_hex */
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include "gost_lcl.h"
19 #include "e_gost_err.h"
20 /* -----init, cleanup, copy - uniform for all algs  ---------------*/
21 /* Allocates new gost_pmeth_data structure and assigns it as data */
22 static int pkey_gost_init(EVP_PKEY_CTX *ctx)
23 {
24     struct gost_pmeth_data *data;
25     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
26
27     data = OPENSSL_malloc(sizeof(*data));
28     if (!data)
29         return 0;
30     memset(data, 0, sizeof(*data));
31     if (pkey && EVP_PKEY_get0(pkey)) {
32         switch (EVP_PKEY_base_id(pkey)) {
33         case NID_id_GostR3410_2001:
34             data->sign_param_nid =
35                 EC_GROUP_get_curve_name(EC_KEY_get0_group
36                                         (EVP_PKEY_get0((EVP_PKEY *)pkey)));
37             break;
38         default:
39             return 0;
40         }
41     }
42     EVP_PKEY_CTX_set_data(ctx, data);
43     return 1;
44 }
45
46 /* Copies contents of gost_pmeth_data structure */
47 static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
48 {
49     struct gost_pmeth_data *dst_data, *src_data;
50     if (!pkey_gost_init(dst)) {
51         return 0;
52     }
53     src_data = EVP_PKEY_CTX_get_data(src);
54     dst_data = EVP_PKEY_CTX_get_data(dst);
55     *dst_data = *src_data;
56     if (src_data->shared_ukm) {
57         dst_data->shared_ukm = NULL;
58     }
59     return 1;
60 }
61
62 /* Frees up gost_pmeth_data structure */
63 static void pkey_gost_cleanup(EVP_PKEY_CTX *ctx)
64 {
65     struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
66
67     OPENSSL_free(data->shared_ukm);
68     OPENSSL_free(data);
69 }
70
71 /* --------------------- control functions  ------------------------------*/
72 static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
73 {
74     struct gost_pmeth_data *pctx =
75         (struct gost_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
76     switch (type) {
77     case EVP_PKEY_CTRL_MD:
78         {
79             if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94) {
80                 GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
81                 return 0;
82             }
83             pctx->md = (EVP_MD *)p2;
84             return 1;
85         }
86
87     case EVP_PKEY_CTRL_GET_MD:
88         *(const EVP_MD **)p2 = pctx->md;
89         return 1;
90
91     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
92     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
93     case EVP_PKEY_CTRL_PKCS7_SIGN:
94     case EVP_PKEY_CTRL_DIGESTINIT:
95 #ifndef OPENSSL_NO_CMS
96     case EVP_PKEY_CTRL_CMS_ENCRYPT:
97     case EVP_PKEY_CTRL_CMS_DECRYPT:
98     case EVP_PKEY_CTRL_CMS_SIGN:
99 #endif
100         return 1;
101
102     case EVP_PKEY_CTRL_GOST_PARAMSET:
103         pctx->sign_param_nid = (int)p1;
104         return 1;
105     case EVP_PKEY_CTRL_SET_IV:
106         pctx->shared_ukm = OPENSSL_malloc((int)p1);
107         if (pctx->shared_ukm == NULL) {
108             GOSTerr(GOST_F_PKEY_GOST_CTRL, ERR_R_MALLOC_FAILURE);
109             return 0;
110         }
111         memcpy(pctx->shared_ukm, p2, (int)p1);
112         return 1;
113     case EVP_PKEY_CTRL_PEER_KEY:
114         if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
115             return 1;
116         if (p1 == 2)            /* TLS: peer key used? */
117             return pctx->peer_key_used;
118         if (p1 == 3)            /* TLS: peer key used! */
119             return (pctx->peer_key_used = 1);
120         return -2;
121     }
122     return -2;
123 }
124
125 static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
126                                 const char *type, const char *value)
127 {
128     int param_nid = 0;
129
130     if (strcmp(type, param_ctrl_string) == 0) {
131         if (!value) {
132             return 0;
133         }
134         if (strlen(value) == 1) {
135             switch (toupper((unsigned char)value[0])) {
136             case 'A':
137                 param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet;
138                 break;
139             case 'B':
140                 param_nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet;
141                 break;
142             case 'C':
143                 param_nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet;
144                 break;
145             case '0':
146                 param_nid = NID_id_GostR3410_2001_TestParamSet;
147                 break;
148             default:
149                 return 0;
150             }
151         } else if ((strlen(value) == 2)
152                    && (toupper((unsigned char)value[0]) == 'X')) {
153             switch (toupper((unsigned char)value[1])) {
154             case 'A':
155                 param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet;
156                 break;
157             case 'B':
158                 param_nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet;
159                 break;
160             default:
161                 return 0;
162             }
163         } else {
164             R3410_2001_params *p = R3410_2001_paramset;
165             param_nid = OBJ_txt2nid(value);
166             if (param_nid == NID_undef) {
167                 return 0;
168             }
169             for (; p->nid != NID_undef; p++) {
170                 if (p->nid == param_nid)
171                     break;
172             }
173             if (p->nid == NID_undef) {
174                 GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR, GOST_R_INVALID_PARAMSET);
175                 return 0;
176             }
177         }
178
179         return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
180                               param_nid, NULL);
181     }
182     return -2;
183 }
184
185 /* --------------------- key generation  --------------------------------*/
186
187 static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx)
188 {
189     return 1;
190 }
191
192 static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
193 {
194     struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
195     EC_KEY *ec = NULL;
196
197     if (data->sign_param_nid == NID_undef) {
198         GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
199         return 0;
200     }
201     if (!ec)
202         ec = EC_KEY_new();
203     if (!fill_GOST2001_params(ec, data->sign_param_nid)) {
204         EC_KEY_free(ec);
205         return 0;
206     }
207     EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec);
208     return 1;
209 }
210
211 /* Generates GOST_R3410 2001 key and assigns it using specified type */
212 static int pkey_gost01cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
213 {
214     EC_KEY *ec;
215     if (!pkey_gost01_paramgen(ctx, pkey))
216         return 0;
217     ec = EVP_PKEY_get0(pkey);
218     gost2001_keygen(ec);
219     return 1;
220 }
221
222 /* ----------- sign callbacks --------------------------------------*/
223 /*
224  * Packs signature according to Cryptopro rules
225  * and frees up DSA_SIG structure
226  */
227 int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
228 {
229     *siglen = 2 * order;
230     memset(sig, 0, *siglen);
231     store_bignum(s->s, sig, order);
232     store_bignum(s->r, sig + order, order);
233     DSA_SIG_free(s);
234     return 1;
235 }
236
237
238 static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
239                                size_t *siglen, const unsigned char *tbs,
240                                size_t tbs_len)
241 {
242     DSA_SIG *unpacked_sig = NULL;
243     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
244     if (!siglen)
245         return 0;
246     if (!sig) {
247         *siglen = 64;           /* better to check size of curve order */
248         return 1;
249     }
250     unpacked_sig = gost2001_do_sign(tbs, tbs_len, EVP_PKEY_get0(pkey));
251     if (!unpacked_sig) {
252         return 0;
253     }
254     return pack_sign_cp(unpacked_sig, 32, sig, siglen);
255 }
256
257 /* ------------------- verify callbacks ---------------------------*/
258 /* Unpack signature according to cryptopro rules  */
259 DSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen)
260 {
261     DSA_SIG *s;
262
263     s = DSA_SIG_new();
264     if (s == NULL) {
265         GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE);
266         return NULL;
267     }
268     s->s = BN_bin2bn(sig, siglen / 2, NULL);
269     s->r = BN_bin2bn(sig + siglen / 2, siglen / 2, NULL);
270     return s;
271 }
272
273
274 static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
275                                  size_t siglen, const unsigned char *tbs,
276                                  size_t tbs_len)
277 {
278     int ok = 0;
279     EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
280     DSA_SIG *s = unpack_cp_signature(sig, siglen);
281     if (!s)
282         return 0;
283 #ifdef DEBUG_SIGN
284     fprintf(stderr, "R=");
285     BN_print_fp(stderr, s->r);
286     fprintf(stderr, "\nS=");
287     BN_print_fp(stderr, s->s);
288     fprintf(stderr, "\n");
289 #endif
290     if (pub_key)
291         ok = gost2001_do_verify(tbs, tbs_len, s, EVP_PKEY_get0(pub_key));
292     DSA_SIG_free(s);
293     return ok;
294 }
295
296 /* ------------- encrypt init -------------------------------------*/
297 /* Generates ephermeral key */
298 static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
299 {
300     return 1;
301 }
302
303 /* --------------- Derive init ------------------------------------*/
304 static int pkey_gost_derive_init(EVP_PKEY_CTX *ctx)
305 {
306     return 1;
307 }
308
309 /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
310 static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
311 {
312     struct gost_mac_pmeth_data *data = OPENSSL_malloc(sizeof(*data));
313
314     if (!data)
315         return 0;
316     memset(data, 0, sizeof(*data));
317     EVP_PKEY_CTX_set_data(ctx, data);
318     return 1;
319 }
320
321 static void pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx)
322 {
323     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
324     OPENSSL_free(data);
325 }
326
327 static int pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
328 {
329     struct gost_mac_pmeth_data *dst_data, *src_data;
330     if (!pkey_gost_mac_init(dst)) {
331         return 0;
332     }
333     src_data = EVP_PKEY_CTX_get_data(src);
334     dst_data = EVP_PKEY_CTX_get_data(dst);
335     *dst_data = *src_data;
336     return 1;
337 }
338
339 static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
340 {
341     struct gost_mac_pmeth_data *data =
342         (struct gost_mac_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
343
344     switch (type) {
345     case EVP_PKEY_CTRL_MD:
346         {
347             if (EVP_MD_type((const EVP_MD *)p2) != NID_id_Gost28147_89_MAC) {
348                 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
349                         GOST_R_INVALID_DIGEST_TYPE);
350                 return 0;
351             }
352             data->md = (EVP_MD *)p2;
353             return 1;
354         }
355
356     case EVP_PKEY_CTRL_GET_MD:
357         *(const EVP_MD **)p2 = data->md;
358         return 1;
359
360     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
361     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
362     case EVP_PKEY_CTRL_PKCS7_SIGN:
363         return 1;
364     case EVP_PKEY_CTRL_SET_MAC_KEY:
365         if (p1 != 32) {
366             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH);
367             return 0;
368         }
369
370         memcpy(data->key, p2, 32);
371         data->key_set = 1;
372         return 1;
373     case EVP_PKEY_CTRL_DIGESTINIT:
374         {
375             EVP_MD_CTX *mctx = p2;
376             void *key;
377             if (!data->key_set) {
378                 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
379                 if (!pkey) {
380                     GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
381                             GOST_R_MAC_KEY_NOT_SET);
382                     return 0;
383                 }
384                 key = EVP_PKEY_get0(pkey);
385                 if (!key) {
386                     GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
387                             GOST_R_MAC_KEY_NOT_SET);
388                     return 0;
389                 }
390             } else {
391                 key = &(data->key);
392             }
393             return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32, key);
394         }
395     }
396     return -2;
397 }
398
399 static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
400                                   const char *type, const char *value)
401 {
402     if (strcmp(type, key_ctrl_string) == 0) {
403         if (strlen(value) != 32) {
404             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
405                     GOST_R_INVALID_MAC_KEY_LENGTH);
406             return 0;
407         }
408         return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
409                                   32, (char *)value);
410     }
411     if (strcmp(type, hexkey_ctrl_string) == 0) {
412         long keylen;
413         int ret;
414         unsigned char *keybuf = string_to_hex(value, &keylen);
415         if (!keybuf || keylen != 32) {
416             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
417                     GOST_R_INVALID_MAC_KEY_LENGTH);
418             OPENSSL_free(keybuf);
419             return 0;
420         }
421         ret = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, keybuf);
422         OPENSSL_free(keybuf);
423         return ret;
424
425     }
426     return -2;
427 }
428
429 static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
430 {
431     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
432     unsigned char *keydata;
433     if (!data->key_set) {
434         GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET);
435         return 0;
436     }
437     keydata = OPENSSL_malloc(32);
438     if (keydata == NULL)
439         return 0;
440     memcpy(keydata, data->key, 32);
441     EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata);
442     return 1;
443 }
444
445 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
446 {
447     return 1;
448 }
449
450 static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
451                                  size_t *siglen, EVP_MD_CTX *mctx)
452 {
453     unsigned int tmpsiglen = *siglen; /* for platforms where
454                                        * sizeof(int)!=sizeof(size_t) */
455     int ret;
456     if (!sig) {
457         *siglen = 4;
458         return 1;
459     }
460     ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
461     *siglen = tmpsiglen;
462     return ret;
463 }
464
465 /* ----------------------------------------------------------------*/
466 int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags)
467 {
468     *pmeth = EVP_PKEY_meth_new(id, flags);
469     if (!*pmeth)
470         return 0;
471
472     switch (id) {
473     case NID_id_GostR3410_2001:
474         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_ctrl, pkey_gost_ctrl01_str);
475         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
476         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
477
478         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cp_keygen);
479
480         EVP_PKEY_meth_set_encrypt(*pmeth,
481                                   pkey_gost_encrypt_init,
482                                   pkey_GOST01cp_encrypt);
483         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
484         EVP_PKEY_meth_set_derive(*pmeth,
485                                  pkey_gost_derive_init, pkey_gost2001_derive);
486         EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,
487                                    pkey_gost01_paramgen);
488         break;
489     case NID_id_Gost28147_89_MAC:
490         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl,
491                                pkey_gost_mac_ctrl_str);
492         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init,
493                                   pkey_gost_mac_signctx);
494         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen);
495         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init);
496         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
497         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
498         return 1;
499     default:                   /* Unsupported method */
500         return 0;
501     }
502     EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
503     EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);
504
505     EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy);
506     /*
507      * FIXME derive etc...
508      */
509
510     return 1;
511 }