X-Git-Url: http://wagner.pp.ru/gitweb/?a=blobdiff_plain;f=gost_pmeth.c;h=a29e5f08cb5860644811396c83a0010de43fc4b0;hb=14e654cab19089027b00733594480eb03d8c6da5;hp=e87c5197d7e997a7885fd63651b56eecc3d7a533;hpb=cba16944bff9d8c5dcf37be641822cd3de6d2ec1;p=openssl-gost%2Fengine.git diff --git a/gost_pmeth.c b/gost_pmeth.c index e87c519..a29e5f0 100644 --- a/gost_pmeth.c +++ b/gost_pmeth.c @@ -10,11 +10,11 @@ #include #include #include +#include #include /* For string_to_hex */ #include #include #include -#include "gost_params.h" #include "gost_lcl.h" #include "e_gost_err.h" @@ -24,15 +24,13 @@ static int pkey_gost_init(EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); - data = OPENSSL_malloc(sizeof(struct gost_pmeth_data)); + + data = OPENSSL_malloc(sizeof(*data)); if (!data) return 0; - memset(data, 0, sizeof(struct gost_pmeth_data)); + memset(data, 0, sizeof(*data)); if (pkey && EVP_PKEY_get0(pkey)) { switch (EVP_PKEY_base_id(pkey)) { - case NID_id_GostR3410_94: - data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey)); - break; case NID_id_GostR3410_2001: case NID_id_GostR3410_2012_256: case NID_id_GostR3410_2012_512: @@ -79,8 +77,7 @@ static void pkey_gost_cleanup(EVP_PKEY_CTX *ctx) struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); if (!data) return; - if (data->shared_ukm) - OPENSSL_free(data->shared_ukm); + OPENSSL_free(data->shared_ukm); OPENSSL_free(data); } @@ -149,8 +146,10 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_SET_IV: OPENSSL_assert(p2 != NULL); pctx->shared_ukm = OPENSSL_malloc((int)p1); - if (!pctx->shared_ukm) + if (pctx->shared_ukm == NULL) { + GOSTerr(GOST_F_PKEY_GOST_CTRL, ERR_R_MALLOC_FAILURE); return 0; + } memcpy(pctx->shared_ukm, p2, (int)p1); return 1; case EVP_PKEY_CTRL_PEER_KEY: @@ -167,73 +166,12 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return -2; } -static int pkey_gost94_ctrl_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) -{ - int param_nid = 0; - if (!strcmp(type, param_ctrl_string)) { - if (!value) { - return 0; - } - if (strlen(value) == 1) { - switch (toupper((unsigned char)value[0])) { - case 'A': - param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet; - break; - case 'B': - param_nid = NID_id_GostR3410_94_CryptoPro_B_ParamSet; - break; - case 'C': - param_nid = NID_id_GostR3410_94_CryptoPro_C_ParamSet; - break; - case 'D': - param_nid = NID_id_GostR3410_94_CryptoPro_D_ParamSet; - break; - default: - return 0; - } - } else if ((strlen(value) == 2) - && (toupper((unsigned char)value[0]) == 'X')) { - switch (toupper((unsigned char)value[1])) { - case 'A': - param_nid = NID_id_GostR3410_94_CryptoPro_XchA_ParamSet; - break; - case 'B': - param_nid = NID_id_GostR3410_94_CryptoPro_XchB_ParamSet; - break; - case 'C': - param_nid = NID_id_GostR3410_94_CryptoPro_XchC_ParamSet; - break; - default: - return 0; - } - } else { - R3410_params *p = R3410_paramset; - param_nid = OBJ_txt2nid(value); - if (param_nid == NID_undef) { - return 0; - } - for (; p->nid != NID_undef; p++) { - if (p->nid == param_nid) - break; - } - if (p->nid == NID_undef) { - GOSTerr(GOST_F_PKEY_GOST94_CTRL_STR, GOST_R_INVALID_PARAMSET); - return 0; - } - } - - return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, - param_nid, NULL); - } - return -2; -} - static int pkey_gost_ec_ctrl_str_256(EVP_PKEY_CTX *ctx, const char *type, const char *value) { int param_nid = 0; - if (!strcmp(type, param_ctrl_string)) { + + if (strcmp(type, param_ctrl_string) == 0) { if (!value) { return 0; } @@ -339,30 +277,13 @@ static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx) return 1; } -static int pkey_gost94_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) -{ - struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); - DSA *dsa = NULL; - if (!data || data->sign_param_nid == NID_undef) { - GOSTerr(GOST_F_PKEY_GOST94_PARAMGEN, GOST_R_NO_PARAMETERS_SET); - return 0; - } - dsa = DSA_new(); - if (!fill_GOST94_params(dsa, data->sign_param_nid) - || !EVP_PKEY_assign(pkey, NID_id_GostR3410_94, dsa)) { - DSA_free(dsa); - return 0; - } - return 1; -} - static int pkey_gost2001_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); EC_KEY *ec = NULL; if (!data || data->sign_param_nid == NID_undef) { - GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET); + GOSTerr(GOST_F_PKEY_GOST2001_PARAMGEN, GOST_R_NO_PARAMETERS_SET); return 0; } @@ -382,7 +303,7 @@ static int pkey_gost2012_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) int result = 0; if (!data || data->sign_param_nid == NID_undef) { - GOSTerr(GOST_F_PKEY_GOST12_PARAMGEN, GOST_R_NO_PARAMETERS_SET); + GOSTerr(GOST_F_PKEY_GOST2012_PARAMGEN, GOST_R_NO_PARAMETERS_SET); return 0; } @@ -420,17 +341,6 @@ static int pkey_gost2012_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) } /* ----------- keygen callbacks --------------------------------------*/ -/* Generates Gost_R3410_94_cp key */ -static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) -{ - DSA *dsa; - if (!pkey_gost94_paramgen(ctx, pkey)) - return 0; - dsa = EVP_PKEY_get0(pkey); - gost_sign_keygen(dsa); - return 1; -} - /* Generates GOST_R3410 2001 key and assigns it using specified type */ static int pkey_gost2001cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { @@ -453,24 +363,20 @@ static int pkey_gost2012cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) } /* ----------- sign callbacks --------------------------------------*/ - -static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, - size_t *siglen, const unsigned char *tbs, - size_t tbs_len) +/* + * Packs signature according to Cryptopro rules + * and frees up DSA_SIG structure + */ +int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen) { - DSA_SIG *unpacked_sig = NULL; - EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); - if (!siglen) - return 0; - if (!sig) { - *siglen = 64; /* better to check size of pkey->pkey.dsa-q */ - return 1; - } - unpacked_sig = gost_do_sign(tbs, tbs_len, EVP_PKEY_get0(pkey)); - if (!unpacked_sig) { - return 0; - } - return pack_sign_cp(unpacked_sig, 32, sig, siglen); + const BIGNUM *sig_r = NULL, *sig_s = NULL; + DSA_SIG_get0(s, &sig_r, &sig_s); + *siglen = 2 * order; + memset(sig, 0, *siglen); + store_bignum(sig_s, sig, order); + store_bignum(sig_r, sig + order, order); + DSA_SIG_free(s); + return 1; } static int pkey_gost_ec_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, @@ -510,20 +416,21 @@ static int pkey_gost_ec_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, } /* ------------------- verify callbacks ---------------------------*/ - -static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, - size_t siglen, const unsigned char *tbs, - size_t tbs_len) +/* Unpack signature according to cryptopro rules */ +DSA_SIG *unpack_cp_signature(const unsigned char *sigbuf, size_t siglen) { - int ok = 0; - EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx); - DSA_SIG *s = (sig) ? unpack_cp_signature(sig, siglen) : NULL; - if (!s) - return 0; - if (pub_key) - ok = gost_do_verify(tbs, tbs_len, s, EVP_PKEY_get0(pub_key)); - DSA_SIG_free(s); - return ok; + DSA_SIG *sig; + BIGNUM *r = NULL, *s = NULL; + + sig = DSA_SIG_new(); + if (sig == NULL) { + GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE); + return NULL; + } + s = BN_bin2bn(sigbuf, siglen / 2, NULL); + r = BN_bin2bn(sigbuf + siglen / 2, siglen / 2, NULL); + DSA_SIG_set0(sig, r, s); + return sig; } static int pkey_gost_ec_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, @@ -564,11 +471,23 @@ static int pkey_gost_derive_init(EVP_PKEY_CTX *ctx) /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/ static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx) { - struct gost_mac_pmeth_data *data; - data = OPENSSL_malloc(sizeof(struct gost_mac_pmeth_data)); + struct gost_mac_pmeth_data *data = OPENSSL_malloc(sizeof(*data)); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); + if (!data) return 0; - memset(data, 0, sizeof(struct gost_mac_pmeth_data)); + memset(data, 0, sizeof(*data)); + data->mac_size = 4; + data->mac_param_nid = NID_undef; + + if (pkey) { + struct gost_mac_key *key = EVP_PKEY_get0(pkey); + if (key) { + data->mac_param_nid = key->mac_param_nid; + data->mac_size = key->mac_size; + } + } + EVP_PKEY_CTX_set_data(ctx, data); return 1; } @@ -604,7 +523,8 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_MD: { int nid = EVP_MD_type((const EVP_MD *)p2); - if (nid != NID_id_Gost28147_89_MAC && nid != NID_gost_mac_12) { + if (nid != NID_id_Gost28147_89_MAC && nid != NID_gost_mac_12 + && nid != NID_magma_mac && nid != NID_grasshopper_mac) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_DIGEST_TYPE); return 0; @@ -612,7 +532,6 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) data->md = (EVP_MD *)p2; return 1; } - break; case EVP_PKEY_CTRL_GET_MD: *(const EVP_MD **)p2 = data->md; @@ -631,10 +550,16 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) memcpy(data->key, p2, 32); data->key_set = 1; return 1; + case EVP_PKEY_CTRL_GOST_PARAMSET: + { + struct gost_cipher_info *param = p2; + data->mac_param_nid = param->nid; + return 1; + } case EVP_PKEY_CTRL_DIGESTINIT: { EVP_MD_CTX *mctx = p2; - void *key; + struct gost_mac_key *key; if (!data->key_set) { EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); if (!pkey) { @@ -648,10 +573,22 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) GOST_R_MAC_KEY_NOT_SET); return 0; } + return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx)) + (mctx, EVP_MD_CTRL_SET_KEY, 0, key); } else { - key = &(data->key); + return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx)) + (mctx, EVP_MD_CTRL_SET_KEY, 32, &(data->key)); } - return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32, key); + } + case EVP_PKEY_CTRL_MAC_LEN: + { + if (p1 < 1 || p1 > 8) { + + GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_SIZE); + return 0; + } + data->mac_size = p1; + return 1; } } return -2; @@ -660,7 +597,7 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { - if (!strcmp(type, key_ctrl_string)) { + if (strcmp(type, key_ctrl_string) == 0) { if (strlen(value) != 32) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_KEY_LENGTH); @@ -669,8 +606,8 @@ static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, (char *)value); } - if (!strcmp(type, hexkey_ctrl_string)) { - long keylen = 0; + if (strcmp(type, hexkey_ctrl_string) == 0) { + long keylen; int ret; unsigned char *keybuf = string_to_hex(value, &keylen); if (!keybuf || keylen != 32) { @@ -684,6 +621,34 @@ static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, return ret; } + if (!strcmp(type, maclen_ctrl_string)) { + char *endptr; + long size = strtol(value, &endptr, 10); + if (*endptr != '\0') { + GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_SIZE); + return 0; + } + return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN, size, NULL); + } + if (strcmp(type, param_ctrl_string) == 0) { + ASN1_OBJECT *obj = OBJ_txt2obj(value, 0); + const struct gost_cipher_info *param = NULL; + if (obj == NULL) { + GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_PARAMS); + return 0; + } + + param = get_encryption_params(obj); + ASN1_OBJECT_free(obj); + if (param == NULL) { + GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_PARAMS); + return 0; + } + + + return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, 0, + (void *)param); + } return -2; } @@ -691,15 +656,17 @@ static int pkey_gost_mac_keygen_base(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey, int mac_nid) { struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); - unsigned char *keydata; + struct gost_mac_key *keydata; if (!data || !data->key_set) { - GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET); + GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN_BASE, GOST_R_MAC_KEY_NOT_SET); return 0; } - keydata = OPENSSL_malloc(32); - if (!keydata) + keydata = OPENSSL_malloc(sizeof(struct gost_mac_key)); + if (keydata == NULL) return 0; - memcpy(keydata, data->key, 32); + memcpy(keydata->key, data->key, 32); + keydata->mac_param_nid = data->mac_param_nid; + keydata->mac_size = data->mac_size; EVP_PKEY_assign(pkey, mac_nid, keydata); return 1; } @@ -716,6 +683,18 @@ static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) { + struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); + + if (data == NULL) { + pkey_gost_mac_init(ctx); + } + + data = EVP_PKEY_CTX_get_data(ctx); + if (!data) { + GOSTerr(GOST_F_PKEY_GOST_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET); + return 0; + } + return 1; } @@ -724,6 +703,7 @@ static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, { unsigned int tmpsiglen; int ret; + struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); if (!siglen) return 0; @@ -731,11 +711,14 @@ static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, * sizeof(size_t) */ if (!sig) { - *siglen = 4; + *siglen = data->mac_size; return 1; } + + EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx)) + (mctx, EVP_MD_CTRL_MAC_LEN, data->mac_size, NULL); ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen); - *siglen = tmpsiglen; + *siglen = data->mac_size; return ret; } @@ -747,20 +730,6 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags) return 0; switch (id) { - case NID_id_GostR3410_94: - EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_ctrl, pkey_gost94_ctrl_str); - EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost94cp_keygen); - EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cp_sign); - EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cp_verify); - EVP_PKEY_meth_set_encrypt(*pmeth, - pkey_gost_encrypt_init, - pkey_GOST94cp_encrypt); - EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt); - EVP_PKEY_meth_set_derive(*pmeth, - pkey_gost_derive_init, pkey_gost94_derive); - EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init, - pkey_gost94_paramgen); - break; case NID_id_GostR3410_2001: EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_ctrl, pkey_gost_ec_ctrl_str_256); @@ -834,6 +803,28 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags) EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup); EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy); return 1; +/* TODO + case NID_magma_mac: + EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl, + pkey_gost_mac_ctrl_str); + EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init, + pkey_gost_mac_signctx); + EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen_12); + EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init); + EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup); + EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy); + return 1; + case NID_grasshopper_mac: + EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl, + pkey_gost_mac_ctrl_str); + EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init, + pkey_gost_mac_signctx); + EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen_12); + EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init); + EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup); + EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy); + return 1; +*/ default: /* Unsupported method */ return 0; }