]> wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - gost_ec_keyx.c
Refactoring of VKO
[openssl-gost/engine.git] / gost_ec_keyx.c
index c2a465b15c342f188f24eaee584abf95a80faec8..03537a3bb0aecd136b43cdebb75892217d91b1c4 100644 (file)
@@ -8,6 +8,7 @@
  *          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>
 /* Implementation of CryptoPro VKO 34.10-2001/2012 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, int dgst_nid)
+                           const unsigned char *ukm, size_t ukm_size,
+                           int vko_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;
-    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;
+    EVP_MD_CTX *mdctx = NULL;
+    const EVP_MD *md = NULL;
+    int buf_len, half_len;
+    int ret = 0;
 
     if (!ctx) {
         GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
@@ -40,57 +39,65 @@ static int VKO_compute_key(unsigned char *shared_key, size_t shared_key_size,
     }
     BN_CTX_start(ctx);
 
-    databuf = OPENSSL_malloc(buf_len);
-    hashbuf = OPENSSL_malloc(buf_len);
-    if (!databuf || !hashbuf) {
-        GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-
-    md = EVP_get_digestbynid(effective_dgst_nid);
+    md = EVP_get_digestbynid(vko_dgst_nid);
     if (!md) {
         GOSTerr(GOST_F_VKO_COMPUTE_KEY, GOST_R_INVALID_DIGEST_TYPE);
         goto err;
     }
 
-    UKM = hashsum2bn(ukm, 8);
+    UKM = hashsum2bn(ukm, ukm_size);
     p = BN_CTX_get(ctx);
     order = BN_CTX_get(ctx);
     X = BN_CTX_get(ctx);
     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);
-    if(!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);
+
+    half_len = BN_num_bytes(order);
+    buf_len = 2 * half_len;
+    databuf = OPENSSL_zalloc(buf_len);
+    if (!databuf) {
+        GOSTerr(GOST_F_VKO_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
     /*
      * Serialize elliptic curve point same way as we do it when saving key
      */
     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;
 }
 
 /*
@@ -116,23 +123,21 @@ int pkey_gost_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
 
     if (key == NULL) {
         *keylen = 32;
-        return 32;
+        return 1;
     }
 
     EVP_PKEY_get_default_digest_nid(my_key, &dgst_nid);
+    if (dgst_nid == NID_id_GostR3411_2012_512)
+        dgst_nid = NID_id_GostR3411_2012_256;
 
     *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,
+                        (EC_KEY *)EVP_PKEY_get0(my_key), data->shared_ukm, 8,
                         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
@@ -182,9 +187,11 @@ int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
         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;
             }
         }
@@ -196,10 +203,12 @@ int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
     if (out) {
         int dgst_nid = NID_undef;
         EVP_PKEY_get_default_digest_nid(pubk, &dgst_nid);
+        if (dgst_nid == NID_id_GostR3411_2012_512)
+            dgst_nid = NID_id_GostR3411_2012_256;
 
         if (!VKO_compute_key(shared_key, 32,
                              EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)),
-                             EVP_PKEY_get0(sec_key), ukm, dgst_nid)) {
+                             EVP_PKEY_get0(sec_key), ukm, 8, dgst_nid)) {
             GOSTerr(GOST_F_PKEY_GOST_ECCP_ENCRYPT,
                     GOST_R_ERROR_COMPUTING_SHARED_KEY);
             goto err;
@@ -318,9 +327,12 @@ int pkey_GOST_ECcp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key,
     memcpy(wrappedKey + 40, gkt->key_info->imit->data, 4);
 
     EVP_PKEY_get_default_digest_nid(priv, &dgst_nid);
+    if (dgst_nid == NID_id_GostR3411_2012_512)
+        dgst_nid = NID_id_GostR3411_2012_256;
+
     if (!VKO_compute_key(sharedKey, 32,
                          EC_KEY_get0_public_key(EVP_PKEY_get0(peerkey)),
-                         EVP_PKEY_get0(priv), wrappedKey, dgst_nid)) {
+                         EVP_PKEY_get0(priv), wrappedKey, 8, dgst_nid)) {
         GOSTerr(GOST_F_PKEY_GOST_ECCP_DECRYPT,
                 GOST_R_ERROR_COMPUTING_SHARED_KEY);
         goto err;