add zeromem engine

anti memory leakage attack
This commit is contained in:
Zhi Guan
2017-03-16 23:20:13 +08:00
parent 3090de8951
commit 7f24b7229e
19 changed files with 3648 additions and 0 deletions

260
engines/zeromem/engine/myengine.c Executable file
View File

@@ -0,0 +1,260 @@
#include <stdio.h>
#include <string.h>
#include <openssl/ecdh.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
#include "myengine.h"
#include "../ec.h"
#include "../util.h"
int get_affine(const EC_GROUP* group, const EC_POINT* point, BIGNUM* x, BIGNUM* y, BN_CTX *ctx){
int ret = 0;
if(EC_POINT_is_at_infinity(group, point)){
return 0;
}
if(x == NULL || y == NULL)
return 0;
if(BN_cmp(&point->Z, BN_value_one()) == 0){
if(!BN_copy(x, &point->X) || !BN_copy(y, &point->Y))
return 0;
BN_set_negative(x, 0);
BN_set_negative(y, 0);
} else {
BIGNUM* z = BN_new();
if(!BN_GF2m_mod_inv(z, &point->Z, &group->field, ctx)){
printf("could not get the inv\n");
return 0;
}
if(!BN_GF2m_mod_mul(x, &point->X, z, &group->field, ctx)){
return 0;
}
if(!BN_GF2m_mod_sqr(z, z, &group->field, ctx)){
return 0;
}
if(!BN_GF2m_mod_mul(y, &point->Y, z, &group->field, ctx)){
return 0;
}
}
return 1;
}
static int my_ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))
{
BN_CTX *ctx;
EC_POINT *tmp=NULL;
BIGNUM *x=NULL, *y=NULL;
const BIGNUM *priv_key;
const EC_GROUP* group;
int ret= -1;
size_t buflen, len;
unsigned char *buf=NULL;
mm256_point_t mPK;
mm_256 mUK;
mm256_point_t mR;
group = EC_KEY_get0_group(ecdh);
printf("curve_name: %d, field type: %d, degree: %d, a: %x, b: %x\n", EC_GROUP_get_curve_name(group), EC_METHOD_get_field_type(EC_GROUP_method_of(group)), EC_GROUP_get_degree(group), BN_get_word(&group->a), BN_get_word(&group->b));
// compute with the syscall only when the filetype is NID_X9_62_characteristic_two_field and the degree is 163
if (!(
EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_characteristic_two_field
&& EC_GROUP_get_degree(group) == 163
))
{
ECDH_METHOD* temp = ECDH_get_default_method();
return temp->compute_key(out, len, pub_key, ecdh, KDF);
}
if (outlen > INT_MAX)
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */
return -1;
}
if ((ctx = BN_CTX_new()) == NULL) goto err;
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
priv_key = EC_KEY_get0_private_key(ecdh);
if (priv_key == NULL)
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE);
goto err;
}
if ((tmp=EC_POINT_new(group)) == NULL)
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
goto err;
}
bn_to_mm256(priv_key, &mUK);
printf("%s\n", BN_bn2hex(priv_key));
print_mm_256(&mUK);
printf("\n");
EC_POINT_to_mm_point(pub_key, &mPK);
print_EC_POINT(pub_key);
printf("\n");
print_mm_point(&mPK);
printf("\n");
init_sqr_table();
gf2_point_mul(&mPK, &mUK, &mR, BN_get_word(&group->a), BN_get_word(&group->b));
print_mm_point(&mR);
printf("\n");
if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx))
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
goto err;
}
print_EC_POINT(tmp);
printf("\n");
if (!get_affine(group, tmp, x, y, ctx))
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
goto err;
}
buflen = (EC_GROUP_get_degree(group) + 7)/8;
len = BN_num_bytes(x);
if (len > buflen)
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR);
goto err;
}
if ((buf = OPENSSL_malloc(buflen)) == NULL)
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
goto err;
}
memset(buf, 0, buflen - len);
if (len != (size_t)BN_bn2bin(x, buf + buflen - len))
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB);
goto err;
}
if (KDF != 0)
{
if (KDF(buf, buflen, out, &outlen) == NULL)
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED);
goto err;
}
ret = outlen;
}
else
{
/* no KDF, just copy as much as we can */
if (outlen > buflen)
outlen = buflen;
memcpy(out, buf, outlen);
ret = outlen;
}
printf("ECC compute key done!\n");
err:
if (tmp) EC_POINT_free(tmp);
if (ctx) BN_CTX_end(ctx);
if (ctx) BN_CTX_free(ctx);
if (buf) OPENSSL_free(buf);
return(ret);
/* if(1){ */
/* ECDH_METHOD* temp = ECDH_get_default_method(); */
/* return temp->compute_key(out, len, pub_key, ecdh, KDF); */
/* } */
/* return 1; */
}
/****************************************************************************
* Functions to handle the engine *
*****************************************************************************/
static int bind_my(ENGINE *e)
{
//const RSA_METHOD *meth1;
if(!ENGINE_set_id(e, engine_my_id)
|| !ENGINE_set_name(e, engine_my_name)
|| !ENGINE_set_ECDH(e, &my_ecdh)
//|| !ENGINE_set_ciphers(e, my_ciphers)
//|| !ENGINE_set_digests(e, my_digests)
|| !ENGINE_set_destroy_function(e, my_destroy)
|| !ENGINE_set_init_function(e, my_init)
|| !ENGINE_set_finish_function(e, my_finish)
/* || !ENGINE_set_ctrl_function(e, my_ctrl) */
/* || !ENGINE_set_cmd_defns(e, my_cmd_defns) */)
return 0;
return 1;
}
#ifdef ENGINE_DYNAMIC_SUPPORT
static int bind_helper(ENGINE *e, const char *id)
{
if(id && (strcmp(id, engine_my_id) != 0))
return 0;
if(!bind_my(e))
return 0;
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
#else
static ENGINE *engine_my(void)
{
ENGINE *ret = ENGINE_new();
if(!ret)
return NULL;
if(!bind_my(ret))
{
ENGINE_free(ret);
return NULL;
}
return ret;
}
void ENGINE_load_myengine(void)
{
/* Copied from eng_[openssl|dyn].c */
ENGINE *toadd = engine_my();
if(!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
#endif
static int my_init(ENGINE *e)
{
printf("my_init\n");
return 1;
}
static int my_finish(ENGINE *e)
{
printf("my_finih\n");
return 1;
}
static int my_destroy(ENGINE *e)
{
printf("my_destroy\n");
return 1;
}

175
engines/zeromem/engine/myengine.h Executable file
View File

@@ -0,0 +1,175 @@
#define INT_MAX 32767
#include <openssl/ec.h>
typedef struct ec_extra_data_st {
struct ec_extra_data_st *next;
void *data;
void *(*dup_func)(void *);
void (*free_func)(void *);
void (*clear_free_func)(void *);
} EC_EXTRA_DATA;
typedef struct ec_key_st {
int version;
EC_GROUP *group;
EC_POINT *pub_key;
BIGNUM *priv_key;
unsigned int enc_flag;
point_conversion_form_t conv_form;
int references;
int flags;
EC_EXTRA_DATA *method_data;
} EC_KEY;
static const char *engine_my_id = "111";
static const char *engine_my_name = "myengine";
/****************************************************************************
* Functions to handle the engine *
***************************************************************************/
static int my_destroy(ENGINE *e);
static int my_init(ENGINE *e);
static int my_finish(ENGINE *e);
/****************************************************************************
* Engine commands *
*****************************************************************************/
static const ENGINE_CMD_DEFN my_cmd_defns[] =
{
{0, NULL, NULL, 0}
};
static int my_ecdh_compute_key(void *out, size_t len, const EC_POINT *pub_key,
EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
/*
some definations missing in openssl header files public accessible
*/
struct ec_point_st {
const EC_METHOD *meth;
/* All members except 'meth' are handled by the method functions,
* * even if they appear generic */
BIGNUM X;
BIGNUM Y;
BIGNUM Z; /* Jacobian projective coordinates:
* (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */
int Z_is_one; /* enable optimized point arithmetics for special case */
} /* EC_POINT */;
typedef struct ec_point_st EC_POINT;
struct ec_group_st {
const EC_METHOD *meth;
EC_POINT *generator; /* optional */
BIGNUM order, cofactor;
int curve_name;/* optional NID for named curve */
int asn1_flag; /* flag to control the asn1 encoding */
point_conversion_form_t asn1_form;
unsigned char *seed; /* optional seed for parameters (appears in ASN1) */
size_t seed_len;
struct EC_EXTRA_DATA *extra_data; /* linked list */
/* The following members are handled by the method functions,
* even if they appear generic */
BIGNUM field; /* Field specification.
* For curves over GF(p), this is the modulus;
* for curves over GF(2^m), this is the
* irreducible polynomial defining the field.
*/
int poly[6]; /* Field specification for curves over GF(2^m).
* The irreducible f(t) is then of the form:
* t^poly[0] + t^poly[1] + ... + t^poly[k]
* where m = poly[0] > poly[1] > ... > poly[k] = 0.
* The array is terminated with poly[k+1]=-1.
* All elliptic curve irreducibles have at most 5
* non-zero terms.
*/
BIGNUM a, b; /* Curve coefficients.
* (Here the assumption is that BIGNUMs can be used
* or abused for all kinds of fields, not just GF(p).)
* For characteristic > 3, the curve is defined
* by a Weierstrass equation of the form
* y^2 = x^3 + a*x + b.
* For characteristic 2, the curve is defined by
* an equation of the form
* y^2 + x*y = x^3 + a*x^2 + b.
*/
int a_is_minus3; /* enable optimized point arithmetics for special case */
void *field_data1; /* method-specific (e.g., Montgomery structure) */
void *field_data2; /* method-specific */
int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); /* method-specific */
} /* EC_GROUP */;
struct ec_key_st {
int version;
EC_GROUP *group;
EC_POINT *pub_key;
BIGNUM *priv_key;
unsigned int enc_flag;
point_conversion_form_t conv_form;
int references;
int flags;
struct EC_EXTRA_DATA *method_data;
} /* EC_KEY */;
struct ecdh_method
{
const char *name;
int (*compute_key)(void *key, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh,void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
#if 0
int (*init)(EC_KEY *eckey);
int (*finish)(EC_KEY *eckey);
#endif
int flags;
char *app_data;
};
static ECDH_METHOD my_ecdh = {
"myengine",
my_ecdh_compute_key,
#if 0
NULL, /* init */
NULL, /* finish */
#endif
0, /* flags */
NULL /* app_data */
};
/****************************************************************************
* Symetric cipher and digest function registrars *
*****************************************************************************/
static int my_ciphers(ENGINE *e, const EVP_CIPHER **cipher,const int **nids, int nid);
static int my_digests(ENGINE *e, const EVP_MD **digest,const int **nids, int nid);
static int my_cipher_nids[] ={ NID_des_cbc, NID_des_ede3_cbc, NID_desx_cbc, 0 };
static int my_digest_nids[] ={ NID_md2, NID_md5, 0 };
/*__declspec(dllexport)*/ void ENGINE_load_myengine(void);

106
engines/zeromem/engine/mytest.c Executable file
View File

@@ -0,0 +1,106 @@
//test.c
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
static void display_engine_list()
{
ENGINE *h;
int loop;
h = ENGINE_get_first();
loop = 0;
printf("listing available engine types\n");
while(h)
{
printf("engine %i, id = \"%s\", name = \"%s\"\n",
loop++, ENGINE_get_id(h), ENGINE_get_name(h));
h = ENGINE_get_next(h);
}
printf("end of list\n");
/* ENGINE_get_first() increases the struct_ref counter, so we
must call ENGINE_free() to decrease it again */
ENGINE_free(h);
}
void test()
{
ENGINE *e = NULL;
int rv;
unsigned char buf[1024];
EVP_PKEY *evpKey;
EC_KEY *key;
EC_POINT *pubkey;
EC_GROUP *group;
EC_builtin_curve *curves;
int crv_len;
char shareKey1[10240],shareKey2[10240];
int ret,nid,size,i,sig_len;
int len1,len2;
crv_len = EC_get_builtin_curves(NULL, 0);
curves = (EC_builtin_curve *)malloc(sizeof(EC_builtin_curve) * crv_len);
EC_get_builtin_curves(curves, crv_len);
nid = NID_sect163k1;
group=EC_GROUP_new_by_curve_name(nid);
key=EC_KEY_new();
ret=EC_KEY_set_group(key,group);
ret=EC_KEY_generate_key(key);
ret=EC_KEY_check_key(key);
pubkey = EC_KEY_get0_public_key(key);
ENGINE_load_myengine();
display_engine_list();
len1=ECDH_compute_key(shareKey1, 10240, pubkey, key, NULL);
e = ENGINE_by_id("111");
printf("get myengine engine OK.name:%s\n",ENGINE_get_name(e));
ENGINE_register_ECDH(e);
//rv = ENGINE_set_default(e,ENGINE_METHOD_ALL);
len2=ECDH_compute_key(shareKey2, 10240, pubkey, key, NULL);
printf("len: %d, %d\n", len1, len2);
if(len1!=len2)
{
printf("err: %d, %d\n", len1, len2);
}
else
{
ret=memcmp(shareKey1,shareKey2,len1);
if(ret==0)
{
printf("right\n");
}
else
printf("wrong\n");
}
printf("test ok!\n");
/*ENGINE_register_RSA(e);
rv = ENGINE_set_default(e,ENGINE_METHOD_ALL);
evpKey = EVP_PKEY_new();
rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
rv = EVP_PKEY_set1_RSA(evpKey,rsa);
rv = EVP_PKEY_encrypt(buf,buf,128,evpKey);
*/
/* rv = ENGINE_finish(e);
rv = ENGINE_free(e);
printf("test end.\n");
return;*/
}
int main()
{
test();
return 0;
}