Skip to content

Commit

Permalink
add sm3 and sm2_z
Browse files Browse the repository at this point in the history
  • Loading branch information
dangfan committed Dec 25, 2023
1 parent 7007cba commit cc51cc7
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 0 deletions.
11 changes: 11 additions & 0 deletions include/ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ int ecc_sign(key_type_t type, const ecc_key_t *key, const uint8_t *data_or_diges
*/
size_t ecdsa_sig2ansi(uint8_t key_len, const uint8_t *input, uint8_t *output);

/**
* Compute Z specified by SM2
*
* @param id User's ID. The first byte contains the length and followed by the ID.
* @param key Pointer to the key
* @param z The output buffer
*
* @return 0: Success, -1: Error
*/
int sm2_z(const uint8_t *id, const ecc_key_t *key, uint8_t *z);

/**
* Compute ECDH result
*
Expand Down
16 changes: 16 additions & 0 deletions include/sm3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef CANOKEY_CRYPTO_SM3_H_
#define CANOKEY_CRYPTO_SM3_H_

#include <stddef.h>
#include <stdint.h>

#define SM3_BLOCK_LENGTH 64
#define SM3_DIGEST_LENGTH 32

void sm3_init(void);
void sm3_update(const uint8_t *data, uint16_t len);
void sm3_final(uint8_t digest[SM3_DIGEST_LENGTH]);
void sm3_raw(const uint8_t *data, size_t len, uint8_t digest[SM3_DIGEST_LENGTH]);

#endif
25 changes: 25 additions & 0 deletions src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <ecc.h>
#include <memzero.h>
#include <rand.h>
#include <sm3.h>
#include <string.h>

#ifdef USE_MBEDCRYPTO
Expand Down Expand Up @@ -346,6 +347,30 @@ size_t ecdsa_sig2ansi(uint8_t key_len, const uint8_t *input, uint8_t *output) {
return 6 + part1_len + part2_len;
}

__attribute__((weak)) int sm2_z(const uint8_t *id, const ecc_key_t *key, uint8_t *z) {
const uint8_t a[] = {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC};
const uint8_t b[] = {0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34, 0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7,
0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92, 0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93};
const uint8_t xg[] = {0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19, 0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94,
0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1, 0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7};
const uint8_t yg[] = {0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C, 0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53,
0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40, 0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0};
const uint8_t entl[2] = {id[0] * 8 >> 8, id[0] * 8 & 0xFF};

sm3_init();
sm3_update(entl, sizeof(entl));
sm3_update(id + 1, id[0]);
sm3_update(a, sizeof(a));
sm3_update(b, sizeof(b));
sm3_update(xg, sizeof(xg));
sm3_update(yg, sizeof(yg));
sm3_update(key->pub, PUBLIC_KEY_LENGTH[SM2]);
sm3_final(z);

return 0;
}

__attribute__((weak)) int K__short_weierstrass_generate(key_type_t type, ecc_key_t *key) {
#ifdef USE_MBEDCRYPTO
if (type == SM2) {
Expand Down
202 changes: 202 additions & 0 deletions src/sm3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
// Modified from https://github.com/AyrA/sm3/blob/master/sm3.c (Dec 24, 2023)
//
// MIT License
//
// Copyright (c) 2019 Kevin Gut
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "sm3.h"
#include <string.h>

#ifdef USE_MBEDCRYPTO
typedef struct {
uint32_t digest[8];
int nblocks;
unsigned char block[64];
int num;
} sm3_ctx_t;

static sm3_ctx_t ctx;
static void sm3_compress(uint32_t digest[8], const unsigned char block[64]);
#endif

__attribute__((weak)) void sm3_init(void) {
#ifdef USE_MBEDCRYPTO
ctx.digest[0] = 0x7380166F;
ctx.digest[1] = 0x4914B2B9;
ctx.digest[2] = 0x172442D7;
ctx.digest[3] = 0xDA8A0600;
ctx.digest[4] = 0xA96F30BC;
ctx.digest[5] = 0x163138AA;
ctx.digest[6] = 0xE38DEE4D;
ctx.digest[7] = 0xB0FB0E4E;

ctx.nblocks = 0;
ctx.num = 0;
#endif
}

__attribute__((weak)) void sm3_update(const uint8_t *data, uint16_t len) {
#ifdef USE_MBEDCRYPTO
if (ctx.num) {
const unsigned int left = SM3_BLOCK_LENGTH - ctx.num;
if (len < left) {
memcpy(ctx.block + ctx.num, data, len);
ctx.num += len;
return;
} else {
memcpy(ctx.block + ctx.num, data, left);
sm3_compress(ctx.digest, ctx.block);
ctx.nblocks++;
data += left;
len -= left;
}
}
while (len >= SM3_BLOCK_LENGTH) {
sm3_compress(ctx.digest, data);
ctx.nblocks++;
data += SM3_BLOCK_LENGTH;
len -= SM3_BLOCK_LENGTH;
}
ctx.num = len;
if (len) {
memcpy(ctx.block, data, len);
}
#else
(void)data;
(void)len;
#endif
}

__attribute__((weak)) void sm3_final(uint8_t digest[SM3_DIGEST_LENGTH]) {
#ifdef USE_MBEDCRYPTO
unsigned int i;
uint32_t *pdigest = (uint32_t *)digest;
uint32_t *count = (uint32_t *)(ctx.block + SM3_BLOCK_LENGTH - 8);

ctx.block[ctx.num] = 0x80;

if (ctx.num + 9 <= SM3_BLOCK_LENGTH) {
memset(ctx.block + ctx.num + 1, 0, SM3_BLOCK_LENGTH - ctx.num - 9);
} else {
memset(ctx.block + ctx.num + 1, 0, SM3_BLOCK_LENGTH - ctx.num - 1);
sm3_compress(ctx.digest, ctx.block);
memset(ctx.block, 0, SM3_BLOCK_LENGTH - 8);
}

count[0] = __builtin_bswap32(ctx.nblocks >> 23);
count[1] = __builtin_bswap32((ctx.nblocks << 9) + (ctx.num << 3));

sm3_compress(ctx.digest, ctx.block);
for (i = 0; i < sizeof(ctx.digest) / sizeof(ctx.digest[0]); i++) {
pdigest[i] = __builtin_bswap32(ctx.digest[i]);
}
#else
(void)digest;
#endif
}

#ifdef USE_MBEDCRYPTO
#define ROTATELEFT(X,n) (((X)<<(n)) | ((X)>>(32-(n))))

#define P0(x) ((x) ^ ROTATELEFT((x),9) ^ ROTATELEFT((x),17))
#define P1(x) ((x) ^ ROTATELEFT((x),15) ^ ROTATELEFT((x),23))

#define FF0(x,y,z) ( (x) ^ (y) ^ (z))
#define FF1(x,y,z) (((x) & (y)) | ( (x) & (z)) | ( (y) & (z)))

#define GG0(x,y,z) ( (x) ^ (y) ^ (z))
#define GG1(x,y,z) (((x) & (y)) | ( (~(x)) & (z)) )

void sm3_compress(uint32_t digest[8], const unsigned char block[64]) {
int j;
uint32_t W[68], W1[64];
const uint32_t *pblock = (const uint32_t *)block;

uint32_t A = digest[0];
uint32_t B = digest[1];
uint32_t C = digest[2];
uint32_t D = digest[3];
uint32_t E = digest[4];
uint32_t F = digest[5];
uint32_t G = digest[6];
uint32_t H = digest[7];
uint32_t SS1, SS2, TT1, TT2, T[64];

for (j = 0; j < 16; j++) {
W[j] = __builtin_bswap32(pblock[j]);
}
for (j = 16; j < 68; j++) {
W[j] = P1(W[j-16] ^ W[j-9] ^ ROTATELEFT(W[j-3],15)) ^ ROTATELEFT(W[j - 13], 7) ^ W[j - 6];;
}
for (j = 0; j < 64; j++) {
W1[j] = W[j] ^ W[j + 4];
}

for (j = 0; j < 16; j++) {

T[j] = 0x79CC4519;
SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j)), 7);
SS2 = SS1 ^ ROTATELEFT(A, 12);
TT1 = FF0(A, B, C) + D + SS2 + W1[j];
TT2 = GG0(E, F, G) + H + SS1 + W[j];
D = C;
C = ROTATELEFT(B, 9);
B = A;
A = TT1;
H = G;
G = ROTATELEFT(F, 19);
F = E;
E = P0(TT2);
}

for (j = 16; j < 64; j++) {

T[j] = 0x7A879D8A;
SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j)), 7);
SS2 = SS1 ^ ROTATELEFT(A, 12);
TT1 = FF1(A, B, C) + D + SS2 + W1[j];
TT2 = GG1(E, F, G) + H + SS1 + W[j];
D = C;
C = ROTATELEFT(B, 9);
B = A;
A = TT1;
H = G;
G = ROTATELEFT(F, 19);
F = E;
E = P0(TT2);
}

digest[0] ^= A;
digest[1] ^= B;
digest[2] ^= C;
digest[3] ^= D;
digest[4] ^= E;
digest[5] ^= F;
digest[6] ^= G;
digest[7] ^= H;
}
#endif

void sm3_raw(const uint8_t *data, size_t len, uint8_t digest[SM3_DIGEST_LENGTH]) {
sm3_init();
sm3_update(data, len);
sm3_final(digest);
}
19 changes: 19 additions & 0 deletions test/test_ecdsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,24 @@ static void test_sig2ansi(void **state) {
}
}

static void test_sm2_z(void **state) {
(void)state;
const uint8_t id[] = {16, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38};
const uint8_t expected[32] = {0x60, 0xf6, 0x87, 0x2d, 0x8b, 0xa1, 0x55, 0x15, 0x59, 0xe0, 0x27, 0x04, 0x82, 0x3c,
0xb3, 0x55, 0xb4, 0x4c, 0xd4, 0xc1, 0x81, 0xd7, 0xfa, 0xf4, 0x1b, 0xe4, 0x24, 0x7c,
0x99, 0xf7, 0xe2, 0xb0};
uint8_t out[32];
ecc_key_t key;
memcpy(key.pub, "\x10\x2a\xe6\xa8\x42\x4f\x20\xaf\xb7\xfb\x35\xde\xf5\x29\x78\x88\x24\x03\x98\x6e\x40\x5d\x0a\xa6\xc7"
"\xf4\x36\xc4\x4d\x49\x95\x8c\xae\x1d\x93\x44\xf9\x36\x16\xab\xd9\x17\x10\x46\xb8\xf8\x3a\xdd\x6b\x4f"
"\x1c\xcf\x86\x98\x74\x5f\xa3\x32\x57\x12\x37\x66\xa3\xc6", 64);
sm2_z(id, &key, out);
for (int i = 0; i != 32; ++i) {
assert_int_equal(out[i], expected[i]);
}
}

int main() {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_ecc_keygen),
Expand All @@ -165,6 +183,7 @@ int main() {
cmocka_unit_test(test_ecc_get_public_key),
cmocka_unit_test(test_ecdh),
cmocka_unit_test(test_sig2ansi),
cmocka_unit_test(test_sm2_z),
};

return cmocka_run_group_tests(tests, NULL, NULL);
Expand Down

0 comments on commit cc51cc7

Please sign in to comment.