mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-22 13:13:42 +08:00
Add ECDSA with curve P-256
for TLS testing
This commit is contained in:
379
src/bn.c
Normal file
379
src/bn.c
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
void bn_set_word(uint32_t *r, uint32_t a, size_t k)
|
||||
{
|
||||
r[0] = a;
|
||||
while (k-- > 1) {
|
||||
r[k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_copy(uint32_t *r, const uint32_t *a, size_t k)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
r[k] = a[k];
|
||||
}
|
||||
}
|
||||
|
||||
int bn_cmp(const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
if (a[k] > b[k]) return 1;
|
||||
else if (a[k] < b[k]) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bn_is_zero(const uint32_t *a, size_t k)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
if (a[k]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bn_is_one(const uint32_t *a, size_t k)
|
||||
{
|
||||
if (a[0] != 1) {
|
||||
return 0;
|
||||
}
|
||||
while (k-- > 1) {
|
||||
if (a[k]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bn_add(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
uint64_t w = 0;
|
||||
size_t i;
|
||||
for (i = 0; i < k; i++) {
|
||||
w += (uint64_t)a[i] + (uint64_t)b[i];
|
||||
r[i] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
return (int)w;
|
||||
}
|
||||
|
||||
int bn_sub(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
int64_t w = 0;
|
||||
size_t i;
|
||||
for (i = 0; i < k; i++) {
|
||||
w += (int64_t)a[i] - (int64_t)b[i];
|
||||
r[i] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
return (int)w;
|
||||
}
|
||||
|
||||
void bn_mul(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
uint64_t w;
|
||||
size_t i, j;
|
||||
for (i = 0; i < k; i++) {
|
||||
r[i] = 0;
|
||||
}
|
||||
for (i = 0; i < k; i++) {
|
||||
w = 0;
|
||||
for (j = 0; j < k; j++) {
|
||||
w += (uint64_t)r[i + j] + (uint64_t)a[i] * (uint64_t)b[j];
|
||||
r[i + j] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
r[i + k] = w;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mul_lo(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
uint64_t w;
|
||||
size_t i, j;
|
||||
for (i = 0; i < k; i++) {
|
||||
r[i] = 0;
|
||||
}
|
||||
for (i = 0; i < k; i++) {
|
||||
w = 0;
|
||||
for (j = 0; j < k - i; j++) {
|
||||
w += (uint64_t)r[i + j] + (uint64_t)a[i] * (uint64_t)b[j];
|
||||
r[i + j] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bn_to_bytes(const uint32_t *a, size_t k, uint8_t *out)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
PUTU32(out, a[k]);
|
||||
out += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_from_bytes(uint32_t *a, size_t k, const uint8_t *in)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
a[k] = GETU32(in);
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
int bn_print(FILE *fp, int fmt, int ind, const char *label, const uint32_t *a, size_t k)
|
||||
{
|
||||
fprintf(fp, "%s: ", label);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < k; i++) {
|
||||
fprintf(fp, "0x%08x, ", a[i]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
while (k-- > 0) {
|
||||
fprintf(fp, "%08x", a[k]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bn_mod_add(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p, size_t k)
|
||||
{
|
||||
int carry;
|
||||
carry = bn_add(r, a, b, k);
|
||||
|
||||
if (carry) {
|
||||
bn_sub(r, r, p, k);
|
||||
} else if (bn_cmp(r, p, k) >= 0) {
|
||||
bn_sub(r, r, p, k);
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mod_sub(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p, size_t k)
|
||||
{
|
||||
if (bn_cmp(a, b, k) >= 0) {
|
||||
bn_sub(r, a, b, k);
|
||||
} else {
|
||||
bn_sub(r, b, a, k);
|
||||
bn_sub(r, p, r, k);
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mod_neg(uint32_t *r, const uint32_t *a, const uint32_t *p, size_t k)
|
||||
{
|
||||
bn_sub(r, p, a, k);
|
||||
}
|
||||
|
||||
void bn_barrett_mod_mul(uint32_t *r, // uint32_t r[k] = a * b mod p
|
||||
const uint32_t *a, // uint32_t a[k]
|
||||
const uint32_t *b, // uint32_t b[k]
|
||||
const uint32_t *p, // uint32_t p[k]
|
||||
const uint32_t *u, // uint32_t u[k + 1] = floor((2^32)^(2*k) / p)
|
||||
uint32_t *tmp, // uint32_t tmp[6*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *p_; // uint32_t p_[k + 1];
|
||||
uint32_t *z; // uint32_t z[2 * k];
|
||||
uint32_t *q; // uint32_t q[2 * (k + 1)];
|
||||
uint32_t *t_; // uint32_t t_[k + 1];
|
||||
size_t i;
|
||||
|
||||
p_ = tmp; tmp += k + 1;
|
||||
z = tmp; tmp += 2 * k;
|
||||
q = tmp; tmp += 2 * (k + 1);
|
||||
t_ = tmp; tmp += k + 1;
|
||||
|
||||
for (i = 0; i < k; i++) {
|
||||
p_[i] = p[i];
|
||||
}
|
||||
p_[k] = 0;
|
||||
|
||||
bn_mul(z, a, b, k);
|
||||
bn_mul(q, z + k - 1, u, k + 1);
|
||||
bn_mul_lo(t_, q + k + 1, p_, k + 1);
|
||||
bn_sub(t_, z, t_, k + 1);
|
||||
|
||||
// reduce at most twice
|
||||
if (bn_cmp(t_, p_, k + 1) >= 0) {
|
||||
bn_sub(t_, t_, p_, k + 1);
|
||||
}
|
||||
if (bn_cmp(t_, p_, k) >= 0) {
|
||||
bn_sub(t_, t_, p_, k);
|
||||
}
|
||||
bn_copy(r, t_, k);
|
||||
}
|
||||
|
||||
void bn_barrett_mod_sqr(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *u, // uint32_t u[k + 1]
|
||||
uint32_t *tmp, // uint32_t tmp[6*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
bn_barrett_mod_mul(r, a, a, p, u, tmp, k);
|
||||
}
|
||||
|
||||
void bn_barrett_mod_exp(uint32_t *r, const uint32_t *a, const uint32_t *e, const uint32_t *p,
|
||||
const uint32_t *u, //
|
||||
uint32_t *tmp, // uint32_t tmp[7*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *t; // uint32_t t[k];
|
||||
uint32_t w;
|
||||
int i, j;
|
||||
|
||||
// t = 1
|
||||
t = tmp; tmp += k;
|
||||
bn_set_word(t, 1, k);
|
||||
|
||||
for (i = k - 1; i >= 0; i--) {
|
||||
w = e[i];
|
||||
for (j = 0; j < 32; j++) {
|
||||
bn_barrett_mod_sqr(t, t, p, u, tmp, k);
|
||||
if (w & 0x80000000) {
|
||||
bn_barrett_mod_mul(t, t, a, p, u, tmp, k);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
bn_copy(r, t, k);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void bn_barrett_mod_inv(uint32_t *r, const uint32_t *a, const uint32_t *p, const uint32_t *u,
|
||||
uint32_t *tmp, // uint32_t tmp[8*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *e; // uint32_t e[k];
|
||||
|
||||
// e = p - 2
|
||||
e = tmp; tmp += k;
|
||||
bn_set_word(e, 2, k);
|
||||
bn_sub(e, p, e, k);
|
||||
|
||||
// a^-1 = a^(p - 2) (mod p)
|
||||
bn_barrett_mod_exp(r, a, e, p, u, tmp, k);
|
||||
}
|
||||
|
||||
// mont(aR, bR) = aR * bR * R^-1 = abR (mod p)
|
||||
void bn_mont_mod_mul(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *z; // uint32_t z[k * 2];
|
||||
uint32_t *c; // uint32_t c[k * 2];
|
||||
uint32_t *t; // uint32_t t[k];
|
||||
|
||||
z = tmp; tmp += 2 * k;
|
||||
c = tmp; tmp += 2 * k;
|
||||
t = tmp; tmp += k;
|
||||
|
||||
bn_mul(z, a, b, k);
|
||||
bn_mul_lo(t, z, p_inv_neg, k);
|
||||
bn_mul(c, t, p, k);
|
||||
bn_add(c, c, z, k * 2);
|
||||
if (bn_cmp(c + k, p, k) >= 0) {
|
||||
bn_sub(c + k, c + k, p, k);
|
||||
}
|
||||
|
||||
bn_copy(r, c + k, k);
|
||||
}
|
||||
|
||||
void bn_mont_mod_sqr(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
bn_mont_mod_mul(r, a, a, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
void bn_mont_mod_exp(
|
||||
uint32_t *r,
|
||||
const uint32_t *a,
|
||||
const uint32_t *e,
|
||||
const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[6 * k];
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *t; // uint32_t t[k];
|
||||
uint32_t w;
|
||||
int i, j;
|
||||
|
||||
// t = 1
|
||||
t = tmp; tmp += k;
|
||||
bn_set_word(t, 1, k);
|
||||
|
||||
for (i = k - 1; i >= 0; i--) {
|
||||
w = e[i];
|
||||
for (j = 0; j < 32; j++) {
|
||||
bn_mont_mod_sqr(t, t, p, p_inv_neg, tmp, k);
|
||||
if (w & 0x80000000) {
|
||||
bn_mont_mod_mul(t, t, a, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
bn_copy(r, t, k);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void bn_mont_mod_inv(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[7 * k];
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *e; // uint32_t e[k];
|
||||
|
||||
// e = p - 2
|
||||
e = tmp; tmp += k;
|
||||
bn_set_word(e, 2, k);
|
||||
bn_sub(e, p, e, k);
|
||||
|
||||
// a^-1 = a^(p - 2) (mod p)
|
||||
bn_mont_mod_exp(r, a, e, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
// mont(a, R^2) = a * R^2 * R^-1 = a * R mod p
|
||||
void bn_mont_set(uint32_t *r,
|
||||
const uint32_t *a,
|
||||
const uint32_t *R_sqr,
|
||||
const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
bn_mont_mod_mul(r, a, R_sqr, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
// mont(aR, 1) = aR * 1 * R^-1 = a (mod p)
|
||||
void bn_mont_get(uint32_t *r,
|
||||
const uint32_t *a,
|
||||
const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t one[k];
|
||||
bn_set_word(one, 1, k);
|
||||
bn_mont_mod_mul(r, a, one, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
12
src/ecdh.c
Normal file
12
src/ecdh.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
387
src/ecdsa.c
Normal file
387
src/ecdsa.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/sha2.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/ecdsa.h>
|
||||
#include <gmssl/bn.h>
|
||||
#include <gmssl/sm2.h>
|
||||
|
||||
|
||||
int ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
secp256r1_print(fp, fmt, ind, "r", sig->r);
|
||||
secp256r1_print(fp, fmt, ind, "s", sig->s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sigbuf, size_t siglen)
|
||||
{
|
||||
ECDSA_SIGNATURE sig;
|
||||
|
||||
if (ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ecdsa_signature_print_ex(fp, fmt, ind, label, &sig);
|
||||
if (siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_t dgst[32], ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
secp256r1_t e;
|
||||
secp256r1_t x1;
|
||||
secp256r1_t y1;
|
||||
secp256r1_t k_inv;
|
||||
SECP256R1_POINT P;
|
||||
|
||||
// e = hash(m)
|
||||
secp256r1_from_32bytes(e, dgst);
|
||||
secp256r1_modn(e, e);
|
||||
|
||||
// (x1, y1) = k*G
|
||||
secp256r1_point_mul_generator(&P, k);
|
||||
secp256r1_point_get_xy(&P, x1, y1);
|
||||
|
||||
// r = x1 mod n
|
||||
secp256r1_modn(sig->r, x1);
|
||||
|
||||
// s = k^-1 * (e + d * r) mod n
|
||||
secp256r1_modn_inv(k_inv, k);
|
||||
secp256r1_modn_mul(sig->s, key->private_key, sig->r);
|
||||
secp256r1_modn_add(sig->s, sig->s, e);
|
||||
secp256r1_modn_mul(sig->s, sig->s, k_inv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
secp256r1_t k;
|
||||
|
||||
// rand k in [1, n-1]
|
||||
do {
|
||||
if (rand_bytes((uint8_t *)k, sizeof(k)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (secp256r1_is_zero(k) || secp256r1_cmp(k, SECP256R1_N) >= 0);
|
||||
|
||||
if (ecdsa_do_sign_ex(key, k, dgst, sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
secp256r1_t e;
|
||||
secp256r1_t w;
|
||||
secp256r1_t u1;
|
||||
secp256r1_t u2;
|
||||
secp256r1_t x1;
|
||||
secp256r1_t y1;
|
||||
SECP256R1_POINT P;
|
||||
SECP256R1_POINT Q;
|
||||
SECP256R1_POINT R;
|
||||
|
||||
// check r, s in [1, n-1]
|
||||
if (secp256r1_is_zero(sig->r)
|
||||
|| secp256r1_cmp(sig->r, SECP256R1_N) >= 0
|
||||
|| secp256r1_is_zero(sig->s)
|
||||
|| secp256r1_cmp(sig->s, SECP256R1_N) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// e = hash(m)
|
||||
secp256r1_from_32bytes(e, dgst);
|
||||
secp256r1_modn(e, e);
|
||||
|
||||
// w = s^-1 (mod n)
|
||||
secp256r1_modn_inv(w, sig->s);
|
||||
|
||||
// u1 = e * w (mod n)
|
||||
secp256r1_modn_mul(u1, e, w);
|
||||
|
||||
// u2 = r * w (mod n)
|
||||
secp256r1_modn_mul(u2, sig->r, w);
|
||||
|
||||
// (x1, y1) = u1*G + u2*Q
|
||||
secp256r1_point_mul_generator(&P, u1);
|
||||
secp256r1_point_mul(&Q, u2, &key->public_key);
|
||||
secp256r1_point_add(&R, &P, &Q);
|
||||
secp256r1_point_get_xy(&R, x1, y1);
|
||||
|
||||
// x1 = x1 mod n
|
||||
secp256r1_modn(x1, x1);
|
||||
|
||||
if (secp256r1_cmp(x1, sig->r) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_signature_to_der(const ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
uint8_t r[32];
|
||||
uint8_t s[32];
|
||||
|
||||
if (!sig) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256r1_to_32bytes(sig->r, r);
|
||||
secp256r1_to_32bytes(sig->s, s);
|
||||
|
||||
if (asn1_integer_to_der(r, 32, NULL, &len) != 1
|
||||
|| asn1_integer_to_der(s, 32, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_integer_to_der(r, 32, out, outlen) != 1
|
||||
|| asn1_integer_to_der(s, 32, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_signature_from_der(ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
const uint8_t *r;
|
||||
const uint8_t *s;
|
||||
size_t dlen, rlen, slen;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_integer_from_der(&r, &rlen, &d, &dlen) != 1
|
||||
|| asn1_integer_from_der(&s, &slen, &d, &dlen) != 1
|
||||
|| asn1_length_le(rlen, 32) != 1
|
||||
|| asn1_length_le(slen, 32) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_from_32bytes(sig->r, r);
|
||||
secp256r1_from_32bytes(sig->s, s);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], uint8_t *sigbuf, size_t *siglen)
|
||||
{
|
||||
ECDSA_SIGNATURE sig;
|
||||
|
||||
if (ecdsa_do_sign(key, dgst, &sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*siglen = 0;
|
||||
if (ecdsa_signature_to_der(&sig, &sigbuf, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig)
|
||||
{
|
||||
unsigned int trys = 200;
|
||||
uint8_t buf[ECDSA_SIGNATURE_MAX_SIZE];
|
||||
size_t len;
|
||||
|
||||
switch (siglen) {
|
||||
case ECDSA_SIGNATURE_COMPACT_SIZE:
|
||||
case ECDSA_SIGNATURE_TYPICAL_SIZE:
|
||||
case ECDSA_SIGNATURE_MAX_SIZE:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (trys--) {
|
||||
if (ecdsa_sign(key, dgst, buf, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len == siglen) {
|
||||
memcpy(sig, buf, len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// might caused by bad randomness
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t *sigbuf, size_t siglen)
|
||||
{
|
||||
int ret;
|
||||
ECDSA_SIGNATURE sig;
|
||||
|
||||
if (ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if ((ret = ecdsa_do_verify(key, dgst, &sig)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ecdsa_sign_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key)
|
||||
{
|
||||
if (!ctx || !key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(ctx, 0, sizeof(ECDSA_SIGN_CTX));
|
||||
|
||||
ctx->key = *key;
|
||||
|
||||
sha256_init(&ctx->sha256_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (data && datalen) {
|
||||
sha256_update(&ctx->sha256_ctx, data, datalen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_finish(ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
||||
{
|
||||
uint8_t dgst[32];
|
||||
|
||||
if (!ctx || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sha256_finish(&ctx->sha256_ctx, dgst);
|
||||
|
||||
if (ecdsa_sign(&ctx->key, dgst, sig, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_finish_fixlen(ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig)
|
||||
{
|
||||
uint8_t dgst[32];
|
||||
|
||||
if (!ctx || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sha256_finish(&ctx->sha256_ctx, dgst);
|
||||
|
||||
if (ecdsa_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int ecdsa_verify_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const uint8_t *sig, size_t siglen)
|
||||
{
|
||||
if (!ctx || !key || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ecdsa_signature_from_der(&ctx->sig, &sig, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->key = *key;
|
||||
|
||||
sha256_init(&ctx->sha256_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_verify_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (data && datalen) {
|
||||
sha256_update(&ctx->sha256_ctx, data, datalen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_verify_finish(ECDSA_SIGN_CTX *ctx)
|
||||
{
|
||||
uint8_t dgst[32];
|
||||
int ret;
|
||||
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sha256_finish(&ctx->sha256_ctx, dgst);
|
||||
|
||||
if ((ret = ecdsa_do_verify(&ctx->key, dgst, &ctx->sig)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
593
src/secp256r1.c
Normal file
593
src/secp256r1.c
Normal file
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/bn.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/secp256r1.h>
|
||||
|
||||
|
||||
const secp256r1_t SECP256R1_P = {
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000001, 0xffffffff,
|
||||
};
|
||||
|
||||
const secp256r1_t SECP256R1_B = {
|
||||
0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0,
|
||||
0x769886bc, 0xb3ebbd55, 0xaa3a93e7, 0x5ac635d8,
|
||||
};
|
||||
|
||||
const secp256r1_t SECP256R1_N = {
|
||||
0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad,
|
||||
0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
|
||||
};
|
||||
|
||||
const uint32_t SECP256R1_U_P[9] = {
|
||||
0x00000003, 0x00000000, 0xffffffff, 0xfffffffe,
|
||||
0xfffffffe, 0xfffffffe, 0xffffffff, 0x00000000,
|
||||
0x00000001,
|
||||
};
|
||||
|
||||
const uint32_t SECP256R1_U_N[9] = {
|
||||
0xeedf9bfe, 0x012ffd85, 0xdf1a6c21, 0x43190552,
|
||||
0xffffffff, 0xfffffffe, 0xffffffff, 0x00000000,
|
||||
0x00000001,
|
||||
};
|
||||
|
||||
int secp256r1_is_zero(const secp256r1_t a) {
|
||||
return bn_is_zero(a, SECP256R1_K);
|
||||
}
|
||||
|
||||
int secp256r1_is_one(const secp256r1_t a) {
|
||||
return bn_is_one(a, SECP256R1_K);
|
||||
}
|
||||
|
||||
int secp256r1_cmp(const secp256r1_t a, const secp256r1_t b) {
|
||||
return bn_cmp(a, b, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_set_zero(secp256r1_t r) {
|
||||
bn_set_word(r, 0, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_set_one(secp256r1_t r) {
|
||||
bn_set_word(r, 1, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_copy(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_copy(r, a, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_to_32bytes(const secp256r1_t a, uint8_t out[32]) {
|
||||
bn_to_bytes(a, SECP256R1_K, out);
|
||||
}
|
||||
|
||||
void secp256r1_from_32bytes(secp256r1_t r, const uint8_t in[32]) {
|
||||
bn_from_bytes(r, SECP256R1_K, in);
|
||||
}
|
||||
|
||||
int secp256r1_print(FILE *fp, int fmt, int ind, const char *label, const secp256r1_t a) {
|
||||
uint8_t bytes[32];
|
||||
secp256r1_to_32bytes(a, bytes);
|
||||
format_bytes(fp, fmt, ind, label, bytes, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void secp256r1_modp_add(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_add(r, a, b, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_dbl(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_add(r, a, a, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_tri(secp256r1_t r, const secp256r1_t a) {
|
||||
secp256r1_t tmp;
|
||||
|
||||
// 这里就出错了,真是太奇怪了!
|
||||
bn_mod_add(tmp, a, a, SECP256R1_P, SECP256R1_K);
|
||||
bn_mod_add(r, tmp, a, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_sub(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_sub(r, a, b, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_neg(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_neg(r, a, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_haf(secp256r1_t r, const secp256r1_t a) {
|
||||
int c = 0;
|
||||
if (a[0] & 1) {
|
||||
c = bn_add(r, a, SECP256R1_P, SECP256R1_K);
|
||||
} else {
|
||||
bn_copy(r, a, SECP256R1_K);
|
||||
}
|
||||
|
||||
r[0] = (r[0] >> 1) | ((r[1] & 1) << 31);
|
||||
r[1] = (r[1] >> 1) | ((r[2] & 1) << 31);
|
||||
r[2] = (r[2] >> 1) | ((r[3] & 1) << 31);
|
||||
r[3] = (r[3] >> 1) | ((r[4] & 1) << 31);
|
||||
r[4] = (r[4] >> 1) | ((r[5] & 1) << 31);
|
||||
r[5] = (r[5] >> 1) | ((r[6] & 1) << 31);
|
||||
r[6] = (r[6] >> 1) | ((r[7] & 1) << 31);
|
||||
r[7] = (r[7] >> 1) | ((c & 1) << 31);
|
||||
}
|
||||
|
||||
void secp256r1_modp_mul(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, b, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_sqr(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, a, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_exp(secp256r1_t r, const secp256r1_t a, const secp256r1_t e) {
|
||||
uint32_t tmp[7*8 + 4];
|
||||
bn_barrett_mod_exp(r, a, e, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void secp256r1_modp_inv(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[8*8 + 4];
|
||||
bn_barrett_mod_inv(r, a, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
|
||||
void secp256r1_modn(secp256r1_t r, const secp256r1_t a) {
|
||||
if (bn_cmp(a, SECP256R1_N, SECP256R1_K) >= 0) {
|
||||
bn_sub(r, a, SECP256R1_N, SECP256R1_K);
|
||||
} else {
|
||||
bn_copy(r, a, SECP256R1_K);
|
||||
}
|
||||
}
|
||||
|
||||
void secp256r1_modn_add(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_add(r, a, b, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_dbl(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_add(r, a, a, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_tri(secp256r1_t r, const secp256r1_t a) {
|
||||
secp256r1_t tmp;
|
||||
bn_mod_add(tmp, a, a, SECP256R1_N, SECP256R1_K);
|
||||
bn_mod_add(r, tmp, a, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_sub(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_sub(r, a, b, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_neg(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_neg(r, a, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_mul(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, b, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_sqr(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, a, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_exp(secp256r1_t r, const secp256r1_t a, const secp256r1_t e) {
|
||||
uint32_t tmp[7*8 + 4];
|
||||
bn_barrett_mod_exp(r, a, e, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void secp256r1_modn_inv(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[8*8 + 4];
|
||||
bn_barrett_mod_inv(r, a, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
|
||||
const SECP256R1_POINT SECP256R1_POINT_G = {
|
||||
{ 0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81,
|
||||
0x63a440f2, 0xf8bce6e5, 0xe12c4247, 0x6b17d1f2, },
|
||||
{ 0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357,
|
||||
0x7c0f9e16, 0x8ee7eb4a, 0xfe1a7f9b, 0x4fe342e2, },
|
||||
{ 1,0,0,0,0,0,0,0, },
|
||||
};
|
||||
|
||||
void secp256r1_point_set_infinity(SECP256R1_POINT *R)
|
||||
{
|
||||
secp256r1_set_one(R->X);
|
||||
secp256r1_set_one(R->Y);
|
||||
secp256r1_set_zero(R->Z);
|
||||
}
|
||||
|
||||
int secp256r1_point_is_at_infinity(const SECP256R1_POINT *P)
|
||||
{
|
||||
if (secp256r1_is_zero(P->Z)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int secp256r1_point_is_on_curve(const SECP256R1_POINT *P)
|
||||
{
|
||||
secp256r1_t t0;
|
||||
secp256r1_t t1;
|
||||
secp256r1_t t2;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check Y^2 + 3 * X * Z^4 == X^3 + b * Z^6
|
||||
|
||||
// t0 = Y^2
|
||||
secp256r1_modp_sqr(t0, P->Y);
|
||||
|
||||
// t1 = Z^2
|
||||
secp256r1_modp_sqr(t1, P->Z);
|
||||
|
||||
// t2 = Z^4
|
||||
secp256r1_modp_sqr(t2, t1);
|
||||
|
||||
// t1 = Z^6
|
||||
secp256r1_modp_mul(t1, t1, t2);
|
||||
|
||||
// t1 = b * Z^6
|
||||
secp256r1_modp_mul(t1, t1, SECP256R1_B);
|
||||
|
||||
// t2 = X * Z^4
|
||||
secp256r1_modp_mul(t2, t2, P->X);
|
||||
|
||||
// t0 = Y^2 + 3 * X * Z^4
|
||||
secp256r1_modp_add(t0, t0, t2);
|
||||
secp256r1_modp_add(t0, t0, t2);
|
||||
secp256r1_modp_add(t0, t0, t2);
|
||||
|
||||
// t2 = X^2
|
||||
secp256r1_modp_sqr(t2, P->X);
|
||||
|
||||
// t2 = X^3
|
||||
secp256r1_modp_mul(t2, t2, P->X);
|
||||
|
||||
// t1 = b * Z^6 + X^3
|
||||
secp256r1_modp_add(t1, t1, t2);
|
||||
|
||||
if (secp256r1_cmp(t0, t1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void secp256r1_point_copy(SECP256R1_POINT *R, const SECP256R1_POINT *P)
|
||||
{
|
||||
secp256r1_copy(R->X, P->X);
|
||||
secp256r1_copy(R->Y, P->Y);
|
||||
secp256r1_copy(R->Z, P->Z);
|
||||
}
|
||||
|
||||
int secp256r1_point_set_xy(SECP256R1_POINT *R, const secp256r1_t x, const secp256r1_t y)
|
||||
{
|
||||
if (secp256r1_cmp(x, SECP256R1_P) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_cmp(y, SECP256R1_P) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_copy(R->X, x);
|
||||
secp256r1_copy(R->Y, y);
|
||||
secp256r1_set_one(R->Z);
|
||||
|
||||
|
||||
if (!secp256r1_point_is_on_curve(R)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_get_xy(const SECP256R1_POINT *P, secp256r1_t x, secp256r1_t y)
|
||||
{
|
||||
secp256r1_t Z_inv;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
return 0;
|
||||
}
|
||||
secp256r1_modp_inv(Z_inv, P->Z);
|
||||
secp256r1_modp_mul(y, P->Y, Z_inv);
|
||||
secp256r1_modp_sqr(Z_inv, Z_inv);
|
||||
secp256r1_modp_mul(x, P->X, Z_inv);
|
||||
secp256r1_modp_mul(y, y, Z_inv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void secp256r1_point_dbl(SECP256R1_POINT *R, const SECP256R1_POINT *P)
|
||||
{
|
||||
/*
|
||||
secp256r1_t T_0;
|
||||
secp256r1_t T_1;
|
||||
secp256r1_t T_2;
|
||||
secp256r1_t T_3;
|
||||
secp256r1_t T_4;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
secp256r1_point_set_infinity(R);
|
||||
return;
|
||||
}
|
||||
|
||||
secp256r1_modp_sqr(T_0, P->X);
|
||||
secp256r1_modp_tri(T_0, T_0);
|
||||
secp256r1_modp_sqr(T_1, T_0);
|
||||
secp256r1_modp_sqr(T_2, P->Y);
|
||||
secp256r1_modp_mul(T_3, P->X, T_2);
|
||||
secp256r1_modp_dbl(T_3, T_3);
|
||||
secp256r1_modp_dbl(T_3, T_3);
|
||||
secp256r1_modp_dbl(T_4, T_3);
|
||||
secp256r1_modp_sub(T_1, T_1, T_4);
|
||||
secp256r1_modp_sub(T_3, T_3, T_1);
|
||||
secp256r1_modp_mul(T_0, T_0, T_3);
|
||||
secp256r1_modp_dbl(T_2, T_2);
|
||||
secp256r1_modp_sqr(T_2, T_2);
|
||||
secp256r1_modp_dbl(T_2, T_2);
|
||||
secp256r1_modp_sub(T_0, T_0, T_2);
|
||||
secp256r1_modp_mul(T_2, P->Y, P->Z);
|
||||
secp256r1_modp_dbl(T_2, T_2);
|
||||
|
||||
secp256r1_copy(R->X, T_1);
|
||||
secp256r1_copy(R->Y, T_0);
|
||||
secp256r1_copy(R->Z, T_2);
|
||||
*/
|
||||
|
||||
const uint32_t *X1 = P->X;
|
||||
const uint32_t *Y1 = P->Y;
|
||||
const uint32_t *Z1 = P->Z;
|
||||
uint32_t *X3 = R->X;
|
||||
uint32_t *Y3 = R->Y;
|
||||
uint32_t *Z3 = R->Z;
|
||||
secp256r1_t S;
|
||||
secp256r1_t M;
|
||||
secp256r1_t Zsqr;
|
||||
secp256r1_t tmp0;
|
||||
|
||||
// 1. S = 2Y
|
||||
secp256r1_modp_dbl(S, Y1);
|
||||
|
||||
// 2. Zsqr = Z^2
|
||||
secp256r1_modp_sqr(Zsqr, Z1);
|
||||
|
||||
// 3. S = S^2 = 4Y^2
|
||||
secp256r1_modp_sqr(S, S);
|
||||
|
||||
// 4. Z = Z*Y
|
||||
secp256r1_modp_mul(Z3, Z1, Y1);
|
||||
|
||||
// 5. Z = 2*Z = 2*Y*Z ===> Z3
|
||||
secp256r1_modp_dbl(Z3, Z3);
|
||||
|
||||
// 6. M = X + Zsqr = X + Z^2
|
||||
secp256r1_modp_add(M, X1, Zsqr);
|
||||
|
||||
// 7. Zsqr = X - Zsqr = X - Z^2
|
||||
secp256r1_modp_sub(Zsqr, X1, Zsqr);
|
||||
|
||||
// 8. Y = S^2 = 16Y^4
|
||||
secp256r1_modp_sqr(Y3, S);
|
||||
|
||||
// 9. Y = Y/2 = 8Y^4
|
||||
secp256r1_modp_haf(Y3, Y3);
|
||||
|
||||
// 10. M = M * Zsqr = (X + Z^2)*(X - Z^2) = X^2 - Z^4
|
||||
secp256r1_modp_mul(M, M, Zsqr);
|
||||
|
||||
// 11. M = 3M = 3X^2 - 3Z^4
|
||||
secp256r1_modp_tri(M, M);
|
||||
|
||||
// 12. S = S * X = 4X*Y^2
|
||||
secp256r1_modp_mul(S, S, X1);
|
||||
|
||||
// 13. tmp0 = 2 * S = 8X*Y^2
|
||||
secp256r1_modp_dbl(tmp0, S);
|
||||
|
||||
// 14. X = M^2 = (3X^2 - 3Z^4)^2
|
||||
secp256r1_modp_sqr(X3, M);
|
||||
|
||||
// 15. X = X - tmp0 = (3X^2 - 3Z^4)^2 - 8X*Y^2 ===> X3
|
||||
secp256r1_modp_sub(X3, X3, tmp0);
|
||||
|
||||
// 16. S = S - X3 = 4X*Y^2 - X3
|
||||
secp256r1_modp_sub(S, S, X3);
|
||||
|
||||
// 17. S = S * M = (3X^2 - 3Z^4)*(4X*Y^2 - X3)
|
||||
secp256r1_modp_mul(S, S, M);
|
||||
|
||||
// 18. Y = S - Y = (3X^2 - 3Z^4)*(4X*Y^2 - X3) - 8Y^4 ===> Y3
|
||||
secp256r1_modp_sub(Y3, S, Y3);
|
||||
}
|
||||
|
||||
void secp256r1_point_add(SECP256R1_POINT *R, const SECP256R1_POINT *P, const SECP256R1_POINT *Q)
|
||||
{
|
||||
secp256r1_t T_1;
|
||||
secp256r1_t T_2;
|
||||
secp256r1_t T_3;
|
||||
secp256r1_t T_4;
|
||||
secp256r1_t T_5;
|
||||
secp256r1_t T_6;
|
||||
secp256r1_t T_7;
|
||||
secp256r1_t T_8;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
*R = *Q;
|
||||
return;
|
||||
}
|
||||
if (secp256r1_point_is_at_infinity(Q)) {
|
||||
*R = *P;
|
||||
return;
|
||||
}
|
||||
|
||||
// 这里的代码是来自zkrypt的,不确定是否有问题
|
||||
secp256r1_modp_sqr(T_1, P->Z); // T_1 = Z_1^2
|
||||
secp256r1_modp_sqr(T_2, Q->Z); // T_2 = Z_2^2
|
||||
secp256r1_modp_mul(T_3, Q->X, T_1); // T_3 = X_2 * Z_1^2
|
||||
secp256r1_modp_mul(T_4, P->X, T_2); // T_4 = X_1 * Z_2^2
|
||||
secp256r1_modp_add(T_5, T_3, T_4); // T_5 = X_2 * Z_1^2 + X_1 * Z_2^2 = C
|
||||
secp256r1_modp_sub(T_3, T_3, T_4); // T_3 = X_2 * Z_1^2 - X_1 * Z_2^2 = B
|
||||
secp256r1_modp_mul(T_1, T_1, P->Z); // T_1 = Z_1^3
|
||||
secp256r1_modp_mul(T_1, T_1, Q->Y); // T_1 = Y_2 * Z_1^3
|
||||
secp256r1_modp_mul(T_2, T_2, Q->Z); // T_2 = Z_2^3
|
||||
secp256r1_modp_mul(T_2, T_2, P->Y); // T_2 = Y_1 * Z_2^3
|
||||
secp256r1_modp_add(T_6, T_1, T_2); // T_6 = Y_2 * Z_1^3 + Y_1 * Z_2^3 = D
|
||||
secp256r1_modp_sub(T_1, T_1, T_2); // T_1 = Y_2 * Z_1^3 - Y_1 * Z_2^3 = A
|
||||
|
||||
if (secp256r1_is_zero(T_1) && secp256r1_is_zero(T_3)) {
|
||||
secp256r1_point_dbl(R, P);
|
||||
return;
|
||||
}
|
||||
|
||||
if (secp256r1_is_one(T_1) && secp256r1_is_zero(T_6)) {
|
||||
secp256r1_point_set_infinity(R);
|
||||
return;
|
||||
}
|
||||
|
||||
secp256r1_modp_sqr(T_6, T_1); // T_6 = A^2
|
||||
secp256r1_modp_mul(T_7, T_3, P->Z); // T_7 = B * Z_1
|
||||
secp256r1_modp_mul(T_7, T_7, Q->Z); // T_7 = B * Z_1 * Z_2 = Z_3
|
||||
secp256r1_modp_sqr(T_8, T_3); // T_8 = B^2
|
||||
secp256r1_modp_mul(T_5, T_5, T_8); // T_5 = B^2 * C
|
||||
secp256r1_modp_mul(T_3, T_3, T_8); // T_3 = B^3
|
||||
secp256r1_modp_mul(T_4, T_4, T_8); // T_4 = B^2 * X_1 * Z_2^2
|
||||
secp256r1_modp_sub(T_6, T_6, T_5); // T_6 = A^2 - B^2 * C = X_3
|
||||
secp256r1_modp_sub(T_4, T_4, T_6); // T_4 = B^2 * X_1 * Z_2^2 - X_3
|
||||
secp256r1_modp_mul(T_1, T_1, T_4); // T_1 = A * (B^2 * X_1 * Z_2^2 - X_3)
|
||||
secp256r1_modp_mul(T_2, T_2, T_3); // T_2 = B^3 * Y_1 * Z_1^3
|
||||
secp256r1_modp_sub(T_1, T_1, T_2); // T_1 = A * (B^2 * X_1 * Z_2^2 - X_3) - B^3 * Y_1 * Z_1^3 = Y_3
|
||||
|
||||
secp256r1_copy(R->X, T_6);
|
||||
secp256r1_copy(R->Y, T_1);
|
||||
secp256r1_copy(R->Z, T_7);
|
||||
}
|
||||
|
||||
void secp256r1_point_neg(SECP256R1_POINT *R, const SECP256R1_POINT *P)
|
||||
{
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
secp256r1_point_set_infinity(R);
|
||||
return;
|
||||
}
|
||||
secp256r1_copy(R->X, P->X);
|
||||
secp256r1_modp_neg(R->Y, P->Y);
|
||||
secp256r1_copy(R->Z, P->Z);
|
||||
}
|
||||
|
||||
void secp256r1_point_sub(SECP256R1_POINT *R, const SECP256R1_POINT *P, const SECP256R1_POINT *Q)
|
||||
{
|
||||
SECP256R1_POINT T;
|
||||
secp256r1_point_neg(&T, Q);
|
||||
secp256r1_point_add(R, P, &T);
|
||||
}
|
||||
|
||||
void secp256r1_point_mul(SECP256R1_POINT *R, const secp256r1_t k, const SECP256R1_POINT *P)
|
||||
{
|
||||
uint32_t bits;
|
||||
int nbits;
|
||||
int i;
|
||||
|
||||
secp256r1_point_set_infinity(R);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
bits = k[i];
|
||||
nbits = 32;
|
||||
while (nbits-- > 0) {
|
||||
secp256r1_point_dbl(R, R);
|
||||
if (bits & 0x80000000) {
|
||||
secp256r1_point_add(R, R, P);
|
||||
}
|
||||
bits <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void secp256r1_point_mul_generator(SECP256R1_POINT *R, const secp256r1_t k)
|
||||
{
|
||||
secp256r1_point_mul(R, k, &SECP256R1_POINT_G);
|
||||
}
|
||||
|
||||
int secp256r1_point_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_POINT *P)
|
||||
{
|
||||
uint8_t bytes[32];
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
secp256r1_to_32bytes(P->X, bytes);
|
||||
format_bytes(fp, fmt, ind, "X", bytes, 32);
|
||||
secp256r1_to_32bytes(P->Y, bytes);
|
||||
format_bytes(fp, fmt, ind, "Y", bytes, 32);
|
||||
secp256r1_to_32bytes(P->Z, bytes);
|
||||
format_bytes(fp, fmt, ind, "Z", bytes, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_to_uncompressed_octets(const SECP256R1_POINT *P, uint8_t octets[65])
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
if (secp256r1_point_get_xy(P, x, y) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
octets[0] = 0x04;
|
||||
secp256r1_to_32bytes(x, octets + 1);
|
||||
secp256r1_to_32bytes(y, octets + 33);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_from_uncompressed_octets(SECP256R1_POINT *P, const uint8_t octets[65])
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
if (octets[0] != 0x04) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_from_32bytes(x, octets + 1);
|
||||
secp256r1_from_32bytes(y, octets + 33);
|
||||
|
||||
if (secp256r1_point_set_xy(P, x, y) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_equ(const SECP256R1_POINT *P, const SECP256R1_POINT *Q)
|
||||
{
|
||||
uint8_t p_octets[65];
|
||||
uint8_t q_octets[65];
|
||||
|
||||
(void)secp256r1_point_to_uncompressed_octets(P, p_octets);
|
||||
(void)secp256r1_point_to_uncompressed_octets(Q, q_octets);
|
||||
|
||||
if (memcmp(p_octets, q_octets, 65) == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
506
src/secp256r1_key.c
Normal file
506
src/secp256r1_key.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/bn.h>
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/sm4.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/pkcs8.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
#include <gmssl/secp256r1_key.h>
|
||||
|
||||
|
||||
int secp256r1_key_generate(SECP256R1_KEY *key)
|
||||
{
|
||||
do {
|
||||
if (rand_bytes((uint8_t *)key->private_key, sizeof(secp256r1_t)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (secp256r1_is_zero(key->private_key) || secp256r1_cmp(key->private_key, SECP256R1_N) >= 0);
|
||||
|
||||
secp256r1_point_mul_generator(&key->public_key, key->private_key);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_key_set_private_key(SECP256R1_KEY *key, const secp256r1_t private_key)
|
||||
{
|
||||
if (!key || !private_key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_is_zero(private_key) || secp256r1_cmp(private_key, SECP256R1_N) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(key, 0, sizeof(SECP256R1_KEY));
|
||||
|
||||
secp256r1_copy(key->private_key, private_key);
|
||||
secp256r1_point_mul_generator(&key->public_key, key->private_key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_equ(const SECP256R1_KEY *key, const SECP256R1_KEY *pub)
|
||||
{
|
||||
if (secp256r1_point_equ(&key->public_key, &pub->public_key) == 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void secp256r1_key_cleanup(SECP256R1_KEY *key)
|
||||
{
|
||||
if (key) {
|
||||
gmssl_secure_clear(key->private_key, sizeof(secp256r1_t));
|
||||
memset(key, 0, sizeof(SECP256R1_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SM2将这个命名为_to_octets,应该更准确一些
|
||||
int secp256r1_public_key_to_bytes(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if (!key || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (out && *out) {
|
||||
if (secp256r1_point_to_uncompressed_octets(&key->public_key, *out) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*out += 65;
|
||||
}
|
||||
*outlen += 65;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_from_bytes(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
if (!key || !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (*inlen < 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(key, 0, sizeof(SECP256R1_KEY));
|
||||
|
||||
if (secp256r1_point_from_uncompressed_octets(&key->public_key, *in) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*in += 65;
|
||||
*inlen -= 65;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_KEY *key)
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
secp256r1_print(fp, fmt, ind, "X", key->public_key.X);
|
||||
secp256r1_print(fp, fmt, ind, "Y", key->public_key.Y);
|
||||
secp256r1_print(fp, fmt, ind, "Z", key->public_key.Z);
|
||||
|
||||
secp256r1_point_get_xy(&key->public_key, x, y);
|
||||
secp256r1_print(fp, fmt, ind, "x", x);
|
||||
secp256r1_print(fp, fmt, ind, "y", y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_KEY *key)
|
||||
{
|
||||
uint8_t buf[32];
|
||||
|
||||
secp256r1_to_32bytes(key->private_key, buf);
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
if (secp256r1_public_key_print(fp, fmt, ind, "public_key", key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(fp, fmt, ind, "private_key", buf, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
uint8_t octets[65];
|
||||
uint8_t *p = octets;
|
||||
size_t len = 0;
|
||||
|
||||
if (!key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// different from SM2
|
||||
if (out && *out) {
|
||||
if (secp256r1_public_key_to_bytes(key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (asn1_bit_octets_to_der(octets, sizeof(octets), out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_from_der(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if ((ret = asn1_bit_octets_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (secp256r1_public_key_from_bytes(key, &d, &dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (dlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int secp256r1_private_key_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int curve = OID_secp256r1;
|
||||
uint8_t params[64];
|
||||
uint8_t pubkey[128];
|
||||
uint8_t *params_ptr = params;
|
||||
uint8_t *pubkey_ptr = pubkey;
|
||||
size_t params_len = 0;
|
||||
size_t pubkey_len = 0;
|
||||
uint8_t prikey[32];
|
||||
size_t len = 0;
|
||||
|
||||
if (!key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ec_named_curve_to_der(curve, ¶ms_ptr, ¶ms_len) != 1
|
||||
|| secp256r1_public_key_to_der(key, &pubkey_ptr, &pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
// fprintf(stderr, "%s %d: params_len = %zu\n", params_len);
|
||||
// fprintf(stderr, "%s %d: pubkey_len = %zu\n", pubkey_len);
|
||||
secp256r1_to_32bytes(key->private_key, prikey);
|
||||
if (asn1_int_to_der(EC_private_key_version, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(prikey, 32, NULL, &len) != 1
|
||||
|| asn1_explicit_to_der(0, params, params_len, NULL, &len) != 1
|
||||
|| asn1_explicit_to_der(1, pubkey, pubkey_len, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_int_to_der(EC_private_key_version, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(prikey, 32, out, outlen) != 1
|
||||
|| asn1_explicit_to_der(0, params, params_len, out, outlen) != 1
|
||||
|| asn1_explicit_to_der(1, pubkey, pubkey_len, out, outlen) != 1) {
|
||||
gmssl_secure_clear(prikey, 32);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
gmssl_secure_clear(prikey, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_from_der(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
int ver;
|
||||
const uint8_t *prikey;
|
||||
const uint8_t *params;
|
||||
const uint8_t *pubkey;
|
||||
size_t prikey_len, params_len, pubkey_len;
|
||||
int curve;
|
||||
SECP256R1_KEY tmp_key;
|
||||
secp256r1_t private_key;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_int_from_der(&ver, &d, &dlen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1
|
||||
|| asn1_explicit_from_der(0, ¶ms, ¶ms_len, &d, &dlen) != 1
|
||||
|| asn1_explicit_from_der(1, &pubkey, &pubkey_len, &d, &dlen) != 1
|
||||
|| asn1_check(ver == EC_private_key_version) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!params || !pubkey) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// public_key
|
||||
if (ec_named_curve_from_der(&curve, ¶ms, ¶ms_len) != 1
|
||||
|| asn1_check(curve == OID_secp256r1) != 1
|
||||
|| asn1_length_is_zero(params_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_from_der(&tmp_key, &pubkey, &pubkey_len) != 1
|
||||
|| asn1_length_is_zero(pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// private_key
|
||||
if (!prikey || prikey_len != 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_from_32bytes(private_key, prikey);
|
||||
if (secp256r1_key_set_private_key(key, private_key) != 1) {
|
||||
gmssl_secure_clear(private_key, 32);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
gmssl_secure_clear(private_key, 32);
|
||||
|
||||
// check
|
||||
if (secp256r1_public_key_equ(key, &tmp_key) != 1) {
|
||||
secp256r1_key_cleanup(key);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int algor = OID_ec_public_key;
|
||||
int algor_param = OID_secp256r1;
|
||||
size_t len = 0;
|
||||
uint8_t prikey[256];
|
||||
uint8_t *p = prikey;
|
||||
size_t prikey_len = 0;
|
||||
|
||||
if (secp256r1_private_key_to_der(key, &p, &prikey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
//fprintf(stderr, "%s %d: prikey_len = %zu\n", __FILE__, __LINE__, prikey_len);
|
||||
|
||||
if (asn1_int_to_der(PKCS8_private_key_info_version, NULL, &len) != 1
|
||||
|| x509_public_key_algor_to_der(algor, algor_param, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(prikey, prikey_len, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_int_to_der(PKCS8_private_key_info_version, out, outlen) != 1
|
||||
|| x509_public_key_algor_to_der(algor, algor_param, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(prikey, prikey_len, out, outlen) != 1) {
|
||||
memset(prikey, 0, sizeof(prikey));
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(prikey, 0, sizeof(prikey));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_from_der(SECP256R1_KEY *key, const uint8_t **attrs, size_t *attrslen,
|
||||
const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
int version;
|
||||
int algor;
|
||||
int algor_param;
|
||||
const uint8_t *prikey;
|
||||
size_t prikey_len;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_int_from_der(&version, &d, &dlen) != 1
|
||||
|| x509_public_key_algor_from_der(&algor, &algor_param, &d, &dlen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1
|
||||
|| asn1_implicit_set_from_der(0, attrs, attrslen, &d, &dlen) < 0
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_check(version == PKCS8_private_key_info_version) != 1
|
||||
|| asn1_check(algor == OID_ec_public_key) != 1
|
||||
|| asn1_check(algor_param == OID_secp256r1) != 1
|
||||
|| secp256r1_private_key_from_der(key, &prikey, &prikey_len) != 1
|
||||
|| asn1_length_is_zero(prikey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_encrypt_to_der(const SECP256R1_KEY *ec_key, const char *pass,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int ret = -1;
|
||||
uint8_t pkey_info[512];
|
||||
uint8_t *p = pkey_info;
|
||||
size_t pkey_info_len = 0;
|
||||
uint8_t salt[16];
|
||||
int iter = 65536;
|
||||
uint8_t iv[16];
|
||||
uint8_t key[16];
|
||||
SM4_KEY sm4_key;
|
||||
uint8_t enced_pkey_info[sizeof(pkey_info) + 32];
|
||||
size_t enced_pkey_info_len;
|
||||
|
||||
if (!ec_key || !pass || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_info_to_der(ec_key, &p, &pkey_info_len) != 1
|
||||
|| rand_bytes(salt, sizeof(salt)) != 1
|
||||
|| rand_bytes(iv, sizeof(iv)) != 1
|
||||
|| sm3_pbkdf2(pass, strlen(pass), salt, sizeof(salt), iter, sizeof(key), key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
if (pkey_info_len != sizeof(pkey_info)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
*/
|
||||
sm4_set_encrypt_key(&sm4_key, key);
|
||||
if (sm4_cbc_padding_encrypt(
|
||||
&sm4_key, iv, pkey_info, pkey_info_len,
|
||||
enced_pkey_info, &enced_pkey_info_len) != 1
|
||||
|| pkcs8_enced_private_key_info_to_der(
|
||||
salt, sizeof(salt), iter, sizeof(key), OID_hmac_sm3,
|
||||
OID_sm4_cbc, iv, sizeof(iv),
|
||||
enced_pkey_info, enced_pkey_info_len, out, outlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(pkey_info, sizeof(pkey_info));
|
||||
gmssl_secure_clear(key, sizeof(key));
|
||||
gmssl_secure_clear(&sm4_key, sizeof(sm4_key));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_decrypt_from_der(SECP256R1_KEY *ec_key,
|
||||
const uint8_t **attrs, size_t *attrs_len,
|
||||
const char *pass, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret = -1;
|
||||
const uint8_t *salt;
|
||||
size_t saltlen;
|
||||
int iter;
|
||||
int keylen;
|
||||
int prf;
|
||||
int cipher;
|
||||
const uint8_t *iv;
|
||||
size_t ivlen;
|
||||
uint8_t key[16];
|
||||
SM4_KEY sm4_key;
|
||||
const uint8_t *enced_pkey_info;
|
||||
size_t enced_pkey_info_len;
|
||||
uint8_t pkey_info[256];
|
||||
const uint8_t *cp = pkey_info;
|
||||
size_t pkey_info_len;
|
||||
|
||||
if (!ec_key || !attrs || !attrs_len || !pass || !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pkcs8_enced_private_key_info_from_der(&salt, &saltlen, &iter, &keylen, &prf,
|
||||
&cipher, &iv, &ivlen, &enced_pkey_info, &enced_pkey_info_len, in, inlen) != 1
|
||||
|| asn1_check(keylen == -1 || keylen == 16) != 1
|
||||
|| asn1_check(prf == - 1 || prf == OID_hmac_sm3) != 1
|
||||
|| asn1_check(cipher == OID_sm4_cbc) != 1
|
||||
|| asn1_check(ivlen == 16) != 1
|
||||
|| asn1_length_le(enced_pkey_info_len, sizeof(pkey_info)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm3_pbkdf2(pass, strlen(pass), salt, saltlen, iter, sizeof(key), key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
sm4_set_decrypt_key(&sm4_key, key);
|
||||
if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_pkey_info, enced_pkey_info_len,
|
||||
pkey_info, &pkey_info_len) != 1
|
||||
|| secp256r1_private_key_info_from_der(ec_key, attrs, attrs_len, &cp, &pkey_info_len) != 1
|
||||
|| asn1_length_is_zero(pkey_info_len) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(&sm4_key, sizeof(sm4_key));
|
||||
gmssl_secure_clear(key, sizeof(key));
|
||||
gmssl_secure_clear(pkey_info, sizeof(pkey_info));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
|
||||
309
src/tls12_handshake.c
Normal file
309
src/tls12_handshake.c
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm3.h>
|
||||
#include <gmssl/sm4.h>
|
||||
#include <gmssl/pem.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/tls.h>
|
||||
|
||||
|
||||
enum {
|
||||
TLS_state_client_hello,
|
||||
TLS_state_server_hello,
|
||||
TLS_state_server_certificate,
|
||||
TLS_state_server_key_exchange,
|
||||
TLS_state_server_certificate_request,
|
||||
TLS_state_server_hello_done,
|
||||
TLS_state_client_certificate,
|
||||
TLS_state_client_key_exchange,
|
||||
TLS_state_client_certificate_verify,
|
||||
TLS_state_client_change_cipher_spec,
|
||||
TLS_state_client_finished,
|
||||
TLS_state_server_change_cipher_spec,
|
||||
TLS_state_server_finished,
|
||||
};
|
||||
|
||||
static const int tls12_ciphers[] = {
|
||||
TLS_cipher_ecdhe_sm4_cbc_sm3,
|
||||
};
|
||||
|
||||
int tls_send_client_hello(TLS_CONNECT *conn)
|
||||
{
|
||||
const int ec_point_formats[] = { TLS_point_uncompressed };
|
||||
size_t ec_point_formats_cnt = sizeof(ec_point_formats)/sizeof(ec_point_formats[0]);
|
||||
const int supported_groups[] = { TLS_curve_sm2p256v1 };
|
||||
size_t supported_groups_cnt = sizeof(supported_groups)/sizeof(supported_groups[0]);
|
||||
const int signature_algors[] = { TLS_sig_sm2sig_sm3 };
|
||||
size_t signature_algors_cnt = sizeof(signature_algors)/sizeof(signature_algors[0]);
|
||||
|
||||
uint8_t *record;
|
||||
size_t recordlen;
|
||||
uint8_t client_random[32];
|
||||
uint8_t client_exts[TLS_MAX_EXTENSIONS_SIZE];
|
||||
size_t client_exts_len;
|
||||
uint8_t *p;
|
||||
|
||||
record = conn->record;
|
||||
|
||||
tls_record_set_protocol(record, TLS_protocol_tls1);
|
||||
|
||||
sm3_init(&conn->sm3_ctx);
|
||||
if (conn->client_certs_len)
|
||||
sm2_sign_init(&conn->sign_ctx, &conn->sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
|
||||
|
||||
tls_random_generate(client_random);
|
||||
|
||||
p = client_exts;
|
||||
client_exts_len = 0;
|
||||
tls_ec_point_formats_ext_to_bytes(ec_point_formats, ec_point_formats_cnt, &p, &client_exts_len);
|
||||
tls_supported_groups_ext_to_bytes(supported_groups, supported_groups_cnt, &p, &client_exts_len);
|
||||
tls_signature_algorithms_ext_to_bytes(signature_algors, signature_algors_cnt, &p, &client_exts_len);
|
||||
|
||||
if (tls_record_set_handshake_client_hello(conn->record, &recordlen,
|
||||
conn->protocol, client_random, NULL, 0,
|
||||
tls12_ciphers, sizeof(tls12_ciphers)/sizeof(tls12_ciphers[0]),
|
||||
client_exts, client_exts_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_trace("send ClientHello\n");
|
||||
tls12_record_trace(stderr, record, recordlen, 0, 0);
|
||||
if (tls_record_send(record, recordlen, conn->sock) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm3_update(&conn->sm3_ctx, record + 5, recordlen - 5);
|
||||
if (conn->client_certs_len) {
|
||||
sm2_sign_update(&conn->sign_ctx, record + 5, recordlen - 5);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_hello(TLS_CONNECT *conn)
|
||||
{
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
|
||||
tls_trace("recv ServerHello\n");
|
||||
if (tls_record_recv(record, &recordlen, conn->sock) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
tls12_record_trace(stderr, record, recordlen, 0, 0);
|
||||
if (tls_record_protocol(record) != conn->protocol) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 这些值要放在哪儿呢?是否放在CONNECT中
|
||||
int protocol;
|
||||
int cipher_suite;
|
||||
uint8_t server_random[32];
|
||||
const uint8_t *random;
|
||||
const uint8_t *session_id;
|
||||
size_t session_id_len;
|
||||
const uint8_t *server_exts;
|
||||
size_t server_exts_len;
|
||||
|
||||
// 扩展的协商结果,-1 表示服务器不支持该扩展(未给出响应)
|
||||
int ec_point_format = -1;
|
||||
int supported_group = -1;
|
||||
int signature_algor = -1;
|
||||
|
||||
if (tls_record_get_handshake_server_hello(record,
|
||||
&protocol, &random, &session_id, &session_id_len, &cipher_suite,
|
||||
&server_exts, &server_exts_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
if (protocol != conn->protocol) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||
return -1;
|
||||
}
|
||||
// tls12_ciphers 应该改为conn的内部变量
|
||||
if (tls_cipher_suite_in_list(cipher_suite, tls12_ciphers, sizeof(tls12_ciphers)/sizeof(tls12_ciphers[0])) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_handshake_failure);
|
||||
return -1;
|
||||
}
|
||||
if (!server_exts) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
if (tls_process_server_hello_exts(server_exts, server_exts_len, &ec_point_format, &supported_group, &signature_algor) != 1
|
||||
|| ec_point_format < 0
|
||||
|| supported_group < 0
|
||||
|| signature_algor < 0) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(server_random, random, 32);
|
||||
memcpy(conn->session_id, session_id, session_id_len);
|
||||
conn->cipher_suite = cipher_suite;
|
||||
sm3_update(&conn->sm3_ctx, record + 5, recordlen - 5);
|
||||
if (conn->client_certs_len) {
|
||||
sm2_sign_update(&conn->sign_ctx, record + 5, recordlen - 5);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_certificate(TLS_CONNECT *conn)
|
||||
{
|
||||
const int depth = 5;
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
int verify_result;
|
||||
|
||||
// recv ServerCertificate
|
||||
tls_trace("recv ServerCertificate\n");
|
||||
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|
||||
|| tls_record_protocol(record) != conn->protocol) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
tls12_record_trace(stderr, record, recordlen, 0, 0);
|
||||
|
||||
if (tls_record_get_handshake_certificate(record,
|
||||
conn->server_certs, &conn->server_certs_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
sm3_update(&conn->sm3_ctx, record + 5, recordlen - 5);
|
||||
if (conn->client_certs_len)
|
||||
sm2_sign_update(&conn->sign_ctx, record + 5, recordlen - 5);
|
||||
|
||||
// verify ServerCertificate
|
||||
if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
||||
conn->ca_certs, conn->ca_certs_len, depth, &verify_result) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_key_exchange(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_certificate_request(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_hello_done(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_client_certificate(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_client_key_exchange(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_certificate_verify(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_client_finished(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_change_cipher_spec(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_finished(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls12_client_handshake(TLS_CONNECT *conn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (conn->state) {
|
||||
case TLS_state_client_hello:
|
||||
ret = tls_send_client_hello(conn);
|
||||
break;
|
||||
case TLS_state_server_hello:
|
||||
ret = tls_recv_server_hello(conn);
|
||||
break;
|
||||
case TLS_state_server_certificate:
|
||||
ret = tls_recv_server_certificate(conn);
|
||||
break;
|
||||
case TLS_state_server_key_exchange:
|
||||
ret = tls_recv_server_key_exchange(conn);
|
||||
break;
|
||||
case TLS_state_server_certificate_request:
|
||||
ret = tls_recv_server_certificate_request(conn);
|
||||
break;
|
||||
case TLS_state_server_hello_done:
|
||||
ret = tls_recv_server_hello_done(conn);
|
||||
break;
|
||||
case TLS_state_client_certificate:
|
||||
ret = tls_send_client_certificate(conn);
|
||||
break;
|
||||
case TLS_state_client_key_exchange:
|
||||
ret = tls_send_client_key_exchange(conn);
|
||||
break;
|
||||
case TLS_state_client_certificate_verify:
|
||||
ret = tls_send_certificate_verify(conn);
|
||||
case TLS_state_client_change_cipher_spec:
|
||||
break;
|
||||
case TLS_state_client_finished:
|
||||
ret = tls_send_client_finished(conn);
|
||||
break;
|
||||
case TLS_state_server_change_cipher_spec:
|
||||
ret = tls_recv_server_change_cipher_spec(conn);
|
||||
break;
|
||||
case TLS_state_server_finished:
|
||||
ret = tls_recv_server_finished(conn);
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
171
src/x509_key.c
171
src/x509_key.c
@@ -14,7 +14,6 @@
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
@@ -79,13 +78,16 @@ int x509_key_generate(X509_KEY *key, int algor, int algor_param)
|
||||
|
||||
switch (algor) {
|
||||
case OID_ec_public_key:
|
||||
if (algor_param != OID_sm2) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_generate(&key->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
if (algor_param == OID_sm2) {
|
||||
if (sm2_key_generate(&key->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (algor_param == OID_secp256r1) {
|
||||
if (secp256r1_key_generate(&key->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OID_lms_hashsig:
|
||||
@@ -156,7 +158,17 @@ int x509_public_key_print(FILE *fp, int fmt, int ind, const char *label, const X
|
||||
{
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
if (sm2_public_key_print(fp, fmt, ind, label, &key->u.sm2_key) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_public_key_print(fp, fmt, ind, label, &key->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_print(fp, fmt, ind, label, &key->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -208,6 +220,15 @@ int x509_key_set_sm2_key(X509_KEY *x509_key, const SM2_KEY *sm2_key)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_key_set_secp256r1_key(X509_KEY *x509_key, const SECP256R1_KEY *secp256r1_key)
|
||||
{
|
||||
memset(x509_key, 0, sizeof(X509_KEY));
|
||||
x509_key->algor = OID_ec_public_key;
|
||||
x509_key->algor_param = OID_secp256r1;
|
||||
x509_key->u.secp256r1_key = *secp256r1_key;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_key_set_lms_key(X509_KEY *x509_key, const LMS_KEY *lms_key)
|
||||
{
|
||||
memset(x509_key, 0, sizeof(X509_KEY));
|
||||
@@ -288,11 +309,21 @@ int x509_public_key_digest(const X509_KEY *key, uint8_t dgst[32])
|
||||
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
if (sm2_z256_point_to_uncompressed_octets(&key->u.sm2_key.public_key, bits) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_z256_point_to_uncompressed_octets(&key->u.sm2_key.public_key, bits) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
len = 65;
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_to_bytes(&key->u.secp256r1_key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
len = 65;
|
||||
break;
|
||||
case OID_hss_lms_hashsig:
|
||||
if (hss_public_key_to_bytes(&key->u.hss_key, &p, &len) != 1) {
|
||||
@@ -340,7 +371,17 @@ int x509_public_key_equ(const X509_KEY *key, const X509_KEY *pub)
|
||||
}
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
if (sm2_public_key_equ(&key->u.sm2_key, &pub->u.sm2_key) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_public_key_equ(&key->u.sm2_key, &pub->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_equ(&key->u.secp256r1_key, &pub->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -456,11 +497,22 @@ int x509_sign_init(X509_SIGN_CTX *ctx, X509_KEY *key, const char *signer_id, siz
|
||||
ctx->sign_algor = key->algor;
|
||||
break;
|
||||
case OID_ec_public_key:
|
||||
if (sm2_sign_init(&ctx->u.sm2_sign_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_sign_init(&ctx->u.sm2_sign_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (ecdsa_sign_init(&ctx->u.ecdsa_sign_ctx, &key->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_ecdsa_with_sha256;
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
@@ -497,6 +549,12 @@ int x509_sign_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
if (ecdsa_sign_update(&ctx->u.ecdsa_sign_ctx, data, datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -536,6 +594,13 @@ int x509_sign_finish(X509_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
*siglen = ECDSA_SIGNATURE_TYPICAL_SIZE;
|
||||
if (ecdsa_sign_finish_fixlen(&ctx->u.ecdsa_sign_ctx, *siglen, sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -574,17 +639,28 @@ int x509_verify_init(X509_SIGN_CTX *ctx, const X509_KEY *key, const char *signer
|
||||
ctx->sign_algor = key->algor;
|
||||
break;
|
||||
case OID_ec_public_key:
|
||||
if (sm2_verify_init(&ctx->u.sm2_verify_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_verify_init(&ctx->u.sm2_verify_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
if (siglen > sizeof(ctx->sig)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(ctx->sig, sig, siglen);
|
||||
ctx->siglen = siglen;
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (ecdsa_verify_init(&ctx->u.ecdsa_sign_ctx, &key->u.secp256r1_key, sig, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_ecdsa_with_sha256;
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
if (siglen > sizeof(ctx->sig)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(ctx->sig, sig, siglen);
|
||||
ctx->siglen = siglen;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
@@ -620,6 +696,12 @@ int x509_verify_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
if (ecdsa_verify_update(&ctx->u.ecdsa_sign_ctx, data, datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -652,7 +734,13 @@ int x509_verify_finish(X509_SIGN_CTX *ctx)
|
||||
}
|
||||
break;
|
||||
case OID_sm2sign_with_sm3:
|
||||
if ((ret = sm2_verify_update(&ctx->u.sm2_verify_ctx, ctx->sig, ctx->siglen)) < 0) {
|
||||
if ((ret = sm2_verify_finish(&ctx->u.sm2_verify_ctx, ctx->sig, ctx->siglen)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
if ((ret = ecdsa_verify_finish(&ctx->u.ecdsa_sign_ctx)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -698,8 +786,15 @@ int x509_public_key_info_to_der(const X509_KEY *x509_key, uint8_t **out, size_t
|
||||
}
|
||||
break;
|
||||
case OID_ec_public_key:
|
||||
sm2_z256_point_to_uncompressed_octets(&x509_key->u.sm2_key.public_key, p);
|
||||
keylen = 65;
|
||||
if (x509_key->algor_param == OID_sm2) {
|
||||
sm2_z256_point_to_uncompressed_octets(&x509_key->u.sm2_key.public_key, p);
|
||||
keylen = 65;
|
||||
} else if (x509_key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_to_bytes(&x509_key->u.secp256r1_key, &p, &keylen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
@@ -758,15 +853,25 @@ int x509_public_key_info_from_der(X509_KEY *x509_key, const uint8_t **in, size_t
|
||||
|
||||
switch (algor) {
|
||||
case OID_ec_public_key:
|
||||
if (algor_param != OID_sm2) {
|
||||
if (publen != 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_z256_point_from_octets(&x509_key->u.sm2_key.public_key, pub, publen) != 1) {
|
||||
if (algor_param == OID_sm2) {
|
||||
if (sm2_z256_point_from_octets(&x509_key->u.sm2_key.public_key, pub, publen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
publen = 0;
|
||||
} else if (algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_from_bytes(&x509_key->u.secp256r1_key, &pub, &publen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
publen = 0;
|
||||
break;
|
||||
case OID_hss_lms_hashsig:
|
||||
if (hss_public_key_from_bytes(&x509_key->u.hss_key, &pub, &publen) != 1) {
|
||||
@@ -806,6 +911,7 @@ int x509_public_key_info_from_der(X509_KEY *x509_key, const uint8_t **in, size_t
|
||||
return 1;
|
||||
}
|
||||
|
||||
// FIXME: this function can not parse depends on algor_param
|
||||
int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE *fp)
|
||||
{
|
||||
if (!key || !fp) {
|
||||
@@ -821,6 +927,7 @@ int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
// FIXME: secp256r1
|
||||
if (sm2_private_key_info_decrypt_from_pem(&key->u.sm2_key, pass, fp) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -901,8 +1008,12 @@ void x509_key_cleanup(X509_KEY *key)
|
||||
if (key) {
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
//sm2_key_cleanup(&key->u.sm2_key);
|
||||
gmssl_secure_clear(&key->u.sm2_key, sizeof(SM2_KEY));
|
||||
if (key->algor_param == OID_sm2) {
|
||||
//sm2_key_cleanup(&key->u.sm2_key);
|
||||
gmssl_secure_clear(&key->u.sm2_key, sizeof(SM2_KEY));
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
secp256r1_key_cleanup(&key->u.secp256r1_key);
|
||||
}
|
||||
break;
|
||||
case OID_lms_hashsig:
|
||||
lms_key_cleanup(&key->u.lms_key);
|
||||
|
||||
Reference in New Issue
Block a user