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

266
engines/zeromem/cba_ecdh_engine.c Executable file
View File

@@ -0,0 +1,266 @@
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/pem.h>
#include <openssl/dso.h>
#include <openssl/engine.h>
#include <openssl/ui.h>
#include <openssl/rand.h>
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
#include <openssl/bn.h>
#include <openssl/ecdh.h>
#include "ec2m_kern.h"
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));
int flags;
char *app_data;
};
#ifndef OPENSSL_NO_HW
/* the header file of vender */
//#include "hwdevice.h"
/* Constants used when creating the ENGINE */
static const char *engine_hwdev_id = "cba_ecdh";
static const char *engine_hwdev_name = "cold boot resistant ECDH";
#ifndef OPENSSL_NO_DYNAMIC_ENGINE
/* Compatibility hack, the dynamic library uses this form in the path */
static const char *engine_hwdev_id_alt = "cba_ecdh";
#endif
static int 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))
{
const EC_GROUP* group;
int ret;
group = EC_KEY_get0_group(ecdh);
// only use our solution if the curve name is SECT163K1
if (EC_GROUP_get_curve_name(group) == NID_sect163k1) {
const BIGNUM* rkey;
BN_CTX *ctx;
BIGNUM* x, *y;
mm256_point_t p, q;
mm_256 mkey;
int r;
ctx = BN_CTX_new();
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
rkey = EC_KEY_get0_private_key(ecdh);
memset(&mkey, 0, sizeof(mkey));
memcpy(&mkey, rkey->d, sizeof(rkey->d[0]) * rkey->top);
ec2m_import_key(&mkey);
r = EC_POINT_get_affine_coordinates_GF2m(group, pub_key, x, y, ctx);
memset(&p, 0, sizeof(p));
memcpy(&p.x, x->d, sizeof(x->d[0]) * x->top);
memcpy(&p.y, y->d, sizeof(y->d[0]) * y->top);
p.z.iv[0] = 1;
r = ec2m_private_operation(&p, &q);
if (r < 0) {
fprintf(stderr, "invalid result: %d\n", r);
}
int xlen = (163 + 7) / 8;
if (KDF != 0)
{
if (KDF(&q.x, xlen, out, &outlen) == NULL)
{
ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED);
return -1;
}
ret = outlen;
}
else
{
/* no KDF, just copy as much as we can */
if (outlen > xlen)
outlen = xlen;
memcpy(out, &q.x, outlen);
ret = outlen;
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
} else {
// use the default method
const ECDH_METHOD* meth = ECDH_OpenSSL();
return meth->compute_key(out, outlen, pub_key, ecdh, KDF);
}
return ret;
}
static ECDH_METHOD ecdh_meth = {
"CBA resistant ECDH method",
compute_key,
0,
NULL
};
static int hwdev_destroy(ENGINE *e)
{
fprintf(stderr, "arrive at hwdev_destroy\n");
return 1;
}
static int hwdev_init(ENGINE *e)
{
fprintf(stderr, "arrive at hwdev_init\n");
ec2m_kern_init();
return 1;
}
static int hwdev_finish(ENGINE *e)
{
fprintf(stderr, "arrive at hwdev_finish\n");
ec2m_kern_clean();
return 1;
}
/* The definitions for control commands specific to this engine */
#define HWDEV_CMD_INIT (ENGINE_CMD_BASE)
#define HWDEV_CMD_EXIT (ENGINE_CMD_BASE + 1)
#define HWDEV_CMD_TEST (ENGINE_CMD_BASE + 2)
static const ENGINE_CMD_DEFN hwdev_cmd_defns[] = {
{HWDEV_CMD_INIT,
"INIT",
"init the hardware device before using",
ENGINE_CMD_FLAG_STRING}, /* may be the password */
{HWDEV_CMD_EXIT,
"EXIT",
"exit the hardware device after using",
ENGINE_CMD_FLAG_NO_INPUT},
{HWDEV_CMD_TEST,
"TEST",
"run the test case of the hardware device",
ENGINE_CMD_FLAG_NUMERIC}, /* may be the number of test case */
{0, NULL, NULL, 0}
};
/* This internal function is used by ENGINE_chil() and possibly by the
* "dynamic" ENGINE support too */
static int hwdev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
{
int to_return = 1;
switch(cmd) {
case HWDEV_CMD_INIT:
fprintf(stderr, "arrive at HWDEV_CMD_INIT, password: %s\n",
(const char *)p);
break;
case HWDEV_CMD_EXIT:
fprintf(stderr, "arrive at HWDEV_CMD_EXIT, no parameters\n");
break;
case HWDEV_CMD_TEST:
fprintf(stderr, "arrive at HWDEV_CMD_TEST, case id: %ld\n",
i);
break;
/* The command isn't understood by this engine */
default:
to_return = 0;
break;
}
return to_return;
}
static EVP_PKEY *hwdev_load_privkey(ENGINE *eng, const char *key_id,
UI_METHOD *ui_method, void *callback_data)
{
fprintf(stderr, "arrive at hwdev_load_privkey\n");
EVP_PKEY *res = NULL;
return res;
}
static EVP_PKEY *hwdev_load_pubkey(ENGINE *eng, const char *key_id,
UI_METHOD *ui_method, void *callback_data)
{
fprintf(stderr, "arrive at hwdev_load_pubkey\n");
EVP_PKEY *res = NULL;
return res;
}
static int bind_helper(ENGINE *e)
{
fprintf(stderr, "arrive at bind_helper\n");
if(!ENGINE_set_id(e, engine_hwdev_id) ||
!ENGINE_set_name(e, engine_hwdev_name) ||
!ENGINE_set_ECDH(e, &ecdh_meth) ||
!ENGINE_set_destroy_function(e, hwdev_destroy) ||
!ENGINE_set_init_function(e, hwdev_init) ||
!ENGINE_set_finish_function(e, hwdev_finish) ||
!ENGINE_set_ctrl_function(e, hwdev_ctrl) ||
!ENGINE_set_load_privkey_function(e, hwdev_load_privkey) ||
!ENGINE_set_load_pubkey_function(e, hwdev_load_pubkey) ||
!ENGINE_set_cmd_defns(e, hwdev_cmd_defns))
return 0;
return 1;
}
static ENGINE *engine_hwdev(void)
{
fprintf(stderr, "arrive at engine_test\n");
ENGINE *ret = ENGINE_new();
if(!ret) {
return NULL;
}
if(!bind_helper(ret)) {
ENGINE_free(ret);
return NULL;
}
return ret;
}
void ENGINE_load_test(void)
{
fprintf(stderr, "arrive at ENGINE_load_test\n");
/* Copied from eng_[openssl|dyn].c */
ENGINE *toadd = engine_hwdev();
if(!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
//#endif
/* This stuff is needed if this ENGINE is being compiled into a self-contained
* shared-library. */
#ifndef OPENSSL_NO_DYNAMIC_ENGINE
static int bind_fn(ENGINE *e, const char *id)
{
fprintf(stderr, "arrive at bind_fn\n");
if(id && (strcmp(id, engine_hwdev_id) != 0) &&
(strcmp(id, engine_hwdev_id_alt) != 0))
return 0;
if(!bind_helper(e))
return 0;
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
#endif /* !OPENSSL_NO_HW */

49
engines/zeromem/ec.h Executable file
View File

@@ -0,0 +1,49 @@
#ifndef _EC_H_
#define _EC_H_
#ifdef EC_DEV
#include <stdint.h>
#else
#include <linux/types.h>
#endif
//extern unsigned int sqr_table[1 << 16];
typedef struct _struct_mm_128{
union{
float fv[4];
double dv[2];
uint64_t iv[2];
uint8_t bv[16];
};
} mm_128;
typedef struct _struct_mm_256{
union{
float fv[8];
double dv[4];
uint64_t iv[4];
uint8_t bv[32];
};
} mm_256;
typedef struct {
mm_256 x;
mm_256 y;
mm_256 z;
} mm256_point_t;
extern void gf2_add(mm_256* a, mm_256* b, mm_256* r);
extern void gf2_mul(mm_256* a, mm_256* b, mm_256* r1, mm_256* r2);
extern void gf2_mod(mm_256* a1, mm_256* a2, mm_256* r);
extern void gf2_sqr(mm_256* a, mm_256* r1, mm_256* r2);
extern void gf2_mod_mul(mm_256* a, mm_256* b, mm_256* r);
extern void gf2_mod_sqr(mm_256* a, mm_256* r);
extern void gf2m_inv(mm_256* a, mm_256 *r);
extern void gf2m_inv_asm(mm_256* a, mm_256 *r);
extern void gf2_point_dbl(mm256_point_t* pa, mm256_point_t* pr, int a, int b);
extern void gf2_point_add(mm256_point_t* pa, mm256_point_t* pb, mm256_point_t* pr, int a, int b);
extern void gf2_point_mul(mm256_point_t* p, mm_256* k, mm256_point_t* q, int a, int b);
extern void gf2_point_mul_with_preset_key(mm256_point_t* p, mm256_point_t* q, int a, int b);
#endif

174
engines/zeromem/ec2m_kern.c Executable file
View File

@@ -0,0 +1,174 @@
#include "ec2m_kern.h"
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <malloc.h>
#include "util.h"
int sock_fd;
int init_netlink(int unit, int portId){
struct sockaddr_nl src_addr;
sock_fd=socket(PF_NETLINK, SOCK_RAW, unit);
if(sock_fd<0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = portId; /* self pid */
/* interested in group 1<<0 */
bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_addr)); //绑定netlink
if(sock_fd < 0)
return -1;
return 0;
}
int send_request(const int func, const void* msg, int mlen)
{
struct nlmsghdr *nlh = NULL;
struct iovec iov;
struct msghdr mhdr;
struct sockaddr_nl dest_addr;
struct ec2m_request_st req;
const int len = mlen + sizeof(struct ec2m_request_st);
req.func = func;
req.len = len;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
memset(&mhdr, 0, sizeof(mhdr));
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(len));
memset(nlh, 0, NLMSG_SPACE(len));
nlh->nlmsg_len = NLMSG_SPACE(len);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
memcpy((void*)NLMSG_DATA(nlh), &req, sizeof(req));
memcpy((void*)NLMSG_DATA(nlh) + sizeof(req), msg, mlen);
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
mhdr.msg_name = (void *)&dest_addr;
mhdr.msg_namelen = sizeof(dest_addr);
mhdr.msg_iov = &iov;
mhdr.msg_iovlen = 1;
sendmsg(sock_fd,&mhdr,0); //通过netlink发送消息
return OK;
}
int recv_response(void* buf, int len)
{
struct ec2m_response_st resp;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
struct msghdr mhdr;
struct sockaddr_nl dest_addr;
int buflen;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
memset(&mhdr, 0, sizeof(mhdr));
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
mhdr.msg_name = (void *)&dest_addr;
mhdr.msg_namelen = sizeof(dest_addr);
mhdr.msg_iov = &iov;
mhdr.msg_iovlen = 1;
buflen = recvmsg(sock_fd, &mhdr, 0);
if(buflen < 0){
fprintf(stderr, "invalid retval of recvmsg %d\n", buflen);
return buflen;
}
buflen -= NLMSG_HDRLEN;
assert(buflen >= sizeof(resp));
memcpy(&resp, NLMSG_DATA(nlh), sizeof(resp));
buflen -= sizeof(resp);
assert(buflen == len);
if (buflen > 0 && buf != NULL) {
memcpy(buf, NLMSG_DATA(nlh) + sizeof(resp), buflen);
}
/* printf("resp: %d, len: %d\n", resp.result, buflen); */
return resp.result;
}
int ec2m_kern_init()
{
int r;
r = init_netlink(NETLINK_ECC, getpid());
if (r < 0)
return r;
return 0;
}
void ec2m_kern_clean()
{
close(sock_fd);
}
int ec2m_import_key(mm_256* key)
{
int r;
/* printf("key: %016lx%016lx%016lx\n", key->iv[2], key->iv[1], key->iv[0]); */
r = send_request(REQ_IMPORT_KEY, key, sizeof(mm_256));
if (r < 0)
return r;
r = recv_response(NULL, 0);
if (r < 0)
return r;
return 0;
}
int ec2m_private_operation(mm256_point_t*p, mm256_point_t*q)
{
int r;
r = send_request(REQ_PRIVATE_OP, p, sizeof(mm256_point_t));
if (r < 0)
return r;
r = recv_response(q, sizeof(mm256_point_t));
if (r < 0)
return r;
return 0;
}

36
engines/zeromem/ec2m_kern.h Executable file
View File

@@ -0,0 +1,36 @@
#ifndef _EC2M_KERN_H_
#define _EC2M_KERN_H_
#define NETLINK_ECC 31
#define MAX_PAYLOAD 1024
#define REQ_IMPORT_KEY 1
#define REQ_PRIVATE_OP 2
#define OK 0
#define FAIL -1
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
#endif
#include "ec.h"
struct ec2m_request_st {
int func;
int len;
};
struct ec2m_response_st
{
int result;
};
extern int ec2m_kern_init(void);
extern void ec2m_kern_clean(void);
extern int ec2m_import_key(mm_256 *key);
extern int ec2m_private_operation(mm256_point_t*p, mm256_point_t*q);
#endif

104
engines/zeromem/ec_inv.c Executable file
View File

@@ -0,0 +1,104 @@
#include "ec.h"
#include "string.h"
#include "stdio.h"
int is_one(mm_256* a)
{
int i;
if (a->iv[0] != 1)
return 0;
for (i = 1; i < 4; i++) {
if (a->iv[i] != 0)
return 0;
}
return 1;
}
void shift_right(mm_256* a)
{
int i;
for (i = 0; i < 3; i++) {
a->iv[i] = (a->iv[i] >> 1) | (a->iv[i + 1] << 63);
}
a->iv[3] >>= 1;
}
void add(mm_256* a, mm_256*b)
{
int i;
for (i = 0; i < 4; i++) {
b->iv[i] = b->iv[i] ^ a->iv[i];
}
}
int deg(mm_256* a)
{
int cnt = 0;
int i;
uint64_t c;
for (i = 3; i >= 0; i--) {
if (a->iv[i] != 0) {
break;
}
}
cnt = i * 64;
c = a->iv[i];
while (c != 0) {
cnt ++;
c >>= 1;
}
return cnt;
}
void gf2m_inv(mm_256* a, mm_256 *r)
{
mm_256 b, c, u, v, f, t;
// b = 1
memset(&b, 0, sizeof(b));
b.iv[0] = 1;
// c = 0
memset(&c, 0, sizeof(c));
// u = a
u = *a;
// v = f
memset(&v, 0, sizeof(v));
memset(&f, 0, sizeof(f));
f.bv[0] = 0xc9;
f.bv[20] = 0x8;
v = f;
while (1) {
while ((u.bv[0] & 0x1) == 0) {
shift_right(&u);
if ((b.iv[0] & 0x1) != 0) {
add(&f, &b);
}
shift_right(&b);
}
if (is_one(&u))
break;
if (deg(&u) < deg(&v)) {
t = u;
u = v;
v = t;
t = b;
b = c;
c = t;
}
add(&v, &u);
add(&c, &b);
/* break; */
}
*r = b;
}

37
engines/zeromem/ec_main.c Executable file
View File

@@ -0,0 +1,37 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ec.h"
#include "test.h"
int main(int argc, char** argv){
/*
int i;
for(i = 0; i < argc; i++){
printf("arg %d: %s\n", i, argv[i]);
}
*/
char* cmd = argv[1];
if(!initDomainParameters(argc, argv)){
return 1;
}
if(strcmp(cmd, "testFieldArithmetic") == 0){
return testFieldArithmetic();
} else if(strcmp(cmd, "testPointArithmetic") == 0){
return testPointArithmetic();
} else if(strcmp(cmd, "testAES") == 0){
return testAES();
} else if(strcmp(cmd, "benchmark_ec2") == 0){
return benchmark_EC2();
} else if(strcmp(cmd, "testKernelEc2m") == 0){
return testKernelEc2m();
} else if(strcmp(cmd, "testMisc") == 0){
return testMisc();
} else if(strcmp(cmd, "testCycles") == 0){
return benchmark_cycles();
}
return 1;
}

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;
}

208
engines/zeromem/kernel/cba-ecc.c Executable file
View File

@@ -0,0 +1,208 @@
#include <linux/version.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/smp.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include "../ec2m_kern.h"
#include "../ec.h"
unsigned int sqr_table[1 << 16];
struct sock *sock_fd = NULL;
mm_256 gkey;
void init_sqr_table(void){
unsigned int i, j;
unsigned int t;
unsigned int n;
for(i = 0; i < sizeof(sqr_table) / sizeof(sqr_table[0]); i++){
t = 0;
j = i;
n = 16;
while(n-- > 0){
t = t << 2;
t |= ((j >> n) & 0x1);
}
sqr_table[i] = t;
}
}
void import_key(void* info) {
mm_256* key;
mm_256 tkey;
int cpu_id;
unsigned long irqs;
cpu_id = get_cpu();
local_irq_save(irqs);
//printk(KERN_INFO"%s on %d\n", __FUNCTION__, cpu_id);
key = (mm_256*)info;
// print value in dr0-3 previously
__asm__(
"movq %%dr0, %%rax\n\t"
"vmovq %%rax, %%xmm15\n\t"
"movq %%dr1, %%rax\n\t"
"vpinsrq $1, %%rax, %%xmm15, %%xmm15\n\t"
"movq %%dr2, %%rax\n\t"
"vmovq %%rax, %%xmm14\n\t"
"vinsertf128 $1, %%xmm14, %%ymm15, %%ymm15\n\t"
"vmovdqu %%ymm15, %0\n\t"
:"=m"(tkey)
:
: "rax", "memory"
);
//printk(KERN_INFO"debug regs:%016llx%016llx%016llx%016llx\n", tkey.iv[3], tkey.iv[2], tkey.iv[1], tkey.iv[0]);
//printk(KERN_INFO"key: %016llx%016llx%016llx\n", key->iv[2], key->iv[1], key->iv[0]);
gkey = *key;
__asm__(
"movq %0, %%dr0\n"
"movq %1, %%dr1\n"
"movq %2, %%dr2\n"
:
:"r"(key->iv[0]),"r"(key->iv[1]),"r"(key->iv[2])
: "memory"
);
local_irq_restore(irqs);
put_cpu();
}
int k_ec2m_import_key(mm_256* key)
{
import_key(key);
smp_call_function(import_key, key, 1);
return OK;
}
int k_ec2m_private_op(mm256_point_t* Q, mm256_point_t* P)
{
int cpu_id;
unsigned long irqs;
cpu_id = get_cpu();
local_irq_save(irqs);
//printk(KERN_INFO"%s on %d\n", __FUNCTION__, cpu_id);
__asm__ __volatile__(
"movq %%dr0, %%rax\n\t"
"vmovq %%rax, %%xmm15\n\t"
"movq %%dr1, %%rax\n\t"
"vpinsrq $1, %%rax, %%xmm15, %%xmm15\n\t"
"movq %%dr2, %%rax\n\t"
"vmovq %%rax, %%xmm14\n\t"
"vinsertf128 $1, %%xmm14, %%ymm15, %%ymm15\n\t"
:
:
: "rax", "memory"
);
gf2_point_mul_with_preset_key(P, Q, 1, 1);
local_irq_restore(irqs);
put_cpu();
return OK;
}
void nl_recv_msg(struct sk_buff* skb){
struct nlmsghdr *nlh;
struct sk_buff* out;
struct ec2m_request_st* req;
struct ec2m_response_st resp;
int pid;
int size;
char *buf;
int r;
nlh=(struct nlmsghdr*)skb->data;
size = nlmsg_len(nlh);// - NLMSG_HDRLEN;
pid = nlh->nlmsg_pid; /*pid of sending process */
/* printk(KERN_INFO "Netlink received a new msg from %d, size: %d\n", pid, size); */
buf = nlmsg_data(nlh);
req = (struct ec2m_request_st*)buf;
/* printk(KERN_INFO "got a request: %d, len: %d", req->func, req->len); */
switch (req->func) {
case REQ_IMPORT_KEY:
{
mm_256* key;
key = (mm_256*) (buf + sizeof(struct ec2m_request_st));
resp.result = k_ec2m_import_key(key);
size = sizeof(struct ec2m_response_st);
buf = kmalloc(size, GFP_KERNEL);
memcpy(buf, &resp, sizeof(resp));
break;
}
case REQ_PRIVATE_OP:
{
mm256_point_t* P;
mm256_point_t Q;
P = (mm256_point_t*) (buf + sizeof(struct ec2m_request_st));
resp.result = k_ec2m_private_op(&Q, P);
size = sizeof(struct ec2m_response_st) + sizeof(mm256_point_t);
buf = kmalloc(size, GFP_KERNEL);
memcpy(buf, &resp, sizeof(resp));
memcpy(buf + sizeof(resp), &Q, sizeof(Q));
break;
}
}
out = nlmsg_new(size, 0);
nlh = nlmsg_put(out, 0, 0, NLMSG_DONE, size, 0);
NETLINK_CB(out).dst_group = 0; /* not in mcast group */
memcpy(nlmsg_data(nlh), buf, size);
r = nlmsg_unicast(sock_fd, out, pid);
if (r < 0){
printk(KERN_INFO "forward msg to %d failed, err code %d\n", pid, r);
}
kfree(buf);
}
int init_netlink(void){
struct netlink_kernel_cfg cfg = {0};
cfg.input = nl_recv_msg;
sock_fd = netlink_kernel_create(&init_net, NETLINK_ECC, &cfg );
if(!sock_fd)
{
printk(KERN_ALERT "Error creating socket.\n");
return -1;
}
printk(KERN_ALERT "creating socket successfully.\n");
return 0;
}
int __init ecc_init(void) {
// init netlink
init_netlink();
init_sqr_table();
return 0;
}
void __exit ecc_exit(void) {
// netlink clean up
if(sock_fd != NULL)
netlink_kernel_release(sock_fd);
}
module_init(ecc_init);
module_exit(ecc_exit);
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,5 @@
#!/bin/bash
sudo rmmod ecc
sudo insmod ecc.ko
dmesg|tail

217
engines/zeromem/kernel_test.c Executable file
View File

@@ -0,0 +1,217 @@
#include <stdio.h>
#include <assert.h>
#include <openssl/bn.h>
#include <openssl/bio.h>
#include <openssl/ec.h>
#include <openssl/objects.h>
#include <openssl/obj_mac.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <string.h>
#include "kernel_test.h"
#include "ec.h"
#include "ec2m_kern.h"
#include "util.h"
#define _NR_sse_switch 312
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 */;
int testSSE(){
// try perform an simple packed add operation
mm_256 a, b, c;
syscall(_NR_sse_switch, 0);
a.iv[0] = 0;
a.iv[1] = 1;
b.iv[0] = 2;
b.iv[1] = 3;
__asm__ __volatile__ ("vmovdqu %0, %%ymm0" : : "m"(a));
__asm__ __volatile__ ("vmovdqu %0, %%ymm1" : : "m"(b));
__asm__ __volatile__ ("vaddpd %ymm0, %ymm1, %ymm1");
__asm__ __volatile__ ("vmovdqu %%ymm1, %0" : "=m"(c) :);
printf("%ld, %ld\n", c.iv[0], c.iv[1]);
//syscall(_NR_sse_switch, 0);
return 1;
}
void print_num(mm_256* m)
{
int i;
int nonzero = 0;
for (i = sizeof(mm_256) - 1; i >= 0; i--) {
if (!nonzero){
if (m->bv[i] != 0)
nonzero = 1;
else
continue;
}
printf("%02x", m->bv[i]);
}
if (!nonzero)
printf("0");
}
void print_point(mm256_point_t* p)
{
print_num(&p->x);
printf(", ");
print_num(&p->y);
printf(", ");
print_num(&p->z);
}
void print_ec_point(EC_POINT* p)
{
printf("(");
BN_print_fp(stdout, &p->X);
printf(":");
BN_print_fp(stdout, &p->Y);
printf(":");
BN_print_fp(stdout, &p->Z);
printf(")");
}
int testAPI()
{
int r;
int nid;
EC_KEY *key;
BIO *bio_out;
const BIGNUM* rkey;
const EC_GROUP* group;
const EC_POINT* ukey;
const EC_POINT* G, *pr;
BIGNUM* x, *y;
BN_CTX* ctx;
mm_256 mkey;
mm256_point_t mp, mq;
mm_256 z_;
init_sqr_table();
ctx = BN_CTX_new();
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
// open stdout as bio
bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
// get curve nid
/* nid = EC_curve_nist2nid("sect163k1"); */
nid = OBJ_sn2nid(SN_sect163k1);
// generate the key
key = EC_KEY_new_by_curve_name(nid);
assert(key != NULL);
r = EC_KEY_generate_key(key);
assert(r == 1);
// print key
EC_KEY_print(bio_out, key, 0);
// get group
group = EC_KEY_get0_group(key);
// get generator
G = EC_GROUP_get0_generator(group);
// get private key
rkey = EC_KEY_get0_private_key(key);
memset(&mkey, 0, sizeof(mkey));
memcpy(&mkey, rkey->d, rkey->top * sizeof(rkey->d[0]));
print_num(&mkey);
printf("\n");
// get the public key
ukey = EC_KEY_get0_public_key(key);
// init api
r = ec2m_kern_init();
assert(r == 0);
printf("ec2m init done.\n");
// import the private key
r = ec2m_import_key(&mkey);
assert(r == 0);
// calculate r=G*k
// r should be equal to the public key
EC_POINT_get_affine_coordinates_GF2m(group, G, x, y, ctx);
memset(&mq, 0, sizeof(mq));
memset(&mp, 0, sizeof(mp));
memcpy(&mp.x, x->d, sizeof(x->d[0]) * x->top);
memcpy(&mp.y, y->d, sizeof(y->d[0]) * y->top);
mp.z.iv[0] = 1;
bn_expand2(x, 3);
bn_expand2(y, 3);
gf2_point_mul(&mp, &mkey, &mq, 1, 1);
print_mm_point(&mq);
printf("\n");
r = ec2m_private_operation(&mp, &mq);
assert(r == 0);
print_mm_point(&mq);
printf("\n");
/* printf("inv(z): "); */
/* gf2m_inv(&mq.z, &z_); */
/* print_num(&z_); */
/* printf("\n"); */
/* gf2_mod_mul(&mq.x, &z_, &mq.x); */
/* gf2_mod_mul(&mq.y, &z_, &mq.y); */
/* gf2_mod_mul(&mq.z, &z_, &mq.z); */
/* print_mm_point(&mq); */
/* printf("\n"); */
pr = EC_POINT_new(group);
EC_POINT_mul(group, pr, NULL, G, rkey, ctx);
print_ec_point(pr);
printf("\n");
EC_POINT_get_affine_coordinates_GF2m(group, pr, x, y, ctx);
ec2m_kern_clean();
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return 0;
}
int main()
{
testSSE();
testAPI();
return 0;
}

6
engines/zeromem/kernel_test.h Executable file
View File

@@ -0,0 +1,6 @@
#ifndef _KERNEL_TEST_H_
#define _KERNEL_TEST_H_
extern int testSSE();
#endif

22
engines/zeromem/sys_ec2m.c Executable file
View File

@@ -0,0 +1,22 @@
#include <unistd.h>
#include "sys_ec2m.h"
int sys_ec2m_alloc(void)
{
return syscall(__NR_ec2m_alloc);
}
int sys_ec2m_free(int rid)
{
return syscall(__NR_ec2m_free, rid);
}
int sys_ec2m_setkey(int rid, mm_256* key, int a, int b)
{
return syscall(__NR_ec2m_setkey, rid, (void*)key, a, b);
}
int sys_ec2m_encrypt(int rid, mm256_point_t* bufin, mm256_point_t* bufout)
{
return syscall(__NR_ec2m_encrypt, rid, (void*)bufin, (void*)bufout);
}

16
engines/zeromem/sys_ec2m.h Executable file
View File

@@ -0,0 +1,16 @@
#ifndef _SYS_EC2M_H_
#define _SYS_EC2M_H_
#define __NR_ec2m_alloc 312
#define __NR_ec2m_free 313
#define __NR_ec2m_setkey 314
#define __NR_ec2m_encrypt 315
#include "ec.h"
extern int sys_ec2m_alloc(void);
extern int sys_ec2m_free(int rid);
extern int sys_ec2m_setkey(int rid, mm_256* key, int a, int b);
extern int sys_ec2m_encrypt(int rid, mm256_point_t* bufin, mm256_point_t* bufout);
#endif

1653
engines/zeromem/test.c Executable file

File diff suppressed because it is too large Load Diff

17
engines/zeromem/test.h Executable file
View File

@@ -0,0 +1,17 @@
#ifndef _TEST_H_
#define _TEST_H_
extern int initDomainParameters(int argc, char** argv);
extern int testFieldArithmetic();
extern int testPointArithmetic();
extern int testAES();
extern int testKernelEc2m();
extern int testMisc();
extern int testEC2M();
extern int benchmark_cycles();
extern int benchmark_EC2();
#endif

215
engines/zeromem/util.c Executable file
View File

@@ -0,0 +1,215 @@
#include <stdlib.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/objects.h>
#include "util.h"
unsigned int sqr_table[1 << 16];
void print_mm_256(mm_256* m){
/* printf("(%lu, %lu, %lu, %lu)", m->iv[3], m->iv[2], m->iv[1], m->iv[0]); */
BIGNUM *bn = BN_new();
mm256_to_bn(m, bn);
printf("%s", BN_bn2hex(bn));
}
void init_sqr_table(){
unsigned int i, j;
unsigned int t;
unsigned int n;
for(i = 0; i < sizeof(sqr_table) / sizeof(sqr_table[0]); i++){
t = 0;
j = i;
n = 16;
while(n-- > 0){
t = t << 2;
t |= ((j >> n) & 0x1);
}
sqr_table[i] = t;
}
}
void ec_point_init(ec_point_t *P) {
P->X = BN_new();
P->Y = BN_new();
P->Z = BN_new();
}
void ec_point_free(ec_point_t *P){
OPENSSL_free(P->X);
OPENSSL_free(P->Y);
OPENSSL_free(P->Z);
}
void bn_to_mm256(const BIGNUM* bn, mm_256* m){
memset(m, 0, sizeof(mm_256));
assert(bn->top <= 4);
int i;
for(i = 0; i < bn->top; i++){
m->iv[i] = bn->d[i];
}
}
void mm256_to_bn(const mm_256* m, BIGNUM* bn){
BN_zero(bn);
int i = 4;
while(i-- > 0){
BN_lshift(bn, bn, 64);
BN_add_word(bn, m->iv[i]);
}
}
void bn_point_to_mm_point(const ec_point_t* src, mm256_point_t* dst){
bn_to_mm256(src->X, &dst->x);
bn_to_mm256(src->Y, &dst->y);
bn_to_mm256(src->Z, &dst->z);
}
void EC_POINT_to_mm_point(const ec_point_st* src, mm256_point_t* dst)
{
bn_to_mm256(&src->X, &dst->x);
bn_to_mm256(&src->Y, &dst->y);
bn_to_mm256(&src->Z, &dst->z);
}
void mm_point_to_EC_POINT(const mm256_point_t* src, ec_point_st* dst)
{
mm256_to_bn(&(src->x), &dst->X);
mm256_to_bn(&(src->y), &dst->Y);
mm256_to_bn(&(src->z), &dst->Z);
}
void mm_point_to_bn_point(const mm256_point_t* src, ec_point_t* dst){
mm256_to_bn(&(src->x), dst->X);
mm256_to_bn(&(src->y), dst->Y);
mm256_to_bn(&(src->z), dst->Z);
}
int cmp_mm_256_with_bn(mm_256* a, BIGNUM* bn){
mm_256 b;
bn_to_mm256(bn, &b);
return memcmp(a, &b, sizeof(mm_256));
}
int cmp_mm_point_with_bn_point(mm256_point_t* a, ec_point_t* b){
mm256_point_t t;
bn_point_to_mm_point(b, &t);
return memcmp(a, &t, sizeof(mm256_point_t));
}
void print_bn_point(ec_point_t* p){
char *px, *py, *pz;
px = BN_bn2str(p->X);
py = BN_bn2str(p->Y);
pz = BN_bn2str(p->Z);
printf("(%s: %s: %s)", px, py, pz);
OPENSSL_free(px);
OPENSSL_free(py);
OPENSSL_free(pz);
}
void print_EC_POINT(ec_point_st*p)
{
char *px, *py, *pz;
if(p->X.d)
px = BN_bn2str(&p->X);
else
px = "";
if(p->Y.d)
py = BN_bn2str(&p->Y);
else
py = "";
if(p->Z.d)
pz = BN_bn2str(&p->Z);
else
pz = "";
printf("(%s: %s: %s)", px, py, pz);
if(p->X.d)
OPENSSL_free(px);
if(p->Y.d)
OPENSSL_free(py);
if(p->Z.d)
OPENSSL_free(pz);
}
void print_mm_point(mm256_point_t* p){
ec_point_t t;
ec_point_init(&t);
mm_point_to_bn_point(p, &t);
print_bn_point(&t);
ec_point_free(&t);
}
void print_affine_bn_point(ec_point_t* p){
char *px, *py;
px = BN_bn2str(p->X);
py = BN_bn2str(p->Y);
printf("(%s, %s)", px, py);
OPENSSL_free(px);
OPENSSL_free(py);
}
void print_affine_mm_point(mm256_point_t* p){
ec_point_t t;
ec_point_init(&t);
mm_point_to_bn_point(p, &t);
print_affine_bn_point(&t);
ec_point_free(&t);
}
void printHex(uint8_t* str, uint32_t len){
uint32_t i;
for(i = 0; i < len; i++){
printf("%02x", str[i]);
}
}
void save_ymm_group(uint8_t* buf){
__asm__("vmovdqu %ymm0, (%rdi)\n\t"
"vmovdqu %ymm1, 32(%rdi)\n\t"
"vmovdqu %ymm2, 64(%rdi)\n\t"
"vmovdqu %ymm3, 96(%rdi)\n\t"
"vmovdqu %ymm4, 128(%rdi)\n\t"
"vmovdqu %ymm5, 160(%rdi)\n\t"
"vmovdqu %ymm6, 192(%rdi)\n\t"
"vmovdqu %ymm7, 224(%rdi)\n\t"
"vmovdqu %ymm8, 256(%rdi)\n\t"
"vmovdqu %ymm9, 288(%rdi)\n\t"
"vmovdqu %ymm10, 320(%rdi)\n\t"
"vmovdqu %ymm11, 352(%rdi)\n\t"
"vmovdqu %ymm12, 384(%rdi)\n\t"
"vmovdqu %ymm13, 416(%rdi)\n\t"
"vmovdqu %ymm14, 448(%rdi)\n\t"
"vmovdqu %ymm15, 480(%rdi)\n\t"
);
__asm__("" ::: "memory");
}
void load_ymm_group(uint8_t* buf){
__asm__("vmovdqu (%rdi), %ymm0\n\t"
"vmovdqu 32(%rdi), %ymm1\n\t"
"vmovdqu 64(%rdi), %ymm2\n\t"
"vmovdqu 96(%rdi), %ymm3\n\t"
"vmovdqu 128(%rdi), %ymm4\n\t"
"vmovdqu 160(%rdi), %ymm5\n\t"
"vmovdqu 192(%rdi), %ymm6\n\t"
"vmovdqu 224(%rdi), %ymm7\n\t"
"vmovdqu 256(%rdi), %ymm8\n\t"
"vmovdqu 288(%rdi), %ymm9\n\t"
"vmovdqu 320(%rdi), %ymm10\n\t"
"vmovdqu 352(%rdi), %ymm11\n\t"
"vmovdqu 384(%rdi), %ymm12\n\t"
"vmovdqu 416(%rdi), %ymm13\n\t"
"vmovdqu 448(%rdi), %ymm14\n\t"
"vmovdqu 480(%rdi), %ymm15\n\t"
);
__asm__("" ::: "memory");
}
void dummy_print(const char* format, ...){
}

82
engines/zeromem/util.h Executable file
View File

@@ -0,0 +1,82 @@
#ifndef _UTIL_H_
#define _UTIL_H_
#include "ec.h"
#include <openssl/bn.h>
//#define DEBUG
//#define PRINT_DEC
#ifdef PRINT_DEC
#define BN_bn2str(bn) BN_bn2dec(bn)
#else
#define BN_bn2str(bn) BN_bn2hex(bn)
#endif
extern void dummy_print(const char* format, ...);
#ifdef DEBUG
#define debug printf
#else
#define debug dummy_print
#endif
extern unsigned int sqr_table[1 << 16];
#define rdtsc_begin(hi, lo)\
asm volatile ("CPUID\n\t"\
"RDTSCP\n\t"\
"movq %%rdx, %0\n\t"\
"movq %%rax, %1\n\t" : "=r" (hi), "=r" (lo) :: "%rax", "%rbx", "%rcx", "%rdx");
#define rdtsc_end(hi, lo)\
asm volatile ("RDTSCP\n\t"\
"movq %%rdx, %0\n\t"\
"movq %%rax, %1\n\t"\
"CPUID\n\t" : "=r" (hi), "=r" (lo) :: "%rax", "%rbx", "%rcx", "%rdx");
typedef struct {
BIGNUM *X;
BIGNUM *Y;
BIGNUM *Z;
} ec_point_t;
typedef struct{
const struct 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_st /* EC_POINT */;
extern void init_sqr_table();
extern void bn_to_mm256(const BIGNUM* bn, mm_256 *m);
extern void mm256_to_bn(const mm_256 *m, BIGNUM* bn);
extern void bn_point_to_mm_point(const ec_point_t* src, mm256_point_t* dst);
extern void mm_point_to_bn_point(const mm256_point_t* src, ec_point_t* dst);
extern void EC_POINT_to_mm_point(const ec_point_st* src, mm256_point_t* dst);
extern void mm_point_to_EC_POINT(const mm256_point_t* src, ec_point_st* dst);
extern void ec_point_init(ec_point_t *P);
extern void ec_point_free(ec_point_t *P);
extern int cmp_mm_256_with_bn(mm_256* a, BIGNUM* bn);
extern int cmp_mm_point_with_bn_point(mm256_point_t* a, ec_point_t* b);
extern void print_affine_bn_point(ec_point_t* p);
extern void print_affine_mm_point(mm256_point_t* p);
extern void print_bn_point(ec_point_t* p);
extern void print_mm_point(mm256_point_t* p);
extern void print_EC_POINT(ec_point_st* p);
extern void printHex(uint8_t* str, uint32_t len);
extern void save_ymm_group(uint8_t* buf);
extern void load_ymm_group(uint8_t* buf);
#endif