]> wagner.pp.ru Git - openssl-gost/engine.git/commitdiff
KDF TREE + test
authorDmitry Belyavskiy <beldmit@gmail.com>
Mon, 3 Sep 2018 13:47:01 +0000 (16:47 +0300)
committerDmitry Belyavskiy <beldmit@gmail.com>
Mon, 3 Sep 2018 13:47:01 +0000 (16:47 +0300)
e_gost_err.c
e_gost_err.h
gost.txt
gost_ec_keyx.c
gost_keyexpimp.c

index 7269287d4c7402544c5e9ebca1c0f71313e54631..da9ab55aec560b90ba22c2743a3b5a53a5ce14b9 100644 (file)
@@ -36,6 +36,7 @@ static ERR_STRING_DATA GOST_str_functs[] = {
     {ERR_PACK(0, GOST_F_GOST_IMIT_CTRL, 0), "gost_imit_ctrl"},
     {ERR_PACK(0, GOST_F_GOST_IMIT_FINAL, 0), "gost_imit_final"},
     {ERR_PACK(0, GOST_F_GOST_IMIT_UPDATE, 0), "gost_imit_update"},
+    {ERR_PACK(0, GOST_F_GOST_KDFTREE2012_256, 0), "gost_kdftree2012_256"},
     {ERR_PACK(0, GOST_F_GOST_KEXP15, 0), "gost_kexp15"},
     {ERR_PACK(0, GOST_F_GOST_KIMP15, 0), "gost_kimp15"},
     {ERR_PACK(0, GOST_F_OMAC_ACPKM_IMIT_CTRL, 0), "omac_acpkm_imit_ctrl"},
index 312689fdd0de5b7faaf4966e1ae735b0616349eb..ce53f82aa6c2c0fffa6cd641c44842324fa0b4f4 100644 (file)
@@ -43,6 +43,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 # define GOST_F_GOST_IMIT_CTRL                            113
 # define GOST_F_GOST_IMIT_FINAL                           114
 # define GOST_F_GOST_IMIT_UPDATE                          115
+# define GOST_F_GOST_KDFTREE2012_256                      149
 # define GOST_F_GOST_KEXP15                               143
 # define GOST_F_GOST_KIMP15                               148
 # define GOST_F_OMAC_ACPKM_IMIT_CTRL                      144
index bf9246a7cac05d4a3a45d29745fb3a62ec72099d..3f3ffcd3c85e714d9dc717c4597d9267c1b6c260 100644 (file)
--- a/gost.txt
+++ b/gost.txt
@@ -23,6 +23,7 @@ GOST_F_GOST_GRASSHOPPER_SET_ASN1_PARAMETERS:112:\
 GOST_F_GOST_IMIT_CTRL:113:gost_imit_ctrl
 GOST_F_GOST_IMIT_FINAL:114:gost_imit_final
 GOST_F_GOST_IMIT_UPDATE:115:gost_imit_update
+GOST_F_GOST_KDFTREE2012_256:149:gost_kdftree2012_256
 GOST_F_GOST_KEXP15:143:gost_kexp15
 GOST_F_GOST_KIMP15:148:gost_kimp15
 GOST_F_OMAC_ACPKM_IMIT_CTRL:144:omac_acpkm_imit_ctrl
index 03537a3bb0aecd136b43cdebb75892217d91b1c4..cc6aacb494bed348d09ed59263b0406fca578e92 100644 (file)
@@ -84,7 +84,7 @@ static int VKO_compute_key(unsigned char *shared_key, size_t shared_key_size,
     EVP_DigestInit_ex(mdctx, md, NULL);
     EVP_DigestUpdate(mdctx, databuf, buf_len);
     EVP_DigestFinal_ex(mdctx, shared_key, NULL);
-    ret = 32;
+    ret = (EVP_MD_size(md) > 0) ? EVP_MD_size(md) : 0;
 
  err:
     BN_free(UKM);
@@ -100,6 +100,57 @@ static int VKO_compute_key(unsigned char *shared_key, size_t shared_key_size,
     return ret;
 }
 
+/*
+ * keyout expected to be 64 bytes
+ * */
+static int gost_keg(const unsigned char *ukm_source, int pkey_nid,
+                    const EC_POINT *pub_key, EC_KEY *priv_key,
+                    unsigned char *keyout)
+{
+/* Adjust UKM */
+    unsigned char real_ukm[16];
+    size_t keylen;
+
+    memset(real_ukm, 0, 16);
+    if (memcmp(ukm_source, real_ukm, 16) == 0)
+        real_ukm[15] = 1;
+    else
+        memcpy(real_ukm, ukm_source, 16);
+
+    switch (pkey_nid) {
+    case NID_id_GostR3410_2012_512:
+        keylen =
+            VKO_compute_key(keyout, 64, pub_key, priv_key, real_ukm, 16,
+                            NID_id_GostR3411_2012_512);
+        return (keylen) ? keylen : 0;
+        break;
+
+    case NID_id_GostR3410_2012_256:
+        {
+            unsigned char tmpkey[32];
+            keylen =
+                VKO_compute_key(tmpkey, 32, pub_key, priv_key, real_ukm, 16,
+                                NID_id_GostR3411_2012_256);
+
+            if (keylen == 0)
+                return 0;
+
+            if (gost_kdftree2012_256
+                (keyout, 64, tmpkey, 32, (const unsigned char *)"kdf tree", 8,
+                 ukm_source + 16, 8, 1) > 0)
+                keylen = 64;
+            else
+                keylen = 0;
+
+            OPENSSL_cleanse(tmpkey, 32);
+            return (keylen) ? keylen : 0;
+            break;
+        }
+    default:
+        return 0;
+    }
+}
+
 /*
  * EVP_PKEY_METHOD callback derive.
  * Implements VKO R 34.10-2001/2012 algorithms
@@ -120,22 +171,52 @@ int pkey_gost_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
         GOSTerr(GOST_F_PKEY_GOST_EC_DERIVE, GOST_R_UKM_NOT_SET);
         return 0;
     }
+    /*
+     * shared_ukm_size = 8 stands for pre-2018 cipher suites
+     * It means 32 bytes of key length, 8 byte UKM, 32-bytes hash
+     *
+     * shared_ukm_size = 32 stands for pre-2018 cipher suites
+     * It means 64 bytes of shared_key, 16 bytes of UKM and either
+     * 64 bytes of hash or 64 bytes of TLSTREE output
+     * */
 
-    if (key == NULL) {
-        *keylen = 32;
-        return 1;
-    }
+    switch (data->shared_ukm_size) {
+    case 8:
+        {
+            if (key == NULL) {
+                *keylen = 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;
+            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, 8,
-                        dgst_nid);
-    return (*keylen) ? 1 : 0;
+            *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, 8, dgst_nid);
+            return (*keylen) ? 1 : 0;
+        }
+        break;
+    case 32:
+        {
+            if (key == NULL) {
+                *keylen = 64;
+                return 1;
+            }
+
+            *keylen = gost_keg(data->shared_ukm, EVP_PKEY_id(my_key),
+                               EC_KEY_get0_public_key(EVP_PKEY_get0(peer_key)),
+                               (EC_KEY *)EVP_PKEY_get0(my_key), key);
+            return (*keylen) ? 1 : 0;
+        }
+
+        break;
+    default:
+        return 0;
+    }
 }
 
 /*
@@ -145,7 +226,7 @@ int pkey_gost_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
 
 /*
  * EVP_PKEY_METHOD callback encrypt
- * Implementation of GOST2001 key transport, cryptopo variation
+ * Implementation of GOST2001/12 key transport, cryptopro variation
  */
 
 int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
index c881e68ecd8afc7a88efc8a85774a234bec2ee20..bfdefbcaf515f2df9aa09d4100f1470ec69d0a63 100644 (file)
@@ -1,5 +1,7 @@
+#include <arpa/inet.h>
 #include <string.h>
 #include <openssl/evp.h>
+#include <openssl/hmac.h>
 
 #include "gost_lcl.h"
 #include "e_gost_err.h"
@@ -109,7 +111,7 @@ int gost_kimp15(const unsigned char *expkey, const size_t expkeylen,
 
     ciph = EVP_CIPHER_CTX_new();
     if (ciph == NULL) {
-        GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
+        GOSTerr(GOST_F_GOST_KIMP15, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -125,7 +127,7 @@ int gost_kimp15(const unsigned char *expkey, const size_t expkeylen,
 
     mac = EVP_MD_CTX_new();
     if (mac == NULL) {
-        GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
+        GOSTerr(GOST_F_GOST_KIMP15, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -155,13 +157,64 @@ int gost_kimp15(const unsigned char *expkey, const size_t expkeylen,
     return ret;
 }
 
-/*
- * keyout expected to be 64 bytes
- * */
-int gost_keg(const unsigned char *seckey, const size_t seckey_len,
-             const EC_POINT *pub, const unsigned char *h, unsigned char *keyout)
+int gost_kdftree2012_256(unsigned char *keyout, size_t keyout_len,
+                         const unsigned char *key, size_t keylen,
+                         const unsigned char *label, size_t label_len,
+                         const unsigned char *seed, size_t seed_len,
+                         const size_t representation)
 {
-    return 0;
+    int iters, i = 0;
+    unsigned char zero = 0;
+    unsigned char *ptr = keyout;
+    HMAC_CTX *ctx = NULL;
+    unsigned char *len_ptr = NULL;
+    uint32_t len_repr = htonl(keyout_len * 8);
+    size_t len_repr_len = 4;
+
+    ctx = HMAC_CTX_new();
+    if (ctx == NULL) {
+        GOSTerr(GOST_F_GOST_KDFTREE2012_256, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    if ((keyout_len == 0) || (keyout_len % 32 != 0)) {
+        GOSTerr(GOST_F_GOST_KDFTREE2012_256, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+    iters = keyout_len / 32;
+
+    len_ptr = (unsigned char *)&len_repr;
+    while (*len_ptr == 0) {
+        len_ptr++;
+        len_repr_len--;
+    }
+
+    for (i = 1; i <= iters; i++) {
+        uint32_t iter_net = htonl(i);
+        unsigned char *rep_ptr =
+            ((unsigned char *)&iter_net) + (4 - representation);
+
+        if (HMAC_Init_ex(ctx, key, keylen,
+                         EVP_get_digestbynid(NID_id_GostR3411_2012_256),
+                         NULL) <= 0
+            || HMAC_Update(ctx, rep_ptr, representation) <= 0
+            || HMAC_Update(ctx, label, label_len) <= 0
+            || HMAC_Update(ctx, &zero, 1) <= 0
+            || HMAC_Update(ctx, seed, seed_len) <= 0
+            || HMAC_Update(ctx, len_ptr, len_repr_len) <= 0
+            || HMAC_Final(ctx, ptr, NULL) <= 0) {
+            GOSTerr(GOST_F_GOST_KDFTREE2012_256, ERR_R_INTERNAL_ERROR);
+            HMAC_CTX_free(ctx);
+            return 0;
+        }
+
+        HMAC_CTX_reset(ctx);
+        ptr += 32;
+    }
+
+    HMAC_CTX_free(ctx);
+
+    return 1;
 }
 
 #ifdef ENABLE_UNIT_TESTS
@@ -215,9 +268,31 @@ int main(void)
         0x5D, 0xAF, 0xE7, 0xB4, 0x2E, 0x3A, 0x8B, 0xD9
     };
 
+    unsigned char kdftree_key[] = {
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+        0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+    };
+
+    unsigned char kdf_label[] = { 0x26, 0xBD, 0xB8, 0x78 };
+    unsigned char kdf_seed[] =
+        { 0xAF, 0x21, 0x43, 0x41, 0x45, 0x65, 0x63, 0x78 };
+    const unsigned char kdf_etalon[] = {
+        0x22, 0xB6, 0x83, 0x78, 0x45, 0xC6, 0xBE, 0xF6,
+        0x5E, 0xA7, 0x16, 0x72, 0xB2, 0x65, 0x83, 0x10,
+        0x86, 0xD3, 0xC7, 0x6A, 0xEB, 0xE6, 0xDA, 0xE9,
+        0x1C, 0xAD, 0x51, 0xD8, 0x3F, 0x79, 0xD1, 0x6B,
+        0x07, 0x4C, 0x93, 0x30, 0x59, 0x9D, 0x7F, 0x8D,
+        0x71, 0x2F, 0xCA, 0x54, 0x39, 0x2F, 0x4D, 0xDD,
+        0xE9, 0x37, 0x51, 0x20, 0x6B, 0x35, 0x84, 0xC8,
+        0xF4, 0x3F, 0x9E, 0x6D, 0xC5, 0x15, 0x31, 0xF9
+    };
+
     unsigned char buf[32 + 16];
     int ret = 0;
     int outlen = 40;
+    unsigned char kdf_result[64];
 
     OpenSSL_add_all_algorithms();
     memset(buf, 0, sizeof(buf));
@@ -248,6 +323,17 @@ int main(void)
         }
     }
 
+    ret = gost_kdftree2012_256(kdf_result, 64, kdftree_key, 32, kdf_label, 4,
+                               kdf_seed, 8, 1);
+    if (ret <= 0)
+        ERR_print_errors_fp(stderr);
+    else {
+        hexdump(stdout, "KDF TREE", kdf_result, 64);
+        if (memcmp(kdf_result, kdf_etalon, 64) != 0) {
+            fprintf(stdout, "ERROR! test failed\n");
+        }
+    }
+
     return 0;
 }