1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Implementation of RFC 4357 (GOST R 34.10) Publick key method *
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 */
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)
24 struct gost_pmeth_data *data;
25 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
27 data = OPENSSL_malloc(sizeof(*data));
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)));
42 EVP_PKEY_CTX_set_data(ctx, data);
46 /* Copies contents of gost_pmeth_data structure */
47 static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
49 struct gost_pmeth_data *dst_data, *src_data;
50 if (!pkey_gost_init(dst)) {
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;
62 /* Frees up gost_pmeth_data structure */
63 static void pkey_gost_cleanup(EVP_PKEY_CTX *ctx)
65 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
67 OPENSSL_free(data->shared_ukm);
71 /* --------------------- control functions ------------------------------*/
72 static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
74 struct gost_pmeth_data *pctx =
75 (struct gost_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
77 case EVP_PKEY_CTRL_MD:
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);
83 pctx->md = (EVP_MD *)p2;
87 case EVP_PKEY_CTRL_GET_MD:
88 *(const EVP_MD **)p2 = pctx->md;
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:
102 case EVP_PKEY_CTRL_GOST_PARAMSET:
103 pctx->sign_param_nid = (int)p1;
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);
111 memcpy(pctx->shared_ukm, p2, (int)p1);
113 case EVP_PKEY_CTRL_PEER_KEY:
114 if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
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);
125 static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
126 const char *type, const char *value)
130 if (strcmp(type, param_ctrl_string) == 0) {
134 if (strlen(value) == 1) {
135 switch (toupper((unsigned char)value[0])) {
137 param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet;
140 param_nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet;
143 param_nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet;
146 param_nid = NID_id_GostR3410_2001_TestParamSet;
151 } else if ((strlen(value) == 2)
152 && (toupper((unsigned char)value[0]) == 'X')) {
153 switch (toupper((unsigned char)value[1])) {
155 param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet;
158 param_nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet;
164 R3410_2001_params *p = R3410_2001_paramset;
165 param_nid = OBJ_txt2nid(value);
166 if (param_nid == NID_undef) {
169 for (; p->nid != NID_undef; p++) {
170 if (p->nid == param_nid)
173 if (p->nid == NID_undef) {
174 GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR, GOST_R_INVALID_PARAMSET);
179 return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
185 /* --------------------- key generation --------------------------------*/
187 static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx)
192 static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
194 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
197 if (data->sign_param_nid == NID_undef) {
198 GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
203 if (!fill_GOST2001_params(ec, data->sign_param_nid)) {
207 EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec);
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)
215 if (!pkey_gost01_paramgen(ctx, pkey))
217 ec = EVP_PKEY_get0(pkey);
222 /* ----------- sign callbacks --------------------------------------*/
224 * Packs signature according to Cryptopro rules
225 * and frees up DSA_SIG structure
227 int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
230 memset(sig, 0, *siglen);
231 store_bignum(s->s, sig, order);
232 store_bignum(s->r, sig + order, order);
238 static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
239 size_t *siglen, const unsigned char *tbs,
242 DSA_SIG *unpacked_sig = NULL;
243 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
247 *siglen = 64; /* better to check size of curve order */
250 unpacked_sig = gost2001_do_sign(tbs, tbs_len, EVP_PKEY_get0(pkey));
254 return pack_sign_cp(unpacked_sig, 32, sig, siglen);
257 /* ------------------- verify callbacks ---------------------------*/
258 /* Unpack signature according to cryptopro rules */
259 DSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen)
265 GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE);
268 s->s = BN_bin2bn(sig, siglen / 2, NULL);
269 s->r = BN_bin2bn(sig + siglen / 2, siglen / 2, NULL);
274 static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
275 size_t siglen, const unsigned char *tbs,
279 EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
280 DSA_SIG *s = unpack_cp_signature(sig, siglen);
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");
291 ok = gost2001_do_verify(tbs, tbs_len, s, EVP_PKEY_get0(pub_key));
296 /* ------------- encrypt init -------------------------------------*/
297 /* Generates ephermeral key */
298 static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
303 /* --------------- Derive init ------------------------------------*/
304 static int pkey_gost_derive_init(EVP_PKEY_CTX *ctx)
309 /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
310 static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
312 struct gost_mac_pmeth_data *data = OPENSSL_malloc(sizeof(*data));
316 memset(data, 0, sizeof(*data));
317 EVP_PKEY_CTX_set_data(ctx, data);
321 static void pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx)
323 struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
327 static int pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
329 struct gost_mac_pmeth_data *dst_data, *src_data;
330 if (!pkey_gost_mac_init(dst)) {
333 src_data = EVP_PKEY_CTX_get_data(src);
334 dst_data = EVP_PKEY_CTX_get_data(dst);
335 *dst_data = *src_data;
339 static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
341 struct gost_mac_pmeth_data *data =
342 (struct gost_mac_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
345 case EVP_PKEY_CTRL_MD:
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);
352 data->md = (EVP_MD *)p2;
356 case EVP_PKEY_CTRL_GET_MD:
357 *(const EVP_MD **)p2 = data->md;
360 case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
361 case EVP_PKEY_CTRL_PKCS7_DECRYPT:
362 case EVP_PKEY_CTRL_PKCS7_SIGN:
364 case EVP_PKEY_CTRL_SET_MAC_KEY:
366 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH);
370 memcpy(data->key, p2, 32);
373 case EVP_PKEY_CTRL_DIGESTINIT:
375 EVP_MD_CTX *mctx = p2;
377 if (!data->key_set) {
378 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
380 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
381 GOST_R_MAC_KEY_NOT_SET);
384 key = EVP_PKEY_get0(pkey);
386 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
387 GOST_R_MAC_KEY_NOT_SET);
393 return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32, key);
399 static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
400 const char *type, const char *value)
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);
408 return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
411 if (strcmp(type, hexkey_ctrl_string) == 0) {
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);
421 ret = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, keybuf);
422 OPENSSL_free(keybuf);
429 static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
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);
437 keydata = OPENSSL_malloc(32);
440 memcpy(keydata, data->key, 32);
441 EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata);
445 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
450 static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
451 size_t *siglen, EVP_MD_CTX *mctx)
453 unsigned int tmpsiglen = *siglen; /* for platforms where
454 * sizeof(int)!=sizeof(size_t) */
460 ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
465 /* ----------------------------------------------------------------*/
466 int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags)
468 *pmeth = EVP_PKEY_meth_new(id, flags);
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);
478 EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cp_keygen);
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);
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);
499 default: /* Unsupported method */
502 EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
503 EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);
505 EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy);
507 * FIXME derive etc...