diff --git a/CMakeLists.txt b/CMakeLists.txt index 56be0371..bbd69ea4 100644 --- a/CMakeLists.txt +++ b/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) diff --git a/README.md b/README.md index b92c42b1..25e06c1d 100644 --- a/README.md +++ b/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协议嵌入到现有的项目中。 diff --git a/include/gmssl/asn1.h b/include/gmssl/asn1.h index 17a17885..d5449ffb 100644 --- a/include/gmssl/asn1.h +++ b/include/gmssl/asn1.h @@ -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); diff --git a/include/gmssl/ec.h b/include/gmssl/ec.h index d45ea9c2..d1995a23 100644 --- a/include/gmssl/ec.h +++ b/include/gmssl/ec.h @@ -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 } diff --git a/include/gmssl/error.h b/include/gmssl/error.h index 81a56e61..9003a195 100644 --- a/include/gmssl/error.h +++ b/include/gmssl/error.h @@ -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, ...); diff --git a/include/gmssl/oid.h b/include/gmssl/oid.h index 85963858..9bcb745a 100644 --- a/include/gmssl/oid.h +++ b/include/gmssl/oid.h @@ -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 diff --git a/include/gmssl/pbkdf2.h b/include/gmssl/pbkdf2.h index e9afc085..a4e63ab0 100644 --- a/include/gmssl/pbkdf2.h +++ b/include/gmssl/pbkdf2.h @@ -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); diff --git a/include/gmssl/rsa.h b/include/gmssl/rsa.h new file mode 100644 index 00000000..c22eda74 --- /dev/null +++ b/include/gmssl/rsa.h @@ -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 +#include +#include + + +#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 diff --git a/include/gmssl/sm2.h b/include/gmssl/sm2.h index 92a8859d..418c58b2 100644 --- a/include/gmssl/sm2.h +++ b/include/gmssl/sm2.h @@ -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); diff --git a/include/gmssl/x509.h b/include/gmssl/x509.h index 20340089..a61da3e1 100644 --- a/include/gmssl/x509.h +++ b/include/gmssl/x509.h @@ -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); diff --git a/include/gmssl/x509_alg.h b/include/gmssl/x509_alg.h index d1fe4d89..7095659f 100644 --- a/include/gmssl/x509_alg.h +++ b/include/gmssl/x509_alg.h @@ -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 diff --git a/include/gmssl/x509_ext.h b/include/gmssl/x509_ext.h index 9d29d08e..4ee0eae4 100644 --- a/include/gmssl/x509_ext.h +++ b/include/gmssl/x509_ext.h @@ -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 + diff --git a/include/gmssl/x509_oid.h b/include/gmssl/x509_oid.h index 89b94a1c..b875fdae 100644 --- a/include/gmssl/x509_oid.h +++ b/include/gmssl/x509_oid.h @@ -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); diff --git a/src/asn1.c b/src/asn1.c index e02045cb..ea91aa6f 100644 --- a/src/asn1.c +++ b/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; } diff --git a/src/cms.c b/src/cms.c index 96baa614..d3467828 100644 --- a/src/cms.c +++ b/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) { diff --git a/src/ec.c b/src/ec.c new file mode 100644 index 00000000..3eadd792 --- /dev/null +++ b/src/ec.c @@ -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 +#include +#include +#include +#include + + +#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; +} diff --git a/src/pbkdf2.c b/src/pbkdf2.c index f6f6efd3..8512246f 100644 --- a/src/pbkdf2.c +++ b/src/pbkdf2.c @@ -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); +} + diff --git a/src/rsa.c b/src/rsa.c new file mode 100644 index 00000000..530d2e44 --- /dev/null +++ b/src/rsa.c @@ -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 +#include +#include +#include +#include +#include +#include + + +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; +} diff --git a/src/sm2_algo.c b/src/sm2_algo.c index a1a36901..ad86e27d 100644 --- a/src/sm2_algo.c +++ b/src/sm2_algo.c @@ -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)); diff --git a/src/sm2_asn1.c b/src/sm2_asn1.c index 1f5a7de5..e96b5cec 100644 --- a/src/sm2_asn1.c +++ b/src/sm2_asn1.c @@ -56,8 +56,8 @@ #include #include #include - -// sm2 curve 1.2.156.10197.1.301 +#include +#include 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; } diff --git a/src/sm2_lib.c b/src/sm2_lib.c index 4e3bf406..3056e667 100644 --- a/src/sm2_lib.c +++ b/src/sm2_lib.c @@ -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); diff --git a/src/tlcp.c b/src/tlcp.c index 960d88f0..c7414e17 100644 --- a/src/tlcp.c +++ b/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(); diff --git a/src/tls.c b/src/tls.c index 94235c65..23328b26 100644 --- a/src/tls.c +++ b/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) diff --git a/src/tls12.c b/src/tls12.c index 155f372d..4fbc7439 100644 --- a/src/tls12.c +++ b/src/tls12.c @@ -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(); diff --git a/src/tls13.c b/src/tls13.c index 9f7d464a..96159098 100644 --- a/src/tls13.c +++ b/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, diff --git a/src/tls_trace.c b/src/tls_trace.c index 3fefb66f..7aeb0361 100644 --- a/src/tls_trace.c +++ b/src/tls_trace.c @@ -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; } diff --git a/src/version.c b/src/version.c index 4d85939b..223c5a56 100644 --- a/src/version.c +++ b/src/version.c @@ -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; } diff --git a/src/x509_alg.c b/src/x509_alg.c index 85d3c7e6..88ea49f7 100644 --- a/src/x509_alg.c +++ b/src/x509_alg.c @@ -49,12 +49,12 @@ #include #include #include +#include #include #include #include -#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: diff --git a/src/x509_cer.c b/src/x509_cer.c index 729a26d0..d5fa001b 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/src/x509_ext.c b/src/x509_ext.c index 012d5168..3029c9c4 100644 --- a/src/x509_ext.c +++ b/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(); diff --git a/src/x509_oid.c b/src/x509_oid.c index acdbe03c..c42dfcee 100644 --- a/src/x509_oid.c +++ b/src/x509_oid.c @@ -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; diff --git a/tests/aestest.c b/tests/aestest.c index 426b1399..d5021d93 100644 --- a/tests/aestest.c +++ b/tests/aestest.c @@ -411,4 +411,3 @@ int main(void) err += test_aes_gcm(); return err; } - diff --git a/tests/asn1test.c b/tests/asn1test.c index de0c326a..f495f8cb 100644 --- a/tests/asn1test.c +++ b/tests/asn1test.c @@ -629,6 +629,5 @@ int main(void) err += test_asn1_ia5_string(); err += test_asn1_utc_time(); err += test_asn1_generalized_time(); - return err; } diff --git a/tests/block_ciphertest.c b/tests/block_ciphertest.c index 481573c1..6daa030f 100644 --- a/tests/block_ciphertest.c +++ b/tests/block_ciphertest.c @@ -53,5 +53,6 @@ int main(void) { - return 0; + int err = 0; + return err; } diff --git a/tests/cmstest.c b/tests/cmstest.c index 7184a4d0..8e4ca8fe 100644 --- a/tests/cmstest.c +++ b/tests/cmstest.c @@ -56,7 +56,558 @@ #include #include -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; +} diff --git a/tests/destest.c b/tests/destest.c index 3dec6bbb..18a1ccac 100644 --- a/tests/destest.c +++ b/tests/destest.c @@ -53,8 +53,9 @@ #include -int main(int argc, char **argv) +int main(void) { - return 0; + int err = 0; + return err; } diff --git a/tests/ectest.c b/tests/ectest.c index efe68ad4..62be7290 100644 --- a/tests/ectest.c +++ b/tests/ectest.c @@ -49,9 +49,108 @@ #include #include #include +#include #include +#include + + +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; } diff --git a/tests/hkdftest.c b/tests/hkdftest.c index 41423b14..b08ade69 100644 --- a/tests/hkdftest.c +++ b/tests/hkdftest.c @@ -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; } diff --git a/tests/pkcs8test.c b/tests/pkcs8test.c index a3a74894..df0fc82a 100644 --- a/tests/pkcs8test.c +++ b/tests/pkcs8test.c @@ -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; } diff --git a/tests/sm2test.c b/tests/sm2test.c index 22528422..ec6c14c7 100644 --- a/tests/sm2test.c +++ b/tests/sm2test.c @@ -49,231 +49,594 @@ #include #include #include +#include #include #include +#include -// 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; } diff --git a/tests/tlstest.c b/tests/tlstest.c index 8bf40ce2..67ccbf60 100644 --- a/tests/tlstest.c +++ b/tests/tlstest.c @@ -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; } - diff --git a/tests/toolstest.sh b/tests/toolstest.sh new file mode 100755 index 00000000..7c4f3786 --- /dev/null +++ b/tests/toolstest.sh @@ -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 + diff --git a/tests/x509_exttest.c b/tests/x509_exttest.c index 8019eb62..60a25a05 100644 --- a/tests/x509_exttest.c +++ b/tests/x509_exttest.c @@ -58,7 +58,7 @@ #include #include - +#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; } diff --git a/tests/x509test.c b/tests/x509test.c index fa69d082..26b0a574 100644 --- a/tests/x509test.c +++ b/tests/x509test.c @@ -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; } diff --git a/tools/certgen.c b/tools/certgen.c index cfe9c2eb..a933c5ab 100644 --- a/tools/certgen.c +++ b/tools/certgen.c @@ -61,43 +61,13 @@ #include #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 country name\n"); - printf(" -ST state of province name\n"); - printf(" -L locality name\n"); - printf(" -O orgnization name\n"); - printf(" -OU orgnizational unit name\n"); - printf(" -CN common name\n"); - printf(" -days validity days\n"); - printf(" -key 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; } diff --git a/tools/certparse.c b/tools/certparse.c index 6eb81f5c..b77c56ef 100644 --- a/tools/certparse.c +++ b/tools/certparse.c @@ -53,26 +53,55 @@ #include #include +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; } diff --git a/tools/reqgen.c b/tools/reqgen.c index 1cce416c..f83d8877 100644 --- a/tools/reqgen.c +++ b/tools/reqgen.c @@ -62,25 +62,9 @@ #include #endif - - -void print_usage(const char *prog) -{ - printf("usage: %s command [options] ...\n", prog); - printf("\n"); - printf("Options:\n"); - printf(" -C country name\n"); - printf(" -O orgnization name\n"); - printf(" -OU orgnizational unit name\n"); - printf(" -CN common name\n"); - printf(" -L locality name\n"); - printf(" -ST state of province name\n"); - printf("\n"); - printf(" -days validity days\n"); - printf(" -keyfile 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; } diff --git a/tools/reqsign.c b/tools/reqsign.c index 9b43793e..c394b1ac 100644 --- a/tools/reqsign.c +++ b/tools/reqsign.c @@ -52,174 +52,162 @@ #include #include #include +#include #include #include #include - - -void print_usage(const char *prog) -{ - printf("Usage: %s command [options] ...\n", prog); - printf("\n"); - printf("Options:\n"); - printf(" -req PKCS #10 certificate request file\n"); - printf(" -cacert CA certificate file\n"); - printf(" -keyfile 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; } diff --git a/tools/sm2decrypt.c b/tools/sm2decrypt.c index 66d6265a..ba6947c6 100644 --- a/tools/sm2decrypt.c +++ b/tools/sm2decrypt.c @@ -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; diff --git a/tools/sm3hmac.c b/tools/sm3hmac.c index d285430f..fcf8478f 100644 --- a/tools/sm3hmac.c +++ b/tools/sm3hmac.c @@ -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));