mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-09-30 17:23:41 +08:00
More tests
This commit is contained in:
201
CMakeLists.txt
201
CMakeLists.txt
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(GmSSL)
|
||||
|
||||
set(CMAKE_MACOSX_RPATH 1)
|
||||
@@ -8,82 +8,66 @@ SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||
include_directories(include)
|
||||
|
||||
add_library(
|
||||
gmssl
|
||||
gmssl
|
||||
|
||||
SHARED
|
||||
|
||||
src/hex.c
|
||||
src/debug.c
|
||||
src/rand.c
|
||||
|
||||
# default sm algors
|
||||
src/sm2_algo.c
|
||||
src/sm2_lib.c
|
||||
src/sm2_asn1.c
|
||||
src/sm2_prn.c
|
||||
src/sm3.c
|
||||
src/sm3_hmac.c
|
||||
src/sm4_common.c
|
||||
src/sm4_setkey.c
|
||||
src/sm4_enc.c
|
||||
src/sm4_modes.c
|
||||
|
||||
# optional sm algors
|
||||
src/sm9_math.c
|
||||
src/zuc_core.c
|
||||
src/zuc_eea.c
|
||||
src/zuc_eia.c
|
||||
|
||||
# optional nist algors
|
||||
src/aes.c
|
||||
src/aes_modes.c
|
||||
src/chacha20.c
|
||||
src/sha256.c
|
||||
src/sha512.c
|
||||
|
||||
# legacy algors
|
||||
src/rc4.c
|
||||
src/des.c
|
||||
src/md5.c
|
||||
src/sha1.c
|
||||
|
||||
# schemes
|
||||
src/hash_drbg.c
|
||||
src/hmac.c
|
||||
|
||||
# abstract
|
||||
src/digest.c
|
||||
src/block_cipher.c
|
||||
|
||||
# pkix
|
||||
src/asn1.c
|
||||
src/base64.c
|
||||
src/pem.c
|
||||
src/pbkdf2.c
|
||||
src/pkcs8.c
|
||||
|
||||
src/x509_str.c
|
||||
src/x509_alg.c
|
||||
src/x509_oid.c
|
||||
src/x509_cer.c
|
||||
src/x509_ext.c
|
||||
src/x509_req.c
|
||||
src/x509_crl.c
|
||||
|
||||
src/cms.c
|
||||
|
||||
# for tls 1.3
|
||||
src/hkdf.c
|
||||
src/gf128.c
|
||||
src/gcm.c
|
||||
|
||||
# ssl/tls/tlcp
|
||||
#src/tls.c
|
||||
#src/tls_trace.c
|
||||
#src/tls12.c
|
||||
#src/tlcp.c
|
||||
#src/tls13.c
|
||||
SHARED
|
||||
|
||||
src/aes.c
|
||||
src/aes_modes.c
|
||||
src/asn1.c
|
||||
src/base64.c
|
||||
src/block_cipher.c
|
||||
src/chacha20.c
|
||||
src/cms.c
|
||||
src/debug.c
|
||||
src/des.c
|
||||
src/digest.c
|
||||
src/ec.c
|
||||
src/gcm.c
|
||||
src/gf128.c
|
||||
src/hash_drbg.c
|
||||
src/hex.c
|
||||
src/hkdf.c
|
||||
src/hmac.c
|
||||
src/md5.c
|
||||
src/pbkdf2.c
|
||||
src/pem.c
|
||||
src/pkcs8.c
|
||||
src/rand.c
|
||||
src/rc4.c
|
||||
src/rsa.c
|
||||
src/sha1.c
|
||||
src/sha256.c
|
||||
src/sha512.c
|
||||
src/sm2_algo.c
|
||||
src/sm2_asn1.c
|
||||
src/sm2_lib.c
|
||||
src/sm2_prn.c
|
||||
src/sm3.c
|
||||
src/sm3_hmac.c
|
||||
src/sm4_common.c
|
||||
src/sm4_enc.c
|
||||
src/sm4_modes.c
|
||||
src/sm4_setkey.c
|
||||
# src/sm9_keygen.c
|
||||
# src/sm9_math.c
|
||||
# src/sm9_sign.c
|
||||
src/tlcp.c
|
||||
src/tls.c
|
||||
src/tls12.c
|
||||
src/tls13.c
|
||||
src/tls_trace.c
|
||||
src/version.c
|
||||
src/x509_alg.c
|
||||
src/x509_cer.c
|
||||
src/x509_crl.c
|
||||
src/x509_ext.c
|
||||
src/x509_oid.c
|
||||
src/x509_req.c
|
||||
src/x509_str.c
|
||||
src/zuc_core.c
|
||||
src/zuc_eea.c
|
||||
src/zuc_eia.c
|
||||
)
|
||||
|
||||
SET_TARGET_PROPERTIES(gmssl PROPERTIES VERSION 3.0 SOVERSION 3)
|
||||
@@ -92,47 +76,44 @@ SET_TARGET_PROPERTIES(gmssl PROPERTIES VERSION 3.0 SOVERSION 3)
|
||||
# tools
|
||||
|
||||
add_executable (sm2keygen tools/sm2keygen.c)
|
||||
target_link_libraries (sm2keygen LINK_PUBLIC gmssl)
|
||||
add_executable (sm2sign tools/sm2sign.c)
|
||||
target_link_libraries (sm2sign LINK_PUBLIC gmssl)
|
||||
add_executable (sm2verify tools/sm2verify.c)
|
||||
target_link_libraries (sm2verify LINK_PUBLIC gmssl)
|
||||
add_executable (sm2encrypt tools/sm2encrypt.c)
|
||||
target_link_libraries (sm2encrypt LINK_PUBLIC gmssl)
|
||||
add_executable (sm2decrypt tools/sm2decrypt.c)
|
||||
target_link_libraries (sm2decrypt LINK_PUBLIC gmssl)
|
||||
|
||||
add_executable (sm3 tools/sm3.c)
|
||||
target_link_libraries (sm3 LINK_PUBLIC gmssl)
|
||||
add_executable (sm3hmac tools/sm3hmac.c)
|
||||
target_link_libraries (sm3hmac LINK_PUBLIC gmssl)
|
||||
|
||||
add_executable (reqgen tools/reqgen.c)
|
||||
target_link_libraries (reqgen LINK_PUBLIC gmssl)
|
||||
add_executable (reqparse tools/reqparse.c)
|
||||
target_link_libraries (reqparse LINK_PUBLIC gmssl)
|
||||
|
||||
add_executable (certgen tools/certgen.c)
|
||||
target_link_libraries (certgen LINK_PUBLIC gmssl)
|
||||
add_executable (certparse tools/certparse.c)
|
||||
target_link_libraries (certparse LINK_PUBLIC gmssl)
|
||||
add_executable (certverify tools/certverify.c)
|
||||
add_executable (reqsign tools/reqsign.c)
|
||||
add_executable (tlcp_client tools/tlcp_client.c)
|
||||
add_executable (tlcp_server tools/tlcp_server.c)
|
||||
add_executable (tls12_client tools/tls12_client.c)
|
||||
add_executable (tls12_server tools/tls12_server.c)
|
||||
add_executable (tls13_client tools/tls13_client.c)
|
||||
add_executable (tls13_server tools/tls13_server.c)
|
||||
|
||||
target_link_libraries (sm2keygen LINK_PUBLIC gmssl)
|
||||
target_link_libraries (sm2sign LINK_PUBLIC gmssl)
|
||||
target_link_libraries (sm2verify LINK_PUBLIC gmssl)
|
||||
target_link_libraries (sm2encrypt LINK_PUBLIC gmssl)
|
||||
target_link_libraries (sm2decrypt LINK_PUBLIC gmssl)
|
||||
target_link_libraries (sm3 LINK_PUBLIC gmssl)
|
||||
target_link_libraries (sm3hmac LINK_PUBLIC gmssl)
|
||||
target_link_libraries (reqgen LINK_PUBLIC gmssl)
|
||||
target_link_libraries (reqparse LINK_PUBLIC gmssl)
|
||||
target_link_libraries (reqsign LINK_PUBLIC gmssl)
|
||||
target_link_libraries (certgen LINK_PUBLIC gmssl)
|
||||
target_link_libraries (certparse LINK_PUBLIC gmssl)
|
||||
target_link_libraries (certverify LINK_PUBLIC gmssl)
|
||||
|
||||
#add_executable (tlcp_client tools/tlcp_client.c)
|
||||
#target_link_libraries (tlcp_client LINK_PUBLIC gmssl)
|
||||
#add_executable (tlcp_server tools/tlcp_server.c)
|
||||
#target_link_libraries (tlcp_server LINK_PUBLIC gmssl)
|
||||
#add_executable (tls12_client tools/tls12_client.c)
|
||||
#target_link_libraries (tls12_client LINK_PUBLIC gmssl)
|
||||
#add_executable (tls12_server tools/tls12_server.c)
|
||||
#target_link_libraries (tls12_server LINK_PUBLIC gmssl)
|
||||
#add_executable (tls13_client tools/tls13_client.c)
|
||||
#target_link_libraries (tls13_client LINK_PUBLIC gmssl)
|
||||
#add_executable (tls13_server tools/tls13_server.c)
|
||||
#target_link_libraries (tls13_server LINK_PUBLIC gmssl)
|
||||
|
||||
|
||||
target_link_libraries (tlcp_client LINK_PUBLIC gmssl)
|
||||
target_link_libraries (tlcp_server LINK_PUBLIC gmssl)
|
||||
target_link_libraries (tls12_client LINK_PUBLIC gmssl)
|
||||
target_link_libraries (tls12_server LINK_PUBLIC gmssl)
|
||||
target_link_libraries (tls13_client LINK_PUBLIC gmssl)
|
||||
target_link_libraries (tls13_server LINK_PUBLIC gmssl)
|
||||
|
||||
# tests
|
||||
enable_testing()
|
||||
@@ -239,6 +220,11 @@ target_link_libraries (x509_exttest LINK_PUBLIC gmssl)
|
||||
add_executable(zuctest tests/zuctest.c)
|
||||
target_link_libraries (zuctest LINK_PUBLIC gmssl)
|
||||
|
||||
add_executable(tlstest tests/tlstest.c)
|
||||
target_link_libraries (tlstest LINK_PUBLIC gmssl)
|
||||
|
||||
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME aes COMMAND aestest)
|
||||
add_test(NAME asn1 COMMAND asn1test)
|
||||
@@ -268,7 +254,7 @@ add_test(NAME sha512 COMMAND sha512test)
|
||||
add_test(NAME sm2 COMMAND sm2test)
|
||||
add_test(NAME sm3 COMMAND sm3test)
|
||||
add_test(NAME sm4 COMMAND sm4test)
|
||||
#add_test(NAME tls COMMAND tlstest)
|
||||
add_test(NAME tls COMMAND tlstest)
|
||||
add_test(NAME x509 COMMAND x509test)
|
||||
add_test(NAME x509_oid COMMAND x509_oidtest)
|
||||
add_test(NAME x509_alg COMMAND x509_algtest)
|
||||
@@ -279,8 +265,9 @@ add_test(NAME x509_ext COMMAND x509_exttest)
|
||||
add_test(NAME zuc COMMAND zuctest)
|
||||
|
||||
|
||||
INSTALL(TARGETS certparse sm3 sm2keygen sm2sign sm2verify sm2encrypt sm2decrypt RUNTIME DESTINATION bin)
|
||||
#INSTALL(TARGETS certparse certgen certverify reqgen tlcp_client tlcp_server tls12_client tls12_server tls13_client tls13_server RUNTIME DESTINATION bin)
|
||||
INSTALL(TARGETS sm3 sm3hmac sm2keygen sm2sign sm2verify sm2encrypt sm2decrypt RUNTIME DESTINATION bin)
|
||||
INSTALL(TARGETS certparse certgen certverify reqgen reqparse reqsign RUNTIME DESTINATION bin)
|
||||
INSTALL(TARGETS tlcp_client tlcp_server tls12_client tls12_server tls13_client tls13_server RUNTIME DESTINATION bin)
|
||||
INSTALL(TARGETS gmssl LIBRARY DESTINATION lib)
|
||||
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/gmssl DESTINATION include)
|
||||
|
||||
|
||||
13
README.md
13
README.md
@@ -2,6 +2,19 @@
|
||||
|
||||
GmSSL的2.x版本的开发始于2016年,目前主分支在功能上实现了对主要国密算法、标准和协议的覆盖,并成功应用于多种互联网场景中。但是随着GmSSL在物联网、区块链等新场景中的应用,及在密码产品合规检测过程中的实践,我们发现应用对GmSSL提出了一些新的需求。由于很难在基于OpenSSL的GmSSL 2.x版本上满足新需求,因此我们重新设计了GmSSL的架构,GmSSL也迎来第三个大版本——GmSSL 3.0。
|
||||
|
||||
## 编译与安装
|
||||
|
||||
GmSSL 3.0 采用了cmake构建系统。下载源代码后将其解压缩,进入源码目录,执行:
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
make test
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## 主要新特性
|
||||
|
||||
* 超轻量:GmSSL 3.0大幅度降低了内存需求和二进制代码体积,不依赖动态内存,可以用于无操作系统的低功耗嵌入式环境(MCU、SOC等),开发者也可以更容易地将国密算法和SSL协议嵌入到现有的项目中。
|
||||
|
||||
@@ -85,23 +85,23 @@ enum ASN1_TAG {
|
||||
ASN1_TAG_ObjectDescriptor = 7,
|
||||
ASN1_TAG_EXTERNAL = 8,
|
||||
ASN1_TAG_REAL = 9,
|
||||
ASN1_TAG_ENUMERATED = 10,
|
||||
ASN1_TAG_EMBEDDED = 11,
|
||||
ASN1_TAG_UTF8String = 12,
|
||||
ASN1_TAG_RELATIVE_OID = 13,
|
||||
ASN1_TAG_NumericString = 18,
|
||||
ASN1_TAG_PrintableString = 19, // printable subset of ascii
|
||||
ASN1_TAG_TeletexString = 20, // T61String
|
||||
ASN1_TAG_VideotexString = 21,
|
||||
ASN1_TAG_IA5String = 22, // 7-bit ascii
|
||||
ASN1_TAG_UTCTime = 23,
|
||||
ASN1_TAG_GeneralizedTime = 24,
|
||||
ASN1_TAG_GraphicString = 25,
|
||||
ASN1_TAG_VisibleString = 26,
|
||||
ASN1_TAG_GeneralString = 27,
|
||||
ASN1_TAG_UniversalString = 28,
|
||||
ASN1_TAG_CHARACTER_STRING = 29,
|
||||
ASN1_TAG_BMPString = 30, // 2-byte unicode with zeros
|
||||
ASN1_TAG_ENUMERATED = 10, // 0x0A
|
||||
ASN1_TAG_EMBEDDED = 11, // 0x0B
|
||||
ASN1_TAG_UTF8String = 12, // 0x0C
|
||||
ASN1_TAG_RELATIVE_OID = 13, // 0x0D
|
||||
ASN1_TAG_NumericString = 18, // 0x12
|
||||
ASN1_TAG_PrintableString = 19, // 0x13, printable subset of ascii
|
||||
ASN1_TAG_TeletexString = 20, // 0x14, T61String
|
||||
ASN1_TAG_VideotexString = 21, // 0x15
|
||||
ASN1_TAG_IA5String = 22, // 0x16, 7-bit ascii
|
||||
ASN1_TAG_UTCTime = 23, // 0x17
|
||||
ASN1_TAG_GeneralizedTime = 24, // 0x18
|
||||
ASN1_TAG_GraphicString = 25, // 0x19
|
||||
ASN1_TAG_VisibleString = 26, // 0x20
|
||||
ASN1_TAG_GeneralString = 27, // 0x21
|
||||
ASN1_TAG_UniversalString = 28, // 0x22
|
||||
ASN1_TAG_CHARACTER_STRING = 29, // 0x23
|
||||
ASN1_TAG_BMPString = 30, // 0x24, 2-byte unicode with zeros
|
||||
ASN1_TAG_SEQUENCE = 0x30,
|
||||
ASN1_TAG_SET = 0x31,
|
||||
ASN1_TAG_EXPLICIT = 0xa0,
|
||||
@@ -126,6 +126,8 @@ int asn1_any_type_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint
|
||||
int asn1_any_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen); // 调用方应保证a,alen为TLV
|
||||
int asn1_any_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen); // 检查输入为TLV
|
||||
|
||||
const char *asn1_boolean_name(int val);
|
||||
int asn1_boolean_from_name(int *val, const char *name);
|
||||
int asn1_boolean_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen);
|
||||
int asn1_boolean_from_der_ex(int tag, int *val, const uint8_t **in, size_t *inlen);
|
||||
#define asn1_boolean_to_der(val,out,outlen) asn1_boolean_to_der_ex(ASN1_TAG_BOOLEAN,val,out,outlen)
|
||||
@@ -182,6 +184,7 @@ int asn1_bits_print(FILE *fp, int fmt, int ind, const char *label, const char **
|
||||
#define asn1_implicit_octet_string_to_der(i,d,dlen,out,outlen) asn1_type_to_der(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen)
|
||||
#define asn1_implicit_octet_string_from_der(i,d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen)
|
||||
|
||||
const char *asn1_null_name(void);
|
||||
int asn1_null_to_der(uint8_t **out, size_t *outlen);
|
||||
int asn1_null_from_der(const uint8_t **in, size_t *inlen);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
curve:
|
||||
NamedCurve:
|
||||
OID_sm2
|
||||
OID_prime192v1
|
||||
OID_prime256v1
|
||||
@@ -71,13 +71,30 @@ curve:
|
||||
OID_secp384r1
|
||||
OID_secp521r1
|
||||
*/
|
||||
const char *ec_curve_name(int curve);
|
||||
int ec_curve_from_name(const char *name);
|
||||
const char *ec_named_curve_name(int curve);
|
||||
int ec_named_curve_from_name(const char *name);
|
||||
int ec_named_curve_to_der(int curve, uint8_t **out, size_t *outlen);
|
||||
int ec_named_curve_from_der(int *curve, const uint8_t **in, size_t *inlen);
|
||||
|
||||
int ec_public_key_algor_to_der(int curve, uint8_t **out, size_t *outlen);
|
||||
int ec_public_key_algor_from_der(int *curve, const uint8_t **in, size_t *inlen);
|
||||
int ec_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
/*
|
||||
ECPoint ::= OCTET STRING -- uncompressed point
|
||||
*/
|
||||
int ec_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
|
||||
/*
|
||||
ECPrivateKey ::= SEQUENCE {
|
||||
version INTEGER, -- value MUST be (1)
|
||||
privateKey OCTET STRING, -- big endian encoding of integer
|
||||
parameters [0] EXPLICIT OBJECT IDENTIFIER OPTIONAL, -- namedCurve
|
||||
publicKey [1] EXPLICIT BIT STRING OPTIONAL -- ECPoint
|
||||
}
|
||||
*/
|
||||
|
||||
enum {
|
||||
EC_private_key_version = 1,
|
||||
};
|
||||
|
||||
int ec_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -76,11 +76,15 @@ void print_der(const uint8_t *in, size_t inlen);
|
||||
void print_bytes(const uint8_t *in, size_t inlen);
|
||||
void print_nodes(const uint32_t *in, size_t inlen);
|
||||
|
||||
#define FMT_CARRAY 0x80
|
||||
|
||||
|
||||
int format_print(FILE *fp, int format, int indent, const char *str, ...);
|
||||
int format_bytes(FILE *fp, int format, int indent, const char *str, const uint8_t *data, size_t datalen);
|
||||
int format_string(FILE *fp, int format, int indent, const char *str, const uint8_t *data, size_t datalen);
|
||||
|
||||
|
||||
|
||||
//int tls_trace(int format, int indent, const char *str, ...);
|
||||
|
||||
|
||||
|
||||
@@ -120,6 +120,9 @@ enum {
|
||||
OID_ce_crl_distribution_points,
|
||||
OID_ce_inhibit_any_policy,
|
||||
OID_ce_freshest_crl,
|
||||
OID_netscape_cert_comment,
|
||||
OID_cert_authority_info_access,
|
||||
OID_ct_precertificate_scts,
|
||||
|
||||
// CRL Extensions
|
||||
//OID_ce_authority_key_identifier,
|
||||
@@ -237,6 +240,12 @@ id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13}
|
||||
#define oid_pkcs5 oid_pkcs,5
|
||||
|
||||
|
||||
#define oid_cnt(nodes) (sizeof(nodes)/sizeof(int))
|
||||
|
||||
|
||||
#define oid_x9_62 1,2,840,10045
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,11 @@ extern "C" {
|
||||
|
||||
|
||||
int pbkdf2_genkey(const DIGEST *digest,
|
||||
const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, size_t count,
|
||||
const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, size_t iter,
|
||||
size_t outlen, uint8_t *out);
|
||||
|
||||
int pbkdf2_hmac_sm3_genkey(
|
||||
const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, size_t iter,
|
||||
size_t outlen, uint8_t *out);
|
||||
|
||||
|
||||
|
||||
94
include/gmssl/rsa.h
Normal file
94
include/gmssl/rsa.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2014 - 2021 The GmSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project.
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* 4. The name "GmSSL Project" must not be used to endorse or promote
|
||||
* products derived from this software without prior written
|
||||
* permission. For written permission, please contact
|
||||
* guanzhi1980@gmail.com.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "GmSSL"
|
||||
* nor may "GmSSL" appear in their names without prior written
|
||||
* permission of the GmSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GMSSL_RSA_H
|
||||
#define GMSSL_RSA_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
RSAPublicKey ::= SEQUENCE {
|
||||
modulus INTEGER, -- n
|
||||
publicExponent INTEGER -- e
|
||||
}
|
||||
|
||||
RSAPrivateKey ::= SEQUENCE {
|
||||
version INTEGER, -- 0
|
||||
modulus INTEGER, -- n
|
||||
publicExponent INTEGER, -- e
|
||||
privateExponent INTEGER, -- d
|
||||
prime1 INTEGER, -- p
|
||||
prime2 INTEGER, -- q
|
||||
exponent1 INTEGER, -- d mod (p-1)
|
||||
exponent2 INTEGER, -- d mod (q-1)
|
||||
coefficient INTEGER -- q^-1 mod p
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
int rsa_public_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) 2014 - 2021 The GmSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -68,8 +68,15 @@ typedef struct {
|
||||
void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33]);
|
||||
void sm2_point_to_uncompressed_octets(const SM2_POINT *P, uint8_t out[65]);
|
||||
int sm2_point_from_octets(SM2_POINT *P, const uint8_t *in, size_t inlen);
|
||||
|
||||
/*
|
||||
RFC 5480 Elliptic Curve Cryptography Subject Public Key Information
|
||||
ECPoint ::= OCTET STRING
|
||||
*/
|
||||
int sm2_point_to_der(const SM2_POINT *P, uint8_t **out, size_t *outlen);
|
||||
int sm2_point_from_der(SM2_POINT *P, const uint8_t **in, size_t *inlen);
|
||||
|
||||
|
||||
int sm2_point_from_x(SM2_POINT *P, const uint8_t x[32], int y);
|
||||
int sm2_point_from_xy(SM2_POINT *P, const uint8_t x[32], const uint8_t y[32]);
|
||||
int sm2_point_is_on_curve(const SM2_POINT *P);
|
||||
@@ -81,14 +88,14 @@ int sm2_point_print(FILE *fp, int fmt, int ind, const char *label, const SM2_POI
|
||||
typedef struct {
|
||||
SM2_POINT public_key;
|
||||
uint8_t private_key[32];
|
||||
uint8_t key_usage[4];
|
||||
} SM2_KEY;
|
||||
|
||||
int sm2_key_generate(SM2_KEY *key);
|
||||
int sm2_key_set_private_key(SM2_KEY *key, const uint8_t private_key[32]);
|
||||
int sm2_key_set_public_key(SM2_KEY *key, const SM2_POINT *public_key);
|
||||
int sm2_key_set_private_key(SM2_KEY *key, const uint8_t private_key[32]); // 自动生成公钥
|
||||
int sm2_key_set_public_key(SM2_KEY *key, const SM2_POINT *public_key); // 自动清空私钥,不要和set_private_key同时用
|
||||
int sm2_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *key);
|
||||
|
||||
int sm2_public_key_equ(const SM2_KEY *sm2_key, const SM2_KEY *pub_key);
|
||||
int sm2_public_key_copy(SM2_KEY *sm2_key, const SM2_KEY *pub_key);
|
||||
int sm2_public_key_digest(const SM2_KEY *key, uint8_t dgst[32]);
|
||||
int sm2_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *pub_key);
|
||||
@@ -98,17 +105,21 @@ from RFC 5915
|
||||
|
||||
ECPrivateKey ::= SEQUENCE {
|
||||
version INTEGER, -- value MUST be (1)
|
||||
privateKey OCTET STRING, -- big endian encoding of integer
|
||||
privateKey OCTET STRING, -- big endian encoding of integer 这里不是以INTEGER编码的,因此长度固定
|
||||
parameters [0] EXPLICIT ECParameters OPTIONAL,
|
||||
-- ONLY namedCurve OID is permitted, by RFC 5480
|
||||
-- MUST always include this field, by RFC 5915
|
||||
publicKey [1] EXPLICIT BIT STRING OPTIONAL
|
||||
publicKey [1] EXPLICIT BIT STRING OPTIONAL -- compressed_point
|
||||
-- SHOULD always include this field, by RFC 5915 }
|
||||
|
||||
ECParameters ::= CHOICE { namedCurve OBJECT IDENTIFIER }
|
||||
*/
|
||||
#define SM2_PRIVATE_KEY_DEFAULT_SIZE 120 // generated
|
||||
#define SM2_PRIVATE_KEY_BUF_SIZE 512 // MUST >= SM2_PRIVATE_KEY_DEFAULT_SIZE
|
||||
|
||||
int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen);
|
||||
int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen);
|
||||
int sm2_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
int sm2_private_key_to_pem(const SM2_KEY *key, FILE *fp);
|
||||
int sm2_private_key_from_pem(SM2_KEY *key, FILE *fp);
|
||||
|
||||
@@ -141,8 +152,13 @@ PrivateKeyInfo ::= SEQUENCE {
|
||||
privateKey OCTET STRING, -- DER-encoding of ECPrivateKey
|
||||
attributes [0] IMPLICIT SET OF Attribute OPTIONAL }
|
||||
*/
|
||||
enum {
|
||||
PKCS8_private_key_info_version = 0,
|
||||
};
|
||||
|
||||
int sm2_private_key_info_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen);
|
||||
int sm2_private_key_info_from_der(SM2_KEY *key, const uint8_t **attrs, size_t *attrslen, const uint8_t **in, size_t *inlen);
|
||||
int sm2_private_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
int sm2_private_key_info_to_pem(const SM2_KEY *key, FILE *fp);
|
||||
int sm2_private_key_info_from_pem(SM2_KEY *key, const uint8_t **attrs, size_t *attrslen, FILE *fp);
|
||||
|
||||
@@ -170,6 +186,7 @@ int sm2_signature_print(FILE *fp, int fmt, int ind, const char *label, const uin
|
||||
int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig);
|
||||
int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig);
|
||||
|
||||
#define SM2_MIN_SIGNATURE_SIZE 8
|
||||
#define SM2_MAX_SIGNATURE_SIZE 72
|
||||
|
||||
int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen);
|
||||
@@ -177,13 +194,10 @@ int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *sig, s
|
||||
|
||||
|
||||
#define SM2_DEFAULT_ID "1234567812345678"
|
||||
#define SM2_DEFAULT_ID_LENGTH (sizeof(SM2_DEFAULT_ID) - 1)
|
||||
#define SM2_DEFAULT_ID_LENGTH (sizeof(SM2_DEFAULT_ID) - 1) // LENGTH for string and SIZE for bytes
|
||||
#define SM2_DEFAULT_ID_BITS (SM2_DEFAULT_ID_LENGTH * 8)
|
||||
#define SM2_DEFAULT_ID_DIGEST_LENGTH SM3_DIGEST_LENGTH
|
||||
|
||||
#define SM2_MAX_ID_BITS 65535
|
||||
#define SM2_MAX_ID_LENGTH (SM2_MAX_ID_BITS/8)
|
||||
#define SM2_MAX_ID_SIZE (SM2_MAX_ID_BITS/8)
|
||||
|
||||
int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id, size_t idlen);
|
||||
|
||||
@@ -191,7 +205,6 @@ int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id, size_t id
|
||||
typedef struct {
|
||||
SM2_KEY key;
|
||||
SM3_CTX sm3_ctx;
|
||||
int flags;
|
||||
} SM2_SIGN_CTX;
|
||||
|
||||
int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen);
|
||||
@@ -209,29 +222,29 @@ SM2Cipher ::= SEQUENCE {
|
||||
HASH OCTET STRING SIZE(32),
|
||||
CipherText OCTET STRING }
|
||||
*/
|
||||
#define SM2_MIN_PLAINTEXT_SIZE 1 // re-compute SM2_MIN_CIPHERTEXT_SIZE when modify
|
||||
#define SM2_MAX_PLAINTEXT_SIZE 255 // re-compute SM2_MAX_CIPHERTEXT_SIZE when modify
|
||||
|
||||
typedef struct {
|
||||
SM2_POINT point;
|
||||
uint8_t hash[32];
|
||||
uint32_t ciphertext_size;
|
||||
uint8_t ciphertext[1];
|
||||
uint8_t ciphertext_size;
|
||||
uint8_t ciphertext[SM2_MAX_PLAINTEXT_SIZE];
|
||||
} SM2_CIPHERTEXT;
|
||||
|
||||
#define SM2_MAX_PLAINTEXT_SIZE 256
|
||||
#define SM2_MAX_CIPHERTEXT_SIZE 512
|
||||
|
||||
#define SM2_CIPHERTEXT_SIZE(inlen) (sizeof(SM2_CIPHERTEXT)-1+(inlen))
|
||||
int sm2_ciphertext_size(size_t inlen, size_t *outlen);
|
||||
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen);
|
||||
int sm2_ciphertext_from_der(SM2_CIPHERTEXT *c, const uint8_t **in, size_t *inlen);
|
||||
int sm2_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen);
|
||||
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out);
|
||||
int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen);
|
||||
|
||||
#define SM2_MIN_CIPHERTEXT_SIZE 45 // dependes on SM2_MIN_PLAINTEXT_SIZE
|
||||
#define SM2_MAX_CIPHERTEXT_SIZE 366 // depends on SM2_MAX_PLAINTEXT_SIZE
|
||||
|
||||
int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
|
||||
int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
|
||||
|
||||
|
||||
|
||||
int sm2_ecdh(const SM2_KEY *key, const SM2_POINT *peer_public, SM2_POINT *out);
|
||||
|
||||
int sm2_selftest(void);
|
||||
|
||||
@@ -310,6 +310,7 @@ IssuerAndSerialNumber ::= SEQUENCE {
|
||||
int x509_cert_get_issuer_and_serial_number(const uint8_t *a, size_t alen,
|
||||
const uint8_t **issuer, size_t *issuer_len,
|
||||
const uint8_t **serial_number, size_t *serial_number_len);
|
||||
int x509_cert_get_issuer(const uint8_t *a, size_t alen, const uint8_t **name, size_t *namelen);
|
||||
int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **subj, size_t *subj_len);
|
||||
int x509_cert_get_subject_public_key(const uint8_t *a, size_t alen, SM2_KEY *public_key);
|
||||
|
||||
|
||||
@@ -94,10 +94,12 @@ int x509_public_key_encryption_algor_print(FILE *fp, int fmt, int ind, const cha
|
||||
|
||||
const char *x509_public_key_algor_name(int oid);
|
||||
int x509_public_key_algor_from_name(const char *name);
|
||||
int x509_public_key_algor_from_der(int *oid, const uint8_t **params, size_t *paramslen, const uint8_t **in, size_t *inlen);
|
||||
int x509_public_key_algor_to_der(int oid, const uint8_t *params, size_t paramslen, uint8_t **out, size_t *outlen);
|
||||
int x509_public_key_algor_to_der(int oid, int curve, uint8_t **out, size_t *outlen);
|
||||
int x509_public_key_algor_from_der(int *oid, int *curve_or_null, const uint8_t **in, size_t *inlen);
|
||||
int x509_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -174,6 +174,21 @@ int x509_general_names_add_general_name(uint8_t *gns, size_t *gnslen, size_t max
|
||||
int choice, const uint8_t *d, size_t dlen);
|
||||
int x509_general_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
|
||||
int x509_general_names_add_other_name(uint8_t *gns, size_t *gnslen, size_t maxlen,
|
||||
const uint32_t *nodes, size_t nodes_count,
|
||||
const uint8_t *value, size_t value_len);
|
||||
#define x509_general_names_add_rfc822_name(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_rfc822_name,(uint8_t*)s,strlen(s))
|
||||
#define x509_general_names_add_dns_name(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_dns_name,(uint8_t*)s,strlen(s))
|
||||
#define x509_general_names_add_x400_address(a,alen,maxlen,d,dlen) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_x400_address,d,dlen)
|
||||
#define x509_general_names_add_directory_name(a,alen,maxlen,d,dlen) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_directory_name,d,dlen)
|
||||
int x509_general_names_add_edi_party_name(uint8_t *gns, size_t *gnslen, size_t maxlen,
|
||||
int assigner_tag, const uint8_t *assigner, size_t assigner_len,
|
||||
int party_name_tag, const uint8_t *party_name, size_t party_name_len);
|
||||
#define x509_general_names_add_uniform_resource_identifier(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_uniform_resource_identifier,(uint8_t*)s,strlen(s))
|
||||
#define x509_general_names_add_ip_address(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_ip_address,(uint8_t*)s,strlen(s))
|
||||
int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t maxlen,
|
||||
const uint32_t *nodes, size_t nodes_cnt);
|
||||
|
||||
/*
|
||||
AuthorityKeyIdentifier ::= SEQUENCE {
|
||||
keyIdentifier [0] IMPLICIT OCTET STRING OPTIONAL,
|
||||
@@ -220,6 +235,8 @@ KeyUsage ::= BIT STRING {
|
||||
#define X509_KU_ENCIPHER_ONLY (1 << 7)
|
||||
#define X509_KU_DECIPHER_ONLY (1 << 8)
|
||||
|
||||
const char *x509_key_usage_name(int flag);
|
||||
int x509_key_usage_from_name(int *flag, const char *name);
|
||||
#define x509_key_usage_to_der(bits,out,outlen) asn1_bits_to_der(bits,out,outlen)
|
||||
#define x509_key_usage_from_der(bits,in,inlen) asn1_bits_from_der(bits,in,inlen)
|
||||
int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, int bits);
|
||||
@@ -266,10 +283,12 @@ PolicyQualifierInfo ::= SEQUENCE {
|
||||
case id-qt-cps : qualifier ::= IA5String
|
||||
case id-qt-unotice : qualifier ::= UserNotice
|
||||
*/
|
||||
int x509_policy_qualifier_info_to_der(int oid,
|
||||
int x509_policy_qualifier_info_to_der(
|
||||
int oid,
|
||||
const uint8_t *qualifier, size_t qualifier_len,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int x509_policy_qualifier_info_from_der(int *oid,
|
||||
int x509_policy_qualifier_info_from_der(
|
||||
int *oid,
|
||||
const uint8_t **qualifier, size_t *qualifier_len,
|
||||
const uint8_t **in, size_t *inlen);
|
||||
int x509_policy_qualifier_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
@@ -308,7 +327,7 @@ int x509_certificate_policies_print(FILE *fp, int fmt, int ind, const char *labe
|
||||
|
||||
/*
|
||||
PolicyMapping ::= SEQUENCE {
|
||||
issuerDomainPolicy CertPolicyId,
|
||||
issuerDomainPolicy CertPolicyId, -- id-anyPolicy or other undefined
|
||||
subjectDomainPolicy CertPolicyId }
|
||||
*/
|
||||
int x509_policy_mapping_to_der(
|
||||
@@ -395,7 +414,8 @@ int x509_general_subtree_print(FILE *fp, int fmt, int ind, const char *label, co
|
||||
/*
|
||||
GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
|
||||
*/
|
||||
int x509_general_subtrees_add_general_subtree(uint8_t *d, size_t *dlen, size_t maxlen,
|
||||
// 应该参考general_names_add_xxx来改写这个函数,只是不知道这个函数用的多不多
|
||||
int x509_general_subtrees_add_general_subtree(uint8_t *d, size_t *dlen, size_t maxlen, // 这个功能和general_names很类似,只是多了一点点内容
|
||||
int base_choice, const uint8_t *base, size_t base_len,
|
||||
int minimum, int maximum);
|
||||
int x509_general_subtrees_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
@@ -431,6 +451,14 @@ int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label,
|
||||
|
||||
/*
|
||||
ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
|
||||
|
||||
KeyPurposeId:
|
||||
OID_kp_server_auth
|
||||
OID_kp_client_auth
|
||||
OID_kp_code_signing
|
||||
OID_kp_email_protection
|
||||
OID_kp_time_stamping
|
||||
OID_kp_ocsp_signing
|
||||
*/
|
||||
#define X509_MAX_KEY_PURPOSES 6
|
||||
int x509_ext_key_usage_to_der(const int *oids, size_t oids_cnt, uint8_t **out, size_t *outlen);
|
||||
@@ -459,6 +487,8 @@ ReasonFlags ::= BIT STRING {
|
||||
#define X509_RF_PRIVILEGE_WITHDRAWN (1 << 7)
|
||||
#define X509_RF_AA_COMPROMISE (1 << 8)
|
||||
|
||||
const char *x509_revoke_reason_name(int flag);
|
||||
int x509_revoke_reason_from_name(int *flag, const char *name);
|
||||
#define x509_revoke_reasons_to_der(bits,out,outlen) asn1_bits_to_der(bits,out,outlen)
|
||||
#define x509_revoke_reasons_from_der(bits,in,inlen) asn1_bits_from_der(bits,in,inlen)
|
||||
int x509_revoke_reasons_print(FILE *fp, int fmt, int ind, const char *label, int bits);
|
||||
@@ -525,3 +555,4 @@ FreshestCRL ::= CRLDistributionPoints
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ id-ce:
|
||||
OID_ce_crl_distribution_points
|
||||
OID_ce_inhibit_any_policy
|
||||
OID_ce_freshest_crl
|
||||
OID_netscape_cert_comment
|
||||
*/
|
||||
const char *x509_ext_id_name(int oid);
|
||||
int x509_ext_id_from_name(const char *name);
|
||||
|
||||
81
src/asn1.c
81
src/asn1.c
@@ -313,34 +313,37 @@ int asn1_header_to_der(int tag, size_t len, uint8_t **out, size_t *outlen)
|
||||
|
||||
// If data == NULL, out should not be NULL
|
||||
// 这个实现是不支持OPTIONAL的
|
||||
int asn1_type_to_der(int tag, const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen)
|
||||
int asn1_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
// 针对IMPLICIT, OPTIONAL
|
||||
if (data == NULL && datalen == 0) {
|
||||
if (!d) {
|
||||
if (dlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: asn1_tag,length,data_to_der这几个函数增加错误检查
|
||||
// 检查这几个函数的返回值
|
||||
asn1_tag_to_der(tag, out, outlen);
|
||||
asn1_length_to_der(datalen, out, outlen);
|
||||
asn1_data_to_der(data, datalen, out, outlen);
|
||||
if (asn1_tag_to_der(tag, out, outlen) != 1
|
||||
|| asn1_length_to_der(dlen, out, outlen) != 1
|
||||
|| asn1_data_to_der(d, dlen, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int asn1_type_from_der(int tag, const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen)
|
||||
int asn1_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
*data = NULL;
|
||||
*datalen = 0;
|
||||
if ((ret = asn1_tag_from_der(tag, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
//if (ret == 0) error_print();
|
||||
else {
|
||||
*d = NULL;
|
||||
*dlen = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (asn1_length_from_der(datalen, in, inlen) != 1
|
||||
|| asn1_data_from_der(data, *datalen, in, inlen) != 1) {
|
||||
if (asn1_length_from_der(dlen, in, inlen) != 1
|
||||
|| asn1_data_from_der(d, *dlen, in, inlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -402,11 +405,38 @@ int asn1_any_from_der(const uint8_t **tlv, size_t *tlvlen, const uint8_t **in, s
|
||||
#define ASN1_TRUE 0xff
|
||||
#define ASN1_FALSE 0x00
|
||||
|
||||
const char *asn1_boolean_name(int val)
|
||||
{
|
||||
switch (val) {
|
||||
case 1: return "true";
|
||||
case 0: return "false";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int asn1_boolean_from_name(int *val, const char *name)
|
||||
{
|
||||
if (strcmp(name, "true") == 0) {
|
||||
*val = 1;
|
||||
return 1;
|
||||
} else if (strcmp(name, "false") == 0) {
|
||||
*val = 0;
|
||||
return 1;
|
||||
}
|
||||
*val = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int asn1_boolean_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if ((out && !(*out)) || !outlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (val < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
*(*out)++ = tag;
|
||||
*(*out)++ = 0x01;
|
||||
@@ -523,6 +553,11 @@ int asn1_bits_to_der_ex(int tag, int bits, uint8_t **out, size_t *outlen)
|
||||
return asn1_bit_string_to_der_ex(tag, buf, nbits, out, outlen);
|
||||
}
|
||||
|
||||
const char *asn1_null_name(void)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
int asn1_null_to_der(uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if ((out && !(*out)) || !outlen) {
|
||||
@@ -591,7 +626,7 @@ static int asn1_oid_node_from_base128(uint32_t *a, const uint8_t **in, size_t *i
|
||||
return 1;
|
||||
}
|
||||
|
||||
int asn1_oid_nodes_to_octets(const uint32_t *nodes, size_t nodes_cnt, uint8_t *out, size_t *outlen)
|
||||
int asn1_object_identifier_to_octets(const uint32_t *nodes, size_t nodes_cnt, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
if (nodes_cnt < 2 || nodes_cnt > 32) {
|
||||
return -1;
|
||||
@@ -667,7 +702,7 @@ int asn1_object_identifier_to_der_ex(int tag, const uint32_t *nodes, size_t node
|
||||
*(*out)++ = tag;
|
||||
(*outlen)++;
|
||||
|
||||
asn1_oid_nodes_to_octets(nodes, nodes_cnt, octets, &octetslen);
|
||||
asn1_object_identifier_to_octets(nodes, nodes_cnt, octets, &octetslen);
|
||||
|
||||
asn1_length_to_der(octetslen, out, outlen);
|
||||
|
||||
@@ -865,6 +900,7 @@ int asn1_boolean_from_der_ex(int tag, int *val, const uint8_t **in, size_t *inle
|
||||
}
|
||||
|
||||
if (*inlen <= 0 || **in != tag) {
|
||||
*val = -1;
|
||||
return 0;
|
||||
}
|
||||
if (*inlen < 3
|
||||
@@ -1242,12 +1278,11 @@ int asn1_length_le(size_t len1, size_t len2)
|
||||
|
||||
int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt)
|
||||
{
|
||||
if (a_cnt != b_cnt
|
||||
|| memcmp(a, b, b_cnt * sizeof(uint32_t)) != 0) {
|
||||
error_print();
|
||||
return 0;
|
||||
if (a_cnt == b_cnt
|
||||
&& memcmp(a, b, b_cnt * sizeof(uint32_t)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
16
src/cms.c
16
src/cms.c
@@ -78,7 +78,7 @@ static uint32_t oid_cms_key_agreement_info[] = { oid_sm2_cms,6 };
|
||||
static const ASN1_OID_INFO cms_content_types[] = {
|
||||
{ OID_cms_data, "data", oid_cms_data, OID_CMS_CONUNT },
|
||||
{ OID_cms_signed_data, "signedData", oid_cms_signed_data, OID_CMS_CONUNT },
|
||||
{ OID_cms_enveloped_data, "envelopedData", oid_cms_signed_data, OID_CMS_CONUNT },
|
||||
{ OID_cms_enveloped_data, "envelopedData", oid_cms_enveloped_data, OID_CMS_CONUNT },
|
||||
{ OID_cms_signed_and_enveloped_data, "signedAndEnvelopedData", oid_cms_signed_and_enveloped_data, OID_CMS_CONUNT },
|
||||
{ OID_cms_encrypted_data, "encryptedData", oid_cms_encrypted_data, OID_CMS_CONUNT },
|
||||
{ OID_cms_key_agreement_info, "keyAgreementInfo", oid_cms_key_agreement_info, OID_CMS_CONUNT }
|
||||
@@ -346,11 +346,11 @@ int cms_enced_content_info_print(FILE *fp, int fmt, int ind, const char *label,
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
x509_encryption_algor_print(fp, fmt, ind, "contentEncryptionAlgorithm", p, len);
|
||||
if ((ret = asn1_implicit_octet_string_from_der(0, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_bytes(fp, fmt, ind, "encryptedContent", d, dlen);
|
||||
if (ret) format_bytes(fp, fmt, ind, "encryptedContent", p, len);
|
||||
if ((ret = asn1_implicit_octet_string_from_der(1, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_bytes(fp, fmt, ind, "sharedInfo1", d, dlen);
|
||||
if (ret) format_bytes(fp, fmt, ind, "sharedInfo1", p, len);
|
||||
if ((ret = asn1_implicit_octet_string_from_der(2, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_bytes(fp, fmt, ind, "sharedInfo2", d, dlen);
|
||||
if (ret) format_bytes(fp, fmt, ind, "sharedInfo2", p, len);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
@@ -658,6 +658,7 @@ int cms_signer_info_to_der(
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (asn1_int_to_der(version, NULL, &len) != 1
|
||||
|| cms_issuer_and_serial_number_to_der(
|
||||
issuer, issuer_len,
|
||||
@@ -732,13 +733,13 @@ int cms_signer_info_print(FILE *fp, int fmt, int ind, const char *label, const u
|
||||
cms_issuer_and_serial_number_print(fp, fmt, ind, "issuerAndSerialNumber", p, len);
|
||||
if (x509_digest_algor_from_der(&val, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "digestAlgorithm: %s\n", x509_digest_algor_name(val));
|
||||
if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) != 1) goto err;
|
||||
if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
if (ret) x509_attributes_print(fp, fmt, ind, "authenticatedAttributes", p, len);
|
||||
if (x509_signature_algor_from_der(&val, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "digestEncryptionAlgorithm: %s\n", x509_signature_algor_name(val));
|
||||
if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
format_bytes(fp, fmt, ind, "encryptedDigest", p, len);
|
||||
if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) != 1) goto err;
|
||||
if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
if (ret) x509_attributes_print(fp, fmt, ind, "unauthenticatedAttributes", p, len);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
@@ -834,6 +835,7 @@ int cms_signer_infos_add_signer_info(
|
||||
const uint8_t *unauthed_attrs, size_t unauthed_attrs_len)
|
||||
{
|
||||
size_t len = *dlen;
|
||||
d += *dlen;
|
||||
if (cms_signer_info_sign_to_der(sm3_ctx, sign_key,
|
||||
issuer, issuer_len, serial_number, serial_number_len,
|
||||
authed_attrs, authed_attrs_len,
|
||||
@@ -1290,7 +1292,7 @@ int cms_recipient_info_encrypt_to_der(
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int pke_algor = OID_sm2encrypt;
|
||||
uint8_t enced_key[SM2_CIPHERTEXT_SIZE(inlen)];
|
||||
uint8_t enced_key[SM2_MAX_CIPHERTEXT_SIZE];
|
||||
size_t enced_key_len;
|
||||
|
||||
if (pke_algor != OID_sm2encrypt) {
|
||||
|
||||
178
src/ec.c
Normal file
178
src/ec.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project.
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* 4. The name "GmSSL Project" must not be used to endorse or promote
|
||||
* products derived from this software without prior written
|
||||
* permission. For written permission, please contact
|
||||
* guanzhi1980@gmail.com.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "GmSSL"
|
||||
* nor may "GmSSL" appear in their names without prior written
|
||||
* permission of the GmSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
#define oid_sm_scheme 1,2,156,10197,1
|
||||
static uint32_t oid_sm2[] = { oid_sm_scheme,301 };
|
||||
|
||||
#define oid_x9_62_curves oid_x9_62,3
|
||||
#define oid_x9_62_prime_curves oid_x9_62_curves,1
|
||||
static uint32_t oid_prime192v1[] = { oid_x9_62_prime_curves,1 };
|
||||
static uint32_t oid_prime256v1[] = { oid_x9_62_prime_curves,7 }; // NIST P-256
|
||||
|
||||
#define oid_secg_curve 1,3,132,0
|
||||
static uint32_t oid_secp256k1[] = { oid_secg_curve,10 };
|
||||
static uint32_t oid_secp384r1[] = { oid_secg_curve,34 }; // NIST P-384
|
||||
static uint32_t oid_secp521r1[] = { oid_secg_curve,35 }; // NIST P-521
|
||||
|
||||
|
||||
static const ASN1_OID_INFO ec_named_curves[] = {
|
||||
{ OID_sm2, "sm2p256v1", oid_sm2, sizeof(oid_sm2)/sizeof(int), 0, "SM2" },
|
||||
{ OID_prime192v1, "prime192v1", oid_prime192v1, sizeof(oid_prime192v1)/sizeof(int), 0, },
|
||||
{ OID_prime256v1, "prime256v1", oid_prime256v1, sizeof(oid_prime256v1)/sizeof(int), 0, "NIST P-256" },
|
||||
{ OID_secp256k1, "secp256k1", oid_secp256k1, sizeof(oid_secp256k1)/sizeof(int) },
|
||||
{ OID_secp384r1, "secp384r1", oid_secp384r1, sizeof(oid_secp384r1)/sizeof(int), 0, "NIST P-384" },
|
||||
{ OID_secp521r1, "secp521r1", oid_secp521r1, sizeof(oid_secp521r1)/sizeof(int), 0, "NIST P-521" }
|
||||
};
|
||||
|
||||
static const int ec_named_curves_count =
|
||||
sizeof(ec_named_curves)/sizeof(ec_named_curves[0]);
|
||||
|
||||
const char *ec_named_curve_name(int oid)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
if (!(info = asn1_oid_info_from_oid(ec_named_curves, ec_named_curves_count, oid))) {
|
||||
error_print();
|
||||
return NULL;
|
||||
}
|
||||
return info->name;
|
||||
}
|
||||
|
||||
int ec_named_curve_from_name(const char *name)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
if (!(info = asn1_oid_info_from_name(ec_named_curves, ec_named_curves_count, name))) {
|
||||
error_print();
|
||||
return OID_undef;
|
||||
}
|
||||
return info->oid;
|
||||
}
|
||||
|
||||
int ec_named_curve_to_der(int oid, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
if (!(info = asn1_oid_info_from_oid(ec_named_curves, ec_named_curves_count, oid))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_named_curve_from_der(int *oid, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const ASN1_OID_INFO *info;
|
||||
if ((ret = asn1_oid_info_from_der(&info, ec_named_curves, ec_named_curves_count, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
else *oid = -1;
|
||||
return ret;
|
||||
}
|
||||
*oid = info->oid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
|
||||
if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
format_bytes(fp, fmt, ind, label, p, len);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ec_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *a;
|
||||
size_t alen;
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
int val;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "version: %d\n", val);
|
||||
if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
format_bytes(fp, fmt, ind, "privateKey", p, len);
|
||||
if ((ret = asn1_explicit_from_der(0, &a, &alen, &d, &dlen)) < 0) goto err;
|
||||
else if (ret) {
|
||||
if (ec_named_curve_from_der(&val, &a, &alen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "parameters: %s\n", ec_named_curve_name(val));
|
||||
if (asn1_length_is_zero(alen) != 1) goto err;
|
||||
}
|
||||
format_print(fp, fmt, ind, "publicKey\n");
|
||||
ind += 4;
|
||||
if ((ret = asn1_explicit_from_der(1, &a, &alen, &d, &dlen)) < 0) goto err;
|
||||
else if (ret) {
|
||||
if (asn1_bit_octets_from_der(&p, &len, &a, &alen) != 1) goto err;
|
||||
format_bytes(fp, fmt, ind, "ECPoint", p, len);
|
||||
if (asn1_length_is_zero(alen) != 1) goto err;
|
||||
}
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -173,3 +173,12 @@ int pbkdf2_genkey(const DIGEST *digest,
|
||||
memset(tmp_block, 0, sizeof(key_block));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pbkdf2_hmac_sm3_genkey(
|
||||
const char *pass, size_t passlen,
|
||||
const uint8_t *salt, size_t saltlen, size_t count,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
return pbkdf2_genkey(DIGEST_sm3(), pass, passlen, salt, saltlen, count, outlen, out);
|
||||
}
|
||||
|
||||
|
||||
80
src/rsa.c
Normal file
80
src/rsa.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2014 - 2021 The GmSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project.
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* 4. The name "GmSSL Project" must not be used to endorse or promote
|
||||
* products derived from this software without prior written
|
||||
* permission. For written permission, please contact
|
||||
* guanzhi1980@gmail.com.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "GmSSL"
|
||||
* nor may "GmSSL" appear in their names without prior written
|
||||
* permission of the GmSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <gmssl/rsa.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
int rsa_public_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen)
|
||||
{
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
int val;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1) goto err;
|
||||
if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
format_bytes(fp, fmt, ind, "modulus", p, len);
|
||||
if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "publicExponent: %d\n",val);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
if (asn1_length_is_zero(alen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -1267,6 +1267,8 @@ int sm2_key_generate(SM2_KEY *key)
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(key, 0, sizeof(SM2_KEY));
|
||||
|
||||
do {
|
||||
bn_rand_range(x, SM2_N);
|
||||
} while (bn_is_zero(x));
|
||||
|
||||
383
src/sm2_asn1.c
383
src/sm2_asn1.c
@@ -56,8 +56,8 @@
|
||||
#include <gmssl/pbkdf2.h>
|
||||
#include <gmssl/pkcs8.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
// sm2 curve 1.2.156.10197.1.301
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
|
||||
|
||||
void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33])
|
||||
@@ -93,11 +93,12 @@ int sm2_point_from_octets(SM2_POINT *P, const uint8_t *in, size_t inlen)
|
||||
|
||||
int sm2_point_to_der(const SM2_POINT *P, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
uint8_t buf[65];
|
||||
if (!P)
|
||||
uint8_t octets[65];
|
||||
if (!P) {
|
||||
return 0;
|
||||
sm2_point_to_uncompressed_octets(P, buf);
|
||||
if (asn1_octet_string_to_der(buf, sizeof(buf), out, outlen) != 1) {
|
||||
}
|
||||
sm2_point_to_uncompressed_octets(P, octets);
|
||||
if (asn1_octet_string_to_der(octets, sizeof(octets), out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -114,6 +115,10 @@ int sm2_point_from_der(SM2_POINT *P, const uint8_t **in, size_t *inlen)
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (dlen != 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_point_from_octets(P, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -124,8 +129,9 @@ int sm2_point_from_der(SM2_POINT *P, const uint8_t **in, size_t *inlen)
|
||||
int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
if (!sig)
|
||||
if (!sig) {
|
||||
return 0;
|
||||
}
|
||||
if (asn1_integer_to_der(sig->r, 32, NULL, &len) != 1
|
||||
|| asn1_integer_to_der(sig->s, 32, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
@@ -160,31 +166,34 @@ int sm2_signature_from_der(SM2_SIGNATURE *sig, const uint8_t **in, size_t *inlen
|
||||
return -1;
|
||||
}
|
||||
memset(sig, 0, sizeof(*sig));
|
||||
memcpy(sig->r, r, rlen);
|
||||
memcpy(sig->s, s, slen);
|
||||
memcpy(sig->r + 32 - rlen, r, rlen); // 需要测试当r, s是比较小的整数时
|
||||
memcpy(sig->s + 32 - slen, s, slen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
int sm2_ciphertext_size(size_t inlen, size_t *outlen)
|
||||
{
|
||||
*outlen = sizeof(SM2_CIPHERTEXT)-1+inlen;
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen)
|
||||
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *C, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
if (!c)
|
||||
if (!C) {
|
||||
return 0;
|
||||
if (asn1_integer_to_der(c->point.x, 32, NULL, &len) != 1
|
||||
|| asn1_integer_to_der(c->point.y, 32, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(c->hash, 32, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(c->ciphertext, c->ciphertext_size, NULL, &len) != 1
|
||||
}
|
||||
if (asn1_integer_to_der(C->point.x, 32, NULL, &len) != 1
|
||||
|| asn1_integer_to_der(C->point.y, 32, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(C->hash, 32, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(C->ciphertext, C->ciphertext_size, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_integer_to_der(c->point.x, 32, out, outlen) != 1
|
||||
|| asn1_integer_to_der(c->point.y, 32, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(c->hash, 32, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(c->ciphertext, c->ciphertext_size, out, outlen) != 1) {
|
||||
|| asn1_integer_to_der(C->point.x, 32, out, outlen) != 1
|
||||
|| asn1_integer_to_der(C->point.y, 32, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(C->hash, 32, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(C->ciphertext, C->ciphertext_size, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -200,7 +209,7 @@ int sm2_ciphertext_from_der(SM2_CIPHERTEXT *C, const uint8_t **in, size_t *inlen
|
||||
const uint8_t *y;
|
||||
const uint8_t *hash;
|
||||
const uint8_t *c;
|
||||
size_t datalen, xlen, ylen, hashlen, clen;
|
||||
size_t xlen, ylen, hashlen, clen;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
@@ -223,130 +232,155 @@ int sm2_ciphertext_from_der(SM2_CIPHERTEXT *C, const uint8_t **in, size_t *inlen
|
||||
memcpy(C->point.y, y, ylen);
|
||||
memcpy(C->hash, hash, hashlen);
|
||||
memcpy(C->ciphertext, c, clen);
|
||||
C->ciphertext_size = (uint32_t)clen;
|
||||
C->ciphertext_size = (uint8_t)clen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: sm2, ecPublicKey 这些公用的OID应该提取到一个地方
|
||||
static const uint32_t oid_sm2[] = { 1,2,156,10197,1,301 };
|
||||
static const size_t oid_sm2_count = sizeof(oid_sm2)/sizeof(oid_sm2[0]);
|
||||
// BIT STRING wrapping of uncompressed point
|
||||
int sm2_public_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
uint8_t buf[65];
|
||||
size_t len = 0;
|
||||
|
||||
if (!key) {
|
||||
return 0;
|
||||
}
|
||||
sm2_point_to_uncompressed_octets(&key->public_key, buf);
|
||||
if (asn1_bit_octets_to_der(buf, sizeof(buf), out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
SM2_POINT P;
|
||||
|
||||
if ((ret = asn1_bit_octets_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (dlen != 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_point_from_octets(&P, d, dlen) != 1
|
||||
|| sm2_key_set_public_key(key, &P) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
int sm2_public_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen)
|
||||
{
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
if (asn1_bit_octets_from_der(&d, &dlen, &a, &alen) != 1) goto err;
|
||||
format_bytes(fp, fmt, ind, "", d, dlen);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int version = 1;
|
||||
uint8_t public_key[65];
|
||||
size_t len = 0;
|
||||
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;
|
||||
|
||||
sm2_point_to_uncompressed_octets(&key->public_key, public_key);
|
||||
|
||||
asn1_int_to_der(version, NULL, &len);
|
||||
asn1_octet_string_to_der(key->private_key, 32, NULL, &len);
|
||||
asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, NULL, ¶ms_len);
|
||||
asn1_explicit_to_der(0, NULL, params_len, NULL, &len);
|
||||
asn1_bit_string_to_der(public_key, sizeof(public_key) * 8, NULL, &pubkey_len);
|
||||
asn1_explicit_to_der(1, NULL, pubkey_len, NULL, &len);
|
||||
|
||||
asn1_sequence_header_to_der(len, out, outlen);
|
||||
asn1_int_to_der(version, out, outlen);
|
||||
asn1_octet_string_to_der(key->private_key, 32, out, outlen);
|
||||
asn1_explicit_header_to_der(0, params_len, out, outlen);
|
||||
asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, out, outlen);
|
||||
asn1_explicit_header_to_der(1, pubkey_len, out, outlen);
|
||||
asn1_bit_string_to_der(public_key, sizeof(public_key) * 8, out, outlen);
|
||||
|
||||
if (ec_named_curve_to_der(OID_sm2, ¶ms_ptr, ¶ms_len) != 1
|
||||
|| sm2_public_key_to_der(key, &pubkey_ptr, &pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_int_to_der(EC_private_key_version, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(key->private_key, 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(key->private_key, 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) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *data;
|
||||
size_t datalen;
|
||||
int version;
|
||||
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;
|
||||
size_t params_len;
|
||||
size_t pubkey_len;
|
||||
size_t prikey_len, params_len, pubkey_len;
|
||||
|
||||
memset(key, 0, sizeof(SM2_KEY));
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_int_from_der(&version, &data, &datalen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikey_len, &data, &datalen) != 1
|
||||
|| asn1_explicit_from_der(0, ¶ms, ¶ms_len, &data, &datalen) < 0
|
||||
|| asn1_explicit_from_der(1, &pubkey, &pubkey_len, &data, &datalen) < 0
|
||||
|| datalen > 0) {
|
||||
return -1;
|
||||
}
|
||||
if (version != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (prikey_len != 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_set_private_key(key, prikey) != 1) {
|
||||
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) {
|
||||
uint32_t nodes[16]; // FIXME: 这个长度不对啊!
|
||||
size_t nodes_count;
|
||||
|
||||
if (asn1_object_identifier_from_der(nodes, &nodes_count, ¶ms, ¶ms_len) != 1
|
||||
|| params_len > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (nodes_count != oid_sm2_count
|
||||
|| memcmp(nodes, oid_sm2, sizeof(oid_sm2)) != 0) {
|
||||
int curve;
|
||||
if (ec_named_curve_from_der(&curve, ¶ms, ¶ms_len) != 1
|
||||
|| asn1_check(curve == OID_sm2) != 1
|
||||
|| asn1_length_is_zero(params_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (asn1_check(prikey_len == 32) != 1
|
||||
|| sm2_key_set_private_key(key, prikey) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pubkey) {
|
||||
const uint8_t *bits;
|
||||
size_t nbits;
|
||||
|
||||
if (asn1_bit_string_from_der(&bits, &nbits, &pubkey, &pubkey_len) != 1
|
||||
|| pubkey_len > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (nbits % 8) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_point_from_octets(&key->public_key, bits, nbits/8) != 1) {
|
||||
if (sm2_public_key_from_der(key, &pubkey, &pubkey_len) != 1
|
||||
|| asn1_length_is_zero(pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
return ec_private_key_print(fp, fmt, ind, label, d, dlen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const uint32_t oid_ec_public_key[] = { 1,2,840,10045,2,1 };
|
||||
static const size_t oid_ec_public_key_count = sizeof(oid_ec_public_key)/sizeof(oid_ec_public_key[0]);
|
||||
|
||||
int sm2_public_key_algor_to_der(uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
if (asn1_object_identifier_to_der(oid_ec_public_key, oid_ec_public_key_count, NULL, &len) != 1
|
||||
|| asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_object_identifier_to_der(oid_ec_public_key, oid_ec_public_key_count, out, outlen) != 1
|
||||
|| asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, out, outlen) != 1) {
|
||||
if (x509_public_key_algor_to_der(OID_ec_public_key, OID_sm2, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -356,36 +390,31 @@ int sm2_public_key_algor_to_der(uint8_t **out, size_t *outlen)
|
||||
int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *data;
|
||||
size_t datalen;
|
||||
uint32_t nodes[ASN1_OID_MAX_NODES];
|
||||
size_t nodes_count;
|
||||
int oid;
|
||||
int curve;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
|
||||
if ((ret = x509_public_key_algor_from_der(&oid, &curve, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1
|
||||
|| asn1_object_identifier_equ(nodes, nodes_count, oid_ec_public_key, oid_ec_public_key_count) != 1) {
|
||||
if (oid != OID_ec_public_key) {
|
||||
printf("%s %d: oid = %d\n", __FILE__, __LINE__, oid);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1
|
||||
|| asn1_object_identifier_equ(nodes, nodes_count, oid_sm2, oid_sm2_count) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (datalen) {
|
||||
if (curve != OID_sm2) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SM2_PRIVATE_KEY_MAX_SIZE 512 // 需要测试这个buffer的最大值
|
||||
|
||||
int sm2_private_key_info_to_der(const SM2_KEY *sm2_key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
uint8_t prikey[512];
|
||||
uint8_t prikey[SM2_PRIVATE_KEY_MAX_SIZE];
|
||||
uint8_t *p = prikey;
|
||||
size_t prikey_len = 0;
|
||||
|
||||
@@ -393,11 +422,11 @@ int sm2_private_key_info_to_der(const SM2_KEY *sm2_key, uint8_t **out, size_t *o
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_int_to_der(0, NULL, &len) != 1
|
||||
if (asn1_int_to_der(PKCS8_private_key_info_version, NULL, &len) != 1
|
||||
|| sm2_public_key_algor_to_der(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(0, out, outlen) != 1
|
||||
|| asn1_int_to_der(PKCS8_private_key_info_version, out, outlen) != 1
|
||||
|| sm2_public_key_algor_to_der(out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(prikey, prikey_len, out, outlen) != 1) {
|
||||
memset(prikey, 0, sizeof(prikey));
|
||||
@@ -416,7 +445,7 @@ int sm2_private_key_info_from_der(SM2_KEY *sm2_key, const uint8_t **attrs, size_
|
||||
size_t dlen;
|
||||
int version;
|
||||
const uint8_t *prikey;
|
||||
size_t prikeylen;
|
||||
size_t prikey_len;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
@@ -424,24 +453,56 @@ int sm2_private_key_info_from_der(SM2_KEY *sm2_key, const uint8_t **attrs, size_
|
||||
}
|
||||
if (asn1_int_from_der(&version, &d, &dlen) != 1
|
||||
|| sm2_public_key_algor_from_der(&d, &dlen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikeylen, &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_check(version == 0) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_from_der(sm2_key, &prikey, &prikeylen) != 1
|
||||
|| asn1_length_is_zero(prikeylen) != 1) {
|
||||
if (asn1_check(version == PKCS8_private_key_info_version) != 1
|
||||
|| sm2_private_key_from_der(sm2_key, &prikey, &prikey_len) != 1
|
||||
|| asn1_length_is_zero(prikey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_private_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
int val;
|
||||
const uint8_t *prikey;
|
||||
size_t prikey_len;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "version: %d\n", val);
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
x509_public_key_algor_print(fp, fmt, ind, "privateKeyAlgorithm", p, len);
|
||||
if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
if (asn1_sequence_from_der(&prikey, &prikey_len, &p, &len) != 1) goto err;
|
||||
ec_private_key_print(fp, fmt, ind + 4, "privateKey", prikey, prikey_len);
|
||||
if (asn1_length_is_zero(len) != 1) goto err;
|
||||
if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
else if (ret) format_bytes(fp, fmt, ind, "attributes", p, len);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#define SM2_PRIVATE_KEY_INFO_MAX_SIZE 512 // 计算长度
|
||||
|
||||
int sm2_private_key_info_to_pem(const SM2_KEY *key, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t buf[SM2_PRIVATE_KEY_INFO_MAX_SIZE];
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
@@ -457,7 +518,7 @@ int sm2_private_key_info_to_pem(const SM2_KEY *key, FILE *fp)
|
||||
|
||||
int sm2_private_key_info_from_pem(SM2_KEY *sm2_key, const uint8_t **attrs, size_t *attrslen, FILE *fp)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t buf[512]; // 这个可能是不够用的,因为attributes可能很长
|
||||
const uint8_t *cp = buf;
|
||||
size_t len;
|
||||
|
||||
@@ -471,51 +532,35 @@ int sm2_private_key_info_from_pem(SM2_KEY *sm2_key, const uint8_t **attrs, size_
|
||||
}
|
||||
|
||||
|
||||
int sm2_public_key_info_to_der(const SM2_KEY *a, uint8_t **out, size_t *outlen)
|
||||
#define SM2_POINT_MAX_SIZE (2 + 65)
|
||||
|
||||
int sm2_public_key_info_to_der(const SM2_KEY *pub_key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
uint8_t bits[65];
|
||||
|
||||
sm2_point_to_uncompressed_octets(&a->public_key, bits);
|
||||
|
||||
sm2_public_key_algor_to_der(NULL, &len);
|
||||
asn1_bit_string_to_der(bits, sizeof(bits)*8, NULL, &len);
|
||||
asn1_sequence_header_to_der(len, out, outlen);
|
||||
sm2_public_key_algor_to_der(out, outlen);
|
||||
asn1_bit_string_to_der(bits, sizeof(bits)*8, out, outlen);
|
||||
if (sm2_public_key_algor_to_der(NULL, &len) != 1
|
||||
|| sm2_public_key_to_der(pub_key, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| sm2_public_key_algor_to_der(out, outlen) != 1
|
||||
|| sm2_public_key_to_der(pub_key, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_info_from_der(SM2_KEY *a, const uint8_t **in, size_t *inlen)
|
||||
int sm2_public_key_info_from_der(SM2_KEY *pub_key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *data;
|
||||
size_t datalen;
|
||||
const uint8_t *bits;
|
||||
size_t nbits;
|
||||
SM2_POINT point;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (sm2_public_key_algor_from_der(&data, &datalen) != 1
|
||||
|| asn1_bit_string_from_der(&bits, &nbits, &data, &datalen) != 1
|
||||
|| datalen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nbits % 8) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_point_from_octets(&point, bits, nbits/8) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(a, 0, sizeof(SM2_KEY));
|
||||
if (sm2_key_set_public_key(a, &point) != 1) {
|
||||
if (sm2_public_key_algor_from_der(&d, &dlen) != 1
|
||||
|| sm2_public_key_from_der(pub_key, &d, &dlen) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -591,6 +636,14 @@ int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_public_key_equ(const SM2_KEY *sm2_key, const SM2_KEY *pub_key)
|
||||
{
|
||||
if (memcmp(sm2_key, pub_key, sizeof(SM2_POINT)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sm2_public_key_copy(SM2_KEY *sm2_key, const SM2_KEY *pub_key)
|
||||
{
|
||||
return sm2_key_set_public_key(sm2_key, &pub_key->public_key);
|
||||
@@ -687,6 +740,12 @@ int sm2_private_key_info_decrypt_from_der(SM2_KEY *sm2,
|
||||
|| sm2_private_key_info_from_der(sm2, attrs, attrs_len, &cp, &pkey_info_len) != 1
|
||||
|| asn1_length_is_zero(pkey_info_len) != 1) {
|
||||
error_print();
|
||||
|
||||
if (pkey_info_len) {
|
||||
format_bytes(stderr, 0, 0, "700", cp, pkey_info_len);
|
||||
}
|
||||
|
||||
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
@@ -723,8 +782,12 @@ int sm2_private_key_info_decrypt_from_pem(SM2_KEY *key, const char *pass, FILE *
|
||||
size_t attrs_len;
|
||||
|
||||
if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len, sizeof(buf)) != 1
|
||||
|| sm2_private_key_info_decrypt_from_der(key, &attrs, &attrs_len, pass, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
|| sm2_private_key_info_decrypt_from_der(key, &attrs, &attrs_len, pass, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_length_is_zero(len) != 1) {
|
||||
format_bytes(stderr, 0, 0, "", cp, len);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id, size_t id
|
||||
int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen)
|
||||
{
|
||||
uint8_t z[32];
|
||||
if (!ctx || !key || !id || idlen > SM2_MAX_ID_SIZE) {
|
||||
if (!ctx || !key || !id || idlen > SM2_MAX_ID_LENGTH) {
|
||||
return -1;
|
||||
}
|
||||
sm2_compute_z(z, &key->public_key, id, idlen);
|
||||
@@ -242,7 +242,7 @@ int sm2_sign_resume(SM2_SIGN_CTX *ctx)
|
||||
int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen)
|
||||
{
|
||||
uint8_t z[32];
|
||||
if (!ctx || !key || !id || idlen > SM2_MAX_ID_SIZE) {
|
||||
if (!ctx || !key || !id || idlen > SM2_MAX_ID_LENGTH) {
|
||||
return -1;
|
||||
}
|
||||
sm2_compute_z(z, &key->public_key, id, idlen);
|
||||
|
||||
51
src/tlcp.c
51
src/tlcp.c
@@ -132,31 +132,35 @@ int tlcp_certificate_chain_verify(const uint8_t *data, size_t datalen, FILE *ca_
|
||||
{
|
||||
const uint8_t *certs;
|
||||
size_t certslen;
|
||||
const uint8_t *der;
|
||||
size_t derlen;
|
||||
X509_CERTIFICATE sign_cert;
|
||||
X509_CERTIFICATE enc_cert;
|
||||
X509_CERTIFICATE ca_cert;
|
||||
|
||||
const uint8_t *sign_cert;
|
||||
size_t sign_cert_len;
|
||||
const uint8_t *enc_cert;
|
||||
size_t enc_cert_len;
|
||||
const uint8_t *ca_cert;
|
||||
size_t ca_cert_len;
|
||||
const uint8_t *sign_issuer;
|
||||
size_t sign_issuer_len;
|
||||
const uint8_t *enc_issuer;
|
||||
size_t enc_issuer_len;
|
||||
|
||||
if (tls_uint24array_from_bytes(&certs, &certslen, &data, &datalen) != 1
|
||||
|| datalen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1
|
||||
|| x509_certificate_from_der(&sign_cert, &der, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
if (tls_uint24array_from_bytes(&sign_cert, &sign_cert_len, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1
|
||||
|| x509_certificate_from_der(&enc_cert, &der, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
if (tls_uint24array_from_bytes(&enc_cert, &enc_cert_len, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_name_equ(&sign_cert.tbs_certificate.issuer,
|
||||
&enc_cert.tbs_certificate.issuer) != 1) {
|
||||
if (x509_cert_get_issuer(sign_cert, sign_cert_len, &sign_issuer, &sign_issuer_len) != 1
|
||||
|| x509_cert_get_issuer(enc_cert, enc_cert_len, &enc_issuer, &enc_issuer_len) != 1
|
||||
|| asn1_check(sign_issuer_len == enc_issuer_len) != 1
|
||||
|| asn1_check(memcmp(sign_issuer, enc_issuer, enc_issuer_len) == 0) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -164,14 +168,12 @@ int tlcp_certificate_chain_verify(const uint8_t *data, size_t datalen, FILE *ca_
|
||||
if (certslen) {
|
||||
const uint8_t *chain = certs;
|
||||
size_t chainlen = certslen;
|
||||
if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1
|
||||
|| x509_certificate_from_der(&ca_cert, &der, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
if (tls_uint24array_from_bytes(&ca_cert, &ca_cert_len, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certificate_verify_by_certificate(&sign_cert, &ca_cert) != 1
|
||||
|| x509_certificate_verify_by_certificate(&enc_cert, &ca_cert) != 1) {
|
||||
if (x509_cert_verify_by_ca_cert(sign_cert, sign_cert_len, ca_cert, ca_cert_len, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, ca_cert, ca_cert_len, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -180,7 +182,9 @@ int tlcp_certificate_chain_verify(const uint8_t *data, size_t datalen, FILE *ca_
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (x509_certificate_from_pem_by_name(&ca_cert, ca_certs_fp, &sign_cert.tbs_certificate.issuer) != 1
|
||||
|
||||
/*
|
||||
if (x509_cert_from_pem_by_subject(&ca_cert, ca_certs_fp, &sign_cert.tbs_certificate.issuer) != 1
|
||||
|| x509_certificate_verify_by_certificate(&sign_cert, &ca_cert) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -190,6 +194,7 @@ int tlcp_certificate_chain_verify(const uint8_t *data, size_t datalen, FILE *ca_
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -241,7 +246,7 @@ int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port,
|
||||
|
||||
sm3_init(&sm3_ctx);
|
||||
if (client_sign_key)
|
||||
sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
tls_record_set_version(record, TLS_version_tlcp);
|
||||
tls_record_set_version(finished, TLS_version_tlcp);
|
||||
|
||||
@@ -333,7 +338,7 @@ int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port,
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_verify_init(&verify_ctx, &server_sign_key, SM2_DEFAULT_ID) != 1
|
||||
if (sm2_verify_init(&verify_ctx, &server_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_verify_update(&verify_ctx, client_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, server_random, 32) != 1
|
||||
|| sm2_verify_update(&verify_ctx, server_enc_cert, server_enc_cert_len) != 1) {
|
||||
@@ -692,7 +697,7 @@ int tlcp_accept(TLS_CONNECT *conn, int port,
|
||||
}
|
||||
|
||||
tls_trace(">>>> ServerKeyExchange\n");
|
||||
if (sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID) != 1
|
||||
if (sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_sign_update(&sign_ctx, client_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, server_random, 32) != 1
|
||||
|| sm2_sign_update(&sign_ctx, server_enc_cert, server_enc_certlen) != 1
|
||||
@@ -820,7 +825,7 @@ int tlcp_accept(TLS_CONNECT *conn, int port,
|
||||
return -1;
|
||||
}
|
||||
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
|
||||
sm2_verify_init(&sign_ctx, &client_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_verify_init(&sign_ctx, &client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
sm2_verify_update(&sign_ctx, handshakes_buf, handshakeslen);
|
||||
if (sm2_verify_finish(&sign_ctx, sig, siglen) != 1) {
|
||||
error_print();
|
||||
|
||||
98
src/tls.c
98
src/tls.c
@@ -583,7 +583,7 @@ int tls_sign_server_ecdh_params(const SM2_KEY *server_sign_key,
|
||||
server_ecdh_params[3] = 65;
|
||||
sm2_point_to_uncompressed_octets(point, server_ecdh_params + 4);
|
||||
|
||||
sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
sm2_sign_update(&sign_ctx, client_random, 32);
|
||||
sm2_sign_update(&sign_ctx, server_random, 32);
|
||||
sm2_sign_update(&sign_ctx, server_ecdh_params, 69);
|
||||
@@ -612,7 +612,7 @@ int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key,
|
||||
server_ecdh_params[3] = 65;
|
||||
sm2_point_to_uncompressed_octets(point, server_ecdh_params + 4);
|
||||
|
||||
sm2_verify_init(&verify_ctx, server_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_verify_init(&verify_ctx, server_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
sm2_verify_update(&verify_ctx, client_random, 32);
|
||||
sm2_verify_update(&verify_ctx, server_random, 32);
|
||||
sm2_verify_update(&verify_ctx, server_ecdh_params, 69);
|
||||
@@ -951,24 +951,16 @@ int tls_record_set_handshake_certificate_from_pem(uint8_t *record, size_t *recor
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
X509_CERTIFICATE cert;
|
||||
uint8_t der[1024];
|
||||
const uint8_t *cp = der;
|
||||
size_t derlen;
|
||||
uint8_t cert[1024];
|
||||
size_t certlen;
|
||||
|
||||
if ((ret = pem_read(fp, "CERTIFICATE", der, &derlen)) < 0) {
|
||||
if ((ret = x509_cert_from_pem(cert, &certlen, sizeof(cert), fp)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
} else if (!ret) {
|
||||
break;
|
||||
}
|
||||
tls_uint24array_to_bytes(der, derlen, &certs, &certslen);
|
||||
if (x509_certificate_from_der(&cert, &cp, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
//x509_certificate_print(stderr, &cert, 0, 0);
|
||||
tls_uint24array_to_bytes(cert, certlen, &certs, &certslen);
|
||||
}
|
||||
datalen = certslen;
|
||||
tls_uint24_to_bytes((uint24_t)certslen, &data, &datalen);
|
||||
@@ -996,25 +988,22 @@ int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *data, s
|
||||
int tls_certificate_get_subject_names(const uint8_t *certs, size_t certslen, uint8_t *names, size_t *nameslen)
|
||||
{
|
||||
*nameslen = 0;
|
||||
const uint8_t *der;
|
||||
size_t derlen;
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
|
||||
while (certslen > 0) {
|
||||
X509_CERTIFICATE cert;
|
||||
const uint8_t *subject;
|
||||
size_t subject_len;
|
||||
|
||||
if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1) {
|
||||
if (tls_uint24array_from_bytes(&cert, &certlen, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certificate_from_der(&cert, &der, &derlen) != 1) {
|
||||
if (x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (derlen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_name_to_der(&cert.tbs_certificate.subject, &names, nameslen) != 1) {
|
||||
if (asn1_sequence_to_der(subject, subject_len, &names, nameslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -1056,7 +1045,6 @@ int tls_certificate_get_second(const uint8_t *data, size_t datalen, const uint8_
|
||||
int tls_certificate_get_public_keys(const uint8_t *data, size_t datalen,
|
||||
SM2_KEY *sign_key, SM2_KEY *enc_key)
|
||||
{
|
||||
X509_CERTIFICATE x509;
|
||||
const uint8_t *cert;
|
||||
const uint8_t *der;
|
||||
size_t certlen, derlen;
|
||||
@@ -1067,23 +1055,26 @@ int tls_certificate_get_public_keys(const uint8_t *data, size_t datalen,
|
||||
}
|
||||
if (tls_certificate_get_first(data, datalen, &cert, &certlen) != 1
|
||||
|| tls_uint24array_from_bytes(&der, &derlen, &cert, &certlen) != 1
|
||||
|| certlen > 0
|
||||
|| x509_certificate_from_der(&x509, &der, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
|| certlen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(sign_key, &x509.tbs_certificate.subject_public_key_info.sm2_key, sizeof(SM2_KEY));
|
||||
if (x509_cert_get_subject_public_key(der, derlen, sign_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enc_key) {
|
||||
if (tls_certificate_get_second(data, datalen, &cert, &certlen) != 1
|
||||
|| tls_uint24array_from_bytes(&der, &derlen, &cert, &certlen) != 1
|
||||
|| certlen > 0
|
||||
|| x509_certificate_from_der(&x509, &der, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
|| certlen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_cert_get_subject_public_key(der, derlen, enc_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(enc_key, &x509.tbs_certificate.subject_public_key_info.sm2_key, sizeof(SM2_KEY));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1092,41 +1083,44 @@ int tls_certificate_get_public_keys(const uint8_t *data, size_t datalen,
|
||||
|
||||
int tls_certificate_chain_verify(const uint8_t *certs, size_t certslen, FILE *ca_certs_fp, int depth)
|
||||
{
|
||||
X509_CERTIFICATE cert;
|
||||
X509_CERTIFICATE cacert;
|
||||
const uint8_t *der;
|
||||
size_t derlen;
|
||||
if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certificate_from_der(&cert, &der, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
const uint8_t *cacert;
|
||||
size_t cacertlen;
|
||||
const uint8_t *subject;
|
||||
size_t subject_len;
|
||||
uint8_t rootcacert[1024];
|
||||
size_t rootcacertlen;
|
||||
const char *signer_id = SM2_DEFAULT_ID;
|
||||
|
||||
if (tls_uint24array_from_bytes(&cert, &certlen, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
while (certslen > 0) {
|
||||
if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1
|
||||
|| x509_certificate_from_der(&cacert, &der, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
if (tls_uint24array_from_bytes(&cacert, &cacertlen, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certificate_verify_by_certificate(&cert, &cacert) != 1) {
|
||||
if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, signer_id, strlen(signer_id)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(&cert, &cacert, sizeof(X509_CERTIFICATE));
|
||||
cert = cacert;
|
||||
certlen = cacertlen;
|
||||
}
|
||||
if (x509_certificate_from_pem_by_name(&cacert, ca_certs_fp, &cert.tbs_certificate.issuer) != 1
|
||||
|| x509_certificate_verify_by_certificate(&cert, &cacert) != 1) {
|
||||
if (x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_cert_from_pem_by_subject(rootcacert, &rootcacertlen, sizeof(rootcacert), subject, subject_len, ca_certs_fp) != 1
|
||||
|| x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, signer_id, strlen(signer_id)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen,
|
||||
const int *cert_types, size_t cert_types_count,
|
||||
const uint8_t *ca_names, size_t ca_names_len)
|
||||
|
||||
@@ -264,7 +264,7 @@ int tls12_connect(TLS_CONNECT *conn, const char *hostname, int port,
|
||||
|
||||
sm3_init(&sm3_ctx);
|
||||
if (client_sign_key)
|
||||
sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
tls_record_set_version(record, TLS_version_tls1);
|
||||
tls_record_set_version(finished, TLS_version_tls12);
|
||||
|
||||
@@ -378,7 +378,7 @@ int tls12_connect(TLS_CONNECT *conn, const char *hostname, int port,
|
||||
}
|
||||
|
||||
tls_trace("++++ generate secrets\n");
|
||||
sm2_keygen(&client_ecdh);
|
||||
sm2_key_generate(&client_ecdh);
|
||||
sm2_ecdh(&client_ecdh, &server_ecdh_public, &server_ecdh_public);
|
||||
memcpy(pre_master_secret, &server_ecdh_public, 32);
|
||||
|
||||
@@ -732,7 +732,7 @@ int tls12_accept(TLS_CONNECT *conn, int port,
|
||||
}
|
||||
|
||||
tls_trace(">>>> ServerKeyExchange\n");
|
||||
sm2_keygen(&server_ecdh);
|
||||
sm2_key_generate(&server_ecdh);
|
||||
if (tls_sign_server_ecdh_params(server_sign_key,
|
||||
client_random, server_random,
|
||||
TLS_curve_sm2p256v1, &server_ecdh.public_key, sig, &siglen) != 1) {
|
||||
@@ -887,7 +887,7 @@ int tls12_accept(TLS_CONNECT *conn, int port,
|
||||
return -1;
|
||||
}
|
||||
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
|
||||
sm2_verify_init(&sign_ctx, &client_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_verify_init(&sign_ctx, &client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
sm2_verify_update(&sign_ctx, handshakes_buf, handshakeslen);
|
||||
if (sm2_verify_finish(&sign_ctx, sig, siglen) != 1) {
|
||||
error_print();
|
||||
|
||||
28
src/tls13.c
28
src/tls13.c
@@ -387,7 +387,7 @@ int tls13_sign(const SM2_KEY *key, const DIGEST_CTX *dgst_ctx, uint8_t *sig, siz
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
|
||||
sm2_sign_init(&sm2_ctx, key, SM2_DEFAULT_ID);
|
||||
sm2_sign_init(&sm2_ctx, key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
sm2_sign_update(&sm2_ctx, prefix, 64);
|
||||
sm2_sign_update(&sm2_ctx, context_str, context_str_len);
|
||||
sm2_sign_update(&sm2_ctx, dgst, dgstlen);
|
||||
@@ -412,7 +412,7 @@ int tls13_verify(const SM2_KEY *key, const DIGEST_CTX *dgst_ctx, const uint8_t *
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
|
||||
sm2_verify_init(&sm2_ctx, key, SM2_DEFAULT_ID);
|
||||
sm2_verify_init(&sm2_ctx, key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
sm2_verify_update(&sm2_ctx, prefix, 64);
|
||||
sm2_verify_update(&sm2_ctx, is_server ? server_context_str : client_context_str, sizeof(server_context_str));
|
||||
sm2_verify_update(&sm2_ctx, dgst, dgstlen);
|
||||
@@ -1013,24 +1013,18 @@ int tls13_record_set_handshake_certificate_from_pem(uint8_t *record, size_t *rec
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
X509_CERTIFICATE cert;
|
||||
uint8_t der[1024];
|
||||
const uint8_t *cp = der;
|
||||
size_t derlen;
|
||||
uint8_t cert[1024];
|
||||
size_t certlen;
|
||||
|
||||
if ((ret = pem_read(fp, "CERTIFICATE", der, &derlen)) < 0) {
|
||||
if (x509_cert_from_pem(cert, &certlen, sizeof(cert), fp) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
} else if (!ret) {
|
||||
break;
|
||||
}
|
||||
tls_uint24array_to_bytes(der, derlen, &certs, &certslen);
|
||||
if (x509_certificate_from_der(&cert, &cp, &derlen) != 1
|
||||
|| derlen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
//x509_certificate_print(stderr, &cert, 0, 0);
|
||||
|
||||
tls_uint24array_to_bytes(cert, certlen, &certs, &certslen);
|
||||
x509_cert_print(stderr, 0, 0, "Certificate", cert, certlen);
|
||||
}
|
||||
datalen = certslen;
|
||||
tls_uint24_to_bytes((uint24_t)certslen, &data, &datalen);
|
||||
@@ -1312,7 +1306,7 @@ int tls13_connect(TLS_CONNECT *conn, const char *hostname, int port, FILE *serve
|
||||
tls_record_set_version(record, TLS_version_tls12);
|
||||
rand_bytes(client_random, 32);
|
||||
rand_bytes(session_id, 32);
|
||||
sm2_keygen(&client_ecdhe);
|
||||
sm2_key_generate(&client_ecdhe);
|
||||
tls13_client_hello_extensions_set(exts, &extslen, &(client_ecdhe.public_key));
|
||||
tls_record_set_handshake_client_hello(record, &recordlen,
|
||||
TLS_version_tls12, client_random, session_id, 32,
|
||||
@@ -1772,7 +1766,7 @@ int tls13_accept(TLS_CONNECT *conn, int port,
|
||||
tls_trace("<<<< ServerHello\n");
|
||||
|
||||
rand_bytes(server_random, 32);
|
||||
sm2_keygen(&server_ecdhe);
|
||||
sm2_key_generate(&server_ecdhe);
|
||||
tls13_server_hello_extensions_set(exts, &extslen, &(server_ecdhe.public_key), NULL);
|
||||
|
||||
if (tls_record_set_handshake_server_hello(enced_record, &enced_recordlen,
|
||||
|
||||
@@ -570,21 +570,12 @@ int tls_certificate_print(FILE *fp, const uint8_t *data, size_t datalen, int for
|
||||
return -1;
|
||||
}
|
||||
while (certslen > 0) {
|
||||
X509_CERTIFICATE cert;
|
||||
if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certificate_from_der(&cert, &der, &derlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (derlen > 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
(void)x509_certificate_print(fp, &cert, format, indent);
|
||||
(void)x509_certificate_to_pem(&cert, fp);
|
||||
(void)x509_cert_print(fp, format, indent, "Certificate", der, derlen);
|
||||
(void)x509_cert_to_pem(der, derlen, fp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ int gmssl_version_num(void)
|
||||
return GMSSL_VERSION_NUM;
|
||||
}
|
||||
|
||||
const char *gmssl_version(void)
|
||||
const char *gmssl_version_str(void)
|
||||
{
|
||||
return GMSSL_VERSION_STR;
|
||||
}
|
||||
|
||||
137
src/x509_alg.c
137
src/x509_alg.c
@@ -49,12 +49,12 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
#define oid_x9_62 1,2,840,10045
|
||||
|
||||
|
||||
static uint32_t oid_sm3[] = { 1,2,156,10197,1,401 };
|
||||
@@ -489,50 +489,7 @@ err:
|
||||
}
|
||||
|
||||
|
||||
#define oid_sm_scheme 1,2,156,10197,1
|
||||
static uint32_t oid_sm2[] = { oid_sm_scheme,301 };
|
||||
|
||||
#define oid_x9_62_curves oid_x9_62,3
|
||||
#define oid_x9_62_prime_curves oid_x9_62_curves,1
|
||||
static uint32_t oid_prime192v1[] = { oid_x9_62_prime_curves,1 };
|
||||
static uint32_t oid_prime256v1[] = { oid_x9_62_prime_curves,7 }; // NIST P-256
|
||||
|
||||
#define oid_secg_curve 1,3,132,0
|
||||
static uint32_t oid_secp256k1[] = { oid_secg_curve,10 };
|
||||
static uint32_t oid_secp384r1[] = { oid_secg_curve,34 }; // NIST P-384
|
||||
static uint32_t oid_secp521r1[] = { oid_secg_curve,35 }; // NIST P-521
|
||||
|
||||
|
||||
static const ASN1_OID_INFO ec_curves[] = {
|
||||
{ OID_sm2, "sm2", oid_sm2, sizeof(oid_sm2)/sizeof(int), 0, "SM2" },
|
||||
{ OID_prime192v1, "prime192v1", oid_prime192v1, sizeof(oid_prime192v1)/sizeof(int), 0, },
|
||||
{ OID_prime256v1, "prime256v1", oid_prime256v1, sizeof(oid_prime256v1)/sizeof(int), 0, "NIST P-256" },
|
||||
{ OID_secp256k1, "secp256k1", oid_secp256k1, sizeof(oid_secp256k1)/sizeof(int) },
|
||||
{ OID_secp384r1, "secp384r1", oid_secp384r1, sizeof(oid_secp384r1)/sizeof(int), 0, "NIST P-384" },
|
||||
{ OID_secp521r1, "secp521r1", oid_secp521r1, sizeof(oid_secp521r1)/sizeof(int), 0, "NIST P-521" }
|
||||
};
|
||||
|
||||
static const int ec_curves_count = sizeof(ec_curves)/sizeof(ec_curves[0]);
|
||||
|
||||
const char *ec_curve_name(int oid)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
if (!(info = asn1_oid_info_from_oid(ec_curves, ec_curves_count, oid))) {
|
||||
error_print();
|
||||
return NULL;
|
||||
}
|
||||
return info->name;
|
||||
}
|
||||
|
||||
int ec_curve_from_name(const char *name)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
if (!(info = asn1_oid_info_from_name(ec_curves, ec_curves_count, name))) {
|
||||
error_print();
|
||||
return OID_undef;
|
||||
}
|
||||
return info->oid;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t oid_ec_public_key[] = { oid_x9_62,2,1 };
|
||||
@@ -566,66 +523,102 @@ int x509_public_key_algor_from_name(const char *name)
|
||||
return info->oid;
|
||||
}
|
||||
|
||||
int x509_ec_public_key_algor_to_der(int curve_oid, uint8_t **out, size_t *outlen)
|
||||
int x509_public_key_algor_to_der(int oid, int curve_or_null, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
size_t len = 0;
|
||||
|
||||
if (!(info = asn1_oid_info_from_oid(ec_curves, ec_curves_count, curve_oid))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), NULL, &len) != 1
|
||||
|| asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), out, outlen) != 1
|
||||
|| asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) {
|
||||
switch (oid) {
|
||||
case OID_ec_public_key:
|
||||
if (asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), NULL, &len) != 1
|
||||
|| ec_named_curve_to_der(curve_or_null, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), out, outlen) != 1
|
||||
|| ec_named_curve_to_der(curve_or_null, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_rsa_encryption:
|
||||
if (asn1_object_identifier_to_der(oid_rsa_encryption, sizeof(oid_rsa_encryption)/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_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), out, outlen) != 1
|
||||
|| asn1_null_to_der(out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_ec_public_key_algor_from_der(int *curve_oid, const uint8_t **in, size_t *inlen)
|
||||
int x509_public_key_algor_from_der(int *oid , int *curve_or_null, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
const ASN1_OID_INFO *info;
|
||||
|
||||
*curve_oid = OID_undef;
|
||||
if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) {
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_oid_info_from_der(&info, x509_public_key_algors, x509_public_key_algors_count, &p, &len) != 1) {
|
||||
|
||||
if (asn1_oid_info_from_der(&info, x509_public_key_algors, x509_public_key_algors_count, &d, &dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (info->oid != OID_ec_public_key) {
|
||||
*oid = info->oid;
|
||||
|
||||
switch (*oid) {
|
||||
case OID_ec_public_key:
|
||||
if (ec_named_curve_from_der(curve_or_null, &d, &dlen) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_rsa_encryption:
|
||||
if ((*curve_or_null = asn1_null_from_der(&d, &dlen)) < 0
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_oid_info_from_der(&info, ec_curves, ec_curves_count, &p, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*curve_oid = info->oid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
int val;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
if (asn1_oid_info_from_der(&info, x509_public_key_algors, x509_public_key_algors_count, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "algorithm: %s\n", info->description);
|
||||
if (info->oid != OID_ec_public_key) goto err;
|
||||
if (asn1_oid_info_from_der(&info, ec_curves, ec_curves_count, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "namedCurve: %s\n", info->name);
|
||||
format_print(fp, fmt, ind, "algorithm: %s\n", info->name);
|
||||
|
||||
switch (info->oid) {
|
||||
case OID_ec_public_key:
|
||||
if (ec_named_curve_from_der(&val, &d, &dlen) != 1) goto err;
|
||||
format_print(fp, fmt, ind, "namedCurve: %s\n", ec_named_curve_name(val));
|
||||
break;
|
||||
case OID_rsa_encryption:
|
||||
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());
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/pem.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/rsa.h>
|
||||
#include <gmssl/x509_oid.h>
|
||||
#include <gmssl/x509_str.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
@@ -500,6 +501,7 @@ int x509_name_set(uint8_t *d, size_t *dlen, size_t maxlen,
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*dlen = 0;
|
||||
if (x509_name_add_country_name(d, dlen, maxlen, country) < 0
|
||||
|| x509_name_add_state_or_province_name(d, dlen, maxlen, tag, (uint8_t *)state, _strlen(state)) < 0
|
||||
|| x509_name_add_locality_name(d, dlen, maxlen, tag, (uint8_t *)locality, _strlen(locality)) < 0
|
||||
@@ -551,16 +553,30 @@ int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uin
|
||||
|
||||
int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
const uint8_t *p = d;
|
||||
size_t len = dlen;
|
||||
int alg;
|
||||
int params;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
if (x509_public_key_algor_from_der(&alg, ¶ms, &p, &len) != 1) goto err;
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
x509_public_key_algor_print(fp, fmt, ind, "algorithm", p, len);
|
||||
format_print(fp, fmt, ind, "subjectPublicKey\n");
|
||||
ind += 4;
|
||||
if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||
format_bytes(fp, fmt, ind, "subjectPublicKey", p, len);
|
||||
switch (alg) {
|
||||
case OID_ec_public_key:
|
||||
format_bytes(fp, fmt, ind, "ECPoint", p, len);
|
||||
break;
|
||||
case OID_rsa_encryption:
|
||||
rsa_public_key_print(fp, fmt, ind, "RSAPublicKey", p, len);
|
||||
break;
|
||||
default:
|
||||
format_bytes(fp, fmt, ind, "raw_data", p, len);
|
||||
}
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
err:
|
||||
@@ -627,12 +643,12 @@ int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
|
||||
if (x509_ext_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err;
|
||||
asn1_object_identifier_print(fp, fmt, ind, "extnID", x509_ext_id_name(oid), nodes, nodes_cnt);
|
||||
if ((ret = asn1_boolean_from_der(&critical, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_print(fp, fmt, ind, "critical: %s\n", critical ? "True" : "False");
|
||||
if (ret) format_print(fp, fmt, ind, "critical: %s\n", asn1_boolean_name(critical));
|
||||
if (asn1_octet_string_from_der(&val, &vlen, &d, &dlen) != 1) goto err;
|
||||
|
||||
switch (oid) {
|
||||
case OID_ce_subject_key_identifier:
|
||||
if (asn1_octet_string_from_der(&p, &len, &val, &vlen)) {
|
||||
if (asn1_octet_string_from_der(&p, &len, &val, &vlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -649,6 +665,8 @@ int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_netscape_cert_comment:
|
||||
case OID_ct_precertificate_scts:
|
||||
case OID_undef:
|
||||
p = val;
|
||||
len = vlen;
|
||||
@@ -683,6 +701,7 @@ int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
|
||||
case OID_ce_crl_distribution_points: return x509_crl_distribution_points_print(fp, fmt, ind, name, p, len);
|
||||
case OID_ce_inhibit_any_policy: format_print(fp, fmt, ind, "%s: %d\n", name, ival);
|
||||
case OID_ce_freshest_crl: return x509_freshest_crl_print(fp, fmt, ind, name, p, len);
|
||||
case OID_netscape_cert_comment: return format_string(fp, fmt, ind, name, p, len);
|
||||
default: format_bytes(fp, fmt, ind, "extnValue", p, len);
|
||||
}
|
||||
return 1;
|
||||
@@ -1257,7 +1276,22 @@ int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **d, size
|
||||
NULL, NULL); // signature
|
||||
}
|
||||
|
||||
|
||||
int x509_cert_get_issuer(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen)
|
||||
{
|
||||
return x509_cert_get_details(a, alen,
|
||||
NULL, // version
|
||||
NULL, NULL, // serial
|
||||
NULL, // signature_algor
|
||||
d, dlen, // issuer
|
||||
NULL, NULL, // validity
|
||||
NULL, NULL, // subject
|
||||
NULL, // subject_public_key
|
||||
NULL, NULL, // issuer_unique_id
|
||||
NULL, NULL, // subject_unique_id
|
||||
NULL, NULL, // extensions
|
||||
NULL, // signature_algor
|
||||
NULL, NULL); // signature
|
||||
}
|
||||
|
||||
int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp)
|
||||
{
|
||||
@@ -1330,6 +1364,7 @@ int x509_certs_get_cert_by_issuer_and_serial_number(
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
183
src/x509_ext.c
183
src/x509_ext.c
@@ -71,6 +71,7 @@ int x509_exts_add_sequence(uint8_t *exts, size_t *extslen, size_t maxlen,
|
||||
size_t curlen = *extslen;
|
||||
size_t vlen = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (asn1_sequence_to_der(d, dlen, &p, &vlen) != 1
|
||||
|| x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|
||||
|| asn1_length_le(curlen, maxlen) != 1
|
||||
@@ -94,6 +95,7 @@ int x509_exts_add_authority_key_identifier(uint8_t *exts, size_t *extslen, size_
|
||||
size_t vlen = 0;
|
||||
size_t len = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (x509_authority_key_identifier_to_der(
|
||||
keyid, keyid_len,
|
||||
issuer, issuer_len,
|
||||
@@ -128,6 +130,8 @@ int x509_exts_add_subject_key_identifier(uint8_t *exts, size_t *extslen, size_t
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
exts += *extslen;
|
||||
if (asn1_octet_string_to_der(d, dlen, &p, &vlen) != 1
|
||||
|| x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|
||||
|| asn1_length_le(curlen, maxlen) != 1
|
||||
@@ -146,6 +150,7 @@ int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int c
|
||||
uint8_t *p = val;
|
||||
size_t vlen = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (asn1_bits_to_der(bits, &p, &vlen) != 1
|
||||
|| x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|
||||
|| asn1_length_le(curlen, maxlen) != 1
|
||||
@@ -203,6 +208,7 @@ int x509_exts_add_name_constraints(uint8_t *exts, size_t *extslen, size_t maxlen
|
||||
size_t vlen = 0;
|
||||
size_t len = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (x509_name_constraints_to_der(
|
||||
permitted_subtrees, permitted_subtrees_len,
|
||||
excluded_subtrees, excluded_subtrees_len,
|
||||
@@ -230,6 +236,7 @@ int x509_exts_add_policy_constraints(uint8_t *exts, size_t *extslen, size_t maxl
|
||||
uint8_t *p = val;
|
||||
size_t vlen = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (x509_policy_constraints_to_der(
|
||||
require_explicit_policy,
|
||||
inhibit_policy_mapping,
|
||||
@@ -252,6 +259,7 @@ int x509_exts_add_basic_constraints(uint8_t *exts, size_t *extslen, size_t maxle
|
||||
uint8_t *p = val;
|
||||
size_t vlen = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (x509_basic_constraints_to_der(ca, path_len_constraint, &p, &vlen) != 1
|
||||
|| x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|
||||
|| asn1_length_le(curlen, maxlen) != 1
|
||||
@@ -272,6 +280,7 @@ int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen,
|
||||
size_t vlen = 0;
|
||||
size_t len = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (x509_ext_key_usage_to_der(key_purposes, key_purposes_cnt, NULL, &len) != 1
|
||||
|| asn1_length_le(len, sizeof(val)) != 1
|
||||
|| x509_ext_key_usage_to_der(key_purposes, key_purposes_cnt, &p, &vlen) != 1
|
||||
@@ -300,6 +309,7 @@ int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxl
|
||||
uint8_t *p = val;
|
||||
size_t vlen = 0;
|
||||
|
||||
exts += *extslen;
|
||||
if (x509_inhibit_any_policy_to_der(skip_certs, &p, &vlen) != 1
|
||||
|| x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|
||||
|| asn1_length_le(curlen, maxlen) != 1
|
||||
@@ -505,6 +515,17 @@ int x509_general_names_add_general_name(uint8_t *gns, size_t *gnslen, size_t max
|
||||
{
|
||||
size_t len = 0;
|
||||
uint8_t *p = gns + *gnslen;
|
||||
|
||||
switch (choice) {
|
||||
case X509_gn_rfc822_name:
|
||||
case X509_gn_dns_name:
|
||||
case X509_gn_uniform_resource_identifier:
|
||||
if (asn1_ia5_string_check((char *)d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (x509_general_name_to_der(choice, d, dlen, NULL, &len) != 1
|
||||
|| asn1_length_le(*gnslen + len, maxlen) != 1
|
||||
|| x509_general_name_to_der(choice, d, dlen, &p, gnslen) != 1) {
|
||||
@@ -514,6 +535,66 @@ int x509_general_names_add_general_name(uint8_t *gns, size_t *gnslen, size_t max
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_general_names_add_other_name(uint8_t *gns, size_t *gnslen, size_t maxlen,
|
||||
const uint32_t *nodes, size_t nodes_cnt,
|
||||
const uint8_t *value, size_t value_len)
|
||||
{
|
||||
int choice = X509_gn_other_name;
|
||||
uint8_t buf[128];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if (x509_other_name_to_der(nodes, nodes_cnt, value, value_len, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| x509_general_names_add_general_name(gns, gnslen, maxlen, choice, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_general_names_add_edi_party_name(uint8_t *gns, size_t *gnslen, size_t maxlen,
|
||||
int assigner_tag, const uint8_t *assigner, size_t assigner_len,
|
||||
int party_name_tag, const uint8_t *party_name, size_t party_name_len)
|
||||
{
|
||||
int choice = X509_gn_edi_party_name;
|
||||
uint8_t buf[128];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if (x509_edi_party_name_to_der(
|
||||
assigner_tag, assigner, assigner_len,
|
||||
party_name_tag, party_name, party_name_len,
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| x509_general_names_add_general_name(gns, gnslen, maxlen, choice, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t maxlen,
|
||||
const uint32_t *nodes, size_t nodes_cnt)
|
||||
{
|
||||
int choice = X509_gn_registered_id;
|
||||
uint8_t d[128];
|
||||
size_t dlen;
|
||||
|
||||
if (asn1_object_identifier_to_octets(nodes, nodes_cnt, d, &dlen) != 1
|
||||
|| x509_general_names_add_general_name(gns, gnslen, maxlen, choice, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_general_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
int choice;
|
||||
@@ -614,6 +695,37 @@ static const char *x509_key_usages[] = {
|
||||
static size_t x509_key_usages_count =
|
||||
sizeof(x509_key_usages)/sizeof(x509_key_usages[0]);
|
||||
|
||||
const char *x509_key_usage_name(int flag)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < x509_key_usages_count; i++) {
|
||||
if (flag & 1) {
|
||||
if (flag >> 1) {
|
||||
error_print();
|
||||
return NULL;
|
||||
}
|
||||
return x509_key_usages[i];
|
||||
}
|
||||
flag >>= 1;
|
||||
}
|
||||
error_print();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int x509_key_usage_from_name(int *flag, const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < x509_key_usages_count; i++) {
|
||||
if (strcmp(name, x509_key_usages[i]) == 0) {
|
||||
*flag = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
*flag = 0;
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, int bits)
|
||||
{
|
||||
return asn1_bits_print(fp, fmt, ind, label, x509_key_usages, x509_key_usages_count, bits);
|
||||
@@ -647,6 +759,7 @@ int x509_notice_reference_from_der(
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
else error_print();
|
||||
return ret;
|
||||
}
|
||||
if (x509_display_text_from_der(org_tag, org, org_len, &d, &dlen) != 1
|
||||
@@ -655,7 +768,7 @@ int x509_notice_reference_from_der(
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_notice_reference_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
@@ -747,6 +860,7 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 是否要针对oid = cps的IA5String做一个方便的接口呢?毕竟oid 只有两个可选项
|
||||
int x509_policy_qualifier_info_to_der(
|
||||
int oid,
|
||||
const uint8_t *qualifier, size_t qualifier_len,
|
||||
@@ -1097,18 +1211,20 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t *
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
else {
|
||||
*ca = -1;
|
||||
*path_len_cons = -1;
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ca = 0;
|
||||
*path_len_cons = 0; // FIXME: 默认值应该设置为多少?
|
||||
|
||||
if (asn1_boolean_from_der(ca, &d, &dlen) < 0
|
||||
|| asn1_int_from_der(path_len_cons, &d, &dlen) < 0
|
||||
|| asn1_check(ca >= 0 || path_len_cons >= 0) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (*ca < 0) *ca = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1120,7 +1236,7 @@ int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label,
|
||||
ind += 4;
|
||||
|
||||
if ((ret = asn1_boolean_from_der(&val, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_print(fp, fmt, ind, "cA: %s\n", val ? "True" : "False");
|
||||
if (ret) format_print(fp, fmt, ind, "cA: %s\n", asn1_boolean_name(val));
|
||||
if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_print(fp, fmt, ind, "pathLenConstraint: %d\n", val);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
@@ -1164,15 +1280,14 @@ int x509_general_subtree_from_der(
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
*minimum = 0;
|
||||
*maximum = -1;
|
||||
if (x509_general_name_from_der(base_choice, base, base_len, &d, &dlen) != 1
|
||||
|| asn1_int_from_der(minimum, &d, &dlen) < 0
|
||||
|| asn1_int_from_der(maximum, &d, &dlen) < 0
|
||||
|| asn1_implicit_int_from_der(0, minimum, &d, &dlen) < 0
|
||||
|| asn1_implicit_int_from_der(1, maximum, &d, &dlen) < 0
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (*minimum < 0) *minimum = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1187,9 +1302,9 @@ int x509_general_subtree_print(FILE *fp, int fmt, int ind, const char *label, co
|
||||
|
||||
if (x509_general_name_from_der(&choice, &p, &len, &d, &dlen) != 1) goto err;
|
||||
x509_general_name_print(fp, fmt, ind, "base", choice, p, len);
|
||||
if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err;
|
||||
if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_print(fp, fmt, ind, "minimum: %d\n", val);
|
||||
if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err;
|
||||
if ((ret = asn1_implicit_int_from_der(1, &val, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_print(fp, fmt, ind, "maximum: %d\n", val);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
@@ -1337,7 +1452,7 @@ int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label,
|
||||
|
||||
if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_print(fp, fmt, ind, "requireExplicitPolicy: %d\n", val);
|
||||
if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err;
|
||||
if ((ret = asn1_implicit_int_from_der(1, &val, &d, &dlen)) < 0) goto err;
|
||||
if (ret) format_print(fp, fmt, ind, "inhibitPolicyMapping: %d\n", val);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
return 1;
|
||||
@@ -1403,15 +1518,16 @@ int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, con
|
||||
int x509_ext_key_usage_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
int oid;
|
||||
format_print(fp, fmt, ind, "%s: ", label);
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
while (dlen) {
|
||||
if (x509_key_purpose_from_der(&oid, &d, &dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
fprintf(fp, "%s%s", x509_key_purpose_name(oid), dlen ? ", " : "");
|
||||
format_print(fp, fmt, ind, "%s\n", x509_key_purpose_name(oid));
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1430,6 +1546,36 @@ static const char *x509_revoke_reasons[] = {
|
||||
static size_t x509_revoke_reasons_count =
|
||||
sizeof(x509_revoke_reasons)/sizeof(x509_revoke_reasons[0]);
|
||||
|
||||
const char *x509_revoke_reason_name(int flag)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < x509_revoke_reasons_count; i++) {
|
||||
if (flag & 1) {
|
||||
if (flag >> 1) {
|
||||
error_print();
|
||||
return NULL;
|
||||
}
|
||||
return x509_revoke_reasons[i];
|
||||
}
|
||||
flag >>= 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int x509_revoke_reason_from_name(int *flag, const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < x509_revoke_reasons_count; i++) {
|
||||
if (strcmp(name, x509_revoke_reasons[i]) == 0) {
|
||||
*flag = 1 << i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
*flag = 0;
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int x509_revoke_reasons_print(FILE *fp, int fmt, int ind, const char *label, int bits)
|
||||
{
|
||||
return asn1_bits_print(fp, fmt, ind, label, x509_revoke_reasons, x509_revoke_reasons_count, bits);
|
||||
@@ -1548,7 +1694,10 @@ int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label,
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
format_bytes(stderr, 0, 0, "1697", d, dlen);
|
||||
|
||||
if ((ret = asn1_explicit_from_der(0, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
/*
|
||||
if (ret) {
|
||||
int choice;
|
||||
const uint8_t *name;
|
||||
@@ -1558,11 +1707,13 @@ int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label,
|
||||
x509_distribution_point_name_print(fp, fmt, ind, "DistributionPointName", choice, name, namelen);
|
||||
if (asn1_length_is_zero(len) != 1) goto err;
|
||||
}
|
||||
|
||||
if ((ret = asn1_implicit_bits_from_der(1, &bits, &d, &dlen)) < 0) goto err;
|
||||
if (ret) x509_revoke_reasons_print(fp, fmt, ind, "reasons", bits);
|
||||
if ((ret = asn1_implicit_sequence_from_der(2, &p, &len, &d, &dlen)) < 0) goto err;
|
||||
if (ret) x509_general_names_print(fp, fmt, ind, "cRLIssuer", p, len);
|
||||
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||
*/
|
||||
return 1;
|
||||
err:
|
||||
error_print();
|
||||
|
||||
@@ -75,6 +75,7 @@ static uint32_t oid_at_country_name[] = { oid_at,6 };
|
||||
static uint32_t oid_at_serial_number[] = { oid_at,5 };
|
||||
static uint32_t oid_at_pseudonym[] = { oid_at,65 };
|
||||
static uint32_t oid_domain_component[] = { 0,9,2342,19200300,100,1,25 };
|
||||
|
||||
static const size_t oid_at_cnt = sizeof(oid_at_name)/sizeof(int);
|
||||
|
||||
static const ASN1_OID_INFO x509_name_types[] = {
|
||||
@@ -165,6 +166,10 @@ static uint32_t oid_ce_freshest_crl[] = { oid_ce,46 };
|
||||
static uint32_t oid_ce_inhibit_any_policy[] = { oid_ce,54 };
|
||||
static const size_t oid_ce_cnt = sizeof(oid_ce_subject_directory_attributes)/sizeof(int);
|
||||
|
||||
static uint32_t oid_netscape_cert_comment[] = { 2,16,840,1,113730,1,13 };
|
||||
static uint32_t oid_cert_authority_info_access[] = { 1,3,6,1,5,5,7,1,1 };
|
||||
static uint32_t oid_ct_precertificate_scts[] = { 1,3,6,1,4,1,11129,2,4,2 };
|
||||
|
||||
static const ASN1_OID_INFO x509_ext_ids[] = {
|
||||
{ OID_ce_authority_key_identifier, "AuthorityKeyIdentifier", oid_ce_authority_key_identifier, oid_ce_cnt },
|
||||
{ OID_ce_subject_key_identifier, "SubjectKeyIdentifier", oid_ce_subject_key_identifier, oid_ce_cnt },
|
||||
@@ -181,6 +186,9 @@ static const ASN1_OID_INFO x509_ext_ids[] = {
|
||||
{ OID_ce_crl_distribution_points, "CRLDistributionPoints", oid_ce_crl_distribution_points, oid_ce_cnt },
|
||||
{ OID_ce_inhibit_any_policy, "InhibitAnyPolicy", oid_ce_inhibit_any_policy, oid_ce_cnt },
|
||||
{ OID_ce_freshest_crl, "FreshestCRL", oid_ce_freshest_crl, oid_ce_cnt },
|
||||
{ OID_netscape_cert_comment, "NetscapeCertComment", oid_netscape_cert_comment, sizeof(oid_netscape_cert_comment)/sizeof(int) },
|
||||
{ OID_cert_authority_info_access, "CertificateAuthorityInformationAccess", oid_cert_authority_info_access, sizeof(oid_cert_authority_info_access)/sizeof(int) },
|
||||
{ OID_ct_precertificate_scts, "CT-PrecertificateSCTs", oid_ct_precertificate_scts, sizeof(oid_ct_precertificate_scts)/sizeof(int) },
|
||||
};
|
||||
|
||||
static const int x509_ext_ids_count =
|
||||
@@ -189,6 +197,9 @@ static const int x509_ext_ids_count =
|
||||
const char *x509_ext_id_name(int oid)
|
||||
{
|
||||
const ASN1_OID_INFO *info;
|
||||
if (oid == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(info = asn1_oid_info_from_oid(x509_ext_ids, x509_ext_ids_count, oid))) {
|
||||
error_print();
|
||||
return NULL;
|
||||
@@ -340,13 +351,12 @@ int x509_cert_policy_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, c
|
||||
int ret;
|
||||
if ((ret = asn1_object_identifier_from_der(nodes, nodes_cnt, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
*oid = -1;
|
||||
else *oid = -1;
|
||||
return ret;
|
||||
}
|
||||
if (*nodes_cnt == sizeof(oid_any_policy)/sizeof(int)
|
||||
&& memcmp(nodes, oid_any_policy, sizeof(oid_any_policy))) {
|
||||
if (asn1_object_identifier_equ(nodes, *nodes_cnt, oid_any_policy, oid_cnt(oid_any_policy)))
|
||||
*oid = OID_any_policy;
|
||||
}
|
||||
else *oid = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -424,7 +434,7 @@ int x509_key_purpose_from_der(int *oid, const uint8_t **in, size_t *inlen)
|
||||
const ASN1_OID_INFO *info;
|
||||
if ((ret = asn1_oid_info_from_der(&info, x509_key_purposes, x509_key_purposes_count, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
else *oid = 0;
|
||||
else *oid = -1;
|
||||
return ret;
|
||||
}
|
||||
*oid = info->oid;
|
||||
|
||||
@@ -411,4 +411,3 @@ int main(void)
|
||||
err += test_aes_gcm();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -629,6 +629,5 @@ int main(void)
|
||||
err += test_asn1_ia5_string();
|
||||
err += test_asn1_utc_time();
|
||||
err += test_asn1_generalized_time();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -53,5 +53,6 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
int err = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
553
tests/cmstest.c
553
tests/cmstest.c
@@ -56,7 +56,558 @@
|
||||
#include <gmssl/sm4.h>
|
||||
#include <gmssl/cms.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
static int test_cms_content_type(void)
|
||||
{
|
||||
int tests[] = {
|
||||
OID_cms_data,
|
||||
OID_cms_signed_data,
|
||||
OID_cms_enveloped_data,
|
||||
OID_cms_signed_and_enveloped_data,
|
||||
OID_cms_encrypted_data,
|
||||
OID_cms_key_agreement_info,
|
||||
};
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
||||
if (cms_content_type_to_der(tests[i], &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(stderr, 0, 4, "", buf, len);
|
||||
}
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
||||
int oid;
|
||||
if (cms_content_type_from_der(&oid, &cp, &len) != 1
|
||||
|| asn1_check(oid == tests[i]) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "%s\n", cms_content_type_name(oid));
|
||||
}
|
||||
(void)asn1_length_is_zero(len);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_content_info(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
uint8_t data[20] = { 0x01,0x02 };
|
||||
int oid;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if (cms_content_info_to_der(OID_cms_data, data, sizeof(data), &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_content_info_print(stderr, 0, 0, "ContentInfo", d, dlen);
|
||||
|
||||
p = buf;
|
||||
cp = buf;
|
||||
len = 0;
|
||||
|
||||
// 当类型为OID_cms_data, 数据是OCTET STRING,需要再解析一次
|
||||
|
||||
if (cms_content_info_to_der(OID_cms_data, data, sizeof(data), &p, &len) != 1
|
||||
|| cms_content_info_from_der(&oid, &d, &dlen, &cp, &len) != 1
|
||||
|| asn1_check(oid == OID_cms_data) != 1
|
||||
// || asn1_check(dlen == sizeof(data)) != 1
|
||||
// || asn1_check(memcmp(data, d, dlen) == 0) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_enced_content_info(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
uint8_t iv[16] = {0};
|
||||
uint8_t enced[32] = { 0x01,0x02 };
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int oid;
|
||||
int cipher;
|
||||
const uint8_t *piv;
|
||||
size_t ivlen;
|
||||
const uint8_t *shared_info1;
|
||||
size_t shared_info1_len;
|
||||
const uint8_t *shared_info2;
|
||||
size_t shared_info2_len;
|
||||
|
||||
if (cms_enced_content_info_to_der(OID_cms_data,
|
||||
OID_sm4_cbc, iv, sizeof(iv), enced, sizeof(enced),
|
||||
NULL, 0, NULL, 0, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_enced_content_info_print(stderr, 0, 0, "EncryptedContentInfo", d, dlen);
|
||||
|
||||
p = buf;
|
||||
cp = buf;
|
||||
len = 0;
|
||||
|
||||
if (cms_enced_content_info_to_der(OID_cms_data,
|
||||
OID_sm4_cbc, iv, sizeof(iv), enced, sizeof(enced),
|
||||
NULL, 0, NULL, 0, &p, &len) != 1
|
||||
|| cms_enced_content_info_from_der(&oid,
|
||||
&cipher, &piv, &ivlen, &d, &dlen,
|
||||
&shared_info1, &shared_info1_len,
|
||||
&shared_info2, &shared_info2_len, &cp, &len) != 1
|
||||
|| asn1_check(oid == OID_cms_data) != 1
|
||||
|| asn1_check(cipher == OID_sm4_cbc) != 1
|
||||
|| asn1_check(ivlen == sizeof(iv)) != 1
|
||||
|| asn1_check(dlen == sizeof(enced)) != 1
|
||||
|| asn1_check(shared_info1 == NULL) != 1
|
||||
|| asn1_check(shared_info1_len == 0) != 1
|
||||
|| asn1_check(shared_info2 == NULL) != 1
|
||||
|| asn1_check(shared_info2_len == 0) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_enced_content_info_encrypt(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
uint8_t key[16] = {0};
|
||||
uint8_t iv[16] = {1};
|
||||
uint8_t data[20] = {2};
|
||||
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int oid;
|
||||
int cipher;
|
||||
const uint8_t *piv;
|
||||
size_t ivlen;
|
||||
uint8_t data2[256];
|
||||
const uint8_t *shared_info1;
|
||||
size_t shared_info1_len;
|
||||
const uint8_t *shared_info2;
|
||||
size_t shared_info2_len;
|
||||
|
||||
if (cms_enced_content_info_encrypt_to_der(
|
||||
OID_sm4_cbc,
|
||||
key, sizeof(key),
|
||||
iv, sizeof(iv),
|
||||
OID_cms_data, data, sizeof(data),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_enced_content_info_print(stderr, 0, 0, "EncryptedContentInfo", d, dlen);
|
||||
|
||||
p = buf;
|
||||
cp = buf;
|
||||
len = 0;
|
||||
|
||||
if (cms_enced_content_info_encrypt_to_der(
|
||||
OID_sm4_cbc,
|
||||
key, sizeof(key),
|
||||
iv, sizeof(iv),
|
||||
OID_cms_data, data, sizeof(data),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
&p, &len) != 1
|
||||
// 显然这个解密函数是有问题的,在from_der的时候不知道密文的长度,因此无法知道需要的输出缓冲长度
|
||||
|| cms_enced_content_info_decrypt_from_der(
|
||||
&cipher,
|
||||
key, sizeof(key),
|
||||
&oid, data2, &dlen,
|
||||
&shared_info1, &shared_info1_len,
|
||||
&shared_info2, &shared_info2_len,
|
||||
&cp, &len) != 1
|
||||
|| asn1_check(cipher == OID_sm4_cbc) != 1
|
||||
|| asn1_check(oid = OID_cms_data) != 1
|
||||
|| asn1_check(dlen == sizeof(data)) != 1
|
||||
|| asn1_check(memcmp(data, data2, dlen) == 0) != 1
|
||||
|| asn1_check(shared_info1 == NULL) != 1
|
||||
|| asn1_check(shared_info2 == NULL) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_issuer_and_serial_number(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
uint8_t issuer[256];
|
||||
size_t issuer_len;
|
||||
uint8_t serial[20] = {1};
|
||||
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
const uint8_t *pissuer;
|
||||
const uint8_t *pserial;
|
||||
size_t serial_len;
|
||||
|
||||
if (x509_name_set(issuer, &issuer_len, sizeof(issuer),
|
||||
"CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1
|
||||
|| cms_issuer_and_serial_number_to_der(
|
||||
issuer, issuer_len, serial, sizeof(serial), &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_issuer_and_serial_number_print(stderr, 0, 0, "IssuerAndSerialNumber", d, dlen);
|
||||
|
||||
p = buf;
|
||||
cp = buf;
|
||||
len = 0;
|
||||
|
||||
if (x509_name_set(issuer, &issuer_len, sizeof(issuer),
|
||||
"CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1
|
||||
|| cms_issuer_and_serial_number_to_der(
|
||||
issuer, issuer_len, serial, sizeof(serial), &p, &len) != 1
|
||||
|| cms_issuer_and_serial_number_from_der(
|
||||
&pissuer, &issuer_len, &pserial, &serial_len, &cp, &len) != 1
|
||||
|| asn1_check(memcmp(pissuer, issuer, issuer_len) == 0) != 1
|
||||
|| asn1_check(serial_len == sizeof(serial)) != 1
|
||||
|| asn1_check(memcmp(serial, pserial, serial_len) == 0) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_signer_info(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
uint8_t issuer_buf[256];
|
||||
size_t issuer_len;
|
||||
uint8_t serial_buf[20];
|
||||
uint8_t sig_buf[256];
|
||||
size_t siglen;
|
||||
|
||||
int version;
|
||||
const uint8_t *issuer;
|
||||
const uint8_t *serial;
|
||||
size_t serial_len;
|
||||
int digest_alg;
|
||||
const uint8_t *auth_attrs;
|
||||
size_t auth_attrs_len;
|
||||
int sig_alg;
|
||||
const uint8_t *sig;
|
||||
const uint8_t *unauth_attrs;
|
||||
size_t unauth_attrs_len;
|
||||
|
||||
|
||||
if (x509_name_set(issuer_buf, &issuer_len, sizeof(issuer_buf),
|
||||
"CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cms_signer_info_to_der(
|
||||
CMS_version_v1,
|
||||
issuer_buf, issuer_len,
|
||||
serial_buf, sizeof(serial_buf),
|
||||
OID_sm3,
|
||||
NULL, 0,
|
||||
OID_sm2sign_with_sm3,
|
||||
sig_buf, siglen,
|
||||
NULL, 0,
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_signer_info_print(stderr, 0, 0, "SignerInfo", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (cms_signer_info_to_der(
|
||||
CMS_version_v1,
|
||||
issuer_buf, issuer_len,
|
||||
serial_buf, sizeof(serial_buf),
|
||||
OID_sm3,
|
||||
NULL, 0,
|
||||
OID_sm2sign_with_sm3,
|
||||
sig_buf, siglen,
|
||||
NULL, 0,
|
||||
&p, &len) != 1
|
||||
|| cms_signer_info_from_der(
|
||||
&version,
|
||||
&issuer, &issuer_len,
|
||||
&serial, &serial_len,
|
||||
&digest_alg,
|
||||
&auth_attrs, &auth_attrs_len,
|
||||
&sig_alg,
|
||||
&sig, &siglen,
|
||||
&unauth_attrs, &unauth_attrs_len,
|
||||
&cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_signer_info_sign(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
SM3_CTX sm3_ctx;
|
||||
SM2_KEY sm2_key;
|
||||
|
||||
uint8_t issuer_buf[256];
|
||||
size_t issuer_len;
|
||||
uint8_t serial_buf[20];
|
||||
uint8_t auth_attrs_buf[80];
|
||||
|
||||
// 这个函数的验证是需要证书的
|
||||
uint8_t certs[1024];
|
||||
size_t certslen;
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
|
||||
const uint8_t *issuer;
|
||||
const uint8_t *serial;
|
||||
size_t serial_len;
|
||||
const uint8_t *auth_attrs;
|
||||
size_t auth_attrs_len;
|
||||
const uint8_t *unauth_attrs;
|
||||
size_t unauth_attrs_len;
|
||||
|
||||
|
||||
sm2_key_generate(&sm2_key);
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, (uint8_t *)"hello", 5);
|
||||
|
||||
x509_name_set(issuer_buf, &issuer_len, sizeof(issuer_buf), "CN", "Beijing", "Haidian", "PKU", "CS", "CA");
|
||||
|
||||
if (cms_signer_info_sign_to_der(
|
||||
&sm3_ctx, &sm2_key,
|
||||
issuer_buf, issuer_len,
|
||||
serial_buf, sizeof(serial_buf),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_signer_info_print(stderr, 0, 0, "SignerInfo", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (cms_signer_info_sign_to_der(
|
||||
&sm3_ctx, &sm2_key,
|
||||
issuer_buf, issuer_len,
|
||||
serial_buf, sizeof(serial_buf),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
&p, &len) != 1
|
||||
|| cms_signer_info_verify_from_der(
|
||||
&sm3_ctx, certs, certslen,
|
||||
&cert, &certlen,
|
||||
&issuer, &issuer_len,
|
||||
&serial, &serial_len,
|
||||
&auth_attrs, &auth_attrs_len,
|
||||
&unauth_attrs, &unauth_attrs_len,
|
||||
&cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_signer_infos(void)
|
||||
{
|
||||
uint8_t buf[1280];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
uint8_t signer_infos[1024];
|
||||
size_t signer_infos_len = 0;
|
||||
|
||||
SM3_CTX sm3_ctx;
|
||||
SM2_KEY sm2_key;
|
||||
|
||||
uint8_t issuer_buf[256];
|
||||
size_t issuer_len;
|
||||
uint8_t serial_buf[20];
|
||||
|
||||
sm2_key_generate(&sm2_key);
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, (uint8_t *)"hello", 5);
|
||||
x509_name_set(issuer_buf, &issuer_len, sizeof(issuer_buf), "CN", "Beijing", "Haidian", "PKU", "CS", "CA");
|
||||
|
||||
|
||||
if (cms_signer_infos_add_signer_info(
|
||||
signer_infos, &signer_infos_len, sizeof(signer_infos),
|
||||
&sm3_ctx, &sm2_key,
|
||||
issuer_buf, issuer_len,
|
||||
serial_buf, sizeof(serial_buf),
|
||||
NULL, 0,
|
||||
NULL, 0) != 1
|
||||
|| cms_signer_infos_add_signer_info(
|
||||
signer_infos, &signer_infos_len, sizeof(signer_infos),
|
||||
&sm3_ctx, &sm2_key,
|
||||
issuer_buf, issuer_len,
|
||||
serial_buf, sizeof(serial_buf),
|
||||
NULL, 0,
|
||||
NULL, 0) != 1
|
||||
|| cms_signer_infos_add_signer_info(
|
||||
signer_infos, &signer_infos_len, sizeof(signer_infos),
|
||||
&sm3_ctx, &sm2_key,
|
||||
issuer_buf, issuer_len,
|
||||
serial_buf, sizeof(serial_buf),
|
||||
NULL, 0,
|
||||
NULL, 0) != 1
|
||||
|| cms_signer_infos_to_der(signer_infos, signer_infos_len, &p, &len) != 1
|
||||
|| cms_signer_infos_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1){
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_signer_infos_print(stderr, 0, 0, "SET OF SignerInfo", d, dlen);
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_digest_algors(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int oids[] = {
|
||||
OID_sm3,
|
||||
OID_md5,
|
||||
OID_sha1,
|
||||
OID_sha256,
|
||||
OID_sha512,
|
||||
};
|
||||
|
||||
int algs[16];
|
||||
size_t algs_cnt;
|
||||
|
||||
if (cms_digest_algors_to_der(oids, sizeof(oids)/sizeof(oids[0]), &p, &len) != 1
|
||||
|| asn1_set_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
cms_digest_algors_print(stderr, 0, 0, "digestAlgorithms", d, dlen);
|
||||
|
||||
if (cms_digest_algors_to_der(oids, sizeof(oids)/sizeof(oids[0]), &p, &len) != 1
|
||||
|| cms_digest_algors_from_der(algs, &algs_cnt, sizeof(algs)/sizeof(algs[0]), &cp, &len) != 1
|
||||
|| asn1_check(algs_cnt == sizeof(oids)/sizeof(oids[0])) != 1
|
||||
|| asn1_check(memcmp(algs, oids, sizeof(oids)) == 0) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_cms_signed_data(void)
|
||||
{
|
||||
// 这个函数需要证书了,我们需要一个很容易生成证书的函数。
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int err;
|
||||
err += test_cms_content_type();
|
||||
err += test_cms_content_info();
|
||||
err += test_cms_enced_content_info();
|
||||
err += test_cms_enced_content_info_encrypt();
|
||||
err += test_cms_issuer_and_serial_number();
|
||||
err += test_cms_signer_info();
|
||||
err += test_cms_signer_info_sign();
|
||||
err += test_cms_signer_infos();
|
||||
err += test_cms_digest_algors();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -53,8 +53,9 @@
|
||||
#include <gmssl/des.h>
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
int err = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
101
tests/ectest.c
101
tests/ectest.c
@@ -49,9 +49,108 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
static int test_ec_named_curve(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
char *curves[] = {
|
||||
"sm2p256v1",
|
||||
"prime192v1",
|
||||
"prime256v1",
|
||||
"secp256k1",
|
||||
"secp384r1",
|
||||
"secp521r1",
|
||||
};
|
||||
int oid;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(curves)/sizeof(curves[0]); i++) {
|
||||
if ((oid = ec_named_curve_from_name(curves[i])) == OID_undef) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ec_named_curve_to_der(oid, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(curves)/sizeof(curves[0]); i++) {
|
||||
if (ec_named_curve_from_der(&oid, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (oid != ec_named_curve_from_name(curves[i])) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "%s\n", ec_named_curve_name(oid));
|
||||
}
|
||||
(void)asn1_length_is_zero(len);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_ec_point_print(void)
|
||||
{
|
||||
SM2_KEY sm2_key;
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_point_to_der(&(sm2_key.public_key), &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ec_point_print(stderr, 0, 4, "ECPoint", buf, len);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_ec_private_key_print(void)
|
||||
{
|
||||
SM2_KEY sm2_key;
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_to_der(&sm2_key, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ec_private_key_print(stderr, 0, 4, "ECPrivateKey", d, dlen);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
int err = 0;
|
||||
err += test_ec_named_curve();
|
||||
err += test_ec_point_print();
|
||||
err += test_ec_private_key_print();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -243,11 +243,12 @@ int test_hkdf(void)
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_hkdf();
|
||||
return 0;
|
||||
int err = 0;
|
||||
err += test_hkdf();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -390,6 +390,7 @@ static int test_pkcs8(void)
|
||||
return -1;
|
||||
}
|
||||
pkcs8_enced_private_key_info_print(stderr, 0, 0, "test_pkcs8: 392", d, dlen);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
memset(&sm2_key, 0, sizeof(sm2_key));
|
||||
@@ -398,6 +399,7 @@ static int test_pkcs8(void)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
sm2_key_print(stderr, 0, 0, "SM2_KEY", &sm2_key);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
@@ -441,13 +443,15 @@ static int test_pkcs8_pem(void)
|
||||
int main(void)
|
||||
{
|
||||
int err = 0;
|
||||
/*
|
||||
err += test_pbkdf2_params();
|
||||
err += test_pbkdf2_algor();
|
||||
err += test_pbes2_enc_algor();
|
||||
err += test_pbes2_params();
|
||||
err += test_pbes2_algor();
|
||||
err += test_pkcs8_enced_private_key_info();
|
||||
*/
|
||||
err += test_pkcs8();
|
||||
err += test_pkcs8_pem();
|
||||
// err += test_pkcs8_pem();
|
||||
return err;
|
||||
}
|
||||
|
||||
645
tests/sm2test.c
645
tests/sm2test.c
@@ -49,231 +49,594 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/pkcs8.h>
|
||||
|
||||
|
||||
// SM2还需要大量的测试覆盖
|
||||
/*
|
||||
void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33]);
|
||||
void sm2_point_to_uncompressed_octets(const SM2_POINT *P, uint8_t out[65]);
|
||||
int sm2_point_from_octets(SM2_POINT *P, const uint8_t *in, size_t inlen);
|
||||
int sm2_point_from_x(SM2_POINT *P, const uint8_t x[32]);
|
||||
int sm2_point_from_xy(SM2_POINT *P, const uint8_t x[32], const uint8_t y[32]);
|
||||
int sm2_point_is_on_curve(const SM2_POINT *P);
|
||||
*/
|
||||
|
||||
static int test_sm2_point(void)
|
||||
{
|
||||
SM2_POINT P;
|
||||
SM2_POINT P, Q;
|
||||
uint8_t k[32] = {0};
|
||||
uint8_t buf[65] = {0};
|
||||
int i;
|
||||
|
||||
k[31] = 2;
|
||||
for (i = 1; i < 8; i++) {
|
||||
k[31] = (uint8_t)i;
|
||||
|
||||
printf("k = "); for (i = 0; i < 32; i++) printf("%02x", k[i]); printf("\n");
|
||||
if (sm2_point_mul_generator(&P, k) != 1
|
||||
|| sm2_point_is_on_curve(&P) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 0, "k = %d, ", i);
|
||||
sm2_point_print(stderr, 0, 0, "k * G", &P);
|
||||
|
||||
sm2_point_mul_generator(&P, k);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sm2_point_to_compressed_octets(&P, buf);
|
||||
format_bytes(stderr, 0, 4, "compressedPoint", buf, 33);
|
||||
memset(&Q, 0, sizeof(Q));
|
||||
if (sm2_point_from_x(&Q, buf + 1, buf[0]) != 1
|
||||
|| memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) {
|
||||
|
||||
sm2_point_print(stdout, 0, 4, "k * G", &P);
|
||||
sm2_point_print(stderr, 0, 4, "P", &P);
|
||||
sm2_point_print(stderr, 0, 4, "Q", &Q);
|
||||
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sm2_point_to_uncompressed_octets(&P, buf);
|
||||
format_bytes(stderr, 0, 4, "compressedPoint", buf, 65);
|
||||
memset(&Q, 0, sizeof(Q));
|
||||
if (sm2_point_from_octets(&Q, buf, 65) != 1
|
||||
|| memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_point_der(void)
|
||||
{
|
||||
SM2_POINT P, Q;
|
||||
uint8_t k[32] = {0};
|
||||
uint8_t buf[512];
|
||||
int i;
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
k[31] = i;
|
||||
memset(&P, 0, sizeof(P));
|
||||
memset(&Q, 0, sizeof(Q));
|
||||
|
||||
if (sm2_point_mul_generator(&P, k) != 1
|
||||
|| sm2_point_to_der(&P, &p, &len) != 1
|
||||
|| format_bytes(stderr, 0, 4, "ECPoint", buf, len) != 1
|
||||
|| sm2_point_from_der(&Q, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) {
|
||||
error_print();
|
||||
sm2_point_print(stderr, 0, 4, "P", &P);
|
||||
sm2_point_print(stderr, 0, 4, "Q", &Q);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_point_octets(void)
|
||||
{
|
||||
SM2_POINT P, Q;
|
||||
uint8_t k[32] = {0};
|
||||
uint8_t buf[33];
|
||||
int i;
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
k[31] = i;
|
||||
memset(&P, 0, sizeof(P));
|
||||
memset(&Q, 0, sizeof(Q));
|
||||
|
||||
if (sm2_point_mul_generator(&P, k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_point_to_compressed_octets(&P, buf);
|
||||
format_bytes(stderr, 0, 4, "compressedPoint", buf, sizeof(buf));
|
||||
if (sm2_point_from_octets(&Q, buf, sizeof(buf)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) {
|
||||
error_print();
|
||||
sm2_point_print(stderr, 0, 4, "P", &P);
|
||||
sm2_point_print(stderr, 0, 4, "Q", &Q);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_point_from_x(void)
|
||||
{
|
||||
SM2_POINT P, Q;
|
||||
uint8_t k[32] = {0};
|
||||
uint8_t buf[33];
|
||||
int i;
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
k[31] = i;
|
||||
memset(&P, 0, sizeof(P));
|
||||
memset(&Q, 0, sizeof(Q));
|
||||
|
||||
if (sm2_point_mul_generator(&P, k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_point_to_compressed_octets(&P, buf);
|
||||
if (sm2_point_from_x(&Q, buf + 1, buf[0]) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) {
|
||||
error_print();
|
||||
sm2_point_print(stderr, 0, 4, "P", &P);
|
||||
sm2_point_print(stderr, 0, 4, "Q", &Q);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_signature(void)
|
||||
{
|
||||
SM2_SIGNATURE sig;
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
// MinLen
|
||||
memset(&sig, 0x00, sizeof(sig));
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_signature_to_der(&sig, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "SM2_MIN_SIGNATURE_SIZE: %zu\n", len);
|
||||
format_bytes(stderr, 0, 4, "", buf, len);
|
||||
sm2_signature_print(stderr, 0, 4, "signature", buf, len);
|
||||
if (len != SM2_MIN_SIGNATURE_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_signature_from_der(&sig, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
sm2_point_to_compressed_octets(&P, buf);
|
||||
for (i = 0; i < 33; i++) printf("%02x", buf[i]); printf("\n");
|
||||
// MaxLen
|
||||
memset(&sig, 0x80, sizeof(sig));
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_signature_to_der(&sig, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "SM2_MAX_SIGNATURE_SIZE: %zu\n", len);
|
||||
format_bytes(stderr, 0, 4, "", buf, len);
|
||||
sm2_signature_print(stderr, 0, 4, "signature", buf, len);
|
||||
if (len != SM2_MAX_SIGNATURE_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_signature_from_der(&sig, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
sm2_point_to_uncompressed_octets(&P, buf);
|
||||
for (i = 0; i < 65; i++) printf("%02x", buf[i]); printf("\n");
|
||||
|
||||
memset(&P, 0, sizeof(SM2_POINT));
|
||||
/*
|
||||
i = sm2_point_from_x(&P, buf + 1);
|
||||
printf("sm2_point_from_x: %d\n", i);
|
||||
*/
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sm2_point_from_octets(&P, buf, 65);
|
||||
static int test_sm2_sign(void)
|
||||
{
|
||||
int ret;
|
||||
SM2_KEY sm2_key;
|
||||
SM2_SIGN_CTX sign_ctx;
|
||||
uint8_t msg[] = "Hello World!";
|
||||
uint8_t sig[SM2_MAX_SIGNATURE_SIZE] = {0};
|
||||
size_t siglen;
|
||||
|
||||
i = sm2_point_is_on_curve(&P);
|
||||
printf("point_is_on_curve: %d\n", i);
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key);
|
||||
|
||||
if (sm2_sign_init(&sign_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_sign_update(&sign_ctx, msg, sizeof(msg)) != 1
|
||||
|| sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(stderr, 0, 4, "signature", sig, siglen);
|
||||
sm2_signature_print(stderr, 0, 4, "signature", sig, siglen);
|
||||
|
||||
if (sm2_verify_init(&sign_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| sm2_verify_update(&sign_ctx, msg, sizeof(msg)) != 1
|
||||
|| (ret = sm2_verify_finish(&sign_ctx, sig, siglen)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "verification: %s\n", ret ? "success" : "failed");
|
||||
|
||||
|
||||
// FIXME: 还应该增加验证不通过的测试
|
||||
// 还应该增加底层的参数
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_ciphertext(void)
|
||||
{
|
||||
SM2_CIPHERTEXT C;
|
||||
uint8_t buf[1024];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
// {0, 0, Hash, NULL}
|
||||
memset(&C, 0, sizeof(SM2_CIPHERTEXT));
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_ciphertext_to_der(&C, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "SM2_NULL_CIPHERTEXT_SIZE: %zu\n", len);
|
||||
format_bytes(stderr, 0, 4, "", buf, len);
|
||||
if (sm2_ciphertext_from_der(&C, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// {0, 0, Hash, MinLen}
|
||||
C.ciphertext_size = SM2_MIN_PLAINTEXT_SIZE;
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_ciphertext_to_der(&C, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "SM2_MIN_PLAINTEXT_SIZE: %zu\n", SM2_MIN_PLAINTEXT_SIZE);
|
||||
format_print(stderr, 0, 4, "SM2_MIN_CIPHERTEXT_SIZE: %zu\n", len);
|
||||
format_bytes(stderr, 0, 4, "", buf, len);
|
||||
if (len != SM2_MIN_CIPHERTEXT_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_ciphertext_from_der(&C, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// { 33, 33, Hash, NULL }
|
||||
memset(&C, 0x80, sizeof(SM2_POINT));
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_ciphertext_to_der(&C, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "ciphertext len: %zu\n", len);
|
||||
format_bytes(stderr, 0, 4, "", buf, len);
|
||||
if (sm2_ciphertext_from_der(&C, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// { 33, 33, Hash, MaxLen }
|
||||
C.ciphertext_size = SM2_MAX_PLAINTEXT_SIZE;//SM2_MAX_PLAINTEXT_SIZE;
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_ciphertext_to_der(&C, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "SM2_MAX_PLAINTEXT_SIZE: %zu\n", SM2_MAX_PLAINTEXT_SIZE);
|
||||
format_print(stderr, 0, 4, "SM2_MAX_CIPHERTEXT_SIZE: %zu\n", len);
|
||||
format_bytes(stderr, 0, 4, "", buf, len);
|
||||
if (len != SM2_MAX_CIPHERTEXT_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_ciphertext_from_der(&C, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int test_sm2_do_encrypt(void)
|
||||
{
|
||||
SM2_KEY key;
|
||||
SM2_KEY sm2_key;
|
||||
uint8_t plaintext[] = "Hello World!";
|
||||
uint8_t cipherbuf[SM2_CIPHERTEXT_SIZE(sizeof(plaintext))] = {0};
|
||||
SM2_CIPHERTEXT *ciphertext = (SM2_CIPHERTEXT *)cipherbuf;
|
||||
uint8_t plainbuf[sizeof(cipherbuf)] = {0};
|
||||
SM2_CIPHERTEXT ciphertext;
|
||||
|
||||
uint8_t plainbuf[SM2_MAX_PLAINTEXT_SIZE] = {0};
|
||||
size_t plainlen = 0;
|
||||
int r = 0;
|
||||
|
||||
sm2_key_generate(&key);
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_do_encrypt(&key, plaintext, sizeof(plaintext), ciphertext);
|
||||
if (sm2_do_encrypt(&sm2_key, plaintext, sizeof(plaintext), &ciphertext) != 1
|
||||
|| sm2_do_decrypt(&sm2_key, &ciphertext, plainbuf, &plainlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//sm2_ciphertext_print(stdout, 0, 4, "ciphertext", ciphertext);
|
||||
if (plainlen != sizeof(plaintext)
|
||||
|| memcmp(plainbuf, plaintext, sizeof(plaintext)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_do_decrypt(&key, ciphertext, plainbuf, &plainlen);
|
||||
|
||||
printf("plaintext = %s\n", (char *)plainbuf);
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_sign(void)
|
||||
|
||||
static int test_sm2_encrypt(void)
|
||||
{
|
||||
SM2_KEY key;
|
||||
SM2_SIGN_CTX ctx;
|
||||
uint8_t msg[] = "Hello World!";
|
||||
uint8_t sig[128] = {0};
|
||||
size_t siglen = sizeof(sig);
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sm2_key_generate(&key);
|
||||
sm2_key_print(stdout, 0, 4, "sm2_key", &key);
|
||||
|
||||
sm2_sign_init(&ctx, &key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID));
|
||||
sm2_sign_update(&ctx, msg, sizeof(msg));
|
||||
sm2_sign_finish(&ctx, sig, &siglen);
|
||||
|
||||
sm2_signature_print(stdout, 0, 4, "signature", sig, siglen);
|
||||
|
||||
sm2_verify_init(&ctx, &key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID));
|
||||
sm2_verify_update(&ctx, msg, sizeof(msg));
|
||||
r = sm2_verify_finish(&ctx, sig, siglen);
|
||||
printf("verify %s\n", r > 0 ? "success" : "failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_point_octets(void)
|
||||
{
|
||||
int err = 0;
|
||||
SM2_KEY sm2_key;
|
||||
SM2_POINT point;
|
||||
uint8_t buf[65];
|
||||
uint8_t msg[SM2_MAX_PLAINTEXT_SIZE];
|
||||
uint8_t cbuf[SM2_MAX_CIPHERTEXT_SIZE+100];
|
||||
uint8_t mbuf[SM2_MAX_CIPHERTEXT_SIZE];
|
||||
size_t lens[] = {
|
||||
// 0,
|
||||
1,
|
||||
16,
|
||||
SM2_MAX_PLAINTEXT_SIZE,
|
||||
};
|
||||
size_t clen, mlen;
|
||||
int i;
|
||||
|
||||
// compress
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint8_t buf[33];
|
||||
sm2_key_generate(&sm2_key);
|
||||
sm2_point_to_compressed_octets(&sm2_key.public_key, buf);
|
||||
if (sm2_point_from_octets(&point, buf, sizeof(buf)) != 1) {
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(msg); i++) {
|
||||
msg[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) {
|
||||
|
||||
format_bytes(stderr, 0, 4, "mesg", msg, lens[i]);
|
||||
|
||||
if (sm2_encrypt(&sm2_key, msg, lens[i], cbuf, &clen) != 1) {
|
||||
error_print();
|
||||
err++;
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(&sm2_key.public_key, &point, sizeof(SM2_POINT)) != 0) {
|
||||
format_print(stderr, 0, 4, "inlen = %zu, outlen = %zu\n", lens[i], clen);
|
||||
format_bytes(stderr, 0, 4, "", cbuf, clen);
|
||||
sm2_ciphertext_print(stderr, 0, 4, "ciphertext", cbuf, clen);
|
||||
|
||||
if (sm2_decrypt(&sm2_key, cbuf, clen, mbuf, &mlen) != 1) {
|
||||
error_print();
|
||||
err++;
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
format_bytes(stderr, 0, 4, "mbuf", mbuf, mlen);
|
||||
|
||||
if (mlen != lens[i]
|
||||
|| memcmp(mbuf, msg, lens[i]) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// uncompress
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint8_t buf[65];
|
||||
sm2_key_generate(&sm2_key);
|
||||
sm2_point_to_uncompressed_octets(&sm2_key.public_key, buf);
|
||||
if (sm2_point_from_octets(&point, buf, sizeof(buf)) != 1) {
|
||||
error_print();
|
||||
err++;
|
||||
break;
|
||||
}
|
||||
if (memcmp(&sm2_key.public_key, &point, sizeof(SM2_POINT)) != 0) {
|
||||
error_print();
|
||||
err++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s : %s\n", __func__, err ? "failed" : "ok");
|
||||
return err;
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int test_sm2_private_key(void)
|
||||
{
|
||||
int err = 0;
|
||||
SM2_KEY sm2_key;
|
||||
SM2_KEY sm2_tmp;
|
||||
uint8_t buf[256];
|
||||
SM2_KEY tmp_key;
|
||||
uint8_t buf[SM2_PRIVATE_KEY_BUF_SIZE];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
sm2_key_generate(&sm2_key);
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key);
|
||||
|
||||
if (sm2_private_key_to_der(&sm2_key, &p, &len) != 1) {
|
||||
error_print();
|
||||
err++;
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_from_der(&sm2_tmp, &cp, &len) != 1
|
||||
|| len > 0) {
|
||||
format_bytes(stderr, 0, 4, "ECPrivateKey", buf, len);
|
||||
format_print(stderr, 0, 4, "#define SM2_PRIVATE_KEY_DEFAULT_SIZE %zu\n", len);
|
||||
if (sm2_private_key_from_der(&tmp_key, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1
|
||||
|| memcmp(&tmp_key, &sm2_key, sizeof(SM2_KEY)) != 0) {
|
||||
error_print();
|
||||
err++;
|
||||
goto end;
|
||||
}
|
||||
if (memcmp(&sm2_tmp, &sm2_key, sizeof(SM2_KEY)) != 0) {
|
||||
error_print();
|
||||
err++;
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s : ok\n", __func__);
|
||||
end:
|
||||
printf("%s : %s\n", __func__, err ? "failed" : "ok");
|
||||
return err;
|
||||
cp = p = buf; len = 0;
|
||||
memset(&tmp_key, 0, sizeof(tmp_key));
|
||||
if (sm2_private_key_to_der(&sm2_key, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_private_key_print(stderr, 0, 4, "ECPrivateKey", d, dlen);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_public_key_info(void)
|
||||
static int test_sm2_private_key_info(void)
|
||||
{
|
||||
int err = 0;
|
||||
SM2_KEY sm2_key;
|
||||
SM2_KEY sm2_tmp;
|
||||
uint8_t buf[256];
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
sm2_key_generate(&sm2_key);
|
||||
SM2_KEY sm2_key;
|
||||
SM2_KEY tmp_key;
|
||||
const uint8_t *attrs;
|
||||
size_t attrs_len;
|
||||
|
||||
if (sm2_public_key_info_to_der(&sm2_key, &p, &len) != 1) {
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
err++;
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
if (sm2_public_key_info_from_der(&sm2_tmp, &cp, &len) != 1
|
||||
|| len > 0) {
|
||||
sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key);
|
||||
|
||||
if (sm2_private_key_info_to_der(&sm2_key, &p, &len) != 1) {
|
||||
error_print();
|
||||
err++;
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(&sm2_key.public_key, &sm2_tmp.public_key, sizeof(SM2_POINT)) != 0) {
|
||||
format_bytes(stderr, 0, 4, "PrivateKeyInfo", buf, len);
|
||||
format_print(stderr, 0, 4, "sizeof(PrivateKeyInfo): %zu\n", len);
|
||||
if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
err++;
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
printf("%s : ok\n", __func__);
|
||||
end:
|
||||
printf("%s : %s\n", __func__, err ? "failed" : "ok");
|
||||
return err;
|
||||
sm2_private_key_info_print(stderr, 0, 4, "PrivateKeyInfo", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_private_key_info_to_der(&sm2_key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_info_from_der(&tmp_key, &attrs, &attrs_len, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1
|
||||
|| memcmp(&tmp_key, &sm2_key, sizeof(SM2_KEY)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_enced_private_key_info(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
SM2_KEY sm2_key;
|
||||
SM2_KEY tmp_key;
|
||||
const uint8_t *attrs;
|
||||
size_t attrs_len;
|
||||
const char *pass = "Password";
|
||||
|
||||
if (sm2_key_generate(&sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key);
|
||||
|
||||
if (sm2_private_key_info_encrypt_to_der(&sm2_key, pass, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(stderr, 0, 4, "EncryptedPrivateKeyInfo", buf, len);
|
||||
format_print(stderr, 0, 4, "sizeof(EncryptedPrivateKeyInfo): %zu\n", len);
|
||||
if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
pkcs8_enced_private_key_info_print(stderr, 0, 4, "EncryptedPrivateKeyInfo", d, dlen);
|
||||
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (sm2_private_key_info_encrypt_to_der(&sm2_key, pass, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_private_key_info_decrypt_from_der(&tmp_key, &attrs, &attrs_len, pass, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1
|
||||
|| memcmp(&tmp_key, &sm2_key, sizeof(SM2_KEY)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err = 0;
|
||||
err += sm2_selftest();
|
||||
err += test_sm2_point();
|
||||
err += test_sm2_sign();
|
||||
err += test_sm2_do_encrypt();
|
||||
err += test_sm2_point_octets();
|
||||
err += test_sm2_point_from_x();
|
||||
err += test_sm2_point_der();
|
||||
err += test_sm2_private_key();
|
||||
err += test_sm2_public_key_info();
|
||||
err += test_sm2_private_key_info();
|
||||
err += test_sm2_enced_private_key_info();
|
||||
err += test_sm2_signature();
|
||||
err += test_sm2_sign();
|
||||
err += test_sm2_ciphertext();
|
||||
err += test_sm2_do_encrypt();
|
||||
err += test_sm2_encrypt();
|
||||
if (!err) printf("%s all tests passed\n", __FILE__);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -184,14 +184,12 @@ static int test_tls_server_hello(void)
|
||||
uint8_t version[2] = {1,1};
|
||||
uint8_t random[32];
|
||||
uint16_t cipher_suite = TLCP_cipher_ecdhe_sm4_cbc_sm3;
|
||||
uint8_t comp_meth = 0;
|
||||
|
||||
tls_record_set_handshake_server_hello(record, &recordlen,
|
||||
version,
|
||||
random,
|
||||
NULL, 0,
|
||||
cipher_suite,
|
||||
comp_meth,
|
||||
NULL, 0);
|
||||
|
||||
tls_server_hello_print(stdout, record + 5 + 4, recordlen - 5 -4, 0, 0);
|
||||
@@ -348,6 +346,5 @@ int main(void)
|
||||
err += test_tls_alert();
|
||||
err += test_tls_change_cipher_spec();
|
||||
err += test_tls_application_data();
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
36
tests/toolstest.sh
Executable file
36
tests/toolstest.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
rm -fr *.pem
|
||||
rm -fr *.der
|
||||
|
||||
# generate sm2 keypair and encrypt with password
|
||||
sm2keygen -pass 123456 -out cakey.pem -pubout capubkey.pem
|
||||
|
||||
# generate a self-signed certificate
|
||||
certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN CA -days 365 -key cakey.pem -pass 123456 -out cacert.pem
|
||||
certparse -in cacert.pem
|
||||
|
||||
# generate a req and sign by ca certificate
|
||||
sm2keygen -pass 123456 -out key.pem -pubout pubkey.pem
|
||||
reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -days 365 -key key.pem -pass 123456 -out req.pem
|
||||
reqparse -in req.pem
|
||||
reqsign -in req.pem -days 365 -cacert cacert.pem -key cakey.pem -pass 123456 -out cert.pem
|
||||
certparse -in cert.pem
|
||||
|
||||
# hash and hmac
|
||||
echo -n "abc" | sm3
|
||||
echo -n "abc" | sm3hmac -keyhex 1122334455667788
|
||||
|
||||
# encrypt with public key
|
||||
echo hello | sm2encrypt -pubkey pubkey.pem -out ciphertext.der
|
||||
sm2decrypt -in ciphertext.der -key key.pem -pass 123456
|
||||
|
||||
# encrypt with certificate
|
||||
echo hello | sm2encrypt -cert cert.pem -out ciphertext.der
|
||||
sm2decrypt -in ciphertext.der -key key.pem -pass 123456
|
||||
|
||||
# sign and verify with public key and certificate
|
||||
echo hello | sm2sign -key key.pem -pass 123456 -out signature.der
|
||||
echo hello | sm2verify -pubkey pubkey.pem -sig signature.der
|
||||
echo hello | sm2verify -cert cert.pem -sig signature.der
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
#define cnt(nodes) (sizeof(nodes)/sizeof(int))
|
||||
|
||||
static int test_x509_other_name(void)
|
||||
{
|
||||
@@ -152,10 +152,6 @@ static int test_x509_edi_party_name(void)
|
||||
|
||||
static int test_x509_general_name(void)
|
||||
{
|
||||
|
||||
uint8_t gns[512];
|
||||
size_t gnslen = 0;
|
||||
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
@@ -163,14 +159,32 @@ static int test_x509_general_name(void)
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if (x509_general_names_add_general_name(gns, &gnslen, sizeof(gns), X509_gn_rfc822_name, (uint8_t *)"guan@pku.edu.cn", 15) != 1
|
||||
|| format_bytes(stderr, 0, 0, "", gns, gnslen) > 2
|
||||
|| x509_general_names_add_general_name(gns, &gnslen, sizeof(gns), X509_gn_dns_name, (uint8_t *)"www.pku.edu.cn", 14) != 1
|
||||
|| format_bytes(stderr, 0, 0, "", gns, gnslen) > 2
|
||||
|| x509_general_names_add_general_name(gns, &gnslen, sizeof(gns), X509_gn_uniform_resource_identifier, (uint8_t *)"http://localhost", 14) != 1
|
||||
|| format_bytes(stderr, 0, 0, "", gns, gnslen) > 2
|
||||
|| x509_general_names_add_general_name(gns, &gnslen, sizeof(gns), X509_gn_ip_address, (uint8_t *)"10.0.0.1", 8) != 1
|
||||
|| format_bytes(stderr, 0, 0, "", gns, gnslen) > 2
|
||||
uint8_t gns[512];
|
||||
size_t gnslen;
|
||||
uint32_t other_id[] = { 1,3,5,7 };
|
||||
uint8_t value[] = { ASN1_TAG_OCTET_STRING, 0x02, 0x05, 0x05 };
|
||||
uint8_t x400[] = { ASN1_TAG_SEQUENCE, 0x00 };
|
||||
uint8_t name[512];
|
||||
size_t namelen;
|
||||
uint32_t reg_id[] = { 2,4,6,8 };
|
||||
|
||||
if (x509_name_set(name, &namelen, sizeof(name),
|
||||
"CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
gnslen = 0;
|
||||
if (x509_general_names_add_other_name(gns, &gnslen, sizeof(gns), other_id, cnt(other_id), value, sizeof(value)) != 1
|
||||
|| x509_general_names_add_rfc822_name(gns, &gnslen, sizeof(gns), "guan@pku.edu.cn") != 1
|
||||
|| x509_general_names_add_dns_name(gns, &gnslen, sizeof(gns), "www.pku.edu.cn") != 1
|
||||
|| x509_general_names_add_x400_address(gns, &gnslen, sizeof(gns), x400, sizeof(x400)) != 1
|
||||
|| x509_general_names_add_directory_name(gns, &gnslen, sizeof(gns), name, namelen) != 1
|
||||
|| x509_general_names_add_edi_party_name(gns, &gnslen, sizeof(gns),
|
||||
ASN1_TAG_PrintableString, (uint8_t *)"Assigner", strlen("Assigner"),
|
||||
ASN1_TAG_PrintableString, (uint8_t *)"PartyName", strlen("PartyName")) != 1
|
||||
|| x509_general_names_add_uniform_resource_identifier(gns, &gnslen, sizeof(gns), "http://localhost") != 1
|
||||
|| x509_general_names_add_ip_address(gns, &gnslen, sizeof(gns), "127.0.0.1") != 1
|
||||
|| x509_general_names_add_registered_id(gns, &gnslen, sizeof(gns), reg_id, cnt(reg_id)) != 1
|
||||
|| x509_general_names_to_der(gns, gnslen, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
@@ -178,13 +192,91 @@ static int test_x509_general_name(void)
|
||||
return -1;
|
||||
}
|
||||
x509_general_names_print(stderr, 0, 0, "GeneralNames", d, dlen);
|
||||
{
|
||||
size_t i;
|
||||
printf("uint8_t general_names[%zu] = {", dlen);
|
||||
for (i = 0; i < dlen; i++) {
|
||||
if (i % 16 == 0) {
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("0x%02x,", d[i]);
|
||||
}
|
||||
printf("\n};\n");
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t general_names[202] = {
|
||||
0x80,0x0b,0x06,0x03,0x2b,0x05,0x07,0xa0,0x04,0x04,0x02,0x05,0x05,0x81,0x0f,0x67,
|
||||
0x75,0x61,0x6e,0x40,0x70,0x6b,0x75,0x2e,0x65,0x64,0x75,0x2e,0x63,0x6e,0x82,0x0e,
|
||||
0x77,0x77,0x77,0x2e,0x70,0x6b,0x75,0x2e,0x65,0x64,0x75,0x2e,0x63,0x6e,0x83,0x02,
|
||||
0x30,0x00,0x84,0x59,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,
|
||||
0x4e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x42,0x65,0x69,0x6a,
|
||||
0x69,0x6e,0x67,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x48,0x61,
|
||||
0x69,0x64,0x69,0x61,0x6e,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x0a,0x13,0x03,
|
||||
0x50,0x4b,0x55,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x0b,0x13,0x02,0x43,0x53,
|
||||
0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x13,0x02,0x43,0x41,0x85,0x19,0xa0,
|
||||
0x0a,0x13,0x08,0x41,0x73,0x73,0x69,0x67,0x6e,0x65,0x72,0xa1,0x0b,0x13,0x09,0x50,
|
||||
0x61,0x72,0x74,0x79,0x4e,0x61,0x6d,0x65,0x86,0x10,0x68,0x74,0x74,0x70,0x3a,0x2f,
|
||||
0x2f,0x6c,0x6f,0x63,0x61,0x6c,0x68,0x6f,0x73,0x74,0x87,0x09,0x31,0x32,0x37,0x2e,
|
||||
0x30,0x2e,0x30,0x2e,0x31,0x88,0x03,0x54,0x06,0x08,
|
||||
};
|
||||
|
||||
static int test_x509_authority_key_identifier(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
uint8_t keyid[32];
|
||||
uint8_t serial[20];
|
||||
|
||||
const uint8_t *keyidp;
|
||||
size_t keyidlen;
|
||||
const uint8_t *issuerp;
|
||||
size_t issuerlen;
|
||||
const uint8_t *serialp;
|
||||
size_t seriallen;
|
||||
|
||||
sm3_digest((uint8_t *)"abc", 3, keyid);
|
||||
rand_bytes(serial, sizeof(serial));
|
||||
|
||||
if (x509_authority_key_identifier_to_der(
|
||||
keyid, sizeof(keyid),
|
||||
general_names, sizeof(general_names),
|
||||
serial, sizeof(serial),
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_authority_key_identifier_print(stderr, 0, 0, "AuthorityKeyIdentifier", d, dlen);
|
||||
|
||||
p = buf;
|
||||
cp = buf;
|
||||
len = 0;
|
||||
if (x509_authority_key_identifier_to_der(
|
||||
keyid, sizeof(keyid),
|
||||
general_names, sizeof(general_names),
|
||||
serial, sizeof(serial),
|
||||
&p, &len) != 1
|
||||
|| x509_authority_key_identifier_from_der(
|
||||
&keyidp, &keyidlen,
|
||||
&issuerp, &issuerlen,
|
||||
&serialp, &seriallen,
|
||||
&cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -209,6 +301,9 @@ static int test_x509_key_usage(void)
|
||||
int usage;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= 8; i++) {
|
||||
format_print(stderr, 0, 4, "%d %s\n", i, x509_key_usage_name(1 << i));
|
||||
}
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
||||
if (x509_key_usage_to_der(tests[i], &p, &len) != 1) {
|
||||
error_print();
|
||||
@@ -232,16 +327,15 @@ static int test_x509_key_usage(void)
|
||||
|
||||
static int test_x509_notice_reference(void)
|
||||
{
|
||||
int notice_nums[] = { 1,2,3,4,5 };
|
||||
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int notice_nums[] = { 1,2,3,4,5 };
|
||||
|
||||
int org_tag;
|
||||
const uint8_t *org;
|
||||
size_t orglen;
|
||||
@@ -280,6 +374,383 @@ static int test_x509_notice_reference(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_user_notice(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int notice_nums[] = { 1,2,3,4,5 };
|
||||
|
||||
int org_tag;
|
||||
const uint8_t *org;
|
||||
size_t orglen;
|
||||
int nums[32];
|
||||
size_t nums_cnt;
|
||||
int text_tag;
|
||||
const uint8_t *text;
|
||||
size_t textlen;
|
||||
|
||||
if (x509_user_notice_to_der(
|
||||
ASN1_TAG_IA5String, (uint8_t *)"Hello", 5,
|
||||
notice_nums, sizeof(notice_nums)/sizeof(notice_nums[0]),
|
||||
ASN1_TAG_IA5String, (uint8_t *)"World", 5,
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_user_notice_print(stderr, 0, 0, "UserNotice", d, dlen);
|
||||
|
||||
p = buf;
|
||||
cp = buf;
|
||||
len = 0;
|
||||
|
||||
if (x509_user_notice_to_der(
|
||||
ASN1_TAG_IA5String, (uint8_t *)"Hello", 5,
|
||||
notice_nums, sizeof(notice_nums)/sizeof(notice_nums[0]),
|
||||
ASN1_TAG_IA5String, (uint8_t *)"World", 5,
|
||||
&p, &len) != 1
|
||||
|| x509_user_notice_from_der(
|
||||
&org_tag, &org, &orglen,
|
||||
nums, &nums_cnt, sizeof(nums)/sizeof(nums[0]),
|
||||
&text_tag, &text, &textlen,
|
||||
&cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_policy_qualifier_info(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
|
||||
if (x509_policy_qualifier_info_to_der(
|
||||
OID_qt_cps,
|
||||
(uint8_t *)"Qualifier", strlen("Qualifier"),
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_policy_qualifier_info_print(stderr, 0, 0, "PolicyQualifierInfo", d, dlen);
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_policy_mapping(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int issuer_policy_oid;
|
||||
uint32_t issuer_policy_nodes[32];
|
||||
size_t issuer_policy_nodes_cnt;
|
||||
int subject_policy_oid;
|
||||
uint32_t subject_policy_nodes[32];
|
||||
size_t subject_policy_nodes_cnt;
|
||||
|
||||
if (x509_policy_mapping_to_der(
|
||||
OID_any_policy, NULL, 0,
|
||||
OID_any_policy, NULL, 0,
|
||||
&p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_policy_mapping_print(stderr, 0, 0, "PolicyMapping", d, dlen);
|
||||
|
||||
p = buf;
|
||||
cp = buf;
|
||||
len = 0;
|
||||
|
||||
if (x509_policy_mapping_to_der(
|
||||
OID_any_policy, NULL, 0,
|
||||
OID_any_policy, NULL, 0,
|
||||
&p, &len) != 1
|
||||
|| x509_policy_mapping_from_der(
|
||||
&issuer_policy_oid, issuer_policy_nodes, &issuer_policy_nodes_cnt,
|
||||
&subject_policy_oid, subject_policy_nodes, &subject_policy_nodes_cnt,
|
||||
&cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 这里的一些OID应该在RFC中有,但是我们不实现
|
||||
static int test_x509_attribute(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int test_x509_basic_constraints(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int ca;
|
||||
int path;
|
||||
|
||||
if (x509_basic_constraints_to_der(1, 4, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_basic_constraints_print(stderr, 0, 0, "BasicConstraints", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (x509_basic_constraints_to_der(-1, 4, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_basic_constraints_print(stderr, 0, 0, "BasicConstraints", d, dlen);
|
||||
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (x509_basic_constraints_to_der(-1, -1, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_basic_constraints_print(stderr, 0, 0, "BasicConstraints", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (x509_basic_constraints_to_der(1, 4, &p, &len) != 1
|
||||
|| x509_basic_constraints_from_der(&ca, &path, &cp, &len) != 1
|
||||
|| asn1_check(ca == 1) != 1
|
||||
|| asn1_check(path == 4) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (x509_basic_constraints_to_der(-1, 4, &p, &len) != 1
|
||||
|| x509_basic_constraints_from_der(&ca, &path, &cp, &len) != 1
|
||||
|| asn1_check(ca == 0) != 1
|
||||
|| asn1_check(path == 4) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (x509_basic_constraints_to_der(-1, -1, &p, &len) != 1 // should return error
|
||||
|| x509_basic_constraints_from_der(&ca, &path, &cp, &len) != -1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_general_subtree(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
uint8_t *dns = (uint8_t *)"www.pku.edu.cn";
|
||||
size_t dnslen = strlen((char *)dns);
|
||||
|
||||
int choice;
|
||||
const uint8_t *dns_name;
|
||||
size_t dns_name_len;
|
||||
int min_dis;
|
||||
int max_dis;
|
||||
|
||||
if (x509_general_subtree_to_der(X509_gn_dns_name, dns, dnslen, 1, 5, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_general_subtree_print(stderr, 0, 0, "GeneralSubtree", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
min_dis = max_dis = 99;
|
||||
if (x509_general_subtree_to_der(X509_gn_dns_name, dns, dnslen, -1, 5, &p, &len) != 1
|
||||
|| x509_general_subtree_from_der(&choice, &dns_name, &dns_name_len, &min_dis, &max_dis, &cp, &len) != 1
|
||||
|| asn1_check(choice == X509_gn_dns_name) != 1
|
||||
|| asn1_check(dns_name_len == dnslen && memcmp(dns_name, dns, dnslen) == 0) != 1
|
||||
|| asn1_check(min_dis == 0) != 1
|
||||
|| asn1_check(max_dis == 5) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
min_dis = max_dis = 99;
|
||||
if (x509_general_subtree_to_der(X509_gn_dns_name, dns, dnslen, 1, -1, &p, &len) != 1
|
||||
|| x509_general_subtree_from_der(&choice, &dns_name, &dns_name_len, &min_dis, &max_dis, &cp, &len) != 1
|
||||
|| asn1_check(choice == X509_gn_dns_name) != 1
|
||||
|| asn1_check(dns_name_len == dnslen && memcmp(dns_name, dns, dnslen) == 0) != 1
|
||||
|| asn1_check(min_dis == 1) != 1
|
||||
|| asn1_check(max_dis == -1) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_policy_constraints(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int val1;
|
||||
int val2;
|
||||
|
||||
if (x509_policy_constraints_to_der(2, 5, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_policy_constraints_print(stderr, 0, 0, "PolicyConstraints", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (x509_policy_constraints_to_der(2, -1, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_policy_constraints_print(stderr, 0, 0, "PolicyConstraints", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
if (x509_policy_constraints_to_der(-1, 5, &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_policy_constraints_print(stderr, 0, 0, "PolicyConstraints", d, dlen);
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
val1 = val2 = 99;
|
||||
if (x509_policy_constraints_to_der(2, 5, &p, &len) != 1
|
||||
|| x509_policy_constraints_from_der(&val1, &val2, &cp, &len) != 1
|
||||
|| asn1_check(val1 == 2) != 1
|
||||
|| asn1_check(val2 == 5) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp = p = buf; len = 0;
|
||||
val1 = val2 = 99;
|
||||
if (x509_policy_constraints_to_der(-1, -1, &p, &len) != 1
|
||||
|| x509_policy_constraints_from_der(&val1, &val2, &cp, &len) != 1
|
||||
|| asn1_check(val1 == -1) != 1
|
||||
|| asn1_check(val2 == -1) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_ext_key_usage(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
int kp[] = {
|
||||
OID_kp_server_auth,
|
||||
OID_kp_client_auth,
|
||||
OID_kp_code_signing,
|
||||
OID_kp_email_protection,
|
||||
OID_kp_time_stamping,
|
||||
OID_kp_ocsp_signing,
|
||||
};
|
||||
int oids[16] = {0};
|
||||
size_t oids_cnt;
|
||||
int i;
|
||||
|
||||
if (x509_ext_key_usage_to_der(kp, sizeof(kp)/sizeof(int), &p, &len) != 1
|
||||
|| asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_ext_key_usage_print(stderr, 0, 0, "ExtKeyUsageSyntax", d, dlen);
|
||||
|
||||
if (x509_ext_key_usage_to_der(kp, sizeof(kp)/sizeof(int), &p, &len) != 1
|
||||
|| x509_ext_key_usage_from_der(oids, &oids_cnt, sizeof(oids)/sizeof(oids[0]), &cp, &len) != 1
|
||||
|| asn1_check(oids_cnt == sizeof(kp)/sizeof(int)) != 1
|
||||
|| asn1_check(memcmp(oids, kp, sizeof(kp)) == 0) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_revoke_reasons(void)
|
||||
{
|
||||
int tests[] = {
|
||||
@@ -317,6 +788,99 @@ static int test_x509_revoke_reasons(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_exts(void)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
uint8_t exts[512];
|
||||
size_t extslen = 0;
|
||||
uint8_t keyid[32] = {1};
|
||||
uint8_t serial[20] = {2};
|
||||
|
||||
if (0
|
||||
|| x509_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts), 1,
|
||||
keyid, sizeof(keyid),
|
||||
general_names, sizeof(general_names),
|
||||
serial, sizeof(serial)) != 1
|
||||
|| x509_exts_add_subject_key_identifier(exts, &extslen, sizeof(exts), 0,
|
||||
keyid, sizeof(keyid)) != 1
|
||||
|| x509_exts_add_key_usage(exts, &extslen, sizeof(exts), 0,
|
||||
X509_KU_NON_REPUDIATION|X509_KU_CRL_SIGN) != 1
|
||||
|| x509_exts_to_der(exts, extslen, &p, &len) != 1
|
||||
|| x509_exts_from_der(&d, &dlen, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_exts_print(stderr, 0, 0, "Extensions", d, dlen);
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_x509_cert_with_exts(void)
|
||||
{
|
||||
uint8_t cert[1024];
|
||||
size_t certlen;
|
||||
uint8_t serial[20];
|
||||
uint8_t name[256];
|
||||
size_t namelen;
|
||||
time_t not_before, not_after;
|
||||
SM2_KEY sm2_key;
|
||||
uint8_t uniq_id[32];
|
||||
uint8_t exts[512];
|
||||
size_t extslen = 0;
|
||||
uint8_t keyid[32] = {1};
|
||||
|
||||
|
||||
rand_bytes(serial, sizeof(serial));
|
||||
x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "CA");
|
||||
time(¬_before);
|
||||
x509_validity_add_days(¬_after, not_before, 365);
|
||||
sm2_key_generate(&sm2_key);
|
||||
sm3_digest((uint8_t *)&(sm2_key.public_key), sizeof(SM2_POINT), uniq_id);
|
||||
|
||||
if (x509_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts), 1,
|
||||
keyid, sizeof(keyid),
|
||||
general_names, sizeof(general_names),
|
||||
serial, sizeof(serial)) != 1
|
||||
|| x509_exts_add_subject_key_identifier(exts, &extslen, sizeof(exts), 0,
|
||||
keyid, sizeof(keyid)) != 1
|
||||
|| x509_exts_add_key_usage(exts, &extslen, sizeof(exts), 0,
|
||||
X509_KU_NON_REPUDIATION|X509_KU_CRL_SIGN) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x509_cert_sign(
|
||||
cert, &certlen, sizeof(cert),
|
||||
X509_version_v3,
|
||||
serial, sizeof(serial),
|
||||
OID_sm2sign_with_sm3,
|
||||
name, namelen,
|
||||
not_before, not_after,
|
||||
name, namelen,
|
||||
&sm2_key,
|
||||
uniq_id, sizeof(uniq_id),
|
||||
uniq_id, sizeof(uniq_id),
|
||||
exts, extslen,
|
||||
&sm2_key,
|
||||
SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
x509_cert_print(stderr, 0, 0, "Certificate", cert, certlen);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -324,11 +888,21 @@ static int test_x509_revoke_reasons(void)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int err = 0;
|
||||
err += test_x509_other_name();
|
||||
err += test_x509_edi_party_name();
|
||||
//err += test_x509_other_name();
|
||||
//err += test_x509_edi_party_name();
|
||||
err += test_x509_general_name();
|
||||
err += test_x509_authority_key_identifier();
|
||||
err += test_x509_key_usage();
|
||||
err += test_x509_notice_reference();
|
||||
err += test_x509_user_notice();
|
||||
err += test_x509_policy_qualifier_info();
|
||||
err += test_x509_policy_mapping();
|
||||
err += test_x509_basic_constraints();
|
||||
err += test_x509_general_subtree();
|
||||
err += test_x509_policy_constraints();
|
||||
err += test_x509_ext_key_usage();
|
||||
err += test_x509_revoke_reasons();
|
||||
err += test_x509_exts();
|
||||
err += test_x509_cert_with_exts();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -419,28 +419,19 @@ static int test_x509_cert(void)
|
||||
}
|
||||
x509_cert_print(stderr, 0, 4, "Certificate", cert, certlen);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int test_x509_cert_request(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err = 0;
|
||||
// err += test_x509_version();
|
||||
// err += test_x509_validity();
|
||||
// err += test_x509_attr_type_and_value();
|
||||
// err += test_x509_rdn();
|
||||
// err += test_x509_name();
|
||||
// err += test_x509_public_key_info();
|
||||
// err += test_x509_tbs_cert();
|
||||
err += test_x509_version();
|
||||
err += test_x509_validity();
|
||||
err += test_x509_attr_type_and_value();
|
||||
err += test_x509_rdn();
|
||||
err += test_x509_name();
|
||||
err += test_x509_public_key_info();
|
||||
err += test_x509_tbs_cert();
|
||||
err += test_x509_cert();
|
||||
//err += test_x509_cert_request();
|
||||
//test_x509_extensions();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -61,43 +61,13 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static const char *options = "[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num -key file [-pass pass]";
|
||||
|
||||
/*
|
||||
from RFC 2253
|
||||
|
||||
String X.500 AttributeType
|
||||
------------------------------
|
||||
CN commonName
|
||||
L localityName
|
||||
ST stateOrProvinceName
|
||||
O organizationName
|
||||
OU organizationalUnitName
|
||||
C countryName
|
||||
STREET streetAddress
|
||||
DC domainComponent
|
||||
UID userid
|
||||
*/
|
||||
|
||||
void print_usage(const char *prog)
|
||||
{
|
||||
printf("Usage: %s command [options] ...\n", prog);
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -C <str> country name\n");
|
||||
printf(" -ST <str> state of province name\n");
|
||||
printf(" -L <str> locality name\n");
|
||||
printf(" -O <str> orgnization name\n");
|
||||
printf(" -OU <str> orgnizational unit name\n");
|
||||
printf(" -CN <str> common name\n");
|
||||
printf(" -days <num> validity days\n");
|
||||
printf(" -key <file> private key file\n");
|
||||
printf(" -pass pass password\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = 1;
|
||||
char *prog = argv[0];
|
||||
|
||||
char *country = NULL;
|
||||
char *state = NULL;
|
||||
char *locality = NULL;
|
||||
@@ -126,72 +96,68 @@ int main(int argc, char **argv)
|
||||
|
||||
while (argc > 0) {
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
print_usage(prog);
|
||||
help:
|
||||
printf("usage: %s %s\n", prog, options);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(*argv, "-CN")) {
|
||||
if (--argc < 1) goto bad;
|
||||
common_name = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-O")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-OU")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org_unit = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-C")) {
|
||||
if (--argc < 1) goto bad;
|
||||
country = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-ST")) {
|
||||
if (--argc < 1) goto bad;
|
||||
state = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-L")) {
|
||||
if (--argc < 1) goto bad;
|
||||
locality = *(++argv);
|
||||
} else if (!strcmp(*argv, "-key")) {
|
||||
if (--argc < 1) goto bad;
|
||||
keyfile = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-days")) {
|
||||
if (--argc < 1) goto bad;
|
||||
days = atoi(*(++argv));
|
||||
|
||||
} else if (!strcmp(*argv, "-pass")) {
|
||||
if (--argc < 1) goto bad;
|
||||
pass = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-out")) {
|
||||
if (--argc < 1) goto bad;
|
||||
outfile = *(++argv);
|
||||
|
||||
|
||||
} else {
|
||||
bad:
|
||||
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
|
||||
print_usage(prog);
|
||||
return 0;
|
||||
fprintf(stderr, "usage: %s %s\n", prog, options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (days <= 0 || !keyfile) {
|
||||
error_print();
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(keyfp = fopen(keyfile, "r"))) {
|
||||
error_print();
|
||||
goto bad;
|
||||
if (!common_name || days <= 0 || !keyfile) {
|
||||
fprintf(stderr, "%s: missing options\n", prog);
|
||||
fprintf(stderr, "usage: %s %s\n", prog, options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pass) {
|
||||
#ifndef WIN32
|
||||
pass = getpass("Encryption Password : ");
|
||||
#else
|
||||
}
|
||||
if (!pass || strlen(pass) == 0) {
|
||||
fprintf(stderr, "%s: '-pass' option required\n", prog);
|
||||
#endif
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!(keyfp = fopen(keyfile, "r"))
|
||||
|| sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (outfile) {
|
||||
@@ -202,8 +168,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
time(¬_before);
|
||||
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1
|
||||
|| rand_bytes(serial, sizeof(serial)) != 1
|
||||
if (rand_bytes(serial, sizeof(serial)) != 1
|
||||
|| x509_name_set(name, &namelen, sizeof(name),
|
||||
country, state, locality, org, org_unit, common_name) != 1
|
||||
|| x509_validity_add_days(¬_after, not_before, days) != 1
|
||||
@@ -224,11 +189,9 @@ int main(int argc, char **argv)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
fprintf(stderr, "%s: commands should not be used together\n", prog);
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
return -1;
|
||||
memset(&sm2_key, 0, sizeof(SM2_KEY));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -53,26 +53,55 @@
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
static const char *options = "[-in file]";
|
||||
|
||||
int main(void)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t cert[1024];
|
||||
char *prog = argv[0];
|
||||
char *infile = NULL;
|
||||
FILE *infp = stdin;
|
||||
|
||||
uint8_t cert[18192];
|
||||
size_t certlen;
|
||||
|
||||
for (;;) {
|
||||
int ret = x509_cert_from_pem(cert, &certlen, sizeof(cert), stdin);
|
||||
if (ret < 0) {
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
while (argc > 0) {
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
printf("usage: %s %s\n", prog, options);
|
||||
return 0;
|
||||
} else if (!strcmp(*argv, "-in")) {
|
||||
if (--argc < 1) goto bad;
|
||||
infile = *(++argv);
|
||||
} else {
|
||||
bad:
|
||||
fprintf(stderr, "%s: llegal option '%s'\n", prog, *argv);
|
||||
printf("usage: %s %s\n", prog, options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (infile) {
|
||||
if (!(infp = fopen(infile, "r"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
if ((ret = x509_cert_from_pem(cert, &certlen, sizeof(cert), infp)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (!ret) {
|
||||
break;
|
||||
}
|
||||
fprintf(stdout, "Certificate\n");
|
||||
x509_cert_print(stdout, 0, 0, "Certificate", cert, certlen);
|
||||
x509_cert_to_pem(cert, certlen, stdout);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
135
tools/reqgen.c
135
tools/reqgen.c
@@ -62,25 +62,9 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void print_usage(const char *prog)
|
||||
{
|
||||
printf("usage: %s command [options] ...\n", prog);
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -C <str> country name\n");
|
||||
printf(" -O <str> orgnization name\n");
|
||||
printf(" -OU <str> orgnizational unit name\n");
|
||||
printf(" -CN <str> common name\n");
|
||||
printf(" -L <str> locality name\n");
|
||||
printf(" -ST <str> state of province name\n");
|
||||
printf("\n");
|
||||
printf(" -days <num> validity days\n");
|
||||
printf(" -keyfile <file> private key file\n");
|
||||
printf(" -pass password password\n");
|
||||
printf(" -out file output req file\n");
|
||||
}
|
||||
static const char *options =
|
||||
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num"
|
||||
" -key file [-pass pass] [-out file]";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -88,6 +72,7 @@ int main(int argc, char **argv)
|
||||
char *prog = argv[0];
|
||||
char *country = NULL;
|
||||
char *state = NULL;
|
||||
char *locality = NULL;
|
||||
char *org = NULL;
|
||||
char *org_unit = NULL;
|
||||
char *common_name = NULL;
|
||||
@@ -107,10 +92,9 @@ int main(int argc, char **argv)
|
||||
|
||||
SM2_KEY sm2_key; // 这个应该是从文件中读取的!
|
||||
|
||||
|
||||
if (argc < 2) {
|
||||
print_usage(prog);
|
||||
return 0;
|
||||
fprintf(stderr, "usage: %s %s\n", prog, options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
argc--;
|
||||
@@ -118,114 +102,89 @@ int main(int argc, char **argv)
|
||||
|
||||
while (argc >= 1) {
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
print_usage(prog);
|
||||
printf("usage: %s %s\n", prog, options);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(*argv, "-CN")) {
|
||||
if (--argc < 1) goto bad;
|
||||
common_name = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-O")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-OU")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org_unit = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-C")) {
|
||||
if (--argc < 1) goto bad;
|
||||
country = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-ST")) {
|
||||
if (--argc < 1) goto bad;
|
||||
state = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-keyfile")) {
|
||||
} else if (!strcmp(*argv, "-L")) {
|
||||
if (--argc < 1) goto bad;
|
||||
locality = *(++argv);
|
||||
} else if (!strcmp(*argv, "-O")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org = *(++argv);
|
||||
} else if (!strcmp(*argv, "-OU")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org_unit = *(++argv);
|
||||
} else if (!strcmp(*argv, "-CN")) {
|
||||
if (--argc < 1) goto bad;
|
||||
common_name = *(++argv);
|
||||
} else if (!strcmp(*argv, "-key")) {
|
||||
if (--argc < 1) goto bad;
|
||||
keyfile = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-pass")) {
|
||||
if (--argc < 1) goto bad;
|
||||
pass = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-days")) {
|
||||
if (--argc < 1) goto bad;
|
||||
days = atoi(*(++argv));
|
||||
|
||||
} else if (!strcmp(*argv, "-out")) {
|
||||
if (--argc < 1) goto bad;
|
||||
outfile = *(++argv);
|
||||
|
||||
} else {
|
||||
print_usage(prog);
|
||||
return 0;
|
||||
break;
|
||||
bad:
|
||||
fprintf(stderr, "usage: %s %s\n", prog, options);
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (days <= 0 && !keyfile) {
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(keyfp = fopen(keyfile, "r"))) {
|
||||
goto bad;
|
||||
if (!common_name || days <= 0 || !keyfile) {
|
||||
fprintf(stderr, "%s: missing options\n", prog);
|
||||
fprintf(stderr, "usage: %s %s\n", prog, options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (outfile) {
|
||||
if (!(outfp = fopen(outfile, "w"))) {
|
||||
if (!(outfp = fopen(outfile, "wb"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pass) {
|
||||
#ifndef WIN32
|
||||
pass = getpass("Encryption Password : ");
|
||||
#else
|
||||
}
|
||||
if (!pass || strlen(pass) == 0) {
|
||||
fprintf(stderr, "%s: '-pass' option required\n", prog);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
if (!(keyfp = fopen(keyfile, "r"))
|
||||
|| sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (x509_name_set(name, &namelen, sizeof(name),
|
||||
country, state, NULL, org, org_unit, common_name) != 1) {
|
||||
country, state, NULL, org, org_unit, common_name) != 1
|
||||
|| x509_req_sign(req, &reqlen, sizeof(req),
|
||||
X509_version_v1,
|
||||
name, namelen,
|
||||
&sm2_key,
|
||||
NULL, 0,
|
||||
OID_sm2sign_with_sm3,
|
||||
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1
|
||||
|| x509_req_to_pem(req, reqlen, outfp) != 1) {
|
||||
memset(&sm2_key, 0, sizeof(SM2_KEY));
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (x509_req_sign(req, &reqlen, sizeof(req),
|
||||
X509_version_v1,
|
||||
name, namelen,
|
||||
&sm2_key,
|
||||
NULL, 0,
|
||||
OID_sm2sign_with_sm3,
|
||||
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (x509_req_to_pem(req, reqlen, outfp) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto end;
|
||||
|
||||
bad:
|
||||
fprintf(stderr, "%s: commands should not be used together\n", prog);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
memset(&sm2_key, 0, sizeof(SM2_KEY));
|
||||
return 0;
|
||||
}
|
||||
|
||||
238
tools/reqsign.c
238
tools/reqsign.c
@@ -52,174 +52,162 @@
|
||||
#include <unistd.h>
|
||||
#include <gmssl/pem.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/x509_req.h>
|
||||
#include <gmssl/pkcs8.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
|
||||
void print_usage(const char *prog)
|
||||
{
|
||||
printf("Usage: %s command [options] ...\n", prog);
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -req <file> PKCS #10 certificate request file\n");
|
||||
printf(" -cacert <file> CA certificate file\n");
|
||||
printf(" -keyfile <file> private key of cacert\n");
|
||||
}
|
||||
static const char *usage = "usage: %s [-in file] -days num -cacert file -key file [-pass str] [-out file]\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = -1;
|
||||
char *prog = argv[0];
|
||||
char *infile = NULL;
|
||||
char *outfile = NULL;
|
||||
char *cacertfile = NULL;
|
||||
char *keyfile = NULL;
|
||||
char *pass = NULL;
|
||||
int days = 0;
|
||||
|
||||
FILE *infp = stdin;
|
||||
uint8_t req[512];
|
||||
size_t reqlen;
|
||||
const uint8_t *subject;
|
||||
size_t subject_len;
|
||||
SM2_KEY subject_public_key;
|
||||
|
||||
FILE *outfp = stdout;
|
||||
|
||||
FILE *cacertfp = NULL;
|
||||
uint8_t cacert[1024];
|
||||
size_t cacertlen;
|
||||
const uint8_t *issuer;
|
||||
size_t issuer_len;
|
||||
SM2_KEY issuer_public_key;
|
||||
|
||||
FILE *keyfp = NULL;
|
||||
SM2_KEY sm2_key;
|
||||
|
||||
X509_CERTIFICATE cert;
|
||||
|
||||
char *pass;
|
||||
|
||||
uint8_t cert[1024];
|
||||
size_t certlen;
|
||||
uint8_t serial[12];
|
||||
X509_NAME name;
|
||||
time_t not_before;
|
||||
SM2_KEY sm2_key; // 这个应该是从文件中读取的!
|
||||
uint8_t uniq_id[32];
|
||||
time_t not_before, not_after;
|
||||
|
||||
uint8_t buf[1024];
|
||||
const uint8_t *cp = buf;
|
||||
uint8_t *p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
print_usage(prog);
|
||||
return 0;
|
||||
fprintf(stderr, usage, prog);
|
||||
return 1;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
while (argc >= 1) {
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
print_usage(prog);
|
||||
help:
|
||||
printf(usage, prog);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(*argv, "-CN")) {
|
||||
} else if (!strcmp(*argv, "-in")) {
|
||||
if (--argc < 1) goto bad;
|
||||
common_name = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-O")) {
|
||||
infile = *(++argv);
|
||||
} else if (!strcmp(*argv, "-cacert")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-OU")) {
|
||||
if (--argc < 1) goto bad;
|
||||
org_unit = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-C")) {
|
||||
if (--argc < 1) goto bad;
|
||||
country = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-ST")) {
|
||||
if (--argc < 1) goto bad;
|
||||
state = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-keyfile")) {
|
||||
cacertfile = *(++argv);
|
||||
} else if (!strcmp(*argv, "-key")) {
|
||||
if (--argc < 1) goto bad;
|
||||
keyfile = *(++argv);
|
||||
|
||||
} else if (!strcmp(*argv, "-pass")) {
|
||||
if (--argc < 1) goto bad;
|
||||
pass = *(++argv);
|
||||
} else if (!strcmp(*argv, "-days")) {
|
||||
if (--argc < 1) goto bad;
|
||||
days = atoi(*(++argv));
|
||||
|
||||
} else if (!strcmp(*argv, "-out")) {
|
||||
if (--argc < 1) goto bad;
|
||||
outfile = *(++argv);
|
||||
} else {
|
||||
print_usage(prog);
|
||||
return 0;
|
||||
bad:
|
||||
error_print();
|
||||
break;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (days <= 0 && !keyfile) {
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(keyfp = fopen(keyfile, "r"))) {
|
||||
goto bad;
|
||||
}
|
||||
|
||||
pass = getpass("Password : ");
|
||||
if (sm2_enced_private_key_info_from_pem(&sm2_key, pass, keyfp) != 1) {
|
||||
if (days <= 0
|
||||
|| !cacertfile
|
||||
|| !keyfile) {
|
||||
error_print();
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (infile) {
|
||||
if (!(infp = fopen(infile, "r"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (x509_req_from_pem(req, &reqlen, sizeof(req), infp) != 1
|
||||
|| x509_req_get_details(req, reqlen,
|
||||
NULL, &subject, &subject_len, &subject_public_key,
|
||||
NULL, NULL, NULL, NULL, NULL) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(cacertfp = fopen(cacertfile, "r"))
|
||||
|| x509_cert_from_pem(cacert, &cacertlen, sizeof(cacert), cacertfp) != 1
|
||||
|| x509_cert_get_subject(cacert, cacertlen, &issuer, &issuer_len) != 1
|
||||
|| x509_cert_get_subject_public_key(cacert, cacertlen, &issuer_public_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (outfile) {
|
||||
if (!(outfp = fopen(outfile, "w"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pass) {
|
||||
pass = getpass("Password : ");
|
||||
}
|
||||
if (!pass || strlen(pass) == 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!(keyfp = fopen(keyfile, "r"))
|
||||
|| sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1
|
||||
|| sm2_public_key_equ(&sm2_key, &issuer_public_key) != 1) {
|
||||
error_print();
|
||||
memset(&sm2_key, 0, sizeof(SM2_KEY));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rand_bytes(serial, sizeof(serial));
|
||||
|
||||
|
||||
|
||||
memset(&name, 0, sizeof(name));
|
||||
|
||||
|
||||
|
||||
if (country) {
|
||||
if (x509_name_set_country(&name, country) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (state) {
|
||||
if (x509_name_set_state_or_province(&name, state) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (org) {
|
||||
if (x509_name_set_organization(&name, org) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (org_unit) {
|
||||
if (x509_name_set_organizational_unit(&name, org_unit) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (!common_name) {
|
||||
error_print();
|
||||
goto end;
|
||||
} else {
|
||||
if (x509_name_set_common_name(&name, common_name) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
time(¬_before);
|
||||
|
||||
if (x509_validity_add_days(¬_after, not_before, days) != 1
|
||||
|| x509_cert_sign(
|
||||
cert, &certlen, sizeof(cert),
|
||||
X509_version_v3,
|
||||
serial, sizeof(serial),
|
||||
OID_sm2sign_with_sm3,
|
||||
subject, subject_len,
|
||||
not_before, not_after,
|
||||
issuer, issuer_len,
|
||||
&subject_public_key,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|
||||
|| x509_cert_to_pem(cert, certlen, outfp) != 1) {
|
||||
memset(&sm2_key, 0, sizeof(SM2_KEY));
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&cert, 0, sizeof(cert));
|
||||
x509_certificate_set_version(&cert, X509_version_v3);
|
||||
x509_certificate_set_serial_number(&cert, serial, sizeof(serial));
|
||||
x509_certificate_set_signature_algor(&cert, OID_sm2sign_with_sm3);
|
||||
x509_certificate_set_issuer(&cert, &name);
|
||||
x509_certificate_set_subject(&cert, &name);
|
||||
x509_certificate_set_validity(&cert, not_before, days);
|
||||
x509_certificate_set_subject_public_key_info_sm2(&cert, &sm2_key);
|
||||
x509_certificate_set_issuer_unique_id(&cert, uniq_id, sizeof(uniq_id));
|
||||
x509_certificate_set_subject_unique_id(&cert, uniq_id, sizeof(uniq_id));
|
||||
x509_certificate_sign_sm2(&cert, &sm2_key);
|
||||
|
||||
x509_certificate_to_pem(&cert, stdout);
|
||||
ret = 0;
|
||||
goto end;
|
||||
|
||||
bad:
|
||||
fprintf(stderr, "%s: commands should not be used together\n", prog);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
memset(&sm2_key, 0, sizeof(SM2_KEY));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ int main(int argc, char **argv)
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
help:
|
||||
fprintf(stderr, "usage: %s -key pem [-pass password] [-in file] [-out file]\n", prog);
|
||||
goto help;
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(*argv, "-key")) {
|
||||
if (--argc < 1) goto bad;
|
||||
@@ -156,9 +156,6 @@ help:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
error_print_msg("outlen = %zu\n", outlen);
|
||||
|
||||
if (outlen != fwrite(outbuf, 1, outlen, outfp)) {
|
||||
error_print();
|
||||
return -1;
|
||||
|
||||
@@ -64,9 +64,10 @@ int main(int argc, char **argv)
|
||||
size_t keylen;
|
||||
FILE *in = stdin;
|
||||
SM3_HMAC_CTX ctx;
|
||||
unsigned char dgst[32];
|
||||
unsigned char buf[4096];
|
||||
uint8_t dgst[32];
|
||||
uint8_t buf[4096];
|
||||
size_t len;
|
||||
size_t i;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
@@ -114,8 +115,13 @@ help:
|
||||
}
|
||||
sm3_hmac_finish(&ctx, dgst);
|
||||
|
||||
|
||||
format_bytes(stdout, 0, 0, "", dgst, sizeof(dgst));
|
||||
for (i = 0; i < sizeof(dgst); i++) {
|
||||
printf("%02x", dgst[i]);
|
||||
}
|
||||
if (infile) {
|
||||
printf(" : %s", infile);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(key, 0, sizeof(key));
|
||||
|
||||
Reference in New Issue
Block a user