feat add soft sm3

This commit is contained in:
tqcq 2024-12-23 11:52:29 +08:00
parent 3fbfb12294
commit 1cf9d96dd1
19 changed files with 6422 additions and 1931 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
out/
compile_commands.json
Makefile.in Makefile.in
build* build*
.vscode .vscode

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

257
AWSMServer/src/map.c Normal file
View File

@ -0,0 +1,257 @@
#include "map.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
struct cell {
struct cell *next;
void *value;
char key[];
} cell;
struct map {
struct cell **elems;
int capacity;
int size;
};
// Internal helper functions. Implemented at the bottom of this file.
static unsigned int hash(const char *key);
static void extend_if_necessary(map m);
/**
* Create a new, empty map.
*
* The returned map has dynamically allocated memory associated with it, and
* this memory must be reclaimed after use with `map_destroy`.
*/
map map_create() {
// Allocate space for the map's primary data structure. More space will be
// allocated in the future when values are added to the map.
map m = malloc(sizeof(map));
assert(m != NULL);
m->elems = calloc(1, sizeof(struct cell *));
assert(m->elems != NULL);
// Initialize metadata. The map starts with capacity for one entry.
m->capacity = 1;
m->size = 0;
return m;
}
/**
* Free the memory used for a map after use.
*
* Note that this routine does not free any memory that was allocated for the
* values stored in the map. That memory must be freed by the client as
* appropriate.
*/
void map_destroy(map m) {
// Loop over each cell in the map and free it.
for (int i = 0; i < m->capacity; i += 1) {
struct cell *curr = m->elems[i];
while (curr != NULL) {
struct cell *next = curr->next;
free(curr);
curr = next;
}
}
free(m->elems);
free(m);
}
/**
* Get the size of a map.
*/
int map_size(const map m) { return m->size; }
/**
* Determine whether a map contains a given key.
*
* Keys are case-sensitive.
*/
bool map_contains(const map m, const char *key) {
int b = hash(key) % m->capacity;
// Search linearly for a matching key through the appropriate linked list.
for (struct cell *curr = m->elems[b]; curr != NULL; curr = curr->next) {
if (strcmp(curr->key, key) == 0)
return true;
}
return false;
}
/**
* Set the value for a given key within a map.
*
* This will add a new key if it does not exist. If the key already exists, the
* new value will replace the old one.
*/
void map_set(map m, const char *key, void *value) {
int b = hash(key) % m->capacity;
// First, look for an existing entry with the given key in the map. If it
// exists, simply update its value.
for (struct cell *curr = m->elems[b]; curr != NULL; curr = curr->next) {
if (strcmp(curr->key, key) == 0) {
curr->value = value;
return;
}
}
extend_if_necessary(m);
b = hash(key) % m->capacity;
// No existing key was found, so insert it as a new entry at the head of the
// list.
struct cell *new = malloc(sizeof(struct cell) + strlen(key) + 1);
new->next = m->elems[b];
new->value = value;
strcpy(new->key, key);
m->elems[b] = new;
m->size += 1;
}
/**
* Retrieve the value for a given key in a map.
*
* Crashes if the map does not contain the given key.
*/
void *map_get(const map m, const char *key) {
int b = hash(key) % m->capacity;
// Search linearly for a matching key through the appropriate linked list.
for (struct cell *curr = m->elems[b]; curr != NULL; curr = curr->next) {
if (strcmp(curr->key, key) == 0)
return curr->value;
}
// Key not found.
bool key_found = false;
assert(key_found);
exit(1);
}
/**
* Remove a key and its value from a map.
*
* Crashes if the map does not already contain the key.
*/
void *map_remove(map m, const char *key) {
int b = hash(key) % m->capacity;
// Here, use a double pointer to make removal easier.
struct cell **curr;
for (curr = &m->elems[b]; *curr != NULL; curr = &(*curr)->next) {
if (strcmp((*curr)->key, key) == 0) {
// Bridge the linked list accross the removed element.
struct cell *found = *curr;
*curr = (*curr)->next;
void *value = found->value;
free(found);
m->size -= 1;
return value;
}
}
// Key not found.
bool key_found = false;
assert(key_found);
exit(1);
}
/**
* Get the "first" key (arbitrarily ordered) in a map. If the map is empty,
* returns NULL.
*/
const char *map_first(map m) {
// Find and return the first cell in the first non-empty bucket.
for (int i = 0; i < m->capacity; i += 1) {
if (m->elems[i] != NULL) {
return m->elems[i]->key;
}
}
return NULL;
}
/**
* Get the next key after a given key within a map.
*
* Used for iteration. Returns NULL if there are no more keys. Note that the
* provided `key` must have been returned from a previous call to `map_first`
* or `map_next`. Passing other strings produces undefined behavior.
*/
const char *map_next(map m, const char *key) {
// First, get a reference to the current cell and check its successor.
struct cell *curr = (void *)(key - sizeof(struct cell));
if (curr->next != NULL) {
return curr->next->key;
}
// If no immediate successor exists, begin searching the rest of the buckets.
int b = hash(key) % m->capacity;
for (int i = b + 1; i < m->capacity; i += 1) {
if (m->elems[i] != NULL) {
return m->elems[i]->key;
}
}
// No more keys.
return NULL;
}
/**
* Internal helper; hash a string key.
*/
static unsigned int hash(const char *key) {
unsigned int hash = -1;
while (*key) {
hash *= 31;
hash ^= (unsigned char)*key;
key += 1;
}
return hash;
}
/*
* Grow the capacity of the hash map by a factor of two, only when the map's
* load becomes greater than one.
*/
static void extend_if_necessary(map m) {
if (m->size == m->capacity) {
// Save old values first, since all map entries will need to be copied over.
int capacity = m->capacity;
struct cell **elems = m->elems;
// Doubling the capacity when necessary allows for an amortized constant
// runtime for extension.
m->capacity *= 2;
m->elems = calloc(m->capacity, sizeof(struct cell *));
for (int i = 0; i < capacity; i += 1) {
struct cell *curr = elems[i];
while (curr != NULL) {
struct cell *next = curr->next;
// Move the entry from the old data structure to the new.
int b = hash(curr->key) % m->capacity;
curr->next = m->elems[b];
m->elems[b] = curr;
curr = next;
}
}
free(elems);
}
}

84
AWSMServer/src/map.h Normal file
View File

@ -0,0 +1,84 @@
#ifndef __MAP_H
#define __MAP_H
#include <stdbool.h>
/**
* Hash map implementation for C.
*
* This hash map uses strings as keys, and allows association of any arbitrary
* value type through the use of `void *` pointers. Additionally, this
* implementation leaves memory management of stored values to the client (for
* example, destroying a map using `map_destroy` will free the memory for the
* map itself, but it will not free memory that was used to store its values).
*/
typedef struct map *map;
/**
* Create a new, empty map.
*
* The returned map has dynamically allocated memory associated with it, and
* this memory must be reclaimed after use with `map_destroy`.
*/
map map_create();
/**
* Free the memory used for a map after use.
*
* Note that this routine does not free any memory that was allocated for the
* values stored in the map. That memory must be freed by the client as
* appropriate.
*/
void map_destroy(map m);
/**
* Get the size of a map.
*/
int map_size(const map m);
/**
* Determine whether a map contains a given key.
*
* Keys are case-sensitive.
*/
bool map_contains(const map m, const char *key);
/**
* Set the value for a given key within a map.
*
* This will add a new key if it does not exist. If the key already exists, the
* new value will replace the old one.
*/
void map_set(map m, const char *key, void *value);
/**
* Retrieve the value for a given key in a map.
*
* Crashes if the map does not contain the given key.
*/
void *map_get(const map m, const char *key);
/**
* Remove a key and return its value from a map.
*
* Crashes if the map does not already contain the key.
*/
void *map_remove(map m, const char *key);
/**
* Iterate over a map's keys.
*
* Usage:
*
* for (char *key = map_first(m); key != NULL; key = map_next(m, key)) {
* ...
* }
*
* Note that the `key` passed to `map_next` must have come from a previous call
* to `map_first` or `map_next`. Passing strings from other sources produces
* undefined behavior.
*/
const char *map_first(map m);
const char *map_next(map m, const char *key);
#endif

View File

@ -0,0 +1,829 @@
#include "typedef.h"
#include "big.h"
typedef struct
{
u64 m_low;
u64 m_high;
} uint128_t;
void vli_clear(u64 *vli, u8 ndigits)
{
int i;
for (i = 0; i < ndigits; ++i) {
vli[i] = 0;
}
}
/* Returns true if vli == 0, false otherwise. */
int vli_is_zero(u64 *vli, u8 ndigits)
{
int i;
for (i = 0; i < ndigits; ++i) {
if (vli[i])
return 0;
}
return 1;
}
/* Returns nonzero if bit bit of vli is set. */
u64 vli_test_bit(u64 *vli, u8 bit, u8 ndigits)
{
return (vli[bit/64] & ((u64)1 << (bit % 64)));
}
/* Counts the number of 64-bit "digits" in vli. */
u32 vli_num_digits(u64 *vli, u8 ndigits)
{
int i;
/* Search from the end until we find a non-zero digit.
* We do it in reverse because we expect that most digits will
* be nonzero.
*/
for (i = ndigits - 1; i >= 0 && vli[i] == 0; --i);
return (i + 1);
}
/* Counts the number of bits required for vli. */
u32 vli_num_bits(u64 *vli, u8 ndigits)
{
u32 i, num_digits;
u64 digit;
num_digits = vli_num_digits(vli, ndigits);
if (num_digits == 0)
return 0;
digit = vli[num_digits - 1];
for (i = 0; digit; ++i)
digit >>= 1;
return ((num_digits - 1) * 64 + i);
}
/* Sets dest = src. */
void vli_set(u64 *dest, u64 *src, u8 ndigits)
{
u32 i;
for (i = 0; i < ndigits; ++i)
dest[i] = src[i];
}
/* Returns sign of left - right. */
int vli_cmp(u64 *left, u64 *right, u8 ndigits)
{
int i;
for (i = ndigits - 1; i >= 0; --i) {
if (left[i] > right[i])
return 1;
else if (left[i] < right[i])
return -1;
}
return 0;
}
/* Computes result = in << c, returning carry. Can modify in place
* (if result == in). 0 < shift < 64.
*/
u64 vli_lshift(u64 *result, u64 *in, u32 shift, u8 ndigits)
{
u64 carry = 0;
int i;
for (i = 0; i < ndigits; ++i) {
u64 temp = in[i];
result[i] = (temp << shift) | carry;
carry = shift ? temp >> (64 - shift) : 0;
}
return carry;
}
/* Computes result = in >> c, returning carry. Can modify in place
* (if result == in). 0 < shift < 64.
*/
u64 vli_rshift(u64 *result, u64 *in, u32 shift, u8 ndigits)
{
u64 carry = 0;
int i;
for (i = ndigits -1; i >= 0; --i) {
u64 temp = in[i];
result[i] = (temp >> shift) | carry;
carry = shift ? temp << (64 - shift) : 0;
}
return carry;
}
/* Computes result = left + right, returning carry. Can modify in place. */
u64 vli_add(u64 *result, u64 *left, u64 *right, u8 ndigits)
{
u64 carry = 0;
u32 i;
for (i = 0; i < ndigits; ++i) {
u64 sum;
sum = left[i] + right[i] + carry;
if (sum != left[i]) {
carry = (sum < left[i]);
}
result[i] = sum;
}
return carry;
}
/* Computes result = left - right, returning borrow. Can modify in place. */
u64 vli_sub(u64 *result, u64 *left, u64 *right, u8 ndigits)
{
u64 borrow = 0;
int i;
for (i = 0; i < ndigits; ++i) {
u64 diff;
diff = left[i] - right[i] - borrow;
if (diff != left[i])
borrow = (diff > left[i]);
result[i] = diff;
}
return borrow;
}
static uint128_t mul_64_64(u64 left, u64 right)
{
u64 a0 = left & 0xffffffffull;
u64 a1 = left >> 32;
u64 b0 = right & 0xffffffffull;
u64 b1 = right >> 32;
u64 m0 = a0 * b0;
u64 m1 = a0 * b1;
u64 m2 = a1 * b0;
u64 m3 = a1 * b1;
uint128_t result;
m2 += (m0 >> 32);
m2 += m1;
/* Overflow */
if (m2 < m1)
m3 += 0x100000000ull;
result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
result.m_high = m3 + (m2 >> 32);
return result;
}
static uint128_t add_128_128(uint128_t a, uint128_t b)
{
uint128_t result;
result.m_low = a.m_low + b.m_low;
result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low);
return result;
}
static u64 vli_add_digit_mul(u64 *result, u64 *b, u64 c, u64 *d, u8 digits)
{
uint128_t mul;
u64 carry;
u32 i;
if (c == 0)
return 0;
carry = 0;
for (i = 0; i < digits; i++) {
mul = mul_64_64(c, d[i]);
if ((result[i] = b[i] + carry) < carry) {
carry = 1;
} else {
carry = 0;
}
if ((result[i] += mul.m_low) < mul.m_low) {
carry++;
}
carry += mul.m_high;
}
return carry;
}
void bn_mult(u64 *result, u64 *left, u64 *right, u8 ndigits)
{
u64 t[2*128];
u32 bdigits, cdigits, i;
vli_clear(t, 2*ndigits);
bdigits = vli_num_digits(left, ndigits);
cdigits = vli_num_digits(right, ndigits);
for(i=0; i<bdigits; i++) {
t[i+cdigits] += vli_add_digit_mul(&t[i], &t[i], left[i], right, cdigits);
}
vli_set(result, t, 2*ndigits);
}
#define BN_DIGIT_BITS 32
#define BN_MAX_DIGIT 0xFFFFFFFF
static u32 vli_sub_digit_mult(u32 *a, u32 *b, u32 c, u32 *d, u32 digits)
{
u64 result;
u32 borrow, rh, rl;
u32 i;
if(c == 0)
return 0;
borrow = 0;
for(i=0; i<digits; i++) {
result = (u64)c * d[i];
rl = result & BN_MAX_DIGIT;
rh = (result >> BN_DIGIT_BITS) & BN_MAX_DIGIT;
if((a[i] = b[i] - borrow) > (BN_MAX_DIGIT - borrow)) {
borrow = 1;
} else {
borrow = 0;
}
if((a[i] -= rl) > (BN_MAX_DIGIT - rl)) {
borrow++;
}
borrow += rh;
}
return borrow;
}
static u32 bn_digit_bits(u32 a)
{
u32 i;
for(i = 0; i< sizeof(a) * 8; i++) {
if(a == 0) break;
a >>= 1;
}
return i;
}
void bn_div(u32 *a, u32 *b, u32 *c, u32 cdigits, u32 *d, u32 ddigits)
{
u32 ai, t, cc[128+1], dd[128/2];
u32 dddigits, shift;
u64 tmp;
int i;
dddigits = ddigits;
shift = BN_DIGIT_BITS - bn_digit_bits(d[dddigits-1]);
vli_clear((u64*)cc, dddigits/2);
cc[cdigits] = vli_lshift((u64*)cc, (u64*)c, shift, cdigits/2);
vli_lshift((u64*)dd, (u64*)d, shift, dddigits/2);
t = dd[dddigits-1];
vli_clear((u64*)a, cdigits/2);
i = cdigits - dddigits;
for(; i>=0; i--) {
if(t == BN_MAX_DIGIT) {
ai = cc[i+dddigits];
} else {
tmp = cc[i+dddigits-1];
tmp += (u64)cc[i+dddigits] << BN_DIGIT_BITS;
ai = tmp / (t + 1);
}
cc[i+dddigits] -= vli_sub_digit_mult(&cc[i], &cc[i], ai, dd, dddigits);
while(cc[i+dddigits] || (vli_cmp((u64*)&cc[i], (u64*)dd, dddigits/2) >= 0)) {
ai++;
cc[i+dddigits] -= vli_sub((u64*)&cc[i], (u64*)&cc[i], (u64*)dd, dddigits/2);
}
a[i] = ai;
}
vli_rshift((u64*)b, (u64*)cc, shift, dddigits/2);
}
void vli_div(u64 *result, u64 *remainder, u64 *left, u64 cdigits, u64 *right, u8 ddigits)
{
bn_div((u32*)result, (u32*)remainder, (u32*)left, cdigits*2, (u32*)right, ddigits*2);
}
void bn_mod(u64 *result, u64 *left, u64 *right, u8 ndigits)
{
u64 t[2*128];
vli_div(t, result, left, ndigits*2, right, ndigits);
}
void _vli_mult(u64 *result, u64 *left, u64 *right, u8 ndigits)
{
uint128_t r01 = { 0, 0 };
u64 r2 = 0;
unsigned int i, k;
/* Compute each digit of result in sequence, maintaining the
* carries.
*/
for (k = 0; k < ndigits * 2 - 1; k++) {
unsigned int min;
if (k < ndigits)
min = 0;
else
min = (k + 1) - ndigits;
for (i = min; i <= k && i < ndigits; i++) {
uint128_t product;
product = mul_64_64(left[i], right[k - i]);
r01 = add_128_128(r01, product);
r2 += (r01.m_high < product.m_high);
}
result[k] = r01.m_low;
r01.m_low = r01.m_high;
r01.m_high = r2;
r2 = 0;
}
result[ndigits * 2 - 1] = r01.m_low;
}
void vli_mult(u64 *result, u64 *left, u64 *right, u8 ndigits)
{
#if 1
bn_mult(result, left, right, ndigits);
#else
_vli_mult(result, left, right, ndigits);
#endif
}
void vli_square(u64 *result, u64 *left, u8 ndigits)
{
uint128_t r01 = { 0, 0 };
u64 r2 = 0;
int i, k;
for (k = 0; k < ndigits * 2 - 1; k++) {
unsigned int min;
if (k < ndigits)
min = 0;
else
min = (k + 1) - ndigits;
for (i = min; i <= k && i <= k - i; i++) {
uint128_t product;
product = mul_64_64(left[i], left[k - i]);
if (i < k - i) {
r2 += product.m_high >> 63;
product.m_high = (product.m_high << 1) |
(product.m_low >> 63);
product.m_low <<= 1;
}
r01 = add_128_128(r01, product);
r2 += (r01.m_high < product.m_high);
}
result[k] = r01.m_low;
r01.m_low = r01.m_high;
r01.m_high = r2;
r2 = 0;
}
result[ndigits * 2 - 1] = r01.m_low;
}
/* Computes result = (left + right) % mod.
Assumes that left < mod and right < mod, result != mod. */
void vli_mod_add(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits)
{
u64 carry;
carry = vli_add(result, left, right, ndigits);
/* result > mod (result = mod + remainder), so subtract mod to
* get remainder.
*/
if(carry || vli_cmp(result, mod, ndigits) >= 0) {
/* result > mod (result = mod + remainder), so subtract mod to get remainder. */
vli_sub(result, result, mod, ndigits);
}
}
/* Computes result = (left - right) % mod.
* Assumes that left < mod and right < mod, result != mod.
*/
void vli_mod_sub(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits)
{
u64 borrow;
borrow = vli_sub(result, left, right, ndigits);
/* In this case, result == -diff == (max int) - diff.
* Since -x % d == d - x, we can get the correct result from
* result + mod (with overflow).
*/
if(borrow)
vli_add(result, result, mod, ndigits);
}
/* Computes result = product % curve_prime
* from http://www.nsa.gov/ia/_files/nist-routines.pdf
*/
void vli_mmod_fast_nist_256(u64 *result, u64 *product, u64 *curve_prime, u8 ndigits)
{
u64 tmp[2 * 128];
int carry;
/* t */
vli_set(result, product, ndigits);
/* s1 */
tmp[0] = 0;
tmp[1] = product[5] & 0xffffffff00000000ull;
tmp[2] = product[6];
tmp[3] = product[7];
carry = vli_lshift(tmp, tmp, 1, ndigits);
carry += vli_add(result, result, tmp, ndigits);
/* s2 */
tmp[1] = product[6] << 32;
tmp[2] = (product[6] >> 32) | (product[7] << 32);
tmp[3] = product[7] >> 32;
carry += vli_lshift(tmp, tmp, 1, ndigits);
carry += vli_add(result, result, tmp, ndigits);
/* s3 */
tmp[0] = product[4];
tmp[1] = product[5] & 0xffffffff;
tmp[2] = 0;
tmp[3] = product[7];
carry += vli_add(result, result, tmp, ndigits);
/* s4 */
tmp[0] = (product[4] >> 32) | (product[5] << 32);
tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
tmp[2] = product[7];
tmp[3] = (product[6] >> 32) | (product[4] << 32);
carry += vli_add(result, result, tmp, ndigits);
/* d1 */
tmp[0] = (product[5] >> 32) | (product[6] << 32);
tmp[1] = (product[6] >> 32);
tmp[2] = 0;
tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
carry -= vli_sub(result, result, tmp, ndigits);
/* d2 */
tmp[0] = product[6];
tmp[1] = product[7];
tmp[2] = 0;
tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
carry -= vli_sub(result, result, tmp, ndigits);
/* d3 */
tmp[0] = (product[6] >> 32) | (product[7] << 32);
tmp[1] = (product[7] >> 32) | (product[4] << 32);
tmp[2] = (product[4] >> 32) | (product[5] << 32);
tmp[3] = (product[6] << 32);
carry -= vli_sub(result, result, tmp, ndigits);
/* d4 */
tmp[0] = product[7];
tmp[1] = product[4] & 0xffffffff00000000ull;
tmp[2] = product[5];
tmp[3] = product[6] & 0xffffffff00000000ull;
carry -= vli_sub(result, result, tmp, ndigits);
if (carry < 0) {
do {
carry += vli_add(result, result, curve_prime, ndigits);
} while (carry < 0);
} else {
while (carry || vli_cmp(curve_prime, result, ndigits) != 1){
carry -= vli_sub(result, result, curve_prime, ndigits);
}
}
}
void vli_mmod_fast_sm2_256(u64 *result, u64 *_product, u64 *mod, u8 ndigits)
{
u32 tmp1[8];
u32 tmp2[8];
u32 tmp3[8];
u32 *product = (u32 *)_product;
int carry = 0;
vli_set(result, (u64 *)product, ndigits);
vli_clear((u64 *)tmp1, ndigits);
vli_clear((u64 *)tmp2, ndigits);
vli_clear((u64 *)tmp3, ndigits);
/* Y0 */
tmp1[0] = tmp1[3] = tmp1[7] = product[8];
tmp2[2] = product[8];
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
carry -= vli_sub(result, result, (u64 *)tmp2, ndigits);
/* Y1 */
tmp1[0] = tmp1[1] = tmp1[4] = tmp1[7] = product[9];
tmp1[3] = 0;
tmp2[2] = product[9];
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
carry -= vli_sub(result, result, (u64 *)tmp2, ndigits);
/* Y2 */
tmp1[0] = tmp1[1] = tmp1[5] = tmp1[7] = product[10];
tmp1[4] = 0;
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
/* Y3 */
tmp1[0] = tmp1[1] = tmp1[3] = tmp1[6] = tmp1[7] = product[11];
tmp1[5] = 0;
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
/* Y4 */
tmp1[0] = tmp1[1] = tmp1[3] = tmp1[4] = tmp1[7] = tmp3[7] = product[12];
tmp1[6] = 0;
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
carry += vli_add(result, result, (u64 *)tmp3, ndigits);
/* Y5 */
tmp1[0] = tmp1[1] = tmp1[3] = tmp1[4] = tmp1[5] = tmp1[7] = product[13];
tmp2[2] = product[13];
tmp3[0] = tmp3[3] = tmp3[7] = product[13];
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
carry += vli_add(result, result, (u64 *)tmp3, ndigits);
carry -= vli_sub(result, result, (u64 *)tmp2, ndigits);
/* Y6 */
tmp1[0] = tmp1[1] = tmp1[3] = tmp1[4] = tmp1[5] = tmp1[6] = tmp1[7] = product[14];
tmp2[2] = product[14];
tmp3[0] = tmp3[1] = tmp3[4] = tmp3[7] = product[14];
tmp3[3] = 0;
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
carry += vli_add(result, result, (u64 *)tmp3, ndigits);
carry -= vli_sub(result, result, (u64 *)tmp2, ndigits);
/* Y7 */
tmp1[0] = tmp1[1] = tmp1[3] = tmp1[4] = tmp1[5] = tmp1[6] = tmp1[7] = product[15];
tmp3[0] = tmp3[1] = tmp3[5] = product[15];
tmp3[4] = 0;
tmp3[7] = 0;
tmp2[7] = product[15];
tmp2[2] = 0;
carry += vli_lshift((u64 *)tmp2, (u64 *)tmp2, 1, ndigits);
carry += vli_add(result, result, (u64 *)tmp1, ndigits);
carry += vli_add(result, result, (u64 *)tmp3, ndigits);
carry += vli_add(result, result, (u64 *)tmp2, ndigits);
if (carry < 0) {
do {
carry += vli_add(result, result, mod, ndigits);
} while(carry < 0);
} else {
while (carry || vli_cmp(mod, result, ndigits) != 1)
{
carry -= vli_sub(result, result, mod, ndigits);
}
}
}
/* Computes result = (product) % mod. */
void _vli_mod(u64 *result, u64 *product, u64 *mod, u8 ndigits)
{
u64 modMultiple[2 * 128];
u32 digitShift, bitShift;
u32 productBits;
u32 modBits = vli_num_bits(mod, ndigits);
productBits = vli_num_bits(product + ndigits, ndigits);
if (productBits) {
productBits += ndigits * 64;
} else {
productBits = vli_num_bits(product, ndigits);
}
if (productBits < modBits) {
/* product < mod. */
vli_set(result, product, ndigits);
return;
}
/* Shift mod by (leftBits - modBits). This multiplies mod by the largest
power of two possible while still resulting in a number less than left. */
vli_clear(modMultiple, ndigits);
vli_clear(modMultiple + ndigits, ndigits);
digitShift = (productBits - modBits) / 64;
bitShift = (productBits - modBits) % 64;
if (bitShift) {
modMultiple[digitShift + ndigits] = vli_lshift(modMultiple + digitShift, mod, bitShift, ndigits);
} else {
vli_set(modMultiple + digitShift, mod, ndigits);
}
/* Subtract all multiples of mod to get the remainder. */
vli_clear(result, ndigits);
result[0] = 1; /* Use result as a temp var to store 1 (for subtraction) */
while (productBits > ndigits * 64 || vli_cmp(modMultiple, mod, ndigits) >= 0)
{
u64 carry;
int cmp = vli_cmp(modMultiple + ndigits, product + ndigits, ndigits);
if (cmp < 0 || (cmp == 0 && vli_cmp(modMultiple, product, ndigits) <= 0)) {
if (vli_sub(product, product, modMultiple, ndigits))
{
/* borrow */
vli_sub(product + ndigits, product + ndigits, result, ndigits);
}
vli_sub(product + ndigits, product + ndigits, modMultiple + ndigits, ndigits);
}
carry = (modMultiple[ndigits] & 0x01) << 63;
vli_rshift(modMultiple + ndigits, modMultiple + ndigits, 1, ndigits);
vli_rshift(modMultiple, modMultiple, 1, ndigits);
modMultiple[ndigits-1] |= carry;
--productBits;
}
vli_set(result, product, ndigits);
}
/* Computes result = (product) % mod. */
void vli_mod(u64 *result, u64 *product, u64 *mod, u8 ndigits)
{
bn_mod(result, product, mod, ndigits);
}
/* Computes result = (left * right) % curve->p. */
void vli_mod_mult_fast(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits)
{
u64 product[2 * 128];
vli_mult(product, left, right, ndigits);
vli_mod(result, product, mod, ndigits);
}
/* Computes result = left^2 % curve->p. */
void vli_mod_square_fast(u64 *result, u64 *left, u64 *mod, u8 ndigits)
{
u64 product[2 * 128];
vli_square(product, left, ndigits);
vli_mod(result, product, mod, ndigits);
}
/* Computes result = (left * right) % mod. */
void vli_mod_mult(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits)
{
u64 product[2 * 1024];
vli_mult(product, left, right, ndigits);
vli_mod(result, product, mod, ndigits);
}
/* Computes result = left^2 % mod. */
void vli_mod_square(u64 *result, u64 *left, u64 *mod, u8 ndigits)
{
u64 product[2 * 128];
vli_square(product, left, ndigits);
vli_mod(result, product, mod, ndigits);
}
#define DIGIT_2MSB(x) (u64)(((x) >> (VLI_DIGIT_BITS - 2)) & 0x03)
/* Computes result = left^p % mod. */
void vli_mod_exp(u64 *result, u64 *left, u64 *p, u64 *mod, u8 ndigits)
{
u64 bpower[3][128], t[128];
u64 ci_bits, ci;
u32 j, s;
u32 digits;
int i;
vli_set(bpower[0], left, ndigits);
vli_mod_mult(bpower[1], bpower[0], left, mod, ndigits);
vli_mod_mult(bpower[2], bpower[1], left, mod, ndigits);
vli_clear(t, ndigits);
t[0] = 1;
digits = vli_num_digits(p , ndigits);
i = digits - 1;
for ( ; i >= 0; i--) {
ci = p[i];
ci_bits = VLI_DIGIT_BITS;
if (i == (digits - 1)) {
while (!DIGIT_2MSB(ci)) {
ci <<= 2;
ci_bits -= 2;
}
}
for( j = 0; j < ci_bits; j += 2) {
vli_mod_mult(t, t, t, mod, ndigits);
vli_mod_mult(t, t, t, mod, ndigits);
if ((s = DIGIT_2MSB(ci)) != 0) {
vli_mod_mult(t, t, bpower[s-1], mod, ndigits);
}
ci <<= 2;
}
}
vli_set(result, t, ndigits);
}
#define EVEN(vli) (!(vli[0] & 1))
/* Computes result = (1 / p_input) % mod. All VLIs are the same size.
* See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
* https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
*/
void vli_mod_inv(u64 *result, u64 *input, u64 *mod, u8 ndigits)
{
u64 a[128], b[128];
u64 u[128], v[128];
u64 carry;
int cmp_result;
if (vli_is_zero(input, ndigits)) {
vli_clear(result, ndigits);
return;
}
vli_set(a, input, ndigits);
vli_set(b, mod, ndigits);
vli_clear(u, ndigits);
u[0] = 1;
vli_clear(v, ndigits);
while ((cmp_result = vli_cmp(a, b, ndigits)) != 0) {
carry = 0;
if (EVEN(a)) {
vli_rshift(a, a, 1, ndigits);
if (!EVEN(u))
carry = vli_add(u, u, mod, ndigits);
vli_rshift(u, u, 1, ndigits);
if (carry)
u[ndigits - 1] |= 0x8000000000000000ull;
} else if (EVEN(b)) {
vli_rshift(b, b, 1, ndigits);
if (!EVEN(v))
carry = vli_add(v, v, mod, ndigits);
vli_rshift(v, v, 1, ndigits);
if (carry)
v[ndigits - 1] |= 0x8000000000000000ull;
} else if (cmp_result > 0) {
vli_sub(a, a, b, ndigits);
vli_rshift(a, a, 1, ndigits);
if (vli_cmp(u, v, ndigits) < 0)
vli_add(u, u, mod, ndigits);
vli_sub(u, u, v, ndigits);
if (!EVEN(u))
carry = vli_add(u, u, mod, ndigits);
vli_rshift(u, u, 1, ndigits);
if (carry)
u[ndigits - 1] |= 0x8000000000000000ull;
} else {
vli_sub(b, b, a, ndigits);
vli_rshift(b, b, 1, ndigits);
if (vli_cmp(v, u, ndigits) < 0)
vli_add(v, v, mod, ndigits);
vli_sub(v, v, u, ndigits);
if (!EVEN(v))
carry = vli_add(v, v, mod, ndigits);
vli_rshift(v, v, 1, ndigits);
if (carry)
v[ndigits - 1] |= 0x8000000000000000ull;
}
}
vli_set(result, u, ndigits);
}

View File

@ -0,0 +1,88 @@
#ifndef _BIG_H_
#define _BIG_H_
#include "typedef.h"
#define VLI_DIGIT_BITS 64
#define VLI_DIGIT_BYTES (VLI_DIGIT_BITS/8)
void vli_clear(u64 *vli, u8 ndigits);
/* Returns true if vli == 0, false otherwise. */
int vli_is_zero(u64 *vli, u8 ndigits);
/* Returns nonzero if bit bit of vli is set. */
u64 vli_test_bit(u64 *vli, u8 bit, u8 ndigits);
/* Counts the number of 8-bit "digits" in vli. */
u32 vli_num_digits(u64 *vli, u8 ndigits);
/* Counts the number of bits required for vli. */
u32 vli_num_bits(u64 *vli, u8 ndigits);
/* Sets dest = src. */
void vli_set(u64 *dest, u64 *src, u8 ndigits);
/* Returns sign of left - right. */
int vli_cmp(u64 *left, u64 *right, u8 ndigits);
/* Computes result = in << c, returning carry. Can modify in place
* (if result == in). 0 < shift < 8.
*/
u64 vli_lshift(u64 *result, u64 *in, u32 shift, u8 ndigits);
/* Computes result = (left * right) % curve->p. */
void vli_mod_mult_fast(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits);
/* Computes result = left^2 % curve->p. */
void vli_mod_square_fast(u64 *result, u64 *left, u64 *mod, u8 ndigits);
/* Computes result = in >> c, returning carry. Can modify in place
* (if result == in). 0 < shift < 64.
*/
u64 vli_rshift(u64 *result, u64 *in, u32 shift, u8 ndigits);
/* Computes result = left + right, returning carry. Can modify in place. */
u64 vli_add(u64 *result, u64 *left, u64 *right, u8 ndigits);
/* Computes result = left - right, returning borrow. Can modify in place. */
u64 vli_sub(u64 *result, u64 *left, u64 *right, u8 ndigits);
/* Computes result = left * right. */
void vli_mult(u64 *result, u64 *left, u64 *right, u8 ndigits);
/* Computes result = left^2. */
void vli_square(u64 *result, u64 *left, u8 ndigits);
/* Computes result = (left + right) % mod.
Assumes that left < mod and right < mod, result != mod. */
void vli_mod_add(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits);
/* Computes result = (left - right) % mod.
Assumes that left < mod and right < mod, result != mod. */
void vli_mod_sub(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits);
/* Computes result = (left * right) % mod. */
void vli_mod_mult(u64 *result, u64 *left, u64 *right, u64 *mod, u8 ndigits);
/* Computes result = left^2 % mod. */
void vli_mod_square(u64 *result, u64 *left, u64 *mod, u8 ndigits);
/* Computes result = left^p % mod. */
void vli_mod_exp(u64 *result, u64 *left, u64 *p, u64 *mod, u8 ndigits);
/* Computes result = (product) % mod. */
void vli_mod(u64 *result, u64 *product, u64 *mod, u8 ndigits);
/* Computes result = (1 / input) % mod. All VLIs are the same size.
* See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
* https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
*/
void vli_mod_inv(u64 *result, u64 *input, u64 *mod, u8 ndigits);
/* Computes result = (left / right).
* remainder = (left % right).
*/
void vli_div(u64 *result, u64 *remainder, u64 *left, u64 cdigits, u64 *right, u8 ddigits);
#endif

View File

@ -0,0 +1,352 @@
#include <stdio.h>
#include "typedef.h"
#include "ecc.h"
#include "big.h"
static u64 cpu_to_be64(u64 x)
{
u64 r;
int i, len;
char *p, *q;
len = sizeof(x);
q = (char *)&x + len - 1;
p = (char *)&r;
for (i = 0; i < len; i++)
{
*p = *q;
p++;
q--;
}
return r;
}
static u64 be64_to_cpu(u64 x)
{
u64 r;
int i, len;
char *p, *q;
len = sizeof(x);
q = (char *)&x + len - 1;
p = (char *)&r;
for (i = 0; i < len; i++)
{
*p = *q;
p++;
q--;
}
return r;
}
/* Returns 1 if point is the point at infinity, 0 otherwise. */
int ecc_point_is_zero(struct ecc_curve *curve, ecc_point *point)
{
return (vli_is_zero(point->x, curve->ndigits)
&& vli_is_zero(point->y, curve->ndigits));
}
/* Double in place */
void ecc_point_double_jacobian(struct ecc_curve *curve, u64 *X1, u64 *Y1, u64 *Z1)
{
/* t1 = X, t2 = Y, t3 = Z */
u64 t4[ECC_MAX_DIGITS];
u64 t5[ECC_MAX_DIGITS];
if(vli_is_zero(Z1, curve->ndigits))
return;
vli_mod_square_fast(t4, Y1, curve->p, curve->ndigits); /* t4 = y1^2 */
vli_mod_mult_fast(t5, X1, t4, curve->p, curve->ndigits); /* t5 = x1*y1^2 = A */
vli_mod_square_fast(t4, t4, curve->p, curve->ndigits); /* t4 = y1^4 */
vli_mod_mult_fast(Y1, Y1, Z1, curve->p, curve->ndigits); /* t2 = y1*z1 = z3 */
vli_mod_square_fast(Z1, Z1, curve->p, curve->ndigits); /* t3 = z1^2 */
vli_mod_add(X1, X1, Z1, curve->p, curve->ndigits); /* t1 = x1 + z1^2 */
vli_mod_add(Z1, Z1, Z1, curve->p, curve->ndigits); /* t3 = 2*z1^2 */
vli_mod_sub(Z1, X1, Z1, curve->p, curve->ndigits); /* t3 = x1 - z1^2 */
vli_mod_mult_fast(X1, X1, Z1, curve->p, curve->ndigits); /* t1 = x1^2 - z1^4 */
vli_mod_add(Z1, X1, X1, curve->p, curve->ndigits); /* t3 = 2*(x1^2 - z1^4) */
vli_mod_add(X1, X1, Z1, curve->p, curve->ndigits); /* t1 = 3*(x1^2 - z1^4) */
if (vli_test_bit(X1, 0, curve->ndigits)) {
u64 carry = vli_add(X1, X1, curve->p, curve->ndigits);
vli_rshift(X1, X1, 1, curve->ndigits);
X1[ECC_MAX_DIGITS-1] |= carry << 63;
} else {
vli_rshift(X1, X1, 1, curve->ndigits);
}
/* t1 = 3/2*(x1^2 - z1^4) = B */
vli_mod_square_fast(Z1, X1, curve->p, curve->ndigits); /* t3 = B^2 */
vli_mod_sub(Z1, Z1, t5, curve->p, curve->ndigits); /* t3 = B^2 - A */
vli_mod_sub(Z1, Z1, t5, curve->p, curve->ndigits); /* t3 = B^2 - 2A = x3 */
vli_mod_sub(t5, t5, Z1, curve->p, curve->ndigits); /* t5 = A - x3 */
vli_mod_mult_fast(X1, X1, t5, curve->p, curve->ndigits); /* t1 = B * (A - x3) */
vli_mod_sub(t4, X1, t4, curve->p, curve->ndigits); /* t4 = B * (A - x3) - y1^4 = y3 */
vli_set(X1, Z1, curve->ndigits);
vli_set(Z1, Y1, curve->ndigits);
vli_set(Y1, t4, curve->ndigits);
}
/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
void apply_z(struct ecc_curve *curve, u64 *X1, u64 *Y1, u64 *Z)
{
u64 t1[ECC_MAX_DIGITS];
vli_mod_square_fast(t1, Z, curve->p, curve->ndigits); /* z^2 */
vli_mod_mult_fast(X1, X1, t1, curve->p, curve->ndigits); /* x1 * z^2 */
vli_mod_mult_fast(t1, t1, Z, curve->p, curve->ndigits); /* z^3 */
vli_mod_mult_fast(Y1, Y1, t1, curve->p, curve->ndigits); /* y1 * z^3 */
}
/* P = (x1, y1) => 2P, (x2, y2) => P' */
void XYcZ_initial_double(struct ecc_curve *curve, u64 *X1, u64 *Y1, u64 *X2, u64 *Y2, u64 *initialZ)
{
u64 z[ECC_MAX_DIGITS];
vli_set(X2, X1, curve->ndigits);
vli_set(Y2, Y1, curve->ndigits);
if (initialZ) {
vli_set(z, initialZ, curve->ndigits);
} else {
vli_clear(z, curve->ndigits);
z[0] = 1;
}
apply_z(curve, X1, Y1, z);
ecc_point_double_jacobian(curve, X1, Y1, z);
apply_z(curve, X2, Y2, z);
}
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
or P => P', Q => P + Q
*/
void XYcZ_add(struct ecc_curve *curve, u64 *X1, u64 *Y1, u64 *X2, u64 *Y2)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
u64 t5[ECC_MAX_DIGITS];
vli_mod_sub(t5, X2, X1, curve->p, curve->ndigits); /* t5 = x2 - x1 */
vli_mod_square_fast(t5, t5, curve->p, curve->ndigits); /* t5 = (x2 - x1)^2 = A */
vli_mod_mult_fast(X1, X1, t5, curve->p, curve->ndigits); /* t1 = x1*A = B */
vli_mod_mult_fast(X2, X2, t5, curve->p, curve->ndigits); /* t3 = x2*A = C */
vli_mod_sub(Y2, Y2, Y1, curve->p, curve->ndigits); /* t4 = y2 - y1 */
vli_mod_square_fast(t5, Y2, curve->p, curve->ndigits); /* t5 = (y2 - y1)^2 = D */
vli_mod_sub(t5, t5, X1, curve->p, curve->ndigits); /* t5 = D - B */
vli_mod_sub(t5, t5, X2, curve->p, curve->ndigits); /* t5 = D - B - C = x3 */
vli_mod_sub(X2, X2, X1, curve->p, curve->ndigits); /* t3 = C - B */
vli_mod_mult_fast(Y1, Y1, X2, curve->p, curve->ndigits); /* t2 = y1*(C - B) */
vli_mod_sub(X2, X1, t5, curve->p, curve->ndigits); /* t3 = B - x3 */
vli_mod_mult_fast(Y2, Y2, X2, curve->p, curve->ndigits); /* t4 = (y2 - y1)*(B - x3) */
vli_mod_sub(Y2, Y2, Y1, curve->p, curve->ndigits); /* t4 = y3 */
vli_set(X2, t5, curve->ndigits);
}
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
* Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
* or P => P - Q, Q => P + Q
*/
void XYcZ_addC(struct ecc_curve *curve, u64 *X1, u64 *Y1, u64 *X2, u64 *Y2)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
u64 t5[ECC_MAX_DIGITS];
u64 t6[ECC_MAX_DIGITS];
u64 t7[ECC_MAX_DIGITS];
vli_mod_sub(t5, X2, X1, curve->p, curve->ndigits); /* t5 = x2 - x1 */
vli_mod_square_fast(t5, t5, curve->p, curve->ndigits); /* t5 = (x2 - x1)^2 = A */
vli_mod_mult_fast(X1, X1, t5, curve->p, curve->ndigits); /* t1 = x1*A = B */
vli_mod_mult_fast(X2, X2, t5, curve->p, curve->ndigits); /* t3 = x2*A = C */
vli_mod_add(t5, Y2, Y1, curve->p, curve->ndigits); /* t4 = y2 + y1 */
vli_mod_sub(Y2, Y2, Y1, curve->p, curve->ndigits); /* t4 = y2 - y1 */
vli_mod_sub(t6, X2, X1, curve->p, curve->ndigits); /* t6 = C - B */
vli_mod_mult_fast(Y1, Y1, t6, curve->p, curve->ndigits); /* t2 = y1 * (C - B) */
vli_mod_add(t6, X1, X2, curve->p, curve->ndigits); /* t6 = B + C */
vli_mod_square_fast(X2, Y2, curve->p, curve->ndigits); /* t3 = (y2 - y1)^2 */
vli_mod_sub(X2, X2, t6, curve->p, curve->ndigits); /* t3 = x3 */
vli_mod_sub(t7, X1, X2, curve->p, curve->ndigits); /* t7 = B - x3 */
vli_mod_mult_fast(Y2, Y2, t7, curve->p, curve->ndigits); /* t4 = (y2 - y1)*(B - x3) */
vli_mod_sub(Y2, Y2, Y1, curve->p, curve->ndigits); /* t4 = y3 */
vli_mod_square_fast(t7, t5, curve->p, curve->ndigits); /* t7 = (y2 + y1)^2 = F */
vli_mod_sub(t7, t7, t6, curve->p, curve->ndigits); /* t7 = x3' */
vli_mod_sub(t6, t7, X1, curve->p, curve->ndigits); /* t6 = x3' - B */
vli_mod_mult_fast(t6, t6, t5, curve->p, curve->ndigits); /* t6 = (y2 + y1)*(x3' - B) */
vli_mod_sub(Y1, t6, Y1, curve->p, curve->ndigits); /* t2 = y3' */
vli_set(X1, t7, curve->ndigits);
}
void ecc_point_mult(struct ecc_curve *curve, ecc_point *result, ecc_point *point, u64 *scalar, u64 *initialZ)
{
/* R0 and R1 */
u64 Rx[2][ECC_MAX_DIGITS];
u64 Ry[2][ECC_MAX_DIGITS];
u64 z[ECC_MAX_DIGITS];
int i, nb;
vli_set(Rx[1], point->x, curve->ndigits);
vli_set(Ry[1], point->y, curve->ndigits);
XYcZ_initial_double(curve, Rx[1], Ry[1], Rx[0], Ry[0], initialZ);
for (i = vli_num_bits(scalar, curve->ndigits) - 2; i > 0; --i) {
nb = !vli_test_bit(scalar, i, curve->ndigits);
XYcZ_addC(curve, Rx[1-nb], Ry[1-nb], Rx[nb], Ry[nb]);
XYcZ_add(curve, Rx[nb], Ry[nb], Rx[1-nb], Ry[1-nb]);
}
nb = !vli_test_bit(scalar, 0, curve->ndigits);
XYcZ_addC(curve, Rx[1-nb], Ry[1-nb], Rx[nb], Ry[nb]);
/* Find final 1/Z value. */
vli_mod_sub(z, Rx[1], Rx[0], curve->p, curve->ndigits); /* X1 - X0 */
vli_mod_mult_fast(z, z, Ry[1-nb], curve->p, curve->ndigits); /* Yb * (X1 - X0) */
vli_mod_mult_fast(z, z, point->x, curve->p, curve->ndigits); /* xP * Yb * (X1 - X0) */
vli_mod_inv(z, z, curve->p, curve->ndigits); /* 1 / (xP * Yb * (X1 - X0)) */
vli_mod_mult_fast(z, z, point->y, curve->p, curve->ndigits); /* yP / (xP * Yb * (X1 - X0)) */
vli_mod_mult_fast(z, z, Rx[1-nb], curve->p, curve->ndigits); /* Xb * yP / (xP * Yb * (X1 - X0)) */
/* End 1/Z calculation */
XYcZ_add(curve, Rx[nb], Ry[nb], Rx[1-nb], Ry[1-nb]);
apply_z(curve, Rx[0], Ry[0], z);
vli_set(result->x, Rx[0], curve->ndigits);
vli_set(result->y, Ry[0], curve->ndigits);
}
static u32 max(u32 a, u32 b)
{
return (a > b ? a : b);
}
void ecc_point_mult2(struct ecc_curve *curve, ecc_point *result, ecc_point *g, ecc_point *p, u64 *s, u64 *t)
{
u64 tx[ECC_MAX_DIGITS];
u64 ty[ECC_MAX_DIGITS];
u64 tz[ECC_MAX_DIGITS];
u64 z[ECC_MAX_DIGITS];
ecc_point sum;
u64 *rx;
u64 *ry;
int i;
ecc_point *points[4] = {NULL, g, p, &sum};
u32 numBits;
ecc_point *point;
rx = result->x;
ry = result->y;
/* Calculate sum = G + Q. */
vli_set(sum.x, p->x, curve->ndigits);
vli_set(sum.y, p->y, curve->ndigits);
vli_set(tx, g->x, curve->ndigits);
vli_set(ty, g->y, curve->ndigits);
vli_mod_sub(z, sum.x, tx, curve->p, curve->ndigits); /* Z = x2 - x1 */
XYcZ_add(curve, tx, ty, sum.x, sum.y);
vli_mod_inv(z, z, curve->p, curve->ndigits); /* Z = 1/Z */
apply_z(curve, sum.x, sum.y, z);
numBits = max(vli_num_bits(s, curve->ndigits), vli_num_bits(t, curve->ndigits));
point = points[(!!vli_test_bit(s, numBits-1, curve->ndigits))
| ((!!vli_test_bit(t, numBits-1, curve->ndigits)) << 1)];
vli_set(rx, point->x, curve->ndigits);
vli_set(ry, point->y, curve->ndigits);
vli_clear(z, curve->ndigits);
z[0] = 1;
for (i = numBits - 2; i >= 0; --i) {
int index;
ecc_point *point;
ecc_point_double_jacobian(curve, rx, ry, z);
index = (!!vli_test_bit(s, i, curve->ndigits)) | ((!!vli_test_bit(t, i, curve->ndigits)) << 1);
point = points[index];
if(point) {
vli_set(tx, point->x, curve->ndigits);
vli_set(ty, point->y, curve->ndigits);
apply_z(curve, tx, ty, z);
vli_mod_sub(tz, rx, tx, curve->p, curve->ndigits); /* Z = x2 - x1 */
XYcZ_add(curve, tx, ty, rx, ry);
vli_mod_mult_fast(z, z, tz, curve->p, curve->ndigits);
}
}
vli_mod_inv(z, z, curve->p, curve->ndigits); /* Z = 1/Z */
apply_z(curve, rx, ry, z);
}
void ecc_point_add(struct ecc_curve *curve, ecc_point *result, ecc_point *left, ecc_point *right)
{
u64 x1[ECC_MAX_DIGITS];
u64 y1[ECC_MAX_DIGITS];
u64 x2[ECC_MAX_DIGITS];
u64 y2[ECC_MAX_DIGITS];
u64 z[ECC_MAX_DIGITS];
vli_set(x1, left->x, curve->ndigits);
vli_set(y1, left->y, curve->ndigits);
vli_set(x2, right->x, curve->ndigits);
vli_set(y2, right->y, curve->ndigits);
vli_mod_sub(z, x2, x1, curve->p, curve->ndigits); /* Z = x2 - x1 */
XYcZ_add(curve, x1, y1, x2, y2);
vli_mod_inv(z, z, curve->p, curve->ndigits); /* Z = 1/Z */
apply_z(curve, x2,y2, z);
vli_set(result->x, x2, curve->ndigits);
vli_set(result->y, y2, curve->ndigits);
}
void ecc_bytes2native(u64 *native, void *bytes, u8 ndigits)
{
u64 *_bytes = (u64*)bytes;
unsigned int i;
for (i = 0; i < ndigits/2; ++i) {
if (native == _bytes) {
u64 temp;
temp = be64_to_cpu(native[i]);
native[i] = be64_to_cpu(_bytes[ndigits - i - 1]);
_bytes[ndigits - i - 1] = temp;
}else {
native[i] = be64_to_cpu(_bytes[ndigits - i - 1]);
native[ndigits - i - 1] = be64_to_cpu(_bytes[i]);
}
}
}
void ecc_native2bytes(void *bytes, u64 *native, u8 ndigits)
{
u64 *_bytes = (u64*)bytes;
unsigned int i;
for (i = 0; i < ndigits/2; ++i) {
if (_bytes == native) {
u64 temp;
temp = cpu_to_be64(_bytes[ndigits - i - 1]);
_bytes[ndigits - i - 1] = cpu_to_be64(native[i]);
native[i] = temp;
} else {
_bytes[i] = cpu_to_be64(native[ndigits - i - 1]);
_bytes[ndigits - i - 1] = cpu_to_be64(native[i]);
}
}
}

View File

@ -0,0 +1,64 @@
#ifndef _ECC_H_
#define _ECC_H_
#include "typedef.h"
#define ECC_WORDSIZE 8
#define ECC_NUMBITS 256
#define ECC_NUMWORD (ECC_NUMBITS/ECC_WORDSIZE) //32
#define ECC_MAX_DIGITS 4
#define SWAP(a,b) { u32 t = a; a = b; b = t;}
/*
#define digit2str16(x, y) { \
(y)[0] = (u64)((x >> 8 ) & 0x000000FF); \
(y)[1] = (u64)((x >> 0 ) & 0x000000FF); \
}
#define str2digit16(y, x) { \
x = ((((u16)(y)[0]) & 0x000000FF) << 8) | \
((((u16)(y)[1]) & 0x000000FF) << 0 ); \
}
#define digit2str32(x, y) { \
(y)[0] = (u64)((x >> 24) & 0x000000FF); \
(y)[1] = (u64)((x >> 16) & 0x000000FF); \
(y)[2] = (u64)((x >> 8 ) & 0x000000FF); \
(y)[3] = (u64)((x >> 0 ) & 0x000000FF); \
}
#define str2digit32(y, x) { \
x = ((((u32)(y)[0]) & 0x000000FF) << 24) | \
((((u32)(y)[1]) & 0x000000FF) << 16) | \
((((u32)(y)[2]) & 0x000000FF) << 8 ) | \
((((u32)(y)[3]) & 0x000000FF) << 0 ); \
}
*/
typedef struct ecc_point
{
u64 x[ECC_MAX_DIGITS];
u64 y[ECC_MAX_DIGITS];
} ecc_point;
struct ecc_curve {
u8 ndigits;
struct ecc_point g;
u64 p[ECC_MAX_DIGITS];
u64 n[ECC_MAX_DIGITS];
u64 h[ECC_MAX_DIGITS];
u64 a[ECC_MAX_DIGITS];
u64 b[ECC_MAX_DIGITS];
};
void ecc_bytes2native(u64 *native, void *bytes, u8 ndigits);
void ecc_native2bytes(void *bytes, u64 *native, u8 ndigits);
void ecc_point_add(struct ecc_curve *curve, ecc_point *result, ecc_point *x, ecc_point *y);
void ecc_point_mult(struct ecc_curve *curve, ecc_point *result, ecc_point *point, u64 *scalar, u64 *initialZ);
void ecc_point_mult2(struct ecc_curve *curve, ecc_point *result, ecc_point *g, ecc_point *p, u64 *s, u64 *t);
int ecc_point_is_zero(struct ecc_curve *curve, ecc_point *point);
#endif

View File

@ -0,0 +1,28 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "typedef.h"
int vli_get_random(u8 *data, u32 len)
{
int i;
int r;
if (len >= 4)
{
for (i = 0; i < len / 4; i++)
{
r = rand();
memcpy(data + i * 4, &r, 4);
}
}
if (len % 4)
{
r = rand();
memcpy(data + i * 4, &r, len % 4);
}
return len;
}

View File

@ -0,0 +1,10 @@
#ifndef _RANDOM_H_
#define _RANDOM_H_
#include "typedef.h"
int vli_get_random(u8 *p_data, u32 len);
#endif

View File

@ -0,0 +1,537 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "big.h"
#include "ecc.h"
#include "sm2.h"
#include "sm3.h"
struct ecc_curve sm2_curve = {
ECC_MAX_DIGITS,
{
{0x715A4589334C74C7ull, 0x8FE30BBFF2660BE1ull, 0x5F9904466A39C994ull, 0x32C4AE2C1F198119ull},
{0x02DF32E52139F0A0ull, 0xD0A9877CC62A4740ull, 0x59BDCEE36B692153ull, 0xBC3736A2F4F6779Cull},
},
{0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFEFFFFFFFFull},
{0x53BBF40939D54123ull, 0x7203DF6B21C6052Bull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFEFFFFFFFFull},
{
0x0000000000000001ull,
0x0000000000000000ull,
0x0000000000000000ull,
0x0000000000000000ull,
},
{0xFFFFFFFFFFFFFFFCull, 0xFFFFFFFF00000000ull, 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFEFFFFFFFFull},
{0xDDBCBD414D940E93ull, 0xF39789F515AB8F92ull, 0x4D5A9E4BCF6509A7ull, 0x28E9FA9E9D9F5E34ull},
};
static void
sm2_w(u64 *result, u64 *x)
{
result[0] = x[0];
result[1] = x[1];
result[1] |= 0x80;
result[2] = 0;
result[3] = 0;
}
static void
sm3_kdf(u8 *Z, u32 zlen, u8 *K, u32 klen)
{
u32 ct = 0x00000001;
u8 ct_char[32];
u8 *hash = K;
u32 i, t;
struct sm3_ctx md[1];
t = klen / ECC_NUMWORD;
//s4: K=Ha1||Ha2||...
for (i = 0; i < t; i++) {
//s2: Hai=Hv(Z||ct)
sm3_init(md);
sm3_update(md, Z, zlen);
put_unaligned_be32(ct, ct_char);
sm3_update(md, ct_char, 4);
sm3_final(md, hash);
hash += 32;
ct++;
}
t = klen % ECC_NUMBITS;
if (t) {
sm3_init(md);
sm3_update(md, Z, zlen);
put_unaligned_be32(ct, ct_char);
sm3_update(md, ct_char, 4);
sm3_final(md, ct_char);
memcpy(hash, ct_char, t);
}
}
static void
sm3_z(u8 *id, u32 idlen, ecc_point *pub, u8 *hash)
{
u8 a[ECC_NUMWORD];
u8 b[ECC_NUMWORD];
u8 x[ECC_NUMWORD];
u8 y[ECC_NUMWORD];
u8 idlen_char[2];
struct sm3_ctx md[1];
put_unaligned_be16(idlen << 3, idlen_char);
ecc_bytes2native((u64 *) a, sm2_curve.a, sm2_curve.ndigits);
ecc_bytes2native((u64 *) b, sm2_curve.b, sm2_curve.ndigits);
ecc_bytes2native((u64 *) x, sm2_curve.g.x, sm2_curve.ndigits);
ecc_bytes2native((u64 *) y, sm2_curve.g.y, sm2_curve.ndigits);
sm3_init(md);
sm3_update(md, idlen_char, 2);
sm3_update(md, id, idlen);
sm3_update(md, a, ECC_NUMWORD);
sm3_update(md, b, ECC_NUMWORD);
sm3_update(md, x, ECC_NUMWORD);
sm3_update(md, y, ECC_NUMWORD);
sm3_update(md, (u8 *) pub->x, ECC_NUMWORD);
sm3_update(md, (u8 *) pub->y, ECC_NUMWORD);
sm3_final(md, hash);
return;
}
static int
sm2_valid_public_key(ecc_point *publicKey)
{
u64 na[ECC_MAX_DIGITS] = {3}; /* a mod p = (-3) mod p */
u64 tmp1[ECC_MAX_DIGITS];
u64 tmp2[ECC_MAX_DIGITS];
if (ecc_point_is_zero(&sm2_curve, publicKey)) return 1;
if (vli_cmp(sm2_curve.p, publicKey->x, sm2_curve.ndigits) != 1
|| vli_cmp(sm2_curve.p, publicKey->y, sm2_curve.ndigits) != 1)
return 1;
/* tmp1 = y^2 */
vli_mod_square_fast(tmp1, publicKey->y, sm2_curve.p, sm2_curve.ndigits);
/* tmp2 = x^2 */
vli_mod_square_fast(tmp2, publicKey->x, sm2_curve.p, sm2_curve.ndigits);
/* tmp2 = x^2 + a = x^2 - 3 */
vli_mod_sub(tmp2, tmp2, na, sm2_curve.p, sm2_curve.ndigits);
/* tmp2 = x^3 + ax */
vli_mod_mult_fast(tmp2, tmp2, publicKey->x, sm2_curve.p, sm2_curve.ndigits);
/* tmp2 = x^3 + ax + b */
vli_mod_add(tmp2, tmp2, sm2_curve.b, sm2_curve.p, sm2_curve.ndigits);
/* Make sure that y^2 == x^3 + ax + b */
if (vli_cmp(tmp1, tmp2, sm2_curve.ndigits) != 0) return 1;
return 0;
}
int
sm2_make_prikey(u8 *prikey)
{
ecc_point pub[1];
u64 pri[ECC_MAX_DIGITS];
int i = 10;
do {
vli_get_random((u8 *) pri, ECC_NUMWORD);
if (vli_cmp(sm2_curve.n, pri, sm2_curve.ndigits) != 1) { vli_sub(pri, pri, sm2_curve.n, sm2_curve.ndigits); }
/* The private key cannot be 0 (mod p). */
if (!vli_is_zero(pri, sm2_curve.ndigits)) {
ecc_native2bytes(prikey, pri, sm2_curve.ndigits);
return 0;
}
} while (i--);
return -1;
}
int
sm2_make_pubkey(u8 *prikey, ecc_point *pubkey)
{
ecc_point pub[1];
u64 pri[ECC_MAX_DIGITS];
ecc_bytes2native(pri, prikey, sm2_curve.ndigits);
ecc_point_mult(&sm2_curve, pub, &sm2_curve.g, pri, NULL);
ecc_native2bytes(pubkey->x, pub->x, sm2_curve.ndigits);
ecc_native2bytes(pubkey->y, pub->y, sm2_curve.ndigits);
return 0;
}
int
sm2_make_keypair(u8 *prikey, ecc_point *pubkey)
{
sm2_make_prikey(prikey);
sm2_make_pubkey(prikey, pubkey);
return 0;
}
int
sm2_point_mult(ecc_point *G, u8 *k, ecc_point *P)
{
int rc = 0;
ecc_point G_[1];
ecc_point P_[1];
u64 k_[ECC_MAX_DIGITS];
ecc_bytes2native(k_, k, sm2_curve.ndigits);
ecc_bytes2native(G_->x, G->x, sm2_curve.ndigits);
ecc_bytes2native(G_->y, G->y, sm2_curve.ndigits);
ecc_point_mult(&sm2_curve, P_, G_, k_, NULL);
ecc_native2bytes(P->x, P_->x, sm2_curve.ndigits);
ecc_native2bytes(P->y, P_->y, sm2_curve.ndigits);
return rc;
}
int
sm2_sign(u8 *r_, u8 *s_, u8 *prikey, u8 *hash_)
{
u64 k[ECC_MAX_DIGITS];
u64 one[ECC_MAX_DIGITS] = {1};
u64 random[ECC_MAX_DIGITS];
u64 pri[ECC_MAX_DIGITS];
u64 hash[ECC_MAX_DIGITS];
u64 r[ECC_MAX_DIGITS];
u64 s[ECC_MAX_DIGITS];
ecc_point p;
ecc_bytes2native(pri, prikey, sm2_curve.ndigits);
ecc_bytes2native(hash, hash_, sm2_curve.ndigits);
vli_get_random((u8 *) random, ECC_NUMWORD);
if (vli_is_zero(random, sm2_curve.ndigits)) {
/* The random number must not be 0. */
return -1;
}
vli_set(k, random, sm2_curve.ndigits);
if (vli_cmp(sm2_curve.n, k, sm2_curve.ndigits) != 1) { vli_sub(k, k, sm2_curve.n, sm2_curve.ndigits); }
/* tmp = k * G */
ecc_point_mult(&sm2_curve, &p, &sm2_curve.g, k, NULL);
/* r = x1 + e (mod n) */
vli_mod_add(r, p.x, hash, sm2_curve.n, sm2_curve.ndigits);
if (vli_cmp(sm2_curve.n, r, sm2_curve.ndigits) != 1) { vli_sub(r, r, sm2_curve.n, sm2_curve.ndigits); }
if (vli_is_zero(r, sm2_curve.ndigits)) {
/* If r == 0, fail (need a different random number). */
return -1;
}
/* s = r*d */
vli_mod_mult(s, r, pri, sm2_curve.n, sm2_curve.ndigits);
/* k-r*d */
vli_mod_sub(s, k, s, sm2_curve.n, sm2_curve.ndigits);
/* 1+d */
vli_mod_add(pri, pri, one, sm2_curve.n, sm2_curve.ndigits);
/* (1+d)' */
vli_mod_inv(pri, pri, sm2_curve.n, sm2_curve.ndigits);
/* (1+d)'*(k-r*d) */
vli_mod_mult(s, pri, s, sm2_curve.n, sm2_curve.ndigits);
ecc_native2bytes(r_, r, sm2_curve.ndigits);
ecc_native2bytes(s_, s, sm2_curve.ndigits);
return 0;
}
static int
sm2_verify(ecc_point *pubkey, u8 *hash_, u8 *r_, u8 *s_)
{
ecc_point result;
ecc_point pub[1];
u64 t[ECC_MAX_DIGITS];
u64 r[ECC_MAX_DIGITS];
u64 s[ECC_MAX_DIGITS];
u64 hash[ECC_MAX_DIGITS];
ecc_bytes2native(pub->x, pubkey->x, sm2_curve.ndigits);
ecc_bytes2native(pub->y, pubkey->y, sm2_curve.ndigits);
ecc_bytes2native(r, r_, sm2_curve.ndigits);
ecc_bytes2native(s, s_, sm2_curve.ndigits);
ecc_bytes2native(hash, hash_, sm2_curve.ndigits);
if (vli_is_zero(r, sm2_curve.ndigits) || vli_is_zero(s, sm2_curve.ndigits)) {
/* r, s must not be 0. */
return -1;
}
if (vli_cmp(sm2_curve.n, r, sm2_curve.ndigits) != 1 || vli_cmp(sm2_curve.n, s, sm2_curve.ndigits) != 1) {
/* r, s must be < n. */
return -1;
}
vli_mod_add(t, r, s, sm2_curve.n, sm2_curve.ndigits);// r + s
if (t == 0) return -1;
ecc_point_mult2(&sm2_curve, &result, &sm2_curve.g, pub, s, t);
/* v = x1 + e (mod n) */
vli_mod_add(result.x, result.x, hash, sm2_curve.n, sm2_curve.ndigits);
if (vli_cmp(sm2_curve.n, result.x, sm2_curve.ndigits) != 1) {
vli_sub(result.x, result.x, sm2_curve.n, sm2_curve.ndigits);
}
/* Accept only if v == r. */
return vli_cmp(result.x, r, sm2_curve.ndigits);
}
int
sm2_shared_point(u8 *selfPriKey,
u8 *selfTempPriKey,
ecc_point *selfTempPubKey,
ecc_point *otherPubKey,
ecc_point *otherTempPubKey,
ecc_point *key)
{
ecc_point selfTempPub;
ecc_point otherTempPub;
ecc_point otherPub;
ecc_point U[1];
u64 selfTempPri[ECC_MAX_DIGITS];
u64 selfPri[ECC_MAX_DIGITS];
u64 temp1[ECC_MAX_DIGITS];
u64 temp2[ECC_MAX_DIGITS];
u64 tA[ECC_MAX_DIGITS];
ecc_bytes2native(selfTempPri, selfTempPriKey, sm2_curve.ndigits);
ecc_bytes2native(selfPri, selfPriKey, sm2_curve.ndigits);
ecc_bytes2native(selfTempPub.x, selfTempPubKey->x, sm2_curve.ndigits);
ecc_bytes2native(selfTempPub.y, selfTempPubKey->y, sm2_curve.ndigits);
ecc_bytes2native(otherTempPub.x, otherTempPubKey->x, sm2_curve.ndigits);
ecc_bytes2native(otherTempPub.y, otherTempPubKey->y, sm2_curve.ndigits);
ecc_bytes2native(otherPub.x, otherPubKey->x, sm2_curve.ndigits);
ecc_bytes2native(otherPub.y, otherPubKey->y, sm2_curve.ndigits);
/***********x1_=2^w+x2 & (2^w-1)*************/
sm2_w(temp1, selfTempPub.x);
/***********tA=(dA+x1_*rA)mod n *************/
vli_mod_mult(temp1, selfTempPri, temp1, sm2_curve.n, sm2_curve.ndigits);
vli_mod_add(tA, selfPri, temp1, sm2_curve.n, sm2_curve.ndigits);
/***********x2_=2^w+x2 & (2^w-1)*************/
if (sm2_valid_public_key(&otherTempPub) != 0) return -1;
sm2_w(temp2, otherTempPub.x);
/**************U=[h*tA](PB+[x2_]RB)**********/
/* U=[x2_]RB */
ecc_point_mult(&sm2_curve, U, &otherTempPub, temp2, NULL);
/*U=PB+U*/
ecc_point_add(&sm2_curve, U, &otherPub, U);
/*tA=tA*h */
vli_mod_mult(tA, tA, sm2_curve.h, sm2_curve.n, sm2_curve.ndigits);
ecc_point_mult(&sm2_curve, U, U, tA, NULL);
ecc_native2bytes(key->x, U->x, sm2_curve.ndigits);
ecc_native2bytes(key->y, U->y, sm2_curve.ndigits);
return 0;
}
int
sm2_shared_key(ecc_point *point, u8 *ZA, u8 *ZB, u32 keyLen, u8 *key)
{
u8 Z[ECC_NUMWORD * 4];
memcpy(Z, point->x, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD, point->y, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD * 2, ZA, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD * 3, ZB, ECC_NUMWORD);
sm3_kdf(Z, ECC_NUMWORD * 4, key, keyLen);
return 0;
}
/****hash = Hash(Ux||ZA||ZB||x1||y1||x2||y2)****/
int
ECC_Key_ex_hash1(u8 *x, ecc_point *RA, ecc_point *RB, u8 ZA[], u8 ZB[], u8 *hash)
{
struct sm3_ctx md[1];
sm3_init(md);
sm3_update(md, x, ECC_NUMWORD);
sm3_update(md, ZA, ECC_NUMWORD);
sm3_update(md, ZB, ECC_NUMWORD);
sm3_update(md, (u8 *) RA->x, ECC_NUMWORD);
sm3_update(md, (u8 *) RA->y, ECC_NUMWORD);
sm3_update(md, (u8 *) RB->x, ECC_NUMWORD);
sm3_update(md, (u8 *) RB->y, ECC_NUMWORD);
sm3_final(md, (u8 *) hash);
return 0;
}
/****SA = Hash(temp||Uy||Hash)****/
int
ECC_Key_ex_hash2(u8 temp, u8 *y, u8 *hash, u8 *SA)
{
struct sm3_ctx md[1];
sm3_init(md);
sm3_update(md, &temp, 1);
sm3_update(md, y, ECC_NUMWORD);
sm3_update(md, hash, ECC_NUMWORD);
sm3_final(md, SA);
return 0;
}
int
ECC_KeyEx_Init_I(u8 *pri, ecc_point *pub)
{
return sm2_make_pubkey(pri, pub);
}
int
ECC_KeyEx_Re_I(u8 *rb,
u8 *dB,
ecc_point *RA,
ecc_point *PA,
u8 *ZA,
u8 *ZB,
u8 *K,
u32 klen,
ecc_point *RB,
ecc_point *V,
u8 *SB)
{
u8 Z[ECC_NUMWORD * 2 + ECC_NUMBITS / 4] = {0};
u8 hash[ECC_NUMWORD], S1[ECC_NUMWORD];
u8 temp = 0x02;
//--------B2: RB=[rb]G=(x2,y2)--------
sm2_make_pubkey(rb, RB);
/********************************************/
sm2_shared_point(dB, rb, RB, PA, RA, V);
//------------B7:KB=KDF(VX,VY,ZA,ZB,KLEN)----------
memcpy(Z, V->x, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD, (u8 *) V->y, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD * 2, ZA, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD * 3, ZB, ECC_NUMWORD);
sm3_kdf(Z, ECC_NUMWORD * 4, K, klen);
//---------------B8:(optional) SB=hash(0x02||Vy||HASH(Vx||ZA||ZB||x1||y1||x2||y2)-------------
ECC_Key_ex_hash1((u8 *) V->x, RA, RB, ZA, ZB, hash);
ECC_Key_ex_hash2(temp, (u8 *) V->y, hash, SB);
return 0;
}
int
ECC_KeyEx_Init_II(u8 *ra,
u8 *dA,
ecc_point *RA,
ecc_point *RB,
ecc_point *PB,
u8 ZA[],
u8 ZB[],
u8 SB[],
u8 K[],
u32 klen,
u8 SA[])
{
u8 Z[ECC_NUMWORD * 2 + ECC_NUMWORD * 2] = {0};
u8 hash[ECC_NUMWORD], S1[ECC_NUMWORD];
u8 temp[2] = {0x02, 0x03};
ecc_point U[1];
/********************************************/
sm2_shared_point(dA, ra, RA, PB, RB, U);
/************KA=KDF(UX,UY,ZA,ZB,KLEN)**********/
memcpy(Z, U->x, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD, U->y, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD * 2, ZA, ECC_NUMWORD);
memcpy(Z + ECC_NUMWORD * 2 + ECC_NUMWORD, ZB, ECC_NUMWORD);
sm3_kdf(Z, ECC_NUMWORD * 2 + ECC_NUMWORD * 2, K, klen);
/****S1 = Hash(0x02||Uy||Hash(Ux||ZA||ZB||x1||y1||x2||y2))****/
ECC_Key_ex_hash1((u8 *) U->x, RA, RB, ZA, ZB, hash);
ECC_Key_ex_hash2(temp[0], (u8 *) U->y, hash, S1);
/*test S1=SB?*/
if (memcmp(S1, SB, ECC_NUMWORD) != 0) return -1;
/*SA = Hash(0x03||yU||Hash(xU||ZA||ZB||x1||y1||x2||y2)) */
ECC_Key_ex_hash2(temp[1], (u8 *) U->y, hash, SA);
return 0;
}
int
ECC_KeyEx_Re_II(ecc_point *V, ecc_point *RA, ecc_point *RB, u8 ZA[], u8 ZB[], u8 SA[])
{
u8 hash[ECC_NUMWORD];
u8 S2[ECC_NUMWORD];
u8 temp = 0x03;
/*S2 = Hash(0x03||Vy||Hash(Vx||ZA||ZB||x1||y1||x2||y2))*/
ECC_Key_ex_hash1((u8 *) V->x, RA, RB, ZA, ZB, hash);
ECC_Key_ex_hash2(temp, (u8 *) V->y, hash, S2);
if (memcmp(S2, SA, ECC_NUMWORD) != 0) return -1;
return 0;
}
static int
do_sm2_verify(char *pubkey, char *data_addr, int data_len, char *sign_addr)
{
int ret = -1;
struct sm3_ctx sm3_ctx;
unsigned char ios_hash[32];
u8 ios_Z[ECC_NUMWORD];
ecc_point ios_pub;
unsigned char sign_data[64];
memcpy(&ios_pub, pubkey, 64);
ret = sm3_init(&sm3_ctx);
sm3_z((u8 *) "1234567812345678", 16, &ios_pub, ios_Z);
sm3_update(&sm3_ctx, ios_Z, ECC_NUMWORD);
sm3_update(&sm3_ctx, (const u8 *) data_addr, data_len);
sm3_final(&sm3_ctx, ios_hash);
memcpy(sign_data, sign_addr, 64);
ret = sm2_verify((ecc_point *) pubkey, ios_hash, sign_data, sign_data + 32);
if (ret) {
printf("verify err ret = %d\n", ret);
return -1;
}
return 0;
}
int
do_sm2_sign(char *prikey, char *pubkey, char *data_addr, int data_len, char *sign_addr)
{
int ret = -1;
struct sm3_ctx sm3_ctx;
unsigned char ios_hash[32];
u8 ios_Z[ECC_NUMWORD];
ecc_point ios_pub;
unsigned char sign_data[64];
memcpy(&ios_pub, pubkey, 64);
ret = sm3_init(&sm3_ctx);
sm3_z((u8 *) "1234567812345678", 16, &ios_pub, ios_Z);
sm3_update(&sm3_ctx, ios_Z, ECC_NUMWORD);
sm3_update(&sm3_ctx, data_addr, data_len);
sm3_final(&sm3_ctx, ios_hash);
//hexdump("hash", ios_hash, 32);
ret = sm2_sign(sign_data, sign_data + 32, prikey, ios_hash);
if (ret) {
printf("sign err ret = %d\n", ret);
return -1;
}
memcpy(sign_addr, sign_data, 64);
return 0;
}

View File

@ -0,0 +1,39 @@
#ifndef _SM2_H_
#define _SM2_H_
#include "ecc.h"
#include "typedef.h"
int vli_get_random(u8 *data, u32 len);
int sm2_make_prikey(u8 *prikey);
int sm2_make_pubkey(u8 *prikey, ecc_point *pubkey);
int sm2_make_keypair(u8 *prikey, ecc_point *pubkey);
int sm2_sign(u8 *r, u8 *s, u8 *pri, u8 *hash);
static int sm2_verify(ecc_point *pubkey, u8 *hash, u8 *r, u8 *s);
int sm2_encrypt(ecc_point *pubKey, u8 *M, u32 Mlen, u8 *C, u32 *Clen);
int sm2_decrypt(u8 *prikey, u8 *C, u32 Clen, u8 *M, u32 *Mlen);
static void sm3_z(u8 *id, u32 idlen, ecc_point *pub, u8 *hash);
int sm2_shared_point(u8 *selfPriKey, u8 *selfTempPriKey,
ecc_point *selfTempPubKey, ecc_point *otherPubKey,
ecc_point *otherTempPubKey, ecc_point *key);
int sm2_shared_key(ecc_point *point, u8 *ZA, u8 *ZB, u32 keyLen, u8 *key);
int sm2_point_mult(ecc_point *G, u8 *k, ecc_point *P);
int ECC_KeyEx_Init_I(u8 *pri, ecc_point *pub);
int ECC_KeyEx_Re_I(u8 *rb, u8 *dB, ecc_point *RA, ecc_point *PA, u8 *ZA, u8 *ZB,
u8 *K, u32 klen, ecc_point *RB, ecc_point *V, u8 *hash);
int ECC_KeyEx_Init_II(u8 *ra, u8 *dA, ecc_point *RA, ecc_point *RB,
ecc_point *PB, u8 ZA[], u8 ZB[], u8 SB[], u8 K[],
u32 klen, u8 SA[]);
int ECC_KeyEx_Re_II(ecc_point *V, ecc_point *RA, ecc_point *RB, u8 ZA[],
u8 ZB[], u8 SA[]);
int do_sm2_sign(char *prikey, char *pubkey, char *data_addr, int data_len,
char *sign_addr);
#endif /* _SM2_H_ */

View File

@ -0,0 +1,248 @@
#include <stdio.h>
#include <string.h>
#include "typedef.h"
#include "sm3.h"
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (u32) (b)[(i) ] << 24 ) \
| ( (u32) (b)[(i) + 1] << 16 ) \
| ( (u32) (b)[(i) + 2] << 8 ) \
| ( (u32) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (u8) ( (n) >> 24 ); \
(b)[(i) + 1] = (u8) ( (n) >> 16 ); \
(b)[(i) + 2] = (u8) ( (n) >> 8 ); \
(b)[(i) + 3] = (u8) ( (n) ); \
}
#endif
/*
* SM3 context setup
*/
int sm3_init(struct sm3_ctx *ctx)
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x7380166F;
ctx->state[1] = 0x4914B2B9;
ctx->state[2] = 0x172442D7;
ctx->state[3] = 0xDA8A0600;
ctx->state[4] = 0xA96F30BC;
ctx->state[5] = 0x163138AA;
ctx->state[6] = 0xE38DEE4D;
ctx->state[7] = 0xB0FB0E4E;
return 0;
}
static void sm3_process(struct sm3_ctx *ctx, u8 data[64])
{
u32 SS1, SS2, TT1, TT2, W[68],W1[64];
u32 A, B, C, D, E, F, G, H;
u32 T[64];
u32 Temp1,Temp2,Temp3,Temp4,Temp5;
int j;
for(j = 0; j < 16; j++)
T[j] = 0x79CC4519;
for(j =16; j < 64; j++)
T[j] = 0x7A879D8A;
GET_ULONG_BE( W[ 0], data, 0 );
GET_ULONG_BE( W[ 1], data, 4 );
GET_ULONG_BE( W[ 2], data, 8 );
GET_ULONG_BE( W[ 3], data, 12 );
GET_ULONG_BE( W[ 4], data, 16 );
GET_ULONG_BE( W[ 5], data, 20 );
GET_ULONG_BE( W[ 6], data, 24 );
GET_ULONG_BE( W[ 7], data, 28 );
GET_ULONG_BE( W[ 8], data, 32 );
GET_ULONG_BE( W[ 9], data, 36 );
GET_ULONG_BE( W[10], data, 40 );
GET_ULONG_BE( W[11], data, 44 );
GET_ULONG_BE( W[12], data, 48 );
GET_ULONG_BE( W[13], data, 52 );
GET_ULONG_BE( W[14], data, 56 );
GET_ULONG_BE( W[15], data, 60 );
#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)) )
#define SHL(x,n) (((x) & 0xFFFFFFFF) << n)
#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
//#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n%32)))
#define P0(x) ((x) ^ ROTL((x),9) ^ ROTL((x),17))
#define P1(x) ((x) ^ ROTL((x),15) ^ ROTL((x),23))
for(j = 16; j < 68; j++ )
{
//W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^ ROTL(W[j - 13],7 ) ^ W[j-6];
//Why thd release's result is different with the debug's ?
//Below is okay. Interesting, Perhaps VC6 has a bug of Optimizaiton.
Temp1 = W[j-16] ^ W[j-9];
Temp2 = ROTL(W[j-3],15);
Temp3 = Temp1 ^ Temp2;
Temp4 = P1(Temp3);
Temp5 = ROTL(W[j - 13],7 ) ^ W[j-6];
W[j] = Temp4 ^ Temp5;
}
for(j = 0; j < 64; j++)
{
W1[j] = W[j] ^ W[j+4];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
for(j =0; j < 16; j++)
{
SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7);
SS2 = SS1 ^ ROTL(A,12);
TT1 = FF0(A,B,C) + D + SS2 + W1[j];
TT2 = GG0(E,F,G) + H + SS1 + W[j];
D = C;
C = ROTL(B,9);
B = A;
A = TT1;
H = G;
G = ROTL(F,19);
F = E;
E = P0(TT2);
}
for(j =16; j < 64; j++)
{
SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7);
SS2 = SS1 ^ ROTL(A,12);
TT1 = FF1(A,B,C) + D + SS2 + W1[j];
TT2 = GG1(E,F,G) + H + SS1 + W[j];
D = C;
C = ROTL(B,9);
B = A;
A = TT1;
H = G;
G = ROTL(F,19);
F = E;
E = P0(TT2);
}
ctx->state[0] ^= A;
ctx->state[1] ^= B;
ctx->state[2] ^= C;
ctx->state[3] ^= D;
ctx->state[4] ^= E;
ctx->state[5] ^= F;
ctx->state[6] ^= G;
ctx->state[7] ^= H;
}
/*
* SM3 process buffer
*/
int sm3_update(struct sm3_ctx *ctx, const u8 *input, u32 ilen)
{
u32 left;
int fill;
if( ilen <= 0 )
return -1;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (u32) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sm3_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sm3_process( ctx, (u8*)input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
return 0;
}
static u8 sm3_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SM3 final digest
*/
int sm3_final(struct sm3_ctx *ctx, u8 *output)
{
u32 last, padn;
u32 high, low;
u8 msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_BE( high, msglen, 0 );
PUT_ULONG_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sm3_update(ctx, (const u8 *)sm3_padding, padn );
sm3_update(ctx, msglen, 8 );
PUT_ULONG_BE( ctx->state[0], output, 0 );
PUT_ULONG_BE( ctx->state[1], output, 4 );
PUT_ULONG_BE( ctx->state[2], output, 8 );
PUT_ULONG_BE( ctx->state[3], output, 12 );
PUT_ULONG_BE( ctx->state[4], output, 16 );
PUT_ULONG_BE( ctx->state[5], output, 20 );
PUT_ULONG_BE( ctx->state[6], output, 24 );
PUT_ULONG_BE( ctx->state[7], output, 28 );
return 0;
}

View File

@ -0,0 +1,20 @@
#ifndef _SM3_H_
#define _SM3_H_
#include "typedef.h"
#define SM3_DATA_LEN 32
struct sm3_ctx {
u32 total[2]; /*!< number of bytes processed */
u32 state[8]; /*!< intermediate digest state */
u8 buffer[64]; /*!< data block being processed */
u8 ipad[64]; /*!< HMAC: inner padding */
u8 opad[64]; /*!< HMAC: outer padding */
};
int sm3_init(struct sm3_ctx *ctx);
int sm3_update(struct sm3_ctx *ctx, const u8 *input, u32 ilen);
int sm3_final(struct sm3_ctx *ctx, u8 *output);
#endif /* _SM3_H_ */

View File

@ -0,0 +1,356 @@
#include <stdio.h>
#include <string.h>
#define SM4_KEY_SCHEDULE 32
typedef struct SM4_KEY_st {
unsigned int rk[SM4_KEY_SCHEDULE];
} SM4_KEY;
typedef void (*block128_f) (const unsigned char in[16],
unsigned char out[16], const void *key);
static const unsigned char SM4_S[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
};
/*
* SM4_SBOX_T[j] == L(SM4_SBOX[j]).
*/
static const unsigned int SM4_SBOX_T[256] = {
0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787,
0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B,
0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D,
0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F,
0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A,
0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3,
0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151,
0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989,
0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020,
0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB,
0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, 0x5B461D1D, 0x1B071C1C,
0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA,
0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616,
0x734E3D3D, 0x08AAA2A2, 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA,
0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF,
0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4,
0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161,
0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC,
0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000,
0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949,
0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313,
0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B,
0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF,
0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686,
0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0,
0x721A6868, 0x01545555, 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0,
0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB,
0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181,
0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D,
0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515,
0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF,
0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545,
0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777,
0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505,
0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, 0x220A2828, 0xC5C20707,
0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6,
0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797,
0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929,
0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6,
0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212,
0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373,
0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121 };
static unsigned int rotl(unsigned int a, unsigned char n)
{
return (a << n) | (a >> (32 - n));
}
static unsigned int load_u32_be(const unsigned char *b, unsigned int n)
{
return ((unsigned int)b[4 * n] << 24) |
((unsigned int)b[4 * n + 1] << 16) |
((unsigned int)b[4 * n + 2] << 8) |
((unsigned int)b[4 * n + 3]);
}
static void store_u32_be(unsigned int v, unsigned char *b)
{
b[0] = (unsigned char)(v >> 24);
b[1] = (unsigned char)(v >> 16);
b[2] = (unsigned char)(v >> 8);
b[3] = (unsigned char)(v);
}
static unsigned int SM4_T_slow(unsigned int X)
{
unsigned int t = 0;
t |= ((unsigned int)SM4_S[(unsigned char)(X >> 24)]) << 24;
t |= ((unsigned int)SM4_S[(unsigned char)(X >> 16)]) << 16;
t |= ((unsigned int)SM4_S[(unsigned char)(X >> 8)]) << 8;
t |= SM4_S[(unsigned char)X];
/*
* L linear transform
*/
return t ^ rotl(t, 2) ^ rotl(t, 10) ^ rotl(t, 18) ^ rotl(t, 24);
}
static unsigned int SM4_T(unsigned int X)
{
return SM4_SBOX_T[(unsigned char)(X >> 24)] ^
rotl(SM4_SBOX_T[(unsigned char)(X >> 16)], 24) ^
rotl(SM4_SBOX_T[(unsigned char)(X >> 8)], 16) ^
rotl(SM4_SBOX_T[(unsigned char)X], 8);
}
static int SM4_set_key(const unsigned char *key, SM4_KEY *ks)
{
/*
* Family Key
*/
static const unsigned int FK[4] =
{ 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
/*
* Constant Key
*/
static const unsigned int 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 int K[4];
int i;
K[0] = load_u32_be(key, 0) ^ FK[0];
K[1] = load_u32_be(key, 1) ^ FK[1];
K[2] = load_u32_be(key, 2) ^ FK[2];
K[3] = load_u32_be(key, 3) ^ FK[3];
for (i = 0; i != SM4_KEY_SCHEDULE; ++i) {
unsigned int X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i];
unsigned int t = 0;
t |= ((unsigned int)SM4_S[(unsigned char)(X >> 24)]) << 24;
t |= ((unsigned int)SM4_S[(unsigned char)(X >> 16)]) << 16;
t |= ((unsigned int)SM4_S[(unsigned char)(X >> 8)]) << 8;
t |= SM4_S[(unsigned char)X];
t = t ^ rotl(t, 13) ^ rotl(t, 23);
K[i % 4] ^= t;
ks->rk[i] = K[i % 4];
}
return 1;
}
#define SM4_RNDS(k0, k1, k2, k3, F) \
do { \
B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]); \
B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]); \
B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]); \
B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \
} while(0)
static void SM4_encrypt(const unsigned char *in, unsigned char *out, const SM4_KEY *ks)
{
unsigned int B0 = load_u32_be(in, 0);
unsigned int B1 = load_u32_be(in, 1);
unsigned int B2 = load_u32_be(in, 2);
unsigned int B3 = load_u32_be(in, 3);
/*
* Uses byte-wise sbox in the first and last rounds to provide some
* protection from cache based side channels.
*/
SM4_RNDS( 0, 1, 2, 3, SM4_T_slow);
SM4_RNDS( 4, 5, 6, 7, SM4_T);
SM4_RNDS( 8, 9, 10, 11, SM4_T);
SM4_RNDS(12, 13, 14, 15, SM4_T);
SM4_RNDS(16, 17, 18, 19, SM4_T);
SM4_RNDS(20, 21, 22, 23, SM4_T);
SM4_RNDS(24, 25, 26, 27, SM4_T);
SM4_RNDS(28, 29, 30, 31, SM4_T_slow);
store_u32_be(B3, out);
store_u32_be(B2, out + 4);
store_u32_be(B1, out + 8);
store_u32_be(B0, out + 12);
}
static void SM4_decrypt(const unsigned char *in, unsigned char *out, const SM4_KEY *ks)
{
unsigned int B0 = load_u32_be(in, 0);
unsigned int B1 = load_u32_be(in, 1);
unsigned int B2 = load_u32_be(in, 2);
unsigned int B3 = load_u32_be(in, 3);
SM4_RNDS(31, 30, 29, 28, SM4_T_slow);
SM4_RNDS(27, 26, 25, 24, SM4_T);
SM4_RNDS(23, 22, 21, 20, SM4_T);
SM4_RNDS(19, 18, 17, 16, SM4_T);
SM4_RNDS(15, 14, 13, 12, SM4_T);
SM4_RNDS(11, 10, 9, 8, SM4_T);
SM4_RNDS( 7, 6, 5, 4, SM4_T);
SM4_RNDS( 3, 2, 1, 0, SM4_T_slow);
store_u32_be(B3, out);
store_u32_be(B2, out + 4);
store_u32_be(B1, out + 8);
store_u32_be(B0, out + 12);
}
static void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const void *key,
unsigned char ivec[16], int *num, block128_f block)
{
unsigned int n;
size_t l = 0;
n = *num;
while (l < len) {
if (n == 0) {
(*block) (ivec, ivec, key);
}
out[l] = in[l] ^ ivec[n];
++l;
n = (n + 1) % 16;
}
*num = n;
}
static int sm4_init_key(const unsigned char *key, SM4_KEY *ks)
{
SM4_set_key(key, ks);
return 1;
}
static void sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const SM4_KEY *key,
unsigned char *ivec)
{
int num = 0;
CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num, (block128_f)SM4_encrypt);
}
static void do_sm4_ofb_encrypt(const char *in_buff, int in_len, char *out_buff, int *out_len, const char *key, const char *iv)
{
SM4_KEY ks;
char ivec[16];
memset(&ks, 0, sizeof(SM4_KEY));
memcpy(ivec, iv, 16);
sm4_init_key(key, &ks);
sm4_ofb128_encrypt(in_buff, out_buff, in_len, &ks, ivec);
*out_len = in_len;
}
static void do_sm4_ecb_decrypt(const char *in_buff, char *out_buff, const char *key)
{
SM4_KEY ks;
memset(&ks, 0, sizeof(SM4_KEY));
sm4_init_key(key, &ks);
SM4_decrypt(in_buff, out_buff, &ks);
//hexdump("in_buff", in_buff, 16);
//hexdump("out_buff", out_buff, 16);
//hexdump("key", key, 16);
}
void do_sm4_ecb_encrypt(const char *in_buff, char *out_buff, const char *key)
{
SM4_KEY ks;
memset(&ks, 0, sizeof(SM4_KEY));
sm4_init_key(key, &ks);
SM4_encrypt(in_buff, out_buff, &ks);
//hexdump("in_buff", in_buff, 16);
//hexdump("out_buff", out_buff, 16);
//hexdump("key", key, 16);
}
#if 0
void hexdump(char *title, const unsigned char *s, int l)
{
int n = 0, j = 0;
char buff[1024];
memset(buff, 0, sizeof(buff));
printf("%s len = %d\n", title ? title : "NULL", l);
for (; n < l; ++n)
{
if ((n % 16) == 0)
{
if (j)
{
printf("%s\n", buff);
j = 0;
memset(buff, 0, sizeof(buff));
}
j += sprintf(buff + j, "%04x ", n);
}
j += sprintf(buff + j, "0x%02x,", s[n]);
}
if (j)
printf("%s\n", buff);
}
int main(int argc, char *argv)
{
unsigned char in[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, \
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, \
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, \
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
unsigned char key[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, \
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
unsigned char iv[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, \
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
unsigned char check[] = {0x69, 0x3d, 0x9a, 0x53, 0x5b, 0xad, 0x5b, 0xb1, \
0x78, 0x6f, 0x53, 0xd7, 0x25, 0x3a, 0x70, 0x56, \
0xf2, 0x07, 0x5d, 0x28, 0xb5, 0x23, 0x5f, 0x58, \
0xd5, 0x00, 0x27, 0xe4, 0x17, 0x7d, 0x2b, 0xce};
char buff[128] = {0};
int len = sizeof(buff);
do_sm4_ofb_encrypt(in, 32, buff, &len, key, iv);
hexdump("enc", buff, 32);
return 0;
}
#endif

View File

@ -0,0 +1,900 @@
#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
// #include "svac_enc.h"
#include "sm2.h"
#include "sm3.h"
#define PRINT_ERR printf
#define PRINT_INFO printf
#define MAGIC_VALUE 0x12121111
#define NALU_MAX_NUM 100
#define VKEK_CACHE_NUM 30
#define HASH_CACHE_NUM 512
#define SM4_OFB 0
#define SM1_OFB 1
#define SM4_ECB 2
#define SM3_HASH 3
#define SM2_SIGN 4
/* svac2.0 p45 */
#define SVAC_NO_IDR_SLICE 1
#define SVAC_IDR_SLICE 2
#define SVAC_NO_IDR_SLICE_EXT 3
#define SVAC_IDR_SLICE_EXT 4
#define SVAC_SUR_SLICE 5
#define SVAC_SEI_SLICE 6
#define SVAC_SPS_SLICE 7
#define SVAC_PPS_SLICE 8
#define SVAC_SEC_SLICE 9
#define SVAC_AUTH_SLICE 10
struct nalu_data {
char *addr;
char *out_addr;
int len;
int out_len;
int encryption_idc;
int authentication_idc;
int type;
int need_add_racing_code;
};
struct vkek_info {
char vkek[16];
char version[32];
};
struct sec_param {
/* <20><>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
int encrypt_flag; //<2F>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>
int encrypt_type; //<2F><><EFBFBD><EFBFBD><EFBFBD>
int auth_flag; //<2F>Ƿ<EFBFBD>ǩ<EFBFBD><C7A9>
int auth_type; //ǩ<><C7A9><EFBFBD>
int hash_type; //ɢ<><C9A2><EFBFBD>
int vek_flag; //<2F>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>evek
int vek_encrypt_type; //vek<65><6B><EFBFBD><EFBFBD><EFBFBD>
char evek[32]; //evek
int vek_len; //vek<65><6B><EFBFBD><EFBFBD>
char vkek_version[128];//vkek version
int version_len; //vkek version<6F><6E><EFBFBD><EFBFBD>
int iv_flag; //<2F>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>iv
char iv[32]; //iv
int iv_len; //iv<69><76><EFBFBD><EFBFBD>
int only_IDR; // sign only for idr
int hash_period; // sign period frame
};
struct hash_cache {
/* һ<><D2BB>gop<6F><70><EFBFBD>256֡ */
char hash[32];
int frame_num;
};
struct svac_handle {
int magic;
/* sm2 <20><>Կ */
char sm2_pubkey[64];
/* sm2 <20><>Կ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD> */
int sm_pubkey_flag;
char sm2_prikey[32];
int sm_prikey_flag;
char vek[16];
char iv[16];
/* process tmp data */
struct nalu_data nalu[NALU_MAX_NUM];
int nalu_num;
int frame_num;
int sign_frame_num;
char sign[128];
int sign_len;
/* current frame is IDR frame */
int idr_flag;
/* current frame <20><><EFBFBD><EFBFBD> sec nalu */
int sec_nalu_flag;
/* current frame <20><><EFBFBD><EFBFBD> auth nalu */
int auth_nalu_flag;
/* <20><>ǰʹ<C7B0>õİ<C3B5>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD> */
struct sec_param curr_param;
/* <20><><EFBFBD>յ<EFBFBD><D5B5>İ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD> */
struct sec_param new_param;
/* <20><>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>ʶ<EFBFBD><CAB6><EFBFBD>µ<EFBFBD>GOP<4F><50>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD> */
int sec_param_update_flag;
int vkek_start;
struct vkek_info vkek_list[VKEK_CACHE_NUM];
int find_vkek_flag;
char idr_hash[32];
struct hash_cache cache[HASH_CACHE_NUM];
int cache_idx;// 0 ~ HASH_CACHE_NUM - 1
char camera_id[64]; //<2F><><EFBFBD><EFBFBD>id
char camera_idc[19];//֤<><D6A4>id
};
#define CHECK_HANDLE(h) \
do { \
if (!h || h->magic != MAGIC_VALUE) { \
PRINT_ERR("handle is error!\n"); \
return -1; \
} \
} while (0)
void hexdump(char *title, const unsigned char *s, int l);
int do_sm2_sign(char *prikey, char *pubkey, char *data_addr, int data_len, char *sign_addr);
int do_base64_encode(unsigned char *dst, int *dlen, unsigned char *src, int slen);
static unsigned int
write_bits(unsigned char data, unsigned int write_len, unsigned char *addr, unsigned int offset)
{
unsigned int offset_in_bytes = offset & 7;
unsigned int offset_of_bytes = offset / 8;
/* if need write twice */
if (offset_in_bytes && offset_in_bytes + write_len > 8) {
unsigned int second_write_len = offset_in_bytes + write_len - 8;
/* clean the bits which will been writen */
addr[offset_of_bytes] &= ~((1 << (8 - offset_in_bytes)) - 1);
/* write the first byte */
addr[offset_of_bytes] |= (data & ((1 << write_len) - 1)) >> second_write_len;
/* write the second byte */
addr[offset_of_bytes + 1] &= ((1 << (8 - second_write_len)) - 1);
addr[offset_of_bytes + 1] |= (data & ((1 << second_write_len) - 1)) << (8 - second_write_len);
} else {
data &= ((1 << write_len) - 1);
addr[offset_of_bytes] &= ~(((1 << write_len) - 1) << (8 - write_len - offset_in_bytes));
addr[offset_of_bytes] |= data << (8 - write_len - offset_in_bytes);
}
return offset + write_len;
}
static unsigned int
write_long_data_bits(unsigned int data, unsigned int write_len, unsigned char *addr, unsigned int offset)
{
unsigned int ret_offset = 0;
if (write_len <= 8)
ret_offset = write_bits((unsigned char) data, write_len, addr, offset);
else {
int i;
int loop;
unsigned int first_write_len = write_len & 7;
/* <20><><EFBFBD><EFBFBD>һ<EFBFBD>ֽڵĵ<DAB5>first_write_len<65><6E><EFBFBD><EFBFBD>*/
if (first_write_len)
offset =
write_bits((unsigned char) ((data >> (write_len - first_write_len)) & ((1 << first_write_len) - 1)),
first_write_len, addr, offset);
loop = (write_len - first_write_len) / 8;
ret_offset = offset;
for (i = 0; i < loop; i++)
ret_offset = write_bits((unsigned char) ((data >> ((loop - i - 1) * 8)) & 0xff), 8, addr, ret_offset);
}
return ret_offset;
}
static unsigned int
write_string_bits(unsigned char *p, unsigned int write_len, unsigned char *addr, unsigned int offset)
{
int i = 0;
unsigned int len = 0;
while (len < write_len) {
if (write_len - len > 8) {
offset = write_bits(p[i], 8, addr, offset);
len += 8;
} else {
offset = write_bits(p[i], write_len - len, addr, offset);
len += write_len - len;
}
i++;
}
return offset;
}
/* if find a nal, return the next address; if it's the end, return NULL */
static char *
findNal(char *buf, int *frame_len, char **nal_start, int *nal_len)
{
int i;
char *start = NULL;
int len = 0;
*nal_start = NULL;
*nal_len = 0;
/* parsing each NALU */
for (i = 0; i < (int) (*frame_len - 3); i++) {
if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x00 && buf[i + 3] == 0x01) {
/* not the first loop */
if (start) {
len = buf + i - start;
*nal_start = start;
*nal_len = len;
*frame_len -= i;
return buf + i;
}
start = buf + i;
}
}
if (start) len = buf + *frame_len - start;
*nal_start = start;
*nal_len = len;
*frame_len = 0;
return NULL;
}
static int
svac_parse_nalu(struct svac_handle *h, char *frame_data, int frame_len)
{
char *ptr, *start = NULL;
int nal_len, frame_len_left = frame_len;
ptr = frame_data;
do {
start = NULL;
nal_len = 0;
ptr = findNal(ptr, &frame_len_left, &start, &nal_len);
if (start) {
memset(&h->nalu[h->nalu_num], 0, sizeof(struct nalu_data));
h->nalu[h->nalu_num].addr = start;
h->nalu[h->nalu_num].len = nal_len;
h->nalu[h->nalu_num].encryption_idc = start[4] & 0x2 ? 1 : 0;//svac2.0 p21
h->nalu[h->nalu_num].authentication_idc = start[4] & 0x1; //svac2.0 p21
h->nalu[h->nalu_num].type = (start[4] >> 2) & 0xf; //svac2.0 p21
if (SVAC_IDR_SLICE == h->nalu[h->nalu_num].type)
h->idr_flag = 1;
else if (SVAC_SEC_SLICE == h->nalu[h->nalu_num].type)
h->sec_nalu_flag = 1;
else if (SVAC_AUTH_SLICE == h->nalu[h->nalu_num].type)
h->auth_nalu_flag = 1;
else if (SVAC_PPS_SLICE == h->nalu[h->nalu_num].type) {
/* pps<70>ĵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>֡<EFBFBD><D6A1> svac2.0 p23 */
h->frame_num = (unsigned char) start[5];
//PRINT_INFO("frame %d\n", h->frame_num);
}
//printf("nalu %d len %d type %d auth_idc %d enc_idc %d\n", h->nalu_num, nal_len, h->nalu[h->nalu_num].type, h->nalu[h->nalu_num].authentication_idc, h->nalu[h->nalu_num].encryption_idc);
h->nalu_num++;
}
} while (frame_len_left);
return 0;
}
/* <20><><EFBFBD><EFBFBD> svac <20>ľ<EFBFBD><C4BE><EFBFBD><EFBFBD><EFBFBD> */
static int
do_add_racing_Code(char *ptr, int *len, int offset)
{
int i, find = 0, start = offset;
unsigned int inlen = *len;
for (i = start; i < inlen - 2; i++) {
if (ptr[i] == 0 && ptr[i + 1] == 0 && !(ptr[i + 2] & 0xfc)) {
find = 1;
break;
}
}
if (find) {
unsigned int code_num = 0, zero_count = 0;
char *tmp = (char *) malloc(*len + 4096 * 5);
memcpy(tmp, ptr, start);
for (i = start; i < inlen; i++) {
if (zero_count == 2 && !(ptr[i] & 0xfc)) {
tmp[i + code_num] = 3;
code_num++;
i--;
zero_count = 0;
continue;
}
if (ptr[i] == 0)
zero_count++;
else
zero_count = 0;
tmp[i + code_num] = ptr[i];
}
memcpy(ptr, tmp, inlen + code_num);
*len = inlen + code_num;
//PRINT_INFO("code_num %d\n", code_num);
free(tmp);
}
return find;
}
/* ȥ<><C8A5> svac <20>ľ<EFBFBD><C4BE><EFBFBD><EFBFBD><EFBFBD> */
static int
do_remove_racing_code(char *ptr, int *len, int offset)
{
int i, find = 0, start;
unsigned int inlen;
inlen = *len;
start = offset;
for (i = start; i < inlen - 2; i++) {
if (ptr[i] == 0 && ptr[i + 1] == 0 && ptr[i + 2] == 0x3) {
find = 1;
break;
}
}
if (find) {
unsigned int code_num = 0, zero_count = 0;
for (i = start; i < inlen; i++) {
if (zero_count == 2 && ptr[i] == 3) {
code_num++;
zero_count = 0;
continue;
}
if (ptr[i] == 0)
zero_count++;
else
zero_count = 0;
ptr[i - code_num] = ptr[i];
}
*len = inlen - code_num;
}
return find;
}
void do_sm4_ecb_encrypt(const char *in_buff, char *out_buff, const char *key);
static int
enc_vek(struct svac_handle *h)
{
do_sm4_ecb_encrypt(h->vek, h->curr_param.evek, h->vkek_list[0].vkek);
h->curr_param.vek_len = 16;
return 0;
}
static int
calc_nalu_hash(struct svac_handle *h)
{
int i;
struct sm3_ctx ctx;
char hash[32];
struct hash_cache *cache;
if (!h->curr_param.auth_flag) return 0;
for (i = 0; i < h->nalu_num; i++) {
if (h->nalu[i].authentication_idc) break;
}
/* û<><C3BB>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD>nalu */
if (i >= h->nalu_num) return 0;
memset(hash, 0, sizeof(hash));
sm3_init(&ctx);
for (i = 0; i < h->nalu_num; i++) {
if (!h->nalu[i].authentication_idc) continue;
sm3_update(&ctx, h->nalu[i].addr + 4, h->nalu[i].len - 4);
//printf("calc_nalu_hash nalu %d len %d\n", i, h->nalu[i].len - 4);
}
sm3_final(&ctx, hash);
if (!h->frame_num) memcpy(h->idr_hash, hash, 32);
cache = &h->cache[h->cache_idx];
memcpy(cache->hash, hash, 32);
cache->frame_num = h->frame_num;
h->cache_idx = (h->cache_idx + 1) % HASH_CACHE_NUM;
return 0;
}
void do_sm4_ofb_encrypt(const char *in_buff, int in_len, char *out_buff, int *out_len, const char *key, const char *iv);
static int
do_dec_and_copy(int encrypt_type,
const char *in_buff,
int in_len,
char *out_buff,
int *out_len,
const char *key,
const char *iv)
{
if (encrypt_type == SM4_OFB) {
do_sm4_ofb_encrypt(in_buff, in_len, out_buff, out_len, key, iv);
} else if (encrypt_type == SM1_OFB) {
PRINT_ERR("unsupport SM1 now!\n");
return -1;
}
return 0;
}
static int
make_bypass_frame(struct svac_handle *h, char *out_buff, int *out_len)
{
int i;
*out_len = 0;
for (i = 0; i < h->nalu_num; i++) {
if (h->nalu[i].type == SVAC_SEC_SLICE) continue;
memcpy(out_buff + *out_len, h->nalu[i].addr, h->nalu[i].len);
*out_len += h->nalu[i].len;
}
return 0;
}
static int
update_new_enc_param(struct svac_handle *h)
{
memcpy(&h->curr_param, &h->new_param, sizeof(struct sec_param));
//printf("h->new_param.enc %d\n", h->new_param.encrypt_flag);
h->sec_param_update_flag = 0;
if (h->curr_param.encrypt_flag) {
char vek[16];
char iv[16];
vli_get_random(vek, 16);
vli_get_random(iv, 16);
memcpy(h->vek, vek, 16);
memcpy(h->iv, iv, 16);
enc_vek(h);
}
return 0;
}
void *
SvacEncCreate(void)
{
int i;
struct svac_handle *h;
h = (struct svac_handle *) malloc(sizeof(struct svac_handle));
if (!h) return NULL;
memset(h, 0, sizeof(struct svac_handle));
h->magic = MAGIC_VALUE;
for (i = 0; i < HASH_CACHE_NUM; i++) h->cache[i].frame_num = -1;
return (void *) h;
}
int
SvacEncSetVkek(void *handle, char *vkek, char *version, int verion_len)
{
struct svac_handle *h = (struct svac_handle *) handle;
CHECK_HANDLE(h);
if (!vkek || !version) return -1;
memcpy(h->vkek_list[0].vkek, vkek, 16);
memset(h->vkek_list[0].version, 0, sizeof(h->vkek_list[0].version));
memcpy(h->vkek_list[0].version, version, verion_len);
h->find_vkek_flag = 1;
return 0;
}
int
SvacEncSetKeyPair(void *handle, char *sm2_prikey, char *sm2_pubkey)
{
struct svac_handle *h = (struct svac_handle *) handle;
CHECK_HANDLE(h);
if (!sm2_prikey || !sm2_pubkey) return -1;
hexdump("sm2_prikey", sm2_prikey, 32);
hexdump("sm2_pubkey", sm2_pubkey, 64);
memcpy(h->sm2_prikey, sm2_prikey, 32);
memcpy(h->sm2_pubkey, sm2_pubkey, 64);
h->sm_prikey_flag = 1;
return 0;
}
int
SvacEncSetIpcId(void *handle, char *id)
{
struct svac_handle *h = (struct svac_handle *) handle;
CHECK_HANDLE(h);
memset(h->camera_id, 0, sizeof(h->camera_id));
memcpy(h->camera_id, id, strlen(id));
return 0;
}
int
SvacEncSetCertId(void *handle, char *cert_id)
{
struct svac_handle *h = (struct svac_handle *) handle;
int serial_len = 0;
CHECK_HANDLE(h);
if (!cert_id) return -1;
serial_len = strlen(cert_id);
if (serial_len > 19) serial_len = 19;
memset(h->camera_idc, 0, sizeof(h->camera_idc));
memcpy(h->camera_idc + 19 - serial_len, cert_id, serial_len);
return 0;
}
int
SvacEncSetLevel(void *handle, char level)
{
struct svac_handle *h = (struct svac_handle *) handle;
h->new_param.encrypt_flag = 0;
h->new_param.encrypt_type = SM4_OFB;
h->new_param.auth_flag = 0;
h->new_param.auth_type = SM2_SIGN;
h->new_param.hash_type = SM3_HASH;
h->new_param.only_IDR = 1;
h->new_param.hash_period = 0;
if (level == 'b' || level == 'B') {
h->new_param.auth_flag = 1;
} else if (level == 'c' || level == 'C') {
h->new_param.encrypt_flag = 1;
h->new_param.auth_flag = 1;
}
h->sec_param_update_flag = 1;
return 0;
}
static int
write_security_nalu_data(struct svac_handle *h, unsigned char *ptr, unsigned int *len)
{
unsigned int offset = 0;
unsigned int l = *len;
/* write encryption_flag */
offset = write_bits(h->curr_param.encrypt_flag, 1, ptr + l, offset);
/* write authentication_flag */
offset = write_bits(h->curr_param.auth_flag, 1, ptr + l, offset);
if (h->curr_param.encrypt_flag) {
unsigned char tmp;
/* write encryption_type */
if (h->curr_param.encrypt_type == SM1_OFB)
tmp = 0;
else
tmp = 1;
offset = write_bits(tmp, 4, ptr + l, offset);
/* write vek_flag */
offset = write_bits(1, 1, ptr + l, offset);
/* write iv_flag */
offset = write_bits(1, 1, ptr + l, offset);
if (1) {
/* write vek_encryption_type */
tmp = 1;
offset = write_bits(tmp, 4, ptr + l, offset);
/* write evek_length_minus1 */
offset = write_bits(h->curr_param.vek_len - 1, 8, ptr + l, offset);
/* write evek */
offset = write_string_bits(h->curr_param.evek, h->curr_param.vek_len * 8, ptr + l, offset);
/* write vkek_verion_length_minus1 */
offset = write_bits(strlen(h->vkek_list[0].version) - 1, 8, ptr + l, offset);
/* write vkek_version */
offset = write_string_bits(h->vkek_list[0].version, strlen(h->vkek_list[0].version) * 8, ptr + l, offset);
}
if (1) {
/* write iv_length_minus1 */
offset = write_bits(16 - 1, 8, ptr + l, offset);
/* write iv */
offset = write_string_bits(h->iv, 16 * 8, ptr + l, offset);
}
}
if (h->curr_param.auth_flag) {
offset = write_bits(0, 2, ptr + l, offset);
offset = write_bits(h->curr_param.only_IDR, 1, ptr + l, offset);
offset = write_bits(0, 2, ptr + l, offset);
offset = write_bits(h->curr_param.hash_period - 1, 8, ptr + l, offset);
offset = write_string_bits(h->camera_idc, 152, ptr + l, offset);
}
if (h->curr_param.encrypt_flag || h->curr_param.auth_flag)
offset = write_string_bits(h->camera_id, 160, ptr + l, offset);
offset = write_bits(1, 1, ptr + l, offset);
if (offset & 7) offset = write_bits(0, 8 - (offset & 7), ptr + l, offset);
assert(!(offset & 7));
l += offset / 8;
*len = l;
return 0;
}
static int
create_security_nalu(struct svac_handle *h, char *ptr, int *len)
{
unsigned int save_len = 0;
unsigned int l = *len;
ptr[l] = 0x00;
l++;
ptr[l] = 0x00;
l++;
ptr[l] = 0x00;
l++;
ptr[l] = 0x01;
l++;
ptr[l] = SVAC_SEC_SLICE << 2 | 0xc0;
l++;
write_security_nalu_data(h, ptr, &l);
*len = l;
do_add_racing_Code(ptr, &l, save_len + 4 + 1);
*len = l;
return 0;
}
static int
write_auth_nalu_data(struct svac_handle *h, unsigned char *ptr, unsigned int *len)
{
unsigned int offset = 0;
unsigned int l = *len;
int i;
/* write frame_num */
offset = write_bits(h->sign_frame_num, 8, ptr + l, offset);
/* write authentication_data_length_minus1 */
offset = write_bits((unsigned int) (h->sign_len - 1), 8, ptr + l, offset);
/* write authentication_data */
for (i = 0; i < (int) h->sign_len; i++) offset = write_bits(h->sign[i], 8, ptr + l, offset);
/* write rbsp_trailing_bits() */
offset = write_bits(1, 1, ptr + l, offset);
if (offset & 7) offset = write_bits(0, 8 - (offset & 7), ptr + l, offset);
l += offset / 8;
*len = l;
return 0;
}
static int
create_auth_nalu(struct svac_handle *h, char *ptr, int *len)
{
unsigned int save_len;
unsigned int l = *len;
save_len = l;
//printf("======= %s ==========\n", __FUNCTION__);
ptr[l] = 0x00;
l++;
ptr[l] = 0x00;
l++;
ptr[l] = 0x00;
l++;
ptr[l] = 0x01;
l++;
ptr[l] = SVAC_AUTH_SLICE << 2 | 0xc0;
l++;
write_auth_nalu_data(h, ptr, &l);
*len = l;
do_add_racing_Code(ptr, &l, save_len + 4 + 1);
*len = l;
return 0;
}
static int
make_enc_frame(struct svac_handle *h, char *out_buff, int *out_data_len)
{
int i;
int out_offset = 0;
int out_nalu_len;
int ret;
*out_data_len = 0;
if (h->idr_flag) { create_security_nalu(h, out_buff, &out_offset); }
for (i = 0; i < h->nalu_num; i++) {
if (((h->nalu[i].type != SVAC_IDR_SLICE) && (h->nalu[i].type != SVAC_NO_IDR_SLICE))
|| (!h->curr_param.encrypt_flag)) {
memcpy(out_buff + out_offset, h->nalu[i].addr, h->nalu[i].len);
h->nalu[i].out_addr = out_buff + out_offset;
//out_buff[out_offset + 4] &= 0xfc;
out_nalu_len = h->nalu[i].len;
if (h->nalu[i].need_add_racing_code) do_add_racing_Code(out_buff + out_offset, &out_nalu_len, 5);
out_offset += out_nalu_len;
h->nalu[i].out_len = out_nalu_len;
} else {
int enc_len;
int out_len;
if (!h->find_vkek_flag) {
PRINT_ERR("Not find vkek [%s]! skip dec frame!\n", h->curr_param.vkek_version);
return -1;
}
if (!h->nalu[i].need_add_racing_code) {
do_remove_racing_code(h->nalu[i].addr, &h->nalu[i].len, 5);
h->nalu[i].need_add_racing_code = 1;
}
memcpy(out_buff + out_offset, h->nalu[i].addr, 5);
enc_len = h->nalu[i].len - 1 - 5;
h->nalu[i].out_addr = out_buff + out_offset;
ret = do_dec_and_copy(h->curr_param.encrypt_type, h->nalu[i].addr + 5, enc_len, out_buff + out_offset + 5,
&out_len, h->vek, h->iv);
if (ret) return -1;
memcpy(out_buff + out_offset + enc_len + 5, h->nalu[i].addr + 5 + enc_len, 1);
out_buff[out_offset + 4] |= 0x2;
out_nalu_len = h->nalu[i].len;
do_add_racing_Code(out_buff + out_offset, &out_nalu_len, 5);
out_offset += out_nalu_len;
h->nalu[i].out_len = out_nalu_len;
}
//PRINT_INFO("out_nalu_len %d out_offset %d\n", out_nalu_len, out_offset);
}
*out_data_len += out_offset;
return 0;
}
static int
calc_frame_hash(struct svac_handle *h, char *out_buff, int *out_data_len)
{
int i;
struct sm3_ctx ctx;
sm3_init(&ctx);
for (i = 0; i < h->nalu_num; i++) {
if ((h->nalu[i].type == SVAC_IDR_SLICE) || (h->nalu[i].type == SVAC_NO_IDR_SLICE)) {
h->nalu[i].out_addr[4] |= 1;
sm3_update(&ctx, h->nalu[i].out_addr + 4, h->nalu[i].out_len - 4);
//printf("calc_frame_hash nalu %d len %d\n", i, h->nalu[i].out_len - 4);
}
}
sm3_final(&ctx, h->idr_hash);
return 0;
}
static int
calc_idr_sign_data(struct svac_handle *h)
{
char sign[64];
int sign_len = 64;
do_sm2_sign(h->sm2_prikey, h->sm2_pubkey, h->idr_hash, 32, sign);
h->sign_len = 64;
h->sign_len = sizeof(h->sign);
do_base64_encode(h->sign, &h->sign_len, sign, sign_len);
return 0;
}
static int
make_auth_nal(struct svac_handle *h, char *out_buff, int *out_data_len)
{
if (!h->curr_param.auth_flag) return 0;
if (h->curr_param.only_IDR && h->idr_flag) {
calc_frame_hash(h, out_buff, out_data_len);
calc_idr_sign_data(h);
create_auth_nalu(h, out_buff, out_data_len);
}
return 0;
}
int
SvacEncProcess(void *handle, char *in_buff, int in_len, char *out_buff, int *out_len)
{
struct svac_handle *h = (struct svac_handle *) handle;
CHECK_HANDLE(h);
if (!in_buff || !out_buff || !out_len) return -1;
h->nalu_num = 0;
h->idr_flag = 0;
h->sec_nalu_flag = 0;
h->auth_nalu_flag = 0;
svac_parse_nalu(h, in_buff, in_len);
if (!h->nalu_num) {
PRINT_ERR("Not find nalu start code!\n");
return -1;
}
if (h->idr_flag && h->sec_param_update_flag) update_new_enc_param(h);
/* <20><><EFBFBD><EFBFBD><EFBFBD>a<EFBFBD><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD> bypass */
if (!h->curr_param.auth_flag && !h->curr_param.encrypt_flag) return make_bypass_frame(h, out_buff, out_len);
make_enc_frame(h, out_buff, out_len);
make_auth_nal(h, out_buff, out_len);
return 0;
}
int
SvacEncRelease(void *handle)
{
struct svac_handle *h = (struct svac_handle *) handle;
CHECK_HANDLE(h);
free(h);
return 0;
}

View File

@ -0,0 +1,151 @@
#ifndef __TYPEDEF_H__
#define __TYPEDEF_H__
typedef int s32;
typedef unsigned int u32;
typedef unsigned char u8;
typedef unsigned short u16;
typedef short s16;
typedef char s8;
#ifdef _MSC_VER
typedef __int64 s64;
#else
typedef long long s64;
#endif
#ifdef _MSC_VER
typedef unsigned __int64 u64;
#else
typedef unsigned long long u64;
#endif
static u16 __get_unaligned_le16(const u8 *p)
{
return p[0] | p[1] << 8;
}
static u32 __get_unaligned_le32(const u8 *p)
{
return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
}
static u64 __get_unaligned_le64(const u8 *p)
{
return (u64)__get_unaligned_le32(p + 4) << 32 |
__get_unaligned_le32(p);
}
static void __put_unaligned_le16(u16 val, u8 *p)
{
*p++ = val;
*p++ = val >> 8;
}
static void __put_unaligned_le32(u32 val, u8 *p)
{
__put_unaligned_le16(val >> 16, p + 2);
__put_unaligned_le16(val, p);
}
static void __put_unaligned_le64(u64 val, u8 *p)
{
__put_unaligned_le32(val >> 32, p + 4);
__put_unaligned_le32(val, p);
}
static u16 get_unaligned_le16(const void *p)
{
return __get_unaligned_le16((const u8 *)p);
}
static u32 get_unaligned_le32(const void *p)
{
return __get_unaligned_le32((const u8 *)p);
}
static u64 get_unaligned_le64(const void *p)
{
return __get_unaligned_le64((const u8 *)p);
}
static void put_unaligned_le16(u16 val, void *p)
{
__put_unaligned_le16(val, p);
}
static void put_unaligned_le32(u32 val, void *p)
{
__put_unaligned_le32(val, p);
}
static void put_unaligned_le64(u64 val, void *p)
{
__put_unaligned_le64(val, p);
}
static u16 __get_unaligned_be16(const u8 *p)
{
return p[0] << 8 | p[1];
}
static u32 __get_unaligned_be32(const u8 *p)
{
return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}
static u64 __get_unaligned_be64(const u8 *p)
{
return (u64)__get_unaligned_be32(p) << 32 |
__get_unaligned_be32(p + 4);
}
static void __put_unaligned_be16(u16 val, u8 *p)
{
*p++ = val >> 8;
*p++ = val;
}
static void __put_unaligned_be32(u32 val, u8 *p)
{
__put_unaligned_be16(val >> 16, p);
__put_unaligned_be16(val, p + 2);
}
static void __put_unaligned_be64(u64 val, u8 *p)
{
__put_unaligned_be32(val >> 32, p);
__put_unaligned_be32(val, p + 4);
}
static u16 get_unaligned_be16(const void *p)
{
return __get_unaligned_be16((const u8 *)p);
}
static u32 get_unaligned_be32(const void *p)
{
return __get_unaligned_be32((const u8 *)p);
}
static u64 get_unaligned_be64(const void *p)
{
return __get_unaligned_be64((const u8 *)p);
}
static void put_unaligned_be16(u16 val, void *p)
{
__put_unaligned_be16(val, p);
}
static void put_unaligned_be32(u32 val, void *p)
{
__put_unaligned_be32(val, p);
}
static void put_unaligned_be64(u64 val, void *p)
{
__put_unaligned_be64(val, p);
}
#endif

View File

@ -1,23 +1,18 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
PROJECT(AWSMRPC) project(AWSMRPC)
OPTION(SUBPROJECT "Using SubProject" ON) option(SUBPROJECT "Using SubProject" ON)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
INCLUDE_DIRECTORIES( include_directories(PUBLIC ${CMAKE_SOURCE_DIR}/utils)
PUBLIC
${CMAKE_SOURCE_DIR}/utils)
LINK_DIRECTORIES(${PROJECT_NAME} link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/lib)
PUBLIC
${CMAKE_SOURCE_DIR}/lib)
ADD_SUBDIRECTORY(utils/VSConfig) add_subdirectory(utils/VSConfig)
ADD_SUBDIRECTORY(utils/VSClock) add_subdirectory(utils/VSClock)
ADD_SUBDIRECTORY(utils/ZMQLayout) add_subdirectory(utils/ZMQLayout)
ADD_SUBDIRECTORY(utils/AWSMProtobuf) add_subdirectory(utils/AWSMProtobuf)
ADD_SUBDIRECTORY(AWSMServer)
ADD_SUBDIRECTORY(AWSM)
add_subdirectory(AWSMServer)
add_subdirectory(AWSM)