mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-19 19:33:38 +08:00
246 lines
6.5 KiB
C
246 lines
6.5 KiB
C
/*
|
|
* Copyright 2014-2021 The GmSSL Project Authors. 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.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <gmssl/sm2.h>
|
|
#include <gmssl/sm3.h>
|
|
#include <gmssl/error.h>
|
|
#include "endian.h"
|
|
|
|
|
|
#define SM2_SIGNATURE_MAX_DER_SIZE 77
|
|
|
|
int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *der, size_t *derlen)
|
|
{
|
|
SM2_SIGNATURE sig;
|
|
uint8_t *p = der;
|
|
size_t len = 0;
|
|
|
|
if (!der && derlen) {
|
|
*derlen = SM2_SIGNATURE_MAX_DER_SIZE;
|
|
return 1;
|
|
}
|
|
if (!key || !der || !derlen) {
|
|
return -1;
|
|
}
|
|
|
|
sm2_do_sign(key, dgst, &sig);
|
|
sm2_signature_to_der(&sig, &p, &len);
|
|
*derlen = len;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *der, size_t derlen)
|
|
{
|
|
int ret;
|
|
SM2_SIGNATURE sig;
|
|
const uint8_t *p = der;
|
|
size_t len = derlen;
|
|
|
|
if (!key || !der || !derlen) {
|
|
error_print();
|
|
return -1;
|
|
}
|
|
if (sm2_signature_from_der(&sig, &p, &len) < 0
|
|
|| len > 0) {
|
|
error_print();
|
|
return -2;
|
|
}
|
|
if ((ret = sm2_do_verify(key, dgst, &sig)) != 1) {
|
|
error_print();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
|
{
|
|
size_t clen = SM2_CIPHERTEXT_SIZE(inlen);
|
|
size_t cbuf[clen];
|
|
SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)cbuf;
|
|
|
|
sm2_do_encrypt(key, in, inlen, c);
|
|
|
|
*outlen = 0;
|
|
sm2_ciphertext_to_der(c, &out, outlen);
|
|
return 1;
|
|
}
|
|
|
|
int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
|
{
|
|
size_t cbuf[inlen];
|
|
SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)cbuf;
|
|
|
|
sm2_ciphertext_from_der(c, &in, &inlen); // FIXME: 检查是否有剩余长度
|
|
sm2_do_decrypt(key, c, out, outlen);
|
|
return 1;
|
|
}
|
|
|
|
extern void sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks);
|
|
|
|
int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id)
|
|
{
|
|
uint8_t zin[] = {
|
|
0x00, 0x80,
|
|
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
|
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
|
0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
|
|
0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34,
|
|
0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7,
|
|
0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92,
|
|
0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93,
|
|
0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19,
|
|
0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94,
|
|
0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1,
|
|
0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7,
|
|
0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C,
|
|
0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53,
|
|
0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40,
|
|
0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x06, 0x90,
|
|
};
|
|
|
|
if (!id || strcmp(id, "1234567812345678")) {
|
|
uint32_t digest[8] = {
|
|
0xadadedb5U, 0x0446043fU, 0x08a87aceU, 0xe86d2243U,
|
|
0x8e232383U, 0xbfc81fe2U, 0xcf9117c8U, 0x4707011dU,
|
|
};
|
|
memcpy(&zin[128], pub->x, 32);
|
|
memcpy(&zin[160], pub->y, 32);
|
|
sm3_compress_blocks(digest, zin, 2);
|
|
PUTU32(z , digest[0]);
|
|
PUTU32(z + 4, digest[1]);
|
|
PUTU32(z + 8, digest[2]);
|
|
PUTU32(z + 12, digest[3]);
|
|
PUTU32(z + 16, digest[4]);
|
|
PUTU32(z + 20, digest[5]);
|
|
PUTU32(z + 24, digest[6]);
|
|
PUTU32(z + 28, digest[7]);
|
|
|
|
} else {
|
|
SM3_CTX ctx;
|
|
uint8_t idbits[2];
|
|
size_t len;
|
|
|
|
len = strlen(id);
|
|
idbits[0] = (uint8_t)(len >> 5);
|
|
idbits[1] = (uint8_t)(len << 3);
|
|
|
|
sm3_init(&ctx);
|
|
sm3_update(&ctx, idbits, 2);
|
|
sm3_update(&ctx, (uint8_t *)id, len);
|
|
sm3_update(&ctx, zin + 18, 128);
|
|
sm3_update(&ctx, pub->x, 32);
|
|
sm3_update(&ctx, pub->y, 32);
|
|
sm3_finish(&ctx, z);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id)
|
|
{
|
|
uint8_t z[32];
|
|
if (!ctx || !key || !id || strlen(id) > SM2_MAX_ID_SIZE) {
|
|
return -1;
|
|
}
|
|
sm2_compute_z(z, &key->public_key, id);
|
|
|
|
sm3_init(&ctx->sm3_ctx);
|
|
sm3_update(&ctx->sm3_ctx, z, 32);
|
|
memcpy(&ctx->key, key, sizeof(SM2_KEY));
|
|
return 1;
|
|
}
|
|
|
|
int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
|
{
|
|
sm3_update(&ctx->sm3_ctx, data, datalen);
|
|
return 1;
|
|
}
|
|
|
|
int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
|
{
|
|
uint8_t dgst[32];
|
|
sm3_finish(&ctx->sm3_ctx, dgst);
|
|
sm2_sign(&ctx->key, dgst, sig, siglen);
|
|
return 1;
|
|
}
|
|
|
|
int sm2_sign_resume(SM2_SIGN_CTX *ctx)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id)
|
|
{
|
|
uint8_t z[32];
|
|
if (!ctx || !key || !id || strlen(id) > SM2_MAX_ID_SIZE) {
|
|
return -1;
|
|
}
|
|
sm2_compute_z(z, &key->public_key, id);
|
|
sm3_init(&ctx->sm3_ctx);
|
|
sm3_update(&ctx->sm3_ctx, z, 32);
|
|
memcpy(&ctx->key, key, sizeof(SM2_KEY));
|
|
return 1;
|
|
}
|
|
|
|
int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
|
{
|
|
sm3_update(&ctx->sm3_ctx, data, datalen);
|
|
return 1;
|
|
}
|
|
|
|
int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen)
|
|
{
|
|
int ret;
|
|
uint8_t dgst[32];
|
|
sm3_finish(&ctx->sm3_ctx, dgst);
|
|
ret = sm2_verify(&ctx->key, dgst, sig, siglen);
|
|
return ret;
|
|
}
|
|
|
|
int sm2_set_private_key(SM2_KEY *key, const uint8_t private_key[32])
|
|
{
|
|
memcpy(&key->private_key, private_key, 32);
|
|
return 1;
|
|
}
|
|
|
|
// FIXME: 检查公钥是否正确
|
|
int sm2_set_public_key(SM2_KEY *key, const uint8_t public_key[64])
|
|
{
|
|
memcpy(&key->public_key, public_key, 64);
|
|
return 1;
|
|
}
|