* for OpenSSL *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
-#include <string.h>
+#include <openssl/asn1.h>
+#ifndef OPENSSL_NO_CMS
+#include <openssl/cms.h>
+#endif
#include "gost_params.h"
#include "gost_lcl.h"
#include "e_gost_err.h"
ASN1_STRING *params = ASN1_STRING_new();
GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
int pkey_param_nid = NID_undef;
- int cipher_param_nid = NID_undef;
+
if (!params || !gkp)
{
GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
}
switch (EVP_PKEY_base_id(key))
{
- case NID_id_GostR3410_2001_cc:
- pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
- cipher_param_nid = NID_id_Gost28147_89_cc;
- break;
- case NID_id_GostR3410_94_cc:
- pkey_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
- cipher_param_nid = NID_id_Gost28147_89_cc;
- break;
case NID_id_GostR3410_2001:
pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
- cipher_param_nid = get_encryption_params(NULL)->nid;
break;
case NID_id_GostR3410_94:
pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
params=NULL;
goto err;
}
- cipher_param_nid = get_encryption_params(NULL)->nid;
break;
}
gkp->key_params = OBJ_nid2obj(pkey_param_nid);
ASN1_OBJECT *palg_obj =NULL;
int ptype = V_ASN1_UNDEF;
int pkey_nid = NID_undef,param_nid = NID_undef;
+ void *_pval;
ASN1_STRING *pval = NULL;
const unsigned char *p;
GOST_KEY_PARAMS *gkp = NULL;
- X509_ALGOR_get0(&palg_obj, &ptype, (void **) (&pval), palg);
+ X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
+ pval = _pval;
if (ptype != V_ASN1_SEQUENCE)
{
GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
{
GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
+ return 0;
}
param_nid = OBJ_obj2nid(gkp->key_params);
GOST_KEY_PARAMS_free(gkp);
switch (pkey_nid)
{
case NID_id_GostR3410_94:
- case NID_id_GostR3410_94_cc:
{
DSA *dsa= EVP_PKEY_get0(pkey);
if (!dsa)
break;
}
case NID_id_GostR3410_2001:
- case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94:
- case NID_id_GostR3410_94_cc:
{
DSA *dsa = EVP_PKEY_get0(pkey);
if (!dsa)
break;
}
case NID_id_GostR3410_2001:
- case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
}
return 1;
}
-BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
+BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey)
{
switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94:
- case NID_id_GostR3410_94_cc:
{
DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
if (!dsa)
return NULL;
}
if (!dsa->priv_key) return NULL;
- return BN_dup(dsa->priv_key);
+ return dsa->priv_key;
break;
}
case NID_id_GostR3410_2001:
- case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
const BIGNUM* priv;
return NULL;
}
if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
- return BN_dup(priv);
+ return (BIGNUM *)priv;
break;
}
}
X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
}
return 1;
+#ifndef OPENSSL_NO_CMS
+ case ASN1_PKEY_CTRL_CMS_SIGN:
+ if (arg1 == 0)
+ {
+ X509_ALGOR *alg1 = NULL, *alg2 = NULL;
+ int nid = EVP_PKEY_base_id(pkey);
+ CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
+ NULL, NULL, &alg1, &alg2);
+ X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
+ V_ASN1_NULL, 0);
+ if (nid == NID_undef)
+ {
+ return (-1);
+ }
+ X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
+ }
+ return 1;
+#endif
case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
if (arg1 == 0)
{
V_ASN1_SEQUENCE, params);
}
return 1;
+#ifndef OPENSSL_NO_CMS
+ case ASN1_PKEY_CTRL_CMS_ENVELOPE:
+ if (arg1 == 0)
+ {
+ X509_ALGOR *alg;
+ ASN1_STRING * params = encode_gost_algor_params(pkey);
+ if (!params)
+ {
+ return -1;
+ }
+ CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL, NULL, &alg);
+ X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
+ V_ASN1_SEQUENCE, params);
+ }
+ return 1;
+#endif
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
*(int *)arg2 = NID_id_GostR3411_94;
return 2;
ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL,&p,priv_len);
if (!s||s->length !=32)
{
- GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
+ GOSTerr(GOST_F_PRIV_DECODE_GOST,
EVP_R_DECODE_ERROR);
return 0;
}
else
{
priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len);
- if (!priv_key || !(pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)))
+ if (!priv_key) return 0;
+ ret= ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL))!=NULL) ;
+ ASN1_INTEGER_free(priv_key);
+ if (!ret)
{
- GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
+ GOSTerr(GOST_F_PRIV_DECODE_GOST,
EVP_R_DECODE_ERROR);
return 0;
}
ASN1_STRING *params = encode_gost_algor_params(pk);
unsigned char *priv_buf = NULL;
int priv_len;
- BIGNUM *key;
ASN1_INTEGER *asn1key=NULL;
if (!params)
{
return 0;
}
- key = gost_get_priv_key(pk);
- asn1key = BN_to_ASN1_INTEGER(key,NULL);
- BN_free(key);
+ asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk),NULL);
priv_len = i2d_ASN1_INTEGER(asn1key,&priv_buf);
ASN1_INTEGER_free(asn1key);
return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params,
priv_buf,priv_len);
}
+/* --------- printing keys --------------------------------*/
+static int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx, int type)
+ {
+ int param_nid = NID_undef;
+
+ if (type == 2)
+ {
+ BIGNUM *key;
-static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent,
+ if (!BIO_indent(out,indent,128)) return 0;
+ BIO_printf(out,"Private key: ");
+ key = gost_get0_priv_key(pkey);
+ if (!key)
+ BIO_printf(out,"<undefined>");
+ else
+ BN_print(out,key);
+ BIO_printf(out,"\n");
+ }
+ if (type >= 1)
+ {
+ BIGNUM *pubkey;
+
+ pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
+ BIO_indent(out,indent,128);
+ BIO_printf(out,"Public key: ");
+ BN_print(out,pubkey);
+ BIO_printf(out,"\n");
+ }
+
+ param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
+ BIO_indent(out,indent,128);
+ BIO_printf(out, "Parameter set: %s\n",OBJ_nid2ln(param_nid));
+ return 1;
+}
+
+static int param_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx)
+ {
+ return print_gost_94(out, pkey, indent, pctx,0);
+ }
+
+static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx)
+ {
+ return print_gost_94(out,pkey, indent, pctx,1);
+ }
+static int priv_print_gost94(BIO *out,const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx)
{
- BIGNUM *key;
+ return print_gost_94(out,pkey,indent,pctx,2);
+ }
+
+static int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx, int type)
+ {
+ int param_nid = NID_undef;
+ if (type == 2)
+ {
+ BIGNUM *key;
+
+ if (!BIO_indent(out,indent,128)) return 0;
+ BIO_printf(out,"Private key: ");
+ key = gost_get0_priv_key(pkey);
+ if (!key)
+ BIO_printf(out,"<undefined)");
+ else
+ BN_print(out,key);
+ BIO_printf(out,"\n");
+ }
+ if (type >= 1)
+ {
+ BN_CTX *ctx = BN_CTX_new();
+ BIGNUM *X,*Y;
+ const EC_POINT *pubkey;
+ const EC_GROUP *group;
+
+ if (!ctx)
+ {
+ GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ BN_CTX_start(ctx);
+ X = BN_CTX_get(ctx);
+ Y = BN_CTX_get(ctx);
+ pubkey = EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
+ group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
+ if (!EC_POINT_get_affine_coordinates_GFp(group,pubkey,X,Y,ctx))
+ {
+ GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_EC_LIB);
+ BN_CTX_free(ctx);
+ return 0;
+ }
+ if (!BIO_indent(out,indent,128)) return 0;
+ BIO_printf(out,"Public key:\n");
+ if (!BIO_indent(out,indent+3,128)) return 0;
+ BIO_printf(out,"X:");
+ BN_print(out,X);
+ BIO_printf(out,"\n");
+ BIO_indent(out,indent+3,128);
+ BIO_printf(out,"Y:");
+ BN_print(out,Y);
+ BIO_printf(out,"\n");
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+
+ param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
if (!BIO_indent(out,indent,128)) return 0;
- key = gost_get_priv_key(pkey);
- if (!key) return 0;
- BN_print(out,key);
- BN_free(key);
+ BIO_printf(out,"Parameter set: %s\n",OBJ_nid2ln(param_nid));
return 1;
+}
+static int param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx)
+ {
+ return print_gost_01(out,pkey,indent,pctx,0);
+ }
+static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx)
+ {
+ return print_gost_01(out,pkey, indent, pctx,1);
+ }
+static int priv_print_gost01(BIO *out,const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx)
+ {
+ return print_gost_01(out,pkey,indent,pctx,2);
}
-
/* ---------------------------------------------------------------------*/
static int param_missing_gost94(const EVP_PKEY *pk)
{
}
if (!efrom)
{
- GOSTerr(GOST_F_PARAM_COPY_GOST94,
+ GOSTerr(GOST_F_PARAM_COPY_GOST01,
GOST_R_KEY_PARAMETERS_MISSING);
return 0;
}
eto = EC_KEY_new();
EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
}
- EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom)));
+ EC_KEY_set_group(eto,EC_KEY_get0_group(efrom));
if (EC_KEY_get0_private_key(eto))
{
gost2001_compute_public(eto);
EC_POINT *pub_key;
BIGNUM *X,*Y;
ASN1_OCTET_STRING *octet= NULL;
+ int len;
const EC_GROUP *group;
if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
if (!octet)
{
- GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE);
+ GOSTerr(GOST_F_PUB_DECODE_GOST01,ERR_R_MALLOC_FAILURE);
return 0;
}
databuf = OPENSSL_malloc(octet->length);
{
databuf[j]=octet->data[i];
}
- if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc)
- {
- X= getbnfrombuf(databuf,octet->length/2);
- Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
- }
- else
- {
- Y= getbnfrombuf(databuf,octet->length/2);
- X= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
- }
+ len=octet->length/2;
+ ASN1_OCTET_STRING_free(octet);
+
+ Y= getbnfrombuf(databuf,len);
+ X= getbnfrombuf(databuf+len,len);
OPENSSL_free(databuf);
pub_key = EC_POINT_new(group);
if (!EC_POINT_set_affine_coordinates_GFp(group
{
GOSTerr(GOST_F_PUB_DECODE_GOST01,
ERR_R_EC_LIB);
+ EC_POINT_free(pub_key);
+ BN_free(X);
+ BN_free(Y);
return 0;
}
BN_free(X);
{
GOSTerr(GOST_F_PUB_DECODE_GOST01,
ERR_R_EC_LIB);
+ EC_POINT_free(pub_key);
return 0;
}
- /*EC_POINT_free(pub_key);*/
+ EC_POINT_free(pub_key);
return 1;
}
BN_free(order);
databuf = OPENSSL_malloc(data_len);
memset(databuf,0,data_len);
- if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc)
- {
- store_bignum(X,databuf,data_len/2);
- store_bignum(Y,databuf+data_len/2,data_len/2);
- }
- else
- {
- store_bignum(X,databuf+data_len/2,data_len/2);
- store_bignum(Y,databuf,data_len/2);
- }
+
+ store_bignum(X,databuf+data_len/2,data_len/2);
+ store_bignum(Y,databuf,data_len/2);
+
BN_free(X);
BN_free(Y);
octet = ASN1_OCTET_STRING_new();
return ret;
}
-static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx)
- {
- const BIGNUM *key;
- if (!BIO_indent(out,indent,128)) return 0;
- key = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
- if (!key) return 0;
- BN_print(out,key);
- return 1;
- }
-static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx)
- {
- return 0;
- }
+
static int pkey_size_gost(const EVP_PKEY *pk)
{
{
return 256;
}
+/*------------------------ ASN1 METHOD for GOST MAC -------------------*/
+static void mackey_free_gost(EVP_PKEY *pk)
+ {
+ if (pk->pkey.ptr) {
+ OPENSSL_free(pk->pkey.ptr);
+ }
+ }
+static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+ switch (op)
+ {
+ case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+ *(int *)arg2 = NID_id_Gost28147_89_MAC;
+ return 2;
+ }
+ return -2;
+}
+
+static int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
+{
+ int nid=gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
+ return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
+}
+static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
+{
+ int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
+ return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
+}
+
+static int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
+{
+ ASN1_OBJECT *obj=NULL;
+ DSA *dsa = EVP_PKEY_get0(pkey);
+ int nid;
+ if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
+ return 0;
+ }
+ nid = OBJ_obj2nid(obj);
+ ASN1_OBJECT_free(obj);
+ if (!dsa)
+ {
+ dsa=DSA_new();
+ if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa)) return 0;
+ }
+ if (!fill_GOST94_params(dsa,nid)) return 0;
+ return 1;
+}
+
+static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+ ASN1_OBJECT *obj=NULL;
+ int nid;
+ EC_KEY *ec = EVP_PKEY_get0(pkey);
+ if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
+ return 0;
+ }
+ nid = OBJ_obj2nid(obj);
+ ASN1_OBJECT_free(obj);
+ if (!ec)
+ {
+ ec = EC_KEY_new();
+ if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec)) return 0;
+ }
+ if (!fill_GOST2001_params(ec, nid)) return 0;
+ return 1;
+}
+
+
+
+
/* ----------------------------------------------------------------------*/
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info)
if (!*ameth) return 0;
switch (nid)
{
- case NID_id_GostR3410_94_cc:
case NID_id_GostR3410_94:
EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94);
EVP_PKEY_asn1_set_private (*ameth,
priv_decode_gost, priv_encode_gost,
- priv_print_gost);
+ priv_print_gost94);
- EVP_PKEY_asn1_set_param (*ameth, 0, 0,
+ EVP_PKEY_asn1_set_param (*ameth,
+ gost94_param_decode, gost94_param_encode,
param_missing_gost94, param_copy_gost94,
- param_cmp_gost94,0 );
+ param_cmp_gost94,param_print_gost94 );
EVP_PKEY_asn1_set_public (*ameth,
pub_decode_gost94, pub_encode_gost94,
pub_cmp_gost94, pub_print_gost94,
EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
break;
- case NID_id_GostR3410_2001_cc:
case NID_id_GostR3410_2001:
EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
EVP_PKEY_asn1_set_private (*ameth,
priv_decode_gost, priv_encode_gost,
- priv_print_gost);
+ priv_print_gost01);
- EVP_PKEY_asn1_set_param (*ameth, 0, 0,
+ EVP_PKEY_asn1_set_param (*ameth,
+ gost2001_param_decode, gost2001_param_encode,
param_missing_gost01, param_copy_gost01,
- param_cmp_gost01, 0);
+ param_cmp_gost01, param_print_gost01);
EVP_PKEY_asn1_set_public (*ameth,
pub_decode_gost01, pub_encode_gost01,
pub_cmp_gost01, pub_print_gost01,
EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
break;
+ case NID_id_Gost28147_89_MAC:
+ EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
+ EVP_PKEY_asn1_set_ctrl(*ameth,mac_ctrl_gost);
+ break;
}
return 1;
}