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]
