Начальный коммит
commit
856bbc8b35
|
@ -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
|
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/cms.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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 <openssl/bn.h>
|
||||||
|
# include <openssl/evp.h>
|
||||||
|
# include <openssl/dsa.h>
|
||||||
|
# include <openssl/asn1t.h>
|
||||||
|
# include <openssl/x509.h>
|
||||||
|
# include <openssl/engine.h>
|
||||||
|
# include <openssl/ec.h>
|
||||||
|
# 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
|
|
@ -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 <stdlib.h>
|
||||||
|
|
||||||
|
# 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
|
Loading…
Reference in New Issue