Hello guys.

Just after 5.9 tag, sending you to consider the Subject patch for -current,
requesting to commit it to the LibreSSL upstream.

Together with prepared and remediation patch (see inline, the original is here:
https://github.com/libressl-portable/openbsd/compare/master...crypto-org-ua:dstu)
I enclose the text of the standard (sorry, only in Ukrainian language) in case
you'll need it for verification of implemented algorithms
(http://atmnis.com/~apelsin/tmp/dstu-4145-2002.doc) + certified and tested use
case for openssl(1) (also inline).

If you have any questions, suggestions, comments, etc., please, Email.

Thank you very much for your assistance and time.

Sergey.
Index: lib/libcrypto/crypto/Makefile
===================================================================
RCS file: /cvs/src/lib/libcrypto/crypto/Makefile,v
retrieving revision 1.67
diff -u -p -r1.67 Makefile
--- lib/libcrypto/crypto/Makefile       19 Oct 2015 16:32:37 -0000      1.67
+++ lib/libcrypto/crypto/Makefile       26 Feb 2016 15:47:37 -0000
@@ -115,6 +115,10 @@ SRCS+= dsa_err.c dsa_ossl.c dsa_depr.c d
 SRCS+= dso_dlfcn.c dso_err.c dso_lib.c dso_null.c
 SRCS+= dso_openssl.c

+# dstu/
+SRCS+= dstu_params.c dstu_err.c dstu_sign.c dstu_asn1.c dstu_compress.c
+SRCS+= dstu_key.c dstu_pmeth.c dstu_ameth.c
+
 # ec/
 SRCS+= ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c
 SRCS+= ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c
@@ -155,6 +159,7 @@ SRCS+= e_old.c pmeth_lib.c pmeth_fn.c pm
 SRCS+= e_aes_cbc_hmac_sha1.c e_rc4_hmac_md5.c
 SRCS+= e_chacha.c evp_aead.c e_chacha20poly1305.c
 SRCS+= e_gost2814789.c m_gost2814789.c m_gostr341194.c m_streebog.c
+SRCS+= e_dstu.c m_dstu.c

 # gost/
 SRCS+= gost2814789.c gost89_keywrap.c gost89_params.c gost89imit_ameth.c
@@ -276,6 +281,7 @@ SRCS+= pcy_cache.c pcy_node.c pcy_data.c
        ${LCRYPTO_SRC}/dh \
        ${LCRYPTO_SRC}/dsa \
        ${LCRYPTO_SRC}/dso \
+       ${LCRYPTO_SRC}/dstu \
        ${LCRYPTO_SRC}/ec \
        ${LCRYPTO_SRC}/ecdh \
        ${LCRYPTO_SRC}/ecdsa \
Index: lib/libssl/src/crypto/asn1/ameth_lib.c
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/asn1/ameth_lib.c,v
retrieving revision 1.15
diff -u -p -r1.15 ameth_lib.c
--- lib/libssl/src/crypto/asn1/ameth_lib.c      9 Nov 2014 19:17:13 -0000       
1.15
+++ lib/libssl/src/crypto/asn1/ameth_lib.c      26 Feb 2016 15:47:38 -0000
@@ -79,6 +79,10 @@ extern const EVP_PKEY_ASN1_METHOD gostim
 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;

+#ifndef OPENSSL_NO_DSTU
+extern const EVP_PKEY_ASN1_METHOD dstu_asn1_meth_le, dstu_asn1_meth_be;
+#endif
+
 /* Keep this sorted in type order !! */
 static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_RSA
@@ -107,6 +111,10 @@ static const EVP_PKEY_ASN1_METHOD *stand
 #ifndef OPENSSL_NO_GOST
        &gostr01_asn1_meths[1],
        &gostr01_asn1_meths[2],
+#endif
+#ifndef OPENSSL_NO_DSTU
+       &dstu_asn1_meth_le,
+       &dstu_asn1_meth_be,
 #endif
 };

Index: lib/libssl/src/crypto/dstu/dstu.h
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu.h
diff -N lib/libssl/src/crypto/dstu/dstu.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu.h   26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,60 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#ifndef HEADER_DSTU_H
+#define HEADER_DSTU_H
+
+#include <openssl/gost.h>
+#include <openssl/evp.h>
+
+#define DSTU_SET_CUSTOM_SBOX (EVP_MD_CTRL_ALG_CTRL + 1)
+#define DSTU_SET_CURVE (EVP_PKEY_ALG_CTRL + 2)
+
+int dstu_do_sign(const EC_KEY * key, const unsigned char *tbs, size_t tbslen, 
unsigned char *sig);
+int dstu_do_verify(const EC_KEY * key, const unsigned char *tbs, size_t 
tbslen, const unsigned char *sig, size_t siglen);
+
+/* BEGIN ERROR CODES */
+/*
+ * The following lines are auto generated by the script mkerr.pl.
+ * Any changes made after this point may be overwritten by the script during
+ * next run.
+ */
+void ERR_load_DSTU_strings(void);
+
+/* Error codes for the DSTU functions. */
+
+/* Function codes. */
+#define DSTU_F_BIND_DSTU                       100
+#define DSTU_F_DSTU_ASN1_PARAM_COPY            102
+#define DSTU_F_DSTU_ASN1_PARAM_DECODE          101
+#define DSTU_F_DSTU_ASN1_PARAM_ENCODE          103
+#define DSTU_F_DSTU_ASN1_PARAM_PRINT           104
+#define DSTU_F_DSTU_ASN1_PRIV_DECODE           105
+#define DSTU_F_DSTU_ASN1_PRIV_ENCODE           106
+#define DSTU_F_DSTU_ASN1_PUB_DECODE            107
+#define DSTU_F_DSTU_ASN1_PUB_ENCODE            108
+#define DSTU_F_DSTU_DO_SIGN                    109
+#define DSTU_F_DSTU_DO_VERIFY                  110
+#define DSTU_F_DSTU_PKEY_CTRL                  116
+#define DSTU_F_DSTU_PKEY_INIT_BE               111
+#define DSTU_F_DSTU_PKEY_INIT_LE               112
+#define DSTU_F_DSTU_PKEY_KEYGEN                        113
+#define DSTU_F_DSTU_PKEY_SIGN                  114
+#define DSTU_F_DSTU_PKEY_VERIFY                        115
+
+/* Reason codes. */
+#define DSTU_R_AMETH_INIT_FAILED               100
+#define DSTU_R_ASN1_PARAMETER_ENCODE_FAILED    103
+#define DSTU_R_INCORRECT_FIELD_TYPE            107
+#define DSTU_R_INVALID_ASN1_PARAMETERS         102
+#define DSTU_R_INVALID_DIGEST_TYPE             108
+#define DSTU_R_NOT_DSTU_KEY                    104
+#define DSTU_R_PMETH_INIT_FAILED               101
+#define DSTU_R_POINT_COMPRESS_FAILED           105
+#define DSTU_R_POINT_UNCOMPRESS_FAILED         106
+
+#endif                         /* HEADER_DSTU_H */
Index: lib/libssl/src/crypto/dstu/dstu_ameth.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_ameth.c
diff -N lib/libssl/src/crypto/dstu/dstu_ameth.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_ameth.c     26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,700 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include "dstu.h"
+#include "dstu_asn1.h"
+#include "dstu_key.h"
+#include "dstu_params.h"
+#include <openssl/x509.h>
+#include <openssl/objects.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#ifndef OPENSSL_NO_CMS
+#include <openssl/cms.h>
+#endif
+#include <string.h>
+#include "dstu_compress.h"
+
+#include "asn1_locl.h"
+
+static int
+dstu_asn1_param_decode(EVP_PKEY * pkey, const unsigned char **pder,
+    int derlen)
+{
+       DSTU_AlgorithmParameters *params =
+       d2i_DSTU_AlgorithmParameters(NULL, pder,
+           derlen);
+       DSTU_KEY *key = NULL;
+       int ret = 0, type;
+       if (!params) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PARAM_DECODE,
+                   DSTU_R_INVALID_ASN1_PARAMETERS);
+               return 0;
+       }
+       type = EVP_PKEY_id(pkey);
+
+       key = key_from_asn1(params, NID_dstu4145le == type);
+       if (!key) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PARAM_DECODE,
+                   DSTU_R_INVALID_ASN1_PARAMETERS);
+               goto err;
+       }
+       if (!EVP_PKEY_assign(pkey, type, key)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PARAM_DECODE, ERR_R_EVP_LIB);
+               goto err;
+       }
+       key = NULL;
+       ret = 1;
+
+err:   DSTU_AlgorithmParameters_free(params);
+
+       if (key)
+               DSTU_KEY_free(key);
+
+       return ret;
+}
+
+static int
+dstu_asn1_param_encode(const EVP_PKEY * pkey, unsigned char **pder)
+{
+       DSTU_AlgorithmParameters *params = NULL;
+       const DSTU_KEY *key = EVP_PKEY_get0((EVP_PKEY *) pkey);
+       int bytes_encoded = 0, type = EVP_PKEY_id(pkey);
+
+       if (!key)
+               return 0;
+
+       params = asn1_from_key(key, NID_dstu4145le == type);
+       if (!params) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PARAM_ENCODE,
+                   DSTU_R_ASN1_PARAMETER_ENCODE_FAILED);
+               return 0;
+       }
+       bytes_encoded = i2d_DSTU_AlgorithmParameters(params, pder);
+
+       DSTU_AlgorithmParameters_free(params);
+
+       return bytes_encoded;
+}
+
+static int
+dstu_asn1_param_copy(EVP_PKEY * to, const EVP_PKEY * from)
+{
+       DSTU_KEY *to_key = EVP_PKEY_get0(to);
+       DSTU_KEY *from_key = EVP_PKEY_get0((EVP_PKEY *) from);
+       const EC_GROUP *from_group;
+
+       if (from_key) {
+               from_group = EC_KEY_get0_group(from_key->ec);
+               if (!from_group)
+                       return 0;
+
+               if (!to_key) {
+                       to_key = DSTU_KEY_new();
+                       if (!EVP_PKEY_assign(to, EVP_PKEY_id(from), to_key)) {
+                               DSTU_KEY_free(to_key);
+                               DSTUerr(DSTU_F_DSTU_ASN1_PARAM_COPY, 
ERR_R_EVP_LIB);
+                               return 0;
+                       }
+               }
+               if (!EC_KEY_set_group(to_key->ec, from_group)) {
+                       DSTUerr(DSTU_F_DSTU_ASN1_PARAM_COPY, ERR_R_EC_LIB);
+                       return 0;
+               }
+               if (from_key->sbox) {
+                       to_key->sbox = copy_sbox(from_key->sbox);
+                       if (!to_key->sbox) {
+                               DSTUerr(DSTU_F_DSTU_ASN1_PARAM_COPY, 
ERR_R_MALLOC_FAILURE);
+                               return 0;
+                       }
+               }
+               return 1;
+       }
+       return 0;
+}
+
+static int
+dstu_asn1_param_cmp(const EVP_PKEY * a, const EVP_PKEY * b)
+{
+       DSTU_KEY *first = EVP_PKEY_get0((EVP_PKEY *) a);
+       DSTU_KEY *second = EVP_PKEY_get0((EVP_PKEY *) b);
+
+       if (!first || !second)
+               return -2;
+
+       if (first->sbox != second->sbox) {
+               if (first->sbox && second->sbox) {
+                       if (memcmp(first->sbox, second->sbox, 
sizeof(default_sbox)))
+                               return 0;
+               } else
+                       return 0;
+       }
+       if (EC_GROUP_cmp(EC_KEY_get0_group(first->ec),
+               EC_KEY_get0_group(second->ec), NULL))
+               return 0;
+       else
+               return 1;
+}
+
+static int
+dstu_asn1_param_print(BIO * out, const EVP_PKEY * pkey, int indent,
+    ASN1_PCTX * pctx)
+{
+       DSTU_KEY *dstu_key = EVP_PKEY_get0((EVP_PKEY *) pkey);
+       EVP_PKEY *pk;
+       int ret;
+
+       pk = EVP_PKEY_new();
+       if (!pk || !EVP_PKEY_set1_EC_KEY(pk, dstu_key->ec)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PARAM_PRINT, ERR_R_EVP_LIB);
+               return 0;
+       }
+       ret = EVP_PKEY_print_params(out, pk, indent, NULL);
+
+       EVP_PKEY_free(pk);
+       return ret;
+}
+
+static int
+dstu_asn1_priv_decode(EVP_PKEY * pk, PKCS8_PRIV_KEY_INFO * p8)
+{
+       ASN1_OBJECT *algoid = NULL;
+       X509_ALGOR *alg = NULL;
+       const unsigned char *prk_encoded = NULL;
+       unsigned char *params_encoded = NULL;
+       ASN1_STRING *params = NULL;
+       DSTU_KEY *key = NULL;
+       BIGNUM *prk = NULL;
+       unsigned char *bn_bytes = NULL;
+       int prk_encoded_bytes = 0, params_type = 0, algnid, res = 0;
+
+       if (!PKCS8_pkey_get0(&algoid, &prk_encoded, &prk_encoded_bytes, &alg, 
p8)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, ERR_R_X509_LIB);
+               return 0;
+       }
+       algnid = OBJ_obj2nid(algoid);
+
+       if ((algnid == NID_dstu4145le) || (algnid == NID_dstu4145be)) {
+               if (!EVP_PKEY_set_type(pk, algnid)) {
+                       DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, ERR_R_EVP_LIB);
+                       return 0;
+               }
+       } else {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+
+       X509_ALGOR_get0(NULL, &params_type, (void **) &params, alg);
+       if (V_ASN1_SEQUENCE != params_type) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE,
+                   ERR_R_EXPECTING_AN_ASN1_SEQUENCE);
+               return 0;
+       }
+       params_encoded = ASN1_STRING_data(params);
+       if (!params_encoded) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       if (!dstu_asn1_param_decode(pk, (const unsigned char **) 
&params_encoded,
+               ASN1_STRING_length(params)))
+               return 0;
+
+       bn_bytes = malloc(prk_encoded_bytes);
+       if (!bn_bytes) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
+               return 0;
+       }
+       reverse_bytes_copy(bn_bytes, prk_encoded, prk_encoded_bytes);
+
+       prk = BN_bin2bn(bn_bytes, prk_encoded_bytes, NULL);
+       if (!prk) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, ERR_R_BN_LIB);
+               goto err;
+       }
+       key = EVP_PKEY_get0((EVP_PKEY *) pk);
+       if (!EC_KEY_set_private_key(key->ec, prk)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, ERR_R_EC_LIB);
+               goto err;
+       }
+       if (!dstu_add_public_key(key->ec)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_DECODE, ERR_R_EC_LIB);
+               goto err;
+       }
+       res = 1;
+
+err:
+       if (prk)
+               BN_free(prk);
+
+       if (bn_bytes)
+               free(bn_bytes);
+
+       return res;
+}
+
+static int
+dstu_asn1_priv_encode(PKCS8_PRIV_KEY_INFO * p8, const EVP_PKEY * pk)
+{
+       unsigned char *encoded_params = NULL;
+       int encoded_params_bytes = 0;
+       unsigned char *prk_encoded = NULL;
+       int prk_encoded_bytes = 0;
+       int ret = 0, algnid = EVP_PKEY_id(pk);
+       DSTU_KEY *key;
+       const BIGNUM *d;
+       ASN1_STRING *params;
+
+       if ((algnid != NID_dstu4145le) && (algnid != NID_dstu4145be)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_ENCODE, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       params = ASN1_STRING_type_new(V_ASN1_SEQUENCE);
+       if (!params) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_ENCODE, ERR_R_ASN1_LIB);
+               return 0;
+       }
+       encoded_params_bytes = dstu_asn1_param_encode(pk, &encoded_params);
+       if (!encoded_params_bytes)
+               goto err;
+
+       key = EVP_PKEY_get0((EVP_PKEY *) pk);
+       if (!key) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_ENCODE, DSTU_R_NOT_DSTU_KEY);
+               goto err;
+       }
+       d = EC_KEY_get0_private_key(key->ec);
+       if (!d) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_ENCODE, DSTU_R_NOT_DSTU_KEY);
+               goto err;
+       }
+       prk_encoded_bytes = BN_num_bytes(d);
+       prk_encoded = malloc(prk_encoded_bytes);
+       if (!prk_encoded) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+               goto err;
+       }
+       if (!BN_bn2bin(d, prk_encoded)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_ENCODE, ERR_R_BN_LIB);
+               goto err;
+       }
+       reverse_bytes(prk_encoded, prk_encoded_bytes);
+
+       ASN1_STRING_set0(params, encoded_params, encoded_params_bytes);
+
+       if (PKCS8_pkey_set0(p8, OBJ_nid2obj(algnid), 0, V_ASN1_SEQUENCE, params,
+               prk_encoded, prk_encoded_bytes)) {
+               prk_encoded = NULL;
+               params = NULL;
+               ret = 1;
+       } else {
+               DSTUerr(DSTU_F_DSTU_ASN1_PRIV_ENCODE, ERR_R_ASN1_LIB);
+       }
+
+err:
+       if (prk_encoded)
+               free(prk_encoded);
+
+       if (params)
+               ASN1_STRING_free(params);
+
+       return ret;
+}
+
+static int
+dstu_asn1_pkey_bits(const EVP_PKEY * pk)
+{
+       DSTU_KEY *key = EVP_PKEY_get0((EVP_PKEY *) pk);
+       const EC_GROUP *group;
+
+       if (key) {
+               group = EC_KEY_get0_group(key->ec);
+               if (group)
+                       return EC_GROUP_get_degree(group);
+       }
+       return 0;
+}
+
+static int
+dstu_asn1_pkey_size(const EVP_PKEY * pk)
+{
+       DSTU_KEY *key = EVP_PKEY_get0((EVP_PKEY *) pk);
+       const EC_GROUP *group;
+       BIGNUM *n = BN_new();
+       int res = 0;
+
+       if (!n)
+               return 0;
+
+       if (key) {
+               group = EC_KEY_get0_group(key->ec);
+               if (group) {
+                       if (EC_GROUP_get_order(group, n, NULL))
+                               res = ASN1_object_size(0, BN_num_bytes(n) * 2,
+                                   V_ASN1_OCTET_STRING);
+               }
+       }
+       BN_free(n);
+       return res;
+}
+
+void
+dstu_asn1_pkey_free(EVP_PKEY * pkey)
+{
+       DSTU_KEY *key = EVP_PKEY_get0(pkey);
+
+       if (key)
+               DSTU_KEY_free(key);
+}
+
+static int
+dstu_asn1_pub_decode(EVP_PKEY * pk, X509_PUBKEY * pub)
+{
+       ASN1_OBJECT *algoid = NULL;
+       const unsigned char *pbk_buf = NULL;
+       unsigned char *compressed = NULL;
+       int pbk_buf_len, param_type, algnid;
+       unsigned char *params_encoded = NULL, *public_key_data;
+       ASN1_STRING *params = NULL;
+       ASN1_OCTET_STRING *public_key = NULL;
+       X509_ALGOR *algid;
+       DSTU_KEY *key = NULL;
+       EC_POINT *point = NULL;
+       int ret = 0;
+
+       if (!X509_PUBKEY_get0_param(&algoid, &pbk_buf, &pbk_buf_len, &algid, 
pub)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, ERR_R_X509_LIB);
+               return 0;
+       }
+       X509_ALGOR_get0(&algoid, &param_type, (void **) &params, algid);
+       if (V_ASN1_SEQUENCE != param_type) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE,
+                   ERR_R_EXPECTING_AN_ASN1_SEQUENCE);
+               return 0;
+       }
+       algnid = OBJ_obj2nid(algoid);
+
+       if ((algnid == NID_dstu4145le) || (algnid == NID_dstu4145be)) {
+               if (!EVP_PKEY_set_type(pk, algnid)) {
+                       DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, ERR_R_EVP_LIB);
+                       return 0;
+               }
+       } else {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+
+       params_encoded = ASN1_STRING_data(params);
+       if (!params_encoded) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       if (!dstu_asn1_param_decode(pk, (const unsigned char **) 
&params_encoded,
+               ASN1_STRING_length(params)))
+               return 0;
+
+       key = EVP_PKEY_get0(pk);
+       if (!key) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       point = EC_POINT_new(EC_KEY_get0_group(key->ec));
+       if (!point) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, ERR_R_EC_LIB);
+               return 0;
+       }
+       public_key_data = ASN1_STRING_data(pub->public_key);
+       if (!d2i_ASN1_OCTET_STRING(&public_key,
+               (const unsigned char **) &public_key_data,
+               ASN1_STRING_length(pub->public_key))) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, ERR_R_ASN1_LIB);
+               goto err;
+       }
+       if (algnid == NID_dstu4145le) {
+               compressed = malloc(ASN1_STRING_length(public_key));
+               if (!compressed) {
+                       DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE, 
ERR_R_MALLOC_FAILURE);
+                       goto err;
+               }
+               reverse_bytes_copy(compressed, ASN1_STRING_data(public_key),
+                   ASN1_STRING_length(public_key));
+               if (!dstu_point_expand(compressed, 
ASN1_STRING_length(public_key),
+                       EC_KEY_get0_group(key->ec), point)) {
+                       free(compressed);
+                       DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE,
+                           DSTU_R_POINT_UNCOMPRESS_FAILED);
+                       goto err;
+               }
+               free(compressed);
+       } else {
+               if (!dstu_point_expand(ASN1_STRING_data(public_key),
+                       ASN1_STRING_length(public_key),
+                       EC_KEY_get0_group(key->ec), point)) {
+                       DSTUerr(DSTU_F_DSTU_ASN1_PUB_DECODE,
+                           DSTU_R_POINT_UNCOMPRESS_FAILED);
+                       goto err;
+               }
+       }
+
+       if (EC_KEY_set_public_key(key->ec, point))
+               ret = 1;
+
+err:
+       if (public_key)
+               ASN1_OCTET_STRING_free(public_key);
+
+       if (point)
+               EC_POINT_free(point);
+
+       return ret;
+}
+
+static int
+dstu_asn1_pub_encode(X509_PUBKEY * pub, const EVP_PKEY * pk)
+{
+       unsigned char *compressed = NULL, *pbk_encoded = NULL;
+       ASN1_OCTET_STRING *public_key = NULL;
+       int ret = 0, algnid = EVP_PKEY_id(pk), field_size, pbk_encoded_bytes;
+       DSTU_KEY *key;
+       const EC_GROUP *group;
+       ASN1_STRING *params;
+       const EC_POINT *point = NULL;
+
+       if ((algnid != NID_dstu4145le) && (algnid != NID_dstu4145be)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       params = ASN1_STRING_type_new(V_ASN1_SEQUENCE);
+       if (!params) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, ERR_R_ASN1_LIB);
+               return 0;
+       }
+       params->length = dstu_asn1_param_encode(pk, &(params->data));
+       if (params->length <= 0)
+               goto err;
+
+       key = EVP_PKEY_get0((EVP_PKEY *) pk);
+       if (!key) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, DSTU_R_NOT_DSTU_KEY);
+               goto err;
+       }
+       group = EC_KEY_get0_group(key->ec);
+       if (!group) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, ERR_R_EC_LIB);
+               goto err;
+       }
+       field_size = (EC_GROUP_get_degree(group) + 7) / 8;
+
+       point = EC_KEY_get0_public_key(key->ec);
+       if (!point) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, DSTU_R_NOT_DSTU_KEY);
+               goto err;
+       }
+       compressed = malloc(field_size);
+       if (!compressed) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+               goto err;
+       }
+       if (!dstu_point_compress(group, point, compressed, field_size)) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, 
DSTU_R_POINT_COMPRESS_FAILED);
+               goto err;
+       }
+       if (algnid == NID_dstu4145le)
+               reverse_bytes(compressed, field_size);
+
+       public_key = ASN1_OCTET_STRING_new();
+       if (!public_key) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, ERR_R_ASN1_LIB);
+               goto err;
+       }
+       ASN1_STRING_set0((ASN1_STRING *) public_key, compressed, field_size);
+       compressed = NULL;
+
+       pbk_encoded_bytes = i2d_ASN1_OCTET_STRING(public_key, &pbk_encoded);
+       if (!pbk_encoded) {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, ERR_R_ASN1_LIB);
+               goto err;
+       }
+       if (X509_PUBKEY_set0_param(pub, OBJ_nid2obj(algnid), V_ASN1_SEQUENCE,
+               params, pbk_encoded, pbk_encoded_bytes)) {
+               pbk_encoded = NULL;
+               params = NULL;
+               ret = 1;
+       } else {
+               DSTUerr(DSTU_F_DSTU_ASN1_PUB_ENCODE, ERR_R_X509_LIB);
+       }
+
+err:
+       if (pbk_encoded)
+               free(pbk_encoded);
+
+       if (public_key)
+               ASN1_OCTET_STRING_free(public_key);
+
+       if (compressed)
+               free(compressed);
+
+       if (params)
+               ASN1_STRING_free(params);
+
+       return ret;
+}
+
+static int
+dstu_asn1_pub_cmp(const EVP_PKEY * a, const EVP_PKEY * b)
+{
+       DSTU_KEY *first = EVP_PKEY_get0((EVP_PKEY *) a);
+       DSTU_KEY *second = EVP_PKEY_get0((EVP_PKEY *) b);
+
+       if (!first || !second)
+               return -2;
+
+       /*
+         * We do not compare sboxes here because it will be done in params_cmp
+         * by EVP API.
+         */
+
+       if (EC_POINT_cmp(EC_KEY_get0_group(first->ec),
+               EC_KEY_get0_public_key(first->ec),
+               EC_KEY_get0_public_key(second->ec), NULL))
+               return 0;
+       else
+               return 1;
+}
+
+static int
+dstu_asn1_pkey_ctrl(EVP_PKEY * pkey, int op, long arg1, void *arg2)
+{
+       switch (op) {
+               case ASN1_PKEY_CTRL_PKCS7_SIGN:
+               if (arg1 == 0) {
+                       X509_ALGOR *alg1 = NULL, *alg2 = NULL;
+                       int nid = EVP_PKEY_base_id(pkey);
+                       PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *) arg2,
+                           NULL, &alg1, &alg2);
+                       X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_dstu34311), 
V_ASN1_NULL, 0);
+                       if (nid == NID_undef) {
+                               return (-1);
+                       }
+                       X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
+               }
+               return 1;
+#ifndef OPENSSL_NO_CMS
+       case ASN1_PKEY_CTRL_CMS_SIGN:
+               if (arg1 == 0) {
+                       X509_ALGOR *alg1 = NULL, *alg2 = NULL;
+                       int nid = EVP_PKEY_base_id(pkey);
+                       CMS_SignerInfo_get0_algs((CMS_SignerInfo *) arg2,
+                           NULL, NULL, &alg1, &alg2);
+                       X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_dstu34311), 
V_ASN1_NULL, 0);
+                       if (nid == NID_undef) {
+                               return (-1);
+                       }
+                       X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
+               }
+               return 1;
+#endif
+       case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+               *((int *) arg2) = NID_dstu34311;
+               return 2;
+       }
+
+       return 0;
+}
+
+static int
+dstu_asn1_priv_print(BIO * out, const EVP_PKEY * pkey, int indent,
+    ASN1_PCTX * pctx)
+{
+       /* Reusing basic EC keys printing. */
+       DSTU_KEY *dstu_key = EVP_PKEY_get0((EVP_PKEY *) pkey);
+       EVP_PKEY *pk;
+       int ret;
+
+       pk = EVP_PKEY_new();
+       if (!pk || !EVP_PKEY_set1_EC_KEY(pk, dstu_key->ec))
+               return 0;
+
+       ret = EVP_PKEY_print_private(out, pk, indent, pctx);
+
+       EVP_PKEY_free(pk);
+       return ret;
+}
+
+static int
+dstu_asn1_pub_print(BIO * out, const EVP_PKEY * pkey, int indent,
+    ASN1_PCTX * pctx)
+{
+       /* Reusing basic EC keys printing. */
+       DSTU_KEY *dstu_key = EVP_PKEY_get0((EVP_PKEY *) pkey);
+       EVP_PKEY *pk;
+       int ret;
+
+       pk = EVP_PKEY_new();
+       if (!pk || !EVP_PKEY_set1_EC_KEY(pk, dstu_key->ec))
+               return 0;
+
+       ret = EVP_PKEY_print_public(out, pk, indent, pctx);
+
+       EVP_PKEY_free(pk);
+       return ret;
+}
+
+const EVP_PKEY_ASN1_METHOD dstu_asn1_meth_le = {
+       .pkey_id = NID_dstu4145le,
+       .pkey_base_id = NID_dstu4145le,
+       .pem_str = SN_dstu4145le,
+       .info = LN_dstu4145le,
+
+       .param_encode = dstu_asn1_param_encode,
+       .param_decode = dstu_asn1_param_decode,
+       .param_copy = dstu_asn1_param_copy,
+       .param_cmp = dstu_asn1_param_cmp,
+       .param_print = dstu_asn1_param_print,
+
+       .priv_encode = dstu_asn1_priv_encode,
+       .priv_decode = dstu_asn1_priv_decode,
+       .priv_print = dstu_asn1_priv_print,
+
+       .pub_encode = dstu_asn1_pub_encode,
+       .pub_decode = dstu_asn1_pub_decode,
+       .pub_cmp = dstu_asn1_pub_cmp,
+       .pub_print = dstu_asn1_pub_print,
+
+       .pkey_size = dstu_asn1_pkey_size,
+       .pkey_bits = dstu_asn1_pkey_bits,
+
+       .pkey_ctrl = dstu_asn1_pkey_ctrl,
+       .pkey_free = dstu_asn1_pkey_free
+};
+
+const EVP_PKEY_ASN1_METHOD dstu_asn1_meth_be = {
+       .pkey_id = NID_dstu4145be,
+       .pkey_base_id = NID_dstu4145be,
+       .pem_str = SN_dstu4145be,
+       .info = LN_dstu4145be,
+
+       .param_encode = dstu_asn1_param_encode,
+       .param_decode = dstu_asn1_param_decode,
+       .param_copy = dstu_asn1_param_copy,
+       .param_cmp = dstu_asn1_param_cmp,
+       .param_print = dstu_asn1_param_print,
+
+       .priv_encode = dstu_asn1_priv_encode,
+       .priv_decode = dstu_asn1_priv_decode,
+       .priv_print = dstu_asn1_priv_print,
+
+       .pub_encode = dstu_asn1_pub_encode,
+       .pub_decode = dstu_asn1_pub_decode,
+       .pub_cmp = dstu_asn1_pub_cmp,
+       .pub_print = dstu_asn1_pub_print,
+
+       .pkey_size = dstu_asn1_pkey_size,
+       .pkey_bits = dstu_asn1_pkey_bits,
+
+       .pkey_ctrl = dstu_asn1_pkey_ctrl,
+       .pkey_free = dstu_asn1_pkey_free
+};
Index: lib/libssl/src/crypto/dstu/dstu_asn1.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_asn1.c
diff -N lib/libssl/src/crypto/dstu/dstu_asn1.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_asn1.c      26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,394 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include "dstu.h"
+#include "dstu_asn1.h"
+
+static const ASN1_TEMPLATE DSTU_Pentanomial_seq_tt[] = {
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_Pentanomial, k),
+               .field_name = "k",
+               .item = &ASN1_INTEGER_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_Pentanomial, j),
+               .field_name = "j",
+               .item = &ASN1_INTEGER_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_Pentanomial, l),
+               .field_name = "l",
+               .item = &ASN1_INTEGER_it
+       },
+};
+
+const ASN1_ITEM DSTU_Pentanomial_it = {
+       ASN1_ITYPE_SEQUENCE,
+       V_ASN1_SEQUENCE,
+       DSTU_Pentanomial_seq_tt,
+       sizeof(DSTU_Pentanomial_seq_tt) / sizeof(ASN1_TEMPLATE),
+       NULL,
+       sizeof(DSTU_Pentanomial),
+       "DSTU_Pentanomial"
+};
+
+DSTU_Pentanomial *
+d2i_DSTU_Pentanomial(DSTU_Pentanomial ** a, const unsigned char **in, long len)
+{
+       return (DSTU_Pentanomial *) ASN1_item_d2i((ASN1_VALUE **) a, in, len, 
(&(DSTU_Pentanomial_it)));
+}
+
+int
+i2d_DSTU_Pentanomial(DSTU_Pentanomial * a, unsigned char **out)
+{
+       return ASN1_item_i2d((ASN1_VALUE *) a, out, (&(DSTU_Pentanomial_it)));
+}
+
+DSTU_Pentanomial *
+DSTU_Pentanomial_new(void)
+{
+       return (DSTU_Pentanomial *) ASN1_item_new((&(DSTU_Pentanomial_it)));
+}
+
+void
+DSTU_Pentanomial_free(DSTU_Pentanomial * a)
+{
+       ASN1_item_free((ASN1_VALUE *) a, (&(DSTU_Pentanomial_it)));
+}
+
+static const ASN1_TEMPLATE DSTU_Polynomial_ch_tt[] = {
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_Polynomial, poly.k),
+               .field_name = "poly.k",
+               .item = &ASN1_INTEGER_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_Polynomial, poly.pentanomial),
+               .field_name = "poly.pentanomial",
+               .item = &DSTU_Pentanomial_it
+       }
+};
+
+const ASN1_ITEM DSTU_Polynomial_it = {
+       ASN1_ITYPE_CHOICE,
+       offsetof(DSTU_Polynomial, type),
+       DSTU_Polynomial_ch_tt,
+       sizeof(DSTU_Polynomial_ch_tt) / sizeof(ASN1_TEMPLATE),
+       NULL,
+       sizeof(DSTU_Polynomial),
+       "DSTU_Polynomial"
+};
+
+DSTU_Polynomial *
+d2i_DSTU_Polynomial(DSTU_Polynomial ** a, const unsigned char **in, long len)
+{
+       return (DSTU_Polynomial *) ASN1_item_d2i((ASN1_VALUE **) a, in, len, 
(&(DSTU_Polynomial_it)));
+}
+
+int
+i2d_DSTU_Polynomial(DSTU_Polynomial * a, unsigned char **out)
+{
+       return ASN1_item_i2d((ASN1_VALUE *) a, out, (&(DSTU_Polynomial_it)));
+       \
+}
+
+DSTU_Polynomial *
+DSTU_Polynomial_new(void)
+{
+       return (DSTU_Polynomial *) ASN1_item_new((&(DSTU_Polynomial_it)));
+}
+
+void
+DSTU_Polynomial_free(DSTU_Polynomial * a)
+{
+       ASN1_item_free((ASN1_VALUE *) a, (&(DSTU_Polynomial_it)));
+}
+
+static const ASN1_TEMPLATE DSTU_BinaryField_seq_tt[] = {
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_BinaryField, m),
+               .field_name = "m",
+               .item = &ASN1_INTEGER_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_BinaryField, poly),
+               .field_name = "poly",
+               .item = &DSTU_Polynomial_it
+       }
+};
+
+const ASN1_ITEM DSTU_BinaryField_it = {
+       ASN1_ITYPE_SEQUENCE,
+       V_ASN1_SEQUENCE,
+       DSTU_BinaryField_seq_tt,
+       sizeof(DSTU_BinaryField_seq_tt) / sizeof(ASN1_TEMPLATE),
+       NULL,
+       sizeof(DSTU_BinaryField),
+       "DSTU_BinaryField"
+};
+
+DSTU_BinaryField *
+d2i_DSTU_BinaryField(DSTU_BinaryField ** a, const unsigned char **in, long len)
+{
+       return (DSTU_BinaryField *) ASN1_item_d2i((ASN1_VALUE **) a, in, len, 
(&(DSTU_BinaryField_it)));
+}
+
+int
+i2d_DSTU_BinaryField(DSTU_BinaryField * a, unsigned char **out)
+{
+       return ASN1_item_i2d((ASN1_VALUE *) a, out, (&(DSTU_BinaryField_it)));
+}
+
+DSTU_BinaryField *
+DSTU_BinaryField_new(void)
+{
+       return (DSTU_BinaryField *) ASN1_item_new((&(DSTU_BinaryField_it)));
+}
+
+void
+DSTU_BinaryField_free(DSTU_BinaryField * a)
+{
+       ASN1_item_free((ASN1_VALUE *) a, (&(DSTU_BinaryField_it)));
+}
+
+static const ASN1_TEMPLATE DSTU_CustomCurveSpec_seq_tt[] = {
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_CustomCurveSpec, field),
+               .field_name = "field",
+               .item = &DSTU_BinaryField_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_CustomCurveSpec, a),
+               .field_name = "a",
+               .item = &ASN1_INTEGER_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_CustomCurveSpec, b),
+               .field_name = "b",
+               .item = &ASN1_OCTET_STRING_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_CustomCurveSpec, n),
+               .field_name = "n",
+               .item = &ASN1_INTEGER_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_CustomCurveSpec, bp),
+               .field_name = "bp",
+               .item = &ASN1_OCTET_STRING_it
+       }
+};
+
+const ASN1_ITEM DSTU_CustomCurveSpec_it = {
+       ASN1_ITYPE_SEQUENCE,
+       V_ASN1_SEQUENCE,
+       DSTU_CustomCurveSpec_seq_tt,
+       sizeof(DSTU_CustomCurveSpec_seq_tt) / sizeof(ASN1_TEMPLATE),
+       NULL,
+       sizeof(DSTU_CustomCurveSpec),
+       "DSTU_CustomCurveSpec"
+};
+
+DSTU_CustomCurveSpec *
+d2i_DSTU_CustomCurveSpec(DSTU_CustomCurveSpec ** a, const unsigned char **in, 
long len)
+{
+       return (DSTU_CustomCurveSpec *) ASN1_item_d2i((ASN1_VALUE **) a, in, 
len, (&(DSTU_CustomCurveSpec_it)));
+}
+
+int
+i2d_DSTU_CustomCurveSpec(DSTU_CustomCurveSpec * a, unsigned char **out)
+{
+       return ASN1_item_i2d((ASN1_VALUE *) a, out, 
(&(DSTU_CustomCurveSpec_it)));
+}
+
+DSTU_CustomCurveSpec *
+DSTU_CustomCurveSpec_new(void)
+{
+       return (DSTU_CustomCurveSpec *) 
ASN1_item_new((&(DSTU_CustomCurveSpec_it)));
+}
+
+void
+DSTU_CustomCurveSpec_free(DSTU_CustomCurveSpec * a)
+{
+       ASN1_item_free((ASN1_VALUE *) a, (&(DSTU_CustomCurveSpec_it)));
+}
+
+static const ASN1_TEMPLATE DSTU_CurveSpec_ch_tt[] = {
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_CurveSpec, curve.named_curve),
+               .field_name = "curve.named_curve",
+               .item = &ASN1_OBJECT_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_CurveSpec, curve.custom_curve),
+               .field_name = "curve.custom_curve",
+               .item = &DSTU_CustomCurveSpec_it
+       }
+};
+
+const ASN1_ITEM DSTU_CurveSpec_it = {
+       ASN1_ITYPE_CHOICE,
+       offsetof(DSTU_CurveSpec, type),
+       DSTU_CurveSpec_ch_tt,
+       sizeof(DSTU_CurveSpec_ch_tt) / sizeof(ASN1_TEMPLATE),
+       NULL,
+       sizeof(DSTU_CurveSpec),
+       "DSTU_CurveSpec"
+};
+
+DSTU_CurveSpec *
+d2i_DSTU_CurveSpec(DSTU_CurveSpec ** a, const unsigned char **in, long len)
+{
+       return (DSTU_CurveSpec *) ASN1_item_d2i((ASN1_VALUE **) a, in, len, 
(&(DSTU_CurveSpec_it)));
+}
+
+int
+i2d_DSTU_CurveSpec(DSTU_CurveSpec * a, unsigned char **out)
+{
+       return ASN1_item_i2d((ASN1_VALUE *) a, out, (&(DSTU_CurveSpec_it)));
+}
+
+DSTU_CurveSpec *
+DSTU_CurveSpec_new(void)
+{
+       return (DSTU_CurveSpec *) ASN1_item_new((&(DSTU_CurveSpec_it)));
+}
+
+void
+DSTU_CurveSpec_free(DSTU_CurveSpec * a)
+{
+       ASN1_item_free((ASN1_VALUE *) a, (&(DSTU_CurveSpec_it)));
+}
+
+static const ASN1_TEMPLATE DSTU_AlgorithmParameters_seq_tt[] = {
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_AlgorithmParameters, curve),
+               .field_name = "curve",
+               .item = &DSTU_CurveSpec_it
+       },
+       {
+               .flags = ASN1_TFLG_OPTIONAL,
+               .tag = 0,
+               .offset = offsetof(DSTU_AlgorithmParameters, sbox),
+               .field_name = "sbox",
+               .item = &ASN1_OCTET_STRING_it
+       }
+};
+
+const ASN1_ITEM DSTU_AlgorithmParameters_it = {
+       ASN1_ITYPE_SEQUENCE,
+       V_ASN1_SEQUENCE,
+       DSTU_AlgorithmParameters_seq_tt,
+       sizeof(DSTU_AlgorithmParameters_seq_tt) / sizeof(ASN1_TEMPLATE),
+       NULL,
+       sizeof(DSTU_AlgorithmParameters),
+       "DSTU_AlgorithmParameters"
+};
+
+DSTU_AlgorithmParameters *
+d2i_DSTU_AlgorithmParameters(DSTU_AlgorithmParameters ** a, const unsigned 
char **in, long len)
+{
+       return (DSTU_AlgorithmParameters *) ASN1_item_d2i((ASN1_VALUE **) a, 
in, len, (&(DSTU_AlgorithmParameters_it)));
+}
+
+int
+i2d_DSTU_AlgorithmParameters(DSTU_AlgorithmParameters * a, unsigned char **out)
+{
+       return ASN1_item_i2d((ASN1_VALUE *) a, out, 
(&(DSTU_AlgorithmParameters_it)));
+}
+
+DSTU_AlgorithmParameters *
+DSTU_AlgorithmParameters_new(void)
+{
+       return (DSTU_AlgorithmParameters *) 
ASN1_item_new((&(DSTU_AlgorithmParameters_it)));
+}
+
+void
+DSTU_AlgorithmParameters_free(DSTU_AlgorithmParameters * a)
+{
+       ASN1_item_free((ASN1_VALUE *) a, (&(DSTU_AlgorithmParameters_it)));
+}
+static const ASN1_TEMPLATE DSTU_Gost28147Parameters_seq_tt[] = {
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_Gost28147Parameters, iv),
+               .field_name = "iv",
+               .item = &ASN1_OCTET_STRING_it
+       },
+       {
+               .flags = 0,
+               .tag = 0,
+               .offset = offsetof(DSTU_Gost28147Parameters, dke),
+               .field_name = "dke",
+               .item = &ASN1_OCTET_STRING_it
+       }
+};
+
+const ASN1_ITEM DSTU_Gost28147Parameters_it = {
+       ASN1_ITYPE_SEQUENCE,
+       V_ASN1_SEQUENCE,
+       DSTU_Gost28147Parameters_seq_tt,
+       sizeof(DSTU_Gost28147Parameters_seq_tt) / sizeof(ASN1_TEMPLATE),
+       NULL,
+       sizeof(DSTU_Gost28147Parameters),
+       "DSTU_Gost28147Parameters"
+};
+
+DSTU_Gost28147Parameters *
+d2i_DSTU_Gost28147Parameters(DSTU_Gost28147Parameters ** a, const unsigned 
char **in, long len)
+{
+       return (DSTU_Gost28147Parameters *) ASN1_item_d2i((ASN1_VALUE **) a, 
in, len, (&(DSTU_Gost28147Parameters_it)));
+}
+
+int
+i2d_DSTU_Gost28147Parameters(DSTU_Gost28147Parameters * a, unsigned char **out)
+{
+       return ASN1_item_i2d((ASN1_VALUE *) a, out, 
(&(DSTU_Gost28147Parameters_it)));
+}
+
+DSTU_Gost28147Parameters *
+DSTU_Gost28147Parameters_new(void)
+{
+       return (DSTU_Gost28147Parameters *) 
ASN1_item_new((&(DSTU_Gost28147Parameters_it)));
+}
+
+void
+DSTU_Gost28147Parameters_free(DSTU_Gost28147Parameters * a)
+{
+       ASN1_item_free((ASN1_VALUE *) a, (&(DSTU_Gost28147Parameters_it)));
+}
Index: lib/libssl/src/crypto/dstu/dstu_asn1.h
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_asn1.h
diff -N lib/libssl/src/crypto/dstu/dstu_asn1.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_asn1.h      26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,70 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#ifndef DSTU_ASN1_H_
+#define DSTU_ASN1_H_
+
+#include <openssl/asn1t.h>
+
+typedef struct DSTU_Pentanomial_st {
+       ASN1_INTEGER *k;
+       ASN1_INTEGER *j;
+       ASN1_INTEGER *l;
+} DSTU_Pentanomial;
+
+DECLARE_ASN1_FUNCTIONS(DSTU_Pentanomial)
+       typedef struct DSTU_Polynomial_st {
+#define DSTU_TRINOMIAL 0
+#define DSTU_PENTANOMIAL 1
+               int type;
+               union {
+                       ASN1_INTEGER *k;
+                       DSTU_Pentanomial *pentanomial;
+               } poly;
+} DSTU_Polynomial;
+
+DECLARE_ASN1_FUNCTIONS(DSTU_Polynomial)
+       typedef struct DSTU_BinaryField_st {
+               ASN1_INTEGER *m;
+               DSTU_Polynomial *poly;
+} DSTU_BinaryField;
+
+DECLARE_ASN1_FUNCTIONS(DSTU_BinaryField)
+       typedef struct DSTU_CustomCurveSpec_st {
+               DSTU_BinaryField *field;
+               ASN1_INTEGER *a;
+               ASN1_OCTET_STRING *b;
+               ASN1_INTEGER *n;
+               ASN1_OCTET_STRING *bp;
+} DSTU_CustomCurveSpec;
+
+DECLARE_ASN1_FUNCTIONS(DSTU_CustomCurveSpec)
+       typedef struct DSTU_CurveSpec_st {
+#define DSTU_STANDARD_CURVE 0
+#define DSTU_CUSTOM_CURVE 1
+               int type;
+               union {
+                       ASN1_OBJECT *named_curve;
+                       DSTU_CustomCurveSpec *custom_curve;
+               } curve;
+
+} DSTU_CurveSpec;
+
+DECLARE_ASN1_FUNCTIONS(DSTU_CurveSpec)
+       typedef struct DSTU_AlgorithmParameters_st {
+               DSTU_CurveSpec *curve;
+               ASN1_OCTET_STRING *sbox;
+} DSTU_AlgorithmParameters;
+
+DECLARE_ASN1_FUNCTIONS(DSTU_AlgorithmParameters)
+       typedef struct DSTU_Gost28147Parameters_st {
+               ASN1_OCTET_STRING *iv;
+               ASN1_OCTET_STRING *dke;
+} DSTU_Gost28147Parameters;
+
+DECLARE_ASN1_FUNCTIONS(DSTU_Gost28147Parameters)
+#endif                         /* DSTU_ASN1_H_ */
Index: lib/libssl/src/crypto/dstu/dstu_compress.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_compress.c
diff -N lib/libssl/src/crypto/dstu/dstu_compress.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_compress.c  26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,204 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include "dstu_compress.h"
+#include "dstu_params.h"
+#include <string.h>
+
+static int
+bn_trace(const BIGNUM * bn, const BIGNUM * p, BN_CTX * ctx)
+{
+       BIGNUM *r = NULL;
+       int res = -1, i;
+
+       BN_CTX_start(ctx);
+
+       r = BN_CTX_get(ctx);
+
+       if (!BN_copy(r, bn))
+               goto err;
+       for (i = 1; i <= (BN_num_bits(p) - 2); i++) {
+               if (!BN_GF2m_mod_sqr(r, r, p, ctx))
+                       goto err;
+               if (!BN_GF2m_add(r, r, bn))
+                       goto err;
+       }
+
+       if (BN_is_one(r))
+               res = 1;
+       else if (BN_is_zero(r))
+               res = 0;
+
+err:
+
+       BN_CTX_end(ctx);
+       return res;
+}
+
+int
+dstu_point_compress(const EC_GROUP * group, const EC_POINT * point,
+    unsigned char *compressed, int compressed_length)
+{
+       int field_size, res = 0, trace;
+       BN_CTX *ctx;
+       BIGNUM *p, *x_inv, *x, *y;
+
+       field_size = (EC_GROUP_get_degree(group) + 7) / 8;
+       if (compressed_length < field_size)
+               return 0;
+
+       ctx = BN_CTX_new();
+       if (!ctx)
+               return 0;
+
+       BN_CTX_start(ctx);
+       p = BN_CTX_get(ctx);
+       x_inv = BN_CTX_get(ctx);
+       x = BN_CTX_get(ctx);
+       y = BN_CTX_get(ctx);
+
+       if (!y)
+               goto err;
+
+       if (!EC_GROUP_get_curve_GF2m(group, p, NULL, NULL, ctx))
+               goto err;
+
+       if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
+               goto err;
+
+       if (BN_is_zero(x)) {
+               memset(compressed, 0, field_size);
+               res = 1;
+               goto err;
+       }
+       if (!BN_GF2m_mod_inv(x_inv, x, p, ctx))
+               goto err;
+
+       if (!BN_GF2m_mod_mul(y, y, x_inv, p, ctx))
+               goto err;
+
+       trace = bn_trace(y, p, ctx);
+       if (-1 == trace)
+               goto err;
+
+       if (trace) {
+               if (!BN_set_bit(x, 0))
+                       goto err;
+       } else {
+               if (!BN_clear_bit(x, 0))
+                       goto err;
+       }
+
+       if (bn_encode(x, compressed, field_size))
+               res = 1;
+
+err:
+
+       if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       return res;
+}
+
+int
+dstu_point_expand(const unsigned char *compressed, int compressed_length,
+    const EC_GROUP * group, EC_POINT * point)
+{
+       int field_size, res = 0, trace, k;
+       BN_CTX *ctx;
+       BIGNUM *p, *a, *b, *x2, *x, *y;
+
+       field_size = (EC_GROUP_get_degree(group) + 7) / 8;
+       if (compressed_length < field_size)
+               return 0;
+
+       ctx = BN_CTX_new();
+       if (!ctx)
+               return 0;
+
+       BN_CTX_start(ctx);
+       p = BN_CTX_get(ctx);
+       a = BN_CTX_get(ctx);
+       b = BN_CTX_get(ctx);
+       x2 = BN_CTX_get(ctx);
+       x = BN_CTX_get(ctx);
+       y = BN_CTX_get(ctx);
+
+       if (!y)
+               goto err;
+
+       if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx))
+               goto err;
+
+       if (!BN_bin2bn(compressed, compressed_length, x))
+               goto err;
+
+       if (BN_is_zero(x)) {
+               if (!BN_GF2m_mod_sqrt(y, b, p, ctx))
+                       goto err;
+
+               if (EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, 
ctx))
+                       res = 1;
+
+               goto err;
+       }
+       k = BN_is_bit_set(x, 0);
+
+       if (!BN_clear_bit(x, 0))
+               goto err;
+
+       trace = bn_trace(x, p, ctx);
+       if (-1 == trace)
+               goto err;
+
+       if ((trace && BN_is_zero(a)) || ((!trace) && BN_is_one(a))) {
+               if (!BN_set_bit(x, 0))
+                       goto err;
+       }
+       if (!BN_GF2m_mod_sqr(x2, x, p, ctx))
+               goto err;
+
+       if (!BN_GF2m_mod_mul(y, x2, x, p, ctx))
+               goto err;
+
+       if (BN_is_one(a)) {
+               if (!BN_GF2m_add(y, y, x2))
+                       goto err;
+       }
+       if (!BN_GF2m_add(y, y, b))
+               goto err;
+
+       if (!BN_GF2m_mod_inv(x2, x2, p, ctx))
+               goto err;
+
+       if (!BN_GF2m_mod_mul(y, y, x2, p, ctx))
+               goto err;
+
+       if (!BN_GF2m_mod_solve_quad(y, y, p, ctx))
+               goto err;
+
+       trace = bn_trace(y, p, ctx);
+
+       if ((k && !trace) || (!k && trace)) {
+               if (!BN_GF2m_add(y, y, BN_value_one()))
+                       goto err;
+       }
+       if (!BN_GF2m_mod_mul(y, y, x, p, ctx))
+               goto err;
+
+       if (EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
+               res = 1;
+
+err:
+
+       if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       return res;
+}
Index: lib/libssl/src/crypto/dstu/dstu_compress.h
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_compress.h
diff -N lib/libssl/src/crypto/dstu/dstu_compress.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_compress.h  26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,21 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#ifndef DSTU_COMPRESS_H_
+#define DSTU_COMPRESS_H_
+
+#include <openssl/ec.h>
+#include "dstu.h"
+
+int
+dstu_point_compress(const EC_GROUP * group, const EC_POINT * point,
+    unsigned char *compressed, int compressed_length);
+int
+dstu_point_expand(const unsigned char *compressed, int compressed_length,
+    const EC_GROUP * group, EC_POINT * point);
+
+#endif                         /* DSTU_COMPRESS_H_ */
Index: lib/libssl/src/crypto/dstu/dstu_err.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_err.c
diff -N lib/libssl/src/crypto/dstu/dstu_err.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_err.c       26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,114 @@
+/* dstu_err.c */
+/*
+ * ====================================================================
+ * Copyright (c) 1999-2013 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software 
must
+ * display the following acknowledgment: "This product includes software
+ * developed by the OpenSSL Project for use in the OpenSSL Toolkit.
+ * (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without prior
+ * written permission. For written permission, please contact
+ * [email protected].
+ *
+ * 5. Products derived from this software may not be called "OpenSSL" nor may
+ * "OpenSSL" appear in their names without prior written permission of the
+ * OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment: "This product includes software developed by the OpenSSL
+ * Project for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * ([email protected]).  This product includes software written by Tim Hudson
+ * ([email protected]).
+ *
+ */
+
+/*
+ * NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "dstu.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_DSTU,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_DSTU,0,reason)
+
+static ERR_STRING_DATA DSTU_str_functs[] = {
+       {ERR_FUNC(DSTU_F_BIND_DSTU), "BIND_DSTU"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PARAM_COPY), "DSTU_ASN1_PARAM_COPY"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PARAM_DECODE), "DSTU_ASN1_PARAM_DECODE"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PARAM_ENCODE), "DSTU_ASN1_PARAM_ENCODE"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PARAM_PRINT), "DSTU_ASN1_PARAM_PRINT"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PRIV_DECODE), "DSTU_ASN1_PRIV_DECODE"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PRIV_ENCODE), "DSTU_ASN1_PRIV_ENCODE"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PUB_DECODE), "DSTU_ASN1_PUB_DECODE"},
+       {ERR_FUNC(DSTU_F_DSTU_ASN1_PUB_ENCODE), "DSTU_ASN1_PUB_ENCODE"},
+       {ERR_FUNC(DSTU_F_DSTU_DO_SIGN), "DSTU_DO_SIGN"},
+       {ERR_FUNC(DSTU_F_DSTU_DO_VERIFY), "DSTU_DO_VERIFY"},
+       {ERR_FUNC(DSTU_F_DSTU_PKEY_CTRL), "DSTU_PKEY_CTRL"},
+       {ERR_FUNC(DSTU_F_DSTU_PKEY_INIT_BE), "DSTU_PKEY_INIT_BE"},
+       {ERR_FUNC(DSTU_F_DSTU_PKEY_INIT_LE), "DSTU_PKEY_INIT_LE"},
+       {ERR_FUNC(DSTU_F_DSTU_PKEY_KEYGEN), "DSTU_PKEY_KEYGEN"},
+       {ERR_FUNC(DSTU_F_DSTU_PKEY_SIGN), "DSTU_PKEY_SIGN"},
+       {ERR_FUNC(DSTU_F_DSTU_PKEY_VERIFY), "DSTU_PKEY_VERIFY"},
+       {0, NULL}
+};
+
+static ERR_STRING_DATA DSTU_str_reasons[] = {
+       {ERR_REASON(DSTU_R_AMETH_INIT_FAILED), "ameth init failed"},
+       {ERR_REASON(DSTU_R_ASN1_PARAMETER_ENCODE_FAILED),
+       "asn1 parameter encode failed"},
+       {ERR_REASON(DSTU_R_INCORRECT_FIELD_TYPE), "incorrect field type"},
+       {ERR_REASON(DSTU_R_INVALID_ASN1_PARAMETERS), "invalid asn1 parameters"},
+       {ERR_REASON(DSTU_R_INVALID_DIGEST_TYPE), "invalid digest type"},
+       {ERR_REASON(DSTU_R_NOT_DSTU_KEY), "not dstu key"},
+       {ERR_REASON(DSTU_R_PMETH_INIT_FAILED), "pmeth init failed"},
+       {ERR_REASON(DSTU_R_POINT_COMPRESS_FAILED), "point compress failed"},
+       {ERR_REASON(DSTU_R_POINT_UNCOMPRESS_FAILED), "point uncompress failed"},
+       {0, NULL}
+};
+
+#endif
+
+void
+ERR_load_DSTU_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+       ERR_load_strings(0, DSTU_str_functs);
+       ERR_load_strings(0, DSTU_str_reasons);
+#endif
+}
Index: lib/libssl/src/crypto/dstu/dstu_key.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_key.c
diff -N lib/libssl/src/crypto/dstu/dstu_key.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_key.c       26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,479 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include "dstu_key.h"
+#include "dstu_asn1.h"
+#include "dstu_compress.h"
+#include "dstu_params.h"
+#include <openssl/objects.h>
+#include <string.h>
+
+DSTU_KEY *
+DSTU_KEY_new(void)
+{
+       DSTU_KEY *key = malloc(sizeof(DSTU_KEY));
+
+       if (!key)
+               return NULL;
+       key->ec = EC_KEY_new();
+       if (!(key->ec)) {
+               free(key);
+               return NULL;
+       }
+       key->sbox = NULL;
+       return key;
+}
+
+void
+DSTU_KEY_set(DSTU_KEY * key, EC_KEY * ec, unsigned char *sbox)
+{
+       if (ec) {
+               if (key->ec)
+                       EC_KEY_free(key->ec);
+               key->ec = ec;
+       }
+       if (sbox) {
+               if (key->sbox)
+                       free(key->sbox);
+               key->sbox = sbox;
+       }
+}
+
+void
+DSTU_KEY_free(DSTU_KEY * key)
+{
+       if (key) {
+               if (key->sbox)
+                       free(key->sbox);
+               if (key->ec)
+                       EC_KEY_free(key->ec);
+               free(key);
+       }
+}
+
+DSTU_AlgorithmParameters *
+asn1_from_key(const DSTU_KEY * key,
+    int is_little_endian)
+{
+       DSTU_AlgorithmParameters *params = DSTU_AlgorithmParameters_new(),
+       *ret =
+       NULL;
+       const EC_GROUP *group = EC_KEY_get0_group(key->ec);
+       int curve_nid, poly[6], field_size;
+       BN_CTX *ctx = NULL;
+       const EC_POINT *g = NULL;
+       BIGNUM *p, *a, *b, *n;
+       unsigned char *compressed = NULL;
+
+       if (!params || !group)
+               return NULL;
+
+       if (key->sbox) {
+               if (!is_default_sbox(key->sbox)) {
+                       params->sbox = ASN1_OCTET_STRING_new();
+                       if (!params->sbox)
+                               goto err;
+
+                       if (!ASN1_OCTET_STRING_set(params->sbox, key->sbox,
+                               sizeof(default_sbox)))
+                               goto err;
+               }
+       }
+       /*
+         * Checking if group represents a standard curve.
+        * If we get NID_undef, that means the curve is custom.
+         */
+       curve_nid = curve_nid_from_group(group);
+       if (NID_undef == curve_nid) {
+               /* Custom curve. */
+               params->curve->curve.custom_curve = DSTU_CustomCurveSpec_new();
+               if (!params->curve->curve.custom_curve)
+                       goto err;
+               params->curve->type = DSTU_CUSTOM_CURVE;
+
+               g = EC_GROUP_get0_generator(group);
+               if (!g)
+                       goto err;
+
+               ctx = BN_CTX_new();
+               BN_CTX_start(ctx);
+
+               p = BN_CTX_get(ctx);
+               a = BN_CTX_get(ctx);
+               b = BN_CTX_get(ctx);
+               n = BN_CTX_get(ctx);
+
+               if (!n)
+                       goto err;
+
+               if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx))
+                       goto err;
+
+               if (!EC_GROUP_get_order(group, n, ctx))
+                       goto err;
+
+               if (!BN_GF2m_poly2arr(p, poly, sizeof(poly) / sizeof(int)))
+                       goto err;
+
+               if 
(!ASN1_INTEGER_set(params->curve->curve.custom_curve->field->m,
+                       poly[0]))
+                       goto err;
+
+               if ((-1 == poly[3]) && (0 == poly[2])) {
+                       /* We have a trinomial. */
+                       params->curve->curve.custom_curve->field->poly->poly.k =
+                           ASN1_INTEGER_new();
+                       if 
(!params->curve->curve.custom_curve->field->poly->poly.k)
+                               goto err;
+                       params->curve->curve.custom_curve->field->poly->type =
+                           DSTU_TRINOMIAL;
+                       if (!ASN1_INTEGER_set
+                           
(params->curve->curve.custom_curve->field->poly->poly.k,
+                               poly[1]))
+                               goto err;
+               } else if ((-1 == poly[5]) && (0 == poly[4])) {
+                       /* We have a pentanomial. */
+                       
params->curve->curve.custom_curve->field->poly->poly.pentanomial =
+                           DSTU_Pentanomial_new();
+                       if (!params->curve->curve.custom_curve->field->poly->
+                           poly.pentanomial)
+                               goto err;
+                       params->curve->curve.custom_curve->field->poly->type =
+                           DSTU_PENTANOMIAL;
+
+                       if (!ASN1_INTEGER_set
+                           (params->curve->curve.custom_curve->field->poly->
+                               poly.pentanomial->l, poly[1]))
+                               goto err;
+
+                       if (!ASN1_INTEGER_set
+                           (params->curve->curve.custom_curve->field->poly->
+                               poly.pentanomial->j, poly[2]))
+                               goto err;
+
+                       if (!ASN1_INTEGER_set
+                           (params->curve->curve.custom_curve->field->poly->
+                               poly.pentanomial->k, poly[3]))
+                               goto err;
+               } else
+                       goto err;
+
+               if (!BN_to_ASN1_INTEGER(a, 
params->curve->curve.custom_curve->a))
+                       goto err;
+
+               if (!BN_to_ASN1_INTEGER(n, 
params->curve->curve.custom_curve->n))
+                       goto err;
+
+               field_size = (poly[0] + 7) / 8;
+
+               compressed = malloc(field_size);
+               if (!compressed)
+                       goto err;
+
+               if (!bn_encode(b, compressed, field_size))
+                       goto err;
+
+               if (is_little_endian)
+                       reverse_bytes(compressed, field_size);
+
+               if (!ASN1_OCTET_STRING_set(params->curve->curve.custom_curve->b,
+                       compressed, field_size))
+                       goto err;
+
+               if (!dstu_point_compress(group, g, compressed, field_size))
+                       goto err;
+
+               if (is_little_endian)
+                       reverse_bytes(compressed, field_size);
+
+               if 
(!ASN1_OCTET_STRING_set(params->curve->curve.custom_curve->bp,
+                       compressed, field_size))
+                       goto err;
+
+       } else {
+               /* Standard curve. */
+               params->curve->curve.named_curve = OBJ_nid2obj(curve_nid);
+               if (!params->curve->curve.named_curve)
+                       goto err;
+               params->curve->type = DSTU_STANDARD_CURVE;
+       }
+
+       ret = params;
+       params = NULL;
+
+err:
+
+       if (compressed)
+               free(compressed);
+
+       if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       if (params)
+               DSTU_AlgorithmParameters_free(params);
+
+       return ret;
+}
+
+DSTU_KEY *
+key_from_asn1(const DSTU_AlgorithmParameters * params,
+    int is_little_endian)
+{
+       DSTU_KEY *key = DSTU_KEY_new(), *ret = NULL;
+       BIGNUM *p, *a, *b, *N;
+       EC_GROUP *group = NULL;
+       EC_POINT *g = NULL;
+       BN_CTX *ctx = NULL;
+       int poly[6];
+       unsigned char *reverse_buffer = NULL;
+
+       if (!key)
+               return NULL;
+
+       if (params->sbox) {
+               if (64 != ASN1_STRING_length(params->sbox))
+                       goto err;
+
+               if (!is_default_sbox(ASN1_STRING_data(params->sbox))) {
+                       key->sbox = copy_sbox(ASN1_STRING_data(params->sbox));
+                       if (!(key->sbox))
+                               goto err;
+               }
+       }
+       if (DSTU_STANDARD_CURVE == params->curve->type) {
+               group = 
group_from_nid(OBJ_obj2nid(params->curve->curve.named_curve));
+               if (!group)
+                       goto err;
+
+               if (!EC_KEY_set_group(key->ec, group))
+                       goto err;
+       } else {
+               poly[0] =
+                   
ASN1_INTEGER_get(params->curve->curve.custom_curve->field->m);
+               if (poly[0] <= 0)
+                       goto err;
+
+               if (DSTU_TRINOMIAL
+                   == params->curve->curve.custom_curve->field->poly->type) {
+                       poly[1] =
+                           ASN1_INTEGER_get(params->curve->curve.custom_curve->
+                           field->poly->poly.k);
+                       if (poly[1] <= 0)
+                               goto err;
+                       poly[2] = 0;
+                       poly[3] = -1;
+               } else {
+                       poly[1] =
+                           ASN1_INTEGER_get(params->curve->curve.custom_curve->
+                           field->poly->poly.pentanomial->l);
+                       if (poly[1] <= 0)
+                               goto err;
+
+                       poly[2] =
+                           ASN1_INTEGER_get(params->curve->curve.custom_curve->
+                           field->poly->poly.pentanomial->j);
+                       if (poly[2] <= 0)
+                               goto err;
+
+                       poly[3] =
+                           ASN1_INTEGER_get(params->curve->curve.custom_curve->
+                           field->poly->poly.pentanomial->k);
+                       if (poly[3] <= 0)
+                               goto err;
+
+                       poly[4] = 0;
+                       poly[5] = -1;
+               }
+
+               ctx = BN_CTX_new();
+               if (!ctx)
+                       goto err;
+
+               BN_CTX_start(ctx);
+
+               p = BN_CTX_get(ctx);
+               a = BN_CTX_get(ctx);
+               b = BN_CTX_get(ctx);
+               N = BN_CTX_get(ctx);
+
+               if (!N)
+                       goto err;
+
+               if (!BN_GF2m_arr2poly(poly, p))
+                       goto err;
+
+               if (!ASN1_INTEGER_to_BN(params->curve->curve.custom_curve->a, 
a))
+                       goto err;
+
+               if (!BN_is_one(a) && !BN_is_zero(a))
+                       goto err;
+
+               if (is_little_endian) {
+                       reverse_buffer =
+                           malloc(ASN1_STRING_length
+                           (params->curve->curve.custom_curve->b));
+                       if (!reverse_buffer)
+                               goto err;
+
+                       reverse_bytes_copy(reverse_buffer,
+                           ASN1_STRING_data(params->curve->
+                               curve.custom_curve->b),
+                           ASN1_STRING_length(params->curve->
+                               curve.custom_curve->b));
+
+                       if (!BN_bin2bn(reverse_buffer,
+                               ASN1_STRING_length(params->curve->
+                                   curve.custom_curve->b), b)) {
+                               free(reverse_buffer);
+                               goto err;
+                       }
+                       free(reverse_buffer);
+               } else {
+                       if (!BN_bin2bn
+                           
(ASN1_STRING_data(params->curve->curve.custom_curve->b),
+                               
ASN1_STRING_length(params->curve->curve.custom_curve->b), b))
+                               goto err;
+               }
+
+               if (!ASN1_INTEGER_to_BN(params->curve->curve.custom_curve->n, 
N))
+                       goto err;
+
+               group = EC_GROUP_new_curve_GF2m(p, a, b, ctx);
+               if (!group)
+                       goto err;
+
+               g = EC_POINT_new(group);
+               if (!g)
+                       goto err;
+
+               if (is_little_endian) {
+                       reverse_buffer =
+                           malloc(ASN1_STRING_length
+                           (params->curve->curve.custom_curve->bp));
+                       if (!reverse_buffer)
+                               goto err;
+
+                       reverse_bytes_copy(reverse_buffer,
+                           ASN1_STRING_data(params->curve->
+                               curve.custom_curve->bp),
+                           ASN1_STRING_length(params->curve->
+                               curve.custom_curve->bp));
+
+                       if (!dstu_point_expand(reverse_buffer,
+                               ASN1_STRING_length(params->curve->
+                                   curve.custom_curve->bp),
+                               group, g)) {
+                               free(reverse_buffer);
+                               goto err;
+                       }
+                       free(reverse_buffer);
+               } else {
+                       if (!dstu_point_expand
+                           
(ASN1_STRING_data(params->curve->curve.custom_curve->bp),
+                               
ASN1_STRING_length(params->curve->curve.custom_curve->bp),
+                               group, g))
+                               goto err;
+               }
+
+               if (!EC_GROUP_set_generator(group, g, N, BN_value_one()))
+                       goto err;
+
+               if (!EC_KEY_set_group(key->ec, group))
+                       goto err;
+       }
+
+       ret = key;
+       key = NULL;
+
+err:
+
+       if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       if (g)
+               EC_POINT_free(g);
+
+       if (group)
+               EC_GROUP_free(group);
+
+       if (key)
+               DSTU_KEY_free(key);
+
+       return ret;
+}
+
+DSTU_KEY_CTX *
+DSTU_KEY_CTX_new(void)
+{
+       DSTU_KEY_CTX *ctx = malloc(sizeof(DSTU_KEY_CTX));
+       if (ctx) {
+               memset(ctx, 0, sizeof(DSTU_KEY_CTX));
+               return ctx;
+       }
+       return NULL;
+}
+
+void
+DSTU_KEY_CTX_set(DSTU_KEY_CTX * ctx, EC_GROUP * group,
+    unsigned char *sbox)
+{
+       if (group) {
+               if (ctx->group)
+                       EC_GROUP_free(ctx->group);
+               ctx->group = group;
+       }
+       if (sbox) {
+               if (ctx->sbox)
+                       free(ctx->sbox);
+               ctx->sbox = sbox;
+       }
+}
+
+DSTU_KEY_CTX *
+DSTU_KEY_CTX_copy(const DSTU_KEY_CTX * ctx)
+{
+       DSTU_KEY_CTX *copy = DSTU_KEY_CTX_new();
+
+       if (!copy)
+               return NULL;
+
+       copy->type = ctx->type;
+
+       if (ctx->group) {
+               copy->group = EC_GROUP_dup(ctx->group);
+               if (!(copy->group)) {
+                       DSTU_KEY_CTX_free(copy);
+                       return NULL;
+               }
+       }
+       if (ctx->sbox) {
+               copy->sbox = copy_sbox(ctx->sbox);
+               if (!(copy->sbox)) {
+                       DSTU_KEY_CTX_free(copy);
+                       return NULL;
+               }
+       }
+       return copy;
+}
+
+void
+DSTU_KEY_CTX_free(DSTU_KEY_CTX * ctx)
+{
+       if (ctx) {
+               if (ctx->group) {
+                       EC_GROUP_free(ctx->group);
+                       ctx->group = NULL;
+               }
+               if (ctx->sbox) {
+                       free(ctx->sbox);
+                       ctx->sbox = NULL;
+               }
+               free(ctx);
+       }
+}
Index: lib/libssl/src/crypto/dstu/dstu_key.h
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_key.h
diff -N lib/libssl/src/crypto/dstu/dstu_key.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_key.h       26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,42 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#ifndef DSTU_KEY_H_
+#define DSTU_KEY_H_
+
+#include <openssl/ec.h>
+#include "dstu_asn1.h"
+
+typedef struct dstu_key_st {
+       EC_KEY *ec;
+       unsigned char *sbox;
+} DSTU_KEY;
+
+typedef struct dstu_key_ctx_st {
+       int type;
+       EC_GROUP *group;
+       unsigned char *sbox;
+} DSTU_KEY_CTX;
+
+DSTU_KEY *DSTU_KEY_new(void);
+void DSTU_KEY_set(DSTU_KEY * key, EC_KEY * ec, unsigned char *sbox);
+DSTU_KEY *
+key_from_asn1(const DSTU_AlgorithmParameters * params,
+    int is_little_endian);
+DSTU_AlgorithmParameters *
+asn1_from_key(const DSTU_KEY * key,
+    int is_little_endian);
+void DSTU_KEY_free(DSTU_KEY * key);
+
+DSTU_KEY_CTX *DSTU_KEY_CTX_new(void);
+void
+DSTU_KEY_CTX_set(DSTU_KEY_CTX * ctx, EC_GROUP * group,
+    unsigned char *sbox);
+DSTU_KEY_CTX *DSTU_KEY_CTX_copy(const DSTU_KEY_CTX * ctx);
+void DSTU_KEY_CTX_free(DSTU_KEY_CTX * ctx);
+
+#endif                         /* DSTU_KEY_H_ */
Index: lib/libssl/src/crypto/dstu/dstu_params.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_params.c
diff -N lib/libssl/src/crypto/dstu/dstu_params.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_params.c    26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,707 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include "dstu_params.h"
+#include "../gost/gost_locl.h"
+#include <string.h>
+#include <openssl/evp.h>
+
+unsigned char default_sbox[64] = {
+       0xa9, 0xd6, 0xeb, 0x45, 0xf1, 0x3c, 0x70, 0x82,
+       0x80, 0xc4, 0x96, 0x7b, 0x23, 0x1f, 0x5e, 0xad,
+       0xf6, 0x58, 0xeb, 0xa4, 0xc0, 0x37, 0x29, 0x1d,
+       0x38, 0xd9, 0x6b, 0xf0, 0x25, 0xca, 0x4e, 0x17,
+       0xf8, 0xe9, 0x72, 0x0d, 0xc6, 0x15, 0xb4, 0x3a,
+       0x28, 0x97, 0x5f, 0x0b, 0xc1, 0xde, 0xa3, 0x64,
+       0x38, 0xb5, 0x64, 0xea, 0x2c, 0x17, 0x9f, 0xd0,
+       0x12, 0x3e, 0x6d, 0xb8, 0xfa, 0xc5, 0x79, 0x04
+};
+
+static void
+unpack_sbox(const unsigned char *packed_sbox, gost_subst_block * unpacked_sbox)
+{
+       int i;
+       for (i = 0; i < 8; i++) {
+               unpacked_sbox->k1[2 * i] = 0x0f & (packed_sbox[i] >> 4);
+               unpacked_sbox->k1[(2 * i) + 1] = 0x0f & packed_sbox[i];
+
+               unpacked_sbox->k2[2 * i] = 0x0f & (packed_sbox[i + 8] >> 4);
+               unpacked_sbox->k2[(2 * i) + 1] = 0x0f & packed_sbox[i + 8];
+
+               unpacked_sbox->k3[2 * i] = 0x0f & (packed_sbox[i + 16] >> 4);
+               unpacked_sbox->k3[(2 * i) + 1] = 0x0f & packed_sbox[i + 16];
+
+               unpacked_sbox->k4[2 * i] = 0x0f & (packed_sbox[i + 24] >> 4);
+               unpacked_sbox->k4[(2 * i) + 1] = 0x0f & packed_sbox[i + 24];
+
+               unpacked_sbox->k5[2 * i] = 0x0f & (packed_sbox[i + 32] >> 4);
+               unpacked_sbox->k5[(2 * i) + 1] = 0x0f & packed_sbox[i + 32];
+
+               unpacked_sbox->k6[2 * i] = 0x0f & (packed_sbox[i + 40] >> 4);
+               unpacked_sbox->k6[(2 * i) + 1] = 0x0f & packed_sbox[i + 40];
+
+               unpacked_sbox->k7[2 * i] = 0x0f & (packed_sbox[i + 48] >> 4);
+               unpacked_sbox->k7[(2 * i) + 1] = 0x0f & packed_sbox[i + 48];
+
+               unpacked_sbox->k8[2 * i] = 0x0f & (packed_sbox[i + 56] >> 4);
+               unpacked_sbox->k8[(2 * i) + 1] = 0x0f & packed_sbox[i + 56];
+       }
+}
+
+static void
+pack_sbox(const gost_subst_block * unpacked_sbox, unsigned char *packed_sbox)
+{
+       int i;
+       for (i = 0; i < 8; i++) {
+               packed_sbox[i] =
+                   ((unpacked_sbox->
+                       k1[2 * i] << 4) & 0xf0) | (unpacked_sbox->k1[(2 * i) +
+                       1] & 0x0f);
+               packed_sbox[i + 8] =
+                   ((unpacked_sbox->
+                       k2[2 * i] << 4) & 0xf0) | (unpacked_sbox->k2[(2 * i) +
+                       1] & 0x0f);
+               packed_sbox[i + 16] =
+                   ((unpacked_sbox->
+                       k3[2 * i] << 4) & 0xf0) | (unpacked_sbox->k3[(2 * i) +
+                       1] & 0x0f);
+               packed_sbox[i + 24] =
+                   ((unpacked_sbox->
+                       k4[2 * i] << 4) & 0xf0) | (unpacked_sbox->k4[(2 * i) +
+                       1] & 0x0f);
+               packed_sbox[i + 32] =
+                   ((unpacked_sbox->
+                       k5[2 * i] << 4) & 0xf0) | (unpacked_sbox->k5[(2 * i) +
+                       1] & 0x0f);
+               packed_sbox[i + 40] =
+                   ((unpacked_sbox->
+                       k6[2 * i] << 4) & 0xf0) | (unpacked_sbox->k6[(2 * i) +
+                       1] & 0x0f);
+               packed_sbox[i + 48] =
+                   ((unpacked_sbox->
+                       k7[2 * i] << 4) & 0xf0) | (unpacked_sbox->k7[(2 * i) +
+                       1] & 0x0f);
+               packed_sbox[i + 56] =
+                   ((unpacked_sbox->
+                       k8[2 * i] << 4) & 0xf0) | (unpacked_sbox->k8[(2 * i) +
+                       1] & 0x0f);
+
+       }
+}
+
+void
+dstu_set_sbox(GOST2814789_KEY * key, const unsigned char sbox[64])
+{
+       gost_subst_block unpacked_sbox;
+       unsigned int t;
+       int i;
+
+       if (!sbox) {
+               /* set default */
+               sbox = default_sbox;
+       }
+       unpack_sbox(sbox, &unpacked_sbox);
+
+       for (i = 0; i < 256; i++) {
+               t = (unsigned int) (unpacked_sbox.k8[i >> 4] << 4 | 
unpacked_sbox.k7[i & 15]) << 24;
+               key->k87[i] = (t << 11) | (t >> 21);
+               t = (unsigned int) (unpacked_sbox.k6[i >> 4] << 4 | 
unpacked_sbox.k5[i & 15]) << 16;
+               key->k65[i] = (t << 11) | (t >> 21);
+               t = (unsigned int) (unpacked_sbox.k4[i >> 4] << 4 | 
unpacked_sbox.k3[i & 15]) << 8;
+               key->k43[i] = (t << 11) | (t >> 21);
+               t = (unsigned int) (unpacked_sbox.k2[i >> 4] << 4 | 
unpacked_sbox.k1[i & 15]) << 0;
+               key->k21[i] = (t << 11) | (t >> 21);
+       }
+}
+
+void
+dstu_get_sbox(const GOST2814789_KEY * ctx, unsigned char sbox[64])
+{
+       gost_subst_block unpacked_sbox;
+       int i;
+
+       for (i = 0; i < 256; i++) {
+               unpacked_sbox.k8[i >> 4] = (ctx->k87[i] >> 28) & 0xf;
+               unpacked_sbox.k7[i & 15] = (ctx->k87[i] >> 24) & 0xf;
+
+               unpacked_sbox.k6[i >> 4] = (ctx->k65[i] >> 20) & 0xf;
+               unpacked_sbox.k5[i & 15] = (ctx->k65[i] >> 16) & 0xf;
+
+               unpacked_sbox.k4[i >> 4] = (ctx->k43[i] >> 12) & 0xf;
+               unpacked_sbox.k3[i & 15] = (ctx->k43[i] >> 8) & 0xf;
+
+               unpacked_sbox.k2[i >> 4] = (ctx->k21[i] >> 4) & 0xf;
+               unpacked_sbox.k1[i & 15] = ctx->k21[i] & 0xf;
+       }
+
+       pack_sbox(&unpacked_sbox, sbox);
+}
+
+int
+bn_encode(const BIGNUM * bn, unsigned char *buffer, int length)
+{
+       int bn_size = BN_num_bytes(bn);
+       if (length < bn_size)
+               return 0;
+
+       memset(buffer, 0, length - bn_size);
+       return BN_bn2bin(bn, buffer + (length - bn_size));
+}
+
+static unsigned char data163[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x05, 0xFF, 0x61, 0x08, 0x46, 0x2A, 0x2D, 0xC8, 0x21, 0x0A, 
0xB4,
+       0x03,
+       0x92, 0x5E, 0x63, 0x8A, 0x19, 0xC1, 0x45, 0x5D, 0x21,
+
+        /* N */ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x02,
+       0xBE,
+       0xC1, 0x2B, 0xE2, 0x26, 0x2D, 0x39, 0xBC, 0xF1, 0x4D,
+
+       /*
+         * Px
+         */
+       0x02, 0xE2, 0xF8, 0x5F, 0x5D, 0xD7, 0x4C, 0xE9, 0x83, 0xA5, 0xC4, 0x23,
+       0x72, 0x29, 0xDA, 0xF8, 0xA3, 0xF3, 0x58, 0x23, 0xBE,
+
+       /*
+         * Py
+         */
+       0x03, 0x82, 0x6F, 0x00, 0x8A, 0x8C, 0x51, 0xD7, 0xB9, 0x52, 0x84, 0xD9,
+       0xD0, 0x3F, 0xF0, 0xE0, 0x0C, 0xE2, 0xCD, 0x72, 0x3A
+};
+
+static unsigned char data167[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x6E, 0xE3, 0xCE, 0xEB, 0x23, 0x08, 0x11, 0x75, 0x9F, 0x20, 
0x51,
+       0x8A,
+       0x09, 0x30, 0xF1, 0xA4, 0x31, 0x5A, 0x82, 0x7D, 0xAC,
+
+        /* N */ 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF,
+       0xB1,
+       0x2E, 0xBC, 0xC7, 0xD7, 0xF2, 0x9F, 0xF7, 0x70, 0x1F,
+
+       /*
+         * Px
+         */
+       0x7A, 0x1F, 0x66, 0x53, 0x78, 0x6A, 0x68, 0x19, 0x28, 0x03, 0x91, 0x0A,
+       0x3D, 0x30, 0xB2, 0xA2, 0x01, 0x8B, 0x21, 0xCD, 0x54,
+
+       /*
+         * Py
+         */
+       0x5F, 0x49, 0xEB, 0x26, 0x78, 0x1C, 0x0E, 0xC6, 0xB8, 0x90, 0x91, 0x56,
+       0xD9, 0x8E, 0xD4, 0x35, 0xE4, 0x5F, 0xD5, 0x99, 0x18
+};
+
+static unsigned char data173[] = {
+        /* A */ 0x00,
+
+        /* B */ 0x10, 0x85, 0x76, 0xC8, 0x04, 0x99, 0xDB, 0x2F, 0xC1, 0x6E, 
0xDD,
+       0xF6,
+       0x85, 0x3B, 0xBB, 0x27, 0x8F, 0x6B, 0x6F, 0xB4, 0x37, 0xD9,
+
+        /* N */ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00,
+       0x18,
+       0x9B, 0x4E, 0x67, 0x60, 0x6E, 0x38, 0x25, 0xBB, 0x28, 0x31,
+
+       /*
+         * Px
+         */
+       0x04, 0xD4, 0x1A, 0x61, 0x9B, 0xCC, 0x6E, 0xAD, 0xF0, 0x44, 0x8F, 0xA2,
+       0x2F, 0xAD, 0x56, 0x7A, 0x91, 0x81, 0xD3, 0x73, 0x89, 0xCA,
+
+       /*
+         * Py
+         */
+       0x10, 0xB5, 0x1C, 0xC1, 0x28, 0x49, 0xB2, 0x34, 0xC7, 0x5E, 0x6D, 0xD2,
+       0x02, 0x8B, 0xF7, 0xFF, 0x5C, 0x1C, 0xE0, 0xD9, 0x91, 0xA1
+};
+
+static unsigned char data179[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x04, 0xA6, 0xE0, 0x85, 0x65, 0x26, 0x43, 0x6F, 0x2F, 0x88, 
0xDD,
+       0x07,
+       0xA3, 0x41, 0xE3, 0x2D, 0x04, 0x18, 0x45, 0x72, 0xBE, 0xB7, 0x10,
+
+        /* N */ 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF,
+       0xFF,
+       0xB9, 0x81, 0x96, 0x04, 0x35, 0xFE, 0x5A, 0xB6, 0x42, 0x36, 0xEF,
+
+       /*
+         * Px
+         */
+       0x06, 0xBA, 0x06, 0xFE, 0x51, 0x46, 0x4B, 0x2B, 0xD2, 0x6D, 0xC5, 0x7F,
+       0x48, 0x81, 0x9B, 0xA9, 0x95, 0x46, 0x67, 0x02, 0x2C, 0x7D, 0x03,
+
+       /*
+         * Py
+         */
+       0x02, 0x5F, 0xBC, 0x36, 0x35, 0x82, 0xDC, 0xEC, 0x06, 0x50, 0x80, 0xCA,
+       0x82, 0x87, 0xAA, 0xFF, 0x09, 0x78, 0x8A, 0x66, 0xDC, 0x3A, 0x9E
+};
+
+static unsigned char data191[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x7B, 0xC8, 0x6E, 0x21, 0x02, 0x90, 0x2E, 0xC4, 0xD5, 0x89, 
0x0E,
+       0x8B,
+       0x6B, 0x49, 0x81, 0xff, 0x27, 0xE0, 0x48, 0x27, 0x50, 0xFE, 0xFC, 0x03,
+
+        /* N */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00,
+       0x00,
+       0x69, 0xA7, 0x79, 0xCA, 0xC1, 0xDA, 0xBC, 0x67, 0x88, 0xF7, 0x47, 0x4F,
+
+       /*
+         * Px
+         */
+       0x71, 0x41, 0x14, 0xB7, 0x62, 0xF2, 0xFF, 0x4A, 0x79, 0x12, 0xA6, 0xD2,
+       0xAC, 0x58, 0xB9, 0xB5, 0xC2, 0xFC, 0xFE, 0x76, 0xDA, 0xEB, 0x71, 0x29,
+
+       /*
+         * Py
+         */
+       0x29, 0xC4, 0x1E, 0x56, 0x8B, 0x77, 0xC6, 0x17, 0xEF, 0xE5, 0x90, 0x2F,
+       0x11, 0xDB, 0x96, 0xFA, 0x96, 0x13, 0xCD, 0x8D, 0x03, 0xDB, 0x08, 0xDA
+};
+
+static unsigned char data233[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x00, 0x69, 0x73, 0xB1, 0x50, 0x95, 0x67, 0x55, 0x34, 0xC7, 
0xCF,
+       0x7E,
+       0x64, 0xA2, 0x1B, 0xD5, 0x4E, 0xF5, 0xDD, 0x3B, 0x8A, 0x03, 0x26, 0xAA,
+       0x93, 0x6E, 0xCE, 0x45, 0x4D, 0x2C,
+
+        /* N */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00,
+       0x00,
+       0x00, 0x00, 0x00, 0x13, 0xE9, 0x74, 0xE7, 0x2F, 0x8A, 0x69, 0x22, 0x03,
+       0x1D, 0x26, 0x03, 0xCF, 0xE0, 0xD7,
+
+       /*
+         * Px
+         */
+       0x00, 0x3F, 0xCD, 0xA5, 0x26, 0xB6, 0xCD, 0xF8, 0x3B, 0xA1, 0x11, 0x8D,
+       0xF3, 0x5B, 0x3C, 0x31, 0x76, 0x1D, 0x35, 0x45, 0xF3, 0x27, 0x28, 0xD0,
+       0x03, 0xEE, 0xB2, 0x5E, 0xFE, 0x96,
+
+       /*
+         * Py
+         */
+       0x00, 0x9C, 0xA8, 0xB5, 0x7A, 0x93, 0x4C, 0x54, 0xDE, 0xED, 0xA9, 0xE5,
+       0x4A, 0x7B, 0xBA, 0xD9, 0x5E, 0x3B, 0x2E, 0x91, 0xC5, 0x4D, 0x32, 0xBE,
+       0x0B, 0x9D, 0xF9, 0x6D, 0x8D, 0x35
+};
+
+static unsigned char data257[] = {
+        /* A */ 0x00,
+
+        /* B */ 0x01, 0xCE, 0xF4, 0x94, 0x72, 0x01, 0x15, 0x65, 0x7E, 0x18, 
0xF9,
+       0x38,
+       0xD7, 0xA7, 0x94, 0x23, 0x94, 0xFF, 0x94, 0x25, 0xC1, 0x45, 0x8C, 0x57,
+       0x86, 0x1F, 0x9E, 0xEA, 0x6A, 0xDB, 0xE3, 0xBE, 0x10,
+
+        /* N */ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00,
+       0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x59, 0x21, 0x3A, 0xF1, 0x82, 0xE9,
+       0x87, 0xD3, 0xE1, 0x77, 0x14, 0x90, 0x7D, 0x47, 0x0D,
+
+       /*
+         * Px
+         */
+       0x00, 0x2A, 0x29, 0xEF, 0x20, 0x7D, 0x0E, 0x9B, 0x6C, 0x55, 0xCD, 0x26,
+       0x0B, 0x30, 0x6C, 0x7E, 0x00, 0x7A, 0xC4, 0x91, 0xCA, 0x1B, 0x10, 0xC6,
+       0x23, 0x34, 0xA9, 0xE8, 0xDC, 0xD8, 0xD2, 0x0F, 0xB7,
+
+       /*
+         * Py
+         */
+       0x01, 0x06, 0x86, 0xD4, 0x1F, 0xF7, 0x44, 0xD4, 0x44, 0x9F, 0xCC, 0xF6,
+       0xD8, 0xEE, 0xA0, 0x31, 0x02, 0xE6, 0x81, 0x2C, 0x93, 0xA9, 0xD6, 0x0B,
+       0x97, 0x8B, 0x70, 0x2C, 0xF1, 0x56, 0xD8, 0x14, 0xEF
+};
+
+static unsigned char data307[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x03, 0x93, 0xC7, 0xF7, 0xD5, 0x36, 0x66, 0xB5, 0x05, 0x4B, 
0x5E,
+       0x6C,
+       0x6D, 0x3D, 0xE9, 0x4F, 0x42, 0x96, 0xC0, 0xC5, 0x99, 0xE2, 0xE2, 0xE2,
+       0x41, 0x05, 0x0D, 0xF1, 0x8B, 0x60, 0x90, 0xBD, 0xC9, 0x01, 0x86, 0x90,
+       0x49, 0x68, 0xBB,
+
+        /* N */ 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF,
+       0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x79, 0xC2, 0xF3,
+       0x82, 0x5D, 0xA7, 0x0D, 0x39, 0x0F, 0xBB, 0xA5, 0x88, 0xD4, 0x60, 0x40,
+       0x22, 0xB7, 0xB7,
+
+       /*
+         * Px
+         */
+       0x02, 0x16, 0xEE, 0x8B, 0x18, 0x9D, 0x29, 0x1A, 0x02, 0x24, 0x98, 0x4C,
+       0x1E, 0x92, 0xF1, 0xD1, 0x6B, 0xF7, 0x5C, 0xCD, 0x82, 0x5A, 0x08, 0x7A,
+       0x23, 0x9B, 0x27, 0x6D, 0x31, 0x67, 0x74, 0x3C, 0x52, 0xC0, 0x2D, 0x6E,
+       0x72, 0x32, 0xAA,
+
+       /*
+         * Py
+         */
+       0x05, 0xD9, 0x30, 0x6B, 0xAC, 0xD2, 0x2B, 0x7F, 0xAE, 0xB0, 0x9D, 0x2E,
+       0x04, 0x9C, 0x6E, 0x28, 0x66, 0xC5, 0xD1, 0x67, 0x77, 0x62, 0xA8, 0xF2,
+       0xF2, 0xDC, 0x9A, 0x11, 0xC7, 0xF7, 0xBE, 0x83, 0x40, 0xAB, 0x22, 0x37,
+       0xC7, 0xF2, 0xA0
+};
+
+static unsigned char data367[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x43, 0xFC, 0x8A, 0xD2, 0x42, 0xB0, 0xB7, 0xA6, 0xF3, 0xD1, 
0x62,
+       0x7A,
+       0xD5, 0x65, 0x44, 0x47, 0x55, 0x6B, 0x47, 0xBF, 0x6A, 0xA4, 0xA6, 0x4B,
+       0x0C, 0x2A, 0xFE, 0x42, 0xCA, 0xDA, 0xB8, 0xF9, 0x3D, 0x92, 0x39, 0x4C,
+       0x79, 0xA7, 0x97, 0x55, 0x43, 0x7B, 0x56, 0x99, 0x51, 0x36,
+
+        /* N */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00,
+       0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C,
+       0x30, 0x0B, 0x75, 0xA3, 0xFA, 0x82, 0x4F, 0x22, 0x42, 0x8F, 0xD2, 0x8C,
+       0xE8, 0x81, 0x22, 0x45, 0xEF, 0x44, 0x04, 0x9B, 0x2D, 0x49,
+
+       /*
+         * Px
+         */
+       0x32, 0x4A, 0x6E, 0xDD, 0xD5, 0x12, 0xF0, 0x8C, 0x49, 0xA9, 0x9A, 0xE0,
+       0xD3, 0xF9, 0x61, 0x19, 0x7A, 0x76, 0x41, 0x3E, 0x7B, 0xE8, 0x1A, 0x40,
+       0x0C, 0xA6, 0x81, 0xE0, 0x96, 0x39, 0xB5, 0xFE, 0x12, 0xE5, 0x9A, 0x10,
+       0x9F, 0x78, 0xBF, 0x4A, 0x37, 0x35, 0x41, 0xB3, 0xB9, 0xA1,
+
+       /*
+         * Py
+         */
+       0x01, 0xAB, 0x59, 0x7A, 0x5B, 0x44, 0x77, 0xF5, 0x9E, 0x39, 0x53, 0x90,
+       0x07, 0xC7, 0xF9, 0x77, 0xD1, 0xA5, 0x67, 0xB9, 0x2B, 0x04, 0x3A, 0x49,
+       0xC6, 0xB6, 0x19, 0x84, 0xC3, 0xFE, 0x34, 0x81, 0xAA, 0xF4, 0x54, 0xCD,
+       0x41, 0xBA, 0x1F, 0x05, 0x16, 0x26, 0x44, 0x2B, 0x3C, 0x10
+};
+
+static unsigned char data431[] = {
+        /* A */ 0x01,
+
+        /* B */ 0x03, 0xCE, 0x10, 0x49, 0x0F, 0x6A, 0x70, 0x8F, 0xC2, 0x6D, 
0xFE,
+       0x8C,
+       0x3D, 0x27, 0xC4, 0xF9, 0x4E, 0x69, 0x01, 0x34, 0xD5, 0xBF, 0xF9, 0x88,
+       0xD8, 0xD2, 0x8A, 0xAE, 0xAE, 0xDE, 0x97, 0x59, 0x36, 0xC6, 0x6B, 0xAC,
+       0x53, 0x6B, 0x18, 0xAE, 0x2D, 0xC3, 0x12, 0xCA, 0x49, 0x31, 0x17, 0xDA,
+       0xA4, 0x69, 0xC6, 0x40, 0xCA, 0xF3,
+
+        /* N */ 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF,
+       0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xBA, 0x31, 0x75, 0x45, 0x80, 0x09, 0xA8, 0xC0, 0xA7,
+       0x24, 0xF0, 0x2F, 0x81, 0xAA, 0x8A, 0x1F, 0xCB, 0xAF, 0x80, 0xD9, 0x0C,
+       0x7A, 0x95, 0x11, 0x05, 0x04, 0xCF,
+
+       /*
+         * Px
+         */
+       0x1A, 0x62, 0xBA, 0x79, 0xD9, 0x81, 0x33, 0xA1, 0x6B, 0xBA, 0xE7, 0xED,
+       0x9A, 0x8E, 0x03, 0xC3, 0x2E, 0x08, 0x24, 0xD5, 0x7A, 0xEF, 0x72, 0xF8,
+       0x89, 0x86, 0x87, 0x4E, 0x5A, 0xAE, 0x49, 0xC2, 0x7B, 0xED, 0x49, 0xA2,
+       0xA9, 0x50, 0x58, 0x06, 0x84, 0x26, 0xC2, 0x17, 0x1E, 0x99, 0xFD, 0x3B,
+       0x43, 0xC5, 0x94, 0x7C, 0x85, 0x7D,
+
+       /*
+         * Py
+         */
+       0x70, 0xB5, 0xE1, 0xE1, 0x40, 0x31, 0xC1, 0xF7, 0x0B, 0xBE, 0xFE, 0x96,
+       0xBD, 0xDE, 0x66, 0xF4, 0x51, 0x75, 0x4B, 0x4C, 0xA5, 0xF4, 0x8D, 0xA2,
+       0x41, 0xF3, 0x31, 0xAA, 0x39, 0x6B, 0x8D, 0x18, 0x39, 0xA8, 0x55, 0xC1,
+       0x76, 0x9B, 0x1E, 0xA1, 0x4B, 0xA5, 0x33, 0x08, 0xB5, 0xE2, 0x72, 0x37,
+       0x24, 0xE0, 0x90, 0xE0, 0x2D, 0xB9
+};
+
+DSTU_NAMED_CURVE dstu_curves[] = {
+       {
+               NID_uacurve0,
+               {
+       163, 7, 6, 3, 0, -1}, data163},
+       {
+               NID_uacurve1,
+               {
+       167, 6, 0, -1, 0, 0}, data167},
+       {
+               NID_uacurve2,
+               {
+       173, 10, 2, 1, 0, -1}, data173},
+       {
+               NID_uacurve3,
+               {
+       179, 4, 2, 1, 0, -1}, data179},
+       {
+               NID_uacurve4,
+               {
+       191, 9, 0, -1, 0, 0}, data191},
+       {
+               NID_uacurve5,
+               {
+       233, 9, 4, 1, 0, -1}, data233},
+       {
+               NID_uacurve6,
+               {
+       257, 12, 0, -1, 0, 0}, data257},
+       {
+               NID_uacurve7,
+               {
+       307, 8, 4, 2, 0, -1}, data307},
+       {
+               NID_uacurve8,
+               {
+       367, 21, 0, -1, 0, 0}, data367},
+       {
+               NID_uacurve9,
+               {
+       431, 5, 3, 1, 0, -1}, data431}
+};
+
+int
+curve_nid_from_group(const EC_GROUP * group)
+{
+       int m = EC_GROUP_get_degree(group), i, nid = NID_undef;
+       EC_GROUP *std_group = NULL;
+
+       for (i = 0; i < (sizeof(dstu_curves) / sizeof(DSTU_NAMED_CURVE)); i++) {
+               if (m == dstu_curves[i].poly[0])
+                       break;
+       }
+
+       if (i < (sizeof(dstu_curves) / sizeof(DSTU_NAMED_CURVE))) {
+               std_group = group_from_named_curve(i);
+
+               if (std_group) {
+                       if (!EC_GROUP_cmp(group, std_group, NULL))
+                               nid = dstu_curves[i].nid;
+               }
+       }
+       if (std_group)
+               EC_GROUP_free(std_group);
+
+       return nid;
+}
+
+EC_GROUP *
+group_from_named_curve(int curve_num)
+{
+       int bytesize = ((dstu_curves[curve_num].poly[0]) + 7) / 8;
+       BIGNUM *p, *a, *b, *Px, *Py, *N;
+       BN_CTX *ctx = NULL;
+       EC_GROUP *group = NULL, *ret = NULL;
+       EC_POINT *P = NULL;
+       unsigned char *data = dstu_curves[curve_num].data;
+
+       ctx = BN_CTX_new();
+       if (!ctx)
+               return NULL;
+
+       BN_CTX_start(ctx);
+
+       p = BN_CTX_get(ctx);
+       a = BN_CTX_get(ctx);
+       b = BN_CTX_get(ctx);
+       N = BN_CTX_get(ctx);
+       Px = BN_CTX_get(ctx);
+       Py = BN_CTX_get(ctx);
+
+       if (!Py)
+               goto err;
+
+       if (!BN_GF2m_arr2poly(dstu_curves[curve_num].poly, p))
+               goto err;
+
+       if (*data)
+               BN_one(a);
+       else
+               BN_zero(a);
+
+       data++;
+
+       if (!BN_bin2bn(data, bytesize, b))
+               goto err;
+       data += bytesize;
+
+       group = EC_GROUP_new_curve_GF2m(p, a, b, ctx);
+       if (!group)
+               goto err;
+
+       if (!BN_bin2bn(data, bytesize, N))
+               goto err;
+       data += bytesize;
+
+       P = EC_POINT_new(group);
+       if (!P)
+               goto err;
+
+       if (!BN_bin2bn(data, bytesize, Px))
+               goto err;
+       data += bytesize;
+
+       if (!BN_bin2bn(data, bytesize, Py))
+               goto err;
+
+       if (!EC_POINT_set_affine_coordinates_GF2m(group, P, Px, Py, ctx))
+               goto err;
+
+       if (!EC_GROUP_set_generator(group, P, N, BN_value_one()))
+               goto err;
+
+       ret = group;
+       group = NULL;
+
+err:   if (P)
+               EC_POINT_free(P);
+       if (group)
+               EC_GROUP_free(group);
+
+       if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       return ret;
+}
+
+EC_GROUP *
+group_from_nid(int nid)
+{
+       int i;
+
+       for (i = 0; i < (sizeof(dstu_curves) / sizeof(DSTU_NAMED_CURVE)); i++) {
+               if (nid == dstu_curves[i].nid)
+                       return group_from_named_curve(i);
+       }
+
+       return NULL;
+}
+
+int
+dstu_generate_key(EC_KEY * key)
+{
+       const EC_GROUP *group = EC_KEY_get0_group(key);
+       BIGNUM *order, *prk;
+       BN_CTX *ctx = NULL;
+       int ret = 0;
+
+       if (!group)
+               return 0;
+
+       ctx = BN_CTX_new();
+       if (!ctx)
+               return 0;
+
+       BN_CTX_start(ctx);
+
+       order = BN_CTX_get(ctx);
+       prk = BN_CTX_get(ctx);
+
+       if (!prk)
+               goto err;
+
+       if (!EC_GROUP_get_order(group, order, NULL))
+               goto err;
+
+       do {
+               if (!BN_rand_range(prk, order))
+                       goto err;
+       }
+       while (BN_is_zero(prk));
+
+       if (!EC_KEY_set_private_key(key, prk))
+               goto err;
+
+       ret = dstu_add_public_key(key);
+
+err:   if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       return ret;
+}
+
+int
+dstu_add_public_key(EC_KEY * key)
+{
+       EC_POINT *pbk = NULL;
+       const EC_GROUP *group = EC_KEY_get0_group(key);
+       const BIGNUM *prk = EC_KEY_get0_private_key(key);
+       int ret = 0;
+
+       if (!group || !prk)
+               return 0;
+
+       pbk = EC_POINT_new(group);
+       if (!pbk)
+               return 0;
+
+       if (!EC_POINT_mul(group, pbk, prk, NULL, NULL, NULL))
+               goto err;
+
+       if (!EC_POINT_invert(group, pbk, NULL))
+               goto err;
+
+       if (!EC_KEY_set_public_key(key, pbk))
+               goto err;
+
+       ret = 1;
+
+err:   if (pbk)
+               EC_POINT_free(pbk);
+       return ret;
+}
+
+void
+reverse_bytes(void *mem, int size)
+{
+       unsigned char *bytes = mem;
+       unsigned char tmp;
+       int i;
+
+       for (i = 0; i < (size / 2); i++) {
+               tmp = bytes[i];
+               bytes[i] = bytes[size - 1 - i];
+               bytes[size - 1 - i] = tmp;
+       }
+}
+
+void
+reverse_bytes_copy(void *dst, const void *src, int size)
+{
+       unsigned char *to = dst;
+       const unsigned char *from = src;
+       int i;
+
+       for (i = 0; i < size; i++)
+               to[i] = from[size - 1 - i];
+}
+
+unsigned char *
+copy_sbox(const unsigned char sbox[64])
+{
+       unsigned char *copy = malloc(sizeof(default_sbox));
+
+       if (copy)
+               memcpy(copy, sbox, sizeof(default_sbox));
+
+       return copy;
+}
+
+int
+is_default_sbox(const unsigned char sbox[64])
+{
+       return !memcmp(default_sbox, sbox, sizeof(default_sbox));
+}
Index: lib/libssl/src/crypto/dstu/dstu_params.h
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_params.h
diff -N lib/libssl/src/crypto/dstu/dstu_params.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_params.h    26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,44 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#ifndef DSTU_PARAMS_H_
+#define DSTU_PARAMS_H_
+
+#include <openssl/ec.h>
+#include "dstu.h"
+
+#define DEFAULT_CURVE 6
+#define get_default_group() group_from_named_curve(DEFAULT_CURVE)
+
+typedef struct dstu_named_curve_st {
+       int nid;
+       int poly[6];
+       unsigned char *data;
+} DSTU_NAMED_CURVE;
+
+extern DSTU_NAMED_CURVE dstu_curves[];
+extern unsigned char default_sbox[64];
+
+int is_default_sbox(const unsigned char sbox[64]);
+unsigned char *copy_sbox(const unsigned char sbox[64]);
+
+EC_GROUP *group_from_named_curve(int curve_num);
+EC_GROUP *group_from_nid(int nid);
+
+int dstu_generate_key(EC_KEY * key);
+int dstu_add_public_key(EC_KEY * key);
+
+void reverse_bytes(void *mem, int size);
+void reverse_bytes_copy(void *dst, const void *src, int size);
+
+int bn_encode(const BIGNUM * bn, unsigned char *buffer, int length);
+int curve_nid_from_group(const EC_GROUP * group);
+
+void dstu_set_sbox(GOST2814789_KEY * key, const unsigned char sbox[64]);
+void dstu_get_sbox(const GOST2814789_KEY * ctx, unsigned char sbox[64]);
+
+#endif                         /* DSTU_PARAMS_H_ */
Index: lib/libssl/src/crypto/dstu/dstu_pmeth.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_pmeth.c
diff -N lib/libssl/src/crypto/dstu/dstu_pmeth.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_pmeth.c     26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,395 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include "dstu.h"
+#include "dstu_key.h"
+#include "dstu_params.h"
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <string.h>
+
+#include "evp_locl.h"
+
+#define CURVE_PARAM_STR "curve"
+#define SBOX_PARAM_STR "sbox"
+
+/*
+ * Since we cannot access fields of EVP_PKEY_CTX to get associated methods to
+ * determine method nid later we use different init callbacks for each method
+ * and store the nid in the data field of ctx.
+ */
+static int
+dstu_pkey_init_le(EVP_PKEY_CTX * ctx)
+{
+       DSTU_KEY_CTX *dstu_ctx = DSTU_KEY_CTX_new();
+
+       if (!dstu_ctx) {
+               DSTUerr(DSTU_F_DSTU_PKEY_INIT_LE, ERR_R_MALLOC_FAILURE);
+               return 0;
+       }
+       dstu_ctx->type = NID_dstu4145le;
+       EVP_PKEY_CTX_set_data(ctx, dstu_ctx);
+       return 1;
+}
+
+static int
+dstu_pkey_init_be(EVP_PKEY_CTX * ctx)
+{
+       DSTU_KEY_CTX *dstu_ctx = DSTU_KEY_CTX_new();
+
+       if (!dstu_ctx) {
+               DSTUerr(DSTU_F_DSTU_PKEY_INIT_BE, ERR_R_MALLOC_FAILURE);
+               return 0;
+       }
+       dstu_ctx->type = NID_dstu4145be;
+       EVP_PKEY_CTX_set_data(ctx, dstu_ctx);
+       return 1;
+}
+
+static void
+dstu_pkey_cleanup(EVP_PKEY_CTX * ctx)
+{
+       DSTU_KEY_CTX *dstu_ctx = EVP_PKEY_CTX_get_data(ctx);
+
+       if (dstu_ctx) {
+               DSTU_KEY_CTX_free(dstu_ctx);
+               /* Just to make sure */
+               EVP_PKEY_CTX_set_data(ctx, NULL);
+       }
+}
+
+static int
+dstu_pkey_keygen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey)
+{
+       DSTU_KEY *key = NULL;
+       DSTU_KEY_CTX *dstu_ctx = EVP_PKEY_CTX_get_data(ctx);
+       unsigned char *sbox = NULL;
+       int ret = 0;
+
+       if (!dstu_ctx) {
+               DSTUerr(DSTU_F_DSTU_PKEY_KEYGEN, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       if (!(dstu_ctx->group)) {
+               dstu_ctx->group = get_default_group();
+               if (!(dstu_ctx->group))
+                       return 0;
+       }
+       key = DSTU_KEY_new();
+       if (!key)
+               goto err;
+
+       if (!EC_KEY_set_group(key->ec, dstu_ctx->group))
+               goto err;
+
+       if (!dstu_generate_key(key->ec))
+               goto err;
+
+       if (dstu_ctx->sbox) {
+               sbox = copy_sbox(dstu_ctx->sbox);
+               if (!sbox)
+                       goto err;
+               DSTU_KEY_set(key, NULL, sbox);
+       }
+       if (!EVP_PKEY_assign(pkey, dstu_ctx->type, key))
+               goto err;
+
+       key = NULL;
+       ret = 1;
+
+err:
+       if (key)
+               DSTU_KEY_free(key);
+
+       return ret;
+}
+
+static int
+dstu_pkey_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2)
+{
+       DSTU_KEY_CTX *dstu_ctx = EVP_PKEY_CTX_get_data(ctx);
+       unsigned char *sbox = NULL;
+       EC_GROUP *group = NULL;
+
+       if (!dstu_ctx) {
+               DSTUerr(DSTU_F_DSTU_PKEY_CTRL, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       switch (type) {
+       case DSTU_SET_CUSTOM_SBOX:
+               if ((!p2) || (sizeof(default_sbox) != p1))
+                       return 0;
+               sbox = copy_sbox((unsigned char *) p2);
+               if (!sbox)
+                       return 0;
+
+               DSTU_KEY_CTX_set(dstu_ctx, NULL, sbox);
+               return 1;
+       case DSTU_SET_CURVE:
+               if (!p2)
+                       return 0;
+
+               group = EC_GROUP_dup((EC_GROUP *) p2);
+               if (!group)
+                       return 0;
+
+               DSTU_KEY_CTX_set(dstu_ctx, group, NULL);
+               return 1;
+       case EVP_PKEY_CTRL_MD:
+               if (NID_dstu34311 != EVP_MD_type((const EVP_MD *) p2)) {
+                       DSTUerr(DSTU_F_DSTU_PKEY_CTRL, 
DSTU_R_INVALID_DIGEST_TYPE);
+                       return 0;
+               }
+               return 1;
+       case EVP_PKEY_CTRL_DIGESTINIT:
+       case EVP_PKEY_CTRL_PKCS7_SIGN:
+#ifndef OPENSSL_NO_CMS
+       case EVP_PKEY_CTRL_CMS_SIGN:
+#endif
+               return 1;
+       }
+       return 0;
+}
+
+static int
+dstu_pkey_ctrl_str(EVP_PKEY_CTX * ctx, const char *type,
+    const char *value)
+{
+       int curve_nid = NID_undef, res = 0;
+       EC_GROUP *group = NULL;
+       unsigned char sbox[sizeof(default_sbox)];
+       BIGNUM *tmp = NULL;
+
+       if (!strcmp(CURVE_PARAM_STR, type)) {
+               curve_nid = OBJ_sn2nid(value);
+               if (NID_undef == curve_nid)
+                       return 0;
+
+               group = group_from_nid(curve_nid);
+               if (group) {
+                       res = dstu_pkey_ctrl(ctx, DSTU_SET_CURVE, 0, group);
+                       EC_GROUP_free(group);
+               }
+               return res;
+       }
+       if (!strcmp(SBOX_PARAM_STR, type)) {
+               tmp = BN_new();
+               if (!tmp)
+                       return 0;
+
+               if ((sizeof(default_sbox) * 2) != BN_hex2bn(&tmp, value)) {
+                       BN_free(tmp);
+                       return 0;
+               }
+               if (BN_is_negative(tmp)) {
+                       BN_free(tmp);
+                       return 0;
+               }
+               if (bn_encode(tmp, sbox, sizeof(sbox)))
+                       res =
+                           dstu_pkey_ctrl(ctx, DSTU_SET_CUSTOM_SBOX, 
sizeof(sbox), sbox);
+               BN_free(tmp);
+               return res;
+       }
+       return 0;
+}
+
+static int
+dstu_pkey_sign(EVP_PKEY_CTX * ctx, unsigned char *sig,
+    size_t * siglen, const unsigned char *tbs,
+    size_t tbslen)
+{
+       EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
+       DSTU_KEY *key = NULL;
+       const EC_GROUP *group = NULL;
+       int field_size, ret = 0, encoded_sig_size;
+       ASN1_OCTET_STRING *dstu_sig = NULL;
+       unsigned char *sig_data = NULL;
+       BIGNUM *n = NULL;
+
+       if (!pkey) {
+               DSTUerr(DSTU_F_DSTU_PKEY_SIGN, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       key = EVP_PKEY_get0(pkey);
+       if (!key) {
+               DSTUerr(DSTU_F_DSTU_PKEY_SIGN, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       group = EC_KEY_get0_group(key->ec);
+       if (!group) {
+               DSTUerr(DSTU_F_DSTU_PKEY_SIGN, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       n = BN_new();
+       if (!n)
+               return 0;
+
+       if (!EC_GROUP_get_order(group, n, NULL))
+               goto err;
+
+       field_size = BN_num_bytes(n);
+       encoded_sig_size = EVP_PKEY_size(pkey);
+
+       if (encoded_sig_size > *siglen) {
+               *siglen = encoded_sig_size;
+               goto err;
+       }
+       *siglen = encoded_sig_size;
+
+       if (sig) {
+               dstu_sig = ASN1_OCTET_STRING_new();
+               if (!dstu_sig)
+                       goto err;
+
+               sig_data = malloc(2 * field_size);
+               if (!sig_data)
+                       goto err;
+
+               if (!dstu_do_sign(key->ec, tbs, tbslen, sig_data))
+                       goto err;
+
+               if (NID_dstu4145le == EVP_PKEY_id(pkey))
+                       reverse_bytes(sig_data, 2 * field_size);
+
+               ASN1_STRING_set0((ASN1_STRING *) dstu_sig, sig_data, 2 * 
field_size);
+               sig_data = NULL;
+
+               *siglen = i2d_ASN1_OCTET_STRING(dstu_sig, &sig);
+       }
+       ret = 1;
+
+err:
+
+       if (sig_data)
+               free(sig_data);
+
+       if (dstu_sig)
+               ASN1_OCTET_STRING_free(dstu_sig);
+
+       if (n)
+               BN_free(n);
+
+       return ret;
+}
+
+/*
+ * static int dstu_pkey_verify_init(EVP_PKEY_CTX *ctx) { return 0; }
+ */
+
+static int
+dstu_pkey_verify(EVP_PKEY_CTX * ctx, const unsigned char *sig,
+    size_t siglen, const unsigned char *tbs,
+    size_t tbslen)
+{
+       EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
+       DSTU_KEY *key = NULL;
+       const EC_GROUP *group = NULL;
+       int field_size, ret = 0;
+       unsigned char *sig_be;
+       ASN1_OCTET_STRING *dstu_sig = NULL;
+       BIGNUM *n = NULL;
+
+       if (!pkey) {
+               DSTUerr(DSTU_F_DSTU_PKEY_VERIFY, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       key = EVP_PKEY_get0(pkey);
+       if (!key) {
+               DSTUerr(DSTU_F_DSTU_PKEY_VERIFY, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       group = EC_KEY_get0_group(key->ec);
+       if (!group) {
+               DSTUerr(DSTU_F_DSTU_PKEY_VERIFY, DSTU_R_NOT_DSTU_KEY);
+               return 0;
+       }
+       n = BN_new();
+       if (!n)
+               return 0;
+
+       if (!EC_GROUP_get_order(group, n, NULL)) {
+               DSTUerr(DSTU_F_DSTU_PKEY_VERIFY, DSTU_R_NOT_DSTU_KEY);
+               goto err;
+       }
+       field_size = BN_num_bytes(n);
+
+       if (!d2i_ASN1_OCTET_STRING(&dstu_sig, &sig, siglen))
+               goto err;
+
+       sig = ASN1_STRING_data(dstu_sig);
+       siglen = ASN1_STRING_length(dstu_sig);
+
+       if (siglen & 0x01)
+               goto err;
+
+       if (siglen < (2 * field_size))
+               goto err;
+
+       if (NID_dstu4145le == EVP_PKEY_id(pkey)) {
+               /* Signature is little-endian, need to reverse it. */
+               sig_be = malloc(siglen);
+               if (!sig_be)
+                       goto err;
+
+               reverse_bytes_copy(sig_be, sig, siglen);
+               ret = dstu_do_verify(key->ec, tbs, tbslen, sig_be, siglen);
+               free(sig_be);
+       } else
+               ret = dstu_do_verify(key->ec, tbs, tbslen, sig, siglen);
+
+err:
+       if (n)
+               BN_free(n);
+
+       if (dstu_sig)
+               ASN1_OCTET_STRING_free(dstu_sig);
+
+       return ret;
+}
+
+static int
+dstu_pkey_copy(EVP_PKEY_CTX * dst, EVP_PKEY_CTX * src)
+{
+       DSTU_KEY_CTX *dstu_src_ctx = EVP_PKEY_CTX_get_data(src), *dstu_dst_ctx;
+
+       if (dstu_src_ctx) {
+               dstu_dst_ctx = DSTU_KEY_CTX_copy(dstu_src_ctx);
+               if (!dstu_dst_ctx)
+                       return 0;
+               EVP_PKEY_CTX_set_data(dst, dstu_dst_ctx);
+       }
+       return 1;
+}
+
+const EVP_PKEY_METHOD dstu_pkey_meth_le = {
+       .pkey_id = NID_dstu4145le,
+       .flags = 0,
+       .init = dstu_pkey_init_le,
+       .cleanup = dstu_pkey_cleanup,
+       .copy = dstu_pkey_copy,
+       .keygen = dstu_pkey_keygen,
+       .sign = dstu_pkey_sign,
+       .verify = dstu_pkey_verify,
+       .ctrl = dstu_pkey_ctrl,
+       .ctrl_str = dstu_pkey_ctrl_str
+};
+
+const EVP_PKEY_METHOD dstu_pkey_meth_be = {
+       .pkey_id = NID_dstu4145be,
+       .flags = 0,
+       .init = dstu_pkey_init_be,
+       .cleanup = dstu_pkey_cleanup,
+       .copy = dstu_pkey_copy,
+       .keygen = dstu_pkey_keygen,
+       .sign = dstu_pkey_sign,
+       .verify = dstu_pkey_verify,
+       .ctrl = dstu_pkey_ctrl,
+       .ctrl_str = dstu_pkey_ctrl_str
+};
Index: lib/libssl/src/crypto/dstu/dstu_sign.c
===================================================================
RCS file: lib/libssl/src/crypto/dstu/dstu_sign.c
diff -N lib/libssl/src/crypto/dstu/dstu_sign.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/dstu/dstu_sign.c      26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,243 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <string.h>
+#include "dstu_params.h"
+
+static int
+bn_truncate_bits(BIGNUM * bn, int bitsize)
+{
+       int num_bits = BN_num_bits(bn);
+       while (num_bits > bitsize) {
+               if (!BN_clear_bit(bn, num_bits - 1))
+                       return 0;
+               num_bits = BN_num_bits(bn);
+       }
+       return 1;
+}
+
+static int
+hash_to_field(const unsigned char *hash, int hash_len, BIGNUM * fe,
+    int fieldsize)
+{
+       unsigned char *h = malloc(hash_len);
+       int i;
+       if (!h)
+               return 0;
+
+       for (i = 0; i < hash_len; i++)
+               h[i] = hash[hash_len - 1 - i];
+
+       if (!BN_bin2bn(h, hash_len, fe)) {
+               free(h);
+               return 0;
+       }
+       free(h);
+       if (BN_is_zero(fe))
+               BN_one(fe);
+
+       return bn_truncate_bits(fe, fieldsize);
+}
+
+static int
+field_to_bn(BIGNUM * fe, const BIGNUM * order)
+{
+       return bn_truncate_bits(fe, BN_num_bits(order) - 1);
+}
+
+int
+dstu_do_sign(const EC_KEY * key, const unsigned char *tbs, size_t tbslen,
+    unsigned char *sig)
+{
+       const BIGNUM *d = EC_KEY_get0_private_key(key);
+       const EC_GROUP *group = EC_KEY_get0_group(key);
+       BIGNUM *e, *Fe, *h, *r, *s, *n, *p;
+       BN_CTX *ctx = NULL;
+       EC_POINT *eG = NULL;
+       int field_size, ret = 0;
+
+       if (!d || !group)
+               return 0;
+
+       /* DSTU supports only binary fields. */
+       if (NID_X9_62_characteristic_two_field
+           != EC_METHOD_get_field_type(EC_GROUP_method_of(group))) {
+               DSTUerr(DSTU_F_DSTU_DO_SIGN, DSTU_R_INCORRECT_FIELD_TYPE);
+               return 0;
+       }
+       ctx = BN_CTX_new();
+       if (!ctx)
+               return 0;
+
+       BN_CTX_start(ctx);
+
+       e = BN_CTX_get(ctx);
+       Fe = BN_CTX_get(ctx);
+       h = BN_CTX_get(ctx);
+       n = BN_CTX_get(ctx);
+       p = BN_CTX_get(ctx);
+       r = BN_CTX_get(ctx);
+       s = BN_CTX_get(ctx);
+
+       if (!s)
+               goto err;
+
+       if (!EC_GROUP_get_order(group, n, ctx))
+               goto err;
+
+       field_size = BN_num_bytes(n);
+
+       if (!EC_GROUP_get_curve_GF2m(group, p, NULL, NULL, ctx))
+               goto err;
+
+       eG = EC_POINT_new(group);
+       if (!eG)
+               goto err;
+
+       if (!hash_to_field(tbs, tbslen, h, EC_GROUP_get_degree(group)))
+               goto err;
+
+       do {
+               do {
+                       do {
+                               if (!BN_rand_range(e, n))
+                                       goto err;
+
+                               if (!EC_POINT_mul(group, eG, e, NULL, NULL, 
ctx))
+                                       goto err;
+
+                               if 
(!EC_POINT_get_affine_coordinates_GF2m(group, eG, Fe, NULL,
+                                       ctx))
+                                       goto err;
+                       } while (BN_is_zero(Fe));
+
+                       if (!BN_GF2m_mod_mul(r, h, Fe, p, ctx))
+                               goto err;
+
+                       if (!field_to_bn(r, n))
+                               goto err;
+               } while (BN_is_zero(r));
+
+               if (!BN_mod_mul(s, d, r, n, ctx))
+                       goto err;
+
+               if (!BN_mod_add_quick(s, s, e, n))
+                       goto err;
+       } while (BN_is_zero(s));
+
+       if (!bn_encode(s, sig, field_size))
+               goto err;
+
+       if (!bn_encode(r, sig + field_size, field_size))
+               goto err;
+
+       ret = 1;
+
+err:
+       if (eG)
+               EC_POINT_free(eG);
+
+       if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       return ret;
+}
+
+int
+dstu_do_verify(const EC_KEY * key, const unsigned char *tbs, size_t tbslen,
+    const unsigned char *sig, size_t siglen)
+{
+       const EC_GROUP *group = EC_KEY_get0_group(key);
+       const EC_POINT *Q = EC_KEY_get0_public_key(key);
+       int ret = 0;
+       BN_CTX *ctx = NULL;
+       EC_POINT *R = NULL;
+       BIGNUM *r, *s, *r1, *n, *Rx, *p;
+
+       if (!group || !Q)
+               return 0;
+
+       /* DSTU supports only binary fields. */
+       if (NID_X9_62_characteristic_two_field
+           != EC_METHOD_get_field_type(EC_GROUP_method_of(group))) {
+               DSTUerr(DSTU_F_DSTU_DO_VERIFY, DSTU_R_INCORRECT_FIELD_TYPE);
+               return 0;
+       }
+       ctx = BN_CTX_new();
+       if (!ctx)
+               return 0;
+
+       BN_CTX_start(ctx);
+
+       n = BN_CTX_get(ctx);
+       r1 = BN_CTX_get(ctx);
+       p = BN_CTX_get(ctx);
+       Rx = BN_CTX_get(ctx);
+       r = BN_CTX_get(ctx);
+       s = BN_CTX_get(ctx);
+
+       if (!s)
+               goto err;
+
+       if (!hash_to_field(tbs, tbslen, r1, EC_GROUP_get_degree(group)))
+               goto err;
+
+       if (!EC_GROUP_get_order(group, n, ctx))
+               goto err;
+
+       if (!EC_GROUP_get_curve_GF2m(group, p, NULL, NULL, ctx))
+               goto err;
+
+       if (!BN_bin2bn(sig, siglen / 2, s))
+               goto err;
+
+       if (!BN_bin2bn(sig + (siglen / 2), siglen / 2, r))
+               goto err;
+
+       if (BN_is_zero(s) || BN_is_zero(r))
+               goto err;
+
+       if ((BN_cmp(s, n) >= 0) || (BN_cmp(r, n) >= 0))
+               goto err;
+
+       R = EC_POINT_new(group);
+       if (!R)
+               goto err;
+
+       if (!EC_POINT_mul(group, R, s, Q, r, ctx))
+               goto err;
+
+       if (EC_POINT_is_at_infinity(group, R))
+               goto err;
+
+       if (!EC_POINT_get_affine_coordinates_GF2m(group, R, Rx, NULL, ctx))
+               goto err;
+
+       if (!BN_GF2m_mod_mul(r1, r1, Rx, p, ctx))
+               goto err;
+
+       if (!field_to_bn(r1, n))
+               goto err;
+
+       if (!BN_cmp(r, r1))
+               ret = 1;
+
+err:
+       if (R)
+               EC_POINT_free(R);
+
+       if (ctx) {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+       }
+       return ret;
+}
Index: lib/libssl/src/crypto/err/err.c
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/err/err.c,v
retrieving revision 1.41
diff -u -p -r1.41 err.c
--- lib/libssl/src/crypto/err/err.c     9 Nov 2014 19:17:13 -0000       1.41
+++ lib/libssl/src/crypto/err/err.c     26 Feb 2016 15:47:38 -0000
@@ -158,11 +158,12 @@ static ERR_STRING_DATA ERR_str_libraries
        {ERR_PACK(ERR_LIB_CMS,0,0),             "CMS routines"},
        {ERR_PACK(ERR_LIB_HMAC,0,0),            "HMAC routines"},
        {ERR_PACK(ERR_LIB_GOST,0,0),            "GOST routines"},
+       {ERR_PACK(ERR_LIB_DSTU,0,0),            "DSTU routines"},
        {0, NULL},
 };

 static ERR_STRING_DATA ERR_str_functs[] = {
-       {ERR_PACK(0,SYS_F_FOPEN, 0),            "fopen"},
+       {ERR_PACK(0,SYS_F_FOPEN, 0),            "fopen"},
        {ERR_PACK(0,SYS_F_CONNECT, 0),          "connect"},
        {ERR_PACK(0,SYS_F_GETSERVBYNAME, 0),    "getservbyname"},
        {ERR_PACK(0,SYS_F_SOCKET, 0),           "socket"},
Index: lib/libssl/src/crypto/err/err.h
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/err/err.h,v
retrieving revision 1.22
diff -u -p -r1.22 err.h
--- lib/libssl/src/crypto/err/err.h     9 Nov 2014 19:17:13 -0000       1.22
+++ lib/libssl/src/crypto/err/err.h     26 Feb 2016 15:47:38 -0000
@@ -196,6 +196,7 @@ typedef struct err_state_st {
 #define ERR_LIB_HMAC           48
 #define ERR_LIB_JPAKE          49
 #define ERR_LIB_GOST           50
+#define ERR_LIB_DSTU           51

 #define ERR_LIB_USER           128

@@ -233,6 +234,7 @@ typedef struct err_state_st {
 #define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),__FILE__,__LINE__)
 #define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__)
 #define GOSTerr(f,r) ERR_PUT_error(ERR_LIB_GOST,(f),(r),__FILE__,__LINE__)
+#define DSTUerr(f,r) ERR_PUT_error(ERR_LIB_DSTU,(f),(r),__FILE__,__LINE__)

 #define ERR_PACK(l,f,r)                (((((unsigned long)l)&0xffL)<<24L)| \
                                ((((unsigned long)f)&0xfffL)<<12L)| \
Index: lib/libssl/src/crypto/err/openssl.ec
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/err/openssl.ec,v
retrieving revision 1.11
diff -u -p -r1.11 openssl.ec
--- lib/libssl/src/crypto/err/openssl.ec        9 Nov 2014 19:17:13 -0000       
1.11
+++ lib/libssl/src/crypto/err/openssl.ec        26 Feb 2016 15:47:38 -0000
@@ -35,6 +35,7 @@ L TS          crypto/ts/ts.h                  
crypto/ts/ts_err.
 L HMAC         crypto/hmac/hmac.h              crypto/hmac/hmac_err.c
 L CMS          crypto/cms/cms.h                crypto/cms/cms_err.c
 L GOST         crypto/gost/gost.h              crypto/gost/gost_err.c
+L DSTU         crypto/dstu/dstu.h              crypto/dstu/dstu_err.c

 # additional header files to be scanned for function names
 L NONE         crypto/x509/x509_vfy.h          NONE
@@ -93,4 +94,3 @@ R RSAREF_R_PUBLIC_KEY                         0x040a
 R RSAREF_R_SIGNATURE                           0x040b
 R RSAREF_R_SIGNATURE_ENCODING                  0x040c
 R RSAREF_R_ENCRYPTION_ALGORITHM                        0x040d
-
Index: lib/libssl/src/crypto/evp/c_all.c
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/evp/c_all.c,v
retrieving revision 1.20
diff -u -p -r1.20 c_all.c
--- lib/libssl/src/crypto/evp/c_all.c   14 Sep 2015 01:45:03 -0000      1.20
+++ lib/libssl/src/crypto/evp/c_all.c   26 Feb 2016 15:47:38 -0000
@@ -223,6 +223,10 @@ OpenSSL_add_all_ciphers(void)
        EVP_add_cipher(EVP_gost2814789_cfb64());
        EVP_add_cipher(EVP_gost2814789_cnt());
 #endif
+
+#ifndef OPENSSL_NO_DSTU
+       EVP_add_cipher(EVP_dstu28147_cfb64());
+#endif
 }

 void
@@ -263,6 +267,9 @@ OpenSSL_add_all_digests(void)
        EVP_add_digest(EVP_gost2814789imit());
        EVP_add_digest(EVP_streebog256());
        EVP_add_digest(EVP_streebog512());
+#endif
+#ifndef OPENSSL_NO_DSTU
+       EVP_add_digest(EVP_dstu34311());
 #endif
 #ifndef OPENSSL_NO_RIPEMD
        EVP_add_digest(EVP_ripemd160());
Index: lib/libssl/src/crypto/evp/e_dstu.c
===================================================================
RCS file: lib/libssl/src/crypto/evp/e_dstu.c
diff -N lib/libssl/src/crypto/evp/e_dstu.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/evp/e_dstu.c  26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,147 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_DSTU
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/gost.h>
+#include "../dstu/dstu_params.h"
+#include "evp_locl.h"
+
+/*
+ * DSTU uses Russian GOST 28147 but with different s-boxes and no key meshing.
+ * We implement CFB mode here because it is mostly used.
+ */
+#define DSTU_CIPHER_BLOCK_SIZE 8
+#define DSTU_CIPHER_SBOX_SIZE 64
+
+/*
+ * 2 bytes for sequence header, 2 bytes for each octet string header and 8 
bytes
+ * for iv and 64 bytes for dke.
+ * Total 78 < 128 so we are ok with 1 byte length.
+ */
+#define DSTU_CIPHER_ASN1_PARAM_SIZE (2 + 2 + DSTU_CIPHER_BLOCK_SIZE + 2 + 
DSTU_CIPHER_SBOX_SIZE)
+
+typedef struct {
+       GOST2814789_KEY ks;
+} EVP_DSTU28147_CTX;
+
+static int
+dstu_cipher_init(EVP_CIPHER_CTX * ctx, const unsigned char *key, const 
unsigned char *iv, int enc)
+{
+       EVP_DSTU28147_CTX *c = ctx->cipher_data;
+
+       /* We do not use key meshing. */
+       c->ks.key_meshing = 0;
+
+       return Gost2814789_set_key(&c->ks, key, ctx->key_len * 8);
+}
+
+static int
+dstu_cipher_ctrl(EVP_CIPHER_CTX * ctx, int cmd, int p1, void *p2)
+{
+       EVP_DSTU28147_CTX *c = ctx->cipher_data;
+
+       switch (cmd) {
+       case EVP_CTRL_INIT:
+               /* Default value to have any s-box set at all. */
+               dstu_set_sbox(&(c->ks), NULL);
+               return 1;
+       case DSTU_SET_CUSTOM_SBOX:
+               /*
+                * Unlike GOST, which accepts nid, we accept pointer to sbox,
+                * so p2 is used!
+                */
+               dstu_set_sbox(&(c->ks), p2);
+               return 1;
+       case EVP_CTRL_PBE_PRF_NID:
+               if (!p2)
+                       return 0;
+               *((int *) (p2)) = NID_hmacWithDstu34311;
+               return 1;
+       }
+
+       return 0;
+}
+
+static int
+dstu_cipher_set_asn1_parameters(EVP_CIPHER_CTX * ctx, ASN1_TYPE * asn1_type)
+{
+       /*
+        * We defined params asn1 structure, but for now we will use manual
+        * composition for speed here.
+        */
+       EVP_DSTU28147_CTX *c = ctx->cipher_data;
+
+       unsigned char params[DSTU_CIPHER_ASN1_PARAM_SIZE];
+       ASN1_STRING seq;
+
+       params[0] = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
+       params[1] = 2 + DSTU_CIPHER_BLOCK_SIZE + 2 + DSTU_CIPHER_SBOX_SIZE;
+       params[2] = V_ASN1_OCTET_STRING;
+       params[3] = DSTU_CIPHER_BLOCK_SIZE;
+
+       memcpy(&(params[4]), ctx->oiv, DSTU_CIPHER_BLOCK_SIZE);
+
+       params[4 + DSTU_CIPHER_BLOCK_SIZE] = V_ASN1_OCTET_STRING;
+       params[4 + DSTU_CIPHER_BLOCK_SIZE + 1] = DSTU_CIPHER_SBOX_SIZE;
+
+       dstu_get_sbox(&(c->ks), &(params[4 + DSTU_CIPHER_BLOCK_SIZE + 2]));
+
+       seq.type = V_ASN1_SEQUENCE;
+       seq.length = sizeof(params);
+       seq.flags = 0;
+       seq.data = params;
+
+       if (ASN1_TYPE_set1(asn1_type, V_ASN1_SEQUENCE, &seq))
+               return 1;
+
+       return -1;
+}
+
+static int
+dstu_cipher_get_asn1_parameters(EVP_CIPHER_CTX * ctx, ASN1_TYPE * asn1_type)
+{
+       if (V_ASN1_SEQUENCE != asn1_type->type)
+               return -1;
+
+       if (DSTU_CIPHER_ASN1_PARAM_SIZE != asn1_type->value.sequence->length)
+               return -1;
+
+       if ((V_ASN1_OCTET_STRING != asn1_type->value.sequence->data[2])
+           || (DSTU_CIPHER_BLOCK_SIZE != asn1_type->value.sequence->data[3]))
+               return -1;
+
+       if ((V_ASN1_OCTET_STRING !=
+               asn1_type->value.sequence->data[4 + DSTU_CIPHER_BLOCK_SIZE])
+           || (DSTU_CIPHER_SBOX_SIZE !=
+               asn1_type->value.sequence->data[4 + DSTU_CIPHER_BLOCK_SIZE + 
1]))
+               return -1;
+
+       memcpy(ctx->oiv, &(asn1_type->value.sequence->data[4]),
+           DSTU_CIPHER_BLOCK_SIZE);
+
+       if (dstu_cipher_ctrl
+           (ctx, EVP_CTRL_GOST_SET_SBOX, DSTU_CIPHER_SBOX_SIZE,
+               &(asn1_type->value.sequence->data[4 + DSTU_CIPHER_BLOCK_SIZE + 
2])))
+               return 1;
+
+       return -1;
+}
+
+BLOCK_CIPHER_func_cfb(dstu28147, Gost2814789, 64, EVP_DSTU28147_CTX, ks)
+#define NID_dstu89_cfb64 NID_dstu28147_cfb
+
+BLOCK_CIPHER_def_cfb(dstu28147, EVP_DSTU28147_CTX, NID_dstu89, 32, 8, 64,
+    EVP_CIPH_NO_PADDING | EVP_CIPH_CTRL_INIT,
+    dstu_cipher_init, NULL, dstu_cipher_set_asn1_parameters,
+    dstu_cipher_get_asn1_parameters, dstu_cipher_ctrl)
+#endif
Index: lib/libssl/src/crypto/evp/evp.h
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/evp/evp.h,v
retrieving revision 1.49
diff -u -p -r1.49 evp.h
--- lib/libssl/src/crypto/evp/evp.h     2 Nov 2015 15:40:53 -0000       1.49
+++ lib/libssl/src/crypto/evp/evp.h     26 Feb 2016 15:47:38 -0000
@@ -680,6 +680,9 @@ const EVP_MD *EVP_gost2814789imit(void);
 const EVP_MD *EVP_streebog256(void);
 const EVP_MD *EVP_streebog512(void);
 #endif
+#ifndef OPENSSL_NO_DSTU
+const EVP_MD *EVP_dstu34311(void);
+#endif
 const EVP_CIPHER *EVP_enc_null(void);          /* does nothing :-) */
 #ifndef OPENSSL_NO_DES
 const EVP_CIPHER *EVP_des_ecb(void);
@@ -812,6 +815,10 @@ const EVP_CIPHER *EVP_chacha20(void);
 const EVP_CIPHER *EVP_gost2814789_ecb(void);
 const EVP_CIPHER *EVP_gost2814789_cfb64(void);
 const EVP_CIPHER *EVP_gost2814789_cnt(void);
+#endif
+
+#ifndef OPENSSL_NO_DSTU
+const EVP_CIPHER *EVP_dstu28147_cfb64(void);
 #endif

 void OPENSSL_add_all_algorithms_noconf(void);
Index: lib/libssl/src/crypto/evp/m_dstu.c
===================================================================
RCS file: lib/libssl/src/crypto/evp/m_dstu.c
diff -N lib/libssl/src/crypto/evp/m_dstu.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libssl/src/crypto/evp/m_dstu.c  26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,78 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_DSTU
+
+#include <openssl/evp.h>
+#include <openssl/gost.h>
+#include <openssl/objects.h>
+
+#include "../dstu/dstu_params.h"
+#include "../dstu/dstu_key.h"
+
+typedef GOSTR341194_CTX DSTU34311_CTX;
+
+static int
+dstu34311_init(EVP_MD_CTX * ctx)
+{
+       DSTU34311_CTX *c = ctx->md_data;
+       EVP_PKEY *pkey;
+       DSTU_KEY *dstu_key;
+
+       memset(c, 0, sizeof(DSTU34311_CTX));
+
+       /* If we have pkey_ctx, it may contain custom sbox, so let's check it */
+       if (ctx->pctx) {
+               pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+               if (pkey) {
+                       dstu_key = EVP_PKEY_get0(pkey);
+                       if (dstu_key) {
+                               if (dstu_key->sbox) {
+                                       dstu_set_sbox(&(c->cipher), 
dstu_key->sbox);
+                                       return 1;
+                               }
+                       }
+               }
+       }
+       dstu_set_sbox(&(c->cipher), NULL);
+       return 1;
+}
+
+static int
+dstu34311_update(EVP_MD_CTX * ctx, const void *data, size_t count)
+{
+       return GOSTR341194_Update(ctx->md_data, data, count);
+}
+
+static int
+dstu34311_final(EVP_MD_CTX * ctx, unsigned char *md)
+{
+       return GOSTR341194_Final(md, ctx->md_data);
+}
+
+static const EVP_MD dstu34311_md = {
+       .type = NID_dstu34311,
+       .pkey_type = NID_undef,
+       .md_size = GOSTR341194_LENGTH,
+       .flags = EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
+       .init = dstu34311_init,
+       .update = dstu34311_update,
+       .final = dstu34311_final,
+       .block_size = GOSTR341194_CBLOCK,
+       .ctx_size = sizeof(EVP_MD *) + sizeof(GOSTR341194_CTX),
+};
+
+const EVP_MD *
+EVP_dstu34311(void)
+{
+       return (&dstu34311_md);
+}
+#endif
Index: lib/libssl/src/crypto/evp/pmeth_lib.c
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/evp/pmeth_lib.c,v
retrieving revision 1.11
diff -u -p -r1.11 pmeth_lib.c
--- lib/libssl/src/crypto/evp/pmeth_lib.c       11 Feb 2015 03:19:37 -0000      
1.11
+++ lib/libssl/src/crypto/evp/pmeth_lib.c       26 Feb 2016 15:47:38 -0000
@@ -82,6 +82,10 @@ extern const EVP_PKEY_METHOD rsa_pkey_me
 extern const EVP_PKEY_METHOD ec_pkey_meth, hmac_pkey_meth, cmac_pkey_meth;
 extern const EVP_PKEY_METHOD gostimit_pkey_meth, gostr01_pkey_meth;

+#ifndef OPENSSL_NO_DSTU
+extern const EVP_PKEY_METHOD dstu_pkey_meth_le, dstu_pkey_meth_be;
+#endif
+
 static const EVP_PKEY_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_RSA
        &rsa_pkey_meth,
@@ -101,6 +105,10 @@ static const EVP_PKEY_METHOD *standard_m
 #endif
        &hmac_pkey_meth,
        &cmac_pkey_meth,
+#ifndef OPENSSL_NO_DSTU
+       &dstu_pkey_meth_le,
+       &dstu_pkey_meth_be,
+#endif
 };

 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,
Index: lib/libssl/src/crypto/objects/obj_mac.num
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/objects/obj_mac.num,v
retrieving revision 1.13
diff -u -p -r1.13 obj_mac.num
--- lib/libssl/src/crypto/objects/obj_mac.num   9 Nov 2014 19:17:13 -0000       
1.13
+++ lib/libssl/src/crypto/objects/obj_mac.num   26 Feb 2016 15:47:38 -0000
@@ -947,3 +947,23 @@ id_tc26_gost3410_2012_256          946
 id_tc26_gost3410_2012_512              947
 id_tc26_signwithdigest_gost3410_2012_256               948
 id_tc26_signwithdigest_gost3410_2012_512               949
+ISO_UA                 950
+ua_pki                 951
+dstu28147              952
+dstu28147_ofb          953
+dstu28147_cfb          954
+dstu28147_wrap         955
+hmacWithDstu34311      956
+dstu34311              957
+dstu4145le             958
+dstu4145be             959
+uacurve0               960
+uacurve1               961
+uacurve2               962
+uacurve3               963
+uacurve4               964
+uacurve5               965
+uacurve6               966
+uacurve7               967
+uacurve8               968
+uacurve9               969
Index: lib/libssl/src/crypto/objects/obj_xref.h
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/objects/obj_xref.h,v
retrieving revision 1.3
diff -u -p -r1.3 obj_xref.h
--- lib/libssl/src/crypto/objects/obj_xref.h    9 Nov 2014 19:17:13 -0000       
1.3
+++ lib/libssl/src/crypto/objects/obj_xref.h    26 Feb 2016 15:47:38 -0000
@@ -42,6 +42,8 @@ static const nid_triple sigoid_srt[] =
        {NID_rsassaPss, NID_undef, NID_rsaEncryption},
        {NID_id_tc26_signwithdigest_gost3410_2012_256, 
NID_id_tc26_gost3411_2012_256, NID_id_GostR3410_2001},
        {NID_id_tc26_signwithdigest_gost3410_2012_512, 
NID_id_tc26_gost3411_2012_512, NID_id_GostR3410_2001},
+       {NID_dstu4145le, NID_dstu34311, NID_dstu4145le},
+       {NID_dstu4145be, NID_dstu34311, NID_dstu4145be},
        };

 static const nid_triple * const sigoid_srt_xref[] =
@@ -78,5 +80,6 @@ static const nid_triple * const sigoid_s
        &sigoid_srt[28],
        &sigoid_srt[30],
        &sigoid_srt[31],
+       &sigoid_srt[32],
+       &sigoid_srt[33],
        };
-
Index: lib/libssl/src/crypto/objects/obj_xref.txt
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/objects/obj_xref.txt,v
retrieving revision 1.2
diff -u -p -r1.2 obj_xref.txt
--- lib/libssl/src/crypto/objects/obj_xref.txt  9 Nov 2014 19:17:13 -0000       
1.2
+++ lib/libssl/src/crypto/objects/obj_xref.txt  26 Feb 2016 15:47:38 -0000
@@ -46,3 +46,6 @@ id_GostR3411_94_with_GostR3410_94_cc  id_
 id_GostR3411_94_with_GostR3410_2001_cc id_GostR3411_94 id_GostR3410_2001_cc
 id_tc26_signwithdigest_gost3410_2012_256       id_tc26_gost3411_2012_256 
id_tc26_gost3410_2012_256
 id_tc26_signwithdigest_gost3410_2012_512       id_tc26_gost3411_2012_512 
id_tc26_gost3410_2012_512
+
+dstu4145le             dstu34311       dstu4145le
+dstu4145be             dstu34311       dstu4145be
Index: lib/libssl/src/crypto/objects/objects.txt
===================================================================
RCS file: /cvs/src/lib/libssl/src/crypto/objects/objects.txt,v
retrieving revision 1.16
diff -u -p -r1.16 objects.txt
--- lib/libssl/src/crypto/objects/objects.txt   9 Nov 2014 19:17:13 -0000       
1.16
+++ lib/libssl/src/crypto/objects/objects.txt   26 Feb 2016 15:47:38 -0000
@@ -558,7 +558,7 @@ id-cmc 19           : id-cmc-responseInfo
 id-cmc 21              : id-cmc-queryPending
 id-cmc 22              : id-cmc-popLinkRandom
 id-cmc 23              : id-cmc-popLinkWitness
-id-cmc 24              : id-cmc-confirmCertAcceptance
+id-cmc 24              : id-cmc-confirmCertAcceptance

 # other names
 id-on 1                        : id-on-personalData
@@ -1240,7 +1240,7 @@ cryptocom 1 8 1           : id-GostR3410-2001-Par
 # Definitions for Camellia cipher - ECB, CFB, OFB MODE

 !Alias ntt-ds 0 3 4401 5
-!Alias camellia ntt-ds 3 1 9
+!Alias camellia ntt-ds 3 1 9

 camellia 1             : CAMELLIA-128-ECB              : camellia-128-ecb
 !Cname camellia-128-ofb128
@@ -1328,3 +1328,29 @@ tc26 1 1 1               : id-tc26-gost3410-2012-256
 tc26 1 1 2             : id-tc26-gost3410-2012-512 : GOST R 34.10-2012 (512 
bit)
 tc26 1 3 2             : id-tc26-signwithdigest-gost3410-2012-256 : GOST R 
34.11-2012 with GOST R 34.10-2012 (256 bit)
 tc26 1 3 3             : id-tc26-signwithdigest-gost3410-2012-512 : GOST R 
34.11-2012 with GOST R 34.10-2012 (512 bit)
+
+# DSTU OIDs
+member-body 804                : ISO-UA
+ISO-UA 2 1 1 1         : ua-pki
+ua-pki 1 1 1           : dstu28147 : DSTU Gost 28147-2009
+dstu28147 2            : dstu28147-ofb : DSTU Gost 28147-2009 OFB mode
+dstu28147 3            : dstu28147-cfb : DSTU Gost 28147-2009 CFB mode
+dstu28147 5            : dstu28147-wrap : DSTU Gost 28147-2009 key wrap
+
+ua-pki 1 1 2           : hmacWithDstu34311 : HMAC DSTU Gost 34311-95
+ua-pki 1 2 1           : dstu34311 : DSTU Gost 34311-95
+
+ua-pki 1 3 1 1         : dstu4145le : DSTU 4145-2002 little endian
+dstu4145le 1 1         : dstu4145be : DSTU 4145-2002 big endian
+
+# DSTU named curves
+dstu4145le 2 0 : uacurve0 : DSTU curve 0
+dstu4145le 2 1 : uacurve1 : DSTU curve 1
+dstu4145le 2 2 : uacurve2 : DSTU curve 2
+dstu4145le 2 3 : uacurve3 : DSTU curve 3
+dstu4145le 2 4 : uacurve4 : DSTU curve 4
+dstu4145le 2 5 : uacurve5 : DSTU curve 5
+dstu4145le 2 6 : uacurve6 : DSTU curve 6
+dstu4145le 2 7 : uacurve7 : DSTU curve 7
+dstu4145le 2 8 : uacurve8 : DSTU curve 8
+dstu4145le 2 9 : uacurve9 : DSTU curve 9
Index: regress/lib/libcrypto/Makefile
===================================================================
RCS file: /cvs/src/regress/lib/libcrypto/Makefile,v
retrieving revision 1.22
diff -u -p -r1.22 Makefile
--- regress/lib/libcrypto/Makefile      25 Sep 2015 16:12:30 -0000      1.22
+++ regress/lib/libcrypto/Makefile      26 Feb 2016 15:47:38 -0000
@@ -14,6 +14,7 @@ SUBDIR= \
        des \
        dh \
        dsa \
+       dstu \
        ec \
        ecdh \
        ecdsa \
Index: regress/lib/libcrypto/dstu/Makefile
===================================================================
RCS file: regress/lib/libcrypto/dstu/Makefile
diff -N regress/lib/libcrypto/dstu/Makefile
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ regress/lib/libcrypto/dstu/Makefile 26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,9 @@
+#      $OpenBSD$
+
+PROG=  dstutest
+LDADD= -lcrypto
+DPADD= ${LIBCRYPTO}
+WARNINGS=      Yes
+CFLAGS+=       -DLIBRESSL_INTERNAL -Werror
+
+.include <bsd.regress.mk>
Index: regress/lib/libcrypto/dstu/dstutest.c
===================================================================
RCS file: regress/lib/libcrypto/dstu/dstutest.c
diff -N regress/lib/libcrypto/dstu/dstutest.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ regress/lib/libcrypto/dstu/dstutest.c       26 Feb 2016 15:47:38 -0000
@@ -0,0 +1,263 @@
+/*
+ * ===========================================================
+ * Author: Ignat Korchagin <[email protected]>.
+ * This file is distributed under the same license as OpenSSL.
+ * ===========================================================
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+
+/*
+ * We need to fake random, if we want to run fixed test vectors test, because
+ * DSTU signature is randomized. We redefine arc4random_buf for this.
+ * We cannot use real arc4random_buf anymore, if we really need random data,
+ * because we will get into endless recursive loop.
+ * Instead, we will implement it using arc4random.
+ */
+
+static void
+real_random(void *buf, size_t n)
+{
+       unsigned char *bytes = buf;
+
+       while (n) {
+               uint32_t rnd = arc4random();
+               size_t to_copy = sizeof(rnd) < n ? sizeof(rnd) : n;
+
+               memcpy(bytes, &rnd, to_copy);
+               bytes += to_copy;
+               n -= to_copy;
+       }
+}
+
+static struct {
+       int fake_rnd;
+       const void *fake_rnd_src;
+       size_t fake_rnd_size;
+} rand_ctrl = {
+       0, NULL, 0
+};
+
+void
+arc4random_buf(void *buf, size_t n)
+{
+       if (rand_ctrl.fake_rnd) {
+               if (n > rand_ctrl.fake_rnd_size) {
+                       exit(1);
+               }
+               memcpy(buf, rand_ctrl.fake_rnd_src, n);
+       } else {
+               real_random(buf, n);
+       }
+}
+
+static unsigned char hash[] =
+{0x10, 0xe6, 0x5a, 0x11, 0xac, 0xcc, 0x36, 0x5e, 0x18, 0x46, 0x67, 0x02,
+       0xb0, 0x64, 0x6d, 0x74, 0x92, 0x41, 0x9a, 0x9d, 0xa6, 0x57, 0xcf, 0x03,
+       0x64, 0x52, 0x7c, 0x33,
+       0x65, 0x55, 0x5b, 0xa7
+};
+
+static char c163[] = "uacurve0";
+static unsigned char e163[] =
+{0x01, 0x02, 0x5e, 0x40, 0xbd, 0x97, 0xdb, 0x01, 0x2b, 0x7a, 0x1d, 0x79,
+       0xde, 0x8e, 0x12, 0x93, 0x2d, 0x24, 0x7f, 0x61, 0xc6
+};
+
+static unsigned char d163[] =
+{0x03, 0xe0, 0x74, 0x8d, 0x62, 0x9e, 0xb5, 0x4a, 0x1d, 0x8f, 0x9a, 0x87,
+       0xeb, 0xde, 0x12, 0xca, 0x0e, 0xed, 0x48, 0x54, 0xa5
+};
+
+static unsigned char s163[] =
+{0x04, 0x2a, 0x66, 0xa7, 0x40, 0x07, 0x84, 0xa7, 0x4a, 0x72, 0xcc, 0xa7,
+       0x5b, 0x0c, 0x35, 0x8b, 0x4c, 0xdd, 0x6c, 0x2a, 0xa6, 0x36, 0x00, 0x00,
+       0xc4, 0x74, 0x66, 0xda,
+       0xd4, 0xe1, 0x01, 0x1b, 0x3e, 0x18, 0x95, 0x27, 0x72, 0xc0, 0x80, 0xa9,
+       0xa3, 0x1b, 0x31,
+       0x01
+};
+
+static char c257[] = "uacurve6";
+static unsigned char e257[] =
+{0x00, 0x43, 0x94, 0xe1, 0x9d, 0xcc, 0x1d, 0xef, 0x57, 0xdd, 0xbe, 0x6f,
+       0xb7, 0x05, 0x65, 0xc7, 0x49, 0xf2, 0x21, 0x44, 0x62, 0x6f, 0x05, 0x0a,
+       0x6d, 0xaa, 0xb4, 0xaf,
+       0x00, 0x71, 0xe6, 0xfe, 0xb9
+};
+
+static unsigned char d257[] =
+{0x00, 0x6f, 0x31, 0xc4, 0x44, 0x59, 0x14, 0xfb, 0x34, 0x7b, 0xa9, 0xbd,
+       0x27, 0x2b, 0xb5, 0xb7, 0xf5, 0x13, 0x42, 0x2f, 0xe1, 0x16, 0xdf, 0xa4,
+       0xf0, 0xdf, 0x34, 0xb1,
+       0xce, 0xb1, 0x1a, 0x64, 0x5c
+};
+
+static unsigned char s257[] =
+{0x04, 0x40, 0x6f, 0x77, 0x37, 0xe8, 0x65, 0xd2, 0x50, 0xd7, 0x0a, 0x29,
+       0xea, 0xdf, 0xe3, 0xc2, 0x3d, 0x37, 0x0c, 0x3f, 0xa7, 0xb5, 0xc9, 0x43,
+       0xcd, 0xed, 0x1b, 0x72,
+       0xf3, 0xe1, 0x53, 0x2d, 0x2c, 0x09, 0xe1, 0x8b, 0x17, 0x72, 0x1d, 0xab,
+       0xeb, 0xec, 0x39, 0xbd,
+       0x4a, 0x87, 0x9a, 0xb0, 0x50, 0x7d, 0x80, 0xe9, 0x99, 0xe1, 0xea, 0x5d,
+       0x65, 0xb5, 0x56, 0xd6,
+       0xf1, 0x66, 0x44, 0x8b, 0xee, 0x26
+};
+
+static char c431[] = "uacurve9";
+static unsigned char e431[] =
+{0x04, 0x57, 0xce, 0x62, 0x0e, 0x2b, 0x71, 0x10, 0x0d, 0x87, 0xf7, 0xe1,
+       0xc2, 0x32, 0x38, 0xaa, 0x36, 0x29, 0xba, 0x52, 0xc6, 0xba, 0xb4, 0x2c,
+       0x6a, 0x22, 0xdb, 0x43,
+       0x78, 0x15, 0xcc, 0xfe, 0xb9, 0xa4, 0x47, 0xb0, 0x2a, 0x82, 0x98, 0xe5,
+       0x26, 0x0a, 0x7f, 0xa9,
+       0x4a, 0x13, 0xc1, 0x82, 0x2d, 0x88, 0x5e, 0x8c, 0x5c, 0x69
+};
+
+static unsigned char d431[] =
+{0x31, 0x13, 0x1b, 0xec, 0x94, 0x8d, 0xac, 0xbb, 0xaf, 0xad, 0xbf, 0x9b,
+       0xb1, 0x50, 0xb0, 0xb7, 0x92, 0xdf, 0x32, 0x24, 0x79, 0x2a, 0x80, 0xf6,
+       0x76, 0x1a, 0x0b, 0x03,
+       0xb3, 0xb8, 0x2d, 0x11, 0x8b, 0xc3, 0xc2, 0x27, 0x1c, 0x04, 0xa0, 0x4c,
+       0x2d, 0x9b, 0x38, 0x76,
+       0xc2, 0x33, 0x86, 0x0b, 0x19, 0x0d, 0xcc, 0xea, 0x01, 0x77
+};
+
+static unsigned char s431[] =
+{0x04, 0x6c, 0xc4, 0xe4, 0xf0, 0xb5, 0xea, 0xb8, 0xe7, 0xaa, 0xf4, 0x17,
+       0xa6, 0xb5, 0xd1, 0xd7, 0x4f, 0xe5, 0x34, 0x81, 0x64, 0x50, 0xdf, 0x6d,
+       0xff, 0xd9, 0x37, 0x7d,
+       0xfc, 0xac, 0x5f, 0x25, 0x67, 0x6a, 0x11, 0x9e, 0x5f, 0x70, 0x0f, 0x92,
+       0xc2, 0x7c, 0x80, 0x17,
+       0xb6, 0xb3, 0xe3, 0xc2, 0x05, 0xf2, 0x74, 0xd5, 0x4c, 0xd3, 0x33, 0x00,
+       0xdd, 0x1e, 0xe8, 0x43,
+       0x63, 0x85, 0x69, 0xe1, 0x10, 0xe4, 0x15, 0xc4, 0x46, 0x0e, 0x4e, 0xb3,
+       0x25, 0x8f, 0xcf, 0xa7,
+       0x50, 0x98, 0xa5, 0xce, 0xb5, 0xad, 0x35, 0xb8, 0xfd, 0x28, 0xd1, 0x21,
+       0x06, 0xb5, 0x51, 0x14,
+       0x87, 0x43, 0x45, 0xef, 0x7d, 0xc1, 0xa1, 0x45, 0xa5, 0xbb, 0x1c, 0xcf,
+       0x27, 0x4b, 0x5d, 0x64,
+       0x80, 0x11
+};
+
+struct dstu_test_vector {
+       char *curve;
+       size_t field_byte_size;
+       unsigned char *e;
+       unsigned char *d;
+       unsigned char *s;
+};
+
+static struct dstu_test_vector vectors[] = {
+       {c163, 21, e163, d163, s163},
+       {c257, 33, e257, d257, s257},
+       {c431, 54, e431, d431, s431}
+};
+
+static int
+sig_test(void)
+{
+       EVP_PKEY_CTX *pkey_ctx = NULL;
+       EVP_PKEY *pkey = NULL;
+       unsigned char sig[256];
+       size_t siglen = sizeof(sig);
+       struct dstu_test_vector *vector;
+       int ret = 1;
+
+       printf("Testing DSTU 4145-2002\n");
+       fflush(NULL);
+
+       pkey = EVP_PKEY_new();
+       if (!pkey) {
+               fprintf(stderr, "EVP_PKEY_new() failed\n");
+               fflush(NULL);
+               goto err;
+       }
+       if (!EVP_PKEY_set_type(pkey, NID_dstu4145le)) {
+               fprintf(stderr, "EVP_PKEY_set_type() failed\n");
+               fflush(NULL);
+               goto err;
+       }
+       pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL);
+       if (!pkey_ctx) {
+               fprintf(stderr, "EVP_PKEY_CTX_new() failed\n");
+               fflush(NULL);
+               goto err;
+       }
+       for (vector = vectors; vector < vectors + (sizeof(vectors) / 
sizeof(struct dstu_test_vector)); vector++) {
+               if (!EVP_PKEY_CTX_ctrl_str(pkey_ctx, "curve", vector->curve)) {
+                       fprintf(stderr, "EVP_PKEY_CTX_ctrl_str() failed\n");
+                       fflush(NULL);
+                       goto err;
+               }
+               rand_ctrl.fake_rnd = 1;
+               rand_ctrl.fake_rnd_src = vector->d;
+               rand_ctrl.fake_rnd_size = vector->field_byte_size;
+
+               if (!EVP_PKEY_keygen_init(pkey_ctx)) {
+                       fprintf(stderr, "EVP_PKEY_keygen_init() failed\n");
+                       fflush(NULL);
+                       goto err;
+               }
+               if (!EVP_PKEY_keygen(pkey_ctx, &pkey)) {
+                       fprintf(stderr, "EVP_PKEY_keygen() failed\n");
+                       fflush(NULL);
+                       goto err;
+               }
+               rand_ctrl.fake_rnd_src = vector->e;
+
+               if (!EVP_PKEY_sign_init(pkey_ctx)) {
+                       fprintf(stderr, "EVP_PKEY_sign_init() failed\n");
+                       fflush(NULL);
+                       goto err;
+               }
+               if (!EVP_PKEY_sign(pkey_ctx, sig, &siglen, hash, sizeof(hash))) 
{
+                       fprintf(stderr, "EVP_PKEY_sign() failed\n");
+                       fflush(NULL);
+                       goto err;
+               }
+               if (memcmp(sig, vector->s, siglen)) {
+                       fprintf(stderr, "%s: test signature mismatch\n", 
vector->curve);
+                       fflush(NULL);
+                       goto err;
+               }
+               if (!EVP_PKEY_verify_init(pkey_ctx)) {
+                       fprintf(stderr, "EVP_PKEY_verify_init() failed\n");
+                       fflush(NULL);
+                       goto err;
+               }
+               if (1 != EVP_PKEY_verify(pkey_ctx, sig, siglen, hash, 
sizeof(hash))) {
+                       fprintf(stderr, "%s: test signature verification 
failed\n",
+                           vector->curve);
+                       fflush(NULL);
+                       goto err;
+               }
+               siglen = sizeof(sig);
+       }
+
+       ret = 0;
+       printf("Passed\n");
+       fflush(NULL);
+
+err:
+       if (pkey_ctx)
+               EVP_PKEY_CTX_free(pkey_ctx);
+
+       if (pkey)
+               EVP_PKEY_free(pkey);
+
+       rand_ctrl.fake_rnd = 0;
+
+       return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+       int err = 0;
+
+       err |= sig_test();
+
+       return err;
+}
Index: regress/lib/libcrypto/evp/evptest.c
===================================================================
RCS file: /cvs/src/regress/lib/libcrypto/evp/evptest.c,v
retrieving revision 1.6
diff -u -p -r1.6 evptest.c
--- regress/lib/libcrypto/evp/evptest.c 18 Jul 2015 17:19:56 -0000      1.6
+++ regress/lib/libcrypto/evp/evptest.c 26 Feb 2016 15:47:38 -0000
@@ -411,7 +411,14 @@ main(int argc, char **argv)
 #endif
 #ifdef OPENSSL_NO_GOST
                        if (strstr(cipher, "md_gost") == cipher ||
-                           strstr(cipher, "streebog") == cipher) {
+                               strstr(cipher, "streebog") == cipher) {
+                               fprintf(stdout, "Cipher disabled, skipping 
%s\n", cipher);
+                               continue;
+                       }
+#endif
+#ifdef OPENSSL_NO_DSTU
+                       if (strstr(cipher, "dstu28147-cfb") == cipher ||
+                               strstr(cipher, "dstu34311") == cipher) {
                                fprintf(stdout, "Cipher disabled, skipping 
%s\n", cipher);
                                continue;
                        }
Index: regress/lib/libcrypto/evp/evptests.txt
===================================================================
RCS file: /cvs/src/regress/lib/libcrypto/evp/evptests.txt,v
retrieving revision 1.3
diff -u -p -r1.3 evptests.txt
--- regress/lib/libcrypto/evp/evptests.txt      18 Nov 2014 21:52:43 -0000      
1.3
+++ regress/lib/libcrypto/evp/evptests.txt      26 Feb 2016 15:47:40 -0000
@@ -74,29 +74,29 @@ AES-128-ECB:2B7E151628AED2A6ABF7158809CF
 
AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::AE2D8A571E03AC9C9EB76FAC45AF8E51:F5D3D58503B9699DE785895A96FDBAAF
 
AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::30C81C46A35CE411E5FBC1191A0A52EF:43B1CD7F598ECE23881B00E3ED030688
 
AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::F69F2445DF4F9B17AD2B417BE66C3710:7B0C785E27E8AD3F8223207104725DD4
-# ECB-AES192.Encrypt and ECB-AES192.Decrypt
+# ECB-AES192.Encrypt and ECB-AES192.Decrypt
 
AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::6BC1BEE22E409F96E93D7E117393172A:BD334F1D6E45F25FF712A214571FA5CC
 
AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::AE2D8A571E03AC9C9EB76FAC45AF8E51:974104846D0AD3AD7734ECB3ECEE4EEF
 
AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::30C81C46A35CE411E5FBC1191A0A52EF:EF7AFD2270E2E60ADCE0BA2FACE6444E
 
AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::F69F2445DF4F9B17AD2B417BE66C3710:9A4B41BA738D6C72FB16691603C18E0E
-# ECB-AES256.Encrypt and ECB-AES256.Decrypt
+# ECB-AES256.Encrypt and ECB-AES256.Decrypt
 
AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::6BC1BEE22E409F96E93D7E117393172A:F3EED1BDB5D2A03C064B5A7E3DB181F8
 
AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::AE2D8A571E03AC9C9EB76FAC45AF8E51:591CCB10D410ED26DC5BA74A31362870
 
AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::30C81C46A35CE411E5FBC1191A0A52EF:B6ED21B99CA6F4F9F153E7B1BEAFED1D
 
AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::F69F2445DF4F9B17AD2B417BE66C3710:23304B7A39F9F3FF067D8D8F9E24ECC7
 # For all CBC encrypts and decrypts, the transformed sequence is
 #   AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec
-# CBC-AES128.Encrypt and CBC-AES128.Decrypt
+# CBC-AES128.Encrypt and CBC-AES128.Decrypt
 
AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:7649ABAC8119B246CEE98E9B12E9197D
 
AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:7649ABAC8119B246CEE98E9B12E9197D:AE2D8A571E03AC9C9EB76FAC45AF8E51:5086CB9B507219EE95DB113A917678B2
 
AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:5086CB9B507219EE95DB113A917678B2:30C81C46A35CE411E5FBC1191A0A52EF:73BED6B8E3C1743B7116E69E22229516
 
AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:73BED6B8E3C1743B7116E69E22229516:F69F2445DF4F9B17AD2B417BE66C3710:3FF1CAA1681FAC09120ECA307586E1A7
-# CBC-AES192.Encrypt and CBC-AES192.Decrypt
+# CBC-AES192.Encrypt and CBC-AES192.Decrypt
 
AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:4F021DB243BC633D7178183A9FA071E8
 
AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:4F021DB243BC633D7178183A9FA071E8:AE2D8A571E03AC9C9EB76FAC45AF8E51:B4D9ADA9AD7DEDF4E5E738763F69145A
 
AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:B4D9ADA9AD7DEDF4E5E738763F69145A:30C81C46A35CE411E5FBC1191A0A52EF:571B242012FB7AE07FA9BAAC3DF102E0
 
AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:571B242012FB7AE07FA9BAAC3DF102E0:F69F2445DF4F9B17AD2B417BE66C3710:08B0E27988598881D920A9E64F5615CD
-# CBC-AES256.Encrypt and CBC-AES256.Decrypt
+# CBC-AES256.Encrypt and CBC-AES256.Decrypt
 
AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:F58C4C04D6E5F1BA779EABFB5F7BFBD6
 
AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:F58C4C04D6E5F1BA779EABFB5F7BFBD6:AE2D8A571E03AC9C9EB76FAC45AF8E51:9CFC4E967EDB808D679F777BC6702C7D
 
AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:9CFC4E967EDB808D679F777BC6702C7D:30C81C46A35CE411E5FBC1191A0A52EF:39F23369A9D9BACFA530E26304231461
@@ -104,12 +104,12 @@ AES-256-CBC:603DEB1015CA71BE2B73AEF0857D
 # We don't support CFB{1,8}-AESxxx.{En,De}crypt
 # For all CFB128 encrypts and decrypts, the transformed sequence is
 #   AES-bits-CFB:key:IV/ciphertext':plaintext:ciphertext:encdec
-# CFB128-AES128.Encrypt
+# CFB128-AES128.Encrypt
 
AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1
 
AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:3B3FD92EB72DAD20333449F8E83CFB4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:C8A64537A0B3A93FCDE3CDAD9F1CE58B:1
 
AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:C8A64537A0B3A93FCDE3CDAD9F1CE58B:30C81C46A35CE411E5FBC1191A0A52EF:26751F67A3CBB140B1808CF187A4F4DF:1
 
AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:26751F67A3CBB140B1808CF187A4F4DF:F69F2445DF4F9B17AD2B417BE66C3710:C04B05357C5D1C0EEAC4C66F9FF7F2E6:1
-# CFB128-AES128.Decrypt
+# CFB128-AES128.Decrypt
 
AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:0
 
AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:3B3FD92EB72DAD20333449F8E83CFB4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:C8A64537A0B3A93FCDE3CDAD9F1CE58B:0
 
AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:C8A64537A0B3A93FCDE3CDAD9F1CE58B:30C81C46A35CE411E5FBC1191A0A52EF:26751F67A3CBB140B1808CF187A4F4DF:0
@@ -124,44 +124,44 @@ AES-192-CFB:8E73B0F7DA0E6452C810F32B8090
 
AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:CDC80D6FDDF18CAB34C25909C99A4174:AE2D8A571E03AC9C9EB76FAC45AF8E51:67CE7F7F81173621961A2B70171D3D7A:0
 
AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:67CE7F7F81173621961A2B70171D3D7A:30C81C46A35CE411E5FBC1191A0A52EF:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:0
 
AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:F69F2445DF4F9B17AD2B417BE66C3710:C05F9F9CA9834FA042AE8FBA584B09FF:0
-# CFB128-AES256.Encrypt
+# CFB128-AES256.Encrypt
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:1
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DC7E84BFDA79164B7ECD8486985D3860:AE2D8A571E03AC9C9EB76FAC45AF8E51:39FFED143B28B1C832113C6331E5407B:1
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39FFED143B28B1C832113C6331E5407B:30C81C46A35CE411E5FBC1191A0A52EF:DF10132415E54B92A13ED0A8267AE2F9:1
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DF10132415E54B92A13ED0A8267AE2F9:F69F2445DF4F9B17AD2B417BE66C3710:75A385741AB9CEF82031623D55B1E471:1
-# CFB128-AES256.Decrypt
+# CFB128-AES256.Decrypt
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:0
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DC7E84BFDA79164B7ECD8486985D3860:AE2D8A571E03AC9C9EB76FAC45AF8E51:39FFED143B28B1C832113C6331E5407B:0
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39FFED143B28B1C832113C6331E5407B:30C81C46A35CE411E5FBC1191A0A52EF:DF10132415E54B92A13ED0A8267AE2F9:0
 
AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DF10132415E54B92A13ED0A8267AE2F9:F69F2445DF4F9B17AD2B417BE66C3710:75A385741AB9CEF82031623D55B1E471:0
 # For all OFB encrypts and decrypts, the transformed sequence is
 #   AES-bits-CFB:key:IV/output':plaintext:ciphertext:encdec
-# OFB-AES128.Encrypt
-AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1
-AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:1
-AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:1
-AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:1
-# OFB-AES128.Decrypt
+# OFB-AES128.Encrypt
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:1
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:1
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:1
+# OFB-AES128.Decrypt
 
AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:0
 
AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:0
 
AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:0
 
AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:0
-# OFB-AES192.Encrypt
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:1
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:1
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:1
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:1
-# OFB-AES192.Decrypt
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:0
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:0
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:0
-AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:0
-# OFB-AES256.Encrypt
+# OFB-AES192.Encrypt
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:1
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:1
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:1
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:1
+# OFB-AES192.Decrypt
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:0
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:0
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:0
+AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:0
+# OFB-AES256.Encrypt
 
AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:1
 
AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:1
 
AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:1
 
AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0126141D67F37BE8538F5A8BE740E484:1
-# OFB-AES256.Decrypt
+# OFB-AES256.Decrypt
 
AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:0
 
AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:0
 
AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:0
@@ -217,19 +217,19 @@ CAMELLIA-128-ECB:000102030405060708090A0
 
CAMELLIA-192-ECB:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:B22F3C36B72D31329EEE8ADDC2906C68:1
 
CAMELLIA-256-ECB:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:2EDF1F3418D53B88841FC8985FB1ECF2:1

-# ECB-CAMELLIA128.Encrypt and ECB-CAMELLIA128.Decrypt
+# ECB-CAMELLIA128.Encrypt and ECB-CAMELLIA128.Decrypt
 
CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::6BC1BEE22E409F96E93D7E117393172A:432FC5DCD628115B7C388D770B270C96
 
CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::AE2D8A571E03AC9C9EB76FAC45AF8E51:0BE1F14023782A22E8384C5ABB7FAB2B
 
CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::30C81C46A35CE411E5FBC1191A0A52EF:A0A1ABCD1893AB6FE0FE5B65DF5F8636
 
CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::F69F2445DF4F9B17AD2B417BE66C3710:E61925E0D5DFAA9BB29F815B3076E51A

-# ECB-CAMELLIA192.Encrypt and ECB-CAMELLIA192.Decrypt
+# ECB-CAMELLIA192.Encrypt and ECB-CAMELLIA192.Decrypt
 
CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::6BC1BEE22E409F96E93D7E117393172A:CCCC6C4E138B45848514D48D0D3439D3
 
CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::AE2D8A571E03AC9C9EB76FAC45AF8E51:5713C62C14B2EC0F8393B6AFD6F5785A
 
CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::30C81C46A35CE411E5FBC1191A0A52EF:B40ED2B60EB54D09D030CF511FEEF366
 
CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::F69F2445DF4F9B17AD2B417BE66C3710:909DBD95799096748CB27357E73E1D26

-# ECB-CAMELLIA256.Encrypt and ECB-CAMELLIA256.Decrypt
+# ECB-CAMELLIA256.Encrypt and ECB-CAMELLIA256.Decrypt
 
CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::6BC1BEE22E409F96E93D7E117393172A:BEFD219B112FA00098919CD101C9CCFA
 
CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::AE2D8A571E03AC9C9EB76FAC45AF8E51:C91D3A8F1AEA08A9386CF4B66C0169EA
 
CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::30C81C46A35CE411E5FBC1191A0A52EF:A623D711DC5F25A51BB8A80D56397D28
@@ -237,19 +237,19 @@ CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF

 # For all CBC encrypts and decrypts, the transformed sequence is
 #   CAMELLIA-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec
-# CBC-CAMELLIA128.Encrypt and CBC-CAMELLIA128.Decrypt
+# CBC-CAMELLIA128.Encrypt and CBC-CAMELLIA128.Decrypt
 
CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:1607CF494B36BBF00DAEB0B503C831AB
 
CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:1607CF494B36BBF00DAEB0B503C831AB:AE2D8A571E03AC9C9EB76FAC45AF8E51:A2F2CF671629EF7840C5A5DFB5074887
 
CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:A2F2CF671629EF7840C5A5DFB5074887:30C81C46A35CE411E5FBC1191A0A52EF:0F06165008CF8B8B5A63586362543E54
 
CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:36A84CDAFD5F9A85ADA0F0A993D6D577:F69F2445DF4F9B17AD2B417BE66C3710:74C64268CDB8B8FAF5B34E8AF3732980

-# CBC-CAMELLIA192.Encrypt and CBC-CAMELLIA192.Decrypt
+# CBC-CAMELLIA192.Encrypt and CBC-CAMELLIA192.Decrypt
 
CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:2A4830AB5AC4A1A2405955FD2195CF93
 
CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2A4830AB5AC4A1A2405955FD2195CF93:AE2D8A571E03AC9C9EB76FAC45AF8E51:5D5A869BD14CE54264F892A6DD2EC3D5
 
CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:5D5A869BD14CE54264F892A6DD2EC3D5:30C81C46A35CE411E5FBC1191A0A52EF:37D359C3349836D884E310ADDF68C449
 
CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:37D359C3349836D884E310ADDF68C449:F69F2445DF4F9B17AD2B417BE66C3710:01FAAA930B4AB9916E9668E1428C6B08

-# CBC-CAMELLIA256.Encrypt and CBC-CAMELLIA256.Decrypt
+# CBC-CAMELLIA256.Encrypt and CBC-CAMELLIA256.Decrypt
 
CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:E6CFA35FC02B134A4D2C0B6737AC3EDA
 
CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E6CFA35FC02B134A4D2C0B6737AC3EDA:AE2D8A571E03AC9C9EB76FAC45AF8E51:36CBEB73BD504B4070B1B7DE2B21EB50
 
CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:36CBEB73BD504B4070B1B7DE2B21EB50:30C81C46A35CE411E5FBC1191A0A52EF:E31A6055297D96CA3330CDF1B1860A83
@@ -258,13 +258,13 @@ CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF
 # We don't support CFB{1,8}-CAMELLIAxxx.{En,De}crypt
 # For all CFB128 encrypts and decrypts, the transformed sequence is
 #   CAMELLIA-bits-CFB:key:IV/ciphertext':plaintext:ciphertext:encdec
-# CFB128-CAMELLIA128.Encrypt
+# CFB128-CAMELLIA128.Encrypt
 
CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:1
 
CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:14F7646187817EB586599146B82BD719:AE2D8A571E03AC9C9EB76FAC45AF8E51:A53D28BB82DF741103EA4F921A44880B:1
 
CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:A53D28BB82DF741103EA4F921A44880B:30C81C46A35CE411E5FBC1191A0A52EF:9C2157A664626D1DEF9EA420FDE69B96:1
 
CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:9C2157A664626D1DEF9EA420FDE69B96:F69F2445DF4F9B17AD2B417BE66C3710:742A25F0542340C7BAEF24CA8482BB09:1

-# CFB128-CAMELLIA128.Decrypt
+# CFB128-CAMELLIA128.Decrypt
 
CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:0
 
CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:14F7646187817EB586599146B82BD719:AE2D8A571E03AC9C9EB76FAC45AF8E51:A53D28BB82DF741103EA4F921A44880B:0
 
CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:A53D28BB82DF741103EA4F921A44880B:30C81C46A35CE411E5FBC1191A0A52EF:9C2157A664626D1DEF9EA420FDE69B96:0
@@ -282,13 +282,13 @@ CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32
 
CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:86F8491627906D780C7A6D46EA331F98:30C81C46A35CE411E5FBC1191A0A52EF:69511CCE594CF710CB98BB63D7221F01:0
 
CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:69511CCE594CF710CB98BB63D7221F01:F69F2445DF4F9B17AD2B417BE66C3710:D5B5378A3ABED55803F25565D8907B84:0

-# CFB128-CAMELLIA256.Encrypt
+# CFB128-CAMELLIA256.Encrypt
 
CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:1
 
CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:CF6107BB0CEA7D7FB1BD31F5E7B06C93:AE2D8A571E03AC9C9EB76FAC45AF8E51:89BEDB4CCDD864EA11BA4CBE849B5E2B:1
 
CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:89BEDB4CCDD864EA11BA4CBE849B5E2B:30C81C46A35CE411E5FBC1191A0A52EF:555FC3F34BDD2D54C62D9E3BF338C1C4:1
 
CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:555FC3F34BDD2D54C62D9E3BF338C1C4:F69F2445DF4F9B17AD2B417BE66C3710:5953ADCE14DB8C7F39F1BD39F359BFFA:1

-# CFB128-CAMELLIA256.Decrypt
+# CFB128-CAMELLIA256.Decrypt
 
CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:0
 
CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:CF6107BB0CEA7D7FB1BD31F5E7B06C93:AE2D8A571E03AC9C9EB76FAC45AF8E51:89BEDB4CCDD864EA11BA4CBE849B5E2B:0
 
CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:89BEDB4CCDD864EA11BA4CBE849B5E2B:30C81C46A35CE411E5FBC1191A0A52EF:555FC3F34BDD2D54C62D9E3BF338C1C4:0
@@ -296,37 +296,37 @@ CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF

 # For all OFB encrypts and decrypts, the transformed sequence is
 #   CAMELLIA-bits-OFB:key:IV/output':plaintext:ciphertext:encdec
-# OFB-CAMELLIA128.Encrypt
+# OFB-CAMELLIA128.Encrypt
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:1
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:25623DB569CA51E01482649977E28D84:1
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:C776634A60729DC657D12B9FCA801E98:1
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:D776379BE0E50825E681DA1A4C980E8E:1

-# OFB-CAMELLIA128.Decrypt
+# OFB-CAMELLIA128.Decrypt
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:0
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:25623DB569CA51E01482649977E28D84:0
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:C776634A60729DC657D12B9FCA801E98:0
 
CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:D776379BE0E50825E681DA1A4C980E8E:0

-# OFB-CAMELLIA192.Encrypt
+# OFB-CAMELLIA192.Encrypt
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:1
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:8ECEB7D0350D72C7F78562AEBDF99339:1
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:BDD62DBBB9700846C53B507F544696F0:1
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:E28014E046B802F385C4C2E13EAD4A72:1

-# OFB-CAMELLIA192.Decrypt
+# OFB-CAMELLIA192.Decrypt
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:0
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:8ECEB7D0350D72C7F78562AEBDF99339:0
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:BDD62DBBB9700846C53B507F544696F0:0
 
CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:E28014E046B802F385C4C2E13EAD4A72:0

-# OFB-CAMELLIA256.Encrypt
+# OFB-CAMELLIA256.Encrypt
 
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:1
 
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:127AD97E8E3994E4820027D7BA109368:1
 
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:6BFF6265A6A6B7A535BC65A80B17214E:1
 
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0A4A0404E26AA78A27CB271E8BF3CF20:1

-# OFB-CAMELLIA256.Decrypt
+# OFB-CAMELLIA256.Decrypt
 
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:0
 
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:127AD97E8E3994E4820027D7BA109368:0
 
CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:6BFF6265A6A6B7A535BC65A80B17214E:0
@@ -351,3 +351,16 @@ ChaCha:555555555555555555555555555555555
 
ChaCha:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:aaaaaaaaaaaaaaaa:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:9aa2a9f656efde5aa7591c5fed4b35aea2895dec7cb4543b9e9f21f5e7bcbcf3c43c748a970888f8248393a09d43e0b7e164bc4d0b0fb240a2d72115c4808906:1
 
ChaCha:00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100:0f1e2d3c4b5a6978:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:9fadf409c00811d00431d67efbd88fba59218d5d6708b1d685863fabbb0e961eea480fd6fb532bfd494b2151015057423ab60a63fe4f55f7a212e2167ccab931:1
 
ChaCha:c46ec1b18ce8a878725a37e780dfb7351f68ed2e194c79fbc6aebee1a667975d:1ada31d5cf688221:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f63a89b75c2271f9368816542ba52f06ed49241792302b00b5e8f80ae9a473afc25b218f519af0fdd406362e8d69de7f54c604a6e00f353f110f771bdca8ab92:1
+
+# DSTU 28147 tests
+dstu28147-cfb:a110827c8acb5da6ac8553f4b94e3b54dcde6fde2d7f89c5d4cb0ea4c0263f35:e34ce94908f9aa27:3bd7264cea7d91e63a28fbfef4600959536fa8e4fed53ab64c68cdf5fa6b4491a21b87c306a14517:fbcf51a67dfe6045a5f34400952183d181aedef334ea69e2f0265e18ec9f9edd129f8567f4ea4d1a:1
+dstu28147-cfb:a110827c8acb5da6ac8553f4b94e3b54dcde6fde2d7f89c5d4cb0ea4c0263f35:e34ce94908f9aa27:3bd7264cea7d91e63a28fbfef4600959536fa8e4fed53ab64c68cdf5fa6b4491a21b87c306a14517:fbcf51a67dfe6045a5f34400952183d181aedef334ea69e2f0265e18ec9f9edd129f8567f4ea4d1a:0
+dstu28147-cfb:164f1564075aca1e26d9b3242346f0f854da62438290cc1d53e5e8d82f62a166:81c1498a2ca0dff3:17d47fe9da6eb8000b378f39261f3e578cb95783a67e52ef99c421ecc333187e6149090e4099c588:5dcc5ed96399c84b51365dea3baf04be03a22706e292bad58c3a247f4396cc15b8798b6b9c1edc50:1
+dstu28147-cfb:164f1564075aca1e26d9b3242346f0f854da62438290cc1d53e5e8d82f62a166:81c1498a2ca0dff3:17d47fe9da6eb8000b378f39261f3e578cb95783a67e52ef99c421ecc333187e6149090e4099c588:5dcc5ed96399c84b51365dea3baf04be03a22706e292bad58c3a247f4396cc15b8798b6b9c1edc50:0
+dstu28147-cfb:13a39905bb829a2bef28a74058834cfa33e3f9d3c651ab2b90cab3811a695b47:912396e3548cda94:7fd960a570b0e05a60325981ac209ad65d6182c1930bc24300387012ec70a5dd797de23d51d98e07:6028314029f2290992f29fa652e6705d6ebe4f678a277da6e08fd675718185933cd5b511c0c0af51:1
+dstu28147-cfb:13a39905bb829a2bef28a74058834cfa33e3f9d3c651ab2b90cab3811a695b47:912396e3548cda94:7fd960a570b0e05a60325981ac209ad65d6182c1930bc24300387012ec70a5dd797de23d51d98e07:6028314029f2290992f29fa652e6705d6ebe4f678a277da6e08fd675718185933cd5b511c0c0af51:0
+
+# DSTU 34311 tests
+dstu34311:::87adff960046b5d0b275cc1c8d2e9a6d37709d21d867f5a67b6bfeb2ff1d72c2a70141dfe527ed41d37cedb49bfde4643c15:b2575c09590219ab899a95669f08631815a35b0e67d63b1b8b184f7d14658da1
+dstu34311:::67ebce4d14953b2ccf0a04e1ceae483c21dc5f2533ec98d5d0a282b752c476349685d1ccbeca2f8a811e7248fddb4f581e8e:b5d5e34507705c6578d85b45f68b198f388cf5a8063d77722d8ff943dd12dac1
+dstu34311:::bf425424f33853daef2ce0217af1fcd6da896d75107454aa08451134db01afd6cba9ce132929b0a72041bd338fa689d348c2:c0ca9b0570896d6d3548f132da81fe54696a6d48b94c0efe1c7537d3a6de11c9
1. Encrypt and decrypt files with DSTU 28147:2009 in CFB mode:
openssl dstu28147-cfb -a -salt -in plain.txt -out cipher.txt
openssl dstu28147-cfb -d -a -in cipher.txt -out decrypted.txt

2. Hash with DSTU 34.311-95
echo -n “abc” | openssl dstu34311

3. DSTU 4145-2002 signature

  - generate default 257-bit curve private key

openssl genpkey -algorithm dstu4145le -out dstu.key

  - generate private key with specified standard curve (X=0..9)

openssl genpkey -algorithm dstu4145le -pkeyopt curve:uacurveX -out dstu.key

  - generate private key with custom sbox for DSTU 34.311-95

openssl genpkey -algorithm dstu4145le -pkeyopt sbox:<sbox in compact 64 byte 
hex> -out dstu.key

  - generate private key with big-endian field encoding

openssl genpkey -algorithm dstu4145be -out dstu.key

  - get public key from private key

openssl pkey -in dstu.key -pubout -out dstu.pub

  - sign a file

openssl pkeyutl -sign -inkey dstu.key -in some.txt > some.sig

  - verify signature

openssl pkeyutl -verify -pubin -inkey dstu.pub -sigfile some.sig -in some.txt

Reply via email to