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, ¶ms_type, (void **) ¶ms, 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 **) > ¶ms_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, ¶m_type, (void **) ¶ms, 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 **) > ¶ms_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] >
