I'm the author of the code and comfortable with any license most suitable
for LibreSSL project. What would you recommend for such code?

Regards,
Ignat

2016-02-29 15:11 GMT+00:00 Bob Beck <[email protected]>:

> Just quickly, because there may be other issues:
>
> +/*
> + * ===========================================================
> + * Author: Ignat Korchagin <[email protected]>.
> + * This file is distributed under the same license as OpenSSL.
> + * ===========================================================
> + */
>
> The above is not sufficent.. it's actually not a license, since
> OpenSSL is distributed under multiple licenses - so this
> probably actually doesn't count as a grant of license.  You will need
> to fix the license somehow for us to consider this.
>
> Please see:
>
>
> http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/share/misc/license.template?rev=HEAD
>
> For a longer discussion please see:
>
> http://www.openbsd.org/policy.html
>
>
> On Mon, Feb 29, 2016 at 7:42 AM, Sergey Prysiazhnyi <[email protected]>
> wrote:
> > 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 n
> > ...
> >
> > [Message clipped]
>

Reply via email to