mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Add LMS/HSS public key DER encoding
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
|
* Copyright 2014-2025 The GmSSL Project. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
@@ -173,6 +173,8 @@ enum {
|
|||||||
OID_cms_signed_and_enveloped_data,
|
OID_cms_signed_and_enveloped_data,
|
||||||
OID_cms_encrypted_data,
|
OID_cms_encrypted_data,
|
||||||
OID_cms_key_agreement_info,
|
OID_cms_key_agreement_info,
|
||||||
|
|
||||||
|
OID_hss_lms_hashsig, // LMS/HSS public key
|
||||||
};
|
};
|
||||||
|
|
||||||
// {iso(1) org(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
|
// {iso(1) org(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
|
||||||
|
|||||||
@@ -279,18 +279,13 @@ int sm3_hss_verify_update(SM3_HSS_SIGN_CTX *ctx, const uint8_t *data, size_t dat
|
|||||||
int sm3_hss_verify_finish(SM3_HSS_SIGN_CTX *ctx);
|
int sm3_hss_verify_finish(SM3_HSS_SIGN_CTX *ctx);
|
||||||
|
|
||||||
|
|
||||||
/*
|
// X.509 related
|
||||||
from RFC 9708
|
int sm3_hss_public_key_to_der(const SM3_HSS_KEY *key, uint8_t **out, size_t *outlen);
|
||||||
|
int sm3_hss_public_key_from_der(SM3_HSS_KEY *key, const uint8_t **in, size_t *inlen);
|
||||||
id-alg-hss-lms-hashsig OBJECT IDENTIFIER ::= {
|
int sm3_hss_public_key_algor_to_der(uint8_t **out, size_t *outlen);
|
||||||
iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
|
int sm3_hss_public_key_algor_from_der(const uint8_t **in, size_t *inlen);
|
||||||
pkcs-9(9) smime(16) alg(3) 17
|
int sm3_hss_public_key_info_to_der(const SM3_HSS_KEY *key, uint8_t **out, size_t *outlen);
|
||||||
}
|
int sm3_hss_public_key_info_from_der(SM3_HSS_KEY *key, const uint8_t **in, size_t *inlen);
|
||||||
*/
|
|
||||||
#include <gmssl/oid.h>
|
|
||||||
|
|
||||||
#define oid_hss_lms_hashsig oid_pkcs,9,16,3,17
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
118
src/sm3_lms.c
118
src/sm3_lms.c
@@ -12,6 +12,7 @@
|
|||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
#include <gmssl/endian.h>
|
#include <gmssl/endian.h>
|
||||||
#include <gmssl/sm3_lms.h>
|
#include <gmssl/sm3_lms.h>
|
||||||
|
#include <gmssl/x509_alg.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
@@ -1935,3 +1936,120 @@ int sm3_hss_private_key_size(const int *lms_types, size_t levels, size_t *len)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// X.509 related
|
||||||
|
int sm3_hss_public_key_to_der(const SM3_HSS_KEY *key, uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
uint8_t octets[SM3_HSS_PUBLIC_KEY_SIZE];
|
||||||
|
uint8_t *p = octets;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (!key) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_public_key_to_bytes(key, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len != sizeof(octets)) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (asn1_bit_octets_to_der(octets, sizeof(octets), out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm3_hss_public_key_from_der(SM3_HSS_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 (dlen != SM3_HSS_PUBLIC_KEY_SIZE) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_public_key_from_bytes(key, &d, &dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (dlen) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm3_hss_public_key_algor_to_der(uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
if (x509_public_key_algor_to_der(OID_hss_lms_hashsig, OID_undef, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm3_hss_public_key_algor_from_der(const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int oid;
|
||||||
|
int param = OID_undef;
|
||||||
|
|
||||||
|
if ((ret = x509_public_key_algor_from_der(&oid, ¶m, in, inlen)) != 1) {
|
||||||
|
if (ret < 0) error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (oid != OID_hss_lms_hashsig) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// param == 0: parameter is empty
|
||||||
|
// param == 1: parameter is null object
|
||||||
|
// param == other values, x509_public_key_algor_from_der fail
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm3_hss_public_key_info_to_der(const SM3_HSS_KEY *key, uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
if (sm3_hss_public_key_algor_to_der(NULL, &len) != 1
|
||||||
|
|| sm3_hss_public_key_to_der(key, NULL, &len) != 1
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| sm3_hss_public_key_algor_to_der(out, outlen) != 1
|
||||||
|
|| sm3_hss_public_key_to_der(key, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm3_hss_public_key_info_from_der(SM3_HSS_KEY *key, const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const uint8_t *d;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||||
|
if (ret < 0) error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (sm3_hss_public_key_algor_from_der(&d, &dlen) != 1
|
||||||
|
|| sm3_hss_public_key_from_der(key, &d, &dlen) != 1
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
|
* Copyright 2014-2025 The GmSSL Project. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
#include <gmssl/asn1.h>
|
#include <gmssl/asn1.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
#include <gmssl/x509_alg.h>
|
#include <gmssl/x509_alg.h>
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
#include <gmssl/sm3_lms.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static uint32_t oid_sm3[] = { 1,2,156,10197,1,401 };
|
static uint32_t oid_sm3[] = { 1,2,156,10197,1,401 };
|
||||||
static uint32_t oid_md5[] = { 1,2,840,113549,2,5 };
|
static uint32_t oid_md5[] = { 1,2,840,113549,2,5 };
|
||||||
@@ -558,10 +560,22 @@ err:
|
|||||||
|
|
||||||
|
|
||||||
static uint32_t oid_ec_public_key[] = { oid_x9_62,2,1 };
|
static uint32_t oid_ec_public_key[] = { oid_x9_62,2,1 };
|
||||||
|
/*
|
||||||
|
from RFC 9708
|
||||||
|
|
||||||
|
id-alg-hss-lms-hashsig OBJECT IDENTIFIER ::= {
|
||||||
|
iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
|
||||||
|
pkcs-9(9) smime(16) alg(3) 17
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
static uint32_t oid_hss_lms_hashsig[] = { oid_pkcs,9,16,3,17 };
|
||||||
|
|
||||||
static const ASN1_OID_INFO x509_public_key_algors[] = {
|
static const ASN1_OID_INFO x509_public_key_algors[] = {
|
||||||
{ OID_ec_public_key, "ecPublicKey", oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), 0, "X9.62 ecPublicKey" },
|
{ OID_ec_public_key, "ecPublicKey", oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), 0, "X9.62 ecPublicKey" },
|
||||||
{ OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), 0, "RSAEncryption" },
|
{ OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), 0, "RSAEncryption" },
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
{ OID_hss_lms_hashsig, "hsslmsHashSig", oid_hss_lms_hashsig, sizeof(oid_hss_lms_hashsig)/sizeof(int), 0, "HSS/LMS HashSig" },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int x509_public_key_algors_count =
|
static const int x509_public_key_algors_count =
|
||||||
@@ -612,6 +626,18 @@ int x509_public_key_algor_to_der(int oid, int curve_or_null, uint8_t **out, size
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
case OID_hss_lms_hashsig:
|
||||||
|
if (asn1_object_identifier_to_der(oid_hss_lms_hashsig, sizeof(oid_hss_lms_hashsig)/sizeof(int), NULL, &len) != 1
|
||||||
|
|| asn1_null_to_der(NULL, &len) != 1
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_object_identifier_to_der(oid_hss_lms_hashsig, sizeof(oid_hss_lms_hashsig)/sizeof(int), out, outlen) != 1
|
||||||
|
|| asn1_null_to_der(out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -646,6 +672,9 @@ int x509_public_key_algor_from_der(int *oid , int *curve_or_null, const uint8_t
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OID_rsa_encryption:
|
case OID_rsa_encryption:
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
case OID_hss_lms_hashsig:
|
||||||
|
#endif
|
||||||
if ((*curve_or_null = asn1_null_from_der(&d, &dlen)) < 0
|
if ((*curve_or_null = asn1_null_from_der(&d, &dlen)) < 0
|
||||||
|| asn1_length_is_zero(dlen) != 1) {
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -676,6 +705,9 @@ int x509_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, c
|
|||||||
format_print(fp, fmt, ind, "namedCurve: %s\n", ec_named_curve_name(val));
|
format_print(fp, fmt, ind, "namedCurve: %s\n", ec_named_curve_name(val));
|
||||||
break;
|
break;
|
||||||
case OID_rsa_encryption:
|
case OID_rsa_encryption:
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
case OID_hss_lms_hashsig:
|
||||||
|
#endif
|
||||||
if ((val = asn1_null_from_der(&d, &dlen)) < 0) goto err;
|
if ((val = asn1_null_from_der(&d, &dlen)) < 0) goto err;
|
||||||
else if (val) format_print(fp, fmt, ind, "parameters: %s\n", asn1_null_name());
|
else if (val) format_print(fp, fmt, ind, "parameters: %s\n", asn1_null_name());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -875,6 +875,79 @@ static int test_sm3_hss_sign(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_public_key_algor(void)
|
||||||
|
{
|
||||||
|
int lms_types[] = {
|
||||||
|
LMS_HASH256_M32_H5
|
||||||
|
};
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
uint8_t buf[512];
|
||||||
|
const uint8_t *cp;
|
||||||
|
uint8_t *p;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types, sizeof(lms_types)/sizeof(lms_types[0])) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = p = buf;
|
||||||
|
len = 0;
|
||||||
|
if (sm3_hss_public_key_to_der(&key, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(&key, 0, sizeof(SM3_HSS_KEY));
|
||||||
|
if (sm3_hss_public_key_from_der(&key, &cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cp = p = buf;
|
||||||
|
len = 0;
|
||||||
|
if (sm3_hss_public_key_algor_to_der(&p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_public_key_algor_from_der(&cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cp = p = buf;
|
||||||
|
len = 0;
|
||||||
|
if (sm3_hss_public_key_info_to_der(&key, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(&key, 0, sizeof(SM3_HSS_KEY));
|
||||||
|
if (sm3_hss_public_key_info_from_der(&key, &cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_SM3_LMS_CROSSCHECK) && defined(ENABLE_SHA2)
|
#if defined(ENABLE_SM3_LMS_CROSSCHECK) && defined(ENABLE_SHA2)
|
||||||
@@ -894,6 +967,7 @@ int main(void)
|
|||||||
if (test_sm3_hss_sign_level1() != 1) goto err;
|
if (test_sm3_hss_sign_level1() != 1) goto err;
|
||||||
if (test_sm3_hss_sign_level2() != 1) goto err;
|
if (test_sm3_hss_sign_level2() != 1) goto err;
|
||||||
if (test_sm3_hss_sign() != 1) goto err;
|
if (test_sm3_hss_sign() != 1) goto err;
|
||||||
|
if (test_sm3_hss_public_key_algor() != 1) goto err;
|
||||||
|
|
||||||
printf("%s all tests passed\n", __FILE__);
|
printf("%s all tests passed\n", __FILE__);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user