提交 0e1dba93 编写于 作者: D Dr. Stephen Henson

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
上级 11d01d37
......@@ -4,6 +4,10 @@
Changes between 0.9.8g and 0.9.9 [xx XXX xxxx]
*) Implement remaining functionality needed to support GOST ciphersuites.
Interop testing has been performed using CryptoPro implementations.
[Victor B. Wagner <vitus@cryptocom.ru>]
*) s390x assembler pack.
[Andy Polyakov]
......
......@@ -1278,6 +1278,7 @@ SSL_set_tlsext_status_ids(con, ids);
if (cbuf_len != 0)
{
BIO_printf(bio_c_out,"shutdown\n");
ret = 0;
goto shut;
}
else
......@@ -1320,6 +1321,7 @@ SSL_set_tlsext_status_ids(con, ids);
if (i <= 0)
{
BIO_printf(bio_c_out,"DONE\n");
ret = 0;
goto shut;
/* goto end; */
}
......@@ -1374,10 +1376,12 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240
BIO_printf(bio_c_out,"read X BLOCK\n");
break;
case SSL_ERROR_SYSCALL:
BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
ret=get_last_socket_error();
BIO_printf(bio_err,"read:errno=%d\n",ret);
goto shut;
case SSL_ERROR_ZERO_RETURN:
BIO_printf(bio_c_out,"closed\n");
ret=0;
goto shut;
case SSL_ERROR_SSL:
ERR_print_errors(bio_err);
......@@ -1428,6 +1432,7 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240
if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
{
BIO_printf(bio_err,"DONE\n");
ret=0;
goto shut;
}
......@@ -1450,12 +1455,13 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240
read_tty=0;
}
}
ret=0;
shut:
if (in_init)
print_stuff(bio_c_out,con,full_log);
SSL_shutdown(con);
SHUTDOWN(SSL_get_fd(con));
ret=0;
end:
if (con != NULL)
{
......
......@@ -196,7 +196,11 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_PKCS7_SIGN:
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
DSAerr(DSA_F_PKEY_DSA_CTRL,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
default:
return -2;
......
......@@ -1016,8 +1016,12 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
#define EVP_PKEY_CTRL_DIGESTINIT 7
/* Used by GOST key encryption in TLS */
#define EVP_PKEY_CTRL_SET_IV 8
#define EVP_PKEY_ALG_CTRL 0x1000
#define EVP_PKEY_FLAG_AUTOARGLEN 2
const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
......@@ -1045,6 +1049,8 @@ void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
......
......@@ -285,13 +285,13 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
{
int ret;
if (!ctx || !ctx->pmeth || !ctx->pmeth->derive || !ctx->pmeth->ctrl)
if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive||ctx->pmeth->encrypt) || !ctx->pmeth->ctrl)
{
EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
if (ctx->operation != EVP_PKEY_OP_DERIVE)
if (ctx->operation != EVP_PKEY_OP_DERIVE && ctx->operation != EVP_PKEY_OP_ENCRYPT)
{
EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_OPERATON_NOT_INITIALIZED);
......
......@@ -390,6 +390,11 @@ EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
return ctx->pkey;
}
EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx)
{
return ctx->peerkey;
}
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
{
ctx->app_data = data;
......
......@@ -116,7 +116,8 @@ static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx)
HMAC_CTX_cleanup(&hctx->ctx);
if (hctx->ktmp.data)
{
OPENSSL_cleanse(hctx->ktmp.data, hctx->ktmp.length);
if (hctx->ktmp.length)
OPENSSL_cleanse(hctx->ktmp.data, hctx->ktmp.length);
OPENSSL_free(hctx->ktmp.data);
hctx->ktmp.data = NULL;
}
......
......@@ -436,6 +436,10 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
case EVP_PKEY_CTRL_PKCS7_SIGN:
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
RSAerr(RSA_F_PKEY_RSA_CTRL,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
default:
return -2;
......
......@@ -91,6 +91,10 @@ int X509_certificate_type(X509 *x, EVP_PKEY *pkey)
break;
case EVP_PKEY_DH:
ret=EVP_PK_DH|EVP_PKT_EXCH;
break;
case NID_id_GostR3410_94:
case NID_id_GostR3410_2001:
ret=EVP_PKT_EXCH|EVP_PKT_SIGN;
break;
default:
break;
......
......@@ -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}
......
......@@ -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
......
......@@ -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;
}
......@@ -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;
}
......@@ -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,
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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) ;
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -120,7 +120,9 @@
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
#ifdef KSSL_DEBUG
#include <openssl/des.h>
#endif
int dtls1_enc(SSL *s, int send)
{
......
......@@ -2378,6 +2378,84 @@ int ssl3_send_client_key_exchange(SSL *s)
EVP_PKEY_free(srvr_pub_pkey);
}
#endif /* !OPENSSL_NO_ECDH */
else if (alg_k & SSL_kGOST)
{
/* GOST key exchange message creation */
EVP_PKEY_CTX *pkey_ctx;
X509 *peer_cert;
size_t msglen;
unsigned int md_len;
int keytype;
unsigned char premaster_secret[32],shared_ukm[32];
EVP_MD_CTX *ukm_hash;
EVP_PKEY *pub_key;
/* Get server sertificate PKEY and create ctx from it */
peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST01)].x509;
if (!peer_cert)
peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST94)].x509;
if (!peer_cert) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
goto err;
}
pkey_ctx=EVP_PKEY_CTX_new(pub_key=X509_get_pubkey(peer_cert),NULL);
/* If we have send a certificate, and certificate key
* parameters match those of server certificate, use
* certificate key for key exchange
*/
/* Otherwise, generate ephemeral key pair */
EVP_PKEY_encrypt_init(pkey_ctx);
/* Generate session key */
RAND_bytes(premaster_secret,32);
/* If we have client certificate, use its secret as peer key */
if (s->cert->key->privatekey) {
if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <0) {
/* If there was an error - just ignore it. Ephemeral key
* would be used
*/
ERR_clear_error();
} else {
/* Set flag "client cert key is used for key
* exchange"*/
}
}
/* Compute shared IV and store it in algorithm-specific
* context data */
ukm_hash = EVP_MD_CTX_create();
EVP_DigestInit(ukm_hash,EVP_get_digestbynid(NID_id_GostR3411_94));
EVP_DigestUpdate(ukm_hash,s->s3->client_random,SSL3_RANDOM_SIZE);
EVP_DigestUpdate(ukm_hash,s->s3->server_random,SSL3_RANDOM_SIZE);
EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
EVP_MD_CTX_destroy(ukm_hash);
if (EVP_PKEY_CTX_ctrl(pkey_ctx,-1,EVP_PKEY_OP_ENCRYPT,EVP_PKEY_CTRL_SET_IV,
8,shared_ukm)<0) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
SSL_R_LIBRARY_BUG);
goto err;
}
/* Make GOST keytransport blob message */
/*Encapsulate it into sequence */
*(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
*(p++)=0x81;
msglen=256;
if (EVP_PKEY_encrypt(pkey_ctx,(unsigned char *)p+1,&msglen,premaster_secret,32)<0) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
SSL_R_LIBRARY_BUG);
goto err;
}
*(p++)= msglen & 0xff;
n=msglen+3;
EVP_PKEY_CTX_free(pkey_ctx);
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,premaster_secret,32);
EVP_PKEY_free(pub_key);
}
#ifndef OPENSSL_NO_PSK
else if (alg_k & SSL_kPSK)
{
......@@ -2496,6 +2574,7 @@ int ssl3_send_client_verify(SSL *s)
unsigned char *p,*d;
unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx=NULL;
#ifndef OPENSSL_NO_RSA
unsigned u=0;
#endif
......@@ -2509,11 +2588,19 @@ int ssl3_send_client_verify(SSL *s)
d=(unsigned char *)s->init_buf->data;
p= &(d[4]);
pkey=s->cert->key->privatekey;
s->method->ssl3_enc->cert_verify_mac(s,
NID_sha1,
&(data[MD5_DIGEST_LENGTH]));
/* Create context from key and test if sha1 is allowed as digest */
pctx = EVP_PKEY_CTX_new(pkey,NULL);
EVP_PKEY_sign_init(pctx);
if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
{
s->method->ssl3_enc->cert_verify_mac(s,
NID_sha1,
&(data[MD5_DIGEST_LENGTH]));
}
else
{
ERR_clear_error();
}
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA)
{
......@@ -2565,10 +2652,30 @@ int ssl3_send_client_verify(SSL *s)
}
else
#endif
{
if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
{
unsigned char signbuf[64];
int i;
size_t sigsize;
s->method->ssl3_enc->cert_verify_mac(s,
NID_id_GostR3411_94,
data);
if (!EVP_PKEY_sign(pctx,signbuf,&sigsize,data,32)) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
ERR_R_INTERNAL_ERROR);
goto err;
}
for (i=63,j=0; i>=0; j++, i--) {
p[2+j]=signbuf[i];
}
s2n(j,p);
n=j+2;
}
else
{
SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
goto err;
}
}
*(d++)=SSL3_MT_CERTIFICATE_VERIFY;
l2n3(n,d);
......@@ -2576,8 +2683,10 @@ int ssl3_send_client_verify(SSL *s)
s->init_num=(int)n+4;
s->init_off=0;
}
EVP_PKEY_CTX_free(pctx);
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
err:
EVP_PKEY_CTX_free(pctx);
return(-1);
}
......
......@@ -1287,6 +1287,62 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
128,
},
#endif
{
1,
"GOST94-GOST89-GOST89",
0x3000080,
SSL_kGOST,
SSL_aGOST94,
SSL_eGOST2814789CNT,
SSL_GOST89MAC,
SSL_TLSV1,
SSL_NOT_EXP|SSL_HIGH,
SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC,
256,
256
},
{
1,
"GOST2001-GOST89-GOST89",
0x3000081,
SSL_kGOST,
SSL_aGOST01,
SSL_eGOST2814789CNT,
SSL_GOST89MAC,
SSL_TLSV1,
SSL_NOT_EXP|SSL_HIGH,
SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94|TLS1_STREAM_MAC,
256,
256
},
{
1,
"GOST94-NULL-GOST94",
0x3000082,
SSL_kGOST,
SSL_aGOST94,
SSL_eNULL,
SSL_GOST94,
SSL_TLSV1,
SSL_NOT_EXP|SSL_STRONG_NONE,
SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94,
0,
0
},
{
1,
"GOST2001-NULL-GOST94",
0x3000083,
SSL_kGOST,
SSL_aGOST01,
SSL_eNULL,
SSL_GOST94,
SSL_TLSV1,
SSL_NOT_EXP|SSL_STRONG_NONE,
SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94,
0,
0
},
#ifndef OPENSSL_NO_CAMELLIA
/* Camellia ciphersuites from RFC4132 (256-bit portion) */
......@@ -2820,7 +2876,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
emask_a = cert->export_mask_a;
#ifdef KSSL_DEBUG
printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);
/* printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);*/
#endif /* KSSL_DEBUG */
alg_k=c->algorithm_mkey;
......
......@@ -511,6 +511,8 @@ int ssl3_accept(SSL *s)
}
else
{
int offset=0;
int dgst_num;
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
......@@ -519,13 +521,14 @@ int ssl3_accept(SSL *s)
* FIXME - digest processing for CertificateVerify
* should be generalized. But it is next step
*/
s->method->ssl3_enc->cert_verify_mac(s,
NID_md5,
&(s->s3->tmp.cert_verify_md[0]));
s->method->ssl3_enc->cert_verify_mac(s,
NID_sha1,
&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
if (s->s3->handshake_buffer)
ssl3_digest_cached_records(s);
for (dgst_num=0; dgst_num<SSL_MAX_DIGEST;dgst_num++)
if (s->s3->handshake_dgst[dgst_num])
{
s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
offset+=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
}
}
break;
......@@ -1181,7 +1184,6 @@ int ssl3_send_server_hello(SSL *s)
return -1;
}
#endif
/* do the header */
l=(p-d);
d=buf;
......@@ -2398,6 +2400,35 @@ int ssl3_get_client_key_exchange(SSL *s)
}
else
#endif
if (alg_k & SSL_kGOST)
{
EVP_PKEY_CTX *pkey_ctx;
unsigned char premaster_secret[32];
size_t outlen;
/* Get our certificate privatec key*/
pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL);
EVP_PKEY_decrypt_init(pkey_ctx);
/* Decrypt session key */
if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)) || p[1]!=0x81 )
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
goto err;
}
if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,p+3,p[2]) <0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
goto err;
}
/* Generate master secret */
EVP_PKEY_CTX_free(pkey_ctx);
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,premaster_secret,32);
}
else
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
......@@ -2487,15 +2518,25 @@ int ssl3_get_cert_verify(SSL *s)
/* we now have a signature that we need to verify */
p=(unsigned char *)s->init_msg;
n2s(p,i);
n-=2;
if (i > n)
/* Check for broken implementations of GOST ciphersuites */
/* If key is GOST and n is exactly 64, it is bare
* signature without length field */
if (n==64 && (pkey->type==NID_id_GostR3410_94 ||
pkey->type == NID_id_GostR3410_2001) )
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
i=64;
}
else
{
n2s(p,i);
n-=2;
if (i > n)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
}
j=EVP_PKEY_size(pkey);
if ((i > j) || (n > j) || (n <= 0))
{
......@@ -2558,6 +2599,28 @@ int ssl3_get_cert_verify(SSL *s)
}
else
#endif
if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
{ unsigned char signature[64];
int idx;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey,NULL);
EVP_PKEY_verify_init(pctx);
if (i!=64) {
fprintf(stderr,"GOST signature length is %d",i);
}
for (idx=0;idx<64;idx++) {
signature[63-idx]=p[idx];
}
j=EVP_PKEY_verify(pctx,signature,64,s->s3->tmp.cert_verify_md,32);
EVP_PKEY_CTX_free(pctx);
if (j<=0)
{
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
SSL_R_BAD_ECDSA_SIGNATURE);
goto f_err;
}
}
else
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
al=SSL_AD_UNSUPPORTED_CERTIFICATE;
......
......@@ -249,6 +249,7 @@ extern "C" {
#define SSL_TXT_kECDH "kECDH"
#define SSL_TXT_kEECDH "kEECDH"
#define SSL_TXT_kPSK "kPSK"
#define SSL_TXT_kGOST "kGOST"
#define SSL_TXT_aRSA "aRSA"
#define SSL_TXT_aDSS "aDSS"
......@@ -257,6 +258,9 @@ extern "C" {
#define SSL_TXT_aKRB5 "aKRB5"
#define SSL_TXT_aECDSA "aECDSA"
#define SSL_TXT_aPSK "aPSK"
#define SSL_TXT_aGOST94 "aGOST94"
#define SSL_TXT_aGOST01 "aGOST01"
#define SSL_TXT_aGOST "aGOST"
#define SSL_TXT_DSS "DSS"
#define SSL_TXT_DH "DH"
......@@ -527,7 +531,7 @@ typedef struct ssl_session_st
/* SSL_OP_ALL: various bug workarounds that should be rather harmless.
* This used to be 0x000FFFFFL before 0.9.7. */
#define SSL_OP_ALL 0x00000FFFL
#define SSL_OP_ALL 0x80000FFFL
/* DTLS options */
#define SSL_OP_NO_QUERY_MTU 0x00001000L
......@@ -566,7 +570,11 @@ typedef struct ssl_session_st
#define SSL_OP_PKCS1_CHECK_2 0x10000000L
#define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
/* Make server add server-hello extension from early version of
* cryptopro draft, when GOST ciphersuite is negotiated.
* Required for interoperability with CryptoPro CSP 3.x
*/
#define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000L
/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
* when just a single record has been written): */
......@@ -1912,7 +1920,10 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_PRF 284
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
#define SSL_F_TLS1_FINAL_FINISH_MAC 283
#define SSL_F_TLS1_PRF 284
#define SSL_F_SSL3_HANDSHAKE_MAC 285
#define SSL_F_TLS1_CERT_VERIFY_MAC 286
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
......@@ -2172,7 +2183,8 @@ void ERR_load_SSL_strings(void);
#define SSL_R_WRONG_VERSION_NUMBER 267
#define SSL_R_X509_LIB 268
#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269
#define SSL_R_NO_REQUIRED_DIGEST 324
#define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 330
#ifdef __cplusplus
}
#endif
......
......@@ -243,7 +243,7 @@ static const SSL_CIPHER cipher_aliases[]={
{0,SSL_TXT_ECDH,0, SSL_kECDHr|SSL_kECDHe|SSL_kEECDH,0,0,0,0,0,0,0,0},
{0,SSL_TXT_kPSK,0, SSL_kPSK, 0,0,0,0,0,0,0,0},
{0,SSL_TXT_kGOST,0, SSL_kGOST,0,0,0,0,0,0,0,0},
/* server authentication aliases */
{0,SSL_TXT_aRSA,0, 0,SSL_aRSA, 0,0,0,0,0,0,0},
......@@ -256,7 +256,9 @@ static const SSL_CIPHER cipher_aliases[]={
{0,SSL_TXT_aECDSA,0, 0,SSL_aECDSA,0,0,0,0,0,0,0},
{0,SSL_TXT_ECDSA,0, 0,SSL_aECDSA, 0,0,0,0,0,0,0},
{0,SSL_TXT_aPSK,0, 0,SSL_aPSK, 0,0,0,0,0,0,0},
{0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0},
{0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0},
{0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0},
/* aliases combining key exchange and server authentication */
{0,SSL_TXT_EDH,0, SSL_kEDH,~SSL_aNULL,0,0,0,0,0,0,0},
......
......@@ -260,6 +260,10 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_PRF), "TLS1_PRF"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
{ERR_FUNC(SSL_F_TLS1_FINAL_FINISH_MAC),"tls1_final_finish_mac"},
{ERR_FUNC(SSL_F_TLS1_PRF),"tls1_prf"},
{ERR_FUNC(SSL_F_SSL3_HANDSHAKE_MAC),"ssl3_handshake_mac"},
{ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC),"tls1_cert_verify_mac"},
{0,NULL}
};
......@@ -523,6 +527,9 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_WRONG_VERSION_NUMBER) ,"wrong version number"},
{ERR_REASON(SSL_R_X509_LIB) ,"x509 lib"},
{ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"},
{ERR_REASON(SSL_R_UNSUPPORTED_DIGEST_TYPE),"unsupported digest type"},
{ERR_REASON(SSL_R_NO_REQUIRED_DIGEST),"digest requred for handshake isn't computed"},
{ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER),"Peer haven't sent GOST certificate, required for selected ciphersuite"},
{0,NULL}
};
......
......@@ -1742,11 +1742,24 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
emask_k=0;
emask_a=0;
#ifdef CIPHER_DEBUG
printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp,
rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);
#endif
cpk = &(c->pkeys[SSL_PKEY_GOST01]);
if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST01;
}
cpk = &(c->pkeys[SSL_PKEY_GOST94]);
if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST94;
}
if (rsa_enc || (rsa_tmp && rsa_sign))
mask_k|=SSL_kRSA;
......@@ -2015,6 +2028,10 @@ X509 *ssl_get_server_send_cert(SSL *s)
/* VRS something else here? */
return(NULL);
}
else if (alg_a & SSL_aGOST94)
i=SSL_PKEY_GOST94;
else if (alg_a & SSL_aGOST01)
i=SSL_PKEY_GOST01;
else /* if (alg_a & SSL_aNULL) */
{
SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR);
......
......@@ -141,6 +141,9 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#ifdef KSSL_DEBUG
#include <openssl/des.h>
#endif
/* seed1 through seed5 are virtually concatenated */
static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
......@@ -878,9 +881,8 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
EVP_DigestSignUpdate(mac_ctx,buf,5);
EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
if (stream_mac) EVP_MD_CTX_copy(&hmac,hash);
EVP_DigestSignFinal(&hmac,md,&md_size);
EVP_MD_CTX_cleanup(&hmac);
EVP_DigestSignFinal(mac_ctx,md,&md_size);
if (!stream_mac) EVP_MD_CTX_cleanup(&hmac);
#ifdef TLS_DEBUG
printf("sec=");
{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
......
......@@ -514,6 +514,20 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
ret += sol;
}
#endif
if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81)
&& (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG))
{ const unsigned char cryptopro_ext[36] = {
0xfd, 0xe8, /*65000*/
0x00, 0x20, /*32 bytes length*/
0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17};
if (limit-ret<36) return NULL;
memcpy(ret,cryptopro_ext,36);
ret+=36;
}
if ((extdatalen = ret-p-2)== 0)
return p;
......@@ -545,7 +559,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
if (data+size > (d+n))
return 1;
fprintf(stderr,"Received extension type %d size %d\n",type,size);
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 0, type, data, size,
s->tlsext_debug_arg);
......
......@@ -3933,3 +3933,4 @@ TS_TST_INFO_get_ext_by_critical 4314 EXIST::FUNCTION:
EVP_PKEY_CTX_new_id 4315 EXIST::FUNCTION:
TS_REQ_get_ext_by_OBJ 4316 EXIST::FUNCTION:
TS_CONF_set_signer_cert 4317 EXIST::FUNCTION:
EVP_PKEY_CTX_get0_peerkey 4318 EXIST::FUNCTION:
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册