/* ==================================================================== * Copyright (c) 2016 The GmSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the GmSSL Project. * (http://gmssl.org/)" * * 4. The name "GmSSL Project" must not be used to endorse or promote * products derived from this software without prior written * permission. For written permission, please contact * guanzhi1980@gmail.com. * * 5. Products derived from this software may not be called "GmSSL" * nor may "GmSSL" appear in their names without prior written * permission of the GmSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the GmSSL Project * (http://gmssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ #ifndef HEADER_SM9_STANDARD_H #define HEADER_SM9_STANDARD_H #include #include #include #ifdef __cplusplus extern "C"{ #endif #include "miracl.h" #include "r-ate.h" #include "kdf_standard.h" #define BNLEN 32 //BN curve with 256bit is used in SM9 algorithm #define SM9_ASK_MEMORY_ERR 0x00000001 //ask for memory fail(申请内存失败) #define SM9_MEMBER_ERR 0x00000002 //the order of group G error(群的阶错误) #define SM9_MY_ECAP_12A_ERR 0x00000003 //R-ate pairing generated error(R-ate对计算出现错误) #define SM9_NOT_VALID_G1 0x00000004 //not valid element of G1 #define SM9_G1BASEPOINT_SET_ERR 0x00000005 //base point of G1 seted error(G1基点设置错误) #define SM9_G2BASEPOINT_SET_ERR 0x00000006 //base point of G2 seted error(G2基点设置错误) #define SM9_GEPUB_ERR 0x00000007 //pubkey error(生成公钥错误) #define SM9_GEPRI_ERR 0x00000008 //privare key error(生成私钥错误) #define SM9_ERR_CMP_S1SB 0x00000009 //S1!=SB #define SM9_ERR_CMP_S2SA 0x0000000A //S2!=SA #define SM9_ERR_RA 0x0000000B //RA error #define SM9_ERR_RB 0x0000000C //RB error #define SM9_ERR_SA 0x0000000D //SA error #define SM9_ERR_SB 0x0000000E //SB error #define SM9_C1_NOT_VALID_G1 0x0000000F //C1不属于群G1 #define SM9_ENCRYPT_ERR 0x00000010 //加密错误 #define SM9_ERR_K1_ZERO 0x00000011 //K1 equals 0(K1全0) #define SM9_C3_MEMCMP_ERR 0x00000012 //C3对比不一致 #define SM9_DECRYPT_ERR 0x00000013 //解密错误 #define SM9_ERR_Encap_C 0x00000014 //cipher error in key encapsulation #define SM9_ERR_Encap_K 0x00000015 //key to be encapsulated #define SM9_ERR_Decap_K 0x00000016 //key generated by decapsulation #define SM9_H_OUTRANGE 0x00000017 //签名H不属于[1,N-1] #define SM9_DATA_MEMCMP_ERR 0x00000018 //数据对比不一致 #define SM9_S_NOT_VALID_G1 0x00000019 //S不属于群G1 #define SM9_L_error 0x0000001A //参数L错误 #define SM9_SIGN_ERR 0x0000001B //签名错误 static unsigned char SM9_q[32] = {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}; static unsigned char SM9_N[32] = {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}; static unsigned char SM9_P1x[32] = {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}; static unsigned char SM9_P1y[32] = {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}; static unsigned char SM9_P2[128] = {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, 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, 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, 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}; static unsigned char SM9_t[32] = {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}; static unsigned char SM9_a[32] = {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}; static unsigned char SM9_b[32] = {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}; epoint *P1; ecn2 P2; big N; //order of group, N(t) big para_a, para_b, para_t, para_q; static BOOL bytes128_to_ecn2(unsigned char Ppubs[], ecn2 *res); static void zzn12_ElementPrint(zzn12 x); static void ecn2_Bytes128_Print(ecn2 x); static void LinkCharZzn12(unsigned char *message, int len, zzn12 w, unsigned char *Z, int Zlen); static int Test_Point(epoint* point); void SM4_standard_block_encrypt(unsigned char key[], unsigned char * message, int mlen, unsigned char *cipher, int * cipher_len); void SM4_standard_block_decrypt(unsigned char key[], unsigned char *cipher, int len, unsigned char *plain, int *plain_len); int SM9_standard_keyex_kdf(unsigned char *IDA, unsigned char *IDB, epoint *RA, epoint *RB, zzn12 g1, zzn12 g2, zzn12 g3, int klen, unsigned char K[]); int SM9_standard_keyex_hash(unsigned char hashid[], unsigned char *IDA, unsigned char *IDB, epoint *RA, epoint *RB, zzn12 g1, zzn12 g2, zzn12 g3, unsigned char hash[]); static int SM9_standard_h1(unsigned char Z[], int Zlen, big n, big h1); int SM9_standard_enc_mac(unsigned char *K, int Klen, unsigned char *M, int Mlen, unsigned char C[]); static int SM9_standard_init(); static int SM9_standard_generateencryptkey(unsigned char hid[], unsigned char *ID, int IDlen, big ke, unsigned char Ppubs[], unsigned char deB[]); int SM9_standard_keyex_inita_i(unsigned char hid[], unsigned char *IDB, unsigned char randA[], unsigned char Ppub[], unsigned char deA[], epoint *RA); int SM9_standard_keyex_reb_i(unsigned char hid[], unsigned char *IDA, unsigned char *IDB, unsigned char randB[], unsigned char Ppub[], unsigned char deB[], epoint *RA, epoint *RB, unsigned char SB[], zzn12 *g1, zzn12 *g2, zzn12 *g3); int SM9_standard_keyex_inita_ii(unsigned char *IDA, unsigned char *IDB, unsigned char randA[], unsigned char Ppub[], unsigned char deA[], epoint *RA, epoint *RB, unsigned char SB[], unsigned char SA[]); int SM9_standard_keyex_reb_ii(unsigned char *IDA, unsigned char *IDB, zzn12 g1, zzn12 g2, zzn12 g3, epoint *RA, epoint *RB, unsigned char SA[]); int SM9_standard_exch_selfcheck(); int SM9_standard_enc_selfcheck(); int SM9_standard_encrypt(unsigned char hid[], unsigned char *IDB, unsigned char *message, int mlen, unsigned char rand[], int EncID, int k1_len, int k2_len, unsigned char Ppub[], unsigned char C[], int *C_len); int SM9_standard_decrypt(unsigned char C[], int C_len, unsigned char deB[], unsigned char *IDB, int EncID, int k1_len, int k2_len, unsigned char M[], int * Mlen); int SM9_standard_key_encap(unsigned char hid[], unsigned char *IDB, unsigned char rand[], unsigned char Ppub[], unsigned char C[], unsigned char K[], int Klen); int SM9_standard_key_decap(unsigned char *IDB, unsigned char deB[], unsigned char C[], int Klen, unsigned char K[]); int SM9_standard_encap_selfcheck(); static int Test_Range(big x); int SM9_standard_h2(unsigned char Z[], int Zlen, big n, big h2); int SM9_standard_generatesignkey(unsigned char hid[], unsigned char *ID, int IDlen, big ks, unsigned char Ppubs[], unsigned char dsa[]); int SM9_standard_sign(unsigned char hid[], unsigned char *IDA, unsigned char *message, int len, unsigned char rand[], unsigned char dsa[], unsigned char Ppub[], unsigned char H[], unsigned char S[]); int SM9_standard_verify(unsigned char H[], unsigned char S[], unsigned char hid[], unsigned char *IDA, unsigned char *message, int len, unsigned char Ppub[]); int SM9_standard_sv_selfcheck(); static BOOL bytes128_to_ecn2(unsigned char Ppubs[], ecn2 *res) { zzn2 x, y; big a, b; ecn2 r; r.x.a = mirvar(0); r.x.b = mirvar(0); r.y.a = mirvar(0); r.y.b = mirvar(0); r.z.a = mirvar(0); r.z.b = mirvar(0); r.marker = MR_EPOINT_INFINITY; x.a = mirvar(0); x.b = mirvar(0); y.a = mirvar(0); y.b = mirvar(0); a = mirvar(0); b = mirvar(0); bytes_to_big(BNLEN, Ppubs, b); bytes_to_big(BNLEN, Ppubs + BNLEN, a); zzn2_from_bigs(a, b, &x); bytes_to_big(BNLEN, Ppubs + BNLEN * 2, b); bytes_to_big(BNLEN, Ppubs + BNLEN * 3, a); zzn2_from_bigs(a, b, &y); return ecn2_set(&x, &y, res); } static void ecn2_Bytes128_Print(ecn2 x) { big tmp; tmp = mirvar(0); redc(x.x.b, tmp); cotnum(tmp, stdout); redc(x.x.a, tmp); cotnum(tmp, stdout); redc(x.y.b, tmp); cotnum(tmp, stdout); redc(x.y.a, tmp); cotnum(tmp, stdout); } static void zzn12_ElementPrint(zzn12 x) { big tmp; tmp = mirvar(0); redc(x.c.b.b, tmp); cotnum(tmp, stdout); redc(x.c.b.a, tmp); cotnum(tmp, stdout); redc(x.c.a.b, tmp); cotnum(tmp, stdout); redc(x.c.a.a, tmp); cotnum(tmp,stdout); redc(x.b.b.b, tmp); cotnum(tmp, stdout); redc(x.b.b.a, tmp); cotnum(tmp, stdout); redc(x.b.a.b, tmp); cotnum(tmp, stdout); redc(x.b.a.a, tmp); cotnum(tmp, stdout); redc(x.a.b.b, tmp); cotnum(tmp, stdout); redc(x.a.b.a, tmp); cotnum(tmp, stdout); redc(x.a.a.b, tmp); cotnum(tmp, stdout); redc(x.a.a.a, tmp); cotnum(tmp, stdout); } static void LinkCharZzn12(unsigned char *message, int len, zzn12 w, unsigned char *Z, int Zlen) { big tmp; tmp = mirvar(0); memcpy(Z, message, len); redc(w.c.b.b, tmp); big_to_bytes(BNLEN, tmp, Z + len, 1); redc(w.c.b.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN, 1); redc(w.c.a.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 2, 1); redc(w.c.a.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 3, 1); redc(w.b.b.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 4, 1); redc(w.b.b.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 5, 1); redc(w.b.a.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 6, 1); redc(w.b.a.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 7, 1); redc(w.a.b.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 8, 1); redc(w.a.b.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 9, 1); redc(w.a.a.b, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 10, 1); redc(w.a.a.a, tmp); big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 11, 1); } static int Test_Point(epoint* point) { big x, y, x_3, tmp; epoint *buf; x = mirvar(0); y = mirvar(0); x_3 = mirvar(0); tmp = mirvar(0); buf = epoint_init(); //test if y^2=x^3+b epoint_get(point, x, y); power(x, 3, para_q, x_3); //x_3=x^3 mod p multiply(x, para_a, x); divide(x, para_q, tmp); add(x_3, x, x); //x=x^3+ax+b add(x, para_b, x); divide(x, para_q, tmp); //x=x^3+ax+b mod p power(y, 2, para_q, y); //y=y^2 mod p if(mr_compare(x, y) != 0) return 1; //test infinity ecurve_mult(N, point, buf); if(point_at_infinity(buf) == FALSE) return 1; return 0; } static int SM9_standard_h1(unsigned char Z[], int Zlen, big n, big h1) { int hlen, i, ZHlen; big hh, i256, tmp, n1; unsigned char *ZH = NULL,*ha = NULL; hh = mirvar(0); i256 = mirvar(0); tmp = mirvar(0); n1 = mirvar(0); convert(1, i256); ZHlen = Zlen + 1; hlen = (int)ceil((5.0 * logb2(n)) / 32.0); decr(n, 1, n1); ZH = (char *)malloc(sizeof(char)*(ZHlen + 1)); if(ZH == NULL) return SM9_ASK_MEMORY_ERR; memcpy(ZH + 1, Z, Zlen); ZH[0] = 0x01; ha = (char *)malloc(sizeof(char)*(hlen + 1)); if(ha == NULL) return SM9_ASK_MEMORY_ERR; SM3_kdf(ZH, ZHlen, hlen, ha); for(i = hlen - 1; i >= 0; i--)//key[从大到小] { premult(i256, ha[i], tmp); add(hh, tmp, hh); premult(i256, 256, i256); divide(i256, n1, tmp); divide(hh, n1, tmp); } incr(hh, 1, h1); free(ZH); free(ha); return 0; } static int SM9_standard_init() { big P1_x, P1_y; para_q = mirvar(0); N = mirvar(0); P1_x = mirvar(0); P1_y = mirvar(0); para_a = mirvar(0); para_b = mirvar(0); para_t = mirvar(0); X.a = mirvar(0); X.b = mirvar(0); P2.x.a = mirvar(0); P2.x.b = mirvar(0); P2.y.a = mirvar(0); P2.y.b = mirvar(0); P2.z.a = mirvar(0); P2.z.b = mirvar(0); P2.marker = MR_EPOINT_INFINITY; P1 = epoint_init(); bytes_to_big(BNLEN, SM9_q, para_q); bytes_to_big(BNLEN, SM9_P1x, P1_x); bytes_to_big(BNLEN, SM9_P1y, P1_y); bytes_to_big(BNLEN, SM9_a, para_a); bytes_to_big(BNLEN, SM9_b, para_b); bytes_to_big(BNLEN, SM9_N, N); bytes_to_big(BNLEN, SM9_t, para_t); mip->TWIST = MR_SEXTIC_M; ecurve_init(para_a, para_b, para_q, MR_PROJECTIVE); //Initialises GF(q) elliptic curve //MR_PROJECTIVE specifying projective coordinates if(!epoint_set(P1_x, P1_y, 0, P1)) return SM9_G1BASEPOINT_SET_ERR; if(!(bytes128_to_ecn2(SM9_P2, &P2))) return SM9_G2BASEPOINT_SET_ERR; set_frobenius_constant(&X); return 0; } static int SM9_standard_generateencryptkey(unsigned char hid[], unsigned char *ID, int IDlen, big ke, unsigned char Ppubs[], unsigned char deB[]) { big h1, t1, t2, rem, xPpub, yPpub, tmp; unsigned char *Z = NULL; int Zlen = IDlen + 1, buf; ecn2 dEB; epoint *Ppub; h1 = mirvar(0); t1 = mirvar(0); t2 = mirvar(0); rem = mirvar(0); tmp = mirvar(0); xPpub = mirvar(0); yPpub = mirvar(0); Ppub = epoint_init(); dEB.x.a = mirvar(0); dEB.x.b = mirvar(0); dEB.y.a = mirvar(0); dEB.y.b = mirvar(0); dEB.z.a = mirvar(0); dEB.z.b = mirvar(0); dEB.marker = MR_EPOINT_INFINITY; Z = (char *)malloc(sizeof(char)*(Zlen + 1)); memcpy(Z, ID, IDlen); memcpy(Z + IDlen, hid, 1); buf = SM9_standard_h1(Z, Zlen, N, h1); if(buf != 0) return buf; add(h1, ke, t1);//t1=H1(IDA||hid,N)+ks xgcd(t1, N, t1, t1, t1);//t1=t1(-1) multiply(ke, t1, t2); divide(t2, N, rem);//t2=ks*t1(-1) //Ppub=[ke]P2 ecurve_mult(ke, P1, Ppub); //deB=[t2]P2 ecn2_copy(&P2, &dEB); ecn2_mul(t2, &dEB); printf("\n**************The private key deB = (xdeB, ydeB):*********************\n"); ecn2_Bytes128_Print(dEB); printf("\n**********************PublicKey Ppubs=[ke]P1:*************************\n"); epoint_get(Ppub, xPpub, yPpub); cotnum(xPpub, stdout); cotnum(yPpub, stdout); epoint_get(Ppub, xPpub, yPpub); big_to_bytes(BNLEN, xPpub, Ppubs, 1); big_to_bytes(BNLEN, yPpub, Ppubs + BNLEN, 1); redc(dEB.x.b, tmp); big_to_bytes(BNLEN, tmp, deB, 1); redc(dEB.x.a, tmp); big_to_bytes(BNLEN, tmp, deB + BNLEN, 1); redc(dEB.y.b, tmp); big_to_bytes(BNLEN, tmp, deB + BNLEN * 2, 1); redc(dEB.y.a, tmp); big_to_bytes(BNLEN, tmp, deB + BNLEN * 3, 1); free(Z); return 0; } static int Test_Range(big x) { big one, decr_n; one = mirvar(0); decr_n = mirvar(0); convert(1, one); decr(N, 1, decr_n); if((mr_compare(x, one) < 0) | (mr_compare(x, decr_n) > 0)) return 1; return 0; } #ifdef __cplusplus } #endif #endif