diff --git a/engines/sm_standard/sm9/kdf_standard.h b/engines/sm_standard/sm9/kdf_standard.h new file mode 100644 index 00000000..508226fd --- /dev/null +++ b/engines/sm_standard/sm9/kdf_standard.h @@ -0,0 +1,406 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + + +#ifndef HEADER_KDF_STANDARD_H +#define HEADER_KDF_STANDARD_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SM3_len 256 +#define SM3_T1 0x79CC4519 +#define SM3_T2 0x7A879D8A +#define SM3_IVA 0x7380166f +#define SM3_IVB 0x4914b2b9 +#define SM3_IVC 0x172442d7 +#define SM3_IVD 0xda8a0600 +#define SM3_IVE 0xa96f30bc +#define SM3_IVF 0x163138aa +#define SM3_IVG 0xe38dee4d +#define SM3_IVH 0xb0fb0e4e + +#define SM2_WORDSIZE 8 +#define SM2_NUMBITS 256 +#define SM2_NUMWORD (SM2_NUMBITS / SM2_WORDSIZE) //32 + +/* Various logical functions */ +#define SM3_p1(x) (x ^ SM3_rotl32(x, 15) ^ SM3_rotl32(x, 23)) +#define SM3_p0(x) (x ^ SM3_rotl32(x, 9) ^ SM3_rotl32(x, 17)) +#define SM3_ff0(a, b, c) (a ^ b ^ c) +#define SM3_ff1(a, b, c) ((a & b) | (a & c) | (b & c)) +#define SM3_gg0(e, f, g) (e ^ f ^ g) +#define SM3_gg1(e, f, g) ((e & f) | ((~e) & g)) +#define SM3_rotl32(x, n) (((x) << n) | ((x) >> (32 - n))) +#define SM3_rotr32(x, n) (((x) >> n) | ((x) << (32 - n))) + + +typedef struct { + unsigned long state[8]; + unsigned long length; + unsigned long curlen; + unsigned char buf[64]; +} SM3_STATE; + + +static void BiToW(unsigned long Bi[], unsigned long W[]); +static void WToW1(unsigned long W[], unsigned long W1[]); +static void CF(unsigned long W[], unsigned long W1[], unsigned long V[]); +static void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[]); +static void SM3_init(SM3_STATE *md); +static void SM3_compress(SM3_STATE *md); +static void SM3_process(SM3_STATE *md, unsigned char *buf, int len); +static void SM3_done(SM3_STATE *md, unsigned char hash[]); +static void SM3_256(unsigned char buf[], int len, unsigned char hash[]); +static void SM3_kdf(unsigned char Z[], unsigned short zlen, unsigned short klen, unsigned char K[]); + + +/* calculate W from Bi */ +static void BiToW(unsigned long Bi[], unsigned long W[]) +{ + int i; + unsigned long tmp; + + for(i = 0; i <= 15; i++) + { + W[i] = Bi[i]; + } + for(i = 16;i <= 67; i++) + { + tmp = W[i - 16] ^ W[i - 9] ^ SM3_rotl32(W[i - 3], 15); + W[i] = SM3_p1(tmp) ^ (SM3_rotl32(W[i - 13], 7)) ^ W[i - 6]; + } +} + + +/* calculate W1 from W */ +static void WToW1(unsigned long W[], unsigned long W1[]) +{ + int i; + for(i = 0; i <= 63; i++) + { + W1[i] = W[i] ^ W[i + 4]; + } +} + + +/* calculate the CF compress function and update V */ +static void CF(unsigned long W[], unsigned long W1[], unsigned long V[]) +{ + unsigned long SS1; + unsigned long SS2; + unsigned long TT1; + unsigned long TT2; + unsigned long A, B, C, D, E, F, G, H; + unsigned long T = SM3_T1; + unsigned long FF; + unsigned long GG; + int j; + + //reg init, set ABCDEFGH = V0 + A = V[0]; + B = V[1]; + C = V[2]; + D = V[3]; + E = V[4]; + F = V[5]; + G = V[6]; + H = V[7]; + + for (j = 0; j <= 63; j++) + { + //SS1 + if (j == 0) + { + T = SM3_T1; + } + else if (j == 16) + { + T = SM3_rotl32(SM3_T2, 16); + } + else + { + T = SM3_rotl32(T, 1); + } + SS1 = SM3_rotl32((SM3_rotl32(A, 12) + E + T), 7); + + //SS2 + SS2 = SS1 ^ SM3_rotl32(A, 12); + + //TT1 + if (j <= 15) + { + FF = SM3_ff0(A, B, C); + } + else + { + FF = SM3_ff1(A, B, C); + } + TT1 = FF + D + SS2 + *W1; + W1++; + + //TT2 + if (j <= 15) + { + GG = SM3_gg0(E, F, G); + } + else + { + GG = SM3_gg1(E, F, G); + } + TT2 = GG + H + SS1 + *W; + W++; + + //D + D = C; + + //C + C = SM3_rotl32(B, 9); + + //B + B = A; + + //A + A = TT1; + + //H + H = G; + + //G + G = SM3_rotl32(F, 19); + + //F + F = E; + + //E + E = SM3_p0(TT2); + } + + //update V + V[0] = A ^ V[0]; + V[1] = B ^ V[1]; + V[2] = C ^ V[2]; + V[3] = D ^ V[3]; + V[4] = E ^ V[4]; + V[5] = F ^ V[5]; + V[6] = G ^ V[6]; + V[7] = H ^ V[7]; +} + + +/* unsigned int endian converse. GM/T 0004-2012 requires to use big-endian. + * if CPu uses little-endian, BigEndian function is a necessary + * call to change the little-endian format into big-endian format. + */ +static void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[]) +{ + unsigned char tmp = 0; + unsigned long i = 0; + for (i = 0; i < bytelen / 4; i++) + { + tmp = des[4 * i]; + des[4 * i] = src[4 * i + 3]; + src[4 * i + 3] = tmp; + + tmp = des[4 * i + 1]; + des[4 * i + 1] = src[4 * i + 2]; + des[4 * i + 2] = tmp; + } +} + + +/* initiate SM3 state */ +static void SM3_init(SM3_STATE *md) +{ + md->curlen = md->length = 0; + md->state[0] = SM3_IVA; + md->state[1] = SM3_IVB; + md->state[2] = SM3_IVC; + md->state[3] = SM3_IVD; + md->state[4] = SM3_IVE; + md->state[5] = SM3_IVF; + md->state[6] = SM3_IVG; + md->state[7] = SM3_IVH; +} + + +/* compress a single a block of message */ +static void SM3_compress(SM3_STATE *md) +{ + unsigned long W[68]; + unsigned long W1[64]; + + //if CPU uses little-endian, BigEndian function is a necessary call + BigEndian(md->buf, 64, md->buf); + BiToW((unsigned long *)md->buf, W); + WToW1(W, W1); + CF(W, W1, md->state); +} + + +/* compress the first(len/64) blocks of message */ +static void SM3_process(SM3_STATE *md, unsigned char *buf, int len) +{ + while (len--) + { + /* copy byte */ + md->buf[md->curlen] = *buf++; + md->curlen++; + + /* is 64 bytes full? */ + if (md->curlen == 64) + { + SM3_compress(md); + md->length += 512; + md->curlen = 0; + } + } +} + + +/* compress the rest message that the SM3_process has left behind */ +static void SM3_done(SM3_STATE *md, unsigned char hash[]) +{ + int i; + unsigned char tmp = 0; + + /* increase the bit length of the message */ + md->length += md->curlen << 3; + + /* append the '1' bit */ + md->buf[md->curlen] = 0x80; + md->curlen++; + + /* if the length is currently above 56 bytes, appends zeros till + it reaches 64 bytes, compress the current block, creat a new + block by appending zeros and length,and then compress it + */ + if (md->curlen > 56) + { + for (; md->curlen < 64;) + { + md->buf[md->curlen] = 0; + md->curlen++; + } + SM3_compress(md); + md->curlen = 0; + } + + /* if the length is less than 56 bytes, pad upto 56 bytes of zeroes */ + for (; md->curlen < 56;) + { + md->buf[md->curlen] = 0; + md->curlen++; + } + + /* since all messages are under 2^32 bits we mark the top bits zero */ + for (i = 56; i < 60; i++) + { + md->buf[i] = 0; + } + + /* append length */ + md->buf[63] = md->length & 0xff; + md->buf[62] = (md->length >> 8) & 0xff; + md->buf[61] = (md->length >> 16) & 0xff; + md->buf[60] = (md->length >> 24) & 0xff; + + SM3_compress(md); + + /* copy output */ + memcpy(hash, md->state, SM3_len / 8); + BigEndian(hash, SM3_len / 8, hash); //if CPU uses little-endian, BigEndian function is a necessary call +} + + +/* calculate a hash value from a given message */ +static void SM3_256(unsigned char buf[], int len, unsigned char hash[]) +{ + SM3_STATE md; + SM3_init(&md); + SM3_process(&md, buf, len); + SM3_done(&md, hash); +} + + +/* key derivation function */ +static void SM3_kdf(unsigned char Z[], unsigned short zlen, unsigned short klen, unsigned char K[]) +{ + unsigned short i, j, t; + unsigned int bitklen; + SM3_STATE md; + unsigned char Ha[SM2_NUMWORD]; + unsigned char ct[4] = {0, 0, 0, 1}; + + bitklen = klen * 8; + + if (bitklen % SM2_NUMBITS) + t = bitklen / SM2_NUMBITS + 1; + else + t = bitklen / SM2_NUMBITS; + + //s4: K = Ha1 || Ha2 || ... + for (i = 1; i < t; i++) + { + //s2: Hai = Hv(Z || ct) + SM3_init(&md); + SM3_process(&md, Z, zlen); + SM3_process(&md, ct, 4); + SM3_done(&md, Ha); + memcpy((K + SM2_NUMWORD * (i - 1)), Ha, SM2_NUMWORD); + + if (ct[3] == 0xff) + { + ct[3] = 0; + if (ct[2] == 0xff) + { + ct[2] = 0; + if (ct[1] == 0xff) + { + ct[1] = 0; + ct[0]++; + } + else + ct[1]++; + } + else + ct[2]++; + } + else + ct[3]++; + } + + //s3 + SM3_init(&md); + SM3_process(&md, Z, zlen); + SM3_process(&md, ct, 4); + SM3_done(&md, Ha); + + if(bitklen % SM2_NUMBITS) + { + i = (SM2_NUMBITS - bitklen + SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8; + j = (bitklen - SM2_NUMBITS * (bitklen / SM2_NUMBITS)) / 8; + memcpy((K + SM2_NUMWORD * (t - 1)), Ha, j); + } + else + { + memcpy((K + SM2_NUMWORD * (t - 1)), Ha, SM2_NUMWORD); + } +} + + +#ifdef __cplusplus +} +# endif +#endif diff --git a/engines/sm_standard/sm9/r-ate.h b/engines/sm_standard/sm9/r-ate.h new file mode 100644 index 00000000..06c06e18 --- /dev/null +++ b/engines/sm_standard/sm9/r-ate.h @@ -0,0 +1,517 @@ +/* ==================================================================== + * Copyright (c) 2007 - 2017 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_R_ATE_H +#define HEADER_R_ATE_H + + +#include "zzn12_operation.h" + + +#ifdef __cplusplus +extern "C"{ +#endif + + +static zzn2 zzn2_pow(zzn2 x, big k) +{ + int i, j, nb, n, nbw, nzs; + big zero; + zzn2 res, u2, t[16]; + + zero = mirvar(0); + + res.a = mirvar(0); + res.b = mirvar(0); + + u2.a = mirvar(0); + u2.b = mirvar(0); + + if(zzn2_iszero(&x)) + { + zzn2_zero(&res); + return res; + } + if(size(k) == 0) + { + zzn2_from_int(1, &res); + return res; + } + if(size(k) == 1) + return x; + + // Prepare table for windowing + zzn2_mul(&x, &x, &u2); + t[0].a = mirvar(0); + t[0].b = mirvar(0); + zzn2_copy(&x, &t[0]); + for(i = 1; i < 16; i++) + { + t[i].a = mirvar(0); + t[i].b = mirvar(0); + zzn2_mul(&t[i - 1], &u2, &t[i]); + } + + // Left to right method - with windows + zzn2_copy(&x, &res); + nb = logb2(k); + if(nb > 1) + for(i = nb - 2; i >= 0;) + { + //Note new parameter of window_size=5. Default to 5, but reduce to 4 (or even 3) to save RAM + n = mr_window(k, i, &nbw, &nzs, 5); + for(j = 0; j < nbw; j++) + zzn2_mul(&res, &res, &res); + if(n > 0) + zzn2_mul(&res, &t[n / 2], &res); + i -= nbw; + if(nzs) + { + for(j = 0; j < nzs; j++) + zzn2_mul(&res, &res, &res); + i -= nzs; + } + } + return res; +} + + +static void set_frobenius_constant(zzn2 *X) +{ + big p, zero, one, two; + p = mirvar(0); + zero = mirvar(0); + one = mirvar(0); + two = mirvar(0); + + convert(0, zero); + convert(1, one); + convert(2, two); + + mip = get_mip(); + copy(mip->modulus, p); + + switch(get_mip()->pmod8) + { + case 5: + zzn2_from_bigs(zero, one, X);// = (sqrt(-2)^(p-1)/2 + break; + case 3: + // = (1+sqrt(-1))^(p-1)/2 + zzn2_from_bigs(one, one, X); + break; + case 7: + zzn2_from_bigs(two, one, X);// = (2+sqrt(-1))^(p-1)/2 + default: + break; + } + + decr(p, 1, p); + subdiv(p, 6, p); + + *X = zzn2_pow(*X, p); +} + + +static void q_power_frobenius(ecn2 A, zzn2 F) +{ + // Fast multiplication of A by q (for Trace-Zero group members only) + zzn2 x, y, z, w, r; + x.a = mirvar(0); + x.b = mirvar(0); + + y.a = mirvar(0); + y.b = mirvar(0); + + z.a = mirvar(0); + z.b = mirvar(0); + + w.a = mirvar(0); + w.b = mirvar(0); + + r.a = mirvar(0); + r.b = mirvar(0); + + ecn2_get(&A, &x, &y, &z); + zzn2_copy(&F, &r);//r=F + if(get_mip()->TWIST == MR_SEXTIC_M) + zzn2_inv(&r); // could be precalculated + zzn2_mul(&r, &r, &w);//w=r*r + zzn2_conj(&x, &x); + zzn2_mul(&w, &x, &x); + zzn2_conj(&y, &y); + zzn2_mul(&w, &r, &w); + zzn2_mul(&w, &y, &y); + zzn2_conj(&z, &z); + ecn2_setxyz(&x, &y, &z, &A); +} + + +static zzn12 line(ecn2 A, ecn2 *C, ecn2 *B, zzn2 slope, zzn2 extra, BOOL Doubling, big Qx, big Qy) +{ + zzn12 res; + zzn2 X, Y, Z, Z2, U, QY, CZ; + big QX; + + QX = mirvar(0); + X.a = mirvar(0); + X.b = mirvar(0); + + Y.a = mirvar(0); + Y.b = mirvar(0); + + Z.a = mirvar(0); + Z.b = mirvar(0); + + Z2.a = mirvar(0); + Z2.b = mirvar(0); + + U.a = mirvar(0); + U.b = mirvar(0); + + QY.a = mirvar(0); + QY.b = mirvar(0); + + CZ.a = mirvar(0); + CZ.b = mirvar(0); + zzn12_init(&res); + + ecn2_getz(C, &CZ); + // Thanks to A. Menezes for pointing out this optimization... + if(Doubling) + { + ecn2_get(&A, &X, &Y, &Z); + zzn2_mul(&Z, &Z, &Z2); //Z2=Z*Z + + //X=slope*X-extra + zzn2_mul(&slope, &X, &X); + zzn2_sub(&X, &extra, &X); + + zzn2_mul(&CZ, &Z2, &U); + + //(-(Z*Z*slope)*Qx); + nres(Qx, QX); + zzn2_mul(&Z2, &slope, &Y); + zzn2_smul(&Y, QX, &Y); + zzn2_negate(&Y, &Y); + + if(get_mip()->TWIST == MR_SEXTIC_M) + { + // "multiplied across" by i to simplify + zzn2_from_big(Qy, &QY); + zzn2_txx(&QY); + zzn2_mul(&U, &QY, &QY); + zzn4_from_zzn2s(&QY, &X, &res.a); + zzn2_copy(&Y, &(res.c.b)); + } + if(get_mip()->TWIST == MR_SEXTIC_D) + { + zzn2_smul(&U, Qy, &QY); + zzn4_from_zzn2s(&QY, &X, &res.a); + zzn2_copy(&Y, &(res.b.b)); + } + } + else + { + //slope*X-Y*Z + ecn2_getxy(B, &X, &Y); + zzn2_mul(&slope, &X, &X); + zzn2_mul(&Y, &CZ, &Y); + zzn2_sub(&X, &Y, &X); + + //(-slope*Qx) + nres(Qx, QX); + zzn2_smul(&slope, QX, &Z); + zzn2_negate(&Z, &Z); + + if(get_mip()->TWIST == MR_SEXTIC_M) + { + zzn2_from_big(Qy, &QY); + zzn2_txx(&QY); + zzn2_mul(&CZ, &QY, &QY); + + zzn4_from_zzn2s(&QY, &X, &res.a); + zzn2_copy(&Z, &(res.c.b)); + } + if(get_mip()->TWIST == MR_SEXTIC_D) + { + zzn2_smul(&CZ, Qy, &QY); + zzn4_from_zzn2s(&QY, &X, &res.a); + zzn2_copy(&Z, &(res.b.b)); + } + } + return res; +} + + +static zzn12 g(ecn2 *A, ecn2 *B, big Qx, big Qy) +{ + zzn2 lam, extra; + BOOL Doubling; + ecn2 P; + zzn12 res; + + lam.a = mirvar(0); + lam.b = mirvar(0); + + extra.a = mirvar(0); + extra.b = mirvar(0); + + P.x.a = mirvar(0); + P.x.b = mirvar(0); + + P.y.a = mirvar(0); + P.y.b = mirvar(0); + + P.z.a = mirvar(0); + P.z.b = mirvar(0); + + P.marker = MR_EPOINT_INFINITY; + + zzn12_init(&res); + ecn2_copy(A, &P); + Doubling = ecn2_add2(B, A, &lam, &extra); + if(A->marker == MR_EPOINT_INFINITY) + { + zzn4_from_int(1, &res.a); + res.miller = FALSE; + res.unitary = TRUE; + } + else + res = line(P, A, B, lam, extra, Doubling, Qx, Qy); + return res; +} + + +static BOOL fast_pairing(ecn2 P, big Qx, big Qy, big x, zzn2 X, zzn12 *r) +{ + int i, nb; + big n, zero, negify_x; + ecn2 A, KA; + zzn12 t0, x0, x1, x2, x3, x4, x5, res; + + zero = mirvar(0); + n = mirvar(0); + negify_x = mirvar(0); + + A.x.a = mirvar(0); + A.x.b = mirvar(0); + + A.y.a = mirvar(0); + A.y.b = mirvar(0); + + A.z.a = mirvar(0); + A.z.b = mirvar(0); + A.marker = MR_EPOINT_INFINITY; + + KA.x.a = mirvar(0); + KA.x.b = mirvar(0); + + KA.y.a = mirvar(0); + KA.y.b = mirvar(0); + + KA.z.a = mirvar(0); + KA.z.b = mirvar(0); + KA.marker = MR_EPOINT_INFINITY; + zzn12_init(&t0); + zzn12_init(&x0); + zzn12_init(&x1); + zzn12_init(&x2); + zzn12_init(&x3); + zzn12_init(&x4); + zzn12_init(&x5); + zzn12_init(&res); + + premult(x, 6, n); + incr(n, 2, n);//n=(6*x+2); + if(mr_compare(x, zero) < 0) //x<0 + negify(n, n); //n=-(6*x+2); + + ecn2_copy(&P, &A); + nb = logb2(n); + zzn4_from_int(1, &res.a); + res.unitary = TRUE; //res=1 + // Short Miller loop + res.miller = TRUE; + + for(i = nb - 2; i >= 0; i--) + { + zzn12_mul(res, res, &res); + zzn12_mul(res, g(&A, &A, Qx, Qy), &res); + if(mr_testbit(n, i)) + zzn12_mul(res, g(&A, &P, Qx, Qy), &res); + } + // Combining ideas due to Longa, Aranha et al. and Naehrig + ecn2_copy(&P, &KA); + q_power_frobenius(KA, X); + if(mr_compare(x, zero) < 0) + { + ecn2_negate(&A, &A); + zzn12_conj(&res, &res); + } + zzn12_mul(res, g(&A, &KA, Qx, Qy), &res); + q_power_frobenius(KA, X); + ecn2_negate(&KA, &KA); + zzn12_mul(res, g(&A, &KA, Qx, Qy), &res); + + if(zzn4_iszero(&res.a) && zzn4_iszero(&res.b) && zzn4_iszero(&res.c)) + return FALSE; + + // The final exponentiation + zzn12_copy(&res, &t0);//t0=r; + zzn12_conj(&res, &res); + zzn12_div(res, t0, &res); + + res.miller = FALSE; + res.unitary = FALSE; + + zzn12_copy(&res, &t0);//t0=r; + zzn12_powq(X, &res); + zzn12_powq(X, &res); + zzn12_mul(res, t0, &res);// r^[(p^6-1)*(p^2+1)] + res.miller = FALSE; + res.unitary = TRUE; + + // Newer new idea... + // See "On the final exponentiation for calculating pairings on ordinary elliptic curves" + // Michael Scott and Naomi Benger and Manuel Charlemagne and Luis J. Dominguez Perez and Ezekiel J. Kachisa + zzn12_copy(&res, &t0); + zzn12_powq(X, &t0); + zzn12_copy(&t0, &x0); + zzn12_powq(X, &x0); //x0=t0 + + zzn12_mul(res, t0, &x1); + zzn12_mul(x0, x1, &x0);// x0*=(res*t0); + zzn12_powq(X, &x0); + + x1 = zzn12_inverse(res);// just a conjugation! + negify(x, negify_x); + x4 = zzn12_pow(res, negify_x);//negify_x=-x x is sparse. + zzn12_copy(&x4, &x3); + zzn12_powq(X, &x3); + + x2 = zzn12_pow(x4, negify_x); + x5 = zzn12_inverse(x2); + t0 = zzn12_pow(x2, negify_x); + + zzn12_powq(X, &x2); + zzn12_div(x4, x2, &x4); + + zzn12_powq(X, &x2); + zzn12_copy(&t0, &res);// res=t0 + zzn12_powq(X, &res); + zzn12_mul(t0, res, &t0); + + zzn12_mul(t0, t0, &t0); + zzn12_mul(t0, x4, &t0); + zzn12_mul(t0, x5, &t0);//t0*=t0;t0*=x4;t0*=x5; + + zzn12_mul(x3, x5, &res); + zzn12_mul(res, t0, &res);//res=x3*x5;res*=t0; + + zzn12_mul(t0, x2, &t0);//t0*=x2; + + zzn12_mul(res, res, &res); + zzn12_mul(res, t0, &res); + zzn12_mul(res, res, &res);//res*=res; res*=t0;res*=res; + + zzn12_mul(res, x1, &t0);// t0=res*x1; + zzn12_mul(res, x0, &res);//res*=x0; + + zzn12_mul(t0, t0, &t0); + zzn12_mul(t0, res, &t0);//t0*=t0;t0*=res; + + zzn12_copy(&t0, r);//r= t0; + + return TRUE; +} + + +static BOOL ecap(ecn2 P, epoint *Q, big x, zzn2 X, zzn12 *r) +{ + BOOL Ok; + big Qx, Qy; + Qx = mirvar(0); + Qy = mirvar(0); + + ecn2_norm(&P); + epoint_get(Q, Qx, Qy); + + Ok = fast_pairing(P, Qx, Qy, x, X, r); + + if(Ok) + return TRUE; + return FALSE; +} + + +static BOOL member(zzn12 r, big x, zzn2 F) +{ + zzn12 w; + big six; + six = mirvar(0); + zzn12_init(&w); + + convert(6, six); + zzn12_copy(&r, &w);//w=r + zzn12_powq(F, &w); + r = zzn12_pow(r, x); + r = zzn12_pow(r, x); + r = zzn12_pow(r, six); // t-1=6x^2 + if(zzn4_compare(&w.a, &r.a) && zzn4_compare(&w.a, &r.a) && zzn4_compare(&w.a, &r.a)) + return TRUE; + return FALSE; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/engines/sm_standard/sm9/sm4_standard.h b/engines/sm_standard/sm9/sm4_standard.h new file mode 100644 index 00000000..3f47a337 --- /dev/null +++ b/engines/sm_standard/sm9/sm4_standard.h @@ -0,0 +1,188 @@ +/* ==================================================================== + * 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_SM4_STANDARD_H +#define HEADER_SM4_STANDARD_H + + +#include + +#ifdef __cplusplus +extern "C"{ +#endif + + +//rotate n bits to the left in a 32bit buffer +#define SM4_rotl32(buf, n) (((buf) << n) | ((buf) >> (32 - n))) + + +static unsigned int SM4_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}; +unsigned char SM4_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}; +static unsigned int SM4_FK[4] = {0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC}; + + +void SM4_keyschedule(unsigned char MK[], unsigned int rk[]) +{ + unsigned int tmp, buf, K[36]; + int i; + for(i = 0; i < 4; i++) + { + K[i] = SM4_FK[i] ^ ((MK[4 * i] << 24) | (MK[4 * i + 1] << 16) + | (MK[4 * i + 2] << 8) | (MK[4 * i + 3])); + } + for(i = 0; i < 32; i++) + { + tmp = K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ SM4_CK[i]; + + //nonlinear operation + buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24 + | (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16 + | (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8 + | (SM4_Sbox[tmp & 0xFF]); + + //linear operation + K[i + 4] = K[i] ^ ((buf) ^ (SM4_rotl32((buf), 13)) ^ (SM4_rotl32((buf), 23))); + rk[i] = K[i + 4]; + } +} + + +void SM4_encrypt(unsigned char MK[], unsigned char PlainText[], unsigned char CipherText[]) +{ + unsigned int rk[32], X[36], tmp, buf; + int i, j; + SM4_keyschedule(MK, rk); + for(j = 0; j < 4; j++) + { + X[j] = (PlainText[j * 4] << 24) | (PlainText[j * 4 + 1] << 16) + | (PlainText[j * 4 + 2] << 8) | (PlainText[j * 4 + 3]); + } + for(i = 0; i < 32; i++) + { + tmp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[i]; + + //nonlinear operation + buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24 + | (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16 + | (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8 + | (SM4_Sbox[tmp & 0xFF]); + + //linear operation + X[i + 4] = X[i] ^ (buf ^ SM4_rotl32((buf), 2) ^ SM4_rotl32((buf), 10) + ^ SM4_rotl32((buf), 18) ^ SM4_rotl32((buf), 24)); + } + for(j = 0; j < 4; j++) + { + CipherText[4 * j] = (X[35 - j] >> 24) & 0xFF; + CipherText[4 * j + 1] = (X[35 - j] >> 16) & 0xFF; + CipherText[4 * j + 2]= (X[35 - j] >> 8) & 0xFF; + CipherText[4 * j + 3] = (X[35 - j]) & 0xFF; + } +} + + +void SM4_decrypt(unsigned char MK[], unsigned char CipherText[], unsigned char PlainText[]) +{ + unsigned int rk[32], X[36], tmp, buf; + int i, j; + SM4_keyschedule(MK, rk); + for(j = 0; j < 4; j++) + { + X[j] = (CipherText[j * 4] << 24) | (CipherText[j * 4 + 1] << 16) | + (CipherText[j * 4 + 2] << 8) | (CipherText[j * 4 + 3]); + } + for(i = 0; i < 32; i++) + { + tmp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[31 - i]; + //nonlinear operation + buf = (SM4_Sbox[(tmp >> 24) & 0xFF]) << 24 + | (SM4_Sbox[(tmp >> 16) & 0xFF]) << 16 + | (SM4_Sbox[(tmp >> 8) & 0xFF]) << 8 + | (SM4_Sbox[tmp & 0xFF]); + //linear operation + X[i + 4] = X[i] ^ (buf ^ SM4_rotl32((buf), 2) ^ SM4_rotl32((buf), 10) + ^ SM4_rotl32((buf), 18) ^ SM4_rotl32((buf), 24)); + } + for(j = 0; j < 4; j++) + { + PlainText[4 * j] = (X[35 - j] >> 24) & 0xFF; + PlainText[4 * j + 1] = (X[35 - j] >> 16) & 0xFF; + PlainText[4 * j + 2] = (X[35 - j] >> 8) & 0xFF; + PlainText[4 * j + 3] = (X[35 - j]) & 0xFF; + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/engines/sm_standard/sm9/sm9_standard.h b/engines/sm_standard/sm9/sm9_standard.h new file mode 100644 index 00000000..5b9f3c37 --- /dev/null +++ b/engines/sm_standard/sm9/sm9_standard.h @@ -0,0 +1,482 @@ +/* ==================================================================== + * 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 diff --git a/engines/sm_standard/sm9/sm9_standard_enc.c b/engines/sm_standard/sm9/sm9_standard_enc.c new file mode 100644 index 00000000..474fcc49 --- /dev/null +++ b/engines/sm_standard/sm9/sm9_standard_enc.c @@ -0,0 +1,477 @@ +/* ==================================================================== + * 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. + * ==================================================================== + */ + + +#include "sm9_standard.h" +#include "sm4_standard.h" +#include "miracl.h" +#include "mirdef.h" + + +void SM4_standard_block_encrypt(unsigned char key[], unsigned char * message, int mlen, unsigned char *cipher, int * cipher_len) +{ + unsigned char mess[16]; + int i, rem = mlen % 16; + + for(i = 0; i < mlen / 16; i++) + SM4_encrypt(key, &message[i * 16], &cipher[i * 16]); + //encrypt the last block + memset(mess, 16 - rem, 16); + if(rem) + memcpy(mess, &message[i * 16], rem); + SM4_encrypt(key, mess, &cipher[i*16]); +} + + +void SM4_standard_block_decrypt(unsigned char key[], unsigned char *cipher, int len, unsigned char *plain, int *plain_len) +{ + int i; + for(i = 0; i < len / 16; i++) + SM4_decrypt(key, cipher + i * 16, plain + i * 16); + *plain_len = len - plain[len - 1]; +} + + +int SM9_standard_enc_mac(unsigned char *K, int Klen, unsigned char *M, int Mlen, unsigned char C[]) +{ + unsigned char *Z = NULL; + int len = Klen + Mlen; + Z = (char *)malloc(sizeof(char)*(len + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + memcpy(Z, M, Mlen); + memcpy(Z + Mlen, K, Klen); + SM3_256(Z, len, C); + + free(Z); + return 0; +} + + +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) +{ + big h, x, y, r; + zzn12 g, w; + epoint *Ppube, *QB, *C1; + unsigned char *Z = NULL, *K = NULL, *C2 = NULL, C3[SM3_len / 8]; + int i = 0, j = 0, Zlen, buf, klen, C2_len; + + //initiate + h = mirvar(0); + r = mirvar(0); + x = mirvar(0); + y = mirvar(0); + QB = epoint_init(); + Ppube = epoint_init(); + C1 = epoint_init(); + zzn12_init(&g); + zzn12_init(&w); + + bytes_to_big(BNLEN, Ppub, x); + bytes_to_big(BNLEN, Ppub + BNLEN, y); + epoint_set(x, y, 0, Ppube); + + //Step1:calculate QB=[H1(IDB||hid,N)]P1+Ppube + Zlen = strlen(IDB) + 1; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + memcpy(Z, IDB, strlen(IDB)); + memcpy(Z + strlen(IDB), hid, 1); + buf = SM9_standard_h1(Z, Zlen, N, h); + if(buf) + return buf; + ecurve_mult(h, P1, QB); + ecurve_add(Ppube, QB); + + printf("\n*******************QB:=[H1(IDB||hid,N)]P1+Ppube*****************\n"); + epoint_get(QB, x, y); + cotnum(x, stdout); + cotnum(y, stdout); + + //Step2:randnom + bytes_to_big(BNLEN, rand, r); + printf("\n***********************randnum r:********************************\n"); + cotnum(r, stdout); + + //Step3:C1=[r]QB + ecurve_mult(r, QB, C1); + printf("\n*************************:C1=[r]QB*******************************\n"); + epoint_get(C1, x, y); + cotnum(x, stdout); + cotnum(y, stdout); + big_to_bytes(BNLEN, x, C, 1); + big_to_bytes(BNLEN, y, C + BNLEN, 1); + + //Step4:g = e(P2, Ppub-e) + if(!ecap(P2, Ppube, para_t, X, &g)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if(!member(g, para_t, X)) + return SM9_MEMBER_ERR; + printf("\n***********************g=e(P2,Ppube):****************************\n"); + zzn12_ElementPrint(g); + + //Step5:calculate w=g^r + w = zzn12_pow(g, r); + printf("\n***************************w=g^r:**********************************\n"); + zzn12_ElementPrint(w); + + free(Z); + //Step6:calculate C2 + if(EncID == 0) + { + C2_len = mlen; + *C_len = BNLEN * 2 + SM3_len / 8 + C2_len; + + //Step:6-1: calculate K=KDF(C1||w||IDB,klen) + klen = mlen + k2_len; + Zlen = strlen(IDB) + BNLEN * 14; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + K = (char *)malloc(sizeof(char)*(klen + 1)); + C2 = (char *)malloc(sizeof(char)*(mlen + 1)); + if(Z == NULL || K == NULL || C2 == NULL) + return SM9_ASK_MEMORY_ERR; + + LinkCharZzn12( C, BNLEN * 2, w, Z, (Zlen - strlen(IDB))); + memcpy(Z + BNLEN * 14, IDB, strlen(IDB)); + SM3_kdf(Z, Zlen, klen, K); + printf("\n*****************K=KDF(C1||w||IDB,klen):***********************\n"); + for(i = 0; i < klen; i++) + printf("%02x", K[i]); + + //Step:6-2: calculate C2=M^K1,and test if K1==0? + for(i = 0; i < mlen; i++) + { + if(K[i] == 0) + j = j + 1; + C2[i] = message[i] ^ K[i]; + } + if(j == mlen) + return SM9_ERR_K1_ZERO; + printf("\n************************* C2=M^K1 :***************************\n"); + for(i = 0; i < C2_len; i++) + printf("%02x", C2[i]); + + //Step7:calculate C3=MAC(K2,C2) + SM9_standard_enc_mac(K + mlen, k2_len, C2, mlen, C3); + printf("\n********************** C3=MAC(K2,C2):*************************\n"); + for(i = 0; i < 32; i++) + printf("%02x", C3[i]); + + memcpy(C + BNLEN * 2, C3, SM3_len / 8); + memcpy(C + BNLEN * 2 + SM3_len / 8, C2, C2_len); + free(Z); + free(K); + free(C2); + } + else + { + C2_len = (mlen / 16 + 1) * 16; + *C_len = BNLEN * 2 + SM3_len / 8 + C2_len; + + //Step:6-1: calculate K=KDF(C1||w||IDB,klen) + klen = k1_len + k2_len; + Zlen = strlen(IDB) + BNLEN * 14; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + K = (char *)malloc(sizeof(char)*(klen + 1)); + C2 = (char *)malloc(sizeof(char)*(C2_len + 1)); + if(Z == NULL || K == NULL || C2 == NULL) + return SM9_ASK_MEMORY_ERR; + + LinkCharZzn12(C, BNLEN * 2, w, Z, Zlen - strlen(IDB)); + memcpy(Z + BNLEN * 14, IDB, strlen(IDB)); + SM3_kdf(Z, Zlen, klen, K); + printf("\n*****************K=KDF(C1||w||IDB,klen):***********************\n"); + for(i = 0; i < klen; i++) + printf("%02x", K[i]); + + //Step:6-2: calculate C2=Enc(K1,M),and also test if K1==0? + for(i = 0; i < k1_len; i++) + { + if(K[i] == 0) + j = j + 1; + } + if(j == k1_len) + return SM9_ERR_K1_ZERO; + + SM4_standard_block_encrypt(K, message, mlen, C2, &C2_len); + printf("\n*********************** C2=Enc(K1,M) :*************************\n"); + for(i = 0; i < C2_len; i++) + printf("%02x", C2[i]); + + //Step7:calculate C3=MAC(K2,C2) + SM9_standard_enc_mac(K + k1_len, k2_len, C2, C2_len, C3); + printf("\n********************** C3=MAC(K2,C2):*************************\n"); + for(i = 0; i < 32; i++) + printf("%02x", C3[i]); + + memcpy(C + BNLEN * 2, C3, SM3_len / 8); + memcpy(C + BNLEN * 2 + SM3_len / 8, C2, C2_len); + free(Z); + free(K); + free(C2); + } + return 0; +} + + +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) +{ + big x, y; + epoint *C1; + zzn12 w; + ecn2 dEB; + int mlen, klen, Zlen, i, number = 0; + unsigned char *Z = NULL, *K = NULL, *K1 = NULL, u[SM3_len / 8]; + + x = mirvar(0); + y = mirvar(0); + 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; + C1 = epoint_init(); + zzn12_init(&w); + + bytes_to_big(BNLEN, C, x); + bytes_to_big(BNLEN, C + BNLEN, y); + bytes128_to_ecn2(deB, &dEB); + + //Step1:get C1,and test if C1 is on G1 + epoint_set(x, y, 1, C1); + if(Test_Point(C1)) + return SM9_C1_NOT_VALID_G1; + + //Step2:w = e(C1, deB) + if(!ecap(dEB, C1, para_t, X, &w)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if(!member(w, para_t, X)) return + SM9_MEMBER_ERR; + printf("\n*********************** w = e(C1, deB):****************************\n"); + zzn12_ElementPrint(w); + + //Step3:Calculate plaintext + mlen = C_len - BNLEN * 2 - SM3_len / 8; + if(EncID == 0) + { + //Step3-1:calculate K=KDF(C1||w||IDB,klen) + klen = mlen + k2_len; + Zlen = strlen(IDB) + BNLEN * 14; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + K = (char *)malloc(sizeof(char)*(klen + 1)); + if(Z == NULL || K == NULL) + return SM9_ASK_MEMORY_ERR; + + LinkCharZzn12(C, BNLEN * 2, w, Z, Zlen - strlen(IDB)); + memcpy(Z + BNLEN * 14, IDB, strlen(IDB)); + SM3_kdf(Z, Zlen, klen, K); + printf("\n*****************K=KDF(C1||w||IDB,klen):***********************\n"); + for(i = 0; i < klen; i++) + printf("%02x", K[i]); + + //Step:3-2: calculate M=C2^K1,and test if K1==0? + for(i = 0; i < mlen; i++) + { + if(K[i] == 0) + number += 1; + M[i] = C[i + C_len - mlen] ^ K[i]; + } + if(number == mlen) + return SM9_ERR_K1_ZERO; + *Mlen = mlen; + + //Step4:calculate u=MAC(K2,C2) + SM9_standard_enc_mac(K + mlen, k2_len, &C[C_len - mlen], mlen, u); + if(memcmp(u, &C[BNLEN * 2], SM3_len / 8)) + return SM9_C3_MEMCMP_ERR; + + printf("\n****************************** M:******************************\n"); + for(i = 0; i < mlen; i++) + printf("%02x", M[i]); + free(Z); + free(K); + } + else + { + //Step:3-1: calculate K=KDF(C1||w||IDB,klen) + klen = k1_len + k2_len; + Zlen = strlen(IDB) + BNLEN * 14; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + K = (char *)malloc(sizeof(char)*(klen + 1)); + K1 = (char *)malloc(sizeof(char)*(k1_len + 1)); + if(Z == NULL || K == NULL || K1 == NULL) + return SM9_ASK_MEMORY_ERR; + + LinkCharZzn12(C, BNLEN * 2, w, Z, Zlen - strlen(IDB)); + memcpy(Z + BNLEN * 14, IDB, strlen(IDB)); + SM3_kdf(Z, Zlen, klen, K); + printf("\n*****************K=KDF(C1||w||IDB,klen):***********************\n"); + for(i = 0; i < klen; i++) + printf("%02x", K[i]); + + //Step:3-2: calculate M=dec(K1,C2),and test if K1==0? + for(i = 0; i < k1_len; i++) + { + if(K[i] == 0) + number += 1; + K1[i] = K[i]; + } + if(number == k1_len) + return SM9_ERR_K1_ZERO; + SM4_standard_block_decrypt(K1, &C[C_len - mlen], mlen, M, Mlen); + + //Step4:calculate u=MAC(K2,C2) + SM9_standard_enc_mac(K + k1_len, k2_len, &C[C_len - mlen], mlen, u); + if(memcmp(u, &C[BNLEN * 2], SM3_len / 8)) + return SM9_C3_MEMCMP_ERR; + free(Z); + free(K); + free(K1); + } + return 0; +} + + +int SM9_standard_enc_selfcheck() +{ + //the master private key + unsigned char KE[32] = {0x00, 0x01, 0xED, 0xEE, 0x37, 0x78, 0xF4, 0x41, 0xF8, 0xDE, 0xA3, 0xD9, 0xFA, 0x0A, 0xCC, 0x4E, + 0x07, 0xEE, 0x36, 0xC9, 0x3F, 0x9A, 0x08, 0x61, 0x8A, 0xF4, 0xAD, 0x85, 0xCE, 0xDE, 0x1C, 0x22}; + unsigned char rand[32] = {0x00, 0x00, 0xAA, 0xC0, 0x54, 0x17, 0x79, 0xC8, 0xFC, 0x45, 0xE3, 0xE2, 0xCB, 0x25, 0xC1, 0x2B, + 0x5D, 0x25, 0x76, 0xB2, 0x12, 0x9A, 0xE8, 0xBB, 0x5E, 0xE2, 0xCB, 0xE5, 0xEC, 0x9E, 0x78, 0x5C}; + //standard datas + unsigned char std_Ppub[64] = {0x78, 0x7E, 0xD7, 0xB8, 0xA5, 0x1F, 0x3A, 0xB8, 0x4E, 0x0A, 0x66, 0x00, 0x3F, 0x32, 0xDA, 0x5C, + 0x72, 0x0B, 0x17, 0xEC, 0xA7, 0x13, 0x7D, 0x39, 0xAB, 0xC6, 0x6E, 0x3C, 0x80, 0xA8, 0x92, 0xFF, + 0x76, 0x9D, 0xE6, 0x17, 0x91, 0xE5, 0xAD, 0xC4, 0xB9, 0xFF, 0x85, 0xA3, 0x13, 0x54, 0x90, 0x0B, + 0x20, 0x28, 0x71, 0x27, 0x9A, 0x8C, 0x49, 0xDC, 0x3F, 0x22, 0x0F, 0x64, 0x4C, 0x57, 0xA7, 0xB1}; + unsigned char std_deB[128] = {0x94, 0x73, 0x6A, 0xCD, 0x2C, 0x8C, 0x87, 0x96, 0xCC, 0x47, 0x85, 0xE9, 0x38, 0x30, 0x1A, 0x13, + 0x9A, 0x05, 0x9D, 0x35, 0x37, 0xB6, 0x41, 0x41, 0x40, 0xB2, 0xD3, 0x1E, 0xEC, 0xF4, 0x16, 0x83, + 0x11, 0x5B, 0xAE, 0x85, 0xF5, 0xD8, 0xBC, 0x6C, 0x3D, 0xBD, 0x9E, 0x53, 0x42, 0x97, 0x9A, 0xCC, + 0xCF, 0x3C, 0x2F, 0x4F, 0x28, 0x42, 0x0B, 0x1C, 0xB4, 0xF8, 0xC0, 0xB5, 0x9A, 0x19, 0xB1, 0x58, + 0x7A, 0xA5, 0xE4, 0x75, 0x70, 0xDA, 0x76, 0x00, 0xCD, 0x76, 0x0A, 0x0C, 0xF7, 0xBE, 0xAF, 0x71, + 0xC4, 0x47, 0xF3, 0x84, 0x47, 0x53, 0xFE, 0x74, 0xFA, 0x7B, 0xA9, 0x2C, 0xA7, 0xD3, 0xB5, 0x5F, + 0x27, 0x53, 0x8A, 0x62, 0xE7, 0xF7, 0xBF, 0xB5, 0x1D, 0xCE, 0x08, 0x70, 0x47, 0x96, 0xD9, 0x4C, + 0x9D, 0x56, 0x73, 0x4F, 0x11, 0x9E, 0xA4, 0x47, 0x32, 0xB5, 0x0E, 0x31, 0xCD, 0xEB, 0x75, 0xC1}; + unsigned char std_C_stream[116] = {0x24, 0x45, 0x47, 0x11, 0x64, 0x49, 0x06, 0x18, 0xE1, 0xEE, 0x20, 0x52, 0x8F, 0xF1, 0xD5, 0x45, + 0xB0, 0xF1, 0x4C, 0x8B, 0xCA, 0xA4, 0x45, 0x44, 0xF0, 0x3D, 0xAB, 0x5D, 0xAC, 0x07, 0xD8, 0xFF, + 0x42, 0xFF, 0xCA, 0x97, 0xD5, 0x7C, 0xDD, 0xC0, 0x5E, 0xA4, 0x05, 0xF2, 0xE5, 0x86, 0xFE, 0xB3, + 0xA6, 0x93, 0x07, 0x15, 0x53, 0x2B, 0x80, 0x00, 0x75, 0x9F, 0x13, 0x05, 0x9E, 0xD5, 0x9A, 0xC0, + 0xBA, 0x67, 0x23, 0x87, 0xBC, 0xD6, 0xDE, 0x50, 0x16, 0xA1, 0x58, 0xA5, 0x2B, 0xB2, 0xE7, 0xFC, + 0x42, 0x91, 0x97, 0xBC, 0xAB, 0x70, 0xB2, 0x5A, 0xFE, 0xE3, 0x7A, 0x2B, 0x9D, 0xB9, 0xF3, 0x67, + 0x1B, 0x5F, 0x5B, 0x0E, 0x95, 0x14, 0x89, 0x68, 0x2F, 0x3E, 0x64, 0xE1, 0x37, 0x8C, 0xDD, 0x5D, + 0xA9, 0x51, 0x3B, 0x1C}; + unsigned char std_C_cipher[128] = {0x24, 0x45, 0x47, 0x11, 0x64, 0x49, 0x06, 0x18, 0xE1, 0xEE, 0x20, 0x52, 0x8F, 0xF1, 0xD5, 0x45, + 0xB0, 0xF1, 0x4C, 0x8B, 0xCA, 0xA4, 0x45, 0x44, 0xF0, 0x3D, 0xAB, 0x5D, 0xAC, 0x07, 0xD8, 0xFF, + 0x42, 0xFF, 0xCA, 0x97, 0xD5, 0x7C, 0xDD, 0xC0, 0x5E, 0xA4, 0x05, 0xF2, 0xE5, 0x86, 0xFE, 0xB3, + 0xA6, 0x93, 0x07, 0x15, 0x53, 0x2B, 0x80, 0x00, 0x75, 0x9F, 0x13, 0x05, 0x9E, 0xD5, 0x9A, 0xC0, + 0xFD, 0x3C, 0x98, 0xDD, 0x92, 0xC4, 0x4C, 0x68, 0x33, 0x26, 0x75, 0xA3, 0x70, 0xCC, 0xEE, 0xDE, + 0x31, 0xE0, 0xC5, 0xCD, 0x20, 0x9C, 0x25, 0x76, 0x01, 0x14, 0x9D, 0x12, 0xB3, 0x94, 0xA2, 0xBE, + 0xE0, 0x5B, 0x6F, 0xAC, 0x6F, 0x11, 0xB9, 0x65, 0x26, 0x8C, 0x99, 0x4F, 0x00, 0xDB, 0xA7, 0xA8, + 0xBB, 0x00, 0xFD, 0x60, 0x58, 0x35, 0x46, 0xCB, 0xDF, 0x46, 0x49, 0x25, 0x08, 0x63, 0xF1, 0x0A}; + unsigned char *std_message = "Chinese IBE standard"; + unsigned char hid[] = {0x03}; + unsigned char *IDB = "Bob"; + + unsigned char Ppub[64], deB[128]; + unsigned char message[1000], C[1000]; + int M_len, C_len;//M_len the length of message //C_len the length of C + int k1_len = 16, k2_len = 32; + int EncID = 0;//0,stream //1 block + int tmp, i; + big ke; + + tmp = SM9_standard_init(); + if(tmp != 0) + return tmp; + + ke = mirvar(0); + bytes_to_big(32, KE, ke); + + printf("\n*********************** SM9 key Generation ***************************\n"); + tmp = SM9_standard_generateencryptkey(hid, IDB, strlen(IDB), ke, Ppub, deB); + if(tmp != 0) + return tmp; + if(memcmp(Ppub, std_Ppub, 64) != 0) + return SM9_GEPUB_ERR; + if(memcmp(deB, std_deB, 128) !=0) + return SM9_GEPRI_ERR; + + printf("\n*********************** SM9 encrypt algorithm **************************\n"); + tmp = SM9_standard_encrypt(hid, IDB, std_message, strlen(std_message), rand, EncID, k1_len, k2_len, Ppub, C, &C_len); + if(tmp != 0) + return tmp; + printf("\n******************************Cipher:************************************\n"); + for(i = 0; i < C_len; i++) + printf("%02x", C[i]); + if(EncID == 0) + tmp = memcmp(C, std_C_stream, C_len); + else + tmp = memcmp(C, std_C_cipher, C_len); + if(tmp) + return SM9_ENCRYPT_ERR; + + printf("\n********************** SM9 Decrypt algorithm **************************\n"); + tmp = SM9_standard_decrypt(std_C_cipher, 128, deB, IDB, 2, k1_len, k2_len, message, &M_len); + printf("\n**************************** Message:***********************************\n"); + for(i = 0; i < M_len; i++) + printf("%02x", message[i]); + if(tmp != 0) + return tmp; + if(memcmp(message, std_message, M_len) != 0) + return SM9_DECRYPT_ERR; + + return 0; +} diff --git a/engines/sm_standard/sm9/sm9_standard_encap.c b/engines/sm_standard/sm9/sm9_standard_encap.c new file mode 100644 index 00000000..a1c8128b --- /dev/null +++ b/engines/sm_standard/sm9/sm9_standard_encap.c @@ -0,0 +1,307 @@ +/* ==================================================================== + * 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. + * ==================================================================== + */ + + +#include "sm9_standard.h" +#include "miracl.h" +#include "mirdef.h" + + +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) +{ + big h, x, y, r; + epoint *Ppube, *QB, *Cipher; + unsigned char *Z = NULL; + int Zlen, buf, i, num = 0; + zzn12 g, w; + + //initiate + h = mirvar(0); + r = mirvar(0); + x = mirvar(0); + y = mirvar(0); + QB = epoint_init(); + Ppube = epoint_init(); + Cipher = epoint_init(); + zzn12_init(&g); + zzn12_init(&w); + + bytes_to_big(BNLEN, Ppub, x); + bytes_to_big(BNLEN, Ppub + BNLEN, y); + epoint_set(x, y, 0, Ppube); + + //----------Step1:calculate QB=[H1(IDB||hid,N)]P1+Ppube---------- + Zlen = strlen(IDB) + 1; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + memcpy(Z, IDB, strlen(IDB)); + memcpy(Z + strlen(IDB), hid, 1); + buf = SM9_standard_h1(Z, Zlen, N, h); + free(Z); + if(buf) + return buf; + printf("\n************************ H1(IDB||hid,N) ************************\n"); + cotnum(h, stdout); + + ecurve_mult(h, P1, QB); + ecurve_add(Ppube, QB); + printf("\n*******************QB:=[H1(IDB||hid,N)]P1+Ppube*****************\n"); + epoint_get(QB, x, y); + cotnum(x, stdout); + cotnum(y, stdout); + + //-------------------- Step2:randnom ------------------- + bytes_to_big(BNLEN, rand, r); + printf("\n***********************randnum r: ******************************\n"); + cotnum(r, stdout); + + //----------------Step3:C=[r]QB------------------------ + ecurve_mult(r, QB, Cipher); + epoint_get(Cipher, x, y); + printf("\n*********************** C=[r]QB: ******************************\n"); + cotnum(x, stdout); + cotnum(y, stdout); + big_to_bytes(BNLEN, x, C, 1); + big_to_bytes(BNLEN, y, C + BNLEN, 1); + + //----------------Step4:g=e(Ppube,P2)------------------------ + if(!ecap(P2, Ppube, para_t, X, &g)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if(!member(g, para_t, X)) + return SM9_MEMBER_ERR; + + printf("\n***********************g=e(Ppube,P2):****************************\n"); + zzn12_ElementPrint(g); + + //----------------Step5:w=g^r------------------------ + w = zzn12_pow(g, r); + printf("\n************************* w=g^r:*********************************\n"); + zzn12_ElementPrint(w); + + //----------------Step6:K=KDF(C||w||IDB,klen)------------------------ + Zlen = strlen(IDB) + BNLEN * 14; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + LinkCharZzn12(C, BNLEN * 2, w, Z, BNLEN * 14); + memcpy(Z + BNLEN * 14, IDB, strlen(IDB)); + + SM3_kdf(Z, Zlen, Klen, K); + free(Z); + //----------------test if K equals 0------------------------ + printf("\n******************* K=KDF(C||w||IDB,klen):***********************\n"); + for(i = 0; i < Klen; i++) + { + if(K[i] == 0) + num += 1; + printf("%02x", K[i]); + } + if(num == Klen) + return SM9_ERR_K1_ZERO; + + return 0; +} + + +int SM9_standard_key_decap(unsigned char *IDB, unsigned char deB[], unsigned char C[], int Klen, unsigned char K[]) +{ + big h, x, y; + epoint *Cipher; + unsigned char *Z = NULL; + int Zlen, i, num = 0; + zzn12 w; + ecn2 dEB; + + //initiate + h = mirvar(0); + x = mirvar(0); + y = mirvar(0); + Cipher = epoint_init(); + zzn12_init(&w); + 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; + + bytes_to_big(BNLEN, C, x); + bytes_to_big(BNLEN, C + BNLEN, y); + epoint_set(x, y, 0, Cipher); + bytes128_to_ecn2(deB, &dEB); + + //----------Step1:test if C is on G1----------------- + if(Test_Point(Cipher)) + return SM9_NOT_VALID_G1; + + //----------Step2:calculate w=e(C,deB)----------------- + if(!ecap(dEB, Cipher, para_t, X, &w)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if(!member(w, para_t, X)) + return SM9_MEMBER_ERR; + + printf("\n***********************w=e(C,deB):****************************\n"); + zzn12_ElementPrint(w); + + //----------Step3:K=KDF(C||w'||IDB,klen)------------------------ + Zlen = strlen(IDB) + BNLEN * 14; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + LinkCharZzn12(C, BNLEN * 2, w, Z, BNLEN * 14); + memcpy(Z + BNLEN * 14, IDB, strlen(IDB)); + SM3_kdf(Z, Zlen, Klen, K); + + //----------------test if K equals 0------------------------ + printf("\n******************* K=KDF(C||w||IDB,klen):***********************\n"); + for(i = 0; i < Klen; i++) + { + if(K[i] == 0) + num += 1; + printf("%02x", K[i]); + } + if(num == Klen) + return SM9_ERR_K1_ZERO; + + free(Z); + return 0; +} + + +int SM9_standard_encap_selfcheck() +{ + //the master private key + unsigned char KE[32] = {0x00, 0x01, 0xED, 0xEE, 0x37, 0x78, 0xF4, 0x41, 0xF8, 0xDE, 0xA3, 0xD9, 0xFA, 0x0A, 0xCC, 0x4E, + 0x07, 0xEE, 0x36, 0xC9, 0x3F, 0x9A, 0x08, 0x61, 0x8A, 0xF4, 0xAD, 0x85, 0xCE, 0xDE, 0x1C, 0x22}; + unsigned char rand[32] = {0x00, 0x00, 0x74, 0x01, 0x5F, 0x84, 0x89, 0xC0, 0x1E, 0xF4, 0x27, 0x04, 0x56, 0xF9, 0xE6, 0x47, + 0x5B, 0xFB, 0x60, 0x2B, 0xDE, 0x7F, 0x33, 0xFD, 0x48, 0x2A, 0xB4, 0xE3, 0x68, 0x4A, 0x67, 0x22}; + //standard datas + unsigned char std_Ppub[64] = {0x78, 0x7E, 0xD7, 0xB8, 0xA5, 0x1F, 0x3A, 0xB8, 0x4E, 0x0A, 0x66, 0x00, 0x3F, 0x32, 0xDA, 0x5C, + 0x72, 0x0B, 0x17, 0xEC, 0xA7, 0x13, 0x7D, 0x39, 0xAB, 0xC6, 0x6E, 0x3C, 0x80, 0xA8, 0x92, 0xFF, + 0x76, 0x9D, 0xE6, 0x17, 0x91, 0xE5, 0xAD, 0xC4, 0xB9, 0xFF, 0x85, 0xA3, 0x13, 0x54, 0x90, 0x0B, + 0x20, 0x28, 0x71, 0x27, 0x9A, 0x8C, 0x49, 0xDC, 0x3F, 0x22, 0x0F, 0x64, 0x4C, 0x57, 0xA7, 0xB1}; + unsigned char std_deB[128] = {0x94, 0x73, 0x6A, 0xCD, 0x2C, 0x8C, 0x87, 0x96, 0xCC, 0x47, 0x85, 0xE9, 0x38, 0x30, 0x1A, 0x13, + 0x9A, 0x05, 0x9D, 0x35, 0x37, 0xB6, 0x41, 0x41, 0x40, 0xB2, 0xD3, 0x1E, 0xEC, 0xF4, 0x16, 0x83, + 0x11, 0x5B, 0xAE, 0x85, 0xF5, 0xD8, 0xBC, 0x6C, 0x3D, 0xBD, 0x9E, 0x53, 0x42, 0x97, 0x9A, 0xCC, + 0xCF, 0x3C, 0x2F, 0x4F, 0x28, 0x42, 0x0B, 0x1C, 0xB4, 0xF8, 0xC0, 0xB5, 0x9A, 0x19, 0xB1, 0x58, + 0x7A, 0xA5, 0xE4, 0x75, 0x70, 0xDA, 0x76, 0x00, 0xCD, 0x76, 0x0A, 0x0C, 0xF7, 0xBE, 0xAF, 0x71, + 0xC4, 0x47, 0xF3, 0x84, 0x47, 0x53, 0xFE, 0x74, 0xFA, 0x7B, 0xA9, 0x2C, 0xA7, 0xD3, 0xB5, 0x5F, + 0x27, 0x53, 0x8A, 0x62, 0xE7, 0xF7, 0xBF, 0xB5, 0x1D, 0xCE, 0x08, 0x70, 0x47, 0x96, 0xD9, 0x4C, + 0x9D, 0x56, 0x73, 0x4F, 0x11, 0x9E, 0xA4, 0x47, 0x32, 0xB5, 0x0E, 0x31, 0xCD, 0xEB, 0x75, 0xC1}; + unsigned char std_K[64] = {0x4F, 0xF5, 0xCF, 0x86, 0xD2, 0xAD, 0x40, 0xC8, 0xF4, 0xBA, 0xC9, 0x8D, 0x76, 0xAB, 0xDB, 0xDE, + 0x0C, 0x0E, 0x2F, 0x0A, 0x82, 0x9D, 0x3F, 0x91, 0x1E, 0xF5, 0xB2, 0xBC, 0xE0, 0x69, 0x54, 0x80}; + unsigned char std_C[64] = {0x1E, 0xDE, 0xE2, 0xC3, 0xF4, 0x65, 0x91, 0x44, 0x91, 0xDE, 0x44, 0xCE, 0xFB, 0x2C, 0xB4, 0x34, + 0xAB, 0x02, 0xC3, 0x08, 0xD9, 0xDC, 0x5E, 0x20, 0x67, 0xB4, 0xFE, 0xD5, 0xAA, 0xAC, 0x8A, 0x0F, + 0x1C, 0x9B, 0x4C, 0x43, 0x5E, 0xCA, 0x35, 0xAB, 0x83, 0xBB, 0x73, 0x41, 0x74, 0xC0, 0xF7, 0x8F, + 0xDE, 0x81, 0xA5, 0x33, 0x74, 0xAF, 0xF3, 0xB3, 0x60, 0x2B, 0xBC, 0x5E, 0x37, 0xBE, 0x9A, 0x4C}; + + unsigned char hid[] = {0x03}, *IDB = "Bob"; + unsigned char Ppub[64], deB[128], C[64], K[32], K_decap[32]; + big ke; + int tmp, i; + int Klen = 32; + + mip = mirsys(1000, 16); + mip->IOBASE = 16; + ke = mirvar(0); + bytes_to_big(32, KE, ke); + + tmp = SM9_standard_init(); + if(tmp != 0) + return tmp; + + printf("\n*********************** SM9 key Generation ***************************\n"); + tmp = SM9_standard_generateencryptkey(hid, IDB, strlen(IDB), ke, Ppub, deB); + if(tmp != 0) + return tmp; + if(memcmp(Ppub, std_Ppub, 64) != 0) + return SM9_GEPUB_ERR; + if(memcmp(deB, std_deB, 128) != 0) + return SM9_GEPRI_ERR; + + printf("\n**********************PublicKey Ppubs=[ke]P1:*************************\n"); + for(i = 0; i < 64; i++) + { + if(i == 32) + printf("\n"); + printf("%02x", Ppub[i]); + } + printf("\n**************The private key deB = (xdeB, ydeB):*********************\n"); + for(i = 0; i < 128; i++) + { + if(i == 64) + printf("\n"); + printf("%02x", deB[i]); + } + + printf("\n///////////////////SM9 Key encapsulation mechanism//////////////////////\n"); + tmp = SM9_standard_key_encap(hid, IDB, rand, Ppub, C, K, Klen); + if(tmp != 0) + return tmp; + + if(memcmp(C, std_C, 64) != 0) + return SM9_ERR_Encap_C; + if(memcmp(K, std_K, Klen) != 0) + return SM9_ERR_Encap_K; + + printf("\n///////////////////SM9 Key decapsulation mechanism//////////////////////\n"); + tmp = SM9_standard_key_decap(IDB, deB, C, Klen, K_decap); + if(tmp != 0) + return tmp; + + if(memcmp(K_decap, std_K, 32) != 0) + return SM9_ERR_Decap_K; + + return 0; +} diff --git a/engines/sm_standard/sm9/sm9_standard_exch.c b/engines/sm_standard/sm9/sm9_standard_exch.c new file mode 100644 index 00000000..be986dfc --- /dev/null +++ b/engines/sm_standard/sm9/sm9_standard_exch.c @@ -0,0 +1,525 @@ +/* ==================================================================== + * 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. + * ==================================================================== + */ + + +#include "sm9_standard.h" +#include "miracl.h" +#include "mirdef.h" + + +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[]) +{ + unsigned char *Z = NULL; + int Zlen; + int IDALen = strlen(IDA), IDBLen = strlen(IDB); + big x1, y1, x2, y2; + + x1 = mirvar(0); + y1 = mirvar(0); + x2 = mirvar(0); + y2 = mirvar(0); + epoint_get(RA, x1, y1); + epoint_get(RB, x2, y2); + + Zlen = IDALen + IDBLen + BNLEN * 40; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + + memcpy(Z, IDA, IDALen); + memcpy(Z + IDALen, IDB, IDBLen); + big_to_bytes(BNLEN, x1, Z + IDALen + IDBLen, 1); + big_to_bytes(BNLEN, y1, Z + IDALen + IDBLen + BNLEN, 1); + big_to_bytes(BNLEN, x2, Z + IDALen + IDBLen + BNLEN * 2, 1); + big_to_bytes(BNLEN, y2, Z + IDALen + IDBLen + BNLEN * 3, 1); + LinkCharZzn12(Z, 0, g1, Z + IDALen + IDBLen + BNLEN * 4, BNLEN * 12); + LinkCharZzn12(Z, 0, g2, Z + IDALen + IDBLen + BNLEN * 16, BNLEN * 12); + LinkCharZzn12(Z, 0, g3, Z + IDALen + IDBLen + BNLEN * 28, BNLEN * 12); + + SM3_kdf(Z, Zlen, klen, K); + free(Z); + return 0; +} + + +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[]) +{ + int Zlen; + int IDALen = strlen(IDA), IDBLen = strlen(IDB); + unsigned char *Z = NULL; + big x1, y1, x2, y2; + + x1 = mirvar(0); + y1 = mirvar(0); + x2 = mirvar(0); + y2 = mirvar(0); + epoint_get(RA, x1, y1); + epoint_get(RB, x2, y2); + + Zlen = IDALen + IDBLen + BNLEN * 28; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + + LinkCharZzn12(Z, 0, g2, Z, BNLEN * 12); + LinkCharZzn12(Z, 0, g3, Z + BNLEN * 12, BNLEN * 12); + memcpy(Z + BNLEN * 24, IDA, IDALen); + memcpy(Z + BNLEN * 24 + IDALen, IDB, IDBLen); + big_to_bytes(BNLEN, x1, Z + BNLEN * 24 + IDALen + IDBLen, 1); + big_to_bytes(BNLEN, y1, Z + BNLEN * 25 + IDALen + IDBLen, 1); + big_to_bytes(BNLEN, x2, Z + BNLEN * 26 + IDALen + IDBLen, 1); + big_to_bytes(BNLEN, y2, Z + BNLEN * 27 + IDALen + IDBLen, 1); + + SM3_256(Z, Zlen, hash); + + Zlen = 1 + BNLEN * 12 + SM3_len / 8; + memcpy(Z, hashid, 1); + LinkCharZzn12(Z, 1, g1, Z, 1 + BNLEN * 12); + memcpy(Z + 1 + BNLEN * 12, hash, SM3_len / 8); + + SM3_256(Z, Zlen, hash); + free(Z); + return 0; +} + + +int SM9_standard_keyex_inita_i(unsigned char hid[], unsigned char *IDB, unsigned char randA[], + unsigned char Ppub[], unsigned char deA[], epoint *RA) +{ + big h, x, y, rA; + epoint *Ppube, *QB; + unsigned char *Z = NULL; + int Zlen, buf; + + //initiate + h = mirvar(0); + rA = mirvar(0); + x = mirvar(0); + y = mirvar(0); + QB = epoint_init(); + Ppube = epoint_init(); + + bytes_to_big(BNLEN, Ppub, x); + bytes_to_big(BNLEN, Ppub + BNLEN, y); + epoint_set(x, y, 0, Ppube); + + //----------A1:calculate QB=[H1(IDB||hid,N)]P1+Ppube---------- + Zlen = strlen(IDB) + 1; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + memcpy(Z, IDB, strlen(IDB)); + memcpy(Z + strlen(IDB), hid, 1); + buf = SM9_standard_h1(Z, Zlen, N, h); + if(buf) + return buf; + ecurve_mult(h, P1, QB); + ecurve_add(Ppube, QB); + printf("\n*******************QB:=[H1(IDB||hid,N)]P1+Ppube*****************\n"); + epoint_get(QB, x, y); + cotnum(x, stdout); + cotnum(y, stdout); + + //--------------- Step A2:randnom ------------------- + bytes_to_big(BNLEN, randA, rA); + printf("\n***********************randnum rA:******************************\n"); + cotnum(rA, stdout); + + //----------------Step A3:RA=[r]QB + ecurve_mult(rA, QB, RA); + + free(Z); + return 0; +} + + + +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) +{ + big h, x, y, rB; + epoint *Ppube, *QA; + unsigned char *Z = NULL, hashid[] = {0x82}; + unsigned char SKB[16]; + ecn2 dEB; + int Zlen, buf, i; + + //initiate + h = mirvar(0); + rB = mirvar(0); + x = mirvar(0); + y = mirvar(0); + QA = epoint_init(); + Ppube = 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; + + bytes_to_big(BNLEN, Ppub, x); + bytes_to_big(BNLEN, Ppub + BNLEN, y); + bytes128_to_ecn2(deB, &dEB); + epoint_set(x, y, 0, Ppube); + + //----------B1:calculate QA=[H1(IDA||hid,N)]P1+Ppube---------- + Zlen = strlen(IDA) + 1; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + memcpy(Z, IDA, strlen(IDA)); + memcpy(Z + strlen(IDA), hid, 1); + + buf = SM9_standard_h1(Z, Zlen, N, h); + if(buf) + return buf; + ecurve_mult(h, P1, QA); + ecurve_add(Ppube, QA); + printf("\n*******************QA:=[H1(IDA||hid,N)]P1+Ppube*****************\n"); + epoint_get(QA, x, y); + cotnum(x, stdout); + cotnum(y, stdout); + + //--------------- Step B2:randnom ------------------- + bytes_to_big(BNLEN, randB, rB); + printf("\n***********************randnum rB:********************************\n"); + cotnum(rB, stdout); + + //----------------Step B3:RB=[rB]QA------------------ + ecurve_mult(rB, QA, RB); + printf("\n*************************:RB=[rB]QA*******************************\n"); + epoint_get(RB, x, y); + cotnum(x, stdout); + cotnum(y, stdout); + + //test if RA is on G1 + if(Test_Point(RA)) + return SM9_NOT_VALID_G1; + + //----------------Step B4:g1=e(deB,RA),g2=(e(P2,Ppube))^rB,g3=g1^rB + if(!ecap(dEB, RA, para_t, X, g1)) + return SM9_MY_ECAP_12A_ERR; + if(!ecap(P2, Ppube, para_t, X, g2)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if((!member(*g1, para_t, X)) || (!member(*g2, para_t, X))) + return SM9_MEMBER_ERR; + + *g2 = zzn12_pow(*g2, rB); + *g3 = zzn12_pow(*g1, rB); + + printf("\n***********************g1=e(RA,deB):****************************\n"); + zzn12_ElementPrint(*g1); + printf("\n*******************g2=(e(P2,Ppub3))^rB:*************************\n"); + zzn12_ElementPrint(*g2); + printf("\n***********************g3=g1^rB:********************************\n"); + zzn12_ElementPrint(*g3); + + //---------------- B5:SKB=KDF(IDA||IDB||RA||RB||g1||g2||g3,klen)---------- + buf = SM9_standard_keyex_kdf(IDA, IDB, RA, RB, *g1, *g2, *g3, 16, SKB); + if(buf) + return buf; + printf("\n***********SKB=KDF(IDA||IDB||RA||RB||g1||g2||g3,klen):***********\n"); + for(i = 0; i < 16; i++) + printf("%02x", SKB[i]); + + //---------------- B6(optional):SB=Hash(0x82||g1||Hash(g2||g3||IDA||IDB||RA||RB))---------- + buf = SM9_standard_keyex_hash(hashid, IDA, IDB, RA, RB, *g1, *g2, *g3, SB); + if(buf) + return buf; + printf("\n********SB=Hash(0x82||g1||Hash(g2||g3||IDA||IDB||RA||RB))********\n"); + for(i = 0; i < SM3_len / 8; i++) + printf("%02x", SB[i]); + + free(Z); + return 0; +} + + +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[]) +{ + big h, x, y, rA; + epoint *Ppube; + unsigned char hashid[] = {0x82}; + unsigned char S1[SM3_len / 8], SKA[16]; + zzn12 g1, g2, g3; + ecn2 dEA; + int buf, i; + + //initiate + h = mirvar(0); + rA = mirvar(0); + x = mirvar(0); + y = mirvar(0); + Ppube = epoint_init(); + dEA.x.a = mirvar(0); + dEA.x.b = mirvar(0); + dEA.y.a = mirvar(0); + dEA.y.b = mirvar(0); + dEA.z.a = mirvar(0); + dEA.z.b = mirvar(0); + dEA.marker = MR_EPOINT_INFINITY; + zzn12_init(&g1); + zzn12_init(&g2); + zzn12_init(&g3); + + bytes_to_big(BNLEN, Ppub, x); + bytes_to_big(BNLEN, Ppub + BNLEN, y); + bytes_to_big(BNLEN, randA, rA); + bytes128_to_ecn2(deA, &dEA); + epoint_set(x, y, 0, Ppube); + + //test if RB is on G1 + if(Test_Point(RB)) + return SM9_NOT_VALID_G1; + + //----------------Step A5:g1=(e(P2,Ppube))^rA,g2=e(deA,RB),g3=g2^rA--------- + if(!ecap(P2, Ppube, para_t, X, &g1)) + return SM9_MY_ECAP_12A_ERR; + if(!ecap(dEA, RB, para_t, X, &g2)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if((!member(g1, para_t, X)) || (!member(g2, para_t, X))) + return SM9_MEMBER_ERR; + + g1 = zzn12_pow(g1, rA); + g3 = zzn12_pow(g2, rA); + printf("\n***********************g1=e(Ppub,P2):****************************\n"); + zzn12_ElementPrint(g1); + printf("\n*******************g2=(e(RB,deA))^rB:*************************\n"); + zzn12_ElementPrint(g2); + printf("\n***********************g3=g2^rB:********************************\n"); + zzn12_ElementPrint(g3); + + //------------------ A6:S1=Hash(0x82||g1||Hash(g2||g3||IDA||IDB||RA||RB))---------- + buf = SM9_standard_keyex_hash(hashid, IDA, IDB, RA, RB, g1, g2, g3, S1); + if(buf) + return buf; + printf("\n*********S1=Hash(0x82||g1||Hash(g2||g3||IDA||IDB||RA||RB))********\n"); + for(i = 0; i < SM3_len / 8; i++) + printf("%02x", S1[i]); + + if(memcmp(S1, SB, SM3_len / 8)) + return SM9_ERR_CMP_S1SB; + + //---------- A7: SKA=KDF(IDA||IDB||RA||RB||g1||g2||g3,klen)---------- + buf = SM9_standard_keyex_kdf(IDA, IDB, RA, RB, g1, g2, g3, 16, SKA); + if(buf) + return buf; + printf("\n************SKA=KDF(IDA||IDB||RA||RB||g1||g2||g3,klen)************\n"); + for(i = 0; i < 16; i++) + printf("%02x", SKA[i]); + + //--------- A8(optional):SA=Hash(0x83||g1||Hash(g2||g3||IDA||IDB||RA||RB))---------- + hashid[0] = (unsigned char)0x83; + buf = SM9_standard_keyex_hash(hashid, IDA, IDB, RA, RB, g1, g2, g3, SA); + if(buf) + return buf; + printf("\n*********SA=Hash(0x83||g1||Hash(g2||g3||IDA||IDB||RA||RB))********\n"); + for(i = 0; i < SM3_len / 8; i++) + printf("%02x", SA[i]); + + return 0; +} + + +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[]) +{ + unsigned char hashid[] = {0x83}; + unsigned char S2[SM3_len / 8]; + int buf, i; + + //---------------- B8(optional):S2=Hash(0x83||g1||Hash(g2||g3||IDA||IDB||RA||RB))---------- + buf = SM9_standard_keyex_hash(hashid, IDA, IDB, RA, RB, g1, g2, g3, S2); + if(buf) + return buf; + printf("\n*************** S2=Hash(0x83||g1||Hash(g2||g3||IDA||IDB||RA||RB))****************\n"); + for(i = 0; i < SM3_len / 8; i++) + printf("%02x", S2[i]); + + if(memcmp(S2, SA, SM3_len / 8)) + return SM9_ERR_CMP_S2SA; + return 0; +} + + +int SM9_standard_exch_selfcheck() +{ + //the master private key + unsigned char KE[32] = {0x00, 0x02, 0xE6, 0x5B, 0x07, 0x62, 0xD0, 0x42, 0xF5, 0x1F, 0x0D, 0x23, 0x54, 0x2B, 0x13, 0xED, + 0x8C, 0xFA, 0x2E, 0x9A, 0x0E, 0x72, 0x06, 0x36, 0x1E, 0x01, 0x3A, 0x28, 0x39, 0x05, 0xE3, 0x1F}; + unsigned char randA[32] = {0x00, 0x00, 0x58, 0x79, 0xDD, 0x1D, 0x51, 0xE1, 0x75, 0x94, 0x6F, 0x23, 0xB1, 0xB4, 0x1E, 0x93, + 0xBA, 0x31, 0xC5, 0x84, 0xAE, 0x59, 0xA4, 0x26, 0xEC, 0x10, 0x46, 0xA4, 0xD0, 0x3B, 0x06, 0xC8}; + unsigned char randB[32] = {0x00, 0x01, 0x8B, 0x98, 0xC4, 0x4B, 0xEF, 0x9F, 0x85, 0x37, 0xFB, 0x7D, 0x07, 0x1B, 0x2C, 0x92, + 0x8B, 0x3B, 0xC6, 0x5B, 0xD3, 0xD6, 0x9E, 0x1E, 0xEE, 0x21, 0x35, 0x64, 0x90, 0x56, 0x34, 0xFE}; + //standard datas + unsigned char std_Ppub[64] = {0x91, 0x74, 0x54, 0x26, 0x68, 0xE8, 0xF1, 0x4A, 0xB2, 0x73, 0xC0, 0x94, 0x5C, 0x36, 0x90, 0xC6, + 0x6E, 0x5D, 0xD0, 0x96, 0x78, 0xB8, 0x6F, 0x73, 0x4C, 0x43, 0x50, 0x56, 0x7E, 0xD0, 0x62, 0x83, + 0x54, 0xE5, 0x98, 0xC6, 0xBF, 0x74, 0x9A, 0x3D, 0xAC, 0xC9, 0xFF, 0xFE, 0xDD, 0x9D, 0xB6, 0x86, + 0x6C, 0x50, 0x45, 0x7C, 0xFC, 0x7A, 0xA2, 0xA4, 0xAD, 0x65, 0xC3, 0x16, 0x8F, 0xF7, 0x42, 0x10}; + unsigned char std_deA[128] = {0x0F, 0xE8, 0xEA, 0xB3, 0x95, 0x19, 0x9B, 0x56, 0xBF, 0x1D, 0x75, 0xBD, 0x2C, 0xD6, 0x10, 0xB6, + 0x42, 0x4F, 0x08, 0xD1, 0x09, 0x29, 0x22, 0xC5, 0x88, 0x2B, 0x52, 0xDC, 0xD6, 0xCA, 0x83, 0x2A, + 0x7D, 0xA5, 0x7B, 0xC5, 0x02, 0x41, 0xF9, 0xE5, 0xBF, 0xDD, 0xC0, 0x75, 0xDD, 0x9D, 0x32, 0xC7, + 0x77, 0x71, 0x00, 0xD7, 0x36, 0x91, 0x6C, 0xFC, 0x16, 0x5D, 0x8D, 0x36, 0xE0, 0x63, 0x4C, 0xD7, + 0x83, 0xA4, 0x57, 0xDA, 0xF5, 0x2C, 0xAD, 0x46, 0x4C, 0x90, 0x3B, 0x26, 0x06, 0x2C, 0xAF, 0x93, + 0x7B, 0xB4, 0x0E, 0x37, 0xDA, 0xDE, 0xD9, 0xED, 0xA4, 0x01, 0x05, 0x0E, 0x49, 0xC8, 0xAD, 0x0C, + 0x69, 0x70, 0x87, 0x6B, 0x9A, 0xAD, 0x1B, 0x7A, 0x50, 0xBB, 0x48, 0x63, 0xA1, 0x1E, 0x57, 0x4A, + 0xF1, 0xFE, 0x3C, 0x59, 0x75, 0x16, 0x1D, 0x73, 0xDE, 0x4C, 0x3A, 0xF6, 0x21, 0xFB, 0x1E, 0xFB}; + unsigned char std_deB[128] = {0x74, 0xCC, 0xC3, 0xAC, 0x9C, 0x38, 0x3C, 0x60, 0xAF, 0x08, 0x39, 0x72, 0xB9, 0x6D, 0x05, 0xC7, + 0x5F, 0x12, 0xC8, 0x90, 0x7D, 0x12, 0x8A, 0x17, 0xAD, 0xAF, 0xBA, 0xB8, 0xC5, 0xA4, 0xAC, 0xF7, + 0x01, 0x09, 0x2F, 0xF4, 0xDE, 0x89, 0x36, 0x26, 0x70, 0xC2, 0x17, 0x11, 0xB6, 0xDB, 0xE5, 0x2D, + 0xCD, 0x5F, 0x8E, 0x40, 0xC6, 0x65, 0x4B, 0x3D, 0xEC, 0xE5, 0x73, 0xC2, 0xAB, 0x3D, 0x29, 0xB2, + 0x44, 0xB0, 0x29, 0x4A, 0xA0, 0x42, 0x90, 0xE1, 0x52, 0x4F, 0xF3, 0xE3, 0xDA, 0x8C, 0xFD, 0x43, + 0x2B, 0xB6, 0x4D, 0xE3, 0xA8, 0x04, 0x0B, 0x5B, 0x88, 0xD1, 0xB5, 0xFC, 0x86, 0xA4, 0xEB, 0xC1, + 0x8C, 0xFC, 0x48, 0xFB, 0x4F, 0xF3, 0x7F, 0x1E, 0x27, 0x72, 0x74, 0x64, 0xF3, 0xC3, 0x4E, 0x21, + 0x53, 0x86, 0x1A, 0xD0, 0x8E, 0x97, 0x2D, 0x16, 0x25, 0xFC, 0x1A, 0x7B, 0xD1, 0x8D, 0x55, 0x39}; + unsigned char std_RA[64] = {0x7C, 0xBA, 0x5B, 0x19, 0x06, 0x9E, 0xE6, 0x6A, 0xA7, 0x9D, 0x49, 0x04, 0x13, 0xD1, 0x18, 0x46, + 0xB9, 0xBA, 0x76, 0xDD, 0x22, 0x56, 0x7F, 0x80, 0x9C, 0xF2, 0x3B, 0x6D, 0x96, 0x4B, 0xB2, 0x65, + 0xA9, 0x76, 0x0C, 0x99, 0xCB, 0x6F, 0x70, 0x63, 0x43, 0xFE, 0xD0, 0x56, 0x37, 0x08, 0x58, 0x64, + 0x95, 0x8D, 0x6C, 0x90, 0x90, 0x2A, 0xBA, 0x7D, 0x40, 0x5F, 0xBE, 0xDF, 0x7B, 0x78, 0x15, 0x99}; + unsigned char std_RB[64] = {0x86, 0x1E, 0x91, 0x48, 0x5F, 0xB7, 0x62, 0x3D, 0x27, 0x94, 0xF4, 0x95, 0x03, 0x1A, 0x35, 0x59, + 0x8B, 0x49, 0x3B, 0xD4, 0x5B, 0xE3, 0x78, 0x13, 0xAB, 0xC7, 0x10, 0xFC, 0xC1, 0xF3, 0x44, 0x82, + 0x32, 0xD9, 0x06, 0xA4, 0x69, 0xEB, 0xC1, 0x21, 0x6A, 0x80, 0x2A, 0x70, 0x52, 0xD5, 0x61, 0x7C, + 0xD4, 0x30, 0xFB, 0x56, 0xFB, 0xA7, 0x29, 0xD4, 0x1D, 0x9B, 0xD6, 0x68, 0xE9, 0xEB, 0x96, 0x00}; + unsigned char std_SA[32] = {0x19, 0x5D, 0x1B, 0x72, 0x56, 0xBA, 0x7E, 0x0E, 0x67, 0xC7, 0x12, 0x02, 0xA2, 0x5F, 0x8C, 0x94, + 0xFF, 0x82, 0x41, 0x70, 0x2C, 0x2F, 0x55, 0xD6, 0x13, 0xAE, 0x1C, 0x6B, 0x98, 0x21, 0x51, 0x72}; + unsigned char std_SB[32] = {0x3B, 0xB4, 0xBC, 0xEE, 0x81, 0x39, 0xC9, 0x60, 0xB4, 0xD6, 0x56, 0x6D, 0xB1, 0xE0, 0xD5, 0xF0, + 0xB2, 0x76, 0x76, 0x80, 0xE5, 0xE1, 0xBF, 0x93, 0x41, 0x03, 0xE6, 0xC6, 0x6E, 0x40, 0xFF, 0xEE}; + + unsigned char hid[] = {0x02}, *IDA = "Alice", *IDB = "Bob"; + unsigned char Ppub[64], deA[128], deB[128]; + unsigned char xy[64], SA[SM3_len / 8], SB[SM3_len / 8]; + epoint *RA, *RB; + big ke, x, y; + zzn12 g1, g2, g3; + int tmp, i; + + mip = mirsys(1000, 16); + mip->IOBASE = 16; + x = mirvar(0); + y = mirvar(0); + ke = mirvar(0); + bytes_to_big(32, KE, ke); + RA = epoint_init(); + RB = epoint_init(); + zzn12_init(&g1); + zzn12_init(&g2); + zzn12_init(&g3); + + tmp = SM9_standard_init(); + if(tmp != 0) + return tmp; + + printf("\n*********************** SM9 key Generation ***************************\n"); + tmp = SM9_standard_generateencryptkey(hid, IDA, strlen(IDA), ke, Ppub, deA); + if(tmp != 0) + return tmp; + tmp = SM9_standard_generateencryptkey(hid, IDB, strlen(IDB), ke, Ppub, deB); + if(tmp != 0) + return tmp; + if(memcmp(Ppub, std_Ppub, 64) != 0) + return SM9_GEPUB_ERR; + if(memcmp(deA, std_deA, 128) != 0) + return SM9_GEPRI_ERR; + if(memcmp(deB, std_deB, 128) != 0) + return SM9_GEPRI_ERR; + + printf("\n**********************PublicKey Ppubs=[ke]P1:*************************\n"); + for(i = 0; i < 64; i++) + printf("%02x", Ppub[i]); + printf("\n**************The private key deA = (xdeA, ydeA):*********************\n"); + for(i = 0; i < 128; i++) + printf("%02x", deA[i]); + printf("\n**************The private key deB = (xdeB, ydeB):*********************\n"); + for(i = 0; i < 128; i++) + printf("%02x", deB[i]); + + printf("\n//////////////////// SM9 Key exchange A1-A4://////////////////////////\n"); + tmp = SM9_standard_keyex_inita_i(hid, IDB, randA, Ppub, deA, RA); + if(tmp != 0) + return tmp; + printf("\n ////////////////////////////:RA=[r]QB //////////////////////////////\n"); + epoint_get(RA, x, y); + cotnum(x, stdout); + cotnum(y, stdout); + big_to_bytes(BNLEN, x, xy, 1); + big_to_bytes(BNLEN, y, xy + BNLEN, 1); + if(memcmp(xy, std_RA, BNLEN * 2) != 0) + return SM9_ERR_RA; + + printf("\n//////////////////////// SM9 Key exchange B1-B7:///////////////////////\n"); + tmp = SM9_standard_keyex_reb_i(hid, IDA, IDB, randB, Ppub, deB, RA, RB, SB, &g1, &g2, &g3); + if(tmp != 0) + return tmp; + epoint_get(RB, x, y); + big_to_bytes(BNLEN, x, xy, 1); + big_to_bytes(BNLEN, y, xy + BNLEN, 1); + + if(memcmp(xy, std_RB, BNLEN * 2) != 0) + return SM9_ERR_RB; + if(memcmp(SB, std_SB, SM3_len / 8) != 0) + return SM9_ERR_SB; + + printf("\n//////////////////////// SM9 Key exchange A5-A8:///////////////////////\n"); + tmp = SM9_standard_keyex_inita_ii(IDA, IDB, randA, Ppub, deA, RA, RB, SB, SA); + if(tmp!=0) + return tmp; + if(memcmp(SA, std_SA, SM3_len / 8) != 0) + return SM9_ERR_SA; + + printf("\n//////////////////////// SM9 Key exchange B8:///////////////////////\n"); + tmp = SM9_standard_keyex_reb_ii(IDA, IDB, g1, g2, g3, RA, RB, SA); + if(tmp != 0) + return tmp; + + return 0; +} diff --git a/engines/sm_standard/sm9/sm9_standard_sv.c b/engines/sm_standard/sm9/sm9_standard_sv.c new file mode 100644 index 00000000..f27fc534 --- /dev/null +++ b/engines/sm_standard/sm9/sm9_standard_sv.c @@ -0,0 +1,446 @@ +/* ==================================================================== + * 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. + * ==================================================================== + */ + + +#include "sm9_standard.h" +#include "miracl.h" +#include "mirdef.h" +#include + + +int SM9_standard_h2(unsigned char Z[], int Zlen, big n, big h2) +{ + int hlen, ZHlen, i; + 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] = 0x02; + 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, h2); + free(ZH); + free(ha); + return 0; +} + + + +int SM9_standard_generatesignkey(unsigned char hid[], unsigned char *ID, int IDlen, big ks, unsigned char Ppubs[], unsigned char dsa[]) +{ + big h1, t1, t2, rem, xdSA, ydSA, tmp; + unsigned char *Z = NULL; + int Zlen = IDlen + 1, buf; + ecn2 Ppub; + epoint *dSA; + + h1 = mirvar(0); + t1 = mirvar(0); + t2 = mirvar(0); + rem = mirvar(0); + tmp = mirvar(0); + xdSA = mirvar(0); + ydSA = mirvar(0); + dSA = epoint_init(); + Ppub.x.a = mirvar(0); + Ppub.x.b = mirvar(0); + Ppub.y.a = mirvar(0); + Ppub.y.b = mirvar(0); + Ppub.z.a = mirvar(0); + Ppub.z.b = mirvar(0); + Ppub.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, ks, t1);//t1=H1(IDA||hid,N)+ks + xgcd(t1, N, t1, t1, t1);//t1=t1(-1) + multiply(ks, t1, t2); + divide(t2, N, rem);//t2=ks*t1(-1) + + //dSA=[t2]P1 + ecurve_mult(t2, P1, dSA); + + //Ppub=[ks]P2 + ecn2_copy(&P2, &Ppub); + ecn2_mul(ks, &Ppub); + + printf("\n*********************The signed key = (xdA, ydA):*********************\n"); + epoint_get(dSA, xdSA, ydSA); + cotnum(xdSA, stdout); + cotnum(ydSA, stdout); + printf("\n**********************PublicKey Ppubs=[ks]P2:*************************\n"); + ecn2_Bytes128_Print(Ppub); + + epoint_get(dSA, xdSA, ydSA); + big_to_bytes(BNLEN, xdSA, dsa, 1); + big_to_bytes(BNLEN, ydSA, dsa + BNLEN, 1); + + redc(Ppub.x.b, tmp); + big_to_bytes(BNLEN, tmp, Ppubs, 1); + redc(Ppub.x.a, tmp); + big_to_bytes(BNLEN, tmp, Ppubs + BNLEN, 1); + redc(Ppub.y.b, tmp); + big_to_bytes(BNLEN, tmp, Ppubs + BNLEN * 2, 1); + redc(Ppub.y.a, tmp); + big_to_bytes(BNLEN, tmp, Ppubs + BNLEN * 3, 1); + + free(Z); + return 0; +} + + +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[]) +{ + big h1, r, h, l, xdSA, ydSA; + big xS, yS, tmp, zero; + zzn12 g, w; + epoint *s, *dSA; + ecn2 Ppubs; + int Zlen, buf; + unsigned char *Z = NULL; + + //initiate + h1 = mirvar(0); + r = mirvar(0); + h = mirvar(0); + l = mirvar(0); + tmp = mirvar(0); + zero = mirvar(0); + xS = mirvar(0); + yS = mirvar(0); + xdSA = mirvar(0); + ydSA = mirvar(0); + s = epoint_init(); + dSA = epoint_init(); + Ppubs.x.a = mirvar(0); + Ppubs.x.b = mirvar(0); + Ppubs.y.a = mirvar(0); + Ppubs.y.b = mirvar(0); + Ppubs.z.a = mirvar(0); + Ppubs.z.b = mirvar(0); + Ppubs.marker = MR_EPOINT_INFINITY; + zzn12_init(&g); + zzn12_init(&w); + + bytes_to_big(BNLEN, rand, r); + bytes_to_big(BNLEN, dsa, xdSA); + bytes_to_big(BNLEN, dsa + BNLEN, ydSA); + epoint_set(xdSA, ydSA, 0, dSA); + bytes128_to_ecn2(Ppub, &Ppubs); + + //Step1:g = e(P1, Ppub-s) + if(!ecap(Ppubs, P1, para_t, X, &g)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if(!member(g, para_t, X)) + return SM9_MEMBER_ERR; + + printf("\n***********************g=e(P1,Ppubs):****************************\n"); + zzn12_ElementPrint(g); + + //Step2:calculate w=g(r) + printf("\n***********************randnum r:********************************\n"); + cotnum(r, stdout); + w = zzn12_pow(g, r); + printf("\n***************************w=gr:**********************************\n"); + zzn12_ElementPrint(w); + + //Step3:calculate h=H2(M||w,N) + Zlen = len + 32 * 12; + Z = (char *)malloc(sizeof(char)*(Zlen + 1)); + if(Z == NULL) + return SM9_ASK_MEMORY_ERR; + + LinkCharZzn12(message, len, w, Z, Zlen); + buf = SM9_standard_h2(Z, Zlen, N, h); + if(buf != 0) + return buf; + printf("\n****************************h:*************************************\n"); + cotnum(h, stdout); + + //Step4:l=(r-h)mod N + subtract(r, h, l); + divide(l, N, tmp); + while(mr_compare(l, zero) < 0) + add(l, N, l); + if(mr_compare(l, zero) == 0) + return SM9_L_error; + printf("\n**************************l=(r-h)mod N:****************************\n"); + cotnum(l, stdout); + + //Step5:S=[l]dSA=(xS,yS) + ecurve_mult(l, dSA, s); + epoint_get(s, xS, yS); + printf("\n**************************S=[l]dSA=(xS,yS):*************************\n"); + cotnum(xS, stdout); + cotnum(yS, stdout); + + big_to_bytes(32, h, H, 1); + big_to_bytes(32, xS, S, 1); + big_to_bytes(32, yS, S + 32, 1); + + free(Z); + return 0; +} + + +int SM9_standard_verify(unsigned char H[], unsigned char S[], unsigned char hid[], unsigned char *IDA, unsigned char *message, int len, unsigned char Ppub[]) +{ + big h, xS, yS, h1, h2; + epoint *S1; + zzn12 g, t, u, w; + ecn2 P, Ppubs; + int Zlen1, Zlen2, buf; + unsigned char * Z1 = NULL, *Z2 = NULL; + + h = mirvar(0); + h1 = mirvar(0); + h2 = mirvar(0); + xS = mirvar(0); + yS = mirvar(0); + P.x.a = mirvar(0); + P.x.b = mirvar(0); + P.y.a = mirvar(0); + P.y.b = mirvar(0); + P.z.a = mirvar(0); + P.z.b = mirvar(0); + P.marker = MR_EPOINT_INFINITY; + Ppubs.x.a = mirvar(0); + Ppubs.x.b = mirvar(0); + Ppubs.y.a = mirvar(0); + Ppubs.y.b = mirvar(0); + Ppubs.z.a = mirvar(0); + Ppubs.z.b = mirvar(0); + Ppubs.marker = MR_EPOINT_INFINITY; + S1 = epoint_init(); + zzn12_init(&g); + zzn12_init(&t); + zzn12_init(&u); + zzn12_init(&w); + + bytes_to_big(BNLEN, H, h); + bytes_to_big(BNLEN, S, xS); + bytes_to_big(BNLEN, S + BNLEN, yS); + bytes128_to_ecn2(Ppub, &Ppubs); + + //Step 1:test if h in the rangge [1,N-1] + if(Test_Range(h)) + return SM9_H_OUTRANGE; + + //Step 2:test if S is on G1 + epoint_set(xS, yS, 0, S1); + if(Test_Point(S1)) + return SM9_S_NOT_VALID_G1; + + //Step3:g = e(P1, Ppub-s) + if(!ecap(Ppubs, P1, para_t, X, &g)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if(!member(g, para_t, X)) + return SM9_MEMBER_ERR; + + printf("\n***********************g=e(P1,Ppubs):****************************\n"); + zzn12_ElementPrint(g); + + //Step4:calculate t=g(h) + t = zzn12_pow(g, h); + printf("\n***************************w=gh:**********************************\n"); + zzn12_ElementPrint(t); + + //Step5:calculate h1=H1(IDA||hid,N) + Zlen1 = strlen(IDA) + 1; + Z1 = (char *)malloc(sizeof(char)*(Zlen1 + 1)); + if(Z1 == NULL) + return SM9_ASK_MEMORY_ERR; + + memcpy(Z1, IDA, strlen(IDA)); + memcpy(Z1 + strlen(IDA), hid, 1); + buf = SM9_standard_h1(Z1, Zlen1, N, h1); + if(buf != 0) + return buf; + printf("\n****************************h1:**********************************\n"); + cotnum(h1, stdout); + + //Step6:P=[h1]P2+Ppubs + ecn2_copy(&P2, &P); + ecn2_mul(h1, &P); + ecn2_add(&Ppubs, &P); + + //Step7:u=e(S1,P) + if(!ecap(P, S1, para_t, X, &u)) + return SM9_MY_ECAP_12A_ERR; + //test if a ZZn12 element is of order q + if(!member(u, para_t, X)) + return SM9_MEMBER_ERR; + printf("\n************************** u=e(S1,P):*****************************\n"); + zzn12_ElementPrint(u); + + //Step8:w=u*t + zzn12_mul(u, t, &w); + printf("\n************************* w=u*t: **********************************\n"); + zzn12_ElementPrint(w); + + //Step9:h2=H2(M||w,N) + Zlen2 = len + 32 * 12; + Z2 = (char *)malloc(sizeof(char)*(Zlen2 + 1)); + if(Z2 == NULL) + return SM9_ASK_MEMORY_ERR; + + LinkCharZzn12(message, len, w, Z2, Zlen2); + buf = SM9_standard_h2(Z2, Zlen2, N, h2); + if(buf != 0) + return buf; + printf("\n**************************** h2:***********************************\n"); + cotnum(h2, stdout); + + free(Z1); + free(Z2); + if(mr_compare(h2, h) != 0) + return SM9_DATA_MEMCMP_ERR; + + return 0; +} + + +int SM9_standard_sv_selfcheck() +{ + //the master private key + unsigned char dA[32] = {0x00, 0x01, 0x30, 0xE7, 0x84, 0x59, 0xD7, 0x85, 0x45, 0xCB, 0x54, 0xC5, 0x87, 0xE0, 0x2C, 0xF4, + 0x80, 0xCE, 0x0B, 0x66, 0x34, 0x0F, 0x31, 0x9F, 0x34, 0x8A, 0x1D, 0x5B, 0x1F, 0x2D, 0xC5, 0xF4}; + unsigned char rand[32] = {0x00, 0x03, 0x3C, 0x86, 0x16, 0xB0, 0x67, 0x04, 0x81, 0x32, 0x03, 0xDF, 0xD0, 0x09, 0x65, 0x02, + 0x2E, 0xD1, 0x59, 0x75, 0xC6, 0x62, 0x33, 0x7A, 0xED, 0x64, 0x88, 0x35, 0xDC, 0x4B, 0x1C, 0xBE}; + + unsigned char h[32], S[64];// Signature + unsigned char Ppub[128], dSA[64]; + + unsigned char std_h[32] = {0x82, 0x3C, 0x4B, 0x21, 0xE4, 0xBD, 0x2D, 0xFE, 0x1E, 0xD9, 0x2C, 0x60, 0x66, 0x53, 0xE9, 0x96, + 0x66, 0x85, 0x63, 0x15, 0x2F, 0xC3, 0x3F, 0x55, 0xD7, 0xBF, 0xBB, 0x9B, 0xD9, 0x70, 0x5A, 0xDB}; + unsigned char std_S[64] = {0x73, 0xBF, 0x96, 0x92, 0x3C, 0xE5, 0x8B, 0x6A, 0xD0, 0xE1, 0x3E, 0x96, 0x43, 0xA4, 0x06, 0xD8, + 0xEB, 0x98, 0x41, 0x7C, 0x50, 0xEF, 0x1B, 0x29, 0xCE, 0xF9, 0xAD, 0xB4, 0x8B, 0x6D, 0x59, 0x8C, + 0x85, 0x67, 0x12, 0xF1, 0xC2, 0xE0, 0x96, 0x8A, 0xB7, 0x76, 0x9F, 0x42, 0xA9, 0x95, 0x86, 0xAE, + 0xD1, 0x39, 0xD5, 0xB8, 0xB3, 0xE1, 0x58, 0x91, 0x82, 0x7C, 0xC2, 0xAC, 0xED, 0x9B, 0xAA, 0x05}; + unsigned char std_Ppub[128] = {0x9F, 0x64, 0x08, 0x0B, 0x30, 0x84, 0xF7, 0x33, 0xE4, 0x8A, 0xFF, 0x4B, 0x41, 0xB5, 0x65, 0x01, + 0x1C, 0xE0, 0x71, 0x1C, 0x5E, 0x39, 0x2C, 0xFB, 0x0A, 0xB1, 0xB6, 0x79, 0x1B, 0x94, 0xC4, 0x08, + 0x29, 0xDB, 0xA1, 0x16, 0x15, 0x2D, 0x1F, 0x78, 0x6C, 0xE8, 0x43, 0xED, 0x24, 0xA3, 0xB5, 0x73, + 0x41, 0x4D, 0x21, 0x77, 0x38, 0x6A, 0x92, 0xDD, 0x8F, 0x14, 0xD6, 0x56, 0x96, 0xEA, 0x5E, 0x32, + 0x69, 0x85, 0x09, 0x38, 0xAB, 0xEA, 0x01, 0x12, 0xB5, 0x73, 0x29, 0xF4, 0x47, 0xE3, 0xA0, 0xCB, + 0xAD, 0x3E, 0x2F, 0xDB, 0x1A, 0x77, 0xF3, 0x35, 0xE8, 0x9E, 0x14, 0x08, 0xD0, 0xEF, 0x1C, 0x25, + 0x41, 0xE0, 0x0A, 0x53, 0xDD, 0xA5, 0x32, 0xDA, 0x1A, 0x7C, 0xE0, 0x27, 0xB7, 0xA4, 0x6F, 0x74, + 0x10, 0x06, 0xE8,0x5F,0x5C,0xDF,0xF0,0x73,0x0E,0x75,0xC0,0x5F,0xB4,0xE3,0x21, 0x6D}; + unsigned char std_dSA[64] = {0xA5, 0x70, 0x2F, 0x05, 0xCF, 0x13, 0x15, 0x30, 0x5E, 0x2D, 0x6E, 0xB6, 0x4B, 0x0D, 0xEB, 0x92, + 0x3D, 0xB1, 0xA0, 0xBC, 0xF0, 0xCA, 0xFF, 0x90, 0x52, 0x3A, 0xC8, 0x75, 0x4A, 0xA6, 0x98, 0x20, + 0x78, 0x55, 0x9A, 0x84, 0x44, 0x11, 0xF9, 0x82, 0x5C, 0x10, 0x9F, 0x5E, 0xE3, 0xF5, 0x2D, 0x72, + 0x0D, 0xD0, 0x17, 0x85, 0x39, 0x2A, 0x72, 0x7B, 0xB1, 0x55, 0x69, 0x52, 0xB2, 0xB0, 0x13, 0xD3}; + + unsigned char hid[] = {0x01}; + unsigned char *IDA = "Alice"; + unsigned char *message = "Chinese IBS standard";//the message to be signed + int mlen = strlen(message), tmp;//the length of message + big ks; + + tmp = SM9_standard_init(); + + if(tmp != 0) + return tmp; + ks = mirvar(0); + + bytes_to_big(32, dA, ks); + + printf("\n*********************** SM9 key Generation ***************************\n"); + tmp = SM9_standard_generatesignkey(hid, IDA, strlen(IDA), ks, Ppub, dSA); + if(tmp != 0) + return tmp; + if(memcmp(Ppub, std_Ppub, 128) != 0) + return SM9_GEPUB_ERR; + if(memcmp(dSA, std_dSA, 64) != 0) + return SM9_GEPRI_ERR; + + printf("\n********************** SM9 signature algorithm***************************\n"); + tmp = SM9_standard_sign(hid, IDA, message, mlen, rand, dSA, Ppub, h, S); + if(tmp != 0) + return tmp; + if(memcmp(h, std_h, 32) != 0) + return SM9_SIGN_ERR; + if(memcmp(S, std_S, 64) != 0) + return SM9_SIGN_ERR; + printf("\n******************* SM9 verification algorithm *************************\n"); + tmp = SM9_standard_verify(h, S, hid, IDA, message, mlen, Ppub); + if(tmp != 0) + return tmp; + + return 0; +} diff --git a/engines/sm_standard/sm9/zzn12_operation.h b/engines/sm_standard/sm9/zzn12_operation.h new file mode 100644 index 00000000..3f535113 --- /dev/null +++ b/engines/sm_standard/sm9/zzn12_operation.h @@ -0,0 +1,462 @@ +/* ==================================================================== + * 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_ZZN12_OPERATION_H +#define HEADER_ZZN12_OPERATION_H + + +#include "miracl.h" + + +#ifdef __cplusplus +extern "C"{ +#endif + +miracl* mip; +zzn2 X; //Frobniues constant +typedef struct +{ + zzn4 a, b, c; + BOOL unitary; // "unitary property means that fast squaring can be used, and inversions are just conjugates + BOOL miller; // "miller" property means that arithmetic on this instance can ignore multiplications + // or divisions by constants - as instance will eventually be raised to (p-1). +} zzn12; + + +static void zzn12_init(zzn12 *x) +{ + x->a.a.a = mirvar(0); + x->a.a.b = mirvar(0); + + x->a.b.a = mirvar(0); + x->a.b.b = mirvar(0); + + x->a.unitary = FALSE; + + + x->b.a.a = mirvar(0); + x->b.a.b = mirvar(0); + + x->b.b.a = mirvar(0); + x->b.b.b = mirvar(0); + + x->b.unitary = FALSE; + + + x->c.a.a = mirvar(0); + x->c.a.b = mirvar(0); + + x->c.b.a = mirvar(0); + x->c.b.b = mirvar(0); + + x->c.unitary = FALSE; + + + x->miller = FALSE; + x->unitary = FALSE; +} + + +static void zzn12_copy(zzn12 *x, zzn12 *y) +{ + zzn4_copy(&x->a, &y->a); + zzn4_copy(&x->b, &y->b); + zzn4_copy(&x->c, &y->c); + + y->miller = x->miller; + y->unitary = x->unitary; +} + + +static void zzn12_mul(zzn12 x, zzn12 y, zzn12 *z) +{ + // Karatsuba + zzn4 Z0, Z1, Z2, Z3, T0, T1; + BOOL zero_c, zero_b; + + Z0.a.a = mirvar(0); + Z0.a.b = mirvar(0); + + Z0.b.a = mirvar(0); + Z0.b.b = mirvar(0); + + Z0.unitary = FALSE; + + + Z1.a.a = mirvar(0); + Z1.a.b = mirvar(0); + + Z1.b.a = mirvar(0); + Z1.b.b = mirvar(0); + + Z1.unitary = FALSE; + + + Z2.a.a = mirvar(0); + Z2.a.b = mirvar(0); + + Z2.b.a = mirvar(0); + Z2.b.b = mirvar(0); + + Z2.unitary = FALSE; + + + Z3.a.a = mirvar(0); + Z3.a.b = mirvar(0); + + Z3.b.a = mirvar(0); + Z3.b.b = mirvar(0); + + Z3.unitary = FALSE; + + + T0.a.a = mirvar(0); + T0.a.b = mirvar(0); + + T0.b.a = mirvar(0); + T0.b.b = mirvar(0); + + T0.unitary = FALSE; + + + T1.a.a = mirvar(0); + T1.a.b = mirvar(0); + + T1.b.a = mirvar(0); + T1.b.b = mirvar(0); + + T1.unitary = FALSE; + + + zzn12_copy(&x, z); + if(zzn4_compare(&x.a, &y.a) && zzn4_compare(&x.a, &y.a) && zzn4_compare(&x.a, &y.a)) + { + if(x.unitary == TRUE) + { + zzn4_copy(&x.a, &Z0); + zzn4_mul(&x.a, &x.a, &z->a); + zzn4_copy(&z->a, &Z3); + zzn4_add(&z->a, &z->a, &z->a); + zzn4_add(&z->a, &Z3, &z->a); + zzn4_conj(&Z0, &Z0); + zzn4_add(&Z0, &Z0, &Z0); + zzn4_sub(&z->a, &Z0, &z->a); + zzn4_copy(&x.c, &Z1); + zzn4_mul(&Z1, &Z1, &Z1); + zzn4_tx(&Z1); + zzn4_copy(&Z1, &Z3); + zzn4_add(&Z1, &Z1, &Z1); + zzn4_add(&Z1, &Z3, &Z1); + zzn4_copy(&x.b, &Z2); + zzn4_mul(&Z2, &Z2, &Z2); + zzn4_copy(&Z2, &Z3); + zzn4_add(&Z2, &Z2, &Z2); + zzn4_add(&Z2, &Z3, &Z2); + zzn4_conj(&x.b, &z->b); + zzn4_add(&z->b, &z->b, &z->b); + zzn4_conj(&x.c, &z->c); + zzn4_add(&z->c, &z->c, &z->c); + zzn4_negate(&z->c, &z->c); + zzn4_add(&z->b, &Z1, &z->b); + zzn4_add(&z->c, &Z2, &z->c); + } + else + { + if(!x.miller) + { // Chung-Hasan SQR2 + zzn4_copy(&x.a, &Z0); + zzn4_mul(&Z0, &Z0, &Z0); + zzn4_mul(&x.b, &x.c, &Z1); + zzn4_add(&Z1, &Z1, &Z1); + zzn4_copy(&x.c, &Z2); + zzn4_mul(&Z2, &Z2, &Z2); + zzn4_mul(&x.a, &x.b, &Z3); + zzn4_add(&Z3, &Z3, &Z3); + zzn4_add(&x.a, &x.b, &z->c); + zzn4_add(&z->c, &x.c, &z->c); + zzn4_mul(&z->c, &z->c, &z->c); + zzn4_tx(&Z1); + zzn4_add(&Z0, &Z1, &z->a); + zzn4_tx(&Z2); + zzn4_add(&Z3, &Z2, &z->b); + zzn4_add(&Z0, &Z1, &T0); + zzn4_add(&T0, &Z2, &T0); + zzn4_add(&T0, &Z3, &T0); + zzn4_sub(&z->c, &T0, &z->c); + } + else + { // Chung-Hasan SQR3 - actually calculate 2x^2 ! + // Slightly dangerous - but works as will be raised to p^{k/2}-1 + // which wipes out the 2. + zzn4_copy(&x.a, &Z0); + zzn4_mul(&Z0, &Z0, &Z0); // a0^2 = S0 + zzn4_copy(&x.c, &Z2); + zzn4_mul(&Z2, &x.b, &Z2); + zzn4_add(&Z2, &Z2, &Z2); // 2a1.a2 = S3 + zzn4_copy(&x.c, &Z3); + zzn4_mul(&Z3, &Z3, &Z3); // a2^2 = S4 + zzn4_add(&x.c, &x.a, &z->c); // a0+a2 + zzn4_copy(&x.b, &Z1); + zzn4_add(&Z1, &z->c, &Z1); + zzn4_mul(&Z1, &Z1, &Z1); // (a0+a1+a2)^2 =S1 + zzn4_sub(&z->c, &x.b, &z->c); + zzn4_mul(&z->c, &z->c, &z->c); // (a0-a1+a2)^2 =S2 + zzn4_add(&Z2, &Z2, &Z2); + zzn4_add(&Z0, &Z0, &Z0); + zzn4_add(&Z3, &Z3, &Z3); + zzn4_sub(&Z1, &z->c, &T0); + zzn4_sub(&T0, &Z2, &T0); + zzn4_sub(&Z1, &Z0, &T1); + zzn4_sub(&T1, &Z3, &T1); + zzn4_add(&z->c, &T1, &z->c); + zzn4_tx(&Z3); + zzn4_add(&T0, &Z3, &z->b); + zzn4_tx(&Z2); + zzn4_add(&Z0, &Z2, &z->a); + } + } + } + else + { + // Karatsuba + zero_b = zzn4_iszero(&y.b); + zero_c = zzn4_iszero(&y.c); + + zzn4_mul(&x.a, &y.a, &Z0); //9 + if(!zero_b) + zzn4_mul(&x.b, &y.b, &Z2); //+6 + + zzn4_add(&x.a, &x.b, &T0); + zzn4_add(&y.a, &y.b, &T1); + zzn4_mul(&T0, &T1, &Z1); //+9 + zzn4_sub(&Z1, &Z0, &Z1); + if(!zero_b) + zzn4_sub(&Z1, &Z2, &Z1); + + zzn4_add(&x.b, &x.c, &T0); + zzn4_add(&y.b, &y.c, &T1); + zzn4_mul(&T0, &T1, &Z3);//+6 + if(!zero_b) + zzn4_sub(&Z3, &Z2, &Z3); + + zzn4_add(&x.a, &x.c, &T0); + zzn4_add(&y.a, &y.c, &T1); + zzn4_mul(&T0, &T1, &T0);//+9=39 for "special case" + if(!zero_b) + zzn4_add(&Z2, &T0, &Z2); + else + zzn4_copy(&T0, &Z2); + + zzn4_sub(&Z2, &Z0, &Z2); + zzn4_copy(&Z1, &z->b); + if(!zero_c) + { + // exploit special form of BN curve line function + zzn4_mul(&x.c, &y.c, &T0); + zzn4_sub(&Z2, &T0, &Z2); + zzn4_sub(&Z3, &T0, &Z3); + zzn4_tx(&T0); + zzn4_add(&z->b, &T0, &z->b); + } + + zzn4_tx(&Z3); + zzn4_add(&Z0, &Z3, &z->a); + zzn4_copy(&Z2, &z->c); + if(!y.unitary) + z->unitary = FALSE; + } +} + + +static void zzn12_conj(zzn12 *x, zzn12 *y) +{ + zzn4_conj(&x->a, &y->a); + zzn4_conj(&x->b, &y->b); + zzn4_negate(&y->b, &y->b); + zzn4_conj(&x->c, &y->c); + y->miller = x->miller; + y->unitary = x->unitary; +} + + +static zzn12 zzn12_inverse(zzn12 w) +{ + zzn4 tmp1, tmp2; + zzn12 res; + + tmp1.a.a = mirvar(0); + tmp1.a.b = mirvar(0); + + tmp1.b.a = mirvar(0); + tmp1.b.b = mirvar(0); + + tmp1.unitary = FALSE; + + + tmp2.a.a = mirvar(0); + tmp2.a.b = mirvar(0); + + tmp2.b.a = mirvar(0); + tmp2.b.b = mirvar(0); + + tmp2.unitary = FALSE; + + + zzn12_init(&res); + + if(w.unitary) + { + zzn12_conj(&w, &res); + return res; + } + //res.a=w.a*w.a-tx(w.b*w.c); + zzn4_mul(&w.a, &w.a, &res.a); + zzn4_mul(&w.b, &w.c, &res.b); + zzn4_tx(&res.b); + zzn4_sub(&res.a, &res.b, &res.a); + + //res.b=tx(w.c*w.c)-w.a*w.b; + zzn4_mul(&w.c, &w.c, &res.c); + zzn4_tx(&res.c); + zzn4_mul(&w.a, &w.b, &res.b); + zzn4_sub(&res.c, &res.b, &res.b); + + //res.c=w.b*w.b-w.a*w.c; + zzn4_mul(&w.b, &w.b, &res.c); + zzn4_mul(&w.a, &w.c, &tmp1); + zzn4_sub(&res.c, &tmp1, &res.c); + + //tmp1=tx(w.b*res.c)+w.a*res.a+tx(w.c*res.b); + zzn4_mul(&w.b, &res.c, &tmp1); + zzn4_tx(&tmp1); + zzn4_mul(&w.a, &res.a, &tmp2); + zzn4_add(&tmp1, &tmp2, &tmp1); + zzn4_mul(&w.c, &res.b, &tmp2); + zzn4_tx(&tmp2); + zzn4_add(&tmp1, &tmp2, &tmp1); + + zzn4_inv(&tmp1); + zzn4_mul(&res.a, &tmp1, &res.a); + zzn4_mul(&res.b, &tmp1, &res.b); + zzn4_mul(&res.c, &tmp1, &res.c); + return res; +} + + +static void zzn12_powq(zzn2 F, zzn12 *y) +{ + zzn2 X2, X3; + X2.a = mirvar(0); + X2.b = mirvar(0); + + X3.a = mirvar(0); + X3.b = mirvar(0); + zzn2_mul(&F, &F, &X2); + zzn2_mul(&X2, &F, &X3); + + zzn4_powq(&X3, &y->a); + zzn4_powq(&X3, &y->b); + zzn4_powq(&X3, &y->c); + zzn4_smul(&y->b, &X, &y->b); + zzn4_smul(&y->c, &X2, &y->c); +} + + +static void zzn12_div(zzn12 x, zzn12 y, zzn12 *z) +{ + y=zzn12_inverse(y); + zzn12_mul(x, y, z); +} + + +static zzn12 zzn12_pow(zzn12 x, big k) +{ + big zero, tmp, tmp1; + int nb, i; + BOOL invert_it; + zzn12 res; + + zero = mirvar(0); + tmp = mirvar(0); + tmp1 = mirvar(0); + + zzn12_init(&res); + copy(k, tmp1); + invert_it = FALSE; + + if(mr_compare(tmp1, zero) == 0) + { + tmp = get_mip()->one; + zzn4_from_big(tmp, &res.a); + return res; + } + if(mr_compare(tmp1, zero) < 0) + { + negify(tmp1, tmp1); + invert_it = TRUE; + } + nb = logb2(k); + zzn12_copy(&x, &res); + if(nb > 1) + for(i = nb - 2; i >= 0; i--) + { + zzn12_mul(res, res, &res); + if(mr_testbit(k, i)) + zzn12_mul(res, x, &res); + } + if(invert_it) + res = zzn12_inverse(res); + return res; +} + +#ifdef __cplusplus +} +#endif + +#endif