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