+int gost_tlstree(int cipher_nid, const unsigned char *in, unsigned char *out,
+ const unsigned char *tlsseq)
+{
+#ifndef L_ENDIAN
+ uint64_t gh_c1 = 0xFFFFFFFF00000000, gh_c2 = 0xFFFFFFFFFFF80000,
+ gh_c3 = 0xFFFFFFFFFFFFFFC0;
+ uint64_t mg_c1 = 0xFFFFFFC000000000, mg_c2 = 0xFFFFFFFFFE000000,
+ mg_c3 = 0xFFFFFFFFFFFFF000;
+#else
+ uint64_t gh_c1 = 0x00000000FFFFFFFF, gh_c2 = 0x0000F8FFFFFFFFFF,
+ gh_c3 = 0xC0FFFFFFFFFFFFFF;
+ uint64_t mg_c1 = 0x00000000C0FFFFFF, mg_c2 = 0x000000FEFFFFFFFF,
+ mg_c3 = 0x00F0FFFFFFFFFFFF;
+#endif
+ uint64_t c1, c2, c3;
+ uint64_t seed1, seed2, seed3;
+ uint64_t seq;
+ unsigned char ko1[32], ko2[32];
+
+ switch (cipher_nid) {
+ case NID_magma_cbc:
+ c1 = mg_c1;
+ c2 = mg_c2;
+ c3 = mg_c3;
+ break;
+ case NID_grasshopper_cbc:
+ c1 = gh_c1;
+ c2 = gh_c2;
+ c3 = gh_c3;
+ break;
+ default:
+ return 0;
+ }
+ memcpy(&seq, tlsseq, 8);
+ seed1 = seq & c1;
+ seed2 = seq & c2;
+ seed3 = seq & c3;
+
+ if (gost_kdftree2012_256(ko1, 32, in, 32, (const unsigned char *)"level1", 6,
+ (const unsigned char *)&seed1, 8, 1) <= 0
+ || gost_kdftree2012_256(ko2, 32, ko1, 32, (const unsigned char *)"level2", 6,
+ (const unsigned char *)&seed2, 8, 1) <= 0
+ || gost_kdftree2012_256(out, 32, ko2, 32, (const unsigned char *)"level3", 6,
+ (const unsigned char *)&seed3, 8, 1) <= 0)
+ return 0;
+
+ return 1;
+}
+