diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2007-10-26 12:06:36 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2007-10-26 12:06:36 +0000 |
commit | 0e1dba934fa53e9736e9156b9e25bd1010290149 (patch) | |
tree | e52e12fa1147b634c215263e93d77c8c9830b39b /engines | |
parent | 11d01d371f67a9cacfeccb1078669c595d65002f (diff) | |
download | openssl-0e1dba934fa53e9736e9156b9e25bd1010290149.tar.gz |
1. Changes for s_client.c to make it return non-zero exit code in case
of handshake failure
2. Changes to x509_certificate_type function (crypto/x509/x509type.c) to
make it recognize GOST certificates as EVP_PKT_SIGN|EVP_PKT_EXCH
(required for s3_srvr to accept GOST client certificates).
3. Changes to EVP
- adding of function EVP_PKEY_CTX_get0_peerkey
- Make function EVP_PKEY_derive_set_peerkey work for context with
ENCRYPT operation, because we use peerkey field in the context to
pass non-ephemeral secret key to GOST encrypt operation.
- added EVP_PKEY_CTRL_SET_IV control command. It is really
GOST-specific, but it is used in SSL code, so it has to go
in some header file, available during libssl compilation
4. Fix to HMAC to avoid call of OPENSSL_cleanse on undefined data
5. Include des.h if KSSL_DEBUG is defined into some libssl files, to
make debugging output which depends on constants defined there, work
and other KSSL_DEBUG output fixes
6. Declaration of real GOST ciphersuites, two authentication methods
SSL_aGOST94 and SSL_aGOST2001 and one key exchange method SSL_kGOST
7. Implementation of these methods.
8. Support for sending unsolicited serverhello extension if GOST
ciphersuite is selected. It is require for interoperability with
CryptoPro CSP 3.0 and 3.6 and controlled by
SSL_OP_CRYPTOPRO_TLSEXT_BUG constant.
This constant is added to SSL_OP_ALL, because it does nothing, if
non-GOST ciphersuite is selected, and all implementation of GOST
include compatibility with CryptoPro.
9. Support for CertificateVerify message without length field. It is
another CryptoPro bug, but support is made unconditional, because it
does no harm for draft-conforming implementation.
10. In tls1_mac extra copy of stream mac context is no more done.
When I've written currently commited code I haven't read
EVP_DigestSignFinal manual carefully enough and haven't noticed that
it does an internal digest ctx copying.
This implementation was tested against
1. CryptoPro CSP 3.6 client and server
2. Cryptopro CSP 3.0 server
Diffstat (limited to 'engines')
-rw-r--r-- | engines/ccgost/e_gost_err.c | 4 | ||||
-rw-r--r-- | engines/ccgost/e_gost_err.h | 4 | ||||
-rw-r--r-- | engines/ccgost/gost2001_keyx.c | 431 | ||||
-rw-r--r-- | engines/ccgost/gost94_keyx.c | 374 | ||||
-rw-r--r-- | engines/ccgost/gost_ameth.c | 73 | ||||
-rw-r--r-- | engines/ccgost/gost_crypt.c | 80 | ||||
-rw-r--r-- | engines/ccgost/gost_ctl.c | 14 | ||||
-rw-r--r-- | engines/ccgost/gost_eng.c | 23 | ||||
-rw-r--r-- | engines/ccgost/gost_lcl.h | 35 | ||||
-rw-r--r-- | engines/ccgost/gost_md.c | 8 | ||||
-rw-r--r-- | engines/ccgost/gost_pmeth.c | 203 |
11 files changed, 339 insertions, 910 deletions
diff --git a/engines/ccgost/e_gost_err.c b/engines/ccgost/e_gost_err.c index 648a2d71e5..d483411fc2 100644 --- a/engines/ccgost/e_gost_err.c +++ b/engines/ccgost/e_gost_err.c @@ -97,6 +97,7 @@ static ERR_STRING_DATA GOST_str_functs[]= {ERR_FUNC(GOST_F_PKEY_GOST01CC_ENCRYPT), "pkey_GOST01cc_encrypt"}, {ERR_FUNC(GOST_F_PKEY_GOST01CP_ENCRYPT), "pkey_GOST01cp_encrypt"}, {ERR_FUNC(GOST_F_PKEY_GOST01_KEYGEN), "PKEY_GOST01_KEYGEN"}, +{ERR_FUNC(GOST_F_PKEY_GOST2001_DERIVE), "PKEY_GOST2001_DERIVE"}, {ERR_FUNC(GOST_F_PKEY_GOST94CC_DECRYPT), "pkey_GOST94cc_decrypt"}, {ERR_FUNC(GOST_F_PKEY_GOST94CC_ENCRYPT), "pkey_GOST94cc_encrypt"}, {ERR_FUNC(GOST_F_PKEY_GOST94CP_DECRYPT), "pkey_GOST94cp_decrypt"}, @@ -148,6 +149,8 @@ static ERR_STRING_DATA GOST_str_reasons[]= {ERR_REASON(GOST_R_NOT_ENOUGH_SPACE_FOR_KEY),"not enough space for key"}, {ERR_REASON(GOST_R_NO_MEMORY) ,"no memory"}, {ERR_REASON(GOST_R_NO_PARAMETERS_SET) ,"no parameters set"}, +{ERR_REASON(GOST_R_NO_PEER_KEY) ,"no peer key"}, +{ERR_REASON(GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR),"no private part of non ephemeral keypair"}, {ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"}, {ERR_REASON(GOST_R_RANDOM_GENERATOR_ERROR),"random generator error"}, {ERR_REASON(GOST_R_RANDOM_GENERATOR_FAILURE),"random generator failure"}, @@ -155,6 +158,7 @@ static ERR_STRING_DATA GOST_str_reasons[]= {ERR_REASON(GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH),"session key mac does not match"}, {ERR_REASON(GOST_R_SIGNATURE_MISMATCH) ,"signature mismatch"}, {ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"}, +{ERR_REASON(GOST_R_UKM_NOT_SET) ,"ukm not set"}, {ERR_REASON(GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND),"unsupported cipher ctl command"}, {ERR_REASON(GOST_R_UNSUPPORTED_PARAMETER_SET),"unsupported parameter set"}, {0,NULL} diff --git a/engines/ccgost/e_gost_err.h b/engines/ccgost/e_gost_err.h index 4fb5a985a3..a672ed9d8d 100644 --- a/engines/ccgost/e_gost_err.h +++ b/engines/ccgost/e_gost_err.h @@ -94,6 +94,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line); #define GOST_F_PKEY_GOST01CC_ENCRYPT 129 #define GOST_F_PKEY_GOST01CP_ENCRYPT 137 #define GOST_F_PKEY_GOST01_KEYGEN 112 +#define GOST_F_PKEY_GOST2001_DERIVE 145 #define GOST_F_PKEY_GOST94CC_DECRYPT 125 #define GOST_F_PKEY_GOST94CC_ENCRYPT 123 #define GOST_F_PKEY_GOST94CP_DECRYPT 126 @@ -142,6 +143,8 @@ void ERR_GOST_error(int function, int reason, char *file, int line); #define GOST_R_NOT_ENOUGH_SPACE_FOR_KEY 125 #define GOST_R_NO_MEMORY 106 #define GOST_R_NO_PARAMETERS_SET 107 +#define GOST_R_NO_PEER_KEY 137 +#define GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR 139 #define GOST_R_PUBLIC_KEY_UNDEFINED 132 #define GOST_R_RANDOM_GENERATOR_ERROR 108 #define GOST_R_RANDOM_GENERATOR_FAILURE 133 @@ -149,6 +152,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line); #define GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH 126 #define GOST_R_SIGNATURE_MISMATCH 110 #define GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q 111 +#define GOST_R_UKM_NOT_SET 138 #define GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND 112 #define GOST_R_UNSUPPORTED_PARAMETER_SET 113 diff --git a/engines/ccgost/gost2001_keyx.c b/engines/ccgost/gost2001_keyx.c index 3cef5f2e38..013659aa23 100644 --- a/engines/ccgost/gost2001_keyx.c +++ b/engines/ccgost/gost2001_keyx.c @@ -18,194 +18,7 @@ #include "gost_lcl.h" #include "gost2001_keyx.h" -/* Transform ECDH shared key into little endian as required by Cryptocom - * key exchange */ -static void *make_key_le(const void *in, size_t inlen, void *out, size_t *outlen) - { - const char* inbuf= in; - char* outbuf= out; - int i; - if (*outlen < inlen) - { - return NULL; - } - for (i=0;i<inlen;i++) - { - outbuf[inlen-1-i]=inbuf[i]; - } - *outlen = inlen; - return out; - } -/* Create gost 2001 ephemeral key with same parameters as peer key */ -static EC_KEY *make_ec_ephemeral_key(EC_KEY *peer_key,BIGNUM *seckey) - { - EC_KEY *out = EC_KEY_new(); - EC_KEY_copy(out,peer_key); - EC_KEY_set_private_key(out,seckey); - gost2001_compute_public(out); - return out; - } -/* Packs GOST elliptic curve key into EVP_PKEY setting same parameters - * as in passed pubkey - */ -static EVP_PKEY *ec_ephemeral_key_to_EVP(EVP_PKEY *pubk,int type,EC_KEY *ephemeral) - { - EVP_PKEY *newkey; - newkey = EVP_PKEY_new(); - EVP_PKEY_assign(newkey,type,ephemeral); - return newkey; - } - -/* - * EVP_PKEY_METHOD callback encrypt - * Implementation of GOST2001 key transport, cryptocom variation - */ - -int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *pctx,unsigned char *out, - size_t *out_len, const unsigned char *key,size_t key_len) - { - EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); - struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); - GOST_KEY_TRANSPORT *gkt = NULL; - int ret=0; - const struct gost_cipher_info *cipher_info; - gost_ctx ctx; - EC_KEY *ephemeral=NULL; - const EC_POINT *pub_key_point=NULL; - unsigned char shared_key[32],encrypted_key[32],hmac[4], - iv[8]={0,0,0,0,0,0,0,0}; - ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk), gost_get_priv_key(data->eph_seckey)); - if (!ephemeral) goto err; - /* compute shared key */ - pub_key_point=EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)); - if (!ECDH_compute_key(shared_key,32,pub_key_point,ephemeral,make_key_le)) - { - GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY); - goto err; - } - /* encrypt session key */ - cipher_info = get_encryption_params(NULL); - gost_init(&ctx, cipher_info->sblock); - gost_key(&ctx,shared_key); - encrypt_cryptocom_key(key,key_len,encrypted_key,&ctx); - /* compute hmac of session key */ - if (!gost_mac(&ctx,32,key,32,hmac)) - { - GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_COMPUTING_MAC); - return -1; - } - gkt = GOST_KEY_TRANSPORT_new(); - if (!gkt) - { - GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_NO_MEMORY); - return -1; - } - /* Store IV which is always zero in our case */ - if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,iv,8)) - { - GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_IV); - goto err; - } - if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,hmac,4)) - { - GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_MAC); - goto err; - } - if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,encrypted_key,32)) - { - GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY); - goto err; - } - - if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey)) - { - GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); - goto err; - } - ASN1_OBJECT_free(gkt->key_agreement_info->cipher); - gkt->key_agreement_info->cipher = OBJ_nid2obj(cipher_info->nid); - if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret = 1; - ; - err: - if (gkt) GOST_KEY_TRANSPORT_free(gkt); - return ret; - } -/* - * EVP_PKEY_METHOD callback decrypt - * Implementation of GOST2001 key transport, cryptocom variation - */ -int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len) - { - /* Form DH params from compute shared key */ - EVP_PKEY *priv=EVP_PKEY_CTX_get0_pkey(pctx); - GOST_KEY_TRANSPORT *gkt = NULL; - const unsigned char *p=in; - unsigned char shared_key[32]; - unsigned char hmac[4],hmac_comp[4]; - unsigned char iv[8]; - int i; - const struct gost_cipher_info *cipher_info; - gost_ctx ctx; - const EC_POINT *pub_key_point; - EVP_PKEY *eph_key; - - if (!key) - { - *key_len = 32; - return 1; - } - /* Parse passed octet string and find out public key, iv and HMAC*/ - gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, - in_len); - if (!gkt) - { - GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); - return 0; - } - eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key); - /* Initialization vector is really ignored here */ - OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); - memcpy(iv,gkt->key_agreement_info->eph_iv->data,8); - /* HMAC should be computed and checked */ - OPENSSL_assert(gkt->key_info->imit->length==4); - memcpy(hmac,gkt->key_info->imit->data,4); - /* Compute shared key */ - pub_key_point=EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)); - i=ECDH_compute_key(shared_key,32,pub_key_point,EVP_PKEY_get0(priv),make_key_le); - EVP_PKEY_free(eph_key); - if (!i) - { - GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY); - GOST_KEY_TRANSPORT_free(gkt); - return 0; - } - /* Decrypt session key */ - cipher_info = get_encryption_params(gkt->key_agreement_info->cipher); - gost_init(&ctx, cipher_info->sblock); - gost_key(&ctx,shared_key); - - if (!decrypt_cryptocom_key(key,*key_len,gkt->key_info->encrypted_key->data, - gkt->key_info->encrypted_key->length, &ctx)) - { - GOST_KEY_TRANSPORT_free(gkt); - return 0; - } - GOST_KEY_TRANSPORT_free(gkt); - /* check HMAC of session key*/ - if (!gost_mac(&ctx,32,key,32,hmac_comp)) - { - GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC); - return 0; - } - /* HMAC of session key is not correct */ - if (memcmp(hmac,hmac_comp,4)!=0) - { - GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH); - return 0; - } - return 1; - } /* Implementation of CryptoPro VKO 34.10-2001 algorithm */ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,const EC_POINT *pub_key,EC_KEY *priv_key,const unsigned char *ukm) @@ -254,110 +67,191 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons return 32; } + +/* + * EVP_PKEY_METHOD callback derive. Implements VKO R 34.10-2001 + * algorithm + */ +int pkey_gost2001_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) +{ + /* Public key of peer in the ctx field peerkey + * Our private key in the ctx pkey + * ukm is in the algorithm specific context data + */ + EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx); + EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx); + struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); + + if (!data->shared_ukm) { + GOSTerr(GOST_F_PKEY_GOST2001_DERIVE, GOST_R_UKM_NOT_SET); + return 0; + } + + if (key == NULL) { + *keylen = 32; + return 32; + } + + *keylen=VKO_compute_key(key, 32, EC_KEY_get0_public_key(EVP_PKEY_get0(peer_key)), + (EC_KEY *)EVP_PKEY_get0(my_key),data->shared_ukm); + return 1; +} + + + + +/* + * EVP_PKEY_METHOD callback encrypt + * Implementation of GOST2001 key transport, cryptocom variation + */ /* Generates ephemeral key based on pubk algorithm * computes shared key using VKO and returns filled up * GOST_KEY_TRANSPORT structure */ -/* Public, because it would be needed in SSL implementation */ -GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_key, - const unsigned char *key,size_t keylen, unsigned char *ukm, - size_t ukm_len) - { +/* + * EVP_PKEY_METHOD callback encrypt + * Implementation of GOST2001 key transport, cryptopo variation + */ + +int pkey_GOST01cp_encrypt (EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key,size_t key_len) + { + GOST_KEY_TRANSPORT *gkt=NULL; + EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); + struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); const struct gost_cipher_info *param=get_encryption_params(NULL); - EC_KEY *ephemeral = NULL; - GOST_KEY_TRANSPORT *gkt=NULL; - const EC_POINT *pub_key_point = EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)); - unsigned char shared_key[32],crypted_key[44]; - gost_ctx ctx; - EVP_PKEY *newkey=NULL; - - /* Do not use vizir cipher parameters with cryptopro */ + unsigned char ukm[8], shared_key[32], crypted_key[44]; + int ret=0; + int key_is_ephemeral=1; + gost_ctx cctx; + EVP_PKEY *sec_key=EVP_PKEY_CTX_get0_peerkey(pctx); + if (data->shared_ukm) + { + memcpy(ukm, data->shared_ukm,8); + } + else if (out) + { + + if (RAND_bytes(ukm,8)<=0) + { + GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, + GOST_R_RANDOM_GENERATOR_FAILURE); + return 0; + } + } + /* Check for private key in the peer_key of context */ + if (sec_key) + { + key_is_ephemeral=0; + if (!gost_get0_priv_key(sec_key)) + { + GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, + GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); + goto err; + } + } + else + { + key_is_ephemeral=1; + if (out) + { + sec_key = EVP_PKEY_new(); + EVP_PKEY_assign(sec_key,EVP_PKEY_base_id(pubk),EC_KEY_new()); + EVP_PKEY_copy_parameters(sec_key,pubk); + if (!gost2001_keygen(EVP_PKEY_get0(sec_key))) + { + goto err; + } + } + } if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param= gost_cipher_list+1; } - ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk),eph_key); - VKO_compute_key(shared_key,32,pub_key_point,ephemeral,ukm); - gost_init(&ctx,param->sblock); - keyWrapCryptoPro(&ctx,shared_key,ukm,key,crypted_key); + if (out) + { + VKO_compute_key(shared_key,32,EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)),EVP_PKEY_get0(sec_key),ukm); + gost_init(&cctx,param->sblock); + keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); + } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { - goto memerr; + goto err; } if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm,8)) { - goto memerr; + goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4)) { - goto memerr; + goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32)) { - goto memerr; - } - newkey = ec_ephemeral_key_to_EVP(pubk,NID_id_GostR3410_2001,ephemeral); - if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,newkey)) - { - GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; - } + } + if (key_is_ephemeral) { + if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?sec_key:pubk)) + { + GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001, + GOST_R_CANNOT_PACK_EPHEMERAL_KEY); + goto err; + } + } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); - EVP_PKEY_free(newkey); - return gkt; - memerr: - GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001, - GOST_R_MALLOC_FAILURE); - err: - GOST_KEY_TRANSPORT_free(gkt); - return NULL; - } - -/* - * EVP_PKEY_METHOD callback encrypt - * Implementation of GOST2001 key transport, cryptopo variation - */ - -int pkey_GOST01cp_encrypt (EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key,size_t key_len) - { - GOST_KEY_TRANSPORT *gkt=NULL; - EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); - struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); - unsigned char ukm[8]; - int ret=0; - if (RAND_bytes(ukm,8)<=0) - { - GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, - GOST_R_RANDOM_GENERATOR_FAILURE); - return 0; - } - - if (!(gkt=make_rfc4490_keytransport_2001(pubk,gost_get_priv_key(data->eph_seckey),key, key_len,ukm,8))) - { - goto err; - } - if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret =1; + if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key); + if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL))>0) ret =1; GOST_KEY_TRANSPORT_free(gkt); return ret; err: + if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key); GOST_KEY_TRANSPORT_free(gkt); return -1; } -/* Public, because it would be needed in SSL implementation */ -int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt, - unsigned char *key_buf,int key_buf_len) +/* + * EVP_PKEY_METHOD callback decrypt + * Implementation of GOST2001 key transport, cryptopo variation + */ +int pkey_GOST01cp_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_len, const unsigned char *in, size_t in_len) { + const unsigned char *p = in; + EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx); + GOST_KEY_TRANSPORT *gkt = NULL; + int ret=0; unsigned char wrappedKey[44]; unsigned char sharedKey[32]; gost_ctx ctx; const struct gost_cipher_info *param=NULL; EVP_PKEY *eph_key=NULL; - + + if (!key) + { + *key_len = 32; + return 1; + } + gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, + in_len); + if (!gkt) + { + GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); + return -1; + } + eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key); + if (!eph_key) { + eph_key = EVP_PKEY_CTX_get0_peerkey(pctx); + if (! eph_key) { + GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, + GOST_R_NO_PEER_KEY); + goto err; + } + /* Increment reference count of peer key */ + CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY); + } + param = get_encryption_params(gkt->key_agreement_info->cipher); gost_init(&ctx,param->sblock); OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); @@ -368,7 +262,7 @@ int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt, memcpy(wrappedKey+40,gkt->key_info->imit->data,4); VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)), EVP_PKEY_get0(priv),wrappedKey); - if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key_buf)) + if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key)) { GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT, GOST_R_ERROR_COMPUTING_SHARED_KEY); @@ -376,35 +270,8 @@ int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt, } EVP_PKEY_free(eph_key); - return 32; - err: - EVP_PKEY_free(eph_key); - return -1; - } -/* - * EVP_PKEY_METHOD callback decrypt - * Implementation of GOST2001 key transport, cryptopo variation - */ -int pkey_GOST01cp_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_len, const unsigned char *in, size_t in_len) - { - const unsigned char *p = in; - EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx); - GOST_KEY_TRANSPORT *gkt = NULL; - int ret=0; - - if (!key) - { - *key_len = 32; - return 1; - } - gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, - in_len); - if (!gkt) - { - GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); - return -1; - } - ret = decrypt_rfc4490_shared_key_2001(priv,gkt,key,*key_len); GOST_KEY_TRANSPORT_free(gkt); + ret=1; +err: return ret; } diff --git a/engines/ccgost/gost94_keyx.c b/engines/ccgost/gost94_keyx.c index a7cdb2a26d..69c4a2271e 100644 --- a/engines/ccgost/gost94_keyx.c +++ b/engines/ccgost/gost94_keyx.c @@ -20,53 +20,6 @@ #include "gost_keywrap.h" #include "gost_lcl.h" /* Common functions for both 94 and 2001 key exchange schemes */ -int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len, - const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx) - { - int i; - int j; - int blocks = crypted_key_len >>3; - unsigned char gamma[8]; - if (max_key_len <crypted_key_len) - { - GOSTerr(GOST_F_DECRYPT_CRYPTOCOM_KEY,GOST_R_NOT_ENOUGH_SPACE_FOR_KEY); - return 0; - } - if ((crypted_key_len & 7) !=0) - { - GOSTerr(GOST_F_DECRYPT_CRYPTOCOM_KEY,GOST_R_INVALID_ENCRYPTED_KEY_SIZE); - return 0; - } - for (i=blocks-1;i>0;i--) - { - gostcrypt(ctx,crypted_key+(i-1)*8,gamma); - for(j=0;j<8;j++) - { - sess_key[i*8+j]=gamma[j]^crypted_key[i*8+j]; - } - } - gostcrypt(ctx,sess_key+crypted_key_len-8,gamma); - for(j=0;j<8;j++) - { - sess_key[j]=gamma[j]^crypted_key[j]; - } - return 1; - } -int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len, - unsigned char *crypted_key, gost_ctx *ctx) - { - int i; - int j; - unsigned char gamma[8]; - memcpy(gamma,sess_key+key_len-8,8); - for (i=0;i<key_len;i+=8) - { - gostcrypt(ctx,gamma,gamma); - for (j=0;j<8;j++) - gamma[j]=crypted_key[i+j]=sess_key[i+j]^gamma[j]; - } - return 1; - } /* Implementation of the Diffi-Hellman key agreement scheme based on * GOST-94 keys */ @@ -87,59 +40,24 @@ static int compute_pair_key_le(unsigned char *pair_key,BIGNUM *pub_key,DH *dh) } return key_size; } -/* - * Computes 256 bit key exchange key for CryptoCom variation of GOST 94 - * algorithm - */ -static int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key) - { - unsigned char dh_key [128]; - int i; - /* Compute key */ - memset(dh_key,0,128); - if (!compute_pair_key_le(dh_key,((DSA *)EVP_PKEY_get0(pubk))->pub_key,dh)) return 0; - /* Fold it down to 256 bit */ - /* According to GOST either 2^1020<p<2^1024 or - * 2^509<p<2^512, so DH_size can be exactly 128 or exactly 64 only - */ - - if (DH_size(dh)==128) - { - for (i=0;i<64;i++) - { - dh_key[i]^=dh_key[64+i]; - } - } - for (i=0;i<32;i++) - { - shared_key[i]=dh_key[i]^dh_key[32+i]; - } - return 1; - } -static DH *make_ephemeral_key(EVP_PKEY *pubk,BIGNUM *ephemeral_key) - { - DH *dh = DH_new(); - dh->g = BN_dup(pubk->pkey.dsa->g); - dh->p = BN_dup(pubk->pkey.dsa->p); - dh->priv_key = BN_dup(ephemeral_key); - /* Generate ephemeral key pair */ - if (!DH_generate_key(dh)) - { - DH_free(dh); - return NULL; - } - return dh; - } /* * Computes 256 bit Key exchange key as specified in RFC 4357 */ -static int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key) +static int make_cp_exchange_key(BIGNUM *priv_key,EVP_PKEY *pubk, unsigned char *shared_key) { unsigned char dh_key [128]; + int ret; gost_hash_ctx hash_ctx; + DH *dh = DH_new(); + memset(dh_key,0,128); - if (!compute_pair_key_le(dh_key,((DSA *)(EVP_PKEY_get0(pubk)))->pub_key,dh)) return 0; + dh->g = BN_dup(pubk->pkey.dsa->g); + dh->p = BN_dup(pubk->pkey.dsa->p); + dh->priv_key = BN_dup(priv_key); + ret=compute_pair_key_le(dh_key,((DSA *)(EVP_PKEY_get0(pubk)))->pub_key,dh) ; + DH_free(dh); + if (!ret) return 0; init_gost_hash_ctx(&hash_ctx,&GostR3411_94_CryptoProParamSet); start_hash(&hash_ctx); hash_block(&hash_ctx,dh_key,128); @@ -148,38 +66,87 @@ static int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key return 1; } +/* EVP_PKEY_METHOD callback derive. Implements VKO R 34.10-94 */ + +int pkey_gost94_derive(EVP_PKEY_CTX *ctx,unsigned char *key,size_t *keylen) + { + EVP_PKEY *pubk = EVP_PKEY_CTX_get0_peerkey(ctx); + EVP_PKEY *mykey = EVP_PKEY_CTX_get0_pkey(ctx); + *keylen = 32; + if (key == NULL) return 1; + + return make_cp_exchange_key(gost_get0_priv_key(mykey), pubk, key); + } + /* EVP_PKEY_METHOD callback encrypt for * GOST R 34.10-94 cryptopro modification */ + int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ) { GOST_KEY_TRANSPORT *gkt=NULL; - DH *dh = NULL; unsigned char shared_key[32], ukm[8],crypted_key[44]; const struct gost_cipher_info *param=get_encryption_params(NULL); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); int size=-1; gost_ctx cctx; + int key_is_ephemeral=1; + EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx); - if (!(data->eph_seckey)) + /* Do not use vizir cipher parameters with cryptopro */ + if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { - GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, - GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT); - return -1; + param= gost_cipher_list+1; } - dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey)); - gost_init(&cctx,param->sblock); - make_cp_exchange_key(dh,pubk,shared_key); - if (RAND_bytes(ukm,8)<=0) + if (mykey) { - GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, - GOST_R_RANDOM_GENERATOR_FAILURE); - return -1; + /* If key already set, it is not ephemeral */ + key_is_ephemeral=0; + if (!gost_get0_priv_key(mykey)) + { + GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, + GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); + goto err; + } + } + else + { + /* Otherwise generate ephemeral key */ + key_is_ephemeral = 1; + if (out) + { + mykey = EVP_PKEY_new(); + EVP_PKEY_assign(mykey, EVP_PKEY_base_id(pubk),DSA_new()); + EVP_PKEY_copy_parameters(mykey,pubk); + if (!gost_sign_keygen(EVP_PKEY_get0(mykey))) + { + goto err; + } + } } - keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); + if (out) + make_cp_exchange_key(gost_get0_priv_key(mykey),pubk,shared_key); + if (data->shared_ukm) + { + memcpy(ukm,data->shared_ukm,8); + } + else if (out) + { + if (RAND_bytes(ukm,8)<=0) + { + GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, + GOST_R_RANDOM_GENERATOR_FAILURE); + goto err; + } + } + + if (out) { + gost_init(&cctx,param->sblock); + keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); + } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { @@ -198,117 +165,40 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, { goto memerr; } - if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey)) + if (key_is_ephemeral) { + if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?mykey:pubk)) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; - } + } + if (out) EVP_PKEY_free(mykey); + } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); - *outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out); + *outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL); if (!size) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); size=-1; } GOST_KEY_TRANSPORT_free(gkt); - DH_free(dh); return 1; memerr: + if (key_is_ephemeral) { + EVP_PKEY_free(mykey); + } GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_MALLOC_FAILURE); err: GOST_KEY_TRANSPORT_free(gkt); - DH_free(dh); return -1; } -/* EVP_PKEY_METHOD callback encrypt for - * GOST R 34.10-94 cryptocom modification - */ - -int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len) - { - EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx); - struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); - /* create DH structure filling parameters from passed pub_key */ - DH *dh = NULL; - GOST_KEY_TRANSPORT *gkt = NULL; - const struct gost_cipher_info *cipher_info; - gost_ctx cctx; - EVP_PKEY *newkey=NULL; - unsigned char shared_key[32],encrypted_key[32],hmac[4], - iv[8]={0,0,0,0,0,0,0,0}; - - if (! data->eph_seckey) - { - GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, - GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT); - return -1; - } - dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey)); - if (!dh) goto err; - /* compute shared key */ - if (!make_gost_shared_key(dh,pubk,shared_key)) - { - GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY); - goto err; - } - /* encrypt session key */ - cipher_info = get_encryption_params(NULL); - gost_init(&cctx, cipher_info->sblock); - gost_key(&cctx,shared_key); - encrypt_cryptocom_key(key,key_len,encrypted_key,&cctx); - /* compute hmac of session key */ - if (!gost_mac(&cctx,32,key,32,hmac)) - { - DH_free(dh); - GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_COMPUTING_MAC); - return -1; - } - gkt = GOST_KEY_TRANSPORT_new(); - if (!gkt) - { - DH_free(dh); - GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_NO_MEMORY); - return -1; - } - /* Store IV which is always zero in our case */ - if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,iv,8)) - { - GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_IV); - goto err; - } - if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,hmac,4)) - { - GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_MAC); - goto err; - } - if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,encrypted_key,32)) - { - GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY); - goto err; - } - if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey)) - { - GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); - goto err; - } - ASN1_OBJECT_free(gkt->key_agreement_info->cipher); - gkt->key_agreement_info->cipher = OBJ_nid2obj(cipher_info->nid); - *outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out); - err: - if (gkt) GOST_KEY_TRANSPORT_free(gkt); - if (dh) DH_free(dh); - if (newkey) EVP_PKEY_free(newkey); - return 1; - } /* EVP_PLEY_METHOD callback decrypt for * GOST R 34.10-94 cryptopro modification */ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len,const unsigned char *in, size_t in_len) { - DH *dh = DH_new(); const unsigned char *p = in; GOST_KEY_TRANSPORT *gkt = NULL; unsigned char wrappedKey[44]; @@ -324,18 +214,28 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le return 1; } - dh->g = BN_dup(priv->pkey.dsa->g); - dh->p = BN_dup(priv->pkey.dsa->p); - dh->priv_key = BN_dup(priv->pkey.dsa->priv_key); gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, in_len); if (!gkt) { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); - DH_free(dh); return 0; } eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key); + /* No ephemeral key in the structure. Check peer key in the context + */ + if (!eph_key) { + eph_key = EVP_PKEY_CTX_get0_peerkey(ctx); + if (! eph_key) { + GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, + GOST_R_NO_PEER_KEY); + goto err; + } + /* Increment reference count of peer key */ + CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY); + } + + param = get_encryption_params(gkt->key_agreement_info->cipher); gost_init(&cctx,param->sblock); OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); @@ -344,7 +244,7 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le memcpy(wrappedKey+8,gkt->key_info->encrypted_key->data,32); OPENSSL_assert(gkt->key_info->imit->length==4); memcpy(wrappedKey+40,gkt->key_info->imit->data,4); - make_cp_exchange_key(dh,eph_key,sharedKey); + make_cp_exchange_key(gost_get0_priv_key(priv),eph_key,sharedKey); if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key)) { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, @@ -354,92 +254,10 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le EVP_PKEY_free(eph_key); GOST_KEY_TRANSPORT_free(gkt); - DH_free(dh); return 1; err: EVP_PKEY_free(eph_key); GOST_KEY_TRANSPORT_free(gkt); - DH_free(dh); return -1; } -/* EVP_PKEY_METHOD callback decrypt for - * GOST R 34.10-94 cryptocom modification - */ - -int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len) - { - /* Form DH params from compute shared key */ - GOST_KEY_TRANSPORT *gkt = NULL; - const unsigned char *p=in; - unsigned char shared_key[32]; - unsigned char hmac[4],hmac_comp[4]; - unsigned char iv[8]; - int i; - const struct gost_cipher_info *cipher_info; - gost_ctx ctx; - DH *dh = DH_new(); - EVP_PKEY *eph_key; - EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx); - - if (!key) - { - *key_len = 32; - return 1; - } - /* Construct DH structure from the our GOST private key */ - dh->g = BN_dup(priv->pkey.dsa->g); - dh->p = BN_dup(priv->pkey.dsa->p); - dh->priv_key = BN_dup(priv->pkey.dsa->priv_key); - /* Parse passed octet string and find out public key, iv and HMAC*/ - gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, - in_len); - if (!gkt) - { - GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); - DH_free(dh); - return 0; - } - eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key); - /* Initialization vector is really ignored here */ - OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); - memcpy(iv,gkt->key_agreement_info->eph_iv->data,8); - /* HMAC should be computed and checked */ - OPENSSL_assert(gkt->key_info->imit->length==4); - memcpy(hmac,gkt->key_info->imit->data,4); - /* Compute shared key */ - i=make_gost_shared_key(dh,eph_key,shared_key); - EVP_PKEY_free(eph_key); - DH_free(dh); - if (!i) - { - GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY); - GOST_KEY_TRANSPORT_free(gkt); - return 0; - } - /* Decrypt session key */ - cipher_info = get_encryption_params(gkt->key_agreement_info->cipher); - gost_init(&ctx, cipher_info->sblock); - gost_key(&ctx,shared_key); - - if (!decrypt_cryptocom_key(key,*key_len,gkt->key_info->encrypted_key->data, - gkt->key_info->encrypted_key->length, &ctx)) - { - GOST_KEY_TRANSPORT_free(gkt); - return 0; - } - GOST_KEY_TRANSPORT_free(gkt); - /* check HMAC of session key*/ - if (!gost_mac(&ctx,32,key,32,hmac_comp)) - { - GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC); - return 0; - } - /* HMAC of session key is not correct */ - if (memcmp(hmac,hmac_comp,4)!=0) - { - GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH); - return 0; - } - return 1; - } diff --git a/engines/ccgost/gost_ameth.c b/engines/ccgost/gost_ameth.c index 39a175f52c..617b03e70a 100644 --- a/engines/ccgost/gost_ameth.c +++ b/engines/ccgost/gost_ameth.c @@ -48,14 +48,6 @@ static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key) } 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; @@ -128,7 +120,6 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) switch (pkey_nid) { case NID_id_GostR3410_94: - case NID_id_GostR3410_94_cc: { DSA *dsa= EVP_PKEY_get0(pkey); if (!dsa) @@ -140,7 +131,6 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) break; } case NID_id_GostR3410_2001: - case NID_id_GostR3410_2001_cc: { EC_KEY *ec = EVP_PKEY_get0(pkey); if (!ec) @@ -160,7 +150,6 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) 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) @@ -174,7 +163,6 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) break; } case NID_id_GostR3410_2001: - case NID_id_GostR3410_2001_cc: { EC_KEY *ec = EVP_PKEY_get0(pkey); if (!ec) @@ -190,12 +178,11 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) } 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) @@ -203,11 +190,10 @@ BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) 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; @@ -216,7 +202,7 @@ BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) return NULL; } if (!(priv=EC_KEY_get0_private_key(ec))) return NULL; - return BN_dup(priv); + return (BIGNUM *)priv; break; } } @@ -322,7 +308,10 @@ static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) 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, EVP_R_DECODE_ERROR); @@ -342,16 +331,13 @@ static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk) 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, @@ -363,10 +349,9 @@ static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent, { BIGNUM *key; if (!BIO_indent(out,indent,128)) return 0; - key = gost_get_priv_key(pkey); + key = gost_get0_priv_key(pkey); if (!key) return 0; BN_print(out,key); - BN_free(key); return 1; } @@ -438,7 +423,7 @@ static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) 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); @@ -543,6 +528,7 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub) 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, @@ -561,16 +547,11 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub) { 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 @@ -578,6 +559,9 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub) { 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); @@ -586,9 +570,10 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub) { 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; } @@ -629,16 +614,10 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk) 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(); @@ -732,7 +711,6 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems 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, @@ -749,7 +727,6 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems 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, diff --git a/engines/ccgost/gost_crypt.c b/engines/ccgost/gost_crypt.c index 9f1bf9adbe..a6736836c4 100644 --- a/engines/ccgost/gost_crypt.c +++ b/engines/ccgost/gost_crypt.c @@ -15,11 +15,6 @@ static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); -#ifdef USE_SSL -/* Specialized init functions which set specific parameters */ -static int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc); -#endif /* Handles block of data in CFB mode */ static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl); @@ -70,30 +65,8 @@ EVP_CIPHER cipher_gost_cpacnt = NULL, }; -#ifdef USE_SSL -static EVP_CIPHER cipher_gost_vizircfb = - { - NID_undef, - 1,/*block_size*/ - 32,/*key_size*/ - 8,/*iv_len - синхропосылка*/ - EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING | - EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, - gost_cipher_init_vizir, - gost_cipher_do_cfb, - gost_cipher_cleanup, - sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ - gost89_set_asn1_parameters, - gost89_get_asn1_parameters, - gost_cipher_ctl, - NULL, - }; -#endif /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */ /* Init functions which set specific parameters */ -#ifdef USE_SSL -static int gost_imit_init_vizir(EVP_MD_CTX *ctx); -#endif static int gost_imit_init_cpa(EVP_MD_CTX *ctx); /* process block of data */ static int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count); @@ -105,27 +78,6 @@ static int gost_imit_cleanup(EVP_MD_CTX *ctx); /* Control function, knows how to set MAC key.*/ static int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr); -#ifdef USE_SSL - -EVP_MD imit_gost_vizir = - { - NID_undef, - NID_undef, - 4, - EVP_MD_FLAG_NEEDS_KEY, - gost_imit_init_vizir, - gost_imit_update, - gost_imit_final, - gost_imit_copy, - gost_imit_cleanup, - gost_imit_ctrl, - NULL, - NULL, - {0,0,0,0,0}, - 8, - sizeof(struct ossl_gost_imit_ctx) - }; -#endif EVP_MD imit_gost_cpa = { NID_id_Gost28147_89_MAC, @@ -241,24 +193,6 @@ static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); return 1; } -#ifdef USE_SSL -/* Initializes EVP_CIPHER_CTX with fixed cryptopro A paramset */ - -/* Initializes EVP_CIPHER_CTX with fixed vizir paramset */ -static int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) - { - struct ossl_gost_cipher_ctx *c=ctx->cipher_data; - gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet); - c->key_meshing=0; - c->count=0; - gost_key(&(c->cctx),key); - - if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); - memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); - return 1; - } -#endif /* def USE_SSL */ /* Initializes EVP_CIPHER_CTX with default values */ int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, @@ -541,16 +475,6 @@ int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) return 1; } -#ifdef USE_SSL - -int gost_imit_init_vizir(EVP_MD_CTX *ctx) - { - struct ossl_gost_imit_ctx *c = ctx->md_data; - memset(c,0,sizeof(struct ossl_gost_imit_ctx)); - gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet); - return 1; - } -#endif int gost_imit_init_cpa(EVP_MD_CTX *ctx) { @@ -612,14 +536,15 @@ int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) if (bytes>0) { memcpy(c->partial_block,p,bytes); - c->bytes_left=bytes; } + c->bytes_left=bytes; return 1; } int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) { struct ossl_gost_imit_ctx *c = ctx->md_data; + if (!c->key_set) return 0; if (c->bytes_left) { int i; @@ -630,7 +555,6 @@ int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) mac_block_mesh(c,c->partial_block); } get_mac(c->buffer,32,md); - if (!c->key_set) return 0; return 1; } diff --git a/engines/ccgost/gost_ctl.c b/engines/ccgost/gost_ctl.c index d94089b9cb..85c2a0f2a4 100644 --- a/engines/ccgost/gost_ctl.c +++ b/engines/ccgost/gost_ctl.c @@ -34,6 +34,17 @@ const ENGINE_CMD_DEFN gost_cmds[]= {0,NULL,NULL,0} }; +void gost_param_free() +{ + int i; + for (i=0;i<=GOST_PARAM_MAX;i++) + if (gost_params[i]!=NULL) + { + OPENSSL_free(gost_params[i]); + gost_params[i]=NULL; + } + +} int gost_control_func(ENGINE *e,int cmd,long i, void *p, void (*f)(void)) { @@ -55,6 +66,7 @@ const char *get_gost_engine_param(int param) tmp = getenv(gost_envnames[param]); if (tmp) { + if (gost_params[param]) OPENSSL_free(gost_params[param]); gost_params[param] = BUF_strdup(tmp); return gost_params[param]; } @@ -68,7 +80,7 @@ int gost_set_default_param(int param, const char *value) tmp = getenv(gost_envnames[param]); /* if there is value in the environment, use it, else -passed string * */ if (!tmp) tmp=value; - if (gost_params[param]) free(gost_params[param]); + if (gost_params[param]) OPENSSL_free(gost_params[param]); gost_params[param] = BUF_strdup(tmp); return 1; diff --git a/engines/ccgost/gost_eng.c b/engines/ccgost/gost_eng.c index daa397f6cc..6acc508832 100644 --- a/engines/ccgost/gost_eng.c +++ b/engines/ccgost/gost_eng.c @@ -37,15 +37,15 @@ static int gost_digest_nids[] = {NID_id_GostR3411_94,NID_id_Gost28147_89_MAC, 0}; static int gost_pkey_meth_nids[] = - {NID_id_GostR3410_94_cc, NID_id_GostR3410_94, NID_id_GostR3410_2001_cc, + {NID_id_GostR3410_94, NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0}; -static EVP_PKEY_METHOD *pmeth_GostR3410_94_cc = NULL, *pmeth_GostR3410_94 = NULL, - *pmeth_GostR3410_2001_cc = NULL, *pmeth_GostR3410_2001 = NULL, +static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL, + *pmeth_GostR3410_2001 = NULL, *pmeth_Gost28147_MAC = NULL; -static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94_cc = NULL, *ameth_GostR3410_94 = NULL, - *ameth_GostR3410_2001_cc = NULL, *ameth_GostR3410_2001 = NULL, +static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL, + *ameth_GostR3410_2001 = NULL, *ameth_Gost28147_MAC = NULL; @@ -61,6 +61,7 @@ static int gost_engine_finish(ENGINE *e) static int gost_engine_destroy(ENGINE *e) { + gost_param_free(); return 1; } @@ -117,16 +118,12 @@ static int bind_gost (ENGINE *e,const char *id) goto end; } - if (!register_ameth_gost(NID_id_GostR3410_94_cc, &ameth_GostR3410_94_cc, "GOST94CC", "GOST R 34.10-94, Cryptocom LTD implementation")) goto end; if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end; - if (!register_ameth_gost(NID_id_GostR3410_2001_cc, &ameth_GostR3410_2001_cc, "GOST2001CC", "GOST R 34.10-2001, Cryptocom LTD implementation")) goto end; if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end; if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC, "GOST-MAC", "GOST 28147-89 MAC")) goto end; - if (!register_pmeth_gost(NID_id_GostR3410_94_cc, &pmeth_GostR3410_94_cc, 0)) goto end; if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end; - if (!register_pmeth_gost(NID_id_GostR3410_2001_cc, &pmeth_GostR3410_2001_cc, 0)) goto end; if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end; if (!register_pmeth_gost(NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0)) goto end; @@ -212,14 +209,12 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth, if (!pmeth) { *nids = gost_pkey_meth_nids; - return 5; + return 3; } switch (nid) { - case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1; case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1; - case NID_id_GostR3410_2001_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1; case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1; case NID_id_Gost28147_89_MAC: *pmeth = pmeth_Gost28147_MAC; return 1; default:; @@ -235,13 +230,11 @@ static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, if (!ameth) { *nids = gost_pkey_meth_nids; - return 5; + return 3; } switch (nid) { - case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1; case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1; - case NID_id_GostR3410_2001_cc: *ameth = ameth_GostR3410_2001_cc; return 1; case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1; case NID_id_Gost28147_89_MAC: *ameth = ameth_Gost28147_MAC; return 1; diff --git a/engines/ccgost/gost_lcl.h b/engines/ccgost/gost_lcl.h index 8026a2de9e..6a67f05123 100644 --- a/engines/ccgost/gost_lcl.h +++ b/engines/ccgost/gost_lcl.h @@ -28,6 +28,7 @@ int gost_control_func(ENGINE *e,int cmd, long i, void *p, void (*f)(void)); const char *get_gost_engine_param(int param); int gost_set_default_param(int param, const char *value); + void gost_param_free(void); /* method registration */ @@ -45,8 +46,8 @@ /* Pmeth internal representation */ struct gost_pmeth_data { int sign_param_nid; /* Should be set whenever parameters are filled */ - EVP_PKEY *eph_seckey; EVP_MD *md; + unsigned char *shared_ukm; }; struct gost_mac_pmeth_data { @@ -146,37 +147,22 @@ const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj); /* Implementation of GOST 28147-89 cipher in CFB and CNT modes */ extern EVP_CIPHER cipher_gost; extern EVP_CIPHER cipher_gost_cpacnt; -#ifdef USE_SSL -#define EVP_MD_FLAG_NEEDS_KEY 0x20 -#define EVP_MD_CTRL_GET_TLS_MAC_KEY_LENGTH (EVP_MD_CTRL_ALG_CTRL+1) -#define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+2) -/* Ciphers and MACs specific for GOST TLS draft */ -extern EVP_CIPHER cipher_gost_vizircfb; -extern EVP_CIPHER cipher_gost_cpacnt; -extern EVP_MD imit_gost_vizir; -extern EVP_MD imit_gost_cpa; -#endif #define EVP_MD_CTRL_KEY_LEN (EVP_MD_CTRL_ALG_CTRL+3) #define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+4) /* EVP_PKEY_METHOD key encryption callbacks */ /* From gost94_keyx.c */ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ); -int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len); int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len ); -int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * in,size_t in_len); /* From gost2001_keyx.c */ int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ); -int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len); int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len ); -int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * in,size_t in_len); - -/* Internal functions to make error processing happy */ -int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len, - const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx); -int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len, - unsigned char *crypted_key, gost_ctx *ctx); +/* derive functions */ +/* From gost2001_keyx.c */ +int pkey_gost2001_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); +/* From gost94_keyx.c */ +int pkey_gost94_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); /* Internal functions for signature algorithms */ int fill_GOST94_params(DSA *dsa,int nid); int fill_GOST2001_params(EC_KEY *eckey, int nid); @@ -201,17 +187,14 @@ BIGNUM *hashsum2bn(const unsigned char *dgst) ; int store_bignum(BIGNUM *bn, unsigned char *buf,int len); /* Read bignum, which can have few MSB all-zeros from buffer*/ BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len); -/* Pack GOST R 34.10 signature according to CryptoCom rules */ -int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen); /* Pack GOST R 34.10 signature according to CryptoPro rules */ int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen); -/* Unpack GOST R 34.10 signature according to CryptoCom rules */ -DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) ; /* Unpack GOST R 34.10 signature according to CryptoPro rules */ DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen) ; /* from ameth.c */ /* Get private key as BIGNUM from both R 34.10-94 and R 34.10-2001 keys*/ -BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) ; +/* Returns pointer into EVP_PKEY structure */ +BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey) ; /* Find NID by GOST 94 parameters */ int gost94_nid_by_params(DSA *p) ; diff --git a/engines/ccgost/gost_md.c b/engines/ccgost/gost_md.c index 294a624d7d..417e10887b 100644 --- a/engines/ccgost/gost_md.c +++ b/engines/ccgost/gost_md.c @@ -59,9 +59,11 @@ int gost_digest_final(EVP_MD_CTX *ctx,unsigned char *md) int gost_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) { - if (to->md_data && from->md_data) - memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_digest_ctx)); - + struct ossl_gost_digest_ctx *md_ctx=to->md_data; + if (to->md_data && from->md_data) { + memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_digest_ctx)); + md_ctx->dctx.cipher_ctx=&(md_ctx->cctx); + } return 1; } diff --git a/engines/ccgost/gost_pmeth.c b/engines/ccgost/gost_pmeth.c index 621c209b42..4f96a7508b 100644 --- a/engines/ccgost/gost_pmeth.c +++ b/engines/ccgost/gost_pmeth.c @@ -40,10 +40,9 @@ static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) src_data = EVP_PKEY_CTX_get_data(src); dst_data = EVP_PKEY_CTX_get_data(dst); *dst_data = *src_data; - if (src_data -> eph_seckey) - { - dst_data ->eph_seckey = NULL; - } + if (src_data -> shared_ukm) { + dst_data->shared_ukm=NULL; + } return 1; } @@ -51,7 +50,7 @@ static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); - if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey); + if (data->shared_ukm) OPENSSL_free(data->shared_ukm); OPENSSL_free(data); } @@ -81,33 +80,15 @@ static int pkey_gost_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_GOST_PARAMSET: pctx->sign_param_nid = (int)p1; return 1; + case EVP_PKEY_CTRL_SET_IV: + pctx->shared_ukm=OPENSSL_malloc((int)p1); + memcpy(pctx->shared_ukm,p2,(int) p1); + return 1; } return -2; } -static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) - { - if(!strcmp(type, param_ctrl_string)) - { - return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, - NID_id_GostR3410_94_CryptoPro_A_ParamSet, - NULL); - } - return -2; - } - -static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) - { - if(!strcmp(type, param_ctrl_string)) - { - return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, - NID_id_GostR3410_2001_ParamSet_cc,NULL); - } - return -2; - } static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) @@ -257,23 +238,18 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx, } /* --------------------- key generation --------------------------------*/ -/* Generates GOST 94 key and assigns it setting specified type */ -static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type) + + +/* Generates Gost_R3410_94_cp key */ +static int pkey_gost94cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); DSA *dsa=NULL; if (data->sign_param_nid == NID_undef) { - if (type== NID_id_GostR3410_94_cc) - { - data->sign_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet; - } - else - { GOSTerr(GOST_F_PKEY_GOST94_KEYGEN, GOST_R_NO_PARAMETERS_SET); return 0; - } } dsa = DSA_new(); if (!fill_GOST94_params(dsa,data->sign_param_nid)) @@ -282,38 +258,20 @@ static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type) return 0; } gost_sign_keygen(dsa); - EVP_PKEY_assign(pkey,type,dsa); + EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa); return 1; } -/* Generates Gost_R3410_94_cc key */ -static int pkey_gost94cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94_cc); - } - -/* Generates Gost_R3410_94_cp key */ -static int pkey_gost94cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94); - } - /* Generates GOST_R3410 2001 key and assigns it using specified type */ -static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type) +static int pkey_gost01cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); EC_KEY *ec=NULL; if (data->sign_param_nid == NID_undef) { - if (type == NID_id_GostR3410_2001_cc) - { - data->sign_param_nid = NID_id_GostR3410_2001_ParamSet_cc; - } - else { GOSTerr(GOST_F_PKEY_GOST01_KEYGEN, GOST_R_NO_PARAMETERS_SET); return 0; - } } ec = EC_KEY_new(); if (!fill_GOST2001_params(ec,data->sign_param_nid)) @@ -323,41 +281,13 @@ static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type) } gost2001_keygen(ec); - EVP_PKEY_assign(pkey,type,ec); + EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec); return 1; } -/* Generates GOST R3410 2001_cc key */ -static int pkey_gost01cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001_cc); - } -/* Generates GOST R3410 2001_cp key */ -static int pkey_gost01cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001); - } /* ----------- sign callbacks --------------------------------------*/ -static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, - const unsigned char *tbs, size_t tbs_len) - { - 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_cc(unpacked_sig,32,sig,siglen); - } static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbs_len) @@ -378,25 +308,6 @@ static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si return pack_sign_cp(unpacked_sig,32,sig,siglen); } -static int pkey_gost01_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, - const unsigned char *tbs, size_t tbs_len) - { - 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 curve order*/ - return 1; - } - unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey)); - if (!unpacked_sig) - { - return 0; - } - return pack_sign_cc(unpacked_sig,32,sig,siglen); - } - static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbs_len) { @@ -417,17 +328,6 @@ static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si } /* ------------------- verify callbacks ---------------------------*/ -static int pkey_gost94_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, - size_t siglen, const unsigned char *tbs, size_t tbs_len) - { - int ok = 0; - EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); - DSA_SIG *s=unpack_cc_signature(sig,siglen); - 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; - } 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) @@ -441,24 +341,6 @@ static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, return ok; } -static int pkey_gost01_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, - size_t siglen, const unsigned char *tbs, size_t tbs_len) - { - int ok = 0; - EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); - DSA_SIG *s=unpack_cc_signature(sig,siglen); -#ifdef DEBUG_SIGN - fprintf(stderr,"R="); - BN_print_fp(stderr,s->r); - fprintf(stderr,"\nS="); - BN_print_fp(stderr,s->s); - fprintf(stderr,"\n"); -#endif - if (!s) return 0; - if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key)); - DSA_SIG_free(s); - return ok; - } static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbs_len) @@ -483,31 +365,13 @@ static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, /* Generates ephermeral key */ static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx) { - struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); - EVP_PKEY *eph_key = EVP_PKEY_new(); - EVP_PKEY *old_key =EVP_PKEY_CTX_get0_pkey(ctx); - - if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey); - EVP_PKEY_assign(eph_key,EVP_PKEY_base_id(old_key),NULL); - if (!EVP_PKEY_copy_parameters(eph_key,old_key)) return 0; - switch (EVP_PKEY_base_id(old_key)) - { - case NID_id_GostR3410_2001: - case NID_id_GostR3410_2001_cc: - gost2001_keygen(EVP_PKEY_get0(eph_key)); - break; - case NID_id_GostR3410_94: - case NID_id_GostR3410_94_cc: - gost_sign_keygen(EVP_PKEY_get0(eph_key)); - break; - - - } - - - data->eph_seckey=eph_key; return 1; } +/* --------------- Derive init ------------------------------------*/ +int pkey_gost_derive_init(EVP_PKEY_CTX *ctx) +{ + return 1; +} /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/ static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx) { @@ -670,15 +534,6 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) switch (id) { - case NID_id_GostR3410_94_cc: - EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94cc_str); - EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cc_keygen); - EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cc_sign); - EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cc_verify); - EVP_PKEY_meth_set_encrypt(*pmeth, - pkey_gost_encrypt_init, pkey_GOST94cc_encrypt); - EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cc_decrypt); - break; case NID_id_GostR3410_94: EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94_str); EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cp_keygen); @@ -687,21 +542,9 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) EVP_PKEY_meth_set_encrypt(*pmeth, pkey_gost_encrypt_init, pkey_GOST94cp_encrypt); EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt); - - - break; - case NID_id_GostR3410_2001_cc: - EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01cc_str); - EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cc_sign); - EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cc_verify); - - EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cc_keygen); - - EVP_PKEY_meth_set_encrypt(*pmeth, - pkey_gost_encrypt_init, pkey_GOST01cc_encrypt); - EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cc_decrypt); + EVP_PKEY_meth_set_derive(*pmeth, + pkey_gost_derive_init, pkey_gost94_derive); break; - /* There is intentionally no break here */ case NID_id_GostR3410_2001: EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str); EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign); @@ -712,6 +555,8 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) EVP_PKEY_meth_set_encrypt(*pmeth, pkey_gost_encrypt_init, pkey_GOST01cp_encrypt); EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt); + EVP_PKEY_meth_set_derive(*pmeth, + pkey_gost_derive_init, pkey_gost2001_derive); break; case NID_id_Gost28147_89_MAC: EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str); |