* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#include <openssl/evp.h>
+#include <openssl/err.h>
#include <openssl/rand.h>
#include <string.h>
#include <openssl/objects.h>
const EC_POINT *pub_key, EC_KEY *priv_key,
const unsigned char *ukm, int dgst_nid)
{
- unsigned char *databuf = NULL, *hashbuf = NULL;
+ unsigned char *databuf = NULL;
BIGNUM *UKM = NULL, *p = NULL, *order = NULL, *X = NULL, *Y = NULL;
const BIGNUM *key = EC_KEY_get0_private_key(priv_key);
EC_POINT *pnt = EC_POINT_new(EC_KEY_get0_group(priv_key));
int i;
BN_CTX *ctx = BN_CTX_new();
- EVP_MD_CTX mdctx;
- const EVP_MD *md;
+ EVP_MD_CTX *mdctx = NULL;
+ const EVP_MD *md = NULL;
int effective_dgst_nid = (dgst_nid == NID_id_GostR3411_2012_512) ?
NID_id_GostR3411_2012_256 : dgst_nid;
int buf_len = (dgst_nid == NID_id_GostR3411_2012_512) ? 128 : 64,
half_len = buf_len >> 1;
+ int ret = 0;
if (!ctx) {
- GOSTerr(GOST_F_VKO_COMPUTE_KEY, GOST_R_NO_MEMORY);
+ GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
return 0;
}
BN_CTX_start(ctx);
- databuf = OPENSSL_malloc(buf_len);
- hashbuf = OPENSSL_malloc(buf_len);
- if (!databuf || !hashbuf) {
- GOSTerr(GOST_F_VKO_COMPUTE_KEY, GOST_R_MALLOC_FAILURE);
+ databuf = OPENSSL_zalloc(buf_len);
+ if (!databuf) {
+ GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
goto err;
}
Y = BN_CTX_get(ctx);
EC_GROUP_get_order(EC_KEY_get0_group(priv_key), order, ctx);
BN_mod_mul(p, key, UKM, order, ctx);
- EC_POINT_mul(EC_KEY_get0_group(priv_key), pnt, NULL, pub_key, p, ctx);
+ if (!EC_POINT_mul
+ (EC_KEY_get0_group(priv_key), pnt, NULL, pub_key, p, ctx)) {
+ GOSTerr(GOST_F_VKO_COMPUTE_KEY, GOST_R_ERROR_POINT_MUL);
+ goto err;
+ }
EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(priv_key),
pnt, X, Y, ctx);
/*
store_bignum(Y, databuf, half_len);
store_bignum(X, databuf + half_len, half_len);
/* And reverse byte order of whole buffer */
- for (i = 0; i < buf_len; i++) {
- hashbuf[buf_len - 1 - i] = databuf[i];
+ BUF_reverse(databuf, NULL, buf_len);
+
+ mdctx = EVP_MD_CTX_new();
+ if (!mdctx) {
+ GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ goto err;
}
- EVP_MD_CTX_init(&mdctx);
- EVP_DigestInit_ex(&mdctx, md, NULL);
- EVP_DigestUpdate(&mdctx, hashbuf, buf_len);
- EVP_DigestFinal_ex(&mdctx, shared_key, NULL);
- EVP_MD_CTX_cleanup(&mdctx);
+ EVP_MD_CTX_init(mdctx);
+ EVP_DigestInit_ex(mdctx, md, NULL);
+ EVP_DigestUpdate(mdctx, databuf, buf_len);
+ EVP_DigestFinal_ex(mdctx, shared_key, NULL);
+ ret = 32;
+
err:
BN_free(UKM);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
+
EC_POINT_free(pnt);
- if (databuf)
- OPENSSL_free(databuf);
- if (hashbuf)
- OPENSSL_free(hashbuf);
- return 32;
+ EVP_MD_CTX_free(mdctx);
+
+ OPENSSL_free(databuf);
+
+ return ret;
}
/*
if (key == NULL) {
*keylen = 32;
- return 32;
+ return 1;
}
EVP_PKEY_get_default_digest_nid(my_key, &dgst_nid);
return (*keylen) ? 1 : 0;
}
-/*
- * 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
} else if (out) {
if (RAND_bytes(ukm, 8) <= 0) {
- GOSTerr(GOST_F_PKEY_GOST_ECCP_ENCRYPT,
- GOST_R_RANDOM_GENERATOR_FAILURE);
+ GOSTerr(GOST_F_PKEY_GOST_ECCP_ENCRYPT, GOST_R_RNG_ERROR);
return 0;
}
}
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 (!gost_ec_keygen(EVP_PKEY_get0(sec_key))) {
+ if (! EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk), EC_KEY_new()) ||
+ ! EVP_PKEY_copy_parameters(sec_key, pubk) ||
+ ! gost_ec_keygen(EVP_PKEY_get0(sec_key))) {
+ GOSTerr(GOST_F_PKEY_GOST_ECCP_ENCRYPT,
+ GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err;
}
}
}
if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS)
&& param == gost_cipher_list) {
- param = gost_cipher_list + 1;
+ param = gost_cipher_list;
}
if (out) {
int dgst_nid = NID_undef;
}
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
- if (key_is_ephemeral && sec_key)
+ if (key_is_ephemeral)
EVP_PKEY_free(sec_key);
if (!key_is_ephemeral) {
/* Set control "public key from client certificate used" */
GOST_KEY_TRANSPORT_free(gkt);
return ret;
err:
- if (key_is_ephemeral && sec_key)
+ if (key_is_ephemeral)
EVP_PKEY_free(sec_key);
GOST_KEY_TRANSPORT_free(gkt);
return -1;
ret = 1;
err:
- if (eph_key)
- EVP_PKEY_free(eph_key);
- if (gkt)
- GOST_KEY_TRANSPORT_free(gkt);
+ EVP_PKEY_free(eph_key);
+ GOST_KEY_TRANSPORT_free(gkt);
return ret;
}