From 856bbc8b35aff2461a59efdb35d68784a9692e49 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Tue, 17 May 2022 18:41:32 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 + decrypto-pro.c | 348 +++++++++++++++++++++++++++++++++++++++++++++++++ gost89.h | 110 ++++++++++++++++ gost_lcl.h | 257 ++++++++++++++++++++++++++++++++++++ gosthash.h | 52 ++++++++ 5 files changed, 769 insertions(+) create mode 100644 Makefile create mode 100644 decrypto-pro.c create mode 100644 gost89.h create mode 100644 gost_lcl.h create mode 100644 gosthash.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fa9aedc --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +decrypto-pro: decrypto-pro.c + gcc -o decrypto-pro decrypto-pro.c /usr/lib/`arch`-linux-gnu/engines-1.1/gost.so -lssl -lcrypto diff --git a/decrypto-pro.c b/decrypto-pro.c new file mode 100644 index 0000000..6461087 --- /dev/null +++ b/decrypto-pro.c @@ -0,0 +1,348 @@ +// https://habrahabr.ru/post/275039/ +// Требуется либо OpenSSL 1.0.x (ГОСТ в составе), либо https://github.com/gost-engine/engine +// Сборка: +// 1) apt-get install libengine-gost-openssl1.1 +// 2) make + +#include +#include +#include + +#include +#include +#include +#include "gost_lcl.h" + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 +#define fill_GOST2001_params fill_GOST_EC_params +#define gost2001_compute_public gost_ec_compute_public +#endif + +/* Convert little-endian byte array into bignum */ +BIGNUM *reverse32bn(char *b, BN_CTX *ctx) +{ + BIGNUM *res; + char buf[32]; + BUF_reverse(buf, b, 32); + res = BN_bin2bn(buf, 32, BN_CTX_get(ctx)); + OPENSSL_cleanse(buf, sizeof(buf)); + return res; +} + +void xor_material(char *buf36, char *buf5C, char *src) +{ + int i; + for(i = 0; i < 32; i++) + { + buf36[i] = src[i] ^ 0x36; + buf5C[i] = src[i] ^ 0x5C; + } +} + +int make_pwd_key(char *result_key, char *start12, int start12_len, char *passw) +{ + int result; + int i; + char pincode4[1024]; + int pin_len; + char current[32]; + char material36[32]; + char material5C[32]; + char hash_result[32]; + gost_hash_ctx ctx; + init_gost_hash_ctx(&ctx, &GostR3411_94_CryptoProParamSet); + memset(pincode4, 0, sizeof(pincode4)); + pin_len = strlen(passw); + if (pin_len*4 > sizeof(pincode4)) { result = 1; goto err; } + for(i = 0; i < pin_len; i++) + pincode4[i*4] = passw[i]; + + start_hash(&ctx); + hash_block(&ctx, start12, start12_len); + if (pin_len) + hash_block(&ctx, pincode4, pin_len * 4); + finish_hash(&ctx, hash_result); + + memcpy(current, (char*)"DENEFH028.760246785.IUEFHWUIO.EF", 32); + + for(i = 0; i < (pin_len?2000:2); i++) + { + xor_material(material36, material5C, current); + start_hash(&ctx); + hash_block(&ctx, material36, 32); + hash_block(&ctx, hash_result, 32); + hash_block(&ctx, material5C, 32); + hash_block(&ctx, hash_result, 32); + finish_hash(&ctx, current); + } + + xor_material(material36, material5C, current); + + start_hash(&ctx); + hash_block(&ctx, material36, 32); + hash_block(&ctx, start12, start12_len); + hash_block(&ctx, material5C, 32); + if (pin_len) + hash_block(&ctx, pincode4, pin_len * 4); + finish_hash(&ctx, current); + + start_hash(&ctx); + hash_block(&ctx, current, 32); + finish_hash(&ctx, result_key); + + result = 0; //ok +err: + return result; +} + +BIGNUM *decode_primary_key(char *pwd_key, char *primary_key, BN_CTX *bn_ctx) +{ + BIGNUM *res; + char buf[32]; + gost_ctx ctx; + gost_init(&ctx, gost_cipher_list->sblock); + gost_key(&ctx, pwd_key); + gost_dec(&ctx, primary_key, buf, 4); + res = reverse32bn(buf, bn_ctx); + OPENSSL_cleanse(buf, sizeof(buf)); + return res; +} + +BIGNUM *remove_mask_and_check_public(char *oid_param_set8, BIGNUM *key_with_mask, BIGNUM *mask, char *public8, BN_CTX *ctx) +{ + int result; + EC_KEY *eckey = NULL; + const EC_POINT *pubkey; + const EC_GROUP *group; + BIGNUM *X, *Y, *order, *raw_secret, *mask_inv; + char outbuf[32], public_X[32]; + ASN1_OBJECT *obj; + int nid; + + order = BN_CTX_get(ctx); + mask_inv = BN_CTX_get(ctx); + raw_secret = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + if (!order || !mask_inv || !raw_secret || !X || !Y) { result = 1; goto err; } + + obj = ASN1_OBJECT_create(0, oid_param_set8+1, *oid_param_set8, NULL, NULL); + nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + + if (!(eckey = EC_KEY_new())) { result = 1; goto err; } + if (!fill_GOST2001_params(eckey, nid)) { result = 1; goto err; } + if (!(group = EC_KEY_get0_group(eckey))) { result = 1; goto err; } + if (!EC_GROUP_get_order(group, order, ctx)) { result = 1; goto err; } + + if (!BN_mod_inverse(mask_inv, mask, order, ctx)) { result = 1; goto err; } + if (!BN_mod_mul(raw_secret, key_with_mask, mask_inv, order, ctx)) { result = 1; goto err; } + + if (!EC_KEY_set_private_key(eckey, raw_secret)) { result = 1; goto err; } + if (!gost2001_compute_public(eckey)) { result = 1; goto err; } + if (!(pubkey = EC_KEY_get0_public_key(eckey))) { result = 1; goto err; } + if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) { result = 1; goto err; } + + store_bignum(X, outbuf, sizeof(outbuf)); + BUF_reverse(public_X, outbuf, sizeof(outbuf)); + if (memcmp(public_X, public8, 8) != 0) { result = 1; goto err; } + + result = 0; //ok +err: + if (eckey) EC_KEY_free(eckey); + if (result == 0) return raw_secret; + return NULL; +} + +int file_length(char *fname) +{ + int len; + FILE *f = fopen(fname, "rb"); + if (f == NULL) return -1; + fseek(f, 0, SEEK_END); + len = ftell(f); + fclose(f); + return len; +} + +int read_file(char *fname, int start_pos, char *buf, int len) +{ + int read_len; + FILE *f = fopen(fname, "rb"); + if (f == NULL) return 1; + if (start_pos) fseek(f, start_pos, SEEK_SET); + read_len = fread(buf, 1, len, f); + fclose(f); + if (read_len != len) return 1; + return 0; //ok +} + +int get_asn1_len(unsigned char *buf, int *size_hdr) +{ + int n, i, res; + int pos = 0; + if ((buf[pos]&0x80) == 0) { + *size_hdr = 1; + return buf[pos]; + } + n = buf[pos++]&0x7f; + res = 0; + for(i = 0; i < n; i++) { + res = res*256 + buf[pos++]; + } + *size_hdr = n+1; + return res; +} + +#define MAX_HEADER 20000 +int read_container(char *fpath, int flag2, char *salt12, char *primary_key, char *masks_key, char *public8, char *oid_param_set8) +{ + int result; + char primary_path[1024+30]; + char masks_path[1024+30]; + char header_path[1024+30]; + char header_buf[MAX_HEADER]; + int header_len; + int i, len, pos, size_hdr; + + if (strlen(fpath)>1024) { result = 1; goto err; } + + sprintf(header_path, "%s/header.key", fpath); + if (flag2 == 0) + { + sprintf(primary_path, "%s/primary.key", fpath); + sprintf(masks_path, "%s/masks.key", fpath); + } + else + { + sprintf(primary_path, "%s/primary2.key", fpath); + sprintf(masks_path, "%s/masks2.key", fpath); + } + + if (read_file(primary_path, 4, primary_key, 32)) { result = 1; goto err; } + if (read_file(masks_path, 4, masks_key, 32)) { result = 1; goto err; } + if (read_file(masks_path, 0x26, salt12, 12)) { result = 1; goto err; } + + header_len = file_length(header_path); + if (header_len < 0x42 || header_len > MAX_HEADER) { result = 1; goto err; } + if (read_file(header_path, 0, header_buf, header_len)) { result = 1; goto err; } + +//------------- skip certificate --------------------------- + pos = 0; + for(i = 0; i < 2; i++) + { + get_asn1_len(header_buf+pos+1, &size_hdr); + pos += size_hdr+1; + if (pos > header_len-8) { result = 2; goto err; } + } + +//------------------ get oid_param_set8 ----------------------- +#define PARAM_SET_POS 34 + if (memcmp(header_buf+pos+PARAM_SET_POS, "\x6\x7", 2) != 0) { result = 2; goto err; } + memcpy(oid_param_set8, header_buf+pos+PARAM_SET_POS+1, 8); + +//------------------ get public8 ----------------------- + result = 2; //not found + pos += 52; + for(i = 0; i < 3; i++) + { + len = get_asn1_len(header_buf+pos+1, &size_hdr); + if (len == 8 && memcmp(header_buf+pos, "\x8a\x8", 2) == 0) + { + memcpy(public8,header_buf+pos+2,8); + result = 0; //ok + break; + } + pos += len+size_hdr+1; + if (pos > header_len-8) { result = 2; goto err; } + } +err: + OPENSSL_cleanse(header_buf, sizeof(header_buf)); + return result; +} + +#define START_OID 0x12 +#define START_KEY 0x28 +unsigned char asn1_private_key[72] = { + 0x30,0x46,2,1,0,0x30,0x1c,6,6,0x2a,0x85,3,2,2,0x13,0x30,0x12,6,7,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,6,7,0x2a,0x85,3,2,2,0x1e,1,4,0x23,2,0x21,0 +}; + +int main(int argc, char **argv) +{ + int result; + char *container_path; + char *passw; + char salt12[12]; + char primary_key[32]; + char masks_key[32]; + char public8[8]; + char oid_param_set8[8]; + BN_CTX *ctx; + BIGNUM *key_with_mask; + BIGNUM *mask; + BIGNUM *raw_key; + char pwd_key[32]; + char outbuf[32]; + + ctx = BN_CTX_new(); + + if (argc == 2) + { + container_path = argv[1]; + passw = ""; + } + else + if (argc == 3) + { + container_path = argv[1]; + passw = argv[2]; + } + else + { + printf("get_private container_path [passw]\n"); + result = 1; + goto err; + } + + if (read_container(container_path, 0, salt12, primary_key, masks_key, public8, oid_param_set8) != 0 && + read_container(container_path, 1, salt12, primary_key, masks_key, public8, oid_param_set8) != 0) + { + printf("can not read container from %s\n", container_path); + result = 2; + goto err; + } + + make_pwd_key(pwd_key, salt12, 12, passw); + key_with_mask = decode_primary_key(pwd_key, primary_key, ctx); + OPENSSL_cleanse(pwd_key, sizeof(pwd_key)); + mask = reverse32bn(masks_key, ctx); + raw_key = remove_mask_and_check_public(oid_param_set8, key_with_mask, mask, public8, ctx); + + if (raw_key) + { + BIO *bio; + store_bignum(raw_key, outbuf, sizeof(outbuf)); + memcpy(asn1_private_key+START_OID, oid_param_set8, 8); + memcpy(asn1_private_key+START_KEY, outbuf, 32); + //bio = BIO_new_file("private.key", "w"); + bio = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT); + PEM_write_bio(bio, "PRIVATE KEY", "", asn1_private_key, sizeof(asn1_private_key)); + BIO_free(bio); + OPENSSL_cleanse(outbuf, sizeof(outbuf)); + OPENSSL_cleanse(asn1_private_key, sizeof(asn1_private_key)); + result = 0; //ok + } + else + { + printf("Error check public key\n"); + result = 3; + } + +err: + BN_CTX_free(ctx); + OPENSSL_cleanse(salt12, sizeof(salt12)); + OPENSSL_cleanse(primary_key, sizeof(primary_key)); + OPENSSL_cleanse(masks_key, sizeof(masks_key)); + return result; +} diff --git a/gost89.h b/gost89.h new file mode 100644 index 0000000..f201363 --- /dev/null +++ b/gost89.h @@ -0,0 +1,110 @@ +/********************************************************************** + * gost89.h * + * Copyright (c) 2005-2006 Cryptocom LTD * + * This file is distributed under the same license as OpenSSL * + * * + * Declarations for GOST 28147-89 encryption algorithm * + * No OpenSSL libraries required to compile and use * + * this code * + **********************************************************************/ +#ifndef GOST89_H +# define GOST89_H + +/* Typedef for unsigned 32-bit integer */ +# if __LONG_MAX__ > 2147483647L +typedef unsigned int u4; +# else +typedef unsigned long u4; +# endif +/* Typedef for unsigned 8-bit integer */ +typedef unsigned char byte; + +/* Internal representation of GOST substitution blocks */ +typedef struct { + byte k8[16]; + byte k7[16]; + byte k6[16]; + byte k5[16]; + byte k4[16]; + byte k3[16]; + byte k2[16]; + byte k1[16]; +} gost_subst_block; + +/* Cipher context includes key and preprocessed substitution block */ +typedef struct { + u4 master_key[8]; + u4 key[8]; + u4 mask[8]; + /* Constant s-boxes -- set up in gost_init(). */ + u4 k87[256], k65[256], k43[256], k21[256]; +} gost_ctx; +/* + * Note: encrypt and decrypt expect full blocks--padding blocks is caller's + * responsibility. All bulk encryption is done in ECB mode by these calls. + * Other modes may be added easily enough. + */ +/* Encrypt several full blocks in ECB mode */ +void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks); +/* Decrypt several full blocks in ECB mode */ +void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks); +/* Encrypts several full blocks in CFB mode using 8byte IV */ +void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear, + byte * cipher, int blocks); +/* Decrypts several full blocks in CFB mode using 8byte IV */ +void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher, + byte * clear, int blocks); + +/* Encrypt one block */ +void gostcrypt(gost_ctx * c, const byte * in, byte * out); +/* Decrypt one block */ +void gostdecrypt(gost_ctx * c, const byte * in, byte * out); +/* Set key into context */ +void gost_key(gost_ctx * c, const byte * k); +/* Set key into context without key mask */ +void gost_key_nomask(gost_ctx * c, const byte * k); +/* Set key into context */ +void magma_key(gost_ctx * c, const byte * k); +/* Set master 256-bit key to be used in TLSTREE calculation into context */ +void magma_master_key(gost_ctx *c, const byte *k); +/* Get key from context */ +void gost_get_key(gost_ctx * c, byte * k); +/* Set S-blocks into context */ +void gost_init(gost_ctx * c, const gost_subst_block * b); +/* Clean up context */ +void gost_destroy(gost_ctx * c); +/* Intermediate function used for calculate hash */ +void gost_enc_with_key(gost_ctx *, byte * key, byte * inblock, + byte * outblock); +/* Compute MAC of given length in bits from data */ +int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data, + unsigned int data_len, unsigned char *mac); +/* + * Compute MAC of given length in bits from data, using non-zero 8-byte IV + * (non-standard, for use in CryptoPro key transport only + */ +int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv, + const unsigned char *data, unsigned int data_len, + unsigned char *mac); +/* Perform one step of MAC calculation like gostcrypt */ +void mac_block(gost_ctx * c, byte * buffer, const byte * block); +/* Extracts MAC value from mac state buffer */ +void get_mac(byte * buffer, int nbits, byte * out); +/* Implements cryptopro key meshing algorithm. Expect IV to be 8-byte size*/ +void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv); +/* Parameter sets specified in RFC 4357 */ +extern gost_subst_block GostR3411_94_TestParamSet; +extern gost_subst_block GostR3411_94_CryptoProParamSet; +extern gost_subst_block Gost28147_TestParamSet; +extern gost_subst_block Gost28147_CryptoProParamSetA; +extern gost_subst_block Gost28147_CryptoProParamSetB; +extern gost_subst_block Gost28147_CryptoProParamSetC; +extern gost_subst_block Gost28147_CryptoProParamSetD; +extern gost_subst_block Gost28147_TC26ParamSetZ; +extern const byte CryptoProKeyMeshingKey[]; +typedef unsigned int word32; +/* For tests. */ +void kboxinit(gost_ctx * c, const gost_subst_block * b); +void magma_get_key(gost_ctx * c, byte * k); +void acpkm_magma_key_meshing(gost_ctx * ctx); +#endif diff --git a/gost_lcl.h b/gost_lcl.h new file mode 100644 index 0000000..c528389 --- /dev/null +++ b/gost_lcl.h @@ -0,0 +1,257 @@ +#ifndef GOST_TOOLS_H +# define GOST_TOOLS_H +/********************************************************************** + * gost_lcl.h * + * Copyright (c) 2006 Cryptocom LTD * + * This file is distributed under the same license as OpenSSL * + * * + * Internal declarations used in GOST engine * + * OpenSSL 0.9.9 libraries required to compile and use * + * this code * + **********************************************************************/ +# include +# include +# include +# include +# include +# include +# include +# include "gost89.h" +# include "gosthash.h" +/* Control commands */ +# define GOST_PARAM_CRYPT_PARAMS 0 +# define GOST_PARAM_PBE_PARAMS 1 +# define GOST_PARAM_MAX 1 +# define GOST_CTRL_CRYPT_PARAMS (ENGINE_CMD_BASE+GOST_PARAM_CRYPT_PARAMS) +# define GOST_CTRL_PBE_PARAMS (ENGINE_CMD_BASE+GOST_PARAM_PBE_PARAMS) + +typedef struct R3410_ec { + int nid; + char *a; + char *b; + char *p; + char *q; + char *x; + char *y; + char *cofactor; +} R3410_ec_params; + +extern R3410_ec_params R3410_2001_paramset[], + *R3410_2012_256_paramset, R3410_2012_512_paramset[]; + +extern const ENGINE_CMD_DEFN gost_cmds[]; +int gost_control_func(ENGINE *e, int cmd, long i, void *p, void (*f) (void)); +const char *get_gost_engine_param(int param); +int gost_set_default_param(int param, const char *value); +void gost_param_free(void); + +/* method registration */ + +int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth, + const char *pemstr, const char *info); +int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags); + +/* Gost-specific pmeth control-function parameters */ +/* For GOST R34.10 parameters */ +# define param_ctrl_string "paramset" +# define EVP_PKEY_CTRL_GOST_PARAMSET (EVP_PKEY_ALG_CTRL+1) +/* For GOST 28147 MAC */ +# define key_ctrl_string "key" +# define hexkey_ctrl_string "hexkey" +# define maclen_ctrl_string "size" +# define EVP_PKEY_CTRL_GOST_MAC_HEXKEY (EVP_PKEY_ALG_CTRL+3) +# define EVP_PKEY_CTRL_MAC_LEN (EVP_PKEY_ALG_CTRL+5) +/* Pmeth internal representation */ +struct gost_pmeth_data { + int sign_param_nid; /* Should be set whenever parameters are + * filled */ + EVP_MD *md; + unsigned char *shared_ukm; + int peer_key_used; +}; + +struct gost_mac_pmeth_data { + short int key_set; + short int mac_size; + int mac_param_nid; + EVP_MD *md; + unsigned char key[32]; +}; + +struct gost_mac_key { + int mac_param_nid; + unsigned char key[32]; + short int mac_size; +}; +/* GOST-specific ASN1 structures */ + +typedef struct { + ASN1_OCTET_STRING *encrypted_key; + ASN1_OCTET_STRING *imit; +} GOST_KEY_INFO; + +DECLARE_ASN1_FUNCTIONS(GOST_KEY_INFO) + +typedef struct { + ASN1_OBJECT *cipher; + X509_PUBKEY *ephem_key; + ASN1_OCTET_STRING *eph_iv; +} GOST_KEY_AGREEMENT_INFO; + +DECLARE_ASN1_FUNCTIONS(GOST_KEY_AGREEMENT_INFO) + +typedef struct { + GOST_KEY_INFO *key_info; + GOST_KEY_AGREEMENT_INFO *key_agreement_info; +} GOST_KEY_TRANSPORT; + +DECLARE_ASN1_FUNCTIONS(GOST_KEY_TRANSPORT) + +typedef struct { /* FIXME incomplete */ + GOST_KEY_TRANSPORT *gkt; +} GOST_CLIENT_KEY_EXCHANGE_PARAMS; + +/* + * Hacks to shorten symbols to 31 characters or less, or OpenVMS. This mimics + * what's done in symhacks.h, but since this is a very local header file, I + * prefered to put this hack directly here. -- Richard Levitte + */ +# ifdef OPENSSL_SYS_VMS +# undef GOST_CLIENT_KEY_EXCHANGE_PARAMS_it +# define GOST_CLIENT_KEY_EXCHANGE_PARAMS_it GOST_CLIENT_KEY_EXC_PARAMS_it +# undef GOST_CLIENT_KEY_EXCHANGE_PARAMS_new +# define GOST_CLIENT_KEY_EXCHANGE_PARAMS_new GOST_CLIENT_KEY_EXC_PARAMS_new +# undef GOST_CLIENT_KEY_EXCHANGE_PARAMS_free +# define GOST_CLIENT_KEY_EXCHANGE_PARAMS_free GOST_CLIENT_KEY_EXC_PARAMS_free +# undef d2i_GOST_CLIENT_KEY_EXCHANGE_PARAMS +# define d2i_GOST_CLIENT_KEY_EXCHANGE_PARAMS d2i_GOST_CLIENT_KEY_EXC_PARAMS +# undef i2d_GOST_CLIENT_KEY_EXCHANGE_PARAMS +# define i2d_GOST_CLIENT_KEY_EXCHANGE_PARAMS i2d_GOST_CLIENT_KEY_EXC_PARAMS +# endif /* End of hack */ +DECLARE_ASN1_FUNCTIONS(GOST_CLIENT_KEY_EXCHANGE_PARAMS) +typedef struct { + ASN1_OBJECT *key_params; + ASN1_OBJECT *hash_params; + ASN1_OBJECT *cipher_params; +} GOST_KEY_PARAMS; + +DECLARE_ASN1_FUNCTIONS(GOST_KEY_PARAMS) + +typedef struct { + ASN1_OCTET_STRING *iv; + ASN1_OBJECT *enc_param_set; +} GOST_CIPHER_PARAMS; + +DECLARE_ASN1_FUNCTIONS(GOST_CIPHER_PARAMS) + +typedef struct { + ASN1_OCTET_STRING *masked_priv_key; + ASN1_OCTET_STRING *public_key; +} MASKED_GOST_KEY; + +DECLARE_ASN1_FUNCTIONS(MASKED_GOST_KEY) + +/*============== Message digest and cipher related structures ==========*/ + /* + * Structure used as EVP_MD_CTX-md_data. It allows to avoid storing + * in the md-data pointers to dynamically allocated memory. I + * cannot invent better way to avoid memory leaks, because openssl + * insist on invoking Init on Final-ed digests, and there is no + * reliable way to find out whether pointer in the passed md_data is + * valid or not. + */ +struct ossl_gost_digest_ctx { + gost_hash_ctx dctx; + gost_ctx cctx; +}; +/* EVP_MD structure for GOST R 34.11 */ +EVP_MD *digest_gost(void); +void digest_gost_destroy(void); +/* EVP MD structure for GOST R 34.11-2012 algorithms */ +EVP_MD *digest_gost2012_256(void); +EVP_MD *digest_gost2012_512(void); +void digest_gost2012_256_destroy(void); +void digest_gost2012_512_destroy(void); +/* EVP_MD structure for GOST 28147 in MAC mode */ +EVP_MD *imit_gost_cpa(void); +void imit_gost_cpa_destroy(void); +EVP_MD *imit_gost_cp_12(void); +void imit_gost_cp_12_destroy(void); +/* Cipher context used for EVP_CIPHER operation */ +struct ossl_gost_cipher_ctx { + int paramNID; + unsigned int count; + int key_meshing; + gost_ctx cctx; +}; +/* Structure to map parameter NID to S-block */ +struct gost_cipher_info { + int nid; + gost_subst_block *sblock; + int key_meshing; +}; +/* Context for MAC */ +struct ossl_gost_imit_ctx { + gost_ctx cctx; + unsigned char buffer[8]; + unsigned char partial_block[8]; + unsigned int count; + int key_meshing; + int bytes_left; + int key_set; + int dgst_size; +}; +/* Table which maps parameter NID to S-blocks */ +extern struct gost_cipher_info gost_cipher_list[]; +/* Find encryption params from ASN1_OBJECT */ +const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj); +/* Implementation of GOST 28147-89 cipher in CFB and CNT modes */ +const EVP_CIPHER *cipher_gost(); +const EVP_CIPHER *cipher_gost_cbc(); +const EVP_CIPHER *cipher_gost_cpacnt(); +const EVP_CIPHER *cipher_gost_cpcnt_12(); +void cipher_gost_destroy(); +# define EVP_MD_CTRL_KEY_LEN (EVP_MD_CTRL_ALG_CTRL+3) +# define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+4) +# define EVP_MD_CTRL_MAC_LEN (EVP_MD_CTRL_ALG_CTRL+5) +/* EVP_PKEY_METHOD key encryption callbacks */ +/* From gost_ec_keyx.c */ +int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, + size_t *outlen, const unsigned char *key, + size_t key_len); + +int pkey_GOST_ECcp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, + size_t *outlen, const unsigned char *in, + size_t in_len); +/* derive functions */ +/* From gost_ec_keyx.c */ +int pkey_gost_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen); +int fill_GOST_EC_params(EC_KEY *eckey, int nid); +int gost_sign_keygen(DSA *dsa); +int gost_ec_keygen(EC_KEY *ec); + +DSA_SIG *gost_ec_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey); + +int gost_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); +int gost_ec_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, EC_KEY *ec); +int gost_ec_compute_public(EC_KEY *ec); +/*============== miscellaneous functions============================= */ +/* from gost_sign.c */ +/* Convert GOST R 34.11 hash sum to bignum according to standard */ +BIGNUM *hashsum2bn(const unsigned char *dgst, int len); +/* + * Store bignum in byte array of given length, prepending by zeros if + * nesseccary + */ +int store_bignum(const BIGNUM *bn, unsigned char *buf, int len); +/* Pack GOST R 34.10 signature according to CryptoPro rules */ +int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen); +/* from ameth.c */ +/* Get private key as BIGNUM from both 34.10-2001 keys*/ +/* Returns pointer into EVP_PKEY structure */ +BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey); + +#endif diff --git a/gosthash.h b/gosthash.h new file mode 100644 index 0000000..003e668 --- /dev/null +++ b/gosthash.h @@ -0,0 +1,52 @@ +/********************************************************************** + * gosthash.h * + * Copyright (c) 2005-2006 Cryptocom LTD * + * This file is distributed under the same license as OpenSSL * + * * + * Declaration of GOST R 34.11-94 hash functions * + * uses and gost89.h Doesn't need OpenSSL * + **********************************************************************/ +#ifndef GOSTHASH_H +# define GOSTHASH_H +# include "gost89.h" +# include + +# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +typedef __int64 ghosthash_len; +# elif defined(__arch64__) +typedef long ghosthash_len; +# else +typedef long long ghosthash_len; +# endif + +typedef struct gost_hash_ctx { + ghosthash_len len; + gost_ctx *cipher_ctx; + int left; + byte H[32]; + byte S[32]; + byte remainder[32]; +} gost_hash_ctx; + +/* Initalizes gost hash ctx, including creation of gost cipher ctx */ + +int init_gost_hash_ctx(gost_hash_ctx * ctx, + const gost_subst_block * subst_block); +void done_gost_hash_ctx(gost_hash_ctx * ctx); + +/* + * Cleans up all fields, except cipher ctx preparing ctx for computing of new + * hash value + */ +int start_hash(gost_hash_ctx * ctx); + +/* Hashes block of data */ +int hash_block(gost_hash_ctx * ctx, const byte * block, size_t length); + +/* + * Finalizes computation of hash and fills buffer (which should be at least + * 32 bytes long) with value of computed hash. + */ +int finish_hash(gost_hash_ctx * ctx, byte * hashval); + +#endif