From 0c5112c41d2e08a388ad8a91a51dcc126035cea5 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:08:52 +0000 Subject: [PATCH 01/18] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20summer2022=E5=9F=BA?= =?UTF-8?q?=E4=BA=8EsecGear=E5=AE=9E=E7=8E=B0=E9=83=A8=E5=88=86=E5=9B=BD?= =?UTF-8?q?=E5=AF=86=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.keep" | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/.keep" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/.keep" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/.keep" new file mode 100644 index 0000000..e69de29 -- Gitee From d6816edf9cc21b42975644d4b7cc352c0503cdf8 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:50:00 +0000 Subject: [PATCH 02/18] report Signed-off-by: wangxiaoxi1 --- ...23\351\241\271\346\212\245\345\221\212.pdf" | Bin 0 -> 215330 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/\347\216\213\345\260\217\346\272\252-22b970374-\347\273\223\351\241\271\346\212\245\345\221\212.pdf" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/\347\216\213\345\260\217\346\272\252-22b970374-\347\273\223\351\241\271\346\212\245\345\221\212.pdf" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/\347\216\213\345\260\217\346\272\252-22b970374-\347\273\223\351\241\271\346\212\245\345\221\212.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..87cc2a7482a6d2363667eee046596bd54ceb64d6 GIT binary patch literal 215330 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

M|-vc(M$2s~z%9&i9wU*3R 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

cEdD6i=K{K$Rurzn> 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
p2MJyPU)DQ2U^Ee%uy&L@g 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⁢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%0D*|D4pQH zE34}1U`oOyZg1!Ezp2pvWgY!rC24PdrpuJ^RE~yGdtil@8NG43p*Rf zZ)0I*W@mZT?fsR<%)-vX{@eIKN>|X%`3H}k`Jd;4q8$Fg1AyWc{@w>G7aQ~M^I!#~ zO8h=PRxU2)-^T({-2Q$p3n!@1ztsSQfwueK`vqYDQ0T+o#saz@08r4y-!YKr_xV&|{%cNrI1=`6d3^^b>uvx}jV%O4wrm4zL^!iqpiDW)L){{V#6U$FoH literal 0 HcmV?d00001 -- Gitee From 45d5df46875e49ed312a059ef478a91de15ba4a8 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:50:20 +0000 Subject: [PATCH 03/18] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20C=5Forigin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../C_origin/.keep" | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/.keep" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/.keep" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/.keep" new file mode 100644 index 0000000..e69de29 -- Gitee From 2484deea0fba3701566019ca6fb1e13dfdf6b84f Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:50:39 +0000 Subject: [PATCH 04/18] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20include?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../C_origin/include/.keep" | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/.keep" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/.keep" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/.keep" new file mode 100644 index 0000000..e69de29 -- Gitee From 50cb30dfd0da797ea042d0cc298fe6d5643af573 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:51:20 +0000 Subject: [PATCH 05/18] include Signed-off-by: wangxiaoxi1 --- .../C_origin/include/include/common_utils.h" | 69 +++ .../C_origin/include/include/ec.h" | 545 ++++++++++++++++++ 2 files changed, 614 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/common_utils.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/ec.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/common_utils.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/common_utils.h" new file mode 100644 index 0000000..9251edc --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/common_utils.h" @@ -0,0 +1,69 @@ +#ifndef SECGEAR_SM_COMMON_UTILS +#define SECGEAR_SM_COMMON_UTILS + +#include +#define debugPrint (printf("%s: %s: %d\n",__FILE__,__FUNCTION__,__LINE__),fflush(stdout),1) + +typedef __uint8_t uint8; +typedef __uint16_t uint16; +typedef __uint32_t uint32; +typedef __uint64_t uint64; + +#define CONCAT_8x4(x0, x1, x2, x3) ((((uint32)(x0) << 8 | (x1)) << 8 | (x2)) << 8 | (x3)) // X = (x0 || x1 || x2 || x3) +#define CONCAT_16x2(x0, x1) ((uint32)(x0) << 16 | (x1)) // X = (x0 || x1) +#define EXTRACT_8_32(X, i) (((X) >> (((i) ^ 3) << 3)) & 0xFF) // X = (x0 || x1 || x2 || x3) +#define EXTRACT_16_32(X, i) (((X) >> (((i) ^ 1) << 4)) & 0xFFFF) // X = (x0 || x1) +#define EXTRACT_16H_31(X) (((X) >> 15) & 0xFFFF) // Higher 16-bit from 31-bit +#define EXTRACT_16L_31(X) ((X) & 0xFFFF) // Lower 16-bit from 31-bit + +#define ROTATE(a, n) (((a) << (n)) | (((a) & 0xFFFFFFFF) >> ((32 - (n)) & 31))) +#define ROTATE_31(a, n) ((((a) << (n)) & 0x7FFFFFFF) | (((a) & 0x7FFFFFFF) >> (31 - (n)))) + +#define GET_BIT_VALUE_32(x, i) (((x) >> (31 - (i))) & 1) + +const uint32 PREFIX_MASK_32[32] = { + 0x00000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE +}; + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/ec.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/ec.h" new file mode 100644 index 0000000..56adbe7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/include/include/ec.h" @@ -0,0 +1,545 @@ +#include /* BigNum */ +#include "common_utils.h" + +typedef struct ec_point_st { + BIGNUM *X; + BIGNUM *Y; + int is_infinity; +} EC_POINT; + +int EC_POINT_init(EC_POINT *point) { + point->X = BN_new(); + point->Y = BN_new(); + point->is_infinity = 0; + if (point->X == NULL || point->Y == NULL) { + BN_free(point->X); + BN_free(point->Y); + return 0; + } + return 1; +} + +EC_POINT *EC_POINT_new() { + EC_POINT *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_POINT_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_POINT_setXY(EC_POINT *r, const BIGNUM *x, const BIGNUM *y) { + if (r == NULL) { + return 0; + } + if (!BN_copy(r->X, x) || !(BN_copy(r->Y, y))) { + return 0; + } + return 1; +} + +const EC_POINT *EC_point_infinity() { + static const EC_POINT const_infinity = { NULL, NULL, 1 }; + return &const_infinity; +} + +int EC_POINT_is_infinity(const EC_POINT *point) { + return point->is_infinity; +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest == NULL) { + return 0; + } + if (EC_POINT_is_infinity(src)) { + dest->is_infinity = 1; + } + else{ + dest->is_infinity = 0; + if (!BN_copy(dest->X, src->X) || !BN_copy(dest->Y, src->Y)) return 0; + } + return 1; +} + +#define NORMAL 0x1 +#define COMPRESS 0x2 +#define MIX 0x4 + +int EC_POINT_ecp2bin(uint8 *out, const EC_POINT *point, int p_bytes, int flag) { + uint8 PC; + uint8 *p = out, *buf; + int i; + buf = malloc(p_bytes); + if (EC_POINT_is_infinity(point)) { + return 0; + } + if (flag == NORMAL) { + PC = 0x04; + *(p++) = PC; + if (!BN_bn2binpad(point->X, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + if (!BN_bn2binpad(point->Y, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_bin2ecp(EC_POINT *point, const uint8 *src, int p_bytes) { + if (point == NULL) { + return 0; + } + uint8 PC = *src; + const uint8 *data = src + 1; + uint8 *buf; + int i; + if (PC == 0x04) { + if (!BN_bin2bn(data, p_bytes, point->X) + || !BN_bin2bn(data+p_bytes, p_bytes, point->Y)) { + return 0; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_ecp2bin_normal(uint8 *out, const EC_POINT *point, int p_bytes) { + return EC_POINT_ecp2bin(out, point, p_bytes, NORMAL); +} + +// int EC_POINT_ecp2bin_compressed(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, COMPRESS); +// } + +// int EC_POINT_ecp2bin_mix(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, MIX); +// } + +typedef struct ec_group_st { + EC_POINT *generator; /* point G */ + BIGNUM *order; /* n */ + BIGNUM *cofactor; /* h */ + BIGNUM *field; /* module p */ + BIGNUM *a, *b; /* ECC parameter */ +} EC_GROUP; + +int EC_GROUP_init(EC_GROUP *group) { + group->generator = EC_POINT_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->generator == NULL || group->b == NULL) { + free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +EC_GROUP *EC_GROUP_new() { + EC_GROUP *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_GROUP_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest == NULL) { + return 0; + } + if (dest == src) { + return 1; + } + if (!EC_POINT_copy(dest->generator, src->generator) + || !BN_copy(dest->order, src->order) + || !BN_copy(dest->cofactor, src->cofactor) + || !BN_copy(dest->field, src->field) + || !BN_copy(dest->a, src->a) + || !BN_copy(dest->b, src->b)) { + return 0; + } + return 1; +} + +int EC_GROUP_set_param(EC_GROUP *group, const BIGNUM *field, const BIGNUM *a, const BIGNUM *b, const BIGNUM *order, const BIGNUM *cofactor, const EC_POINT *point) { + if (group == NULL) { + return 0; + } + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->generator = EC_POINT_new(); + if (group->cofactor == NULL + || group->generator == NULL) { + return 0; + } + if (!BN_copy(group->field, field) + || !BN_copy(group->a, a) + || !BN_copy(group->b, b) + || !BN_copy(group->order, order) + || !BN_copy(group->cofactor, cofactor) + || !EC_POINT_copy(group->generator, point)) { + return 0; + } + return 1; +} + +int EC_POINT_double(EC_POINT *r, const EC_POINT *a, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, EC_point_infinity()); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y)) { + goto done; + } + if (!BN_set_word(bn_value_3, 3) + || !BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_sqr(r->X, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_lshift1_quick(tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, r->X, tmp, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_add(EC_POINT *r, const EC_POINT *a, const EC_POINT *b, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *bx, *by, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (a == b) { + return EC_POINT_double(r, a, group); + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_infinity(b)) { + return EC_POINT_copy(r, a); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + bx = BN_CTX_get(ctx); + by = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y) + || !BN_copy(bx, b->X) + || !BN_copy(by, b->Y)) { + goto done; + } + if (BN_cmp(ax, bx) == 0) { + if (!BN_mod_add_quick(tmp, ay, by, p)) { + goto done; + } + if (BN_is_zero(tmp) + || !EC_POINT_copy(r, EC_point_infinity())) { + goto done; + } + if (!BN_set_word(bn_value_3, 3)) { + goto done; + } + if (!BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + else { + if (!BN_mod_sub_quick(lnum, by, ay, p)) { + goto done; + } + if (!BN_mod_sub_quick(ldeno, bx, ax, p)) { + goto done; + } + if (!BN_mod_inverse(ldeno, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + if (!BN_mod_sqr(tmp, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(tmp, tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, tmp, bx, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_mul(EC_POINT *r, const EC_POINT *a, const BIGNUM *b, const EC_GROUP *group) { + if (r == NULL) { + return 0; + } + if (BN_is_negative(b)) { + EC_POINT *_a = EC_POINT_new(); + BIGNUM *_b = BN_new(); + if (!EC_POINT_copy(_a, a) + || !BN_copy(_b, b) + || !BN_mod_sub_quick(_a->Y, group->field, _a->Y, group->field)) { + return 0; + } + BN_set_negative(_b, 0); + return EC_POINT_mul(r, _a, _b, group); + } + if (!EC_POINT_copy(r, EC_point_infinity())){ + return 0; + } + int bits = BN_num_bits(b); + for (int i = bits-1; i >= 0; --i) { + if (!EC_POINT_double(r, r, group)) { + return 0; + } + if (BN_is_bit_set(b, i)) { + if (!EC_POINT_add(r, r, a, group)) { + return 0; + } + } + } + return 1; +} + +/* + * Only for curve y^2 = x^3 + ax + b. + * Please check infinity before calling. + */ +int EC_POINT_on_curve_simple(const EC_POINT *point, const EC_GROUP *group) { + if (point == NULL || group == NULL) { + return 0; + } + if (EC_POINT_is_infinity(point)) { + return 1; + } + int ret = 0; + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *lhs, *rhs; + EC_POINT *Nq; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return ret; + } + BN_CTX_start(ctx); + p = group->field; + a = group->a; + b = group->b; + x = point->X; + y = point->Y; + lhs = BN_CTX_get(ctx); + rhs = BN_CTX_get(ctx); + Nq = EC_POINT_new(); + if (p == NULL + || a == NULL + || b == NULL + || x == NULL + || y == NULL + || rhs == NULL + || Nq == NULL) { + return ret; + } + if (!BN_mod_mul(lhs, y, y, p, ctx) + || !BN_mod_mul(rhs, x, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, a, p) + || !BN_mod_mul(rhs, rhs, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, b, p) + || !EC_POINT_mul(Nq, point, group->order, group)) { + return ret; + } + if (BN_cmp(lhs, rhs) != 0 + || !EC_POINT_is_infinity(Nq)) { + return ret; + } + ret = 1; + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +typedef struct ec_key_st { + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; +} EC_KEY; + +int EC_KEY_init(EC_KEY *key) { + key->group = EC_GROUP_new(); + key->pub_key = EC_POINT_new(); + key->priv_key = BN_new(); + if (key->group == NULL + || key->pub_key == NULL + || key->priv_key == NULL) { + free(key->group); + free(key->pub_key); + BN_free(key->priv_key); + return 0; + } + return 1; +} + +EC_KEY *EC_KEY_new() { + EC_KEY *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_KEY_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + if (!EC_GROUP_copy(key->group, group)) { + return 0; + } + return 1; +} + +int EC_KEY_set_priv_key(EC_KEY *key, const BIGNUM *priv_key) { + BIGNUM *tmp; + tmp = BN_dup(priv_key); + if (tmp == NULL) { + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = tmp; + return 1; +} + +int EC_KEY_generate_pub_key(EC_KEY *key) { + return EC_POINT_mul(key->pub_key, key->group->generator, key->priv_key, key->group); +} + +const BIGNUM *EC_KEY_get_priv_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_generate_key() {} -- Gitee From 2f59543df460afee5758ece3612dceea27189ba7 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:51:56 +0000 Subject: [PATCH 06/18] sm2 Signed-off-by: wangxiaoxi1 --- .../C_origin/sm2/sm2.h" | 288 ++++++++++++ .../C_origin/sm2/sm2_crypt.h" | 257 +++++++++++ .../C_origin/sm2/sm2_crypt_test.c" | 137 ++++++ .../C_origin/sm2/sm2_exchange.h" | 436 ++++++++++++++++++ .../C_origin/sm2/sm2_exchange_test.c" | 93 ++++ .../C_origin/sm2/sm2_sign.h" | 259 +++++++++++ .../C_origin/sm2/sm2_sign_test.c" | 91 ++++ .../C_origin/sm2/sm2_tests.h" | 236 ++++++++++ .../C_origin/sm2/sm2alltest.c" | 87 ++++ 9 files changed, 1884 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_crypt.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_crypt_test.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_exchange.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_exchange_test.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign_test.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_tests.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2alltest.c" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2.h" new file mode 100644 index 0000000..97e051f --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2.h" @@ -0,0 +1,288 @@ +#ifndef SECGEAR_SM2_H +#define SECGEAR_SM2_H + +/* + * Ref: + * GB/T 32918.1-2016 + * GB/T 32918.2-2016 + * GB/T 32918.3-2016 + * GB/T 32918.4-2016 + * GB/T 32918.5-2017 + */ + +#include +#include "../include/common_utils.h" +#include "../include/ec.h" +#include "../sm3/sm3.h" +#define SM2ERR(msg) fprintf(stderr,msg);goto err; +/* + * export C_INCLUDE_PATH="/PATH/TO/OPENSSL/include"(/opt/homebrew/Cellar/openssl@1.1/1.1.1m/include) + * export CPLUS_INCLUDE_PATH="/PATH/TO/OPENSSL/include" + * export LIBRARY_PATH="/PATH/TO/OPENSSL/lib" + */ + +/* Parameters */ +/* EC: y^2 = x^3 + ax + b */ + +#define SM2_PARAM_CBLOCK 32 +#define SM2_PARAM_LBLOCK (SM2_PARAM_CBLOCK/4) + +const uint8 SM2_P[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; +const uint8 SM2_A[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, +}; +const uint8 SM2_B[SM2_PARAM_CBLOCK] = { + 0x28, 0xE9, 0xFA, 0x9E, + 0x9D, 0x9F, 0x5E, 0x34, + 0x4D, 0x5A, 0x9E, 0x4B, + 0xCF, 0x65, 0x09, 0xA7, + 0xF3, 0x97, 0x89, 0xF5, + 0x15, 0xAB, 0x8F, 0x92, + 0xDD, 0xBC, 0xBD, 0x41, + 0x4D, 0x94, 0x0E, 0x93, +}; +const uint8 SM2_N[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x72, 0x03, 0xDF, 0x6B, + 0x21, 0xC6, 0x05, 0x2B, + 0x53, 0xBB, 0xF4, 0x09, + 0x39, 0xD5, 0x41, 0x23, +}; +const uint8 SM2_XG[SM2_PARAM_CBLOCK] = { + 0x32, 0xC4, 0xAE, 0x2C, + 0x1F, 0x19, 0x81, 0x19, + 0x5F, 0x99, 0x04, 0x46, + 0x6A, 0x39, 0xC9, 0x94, + 0x8F, 0xE3, 0x0B, 0xBF, + 0xF2, 0x66, 0x0B, 0xE1, + 0x71, 0x5A, 0x45, 0x89, + 0x33, 0x4C, 0x74, 0xC7, +}; +const uint8 SM2_YG[SM2_PARAM_CBLOCK] = { + 0xBC, 0x37, 0x36, 0xA2, + 0xF4, 0xF6, 0x77, 0x9C, + 0x59, 0xBD, 0xCE, 0xE3, + 0x6B, 0x69, 0x21, 0x53, + 0xD0, 0xA9, 0x87, 0x7C, + 0xC6, 0x2A, 0x47, 0x40, + 0x02, 0xDF, 0x32, 0xE5, + 0x21, 0x39, 0xF0, 0xA0, +}; + +typedef struct sm2_sig_st { + BIGNUM *r; + BIGNUM *s; +} SM2_SIG; + +int SM2_SIG_init(SM2_SIG *sig) { + sig->r = BN_new(); + sig->s = BN_new(); + if (sig->r == NULL || sig->s == NULL) { + BN_free(sig->r); + BN_free(sig->s); + return 0; + } + return 1; +} + +SM2_SIG *SM2_SIG_new() { + SM2_SIG *ret; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!SM2_SIG_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int sm2_compute_z(uint8 *out, const uint8 *id, const size_t idlen, const EC_KEY *key){ + /* ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */ + uint16 entlen = idlen << 3; + // printf("entlen: %04X\n", entlen); + uint8 e_bytes, *buf; + int p_bytes; + SM3_CTX c; + sm3_init(&c); + // debugPrint; + if (idlen > (UINT16_MAX >> 3)) { + SM2ERR("SM2_compute_z(): idlen too large!\n"); + } + e_bytes = entlen >> 8; + // printf("ENTL_H: %02X\n", e_bytes); + sm3_update(&c, &e_bytes, 1); + e_bytes = entlen & 0xFF; + // printf("ENTL_L: %02X\n", e_bytes); + sm3_update(&c, &e_bytes, 1); + // printf("ID_A: "); + // for (int i=0; igroup->field); + // debugPrint; + buf = malloc(p_bytes); + // debugPrint; + if (!BN_bn2binpad(key->group->a, buf, p_bytes)) { + goto err; + } + // printf("a: "); + // for (int i=0; igroup->b, buf, p_bytes)) { + goto err; + } + // printf("b: "); + // for (int i=0; igroup->generator->X, buf, p_bytes)) { + goto err; + } + // printf("XG: "); + // for (int i=0; igroup->generator->Y, buf, p_bytes)) { + goto err; + } + // printf("YG: "); + // for (int i=0; ipub_key->X, buf, p_bytes) < 0) { + goto err; + } + // printf("XA: "); + // for (int i=0; ipub_key->Y, buf, p_bytes) < 0) { + goto err; + } + // printf("YA: "); + // for (int i=0; i> 3)) { + return 0; + } + } + return 1; +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_crypt.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_crypt.h" new file mode 100644 index 0000000..14928f1 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_crypt.h" @@ -0,0 +1,257 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.4-2016 + */ + +/* Encrypt */ + +int sm2_encrypt(uint8 *out, const uint8 *M, const uint64 klen, const EC_KEY *key) { + SM3_CTX c; + BIGNUM *n, *k, *h, *x_2, *y_2; + EC_POINT *G, *C1, *S, *PB, *tmp_point; + EC_GROUP *group; + uint8 *_C1, *_C2, *_C3, *t, *buf; + size_t C1len, MlenCBLOCK, buflen, i; + int p_bytes; + group = key->group; + n = group->order; + h = group->cofactor; + G = group->generator; + PB = key->pub_key; + x_2 = BN_new(); + y_2 = BN_new(); + k = BN_new(); + C1 = EC_POINT_new(); + tmp_point = EC_POINT_new(); + S = EC_POINT_new(); + if (group == NULL + || n == NULL + || h == NULL + || k == NULL + || G == NULL + || S == NULL + || PB == NULL) { + return 0; + } + p_bytes = BN_num_bytes(group->field); + MlenCBLOCK = klen >> 3; + C1len = (p_bytes << 1 | 1); + buflen = p_bytes << 1; + _C1 = malloc(C1len); + _C2 = malloc(MlenCBLOCK); + _C3 = malloc(SM3_DIGEST_LENGTH); + buf = malloc(buflen); + t = malloc(MlenCBLOCK); + if (t == NULL) { + goto err; + } + for (;;) { + /* A1: k = rand(1, n-1) */ + do { + if (!BN_rand_range(k, n)) { + goto err; + } + } while(BN_is_zero(k)); + #ifdef GBT32918_4_2016_A2_TEST /* For GB/T 32918.4-2016 A.2 test */ + if (p_bytes * 8 == 192) { + BN_hex2bn(&k, "384F30353073AEECE7A1654330A96204D37982A3E15B2CB5"); + /* FP-192 */ + } + else { + /* FP-256 */ + BN_hex2bn(&k, "4C62EEFD6ECFC2B95B92FD6C3D9575148AFA17425546D49018E5388D49DD7B4F"); + } + #endif + #ifdef GBT32918_5_2017_TEST + BN_hex2bn(&k, "59276E27D506861A16680F3AD9C02DCCEF3CC1FA3CDBE4CE6D54B80DEAC1BC21"); + #endif + printf("k: %s\n", BN_bn2hex(k)); + /* A2: C1 = [k]G = (x1, y1), C1 -> bytes */ + if (!EC_POINT_mul(C1, G, k, group) + || !EC_POINT_ecp2bin_normal(_C1, C1, p_bytes)) { + goto err; + } + printf("C1: (%s, \n\t%s)\n", BN_bn2hex(C1->X), BN_bn2hex(C1->Y)); + printf("C1 bin: "); + for (int i=0; i bytes */ + if (!EC_POINT_mul(tmp_point, PB, k, group)) { + goto err; + } + x_2 = tmp_point->X; + y_2 = tmp_point->Y; + printf("(x2, y2): (%s, \n\t%s)\n", BN_bn2hex(x_2), BN_bn2hex(y_2)); + /* A5: t = KDF(x2 || y2, klen), if t == 0, goto A1 */ + printf("klen: %llu\n", klen); + if (!BN_bn2binpad(x_2, buf, p_bytes) + || !BN_bn2binpad(y_2, buf+p_bytes, p_bytes) + || !sm2_KDF(t, buf, buflen, klen)) { + goto err; + } + for (i = 0; i < MlenCBLOCK; ++i) { + if (t[i]) { + goto A6; + } + } + } + /* A6: C2 = M ^ t */ + A6: + printf("t: "); + for (int i=0; igroup; + h = group->cofactor; + dB = key->priv_key; + x_2 = BN_new(); + y_2 = BN_new(); + C1 = EC_POINT_new(); + tmp_point = EC_POINT_new(); + S = EC_POINT_new(); + if (group == NULL + || h == NULL + || x_2 == NULL + || y_2 == NULL + || dB == NULL + || S == NULL) { + return 0; + } + p_bytes = BN_num_bytes(group->field); + MlenCBLOCK = klen >> 3; + C1len = (p_bytes << 1 | 1); + buflen = p_bytes << 1; + _C1 = malloc(C1len); + _C2 = malloc(MlenCBLOCK); + _C3 = malloc(SM3_DIGEST_LENGTH); + u = malloc(SM3_DIGEST_LENGTH); + buf = malloc(buflen); + t = malloc(MlenCBLOCK); + if (t == NULL) { + goto err; + } + /* C = C1 || C3 || C2 */ + if (!memcpy(_C1, C, C1len) + || !memcpy(_C2, C+C1len+SM3_DIGEST_LENGTH, MlenCBLOCK) + || !memcpy(_C3, C+C1len, SM3_DIGEST_LENGTH)) { + goto err; + } + /* B1: C -> C1, check if C1 on the curve */ + if (!EC_POINT_bin2ecp(C1, _C1, p_bytes) + || !EC_POINT_on_curve_simple(C1, group)) { + goto err; + } + /* B2: S = [h]C1, if S == O, goto err */ + if (!EC_POINT_mul(S, C1, h, group) + || EC_POINT_is_infinity(S)) { + goto err; + } + /* B3: [dB]C1 = (x2, y2), x2, y2 -> bytes */ + if (!EC_POINT_mul(tmp_point, C1, dB, group)) { + goto err; + } + x_2 = tmp_point->X; + y_2 = tmp_point->Y; + printf("(x2, y2): (%s, \n\t%s)\n", BN_bn2hex(x_2), BN_bn2hex(y_2)); + /* B4: t = KDF(x2 || y2, klen), if t = 0, goto err */ + if (!BN_bn2binpad(x_2, buf, p_bytes) + || !BN_bn2binpad(y_2, buf+p_bytes, p_bytes) + || !sm2_KDF(t, buf, buflen, klen)) { + goto err; + } + for (i = 0; i < MlenCBLOCK; ++i) { + if (t[i]) { + goto B5; + } + } + goto err; + B5: + /* B5: C -> C2, M' = C2 ^ t*/ + printf("t: "); + for (int i=0; igroup, userB->group)); + // if (!EC_GROUP_same(userA->group, userB->group)) { + // return 0; + // } + int w = (BN_num_bits(userA->group->order) + 1) / 2 - 1; /* For n is not pow of 2 */ + size_t p_bytes = BN_num_bytes(userB->group->field), k_bytes = (klen >> 3) + ((klen & 7) ? 1 : 0), Zlen; + uint8 const_byte; + printf("w = %d\n", w); + SM3_CTX c; + BN_CTX *ctx; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + /* A-pre: */ + BIGNUM *rA, *x_1, *y_1, *tmpa, *tA; + const BIGNUM *nA, *dA, *hA; + EC_POINT *RA, *U, *tmp_pointA; + const EC_POINT *GA, *PA; + EC_GROUP *groupA; + uint8 *Z, *K, *buf, *tmp_char, *SA, *S1, *SB, *S2, *buf_digest; + SA = malloc(SM3_DIGEST_LENGTH); + S1 = malloc(SM3_DIGEST_LENGTH); + SB = malloc(SM3_DIGEST_LENGTH); + S2 = malloc(SM3_DIGEST_LENGTH); + buf_digest = malloc(SM3_DIGEST_LENGTH); + if (buf_digest == NULL) { + return 0; + } + groupA = userA->group; + nA = groupA->order; + dA = userA->priv_key; + hA = groupA->cofactor; + x_1 = BN_CTX_get(ctx); + y_1 = BN_CTX_get(ctx); + tmpa = BN_CTX_get(ctx); + tA = BN_CTX_get(ctx); + rA = BN_CTX_get(ctx); + GA = groupA->generator; + PA = userA->pub_key; + U = EC_POINT_new(); + tmp_pointA = EC_POINT_new(); + RA = EC_POINT_new(); + if (groupA == NULL + || nA == NULL + || dA == NULL + || hA == NULL + || rA == NULL + || GA == NULL + || PA == NULL + || RA == NULL) { + return 0; + } + /* A1: rA = rand(1, n-1) */ + do { + if (!BN_rand_range(rA, nA)) { + return 0; + } + } while(BN_is_zero(rA)); + #ifdef GBT32918_3_2016_A2_TEST + /* For GB/T 32918.3-2016 A.2 test */ + BN_hex2bn(&rA, "83A2C9C8B96E5AF70BD480B472409A9A327257F1EBB73F5B073354B248668563"); + #endif + #ifdef GBT32918_5_2017_TEST + BN_hex2bn(&rA, "D4DE15474DB74D06491C440D305E012400990F3E390C7E87153C12DB2EA60BB3"); + #endif + printf("rA: %s\n", BN_bn2hex(rA)); + /* A2: RA = [rA]G = (x1, y1) */ + if (!EC_POINT_mul(RA, GA, rA, groupA)) { + return 0; + } + printf("RA: (%s, \n\t%s)\n", BN_bn2hex(RA->X), BN_bn2hex(RA->Y)); + /* A3: send RA to userB */ + /* B-pre: */ + BIGNUM *rB, *x_2, *y_2, *tmpb, *tB; + const BIGNUM *nB, *dB, *hB; + EC_POINT *RB, *V, *tmp_pointB; + const EC_POINT *GB, *PB; + EC_GROUP *groupB; + groupB = userB->group; + nB = groupB->order; + dB = userB->priv_key; + hB = groupB->cofactor; + x_2 = BN_CTX_get(ctx); + y_2 = BN_CTX_get(ctx); + tmpb = BN_CTX_get(ctx); + tB = BN_CTX_get(ctx); + rB = BN_CTX_get(ctx); + GB = groupB->generator; + PB = userB->pub_key; + V = EC_POINT_new(); + tmp_pointB = EC_POINT_new(); + RB = EC_POINT_new(); + if (groupB == NULL + || nB == NULL + || dB == NULL + || hB == NULL + || rB == NULL + || GB == NULL + || PB == NULL + || RB == NULL) { + return 0; + } + /* B1: rB = rand(1, n-1) */ + do { + if (!BN_rand_range(rB, nB)) { + return 0; + } + } while(BN_is_zero(rB)); + #ifdef GBT32918_3_2016_A2_TEST + /* For GB/T 32918.3-2016 A.2 test */ + BN_hex2bn(&rB, "33FE21940342161C55619C4A0C060293D543C80AF19748CE176D83477DE71C80"); + #endif + #ifdef GBT32918_5_2017_TEST + BN_hex2bn(&rB, "7E07124814B309489125EAED101113164EBF0F3458C5BD88335C1F9D596243D6"); + #endif + printf("rB: %s\n", BN_bn2hex(rB)); + /* B2: RB = [rB]G = (x2, y2) */ + if (!EC_POINT_mul(RB, GB, rB, groupB)) { + return 0; + } + printf("RB: (%s, \n\t%s)\n", BN_bn2hex(RB->X), BN_bn2hex(RB->Y)); + /* B3: \bar{x_2} = 2^w + (x_2 & (2^w - 1)) */ + if (!BN_one(tmpb) + || !BN_lshift(tmpb, tmpb, w) + || !BN_mod(x_2, RB->X, tmpb, ctx) + || !BN_add(x_2, x_2, tmpb)) { + return 0; + } + printf("bar{x2}: %s\n", BN_bn2hex(x_2)); + /* B4: tB = (dB + \bar{x_2} \times rB) % n */ + if (!BN_mod_mul(tB, x_2, rB, nB, ctx) + || !BN_mod_add_quick(tB, tB, dB, nB)) { + return 0; + } + printf("tB: %s\n", BN_bn2hex(tB)); + /* B5: verify RA is on curve, \bar{x_1} = 2^w + (x_1 & (2^w - 1)) */ + if (!EC_POINT_on_curve_simple(RA, groupB)) { + return 0; + } + printf("On curve: %d\n", EC_POINT_on_curve_simple(RA, groupB)); + if (!BN_one(tmpb) + || !BN_lshift(tmpb, tmpb, w) + || !BN_mod(x_1, RA->X, tmpb, ctx) + || !BN_add(x_1, x_1, tmpb)) { + return 0; + } + printf("bar{x1}: %s\n", BN_bn2hex(x_1)); + /* B6: V = [h \times tB](PA + [\bar{x1}]RA) = (xV, yV) */ + if (!EC_POINT_mul(tmp_pointB, RA, x_1, groupB) + || !printf("[bar{x1}]RA: (%s, \n\t%s)\n", BN_bn2hex(tmp_pointB->X), BN_bn2hex(tmp_pointB->Y)) + || !EC_POINT_add(tmp_pointB, tmp_pointB, PA, groupB) + || !printf("PA + [bar{x1}]RA: (%s, \n\t%s)\n", BN_bn2hex(tmp_pointB->X), BN_bn2hex(tmp_pointB->Y)) + || !BN_mul(tmpb, hB, tB, ctx) + || !EC_POINT_mul(V, tmp_pointB, tmpb, groupB) + || EC_POINT_is_infinity(V)) { + return 0; + } + printf("V: (%s, \n\t%s)\n", BN_bn2hex(V->X), BN_bn2hex(V->Y)); + /* B7: KB = KDF(xV || yV || ZA || ZB, klen) */ + K = malloc((klen + 7) >> 3); + Zlen = (p_bytes + SM3_DIGEST_LENGTH) * 2; + Z = malloc(Zlen); + buf = malloc(p_bytes); + tmp_char = Z; + if (!BN_bn2binpad(V->X, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZA, SM3_DIGEST_LENGTH) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZB, SM3_DIGEST_LENGTH)) { + return 0; + } + printf("Z: "); + for (int i=0; iX, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + printf("SM3(xV || ZA || ZB || x1 || y1 || x2 || y2): "); + for (int i=0; iY, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(SB, &c)) { + return 0; + } + printf("SB: "); + for (int i=0; iX, tmpa, ctx) + || !BN_add(x_1, x_1, tmpa)) { + return 0; + } + printf("bar{x1}: %s\n", BN_bn2hex(x_1)); + /* A5: tA = (dA + \bar{x_1} \times rA) % n */ + if (!BN_mod_mul(tA, x_1, rA, nA, ctx) + || !BN_mod_add_quick(tA, tA, dA, nA)) { + return 0; + } + printf("tA: %s\n", BN_bn2hex(tA)); + /* A6: verify RB is on curve, \bar{x_2} = 2^w + (x_2 & (2^w - 1)) */ + if (!EC_POINT_on_curve_simple(RB, groupA)) { + return 0; + } + printf("On curve: %d\n", EC_POINT_on_curve_simple(RB, groupA)); + if (!BN_one(tmpa) + || !BN_lshift(tmpa, tmpa, w) + || !BN_mod(x_2, RB->X, tmpa, ctx) + || !BN_add(x_2, x_2, tmpa)) { + return 0; + } + printf("bar{x2}: %s\n", BN_bn2hex(x_2)); + /* A7: U = [h \times tA](PB + [\bar{x2}]RB) = (xU, yU) */ + if (!EC_POINT_mul(tmp_pointA, RB, x_2, groupA) + || !printf("[bar{x2}]RB: (%s, \n\t%s)\n", BN_bn2hex(tmp_pointA->X), BN_bn2hex(tmp_pointA->Y)) + || !EC_POINT_add(tmp_pointA, tmp_pointA, PB, groupA) + || !printf("PB + [bar{x2}]RB: (%s, \n\t%s)\n", BN_bn2hex(tmp_pointA->X), BN_bn2hex(tmp_pointA->Y)) + || !BN_mul(tmpa, hA, tA, ctx) + || !EC_POINT_mul(U, tmp_pointA, tmpa, groupA) + || EC_POINT_is_infinity(U)) { + return 0; + } + printf("U: (%s, \n\t%s)\n", BN_bn2hex(U->X), BN_bn2hex(U->Y)); + /* A8: KA = KDF(xU || yU || ZA || ZB, klen) */ + K = malloc((klen + 7) >> 3); + Zlen = (p_bytes + SM3_DIGEST_LENGTH) * 2; + Z = malloc(Zlen); + buf = malloc(p_bytes); + tmp_char = Z; + if (!BN_bn2binpad(U->X, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !BN_bn2binpad(U->Y, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZA, SM3_DIGEST_LENGTH) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZB, SM3_DIGEST_LENGTH)) { + return 0; + } + printf("Z: "); + for (int i=0; iX, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + printf("SM3(xU || ZA || ZB || x1 || y1 || x2 || y2): "); + for (int i=0; iY, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(S1, &c)) { + return 0; + } + printf("S1: "); + for (int i=0; iX, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + printf("SM3(xU || ZA || ZB || x1 || y1 || x2 || y2): "); + for (int i=0; iY, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(SA, &c)) { + return 0; + } + printf("SA: "); + for (int i=0; iX, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + printf("SM3(xV || ZA || ZB || x1 || y1 || x2 || y2): "); + for (int i=0; iY, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(S2, &c)) { + return 0; + } + printf("SA: "); + for (int i=0; i>3, ID_A, ID_B, Pp, Pa, Pb, Pn, PXG, PYG, PdA, PdB, Pklen); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign.h" new file mode 100644 index 0000000..8ab7664 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign.h" @@ -0,0 +1,259 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.2-2016 + */ + +/** SM2 signature generation. + * \param msg massage for signing. + * \param msglen byte length of msg. + * \param id identifier of user A. + * \param idlen byte length of id. + * \param key key of user A. + * \return the sign generated. + */ +SM2_SIG *sm2_sig_gen(const uint8 *msg, const size_t msglen, const uint8 *id, const size_t idlen, const EC_KEY *key) { + SM3_CTX c; + sm3_init(&c); + uint8 *buf; + BN_CTX *ctx; + BIGNUM *e, *n, *k, *x, *r, *s, *rk, *dA, *tmp; + EC_POINT *kG, *G; + SM2_SIG *sig; + // debugPrint; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + sig = SM2_SIG_new(); + if (sig == NULL) { + return 0; + } + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + n = key->group->order; + k = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + r = sig->r; + s = sig->s; + rk = BN_CTX_get(ctx); + dA = key->priv_key; + tmp = BN_CTX_get(ctx); + G = key->group->generator; + kG = EC_POINT_new(); + if (n == NULL + || r == NULL + || s == NULL + || dA == NULL + || tmp == NULL + || G == NULL + || kG == NULL) { + return 0; + } + // debugPrint; + printf("n: %s\n",BN_bn2hex(n)); + buf = malloc(SM3_DIGEST_LENGTH); + // debugPrint; + /* A1: \bar{M} = ZA || M */ + if (!sm2_compute_z(buf, id, idlen, key)) { + goto err; + } + // debugPrint; + printf("Z: "); + for (int i=0; i bn */ + sm3_final(buf, &c); + // debugPrint; + printf("e: "); + for (int i=0; i bn */ + if (!EC_POINT_mul(kG, G, k, key->group)) { + return 0; + } + // debugPrint; + printf("[k]G: (%s, \n\t%s)\n", BN_bn2hex(kG->X), BN_bn2hex(kG->Y)); + // debugPrint; + x = kG->X; + // debugPrint; + /* A5: r = (e + x1) % n, if r=0 or r+k=n, goto A3 */ + if (!BN_mod_add(r, e, x, n, ctx)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + printf("r: %s\n", BN_bn2hex(r)); + // debugPrint; + if (BN_is_zero(r)) continue; + // debugPrint; + if (!BN_add(rk, r, k)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + // debugPrint; + if (BN_cmp(rk, n) == 0) continue; + // debugPrint; + /* A6: s = ((1+dA)^-1 \times (k- r \times dA)) % n, if s=0, goto A3 */ + // wait for dA + // abort(); + // debugPrint; + if (!BN_add(s, dA, BN_value_one()) + || !BN_mod_inverse(s, s, n, ctx) + || !printf("(1+dA)^-1: %s\n", BN_bn2hex(s)) + || !BN_mod_mul(tmp, dA, r, n, ctx) + || !BN_sub(tmp, k, tmp) + || !BN_mod_mul(s, s, tmp, n, ctx)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + // debugPrint; + printf("s: %s\n", BN_bn2hex(s)); + if (BN_is_zero(s)) continue; + // debugPrint; + /* A7: r,s -> byte/u8[], sig = (r, s) */ + // sig->r = r; + // sig->s = s; + break; + } + err: + done: + BN_free(e); + BN_CTX_free(ctx); + // ecpoint free + // abort(); + printf("(r, s) = (%s,\n\t\t%s)\n", BN_bn2hex(r), BN_bn2hex(s)); + return sig; +} + +/* (2) Sign Verify */ + +/** SM2 signature verification. + * \param msg massage for signing. + * \param msglen byte length of msg. + * \param id identifier of user A. + * \param idlen byte length of id. + * \param key key of user A. + * \param sig signature to be verified. + * \return 1 on success and 0 if an error occurred. + */ +int sm2_sig_verify(const uint8 *msg, const size_t msglen, const uint8 *id, const size_t idlen, const EC_KEY *key, const SM2_SIG *sig) { + SM3_CTX c; + sm3_init(&c); + BN_CTX *ctx; + const BIGNUM *r, *s, *n; + BIGNUM *e, *t, *R; + const EC_POINT *G, *PA; + EC_POINT *sG, *tPA, *tmp_point; + uint8 *buf; + r = sig->r; + s = sig->s; + n = key->group->order; + G = key->group->generator; + PA = key->pub_key; + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + R = BN_CTX_get(ctx); + sG = EC_POINT_new(); + tPA = EC_POINT_new(); + tmp_point = EC_POINT_new(); + if (R == NULL || tmp_point == NULL) { + goto err; + } + buf = malloc(SM3_DIGEST_LENGTH); + /* B1: check r' \in [1, n-1], otherwise goto BERR */ + /* B2: check s' \in [1, n-1], otherwise goto BERR */ + if (BN_cmp(r, BN_value_one()) < 0 + || BN_cmp(s, BN_value_one()) < 0 + || BN_cmp(n, r) <= 0 + || BN_cmp(n, s) <= 0) { + goto err; + } + printf("(r, s) = (%s,\n\t\t%s)\n", BN_bn2hex(r), BN_bn2hex(s)); + /* B3: \bar{M'} = ZA || M' */ + if (!sm2_compute_z(buf, id, idlen, key)) { + goto err; + } + if (!sm3_update(&c, buf, SM3_DIGEST_LENGTH) + || !sm3_update(&c, msg, msglen)) { + SM2ERR("sm2_sign(): compute e error!\n"); + } + /* B4: e' = SM3(\bar{M'}), e -> bn */ + // debugPrint; + sm3_final(buf, &c); + // debugPrint; + printf("e: "); + for (int i=0; i bn; t = (r'+s')%n, if t=0, goto BERR */ + if (!BN_mod_add_quick(t, r, s, n) + || !printf("t: %s\n", BN_bn2hex(t)) + || BN_is_zero(t)) { + goto err; + } + /* B6: (x1', y1') = [s']G + [t]PA */ + if (!EC_POINT_mul(sG, G, s, key->group) + || !printf("sG: (%s,\n\t%s)\n", BN_bn2hex(sG->X), BN_bn2hex(sG->Y)) + || !EC_POINT_mul(tPA, PA, t, key->group) + || !printf("tPA: (%s,\n\t%s)\n", BN_bn2hex(tPA->X), BN_bn2hex(tPA->Y)) + || !EC_POINT_add(tmp_point, sG, tPA, key->group)) { + goto err; + } + // debugPrint; + printf("tmp: (%s,\n\t%s)\n", BN_bn2hex(tmp_point->X), BN_bn2hex(tmp_point->Y)); + // debugPrint; + /* B7: x1' -> bn; R = (e' + x1')%n, return R=r' */ + if (!BN_mod_add_quick(R, e, tmp_point->X, n)) { + goto err; + } + // debugPrint; + printf("R: %s\n", BN_bn2hex(R)); + // debugPrint; + if (BN_cmp(R, r) == 0) { + return 1; + } + // debugPrint; + err: + BN_CTX_end(ctx); + /* BERR: not pass, return 0 */ + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign_test.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign_test.c" new file mode 100644 index 0000000..04da924 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_sign_test.c" @@ -0,0 +1,91 @@ +#define GBT32918_2_2016_A2_TEST /* For GB/T 32918.2-2016 A.2 test */ +#include "sm2.h" +#include "sm2_tests.h" + +const uint8 ID_A[] = "ALICE123@YAHOO.COM"; +const uint8 M[] = "message digest"; +const uint8 Pp[] = { + 0x85, 0x42, 0xD6, 0x9E, + 0x4C, 0x04, 0x4F, 0x18, + 0xE8, 0xB9, 0x24, 0x35, + 0xBF, 0x6F, 0xF7, 0xDE, + 0x45, 0x72, 0x83, 0x91, + 0x5C, 0x45, 0x51, 0x7D, + 0x72, 0x2E, 0xDB, 0x8B, + 0x08, 0xF1, 0xDF, 0xC3, +}; +const uint8 Pa[] = { + 0x78, 0x79, 0x68, 0xB4, + 0xFA, 0x32, 0xC3, 0xFD, + 0x24, 0x17, 0x84, 0x2E, + 0x73, 0xBB, 0xFE, 0xFF, + 0x2F, 0x3C, 0x84, 0x8B, + 0x68, 0x31, 0xD7, 0xE0, + 0xEC, 0x65, 0x22, 0x8B, + 0x39, 0x37, 0xE4, 0x98, +}; +const uint8 Pb[] = { + 0x63, 0xE4, 0xC6, 0xD3, + 0xB2, 0x3B, 0x0C, 0x84, + 0x9C, 0xF8, 0x42, 0x41, + 0x48, 0x4B, 0xFE, 0x48, + 0xF6, 0x1D, 0x59, 0xA5, + 0xB1, 0x6B, 0xA0, 0x6E, + 0x6E, 0x12, 0xD1, 0xDA, + 0x27, 0xC5, 0x24, 0x9A, +}; +const uint8 PXG[] = { + 0x42, 0x1D, 0xEB, 0xD6, + 0x1B, 0x62, 0xEA, 0xB6, + 0x74, 0x64, 0x34, 0xEB, + 0xC3, 0xCC, 0x31, 0x5E, + 0x32, 0x22, 0x0B, 0x3B, + 0xAD, 0xD5, 0x0B, 0xDC, + 0x4C, 0x4E, 0x6C, 0x14, + 0x7F, 0xED, 0xD4, 0x3D, +}; +const uint8 PYG[] = { + 0x06, 0x80, 0x51, 0x2B, + 0xCB, 0xB4, 0x2C, 0x07, + 0xD4, 0x73, 0x49, 0xD2, + 0x15, 0x3B, 0x70, 0xC4, + 0xE5, 0xD7, 0xFD, 0xFC, + 0xBF, 0xA3, 0x6E, 0xA1, + 0xA8, 0x58, 0x41, 0xB9, + 0xE4, 0x6E, 0x09, 0xA2, +}; +const uint8 Pn[] = { + 0x85, 0x42, 0xD6, 0x9E, + 0x4C, 0x04, 0x4F, 0x18, + 0xE8, 0xB9, 0x24, 0x35, + 0xBF, 0x6F, 0xF7, 0xDD, + 0x29, 0x77, 0x20, 0x63, + 0x04, 0x85, 0x62, 0x8D, + 0x5A, 0xE7, 0x4E, 0xE7, + 0xC3, 0x2E, 0x79, 0xB7, +}; +const uint8 PdA[] = { + 0x12, 0x8B, 0x2F, 0xA8, + 0xBD, 0x43, 0x3C, 0x6C, + 0x06, 0x8C, 0x8D, 0x80, + 0x3D, 0xFF, 0x79, 0x79, + 0x2A, 0x51, 0x9A, 0x55, + 0x17, 0x1B, 0x1B, 0x65, + 0x0C, 0x23, 0x66, 0x1D, + 0x15, 0x89, 0x72, 0x63, +}; +const uint8 Pk[] = { + 0x6C, 0xB2, 0x8D, 0x99, + 0x38, 0x5C, 0x17, 0x5C, + 0x94, 0xF9, 0x4E, 0x93, + 0x48, 0x17, 0x66, 0x3F, + 0xC1, 0x76, 0xD9, 0x25, + 0xDD, 0x72, 0xB7, 0x27, + 0x26, 0x0D, 0xBA, 0xAE, + 0x1F, 0xB2, 0xF9, 0x6F, +}; + +int main() { + sm2signtest(256>>3, M, ID_A, Pp, Pa, Pb, Pn, PXG, PYG, PdA, Pk); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_tests.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_tests.h" new file mode 100644 index 0000000..730d75c --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm2/sm2_tests.h" @@ -0,0 +1,236 @@ +#ifndef SECGEAR_SM2_TESTS_H +#define SECGEAR_SM2_TESTS_H + +#include "sm2_sign.h" +#include "sm2_exchange.h" +#include "sm2_crypt.h" + +void sm2signtest(const int p_bytes, const uint8 *_M, const uint8 *_ID_A, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dA, const uint8 *_k) { + printf("-----------Sign test start--------------\n"); + /* A.3 is not supported */ + int _w; + printf("ID_A: "); + uint16 entlenC = strlen((char *)_ID_A); + uint16 entlA = entlenC*8; + for (int i=0; iX), BN_bn2hex(G->Y)); + _w = EC_GROUP_set_param(group, p, a, b, n, BN_value_one(), G); + _w = EC_KEY_set_group(userA, group); + _w = EC_KEY_set_priv_key(userA, dA); + printf("userA.dA: %s\n", BN_bn2hex(userA->priv_key)); + _w = EC_KEY_generate_pub_key(userA); + printf("userA.PA: (%s, \n\t%s)\n", BN_bn2hex(userA->pub_key->X), BN_bn2hex(userA->pub_key->Y)); + _w = EC_POINT_mul(kG, G, k, group); + printf("kG: (%s, \n\t%s)\n", BN_bn2hex(kG->X), BN_bn2hex(kG->Y)); + SM2_SIG *sig; + printf("------Sign Generation Start-----\n"); + sig = sm2_sig_gen(_M, strlen((char *)_M), _ID_A, strlen((char *)_ID_A), userA); + printf("------Sign Generation End-----\n"); + printf("(r, s) = (%s,\n\t\t%s)\n", BN_bn2hex(sig->r), BN_bn2hex(sig->s)); + printf("--------Sign Verify Start-------\n"); + _w = sm2_sig_verify(_M, strlen((char *)_M), _ID_A, strlen((char *)_ID_A), userA, sig); + printf("--------Sign Verify End-------\n"); + printf("Verify: %d\n", _w); + printf("-----------Sign test end--------------\n"); +} + +/* h = 1 by default */ +void sm2exchangetest(const int p_bytes, const uint8 *_ID_A, const uint8 *_ID_B, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dA, const uint8 *_dB, const uint64 klen) { + printf("-----------Exchange test start--------------\n"); + /* A.3 is not supported */ + int _w; + printf("ID_A: "); + uint16 entlenAC = strlen((char *)_ID_A); + uint16 entlA = entlenAC*8; + for (int i=0; iX), BN_bn2hex(G->Y)); + _w = EC_GROUP_set_param(group, p, a, b, n, h, G); + _w = EC_KEY_set_group(userA, group); + _w = EC_KEY_set_priv_key(userA, dA); + printf("userA.dA: %s\n", BN_bn2hex(userA->priv_key)); + _w = EC_KEY_generate_pub_key(userA); + printf("userA.PA: (%s, \n\t%s)\n", BN_bn2hex(userA->pub_key->X), BN_bn2hex(userA->pub_key->Y)); + _w = EC_KEY_set_group(userB, group); + _w = EC_KEY_set_priv_key(userB, dB); + printf("userB.dB: %s\n", BN_bn2hex(userB->priv_key)); + _w = EC_KEY_generate_pub_key(userB); + printf("userB.PB: (%s, \n\t%s)\n", BN_bn2hex(userB->pub_key->X), BN_bn2hex(userB->pub_key->Y)); + _w = sm2_compute_z(ZA, _ID_A, strlen((char *)_ID_A), userA); + printf("ZA: "); + for (int i=0; iX), BN_bn2hex(G->Y)); + MlenCBLOCK = strlen((char *)M); + printf("M: %s\n", M); + printf("Message: "); + for (int i=0; ipriv_key)); + _w = EC_KEY_generate_pub_key(userB); + printf("userB.PB: (%s, \n\t%s)\n", BN_bn2hex(userB->pub_key->X), BN_bn2hex(userB->pub_key->Y)); + klen = MlenCBLOCK * 8; + pwlen = (p_bytes << 1 | 1) + MlenCBLOCK + SM3_DIGEST_LENGTH; + pw = malloc(pwlen); + _w = sm2_encrypt(pw, M, klen, userB); + printf("encrypt = %d\n", _w); + printf("pw: "); + for (int i=0; i> 3; +const uint8 sign_ID_A[] = "1234567812345678"; +const uint8 sign_M[] = "message digest"; +const uint8 sign_dA[] = { + 0x39, 0x45, 0x20, 0x8F, + 0x7B, 0x21, 0x44, 0xB1, + 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, + 0x88, 0x93, 0x93, 0x69, + 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, + 0x4D, 0xF7, 0xC5, 0xB8, +}; +const uint8 sign_k[] = { + 0x59, 0x27, 0x6E, 0x27, + 0xD5, 0x06, 0x86, 0x1A, + 0x16, 0x68, 0x0F, 0x3A, + 0xD9, 0xC0, 0x2D, 0xCC, + 0xEF, 0x3C, 0xC1, 0xFA, + 0x3C, 0xDB, 0xE4, 0xCE, + 0x6D, 0x54, 0xB8, 0x0D, + 0xEA, 0xC1, 0xBC, 0x21, +}; + +const uint8 exchange_ID_A[] = "1234567812345678"; +const uint8 exchange_ID_B[] = "1234567812345678"; +const uint8 exchange_dA[] = { + 0x81, 0xEB, 0x26, 0xE9, + 0x41, 0xBB, 0x5A, 0xF1, + 0x6D, 0xF1, 0x16, 0x49, + 0x5F, 0x90, 0x69, 0x52, + 0x72, 0xAE, 0x2C, 0xD6, + 0x3D, 0x6C, 0x4A, 0xE1, + 0x67, 0x84, 0x18, 0xBE, + 0x48, 0x23, 0x00, 0x29, +}; +const uint8 exchange_dB[] = { + 0x78, 0x51, 0x29, 0x91, + 0x7D, 0x45, 0xA9, 0xEA, + 0x54, 0x37, 0xA5, 0x93, + 0x56, 0xB8, 0x23, 0x38, + 0xEA, 0xAD, 0xDA, 0x6C, + 0xEB, 0x19, 0x90, 0x88, + 0xF1, 0x4A, 0xE1, 0x0D, + 0xEF, 0xA2, 0x29, 0xB5, +}; +const uint64 exchange_klen = 128; + +const uint8 crypt_M[] = "encryption standard"; +const uint8 crypt_dB[] = { + 0x39, 0x45, 0x20, 0x8F, + 0x7B, 0x21, 0x44, 0xB1, + 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, + 0x88, 0x93, 0x93, 0x69, + 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, + 0x4D, 0xF7, 0xC5, 0xB8, +}; + +int main(){ + printf("A.2 start: \n"); + sm2signtest(SM2_p_bytes, sign_M, sign_ID_A, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, sign_dA, sign_k); + printf("A.2 end: \n\n\n"); + /* PASSED */ + + printf("B.2 start: \n"); + sm2exchangetest(SM2_p_bytes, exchange_ID_A, exchange_ID_B, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, exchange_dA, exchange_dB, exchange_klen); + printf("B.2 end: \n\n\n"); + /* PASSED */ + + printf("C.2 start: \n"); + sm2crypttest(SM2_p_bytes, crypt_M, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, crypt_dB); + printf("C.2 end: \n\n\n"); + /* PASSED */ + return 0; +} \ No newline at end of file -- Gitee From 388f46730ef53bd40cd64064214fa0a78943a6b0 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:52:21 +0000 Subject: [PATCH 07/18] sm3 Signed-off-by: wangxiaoxi1 --- .../C_origin/sm3/sm3.h" | 183 ++++++++++++++++++ .../C_origin/sm3/sm3test.c" | 53 +++++ 2 files changed, 236 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3test.c" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3.h" new file mode 100644 index 0000000..195d679 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3.h" @@ -0,0 +1,183 @@ +#ifndef SECGEAR_SM3_H +#define SECGEAR_SM3_H + +/* + * Ref: + * GB/T 32905-2016 + */ + +#include +#include "../include/common_utils.h" + +#define SM3_DIGEST_LENGTH 32 +#define SM3_WORD uint32 + +#define SM3_CBLOCK 64 +#define SM3_LBLOCK (SM3_CBLOCK/4) + +typedef struct SM3state_st { + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD Nl, Nh; + SM3_WORD data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17)) +#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23)) + +#define FF(J,X,Y,Z) (J<16 ? (X ^ Y ^ Z) : ((X & Y) | (X & Z) | (Y & Z))) +#define GG(J,X,Y,Z) (J<16 ? (X ^ Y ^ Z) : ((X & Y) | ((~X) & Z))) + +#define T(J) (J<16 ? 0x79cc4519 : 0x7a879d8a) + +#define EXPAND(W0,W7,W13,W3,W10) \ + (P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10) + +#define SM3_A 0x7380166fUL +#define SM3_B 0x4914b2b9UL +#define SM3_C 0x172442d7UL +#define SM3_D 0xda8a0600UL +#define SM3_E 0xa96f30bcUL +#define SM3_F 0x163138aaUL +#define SM3_G 0xe38dee4dUL +#define SM3_H 0xb0fb0e4eUL + +#define SM3_MAKE_STRING(c, s) \ + do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll, (s)); \ + ll=(c)->B; (void)HOST_l2c(ll, (s)); \ + ll=(c)->C; (void)HOST_l2c(ll, (s)); \ + ll=(c)->D; (void)HOST_l2c(ll, (s)); \ + ll=(c)->E; (void)HOST_l2c(ll, (s)); \ + ll=(c)->F; (void)HOST_l2c(ll, (s)); \ + ll=(c)->G; (void)HOST_l2c(ll, (s)); \ + ll=(c)->H; (void)HOST_l2c(ll, (s)); \ + } while (0) + +void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num) { + const unsigned char *data = p; + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD w[68]={}, ww[64]={}; + while (num--) { + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + E = ctx->E; + F = ctx->F; + G = ctx->G; + H = ctx->H; + for (int j = 0; j < 16; ++j) { + HOST_c2l(data, w[j]); + } + for (int j = 16; j < 68; ++j) { + w[j] = EXPAND(w[j-16], w[j-9], w[j-3], w[j-13], w[j-6]); + } + for (int j = 0; j < 64; ++j) { + ww[j] = w[j] ^ w[j+4]; + } + for (int j = 0; j < 64; j++) { + SM3_WORD SS1, SS2, TT1, TT2; + SS1 = ROTATE(ROTATE(A, 12) + E + ROTATE(T(j), j&31), 7); + SS2 = SS1 ^ ROTATE(A, 12); + TT1 = FF(j, A, B, C) + D + SS2 + ww[j]; + TT2 = GG(j, E, F, G) + H + SS1 + w[j]; + D = C; + C = ROTATE(B,9); + B = A; + A = TT1; + H = G; + G = ROTATE(F, 19); + F = E; + E = P0(TT2); + } + ctx->A ^= A; + ctx->B ^= B; + ctx->C ^= C; + ctx->D ^= D; + ctx->E ^= E; + ctx->F ^= F; + ctx->G ^= G; + ctx->H ^= H; + } +} + +int sm3_init(SM3_CTX *c) { + memset(c, 0, sizeof(*c)); + c->A = SM3_A; + c->B = SM3_B; + c->C = SM3_C; + c->D = SM3_D; + c->E = SM3_E; + c->F = SM3_F; + c->G = SM3_G; + c->H = SM3_H; + return 1; +} + +int sm3_update(SM3_CTX *c, const void *data_, size_t len) { + const unsigned char *data = data_; + unsigned char *p; + SM3_WORD l; + size_t n; + if (len == 0) return 1; + l = (c->Nl + (((SM3_WORD) len) << 3)) & 0xffffffffUL; + if (l < c->Nl) c->Nh++; + c->Nh += (SM3_WORD) (len >> 29); + c->Nl = l; + n = c->num; + if (n != 0) { + p = (unsigned char *)c->data; + if (len >= SM3_CBLOCK || len + n >= SM3_CBLOCK) { + memcpy(p + n, data, SM3_CBLOCK - n); + sm3_block_data_order(c, p, 1); + n = SM3_CBLOCK - n; + data += n; + len -= n; + c->num = 0; + memset(p, 0, SM3_CBLOCK); + } + else { + memcpy(p + n, data, len); + c->num += (unsigned int)len; + return 1; + } + } + n = len / SM3_CBLOCK; + if (n > 0) { + sm3_block_data_order(c, data, n); + n *= SM3_CBLOCK; + data += n; + len -= n; + } + if (len != 0) { + p = (unsigned char *)c->data; + c->num = (unsigned int)len; + memcpy(p, data, len); + } + return 1; +} + +int sm3_final(unsigned char *md, SM3_CTX *c) { + unsigned char *p = (unsigned char *)c->data; + size_t n = c->num; + p[n] = 0x80; + n++; + if (n > (SM3_CBLOCK - 8)) { + memset(p + n, 0, SM3_CBLOCK - n); + n = 0; + sm3_block_data_order(c, p, 1); + } + memset(p + n, 0, SM3_CBLOCK - 8 - n); + p += SM3_CBLOCK - 8; + (void)HOST_l2c(c->Nh, p); + (void)HOST_l2c(c->Nl, p); + p -= SM3_CBLOCK; + sm3_block_data_order(c, p, 1); + c->num = 0; + SM3_MAKE_STRING(c, md); + return 1; +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3test.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3test.c" new file mode 100644 index 0000000..00d6754 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm3/sm3test.c" @@ -0,0 +1,53 @@ +#include "sm3.h" +#include +#include + +uint8 p1[] = {0x61, 0x62, 0x63}; +uint8 p2[] = { + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, +}; + +void sm3test(uint8 *md, size_t len, uint8 *res) { + SM3_CTX c; + sm3_init(&c); + sm3_update(&c, md, len); + sm3_final(res, &c); +} + +int main(){ + uint8 res[32]={}; + printf("Test 1: \n"); + // printf("len = %lu\n",sizeof (p1)); + sm3test(p1, 3, res); + for(int i=0;i<32;i++) { + printf("%02X",res[i]); + } + putchar('\n'); + printf("Test 2: \n"); + sm3test(p2, 64, res); + for(int i=0;i<32;i++) { + printf("%02x",res[i]); + } + putchar('\n'); + return 0; +} + +// Test 1: +// 66C7F0F462EEEDD9D1F2D46BDC10E4E24167C4875CF2F7A2297DA02B8F4BA8E0 +// Test 2: +// debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732 -- Gitee From 5b1cd9fc413b75e2e07e535d544719566bfaba8a Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:52:36 +0000 Subject: [PATCH 08/18] sm4 Signed-off-by: wangxiaoxi1 --- .../C_origin/sm4/sm4.h" | 107 ++++++++++++++++++ .../C_origin/sm4/sm4test.c" | 42 +++++++ 2 files changed, 149 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4test.c" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4.h" new file mode 100644 index 0000000..8474251 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4.h" @@ -0,0 +1,107 @@ +#ifndef SECGEAR_SM4_H +#define SECGEAR_SM4_H + +/* + * Ref: + * GB/T 32907-2016 + */ + +#include +#include "../include/common_utils.h" + +#define ENCRYPT 0 +#define DECRYPT 1 +const uint8 Sbox[256] = { + 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, + 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, + 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, + 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, + 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, + 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, + 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, + 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, + 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, + 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, + 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, + 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, + 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, + 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, + 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48, +}; +const uint32 FK[4] = { + 0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC, +}; +const uint32 CK[32] = { + 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, + 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, + 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, + 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, + 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, + 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, + 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, + 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279, +}; +#define L(B) ((B) ^ (ROTATE((B), 2)) ^ (ROTATE((B), 10)) ^ (ROTATE((B), 18)) ^ (ROTATE((B), 24))) +#define LP(B) ((B) ^ (ROTATE((B), 13)) ^ (ROTATE((B), 23))) +#define S(X) (((uint32)Sbox[((X) >> 24) & 0xFF] << 24) | \ + ((uint32)Sbox[((X) >> 16) & 0xFF] << 16) | \ + ((uint32)Sbox[((X) >> 8) & 0xFF] << 8) | \ + ((uint32)Sbox[(X) & 0xFF])) +#define T(X) L(S(X)) +#define TP(X) LP(S(X)) +#define F(X0, X1, X2, X3, rk) ((X0) ^ T((X1) ^ (X2) ^ (X3) ^ (rk))) + +typedef struct sm4_ctx_st { + uint32 M[4]; + uint32 rk[32]; +} SM4_CTX; + +int sm4_init(SM4_CTX *ctx, const uint32 *M, const uint32 *MK) { + memset(ctx, 0, sizeof(*ctx)); + uint32 K[36]; + memset(K, 0, sizeof(K)); + int i; + for (i = 0; i < 4; ++i) { + K[i] = MK[i] ^ FK[i]; + ctx->M[i] = M[i]; + } + for (i = 0; i < 32; ++i) { + ctx->rk[i] = K[i+4] = K[i] ^ TP(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]); + } + return 1; +} + +int sm4_round(SM4_CTX *ctx, int crypt_flag) { + int offset = (crypt_flag ? 31 : 0), i; + uint32 X[36]; + memset(X, 0, sizeof(X)); + for (i = 0; i < 4; ++i) { + X[i] = ctx->M[i]; + } + for (i = 0; i < 32; ++i) { + X[i+4] = F(X[i], X[i+1], X[i+2], X[i+3], ctx->rk[i^offset]); + } + ctx->M[0] = X[35]; + ctx->M[1] = X[34]; + ctx->M[2] = X[33]; + ctx->M[3] = X[32]; + return 1; +} + +int sm4_encrypt(SM4_CTX *ctx) { + return sm4_round(ctx, ENCRYPT); +} + +int sm4_decrypt(SM4_CTX *ctx) { + return sm4_round(ctx, DECRYPT); +} + +int sm4_final(uint32 *out, SM4_CTX *ctx) { + if (!memcpy(out, ctx->M, sizeof(ctx->M))) { + return 0; + } + return 1; +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4test.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4test.c" new file mode 100644 index 0000000..b951234 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm4/sm4test.c" @@ -0,0 +1,42 @@ +#include +#include "sm4.h" + +const uint32 message[] = { + 0x01234567, 0x89ABCDEF, + 0xFEDCBA98, 0x76543210, +}; +const uint32 key[] = { + 0x01234567, 0x89ABCDEF, + 0xFEDCBA98, 0x76543210, +}; +uint32 res[4]; + +void sm4test(const uint32 *M, const uint32 *MK, const int rounds) { + printf("---------SM4 encrypt test (%d)--------------\n", rounds); + SM4_CTX c; + sm4_init(&c, M, MK); + for (int i=0; i Date: Fri, 30 Sep 2022 12:52:52 +0000 Subject: [PATCH 09/18] sm9 Signed-off-by: wangxiaoxi1 --- .../C_origin/sm9/sm9.h" | 316 ++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm9/sm9.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm9/sm9.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm9/sm9.h" new file mode 100644 index 0000000..8a6d3d6 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/sm9/sm9.h" @@ -0,0 +1,316 @@ +#ifndef SECGEAR_SM9_H +#define SECGEAR_SM9_H + +/* + * Ref: + * GB/T 38635.1-2020 + * GB/T 38635.2-2020 + */ + +#include +#include "../include/common_utils.h" +#include "../include/ec.h" +#include "../sm3/sm3.h" +#include "../sm4/sm4.h" +/* + * export C_INCLUDE_PATH="/PATH/TO/OPENSSL/include" + * export CPLUS_INCLUDE_PATH="/PATH/TO/OPENSSL/include" + * export LIBRARY_PATH="/PATH/TO/OPENSSL/lib" + */ + +#define SM9_PARAM_CBLOCK 32 +#define SM9_PARAM_LBLOCK (SM9_PARAM_CBLOCK/4) + +const uint8 SM9_T[SM9_PARAM_CBLOCK] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, + 0x00, 0x58, 0xF9, 0x8A, +}; +const uint8 SM9_TR[] = {}; +const uint8 SM9_Q[SM9_PARAM_CBLOCK] = { + 0xB6, 0x40, 0x00, 0x00, + 0x02, 0xA3, 0xA6, 0xF1, + 0xD6, 0x03, 0xAB, 0x4F, + 0xF5, 0x8E, 0xC7, 0x45, + 0x21, 0xF2, 0x93, 0x4B, + 0x1A, 0x7A, 0xEE, 0xDB, + 0xE5, 0x6F, 0x9B, 0x27, + 0xE3, 0x51, 0x45, 0x7D, +}; +const uint8 SM9_A[SM9_PARAM_CBLOCK] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +const uint8 SM9_B[SM9_PARAM_CBLOCK] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, +}; +const uint8 SM9_N[SM9_PARAM_CBLOCK] = { + 0xB6, 0x40, 0x00, 0x00, + 0x02, 0xA3, 0xA6, 0xF1, + 0xD6, 0x03, 0xAB, 0x4F, + 0xF5, 0x8E, 0xC7, 0x44, + 0x49, 0xF2, 0x93, 0x4B, + 0x18, 0xEA, 0x8B, 0xEE, + 0xE5, 0x6E, 0xE1, 0x9C, + 0xD6, 0x9E, 0xCF, 0x25, +}; +const uint8 SM9_CF = 1; +const uint8 SM9_K = 12; +const uint8 SM9_D1 = 1; +const uint8 SM9_D2 = 2; +const uint8 SM9_CID = 0x12; +const uint8 SM9_XP1[SM9_PARAM_CBLOCK] = { + 0x93, 0xDE, 0x05, 0x1D, + 0x62, 0xBF, 0x71, 0x8F, + 0xF5, 0xED, 0x07, 0x04, + 0x48, 0x7D, 0x01, 0xD6, + 0xE1, 0xE4, 0x08, 0x69, + 0x09, 0xDC, 0x32, 0x80, + 0xE8, 0xC4, 0xE4, 0x81, + 0x7C, 0x66, 0xDD, 0xDD, +}; +const uint8 SM9_YP1[SM9_PARAM_CBLOCK] = { + 0x21, 0xFE, 0x8D, 0xDA, + 0x4F, 0x21, 0xE6, 0x07, + 0x63, 0x10, 0x65, 0x12, + 0x5C, 0x39, 0x5B, 0xBC, + 0x1C, 0x1C, 0x00, 0xCB, + 0xFA, 0x60, 0x24, 0x35, + 0x0C, 0x46, 0x4C, 0xD7, + 0x0A, 0x3E, 0xA6, 0x16, +}; +const uint8 SM9_XP21[SM9_PARAM_CBLOCK] = { + 0x85, 0xAE, 0xF3, 0xD0, + 0x78, 0x64, 0x0C, 0x98, + 0x59, 0x7B, 0x60, 0x27, + 0xB4, 0x41, 0xA0, 0x1F, + 0xF1, 0xDD, 0x2C, 0x19, + 0x0F, 0x5E, 0x93, 0xC4, + 0x54, 0x80, 0x6C, 0x11, + 0xD8, 0x80, 0x61, 0x41, +}; +const uint8 SM9_XP22[SM9_PARAM_CBLOCK] = { + 0x37, 0x22, 0x75, 0x52, + 0x92, 0x13, 0x0B, 0x08, + 0xD2, 0xAA, 0xB9, 0x7F, + 0xD3, 0x4E, 0xC1, 0x20, + 0xEE, 0x26, 0x59, 0x48, + 0xD1, 0x9C, 0x17, 0xAB, + 0xF9, 0xB7, 0x21, 0x3B, + 0xAF, 0x82, 0xD6, 0x5B, +}; +const uint8 SM9_YP21[SM9_PARAM_CBLOCK] = { + 0x17, 0x50, 0x9B, 0x09, + 0x2E, 0x84, 0x5C, 0x12, + 0x66, 0xBA, 0x0D, 0x26, + 0x2C, 0xBE, 0xE6, 0xED, + 0x07, 0x36, 0xA9, 0x6F, + 0xA3, 0x47, 0xC8, 0xBD, + 0x85, 0x6D, 0xC7, 0x6B, + 0x84, 0xEB, 0xEB, 0x96, +}; +const uint8 SM9_YP22[SM9_PARAM_CBLOCK] = { + 0xA7, 0xCF, 0x28, 0xD5, + 0x19, 0xBE, 0x3D, 0xA6, + 0x5F, 0x31, 0x70, 0x15, + 0x3D, 0x27, 0x8F, 0xF2, + 0x47, 0xEF, 0xBA, 0x98, + 0xA7, 0x1A, 0x08, 0x11, + 0x62, 0x15, 0xBB, 0xA5, + 0xC9, 0x99, 0xA7, 0xC7, +}; +const uint8 SM9_EID = 0x04; + +/* + * H1 if typ == 1, H2 if typ == 2. + */ + +typedef struct sm9_ctx_st { + // +} SM9_CTX; + +int sm9_init(SM3_CTX *ctx) { + memset(ctx, 0, sizeof(*ctx)); + return 1; +} + +int sm9_H(BIGNUM *h, const uint8 typ, const uint8 *Z, const size_t Zlen, const EC_GROUP *group) { + const uint64 v = 256; /* SM3: 256bit digest */ + if (h == NULL) { + return 0; + } + int ret = 0; + uint32 hlen, ct = 1, lmt, tmp; + uint8 *_ct, *tmp_u8, *digest, *K, *p; + BN_CTX *ctx; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + BIGNUM *tmp_bn = BN_new(), *n; + n = group->order; + if (tmp_bn == NULL || n == NULL) { + goto err; + } + if (!BN_copy(h, BN_value_one()) + || !BN_mul_word(h, 5) + || !BN_exp(h, n, h, ctx)) { + goto err; + } + hlen = (BN_num_bits(h) + 31) >> 5; + K = (uint8 *)malloc(hlen); + hlen = 8 * hlen; + lmt = (hlen + v - 1) / v; + _ct = (uint8 *)malloc(4UL); + digest = (uint8 *)malloc(SM3_DIGEST_LENGTH); + SM3_CTX c; + while (ct < lmt) { + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, &typ, 1) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c) + || !memcpy(p, digest, SM3_DIGEST_LENGTH)) { + goto err; + } + ++ct; + p += SM3_DIGEST_LENGTH; + } + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c)) { + goto err; + } + tmp = hlen % v; + if (!tmp) { + if (!memcpy(p, digest, SM3_DIGEST_LENGTH)) { + goto err; + } + } + else { + if (!memcpy(p, digest, tmp >> 3)) { + goto err; + } + } + BN_bin2bn(K, hlen >> 3, h); + if (!BN_sub(tmp_bn, n, BN_value_one()) + || !BN_mod(h, h, tmp_bn, ctx)) { + goto err; + } + ret = 1; + err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int sm9_H1(BIGNUM *h, const uint8 typ, const uint8 *Z, const size_t Zlen, const EC_GROUP *group) { + return sm9_H(h, 0x01, Z, Zlen, group); +} + +int sm9_H2(BIGNUM *h, const uint8 typ, const uint8 *Z, const size_t Zlen, const EC_GROUP *group) { + return sm9_H(h, 0x02, Z, Zlen, group); +} + +int sm9_KDF(uint8 *K, const uint8 *Z, const size_t Zlen, const uint64 klen) { + const uint64 v = 256; /* SM3: 256bit digest */ + if (v*0xFFFFFFFFU <= klen) { + return 0; + } + if (klen & 7) { + return 0; + } + uint32 ct = 1, lmt = (klen+v-1)/v, tmp; + uint8 *_ct, *tmp_u8, *digest, *p = K; + _ct = (uint8 *)malloc(4UL); + digest = (uint8 *)malloc(SM3_DIGEST_LENGTH); + SM3_CTX c; + while (ct < lmt) { + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c) + || !memcpy(p, digest, SM3_DIGEST_LENGTH)) { + return 0; + } + ++ct; + p += SM3_DIGEST_LENGTH; + } + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c)) { + return 0; + } + tmp = klen % v; + if (!tmp) { + if (!memcpy(p, digest, SM3_DIGEST_LENGTH)) { + return 0; + } + } + else { + if (!memcpy(p, digest, tmp >> 3)) { + return 0; + } + } + return 1; +} + +typedef struct sm9_sig_st { + BIGNUM *h; + BIGNUM *S; +} SM9_SIG; + +int SM9_SIG_init(SM9_SIG *sig) { + sig->h = BN_new(); + sig->S = BN_new(); + if (sig->h == NULL || sig->S == NULL) { + BN_free(sig->h); + BN_free(sig->S); + return 0; + } + return 1; +} + +SM9_SIG *SM9_SIG_new() { + SM9_SIG *ret; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!SM9_SIG_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +#endif \ No newline at end of file -- Gitee From 0b32370b0ddedc4181ff060416b6ef65553178ba Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:53:10 +0000 Subject: [PATCH 10/18] zuc Signed-off-by: wangxiaoxi1 --- .../C_origin/zuc/zuc.h" | 376 ++++++++++++++++++ .../C_origin/zuc/zuctest1.c" | 84 ++++ .../C_origin/zuc/zuctest2.c" | 80 ++++ .../C_origin/zuc/zuctest3.c" | 83 ++++ 4 files changed, 623 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuc.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest1.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest2.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest3.c" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuc.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuc.h" new file mode 100644 index 0000000..711fcd4 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuc.h" @@ -0,0 +1,376 @@ +#ifndef SECGEAR_ZUC_H +#define SECGEAR_ZUC_H + +#include +#include "../include/common_utils.h" + +/* S_BOX BEGIN */ + +const uint8 ZUC_S[2][256] = { + { + 0x3E, 0x72, 0x5B, 0x47, 0xCA, 0xE0, 0x00, 0x33, 0x04, 0xD1, 0x54, 0x98, 0x09, 0xB9, 0x6D, 0xCB, + 0x7B, 0x1B, 0xF9, 0x32, 0xAF, 0x9D, 0x6A, 0xA5, 0xB8, 0x2D, 0xFC, 0x1D, 0x08, 0x53, 0x03, 0x90, + 0x4D, 0x4E, 0x84, 0x99, 0xE4, 0xCE, 0xD9, 0x91, 0xDD, 0xB6, 0x85, 0x48, 0x8B, 0x29, 0x6E, 0xAC, + 0xCD, 0xC1, 0xF8, 0x1E, 0x73, 0x43, 0x69, 0xC6, 0xB5, 0xBD, 0xFD, 0x39, 0x63, 0x20, 0xD4, 0x38, + 0x76, 0x7D, 0xB2, 0xA7, 0xCF, 0xED, 0x57, 0xC5, 0xF3, 0x2C, 0xBB, 0x14, 0x21, 0x06, 0x55, 0x9B, + 0xE3, 0xEF, 0x5E, 0x31, 0x4F, 0x7F, 0x5A, 0xA4, 0x0D, 0x82, 0x51, 0x49, 0x5F, 0xBA, 0x58, 0x1C, + 0x4A, 0x16, 0xD5, 0x17, 0xA8, 0x92, 0x24, 0x1F, 0x8C, 0xFF, 0xD8, 0xAE, 0x2E, 0x01, 0xD3, 0xAD, + 0x3B, 0x4B, 0xDA, 0x46, 0xEB, 0xC9, 0xDE, 0x9A, 0x8F, 0x87, 0xD7, 0x3A, 0x80, 0x6F, 0x2F, 0xC8, + 0xB1, 0xB4, 0x37, 0xF7, 0x0A, 0x22, 0x13, 0x28, 0x7C, 0xCC, 0x3C, 0x89, 0xC7, 0xC3, 0x96, 0x56, + 0x07, 0xBF, 0x7E, 0xF0, 0x0B, 0x2B, 0x97, 0x52, 0x35, 0x41, 0x79, 0x61, 0xA6, 0x4C, 0x10, 0xFE, + 0xBC, 0x26, 0x95, 0x88, 0x8A, 0xB0, 0xA3, 0xFB, 0xC0, 0x18, 0x94, 0xF2, 0xE1, 0xE5, 0xE9, 0x5D, + 0xD0, 0xDC, 0x11, 0x66, 0x64, 0x5C, 0xEC, 0x59, 0x42, 0x75, 0x12, 0xF5, 0x74, 0x9C, 0xAA, 0x23, + 0x0E, 0x86, 0xAB, 0xBE, 0x2A, 0x02, 0xE7, 0x67, 0xE6, 0x44, 0xA2, 0x6C, 0xC2, 0x93, 0x9F, 0xF1, + 0xF6, 0xFA, 0x36, 0xD2, 0x50, 0x68, 0x9E, 0x62, 0x71, 0x15, 0x3D, 0xD6, 0x40, 0xC4, 0xE2, 0x0F, + 0x8E, 0x83, 0x77, 0x6B, 0x25, 0x05, 0x3F, 0x0C, 0x30, 0xEA, 0x70, 0xB7, 0xA1, 0xE8, 0xA9, 0x65, + 0x8D, 0x27, 0x1A, 0xDB, 0x81, 0xB3, 0xA0, 0xF4, 0x45, 0x7A, 0x19, 0xDF, 0xEE, 0x78, 0x34, 0x60, + }, + { + 0x55, 0xC2, 0x63, 0x71, 0x3B, 0xC8, 0x47, 0x86, 0x9F, 0x3C, 0xDA, 0x5B, 0x29, 0xAA, 0xFD, 0x77, + 0x8C, 0xC5, 0x94, 0x0C, 0xA6, 0x1A, 0x13, 0x00, 0xE3, 0xA8, 0x16, 0x72, 0x40, 0xF9, 0xF8, 0x42, + 0x44, 0x26, 0x68, 0x96, 0x81, 0xD9, 0x45, 0x3E, 0x10, 0x76, 0xC6, 0xA7, 0x8B, 0x39, 0x43, 0xE1, + 0x3A, 0xB5, 0x56, 0x2A, 0xC0, 0x6D, 0xB3, 0x05, 0x22, 0x66, 0xBF, 0xDC, 0x0B, 0xFA, 0x62, 0x48, + 0xDD, 0x20, 0x11, 0x06, 0x36, 0xC9, 0xC1, 0xCF, 0xF6, 0x27, 0x52, 0xBB, 0x69, 0xF5, 0xD4, 0x87, + 0x7F, 0x84, 0x4C, 0xD2, 0x9C, 0x57, 0xA4, 0xBC, 0x4F, 0x9A, 0xDF, 0xFE, 0xD6, 0x8D, 0x7A, 0xEB, + 0x2B, 0x53, 0xD8, 0x5C, 0xA1, 0x14, 0x17, 0xFB, 0x23, 0xD5, 0x7D, 0x30, 0x67, 0x73, 0x08, 0x09, + 0xEE, 0xB7, 0x70, 0x3F, 0x61, 0xB2, 0x19, 0x8E, 0x4E, 0xE5, 0x4B, 0x93, 0x8F, 0x5D, 0xDB, 0xA9, + 0xAD, 0xF1, 0xAE, 0x2E, 0xCB, 0x0D, 0xFC, 0xF4, 0x2D, 0x46, 0x6E, 0x1D, 0x97, 0xE8, 0xD1, 0xE9, + 0x4D, 0x37, 0xA5, 0x75, 0x5E, 0x83, 0x9E, 0xAB, 0x82, 0x9D, 0xB9, 0x1C, 0xE0, 0xCD, 0x49, 0x89, + 0x01, 0xB6, 0xBD, 0x58, 0x24, 0xA2, 0x5F, 0x38, 0x78, 0x99, 0x15, 0x90, 0x50, 0xB8, 0x95, 0xE4, + 0xD0, 0x91, 0xC7, 0xCE, 0xED, 0x0F, 0xB4, 0x6F, 0xA0, 0xCC, 0xF0, 0x02, 0x4A, 0x79, 0xC3, 0xDE, + 0xA3, 0xEF, 0xEA, 0x51, 0xE6, 0x6B, 0x18, 0xEC, 0x1B, 0x2C, 0x80, 0xF7, 0x74, 0xE7, 0xFF, 0x21, + 0x5A, 0x6A, 0x54, 0x1E, 0x41, 0x31, 0x92, 0x35, 0xC4, 0x33, 0x07, 0x0A, 0xBA, 0x7E, 0x0E, 0x34, + 0x88, 0xB1, 0x98, 0x7C, 0xF3, 0x3D, 0x60, 0x6C, 0x7B, 0xCA, 0xD3, 0x1F, 0x32, 0x65, 0x04, 0x28, + 0x64, 0xBE, 0x85, 0x9B, 0x2F, 0x59, 0x8A, 0xD7, 0xB0, 0x25, 0xAC, 0xAF, 0x12, 0x03, 0xE2, 0xF2, + }, +}; + +const uint16 ZUC_D[16] = { + 042327, 023274, 061153, 011536, + 053611, 032742, 070465, 004657, + 046570, 027423, 065704, 015361, + 057046, 036115, 074232, 043654, +}; + +#define ZUC_S0(x) ZUC_S[0][x] +#define ZUC_S1(x) ZUC_S[1][x] +#define ZUC_S_BOX(X) \ + CONCAT_8x4( \ + ZUC_S0(EXTRACT_8_32(X, 0)), \ + ZUC_S1(EXTRACT_8_32(X, 1)), \ + ZUC_S0(EXTRACT_8_32(X, 2)), \ + ZUC_S1(EXTRACT_8_32(X, 3)) \ + ) + +/* S_BOX END */ + +/* MOD_OPERATIONS BEGIN */ + +#define ZUC_MOD_NUM 0x7FFFFFFF +uint32 zuc_add(uint32 a, uint32 b) { + uint32 c = a + b; + return (c & ZUC_MOD_NUM) + (c >> 31); +} +uint32 zuc_mul(uint32 a, uint32 b) { + uint32 res = 0; + for (int i = 0; i < 31; ++i) { + if (b & (1 << i)) { + res = zuc_add(res, ROTATE_31(a, i)); + } + } + return res; +} +uint32 zuc_mul_powof2(uint32 a, uint32 log2b) { + return ROTATE_31(a, log2b); +} + +/* MOD_OPERATIONS END */ + +/* LFSR BEGIN */ + +typedef struct ZUC_LFSR_st { + uint32 S[16]; /* 31-bit */ +} ZUC_LFSR; + +void zuc_lfsr_init(ZUC_LFSR *lfsr, uint32 u) { /* u: 31-bit */ + uint32 v = zuc_add( + zuc_add( + zuc_add( + zuc_mul_powof2(lfsr->S[15], 15), + zuc_mul_powof2(lfsr->S[13], 17) + ), + zuc_add( + zuc_mul_powof2(lfsr->S[10], 21), + zuc_mul_powof2(lfsr->S[4], 20) + ) + ), + zuc_add(lfsr->S[0], zuc_mul_powof2(lfsr->S[0], 8)) + ); + uint32 S16 = zuc_add(v, u); + S16 = zuc_add(S16, ZUC_MOD_NUM); + for (int i = 0; i < 15; ++i) { + lfsr->S[i] = lfsr->S[i + 1]; + } + lfsr->S[15] = S16; +} +void zuc_lfsr_work(ZUC_LFSR *lfsr) { + uint32 S16 = zuc_add( + zuc_add( + zuc_add( + zuc_mul_powof2(lfsr->S[15], 15), + zuc_mul_powof2(lfsr->S[13], 17) + ), + zuc_add( + zuc_mul_powof2(lfsr->S[10], 21), + zuc_mul_powof2(lfsr->S[4], 20) + ) + ), + zuc_add(lfsr->S[0], zuc_mul_powof2(lfsr->S[0], 8)) + ); + S16 = zuc_add(S16, ZUC_MOD_NUM); + for (int i = 0; i < 15; ++i) { + lfsr->S[i] = lfsr->S[i + 1]; + } + lfsr->S[15] = S16; +} + +/* LFSR END */ + +/* BR BEGIN */ + +typedef struct ZUC_BR_st { + uint32 X[4]; /* 32-bit */ +} ZUC_BR_CTX; + +void zuc_br(ZUC_BR_CTX *br, ZUC_LFSR *lfsr) { + br->X[0] = CONCAT_16x2(EXTRACT_16H_31(lfsr->S[15]), EXTRACT_16L_31(lfsr->S[14])); + br->X[1] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[11]), EXTRACT_16H_31(lfsr->S[9])); + br->X[2] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[7]), EXTRACT_16H_31(lfsr->S[5])); + br->X[3] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[2]), EXTRACT_16H_31(lfsr->S[0])); +} + +/* BR END */ + +/* F BEGIN */ + +#define ZUC_L1(X) \ + ((X) ^ ROTATE((X), 2) ^ ROTATE((X), 10) ^ ROTATE((X), 18) ^ ROTATE((X), 24)) +#define ZUC_L2(X) \ + ((X) ^ ROTATE((X), 8) ^ ROTATE((X), 14) ^ ROTATE((X), 22) ^ ROTATE((X), 30)) + +typedef struct ZUC_F_st { + uint32 R1, R2; /* 32-bit */ +} ZUC_F_CTX; + +uint32 zuc_f(ZUC_F_CTX *f, ZUC_BR_CTX *br) { /* X: 32-bit */ + uint32 X0 = br->X[0], X1 = br->X[1], X2 = br->X[2]; + uint32 R1 = f->R1, R2 = f->R2; + uint32 W = (X0 ^ R1) + R2; + uint32 W1 = R1 + X1; + uint32 W2 = R2 ^ X2; + R1 = ZUC_S_BOX(ZUC_L1(CONCAT_16x2( + EXTRACT_16_32(W1, 1), + EXTRACT_16_32(W2, 0) + ))); + R2 = ZUC_S_BOX(ZUC_L2(CONCAT_16x2( + EXTRACT_16_32(W2, 1), + EXTRACT_16_32(W1, 0) + ))); + f->R1 = R1; + f->R2 = R2; + return W; +} + +/* F END */ + +/* ZUC_MAIN BEGIN */ + +#define ZUC_INIT_CONCAT(k, d, iv) (((uint32)(k) << 15 | (d)) << 8 | (iv)) +#define ZUC_INTEGRITY_CONCAT(K1, K2, offset) \ + (((K1) << (offset)) | ((offset) ? (K2) >> (32 - (offset)) : 0)) + +typedef struct ZUCstate_st { + ZUC_LFSR lfsr; + ZUC_BR_CTX br; + ZUC_F_CTX f; +} ZUC_CTX; + +/* Initiate phase. Both k and iv are uint8 arrays of length 16. */ +int zuc_init(ZUC_CTX *z, uint8 k[], uint8 iv[]) { + memset(z, 0, sizeof(*z)); + for (int i = 0; i < 16; ++i) { + z->lfsr.S[i] = ZUC_INIT_CONCAT(k[i], ZUC_D[i], iv[i]); + } + #ifdef SECGEAR_ZUC_DEBUG + printf("LSFR init: \n"); + for (int i = 0; i < 16; ++i) { + printf("%08x%c", z->lfsr.S[i], " \n"[(i & 7) == 7]); + } + #endif + for (int i = 0; i < 32; ++i) { + zuc_br(&z->br, &z->lfsr); + uint32 W = zuc_f(&z->f, &z->br); + zuc_lfsr_init(&z->lfsr, W >> 1); + #ifdef SECGEAR_ZUC_DEBUG + printf("Init round %2d: \n", i); + printf("BR_X: "); + for (int i = 0; i < 4; ++i) { + printf("%08x%c", z->br.X[i], " \n"[i == 3]); + } + printf("F_R: %08x %08x\n", z->f.R1, z->f.R2); + printf("W = %08x S15 = %08x\n", W, z->lfsr.S[15]); + #endif + } + return 1; +} + +/* Work phase. Z is uint32 array that stores output keys. */ +/* len is the length of the key in the unit of 32-bit. */ +int zuc_work(ZUC_CTX *z, uint32 Z[], size_t len) { + zuc_br(&z->br, &z->lfsr); + #ifndef SECGEAR_ZUC_DEBUG + (void)zuc_f(&z->f, &z->br); + #else + uint32 _Z = zuc_f(&z->f, &z->br) ^ z->br.X[3]; + #endif + zuc_lfsr_work(&z->lfsr); + #ifdef SECGEAR_ZUC_DEBUG + printf("Key stream: \n"); + printf("BR_X: "); + for (int i = 0; i < 4; ++i) { + printf("%08x%c", z->br.X[i], " \n"[i == 3]); + } + printf("F_R: %08x %08x\n", z->f.R1, z->f.R2); + printf("Z = %08x S15 = %08x\n", _Z, z->lfsr.S[15]); + #endif + for (size_t i = 0; i < len; ++i) { + zuc_br(&z->br, &z->lfsr); + Z[i] = zuc_f(&z->f, &z->br) ^ z->br.X[3]; + zuc_lfsr_work(&z->lfsr); + #ifdef SECGEAR_ZUC_DEBUG + printf("Key round %2zu: \n", i); + printf("BR_X: "); + for (int i = 0; i < 4; ++i) { + printf("%08x%c", z->br.X[i], " \n"[i == 3]); + } + printf("F_R: %08x %08x\n", z->f.R1, z->f.R2); + printf("Z = %08x S15 = %08x\n", Z[i], z->lfsr.S[15]); + #endif + } + return 1; +} + +/* Generate 32-bit ZUC key stream. Use the array Z[] to receive the output. */ +int zuc_final(uint8 k[], uint8 iv[], uint32 Z[], size_t len) { + ZUC_CTX res, *z; + z = &res; + zuc_init(z, k, iv); + #ifdef SECGEAR_ZUC_DEBUG + printf("After init: \n"); + printf("LSFR: \n"); + for (int i = 0; i < 16; ++i) { + printf("%08x%c", z->lfsr.S[i], " \n"[(i & 7) == 7]); + } + printf("F_R: %08x %08x\n", z->f.R1, z->f.R2); + #endif + zuc_work(z, Z, len); + #ifdef SECGEAR_ZUC_DEBUG + printf("Output: \n"); + for (size_t i = 0; i < len; ++i) { + printf("z[%2zu] = %08x\n", i, Z[i]); + } + #endif + return 1; +} + +/* Use the array obs[] to receive the output. */ +int zuc_confidentiality(uint32 count, uint8 bearer, uint8 direction, uint8 ck[], + uint32 length, uint32 ibs[], uint32 obs[]) { + /* + * @param COUNT (length = 32b, counter) + * @param BEARER (length = 5b, bearer identifier) + * @param DIRECTION (length = 1b, direction identifier) + * @param CK (length = 128b = 8b * 16, confidential key) + * @param LENGTH (length = 32b, bit length of input bit stream) + * @param IBS (length = LENGTH b = 32b * L, input bit stream) + * @param OBS (length = LENGTH b = 32b * L, output bit stream) + */ + + /* Initiate k and iv for ZUC. */ + bearer &= 0x1F; direction &= 1; + uint8 _k[16], _iv[16], _count[4]; + memcpy(_k, ck, sizeof _k); + for (int i = 0; i < 4; ++i) { + _count[i] = EXTRACT_8_32(count, i); + } + _iv[0] = _count[0]; _iv[1] = _count[1]; _iv[2] = _count[2]; _iv[3] = _count[3]; + _iv[4] = (uint8)((bearer << 1 | direction) << 2); _iv[5] = _iv[6] = _iv[7] = 0; + for (int i = 8; i < 16; ++i) { + _iv[i] = _iv[i ^ 8]; + } + size_t L = (length >> 5) + ((length & 0x1F) ? 1 : 0); + uint32 Z[L]; + zuc_final(_k, _iv, Z, L); + for (size_t i = 0; i < L; ++i) { + obs[i] = ibs[i] ^ Z[i]; + } + if (length & 0x1F) { + obs[L - 1] &= PREFIX_MASK_32[length & 0x1F]; + } + #ifdef SECGEAR_ZUC_DEBUG_2 + printf("Output: \n"); + for (size_t i = 0; i < L; ++i) { + printf("%08x%c", obs[i], " \n"[i % 10 == 9]); + } + putchar('\n'); + #endif + return 1; +} + +uint32 zuc_integrity(uint32 count, uint8 bearer, uint8 direction, uint8 ik[], + uint32 length, uint32 M[]) { + /* + * @param COUNT (length = 32b, counter) + * @param BEARER (length = 5b, bearer identifier) + * @param DIRECTION (length = 1b, direction identifier) + * @param IK (length = 128b = 8b * 16, integrity key) + * @param LENGTH (length = 32b, bit length of input bit stream) + * @param M (length = LENGTH b = 32b * L, input massage stream) + * @return MAC (length = 32b, massage verification code) + */ + + /* Initiate k and iv for ZUC. */ + bearer &= 0x1F; direction &= 1; + uint8 _k[16], _iv[16], _count[4]; + memcpy(_k, ik, sizeof _k); + for (int i = 0; i < 4; ++i) { + _count[i] = EXTRACT_8_32(count, i); + } + _iv[0] = _count[0]; _iv[1] = _count[1]; _iv[2] = _count[2]; _iv[3] = _count[3]; + _iv[4] = (uint8)(bearer << 3); _iv[5] = _iv[6] = _iv[7] = 0; + _iv[8] = _iv[0] ^ (uint8)(direction << 7); + _iv[9] = _iv[1]; _iv[10] = _iv[2]; _iv[11] = _iv[3]; + _iv[12] = _iv[4]; _iv[13] = _iv[5]; + _iv[14] = _iv[6] ^ (uint8)(direction << 7); + _iv[15] = _iv[7]; + size_t L = (length >> 5) + ((length & 0x1F) ? 1 : 0) + 2; + uint32 Z[L]; + uint32 T = 0; + zuc_final(_k, _iv, Z, L); + for (size_t i = 0; i < length; ++i) { + if (GET_BIT_VALUE_32(M[i >> 5], i & 0x1F)) { + T = T ^ ZUC_INTEGRITY_CONCAT(Z[i >> 5], Z[(i >> 5) + 1], i & 0x1F); + } + } + T = T ^ ZUC_INTEGRITY_CONCAT(Z[length >> 5], Z[(length >> 5) + 1], length & 0x1F); + T = T ^ Z[L - 1]; + #ifdef SECGEAR_ZUC_DEBUG_3 + printf("Output: \n"); + printf("%08x\n", T); + #endif + return T; +} + +/* ZUC_MAIN END */ + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest1.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest1.c" new file mode 100644 index 0000000..b8a8386 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest1.c" @@ -0,0 +1,84 @@ +#define SECGEAR_ZUC_DEBUG +#include +#include "zuc.h" + +uint8 k_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +uint8 iv_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +uint8 k_test2[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; +uint8 iv_test2[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; + +uint8 k_test3[16] = { + 0x3D, 0x4C, 0x4B, 0xE9, + 0x6A, 0x82, 0xFD, 0xAE, + 0xB5, 0x8F, 0x64, 0x1D, + 0xB1, 0x7B, 0x45, 0x5B, +}; +uint8 iv_test3[16] = { + 0x84, 0x31, 0x9A, 0xA8, + 0xDE, 0x69, 0x15, 0xCA, + 0x1F, 0x6B, 0xDA, 0x6B, + 0xFB, 0xD8, 0xC7, 0x66, +}; + +void zuc_test(uint8 k[], uint8 iv[]) { + // ZUC_CTX res; + // ZUC_CTX *z = &res; + // zuc_init(z, k, iv); + // #ifdef SECGEAR_ZUC_DEBUG + // printf("After init: \n"); + // printf("LSFR: \n"); + // for (int i = 0; i < 16; ++i) { + // printf("%08x%c", z->lfsr.S[i], " \n"[(i & 7) == 7]); + // } + // printf("F_R: %08x %08x\n", z->f.R1, z->f.R2); + // #endif + const size_t LEN = 32; + uint32 keys[LEN]; + zuc_final(k, iv, keys, LEN); + // zuc_work(z, keys, LEN); + // printf("Output: \n"); + // for (size_t i = 0; i < LEN; ++i) { + // printf("z[%2zu] = %08x\n", i, keys[i]); + // } +} + + + +int main(){ + printf("Test 1: \n"); + zuc_test(k_test1, iv_test1); + printf("Test 2: \n"); + zuc_test(k_test2, iv_test2); + printf("Test 3: \n"); + zuc_test(k_test3, iv_test3); + // uint32 a,b,log2b; + // scanf("%u%u",&a,&log2b); + // b = 1u << log2b; + // // scanf("%u%u",&a,&b); + // printf("%u %u\n",a,b); + // printf("add: %u\n",zuc_add(a,b)); + // printf("mul: %u\n",zuc_mul(a,b)); + // printf("mul with 2p: %u\n",zuc_mul_powof2(a,log2b)); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest2.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest2.c" new file mode 100644 index 0000000..04899d4 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest2.c" @@ -0,0 +1,80 @@ +#define SECGEAR_ZUC_DEBUG_2 +#include +#include "zuc.h" + +uint8 ck_test1[16] = { + 0x17, 0x3d, 0x14, 0xba, + 0x50, 0x03, 0x73, 0x1d, + 0x7a, 0x60, 0x04, 0x94, + 0x70, 0xf0, 0x0a, 0x29, +}; +uint32 count_test1 = 0x66035492; +uint8 bearer_test1 = 0xf; +uint8 dirc_test1 = 0x0; +uint32 len_test1 = 0xc1; +uint32 ibs_test1[] = { + 0x6cf65340, 0x735552ab, 0x0c9752fa, 0x6f9025fe, 0x0bd675d9, + 0x005875b2, 0x00000000, +}; + +uint8 ck_test2[16] = { + 0xe5, 0xbd, 0x3e, 0xa0, + 0xeb, 0x55, 0xad, 0xe8, + 0x66, 0xc6, 0xac, 0x58, + 0xbd, 0x54, 0x30, 0x2a, +}; +uint32 count_test2 = 0x56823; +uint8 bearer_test2 = 0x18; +uint8 dirc_test2 = 0x1; +uint32 len_test2 = 0x320; +uint32 ibs_test2[] = { + 0x14a8ef69, 0x3d678507, 0xbbe7270a, 0x7f67ff50, 0x06c3525b, + 0x9807e467, 0xc4e56000, 0xba338f5d, 0x42955903, 0x67518222, + 0x46c80d3b, 0x38f07f4b, 0xe2d8ff58, 0x05f51322, 0x29bde93b, + 0xbbdcaf38, 0x2bf1ee97, 0x3fbf9977, 0xbada8945, 0x847a2a6c, + 0x9ad34a66, 0x7554e04d, 0x1f7fa2c3, 0x3241bd8f, 0x01ba220d, +}; + +uint8 ck_test3[16] = { + 0xe1, 0x3f, 0xed, 0x21, + 0xb4, 0x6e, 0x4e, 0x7e, + 0xc3, 0x12, 0x53, 0xb2, + 0xbb, 0x17, 0xb3, 0xe0, +}; +uint32 count_test3 = 0x2738cdaa; +uint8 bearer_test3 = 0x1a; +uint8 dirc_test3 = 0x0; +uint32 len_test3 = 0xfb3; +uint32 ibs_test3[] = { + 0x8d74e20d, 0x54894e06, 0xd3cb13cb, 0x3933065e, 0x8674be62, 0xadb1c72b, 0x3a646965, 0xab63cb7b, 0x7854dfdc, 0x27e84929, + 0xf49c64b8, 0x72a490b1, 0x3f957b64, 0x827e71f4, 0x1fbd4269, 0xa42c97f8, 0x24537027, 0xf86e9f4a, 0xd82d1df4, 0x51690fdd, + 0x98b6d03f, 0x3a0ebe3a, 0x312d6b84, 0x0ba5a182, 0x0b2a2c97, 0x09c090d2, 0x45ed267c, 0xf845ae41, 0xfa975d33, 0x33ac3009, + 0xfd40eba9, 0xeb5b8857, 0x14b768b6, 0x97138baf, 0x21380eca, 0x49f644d4, 0x8689e421, 0x5760b906, 0x739f0d2b, 0x3f091133, + 0xca15d981, 0xcbe401ba, 0xf72d05ac, 0xe05cccb2, 0xd297f4ef, 0x6a5f58d9, 0x1246cfa7, 0x7215b892, 0xab441d52, 0x78452795, + 0xccb7f5d7, 0x9057a1c4, 0xf77f80d4, 0x6db2033c, 0xb79bedf8, 0xe60551ce, 0x10c667f6, 0x2a97abaf, 0xabbcd677, 0x2018df96, + 0xa282ea73, 0x7ce2cb33, 0x1211f60d, 0x5354ce78, 0xf9918d9c, 0x206ca042, 0xc9b62387, 0xdd709604, 0xa50af16d, 0x8d35a890, + 0x6be484cf, 0x2e74a928, 0x99403643, 0x53249b27, 0xb4c9ae29, 0xeddfc7da, 0x6418791a, 0x4e7baa06, 0x60fa6451, 0x1f2d685c, + 0xc3a5ff70, 0xe0d2b742, 0x92e3b8a0, 0xcd6b04b1, 0xc790b8ea, 0xd2703708, 0x540dea2f, 0xc09c3da7, 0x70f65449, 0xe84d817a, + 0x4f551055, 0xe19ab850, 0x18a0028b, 0x71a144d9, 0x6791e9a3, 0x57793350, 0x4eee0060, 0x340c69d2, 0x74e1bf9d, 0x805dcbcc, + 0x1a6faa97, 0x6800b6ff, 0x2b671dc4, 0x63652fa8, 0xa33ee509, 0x74c1c21b, 0xe01eabb2, 0x16743026, 0x9d72ee51, 0x1c9dde30, + 0x797c9a25, 0xd86ce74f, 0x5b961be5, 0xfdfb6807, 0x814039e7, 0x137636bd, 0x1d7fa9e0, 0x9efd2007, 0x505906a5, 0xac45dfde, + 0xed7757bb, 0xee745749, 0xc2963335, 0x0bee0ea6, 0xf409df45, 0x80160000, +}; + +void zuc_test2(uint32 count, uint8 bearer, uint8 direction, uint8 ck[], + uint32 length, uint32 ibs[], uint32 obs[]) { + zuc_confidentiality(count, bearer, direction, ck, length, ibs, obs); +} + + + +int main(){ + uint32 obs_test[130]; + printf("Test 1: \n"); + zuc_test2(count_test1, bearer_test1, dirc_test1, ck_test1, len_test1, ibs_test1, obs_test); + printf("Test 2: \n"); + zuc_test2(count_test2, bearer_test2, dirc_test2, ck_test2, len_test2, ibs_test2, obs_test); + printf("Test 3: \n"); + zuc_test2(count_test3, bearer_test3, dirc_test3, ck_test3, len_test3, ibs_test3, obs_test); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest3.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest3.c" new file mode 100644 index 0000000..545ee92 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/C_origin/zuc/zuctest3.c" @@ -0,0 +1,83 @@ +#define SECGEAR_ZUC_DEBUG_3 +#include +#include "zuc.h" + +uint8 ik_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +uint32 count_test1 = 0; +uint8 bearer_test1 = 0; +uint8 dirc_test1 = 0; +uint32 len_test1 = 1; +uint32 m_test1[] = { + 0x00000000, +}; + +uint8 ik_test2[16] = { + 0xc9, 0xe6, 0xce, 0xc4, + 0x60, 0x7c, 0x72, 0xdb, + 0x00, 0x0a, 0xef, 0xa8, + 0x83, 0x85, 0xab, 0x0a, +}; +uint32 count_test2 = 0xa94059da; +uint8 bearer_test2 = 0xa; +uint8 dirc_test2 = 0x1; +uint32 len_test2 = 0x241; +uint32 m_test2[] = { + 0x983b41d4, 0x7d780c9e, 0x1ad11d7e, 0xb70391b1, 0xde0b35da, 0x2dc62f83, 0xe7b78d63, 0x06ca0ea0, 0x7e941b7b, + 0xe91348f9, 0xfcb170e2, 0x217fecd9, 0x7f9f68ad, 0xb16e5d7d, 0x21e569d2, 0x80ed775c, 0xebde3f40, 0x93c53881, + 0x00000000, +}; + +uint8 ik_test3[16] = { + 0x6b, 0x8b, 0x08, 0xee, + 0x79, 0xe0, 0xb5, 0x98, + 0x2d, 0x6d, 0x12, 0x8e, + 0xa9, 0xf2, 0x20, 0xcb, +}; +uint32 count_test3 = 0x561eb2dd; +uint8 bearer_test3 = 0x1c; +uint8 dirc_test3 = 0x0; +uint32 len_test3 = 0x1626; +uint32 m_test3[] = { + 0x5bad7247, 0x10ba1c56, 0xd5a315f8, 0xd40f6e09, 0x3780be8e, 0x8de07b69, 0x92432018, 0xe08ed96a, 0x5734af8b, + 0xad8a575d, 0x3a1f162f, 0x85045cc7, 0x70925571, 0xd9f5b94e, 0x454a77c1, 0x6e72936b, 0xf016ae15, 0x7499f054, + 0x3b5d52ca, 0xa6dbeab6, 0x97d2bb73, 0xe41b8075, 0xdce79b4b, 0x86044f66, 0x1d4485a5, 0x43dd7860, 0x6e0419e8, + 0x059859d3, 0xcb2b67ce, 0x0977603f, 0x81ff839e, 0x33185954, 0x4cfbc8d0, 0x0fef1a4c, 0x8510fb54, 0x7d6b06c6, + 0x11ef44f1, 0xbce107cf, 0xa45a06aa, 0xb360152b, 0x28dc1ebe, 0x6f7fe09b, 0x0516f9a5, 0xb02a1bd8, 0x4bb0181e, + 0x2e89e19b, 0xd8125930, 0xd178682f, 0x3862dc51, 0xb636f04e, 0x720c47c3, 0xce51ad70, 0xd94b9b22, 0x55fbae90, + 0x6549f499, 0xf8c6d399, 0x47ed5e5d, 0xf8e2def1, 0x13253e7b, 0x08d0a76b, 0x6bfc68c8, 0x12f375c7, 0x9b8fe5fd, + 0x85976aa6, 0xd46b4a23, 0x39d8ae51, 0x47f680fb, 0xe70f978b, 0x38effd7b, 0x2f7866a2, 0x2554e193, 0xa94e98a6, + 0x8b74bd25, 0xbb2b3f5f, 0xb0a5fd59, 0x887f9ab6, 0x8159b717, 0x8d5b7b67, 0x7cb546bf, 0x41eadca2, 0x16fc1085, + 0x0128f8bd, 0xef5c8d89, 0xf96afa4f, 0xa8b54885, 0x565ed838, 0xa950fee5, 0xf1c3b0a4, 0xf6fb71e5, 0x4dfd169e, + 0x82cecc72, 0x66c850e6, 0x7c5ef0ba, 0x960f5214, 0x060e71eb, 0x172a75fc, 0x1486835c, 0xbea65344, 0x65b055c9, + 0x6a72e410, 0x52241823, 0x25d83041, 0x4b40214d, 0xaa8091d2, 0xe0fb010a, 0xe15c6de9, 0x0850973b, 0xdf1e423b, + 0xe148a237, 0xb87a0c9f, 0x34d4b476, 0x05b803d7, 0x43a86a90, 0x399a4af3, 0x96d3a120, 0x0a62f3d9, 0x507962e8, + 0xe5bee6d3, 0xda2bb3f7, 0x237664ac, 0x7a292823, 0x900bc635, 0x03b29e80, 0xd63f6067, 0xbf8e1716, 0xac25beba, + 0x350deb62, 0xa99fe031, 0x85eb4f69, 0x937ecd38, 0x7941fda5, 0x44ba67db, 0x09117749, 0x38b01827, 0xbcc69c92, + 0xb3f772a9, 0xd2859ef0, 0x03398b1f, 0x6bbad7b5, 0x74f7989a, 0x1d10b2df, 0x798e0dbf, 0x30d65874, 0x64d24878, + 0xcd00c0ea, 0xee8a1a0c, 0xc753a279, 0x79e11b41, 0xdb1de3d5, 0x038afaf4, 0x9f5c682c, 0x3748d8a3, 0xa9ec54e6, + 0xa371275f, 0x1683510f, 0x8e4f9093, 0x8f9ab6e1, 0x34c2cfdf, 0x4841cba8, 0x8e0cff2b, 0x0bcc8e6a, 0xdcb71109, + 0xb5198fec, 0xf1bb7e5c, 0x531aca50, 0xa56a8a3b, 0x6de59862, 0xd41fa113, 0xd9cd9578, 0x08f08571, 0xd9a4bb79, + 0x2af271f6, 0xcc6dbb8d, 0xc7ec36e3, 0x6be1ed30, 0x8164c31c, 0x7c0afc54, 0x1c000000, +}; + +uint32 zuc_test3(uint32 count, uint8 bearer, uint8 direction, uint8 ik[], + uint32 length, uint32 M[]) { + return zuc_integrity(count, bearer, direction, ik, length, M); +} + + + +int main(){ + printf("Test 1: \n"); + zuc_test3(count_test1, bearer_test1, dirc_test1, ik_test1, len_test1, m_test1); + printf("Test 2: \n"); + zuc_test3(count_test2, bearer_test2, dirc_test2, ik_test2, len_test2, m_test2); + printf("Test 3: \n"); + zuc_test3(count_test3, bearer_test3, dirc_test3, ik_test3, len_test3, m_test3); + return 0; +} \ No newline at end of file -- Gitee From 6d22c008a32a14fb2210f37dfb97262598bfd761 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:54:08 +0000 Subject: [PATCH 11/18] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20Formal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Formal/.keep" | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/.keep" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/.keep" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/.keep" new file mode 100644 index 0000000..e69de29 -- Gitee From ee03bb47eeadb76beca71fe70306b049d087f15a Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:54:52 +0000 Subject: [PATCH 12/18] enclave_sm2 Signed-off-by: wangxiaoxi1 --- .../Formal/enclave_SM2/CMakeLists.txt" | 38 ++ .../enclave_SM2/enclave/CMakeLists.txt" | 162 ++++++ .../enclave_SM2/enclave/Enclave.config.xml" | 12 + .../Formal/enclave_SM2/enclave/Enclave.lds" | 11 + .../Formal/enclave_SM2/enclave/enclave_SM2.c" | 116 ++++ .../enclave_SM2/enclave/manifest.txt.in" | 8 + .../enclave/rsa_public_key_cloud.pem" | 11 + .../Formal/enclave_SM2/enclave/sm2.h" | 207 +++++++ .../Formal/enclave_SM2/enclave/sm2_crypt.h" | 204 +++++++ .../enclave_SM2/enclave/sm2_exchange.h" | 335 +++++++++++ .../Formal/enclave_SM2/enclave/sm2_sign.h" | 189 ++++++ .../Formal/enclave_SM2/enclave/sm2_tests.h" | 152 +++++ .../Formal/enclave_SM2/enclave_SM2.edl" | 30 + .../Formal/enclave_SM2/host/CMakeLists.txt" | 88 +++ .../Formal/enclave_SM2/host/main.cpp" | 127 ++++ .../enclave_SM2/include/common_utils.h" | 69 +++ .../Formal/enclave_SM2/include/ec.h" | 545 ++++++++++++++++++ .../Formal/enclave_SM2/sm3/sm3.h" | 183 ++++++ 18 files changed, 2487 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.config.xml" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.lds" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/enclave_SM2.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/manifest.txt.in" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/rsa_public_key_cloud.pem" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_crypt.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_exchange.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_sign.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_tests.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave_SM2.edl" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/main.cpp" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/include/common_utils.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/include/ec.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/sm3/sm3.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/CMakeLists.txt" new file mode 100644 index 0000000..bfc5416 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/CMakeLists.txt" @@ -0,0 +1,38 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +project(enclave_SM2) + +set(CMAKE_C_STANDARD 99) + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE enclave_SM2.edl) +#set(LOCAL_ROOT_PATH "$ENV{CC_SDK}") +#set(SECGEAR_INSTALL_PATH /usr/lib64/) + +if(CC_GP) + set(CODETYPE trustzone) + set(CODEGEN codegen_arm64) + execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) + string(REPLACE "\n" "" UUID ${UUID}) + add_definitions(-DPATH="/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + set(CODEGEN codegen_x86_64) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/CMakeLists.txt" new file mode 100644 index 0000000..7d04cf0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/CMakeLists.txt" @@ -0,0 +1,162 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM2) + +set(CMAKE_C_STANDARD 99) +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave_SM2.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + #set itrustee device key + set(DEVICEPEM ${CMAKE_CURRENT_SOURCE_DIR}/rsa_public_key_cloud.pem) + #set whilelist. default: /vendor/bin/teec_hello + set(WHITE_LIST_0 /vendor/bin/enclave_SM2) + set(WHITE_LIST_OWNER root) + set(WHITE_LIST_1 /vendor/bin/secgear_enclave_SM2) + set(WHITELIST WHITE_LIST_0 WHITE_LIST_1) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(COMMON_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \ + -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") +set(COMMON_CXX_FLAGS "${COMMON_C_FLAGS}") + +if(CC_GP) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt") + + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/enclave_inc + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${SECGEAR_INSTALL_PATH}) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -lsecgear_tee) + + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i /home/sunny/secGear/debug/lib/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT} + DESTINATION /data + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -O2 -nostdinc++") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE + ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.config.xml" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.config.xml" new file mode 100644 index 0000000..a5e05e0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.config.xml" @@ -0,0 +1,12 @@ + + 0 + 0 + 0x100000 + 0x80000 + 10 + 1 + + 1 + 0 + 0xFFFFFFFF + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.lds" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.lds" new file mode 100644 index 0000000..ab77e64 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/Enclave.lds" @@ -0,0 +1,11 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/enclave_SM2.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/enclave_SM2.c" new file mode 100644 index 0000000..9d06a88 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/enclave_SM2.c" @@ -0,0 +1,116 @@ +#include "Enclave1_t.h" +#define SM2_EXCHANGE_OPTIONAL +#include "sm2.h" +#include "sm2_tests.h" + +/* + * Ref: + * GB/T 32918.5-2017 + */ + +const int SM2_p_bytes = 256 >> 3; +uint8 *sign_ID_A; +uint8 *sign_M; +uint8 sign_dA[SM2_p_bytes]; +uint8 sign_k[SM2_p_bytes]; + +void setSignIDA(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(sign_ID_A, src, len + 1); + } +} + +void setSignM(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(sign_M, src, len + 1); + } +} + +void setSignDA(uint8 *src) { + memcpy(sign_dA, src, SM2_p_bytes); +} + +void setSignK(uint8 *src) { + memcpy(sign_k, src, SM2_p_bytes); +} + +void getSignResult(uint8 *buf, size_t len) { + if (len > strlen(sign_buffer)) { + memcpy(buf, sign_buffer, strlen(sign_buffer) + 1); + } +} + +void getSignVerifyResult(uint8 buf) { + memcpy(buf, &sign_verify_ret, 1); +} + +void callsm2signtest() { + sm2signtest(SM2_p_bytes, sign_M, sign_ID_A, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, sign_dA, sign_k); +} + +uint8 *exchange_ID_A; +uint8 *exchange_ID_B; +uint8 exchange_dA[SM2_p_bytes]; +uint8 exchange_dB[SM2_p_bytes]; +uint64 exchange_klen = 128; + +void setExchangeIDA(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(exchange_ID_A, src, len + 1); + } +} + +void setExchangeIDB(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(exchange_ID_B, src, len + 1); + } +} + +void setExchangeDA(uint8 *src) { + memcpy(exchange_dA, src, SM2_p_bytes); +} + +void setExchangeDB(uint8 *src) { + memcpy(exchange_dB, src, SM2_p_bytes); +} + +void setExchangeKLen(uint64 *src) { + memcpy(exchange_klen, src, sizeof(uint64)); +} + +void getExchangeResult(uint8 buf) { + memcpy(buf, &exchange_ret, 1); +} + +void callsm2exchangetest() { + sm2exchangetest(SM2_p_bytes, exchange_ID_A, exchange_ID_B, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, exchange_dA, exchange_dB, exchange_klen); +} + +uint8 *crypt_M; +uint8 crypt_dB[SM2_p_bytes]; + +void setCryptM(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(crypt_M, src, len + 1); + } +} + +void setCryptDB(uint8 *src) { + memcpy(crypt_dB, src, SM2_p_bytes); +} + +void getCryptPW(uint8 *buf, size_t len) { + if (len > strlen(encrypt_pw)) { + memcpy(buf, encrypt_pw, strlen(encrypt_pw) + 1); + } +} + +void getCryptMSG(uint8 *buf, size_t len) { + if (len > strlen(decrypt_msg)) { + memcpy(buf, decrypt_msg, strlen(decrypt_msg) + 1); + } +} + +void callsm2crypttest() { + sm2crypttest(SM2_p_bytes, crypt_M, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, crypt_dB); +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/manifest.txt.in" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/manifest.txt.in" new file mode 100644 index 0000000..7b8ecf5 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/manifest.txt.in" @@ -0,0 +1,8 @@ +gpd.ta.appID: @UUID@ +gpd.ta.service_name: test0108 +gpd.ta.singleInstance: true +gpd.ta.multiSession: false +gpd.ta.multiCommand: false +gpd.ta.instanceKeepAlive: false +gpd.ta.dataSize: 16384 +gpd.ta.stackSize: 20480 diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/rsa_public_key_cloud.pem" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/rsa_public_key_cloud.pem" new file mode 100644 index 0000000..a321f63 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/rsa_public_key_cloud.pem" @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzAPwbnbgBg7JgXERA9Bx +p7GLI1S3e1zL83RMd2+GXb6kO4yMKUL3NUCE2HhA2BtQYmLyGovx59UUcKnU58is +Xux++kH+A2shmOPjYvEFuX0Kt8tc19b8M9b/iHsY8ZmKykqia2a5U+IrECRFJo5p +DWUnl7jrHVtq78BSR1c7iXG1frrEC0AYCuqKJo/fxfmOKL0Y9mENCB3nAwjn9unD +BsO/OhkqvvB3nkeuMfNKPh4wCqtQPve13eTojbuxjX/3ePijplTI5X2Gr+n6Ximn +fYRlytQmMgMl/db0ARSKNApq9bmwzVNrnGWWZWJksdRvf6iL7t17Gs4L9AApOuC9 +WkzxPvwp5ZUqjsGd4oJGWeC6ZE6BTw2vxE+xMFI9uAKHxq9pBKkcGMa0g4fANNNV ++W+8JZGanxEXKB3y/M7BCyQAPCWOHC/RNjmRA1gczLYCPzC4pWu935UZdF1RR6zY +CD3t+FoOGGET/g4CwWgyhb5qkp65Hs6ayYt/DUAqo+yBAgMBAAE= +-----END PUBLIC KEY----- diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2.h" new file mode 100644 index 0000000..27bf249 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2.h" @@ -0,0 +1,207 @@ +#ifndef SECGEAR_SM2_H +#define SECGEAR_SM2_H + +/* + * Ref: + * GB/T 32918.1-2016 + * GB/T 32918.2-2016 + * GB/T 32918.3-2016 + * GB/T 32918.4-2016 + * GB/T 32918.5-2017 + */ + +#include +#include "../include/common_utils.h" +#include "../include/ec.h" +#include "../sm3/sm3.h" +#define SM2ERR(msg) goto err; +/* + * export C_INCLUDE_PATH="/PATH/TO/OPENSSL/include"(/opt/homebrew/Cellar/openssl@1.1/1.1.1m/include) + * export CPLUS_INCLUDE_PATH="/PATH/TO/OPENSSL/include" + * export LIBRARY_PATH="/PATH/TO/OPENSSL/lib" + */ + +/* Parameters */ +/* EC: y^2 = x^3 + ax + b */ + +#define SM2_PARAM_CBLOCK 32 +#define SM2_PARAM_LBLOCK (SM2_PARAM_CBLOCK/4) + +const uint8 SM2_P[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; +const uint8 SM2_A[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, +}; +const uint8 SM2_B[SM2_PARAM_CBLOCK] = { + 0x28, 0xE9, 0xFA, 0x9E, + 0x9D, 0x9F, 0x5E, 0x34, + 0x4D, 0x5A, 0x9E, 0x4B, + 0xCF, 0x65, 0x09, 0xA7, + 0xF3, 0x97, 0x89, 0xF5, + 0x15, 0xAB, 0x8F, 0x92, + 0xDD, 0xBC, 0xBD, 0x41, + 0x4D, 0x94, 0x0E, 0x93, +}; +const uint8 SM2_N[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x72, 0x03, 0xDF, 0x6B, + 0x21, 0xC6, 0x05, 0x2B, + 0x53, 0xBB, 0xF4, 0x09, + 0x39, 0xD5, 0x41, 0x23, +}; +const uint8 SM2_XG[SM2_PARAM_CBLOCK] = { + 0x32, 0xC4, 0xAE, 0x2C, + 0x1F, 0x19, 0x81, 0x19, + 0x5F, 0x99, 0x04, 0x46, + 0x6A, 0x39, 0xC9, 0x94, + 0x8F, 0xE3, 0x0B, 0xBF, + 0xF2, 0x66, 0x0B, 0xE1, + 0x71, 0x5A, 0x45, 0x89, + 0x33, 0x4C, 0x74, 0xC7, +}; +const uint8 SM2_YG[SM2_PARAM_CBLOCK] = { + 0xBC, 0x37, 0x36, 0xA2, + 0xF4, 0xF6, 0x77, 0x9C, + 0x59, 0xBD, 0xCE, 0xE3, + 0x6B, 0x69, 0x21, 0x53, + 0xD0, 0xA9, 0x87, 0x7C, + 0xC6, 0x2A, 0x47, 0x40, + 0x02, 0xDF, 0x32, 0xE5, + 0x21, 0x39, 0xF0, 0xA0, +}; + +typedef struct sm2_sig_st { + BIGNUM *r; + BIGNUM *s; +} SM2_SIG; + +int SM2_SIG_init(SM2_SIG *sig) { + sig->r = BN_new(); + sig->s = BN_new(); + if (sig->r == NULL || sig->s == NULL) { + BN_free(sig->r); + BN_free(sig->s); + return 0; + } + return 1; +} + +SM2_SIG *SM2_SIG_new() { + SM2_SIG *ret; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!SM2_SIG_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int sm2_compute_z(uint8 *out, const uint8 *id, const size_t idlen, const EC_KEY *key){ + /* ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */ + uint16 entlen = idlen << 3; + uint8 e_bytes, *buf; + int p_bytes; + SM3_CTX c; + sm3_init(&c); + if (idlen > (UINT16_MAX >> 3)) { + SM2ERR("SM2_compute_z(): idlen too large!\n"); + } + e_bytes = entlen >> 8; + sm3_update(&c, &e_bytes, 1); + e_bytes = entlen & 0xFF; + sm3_update(&c, &e_bytes, 1); + if (!sm3_update(&c, id, idlen)) { + goto err; + } + p_bytes = BN_num_bytes(key->group->field); + buf = malloc(p_bytes); + if (!BN_bn2binpad(key->group->a, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(key->group->b, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(key->group->generator->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(key->group->generator->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || BN_bn2binpad(key->pub_key->X, buf, p_bytes) < 0 + || !sm3_update(&c, buf, p_bytes) + || BN_bn2binpad(key->pub_key->Y, buf, p_bytes) < 0 + || !sm3_update(&c, buf, p_bytes)) { + goto err; + } + sm3_final(out, &c); + return 1; + err: + return 0; +} + +int sm2_KDF(uint8 *K, const uint8 *Z, const size_t Zlen, const uint64 klen) { + const uint64 v = 256; /* SM3: 256bit digest */ + if (v*0xFFFFFFFFU <= klen) { + return 0; + } + if (klen & 7) { + return 0; + } + uint32 ct = 1, lmt = (klen+v-1)/v, tmp; + uint8 *_ct, *tmp_u8, *digest, *p = K; + _ct = malloc(4UL); + digest = malloc(SM3_DIGEST_LENGTH); + SM3_CTX c; + while (ct < lmt) { + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c) + || !memcpy(p, digest, SM3_DIGEST_LENGTH)) { + return 0; + } + ++ct; + p += SM3_DIGEST_LENGTH; + } + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c)) { + return 0; + } + tmp = klen % v; + if (!tmp) { + if (!memcpy(p, digest, SM3_DIGEST_LENGTH)) { + return 0; + } + } + else { + if (!memcpy(p, digest, tmp >> 3)) { + return 0; + } + } + return 1; +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_crypt.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_crypt.h" new file mode 100644 index 0000000..8ceebef --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_crypt.h" @@ -0,0 +1,204 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.4-2016 + */ + +/* Encrypt */ + +int sm2_encrypt(uint8 *out, const uint8 *M, const uint64 klen, const EC_KEY *key) { + SM3_CTX c; + BIGNUM *n, *k, *h, *x_2, *y_2; + EC_POINT *G, *C1, *S, *PB, *tmp_point; + EC_GROUP *group; + uint8 *_C1, *_C2, *_C3, *t, *buf; + size_t C1len, MlenCBLOCK, buflen, i; + int p_bytes; + group = key->group; + n = group->order; + h = group->cofactor; + G = group->generator; + PB = key->pub_key; + x_2 = BN_new(); + y_2 = BN_new(); + k = BN_new(); + C1 = EC_POINT_new(); + tmp_point = EC_POINT_new(); + S = EC_POINT_new(); + if (group == NULL + || n == NULL + || h == NULL + || k == NULL + || G == NULL + || S == NULL + || PB == NULL) { + return 0; + } + p_bytes = BN_num_bytes(group->field); + MlenCBLOCK = klen >> 3; + C1len = (p_bytes << 1 | 1); + buflen = p_bytes << 1; + _C1 = malloc(C1len); + _C2 = malloc(MlenCBLOCK); + _C3 = malloc(SM3_DIGEST_LENGTH); + buf = malloc(buflen); + t = malloc(MlenCBLOCK); + if (t == NULL) { + goto err; + } + for (;;) { + /* A1: k = rand(1, n-1) */ + do { + if (!BN_rand_range(k, n)) { + goto err; + } + } while(BN_is_zero(k)); + /* A2: C1 = [k]G = (x1, y1), C1 -> bytes */ + if (!EC_POINT_mul(C1, G, k, group) + || !EC_POINT_ecp2bin_normal(_C1, C1, p_bytes)) { + goto err; + } + /* A3: S = [h]PB, if s = O, goto err */ + if (!EC_POINT_mul(S, PB, h, group) + || EC_POINT_is_infinity(S)) { + goto err; + } + /* A4: [k]PB = (x2, y2), x2, y2 -> bytes */ + if (!EC_POINT_mul(tmp_point, PB, k, group)) { + goto err; + } + x_2 = tmp_point->X; + y_2 = tmp_point->Y; + /* A5: t = KDF(x2 || y2, klen), if t == 0, goto A1 */ + if (!BN_bn2binpad(x_2, buf, p_bytes) + || !BN_bn2binpad(y_2, buf+p_bytes, p_bytes) + || !sm2_KDF(t, buf, buflen, klen)) { + goto err; + } + for (i = 0; i < MlenCBLOCK; ++i) { + if (t[i]) { + goto A6; + } + } + } + /* A6: C2 = M ^ t */ + A6: + for (i = 0; i < MlenCBLOCK; ++i) { + _C2[i] = M[i] ^ t[i]; + } + /* A7: C3 = SM3(x2 || M || y2) */ + if (!sm3_init(&c) + || !BN_bn2binpad(x_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, M, MlenCBLOCK) + || !BN_bn2binpad(y_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(_C3, &c)) { + goto err; + } + /* A8: C = C1 || C3 || C2 */ + if (!memcpy(out, _C1, C1len) + || !memcpy(out+C1len, _C3, SM3_DIGEST_LENGTH) + || !memcpy(out+C1len+SM3_DIGEST_LENGTH, _C2, MlenCBLOCK)) { + goto err; + } + return 1; + err: + return 0; +} + +/* Decrypt */ + +int sm2_decrypt(uint8 *_M, const uint8 *C, const uint64 klen, const EC_KEY *key) { + SM3_CTX c; + BIGNUM *dB, *h, *x_2, *y_2; + EC_POINT *C1, *S, *tmp_point; + EC_GROUP *group; + uint8 *_C1, *_C2, *_C3, *t, *buf, *u; + size_t C1len, MlenCBLOCK, buflen, i; + int p_bytes; + group = key->group; + h = group->cofactor; + dB = key->priv_key; + x_2 = BN_new(); + y_2 = BN_new(); + C1 = EC_POINT_new(); + tmp_point = EC_POINT_new(); + S = EC_POINT_new(); + if (group == NULL + || h == NULL + || x_2 == NULL + || y_2 == NULL + || dB == NULL + || S == NULL) { + return 0; + } + p_bytes = BN_num_bytes(group->field); + MlenCBLOCK = klen >> 3; + C1len = (p_bytes << 1 | 1); + buflen = p_bytes << 1; + _C1 = malloc(C1len); + _C2 = malloc(MlenCBLOCK); + _C3 = malloc(SM3_DIGEST_LENGTH); + u = malloc(SM3_DIGEST_LENGTH); + buf = malloc(buflen); + t = malloc(MlenCBLOCK); + if (t == NULL) { + goto err; + } + /* C = C1 || C3 || C2 */ + if (!memcpy(_C1, C, C1len) + || !memcpy(_C2, C+C1len+SM3_DIGEST_LENGTH, MlenCBLOCK) + || !memcpy(_C3, C+C1len, SM3_DIGEST_LENGTH)) { + goto err; + } + /* B1: C -> C1, check if C1 on the curve */ + if (!EC_POINT_bin2ecp(C1, _C1, p_bytes) + || !EC_POINT_on_curve_simple(C1, group)) { + goto err; + } + /* B2: S = [h]C1, if S == O, goto err */ + if (!EC_POINT_mul(S, C1, h, group) + || EC_POINT_is_infinity(S)) { + goto err; + } + /* B3: [dB]C1 = (x2, y2), x2, y2 -> bytes */ + if (!EC_POINT_mul(tmp_point, C1, dB, group)) { + goto err; + } + x_2 = tmp_point->X; + y_2 = tmp_point->Y; + /* B4: t = KDF(x2 || y2, klen), if t = 0, goto err */ + if (!BN_bn2binpad(x_2, buf, p_bytes) + || !BN_bn2binpad(y_2, buf+p_bytes, p_bytes) + || !sm2_KDF(t, buf, buflen, klen)) { + goto err; + } + for (i = 0; i < MlenCBLOCK; ++i) { + if (t[i]) { + goto B5; + } + } + goto err; + B5: + /* B5: C -> C2, M' = C2 ^ t*/ + for (i = 0; i < MlenCBLOCK; ++i) { + _M[i] = _C2[i] ^ t[i]; + } + /* B6: u = SM3(x2 || M' || y2), check if u = C3 */ + if (!sm3_init(&c) + || !BN_bn2binpad(x_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, _M, MlenCBLOCK) + || !BN_bn2binpad(y_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(u, &c) + || memcmp(u, _C3, SM3_DIGEST_LENGTH) != 0) { + goto err; + } + /* B7: output M' */ + return 1; + err: + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_exchange.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_exchange.h" new file mode 100644 index 0000000..3e06a24 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_exchange.h" @@ -0,0 +1,335 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.3-2016 + */ + +/* + * This function should **NOT** be used directly. + * The exchange process should obey the definition in GB/T 32918.3-2016 + */ +int sm2_exchange(const EC_KEY *userA, const EC_KEY *userB, const uint64 klen, const uint8 *ZA, const uint8 *ZB) { + int w = (BN_num_bits(userA->group->order) + 1) / 2 - 1; /* For n is not pow of 2 */ + size_t p_bytes = BN_num_bytes(userB->group->field), k_bytes = (klen >> 3) + ((klen & 7) ? 1 : 0), Zlen; + uint8 const_byte; + SM3_CTX c; + BN_CTX *ctx; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + /* A-pre: */ + BIGNUM *rA, *x_1, *y_1, *tmpa, *tA; + const BIGNUM *nA, *dA, *hA; + EC_POINT *RA, *U, *tmp_pointA; + const EC_POINT *GA, *PA; + EC_GROUP *groupA; + uint8 *Z, *K, *buf, *tmp_char, *SA, *S1, *SB, *S2, *buf_digest; + SA = malloc(SM3_DIGEST_LENGTH); + S1 = malloc(SM3_DIGEST_LENGTH); + SB = malloc(SM3_DIGEST_LENGTH); + S2 = malloc(SM3_DIGEST_LENGTH); + buf_digest = malloc(SM3_DIGEST_LENGTH); + if (buf_digest == NULL) { + return 0; + } + groupA = userA->group; + nA = groupA->order; + dA = userA->priv_key; + hA = groupA->cofactor; + x_1 = BN_CTX_get(ctx); + y_1 = BN_CTX_get(ctx); + tmpa = BN_CTX_get(ctx); + tA = BN_CTX_get(ctx); + rA = BN_CTX_get(ctx); + GA = groupA->generator; + PA = userA->pub_key; + U = EC_POINT_new(); + tmp_pointA = EC_POINT_new(); + RA = EC_POINT_new(); + if (groupA == NULL + || nA == NULL + || dA == NULL + || hA == NULL + || rA == NULL + || GA == NULL + || PA == NULL + || RA == NULL) { + return 0; + } + /* A1: rA = rand(1, n-1) */ + do { + if (!BN_rand_range(rA, nA)) { + return 0; + } + } while(BN_is_zero(rA)); + /* A2: RA = [rA]G = (x1, y1) */ + if (!EC_POINT_mul(RA, GA, rA, groupA)) { + return 0; + } + /* A3: send RA to userB */ + /* B-pre: */ + BIGNUM *rB, *x_2, *y_2, *tmpb, *tB; + const BIGNUM *nB, *dB, *hB; + EC_POINT *RB, *V, *tmp_pointB; + const EC_POINT *GB, *PB; + EC_GROUP *groupB; + groupB = userB->group; + nB = groupB->order; + dB = userB->priv_key; + hB = groupB->cofactor; + x_2 = BN_CTX_get(ctx); + y_2 = BN_CTX_get(ctx); + tmpb = BN_CTX_get(ctx); + tB = BN_CTX_get(ctx); + rB = BN_CTX_get(ctx); + GB = groupB->generator; + PB = userB->pub_key; + V = EC_POINT_new(); + tmp_pointB = EC_POINT_new(); + RB = EC_POINT_new(); + if (groupB == NULL + || nB == NULL + || dB == NULL + || hB == NULL + || rB == NULL + || GB == NULL + || PB == NULL + || RB == NULL) { + return 0; + } + /* B1: rB = rand(1, n-1) */ + do { + if (!BN_rand_range(rB, nB)) { + return 0; + } + } while(BN_is_zero(rB)); + /* B2: RB = [rB]G = (x2, y2) */ + if (!EC_POINT_mul(RB, GB, rB, groupB)) { + return 0; + } + /* B3: \bar{x_2} = 2^w + (x_2 & (2^w - 1)) */ + if (!BN_one(tmpb) + || !BN_lshift(tmpb, tmpb, w) + || !BN_mod(x_2, RB->X, tmpb, ctx) + || !BN_add(x_2, x_2, tmpb)) { + return 0; + } + /* B4: tB = (dB + \bar{x_2} \times rB) % n */ + if (!BN_mod_mul(tB, x_2, rB, nB, ctx) + || !BN_mod_add_quick(tB, tB, dB, nB)) { + return 0; + } + /* B5: verify RA is on curve, \bar{x_1} = 2^w + (x_1 & (2^w - 1)) */ + if (!EC_POINT_on_curve_simple(RA, groupB)) { + return 0; + } + if (!BN_one(tmpb) + || !BN_lshift(tmpb, tmpb, w) + || !BN_mod(x_1, RA->X, tmpb, ctx) + || !BN_add(x_1, x_1, tmpb)) { + return 0; + } + /* B6: V = [h \times tB](PA + [\bar{x1}]RA) = (xV, yV) */ + if (!EC_POINT_mul(tmp_pointB, RA, x_1, groupB) + || !EC_POINT_add(tmp_pointB, tmp_pointB, PA, groupB) + || !BN_mul(tmpb, hB, tB, ctx) + || !EC_POINT_mul(V, tmp_pointB, tmpb, groupB) + || EC_POINT_is_infinity(V)) { + return 0; + } + /* B7: KB = KDF(xV || yV || ZA || ZB, klen) */ + K = malloc((klen + 7) >> 3); + Zlen = (p_bytes + SM3_DIGEST_LENGTH) * 2; + Z = malloc(Zlen); + buf = malloc(p_bytes); + tmp_char = Z; + if (!BN_bn2binpad(V->X, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZA, SM3_DIGEST_LENGTH) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZB, SM3_DIGEST_LENGTH)) { + return 0; + } + if (!sm2_KDF(K, Z, Zlen, klen)) { + return 0; + } + #ifdef SM2_EXCHANGE_OPTIONAL + /* B8: SB = SM3(0x02 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)) (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(V->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 2; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(SB, &c)) { + return 0; + } + #endif + /* B9: Send RB, (and SB, optionals) to userA */ + /* A4: \bar{x_1} = 2^w + (x_1 & (2^w - 1)) */ + if (!BN_one(tmpa) + || !BN_lshift(tmpa, tmpa, w) + || !BN_mod(x_1, RA->X, tmpa, ctx) + || !BN_add(x_1, x_1, tmpa)) { + return 0; + } + /* A5: tA = (dA + \bar{x_1} \times rA) % n */ + if (!BN_mod_mul(tA, x_1, rA, nA, ctx) + || !BN_mod_add_quick(tA, tA, dA, nA)) { + return 0; + } + /* A6: verify RB is on curve, \bar{x_2} = 2^w + (x_2 & (2^w - 1)) */ + if (!EC_POINT_on_curve_simple(RB, groupA)) { + return 0; + } + if (!BN_one(tmpa) + || !BN_lshift(tmpa, tmpa, w) + || !BN_mod(x_2, RB->X, tmpa, ctx) + || !BN_add(x_2, x_2, tmpa)) { + return 0; + } + /* A7: U = [h \times tA](PB + [\bar{x2}]RB) = (xU, yU) */ + if (!EC_POINT_mul(tmp_pointA, RB, x_2, groupA) + || !EC_POINT_add(tmp_pointA, tmp_pointA, PB, groupA) + || !BN_mul(tmpa, hA, tA, ctx) + || !EC_POINT_mul(U, tmp_pointA, tmpa, groupA) + || EC_POINT_is_infinity(U)) { + return 0; + } + /* A8: KA = KDF(xU || yU || ZA || ZB, klen) */ + K = malloc((klen + 7) >> 3); + Zlen = (p_bytes + SM3_DIGEST_LENGTH) * 2; + Z = malloc(Zlen); + buf = malloc(p_bytes); + tmp_char = Z; + if (!BN_bn2binpad(U->X, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !BN_bn2binpad(U->Y, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZA, SM3_DIGEST_LENGTH) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZB, SM3_DIGEST_LENGTH)) { + return 0; + } + if (!sm2_KDF(K, Z, Zlen, klen)) { + return 0; + } + #ifdef SM2_EXCHANGE_OPTIONAL + /* A9: S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)), verify S1==SB (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(U->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 2; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(S1, &c)) { + return 0; + } + if (memcmp(S1, SB, SM3_DIGEST_LENGTH) != 0) { + return 0; + } + #endif + #ifdef SM2_EXCHANGE_OPTIONAL + /* A10: SA = SM3(0x03 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)) (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(U->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 3; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(U->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(SA, &c)) { + return 0; + } + #endif + #ifdef SM2_EXCHANGE_OPTIONAL + /* B10: S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)), verify S2==SA (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(V->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 3; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(S2, &c)) { + return 0; + } + if (memcmp(S2, SA, SM3_DIGEST_LENGTH) != 0) { + return 0; + } + #endif + return 1; + fail: + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_sign.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_sign.h" new file mode 100644 index 0000000..c901603 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_sign.h" @@ -0,0 +1,189 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.2-2016 + */ + +/** SM2 signature generation. + * \param msg massage for signing. + * \param msglen byte length of msg. + * \param id identifier of user A. + * \param idlen byte length of id. + * \param key key of user A. + * \return the sign generated. + */ +SM2_SIG *sm2_sig_gen(const uint8 *msg, const size_t msglen, const uint8 *id, const size_t idlen, const EC_KEY *key) { + SM3_CTX c; + sm3_init(&c); + uint8 *buf; + BN_CTX *ctx; + BIGNUM *e, *n, *k, *x, *r, *s, *rk, *dA, *tmp; + EC_POINT *kG, *G; + SM2_SIG *sig; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + sig = SM2_SIG_new(); + if (sig == NULL) { + return 0; + } + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + n = key->group->order; + k = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + r = sig->r; + s = sig->s; + rk = BN_CTX_get(ctx); + dA = key->priv_key; + tmp = BN_CTX_get(ctx); + G = key->group->generator; + kG = EC_POINT_new(); + if (n == NULL + || r == NULL + || s == NULL + || dA == NULL + || tmp == NULL + || G == NULL + || kG == NULL) { + return 0; + } + buf = malloc(SM3_DIGEST_LENGTH); + /* A1: \bar{M} = ZA || M */ + if (!sm2_compute_z(buf, id, idlen, key)) { + goto err; + } + if (!sm3_update(&c, buf, SM3_DIGEST_LENGTH) + || !sm3_update(&c, msg, msglen)) { + SM2ERR("sm2_sign(): compute e error!\n"); + } + /* A2: e = SM3(\bar{M}), e -> bn */ + sm3_final(buf, &c); + e = BN_bin2bn(buf, SM3_DIGEST_LENGTH, NULL); + if (e == NULL) { + SM2ERR("sm2_sign(): e error!\n"); + } + for (;;) { + /* A3: k = rand(1, n-1) */ + if (!BN_rand_range(k, n)) { + SM2ERR("sm2_sign(): gen k error!\n"); + } + if (BN_is_zero(k)) continue; + /* A4: (x1, y1) = [k]G, x1 -> bn */ + if (!EC_POINT_mul(kG, G, k, key->group)) { + return 0; + } + x = kG->X; + /* A5: r = (e + x1) % n, if r=0 or r+k=n, goto A3 */ + if (!BN_mod_add(r, e, x, n, ctx)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + if (BN_is_zero(r)) continue; + if (!BN_add(rk, r, k)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + if (BN_cmp(rk, n) == 0) continue; + /* A6: s = ((1+dA)^-1 \times (k- r \times dA)) % n, if s=0, goto A3 */ + if (!BN_add(s, dA, BN_value_one()) + || !BN_mod_inverse(s, s, n, ctx) + || !printf("(1+dA)^-1: %s\n", BN_bn2hex(s)) + || !BN_mod_mul(tmp, dA, r, n, ctx) + || !BN_sub(tmp, k, tmp) + || !BN_mod_mul(s, s, tmp, n, ctx)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + if (BN_is_zero(s)) continue; + /* A7: r,s -> byte/u8[], sig = (r, s) */ + break; + } + err: + done: + BN_free(e); + BN_CTX_free(ctx); + return sig; +} + +/* (2) Sign Verify */ + +/** SM2 signature verification. + * \param msg massage for signing. + * \param msglen byte length of msg. + * \param id identifier of user A. + * \param idlen byte length of id. + * \param key key of user A. + * \param sig signature to be verified. + * \return 1 on success and 0 if an error occurred. + */ +int sm2_sig_verify(const uint8 *msg, const size_t msglen, const uint8 *id, const size_t idlen, const EC_KEY *key, const SM2_SIG *sig) { + SM3_CTX c; + sm3_init(&c); + BN_CTX *ctx; + const BIGNUM *r, *s, *n; + BIGNUM *e, *t, *R; + const EC_POINT *G, *PA; + EC_POINT *sG, *tPA, *tmp_point; + uint8 *buf; + r = sig->r; + s = sig->s; + n = key->group->order; + G = key->group->generator; + PA = key->pub_key; + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + R = BN_CTX_get(ctx); + sG = EC_POINT_new(); + tPA = EC_POINT_new(); + tmp_point = EC_POINT_new(); + if (R == NULL || tmp_point == NULL) { + goto err; + } + buf = malloc(SM3_DIGEST_LENGTH); + /* B1: check r' \in [1, n-1], otherwise goto BERR */ + /* B2: check s' \in [1, n-1], otherwise goto BERR */ + if (BN_cmp(r, BN_value_one()) < 0 + || BN_cmp(s, BN_value_one()) < 0 + || BN_cmp(n, r) <= 0 + || BN_cmp(n, s) <= 0) { + goto err; + } + /* B3: \bar{M'} = ZA || M' */ + if (!sm2_compute_z(buf, id, idlen, key)) { + goto err; + } + if (!sm3_update(&c, buf, SM3_DIGEST_LENGTH) + || !sm3_update(&c, msg, msglen)) { + SM2ERR("sm2_sign(): compute e error!\n"); + } + /* B4: e' = SM3(\bar{M'}), e -> bn */ + sm3_final(buf, &c); + e = BN_bin2bn(buf, SM3_DIGEST_LENGTH, NULL); + /* B5: r', s' -> bn; t = (r'+s')%n, if t=0, goto BERR */ + if (!BN_mod_add_quick(t, r, s, n) + || BN_is_zero(t)) { + goto err; + } + /* B6: (x1', y1') = [s']G + [t]PA */ + if (!EC_POINT_mul(sG, G, s, key->group) + || !EC_POINT_mul(tPA, PA, t, key->group) + || !EC_POINT_add(tmp_point, sG, tPA, key->group)) { + goto err; + } + /* B7: x1' -> bn; R = (e' + x1')%n, return R=r' */ + if (!BN_mod_add_quick(R, e, tmp_point->X, n)) { + goto err; + } + if (BN_cmp(R, r) == 0) { + return 1; + } + err: + BN_CTX_end(ctx); + /* BERR: not pass, return 0 */ + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_tests.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_tests.h" new file mode 100644 index 0000000..922559d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave/sm2_tests.h" @@ -0,0 +1,152 @@ +#ifndef SECGEAR_SM2_TESTS_H +#define SECGEAR_SM2_TESTS_H + +#include "sm2_sign.h" +#include "sm2_exchange.h" +#include "sm2_crypt.h" + +uint8 *sign_buffer, sign_verify_ret; + +void sm2signtest(const int p_bytes, const uint8 *_M, const uint8 *_ID_A, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dA, const uint8 *_k) { + /* A.3 is not supported */ + int _w; + uint16 entlenC = strlen((char *)_ID_A); + uint16 entlA = entlenC*8; + BIGNUM *p, *a, *b, *n, *xG, *yG, *dA, *k; + EC_POINT *G, *kG; + EC_GROUP *group; + EC_KEY *userA; + group = EC_GROUP_new(); + p = BN_new(); + a = BN_new(); + b = BN_new(); + n = BN_new(); + xG = BN_new(); + yG = BN_new(); + dA = BN_new(); + k = BN_new(); + G = EC_POINT_new(); + kG = EC_POINT_new(); + userA = EC_KEY_new(); + BN_bin2bn(_p, p_bytes, p); + BN_bin2bn(_a, p_bytes, a); + BN_bin2bn(_b, p_bytes, b); + BN_bin2bn(_n, p_bytes, n); + BN_bin2bn(_XG, p_bytes, xG); + BN_bin2bn(_YG, p_bytes, yG); + BN_bin2bn(_dA, p_bytes, dA); + BN_bin2bn(_k, p_bytes, k); + EC_POINT_setXY(G, xG, yG); + _w = EC_GROUP_set_param(group, p, a, b, n, BN_value_one(), G); + _w = EC_KEY_set_group(userA, group); + _w = EC_KEY_set_priv_key(userA, dA); + _w = EC_KEY_generate_pub_key(userA); + _w = EC_POINT_mul(kG, G, k, group); + SM2_SIG *sig; + sig = sm2_sig_gen(_M, strlen((char *)_M), _ID_A, strlen((char *)_ID_A), userA); + sign_buffer = (uint8 *)malloc(p_bytes * 4); + memcpy(sign_buffer, BN_bn2hex(sig->r), p_bytes * 2); + memcpy(sign_buffer + p_bytes * 2, BN_bn2hex(sig->s), p_bytes * 2); + + _w = sm2_sig_verify(_M, strlen((char *)_M), _ID_A, strlen((char *)_ID_A), userA, sig); + sign_verify_ret = _w; +} + +uint8 exchange_ret; + +/* h = 1 by default */ +void sm2exchangetest(const int p_bytes, const uint8 *_ID_A, const uint8 *_ID_B, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dA, const uint8 *_dB, const uint64 klen) { + /* A.3 is not supported */ + int _w; + uint16 entlenAC = strlen((char *)_ID_A); + uint16 entlA = entlenAC*8; + uint16 entlenBC = strlen((char *)_ID_B); + uint16 entlB = entlenBC*8; + BIGNUM *p, *a, *b, *h, *n, *xG, *yG, *dA, *dB; + EC_POINT *G, *kG; + EC_GROUP *group; + EC_KEY *userA, *userB; + uint8 *ZA, *ZB; + ZA = malloc(SM3_DIGEST_LENGTH); + ZB = malloc(SM3_DIGEST_LENGTH); + group = EC_GROUP_new(); + p = BN_new(); + a = BN_new(); + b = BN_new(); + h = (BIGNUM *)BN_value_one(); + n = BN_new(); + xG = BN_new(); + yG = BN_new(); + dA = BN_new(); + dB = BN_new(); + G = EC_POINT_new(); + kG = EC_POINT_new(); + userA = EC_KEY_new(); + userB = EC_KEY_new(); + BN_bin2bn(_p, p_bytes, p); + BN_bin2bn(_a, p_bytes, a); + BN_bin2bn(_b, p_bytes, b); + BN_bin2bn(_n, p_bytes, n); + BN_bin2bn(_XG, p_bytes, xG); + BN_bin2bn(_YG, p_bytes, yG); + BN_bin2bn(_dA, p_bytes, dA); + BN_bin2bn(_dB, p_bytes, dB); + EC_POINT_setXY(G, xG, yG); + _w = EC_GROUP_set_param(group, p, a, b, n, h, G); + _w = EC_KEY_set_group(userA, group); + _w = EC_KEY_set_priv_key(userA, dA); + _w = EC_KEY_generate_pub_key(userA); + _w = EC_KEY_set_group(userB, group); + _w = EC_KEY_set_priv_key(userB, dB); + _w = EC_KEY_generate_pub_key(userB); + _w = sm2_compute_z(ZA, _ID_A, strlen((char *)_ID_A), userA); + _w = sm2_compute_z(ZB, _ID_B, strlen((char *)_ID_B), userB); + _w = sm2_exchange(userA, userB, klen, ZA, ZB); + exchange_ret = _w; +} + +uint8 *encrypt_pw, *decrypt_msg; + +void sm2crypttest(int p_bytes, const uint8 *M, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dB) { + /* A.3 is not supported */ + int _w; + BIGNUM *p, *a, *b, *n, *xG, *yG, *dB; + EC_POINT *G; + EC_GROUP *group; + EC_KEY *userB; + uint64 klen; + int MlenCBLOCK; + size_t pwlen; + group = EC_GROUP_new(); + p = BN_new(); + a = BN_new(); + b = BN_new(); + n = BN_new(); + xG = BN_new(); + yG = BN_new(); + dB = BN_new(); + G = EC_POINT_new(); + userB = EC_KEY_new(); + BN_bin2bn(_p, p_bytes, p); + BN_bin2bn(_a, p_bytes, a); + BN_bin2bn(_b, p_bytes, b); + BN_bin2bn(_n, p_bytes, n); + BN_bin2bn(_XG, p_bytes, xG); + BN_bin2bn(_YG, p_bytes, yG); + BN_bin2bn(_dB, p_bytes, dB); + EC_POINT_setXY(G, xG, yG); + MlenCBLOCK = strlen((char *)M); + _w = EC_GROUP_set_param(group, p, a, b, n, BN_value_one(), G); + _w = EC_KEY_set_group(userB, group); + _w = EC_KEY_set_priv_key(userB, dB); + _w = EC_KEY_generate_pub_key(userB); + klen = MlenCBLOCK * 8; + pwlen = (p_bytes << 1 | 1) + MlenCBLOCK + SM3_DIGEST_LENGTH; + encrypt_pw = malloc(pwlen); + _w = sm2_encrypt(encrypt_pw, M, klen, userB); + decrypt_msg = malloc(MlenCBLOCK+1); + memset(decrypt_msg, 0, MlenCBLOCK+1); + _w = sm2_decrypt(decrypt_msg, encrypt_pw, klen, userB); +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave_SM2.edl" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave_SM2.edl" new file mode 100644 index 0000000..87d3e65 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/enclave_SM2.edl" @@ -0,0 +1,30 @@ +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + + trusted { + public void callsm2signtest(); + public void callsm2exchangetest(); + public void callsm2crypttest(); + public void setSignIDA([in, size=len] uint8 *src, size_t len); + public void setSignM([in, size=len] uint8 *src, size_t len); + public void setSignDA([in, count=32] uint8 *src); + public void setSignK([in, count=32] uint8 *src); + public void getSignResult([out, size=len] uint8 *buf, size_t len); + public void getSignVerifyResult([out, count=1] uint8 buf); + public void setExchangeIDA([in, size=len] uint8 *src, size_t len); + public void setExchangeIDB([in, size=len] uint8 *src, size_t len); + public void setExchangeDA([in, count=32] uint8 *src); + public void setExchangeDB([in, count=32] uint8 *src); + public void setExchangeKLen([in, count=1] uint64 *src); + public void getExchangeResult([out, count=1] uint8 buf); + public void setCryptM([in, size=len] uint8 *src, size_t len); + public void setCryptDB([in, count=32] uint8 *src); + public void getCryptPW([out, size=len] uint8 *buf, size_t len); + public void getCryptMSG([out, size=len] uint8 *buf, size_t len); + }; + + untrusted { + + }; +}; diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/CMakeLists.txt" new file mode 100644 index 0000000..0d42633 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/CMakeLists.txt" @@ -0,0 +1,88 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM2) +#set host exec name +set(OUTPUT secgear_enclave_SM2) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) + +set(CMAKE_CXX_STANDARD 11) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O2 -fPIE") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim) +else() + target_link_libraries(${OUTPUT} secgear) +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + #itrustee install whitelist /vender/bin/teec_hello + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION /vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/main.cpp" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/main.cpp" new file mode 100644 index 0000000..ef1710e --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/host/main.cpp" @@ -0,0 +1,127 @@ +#include"enclave.h" +#include"Enclave1_u.h" +#include +#include + +#define MAX_LEN 1024 + +#define SM3_DIGEST_LENGTH 32 +const int SM2_p_bytes = 256 >> 3; +const uint8 sign_ID_A[] = "1234567812345678"; +const uint8 sign_M[] = "message digest"; +const uint8 sign_dA[] = { + 0x39, 0x45, 0x20, 0x8F, + 0x7B, 0x21, 0x44, 0xB1, + 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, + 0x88, 0x93, 0x93, 0x69, + 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, + 0x4D, 0xF7, 0xC5, 0xB8, +}; +const uint8 sign_k[] = { + 0x59, 0x27, 0x6E, 0x27, + 0xD5, 0x06, 0x86, 0x1A, + 0x16, 0x68, 0x0F, 0x3A, + 0xD9, 0xC0, 0x2D, 0xCC, + 0xEF, 0x3C, 0xC1, 0xFA, + 0x3C, 0xDB, 0xE4, 0xCE, + 0x6D, 0x54, 0xB8, 0x0D, + 0xEA, 0xC1, 0xBC, 0x21, +}; + +const uint8 exchange_ID_A[] = "1234567812345678"; +const uint8 exchange_ID_B[] = "1234567812345678"; +const uint8 exchange_dA[] = { + 0x81, 0xEB, 0x26, 0xE9, + 0x41, 0xBB, 0x5A, 0xF1, + 0x6D, 0xF1, 0x16, 0x49, + 0x5F, 0x90, 0x69, 0x52, + 0x72, 0xAE, 0x2C, 0xD6, + 0x3D, 0x6C, 0x4A, 0xE1, + 0x67, 0x84, 0x18, 0xBE, + 0x48, 0x23, 0x00, 0x29, +}; +const uint8 exchange_dB[] = { + 0x78, 0x51, 0x29, 0x91, + 0x7D, 0x45, 0xA9, 0xEA, + 0x54, 0x37, 0xA5, 0x93, + 0x56, 0xB8, 0x23, 0x38, + 0xEA, 0xAD, 0xDA, 0x6C, + 0xEB, 0x19, 0x90, 0x88, + 0xF1, 0x4A, 0xE1, 0x0D, + 0xEF, 0xA2, 0x29, 0xB5, +}; +const uint64 exchange_klen = 128; + +const uint8 crypt_M[] = "encryption standard"; +const uint8 crypt_dB[] = { + 0x39, 0x45, 0x20, 0x8F, + 0x7B, 0x21, 0x44, 0xB1, + 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, + 0x88, 0x93, 0x93, 0x69, + 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, + 0x4D, 0xF7, 0xC5, 0xB8, +}; + +int main(int argc, char* argv[]) { + cc_enclave_t *eid; + cc_enclave_result_t ret; + char *path = transferFromString(PATH); + + ret = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &eid); + if (ret != CC_SUCCESS) { + printf("ERR: %#x ,failed to create enclave.\n", ret); + return -1; + } + + u_int8_t buffer[MAX_LEN], tmpu8; + memset(buffer, 0, sizeof buffer); + printf("A.2 start: \n"); + setSignIDA(eid, sign_ID_A, strlen(sign_ID_A)); + setSignM(eid, sign_M, strlen(sign_M)); + setSignDA(eid, sign_dA); + setSignK(eid, sign_k); + callsm2signtest(eid); + getSignResult(eid, buffer, MAX_LEN); + printf("sign sig: %s\n", buffer); + getSignVerifyResult(eid, tmpu8); + printf("sign verify: %x\n", tmpu8); + printf("A.2 end: \n\n\n"); + /* PASSED */ + + printf("B.2 start: \n"); + setExchangeIDA(eid, exchange_ID_A, strlen(exchange_ID_A)); + setExchangeIDB(eid, exchange_ID_B, strlen(exchange_ID_B)); + setExchangeDA(eid, exchange_dA); + setExchangeDB(eid, exchange_dB); + setExchangeKLen(eid, exchange_klen); + callsm2exchangetest(eid); + getExchangeResult(eid, tmpu8); + printf("exchange: %x\n", tmpu8); + printf("B.2 end: \n\n\n"); + /* PASSED */ + + printf("C.2 start: \n"); + setCryptM(eid, crypt_M, strlen(crypt_M)); + setCryptDB(eid, crypt_dB); + callsm2crypttest(eid); + int pwlen = (SM2_p_bytes << 1 | 1) + strlen(crypt_M) + SM3_DIGEST_LENGTH; + getCryptPW(eid, buffer, pwlen); + printf("encrypt pw: "); + for (int i=0; i +#define debugPrint (printf("%s: %s: %d\n",__FILE__,__FUNCTION__,__LINE__),fflush(stdout),1) + +typedef __uint8_t uint8; +typedef __uint16_t uint16; +typedef __uint32_t uint32; +typedef __uint64_t uint64; + +#define CONCAT_8x4(x0, x1, x2, x3) ((((uint32)(x0) << 8 | (x1)) << 8 | (x2)) << 8 | (x3)) // X = (x0 || x1 || x2 || x3) +#define CONCAT_16x2(x0, x1) ((uint32)(x0) << 16 | (x1)) // X = (x0 || x1) +#define EXTRACT_8_32(X, i) (((X) >> (((i) ^ 3) << 3)) & 0xFF) // X = (x0 || x1 || x2 || x3) +#define EXTRACT_16_32(X, i) (((X) >> (((i) ^ 1) << 4)) & 0xFFFF) // X = (x0 || x1) +#define EXTRACT_16H_31(X) (((X) >> 15) & 0xFFFF) // Higher 16-bit from 31-bit +#define EXTRACT_16L_31(X) ((X) & 0xFFFF) // Lower 16-bit from 31-bit + +#define ROTATE(a, n) (((a) << (n)) | (((a) & 0xFFFFFFFF) >> ((32 - (n)) & 31))) +#define ROTATE_31(a, n) ((((a) << (n)) & 0x7FFFFFFF) | (((a) & 0x7FFFFFFF) >> (31 - (n)))) + +#define GET_BIT_VALUE_32(x, i) (((x) >> (31 - (i))) & 1) + +const uint32 PREFIX_MASK_32[32] = { + 0x00000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE +}; + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/include/ec.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/include/ec.h" new file mode 100644 index 0000000..56adbe7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/include/ec.h" @@ -0,0 +1,545 @@ +#include /* BigNum */ +#include "common_utils.h" + +typedef struct ec_point_st { + BIGNUM *X; + BIGNUM *Y; + int is_infinity; +} EC_POINT; + +int EC_POINT_init(EC_POINT *point) { + point->X = BN_new(); + point->Y = BN_new(); + point->is_infinity = 0; + if (point->X == NULL || point->Y == NULL) { + BN_free(point->X); + BN_free(point->Y); + return 0; + } + return 1; +} + +EC_POINT *EC_POINT_new() { + EC_POINT *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_POINT_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_POINT_setXY(EC_POINT *r, const BIGNUM *x, const BIGNUM *y) { + if (r == NULL) { + return 0; + } + if (!BN_copy(r->X, x) || !(BN_copy(r->Y, y))) { + return 0; + } + return 1; +} + +const EC_POINT *EC_point_infinity() { + static const EC_POINT const_infinity = { NULL, NULL, 1 }; + return &const_infinity; +} + +int EC_POINT_is_infinity(const EC_POINT *point) { + return point->is_infinity; +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest == NULL) { + return 0; + } + if (EC_POINT_is_infinity(src)) { + dest->is_infinity = 1; + } + else{ + dest->is_infinity = 0; + if (!BN_copy(dest->X, src->X) || !BN_copy(dest->Y, src->Y)) return 0; + } + return 1; +} + +#define NORMAL 0x1 +#define COMPRESS 0x2 +#define MIX 0x4 + +int EC_POINT_ecp2bin(uint8 *out, const EC_POINT *point, int p_bytes, int flag) { + uint8 PC; + uint8 *p = out, *buf; + int i; + buf = malloc(p_bytes); + if (EC_POINT_is_infinity(point)) { + return 0; + } + if (flag == NORMAL) { + PC = 0x04; + *(p++) = PC; + if (!BN_bn2binpad(point->X, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + if (!BN_bn2binpad(point->Y, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_bin2ecp(EC_POINT *point, const uint8 *src, int p_bytes) { + if (point == NULL) { + return 0; + } + uint8 PC = *src; + const uint8 *data = src + 1; + uint8 *buf; + int i; + if (PC == 0x04) { + if (!BN_bin2bn(data, p_bytes, point->X) + || !BN_bin2bn(data+p_bytes, p_bytes, point->Y)) { + return 0; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_ecp2bin_normal(uint8 *out, const EC_POINT *point, int p_bytes) { + return EC_POINT_ecp2bin(out, point, p_bytes, NORMAL); +} + +// int EC_POINT_ecp2bin_compressed(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, COMPRESS); +// } + +// int EC_POINT_ecp2bin_mix(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, MIX); +// } + +typedef struct ec_group_st { + EC_POINT *generator; /* point G */ + BIGNUM *order; /* n */ + BIGNUM *cofactor; /* h */ + BIGNUM *field; /* module p */ + BIGNUM *a, *b; /* ECC parameter */ +} EC_GROUP; + +int EC_GROUP_init(EC_GROUP *group) { + group->generator = EC_POINT_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->generator == NULL || group->b == NULL) { + free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +EC_GROUP *EC_GROUP_new() { + EC_GROUP *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_GROUP_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest == NULL) { + return 0; + } + if (dest == src) { + return 1; + } + if (!EC_POINT_copy(dest->generator, src->generator) + || !BN_copy(dest->order, src->order) + || !BN_copy(dest->cofactor, src->cofactor) + || !BN_copy(dest->field, src->field) + || !BN_copy(dest->a, src->a) + || !BN_copy(dest->b, src->b)) { + return 0; + } + return 1; +} + +int EC_GROUP_set_param(EC_GROUP *group, const BIGNUM *field, const BIGNUM *a, const BIGNUM *b, const BIGNUM *order, const BIGNUM *cofactor, const EC_POINT *point) { + if (group == NULL) { + return 0; + } + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->generator = EC_POINT_new(); + if (group->cofactor == NULL + || group->generator == NULL) { + return 0; + } + if (!BN_copy(group->field, field) + || !BN_copy(group->a, a) + || !BN_copy(group->b, b) + || !BN_copy(group->order, order) + || !BN_copy(group->cofactor, cofactor) + || !EC_POINT_copy(group->generator, point)) { + return 0; + } + return 1; +} + +int EC_POINT_double(EC_POINT *r, const EC_POINT *a, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, EC_point_infinity()); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y)) { + goto done; + } + if (!BN_set_word(bn_value_3, 3) + || !BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_sqr(r->X, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_lshift1_quick(tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, r->X, tmp, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_add(EC_POINT *r, const EC_POINT *a, const EC_POINT *b, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *bx, *by, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (a == b) { + return EC_POINT_double(r, a, group); + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_infinity(b)) { + return EC_POINT_copy(r, a); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + bx = BN_CTX_get(ctx); + by = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y) + || !BN_copy(bx, b->X) + || !BN_copy(by, b->Y)) { + goto done; + } + if (BN_cmp(ax, bx) == 0) { + if (!BN_mod_add_quick(tmp, ay, by, p)) { + goto done; + } + if (BN_is_zero(tmp) + || !EC_POINT_copy(r, EC_point_infinity())) { + goto done; + } + if (!BN_set_word(bn_value_3, 3)) { + goto done; + } + if (!BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + else { + if (!BN_mod_sub_quick(lnum, by, ay, p)) { + goto done; + } + if (!BN_mod_sub_quick(ldeno, bx, ax, p)) { + goto done; + } + if (!BN_mod_inverse(ldeno, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + if (!BN_mod_sqr(tmp, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(tmp, tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, tmp, bx, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_mul(EC_POINT *r, const EC_POINT *a, const BIGNUM *b, const EC_GROUP *group) { + if (r == NULL) { + return 0; + } + if (BN_is_negative(b)) { + EC_POINT *_a = EC_POINT_new(); + BIGNUM *_b = BN_new(); + if (!EC_POINT_copy(_a, a) + || !BN_copy(_b, b) + || !BN_mod_sub_quick(_a->Y, group->field, _a->Y, group->field)) { + return 0; + } + BN_set_negative(_b, 0); + return EC_POINT_mul(r, _a, _b, group); + } + if (!EC_POINT_copy(r, EC_point_infinity())){ + return 0; + } + int bits = BN_num_bits(b); + for (int i = bits-1; i >= 0; --i) { + if (!EC_POINT_double(r, r, group)) { + return 0; + } + if (BN_is_bit_set(b, i)) { + if (!EC_POINT_add(r, r, a, group)) { + return 0; + } + } + } + return 1; +} + +/* + * Only for curve y^2 = x^3 + ax + b. + * Please check infinity before calling. + */ +int EC_POINT_on_curve_simple(const EC_POINT *point, const EC_GROUP *group) { + if (point == NULL || group == NULL) { + return 0; + } + if (EC_POINT_is_infinity(point)) { + return 1; + } + int ret = 0; + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *lhs, *rhs; + EC_POINT *Nq; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return ret; + } + BN_CTX_start(ctx); + p = group->field; + a = group->a; + b = group->b; + x = point->X; + y = point->Y; + lhs = BN_CTX_get(ctx); + rhs = BN_CTX_get(ctx); + Nq = EC_POINT_new(); + if (p == NULL + || a == NULL + || b == NULL + || x == NULL + || y == NULL + || rhs == NULL + || Nq == NULL) { + return ret; + } + if (!BN_mod_mul(lhs, y, y, p, ctx) + || !BN_mod_mul(rhs, x, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, a, p) + || !BN_mod_mul(rhs, rhs, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, b, p) + || !EC_POINT_mul(Nq, point, group->order, group)) { + return ret; + } + if (BN_cmp(lhs, rhs) != 0 + || !EC_POINT_is_infinity(Nq)) { + return ret; + } + ret = 1; + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +typedef struct ec_key_st { + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; +} EC_KEY; + +int EC_KEY_init(EC_KEY *key) { + key->group = EC_GROUP_new(); + key->pub_key = EC_POINT_new(); + key->priv_key = BN_new(); + if (key->group == NULL + || key->pub_key == NULL + || key->priv_key == NULL) { + free(key->group); + free(key->pub_key); + BN_free(key->priv_key); + return 0; + } + return 1; +} + +EC_KEY *EC_KEY_new() { + EC_KEY *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_KEY_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + if (!EC_GROUP_copy(key->group, group)) { + return 0; + } + return 1; +} + +int EC_KEY_set_priv_key(EC_KEY *key, const BIGNUM *priv_key) { + BIGNUM *tmp; + tmp = BN_dup(priv_key); + if (tmp == NULL) { + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = tmp; + return 1; +} + +int EC_KEY_generate_pub_key(EC_KEY *key) { + return EC_POINT_mul(key->pub_key, key->group->generator, key->priv_key, key->group); +} + +const BIGNUM *EC_KEY_get_priv_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_generate_key() {} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/sm3/sm3.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/sm3/sm3.h" new file mode 100644 index 0000000..195d679 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM2/sm3/sm3.h" @@ -0,0 +1,183 @@ +#ifndef SECGEAR_SM3_H +#define SECGEAR_SM3_H + +/* + * Ref: + * GB/T 32905-2016 + */ + +#include +#include "../include/common_utils.h" + +#define SM3_DIGEST_LENGTH 32 +#define SM3_WORD uint32 + +#define SM3_CBLOCK 64 +#define SM3_LBLOCK (SM3_CBLOCK/4) + +typedef struct SM3state_st { + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD Nl, Nh; + SM3_WORD data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17)) +#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23)) + +#define FF(J,X,Y,Z) (J<16 ? (X ^ Y ^ Z) : ((X & Y) | (X & Z) | (Y & Z))) +#define GG(J,X,Y,Z) (J<16 ? (X ^ Y ^ Z) : ((X & Y) | ((~X) & Z))) + +#define T(J) (J<16 ? 0x79cc4519 : 0x7a879d8a) + +#define EXPAND(W0,W7,W13,W3,W10) \ + (P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10) + +#define SM3_A 0x7380166fUL +#define SM3_B 0x4914b2b9UL +#define SM3_C 0x172442d7UL +#define SM3_D 0xda8a0600UL +#define SM3_E 0xa96f30bcUL +#define SM3_F 0x163138aaUL +#define SM3_G 0xe38dee4dUL +#define SM3_H 0xb0fb0e4eUL + +#define SM3_MAKE_STRING(c, s) \ + do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll, (s)); \ + ll=(c)->B; (void)HOST_l2c(ll, (s)); \ + ll=(c)->C; (void)HOST_l2c(ll, (s)); \ + ll=(c)->D; (void)HOST_l2c(ll, (s)); \ + ll=(c)->E; (void)HOST_l2c(ll, (s)); \ + ll=(c)->F; (void)HOST_l2c(ll, (s)); \ + ll=(c)->G; (void)HOST_l2c(ll, (s)); \ + ll=(c)->H; (void)HOST_l2c(ll, (s)); \ + } while (0) + +void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num) { + const unsigned char *data = p; + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD w[68]={}, ww[64]={}; + while (num--) { + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + E = ctx->E; + F = ctx->F; + G = ctx->G; + H = ctx->H; + for (int j = 0; j < 16; ++j) { + HOST_c2l(data, w[j]); + } + for (int j = 16; j < 68; ++j) { + w[j] = EXPAND(w[j-16], w[j-9], w[j-3], w[j-13], w[j-6]); + } + for (int j = 0; j < 64; ++j) { + ww[j] = w[j] ^ w[j+4]; + } + for (int j = 0; j < 64; j++) { + SM3_WORD SS1, SS2, TT1, TT2; + SS1 = ROTATE(ROTATE(A, 12) + E + ROTATE(T(j), j&31), 7); + SS2 = SS1 ^ ROTATE(A, 12); + TT1 = FF(j, A, B, C) + D + SS2 + ww[j]; + TT2 = GG(j, E, F, G) + H + SS1 + w[j]; + D = C; + C = ROTATE(B,9); + B = A; + A = TT1; + H = G; + G = ROTATE(F, 19); + F = E; + E = P0(TT2); + } + ctx->A ^= A; + ctx->B ^= B; + ctx->C ^= C; + ctx->D ^= D; + ctx->E ^= E; + ctx->F ^= F; + ctx->G ^= G; + ctx->H ^= H; + } +} + +int sm3_init(SM3_CTX *c) { + memset(c, 0, sizeof(*c)); + c->A = SM3_A; + c->B = SM3_B; + c->C = SM3_C; + c->D = SM3_D; + c->E = SM3_E; + c->F = SM3_F; + c->G = SM3_G; + c->H = SM3_H; + return 1; +} + +int sm3_update(SM3_CTX *c, const void *data_, size_t len) { + const unsigned char *data = data_; + unsigned char *p; + SM3_WORD l; + size_t n; + if (len == 0) return 1; + l = (c->Nl + (((SM3_WORD) len) << 3)) & 0xffffffffUL; + if (l < c->Nl) c->Nh++; + c->Nh += (SM3_WORD) (len >> 29); + c->Nl = l; + n = c->num; + if (n != 0) { + p = (unsigned char *)c->data; + if (len >= SM3_CBLOCK || len + n >= SM3_CBLOCK) { + memcpy(p + n, data, SM3_CBLOCK - n); + sm3_block_data_order(c, p, 1); + n = SM3_CBLOCK - n; + data += n; + len -= n; + c->num = 0; + memset(p, 0, SM3_CBLOCK); + } + else { + memcpy(p + n, data, len); + c->num += (unsigned int)len; + return 1; + } + } + n = len / SM3_CBLOCK; + if (n > 0) { + sm3_block_data_order(c, data, n); + n *= SM3_CBLOCK; + data += n; + len -= n; + } + if (len != 0) { + p = (unsigned char *)c->data; + c->num = (unsigned int)len; + memcpy(p, data, len); + } + return 1; +} + +int sm3_final(unsigned char *md, SM3_CTX *c) { + unsigned char *p = (unsigned char *)c->data; + size_t n = c->num; + p[n] = 0x80; + n++; + if (n > (SM3_CBLOCK - 8)) { + memset(p + n, 0, SM3_CBLOCK - n); + n = 0; + sm3_block_data_order(c, p, 1); + } + memset(p + n, 0, SM3_CBLOCK - 8 - n); + p += SM3_CBLOCK - 8; + (void)HOST_l2c(c->Nh, p); + (void)HOST_l2c(c->Nl, p); + p -= SM3_CBLOCK; + sm3_block_data_order(c, p, 1); + c->num = 0; + SM3_MAKE_STRING(c, md); + return 1; +} + +#endif \ No newline at end of file -- Gitee From a97e12375cd8562aba50bf1b0975e2c5e7f897c7 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:55:18 +0000 Subject: [PATCH 13/18] enclave_sm4 Signed-off-by: wangxiaoxi1 --- .../Formal/enclave_SM4/CMakeLists.txt" | 38 ++ .../enclave_SM4/enclave/CMakeLists.txt" | 162 ++++++ .../enclave_SM4/enclave/Enclave.config.xml" | 12 + .../Formal/enclave_SM4/enclave/Enclave.lds" | 11 + .../Formal/enclave_SM4/enclave/enclave_SM4.c" | 42 ++ .../enclave_SM4/enclave/manifest.txt.in" | 8 + .../enclave/rsa_public_key_cloud.pem" | 11 + .../Formal/enclave_SM4/enclave/sm4.h" | 107 ++++ .../Formal/enclave_SM4/enclave_SM4.edl" | 16 + .../Formal/enclave_SM4/host/CMakeLists.txt" | 88 +++ .../Formal/enclave_SM4/host/main.cpp" | 51 ++ .../enclave_SM4/include/common_utils.h" | 69 +++ .../Formal/enclave_SM4/include/ec.h" | 545 ++++++++++++++++++ 13 files changed, 1160 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.config.xml" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.lds" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/enclave_SM4.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/manifest.txt.in" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/rsa_public_key_cloud.pem" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/sm4.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave_SM4.edl" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/main.cpp" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/common_utils.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/ec.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/CMakeLists.txt" new file mode 100644 index 0000000..acd2ef7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/CMakeLists.txt" @@ -0,0 +1,38 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +project(enclave_SM4) + +set(CMAKE_C_STANDARD 99) + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE enclave_SM4.edl) +#set(LOCAL_ROOT_PATH "$ENV{CC_SDK}") +#set(SECGEAR_INSTALL_PATH /usr/lib64/) + +if(CC_GP) + set(CODETYPE trustzone) + set(CODEGEN codegen_arm64) + execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) + string(REPLACE "\n" "" UUID ${UUID}) + add_definitions(-DPATH="/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + set(CODEGEN codegen_x86_64) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/CMakeLists.txt" new file mode 100644 index 0000000..7c4b75d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/CMakeLists.txt" @@ -0,0 +1,162 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM4) + +set(CMAKE_C_STANDARD 99) +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave_SM4.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + #set itrustee device key + set(DEVICEPEM ${CMAKE_CURRENT_SOURCE_DIR}/rsa_public_key_cloud.pem) + #set whilelist. default: /vendor/bin/teec_hello + set(WHITE_LIST_0 /vendor/bin/enclave_SM4) + set(WHITE_LIST_OWNER root) + set(WHITE_LIST_1 /vendor/bin/secgear_enclave_SM4) + set(WHITELIST WHITE_LIST_0 WHITE_LIST_1) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(COMMON_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \ + -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") +set(COMMON_CXX_FLAGS "${COMMON_C_FLAGS}") + +if(CC_GP) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt") + + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/enclave_inc + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${SECGEAR_INSTALL_PATH}) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -lsecgear_tee) + + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i /home/sunny/secGear/debug/lib/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT} + DESTINATION /data + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -O2 -nostdinc++") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE + ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.config.xml" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.config.xml" new file mode 100644 index 0000000..a5e05e0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.config.xml" @@ -0,0 +1,12 @@ + + 0 + 0 + 0x100000 + 0x80000 + 10 + 1 + + 1 + 0 + 0xFFFFFFFF + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.lds" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.lds" new file mode 100644 index 0000000..ab77e64 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/Enclave.lds" @@ -0,0 +1,11 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/enclave_SM4.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/enclave_SM4.c" new file mode 100644 index 0000000..a866474 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave/enclave_SM4.c" @@ -0,0 +1,42 @@ +#include "Enclave1_t.h" +#include +#include "sm4.h" + +uint32 message[4]; +uint32 key[4]; +uint32 res_enc[4], res_dec[4]; + +void sm4test(const uint32 *M, const uint32 *MK, const int rounds) { + SM4_CTX c; + sm4_init(&c, M, MK); + for (int i=0; i +#include "../include/common_utils.h" + +#define ENCRYPT 0 +#define DECRYPT 1 +const uint8 Sbox[256] = { + 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, + 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, + 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, + 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, + 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, + 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, + 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, + 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, + 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, + 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, + 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, + 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, + 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, + 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, + 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48, +}; +const uint32 FK[4] = { + 0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC, +}; +const uint32 CK[32] = { + 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, + 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, + 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, + 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, + 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, + 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, + 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, + 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279, +}; +#define L(B) ((B) ^ (ROTATE((B), 2)) ^ (ROTATE((B), 10)) ^ (ROTATE((B), 18)) ^ (ROTATE((B), 24))) +#define LP(B) ((B) ^ (ROTATE((B), 13)) ^ (ROTATE((B), 23))) +#define S(X) (((uint32)Sbox[((X) >> 24) & 0xFF] << 24) | \ + ((uint32)Sbox[((X) >> 16) & 0xFF] << 16) | \ + ((uint32)Sbox[((X) >> 8) & 0xFF] << 8) | \ + ((uint32)Sbox[(X) & 0xFF])) +#define T(X) L(S(X)) +#define TP(X) LP(S(X)) +#define F(X0, X1, X2, X3, rk) ((X0) ^ T((X1) ^ (X2) ^ (X3) ^ (rk))) + +typedef struct sm4_ctx_st { + uint32 M[4]; + uint32 rk[32]; +} SM4_CTX; + +int sm4_init(SM4_CTX *ctx, const uint32 *M, const uint32 *MK) { + memset(ctx, 0, sizeof(*ctx)); + uint32 K[36]; + memset(K, 0, sizeof(K)); + int i; + for (i = 0; i < 4; ++i) { + K[i] = MK[i] ^ FK[i]; + ctx->M[i] = M[i]; + } + for (i = 0; i < 32; ++i) { + ctx->rk[i] = K[i+4] = K[i] ^ TP(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]); + } + return 1; +} + +int sm4_round(SM4_CTX *ctx, int crypt_flag) { + int offset = (crypt_flag ? 31 : 0), i; + uint32 X[36]; + memset(X, 0, sizeof(X)); + for (i = 0; i < 4; ++i) { + X[i] = ctx->M[i]; + } + for (i = 0; i < 32; ++i) { + X[i+4] = F(X[i], X[i+1], X[i+2], X[i+3], ctx->rk[i^offset]); + } + ctx->M[0] = X[35]; + ctx->M[1] = X[34]; + ctx->M[2] = X[33]; + ctx->M[3] = X[32]; + return 1; +} + +int sm4_encrypt(SM4_CTX *ctx) { + return sm4_round(ctx, ENCRYPT); +} + +int sm4_decrypt(SM4_CTX *ctx) { + return sm4_round(ctx, DECRYPT); +} + +int sm4_final(uint32 *out, SM4_CTX *ctx) { + if (!memcpy(out, ctx->M, sizeof(ctx->M))) { + return 0; + } + return 1; +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave_SM4.edl" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave_SM4.edl" new file mode 100644 index 0000000..3de3690 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/enclave_SM4.edl" @@ -0,0 +1,16 @@ +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + + trusted { + public void setKeys([in, count=4] uint32_t *src); + public void setKeys([in, count=4] uint32_t *src); + public void callsm4test1(); + public void callsm4test2(); + public void getKeys([out, count=4] uint32_t *buf); + }; + + untrusted { + + }; +}; diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/CMakeLists.txt" new file mode 100644 index 0000000..2dae205 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/CMakeLists.txt" @@ -0,0 +1,88 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM4) +#set host exec name +set(OUTPUT secgear_enclave_SM4) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) + +set(CMAKE_CXX_STANDARD 11) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O2 -fPIE") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim) +else() + target_link_libraries(${OUTPUT} secgear) +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + #itrustee install whitelist /vender/bin/teec_hello + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION /vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/main.cpp" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/main.cpp" new file mode 100644 index 0000000..960a50d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/host/main.cpp" @@ -0,0 +1,51 @@ +#include"enclave.h" +#include"Enclave1_u.h" +#include +#include + +const u_int32_t message[4] = { + 0x01234567, 0x89ABCDEF, + 0xFEDCBA98, 0x76543210, +}; +const u_int32_t key[4] = { + 0x01234567, 0x89ABCDEF, + 0xFEDCBA98, 0x76543210, +}; + +int main(int argc, char* argv[]) { + cc_enclave_t *eid; + cc_enclave_result_t ret; + char *path = transferFromString(PATH); + + ret = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &eid); + if (ret != CC_SUCCESS) { + printf("ERR: %#x ,failed to create enclave.\n", ret); + return -1; + } + + u_int32_t res[4]; + setSM4Message(eid, message); + setSM4Key(eid, key); + callsm4test1(eid); + getSM4Result(eid, res); + printf("encrypt 1: "); + for (int i=0; i<4; i++){ + printf("%08X", res[i]); + } + printf("\n"); + + setSM4Message(eid, message); + setSM4Key(eid, key); + callsm4test2(eid); + getSM4Result(eid, res); + printf("encrypt 100000: "); + for (int i=0; i<4; i++){ + printf("%08X", res[i]); + } + printf("\n"); + + if (CC_SUCCESS != cc_enclave_destroy(eid)) { + return -1; + } + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/common_utils.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/common_utils.h" new file mode 100644 index 0000000..9251edc --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/common_utils.h" @@ -0,0 +1,69 @@ +#ifndef SECGEAR_SM_COMMON_UTILS +#define SECGEAR_SM_COMMON_UTILS + +#include +#define debugPrint (printf("%s: %s: %d\n",__FILE__,__FUNCTION__,__LINE__),fflush(stdout),1) + +typedef __uint8_t uint8; +typedef __uint16_t uint16; +typedef __uint32_t uint32; +typedef __uint64_t uint64; + +#define CONCAT_8x4(x0, x1, x2, x3) ((((uint32)(x0) << 8 | (x1)) << 8 | (x2)) << 8 | (x3)) // X = (x0 || x1 || x2 || x3) +#define CONCAT_16x2(x0, x1) ((uint32)(x0) << 16 | (x1)) // X = (x0 || x1) +#define EXTRACT_8_32(X, i) (((X) >> (((i) ^ 3) << 3)) & 0xFF) // X = (x0 || x1 || x2 || x3) +#define EXTRACT_16_32(X, i) (((X) >> (((i) ^ 1) << 4)) & 0xFFFF) // X = (x0 || x1) +#define EXTRACT_16H_31(X) (((X) >> 15) & 0xFFFF) // Higher 16-bit from 31-bit +#define EXTRACT_16L_31(X) ((X) & 0xFFFF) // Lower 16-bit from 31-bit + +#define ROTATE(a, n) (((a) << (n)) | (((a) & 0xFFFFFFFF) >> ((32 - (n)) & 31))) +#define ROTATE_31(a, n) ((((a) << (n)) & 0x7FFFFFFF) | (((a) & 0x7FFFFFFF) >> (31 - (n)))) + +#define GET_BIT_VALUE_32(x, i) (((x) >> (31 - (i))) & 1) + +const uint32 PREFIX_MASK_32[32] = { + 0x00000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE +}; + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/ec.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/ec.h" new file mode 100644 index 0000000..56adbe7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_SM4/include/ec.h" @@ -0,0 +1,545 @@ +#include /* BigNum */ +#include "common_utils.h" + +typedef struct ec_point_st { + BIGNUM *X; + BIGNUM *Y; + int is_infinity; +} EC_POINT; + +int EC_POINT_init(EC_POINT *point) { + point->X = BN_new(); + point->Y = BN_new(); + point->is_infinity = 0; + if (point->X == NULL || point->Y == NULL) { + BN_free(point->X); + BN_free(point->Y); + return 0; + } + return 1; +} + +EC_POINT *EC_POINT_new() { + EC_POINT *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_POINT_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_POINT_setXY(EC_POINT *r, const BIGNUM *x, const BIGNUM *y) { + if (r == NULL) { + return 0; + } + if (!BN_copy(r->X, x) || !(BN_copy(r->Y, y))) { + return 0; + } + return 1; +} + +const EC_POINT *EC_point_infinity() { + static const EC_POINT const_infinity = { NULL, NULL, 1 }; + return &const_infinity; +} + +int EC_POINT_is_infinity(const EC_POINT *point) { + return point->is_infinity; +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest == NULL) { + return 0; + } + if (EC_POINT_is_infinity(src)) { + dest->is_infinity = 1; + } + else{ + dest->is_infinity = 0; + if (!BN_copy(dest->X, src->X) || !BN_copy(dest->Y, src->Y)) return 0; + } + return 1; +} + +#define NORMAL 0x1 +#define COMPRESS 0x2 +#define MIX 0x4 + +int EC_POINT_ecp2bin(uint8 *out, const EC_POINT *point, int p_bytes, int flag) { + uint8 PC; + uint8 *p = out, *buf; + int i; + buf = malloc(p_bytes); + if (EC_POINT_is_infinity(point)) { + return 0; + } + if (flag == NORMAL) { + PC = 0x04; + *(p++) = PC; + if (!BN_bn2binpad(point->X, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + if (!BN_bn2binpad(point->Y, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_bin2ecp(EC_POINT *point, const uint8 *src, int p_bytes) { + if (point == NULL) { + return 0; + } + uint8 PC = *src; + const uint8 *data = src + 1; + uint8 *buf; + int i; + if (PC == 0x04) { + if (!BN_bin2bn(data, p_bytes, point->X) + || !BN_bin2bn(data+p_bytes, p_bytes, point->Y)) { + return 0; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_ecp2bin_normal(uint8 *out, const EC_POINT *point, int p_bytes) { + return EC_POINT_ecp2bin(out, point, p_bytes, NORMAL); +} + +// int EC_POINT_ecp2bin_compressed(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, COMPRESS); +// } + +// int EC_POINT_ecp2bin_mix(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, MIX); +// } + +typedef struct ec_group_st { + EC_POINT *generator; /* point G */ + BIGNUM *order; /* n */ + BIGNUM *cofactor; /* h */ + BIGNUM *field; /* module p */ + BIGNUM *a, *b; /* ECC parameter */ +} EC_GROUP; + +int EC_GROUP_init(EC_GROUP *group) { + group->generator = EC_POINT_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->generator == NULL || group->b == NULL) { + free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +EC_GROUP *EC_GROUP_new() { + EC_GROUP *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_GROUP_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest == NULL) { + return 0; + } + if (dest == src) { + return 1; + } + if (!EC_POINT_copy(dest->generator, src->generator) + || !BN_copy(dest->order, src->order) + || !BN_copy(dest->cofactor, src->cofactor) + || !BN_copy(dest->field, src->field) + || !BN_copy(dest->a, src->a) + || !BN_copy(dest->b, src->b)) { + return 0; + } + return 1; +} + +int EC_GROUP_set_param(EC_GROUP *group, const BIGNUM *field, const BIGNUM *a, const BIGNUM *b, const BIGNUM *order, const BIGNUM *cofactor, const EC_POINT *point) { + if (group == NULL) { + return 0; + } + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->generator = EC_POINT_new(); + if (group->cofactor == NULL + || group->generator == NULL) { + return 0; + } + if (!BN_copy(group->field, field) + || !BN_copy(group->a, a) + || !BN_copy(group->b, b) + || !BN_copy(group->order, order) + || !BN_copy(group->cofactor, cofactor) + || !EC_POINT_copy(group->generator, point)) { + return 0; + } + return 1; +} + +int EC_POINT_double(EC_POINT *r, const EC_POINT *a, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, EC_point_infinity()); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y)) { + goto done; + } + if (!BN_set_word(bn_value_3, 3) + || !BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_sqr(r->X, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_lshift1_quick(tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, r->X, tmp, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_add(EC_POINT *r, const EC_POINT *a, const EC_POINT *b, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *bx, *by, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (a == b) { + return EC_POINT_double(r, a, group); + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_infinity(b)) { + return EC_POINT_copy(r, a); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + bx = BN_CTX_get(ctx); + by = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y) + || !BN_copy(bx, b->X) + || !BN_copy(by, b->Y)) { + goto done; + } + if (BN_cmp(ax, bx) == 0) { + if (!BN_mod_add_quick(tmp, ay, by, p)) { + goto done; + } + if (BN_is_zero(tmp) + || !EC_POINT_copy(r, EC_point_infinity())) { + goto done; + } + if (!BN_set_word(bn_value_3, 3)) { + goto done; + } + if (!BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + else { + if (!BN_mod_sub_quick(lnum, by, ay, p)) { + goto done; + } + if (!BN_mod_sub_quick(ldeno, bx, ax, p)) { + goto done; + } + if (!BN_mod_inverse(ldeno, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + if (!BN_mod_sqr(tmp, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(tmp, tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, tmp, bx, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_mul(EC_POINT *r, const EC_POINT *a, const BIGNUM *b, const EC_GROUP *group) { + if (r == NULL) { + return 0; + } + if (BN_is_negative(b)) { + EC_POINT *_a = EC_POINT_new(); + BIGNUM *_b = BN_new(); + if (!EC_POINT_copy(_a, a) + || !BN_copy(_b, b) + || !BN_mod_sub_quick(_a->Y, group->field, _a->Y, group->field)) { + return 0; + } + BN_set_negative(_b, 0); + return EC_POINT_mul(r, _a, _b, group); + } + if (!EC_POINT_copy(r, EC_point_infinity())){ + return 0; + } + int bits = BN_num_bits(b); + for (int i = bits-1; i >= 0; --i) { + if (!EC_POINT_double(r, r, group)) { + return 0; + } + if (BN_is_bit_set(b, i)) { + if (!EC_POINT_add(r, r, a, group)) { + return 0; + } + } + } + return 1; +} + +/* + * Only for curve y^2 = x^3 + ax + b. + * Please check infinity before calling. + */ +int EC_POINT_on_curve_simple(const EC_POINT *point, const EC_GROUP *group) { + if (point == NULL || group == NULL) { + return 0; + } + if (EC_POINT_is_infinity(point)) { + return 1; + } + int ret = 0; + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *lhs, *rhs; + EC_POINT *Nq; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return ret; + } + BN_CTX_start(ctx); + p = group->field; + a = group->a; + b = group->b; + x = point->X; + y = point->Y; + lhs = BN_CTX_get(ctx); + rhs = BN_CTX_get(ctx); + Nq = EC_POINT_new(); + if (p == NULL + || a == NULL + || b == NULL + || x == NULL + || y == NULL + || rhs == NULL + || Nq == NULL) { + return ret; + } + if (!BN_mod_mul(lhs, y, y, p, ctx) + || !BN_mod_mul(rhs, x, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, a, p) + || !BN_mod_mul(rhs, rhs, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, b, p) + || !EC_POINT_mul(Nq, point, group->order, group)) { + return ret; + } + if (BN_cmp(lhs, rhs) != 0 + || !EC_POINT_is_infinity(Nq)) { + return ret; + } + ret = 1; + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +typedef struct ec_key_st { + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; +} EC_KEY; + +int EC_KEY_init(EC_KEY *key) { + key->group = EC_GROUP_new(); + key->pub_key = EC_POINT_new(); + key->priv_key = BN_new(); + if (key->group == NULL + || key->pub_key == NULL + || key->priv_key == NULL) { + free(key->group); + free(key->pub_key); + BN_free(key->priv_key); + return 0; + } + return 1; +} + +EC_KEY *EC_KEY_new() { + EC_KEY *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_KEY_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + if (!EC_GROUP_copy(key->group, group)) { + return 0; + } + return 1; +} + +int EC_KEY_set_priv_key(EC_KEY *key, const BIGNUM *priv_key) { + BIGNUM *tmp; + tmp = BN_dup(priv_key); + if (tmp == NULL) { + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = tmp; + return 1; +} + +int EC_KEY_generate_pub_key(EC_KEY *key) { + return EC_POINT_mul(key->pub_key, key->group->generator, key->priv_key, key->group); +} + +const BIGNUM *EC_KEY_get_priv_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_generate_key() {} -- Gitee From f35e8784c328e207a1402c59cfb0cb3446e5e12b Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:55:40 +0000 Subject: [PATCH 14/18] enclave_zuc Signed-off-by: wangxiaoxi1 --- .../Formal/enclave_ZUC/CMakeLists.txt" | 38 ++ .../enclave_ZUC/enclave/CMakeLists.txt" | 162 ++++++ .../enclave_ZUC/enclave/Enclave.config.xml" | 12 + .../Formal/enclave_ZUC/enclave/Enclave.lds" | 11 + .../Formal/enclave_ZUC/enclave/enclave_ZUC.c" | 3 + .../enclave_ZUC/enclave/manifest.txt.in" | 8 + .../enclave/rsa_public_key_cloud.pem" | 11 + .../Formal/enclave_ZUC/enclave/zuc.h" | 314 ++++++++++ .../Formal/enclave_ZUC/enclave/zuctest1.c" | 58 ++ .../Formal/enclave_ZUC/enclave/zuctest2.c" | 78 +++ .../Formal/enclave_ZUC/enclave/zuctest3.c" | 81 +++ .../Formal/enclave_ZUC/enclave_ZUC.edl" | 27 + .../Formal/enclave_ZUC/host/CMakeLists.txt" | 88 +++ .../Formal/enclave_ZUC/host/main.cpp" | 27 + .../enclave_ZUC/include/common_utils.h" | 69 +++ .../Formal/enclave_ZUC/include/ec.h" | 545 ++++++++++++++++++ 16 files changed, 1532 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.config.xml" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.lds" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/enclave_ZUC.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/manifest.txt.in" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuc.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest1.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest2.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest3.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave_ZUC.edl" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/main.cpp" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/common_utils.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/ec.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/CMakeLists.txt" new file mode 100644 index 0000000..e1b266d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/CMakeLists.txt" @@ -0,0 +1,38 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +project(enclave_ZUC) + +set(CMAKE_C_STANDARD 99) + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE enclave_ZUC.edl) +#set(LOCAL_ROOT_PATH "$ENV{CC_SDK}") +#set(SECGEAR_INSTALL_PATH /usr/lib64/) + +if(CC_GP) + set(CODETYPE trustzone) + set(CODEGEN codegen_arm64) + execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) + string(REPLACE "\n" "" UUID ${UUID}) + add_definitions(-DPATH="/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + set(CODEGEN codegen_x86_64) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/CMakeLists.txt" new file mode 100644 index 0000000..d600d38 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/CMakeLists.txt" @@ -0,0 +1,162 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_ZUC) + +set(CMAKE_C_STANDARD 99) +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave_ZUC.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + #set itrustee device key + set(DEVICEPEM ${CMAKE_CURRENT_SOURCE_DIR}/rsa_public_key_cloud.pem) + #set whilelist. default: /vendor/bin/teec_hello + set(WHITE_LIST_0 /vendor/bin/enclave_ZUC) + set(WHITE_LIST_OWNER root) + set(WHITE_LIST_1 /vendor/bin/secgear_enclave_ZUC) + set(WHITELIST WHITE_LIST_0 WHITE_LIST_1) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(COMMON_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \ + -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") +set(COMMON_CXX_FLAGS "${COMMON_C_FLAGS}") + +if(CC_GP) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt") + + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/enclave_inc + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${SECGEAR_INSTALL_PATH}) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -lsecgear_tee) + + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i /home/sunny/secGear/debug/lib/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT} + DESTINATION /data + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -O2 -nostdinc++") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE + ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.config.xml" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.config.xml" new file mode 100644 index 0000000..a5e05e0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.config.xml" @@ -0,0 +1,12 @@ + + 0 + 0 + 0x100000 + 0x80000 + 10 + 1 + + 1 + 0 + 0xFFFFFFFF + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.lds" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.lds" new file mode 100644 index 0000000..ab77e64 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/Enclave.lds" @@ -0,0 +1,11 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/enclave_ZUC.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/enclave_ZUC.c" new file mode 100644 index 0000000..01cc67a --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/enclave_ZUC.c" @@ -0,0 +1,3 @@ +#include "Enclave1_t.h" +#include +#include "zuc.h" \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/manifest.txt.in" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/manifest.txt.in" new file mode 100644 index 0000000..7b8ecf5 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/manifest.txt.in" @@ -0,0 +1,8 @@ +gpd.ta.appID: @UUID@ +gpd.ta.service_name: test0108 +gpd.ta.singleInstance: true +gpd.ta.multiSession: false +gpd.ta.multiCommand: false +gpd.ta.instanceKeepAlive: false +gpd.ta.dataSize: 16384 +gpd.ta.stackSize: 20480 diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" new file mode 100644 index 0000000..a321f63 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzAPwbnbgBg7JgXERA9Bx +p7GLI1S3e1zL83RMd2+GXb6kO4yMKUL3NUCE2HhA2BtQYmLyGovx59UUcKnU58is +Xux++kH+A2shmOPjYvEFuX0Kt8tc19b8M9b/iHsY8ZmKykqia2a5U+IrECRFJo5p +DWUnl7jrHVtq78BSR1c7iXG1frrEC0AYCuqKJo/fxfmOKL0Y9mENCB3nAwjn9unD +BsO/OhkqvvB3nkeuMfNKPh4wCqtQPve13eTojbuxjX/3ePijplTI5X2Gr+n6Ximn +fYRlytQmMgMl/db0ARSKNApq9bmwzVNrnGWWZWJksdRvf6iL7t17Gs4L9AApOuC9 +WkzxPvwp5ZUqjsGd4oJGWeC6ZE6BTw2vxE+xMFI9uAKHxq9pBKkcGMa0g4fANNNV ++W+8JZGanxEXKB3y/M7BCyQAPCWOHC/RNjmRA1gczLYCPzC4pWu935UZdF1RR6zY +CD3t+FoOGGET/g4CwWgyhb5qkp65Hs6ayYt/DUAqo+yBAgMBAAE= +-----END PUBLIC KEY----- diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuc.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuc.h" new file mode 100644 index 0000000..d8ea3ea --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuc.h" @@ -0,0 +1,314 @@ +#ifndef SECGEAR_ZUC_H +#define SECGEAR_ZUC_H + +#include +#include "../include/common_utils.h" + +/* S_BOX BEGIN */ + +const uint8 ZUC_S[2][256] = { + { + 0x3E, 0x72, 0x5B, 0x47, 0xCA, 0xE0, 0x00, 0x33, 0x04, 0xD1, 0x54, 0x98, 0x09, 0xB9, 0x6D, 0xCB, + 0x7B, 0x1B, 0xF9, 0x32, 0xAF, 0x9D, 0x6A, 0xA5, 0xB8, 0x2D, 0xFC, 0x1D, 0x08, 0x53, 0x03, 0x90, + 0x4D, 0x4E, 0x84, 0x99, 0xE4, 0xCE, 0xD9, 0x91, 0xDD, 0xB6, 0x85, 0x48, 0x8B, 0x29, 0x6E, 0xAC, + 0xCD, 0xC1, 0xF8, 0x1E, 0x73, 0x43, 0x69, 0xC6, 0xB5, 0xBD, 0xFD, 0x39, 0x63, 0x20, 0xD4, 0x38, + 0x76, 0x7D, 0xB2, 0xA7, 0xCF, 0xED, 0x57, 0xC5, 0xF3, 0x2C, 0xBB, 0x14, 0x21, 0x06, 0x55, 0x9B, + 0xE3, 0xEF, 0x5E, 0x31, 0x4F, 0x7F, 0x5A, 0xA4, 0x0D, 0x82, 0x51, 0x49, 0x5F, 0xBA, 0x58, 0x1C, + 0x4A, 0x16, 0xD5, 0x17, 0xA8, 0x92, 0x24, 0x1F, 0x8C, 0xFF, 0xD8, 0xAE, 0x2E, 0x01, 0xD3, 0xAD, + 0x3B, 0x4B, 0xDA, 0x46, 0xEB, 0xC9, 0xDE, 0x9A, 0x8F, 0x87, 0xD7, 0x3A, 0x80, 0x6F, 0x2F, 0xC8, + 0xB1, 0xB4, 0x37, 0xF7, 0x0A, 0x22, 0x13, 0x28, 0x7C, 0xCC, 0x3C, 0x89, 0xC7, 0xC3, 0x96, 0x56, + 0x07, 0xBF, 0x7E, 0xF0, 0x0B, 0x2B, 0x97, 0x52, 0x35, 0x41, 0x79, 0x61, 0xA6, 0x4C, 0x10, 0xFE, + 0xBC, 0x26, 0x95, 0x88, 0x8A, 0xB0, 0xA3, 0xFB, 0xC0, 0x18, 0x94, 0xF2, 0xE1, 0xE5, 0xE9, 0x5D, + 0xD0, 0xDC, 0x11, 0x66, 0x64, 0x5C, 0xEC, 0x59, 0x42, 0x75, 0x12, 0xF5, 0x74, 0x9C, 0xAA, 0x23, + 0x0E, 0x86, 0xAB, 0xBE, 0x2A, 0x02, 0xE7, 0x67, 0xE6, 0x44, 0xA2, 0x6C, 0xC2, 0x93, 0x9F, 0xF1, + 0xF6, 0xFA, 0x36, 0xD2, 0x50, 0x68, 0x9E, 0x62, 0x71, 0x15, 0x3D, 0xD6, 0x40, 0xC4, 0xE2, 0x0F, + 0x8E, 0x83, 0x77, 0x6B, 0x25, 0x05, 0x3F, 0x0C, 0x30, 0xEA, 0x70, 0xB7, 0xA1, 0xE8, 0xA9, 0x65, + 0x8D, 0x27, 0x1A, 0xDB, 0x81, 0xB3, 0xA0, 0xF4, 0x45, 0x7A, 0x19, 0xDF, 0xEE, 0x78, 0x34, 0x60, + }, + { + 0x55, 0xC2, 0x63, 0x71, 0x3B, 0xC8, 0x47, 0x86, 0x9F, 0x3C, 0xDA, 0x5B, 0x29, 0xAA, 0xFD, 0x77, + 0x8C, 0xC5, 0x94, 0x0C, 0xA6, 0x1A, 0x13, 0x00, 0xE3, 0xA8, 0x16, 0x72, 0x40, 0xF9, 0xF8, 0x42, + 0x44, 0x26, 0x68, 0x96, 0x81, 0xD9, 0x45, 0x3E, 0x10, 0x76, 0xC6, 0xA7, 0x8B, 0x39, 0x43, 0xE1, + 0x3A, 0xB5, 0x56, 0x2A, 0xC0, 0x6D, 0xB3, 0x05, 0x22, 0x66, 0xBF, 0xDC, 0x0B, 0xFA, 0x62, 0x48, + 0xDD, 0x20, 0x11, 0x06, 0x36, 0xC9, 0xC1, 0xCF, 0xF6, 0x27, 0x52, 0xBB, 0x69, 0xF5, 0xD4, 0x87, + 0x7F, 0x84, 0x4C, 0xD2, 0x9C, 0x57, 0xA4, 0xBC, 0x4F, 0x9A, 0xDF, 0xFE, 0xD6, 0x8D, 0x7A, 0xEB, + 0x2B, 0x53, 0xD8, 0x5C, 0xA1, 0x14, 0x17, 0xFB, 0x23, 0xD5, 0x7D, 0x30, 0x67, 0x73, 0x08, 0x09, + 0xEE, 0xB7, 0x70, 0x3F, 0x61, 0xB2, 0x19, 0x8E, 0x4E, 0xE5, 0x4B, 0x93, 0x8F, 0x5D, 0xDB, 0xA9, + 0xAD, 0xF1, 0xAE, 0x2E, 0xCB, 0x0D, 0xFC, 0xF4, 0x2D, 0x46, 0x6E, 0x1D, 0x97, 0xE8, 0xD1, 0xE9, + 0x4D, 0x37, 0xA5, 0x75, 0x5E, 0x83, 0x9E, 0xAB, 0x82, 0x9D, 0xB9, 0x1C, 0xE0, 0xCD, 0x49, 0x89, + 0x01, 0xB6, 0xBD, 0x58, 0x24, 0xA2, 0x5F, 0x38, 0x78, 0x99, 0x15, 0x90, 0x50, 0xB8, 0x95, 0xE4, + 0xD0, 0x91, 0xC7, 0xCE, 0xED, 0x0F, 0xB4, 0x6F, 0xA0, 0xCC, 0xF0, 0x02, 0x4A, 0x79, 0xC3, 0xDE, + 0xA3, 0xEF, 0xEA, 0x51, 0xE6, 0x6B, 0x18, 0xEC, 0x1B, 0x2C, 0x80, 0xF7, 0x74, 0xE7, 0xFF, 0x21, + 0x5A, 0x6A, 0x54, 0x1E, 0x41, 0x31, 0x92, 0x35, 0xC4, 0x33, 0x07, 0x0A, 0xBA, 0x7E, 0x0E, 0x34, + 0x88, 0xB1, 0x98, 0x7C, 0xF3, 0x3D, 0x60, 0x6C, 0x7B, 0xCA, 0xD3, 0x1F, 0x32, 0x65, 0x04, 0x28, + 0x64, 0xBE, 0x85, 0x9B, 0x2F, 0x59, 0x8A, 0xD7, 0xB0, 0x25, 0xAC, 0xAF, 0x12, 0x03, 0xE2, 0xF2, + }, +}; + +const uint16 ZUC_D[16] = { + 042327, 023274, 061153, 011536, + 053611, 032742, 070465, 004657, + 046570, 027423, 065704, 015361, + 057046, 036115, 074232, 043654, +}; + +#define ZUC_S0(x) ZUC_S[0][x] +#define ZUC_S1(x) ZUC_S[1][x] +#define ZUC_S_BOX(X) \ + CONCAT_8x4( \ + ZUC_S0(EXTRACT_8_32(X, 0)), \ + ZUC_S1(EXTRACT_8_32(X, 1)), \ + ZUC_S0(EXTRACT_8_32(X, 2)), \ + ZUC_S1(EXTRACT_8_32(X, 3)) \ + ) + +/* S_BOX END */ + +/* MOD_OPERATIONS BEGIN */ + +#define ZUC_MOD_NUM 0x7FFFFFFF +uint32 zuc_add(uint32 a, uint32 b) { + uint32 c = a + b; + return (c & ZUC_MOD_NUM) + (c >> 31); +} +uint32 zuc_mul(uint32 a, uint32 b) { + uint32 res = 0; + for (int i = 0; i < 31; ++i) { + if (b & (1 << i)) { + res = zuc_add(res, ROTATE_31(a, i)); + } + } + return res; +} +uint32 zuc_mul_powof2(uint32 a, uint32 log2b) { + return ROTATE_31(a, log2b); +} + +/* MOD_OPERATIONS END */ + +/* LFSR BEGIN */ + +typedef struct ZUC_LFSR_st { + uint32 S[16]; /* 31-bit */ +} ZUC_LFSR; + +void zuc_lfsr_init(ZUC_LFSR *lfsr, uint32 u) { /* u: 31-bit */ + uint32 v = zuc_add( + zuc_add( + zuc_add( + zuc_mul_powof2(lfsr->S[15], 15), + zuc_mul_powof2(lfsr->S[13], 17) + ), + zuc_add( + zuc_mul_powof2(lfsr->S[10], 21), + zuc_mul_powof2(lfsr->S[4], 20) + ) + ), + zuc_add(lfsr->S[0], zuc_mul_powof2(lfsr->S[0], 8)) + ); + uint32 S16 = zuc_add(v, u); + S16 = zuc_add(S16, ZUC_MOD_NUM); + for (int i = 0; i < 15; ++i) { + lfsr->S[i] = lfsr->S[i + 1]; + } + lfsr->S[15] = S16; +} +void zuc_lfsr_work(ZUC_LFSR *lfsr) { + uint32 S16 = zuc_add( + zuc_add( + zuc_add( + zuc_mul_powof2(lfsr->S[15], 15), + zuc_mul_powof2(lfsr->S[13], 17) + ), + zuc_add( + zuc_mul_powof2(lfsr->S[10], 21), + zuc_mul_powof2(lfsr->S[4], 20) + ) + ), + zuc_add(lfsr->S[0], zuc_mul_powof2(lfsr->S[0], 8)) + ); + S16 = zuc_add(S16, ZUC_MOD_NUM); + for (int i = 0; i < 15; ++i) { + lfsr->S[i] = lfsr->S[i + 1]; + } + lfsr->S[15] = S16; +} + +/* LFSR END */ + +/* BR BEGIN */ + +typedef struct ZUC_BR_st { + uint32 X[4]; /* 32-bit */ +} ZUC_BR_CTX; + +void zuc_br(ZUC_BR_CTX *br, ZUC_LFSR *lfsr) { + br->X[0] = CONCAT_16x2(EXTRACT_16H_31(lfsr->S[15]), EXTRACT_16L_31(lfsr->S[14])); + br->X[1] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[11]), EXTRACT_16H_31(lfsr->S[9])); + br->X[2] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[7]), EXTRACT_16H_31(lfsr->S[5])); + br->X[3] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[2]), EXTRACT_16H_31(lfsr->S[0])); +} + +/* BR END */ + +/* F BEGIN */ + +#define ZUC_L1(X) \ + ((X) ^ ROTATE((X), 2) ^ ROTATE((X), 10) ^ ROTATE((X), 18) ^ ROTATE((X), 24)) +#define ZUC_L2(X) \ + ((X) ^ ROTATE((X), 8) ^ ROTATE((X), 14) ^ ROTATE((X), 22) ^ ROTATE((X), 30)) + +typedef struct ZUC_F_st { + uint32 R1, R2; /* 32-bit */ +} ZUC_F_CTX; + +uint32 zuc_f(ZUC_F_CTX *f, ZUC_BR_CTX *br) { /* X: 32-bit */ + uint32 X0 = br->X[0], X1 = br->X[1], X2 = br->X[2]; + uint32 R1 = f->R1, R2 = f->R2; + uint32 W = (X0 ^ R1) + R2; + uint32 W1 = R1 + X1; + uint32 W2 = R2 ^ X2; + R1 = ZUC_S_BOX(ZUC_L1(CONCAT_16x2( + EXTRACT_16_32(W1, 1), + EXTRACT_16_32(W2, 0) + ))); + R2 = ZUC_S_BOX(ZUC_L2(CONCAT_16x2( + EXTRACT_16_32(W2, 1), + EXTRACT_16_32(W1, 0) + ))); + f->R1 = R1; + f->R2 = R2; + return W; +} + +/* F END */ + +/* ZUC_MAIN BEGIN */ + +#define ZUC_INIT_CONCAT(k, d, iv) (((uint32)(k) << 15 | (d)) << 8 | (iv)) +#define ZUC_INTEGRITY_CONCAT(K1, K2, offset) \ + (((K1) << (offset)) | ((offset) ? (K2) >> (32 - (offset)) : 0)) + +typedef struct ZUCstate_st { + ZUC_LFSR lfsr; + ZUC_BR_CTX br; + ZUC_F_CTX f; +} ZUC_CTX; + +/* Initiate phase. Both k and iv are uint8 arrays of length 16. */ +int zuc_init(ZUC_CTX *z, uint8 k[], uint8 iv[]) { + memset(z, 0, sizeof(*z)); + for (int i = 0; i < 16; ++i) { + z->lfsr.S[i] = ZUC_INIT_CONCAT(k[i], ZUC_D[i], iv[i]); + } + for (int i = 0; i < 32; ++i) { + zuc_br(&z->br, &z->lfsr); + uint32 W = zuc_f(&z->f, &z->br); + zuc_lfsr_init(&z->lfsr, W >> 1); + } + return 1; +} + +/* Work phase. Z is uint32 array that stores output keys. */ +/* len is the length of the key in the unit of 32-bit. */ +int zuc_work(ZUC_CTX *z, uint32 Z[], size_t len) { + zuc_br(&z->br, &z->lfsr); + (void)zuc_f(&z->f, &z->br); + zuc_lfsr_work(&z->lfsr); + for (size_t i = 0; i < len; ++i) { + zuc_br(&z->br, &z->lfsr); + Z[i] = zuc_f(&z->f, &z->br) ^ z->br.X[3]; + zuc_lfsr_work(&z->lfsr); + } + return 1; +} + +/* Generate 32-bit ZUC key stream. Use the array Z[] to receive the output. */ +int zuc_final(uint8 k[], uint8 iv[], uint32 Z[], size_t len) { + ZUC_CTX res, *z; + z = &res; + zuc_init(z, k, iv); + zuc_work(z, Z, len); + return 1; +} + +/* Use the array obs[] to receive the output. */ +int zuc_confidentiality(uint32 count, uint8 bearer, uint8 direction, uint8 ck[], + uint32 length, uint32 ibs[], uint32 obs[]) { + /* + * @param COUNT (length = 32b, counter) + * @param BEARER (length = 5b, bearer identifier) + * @param DIRECTION (length = 1b, direction identifier) + * @param CK (length = 128b = 8b * 16, confidential key) + * @param LENGTH (length = 32b, bit length of input bit stream) + * @param IBS (length = LENGTH b = 32b * L, input bit stream) + * @param OBS (length = LENGTH b = 32b * L, output bit stream) + */ + + /* Initiate k and iv for ZUC. */ + bearer &= 0x1F; direction &= 1; + uint8 _k[16], _iv[16], _count[4]; + memcpy(_k, ck, sizeof _k); + for (int i = 0; i < 4; ++i) { + _count[i] = EXTRACT_8_32(count, i); + } + _iv[0] = _count[0]; _iv[1] = _count[1]; _iv[2] = _count[2]; _iv[3] = _count[3]; + _iv[4] = (uint8)((bearer << 1 | direction) << 2); _iv[5] = _iv[6] = _iv[7] = 0; + for (int i = 8; i < 16; ++i) { + _iv[i] = _iv[i ^ 8]; + } + size_t L = (length >> 5) + ((length & 0x1F) ? 1 : 0); + uint32 Z[L]; + zuc_final(_k, _iv, Z, L); + for (size_t i = 0; i < L; ++i) { + obs[i] = ibs[i] ^ Z[i]; + } + if (length & 0x1F) { + obs[L - 1] &= PREFIX_MASK_32[length & 0x1F]; + } + return 1; +} + +uint32 zuc_integrity(uint32 count, uint8 bearer, uint8 direction, uint8 ik[], + uint32 length, uint32 M[]) { + /* + * @param COUNT (length = 32b, counter) + * @param BEARER (length = 5b, bearer identifier) + * @param DIRECTION (length = 1b, direction identifier) + * @param IK (length = 128b = 8b * 16, integrity key) + * @param LENGTH (length = 32b, bit length of input bit stream) + * @param M (length = LENGTH b = 32b * L, input massage stream) + * @return MAC (length = 32b, massage verification code) + */ + + /* Initiate k and iv for ZUC. */ + bearer &= 0x1F; direction &= 1; + uint8 _k[16], _iv[16], _count[4]; + memcpy(_k, ik, sizeof _k); + for (int i = 0; i < 4; ++i) { + _count[i] = EXTRACT_8_32(count, i); + } + _iv[0] = _count[0]; _iv[1] = _count[1]; _iv[2] = _count[2]; _iv[3] = _count[3]; + _iv[4] = (uint8)(bearer << 3); _iv[5] = _iv[6] = _iv[7] = 0; + _iv[8] = _iv[0] ^ (uint8)(direction << 7); + _iv[9] = _iv[1]; _iv[10] = _iv[2]; _iv[11] = _iv[3]; + _iv[12] = _iv[4]; _iv[13] = _iv[5]; + _iv[14] = _iv[6] ^ (uint8)(direction << 7); + _iv[15] = _iv[7]; + size_t L = (length >> 5) + ((length & 0x1F) ? 1 : 0) + 2; + uint32 Z[L]; + uint32 T = 0; + zuc_final(_k, _iv, Z, L); + for (size_t i = 0; i < length; ++i) { + if (GET_BIT_VALUE_32(M[i >> 5], i & 0x1F)) { + T = T ^ ZUC_INTEGRITY_CONCAT(Z[i >> 5], Z[(i >> 5) + 1], i & 0x1F); + } + } + T = T ^ ZUC_INTEGRITY_CONCAT(Z[length >> 5], Z[(length >> 5) + 1], length & 0x1F); + T = T ^ Z[L - 1]; + return T; +} + +/* ZUC_MAIN END */ + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest1.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest1.c" new file mode 100644 index 0000000..c1cb8eb --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest1.c" @@ -0,0 +1,58 @@ +#define SECGEAR_ZUC_DEBUG +#include +#include "zuc.h" + +uint8 k_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +uint8 iv_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +uint8 k_test2[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; +uint8 iv_test2[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; + +uint8 k_test3[16] = { + 0x3D, 0x4C, 0x4B, 0xE9, + 0x6A, 0x82, 0xFD, 0xAE, + 0xB5, 0x8F, 0x64, 0x1D, + 0xB1, 0x7B, 0x45, 0x5B, +}; +uint8 iv_test3[16] = { + 0x84, 0x31, 0x9A, 0xA8, + 0xDE, 0x69, 0x15, 0xCA, + 0x1F, 0x6B, 0xDA, 0x6B, + 0xFB, 0xD8, 0xC7, 0x66, +}; + +void zuc_test(uint8 k[], uint8 iv[]) { + const size_t LEN = 32; + uint32 keys[LEN]; + zuc_final(k, iv, keys, LEN); +} + +int main(){ + printf("Test 1: \n"); + zuc_test(k_test1, iv_test1); + printf("Test 2: \n"); + zuc_test(k_test2, iv_test2); + printf("Test 3: \n"); + zuc_test(k_test3, iv_test3); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest2.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest2.c" new file mode 100644 index 0000000..2db8404 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest2.c" @@ -0,0 +1,78 @@ +#define SECGEAR_ZUC_DEBUG_2 +#include +#include "zuc.h" + +uint8 ck_test1[16] = { + 0x17, 0x3d, 0x14, 0xba, + 0x50, 0x03, 0x73, 0x1d, + 0x7a, 0x60, 0x04, 0x94, + 0x70, 0xf0, 0x0a, 0x29, +}; +uint32 count_test1 = 0x66035492; +uint8 bearer_test1 = 0xf; +uint8 dirc_test1 = 0x0; +uint32 len_test1 = 0xc1; +uint32 ibs_test1[] = { + 0x6cf65340, 0x735552ab, 0x0c9752fa, 0x6f9025fe, 0x0bd675d9, + 0x005875b2, 0x00000000, +}; + +uint8 ck_test2[16] = { + 0xe5, 0xbd, 0x3e, 0xa0, + 0xeb, 0x55, 0xad, 0xe8, + 0x66, 0xc6, 0xac, 0x58, + 0xbd, 0x54, 0x30, 0x2a, +}; +uint32 count_test2 = 0x56823; +uint8 bearer_test2 = 0x18; +uint8 dirc_test2 = 0x1; +uint32 len_test2 = 0x320; +uint32 ibs_test2[] = { + 0x14a8ef69, 0x3d678507, 0xbbe7270a, 0x7f67ff50, 0x06c3525b, + 0x9807e467, 0xc4e56000, 0xba338f5d, 0x42955903, 0x67518222, + 0x46c80d3b, 0x38f07f4b, 0xe2d8ff58, 0x05f51322, 0x29bde93b, + 0xbbdcaf38, 0x2bf1ee97, 0x3fbf9977, 0xbada8945, 0x847a2a6c, + 0x9ad34a66, 0x7554e04d, 0x1f7fa2c3, 0x3241bd8f, 0x01ba220d, +}; + +uint8 ck_test3[16] = { + 0xe1, 0x3f, 0xed, 0x21, + 0xb4, 0x6e, 0x4e, 0x7e, + 0xc3, 0x12, 0x53, 0xb2, + 0xbb, 0x17, 0xb3, 0xe0, +}; +uint32 count_test3 = 0x2738cdaa; +uint8 bearer_test3 = 0x1a; +uint8 dirc_test3 = 0x0; +uint32 len_test3 = 0xfb3; +uint32 ibs_test3[] = { + 0x8d74e20d, 0x54894e06, 0xd3cb13cb, 0x3933065e, 0x8674be62, 0xadb1c72b, 0x3a646965, 0xab63cb7b, 0x7854dfdc, 0x27e84929, + 0xf49c64b8, 0x72a490b1, 0x3f957b64, 0x827e71f4, 0x1fbd4269, 0xa42c97f8, 0x24537027, 0xf86e9f4a, 0xd82d1df4, 0x51690fdd, + 0x98b6d03f, 0x3a0ebe3a, 0x312d6b84, 0x0ba5a182, 0x0b2a2c97, 0x09c090d2, 0x45ed267c, 0xf845ae41, 0xfa975d33, 0x33ac3009, + 0xfd40eba9, 0xeb5b8857, 0x14b768b6, 0x97138baf, 0x21380eca, 0x49f644d4, 0x8689e421, 0x5760b906, 0x739f0d2b, 0x3f091133, + 0xca15d981, 0xcbe401ba, 0xf72d05ac, 0xe05cccb2, 0xd297f4ef, 0x6a5f58d9, 0x1246cfa7, 0x7215b892, 0xab441d52, 0x78452795, + 0xccb7f5d7, 0x9057a1c4, 0xf77f80d4, 0x6db2033c, 0xb79bedf8, 0xe60551ce, 0x10c667f6, 0x2a97abaf, 0xabbcd677, 0x2018df96, + 0xa282ea73, 0x7ce2cb33, 0x1211f60d, 0x5354ce78, 0xf9918d9c, 0x206ca042, 0xc9b62387, 0xdd709604, 0xa50af16d, 0x8d35a890, + 0x6be484cf, 0x2e74a928, 0x99403643, 0x53249b27, 0xb4c9ae29, 0xeddfc7da, 0x6418791a, 0x4e7baa06, 0x60fa6451, 0x1f2d685c, + 0xc3a5ff70, 0xe0d2b742, 0x92e3b8a0, 0xcd6b04b1, 0xc790b8ea, 0xd2703708, 0x540dea2f, 0xc09c3da7, 0x70f65449, 0xe84d817a, + 0x4f551055, 0xe19ab850, 0x18a0028b, 0x71a144d9, 0x6791e9a3, 0x57793350, 0x4eee0060, 0x340c69d2, 0x74e1bf9d, 0x805dcbcc, + 0x1a6faa97, 0x6800b6ff, 0x2b671dc4, 0x63652fa8, 0xa33ee509, 0x74c1c21b, 0xe01eabb2, 0x16743026, 0x9d72ee51, 0x1c9dde30, + 0x797c9a25, 0xd86ce74f, 0x5b961be5, 0xfdfb6807, 0x814039e7, 0x137636bd, 0x1d7fa9e0, 0x9efd2007, 0x505906a5, 0xac45dfde, + 0xed7757bb, 0xee745749, 0xc2963335, 0x0bee0ea6, 0xf409df45, 0x80160000, +}; + +void zuc_test2(uint32 count, uint8 bearer, uint8 direction, uint8 ck[], + uint32 length, uint32 ibs[], uint32 obs[]) { + zuc_confidentiality(count, bearer, direction, ck, length, ibs, obs); +} + +int main(){ + uint32 obs_test[130]; + printf("Test 1: \n"); + zuc_test2(count_test1, bearer_test1, dirc_test1, ck_test1, len_test1, ibs_test1, obs_test); + printf("Test 2: \n"); + zuc_test2(count_test2, bearer_test2, dirc_test2, ck_test2, len_test2, ibs_test2, obs_test); + printf("Test 3: \n"); + zuc_test2(count_test3, bearer_test3, dirc_test3, ck_test3, len_test3, ibs_test3, obs_test); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest3.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest3.c" new file mode 100644 index 0000000..7a09e8c --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave/zuctest3.c" @@ -0,0 +1,81 @@ +#define SECGEAR_ZUC_DEBUG_3 +#include +#include "zuc.h" + +uint8 ik_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +uint32 count_test1 = 0; +uint8 bearer_test1 = 0; +uint8 dirc_test1 = 0; +uint32 len_test1 = 1; +uint32 m_test1[] = { + 0x00000000, +}; + +uint8 ik_test2[16] = { + 0xc9, 0xe6, 0xce, 0xc4, + 0x60, 0x7c, 0x72, 0xdb, + 0x00, 0x0a, 0xef, 0xa8, + 0x83, 0x85, 0xab, 0x0a, +}; +uint32 count_test2 = 0xa94059da; +uint8 bearer_test2 = 0xa; +uint8 dirc_test2 = 0x1; +uint32 len_test2 = 0x241; +uint32 m_test2[] = { + 0x983b41d4, 0x7d780c9e, 0x1ad11d7e, 0xb70391b1, 0xde0b35da, 0x2dc62f83, 0xe7b78d63, 0x06ca0ea0, 0x7e941b7b, + 0xe91348f9, 0xfcb170e2, 0x217fecd9, 0x7f9f68ad, 0xb16e5d7d, 0x21e569d2, 0x80ed775c, 0xebde3f40, 0x93c53881, + 0x00000000, +}; + +uint8 ik_test3[16] = { + 0x6b, 0x8b, 0x08, 0xee, + 0x79, 0xe0, 0xb5, 0x98, + 0x2d, 0x6d, 0x12, 0x8e, + 0xa9, 0xf2, 0x20, 0xcb, +}; +uint32 count_test3 = 0x561eb2dd; +uint8 bearer_test3 = 0x1c; +uint8 dirc_test3 = 0x0; +uint32 len_test3 = 0x1626; +uint32 m_test3[] = { + 0x5bad7247, 0x10ba1c56, 0xd5a315f8, 0xd40f6e09, 0x3780be8e, 0x8de07b69, 0x92432018, 0xe08ed96a, 0x5734af8b, + 0xad8a575d, 0x3a1f162f, 0x85045cc7, 0x70925571, 0xd9f5b94e, 0x454a77c1, 0x6e72936b, 0xf016ae15, 0x7499f054, + 0x3b5d52ca, 0xa6dbeab6, 0x97d2bb73, 0xe41b8075, 0xdce79b4b, 0x86044f66, 0x1d4485a5, 0x43dd7860, 0x6e0419e8, + 0x059859d3, 0xcb2b67ce, 0x0977603f, 0x81ff839e, 0x33185954, 0x4cfbc8d0, 0x0fef1a4c, 0x8510fb54, 0x7d6b06c6, + 0x11ef44f1, 0xbce107cf, 0xa45a06aa, 0xb360152b, 0x28dc1ebe, 0x6f7fe09b, 0x0516f9a5, 0xb02a1bd8, 0x4bb0181e, + 0x2e89e19b, 0xd8125930, 0xd178682f, 0x3862dc51, 0xb636f04e, 0x720c47c3, 0xce51ad70, 0xd94b9b22, 0x55fbae90, + 0x6549f499, 0xf8c6d399, 0x47ed5e5d, 0xf8e2def1, 0x13253e7b, 0x08d0a76b, 0x6bfc68c8, 0x12f375c7, 0x9b8fe5fd, + 0x85976aa6, 0xd46b4a23, 0x39d8ae51, 0x47f680fb, 0xe70f978b, 0x38effd7b, 0x2f7866a2, 0x2554e193, 0xa94e98a6, + 0x8b74bd25, 0xbb2b3f5f, 0xb0a5fd59, 0x887f9ab6, 0x8159b717, 0x8d5b7b67, 0x7cb546bf, 0x41eadca2, 0x16fc1085, + 0x0128f8bd, 0xef5c8d89, 0xf96afa4f, 0xa8b54885, 0x565ed838, 0xa950fee5, 0xf1c3b0a4, 0xf6fb71e5, 0x4dfd169e, + 0x82cecc72, 0x66c850e6, 0x7c5ef0ba, 0x960f5214, 0x060e71eb, 0x172a75fc, 0x1486835c, 0xbea65344, 0x65b055c9, + 0x6a72e410, 0x52241823, 0x25d83041, 0x4b40214d, 0xaa8091d2, 0xe0fb010a, 0xe15c6de9, 0x0850973b, 0xdf1e423b, + 0xe148a237, 0xb87a0c9f, 0x34d4b476, 0x05b803d7, 0x43a86a90, 0x399a4af3, 0x96d3a120, 0x0a62f3d9, 0x507962e8, + 0xe5bee6d3, 0xda2bb3f7, 0x237664ac, 0x7a292823, 0x900bc635, 0x03b29e80, 0xd63f6067, 0xbf8e1716, 0xac25beba, + 0x350deb62, 0xa99fe031, 0x85eb4f69, 0x937ecd38, 0x7941fda5, 0x44ba67db, 0x09117749, 0x38b01827, 0xbcc69c92, + 0xb3f772a9, 0xd2859ef0, 0x03398b1f, 0x6bbad7b5, 0x74f7989a, 0x1d10b2df, 0x798e0dbf, 0x30d65874, 0x64d24878, + 0xcd00c0ea, 0xee8a1a0c, 0xc753a279, 0x79e11b41, 0xdb1de3d5, 0x038afaf4, 0x9f5c682c, 0x3748d8a3, 0xa9ec54e6, + 0xa371275f, 0x1683510f, 0x8e4f9093, 0x8f9ab6e1, 0x34c2cfdf, 0x4841cba8, 0x8e0cff2b, 0x0bcc8e6a, 0xdcb71109, + 0xb5198fec, 0xf1bb7e5c, 0x531aca50, 0xa56a8a3b, 0x6de59862, 0xd41fa113, 0xd9cd9578, 0x08f08571, 0xd9a4bb79, + 0x2af271f6, 0xcc6dbb8d, 0xc7ec36e3, 0x6be1ed30, 0x8164c31c, 0x7c0afc54, 0x1c000000, +}; + +uint32 zuc_test3(uint32 count, uint8 bearer, uint8 direction, uint8 ik[], + uint32 length, uint32 M[]) { + return zuc_integrity(count, bearer, direction, ik, length, M); +} + +int main(){ + printf("Test 1: \n"); + zuc_test3(count_test1, bearer_test1, dirc_test1, ik_test1, len_test1, m_test1); + printf("Test 2: \n"); + zuc_test3(count_test2, bearer_test2, dirc_test2, ik_test2, len_test2, m_test2); + printf("Test 3: \n"); + zuc_test3(count_test3, bearer_test3, dirc_test3, ik_test3, len_test3, m_test3); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave_ZUC.edl" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave_ZUC.edl" new file mode 100644 index 0000000..0e454ee --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/enclave_ZUC.edl" @@ -0,0 +1,27 @@ +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + + trusted { + public void setRSAsource([in, size=len] char* src, size_t len); + public void getRSAresult([out, size=len] char* buf, size_t len); + public void calcEmbeddingResult(); + public void initKeys([in] uint32_t *src); + public void registerSeed([in] uint32_t *src); + public void setKeys([in,count=2] uint32_t *K); + public void getKeys([out,count=2] uint32_t *K); + public void setD([in, size=len] char* src, size_t len); + public void setCD([in, size=len] char* src, size_t len); + public void setN([in, size=len] char* src, size_t len); + public void getCD([out, size=len] char* buf, size_t len); + public void getX([out, size=len] char* buf, size_t len); + public void getMu([out, size=len] char* buf, size_t len); + public void getK([out, size=len] char* buf, size_t len); + public void getNWID([out, size=len] char* buf, size_t len); + public void setNPW([in, size=len] char* src, size_t len); + }; + + untrusted { + + }; +}; diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/CMakeLists.txt" new file mode 100644 index 0000000..1330657 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/CMakeLists.txt" @@ -0,0 +1,88 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_ZUC) +#set host exec name +set(OUTPUT secgear_enclave_ZUC) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) + +set(CMAKE_CXX_STANDARD 11) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O2 -fPIE") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim) +else() + target_link_libraries(${OUTPUT} secgear) +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + #itrustee install whitelist /vender/bin/teec_hello + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION /vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/main.cpp" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/main.cpp" new file mode 100644 index 0000000..9add3a7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/host/main.cpp" @@ -0,0 +1,27 @@ +#include"enclave.h" +#include"Enclave1_u.h" +#include +#include + +#define MAX_LEN 1024 + +using namespace std; + +int main(int argc, char* argv[]) { + cc_enclave_t *eid; + cc_enclave_result_t ret; + char *path = transferFromString(PATH); + + ret = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &eid); + if (ret != CC_SUCCESS) { + printf("ERR: %#x ,failed to create enclave.\n", ret); + return -1; + } + + + + if (CC_SUCCESS != cc_enclave_destroy(eid)) { + return -1; + } + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/common_utils.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/common_utils.h" new file mode 100644 index 0000000..9251edc --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/common_utils.h" @@ -0,0 +1,69 @@ +#ifndef SECGEAR_SM_COMMON_UTILS +#define SECGEAR_SM_COMMON_UTILS + +#include +#define debugPrint (printf("%s: %s: %d\n",__FILE__,__FUNCTION__,__LINE__),fflush(stdout),1) + +typedef __uint8_t uint8; +typedef __uint16_t uint16; +typedef __uint32_t uint32; +typedef __uint64_t uint64; + +#define CONCAT_8x4(x0, x1, x2, x3) ((((uint32)(x0) << 8 | (x1)) << 8 | (x2)) << 8 | (x3)) // X = (x0 || x1 || x2 || x3) +#define CONCAT_16x2(x0, x1) ((uint32)(x0) << 16 | (x1)) // X = (x0 || x1) +#define EXTRACT_8_32(X, i) (((X) >> (((i) ^ 3) << 3)) & 0xFF) // X = (x0 || x1 || x2 || x3) +#define EXTRACT_16_32(X, i) (((X) >> (((i) ^ 1) << 4)) & 0xFFFF) // X = (x0 || x1) +#define EXTRACT_16H_31(X) (((X) >> 15) & 0xFFFF) // Higher 16-bit from 31-bit +#define EXTRACT_16L_31(X) ((X) & 0xFFFF) // Lower 16-bit from 31-bit + +#define ROTATE(a, n) (((a) << (n)) | (((a) & 0xFFFFFFFF) >> ((32 - (n)) & 31))) +#define ROTATE_31(a, n) ((((a) << (n)) & 0x7FFFFFFF) | (((a) & 0x7FFFFFFF) >> (31 - (n)))) + +#define GET_BIT_VALUE_32(x, i) (((x) >> (31 - (i))) & 1) + +const uint32 PREFIX_MASK_32[32] = { + 0x00000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE +}; + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/ec.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/ec.h" new file mode 100644 index 0000000..56adbe7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Formal/enclave_ZUC/include/ec.h" @@ -0,0 +1,545 @@ +#include /* BigNum */ +#include "common_utils.h" + +typedef struct ec_point_st { + BIGNUM *X; + BIGNUM *Y; + int is_infinity; +} EC_POINT; + +int EC_POINT_init(EC_POINT *point) { + point->X = BN_new(); + point->Y = BN_new(); + point->is_infinity = 0; + if (point->X == NULL || point->Y == NULL) { + BN_free(point->X); + BN_free(point->Y); + return 0; + } + return 1; +} + +EC_POINT *EC_POINT_new() { + EC_POINT *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_POINT_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_POINT_setXY(EC_POINT *r, const BIGNUM *x, const BIGNUM *y) { + if (r == NULL) { + return 0; + } + if (!BN_copy(r->X, x) || !(BN_copy(r->Y, y))) { + return 0; + } + return 1; +} + +const EC_POINT *EC_point_infinity() { + static const EC_POINT const_infinity = { NULL, NULL, 1 }; + return &const_infinity; +} + +int EC_POINT_is_infinity(const EC_POINT *point) { + return point->is_infinity; +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest == NULL) { + return 0; + } + if (EC_POINT_is_infinity(src)) { + dest->is_infinity = 1; + } + else{ + dest->is_infinity = 0; + if (!BN_copy(dest->X, src->X) || !BN_copy(dest->Y, src->Y)) return 0; + } + return 1; +} + +#define NORMAL 0x1 +#define COMPRESS 0x2 +#define MIX 0x4 + +int EC_POINT_ecp2bin(uint8 *out, const EC_POINT *point, int p_bytes, int flag) { + uint8 PC; + uint8 *p = out, *buf; + int i; + buf = malloc(p_bytes); + if (EC_POINT_is_infinity(point)) { + return 0; + } + if (flag == NORMAL) { + PC = 0x04; + *(p++) = PC; + if (!BN_bn2binpad(point->X, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + if (!BN_bn2binpad(point->Y, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_bin2ecp(EC_POINT *point, const uint8 *src, int p_bytes) { + if (point == NULL) { + return 0; + } + uint8 PC = *src; + const uint8 *data = src + 1; + uint8 *buf; + int i; + if (PC == 0x04) { + if (!BN_bin2bn(data, p_bytes, point->X) + || !BN_bin2bn(data+p_bytes, p_bytes, point->Y)) { + return 0; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_ecp2bin_normal(uint8 *out, const EC_POINT *point, int p_bytes) { + return EC_POINT_ecp2bin(out, point, p_bytes, NORMAL); +} + +// int EC_POINT_ecp2bin_compressed(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, COMPRESS); +// } + +// int EC_POINT_ecp2bin_mix(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, MIX); +// } + +typedef struct ec_group_st { + EC_POINT *generator; /* point G */ + BIGNUM *order; /* n */ + BIGNUM *cofactor; /* h */ + BIGNUM *field; /* module p */ + BIGNUM *a, *b; /* ECC parameter */ +} EC_GROUP; + +int EC_GROUP_init(EC_GROUP *group) { + group->generator = EC_POINT_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->generator == NULL || group->b == NULL) { + free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +EC_GROUP *EC_GROUP_new() { + EC_GROUP *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_GROUP_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest == NULL) { + return 0; + } + if (dest == src) { + return 1; + } + if (!EC_POINT_copy(dest->generator, src->generator) + || !BN_copy(dest->order, src->order) + || !BN_copy(dest->cofactor, src->cofactor) + || !BN_copy(dest->field, src->field) + || !BN_copy(dest->a, src->a) + || !BN_copy(dest->b, src->b)) { + return 0; + } + return 1; +} + +int EC_GROUP_set_param(EC_GROUP *group, const BIGNUM *field, const BIGNUM *a, const BIGNUM *b, const BIGNUM *order, const BIGNUM *cofactor, const EC_POINT *point) { + if (group == NULL) { + return 0; + } + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->generator = EC_POINT_new(); + if (group->cofactor == NULL + || group->generator == NULL) { + return 0; + } + if (!BN_copy(group->field, field) + || !BN_copy(group->a, a) + || !BN_copy(group->b, b) + || !BN_copy(group->order, order) + || !BN_copy(group->cofactor, cofactor) + || !EC_POINT_copy(group->generator, point)) { + return 0; + } + return 1; +} + +int EC_POINT_double(EC_POINT *r, const EC_POINT *a, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, EC_point_infinity()); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y)) { + goto done; + } + if (!BN_set_word(bn_value_3, 3) + || !BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_sqr(r->X, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_lshift1_quick(tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, r->X, tmp, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_add(EC_POINT *r, const EC_POINT *a, const EC_POINT *b, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *bx, *by, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (a == b) { + return EC_POINT_double(r, a, group); + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_infinity(b)) { + return EC_POINT_copy(r, a); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + bx = BN_CTX_get(ctx); + by = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y) + || !BN_copy(bx, b->X) + || !BN_copy(by, b->Y)) { + goto done; + } + if (BN_cmp(ax, bx) == 0) { + if (!BN_mod_add_quick(tmp, ay, by, p)) { + goto done; + } + if (BN_is_zero(tmp) + || !EC_POINT_copy(r, EC_point_infinity())) { + goto done; + } + if (!BN_set_word(bn_value_3, 3)) { + goto done; + } + if (!BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + else { + if (!BN_mod_sub_quick(lnum, by, ay, p)) { + goto done; + } + if (!BN_mod_sub_quick(ldeno, bx, ax, p)) { + goto done; + } + if (!BN_mod_inverse(ldeno, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + if (!BN_mod_sqr(tmp, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(tmp, tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, tmp, bx, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_mul(EC_POINT *r, const EC_POINT *a, const BIGNUM *b, const EC_GROUP *group) { + if (r == NULL) { + return 0; + } + if (BN_is_negative(b)) { + EC_POINT *_a = EC_POINT_new(); + BIGNUM *_b = BN_new(); + if (!EC_POINT_copy(_a, a) + || !BN_copy(_b, b) + || !BN_mod_sub_quick(_a->Y, group->field, _a->Y, group->field)) { + return 0; + } + BN_set_negative(_b, 0); + return EC_POINT_mul(r, _a, _b, group); + } + if (!EC_POINT_copy(r, EC_point_infinity())){ + return 0; + } + int bits = BN_num_bits(b); + for (int i = bits-1; i >= 0; --i) { + if (!EC_POINT_double(r, r, group)) { + return 0; + } + if (BN_is_bit_set(b, i)) { + if (!EC_POINT_add(r, r, a, group)) { + return 0; + } + } + } + return 1; +} + +/* + * Only for curve y^2 = x^3 + ax + b. + * Please check infinity before calling. + */ +int EC_POINT_on_curve_simple(const EC_POINT *point, const EC_GROUP *group) { + if (point == NULL || group == NULL) { + return 0; + } + if (EC_POINT_is_infinity(point)) { + return 1; + } + int ret = 0; + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *lhs, *rhs; + EC_POINT *Nq; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return ret; + } + BN_CTX_start(ctx); + p = group->field; + a = group->a; + b = group->b; + x = point->X; + y = point->Y; + lhs = BN_CTX_get(ctx); + rhs = BN_CTX_get(ctx); + Nq = EC_POINT_new(); + if (p == NULL + || a == NULL + || b == NULL + || x == NULL + || y == NULL + || rhs == NULL + || Nq == NULL) { + return ret; + } + if (!BN_mod_mul(lhs, y, y, p, ctx) + || !BN_mod_mul(rhs, x, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, a, p) + || !BN_mod_mul(rhs, rhs, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, b, p) + || !EC_POINT_mul(Nq, point, group->order, group)) { + return ret; + } + if (BN_cmp(lhs, rhs) != 0 + || !EC_POINT_is_infinity(Nq)) { + return ret; + } + ret = 1; + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +typedef struct ec_key_st { + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; +} EC_KEY; + +int EC_KEY_init(EC_KEY *key) { + key->group = EC_GROUP_new(); + key->pub_key = EC_POINT_new(); + key->priv_key = BN_new(); + if (key->group == NULL + || key->pub_key == NULL + || key->priv_key == NULL) { + free(key->group); + free(key->pub_key); + BN_free(key->priv_key); + return 0; + } + return 1; +} + +EC_KEY *EC_KEY_new() { + EC_KEY *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_KEY_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + if (!EC_GROUP_copy(key->group, group)) { + return 0; + } + return 1; +} + +int EC_KEY_set_priv_key(EC_KEY *key, const BIGNUM *priv_key) { + BIGNUM *tmp; + tmp = BN_dup(priv_key); + if (tmp == NULL) { + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = tmp; + return 1; +} + +int EC_KEY_generate_pub_key(EC_KEY *key) { + return EC_POINT_mul(key->pub_key, key->group->generator, key->priv_key, key->group); +} + +const BIGNUM *EC_KEY_get_priv_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_generate_key() {} -- Gitee From e9d6b7e669405bacd912c3fc77901461216ed56a Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:56:07 +0000 Subject: [PATCH 15/18] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20Informal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Informal/.keep" | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/.keep" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/.keep" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/.keep" new file mode 100644 index 0000000..e69de29 -- Gitee From d510cb13aa9027b50887df068d59b483c1f6a927 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:56:36 +0000 Subject: [PATCH 16/18] enclave_SM2 Signed-off-by: wangxiaoxi1 --- .../Informal/enclave_SM2/CMakeLists.txt" | 38 ++ .../enclave_SM2/enclave/CMakeLists.txt" | 162 ++++++ .../enclave_SM2/enclave/Enclave.config.xml" | 12 + .../Informal/enclave_SM2/enclave/Enclave.lds" | 11 + .../enclave_SM2/enclave/enclave_SM2.c" | 117 ++++ .../enclave_SM2/enclave/manifest.txt.in" | 8 + .../enclave/rsa_public_key_cloud.pem" | 11 + .../Informal/enclave_SM2/enclave/sm2.h" | 207 +++++++ .../Informal/enclave_SM2/enclave/sm2_crypt.h" | 217 +++++++ .../enclave_SM2/enclave/sm2_exchange.h" | 349 +++++++++++ .../Informal/enclave_SM2/enclave/sm2_sign.h" | 196 +++++++ .../Informal/enclave_SM2/enclave/sm2_tests.h" | 152 +++++ .../Informal/enclave_SM2/enclave_SM2.edl" | 30 + .../Informal/enclave_SM2/host/CMakeLists.txt" | 88 +++ .../Informal/enclave_SM2/host/main.cpp" | 127 ++++ .../enclave_SM2/include/common_utils.h" | 69 +++ .../Informal/enclave_SM2/include/ec.h" | 545 ++++++++++++++++++ .../Informal/enclave_SM2/sm3/sm3.h" | 183 ++++++ 18 files changed, 2522 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.config.xml" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.lds" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/enclave_SM2.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/manifest.txt.in" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/rsa_public_key_cloud.pem" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_crypt.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_exchange.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_sign.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_tests.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave_SM2.edl" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/main.cpp" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/include/common_utils.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/include/ec.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/sm3/sm3.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/CMakeLists.txt" new file mode 100644 index 0000000..bfc5416 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/CMakeLists.txt" @@ -0,0 +1,38 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +project(enclave_SM2) + +set(CMAKE_C_STANDARD 99) + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE enclave_SM2.edl) +#set(LOCAL_ROOT_PATH "$ENV{CC_SDK}") +#set(SECGEAR_INSTALL_PATH /usr/lib64/) + +if(CC_GP) + set(CODETYPE trustzone) + set(CODEGEN codegen_arm64) + execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) + string(REPLACE "\n" "" UUID ${UUID}) + add_definitions(-DPATH="/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + set(CODEGEN codegen_x86_64) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/CMakeLists.txt" new file mode 100644 index 0000000..7d04cf0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/CMakeLists.txt" @@ -0,0 +1,162 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM2) + +set(CMAKE_C_STANDARD 99) +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave_SM2.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + #set itrustee device key + set(DEVICEPEM ${CMAKE_CURRENT_SOURCE_DIR}/rsa_public_key_cloud.pem) + #set whilelist. default: /vendor/bin/teec_hello + set(WHITE_LIST_0 /vendor/bin/enclave_SM2) + set(WHITE_LIST_OWNER root) + set(WHITE_LIST_1 /vendor/bin/secgear_enclave_SM2) + set(WHITELIST WHITE_LIST_0 WHITE_LIST_1) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(COMMON_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \ + -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") +set(COMMON_CXX_FLAGS "${COMMON_C_FLAGS}") + +if(CC_GP) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt") + + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/enclave_inc + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${SECGEAR_INSTALL_PATH}) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -lsecgear_tee) + + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i /home/sunny/secGear/debug/lib/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT} + DESTINATION /data + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -O2 -nostdinc++") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE + ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.config.xml" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.config.xml" new file mode 100644 index 0000000..a5e05e0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.config.xml" @@ -0,0 +1,12 @@ + + 0 + 0 + 0x100000 + 0x80000 + 10 + 1 + + 1 + 0 + 0xFFFFFFFF + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.lds" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.lds" new file mode 100644 index 0000000..ab77e64 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/Enclave.lds" @@ -0,0 +1,11 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/enclave_SM2.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/enclave_SM2.c" new file mode 100644 index 0000000..6685bb0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/enclave_SM2.c" @@ -0,0 +1,117 @@ +#include "Enclave1_t.h" +#define GBT32918_5_2017_TEST +#define SM2_EXCHANGE_OPTIONAL +#include "sm2.h" +#include "sm2_tests.h" + +/* + * Ref: + * GB/T 32918.5-2017 + */ + +const int SM2_p_bytes = 256 >> 3; +uint8 *sign_ID_A; +uint8 *sign_M; +uint8 sign_dA[SM2_p_bytes]; +uint8 sign_k[SM2_p_bytes]; + +void setSignIDA(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(sign_ID_A, src, len + 1); + } +} + +void setSignM(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(sign_M, src, len + 1); + } +} + +void setSignDA(uint8 *src) { + memcpy(sign_dA, src, SM2_p_bytes); +} + +void setSignK(uint8 *src) { + memcpy(sign_k, src, SM2_p_bytes); +} + +void getSignResult(uint8 *buf, size_t len) { + if (len > strlen(sign_buffer)) { + memcpy(buf, sign_buffer, strlen(sign_buffer) + 1); + } +} + +void getSignVerifyResult(uint8 buf) { + memcpy(buf, &sign_verify_ret, 1); +} + +void callsm2signtest() { + sm2signtest(SM2_p_bytes, sign_M, sign_ID_A, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, sign_dA, sign_k); +} + +uint8 *exchange_ID_A; +uint8 *exchange_ID_B; +uint8 exchange_dA[SM2_p_bytes]; +uint8 exchange_dB[SM2_p_bytes]; +uint64 exchange_klen = 128; + +void setExchangeIDA(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(exchange_ID_A, src, len + 1); + } +} + +void setExchangeIDB(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(exchange_ID_B, src, len + 1); + } +} + +void setExchangeDA(uint8 *src) { + memcpy(exchange_dA, src, SM2_p_bytes); +} + +void setExchangeDB(uint8 *src) { + memcpy(exchange_dB, src, SM2_p_bytes); +} + +void setExchangeKLen(uint64 *src) { + memcpy(exchange_klen, src, sizeof(uint64)); +} + +void getExchangeResult(uint8 buf) { + memcpy(buf, &exchange_ret, 1); +} + +void callsm2exchangetest() { + sm2exchangetest(SM2_p_bytes, exchange_ID_A, exchange_ID_B, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, exchange_dA, exchange_dB, exchange_klen); +} + +uint8 *crypt_M; +uint8 crypt_dB[SM2_p_bytes]; + +void setCryptM(uint8 *src, size_t len) { + if (len < MAX_LEN) { + memcpy(crypt_M, src, len + 1); + } +} + +void setCryptDB(uint8 *src) { + memcpy(crypt_dB, src, SM2_p_bytes); +} + +void getCryptPW(uint8 *buf, size_t len) { + if (len > strlen(encrypt_pw)) { + memcpy(buf, encrypt_pw, strlen(encrypt_pw) + 1); + } +} + +void getCryptMSG(uint8 *buf, size_t len) { + if (len > strlen(decrypt_msg)) { + memcpy(buf, decrypt_msg, strlen(decrypt_msg) + 1); + } +} + +void callsm2crypttest() { + sm2crypttest(SM2_p_bytes, crypt_M, SM2_P, SM2_A, SM2_B, SM2_N, SM2_XG, SM2_YG, crypt_dB); +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/manifest.txt.in" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/manifest.txt.in" new file mode 100644 index 0000000..7b8ecf5 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/manifest.txt.in" @@ -0,0 +1,8 @@ +gpd.ta.appID: @UUID@ +gpd.ta.service_name: test0108 +gpd.ta.singleInstance: true +gpd.ta.multiSession: false +gpd.ta.multiCommand: false +gpd.ta.instanceKeepAlive: false +gpd.ta.dataSize: 16384 +gpd.ta.stackSize: 20480 diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/rsa_public_key_cloud.pem" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/rsa_public_key_cloud.pem" new file mode 100644 index 0000000..a321f63 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/rsa_public_key_cloud.pem" @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzAPwbnbgBg7JgXERA9Bx +p7GLI1S3e1zL83RMd2+GXb6kO4yMKUL3NUCE2HhA2BtQYmLyGovx59UUcKnU58is +Xux++kH+A2shmOPjYvEFuX0Kt8tc19b8M9b/iHsY8ZmKykqia2a5U+IrECRFJo5p +DWUnl7jrHVtq78BSR1c7iXG1frrEC0AYCuqKJo/fxfmOKL0Y9mENCB3nAwjn9unD +BsO/OhkqvvB3nkeuMfNKPh4wCqtQPve13eTojbuxjX/3ePijplTI5X2Gr+n6Ximn +fYRlytQmMgMl/db0ARSKNApq9bmwzVNrnGWWZWJksdRvf6iL7t17Gs4L9AApOuC9 +WkzxPvwp5ZUqjsGd4oJGWeC6ZE6BTw2vxE+xMFI9uAKHxq9pBKkcGMa0g4fANNNV ++W+8JZGanxEXKB3y/M7BCyQAPCWOHC/RNjmRA1gczLYCPzC4pWu935UZdF1RR6zY +CD3t+FoOGGET/g4CwWgyhb5qkp65Hs6ayYt/DUAqo+yBAgMBAAE= +-----END PUBLIC KEY----- diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2.h" new file mode 100644 index 0000000..27bf249 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2.h" @@ -0,0 +1,207 @@ +#ifndef SECGEAR_SM2_H +#define SECGEAR_SM2_H + +/* + * Ref: + * GB/T 32918.1-2016 + * GB/T 32918.2-2016 + * GB/T 32918.3-2016 + * GB/T 32918.4-2016 + * GB/T 32918.5-2017 + */ + +#include +#include "../include/common_utils.h" +#include "../include/ec.h" +#include "../sm3/sm3.h" +#define SM2ERR(msg) goto err; +/* + * export C_INCLUDE_PATH="/PATH/TO/OPENSSL/include"(/opt/homebrew/Cellar/openssl@1.1/1.1.1m/include) + * export CPLUS_INCLUDE_PATH="/PATH/TO/OPENSSL/include" + * export LIBRARY_PATH="/PATH/TO/OPENSSL/lib" + */ + +/* Parameters */ +/* EC: y^2 = x^3 + ax + b */ + +#define SM2_PARAM_CBLOCK 32 +#define SM2_PARAM_LBLOCK (SM2_PARAM_CBLOCK/4) + +const uint8 SM2_P[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; +const uint8 SM2_A[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, +}; +const uint8 SM2_B[SM2_PARAM_CBLOCK] = { + 0x28, 0xE9, 0xFA, 0x9E, + 0x9D, 0x9F, 0x5E, 0x34, + 0x4D, 0x5A, 0x9E, 0x4B, + 0xCF, 0x65, 0x09, 0xA7, + 0xF3, 0x97, 0x89, 0xF5, + 0x15, 0xAB, 0x8F, 0x92, + 0xDD, 0xBC, 0xBD, 0x41, + 0x4D, 0x94, 0x0E, 0x93, +}; +const uint8 SM2_N[SM2_PARAM_CBLOCK] = { + 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x72, 0x03, 0xDF, 0x6B, + 0x21, 0xC6, 0x05, 0x2B, + 0x53, 0xBB, 0xF4, 0x09, + 0x39, 0xD5, 0x41, 0x23, +}; +const uint8 SM2_XG[SM2_PARAM_CBLOCK] = { + 0x32, 0xC4, 0xAE, 0x2C, + 0x1F, 0x19, 0x81, 0x19, + 0x5F, 0x99, 0x04, 0x46, + 0x6A, 0x39, 0xC9, 0x94, + 0x8F, 0xE3, 0x0B, 0xBF, + 0xF2, 0x66, 0x0B, 0xE1, + 0x71, 0x5A, 0x45, 0x89, + 0x33, 0x4C, 0x74, 0xC7, +}; +const uint8 SM2_YG[SM2_PARAM_CBLOCK] = { + 0xBC, 0x37, 0x36, 0xA2, + 0xF4, 0xF6, 0x77, 0x9C, + 0x59, 0xBD, 0xCE, 0xE3, + 0x6B, 0x69, 0x21, 0x53, + 0xD0, 0xA9, 0x87, 0x7C, + 0xC6, 0x2A, 0x47, 0x40, + 0x02, 0xDF, 0x32, 0xE5, + 0x21, 0x39, 0xF0, 0xA0, +}; + +typedef struct sm2_sig_st { + BIGNUM *r; + BIGNUM *s; +} SM2_SIG; + +int SM2_SIG_init(SM2_SIG *sig) { + sig->r = BN_new(); + sig->s = BN_new(); + if (sig->r == NULL || sig->s == NULL) { + BN_free(sig->r); + BN_free(sig->s); + return 0; + } + return 1; +} + +SM2_SIG *SM2_SIG_new() { + SM2_SIG *ret; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!SM2_SIG_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int sm2_compute_z(uint8 *out, const uint8 *id, const size_t idlen, const EC_KEY *key){ + /* ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */ + uint16 entlen = idlen << 3; + uint8 e_bytes, *buf; + int p_bytes; + SM3_CTX c; + sm3_init(&c); + if (idlen > (UINT16_MAX >> 3)) { + SM2ERR("SM2_compute_z(): idlen too large!\n"); + } + e_bytes = entlen >> 8; + sm3_update(&c, &e_bytes, 1); + e_bytes = entlen & 0xFF; + sm3_update(&c, &e_bytes, 1); + if (!sm3_update(&c, id, idlen)) { + goto err; + } + p_bytes = BN_num_bytes(key->group->field); + buf = malloc(p_bytes); + if (!BN_bn2binpad(key->group->a, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(key->group->b, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(key->group->generator->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(key->group->generator->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || BN_bn2binpad(key->pub_key->X, buf, p_bytes) < 0 + || !sm3_update(&c, buf, p_bytes) + || BN_bn2binpad(key->pub_key->Y, buf, p_bytes) < 0 + || !sm3_update(&c, buf, p_bytes)) { + goto err; + } + sm3_final(out, &c); + return 1; + err: + return 0; +} + +int sm2_KDF(uint8 *K, const uint8 *Z, const size_t Zlen, const uint64 klen) { + const uint64 v = 256; /* SM3: 256bit digest */ + if (v*0xFFFFFFFFU <= klen) { + return 0; + } + if (klen & 7) { + return 0; + } + uint32 ct = 1, lmt = (klen+v-1)/v, tmp; + uint8 *_ct, *tmp_u8, *digest, *p = K; + _ct = malloc(4UL); + digest = malloc(SM3_DIGEST_LENGTH); + SM3_CTX c; + while (ct < lmt) { + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c) + || !memcpy(p, digest, SM3_DIGEST_LENGTH)) { + return 0; + } + ++ct; + p += SM3_DIGEST_LENGTH; + } + tmp_u8 = _ct; + HOST_l2c(ct, tmp_u8); + if (!sm3_init(&c) + || !sm3_update(&c, Z, Zlen) + || !sm3_update(&c, _ct, 4UL) + || !sm3_final(digest, &c)) { + return 0; + } + tmp = klen % v; + if (!tmp) { + if (!memcpy(p, digest, SM3_DIGEST_LENGTH)) { + return 0; + } + } + else { + if (!memcpy(p, digest, tmp >> 3)) { + return 0; + } + } + return 1; +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_crypt.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_crypt.h" new file mode 100644 index 0000000..c9dc136 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_crypt.h" @@ -0,0 +1,217 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.4-2016 + */ + +/* Encrypt */ + +int sm2_encrypt(uint8 *out, const uint8 *M, const uint64 klen, const EC_KEY *key) { + SM3_CTX c; + BIGNUM *n, *k, *h, *x_2, *y_2; + EC_POINT *G, *C1, *S, *PB, *tmp_point; + EC_GROUP *group; + uint8 *_C1, *_C2, *_C3, *t, *buf; + size_t C1len, MlenCBLOCK, buflen, i; + int p_bytes; + group = key->group; + n = group->order; + h = group->cofactor; + G = group->generator; + PB = key->pub_key; + x_2 = BN_new(); + y_2 = BN_new(); + k = BN_new(); + C1 = EC_POINT_new(); + tmp_point = EC_POINT_new(); + S = EC_POINT_new(); + if (group == NULL + || n == NULL + || h == NULL + || k == NULL + || G == NULL + || S == NULL + || PB == NULL) { + return 0; + } + p_bytes = BN_num_bytes(group->field); + MlenCBLOCK = klen >> 3; + C1len = (p_bytes << 1 | 1); + buflen = p_bytes << 1; + _C1 = malloc(C1len); + _C2 = malloc(MlenCBLOCK); + _C3 = malloc(SM3_DIGEST_LENGTH); + buf = malloc(buflen); + t = malloc(MlenCBLOCK); + if (t == NULL) { + goto err; + } + for (;;) { + /* A1: k = rand(1, n-1) */ + do { + if (!BN_rand_range(k, n)) { + goto err; + } + } while(BN_is_zero(k)); + #ifdef GBT32918_4_2016_A2_TEST /* For GB/T 32918.4-2016 A.2 test */ + if (p_bytes * 8 == 192) { + /* FP-192 */ + BN_hex2bn(&k, "384F30353073AEECE7A1654330A96204D37982A3E15B2CB5"); + } + else { + /* FP-256 */ + BN_hex2bn(&k, "4C62EEFD6ECFC2B95B92FD6C3D9575148AFA17425546D49018E5388D49DD7B4F"); + } + #endif + #ifdef GBT32918_5_2017_TEST + BN_hex2bn(&k, "59276E27D506861A16680F3AD9C02DCCEF3CC1FA3CDBE4CE6D54B80DEAC1BC21"); + #endif + /* A2: C1 = [k]G = (x1, y1), C1 -> bytes */ + if (!EC_POINT_mul(C1, G, k, group) + || !EC_POINT_ecp2bin_normal(_C1, C1, p_bytes)) { + goto err; + } + /* A3: S = [h]PB, if s = O, goto err */ + if (!EC_POINT_mul(S, PB, h, group) + || EC_POINT_is_infinity(S)) { + goto err; + } + /* A4: [k]PB = (x2, y2), x2, y2 -> bytes */ + if (!EC_POINT_mul(tmp_point, PB, k, group)) { + goto err; + } + x_2 = tmp_point->X; + y_2 = tmp_point->Y; + /* A5: t = KDF(x2 || y2, klen), if t == 0, goto A1 */ + if (!BN_bn2binpad(x_2, buf, p_bytes) + || !BN_bn2binpad(y_2, buf+p_bytes, p_bytes) + || !sm2_KDF(t, buf, buflen, klen)) { + goto err; + } + for (i = 0; i < MlenCBLOCK; ++i) { + if (t[i]) { + goto A6; + } + } + } + /* A6: C2 = M ^ t */ + A6: + for (i = 0; i < MlenCBLOCK; ++i) { + _C2[i] = M[i] ^ t[i]; + } + /* A7: C3 = SM3(x2 || M || y2) */ + if (!sm3_init(&c) + || !BN_bn2binpad(x_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, M, MlenCBLOCK) + || !BN_bn2binpad(y_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(_C3, &c)) { + goto err; + } + /* A8: C = C1 || C3 || C2 */ + if (!memcpy(out, _C1, C1len) + || !memcpy(out+C1len, _C3, SM3_DIGEST_LENGTH) + || !memcpy(out+C1len+SM3_DIGEST_LENGTH, _C2, MlenCBLOCK)) { + goto err; + } + return 1; + err: + return 0; +} + +/* Decrypt */ + +int sm2_decrypt(uint8 *_M, const uint8 *C, const uint64 klen, const EC_KEY *key) { + SM3_CTX c; + BIGNUM *dB, *h, *x_2, *y_2; + EC_POINT *C1, *S, *tmp_point; + EC_GROUP *group; + uint8 *_C1, *_C2, *_C3, *t, *buf, *u; + size_t C1len, MlenCBLOCK, buflen, i; + int p_bytes; + group = key->group; + h = group->cofactor; + dB = key->priv_key; + x_2 = BN_new(); + y_2 = BN_new(); + C1 = EC_POINT_new(); + tmp_point = EC_POINT_new(); + S = EC_POINT_new(); + if (group == NULL + || h == NULL + || x_2 == NULL + || y_2 == NULL + || dB == NULL + || S == NULL) { + return 0; + } + p_bytes = BN_num_bytes(group->field); + MlenCBLOCK = klen >> 3; + C1len = (p_bytes << 1 | 1); + buflen = p_bytes << 1; + _C1 = malloc(C1len); + _C2 = malloc(MlenCBLOCK); + _C3 = malloc(SM3_DIGEST_LENGTH); + u = malloc(SM3_DIGEST_LENGTH); + buf = malloc(buflen); + t = malloc(MlenCBLOCK); + if (t == NULL) { + goto err; + } + /* C = C1 || C3 || C2 */ + if (!memcpy(_C1, C, C1len) + || !memcpy(_C2, C+C1len+SM3_DIGEST_LENGTH, MlenCBLOCK) + || !memcpy(_C3, C+C1len, SM3_DIGEST_LENGTH)) { + goto err; + } + /* B1: C -> C1, check if C1 on the curve */ + if (!EC_POINT_bin2ecp(C1, _C1, p_bytes) + || !EC_POINT_on_curve_simple(C1, group)) { + goto err; + } + /* B2: S = [h]C1, if S == O, goto err */ + if (!EC_POINT_mul(S, C1, h, group) + || EC_POINT_is_infinity(S)) { + goto err; + } + /* B3: [dB]C1 = (x2, y2), x2, y2 -> bytes */ + if (!EC_POINT_mul(tmp_point, C1, dB, group)) { + goto err; + } + x_2 = tmp_point->X; + y_2 = tmp_point->Y; + /* B4: t = KDF(x2 || y2, klen), if t = 0, goto err */ + if (!BN_bn2binpad(x_2, buf, p_bytes) + || !BN_bn2binpad(y_2, buf+p_bytes, p_bytes) + || !sm2_KDF(t, buf, buflen, klen)) { + goto err; + } + for (i = 0; i < MlenCBLOCK; ++i) { + if (t[i]) { + goto B5; + } + } + goto err; + B5: + /* B5: C -> C2, M' = C2 ^ t*/ + for (i = 0; i < MlenCBLOCK; ++i) { + _M[i] = _C2[i] ^ t[i]; + } + /* B6: u = SM3(x2 || M' || y2), check if u = C3 */ + if (!sm3_init(&c) + || !BN_bn2binpad(x_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, _M, MlenCBLOCK) + || !BN_bn2binpad(y_2, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(u, &c) + || memcmp(u, _C3, SM3_DIGEST_LENGTH) != 0) { + goto err; + } + /* B7: output M' */ + return 1; + err: + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_exchange.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_exchange.h" new file mode 100644 index 0000000..bde0756 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_exchange.h" @@ -0,0 +1,349 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.3-2016 + */ + +/* + * This function should **NOT** be used directly. + * The exchange process should obey the definition in GB/T 32918.3-2016 + */ +int sm2_exchange(const EC_KEY *userA, const EC_KEY *userB, const uint64 klen, const uint8 *ZA, const uint8 *ZB) { + int w = (BN_num_bits(userA->group->order) + 1) / 2 - 1; /* For n is not pow of 2 */ + size_t p_bytes = BN_num_bytes(userB->group->field), k_bytes = (klen >> 3) + ((klen & 7) ? 1 : 0), Zlen; + uint8 const_byte; + SM3_CTX c; + BN_CTX *ctx; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + /* A-pre: */ + BIGNUM *rA, *x_1, *y_1, *tmpa, *tA; + const BIGNUM *nA, *dA, *hA; + EC_POINT *RA, *U, *tmp_pointA; + const EC_POINT *GA, *PA; + EC_GROUP *groupA; + uint8 *Z, *K, *buf, *tmp_char, *SA, *S1, *SB, *S2, *buf_digest; + SA = malloc(SM3_DIGEST_LENGTH); + S1 = malloc(SM3_DIGEST_LENGTH); + SB = malloc(SM3_DIGEST_LENGTH); + S2 = malloc(SM3_DIGEST_LENGTH); + buf_digest = malloc(SM3_DIGEST_LENGTH); + if (buf_digest == NULL) { + return 0; + } + groupA = userA->group; + nA = groupA->order; + dA = userA->priv_key; + hA = groupA->cofactor; + x_1 = BN_CTX_get(ctx); + y_1 = BN_CTX_get(ctx); + tmpa = BN_CTX_get(ctx); + tA = BN_CTX_get(ctx); + rA = BN_CTX_get(ctx); + GA = groupA->generator; + PA = userA->pub_key; + U = EC_POINT_new(); + tmp_pointA = EC_POINT_new(); + RA = EC_POINT_new(); + if (groupA == NULL + || nA == NULL + || dA == NULL + || hA == NULL + || rA == NULL + || GA == NULL + || PA == NULL + || RA == NULL) { + return 0; + } + /* A1: rA = rand(1, n-1) */ + do { + if (!BN_rand_range(rA, nA)) { + return 0; + } + } while(BN_is_zero(rA)); + #ifdef GBT32918_3_2016_A2_TEST + /* For GB/T 32918.3-2016 A.2 test */ + BN_hex2bn(&rA, "83A2C9C8B96E5AF70BD480B472409A9A327257F1EBB73F5B073354B248668563"); + #endif + #ifdef GBT32918_5_2017_TEST + BN_hex2bn(&rA, "D4DE15474DB74D06491C440D305E012400990F3E390C7E87153C12DB2EA60BB3"); + #endif + /* A2: RA = [rA]G = (x1, y1) */ + if (!EC_POINT_mul(RA, GA, rA, groupA)) { + return 0; + } + /* A3: send RA to userB */ + /* B-pre: */ + BIGNUM *rB, *x_2, *y_2, *tmpb, *tB; + const BIGNUM *nB, *dB, *hB; + EC_POINT *RB, *V, *tmp_pointB; + const EC_POINT *GB, *PB; + EC_GROUP *groupB; + groupB = userB->group; + nB = groupB->order; + dB = userB->priv_key; + hB = groupB->cofactor; + x_2 = BN_CTX_get(ctx); + y_2 = BN_CTX_get(ctx); + tmpb = BN_CTX_get(ctx); + tB = BN_CTX_get(ctx); + rB = BN_CTX_get(ctx); + GB = groupB->generator; + PB = userB->pub_key; + V = EC_POINT_new(); + tmp_pointB = EC_POINT_new(); + RB = EC_POINT_new(); + if (groupB == NULL + || nB == NULL + || dB == NULL + || hB == NULL + || rB == NULL + || GB == NULL + || PB == NULL + || RB == NULL) { + return 0; + } + /* B1: rB = rand(1, n-1) */ + do { + if (!BN_rand_range(rB, nB)) { + return 0; + } + } while(BN_is_zero(rB)); + #ifdef GBT32918_3_2016_A2_TEST + /* For GB/T 32918.3-2016 A.2 test */ + BN_hex2bn(&rB, "33FE21940342161C55619C4A0C060293D543C80AF19748CE176D83477DE71C80"); + #endif + #ifdef GBT32918_5_2017_TEST + BN_hex2bn(&rB, "7E07124814B309489125EAED101113164EBF0F3458C5BD88335C1F9D596243D6"); + #endif + /* B2: RB = [rB]G = (x2, y2) */ + if (!EC_POINT_mul(RB, GB, rB, groupB)) { + return 0; + } + /* B3: \bar{x_2} = 2^w + (x_2 & (2^w - 1)) */ + if (!BN_one(tmpb) + || !BN_lshift(tmpb, tmpb, w) + || !BN_mod(x_2, RB->X, tmpb, ctx) + || !BN_add(x_2, x_2, tmpb)) { + return 0; + } + /* B4: tB = (dB + \bar{x_2} \times rB) % n */ + if (!BN_mod_mul(tB, x_2, rB, nB, ctx) + || !BN_mod_add_quick(tB, tB, dB, nB)) { + return 0; + } + /* B5: verify RA is on curve, \bar{x_1} = 2^w + (x_1 & (2^w - 1)) */ + if (!EC_POINT_on_curve_simple(RA, groupB)) { + return 0; + } + if (!BN_one(tmpb) + || !BN_lshift(tmpb, tmpb, w) + || !BN_mod(x_1, RA->X, tmpb, ctx) + || !BN_add(x_1, x_1, tmpb)) { + return 0; + } + /* B6: V = [h \times tB](PA + [\bar{x1}]RA) = (xV, yV) */ + if (!EC_POINT_mul(tmp_pointB, RA, x_1, groupB) + || !EC_POINT_add(tmp_pointB, tmp_pointB, PA, groupB) + || !BN_mul(tmpb, hB, tB, ctx) + || !EC_POINT_mul(V, tmp_pointB, tmpb, groupB) + || EC_POINT_is_infinity(V)) { + return 0; + } + /* B7: KB = KDF(xV || yV || ZA || ZB, klen) */ + K = malloc((klen + 7) >> 3); + Zlen = (p_bytes + SM3_DIGEST_LENGTH) * 2; + Z = malloc(Zlen); + buf = malloc(p_bytes); + tmp_char = Z; + if (!BN_bn2binpad(V->X, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZA, SM3_DIGEST_LENGTH) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZB, SM3_DIGEST_LENGTH)) { + return 0; + } + if (!sm2_KDF(K, Z, Zlen, klen)) { + return 0; + } + #ifdef SM2_EXCHANGE_OPTIONAL + /* B8: SB = SM3(0x02 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)) (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(V->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 2; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(SB, &c)) { + return 0; + } + #endif + /* B9: Send RB, (and SB, optionals) to userA */ + /* A4: \bar{x_1} = 2^w + (x_1 & (2^w - 1)) */ + if (!BN_one(tmpa) + || !BN_lshift(tmpa, tmpa, w) + || !BN_mod(x_1, RA->X, tmpa, ctx) + || !BN_add(x_1, x_1, tmpa)) { + return 0; + } + /* A5: tA = (dA + \bar{x_1} \times rA) % n */ + if (!BN_mod_mul(tA, x_1, rA, nA, ctx) + || !BN_mod_add_quick(tA, tA, dA, nA)) { + return 0; + } + /* A6: verify RB is on curve, \bar{x_2} = 2^w + (x_2 & (2^w - 1)) */ + if (!EC_POINT_on_curve_simple(RB, groupA)) { + return 0; + } + if (!BN_one(tmpa) + || !BN_lshift(tmpa, tmpa, w) + || !BN_mod(x_2, RB->X, tmpa, ctx) + || !BN_add(x_2, x_2, tmpa)) { + return 0; + } + /* A7: U = [h \times tA](PB + [\bar{x2}]RB) = (xU, yU) */ + if (!EC_POINT_mul(tmp_pointA, RB, x_2, groupA) + || !EC_POINT_add(tmp_pointA, tmp_pointA, PB, groupA) + || !BN_mul(tmpa, hA, tA, ctx) + || !EC_POINT_mul(U, tmp_pointA, tmpa, groupA) + || EC_POINT_is_infinity(U)) { + return 0; + } + /* A8: KA = KDF(xU || yU || ZA || ZB, klen) */ + K = malloc((klen + 7) >> 3); + Zlen = (p_bytes + SM3_DIGEST_LENGTH) * 2; + Z = malloc(Zlen); + buf = malloc(p_bytes); + tmp_char = Z; + if (!BN_bn2binpad(U->X, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !BN_bn2binpad(U->Y, buf, p_bytes) + || !memcpy(tmp_char, buf, p_bytes) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZA, SM3_DIGEST_LENGTH) + || !(tmp_char += p_bytes) + || !memcpy(tmp_char, ZB, SM3_DIGEST_LENGTH)) { + return 0; + } + if (!sm2_KDF(K, Z, Zlen, klen)) { + return 0; + } + #ifdef SM2_EXCHANGE_OPTIONAL + /* A9: S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)), verify S1==SB (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(U->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 2; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(S1, &c)) { + return 0; + } + if (memcmp(S1, SB, SM3_DIGEST_LENGTH) != 0) { + return 0; + } + #endif + #ifdef SM2_EXCHANGE_OPTIONAL + /* A10: SA = SM3(0x03 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)) (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(U->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 3; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(U->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(SA, &c)) { + return 0; + } + #endif + #ifdef SM2_EXCHANGE_OPTIONAL + /* B10: S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)), verify S2==SA (optional) */ + if (!sm3_init(&c) + || !BN_bn2binpad(V->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, ZA, SM3_DIGEST_LENGTH) + || !sm3_update(&c, ZB, SM3_DIGEST_LENGTH) + || !BN_bn2binpad(RA->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RA->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->X, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !BN_bn2binpad(RB->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_final(buf_digest, &c)) { + return 0; + } + const_byte = 3; + if (!sm3_init(&c) + || !(sm3_update(&c, &const_byte, 1), 1) + || !BN_bn2binpad(V->Y, buf, p_bytes) + || !sm3_update(&c, buf, p_bytes) + || !sm3_update(&c, buf_digest, SM3_DIGEST_LENGTH) + || !sm3_final(S2, &c)) { + return 0; + } + if (memcmp(S2, SA, SM3_DIGEST_LENGTH) != 0) { + return 0; + } + #endif + return 1; + fail: + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_sign.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_sign.h" new file mode 100644 index 0000000..38baf47 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_sign.h" @@ -0,0 +1,196 @@ +#include "sm2.h" + +/* + * Ref: + * GB/T 32918.2-2016 + */ + +/** SM2 signature generation. + * \param msg massage for signing. + * \param msglen byte length of msg. + * \param id identifier of user A. + * \param idlen byte length of id. + * \param key key of user A. + * \return the sign generated. + */ +SM2_SIG *sm2_sig_gen(const uint8 *msg, const size_t msglen, const uint8 *id, const size_t idlen, const EC_KEY *key) { + SM3_CTX c; + sm3_init(&c); + uint8 *buf; + BN_CTX *ctx; + BIGNUM *e, *n, *k, *x, *r, *s, *rk, *dA, *tmp; + EC_POINT *kG, *G; + SM2_SIG *sig; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + sig = SM2_SIG_new(); + if (sig == NULL) { + return 0; + } + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + n = key->group->order; + k = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + r = sig->r; + s = sig->s; + rk = BN_CTX_get(ctx); + dA = key->priv_key; + tmp = BN_CTX_get(ctx); + G = key->group->generator; + kG = EC_POINT_new(); + if (n == NULL + || r == NULL + || s == NULL + || dA == NULL + || tmp == NULL + || G == NULL + || kG == NULL) { + return 0; + } + buf = malloc(SM3_DIGEST_LENGTH); + /* A1: \bar{M} = ZA || M */ + if (!sm2_compute_z(buf, id, idlen, key)) { + goto err; + } + if (!sm3_update(&c, buf, SM3_DIGEST_LENGTH) + || !sm3_update(&c, msg, msglen)) { + SM2ERR("sm2_sign(): compute e error!\n"); + } + /* A2: e = SM3(\bar{M}), e -> bn */ + sm3_final(buf, &c); + e = BN_bin2bn(buf, SM3_DIGEST_LENGTH, NULL); + if (e == NULL) { + SM2ERR("sm2_sign(): e error!\n"); + } + for (;;) { + /* A3: k = rand(1, n-1) */ + if (!BN_rand_range(k, n)) { + SM2ERR("sm2_sign(): gen k error!\n"); + } + #ifdef GBT32918_2_2016_A2_TEST + /* For GB/T 32918.2-2016 A.2 test */ + BN_hex2bn(&k, "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F"); + #endif + #ifdef GBT32918_5_2017_TEST + BN_hex2bn(&k, "59276E27D506861A16680F3AD9C02DCCEF3CC1FA3CDBE4CE6D54B80DEAC1BC21"); + #endif + if (BN_is_zero(k)) continue; + /* A4: (x1, y1) = [k]G, x1 -> bn */ + if (!EC_POINT_mul(kG, G, k, key->group)) { + return 0; + } + x = kG->X; + /* A5: r = (e + x1) % n, if r=0 or r+k=n, goto A3 */ + if (!BN_mod_add(r, e, x, n, ctx)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + if (BN_is_zero(r)) continue; + if (!BN_add(rk, r, k)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + if (BN_cmp(rk, n) == 0) continue; + /* A6: s = ((1+dA)^-1 \times (k- r \times dA)) % n, if s=0, goto A3 */ + if (!BN_add(s, dA, BN_value_one()) + || !BN_mod_inverse(s, s, n, ctx) + || !printf("(1+dA)^-1: %s\n", BN_bn2hex(s)) + || !BN_mod_mul(tmp, dA, r, n, ctx) + || !BN_sub(tmp, k, tmp) + || !BN_mod_mul(s, s, tmp, n, ctx)) { + SM2ERR("sm2_sign(): internal error!\n"); + } + if (BN_is_zero(s)) continue; + /* A7: r,s -> byte/u8[], sig = (r, s) */ + break; + } + err: + done: + BN_free(e); + BN_CTX_free(ctx); + return sig; +} + +/* (2) Sign Verify */ + +/** SM2 signature verification. + * \param msg massage for signing. + * \param msglen byte length of msg. + * \param id identifier of user A. + * \param idlen byte length of id. + * \param key key of user A. + * \param sig signature to be verified. + * \return 1 on success and 0 if an error occurred. + */ +int sm2_sig_verify(const uint8 *msg, const size_t msglen, const uint8 *id, const size_t idlen, const EC_KEY *key, const SM2_SIG *sig) { + SM3_CTX c; + sm3_init(&c); + BN_CTX *ctx; + const BIGNUM *r, *s, *n; + BIGNUM *e, *t, *R; + const EC_POINT *G, *PA; + EC_POINT *sG, *tPA, *tmp_point; + uint8 *buf; + r = sig->r; + s = sig->s; + n = key->group->order; + G = key->group->generator; + PA = key->pub_key; + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + R = BN_CTX_get(ctx); + sG = EC_POINT_new(); + tPA = EC_POINT_new(); + tmp_point = EC_POINT_new(); + if (R == NULL || tmp_point == NULL) { + goto err; + } + buf = malloc(SM3_DIGEST_LENGTH); + /* B1: check r' \in [1, n-1], otherwise goto BERR */ + /* B2: check s' \in [1, n-1], otherwise goto BERR */ + if (BN_cmp(r, BN_value_one()) < 0 + || BN_cmp(s, BN_value_one()) < 0 + || BN_cmp(n, r) <= 0 + || BN_cmp(n, s) <= 0) { + goto err; + } + /* B3: \bar{M'} = ZA || M' */ + if (!sm2_compute_z(buf, id, idlen, key)) { + goto err; + } + if (!sm3_update(&c, buf, SM3_DIGEST_LENGTH) + || !sm3_update(&c, msg, msglen)) { + SM2ERR("sm2_sign(): compute e error!\n"); + } + /* B4: e' = SM3(\bar{M'}), e -> bn */ + sm3_final(buf, &c); + e = BN_bin2bn(buf, SM3_DIGEST_LENGTH, NULL); + /* B5: r', s' -> bn; t = (r'+s')%n, if t=0, goto BERR */ + if (!BN_mod_add_quick(t, r, s, n) + || BN_is_zero(t)) { + goto err; + } + /* B6: (x1', y1') = [s']G + [t]PA */ + if (!EC_POINT_mul(sG, G, s, key->group) + || !EC_POINT_mul(tPA, PA, t, key->group) + || !EC_POINT_add(tmp_point, sG, tPA, key->group)) { + goto err; + } + /* B7: x1' -> bn; R = (e' + x1')%n, return R=r' */ + if (!BN_mod_add_quick(R, e, tmp_point->X, n)) { + goto err; + } + if (BN_cmp(R, r) == 0) { + return 1; + } + err: + BN_CTX_end(ctx); + /* BERR: not pass, return 0 */ + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_tests.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_tests.h" new file mode 100644 index 0000000..922559d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave/sm2_tests.h" @@ -0,0 +1,152 @@ +#ifndef SECGEAR_SM2_TESTS_H +#define SECGEAR_SM2_TESTS_H + +#include "sm2_sign.h" +#include "sm2_exchange.h" +#include "sm2_crypt.h" + +uint8 *sign_buffer, sign_verify_ret; + +void sm2signtest(const int p_bytes, const uint8 *_M, const uint8 *_ID_A, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dA, const uint8 *_k) { + /* A.3 is not supported */ + int _w; + uint16 entlenC = strlen((char *)_ID_A); + uint16 entlA = entlenC*8; + BIGNUM *p, *a, *b, *n, *xG, *yG, *dA, *k; + EC_POINT *G, *kG; + EC_GROUP *group; + EC_KEY *userA; + group = EC_GROUP_new(); + p = BN_new(); + a = BN_new(); + b = BN_new(); + n = BN_new(); + xG = BN_new(); + yG = BN_new(); + dA = BN_new(); + k = BN_new(); + G = EC_POINT_new(); + kG = EC_POINT_new(); + userA = EC_KEY_new(); + BN_bin2bn(_p, p_bytes, p); + BN_bin2bn(_a, p_bytes, a); + BN_bin2bn(_b, p_bytes, b); + BN_bin2bn(_n, p_bytes, n); + BN_bin2bn(_XG, p_bytes, xG); + BN_bin2bn(_YG, p_bytes, yG); + BN_bin2bn(_dA, p_bytes, dA); + BN_bin2bn(_k, p_bytes, k); + EC_POINT_setXY(G, xG, yG); + _w = EC_GROUP_set_param(group, p, a, b, n, BN_value_one(), G); + _w = EC_KEY_set_group(userA, group); + _w = EC_KEY_set_priv_key(userA, dA); + _w = EC_KEY_generate_pub_key(userA); + _w = EC_POINT_mul(kG, G, k, group); + SM2_SIG *sig; + sig = sm2_sig_gen(_M, strlen((char *)_M), _ID_A, strlen((char *)_ID_A), userA); + sign_buffer = (uint8 *)malloc(p_bytes * 4); + memcpy(sign_buffer, BN_bn2hex(sig->r), p_bytes * 2); + memcpy(sign_buffer + p_bytes * 2, BN_bn2hex(sig->s), p_bytes * 2); + + _w = sm2_sig_verify(_M, strlen((char *)_M), _ID_A, strlen((char *)_ID_A), userA, sig); + sign_verify_ret = _w; +} + +uint8 exchange_ret; + +/* h = 1 by default */ +void sm2exchangetest(const int p_bytes, const uint8 *_ID_A, const uint8 *_ID_B, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dA, const uint8 *_dB, const uint64 klen) { + /* A.3 is not supported */ + int _w; + uint16 entlenAC = strlen((char *)_ID_A); + uint16 entlA = entlenAC*8; + uint16 entlenBC = strlen((char *)_ID_B); + uint16 entlB = entlenBC*8; + BIGNUM *p, *a, *b, *h, *n, *xG, *yG, *dA, *dB; + EC_POINT *G, *kG; + EC_GROUP *group; + EC_KEY *userA, *userB; + uint8 *ZA, *ZB; + ZA = malloc(SM3_DIGEST_LENGTH); + ZB = malloc(SM3_DIGEST_LENGTH); + group = EC_GROUP_new(); + p = BN_new(); + a = BN_new(); + b = BN_new(); + h = (BIGNUM *)BN_value_one(); + n = BN_new(); + xG = BN_new(); + yG = BN_new(); + dA = BN_new(); + dB = BN_new(); + G = EC_POINT_new(); + kG = EC_POINT_new(); + userA = EC_KEY_new(); + userB = EC_KEY_new(); + BN_bin2bn(_p, p_bytes, p); + BN_bin2bn(_a, p_bytes, a); + BN_bin2bn(_b, p_bytes, b); + BN_bin2bn(_n, p_bytes, n); + BN_bin2bn(_XG, p_bytes, xG); + BN_bin2bn(_YG, p_bytes, yG); + BN_bin2bn(_dA, p_bytes, dA); + BN_bin2bn(_dB, p_bytes, dB); + EC_POINT_setXY(G, xG, yG); + _w = EC_GROUP_set_param(group, p, a, b, n, h, G); + _w = EC_KEY_set_group(userA, group); + _w = EC_KEY_set_priv_key(userA, dA); + _w = EC_KEY_generate_pub_key(userA); + _w = EC_KEY_set_group(userB, group); + _w = EC_KEY_set_priv_key(userB, dB); + _w = EC_KEY_generate_pub_key(userB); + _w = sm2_compute_z(ZA, _ID_A, strlen((char *)_ID_A), userA); + _w = sm2_compute_z(ZB, _ID_B, strlen((char *)_ID_B), userB); + _w = sm2_exchange(userA, userB, klen, ZA, ZB); + exchange_ret = _w; +} + +uint8 *encrypt_pw, *decrypt_msg; + +void sm2crypttest(int p_bytes, const uint8 *M, const uint8 *_p, const uint8 *_a, const uint8 *_b, const uint8 *_n, const uint8 *_XG, const uint8 *_YG, const uint8 *_dB) { + /* A.3 is not supported */ + int _w; + BIGNUM *p, *a, *b, *n, *xG, *yG, *dB; + EC_POINT *G; + EC_GROUP *group; + EC_KEY *userB; + uint64 klen; + int MlenCBLOCK; + size_t pwlen; + group = EC_GROUP_new(); + p = BN_new(); + a = BN_new(); + b = BN_new(); + n = BN_new(); + xG = BN_new(); + yG = BN_new(); + dB = BN_new(); + G = EC_POINT_new(); + userB = EC_KEY_new(); + BN_bin2bn(_p, p_bytes, p); + BN_bin2bn(_a, p_bytes, a); + BN_bin2bn(_b, p_bytes, b); + BN_bin2bn(_n, p_bytes, n); + BN_bin2bn(_XG, p_bytes, xG); + BN_bin2bn(_YG, p_bytes, yG); + BN_bin2bn(_dB, p_bytes, dB); + EC_POINT_setXY(G, xG, yG); + MlenCBLOCK = strlen((char *)M); + _w = EC_GROUP_set_param(group, p, a, b, n, BN_value_one(), G); + _w = EC_KEY_set_group(userB, group); + _w = EC_KEY_set_priv_key(userB, dB); + _w = EC_KEY_generate_pub_key(userB); + klen = MlenCBLOCK * 8; + pwlen = (p_bytes << 1 | 1) + MlenCBLOCK + SM3_DIGEST_LENGTH; + encrypt_pw = malloc(pwlen); + _w = sm2_encrypt(encrypt_pw, M, klen, userB); + decrypt_msg = malloc(MlenCBLOCK+1); + memset(decrypt_msg, 0, MlenCBLOCK+1); + _w = sm2_decrypt(decrypt_msg, encrypt_pw, klen, userB); +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave_SM2.edl" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave_SM2.edl" new file mode 100644 index 0000000..87d3e65 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/enclave_SM2.edl" @@ -0,0 +1,30 @@ +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + + trusted { + public void callsm2signtest(); + public void callsm2exchangetest(); + public void callsm2crypttest(); + public void setSignIDA([in, size=len] uint8 *src, size_t len); + public void setSignM([in, size=len] uint8 *src, size_t len); + public void setSignDA([in, count=32] uint8 *src); + public void setSignK([in, count=32] uint8 *src); + public void getSignResult([out, size=len] uint8 *buf, size_t len); + public void getSignVerifyResult([out, count=1] uint8 buf); + public void setExchangeIDA([in, size=len] uint8 *src, size_t len); + public void setExchangeIDB([in, size=len] uint8 *src, size_t len); + public void setExchangeDA([in, count=32] uint8 *src); + public void setExchangeDB([in, count=32] uint8 *src); + public void setExchangeKLen([in, count=1] uint64 *src); + public void getExchangeResult([out, count=1] uint8 buf); + public void setCryptM([in, size=len] uint8 *src, size_t len); + public void setCryptDB([in, count=32] uint8 *src); + public void getCryptPW([out, size=len] uint8 *buf, size_t len); + public void getCryptMSG([out, size=len] uint8 *buf, size_t len); + }; + + untrusted { + + }; +}; diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/CMakeLists.txt" new file mode 100644 index 0000000..0d42633 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/CMakeLists.txt" @@ -0,0 +1,88 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM2) +#set host exec name +set(OUTPUT secgear_enclave_SM2) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) + +set(CMAKE_CXX_STANDARD 11) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O2 -fPIE") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim) +else() + target_link_libraries(${OUTPUT} secgear) +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + #itrustee install whitelist /vender/bin/teec_hello + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION /vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/main.cpp" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/main.cpp" new file mode 100644 index 0000000..ef1710e --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/host/main.cpp" @@ -0,0 +1,127 @@ +#include"enclave.h" +#include"Enclave1_u.h" +#include +#include + +#define MAX_LEN 1024 + +#define SM3_DIGEST_LENGTH 32 +const int SM2_p_bytes = 256 >> 3; +const uint8 sign_ID_A[] = "1234567812345678"; +const uint8 sign_M[] = "message digest"; +const uint8 sign_dA[] = { + 0x39, 0x45, 0x20, 0x8F, + 0x7B, 0x21, 0x44, 0xB1, + 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, + 0x88, 0x93, 0x93, 0x69, + 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, + 0x4D, 0xF7, 0xC5, 0xB8, +}; +const uint8 sign_k[] = { + 0x59, 0x27, 0x6E, 0x27, + 0xD5, 0x06, 0x86, 0x1A, + 0x16, 0x68, 0x0F, 0x3A, + 0xD9, 0xC0, 0x2D, 0xCC, + 0xEF, 0x3C, 0xC1, 0xFA, + 0x3C, 0xDB, 0xE4, 0xCE, + 0x6D, 0x54, 0xB8, 0x0D, + 0xEA, 0xC1, 0xBC, 0x21, +}; + +const uint8 exchange_ID_A[] = "1234567812345678"; +const uint8 exchange_ID_B[] = "1234567812345678"; +const uint8 exchange_dA[] = { + 0x81, 0xEB, 0x26, 0xE9, + 0x41, 0xBB, 0x5A, 0xF1, + 0x6D, 0xF1, 0x16, 0x49, + 0x5F, 0x90, 0x69, 0x52, + 0x72, 0xAE, 0x2C, 0xD6, + 0x3D, 0x6C, 0x4A, 0xE1, + 0x67, 0x84, 0x18, 0xBE, + 0x48, 0x23, 0x00, 0x29, +}; +const uint8 exchange_dB[] = { + 0x78, 0x51, 0x29, 0x91, + 0x7D, 0x45, 0xA9, 0xEA, + 0x54, 0x37, 0xA5, 0x93, + 0x56, 0xB8, 0x23, 0x38, + 0xEA, 0xAD, 0xDA, 0x6C, + 0xEB, 0x19, 0x90, 0x88, + 0xF1, 0x4A, 0xE1, 0x0D, + 0xEF, 0xA2, 0x29, 0xB5, +}; +const uint64 exchange_klen = 128; + +const uint8 crypt_M[] = "encryption standard"; +const uint8 crypt_dB[] = { + 0x39, 0x45, 0x20, 0x8F, + 0x7B, 0x21, 0x44, 0xB1, + 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, + 0x88, 0x93, 0x93, 0x69, + 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, + 0x4D, 0xF7, 0xC5, 0xB8, +}; + +int main(int argc, char* argv[]) { + cc_enclave_t *eid; + cc_enclave_result_t ret; + char *path = transferFromString(PATH); + + ret = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &eid); + if (ret != CC_SUCCESS) { + printf("ERR: %#x ,failed to create enclave.\n", ret); + return -1; + } + + u_int8_t buffer[MAX_LEN], tmpu8; + memset(buffer, 0, sizeof buffer); + printf("A.2 start: \n"); + setSignIDA(eid, sign_ID_A, strlen(sign_ID_A)); + setSignM(eid, sign_M, strlen(sign_M)); + setSignDA(eid, sign_dA); + setSignK(eid, sign_k); + callsm2signtest(eid); + getSignResult(eid, buffer, MAX_LEN); + printf("sign sig: %s\n", buffer); + getSignVerifyResult(eid, tmpu8); + printf("sign verify: %x\n", tmpu8); + printf("A.2 end: \n\n\n"); + /* PASSED */ + + printf("B.2 start: \n"); + setExchangeIDA(eid, exchange_ID_A, strlen(exchange_ID_A)); + setExchangeIDB(eid, exchange_ID_B, strlen(exchange_ID_B)); + setExchangeDA(eid, exchange_dA); + setExchangeDB(eid, exchange_dB); + setExchangeKLen(eid, exchange_klen); + callsm2exchangetest(eid); + getExchangeResult(eid, tmpu8); + printf("exchange: %x\n", tmpu8); + printf("B.2 end: \n\n\n"); + /* PASSED */ + + printf("C.2 start: \n"); + setCryptM(eid, crypt_M, strlen(crypt_M)); + setCryptDB(eid, crypt_dB); + callsm2crypttest(eid); + int pwlen = (SM2_p_bytes << 1 | 1) + strlen(crypt_M) + SM3_DIGEST_LENGTH; + getCryptPW(eid, buffer, pwlen); + printf("encrypt pw: "); + for (int i=0; i +#define debugPrint (printf("%s: %s: %d\n",__FILE__,__FUNCTION__,__LINE__),fflush(stdout),1) + +typedef __uint8_t uint8; +typedef __uint16_t uint16; +typedef __uint32_t uint32; +typedef __uint64_t uint64; + +#define CONCAT_8x4(x0, x1, x2, x3) ((((uint32)(x0) << 8 | (x1)) << 8 | (x2)) << 8 | (x3)) // X = (x0 || x1 || x2 || x3) +#define CONCAT_16x2(x0, x1) ((uint32)(x0) << 16 | (x1)) // X = (x0 || x1) +#define EXTRACT_8_32(X, i) (((X) >> (((i) ^ 3) << 3)) & 0xFF) // X = (x0 || x1 || x2 || x3) +#define EXTRACT_16_32(X, i) (((X) >> (((i) ^ 1) << 4)) & 0xFFFF) // X = (x0 || x1) +#define EXTRACT_16H_31(X) (((X) >> 15) & 0xFFFF) // Higher 16-bit from 31-bit +#define EXTRACT_16L_31(X) ((X) & 0xFFFF) // Lower 16-bit from 31-bit + +#define ROTATE(a, n) (((a) << (n)) | (((a) & 0xFFFFFFFF) >> ((32 - (n)) & 31))) +#define ROTATE_31(a, n) ((((a) << (n)) & 0x7FFFFFFF) | (((a) & 0x7FFFFFFF) >> (31 - (n)))) + +#define GET_BIT_VALUE_32(x, i) (((x) >> (31 - (i))) & 1) + +const uint32 PREFIX_MASK_32[32] = { + 0x00000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE +}; + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/include/ec.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/include/ec.h" new file mode 100644 index 0000000..56adbe7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/include/ec.h" @@ -0,0 +1,545 @@ +#include /* BigNum */ +#include "common_utils.h" + +typedef struct ec_point_st { + BIGNUM *X; + BIGNUM *Y; + int is_infinity; +} EC_POINT; + +int EC_POINT_init(EC_POINT *point) { + point->X = BN_new(); + point->Y = BN_new(); + point->is_infinity = 0; + if (point->X == NULL || point->Y == NULL) { + BN_free(point->X); + BN_free(point->Y); + return 0; + } + return 1; +} + +EC_POINT *EC_POINT_new() { + EC_POINT *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_POINT_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_POINT_setXY(EC_POINT *r, const BIGNUM *x, const BIGNUM *y) { + if (r == NULL) { + return 0; + } + if (!BN_copy(r->X, x) || !(BN_copy(r->Y, y))) { + return 0; + } + return 1; +} + +const EC_POINT *EC_point_infinity() { + static const EC_POINT const_infinity = { NULL, NULL, 1 }; + return &const_infinity; +} + +int EC_POINT_is_infinity(const EC_POINT *point) { + return point->is_infinity; +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest == NULL) { + return 0; + } + if (EC_POINT_is_infinity(src)) { + dest->is_infinity = 1; + } + else{ + dest->is_infinity = 0; + if (!BN_copy(dest->X, src->X) || !BN_copy(dest->Y, src->Y)) return 0; + } + return 1; +} + +#define NORMAL 0x1 +#define COMPRESS 0x2 +#define MIX 0x4 + +int EC_POINT_ecp2bin(uint8 *out, const EC_POINT *point, int p_bytes, int flag) { + uint8 PC; + uint8 *p = out, *buf; + int i; + buf = malloc(p_bytes); + if (EC_POINT_is_infinity(point)) { + return 0; + } + if (flag == NORMAL) { + PC = 0x04; + *(p++) = PC; + if (!BN_bn2binpad(point->X, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + if (!BN_bn2binpad(point->Y, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_bin2ecp(EC_POINT *point, const uint8 *src, int p_bytes) { + if (point == NULL) { + return 0; + } + uint8 PC = *src; + const uint8 *data = src + 1; + uint8 *buf; + int i; + if (PC == 0x04) { + if (!BN_bin2bn(data, p_bytes, point->X) + || !BN_bin2bn(data+p_bytes, p_bytes, point->Y)) { + return 0; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_ecp2bin_normal(uint8 *out, const EC_POINT *point, int p_bytes) { + return EC_POINT_ecp2bin(out, point, p_bytes, NORMAL); +} + +// int EC_POINT_ecp2bin_compressed(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, COMPRESS); +// } + +// int EC_POINT_ecp2bin_mix(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, MIX); +// } + +typedef struct ec_group_st { + EC_POINT *generator; /* point G */ + BIGNUM *order; /* n */ + BIGNUM *cofactor; /* h */ + BIGNUM *field; /* module p */ + BIGNUM *a, *b; /* ECC parameter */ +} EC_GROUP; + +int EC_GROUP_init(EC_GROUP *group) { + group->generator = EC_POINT_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->generator == NULL || group->b == NULL) { + free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +EC_GROUP *EC_GROUP_new() { + EC_GROUP *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_GROUP_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest == NULL) { + return 0; + } + if (dest == src) { + return 1; + } + if (!EC_POINT_copy(dest->generator, src->generator) + || !BN_copy(dest->order, src->order) + || !BN_copy(dest->cofactor, src->cofactor) + || !BN_copy(dest->field, src->field) + || !BN_copy(dest->a, src->a) + || !BN_copy(dest->b, src->b)) { + return 0; + } + return 1; +} + +int EC_GROUP_set_param(EC_GROUP *group, const BIGNUM *field, const BIGNUM *a, const BIGNUM *b, const BIGNUM *order, const BIGNUM *cofactor, const EC_POINT *point) { + if (group == NULL) { + return 0; + } + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->generator = EC_POINT_new(); + if (group->cofactor == NULL + || group->generator == NULL) { + return 0; + } + if (!BN_copy(group->field, field) + || !BN_copy(group->a, a) + || !BN_copy(group->b, b) + || !BN_copy(group->order, order) + || !BN_copy(group->cofactor, cofactor) + || !EC_POINT_copy(group->generator, point)) { + return 0; + } + return 1; +} + +int EC_POINT_double(EC_POINT *r, const EC_POINT *a, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, EC_point_infinity()); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y)) { + goto done; + } + if (!BN_set_word(bn_value_3, 3) + || !BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_sqr(r->X, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_lshift1_quick(tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, r->X, tmp, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_add(EC_POINT *r, const EC_POINT *a, const EC_POINT *b, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *bx, *by, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (a == b) { + return EC_POINT_double(r, a, group); + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_infinity(b)) { + return EC_POINT_copy(r, a); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + bx = BN_CTX_get(ctx); + by = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y) + || !BN_copy(bx, b->X) + || !BN_copy(by, b->Y)) { + goto done; + } + if (BN_cmp(ax, bx) == 0) { + if (!BN_mod_add_quick(tmp, ay, by, p)) { + goto done; + } + if (BN_is_zero(tmp) + || !EC_POINT_copy(r, EC_point_infinity())) { + goto done; + } + if (!BN_set_word(bn_value_3, 3)) { + goto done; + } + if (!BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + else { + if (!BN_mod_sub_quick(lnum, by, ay, p)) { + goto done; + } + if (!BN_mod_sub_quick(ldeno, bx, ax, p)) { + goto done; + } + if (!BN_mod_inverse(ldeno, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + if (!BN_mod_sqr(tmp, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(tmp, tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, tmp, bx, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_mul(EC_POINT *r, const EC_POINT *a, const BIGNUM *b, const EC_GROUP *group) { + if (r == NULL) { + return 0; + } + if (BN_is_negative(b)) { + EC_POINT *_a = EC_POINT_new(); + BIGNUM *_b = BN_new(); + if (!EC_POINT_copy(_a, a) + || !BN_copy(_b, b) + || !BN_mod_sub_quick(_a->Y, group->field, _a->Y, group->field)) { + return 0; + } + BN_set_negative(_b, 0); + return EC_POINT_mul(r, _a, _b, group); + } + if (!EC_POINT_copy(r, EC_point_infinity())){ + return 0; + } + int bits = BN_num_bits(b); + for (int i = bits-1; i >= 0; --i) { + if (!EC_POINT_double(r, r, group)) { + return 0; + } + if (BN_is_bit_set(b, i)) { + if (!EC_POINT_add(r, r, a, group)) { + return 0; + } + } + } + return 1; +} + +/* + * Only for curve y^2 = x^3 + ax + b. + * Please check infinity before calling. + */ +int EC_POINT_on_curve_simple(const EC_POINT *point, const EC_GROUP *group) { + if (point == NULL || group == NULL) { + return 0; + } + if (EC_POINT_is_infinity(point)) { + return 1; + } + int ret = 0; + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *lhs, *rhs; + EC_POINT *Nq; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return ret; + } + BN_CTX_start(ctx); + p = group->field; + a = group->a; + b = group->b; + x = point->X; + y = point->Y; + lhs = BN_CTX_get(ctx); + rhs = BN_CTX_get(ctx); + Nq = EC_POINT_new(); + if (p == NULL + || a == NULL + || b == NULL + || x == NULL + || y == NULL + || rhs == NULL + || Nq == NULL) { + return ret; + } + if (!BN_mod_mul(lhs, y, y, p, ctx) + || !BN_mod_mul(rhs, x, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, a, p) + || !BN_mod_mul(rhs, rhs, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, b, p) + || !EC_POINT_mul(Nq, point, group->order, group)) { + return ret; + } + if (BN_cmp(lhs, rhs) != 0 + || !EC_POINT_is_infinity(Nq)) { + return ret; + } + ret = 1; + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +typedef struct ec_key_st { + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; +} EC_KEY; + +int EC_KEY_init(EC_KEY *key) { + key->group = EC_GROUP_new(); + key->pub_key = EC_POINT_new(); + key->priv_key = BN_new(); + if (key->group == NULL + || key->pub_key == NULL + || key->priv_key == NULL) { + free(key->group); + free(key->pub_key); + BN_free(key->priv_key); + return 0; + } + return 1; +} + +EC_KEY *EC_KEY_new() { + EC_KEY *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_KEY_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + if (!EC_GROUP_copy(key->group, group)) { + return 0; + } + return 1; +} + +int EC_KEY_set_priv_key(EC_KEY *key, const BIGNUM *priv_key) { + BIGNUM *tmp; + tmp = BN_dup(priv_key); + if (tmp == NULL) { + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = tmp; + return 1; +} + +int EC_KEY_generate_pub_key(EC_KEY *key) { + return EC_POINT_mul(key->pub_key, key->group->generator, key->priv_key, key->group); +} + +const BIGNUM *EC_KEY_get_priv_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_generate_key() {} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/sm3/sm3.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/sm3/sm3.h" new file mode 100644 index 0000000..195d679 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM2/sm3/sm3.h" @@ -0,0 +1,183 @@ +#ifndef SECGEAR_SM3_H +#define SECGEAR_SM3_H + +/* + * Ref: + * GB/T 32905-2016 + */ + +#include +#include "../include/common_utils.h" + +#define SM3_DIGEST_LENGTH 32 +#define SM3_WORD uint32 + +#define SM3_CBLOCK 64 +#define SM3_LBLOCK (SM3_CBLOCK/4) + +typedef struct SM3state_st { + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD Nl, Nh; + SM3_WORD data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17)) +#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23)) + +#define FF(J,X,Y,Z) (J<16 ? (X ^ Y ^ Z) : ((X & Y) | (X & Z) | (Y & Z))) +#define GG(J,X,Y,Z) (J<16 ? (X ^ Y ^ Z) : ((X & Y) | ((~X) & Z))) + +#define T(J) (J<16 ? 0x79cc4519 : 0x7a879d8a) + +#define EXPAND(W0,W7,W13,W3,W10) \ + (P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10) + +#define SM3_A 0x7380166fUL +#define SM3_B 0x4914b2b9UL +#define SM3_C 0x172442d7UL +#define SM3_D 0xda8a0600UL +#define SM3_E 0xa96f30bcUL +#define SM3_F 0x163138aaUL +#define SM3_G 0xe38dee4dUL +#define SM3_H 0xb0fb0e4eUL + +#define SM3_MAKE_STRING(c, s) \ + do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll, (s)); \ + ll=(c)->B; (void)HOST_l2c(ll, (s)); \ + ll=(c)->C; (void)HOST_l2c(ll, (s)); \ + ll=(c)->D; (void)HOST_l2c(ll, (s)); \ + ll=(c)->E; (void)HOST_l2c(ll, (s)); \ + ll=(c)->F; (void)HOST_l2c(ll, (s)); \ + ll=(c)->G; (void)HOST_l2c(ll, (s)); \ + ll=(c)->H; (void)HOST_l2c(ll, (s)); \ + } while (0) + +void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num) { + const unsigned char *data = p; + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD w[68]={}, ww[64]={}; + while (num--) { + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + E = ctx->E; + F = ctx->F; + G = ctx->G; + H = ctx->H; + for (int j = 0; j < 16; ++j) { + HOST_c2l(data, w[j]); + } + for (int j = 16; j < 68; ++j) { + w[j] = EXPAND(w[j-16], w[j-9], w[j-3], w[j-13], w[j-6]); + } + for (int j = 0; j < 64; ++j) { + ww[j] = w[j] ^ w[j+4]; + } + for (int j = 0; j < 64; j++) { + SM3_WORD SS1, SS2, TT1, TT2; + SS1 = ROTATE(ROTATE(A, 12) + E + ROTATE(T(j), j&31), 7); + SS2 = SS1 ^ ROTATE(A, 12); + TT1 = FF(j, A, B, C) + D + SS2 + ww[j]; + TT2 = GG(j, E, F, G) + H + SS1 + w[j]; + D = C; + C = ROTATE(B,9); + B = A; + A = TT1; + H = G; + G = ROTATE(F, 19); + F = E; + E = P0(TT2); + } + ctx->A ^= A; + ctx->B ^= B; + ctx->C ^= C; + ctx->D ^= D; + ctx->E ^= E; + ctx->F ^= F; + ctx->G ^= G; + ctx->H ^= H; + } +} + +int sm3_init(SM3_CTX *c) { + memset(c, 0, sizeof(*c)); + c->A = SM3_A; + c->B = SM3_B; + c->C = SM3_C; + c->D = SM3_D; + c->E = SM3_E; + c->F = SM3_F; + c->G = SM3_G; + c->H = SM3_H; + return 1; +} + +int sm3_update(SM3_CTX *c, const void *data_, size_t len) { + const unsigned char *data = data_; + unsigned char *p; + SM3_WORD l; + size_t n; + if (len == 0) return 1; + l = (c->Nl + (((SM3_WORD) len) << 3)) & 0xffffffffUL; + if (l < c->Nl) c->Nh++; + c->Nh += (SM3_WORD) (len >> 29); + c->Nl = l; + n = c->num; + if (n != 0) { + p = (unsigned char *)c->data; + if (len >= SM3_CBLOCK || len + n >= SM3_CBLOCK) { + memcpy(p + n, data, SM3_CBLOCK - n); + sm3_block_data_order(c, p, 1); + n = SM3_CBLOCK - n; + data += n; + len -= n; + c->num = 0; + memset(p, 0, SM3_CBLOCK); + } + else { + memcpy(p + n, data, len); + c->num += (unsigned int)len; + return 1; + } + } + n = len / SM3_CBLOCK; + if (n > 0) { + sm3_block_data_order(c, data, n); + n *= SM3_CBLOCK; + data += n; + len -= n; + } + if (len != 0) { + p = (unsigned char *)c->data; + c->num = (unsigned int)len; + memcpy(p, data, len); + } + return 1; +} + +int sm3_final(unsigned char *md, SM3_CTX *c) { + unsigned char *p = (unsigned char *)c->data; + size_t n = c->num; + p[n] = 0x80; + n++; + if (n > (SM3_CBLOCK - 8)) { + memset(p + n, 0, SM3_CBLOCK - n); + n = 0; + sm3_block_data_order(c, p, 1); + } + memset(p + n, 0, SM3_CBLOCK - 8 - n); + p += SM3_CBLOCK - 8; + (void)HOST_l2c(c->Nh, p); + (void)HOST_l2c(c->Nl, p); + p -= SM3_CBLOCK; + sm3_block_data_order(c, p, 1); + c->num = 0; + SM3_MAKE_STRING(c, md); + return 1; +} + +#endif \ No newline at end of file -- Gitee From 8cf413bc4ae2abeb96c3690edb64097de2056298 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:56:56 +0000 Subject: [PATCH 17/18] enclave_SM4 Signed-off-by: wangxiaoxi1 --- .../Informal/enclave_SM4/CMakeLists.txt" | 38 ++ .../enclave_SM4/enclave/CMakeLists.txt" | 162 ++++++ .../enclave_SM4/enclave/Enclave.config.xml" | 12 + .../Informal/enclave_SM4/enclave/Enclave.lds" | 11 + .../enclave_SM4/enclave/enclave_SM4.c" | 42 ++ .../enclave_SM4/enclave/manifest.txt.in" | 8 + .../enclave/rsa_public_key_cloud.pem" | 11 + .../Informal/enclave_SM4/enclave/sm4.h" | 107 ++++ .../Informal/enclave_SM4/enclave_SM4.edl" | 16 + .../Informal/enclave_SM4/host/CMakeLists.txt" | 88 +++ .../Informal/enclave_SM4/host/main.cpp" | 51 ++ .../enclave_SM4/include/common_utils.h" | 69 +++ .../Informal/enclave_SM4/include/ec.h" | 545 ++++++++++++++++++ 13 files changed, 1160 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.config.xml" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.lds" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/enclave_SM4.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/manifest.txt.in" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/rsa_public_key_cloud.pem" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/sm4.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave_SM4.edl" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/main.cpp" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/common_utils.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/ec.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/CMakeLists.txt" new file mode 100644 index 0000000..acd2ef7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/CMakeLists.txt" @@ -0,0 +1,38 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +project(enclave_SM4) + +set(CMAKE_C_STANDARD 99) + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE enclave_SM4.edl) +#set(LOCAL_ROOT_PATH "$ENV{CC_SDK}") +#set(SECGEAR_INSTALL_PATH /usr/lib64/) + +if(CC_GP) + set(CODETYPE trustzone) + set(CODEGEN codegen_arm64) + execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) + string(REPLACE "\n" "" UUID ${UUID}) + add_definitions(-DPATH="/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + set(CODEGEN codegen_x86_64) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/CMakeLists.txt" new file mode 100644 index 0000000..7c4b75d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/CMakeLists.txt" @@ -0,0 +1,162 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM4) + +set(CMAKE_C_STANDARD 99) +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave_SM4.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + #set itrustee device key + set(DEVICEPEM ${CMAKE_CURRENT_SOURCE_DIR}/rsa_public_key_cloud.pem) + #set whilelist. default: /vendor/bin/teec_hello + set(WHITE_LIST_0 /vendor/bin/enclave_SM4) + set(WHITE_LIST_OWNER root) + set(WHITE_LIST_1 /vendor/bin/secgear_enclave_SM4) + set(WHITELIST WHITE_LIST_0 WHITE_LIST_1) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(COMMON_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \ + -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") +set(COMMON_CXX_FLAGS "${COMMON_C_FLAGS}") + +if(CC_GP) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt") + + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/enclave_inc + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${SECGEAR_INSTALL_PATH}) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -lsecgear_tee) + + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i /home/sunny/secGear/debug/lib/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT} + DESTINATION /data + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -O2 -nostdinc++") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE + ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.config.xml" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.config.xml" new file mode 100644 index 0000000..a5e05e0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.config.xml" @@ -0,0 +1,12 @@ + + 0 + 0 + 0x100000 + 0x80000 + 10 + 1 + + 1 + 0 + 0xFFFFFFFF + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.lds" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.lds" new file mode 100644 index 0000000..ab77e64 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/Enclave.lds" @@ -0,0 +1,11 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/enclave_SM4.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/enclave_SM4.c" new file mode 100644 index 0000000..a866474 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave/enclave_SM4.c" @@ -0,0 +1,42 @@ +#include "Enclave1_t.h" +#include +#include "sm4.h" + +uint32 message[4]; +uint32 key[4]; +uint32 res_enc[4], res_dec[4]; + +void sm4test(const uint32 *M, const uint32 *MK, const int rounds) { + SM4_CTX c; + sm4_init(&c, M, MK); + for (int i=0; i +#include "../include/common_utils.h" + +#define ENCRYPT 0 +#define DECRYPT 1 +const uint8 Sbox[256] = { + 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, + 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, + 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, + 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, + 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, + 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, + 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, + 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, + 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, + 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, + 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, + 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, + 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, + 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, + 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48, +}; +const uint32 FK[4] = { + 0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC, +}; +const uint32 CK[32] = { + 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, + 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, + 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, + 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, + 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, + 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, + 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, + 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279, +}; +#define L(B) ((B) ^ (ROTATE((B), 2)) ^ (ROTATE((B), 10)) ^ (ROTATE((B), 18)) ^ (ROTATE((B), 24))) +#define LP(B) ((B) ^ (ROTATE((B), 13)) ^ (ROTATE((B), 23))) +#define S(X) (((uint32)Sbox[((X) >> 24) & 0xFF] << 24) | \ + ((uint32)Sbox[((X) >> 16) & 0xFF] << 16) | \ + ((uint32)Sbox[((X) >> 8) & 0xFF] << 8) | \ + ((uint32)Sbox[(X) & 0xFF])) +#define T(X) L(S(X)) +#define TP(X) LP(S(X)) +#define F(X0, X1, X2, X3, rk) ((X0) ^ T((X1) ^ (X2) ^ (X3) ^ (rk))) + +typedef struct sm4_ctx_st { + uint32 M[4]; + uint32 rk[32]; +} SM4_CTX; + +int sm4_init(SM4_CTX *ctx, const uint32 *M, const uint32 *MK) { + memset(ctx, 0, sizeof(*ctx)); + uint32 K[36]; + memset(K, 0, sizeof(K)); + int i; + for (i = 0; i < 4; ++i) { + K[i] = MK[i] ^ FK[i]; + ctx->M[i] = M[i]; + } + for (i = 0; i < 32; ++i) { + ctx->rk[i] = K[i+4] = K[i] ^ TP(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]); + } + return 1; +} + +int sm4_round(SM4_CTX *ctx, int crypt_flag) { + int offset = (crypt_flag ? 31 : 0), i; + uint32 X[36]; + memset(X, 0, sizeof(X)); + for (i = 0; i < 4; ++i) { + X[i] = ctx->M[i]; + } + for (i = 0; i < 32; ++i) { + X[i+4] = F(X[i], X[i+1], X[i+2], X[i+3], ctx->rk[i^offset]); + } + ctx->M[0] = X[35]; + ctx->M[1] = X[34]; + ctx->M[2] = X[33]; + ctx->M[3] = X[32]; + return 1; +} + +int sm4_encrypt(SM4_CTX *ctx) { + return sm4_round(ctx, ENCRYPT); +} + +int sm4_decrypt(SM4_CTX *ctx) { + return sm4_round(ctx, DECRYPT); +} + +int sm4_final(uint32 *out, SM4_CTX *ctx) { + if (!memcpy(out, ctx->M, sizeof(ctx->M))) { + return 0; + } + return 1; +} + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave_SM4.edl" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave_SM4.edl" new file mode 100644 index 0000000..3de3690 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/enclave_SM4.edl" @@ -0,0 +1,16 @@ +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + + trusted { + public void setKeys([in, count=4] uint32_t *src); + public void setKeys([in, count=4] uint32_t *src); + public void callsm4test1(); + public void callsm4test2(); + public void getKeys([out, count=4] uint32_t *buf); + }; + + untrusted { + + }; +}; diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/CMakeLists.txt" new file mode 100644 index 0000000..2dae205 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/CMakeLists.txt" @@ -0,0 +1,88 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_SM4) +#set host exec name +set(OUTPUT secgear_enclave_SM4) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) + +set(CMAKE_CXX_STANDARD 11) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O2 -fPIE") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim) +else() + target_link_libraries(${OUTPUT} secgear) +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + #itrustee install whitelist /vender/bin/teec_hello + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION /vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/main.cpp" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/main.cpp" new file mode 100644 index 0000000..960a50d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/host/main.cpp" @@ -0,0 +1,51 @@ +#include"enclave.h" +#include"Enclave1_u.h" +#include +#include + +const u_int32_t message[4] = { + 0x01234567, 0x89ABCDEF, + 0xFEDCBA98, 0x76543210, +}; +const u_int32_t key[4] = { + 0x01234567, 0x89ABCDEF, + 0xFEDCBA98, 0x76543210, +}; + +int main(int argc, char* argv[]) { + cc_enclave_t *eid; + cc_enclave_result_t ret; + char *path = transferFromString(PATH); + + ret = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &eid); + if (ret != CC_SUCCESS) { + printf("ERR: %#x ,failed to create enclave.\n", ret); + return -1; + } + + u_int32_t res[4]; + setSM4Message(eid, message); + setSM4Key(eid, key); + callsm4test1(eid); + getSM4Result(eid, res); + printf("encrypt 1: "); + for (int i=0; i<4; i++){ + printf("%08X", res[i]); + } + printf("\n"); + + setSM4Message(eid, message); + setSM4Key(eid, key); + callsm4test2(eid); + getSM4Result(eid, res); + printf("encrypt 100000: "); + for (int i=0; i<4; i++){ + printf("%08X", res[i]); + } + printf("\n"); + + if (CC_SUCCESS != cc_enclave_destroy(eid)) { + return -1; + } + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/common_utils.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/common_utils.h" new file mode 100644 index 0000000..9251edc --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/common_utils.h" @@ -0,0 +1,69 @@ +#ifndef SECGEAR_SM_COMMON_UTILS +#define SECGEAR_SM_COMMON_UTILS + +#include +#define debugPrint (printf("%s: %s: %d\n",__FILE__,__FUNCTION__,__LINE__),fflush(stdout),1) + +typedef __uint8_t uint8; +typedef __uint16_t uint16; +typedef __uint32_t uint32; +typedef __uint64_t uint64; + +#define CONCAT_8x4(x0, x1, x2, x3) ((((uint32)(x0) << 8 | (x1)) << 8 | (x2)) << 8 | (x3)) // X = (x0 || x1 || x2 || x3) +#define CONCAT_16x2(x0, x1) ((uint32)(x0) << 16 | (x1)) // X = (x0 || x1) +#define EXTRACT_8_32(X, i) (((X) >> (((i) ^ 3) << 3)) & 0xFF) // X = (x0 || x1 || x2 || x3) +#define EXTRACT_16_32(X, i) (((X) >> (((i) ^ 1) << 4)) & 0xFFFF) // X = (x0 || x1) +#define EXTRACT_16H_31(X) (((X) >> 15) & 0xFFFF) // Higher 16-bit from 31-bit +#define EXTRACT_16L_31(X) ((X) & 0xFFFF) // Lower 16-bit from 31-bit + +#define ROTATE(a, n) (((a) << (n)) | (((a) & 0xFFFFFFFF) >> ((32 - (n)) & 31))) +#define ROTATE_31(a, n) ((((a) << (n)) & 0x7FFFFFFF) | (((a) & 0x7FFFFFFF) >> (31 - (n)))) + +#define GET_BIT_VALUE_32(x, i) (((x) >> (31 - (i))) & 1) + +const uint32 PREFIX_MASK_32[32] = { + 0x00000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE +}; + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/ec.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/ec.h" new file mode 100644 index 0000000..56adbe7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_SM4/include/ec.h" @@ -0,0 +1,545 @@ +#include /* BigNum */ +#include "common_utils.h" + +typedef struct ec_point_st { + BIGNUM *X; + BIGNUM *Y; + int is_infinity; +} EC_POINT; + +int EC_POINT_init(EC_POINT *point) { + point->X = BN_new(); + point->Y = BN_new(); + point->is_infinity = 0; + if (point->X == NULL || point->Y == NULL) { + BN_free(point->X); + BN_free(point->Y); + return 0; + } + return 1; +} + +EC_POINT *EC_POINT_new() { + EC_POINT *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_POINT_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_POINT_setXY(EC_POINT *r, const BIGNUM *x, const BIGNUM *y) { + if (r == NULL) { + return 0; + } + if (!BN_copy(r->X, x) || !(BN_copy(r->Y, y))) { + return 0; + } + return 1; +} + +const EC_POINT *EC_point_infinity() { + static const EC_POINT const_infinity = { NULL, NULL, 1 }; + return &const_infinity; +} + +int EC_POINT_is_infinity(const EC_POINT *point) { + return point->is_infinity; +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest == NULL) { + return 0; + } + if (EC_POINT_is_infinity(src)) { + dest->is_infinity = 1; + } + else{ + dest->is_infinity = 0; + if (!BN_copy(dest->X, src->X) || !BN_copy(dest->Y, src->Y)) return 0; + } + return 1; +} + +#define NORMAL 0x1 +#define COMPRESS 0x2 +#define MIX 0x4 + +int EC_POINT_ecp2bin(uint8 *out, const EC_POINT *point, int p_bytes, int flag) { + uint8 PC; + uint8 *p = out, *buf; + int i; + buf = malloc(p_bytes); + if (EC_POINT_is_infinity(point)) { + return 0; + } + if (flag == NORMAL) { + PC = 0x04; + *(p++) = PC; + if (!BN_bn2binpad(point->X, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + if (!BN_bn2binpad(point->Y, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_bin2ecp(EC_POINT *point, const uint8 *src, int p_bytes) { + if (point == NULL) { + return 0; + } + uint8 PC = *src; + const uint8 *data = src + 1; + uint8 *buf; + int i; + if (PC == 0x04) { + if (!BN_bin2bn(data, p_bytes, point->X) + || !BN_bin2bn(data+p_bytes, p_bytes, point->Y)) { + return 0; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_ecp2bin_normal(uint8 *out, const EC_POINT *point, int p_bytes) { + return EC_POINT_ecp2bin(out, point, p_bytes, NORMAL); +} + +// int EC_POINT_ecp2bin_compressed(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, COMPRESS); +// } + +// int EC_POINT_ecp2bin_mix(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, MIX); +// } + +typedef struct ec_group_st { + EC_POINT *generator; /* point G */ + BIGNUM *order; /* n */ + BIGNUM *cofactor; /* h */ + BIGNUM *field; /* module p */ + BIGNUM *a, *b; /* ECC parameter */ +} EC_GROUP; + +int EC_GROUP_init(EC_GROUP *group) { + group->generator = EC_POINT_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->generator == NULL || group->b == NULL) { + free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +EC_GROUP *EC_GROUP_new() { + EC_GROUP *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_GROUP_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest == NULL) { + return 0; + } + if (dest == src) { + return 1; + } + if (!EC_POINT_copy(dest->generator, src->generator) + || !BN_copy(dest->order, src->order) + || !BN_copy(dest->cofactor, src->cofactor) + || !BN_copy(dest->field, src->field) + || !BN_copy(dest->a, src->a) + || !BN_copy(dest->b, src->b)) { + return 0; + } + return 1; +} + +int EC_GROUP_set_param(EC_GROUP *group, const BIGNUM *field, const BIGNUM *a, const BIGNUM *b, const BIGNUM *order, const BIGNUM *cofactor, const EC_POINT *point) { + if (group == NULL) { + return 0; + } + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->generator = EC_POINT_new(); + if (group->cofactor == NULL + || group->generator == NULL) { + return 0; + } + if (!BN_copy(group->field, field) + || !BN_copy(group->a, a) + || !BN_copy(group->b, b) + || !BN_copy(group->order, order) + || !BN_copy(group->cofactor, cofactor) + || !EC_POINT_copy(group->generator, point)) { + return 0; + } + return 1; +} + +int EC_POINT_double(EC_POINT *r, const EC_POINT *a, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, EC_point_infinity()); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y)) { + goto done; + } + if (!BN_set_word(bn_value_3, 3) + || !BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_sqr(r->X, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_lshift1_quick(tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, r->X, tmp, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_add(EC_POINT *r, const EC_POINT *a, const EC_POINT *b, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *bx, *by, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (a == b) { + return EC_POINT_double(r, a, group); + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_infinity(b)) { + return EC_POINT_copy(r, a); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + bx = BN_CTX_get(ctx); + by = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y) + || !BN_copy(bx, b->X) + || !BN_copy(by, b->Y)) { + goto done; + } + if (BN_cmp(ax, bx) == 0) { + if (!BN_mod_add_quick(tmp, ay, by, p)) { + goto done; + } + if (BN_is_zero(tmp) + || !EC_POINT_copy(r, EC_point_infinity())) { + goto done; + } + if (!BN_set_word(bn_value_3, 3)) { + goto done; + } + if (!BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + else { + if (!BN_mod_sub_quick(lnum, by, ay, p)) { + goto done; + } + if (!BN_mod_sub_quick(ldeno, bx, ax, p)) { + goto done; + } + if (!BN_mod_inverse(ldeno, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + if (!BN_mod_sqr(tmp, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(tmp, tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, tmp, bx, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_mul(EC_POINT *r, const EC_POINT *a, const BIGNUM *b, const EC_GROUP *group) { + if (r == NULL) { + return 0; + } + if (BN_is_negative(b)) { + EC_POINT *_a = EC_POINT_new(); + BIGNUM *_b = BN_new(); + if (!EC_POINT_copy(_a, a) + || !BN_copy(_b, b) + || !BN_mod_sub_quick(_a->Y, group->field, _a->Y, group->field)) { + return 0; + } + BN_set_negative(_b, 0); + return EC_POINT_mul(r, _a, _b, group); + } + if (!EC_POINT_copy(r, EC_point_infinity())){ + return 0; + } + int bits = BN_num_bits(b); + for (int i = bits-1; i >= 0; --i) { + if (!EC_POINT_double(r, r, group)) { + return 0; + } + if (BN_is_bit_set(b, i)) { + if (!EC_POINT_add(r, r, a, group)) { + return 0; + } + } + } + return 1; +} + +/* + * Only for curve y^2 = x^3 + ax + b. + * Please check infinity before calling. + */ +int EC_POINT_on_curve_simple(const EC_POINT *point, const EC_GROUP *group) { + if (point == NULL || group == NULL) { + return 0; + } + if (EC_POINT_is_infinity(point)) { + return 1; + } + int ret = 0; + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *lhs, *rhs; + EC_POINT *Nq; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return ret; + } + BN_CTX_start(ctx); + p = group->field; + a = group->a; + b = group->b; + x = point->X; + y = point->Y; + lhs = BN_CTX_get(ctx); + rhs = BN_CTX_get(ctx); + Nq = EC_POINT_new(); + if (p == NULL + || a == NULL + || b == NULL + || x == NULL + || y == NULL + || rhs == NULL + || Nq == NULL) { + return ret; + } + if (!BN_mod_mul(lhs, y, y, p, ctx) + || !BN_mod_mul(rhs, x, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, a, p) + || !BN_mod_mul(rhs, rhs, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, b, p) + || !EC_POINT_mul(Nq, point, group->order, group)) { + return ret; + } + if (BN_cmp(lhs, rhs) != 0 + || !EC_POINT_is_infinity(Nq)) { + return ret; + } + ret = 1; + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +typedef struct ec_key_st { + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; +} EC_KEY; + +int EC_KEY_init(EC_KEY *key) { + key->group = EC_GROUP_new(); + key->pub_key = EC_POINT_new(); + key->priv_key = BN_new(); + if (key->group == NULL + || key->pub_key == NULL + || key->priv_key == NULL) { + free(key->group); + free(key->pub_key); + BN_free(key->priv_key); + return 0; + } + return 1; +} + +EC_KEY *EC_KEY_new() { + EC_KEY *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_KEY_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + if (!EC_GROUP_copy(key->group, group)) { + return 0; + } + return 1; +} + +int EC_KEY_set_priv_key(EC_KEY *key, const BIGNUM *priv_key) { + BIGNUM *tmp; + tmp = BN_dup(priv_key); + if (tmp == NULL) { + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = tmp; + return 1; +} + +int EC_KEY_generate_pub_key(EC_KEY *key) { + return EC_POINT_mul(key->pub_key, key->group->generator, key->priv_key, key->group); +} + +const BIGNUM *EC_KEY_get_priv_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_generate_key() {} -- Gitee From 5a01fac706abde825c4d671497c651a3eeb59155 Mon Sep 17 00:00:00 2001 From: wangxiaoxi1 Date: Fri, 30 Sep 2022 12:57:20 +0000 Subject: [PATCH 18/18] enclave_ZUC Signed-off-by: wangxiaoxi1 --- .../Informal/enclave_ZUC/CMakeLists.txt" | 38 ++ .../enclave_ZUC/enclave/CMakeLists.txt" | 162 ++++++ .../enclave_ZUC/enclave/Enclave.config.xml" | 12 + .../Informal/enclave_ZUC/enclave/Enclave.lds" | 11 + .../enclave_ZUC/enclave/enclave_ZUC.c" | 3 + .../enclave_ZUC/enclave/manifest.txt.in" | 8 + .../enclave/rsa_public_key_cloud.pem" | 11 + .../Informal/enclave_ZUC/enclave/zuc.h" | 314 ++++++++++ .../Informal/enclave_ZUC/enclave/zuctest1.c" | 58 ++ .../Informal/enclave_ZUC/enclave/zuctest2.c" | 78 +++ .../Informal/enclave_ZUC/enclave/zuctest3.c" | 81 +++ .../Informal/enclave_ZUC/enclave_ZUC.edl" | 27 + .../Informal/enclave_ZUC/host/CMakeLists.txt" | 88 +++ .../Informal/enclave_ZUC/host/main.cpp" | 27 + .../enclave_ZUC/include/common_utils.h" | 69 +++ .../Informal/enclave_ZUC/include/ec.h" | 545 ++++++++++++++++++ 16 files changed, 1532 insertions(+) create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.config.xml" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.lds" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/enclave_ZUC.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/manifest.txt.in" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuc.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest1.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest2.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest3.c" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave_ZUC.edl" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/CMakeLists.txt" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/main.cpp" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/common_utils.h" create mode 100644 "summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/ec.h" diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/CMakeLists.txt" new file mode 100644 index 0000000..e1b266d --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/CMakeLists.txt" @@ -0,0 +1,38 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +project(enclave_ZUC) + +set(CMAKE_C_STANDARD 99) + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE enclave_ZUC.edl) +#set(LOCAL_ROOT_PATH "$ENV{CC_SDK}") +#set(SECGEAR_INSTALL_PATH /usr/lib64/) + +if(CC_GP) + set(CODETYPE trustzone) + set(CODEGEN codegen_arm64) + execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) + string(REPLACE "\n" "" UUID ${UUID}) + add_definitions(-DPATH="/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + set(CODEGEN codegen_x86_64) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/CMakeLists.txt" new file mode 100644 index 0000000..d600d38 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/CMakeLists.txt" @@ -0,0 +1,162 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_ZUC) + +set(CMAKE_C_STANDARD 99) +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave_ZUC.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + #set itrustee device key + set(DEVICEPEM ${CMAKE_CURRENT_SOURCE_DIR}/rsa_public_key_cloud.pem) + #set whilelist. default: /vendor/bin/teec_hello + set(WHITE_LIST_0 /vendor/bin/enclave_ZUC) + set(WHITE_LIST_OWNER root) + set(WHITE_LIST_1 /vendor/bin/secgear_enclave_ZUC) + set(WHITELIST WHITE_LIST_0 WHITE_LIST_1) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(COMMON_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \ + -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") +set(COMMON_CXX_FLAGS "${COMMON_C_FLAGS}") + +if(CC_GP) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt") + + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/enclave_inc + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${SECGEAR_INSTALL_PATH}) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -lsecgear_tee) + + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i /home/sunny/secGear/debug/lib/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT} + DESTINATION /data + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -O2 -nostdinc++") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE + ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.config.xml" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.config.xml" new file mode 100644 index 0000000..a5e05e0 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.config.xml" @@ -0,0 +1,12 @@ + + 0 + 0 + 0x100000 + 0x80000 + 10 + 1 + + 1 + 0 + 0xFFFFFFFF + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.lds" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.lds" new file mode 100644 index 0000000..ab77e64 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/Enclave.lds" @@ -0,0 +1,11 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/enclave_ZUC.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/enclave_ZUC.c" new file mode 100644 index 0000000..01cc67a --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/enclave_ZUC.c" @@ -0,0 +1,3 @@ +#include "Enclave1_t.h" +#include +#include "zuc.h" \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/manifest.txt.in" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/manifest.txt.in" new file mode 100644 index 0000000..7b8ecf5 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/manifest.txt.in" @@ -0,0 +1,8 @@ +gpd.ta.appID: @UUID@ +gpd.ta.service_name: test0108 +gpd.ta.singleInstance: true +gpd.ta.multiSession: false +gpd.ta.multiCommand: false +gpd.ta.instanceKeepAlive: false +gpd.ta.dataSize: 16384 +gpd.ta.stackSize: 20480 diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" new file mode 100644 index 0000000..a321f63 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/rsa_public_key_cloud.pem" @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzAPwbnbgBg7JgXERA9Bx +p7GLI1S3e1zL83RMd2+GXb6kO4yMKUL3NUCE2HhA2BtQYmLyGovx59UUcKnU58is +Xux++kH+A2shmOPjYvEFuX0Kt8tc19b8M9b/iHsY8ZmKykqia2a5U+IrECRFJo5p +DWUnl7jrHVtq78BSR1c7iXG1frrEC0AYCuqKJo/fxfmOKL0Y9mENCB3nAwjn9unD +BsO/OhkqvvB3nkeuMfNKPh4wCqtQPve13eTojbuxjX/3ePijplTI5X2Gr+n6Ximn +fYRlytQmMgMl/db0ARSKNApq9bmwzVNrnGWWZWJksdRvf6iL7t17Gs4L9AApOuC9 +WkzxPvwp5ZUqjsGd4oJGWeC6ZE6BTw2vxE+xMFI9uAKHxq9pBKkcGMa0g4fANNNV ++W+8JZGanxEXKB3y/M7BCyQAPCWOHC/RNjmRA1gczLYCPzC4pWu935UZdF1RR6zY +CD3t+FoOGGET/g4CwWgyhb5qkp65Hs6ayYt/DUAqo+yBAgMBAAE= +-----END PUBLIC KEY----- diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuc.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuc.h" new file mode 100644 index 0000000..d8ea3ea --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuc.h" @@ -0,0 +1,314 @@ +#ifndef SECGEAR_ZUC_H +#define SECGEAR_ZUC_H + +#include +#include "../include/common_utils.h" + +/* S_BOX BEGIN */ + +const uint8 ZUC_S[2][256] = { + { + 0x3E, 0x72, 0x5B, 0x47, 0xCA, 0xE0, 0x00, 0x33, 0x04, 0xD1, 0x54, 0x98, 0x09, 0xB9, 0x6D, 0xCB, + 0x7B, 0x1B, 0xF9, 0x32, 0xAF, 0x9D, 0x6A, 0xA5, 0xB8, 0x2D, 0xFC, 0x1D, 0x08, 0x53, 0x03, 0x90, + 0x4D, 0x4E, 0x84, 0x99, 0xE4, 0xCE, 0xD9, 0x91, 0xDD, 0xB6, 0x85, 0x48, 0x8B, 0x29, 0x6E, 0xAC, + 0xCD, 0xC1, 0xF8, 0x1E, 0x73, 0x43, 0x69, 0xC6, 0xB5, 0xBD, 0xFD, 0x39, 0x63, 0x20, 0xD4, 0x38, + 0x76, 0x7D, 0xB2, 0xA7, 0xCF, 0xED, 0x57, 0xC5, 0xF3, 0x2C, 0xBB, 0x14, 0x21, 0x06, 0x55, 0x9B, + 0xE3, 0xEF, 0x5E, 0x31, 0x4F, 0x7F, 0x5A, 0xA4, 0x0D, 0x82, 0x51, 0x49, 0x5F, 0xBA, 0x58, 0x1C, + 0x4A, 0x16, 0xD5, 0x17, 0xA8, 0x92, 0x24, 0x1F, 0x8C, 0xFF, 0xD8, 0xAE, 0x2E, 0x01, 0xD3, 0xAD, + 0x3B, 0x4B, 0xDA, 0x46, 0xEB, 0xC9, 0xDE, 0x9A, 0x8F, 0x87, 0xD7, 0x3A, 0x80, 0x6F, 0x2F, 0xC8, + 0xB1, 0xB4, 0x37, 0xF7, 0x0A, 0x22, 0x13, 0x28, 0x7C, 0xCC, 0x3C, 0x89, 0xC7, 0xC3, 0x96, 0x56, + 0x07, 0xBF, 0x7E, 0xF0, 0x0B, 0x2B, 0x97, 0x52, 0x35, 0x41, 0x79, 0x61, 0xA6, 0x4C, 0x10, 0xFE, + 0xBC, 0x26, 0x95, 0x88, 0x8A, 0xB0, 0xA3, 0xFB, 0xC0, 0x18, 0x94, 0xF2, 0xE1, 0xE5, 0xE9, 0x5D, + 0xD0, 0xDC, 0x11, 0x66, 0x64, 0x5C, 0xEC, 0x59, 0x42, 0x75, 0x12, 0xF5, 0x74, 0x9C, 0xAA, 0x23, + 0x0E, 0x86, 0xAB, 0xBE, 0x2A, 0x02, 0xE7, 0x67, 0xE6, 0x44, 0xA2, 0x6C, 0xC2, 0x93, 0x9F, 0xF1, + 0xF6, 0xFA, 0x36, 0xD2, 0x50, 0x68, 0x9E, 0x62, 0x71, 0x15, 0x3D, 0xD6, 0x40, 0xC4, 0xE2, 0x0F, + 0x8E, 0x83, 0x77, 0x6B, 0x25, 0x05, 0x3F, 0x0C, 0x30, 0xEA, 0x70, 0xB7, 0xA1, 0xE8, 0xA9, 0x65, + 0x8D, 0x27, 0x1A, 0xDB, 0x81, 0xB3, 0xA0, 0xF4, 0x45, 0x7A, 0x19, 0xDF, 0xEE, 0x78, 0x34, 0x60, + }, + { + 0x55, 0xC2, 0x63, 0x71, 0x3B, 0xC8, 0x47, 0x86, 0x9F, 0x3C, 0xDA, 0x5B, 0x29, 0xAA, 0xFD, 0x77, + 0x8C, 0xC5, 0x94, 0x0C, 0xA6, 0x1A, 0x13, 0x00, 0xE3, 0xA8, 0x16, 0x72, 0x40, 0xF9, 0xF8, 0x42, + 0x44, 0x26, 0x68, 0x96, 0x81, 0xD9, 0x45, 0x3E, 0x10, 0x76, 0xC6, 0xA7, 0x8B, 0x39, 0x43, 0xE1, + 0x3A, 0xB5, 0x56, 0x2A, 0xC0, 0x6D, 0xB3, 0x05, 0x22, 0x66, 0xBF, 0xDC, 0x0B, 0xFA, 0x62, 0x48, + 0xDD, 0x20, 0x11, 0x06, 0x36, 0xC9, 0xC1, 0xCF, 0xF6, 0x27, 0x52, 0xBB, 0x69, 0xF5, 0xD4, 0x87, + 0x7F, 0x84, 0x4C, 0xD2, 0x9C, 0x57, 0xA4, 0xBC, 0x4F, 0x9A, 0xDF, 0xFE, 0xD6, 0x8D, 0x7A, 0xEB, + 0x2B, 0x53, 0xD8, 0x5C, 0xA1, 0x14, 0x17, 0xFB, 0x23, 0xD5, 0x7D, 0x30, 0x67, 0x73, 0x08, 0x09, + 0xEE, 0xB7, 0x70, 0x3F, 0x61, 0xB2, 0x19, 0x8E, 0x4E, 0xE5, 0x4B, 0x93, 0x8F, 0x5D, 0xDB, 0xA9, + 0xAD, 0xF1, 0xAE, 0x2E, 0xCB, 0x0D, 0xFC, 0xF4, 0x2D, 0x46, 0x6E, 0x1D, 0x97, 0xE8, 0xD1, 0xE9, + 0x4D, 0x37, 0xA5, 0x75, 0x5E, 0x83, 0x9E, 0xAB, 0x82, 0x9D, 0xB9, 0x1C, 0xE0, 0xCD, 0x49, 0x89, + 0x01, 0xB6, 0xBD, 0x58, 0x24, 0xA2, 0x5F, 0x38, 0x78, 0x99, 0x15, 0x90, 0x50, 0xB8, 0x95, 0xE4, + 0xD0, 0x91, 0xC7, 0xCE, 0xED, 0x0F, 0xB4, 0x6F, 0xA0, 0xCC, 0xF0, 0x02, 0x4A, 0x79, 0xC3, 0xDE, + 0xA3, 0xEF, 0xEA, 0x51, 0xE6, 0x6B, 0x18, 0xEC, 0x1B, 0x2C, 0x80, 0xF7, 0x74, 0xE7, 0xFF, 0x21, + 0x5A, 0x6A, 0x54, 0x1E, 0x41, 0x31, 0x92, 0x35, 0xC4, 0x33, 0x07, 0x0A, 0xBA, 0x7E, 0x0E, 0x34, + 0x88, 0xB1, 0x98, 0x7C, 0xF3, 0x3D, 0x60, 0x6C, 0x7B, 0xCA, 0xD3, 0x1F, 0x32, 0x65, 0x04, 0x28, + 0x64, 0xBE, 0x85, 0x9B, 0x2F, 0x59, 0x8A, 0xD7, 0xB0, 0x25, 0xAC, 0xAF, 0x12, 0x03, 0xE2, 0xF2, + }, +}; + +const uint16 ZUC_D[16] = { + 042327, 023274, 061153, 011536, + 053611, 032742, 070465, 004657, + 046570, 027423, 065704, 015361, + 057046, 036115, 074232, 043654, +}; + +#define ZUC_S0(x) ZUC_S[0][x] +#define ZUC_S1(x) ZUC_S[1][x] +#define ZUC_S_BOX(X) \ + CONCAT_8x4( \ + ZUC_S0(EXTRACT_8_32(X, 0)), \ + ZUC_S1(EXTRACT_8_32(X, 1)), \ + ZUC_S0(EXTRACT_8_32(X, 2)), \ + ZUC_S1(EXTRACT_8_32(X, 3)) \ + ) + +/* S_BOX END */ + +/* MOD_OPERATIONS BEGIN */ + +#define ZUC_MOD_NUM 0x7FFFFFFF +uint32 zuc_add(uint32 a, uint32 b) { + uint32 c = a + b; + return (c & ZUC_MOD_NUM) + (c >> 31); +} +uint32 zuc_mul(uint32 a, uint32 b) { + uint32 res = 0; + for (int i = 0; i < 31; ++i) { + if (b & (1 << i)) { + res = zuc_add(res, ROTATE_31(a, i)); + } + } + return res; +} +uint32 zuc_mul_powof2(uint32 a, uint32 log2b) { + return ROTATE_31(a, log2b); +} + +/* MOD_OPERATIONS END */ + +/* LFSR BEGIN */ + +typedef struct ZUC_LFSR_st { + uint32 S[16]; /* 31-bit */ +} ZUC_LFSR; + +void zuc_lfsr_init(ZUC_LFSR *lfsr, uint32 u) { /* u: 31-bit */ + uint32 v = zuc_add( + zuc_add( + zuc_add( + zuc_mul_powof2(lfsr->S[15], 15), + zuc_mul_powof2(lfsr->S[13], 17) + ), + zuc_add( + zuc_mul_powof2(lfsr->S[10], 21), + zuc_mul_powof2(lfsr->S[4], 20) + ) + ), + zuc_add(lfsr->S[0], zuc_mul_powof2(lfsr->S[0], 8)) + ); + uint32 S16 = zuc_add(v, u); + S16 = zuc_add(S16, ZUC_MOD_NUM); + for (int i = 0; i < 15; ++i) { + lfsr->S[i] = lfsr->S[i + 1]; + } + lfsr->S[15] = S16; +} +void zuc_lfsr_work(ZUC_LFSR *lfsr) { + uint32 S16 = zuc_add( + zuc_add( + zuc_add( + zuc_mul_powof2(lfsr->S[15], 15), + zuc_mul_powof2(lfsr->S[13], 17) + ), + zuc_add( + zuc_mul_powof2(lfsr->S[10], 21), + zuc_mul_powof2(lfsr->S[4], 20) + ) + ), + zuc_add(lfsr->S[0], zuc_mul_powof2(lfsr->S[0], 8)) + ); + S16 = zuc_add(S16, ZUC_MOD_NUM); + for (int i = 0; i < 15; ++i) { + lfsr->S[i] = lfsr->S[i + 1]; + } + lfsr->S[15] = S16; +} + +/* LFSR END */ + +/* BR BEGIN */ + +typedef struct ZUC_BR_st { + uint32 X[4]; /* 32-bit */ +} ZUC_BR_CTX; + +void zuc_br(ZUC_BR_CTX *br, ZUC_LFSR *lfsr) { + br->X[0] = CONCAT_16x2(EXTRACT_16H_31(lfsr->S[15]), EXTRACT_16L_31(lfsr->S[14])); + br->X[1] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[11]), EXTRACT_16H_31(lfsr->S[9])); + br->X[2] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[7]), EXTRACT_16H_31(lfsr->S[5])); + br->X[3] = CONCAT_16x2(EXTRACT_16L_31(lfsr->S[2]), EXTRACT_16H_31(lfsr->S[0])); +} + +/* BR END */ + +/* F BEGIN */ + +#define ZUC_L1(X) \ + ((X) ^ ROTATE((X), 2) ^ ROTATE((X), 10) ^ ROTATE((X), 18) ^ ROTATE((X), 24)) +#define ZUC_L2(X) \ + ((X) ^ ROTATE((X), 8) ^ ROTATE((X), 14) ^ ROTATE((X), 22) ^ ROTATE((X), 30)) + +typedef struct ZUC_F_st { + uint32 R1, R2; /* 32-bit */ +} ZUC_F_CTX; + +uint32 zuc_f(ZUC_F_CTX *f, ZUC_BR_CTX *br) { /* X: 32-bit */ + uint32 X0 = br->X[0], X1 = br->X[1], X2 = br->X[2]; + uint32 R1 = f->R1, R2 = f->R2; + uint32 W = (X0 ^ R1) + R2; + uint32 W1 = R1 + X1; + uint32 W2 = R2 ^ X2; + R1 = ZUC_S_BOX(ZUC_L1(CONCAT_16x2( + EXTRACT_16_32(W1, 1), + EXTRACT_16_32(W2, 0) + ))); + R2 = ZUC_S_BOX(ZUC_L2(CONCAT_16x2( + EXTRACT_16_32(W2, 1), + EXTRACT_16_32(W1, 0) + ))); + f->R1 = R1; + f->R2 = R2; + return W; +} + +/* F END */ + +/* ZUC_MAIN BEGIN */ + +#define ZUC_INIT_CONCAT(k, d, iv) (((uint32)(k) << 15 | (d)) << 8 | (iv)) +#define ZUC_INTEGRITY_CONCAT(K1, K2, offset) \ + (((K1) << (offset)) | ((offset) ? (K2) >> (32 - (offset)) : 0)) + +typedef struct ZUCstate_st { + ZUC_LFSR lfsr; + ZUC_BR_CTX br; + ZUC_F_CTX f; +} ZUC_CTX; + +/* Initiate phase. Both k and iv are uint8 arrays of length 16. */ +int zuc_init(ZUC_CTX *z, uint8 k[], uint8 iv[]) { + memset(z, 0, sizeof(*z)); + for (int i = 0; i < 16; ++i) { + z->lfsr.S[i] = ZUC_INIT_CONCAT(k[i], ZUC_D[i], iv[i]); + } + for (int i = 0; i < 32; ++i) { + zuc_br(&z->br, &z->lfsr); + uint32 W = zuc_f(&z->f, &z->br); + zuc_lfsr_init(&z->lfsr, W >> 1); + } + return 1; +} + +/* Work phase. Z is uint32 array that stores output keys. */ +/* len is the length of the key in the unit of 32-bit. */ +int zuc_work(ZUC_CTX *z, uint32 Z[], size_t len) { + zuc_br(&z->br, &z->lfsr); + (void)zuc_f(&z->f, &z->br); + zuc_lfsr_work(&z->lfsr); + for (size_t i = 0; i < len; ++i) { + zuc_br(&z->br, &z->lfsr); + Z[i] = zuc_f(&z->f, &z->br) ^ z->br.X[3]; + zuc_lfsr_work(&z->lfsr); + } + return 1; +} + +/* Generate 32-bit ZUC key stream. Use the array Z[] to receive the output. */ +int zuc_final(uint8 k[], uint8 iv[], uint32 Z[], size_t len) { + ZUC_CTX res, *z; + z = &res; + zuc_init(z, k, iv); + zuc_work(z, Z, len); + return 1; +} + +/* Use the array obs[] to receive the output. */ +int zuc_confidentiality(uint32 count, uint8 bearer, uint8 direction, uint8 ck[], + uint32 length, uint32 ibs[], uint32 obs[]) { + /* + * @param COUNT (length = 32b, counter) + * @param BEARER (length = 5b, bearer identifier) + * @param DIRECTION (length = 1b, direction identifier) + * @param CK (length = 128b = 8b * 16, confidential key) + * @param LENGTH (length = 32b, bit length of input bit stream) + * @param IBS (length = LENGTH b = 32b * L, input bit stream) + * @param OBS (length = LENGTH b = 32b * L, output bit stream) + */ + + /* Initiate k and iv for ZUC. */ + bearer &= 0x1F; direction &= 1; + uint8 _k[16], _iv[16], _count[4]; + memcpy(_k, ck, sizeof _k); + for (int i = 0; i < 4; ++i) { + _count[i] = EXTRACT_8_32(count, i); + } + _iv[0] = _count[0]; _iv[1] = _count[1]; _iv[2] = _count[2]; _iv[3] = _count[3]; + _iv[4] = (uint8)((bearer << 1 | direction) << 2); _iv[5] = _iv[6] = _iv[7] = 0; + for (int i = 8; i < 16; ++i) { + _iv[i] = _iv[i ^ 8]; + } + size_t L = (length >> 5) + ((length & 0x1F) ? 1 : 0); + uint32 Z[L]; + zuc_final(_k, _iv, Z, L); + for (size_t i = 0; i < L; ++i) { + obs[i] = ibs[i] ^ Z[i]; + } + if (length & 0x1F) { + obs[L - 1] &= PREFIX_MASK_32[length & 0x1F]; + } + return 1; +} + +uint32 zuc_integrity(uint32 count, uint8 bearer, uint8 direction, uint8 ik[], + uint32 length, uint32 M[]) { + /* + * @param COUNT (length = 32b, counter) + * @param BEARER (length = 5b, bearer identifier) + * @param DIRECTION (length = 1b, direction identifier) + * @param IK (length = 128b = 8b * 16, integrity key) + * @param LENGTH (length = 32b, bit length of input bit stream) + * @param M (length = LENGTH b = 32b * L, input massage stream) + * @return MAC (length = 32b, massage verification code) + */ + + /* Initiate k and iv for ZUC. */ + bearer &= 0x1F; direction &= 1; + uint8 _k[16], _iv[16], _count[4]; + memcpy(_k, ik, sizeof _k); + for (int i = 0; i < 4; ++i) { + _count[i] = EXTRACT_8_32(count, i); + } + _iv[0] = _count[0]; _iv[1] = _count[1]; _iv[2] = _count[2]; _iv[3] = _count[3]; + _iv[4] = (uint8)(bearer << 3); _iv[5] = _iv[6] = _iv[7] = 0; + _iv[8] = _iv[0] ^ (uint8)(direction << 7); + _iv[9] = _iv[1]; _iv[10] = _iv[2]; _iv[11] = _iv[3]; + _iv[12] = _iv[4]; _iv[13] = _iv[5]; + _iv[14] = _iv[6] ^ (uint8)(direction << 7); + _iv[15] = _iv[7]; + size_t L = (length >> 5) + ((length & 0x1F) ? 1 : 0) + 2; + uint32 Z[L]; + uint32 T = 0; + zuc_final(_k, _iv, Z, L); + for (size_t i = 0; i < length; ++i) { + if (GET_BIT_VALUE_32(M[i >> 5], i & 0x1F)) { + T = T ^ ZUC_INTEGRITY_CONCAT(Z[i >> 5], Z[(i >> 5) + 1], i & 0x1F); + } + } + T = T ^ ZUC_INTEGRITY_CONCAT(Z[length >> 5], Z[(length >> 5) + 1], length & 0x1F); + T = T ^ Z[L - 1]; + return T; +} + +/* ZUC_MAIN END */ + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest1.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest1.c" new file mode 100644 index 0000000..c1cb8eb --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest1.c" @@ -0,0 +1,58 @@ +#define SECGEAR_ZUC_DEBUG +#include +#include "zuc.h" + +uint8 k_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +uint8 iv_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +uint8 k_test2[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; +uint8 iv_test2[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; + +uint8 k_test3[16] = { + 0x3D, 0x4C, 0x4B, 0xE9, + 0x6A, 0x82, 0xFD, 0xAE, + 0xB5, 0x8F, 0x64, 0x1D, + 0xB1, 0x7B, 0x45, 0x5B, +}; +uint8 iv_test3[16] = { + 0x84, 0x31, 0x9A, 0xA8, + 0xDE, 0x69, 0x15, 0xCA, + 0x1F, 0x6B, 0xDA, 0x6B, + 0xFB, 0xD8, 0xC7, 0x66, +}; + +void zuc_test(uint8 k[], uint8 iv[]) { + const size_t LEN = 32; + uint32 keys[LEN]; + zuc_final(k, iv, keys, LEN); +} + +int main(){ + printf("Test 1: \n"); + zuc_test(k_test1, iv_test1); + printf("Test 2: \n"); + zuc_test(k_test2, iv_test2); + printf("Test 3: \n"); + zuc_test(k_test3, iv_test3); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest2.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest2.c" new file mode 100644 index 0000000..2db8404 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest2.c" @@ -0,0 +1,78 @@ +#define SECGEAR_ZUC_DEBUG_2 +#include +#include "zuc.h" + +uint8 ck_test1[16] = { + 0x17, 0x3d, 0x14, 0xba, + 0x50, 0x03, 0x73, 0x1d, + 0x7a, 0x60, 0x04, 0x94, + 0x70, 0xf0, 0x0a, 0x29, +}; +uint32 count_test1 = 0x66035492; +uint8 bearer_test1 = 0xf; +uint8 dirc_test1 = 0x0; +uint32 len_test1 = 0xc1; +uint32 ibs_test1[] = { + 0x6cf65340, 0x735552ab, 0x0c9752fa, 0x6f9025fe, 0x0bd675d9, + 0x005875b2, 0x00000000, +}; + +uint8 ck_test2[16] = { + 0xe5, 0xbd, 0x3e, 0xa0, + 0xeb, 0x55, 0xad, 0xe8, + 0x66, 0xc6, 0xac, 0x58, + 0xbd, 0x54, 0x30, 0x2a, +}; +uint32 count_test2 = 0x56823; +uint8 bearer_test2 = 0x18; +uint8 dirc_test2 = 0x1; +uint32 len_test2 = 0x320; +uint32 ibs_test2[] = { + 0x14a8ef69, 0x3d678507, 0xbbe7270a, 0x7f67ff50, 0x06c3525b, + 0x9807e467, 0xc4e56000, 0xba338f5d, 0x42955903, 0x67518222, + 0x46c80d3b, 0x38f07f4b, 0xe2d8ff58, 0x05f51322, 0x29bde93b, + 0xbbdcaf38, 0x2bf1ee97, 0x3fbf9977, 0xbada8945, 0x847a2a6c, + 0x9ad34a66, 0x7554e04d, 0x1f7fa2c3, 0x3241bd8f, 0x01ba220d, +}; + +uint8 ck_test3[16] = { + 0xe1, 0x3f, 0xed, 0x21, + 0xb4, 0x6e, 0x4e, 0x7e, + 0xc3, 0x12, 0x53, 0xb2, + 0xbb, 0x17, 0xb3, 0xe0, +}; +uint32 count_test3 = 0x2738cdaa; +uint8 bearer_test3 = 0x1a; +uint8 dirc_test3 = 0x0; +uint32 len_test3 = 0xfb3; +uint32 ibs_test3[] = { + 0x8d74e20d, 0x54894e06, 0xd3cb13cb, 0x3933065e, 0x8674be62, 0xadb1c72b, 0x3a646965, 0xab63cb7b, 0x7854dfdc, 0x27e84929, + 0xf49c64b8, 0x72a490b1, 0x3f957b64, 0x827e71f4, 0x1fbd4269, 0xa42c97f8, 0x24537027, 0xf86e9f4a, 0xd82d1df4, 0x51690fdd, + 0x98b6d03f, 0x3a0ebe3a, 0x312d6b84, 0x0ba5a182, 0x0b2a2c97, 0x09c090d2, 0x45ed267c, 0xf845ae41, 0xfa975d33, 0x33ac3009, + 0xfd40eba9, 0xeb5b8857, 0x14b768b6, 0x97138baf, 0x21380eca, 0x49f644d4, 0x8689e421, 0x5760b906, 0x739f0d2b, 0x3f091133, + 0xca15d981, 0xcbe401ba, 0xf72d05ac, 0xe05cccb2, 0xd297f4ef, 0x6a5f58d9, 0x1246cfa7, 0x7215b892, 0xab441d52, 0x78452795, + 0xccb7f5d7, 0x9057a1c4, 0xf77f80d4, 0x6db2033c, 0xb79bedf8, 0xe60551ce, 0x10c667f6, 0x2a97abaf, 0xabbcd677, 0x2018df96, + 0xa282ea73, 0x7ce2cb33, 0x1211f60d, 0x5354ce78, 0xf9918d9c, 0x206ca042, 0xc9b62387, 0xdd709604, 0xa50af16d, 0x8d35a890, + 0x6be484cf, 0x2e74a928, 0x99403643, 0x53249b27, 0xb4c9ae29, 0xeddfc7da, 0x6418791a, 0x4e7baa06, 0x60fa6451, 0x1f2d685c, + 0xc3a5ff70, 0xe0d2b742, 0x92e3b8a0, 0xcd6b04b1, 0xc790b8ea, 0xd2703708, 0x540dea2f, 0xc09c3da7, 0x70f65449, 0xe84d817a, + 0x4f551055, 0xe19ab850, 0x18a0028b, 0x71a144d9, 0x6791e9a3, 0x57793350, 0x4eee0060, 0x340c69d2, 0x74e1bf9d, 0x805dcbcc, + 0x1a6faa97, 0x6800b6ff, 0x2b671dc4, 0x63652fa8, 0xa33ee509, 0x74c1c21b, 0xe01eabb2, 0x16743026, 0x9d72ee51, 0x1c9dde30, + 0x797c9a25, 0xd86ce74f, 0x5b961be5, 0xfdfb6807, 0x814039e7, 0x137636bd, 0x1d7fa9e0, 0x9efd2007, 0x505906a5, 0xac45dfde, + 0xed7757bb, 0xee745749, 0xc2963335, 0x0bee0ea6, 0xf409df45, 0x80160000, +}; + +void zuc_test2(uint32 count, uint8 bearer, uint8 direction, uint8 ck[], + uint32 length, uint32 ibs[], uint32 obs[]) { + zuc_confidentiality(count, bearer, direction, ck, length, ibs, obs); +} + +int main(){ + uint32 obs_test[130]; + printf("Test 1: \n"); + zuc_test2(count_test1, bearer_test1, dirc_test1, ck_test1, len_test1, ibs_test1, obs_test); + printf("Test 2: \n"); + zuc_test2(count_test2, bearer_test2, dirc_test2, ck_test2, len_test2, ibs_test2, obs_test); + printf("Test 3: \n"); + zuc_test2(count_test3, bearer_test3, dirc_test3, ck_test3, len_test3, ibs_test3, obs_test); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest3.c" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest3.c" new file mode 100644 index 0000000..7a09e8c --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave/zuctest3.c" @@ -0,0 +1,81 @@ +#define SECGEAR_ZUC_DEBUG_3 +#include +#include "zuc.h" + +uint8 ik_test1[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +uint32 count_test1 = 0; +uint8 bearer_test1 = 0; +uint8 dirc_test1 = 0; +uint32 len_test1 = 1; +uint32 m_test1[] = { + 0x00000000, +}; + +uint8 ik_test2[16] = { + 0xc9, 0xe6, 0xce, 0xc4, + 0x60, 0x7c, 0x72, 0xdb, + 0x00, 0x0a, 0xef, 0xa8, + 0x83, 0x85, 0xab, 0x0a, +}; +uint32 count_test2 = 0xa94059da; +uint8 bearer_test2 = 0xa; +uint8 dirc_test2 = 0x1; +uint32 len_test2 = 0x241; +uint32 m_test2[] = { + 0x983b41d4, 0x7d780c9e, 0x1ad11d7e, 0xb70391b1, 0xde0b35da, 0x2dc62f83, 0xe7b78d63, 0x06ca0ea0, 0x7e941b7b, + 0xe91348f9, 0xfcb170e2, 0x217fecd9, 0x7f9f68ad, 0xb16e5d7d, 0x21e569d2, 0x80ed775c, 0xebde3f40, 0x93c53881, + 0x00000000, +}; + +uint8 ik_test3[16] = { + 0x6b, 0x8b, 0x08, 0xee, + 0x79, 0xe0, 0xb5, 0x98, + 0x2d, 0x6d, 0x12, 0x8e, + 0xa9, 0xf2, 0x20, 0xcb, +}; +uint32 count_test3 = 0x561eb2dd; +uint8 bearer_test3 = 0x1c; +uint8 dirc_test3 = 0x0; +uint32 len_test3 = 0x1626; +uint32 m_test3[] = { + 0x5bad7247, 0x10ba1c56, 0xd5a315f8, 0xd40f6e09, 0x3780be8e, 0x8de07b69, 0x92432018, 0xe08ed96a, 0x5734af8b, + 0xad8a575d, 0x3a1f162f, 0x85045cc7, 0x70925571, 0xd9f5b94e, 0x454a77c1, 0x6e72936b, 0xf016ae15, 0x7499f054, + 0x3b5d52ca, 0xa6dbeab6, 0x97d2bb73, 0xe41b8075, 0xdce79b4b, 0x86044f66, 0x1d4485a5, 0x43dd7860, 0x6e0419e8, + 0x059859d3, 0xcb2b67ce, 0x0977603f, 0x81ff839e, 0x33185954, 0x4cfbc8d0, 0x0fef1a4c, 0x8510fb54, 0x7d6b06c6, + 0x11ef44f1, 0xbce107cf, 0xa45a06aa, 0xb360152b, 0x28dc1ebe, 0x6f7fe09b, 0x0516f9a5, 0xb02a1bd8, 0x4bb0181e, + 0x2e89e19b, 0xd8125930, 0xd178682f, 0x3862dc51, 0xb636f04e, 0x720c47c3, 0xce51ad70, 0xd94b9b22, 0x55fbae90, + 0x6549f499, 0xf8c6d399, 0x47ed5e5d, 0xf8e2def1, 0x13253e7b, 0x08d0a76b, 0x6bfc68c8, 0x12f375c7, 0x9b8fe5fd, + 0x85976aa6, 0xd46b4a23, 0x39d8ae51, 0x47f680fb, 0xe70f978b, 0x38effd7b, 0x2f7866a2, 0x2554e193, 0xa94e98a6, + 0x8b74bd25, 0xbb2b3f5f, 0xb0a5fd59, 0x887f9ab6, 0x8159b717, 0x8d5b7b67, 0x7cb546bf, 0x41eadca2, 0x16fc1085, + 0x0128f8bd, 0xef5c8d89, 0xf96afa4f, 0xa8b54885, 0x565ed838, 0xa950fee5, 0xf1c3b0a4, 0xf6fb71e5, 0x4dfd169e, + 0x82cecc72, 0x66c850e6, 0x7c5ef0ba, 0x960f5214, 0x060e71eb, 0x172a75fc, 0x1486835c, 0xbea65344, 0x65b055c9, + 0x6a72e410, 0x52241823, 0x25d83041, 0x4b40214d, 0xaa8091d2, 0xe0fb010a, 0xe15c6de9, 0x0850973b, 0xdf1e423b, + 0xe148a237, 0xb87a0c9f, 0x34d4b476, 0x05b803d7, 0x43a86a90, 0x399a4af3, 0x96d3a120, 0x0a62f3d9, 0x507962e8, + 0xe5bee6d3, 0xda2bb3f7, 0x237664ac, 0x7a292823, 0x900bc635, 0x03b29e80, 0xd63f6067, 0xbf8e1716, 0xac25beba, + 0x350deb62, 0xa99fe031, 0x85eb4f69, 0x937ecd38, 0x7941fda5, 0x44ba67db, 0x09117749, 0x38b01827, 0xbcc69c92, + 0xb3f772a9, 0xd2859ef0, 0x03398b1f, 0x6bbad7b5, 0x74f7989a, 0x1d10b2df, 0x798e0dbf, 0x30d65874, 0x64d24878, + 0xcd00c0ea, 0xee8a1a0c, 0xc753a279, 0x79e11b41, 0xdb1de3d5, 0x038afaf4, 0x9f5c682c, 0x3748d8a3, 0xa9ec54e6, + 0xa371275f, 0x1683510f, 0x8e4f9093, 0x8f9ab6e1, 0x34c2cfdf, 0x4841cba8, 0x8e0cff2b, 0x0bcc8e6a, 0xdcb71109, + 0xb5198fec, 0xf1bb7e5c, 0x531aca50, 0xa56a8a3b, 0x6de59862, 0xd41fa113, 0xd9cd9578, 0x08f08571, 0xd9a4bb79, + 0x2af271f6, 0xcc6dbb8d, 0xc7ec36e3, 0x6be1ed30, 0x8164c31c, 0x7c0afc54, 0x1c000000, +}; + +uint32 zuc_test3(uint32 count, uint8 bearer, uint8 direction, uint8 ik[], + uint32 length, uint32 M[]) { + return zuc_integrity(count, bearer, direction, ik, length, M); +} + +int main(){ + printf("Test 1: \n"); + zuc_test3(count_test1, bearer_test1, dirc_test1, ik_test1, len_test1, m_test1); + printf("Test 2: \n"); + zuc_test3(count_test2, bearer_test2, dirc_test2, ik_test2, len_test2, m_test2); + printf("Test 3: \n"); + zuc_test3(count_test3, bearer_test3, dirc_test3, ik_test3, len_test3, m_test3); + return 0; +} \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave_ZUC.edl" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave_ZUC.edl" new file mode 100644 index 0000000..0e454ee --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/enclave_ZUC.edl" @@ -0,0 +1,27 @@ +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + + trusted { + public void setRSAsource([in, size=len] char* src, size_t len); + public void getRSAresult([out, size=len] char* buf, size_t len); + public void calcEmbeddingResult(); + public void initKeys([in] uint32_t *src); + public void registerSeed([in] uint32_t *src); + public void setKeys([in,count=2] uint32_t *K); + public void getKeys([out,count=2] uint32_t *K); + public void setD([in, size=len] char* src, size_t len); + public void setCD([in, size=len] char* src, size_t len); + public void setN([in, size=len] char* src, size_t len); + public void getCD([out, size=len] char* buf, size_t len); + public void getX([out, size=len] char* buf, size_t len); + public void getMu([out, size=len] char* buf, size_t len); + public void getK([out, size=len] char* buf, size_t len); + public void getNWID([out, size=len] char* buf, size_t len); + public void setNPW([in, size=len] char* src, size_t len); + }; + + untrusted { + + }; +}; diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/CMakeLists.txt" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/CMakeLists.txt" new file mode 100644 index 0000000..1330657 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/CMakeLists.txt" @@ -0,0 +1,88 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +#set auto code prefix +set(PREFIX enclave_ZUC) +#set host exec name +set(OUTPUT secgear_enclave_ZUC) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) + +set(CMAKE_CXX_STANDARD 11) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O2 -fPIE") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${SECGEAR_INSTALL_PATH}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim) +else() + target_link_libraries(${OUTPUT} secgear) +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + #itrustee install whitelist /vender/bin/teec_hello + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION /vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/main.cpp" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/main.cpp" new file mode 100644 index 0000000..9add3a7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/host/main.cpp" @@ -0,0 +1,27 @@ +#include"enclave.h" +#include"Enclave1_u.h" +#include +#include + +#define MAX_LEN 1024 + +using namespace std; + +int main(int argc, char* argv[]) { + cc_enclave_t *eid; + cc_enclave_result_t ret; + char *path = transferFromString(PATH); + + ret = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &eid); + if (ret != CC_SUCCESS) { + printf("ERR: %#x ,failed to create enclave.\n", ret); + return -1; + } + + + + if (CC_SUCCESS != cc_enclave_destroy(eid)) { + return -1; + } + return 0; +} diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/common_utils.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/common_utils.h" new file mode 100644 index 0000000..9251edc --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/common_utils.h" @@ -0,0 +1,69 @@ +#ifndef SECGEAR_SM_COMMON_UTILS +#define SECGEAR_SM_COMMON_UTILS + +#include +#define debugPrint (printf("%s: %s: %d\n",__FILE__,__FUNCTION__,__LINE__),fflush(stdout),1) + +typedef __uint8_t uint8; +typedef __uint16_t uint16; +typedef __uint32_t uint32; +typedef __uint64_t uint64; + +#define CONCAT_8x4(x0, x1, x2, x3) ((((uint32)(x0) << 8 | (x1)) << 8 | (x2)) << 8 | (x3)) // X = (x0 || x1 || x2 || x3) +#define CONCAT_16x2(x0, x1) ((uint32)(x0) << 16 | (x1)) // X = (x0 || x1) +#define EXTRACT_8_32(X, i) (((X) >> (((i) ^ 3) << 3)) & 0xFF) // X = (x0 || x1 || x2 || x3) +#define EXTRACT_16_32(X, i) (((X) >> (((i) ^ 1) << 4)) & 0xFFFF) // X = (x0 || x1) +#define EXTRACT_16H_31(X) (((X) >> 15) & 0xFFFF) // Higher 16-bit from 31-bit +#define EXTRACT_16L_31(X) ((X) & 0xFFFF) // Lower 16-bit from 31-bit + +#define ROTATE(a, n) (((a) << (n)) | (((a) & 0xFFFFFFFF) >> ((32 - (n)) & 31))) +#define ROTATE_31(a, n) ((((a) << (n)) & 0x7FFFFFFF) | (((a) & 0x7FFFFFFF) >> (31 - (n)))) + +#define GET_BIT_VALUE_32(x, i) (((x) >> (31 - (i))) & 1) + +const uint32 PREFIX_MASK_32[32] = { + 0x00000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE +}; + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#endif \ No newline at end of file diff --git "a/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/ec.h" "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/ec.h" new file mode 100644 index 0000000..56adbe7 --- /dev/null +++ "b/summer2022\345\237\272\344\272\216secGear\345\256\236\347\216\260\351\203\250\345\210\206\345\233\275\345\257\206\347\256\227\346\263\225/Informal/enclave_ZUC/include/ec.h" @@ -0,0 +1,545 @@ +#include /* BigNum */ +#include "common_utils.h" + +typedef struct ec_point_st { + BIGNUM *X; + BIGNUM *Y; + int is_infinity; +} EC_POINT; + +int EC_POINT_init(EC_POINT *point) { + point->X = BN_new(); + point->Y = BN_new(); + point->is_infinity = 0; + if (point->X == NULL || point->Y == NULL) { + BN_free(point->X); + BN_free(point->Y); + return 0; + } + return 1; +} + +EC_POINT *EC_POINT_new() { + EC_POINT *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_POINT_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_POINT_setXY(EC_POINT *r, const BIGNUM *x, const BIGNUM *y) { + if (r == NULL) { + return 0; + } + if (!BN_copy(r->X, x) || !(BN_copy(r->Y, y))) { + return 0; + } + return 1; +} + +const EC_POINT *EC_point_infinity() { + static const EC_POINT const_infinity = { NULL, NULL, 1 }; + return &const_infinity; +} + +int EC_POINT_is_infinity(const EC_POINT *point) { + return point->is_infinity; +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest == NULL) { + return 0; + } + if (EC_POINT_is_infinity(src)) { + dest->is_infinity = 1; + } + else{ + dest->is_infinity = 0; + if (!BN_copy(dest->X, src->X) || !BN_copy(dest->Y, src->Y)) return 0; + } + return 1; +} + +#define NORMAL 0x1 +#define COMPRESS 0x2 +#define MIX 0x4 + +int EC_POINT_ecp2bin(uint8 *out, const EC_POINT *point, int p_bytes, int flag) { + uint8 PC; + uint8 *p = out, *buf; + int i; + buf = malloc(p_bytes); + if (EC_POINT_is_infinity(point)) { + return 0; + } + if (flag == NORMAL) { + PC = 0x04; + *(p++) = PC; + if (!BN_bn2binpad(point->X, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + if (!BN_bn2binpad(point->Y, buf, p_bytes)) { + return 0; + } + for (i = 0; i < p_bytes; ++i) { + *(p++) = buf[i]; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_bin2ecp(EC_POINT *point, const uint8 *src, int p_bytes) { + if (point == NULL) { + return 0; + } + uint8 PC = *src; + const uint8 *data = src + 1; + uint8 *buf; + int i; + if (PC == 0x04) { + if (!BN_bin2bn(data, p_bytes, point->X) + || !BN_bin2bn(data+p_bytes, p_bytes, point->Y)) { + return 0; + } + } + else { + goto err; /* not supported */ + } + return 1; + err: + return 0; +} + +int EC_POINT_ecp2bin_normal(uint8 *out, const EC_POINT *point, int p_bytes) { + return EC_POINT_ecp2bin(out, point, p_bytes, NORMAL); +} + +// int EC_POINT_ecp2bin_compressed(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, COMPRESS); +// } + +// int EC_POINT_ecp2bin_mix(uint8 *out, const EC_POINT *point, int p_bytes) { +// return EC_POINT_ecp2bin(out, point, p_bytes, MIX); +// } + +typedef struct ec_group_st { + EC_POINT *generator; /* point G */ + BIGNUM *order; /* n */ + BIGNUM *cofactor; /* h */ + BIGNUM *field; /* module p */ + BIGNUM *a, *b; /* ECC parameter */ +} EC_GROUP; + +int EC_GROUP_init(EC_GROUP *group) { + group->generator = EC_POINT_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->generator == NULL || group->b == NULL) { + free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +EC_GROUP *EC_GROUP_new() { + EC_GROUP *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_GROUP_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest == NULL) { + return 0; + } + if (dest == src) { + return 1; + } + if (!EC_POINT_copy(dest->generator, src->generator) + || !BN_copy(dest->order, src->order) + || !BN_copy(dest->cofactor, src->cofactor) + || !BN_copy(dest->field, src->field) + || !BN_copy(dest->a, src->a) + || !BN_copy(dest->b, src->b)) { + return 0; + } + return 1; +} + +int EC_GROUP_set_param(EC_GROUP *group, const BIGNUM *field, const BIGNUM *a, const BIGNUM *b, const BIGNUM *order, const BIGNUM *cofactor, const EC_POINT *point) { + if (group == NULL) { + return 0; + } + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + group->order = BN_new(); + group->cofactor = BN_new(); + group->generator = EC_POINT_new(); + if (group->cofactor == NULL + || group->generator == NULL) { + return 0; + } + if (!BN_copy(group->field, field) + || !BN_copy(group->a, a) + || !BN_copy(group->b, b) + || !BN_copy(group->order, order) + || !BN_copy(group->cofactor, cofactor) + || !EC_POINT_copy(group->generator, point)) { + return 0; + } + return 1; +} + +int EC_POINT_double(EC_POINT *r, const EC_POINT *a, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, EC_point_infinity()); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y)) { + goto done; + } + if (!BN_set_word(bn_value_3, 3) + || !BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_sqr(r->X, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_lshift1_quick(tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, r->X, tmp, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_add(EC_POINT *r, const EC_POINT *a, const EC_POINT *b, const EC_GROUP *group) { + const BIGNUM *p; + BN_CTX *ctx = NULL; + int ret = 0; + BIGNUM *ax, *ay, *bx, *by, *lnum, *ldeno; + BIGNUM *tmp, *bn_value_3; + if (r == NULL) { + return 0; + } + if (a == b) { + return EC_POINT_double(r, a, group); + } + if (EC_POINT_is_infinity(a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_infinity(b)) { + return EC_POINT_copy(r, a); + } + p = group->field; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + ax = BN_CTX_get(ctx); + ay = BN_CTX_get(ctx); + bx = BN_CTX_get(ctx); + by = BN_CTX_get(ctx); + lnum = BN_CTX_get(ctx); + ldeno = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + bn_value_3 = BN_CTX_get(ctx); + if (bn_value_3 == NULL) { + goto done; + } + if (!BN_copy(ax, a->X) + || !BN_copy(ay, a->Y) + || !BN_copy(bx, b->X) + || !BN_copy(by, b->Y)) { + goto done; + } + if (BN_cmp(ax, bx) == 0) { + if (!BN_mod_add_quick(tmp, ay, by, p)) { + goto done; + } + if (BN_is_zero(tmp) + || !EC_POINT_copy(r, EC_point_infinity())) { + goto done; + } + if (!BN_set_word(bn_value_3, 3)) { + goto done; + } + if (!BN_mod_sqr(lnum, ax, p, ctx) + || !BN_mod_mul(lnum, lnum, bn_value_3, p, ctx) + || !BN_mod_add_quick(lnum, lnum, group->a, p) + || !BN_mod_lshift1_quick(ldeno, ay, p) + || !BN_mod_inverse(ldeno, ldeno, p, ctx) + || !BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + else { + if (!BN_mod_sub_quick(lnum, by, ay, p)) { + goto done; + } + if (!BN_mod_sub_quick(ldeno, bx, ax, p)) { + goto done; + } + if (!BN_mod_inverse(ldeno, ldeno, p, ctx)) { + goto done; + } + if (!BN_mod_mul(lnum, lnum, ldeno, p, ctx)) { + goto done; + } + } + if (!BN_mod_sqr(tmp, lnum, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(tmp, tmp, ax, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->X, tmp, bx, p)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, ax, r->X, p)) { + goto done; + } + if (!BN_mod_mul(r->Y, lnum, r->Y, p, ctx)) { + goto done; + } + if (!BN_mod_sub_quick(r->Y, r->Y, ay, p)) { + goto done; + } + if (r == NULL) { + r = EC_POINT_new(); + if (r == NULL) { + goto done; + } + } + ret = 1; + done: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +int EC_POINT_mul(EC_POINT *r, const EC_POINT *a, const BIGNUM *b, const EC_GROUP *group) { + if (r == NULL) { + return 0; + } + if (BN_is_negative(b)) { + EC_POINT *_a = EC_POINT_new(); + BIGNUM *_b = BN_new(); + if (!EC_POINT_copy(_a, a) + || !BN_copy(_b, b) + || !BN_mod_sub_quick(_a->Y, group->field, _a->Y, group->field)) { + return 0; + } + BN_set_negative(_b, 0); + return EC_POINT_mul(r, _a, _b, group); + } + if (!EC_POINT_copy(r, EC_point_infinity())){ + return 0; + } + int bits = BN_num_bits(b); + for (int i = bits-1; i >= 0; --i) { + if (!EC_POINT_double(r, r, group)) { + return 0; + } + if (BN_is_bit_set(b, i)) { + if (!EC_POINT_add(r, r, a, group)) { + return 0; + } + } + } + return 1; +} + +/* + * Only for curve y^2 = x^3 + ax + b. + * Please check infinity before calling. + */ +int EC_POINT_on_curve_simple(const EC_POINT *point, const EC_GROUP *group) { + if (point == NULL || group == NULL) { + return 0; + } + if (EC_POINT_is_infinity(point)) { + return 1; + } + int ret = 0; + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *lhs, *rhs; + EC_POINT *Nq; + ctx = BN_CTX_new(); + if (ctx == NULL) { + return ret; + } + BN_CTX_start(ctx); + p = group->field; + a = group->a; + b = group->b; + x = point->X; + y = point->Y; + lhs = BN_CTX_get(ctx); + rhs = BN_CTX_get(ctx); + Nq = EC_POINT_new(); + if (p == NULL + || a == NULL + || b == NULL + || x == NULL + || y == NULL + || rhs == NULL + || Nq == NULL) { + return ret; + } + if (!BN_mod_mul(lhs, y, y, p, ctx) + || !BN_mod_mul(rhs, x, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, a, p) + || !BN_mod_mul(rhs, rhs, x, p, ctx) + || !BN_mod_add_quick(rhs, rhs, b, p) + || !EC_POINT_mul(Nq, point, group->order, group)) { + return ret; + } + if (BN_cmp(lhs, rhs) != 0 + || !EC_POINT_is_infinity(Nq)) { + return ret; + } + ret = 1; + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} + +typedef struct ec_key_st { + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; +} EC_KEY; + +int EC_KEY_init(EC_KEY *key) { + key->group = EC_GROUP_new(); + key->pub_key = EC_POINT_new(); + key->priv_key = BN_new(); + if (key->group == NULL + || key->pub_key == NULL + || key->priv_key == NULL) { + free(key->group); + free(key->pub_key); + BN_free(key->priv_key); + return 0; + } + return 1; +} + +EC_KEY *EC_KEY_new() { + EC_KEY *ret = NULL; + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + if (!EC_KEY_init(ret)) { + free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + if (!EC_GROUP_copy(key->group, group)) { + return 0; + } + return 1; +} + +int EC_KEY_set_priv_key(EC_KEY *key, const BIGNUM *priv_key) { + BIGNUM *tmp; + tmp = BN_dup(priv_key); + if (tmp == NULL) { + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = tmp; + return 1; +} + +int EC_KEY_generate_pub_key(EC_KEY *key) { + return EC_POINT_mul(key->pub_key, key->group->generator, key->priv_key, key->group); +} + +const BIGNUM *EC_KEY_get_priv_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_generate_key() {} -- Gitee