summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--apps/s_client.c10
-rw-r--r--crypto/dsa/dsa_pmeth.c6
-rw-r--r--crypto/evp/evp.h6
-rw-r--r--crypto/evp/pmeth_fn.c4
-rw-r--r--crypto/evp/pmeth_lib.c5
-rw-r--r--crypto/hmac/hm_pmeth.c3
-rw-r--r--crypto/rsa/rsa_pmeth.c4
-rw-r--r--crypto/x509/x509type.c4
-rw-r--r--engines/ccgost/e_gost_err.c4
-rw-r--r--engines/ccgost/e_gost_err.h4
-rw-r--r--engines/ccgost/gost2001_keyx.c431
-rw-r--r--engines/ccgost/gost94_keyx.c374
-rw-r--r--engines/ccgost/gost_ameth.c73
-rw-r--r--engines/ccgost/gost_crypt.c80
-rw-r--r--engines/ccgost/gost_ctl.c14
-rw-r--r--engines/ccgost/gost_eng.c23
-rw-r--r--engines/ccgost/gost_lcl.h35
-rw-r--r--engines/ccgost/gost_md.c8
-rw-r--r--engines/ccgost/gost_pmeth.c203
-rw-r--r--ssl/d1_enc.c4
-rw-r--r--ssl/s3_clnt.c123
-rw-r--r--ssl/s3_lib.c58
-rw-r--r--ssl/s3_srvr.c95
-rw-r--r--ssl/ssl.h20
-rw-r--r--ssl/ssl_ciph.c6
-rw-r--r--ssl/ssl_err.c7
-rw-r--r--ssl/ssl_lib.c17
-rw-r--r--ssl/t1_enc.c8
-rw-r--r--ssl/t1_lib.c16
-rwxr-xr-xutil/libeay.num1
31 files changed, 699 insertions, 951 deletions
diff --git a/CHANGES b/CHANGES
index eccf5e23df..ab2ea4d6f3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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]
diff --git a/apps/s_client.c b/apps/s_client.c
index 3ccaca3330..0c3545a4ca 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -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)
{
diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c
index 935258b24d..646ef3f093 100644
--- a/crypto/dsa/dsa_pmeth.c
+++ b/crypto/dsa/dsa_pmeth.c
@@ -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;
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index 65538d4eac..acb55fafe8 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -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);
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
index d52dc43f07..7dd0f2083a 100644
--- a/crypto/evp/pmeth_fn.c
+++ b/crypto/evp/pmeth_fn.c
@@ -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);
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 6abb951d0c..764271a36d 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -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;
diff --git a/crypto/hmac/hm_pmeth.c b/crypto/hmac/hm_pmeth.c
index 27a5c8ea57..6355a44413 100644
--- a/crypto/hmac/hm_pmeth.c
+++ b/crypto/hmac/hm_pmeth.c
@@ -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;
}
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index 98a8ce44c3..de917c637a 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -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;
diff --git a/crypto/x509/x509type.c b/crypto/x509/x509type.c
index 2cd994c5b0..3385ad3f67 100644
--- a/crypto/x509/x509type.c
+++ b/crypto/x509/x509type.c
@@ -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;
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
- */
<