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]
if (cbuf_len != 0)
{
BIO_printf(bio_c_out,"shutdown\n");
+ ret = 0;
goto shut;
}
else
if (i <= 0)
{
BIO_printf(bio_c_out,"DONE\n");
+ ret = 0;
goto shut;
/* goto end; */
}
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);
if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
{
BIO_printf(bio_err,"DONE\n");
+ ret=0;
goto shut;
}
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)
{
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;
#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);
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);
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);
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;
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;
}
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;
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;
{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"},
{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"},
{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}
#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
#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
#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
#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)
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);
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);
}
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;
}
#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 */
}
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);
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)
{
{
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];
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);
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,
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;
- }
}
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;
switch (pkey_nid)
{
case NID_id_GostR3410_94:
- case NID_id_GostR3410_94_cc:
{
DSA *dsa= EVP_PKEY_get0(pkey);
if (!dsa)
break;
}
case NID_id_GostR3410_2001:
- case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94:
- case NID_id_GostR3410_94_cc:
{
DSA *dsa = EVP_PKEY_get0(pkey);
if (!dsa)
break;
}
case NID_id_GostR3410_2001:
- case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
}
return 1;
}
-BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
+BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey)
{
switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94:
- case NID_id_GostR3410_94_cc:
{
DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
if (!dsa)
return NULL;
}
if (!dsa->priv_key) return NULL;
- return BN_dup(dsa->priv_key);
+ return dsa->priv_key;
break;
}
case NID_id_GostR3410_2001:
- case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
const BIGNUM* priv;
return NULL;
}
if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
- return BN_dup(priv);
+ return (BIGNUM *)priv;
break;
}
}
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);
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,
{
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;
}
eto = EC_KEY_new();
EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
}
- EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom)));
+ EC_KEY_set_group(eto,EC_KEY_get0_group(efrom));
if (EC_KEY_get0_private_key(eto))
{
gost2001_compute_public(eto);
EC_POINT *pub_key;
BIGNUM *X,*Y;
ASN1_OCTET_STRING *octet= NULL;
+ int len;
const EC_GROUP *group;
if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
{
databuf[j]=octet->data[i];
}
- if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc)
- {
- X= getbnfrombuf(databuf,octet->length/2);
- Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
- }
- else
- {
- Y= getbnfrombuf(databuf,octet->length/2);
- X= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
- }
+ len=octet->length/2;
+ ASN1_OCTET_STRING_free(octet);
+
+ Y= getbnfrombuf(databuf,len);
+ X= getbnfrombuf(databuf+len,len);
OPENSSL_free(databuf);
pub_key = EC_POINT_new(group);
if (!EC_POINT_set_affine_coordinates_GFp(group
{
GOSTerr(GOST_F_PUB_DECODE_GOST01,
ERR_R_EC_LIB);
+ EC_POINT_free(pub_key);
+ BN_free(X);
+ BN_free(Y);
return 0;
}
BN_free(X);
{
GOSTerr(GOST_F_PUB_DECODE_GOST01,
ERR_R_EC_LIB);
+ EC_POINT_free(pub_key);
return 0;
}
- /*EC_POINT_free(pub_key);*/
+ EC_POINT_free(pub_key);
return 1;
}
BN_free(order);
databuf = OPENSSL_malloc(data_len);
memset(databuf,0,data_len);
- if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc)
- {
- store_bignum(X,databuf,data_len/2);
- store_bignum(Y,databuf+data_len/2,data_len/2);
- }
- else
- {
- store_bignum(X,databuf+data_len/2,data_len/2);
- store_bignum(Y,databuf,data_len/2);
- }
+
+ store_bignum(X,databuf+data_len/2,data_len/2);
+ store_bignum(Y,databuf,data_len/2);
+
BN_free(X);
BN_free(Y);
octet = ASN1_OCTET_STRING_new();
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,
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,
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);
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);
/* 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,
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,
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)
{
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;
mac_block_mesh(c,c->partial_block);
}
get_mac(c->buffer,32,md);
- if (!c->key_set) return 0;
return 1;
}
{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))
{
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];
}
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;
{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;
static int gost_engine_destroy(ENGINE *e)
{
+ gost_param_free();
return 1;
}
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;
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:;
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;
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 */
/* 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 {
/* 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);
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) ;
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;
}
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;
}
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);
}
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)
}
/* --------------------- 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))
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))
}
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)
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)
{
}
/* ------------------- 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)
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)
/* 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)
{
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);
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);
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);
#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)
{
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)
{
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
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)
{
}
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);
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);
}
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) */
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;
}
else
{
+ int offset=0;
+ int dgst_num;
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
* 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;
return -1;
}
#endif
-
/* do the header */
l=(p-d);
d=buf;
}
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,
/* 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))
{
}
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;
#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"
#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"
/* 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
#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): */
#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
#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
{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},
{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},
{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}
};
{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}
};
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;
/* 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);
#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,
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"); }
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;
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);
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: