Init commit of gmssl-v3

This commit is contained in:
Zhi Guan
2021-07-13 19:21:43 +08:00
commit 0af5775be3
157 changed files with 60619 additions and 0 deletions

220
.gitignore vendored Normal file
View File

@@ -0,0 +1,220 @@
# Ignore editor artefacts
/.dir-locals.el
# Top level excludes
/Makefile.orig
/MINFO
/TABLE
/*.a
/*.pc
/rehash.time
/inc.*
/makefile.*
/out.*
/tmp.*
/configdata.pm
/build
/Makefile
# *all* Makefiles
#Makefile
*.tmp
# Java
/java/*.class
/java/Makefile*
# Links under apps
/apps/CA.pl
/apps/tsget
/apps/tsget.pl
/apps/md4.c
# Auto generated headers
/crypto/buildinf.h
/crypto/include/internal/*_conf.h
/openssl/include/opensslconf.h
/util/domd
# Executables
/apps/openssl
/test/sha256t
/test/sha512t
/test/gost2814789t
/test/ssltest_old
/test/*test
/test/fips_aesavs
/test/fips_desmovs
/test/fips_dhvs
/test/fips_drbgvs
/test/fips_dssvs
/test/fips_ecdhvs
/test/fips_ecdsavs
/test/fips_rngvs
/test/fips_test_suite
/test/ssltest_old
/test/x509aux
/test/v3ext
# Certain files that get created by tests on the fly
/test/*.ss
/test/*.srl
/test/.rnd
/test/test*.pem
/test/newkey.pem
/test/*.log
/test/buildtest_*
/test/*.p
/test/*.dd
/test/*.dp
/test/*.pd
/test/*.p
/util/shlib_wrap.sh
# Fuzz stuff.
# Anything without an extension is an executable on Unix, so we keep files
# with extensions. And we keep the corpora subddir versioned as well.
# Anything more generic with extensions that should be ignored will be taken
# care of by general ignores for those extensions (*.o, *.obj, *.exe, ...)
/fuzz/*
!/fuzz/README*
!/fuzz/corpora
!/fuzz/*.*
# Misc auto generated files
/include/openssl/opensslconf.h
/tools/c_rehash
/tools/c_rehash.pl
/tags
/TAGS
/crypto.map
/ssl.map
# Windows (legacy)
/tmp32
/tmp32.dbg
/tmp32dll
/tmp32dll.dbg
/out32
/out32.dbg
/out32dll
/out32dll.dbg
/inc32
/MINFO
/ms/.rnd
/ms/bcb.mak
/ms/libeay32.def
/ms/nt.mak
/ms/ntdll.mak
/ms/ssleay32.def
/ms/version32.rc
# Files created on other branches that are not held in git, and are not
# needed on this branch
/include/openssl/asn1_mac.h
/include/openssl/des_old.h
/include/openssl/fips.h
/include/openssl/fips_rand.h
/include/openssl/krb5_asn.h
/include/openssl/kssl.h
/include/openssl/pq_compat.h
/include/openssl/ssl23.h
/include/openssl/tmdiff.h
/include/openssl/ui_compat.h
/test/fips_aesavs.c
/test/fips_desmovs.c
/test/fips_dsatest.c
/test/fips_dssvs.c
/test/fips_hmactest.c
/test/fips_randtest.c
/test/fips_rngvs.c
/test/fips_rsagtest.c
/test/fips_rsastest.c
/test/fips_rsavtest.c
/test/fips_shatest.c
/test/fips_test_suite.c
/test/shatest.c
##### Generic patterns
# Auto generated assembly language source files
*.s
!/crypto/*/asm/*.s
/crypto/arm*.S
/crypto/*/*.S
*.asm
!/crypto/*/asm/*.asm
# Object files
*.o
*.obj
# editor artefacts
*.swp
.#*
\#*#
*~
# Certificate symbolic links
*.0
# All kinds of executables
*.so
*.so.*
*.dylib
*.dylib.*
*.dll
*.dll.*
*.exe
*.pyc
*.exp
*.lib
*.pdb
*.ilk
*.def
*.rc
*.res
# Misc generated stuff
Makefile.save
/crypto/**/lib
/engines/**/lib
/ssl/**/lib
*.bak
cscope.*
*.d
# macOS
.DS_Store
*.tar.gz
# add by LiTianjue for GmSSL
# auto create by Configure
crypto/opensslconf.h
tool/c_rehash
# exec file
apps/gmssl
apps/gmca/.ca
# gmtls
/ssl/ssl_load.c
# demos
/demos
/demos/kdf
/demos/ssl
/demos/otp
/demos/sm9
# engines
/engines/e_skf*
/engines/e_sdf*
/engines/sdf
/engines/skf
include/openssl/srp.h
/*.sh
/rust
/python

201
CMakeLists.txt Normal file
View File

@@ -0,0 +1,201 @@
cmake_minimum_required(VERSION 2.8.11)
project(GmSSL)
include_directories(include)
add_library(
gmssl
src/hex.c
src/debug.c
src/rand.c
src/sm2_lib.c
src/sm2_prn.c
src/sm2_algo.c
src/sm2_asn1.c
src/sm3.c
src/sm3_hmac.c
src/sm4_common.c
src/sm4_setkey.c
src/sm4_enc.c
src/sm4_cbc.c
src/sm9_math.c
src/zuc_core.c
src/zuc_eea.c
src/zuc_eia.c
src/hash_drbg.c
src/hmac.c
src/hkdf.c
#src/cmac.c
src/pbkdf2.c
src/pkcs8.c
src/oid.c
src/asn1.c
src/rc4.c
src/md5.c
src/des.c
src/aes.c
src/chacha20.c
src/sha1.c
src/sha256.c
src/sha512.c
src/digest.c
#src/digest_asn1.c
src/x509_lib.c
src/x509_asn1.c
src/x509_ext.c
src/x509_algor.c
src/base64.c
src/pem.c
src/tls.c
src/tls_cipher.c
src/tls_trace.c
src/tls12.c
src/tlcp.c
src/cms.c
)
target_include_directories (gmssl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
# tools
add_executable (digest tools/digest.c)
target_link_libraries (digest LINK_PUBLIC gmssl)
add_executable (certview tools/certview.c)
target_link_libraries (certview LINK_PUBLIC gmssl)
add_executable (certgen tools/certgen.c)
target_link_libraries (certgen LINK_PUBLIC gmssl)
add_executable (certverify tools/certverify.c)
target_link_libraries (certverify LINK_PUBLIC gmssl)
add_executable (reqgen tools/reqgen.c)
target_link_libraries (reqgen LINK_PUBLIC gmssl)
add_executable (sm3sum tools/sm3sum.c)
target_link_libraries (sm3sum LINK_PUBLIC gmssl)
add_executable (sm2gen tools/sm2gen.c)
target_link_libraries (sm2gen 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 (pkcs8gen tools/pkcs8gen.c)
target_link_libraries (pkcs8gen LINK_PUBLIC gmssl)
add_executable (sm2view tools/sm2view.c)
target_link_libraries (sm2view LINK_PUBLIC gmssl)
add_executable (pkcs8view tools/pkcs8view.c)
target_link_libraries (pkcs8view 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)
# tests
add_executable(sm2test tests/sm2test.c)
target_link_libraries (sm2test LINK_PUBLIC gmssl)
add_executable(sm2asn1test tests/sm2asn1test.c)
target_link_libraries (sm2asn1test LINK_PUBLIC gmssl)
add_executable(sm3test tests/sm3test.c)
target_link_libraries (sm3test LINK_PUBLIC gmssl)
add_executable(md5test tests/md5test.c)
target_link_libraries (md5test LINK_PUBLIC gmssl)
add_executable(sha1test tests/sha1test.c)
target_link_libraries (sha1test LINK_PUBLIC gmssl)
add_executable(sha224test tests/sha224test.c)
target_link_libraries (sha224test LINK_PUBLIC gmssl)
add_executable(sha256test tests/sha256test.c)
target_link_libraries (sha256test LINK_PUBLIC gmssl)
add_executable(sha384test tests/sha384test.c)
target_link_libraries (sha384test LINK_PUBLIC gmssl)
add_executable(sha512test tests/sha512test.c)
target_link_libraries (sha512test LINK_PUBLIC gmssl)
add_executable(hmactest tests/hmactest.c)
target_link_libraries (hmactest LINK_PUBLIC gmssl)
add_executable(hkdftest tests/hkdftest.c)
target_link_libraries (hkdftest LINK_PUBLIC gmssl)
add_executable(digesttest tests/digesttest.c)
target_link_libraries (digesttest LINK_PUBLIC gmssl)
add_executable(sm4test tests/sm4test.c)
target_link_libraries (sm4test LINK_PUBLIC gmssl)
add_executable(sm4cbctest tests/sm4cbctest.c)
target_link_libraries (sm4cbctest LINK_PUBLIC gmssl)
add_executable(zuctest tests/zuctest.c)
target_link_libraries (zuctest LINK_PUBLIC gmssl)
add_executable(aestest tests/aestest.c)
target_link_libraries (aestest LINK_PUBLIC gmssl)
add_executable(rc4test tests/rc4test.c)
target_link_libraries (rc4test LINK_PUBLIC gmssl)
add_executable(chacha20test tests/chacha20test.c)
target_link_libraries (chacha20test LINK_PUBLIC gmssl)
add_executable(hash_drbgtest tests/hash_drbgtest.c)
target_link_libraries (hash_drbgtest LINK_PUBLIC gmssl)
add_executable(pbkdf2test tests/pbkdf2test.c)
target_link_libraries (pbkdf2test LINK_PUBLIC gmssl)
add_executable(pkcs8test tests/pkcs8test.c)
target_link_libraries (pkcs8test LINK_PUBLIC gmssl)
add_executable(oidtest tests/oidtest.c)
target_link_libraries (oidtest LINK_PUBLIC gmssl)
add_executable(asn1test tests/asn1test.c)
target_link_libraries (asn1test LINK_PUBLIC gmssl)
add_executable(base64test tests/base64test.c)
target_link_libraries (base64test LINK_PUBLIC gmssl)
add_executable(x509test tests/x509test.c)
target_link_libraries (x509test LINK_PUBLIC gmssl)
add_executable(cmstest tests/cmstest.c)
target_link_libraries (cmstest LINK_PUBLIC gmssl)
#add_executable(tlstest tests/tlstest.c)
#target_link_libraries (tlstest LINK_PUBLIC gmssl)

16
README.md Normal file
View File

@@ -0,0 +1,16 @@
# GMSSL v3
更快、更小、更安全是下一个大版本升级GmSSL v3.0)的主要目标,我们将从下列方向进行改进:
1. 采用CMake替代目前基于Perl的构建系统
2. 支持Linux/Windows/macOS/Android/iOS等主流操作系统移除对嵌入式OS等其他系统的支持
3. 支持X86/ARM/RISC-V针对上述平台64位指令集做汇编层面的优化
4. 将C语言标准由目前的C89更新为最新的C99或C11及部分GCC特性移除对Perl的依赖
5. 移除不安全的算法和协议仅支持国密算法和主流国际算法提升对AEAD、TLS 1.3等新标准的默认支持力度
6. 提升密码算法抗木马、抗侧信道攻击的安全性
7. 降低运行时堆内存的使用量,降低总体二进制代码体积
8. 提供特定于国密算法和协议的统一的多语言支持Rust/Java/Go/PHP封装
9. 保持和OpenSSL最新版本的兼容性实现GmSSL和OpenSSL在同一个软件中的共存

91
include/gmssl/aes.h Normal file
View File

@@ -0,0 +1,91 @@
/*
* 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_AES_H
#define GMSSL_AES_H
#include <stdint.h>
#include <stdlib.h>
#define AES128_KEY_BITS 128
#define AES192_KEY_BITS 192
#define AES256_KEY_BITS 256
#define AES128_KEY_SIZE (AES128_KEY_BITS/8)
#define AES192_KEY_SIZE (AES192_KEY_BITS/8)
#define AES256_KEY_SIZE (AES256_KEY_BITS/8)
#define AES_BLOCK_SIZE 16
#define AES128_ROUNDS 10
#define AES192_ROUNDS 12
#define AES256_ROUNDS 14
#define AES_MAX_ROUNDS AES256_ROUNDS
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t rk[4 * (AES_MAX_ROUNDS + 1)];
int rounds;
} AES_KEY;
int aes_set_encrypt_key(AES_KEY *aes_key, const uint8_t *key, size_t keylen);
int aes_set_decrypt_key(AES_KEY *aes_key, const uint8_t *key, size_t keylen);
void aes_encrypt(const AES_KEY *aes_key, const uint8_t in[AES_BLOCK_SIZE], uint8_t out[AES_BLOCK_SIZE]);
void aes_decrypt(const AES_KEY *aes_key, const uint8_t in[AES_BLOCK_SIZE], uint8_t out[AES_BLOCK_SIZE]);
#ifdef __cplusplus
}
#endif
#endif

272
include/gmssl/asn1.h Normal file
View File

@@ -0,0 +1,272 @@
/*
* 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_ASN1_H
#define GMSSL_ASN1_H
#include <stdlib.h>
#include <time.h>
#if __cplusplus
extern "C" {
#endif
#define ASN1_TAG_UNIVERSAL 0x00
#define ASN1_TAG_APPLICATION 0x40
#define ASN1_TAG_CONTENT_SPECIFIC 0x80
#define ASN1_TAG_PRIVATE 0xC0
#define ASN1_TAG_PRIMITIVE 0x00
#define ASN1_TAG_CONSTRUCTED 0x20
#define ASN1_TAG_IMPLICIT(index) (ASN1_TAG_CONTENT_SPECIFIC|(index))
#define ASN1_TAG_EXPLICIT(index) ASN1_TAG_IMPLICIT(ASN1_TAG_CONSTRUCTED|(index))
// https://www.obj-sys.com/asn1tutorial/node128.html
enum ASN1_TAG {
ASN1_TAG_BOOLEAN = 1,
ASN1_TAG_INTEGER = 2,
ASN1_TAG_BIT_STRING = 3,
ASN1_TAG_OCTET_STRING = 4,
ASN1_TAG_NULL = 5,
ASN1_TAG_OBJECT_IDENTIFIER = 6,
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_SEQUENCE = 0x30,
ASN1_TAG_SET = 0x31,
ASN1_TAG_EXPLICIT = 0xa0,
};
#define ASN1_TRUE 0xff
#define ASN1_FALSE 0x00
// 用来解析未定义的OID
typedef struct {
int oid;
uint32_t nodes[16];
size_t nodes_count;
} ASN1_OID_INFO;
const char *asn1_tag_name(int tag);
// private
void asn1_tag_to_der(int tag, uint8_t **out, size_t *outlen);
void asn1_length_to_der(size_t len, uint8_t **in, size_t *inlen);
void asn1_data_to_der(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen);
int asn1_tag_from_der(int tag, const uint8_t **in, size_t *inlen);
int asn1_length_from_der(size_t *len, const uint8_t **in, size_t *inlen);
int asn1_data_from_der(const uint8_t **data, size_t datalen, const uint8_t **in, size_t *inlen);
const char *asn1_object_identifier_name(int oid);
const char *asn1_object_identifier_description(int oid);
int asn1_object_identifier_from_name(int *oid, const char *name);
int asn1_utf8_string_check(const char *a, size_t alen);
int asn1_printable_string_check(const char *a, size_t alen);
int asn1_ia5_string_check(const char *a, size_t alen);
int asn1_header_to_der(int tag, size_t len, uint8_t **out, size_t *outlen);
int asn1_type_to_der(int tag, const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen);
int asn1_type_from_der(int tag, const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen);
int asn1_type_copy_from_der(int tag, size_t maxlen, uint8_t *data, size_t *datalen, const uint8_t **in, size_t *inlen);
#define asn1_sequence_copy_from_der(maxl,d,dl,i,il) asn1_type_copy_from_der(ASN1_TAG_SEQUENCE,maxl,d,dl,i,il)
// FIXME: 调整一下参数位置maxl放在dl前面
int asn1_any_tag_from_der(int *tag, const uint8_t **in, size_t *inlen);
int asn1_any_type_from_der(int *tag, const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen);
int asn1_any_from_der(const uint8_t **tlv, size_t *tlvlen, const uint8_t **in, size_t *inlen);
int asn1_boolean_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen);
int asn1_integer_to_der_ex(int tag, const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen);
int asn1_int_to_der_ex(int tag, int a, uint8_t **out, size_t *outlen);
int asn1_bit_string_to_der_ex(int tag, const uint8_t *bits, size_t nbits, uint8_t **out, size_t *outlen);
int asn1_bits_to_der_ex(int tag, int bits, uint8_t **out, size_t *outlen);
int asn1_null_to_der(uint8_t **out, size_t *outlen);
int asn1_object_identifier_to_der_ex(int tag, int oid, const uint32_t *nodes, size_t nodes_count, uint8_t **out, size_t *outlen);
int asn1_utf8_string_to_der_ex(int tag, const char *a, uint8_t **out, size_t *outlen);
int asn1_printable_string_to_der_ex(int tag, const char *a, uint8_t **out, size_t *outlen);
int asn1_ia5_string_to_der_ex(int tag, const char *a, uint8_t **out, size_t *outlen);
int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen);
int asn1_generalized_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen);
int asn1_boolean_from_der_ex(int tag, int *val, const uint8_t **in, size_t *inlen);
int asn1_integer_from_der_ex(int tag, const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen);
int asn1_int_from_der_ex(int tag, int *a, const uint8_t **in, size_t *inlen);
int asn1_bit_string_from_der_ex(int tag, const uint8_t **bits, size_t *nbits, const uint8_t **in, size_t *inlen);
int asn1_bits_from_der_ex(int tag, int *bits, const uint8_t **in, size_t *inlen);
int asn1_octet_string_from_der_ex(int tag, const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen);
int asn1_null_from_der(const uint8_t **in, size_t *inlen);
int asn1_object_identifier_from_der_ex(int tag, int *oid, uint32_t *nodes, size_t *nodes_count, const uint8_t **in, size_t *inlen);
int asn1_utf8_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen);
int asn1_printable_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen);
int asn1_ia5_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen);
int asn1_utc_time_from_der_ex(int tag, time_t *t, const uint8_t **in, size_t *inlen);
int asn1_generalized_time_from_der_ex(int tag, time_t *t, const uint8_t **in, size_t *inlen);
#define asn1_boolean_to_der(a,d,dl) asn1_boolean_to_der_ex(ASN1_TAG_BOOLEAN,a,d,dl)
#define asn1_integer_to_der(a,al,d,dl) asn1_integer_to_der_ex(ASN1_TAG_INTEGER,a,al,d,dl)
#define asn1_int_to_der(a,d,dl) asn1_int_to_der_ex(ASN1_TAG_INTEGER,a,d,dl)
#define asn1_bit_string_to_der(a,al,d,dl) asn1_bit_string_to_der_ex(ASN1_TAG_BIT_STRING,a,al,d,dl)
#define asn1_bits_to_der(a,d,dl) asn1_bits_to_der_ex(ASN1_TAG_BIT_STRING,a,d,dl)
#define asn1_octet_string_to_der(a,al,d,dl) asn1_type_to_der(ASN1_TAG_OCTET_STRING,a,al,d,dl)
#define asn1_object_identifier_to_der(oid,a,al,d,dl) asn1_object_identifier_to_der_ex(ASN1_TAG_OBJECT_IDENTIFIER,oid,a,al,d,dl)
#define asn1_utf8_string_to_der(a,d,dl) asn1_utf8_string_to_der_ex(ASN1_TAG_UTF8String,a,d,dl)
#define asn1_printable_string_to_der(a,d,dl) asn1_printable_string_to_der_ex(ASN1_TAG_PrintableString,a,d,dl)
#define asn1_ia5_string_to_der(a,d,dl) asn1_ia5_string_to_der_ex(ASN1_TAG_IA5String,a,d,dl)
#define asn1_utc_time_to_der(a,d,dl) asn1_utc_time_to_der_ex(ASN1_TAG_UTCTime,a,d,dl)
#define asn1_generalized_time_to_der(a,d,dl) asn1_generalized_time_to_der_ex(ASN1_TAG_GeneralizedTime,a,d,dl)
#define asn1_sequence_header_to_der(al,d,dl) asn1_header_to_der(ASN1_TAG_SEQUENCE,al,d,dl)
#define asn1_set_header_to_der(al,d,dl) asn1_header_to_der(ASN1_TAG_SET,al,d,dl)
#define asn1_explicit_header_to_der(i,al,d,dl) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),al,d,dl)
#define asn1_sequence_to_der(a,al,d,dl) asn1_type_to_der(ASN1_TAG_SEQUENCE,a,al,d,dl)
#define asn1_set_to_der(a,al,d,dl) asn1_type_to_der(ASN1_TAG_SET,a,al,d,dl)
#define asn1_explicit_to_der(i,a,al,d,dl) asn1_type_to_der(ASN1_TAG_EXPLICIT(i),a,al,d,dl)
#define asn1_boolean_from_der(a,d,dl) asn1_boolean_from_der_ex(ASN1_TAG_BOOLEAN,a,d,dl)
#define asn1_integer_from_der(a,al,d,dl) asn1_integer_from_der_ex(ASN1_TAG_INTEGER,a,al,d,dl)
#define asn1_int_from_der(a,d,dl) asn1_int_from_der_ex(ASN1_TAG_INTEGER,a,d,dl)
#define asn1_bit_string_from_der(a,al,d,dl) asn1_bit_string_from_der_ex(ASN1_TAG_BIT_STRING,a,al,d,dl)
#define asn1_bits_from_der(a,d,dl) asn1_bits_from_der_ex(ASN1_TAG_BIT_STRING,a,d,dl)
#define asn1_octet_string_from_der(a,al,d,dl) asn1_type_from_der(ASN1_TAG_OCTET_STRING,a,al,d,dl)
#define asn1_object_identifier_from_der(oid,a,al,d,dl) asn1_object_identifier_from_der_ex(ASN1_TAG_OBJECT_IDENTIFIER,oid,a,al,d,dl)
#define asn1_utf8_string_from_der(a,al,d,dl) asn1_utf8_string_from_der_ex(ASN1_TAG_UTF8String,a,al,d,dl)
#define asn1_printable_string_from_der(a,al,d,dl) asn1_printable_string_from_der_ex(ASN1_TAG_PrintableString,a,al,d,dl)
#define asn1_ia5_string_from_der(a,al,d,dl) asn1_ia5_string_from_der_ex(ASN1_TAG_IA5String,a,al,d,dl)
#define asn1_utc_time_from_der(a,d,dl) asn1_utc_time_from_der_ex(ASN1_TAG_UTCTime,a,d,dl)
#define asn1_generalized_time_from_der(a,d,dl) asn1_generalized_time_from_der_ex(ASN1_TAG_GeneralizedTime,a,d,dl)
#define asn1_sequence_from_der(a,al,d,dl) asn1_type_from_der(ASN1_TAG_SEQUENCE,a,al,d,dl)
#define asn1_set_from_der(a,al,d,dl) asn1_type_from_der(ASN1_TAG_SET,a,al,d,dl)
#define asn1_implicit_from_der(i,a,al,d,dl) asn1_type_from_der(ASN1_TAG_EXPLICIT(i),a,al,d,dl)
#define asn1_explicit_from_der(i,a,al,d,dl) asn1_type_from_der(ASN1_TAG_EXPLICIT(i),a,al,d,dl)
#define asn1_implicit_boolean_to_der(i,a,d,dl) asn1_boolean_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_integer_to_der(i,a,al,d,dl) asn1_integer_to_der_ex(ASN1_TAG_IMPLICIT(i),a,al,d,dl)
#define asn1_implicit_int_to_der(i,a,d,dl) asn1_int_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_bit_string_to_der(i,a,al,d,dl) asn1_bit_string_to_der_ex(ASN1_TAG_IMPLICIT(i),a,al,d,dl)
#define asn1_implicit_bits_to_der(i,a,d,dl) asn1_bits_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_octet_string_to_der(i,a,al,d,dl) asn1_type_to_der(ASN1_TAG_IMPLICIT(i),a,al,d,dl)
#define asn1_implicit_object_identifier_to_der(i,oid,a,al,d,dl) asn1_object_identifier_to_der_ex(ASN1_TAG_IMPLICIT(i),oid,a,al,d,dl)
#define asn1_implicit_utf8_string_to_der(i,a,d,dl) asn1_utf8_string_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_printable_string_to_der(i,a,d,dl) asn1_printable_string_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_ia5_string_to_der(i,a,d,dl) asn1_ia5_string_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_utc_time_to_der(i,a,d,dl) asn1_utc_time_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_generalized_time_to_der(i,a,d,dl) asn1_generalized_time_to_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_sequence_header_to_der(i,al,d,dl) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),al,d,dl)
#define asn1_implicit_set_header_to_der(i,al,d,dl) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),al,d,dl)
#define asn1_implicit_sequence_to_der(i,a,al,d,dl) asn1_type_to_der(ASN1_TAG_EXPLICIT(i),a,al,d,dl)
#define asn1_implicit_set_to_der(i,a,al,d,dl) asn1_type_to_der(ASN1_TAG_EXPLICIT(i),a,al,d,dl)
#define asn1_implicit_boolean_from_der(i,a,d,dl) asn1_boolean_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_integer_from_der(i,a,al,d,dl) asn1_integer_from_der_ex(ASN1_TAG_IMPLICIT(i),a,al,d,dl)
#define asn1_implicit_int_from_der(i,a,d,dl) asn1_int_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_bit_string_from_der(i,a,al,d,dl) asn1_bit_string_from_der_ex(ASN1_TAG_IMPLICIT(i),a,al,d,dl)
#define asn1_implicit_bits_from_der(i,a,d,dl) asn1_bits_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_octet_string_from_der(i,a,al,d,dl) asn1_type_from_der(ASN1_TAG_IMPLICIT(i),a,al,d,dl)
#define asn1_implicit_object_identifier_from_der(i,oid,a,al,d,dl) asn1_object_identifier_from_der_ex(ASN1_TAG_IMPLICIT(i),oid,a,al,d,dl)
#define asn1_implicit_utf8_string_from_der(i,a,d,dl) asn1_utf8_string_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_printable_string_from_der(i,a,d,dl) asn1_printable_string_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_ia5_string_from_der(i,a,d,dl) asn1_ia5_string_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_utc_time_from_der(i,a,d,dl) asn1_utc_time_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_generalized_time_from_der(i,a,d,dl) asn1_generalized_time_from_der_ex(ASN1_TAG_IMPLICIT(i),a,d,dl)
#define asn1_implicit_sequence_from_der(i,a,al,d,dl) asn1_type_from_der(ASN1_TAG_EXPLICIT(i),a,al,d,dl)
#define asn1_implicit_set_from_der(i,a,al,d,dl) asn1_type_from_der(ASN1_TAG_EXPLICIT(i),a,al,d,dl)
int asn1_cstring_to_der(int tag, const char *a, uint8_t **out, size_t *outlen);
int asn1_cstring_from_der(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen);
typedef struct {
size_t datalen;
uint8_t data[1];
} ASN1_SEQUENCE_OF;
int asn1_sequence_of_get_next_item(const ASN1_SEQUENCE_OF *a, const uint8_t **next, const uint8_t **data, size_t *datalen);
int asn1_sequence_of_get_count(const ASN1_SEQUENCE_OF *a, size_t *count);
#if __cplusplus
}
#endif
#endif

96
include/gmssl/base64.h Normal file
View File

@@ -0,0 +1,96 @@
/*
* 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_BASE64_H
#define GMSSL_BASE64_H
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
/* number saved in a partial encode/decode */
int num;
/*
* The length is either the output line length (in input bytes) or the
* shortest input line length that is ok. Once decoding begins, the
* length is adjusted up each time a longer line is decoded
*/
int length;
/* data to encode */
unsigned char enc_data[80];
/* number read on current line */
int line_num;
int expect_nl;
} BASE64_CTX;
# define BASE64_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80)
# define BASE64_DECODE_LENGTH(l) ((l+3)/4*3+80)
void base64_encode_init(BASE64_CTX *ctx);
int base64_encode_update(BASE64_CTX *ctx, const uint8_t *in, int inlen, uint8_t *out, int *outlen);
void base64_encode_finish(BASE64_CTX *ctx, uint8_t *out, int *outlen);
void base64_decode_init(BASE64_CTX *ctx);
int base64_decode_update(BASE64_CTX *ctx, const uint8_t *in, int inlen, uint8_t *out, int *outlen);
int base64_decode_finish(BASE64_CTX *ctx, uint8_t *out, int *outlen);
int base64_encode_block(unsigned char *t, const unsigned char *f, int dlen);
int base64_decode_block(unsigned char *t, const unsigned char *f, int n);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,115 @@
/*
* 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_BLOCK_CIPHER_H
#define GMSSL_BLOCK_CIPHER_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/aes.h>
#include <gmssl/sm4.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct BLOCK_CIPHER BLOCK_CIPHER;
typedef struct BLOCK_CIPHER_KEY BLOCK_CIPHER_KEY;
struct BLOCK_CIPHER_KEY {
union {
SM4_KEY sm4_key;
AES_KEY aes_key;
} u;
const BLOCK_CIPHER *cipher;
};
typedef int (*block_cipher_set_encrypt_key_func)(BLOCK_CIPHER_KEY *key, const uint8_t *user_key, size_t keylen);
typedef int (*block_cipher_set_decrypt_key_func)(BLOCK_CIPHER_KEY *key, const uint8_t *user_key, size_t keylen);
typedef void (*block_cipher_encrypt_func)(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out);
typedef void (*block_cipher_decrypt_func)(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out);
struct BLOCK_CIPHER {
int oid;
size_t key_min_size;
size_t key_max_size;
size_t block_size;
block_cipher_set_encrypt_key_func set_encrypt_key;
block_cipher_set_decrypt_key_func set_decrypt_key;
block_cipher_encrypt_func encrypt;
block_cipher_decrypt_func decrypt;
};
int block_cipher_set_encrypt_key(BLOCK_CIPHER_KEY *key, const uint8_t *user_key, size_t keylen);
int block_cipher_set_decrypt_key(BLOCK_CIPHER_KEY *key, const uint8_t *user_key, size_t keylen);
void block_cipher_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out);
void block_cipher_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out);
const BLOCK_CIPHER *BLOCK_CIPHER_aes(void);
const BLOCK_CIPHER *BLOCK_CIPHER_sm4(void);
const BLOCK_CIPHER *block_cipher_from_name(const char *name);
void block_cipher_ecb_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, size_t nblocks, uint8_t *out);
void block_cipher_ecb_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, size_t nblocks, uint8_t *out);
void block_cipher_cbc_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv,
const uint8_t *in, size_t nblocks, uint8_t *out);
void block_cipher_cbc_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv,
const uint8_t *in, size_t nblocks, uint8_t *out);
void block_cipher_ctr_encrypt(const BLOCK_CIPHER_KEY *key, uint8_t *counter,
const uint8_t *in, size_t nblocks, uint8_t *out);
#ifdef __cplusplus
}
#endif
#endif

97
include/gmssl/chacha20.h Normal file
View File

@@ -0,0 +1,97 @@
/*
* 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.
*/
/* RFC 8439 "ChaCha20 and Poly1305 for IETF Protocols" */
#ifndef GMSSL_CHACHA20_H
#define GMSSL_CHACHA20_H
#define CHACHA20_IS_BIG_ENDIAN 0
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define CHACHA20_KEY_BITS 256
#define CHACHA20_NONCE_BITS 96
#define CHACHA20_COUNTER_BITS 32
#define CHACHA20_KEY_SIZE (CHACHA20_KEY_BITS/8)
#define CHACHA20_NONCE_SIZE (CHACHA20_NONCE_BITS/8)
#define CHACHA20_COUNTER_SIZE (CHACHA20_COUNTER_BITS/8)
#define CHACHA20_KEY_WORDS (CHACHA20_KEY_SIZE/sizeof(uint32_t))
#define CHACHA20_NONCE_WORDS (CHACHA20_NONCE_SIZE/sizeof(uint32_t))
#define CHACHA20_COUNTER_WORDS (CHACHA20_COUNTER_SIZE/sizeof(uint32_t))
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t d[16];
} CHACHA20_STATE;
void chacha20_set_key(CHACHA20_STATE *state,
const uint8_t key[CHACHA20_KEY_SIZE],
const uint8_t nonce[CHACHA20_NONCE_SIZE],
uint32_t counter);
void chacha20_generate_keystream(CHACHA20_STATE *state,
unsigned int counts,
uint8_t *out);
#ifdef __cplusplus
}
#endif
#endif

109
include/gmssl/cipher.h Normal file
View File

@@ -0,0 +1,109 @@
/*
* 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_CIPHER_H
#define GMSSL_CIPHER_H
#ifdef __cplusplus
extern "C" {
#endif
struct cipher_st {
int nid;
size_t block_size;
size_t key_size;
size_t iv_size;
unsigned long flags;
int (*init)(CIPHER_CTX *ctx, const uint8_t *key);
int (*encrypt)(CIPHER_CTX *ctx);
};
struct cipher_ctx_st {
CIPHER *cipher;
int is_encrypt;
uint8_t iv[16];
uint8_t block[16];
};
int cipher_encyrpt_init(CIPHER_CTX *ctx, const CIPHER *cipher, const uint8_t *key, const uint8_t *iv);
int cipher_encrypt_update(CIPHER_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
int cipher_encrypt_finish(CIPHER_CTX *ctx, uint8_t *out, size_t *outlen);
int cipher_decrypt_init(CIPHER_CTX *ctx, const CIPHER *cipher, const uint8_t *key, const uint8_t *iv);
int cipher_decrypt_update(CIPHER_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
int cipher_decrypt_finish(CIPHER_CTX *ctx, uint8_t *out, size_t *outlen);
int cipher_init(CIPHER_CTX *ctx, const CIPHER *cipher, const uint8_t *key, const uint8_t *iv, int enc);
int cipher_update(CIPHER_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
int cipher_finish(CIPHER_CTX *ctx, uint8_t *out, size_t *outlen);
const CIPHER *CIPHER_sm4_ecb(void);
const CIPHER *CIPHER_sm4_cbc(void);
const CIPHER *CIPHER_sm4_ofb(void);
const CIPHER *CIPHER_sm4_cfb1(void);
const CIPHER *CIPHER_sm4_cfb8(void);
const CIPHER *CIPHER_sm4_cfb128(void);
const CIPHER *CIPHER_sm4_ctr(void);
const CIPHER *CIPHER_sm4_gcm(void);
const CIPHER *CIPHER_zuc(void);
const CIPHER *CIPHER_zuc256(void);
#ifdef __cplusplus
}
#endif
#endif

86
include/gmssl/cmac.h Normal file
View File

@@ -0,0 +1,86 @@
/*
* 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.
*/
/* NIST SP 800-38B "Recommendation for Block Cipher Modes of Operation:
* The CMAC Mode for Authentication"
*/
#ifndef GMSSL_CMAC_H
#define GMSSL_CMAC_H
#include <stdint.h>
#include <stdlib.h>
#include <gmssl/block_cipher.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
const BLOCK_CIPHER *cipher;
BLOCK_CIPHER_KEY cipher_key;
uint8_t k1[16];
uint8_t k2[16];
uint8_t temp_block[16];
uint8_t last_block[16];
int last_block_nbytes; /* -1 means context not initialised */
} CMAC_CTX;
int cmac_init(CMAC_CTX *ctx, const BLOCK_CIPHER *cipher, const uint8_t *key, size_t keylen);
int cmac_update(CMAC_CTX *ctx, const uint8_t *in, size_t inlen);
int cmac_finish(CMAC_CTX *ctx, uint8_t *out, size_t *outlen);
int cmac_finish_and_verify(CMAC_CTX *ctx, const uint8_t *mac, size_t maclen);
#ifdef __cplusplus
}
#endif
#endif

276
include/gmssl/cms.h Executable file
View File

@@ -0,0 +1,276 @@
/*
* Copyright (c) 2021 - 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.
*/
/*
ContentInfo ::= SEQUENCE {
contentType OBJECT IDENTIFIER,
content [0] EXPLICIT ANY OPTIONAL
}
data 1.2.156.10197.6.1.4.2.1
data ::= OCTET STRING
SignedData ::= SEQUENCE {
version INTEGER (1),
digestAlgorithms SET OF AlgorithmIdentifier,
contentInfo ContentInfo,
certificates [0] IMPLICIT SET OF Certificate OPTIONAL,
crls [1] IMPLICIT SET OF CertificateRevocationList OPTIONAL,
signerInfos SET OF SignerInfo
}
SignerInfo ::= SEQUENCE {
version INTEGER (1),
issuerAndSerialNumber IssuerAndSerialNumber,
digestAlgorithm AlgorithmIdentifier,
authenticatedAttributes [0] IMPLICIT SET OF Attribute OPTINOAL,
digestEncryptionAlgorithm AlgorithmIdentifier,
encryptedDigest OCTET STRING,
unauthenticatedAttributes [1] IMPLICIT SET OF Attribute OPTINOAL,
}
EnvelopedData ::= SEQUENCE {
version INTEGER (1),
recipientInfos SET OF RecipientInfo,
encryptedContentInfo EncryptedContentInfo
}
EncryptedContentInfo ::= SEQUENCE {
contentType OBJECT IDENTIFIER,
contentEncryptionAlgorithm AlgorithmIdentifier,
encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL,
sharedInfo1 [1] IMPLICIT OCTET STRING OPTIONAL,
sharedInfo2 [2] IMPLICIT OCTET STRING OPTIONAL,
}
RecipientInfo ::= SEQUENCE {
version INTEGER (1),
issuerAndSerialNumber IssuerAndSerialNumber,
keyEncryptionAlgorithm AlgorithmIdentifier,
encryptedKey OCTET STRING
}
SignedAndEnvelopedData ::= SEQUENCE {
version INTEGER (1),
recipientInfos SET OF RecipientInfo,
digestAlgorithms SET OF AlgorithmIdentifier,
encryptedContentInfo EncryptedContentInfo,
certificates [0] IMPLICIT SET OF Certificate OPTIONAL,
crls [1] IMPLICIT SET OF CertificateRevocationList OPTIONAL,
signerInfos SET OF SignerInfo
}
EncryptedData ::= SEQUENCE {
version INTEGER (1),
encryptedContentInfo EncryptedContentInfo
}
KeyAgreementInfo ::= SEQUENCE {
version INTEGER (1),
tempPublicKeyR SM2PublicKey,
userCertificate Certificate,
userID OCTET STRING
}
*/
#ifndef GMSSL_CMS_H
#define GMSSL_CMS_H
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <gmssl/x509.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
CMS_version = 1,
};
typedef enum {
CMS_data = 1,
CMS_signed_data = 2,
CMS_enveloped_data = 3,
CMS_signed_and_enveloped_data = 4,
CMS_encrypted_data = 5,
CMS_key_agreement_info = 6,
} CMS_CONTENT_TYPE;
/*
IssuerAndSerialNumber ::= SEQUENCE {
issuer Name,
serialNumber INTEGER }
*/
int cms_issuer_and_serial_number_from_certificate(const X509_NAME **issuer,
const uint8_t **serial_number, size_t *serial_number_len,
const X509_CERTIFICATE *cert);
int cms_public_key_from_certificate(const SM2_KEY **pub_key,
const X509_CERTIFICATE *cert);
int cms_issuer_and_serial_number_to_der(const X509_NAME *issuer,
const uint8_t *serial_number, size_t serial_number_len,
uint8_t **out, size_t *outlen);
int cms_issuer_and_serial_number_from_der(X509_NAME *issuer,
const uint8_t **serial_number, size_t *serial_number_len,
const uint8_t **in, size_t *inlen);
const char *cms_content_type_name(int type);
int cms_content_type_to_der(int type, uint8_t **out, size_t *outlen);
int cms_content_type_from_der(int *type, const uint8_t **in, size_t *inlen);
int cms_content_info_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent);
int cms_content_info_set_data(uint8_t *content_info, size_t *content_info_len,
const uint8_t *data, size_t datalen);
int cms_content_info_get_data(const uint8_t *content_info, size_t content_info_len,
const uint8_t **data, size_t *datalen);
int cms_data_print(FILE *fp, const uint8_t *in, size_t inlen, int format, int indent);
int cms_signer_info_to_der(const X509_NAME *issuer,
const uint8_t *serial_number, size_t serial_number_len, int digest_algor,
const uint8_t *authed_attrs, size_t authed_attrs_len,
const uint8_t *enced_digest, size_t enced_digest_len,
const uint8_t *unauthed_attrs, size_t unauthed_attrs_len,
uint8_t **out, size_t *outlen);
int cms_signer_info_from_der(X509_NAME *issuer,
const uint8_t **serial_number, size_t *serial_number_len,
int *digest_algor, uint32_t *nodes, size_t *nodes_count,
const uint8_t **authed_attrs, size_t *authed_attrs_len,
int *sign_algor, uint32_t *sign_algor_nodes, size_t *sign_algor_nodes_count,
const uint8_t **enced_digest, size_t *enced_digest_len,
const uint8_t **unauthed_attrs, size_t *unauthed_attrs_len,
const uint8_t **in, size_t *inlen);
int cms_signer_info_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent);
int cms_signer_info_sign_to_der(const SM2_KEY *sm2_key, const SM3_CTX *sm3_ctx,
const X509_NAME *issuer, const uint8_t *serial_number, size_t serial_number_len,
const uint8_t *authed_attrs, size_t authed_attrs_len,
const uint8_t *unauthed_attrs, size_t unauthed_attrs_len,
uint8_t **out, size_t *outlen);
int cms_signer_info_verify_from_der(
const SM2_KEY *sm2_key, const SM3_CTX *sm3_ctx,
X509_NAME *issuer, const uint8_t **serial_number, size_t *serial_number_len,
int *digest_algor, uint32_t *digest_nodes, size_t *digest_algor_nodes_count,
const uint8_t **authed_attrs, size_t *authed_attrs_len,
int *sign_algor, uint32_t *sign_algor_nodes, size_t *sign_algor_nodes_count,
const uint8_t **unauthed_attrs, size_t *unauthed_attrs_len,
const uint8_t **in, size_t *inlen);
int cms_signed_data_to_der(
const int *digest_algors, const size_t digset_algors_count,
const int content_type, const uint8_t *content, const size_t content_len,
const X509_CERTIFICATE *certs, size_t certs_count,
const uint8_t **crls, const size_t *crls_lens, const size_t crls_count,
const uint8_t **signer_infos, size_t *signer_infos_lens, size_t signer_infos_count,
uint8_t **out, size_t *outlen);
int cms_signed_data_from_der(
const uint8_t **digest_algors, size_t *digest_algors_len,
int *content_type, const uint8_t **content, size_t *content_len,
const uint8_t **certs, size_t *certs_len,
const uint8_t **crls, size_t *crls_len,
const uint8_t **signer_infos, size_t *signer_infos_len,
const uint8_t **in, size_t *inlen);
int cms_signed_data_print(FILE *fp, const uint8_t *in, size_t inlen, int format, int indent);
int cms_signed_data_sign_to_der(const SM2_KEY *sign_keys, const X509_CERTIFICATE *sign_certs, size_t sign_count,
int content_type, const uint8_t *content, size_t content_len,
const uint8_t **crls, size_t *crls_lens, size_t crls_count,
uint8_t **out, size_t *outlen);
int cms_signed_data_verify_from_der(const uint8_t *signed_data, size_t signed_data_len);
int cms_sign(const SM2_KEY *sign_keys,
const X509_CERTIFICATE *sign_certs, size_t sign_count,
int content_type, const uint8_t *content, size_t content_len,
const uint8_t **crls, size_t *crls_lens, size_t crls_count,
uint8_t *content_info, size_t *content_info_len);
#ifdef __cplusplus
}
#endif
#endif

122
include/gmssl/crl.h Normal file
View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2020 - 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_CRL_H
#define GMSSL_CRL_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum X509_CRLReason {
X509_cr_unspecified = 0,
X509_cr_keyCompromise,
X509_cr_cACompromise,
X509_cr_affiliationChanged,
X509_cr_superseded,
X509_cr_cessationOfOperation,
X509_cr_certificateHold,
X509_cr_7_not_assigned = 7,
X509_cr_removeFromCRL,
X509_cr_privilegeWithdrawn,
X509_cr_aACompromise,
} CRL_REASON;
typedef struct {
uint8_t serial_number[20];
size_t serial_number_len;
time_t revoke_date;
CRL_EXTENSIONS crlEntryExtensions;
} CRL_REVOKED_CERT;
typedef struct {
int version; // OPTIONAL, if present MUST be v2
int signature_algor;
X509_NAME issuer;
time_t this_update;
time_t next_update;
uint8_t *revoked_certs;
size_t revoked_certs_count;
X509_EXTENSION crl_exts[32];
size_t crl_exts_count;
uint8_t buf[1024];
} CRL_TBS_CERT_LIST;
typedef struct {
X509_TBS_CERT_LIST tbs_cert_list;
int signature_algor;
uint8_t signature[128];
size_t signature_len;
} CRL_CERT_LIST;
#ifdef __cplusplus
}
#endif
#endif

95
include/gmssl/des.h Normal file
View File

@@ -0,0 +1,95 @@
/*
* 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.
*/
/* FIPS PUB 46-3 "Data Encryption Standard (DES)" */
#ifndef GMSSL_DES_H
#define GMSSL_DES_H
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DES_KEY_BITS 56
#define DES_BLOCK_BITS 64
#define DES_KEY_SIZE (DES_KEY_BITS/8)
#define DES_BLOCK_SIZE (DES_BLOCK_BITS/8)
#define DES_RK_BITS 48
#define DES_RK_SIZE (DES_RK_BITS/8)
#define DES_ROUNDS 16
typedef struct {
uint64_t rk[DES_ROUNDS];
} DES_KEY;
void des_set_encrypt_key(DES_KEY *key, const unsigned char user_key[8]);
void des_set_decrypt_key(DES_KEY *key, const unsigned char user_key[8]);
void des_encrypt(DES_KEY *key, const unsigned char in[8], unsigned char out[8]);
typedef struct {
DES_KEY K[3];
} DES_EDE_KEY;
void des_ede_set_encrypt_key(DES_EDE_KEY *key, const unsigned char user_key[24]);
void des_ede_set_decrypt_key(DES_EDE_KEY *key, const unsigned char user_key[24]);
void des_ede_encrypt(DES_EDE_KEY *key, const unsigned char in[8], unsigned char out[8]);
#ifdef __cplusplus
}
#endif
#endif

138
include/gmssl/digest.h Normal file
View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 2021 - 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_DIGEST_H
#define GMSSL_DIGEST_H
#include <stdint.h>
#include <stdlib.h>
#include <gmssl/sm3.h>
#include <gmssl/md5.h>
#include <gmssl/sha1.h>
#include <gmssl/sha2.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct digest_st DIGEST;
typedef struct digest_ctx_st DIGEST_CTX;
#define DIGEST_MAX_SIZE 64
#define DIGEST_MAX_BLOCK_SIZE (1024/8)
struct digest_ctx_st {
const DIGEST *digest;
union {
SM3_CTX sm3_ctx;
MD5_CTX md5_ctx;
SHA1_CTX sha1_ctx;
SHA224_CTX sha224_ctx;
SHA256_CTX sha256_ctx;
SHA384_CTX sha384_ctx;
SHA512_CTX sha512_ctx;
} u;
};
struct digest_st {
int nid;
size_t digest_size;
size_t block_size;
size_t ctx_size;
int (*init)(DIGEST_CTX *ctx);
int (*update)(DIGEST_CTX *ctx, const unsigned char *data, size_t datalen);
int (*finish)(DIGEST_CTX *ctx, unsigned char *dgst);
};
int digest_nid(const DIGEST *digest);
const char *digest_name(const DIGEST *digest);
size_t digest_size(const DIGEST *digest);
size_t digest_block_size(const DIGEST *digest);
const DIGEST *DIGEST_sm3(void);
const DIGEST *DIGEST_md5(void);
const DIGEST *DIGEST_sha1(void);
const DIGEST *DIGEST_sha224(void);
const DIGEST *DIGEST_sha256(void);
const DIGEST *DIGEST_sha384(void);
const DIGEST *DIGEST_sha512(void);
const DIGEST *DIGEST_sha512_224(void);
const DIGEST *DIGEST_sha512_256(void);
const DIGEST *digest_from_name(const char *name);
int digest_ctx_nid(const DIGEST_CTX *ctx);
const char *digest_ctx_name(const DIGEST_CTX *ctx);
size_t digest_ctx_size(const DIGEST_CTX *ctx);
size_t digest_ctx_block_size(const DIGEST_CTX *ctx);
const DIGEST *digest_ctx_digest(const DIGEST_CTX *ctx);
int digest_ctx_init(DIGEST_CTX *ctx);
int digest_init(DIGEST_CTX *ctx, const DIGEST *algor);
int digest_update(DIGEST_CTX *ctx, const unsigned char *data, size_t datalen);
int digest_finish(DIGEST_CTX *ctx, unsigned char *dgst, size_t *dgstlen);
void digest_ctx_cleanup(DIGEST_CTX *ctx);
int digest(const DIGEST *digest, const unsigned char *data, size_t datalen,
unsigned char *dgst, size_t *dgstlen);
const char *digest_algor_name(int oid);
int digest_algor_to_der(int oid, uint8_t **out, size_t *outlen);
int digest_algor_from_der(int *oid, uint32_t *nodes, size_t *nodes_count,
const uint8_t **in, size_t *inlen);
#ifdef __cplusplus
}
#endif
#endif

81
include/gmssl/error.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* 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_ERROR_H
#define GMSSL_ERROR_H
#include <stdio.h>
#include <stdarg.h>
#include <libgen.h>
#define error_print(fmt, args...) \
fprintf(stderr, "error: %s %d: %s: " fmt "\n", basename(__FILE__), __LINE__, __FUNCTION__, ##args)
#ifdef __cplusplus
extern "C" {
#endif
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);
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 tls_trace(int format, int indent, const char *str, ...);
#ifdef __cplusplus
}
#endif
#endif

100
include/gmssl/gcm.h Normal file
View File

@@ -0,0 +1,100 @@
/*
* 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_GCM_H
#define GMSSL_GCM_H
#ifdef __cplusplus
extern "C" {
#endif
#define GCM_IV_MIN_SIZE 1
#define GCM_IV_MAX_SIZE ((uint64_t)(1 << (64-3)))
#define GCM_IV_DEFAULT_BITS 96
#define GCM_IV_DEFAULT_SIZE 12
#define GCM_MIN_AAD_SIZE 0
#define GCM_MAX_AAD_SIZE ((uint64_t)(1 << (64-3)))
#define GCM_MIN_PLAINTEXT_SIZE 0
#define GCM_MAX_PLAINTEXT_SIZE ((((uint64_t)1 << 39) - 256) >> 3)
#define GCM_IS_LITTLE_ENDIAN 1
typedef struct {
__uint128_t H;
__uint128_t X;
size_t aadlen;
size_t cipherlen;
uint8_t block[16];
unsigned int num;
} GHASH_CTX;
void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen);
void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen);
void ghash_finish(GHASH_CTX *ctx, uint8_t out[16]);
typedef struct {
BLOCK_CIPHER *cipher;
BLOCK_CIPHER_KEY key;
uint8_t counter[16];
uint8_t enced_iv[16];
GHASH_CTX ghash_ctx;
} GCM_CTX;
#ifdef __cplusplus
}
#endif
#endif

118
include/gmssl/hash_drbg.h Normal file
View File

@@ -0,0 +1,118 @@
/*
* 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.
*/
/* NIST SP800-90A Rev.1 "Recommendation for Random Number Generation
* Using Deterministic Random Bit Generators", 10.1.1 Hash_DRBG */
#ifndef GMSSL_HASH_DRBG_H
#define GMSSL_HASH_DRBG_H
#include <stdint.h>
#include <stdlib.h>
#include <gmssl/digest.h>
/* seedlen for hash_drgb, table 2 of nist sp 800-90a rev.1 */
#define HASH_DRBG_SM3_SEED_BITS 440 /* 55 bytes */
#define HASH_DRBG_SHA1_SEED_BITS 440
#define HASH_DRBG_SHA224_SEED_BITS 440
#define HASH_DRBG_SHA512_224_SEED_BITS 440
#define HASH_DRBG_SHA256_SEED_BITS 440
#define HASH_DRBG_SHA512_256_SEED_BITS 440
#define HASH_DRBG_SHA384_SEED_BITS 888 /* 110 bytes */
#define HASH_DRBG_SHA512_SEED_BITS 888
#define HASH_DRBG_MAX_SEED_BITS 888
#define HASH_DRBG_SM3_SEED_SIZE (HASH_DRBG_SM3_SEED_BITS/8)
#define HASH_DRBG_SHA1_SEED_SIZE (HASH_DRBG_SHA1_SEED_BITS/8)
#define HASH_DRBG_SHA224_SEED_SIZE (HASH_DRBG_SHA224_SEED_BITS/8)
#define HASH_DRBG_SHA512_224_SEED_SIZE (HASH_DRBG_SHA512_224_SEED_BITS/8)
#define HASH_DRBG_SHA256_SEED_SIZE (HASH_DRBG_SHA256_SEED_BITS/8)
#define HASH_DRBG_SHA512_256_SEED_SIZE (HASH_DRBG_SHA512_256_SEED_BITS/8)
#define HASH_DRBG_SHA384_SEED_SIZE (HASH_DRBG_SHA384_SEED_BITS/8)
#define HASH_DRBG_SHA512_SEED_SIZE (HASH_DRBG_SHA512_SEED_BITS/8)
#define HASH_DRBG_MAX_SEED_SIZE (HASH_DRBG_MAX_SEED_BITS/8)
#define HASH_DRBG_RESEED_INTERVAL ((uint64_t)1 << 48)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
const DIGEST *digest;
uint8_t V[HASH_DRBG_MAX_SEED_SIZE];
uint8_t C[HASH_DRBG_MAX_SEED_SIZE];
size_t seedlen;
uint64_t reseed_counter;
} HASH_DRBG;
int hash_drbg_init(HASH_DRBG *drbg,
const DIGEST *digest,
const uint8_t *entropy, size_t entropy_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *personalstr, size_t personalstr_len);
int hash_drbg_reseed(HASH_DRBG *drbg,
const uint8_t *entropy, size_t entropy_len,
const uint8_t *additional, size_t additional_len);
int hash_drbg_generate(HASH_DRBG *drbg,
const uint8_t *additional, size_t additional_len,
size_t outlen, uint8_t *out);
void hash_drbg_cleanup(HASH_DRBG *drbg);
#ifdef __cplusplus
}
#endif
#endif

68
include/gmssl/hex.h Normal file
View File

@@ -0,0 +1,68 @@
/*
* 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_HEX_H
#define GMSSL_HEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int hex2bin(const char *in, size_t inlen, uint8_t *out);
int OPENSSL_hexchar2int(unsigned char c);
unsigned char *OPENSSL_hexstr2buf(const char *str, size_t *len);
#ifdef __cplusplus
}
#endif
#endif

76
include/gmssl/hkdf.h Normal file
View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2021 - 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.
*/
// RFC 5869
#ifndef GMSSL_HKDF_H
#define GMSSL_HKDF_H
#include <string.h>
#include <gmssl/digest.h>
#include <gmssl/hmac.h>
#ifdef __cplusplus
extern "C" {
#endif
int hkdf_extract(const DIGEST *digest, const uint8_t *salt, size_t saltlen,
const uint8_t *ikm, size_t ikmlen,
uint8_t *prk, size_t *prklen);
int hkdf_expand(const DIGEST *digest, const uint8_t *prk, size_t prklen,
const uint8_t *info, size_t infolen,
size_t L, uint8_t *okm);
#ifdef __cplusplus
}
#endif
#endif

86
include/gmssl/hmac.h Normal file
View File

@@ -0,0 +1,86 @@
/*
* 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_HMAC_H
#define GMSSL_HMAC_H
#include <string.h>
#include <gmssl/digest.h>
#ifdef __cplusplus
extern "C" {
#endif
#define HMAC_MAX_SIZE (DIGEST_MAX_SIZE)
typedef struct hmac_ctx_st {
const DIGEST *digest;
DIGEST_CTX digest_ctx;
DIGEST_CTX i_ctx;
DIGEST_CTX o_ctx;
} HMAC_CTX;
size_t hmac_size(const HMAC_CTX *ctx);
int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, size_t keylen);
int hmac_update(HMAC_CTX *ctx, const unsigned char *data, size_t datalen);
int hmac_finish(HMAC_CTX *ctx, unsigned char *mac, size_t *maclen);
int hmac_reset(HMAC_CTX *ctx);
int hmac(const DIGEST *md, const unsigned char *key, size_t keylen,
const unsigned char *data, size_t dlen,
unsigned char *mac, size_t *maclen);
#ifdef __cplusplus
}
#endif
#endif

85
include/gmssl/md5.h Executable file
View File

@@ -0,0 +1,85 @@
/*
* 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_MD5_H
#define GMSSL_MD5_H
#define MD5_IS_BIG_ENDIAN 0
#define MD5_DIGEST_SIZE 16
#define MD5_BLOCK_SIZE 64
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t state[4];
uint64_t nblocks; /* num of processed blocks */
unsigned char block[64]; /* buffer */
int num; /* buffered bytes in |block| */
} MD5_CTX;
void md5_init(MD5_CTX *ctx);
void md5_update(MD5_CTX *ctx, const uint8_t* data, size_t datalen);
void md5_finish(MD5_CTX *ctx, uint8_t dgst[MD5_DIGEST_SIZE]);
void md5_compress(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE]);
void md5_digest(const uint8_t *data, size_t datalen, uint8_t dgst[MD5_DIGEST_SIZE]);
#ifdef __cplusplus
}
#endif
#endif

313
include/gmssl/oid.h Normal file
View File

@@ -0,0 +1,313 @@
/*
* Copyright (c) 2014 - 2021 The GmSSL Project. All rights reserved.
*
OCSPSigning * 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_OID_H
#define GMSSL_OID_H
#ifdef __cplusplus
extern "C" {
#endif
enum {
OID_undef = 0,
//OID_aes,
// ShangMi schemes in GM/T 0006-2012
OID_sm1,
OID_ssf33,
OID_sm4,
OID_zuc,
OID_sm2,
OID_sm2sign,
OID_sm2keyagreement,
OID_sm2encrypt,
OID_sm9,
OID_sm9sign,
OID_sm9keyagreement,
OID_sm9encrypt,
OID_sm3,
OID_sm3_keyless,
OID_hmac_sm3,
OID_sm2sign_with_sm3,
OID_rsasign_with_sm3,
OID_x9_62_ecPublicKey, // start of X9.62 curves
OID_prime192v1,
OID_prime192v2,
OID_prime192v3,
OID_prime239v1,
OID_prime239v2,
OID_prime239v3,
OID_prime256v1,
OID_secp256k1, // start of SECG curves (secure curves only!)
OID_secp192k1,
OID_secp224k1,
OID_secp224r1,
OID_secp384r1,
OID_secp521r1,
OID_at_commonName, // start of X.509 Attributes
OID_at_surname,
OID_at_serialNumber,
OID_at_countryName,
OID_at_localityName,
OID_at_stateOrProvinceName,
OID_at_streetAddress,
OID_at_organizationName,
OID_at_organizationalUnitName,
OID_at_title,
OID_at_description,
OID_at_searchGuide,
OID_at_businessCategory,
OID_at_postalAddress,
OID_at_postalCode,
OID_at_postOfficeBox,
OID_at_physicalDeliveryOfficeName,
OID_at_telephoneNumber,
OID_at_telexNumber,
OID_at_teletexTerminalIdentifier,
OID_at_facsimileTelephoneNumber,
OID_at_x121Address,
OID_at_internationaliSDNNumber,
OID_at_registeredAddress,
OID_at_destinationIndicator,
OID_at_preferredDeliveryMethod,
OID_at_presentationAddress,
OID_at_supportedApplicationContext,
OID_at_member,
OID_at_owner,
OID_at_roleOccupant,
OID_at_seeAlso,
OID_at_userPassword,
OID_at_userCertificate,
OID_at_caCertificate,
OID_at_authorityRevocationList,
OID_at_certificateRevocationList,
OID_at_crossCertificatePair,
OID_at_name,
OID_at_givenName,
OID_at_initials,
OID_at_generationQualifier,
OID_at_x500UniqueIdentifier,
OID_at_dnQualifier,
OID_at_enhancedSearchGuide,
OID_at_protocolInformation,
OID_at_distinguishedName,
OID_at_uniqueMember,
OID_at_houseIdentifier,
OID_at_supportedAlgorithms,
OID_at_deltaRevocationList,
OID_at_dmdName,
OID_at_pseudonym,
OID_at_role,
/* ext 1 */ OID_ce_authorityKeyIdentifier,
/* ext 2 */ OID_ce_subjectKeyIdentifier,
/* ext 3 */ OID_ce_keyUsage,
/* ext 4 */ OID_ce_certificatePolicies, // start of X.500v3 Certificate Extensions
/* ext 5 */ OID_ce_policyMappings, // start of OID_ce_certificatePolicies,
/* ext 6 */ OID_ce_subjectAltName,
/* ext 7 */ OID_ce_issuerAltName,
/* ext 8 */ OID_ce_subjectDirectoryAttributes,
/* ext 9 */ OID_ce_basicConstraints,
/* ext 10 */ OID_ce_nameConstraints,
/* ext 11 */ OID_ce_policyConstraints,
/* ext 12 */ OID_ce_extKeyUsage,
/* ext 13 */ OID_ce_crlDistributionPoints,
/* ext 14 */ OID_ce_inhibitAnyPolicy,
/* ext 15 */ OID_ce_freshestCRL,
OID_ce_primaryKeyUsageRestriction,
OID_ce_privateKeyUsagePeriod,
OID_ce_crlNumber,
OID_ce_reasonCode,
OID_ce_instructionCode,
OID_ce_invalidityDate,
OID_ce_deltaCRLIndicator,
OID_ce_issuingDistributionPoint,
OID_ce_certificateIssuer,
OID_kp_serverAuth, // start of X.509 KeyPropuseID
OID_kp_clientAuth,
OID_kp_codeSigning,
OID_kp_emailProtection,
OID_kp_timeStamping,
OID_kp_OCSPSigning,
OID_qt_cps,
OID_qt_unotice,
OID_MAX,
OID_md5,
OID_sha1,
OID_sha224,
OID_sha256,
OID_sha384,
OID_sha512,
OID_sha512_224,
OID_sha512_256,
OID_pbkdf2, // {pkcs-5 12}
OID_pbes2, // {pkcs-5 13}
OID_hmacWithSHA1,
OID_hmacWithSHA224,
OID_sm4_ecb, // 1 2 156 10197 1 104 1
OID_sm4_cbc, // 1 2 156 10197 1 104 2
};
typedef struct {
int oid;
uint32_t nodes[32];
int nodes_count;
} ASN1_OBJECT_IDENTIFIER;
const char *asn1_sm_oid_name(int oid);
const char *asn1_sm_oid_description(int oid);
void asn1_sm_oid_to_octets(int oid, uint8_t *out, size_t *outlen);
int asn1_sm_oid_from_octets(const uint8_t *in, size_t inlen);
int asn1_sm_oid_from_name(const char *name);
const char *asn1_x9_62_curve_oid_name(int oid);
const char *asn1_x9_62_curve_oid_description(int oid);
void asn1_x9_62_curve_oid_to_octets(int oid, uint8_t *out, size_t *outlen);
int asn1_x9_62_curve_oid_from_octets(const uint8_t *in, size_t inlen);
int asn1_x9_62_curve_oid_from_name(const char *name);
const char *asn1_secg_curve_oid_name(int oid);
const char *asn1_secg_curve_oid_description(int oid);
void asn1_secg_curve_oid_to_octets(int oid, uint8_t *out, size_t *outlen);
int asn1_secg_curve_oid_from_octets(const uint8_t *in, size_t inlen);
int asn1_secg_curve_oid_from_name(const char *name);
const char *asn1_x509_oid_name(int oid);
const char *asn1_x509_oid_description(int oid);
void asn1_x509_oid_to_octets(int oid, uint8_t *out, size_t *outlen);
int asn1_x509_oid_from_octets(const uint8_t *in, size_t inlen);
int asn1_x509_oid_from_name(const char *name);
const char *asn1_x509_kp_oid_name(int oid);
const char *asn1_x509_kp_oid_description(int oid);
void asn1_x509_kp_oid_to_octets(int oid, uint8_t *out, size_t *outlen);
int asn1_x509_kp_oid_from_octets(const uint8_t *in, size_t inlen);
int asn1_x509_kp_oid_from_name(const char *name);
void asn1_oid_to_octets(int oid, uint8_t *out, size_t *outlen);
int asn1_oid_from_octets(const uint8_t *in, size_t inlen);
int asn1_oid_nodes_to_octets(const uint32_t *nodes, size_t nodes_count, uint8_t *out, size_t *outlen);
int asn1_oid_nodes_from_octets(uint32_t *nodes, size_t *nodes_count, const uint8_t *in, size_t inlen);
int test_asn1_oid(void);
int test_asn1_object_identifier(void);
#ifdef __cplusplus
}
#endif
#endif

79
include/gmssl/pbkdf2.h Normal file
View File

@@ -0,0 +1,79 @@
/*
* 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_PBKDF2_H
#define GMSSL_PBKDF2_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/hmac.h>
#define PBKDF2_MIN_ITER 10000
#define PBKDF2_MIN_SALT_SIZE 64
#define PBKDF2_DEFAULT_SALT_SIZE 8
#ifdef __cplusplus
extern "C" {
#endif
int pbkdf2_genkey(const DIGEST *digest,
const char *pass, size_t passlen,
const uint8_t *salt, size_t saltlen,
unsigned int count, size_t outlen, uint8_t *out);
#ifdef __cplusplus
}
#endif
#endif

72
include/gmssl/pem.h Normal file
View File

@@ -0,0 +1,72 @@
/*
* 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_PEM_H
#define GMSSL_PEM_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/base64.h>
#ifdef __cplusplus
extern "C" {
#endif
int pem_read(FILE *fp, const char *name, uint8_t *data, size_t *datalen);
int pem_write(FILE *fp, const char *name, const uint8_t *data, size_t datalen);
#ifdef __cplusplus
}
#endif
#endif

167
include/gmssl/pkcs8.h Normal file
View File

@@ -0,0 +1,167 @@
/*
* Copyright (c) 2021 - 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_PKCS8_H
#define GMSSL_PKCS8_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/sm2.h>
#include <gmssl/pem.h>
#ifdef __cplusplus
extern "C" {
#endif
// EncryptedPrivateKeyInfo
int sm2_enced_private_key_info_to_der(const SM2_KEY *key, const char *pass, uint8_t **out, size_t *outlen);
int sm2_enced_private_key_info_from_der(SM2_KEY *key, const uint8_t **attrs, size_t *attrslen, const char *pass, const uint8_t **in, size_t *inlen);
int sm2_enced_private_key_info_to_pem(const SM2_KEY *key, const char *pass, FILE *fp);
int sm2_enced_private_key_info_from_pem(SM2_KEY *key, const char *pass, FILE *fp);
/*
prf must be OID_hmac_sm3
cipher must be OID_sm4_cbc
*/
int pbkdf2_params_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int keylen, // optional, -1
int prf,
uint8_t **out, size_t *outlen);
int pbkdf2_params_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *keylen, // -1, optional
int *prf,
const uint8_t **in, size_t *inlen);
int pbkdf2_algor_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int keylen,
int prf,
uint8_t **out, size_t *outlen);
int pbkdf2_algor_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *keylen,
int *prf,
const uint8_t **in, size_t *inlen);
int pbes2_enc_algor_to_der(
int cipher,
const uint8_t *iv, size_t ivlen,
uint8_t **out, size_t *outlen);
int pbes2_enc_algor_from_der(
int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **in, size_t *inlen);
int pbes2_params_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int prf,
int cipher,
const uint8_t *iv, size_t ivlen,
uint8_t **out, size_t *outlen);
int pbes2_params_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *prf,
int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **in, size_t *inlen);
int pbes2_algor_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int prf,
int cipher,
const uint8_t *iv, size_t ivlen,
uint8_t **out, size_t *outlen);
int pbes2_algor_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *prf,
int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **in, size_t *inlen);
int pkcs8_enced_private_key_info_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int prf,
int cipher,
const uint8_t *iv, size_t ivlen,
const uint8_t *enced, size_t encedlen,
uint8_t **out, size_t *outlen);
int pkcs8_enced_private_key_info_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *prf,
int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **enced, size_t *encedlen,
const uint8_t **in, size_t *inlen);
#ifdef __cplusplus
}
#endif
#endif

63
include/gmssl/rand.h Normal file
View File

@@ -0,0 +1,63 @@
/*
* 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_RAND_H
#define GMSSL_RAND_H
#include <stdint.h>
#include <stdlib.h>
int rand_bytes(uint8_t *buf, size_t len);
#ifdef __cplusplus
}
#endif
#endif

75
include/gmssl/rc4.h Normal file
View File

@@ -0,0 +1,75 @@
/*
* 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_RC4_H
#define GMSSL_RC4_H
#define RC4_MIN_KEY_BITS 40
#define RC4_STATE_NUM_WORDS 256
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned char d[256];
} RC4_STATE;
void rc4_set_key(RC4_STATE *state, const uint8_t *key, size_t keylen);
void rc4_generate_keystream(RC4_STATE *state, size_t outlen, uint8_t *out);
#ifdef __cplusplus
}
#endif
#endif

86
include/gmssl/sha1.h Executable file
View File

@@ -0,0 +1,86 @@
/*
* 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_SHA1_H
#define GMSSL_SHA1_H
#define SHA1_IS_BIG_ENDIAN 1
#define SHA1_DIGEST_LENGTH 20
#define SHA1_BLOCK_SIZE 64
#define SHA1_STATE_WORDS (SHA1_DIGEST_LENGTH/sizeof(uint32_t))
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t state[SHA1_STATE_WORDS];
uint64_t nblocks; /* num of processed blocks */
uint8_t block[SHA1_BLOCK_SIZE]; /* buffer */
int num; /* buffered bytes in |block| */
} SHA1_CTX;
void sha1_init(SHA1_CTX *ctx);
void sha1_update(SHA1_CTX *ctx, const uint8_t *data, size_t datalen);
void sha1_finish(SHA1_CTX *ctx, uint8_t dgst[SHA1_DIGEST_LENGTH]);
void sha1_compress(uint32_t state[SHA1_STATE_WORDS], const uint8_t block[SHA1_BLOCK_SIZE]);
void sha1_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SHA1_DIGEST_LENGTH]);
#ifdef __cplusplus
}
#endif
#endif

140
include/gmssl/sha2.h Executable file
View File

@@ -0,0 +1,140 @@
/*
* 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_SHA2_H
#define GMSSL_SHA2_H
#define SHA2_IS_BIG_ENDIAN 1
#define SHA224_DIGEST_SIZE 28
#define SHA256_DIGEST_SIZE 32
#define SHA384_DIGEST_SIZE 48
#define SHA512_DIGEST_SIZE 64
#define SHA224_BLOCK_SIZE 64
#define SHA256_BLOCK_SIZE 64
#define SHA384_BLOCK_SIZE 128
#define SHA512_BLOCK_SIZE 128
#define SHA224_STATE_WORDS 8
#define SHA256_STATE_WORDS 8
#define SHA384_STATE_WORDS 8
#define SHA512_STATE_WORDS 8
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t state[SHA224_STATE_WORDS];
uint64_t nblocks;
unsigned char block[SHA224_BLOCK_SIZE];
int num;
} SHA224_CTX;
void sha224_init(SHA224_CTX *ctx);
void sha224_update(SHA224_CTX *ctx, const unsigned char* data, size_t datalen);
void sha224_finish(SHA224_CTX *ctx, unsigned char dgst[SHA224_DIGEST_SIZE]);
void sha224_compress(uint32_t dgst[8], const unsigned char block[SHA224_BLOCK_SIZE]);
void sha224_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA224_DIGEST_SIZE]);
typedef struct {
uint32_t state[8];
uint64_t nblocks;
unsigned char block[64];
int num;
} SHA256_CTX;
void sha256_init(SHA256_CTX *ctx);
void sha256_update(SHA256_CTX *ctx, const unsigned char* data, size_t datalen);
void sha256_finish(SHA256_CTX *ctx, unsigned char dgst[SHA256_DIGEST_SIZE]);
void sha256_compress(uint32_t dgst[8], const unsigned char block[SHA256_BLOCK_SIZE]);
void sha256_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA256_DIGEST_SIZE]);
typedef struct {
uint64_t state[8];
uint64_t nblocks;
unsigned char block[128];
int num;
} SHA384_CTX;
void sha384_init(SHA384_CTX *ctx);
void sha384_update(SHA384_CTX *ctx, const unsigned char* data, size_t datalen);
void sha384_finish(SHA384_CTX *ctx, unsigned char dgst[SHA384_DIGEST_SIZE]);
void sha384_compress(uint64_t dgst[8], const unsigned char block[SHA384_BLOCK_SIZE]);
void sha384_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA384_DIGEST_SIZE]);
typedef struct {
uint64_t state[8];
uint64_t nblocks;
unsigned char block[128];
int num;
} SHA512_CTX;
void sha512_init(SHA512_CTX *ctx);
void sha512_update(SHA512_CTX *ctx, const unsigned char* data, size_t datalen);
void sha512_finish(SHA512_CTX *ctx, unsigned char dgst[SHA512_DIGEST_SIZE]);
void sha512_compress(uint64_t dgst[8], const unsigned char block[SHA512_BLOCK_SIZE]);
void sha512_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA512_DIGEST_SIZE]);
#ifdef __cplusplus
}
#endif
#endif

130
include/gmssl/sha3.h Normal file
View File

@@ -0,0 +1,130 @@
/*
* 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.
*/
#ifndef GMSSL_SHA3_H
#define GMSSL_SHA3_H
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SHA3_KECCAK_P_SIZE (1600/8)
#define SHA3_224_DIGEST_SIZE (224/8)
#define SHA3_256_DIGEST_SIZE (256/8)
#define SHA3_384_DIGEST_SIZE (384/8)
#define SHA3_512_DIGEST_SIZE (512/8)
#define SHA3_224_CAPACITY (SHA3_224_DIGEST_SIZE * 2)
#define SHA3_256_CAPACITY (SHA3_256_DIGEST_SIZE * 2)
#define SHA3_384_CAPACITY (SHA3_384_DIGEST_SIZE * 2)
#define SHA3_512_CAPACITY (SHA3_512_DIGEST_SIZE * 2)
#define SHA3_224_BLOCK_SIZE (SHA3_KECCAK_P_SIZE - SHA3_224_CAPACITY) // 144
#define SHA3_256_BLOCK_SIZE (SHA3_KECCAK_P_SIZE - SHA3_224_CAPACITY) // 136
#define SHA3_384_BLOCK_SIZE (SHA3_KECCAK_P_SIZE - SHA3_224_CAPACITY) // 104
#define SHA3_512_BLOCK_SIZE (SHA3_KECCAK_P_SIZE - SHA3_224_CAPACITY) // 72
typedef struct {
uint64_t A[5][5];
uint8_t buf[SHA3_224_BLOCK_SIZE];
int num;
} SHA3_224_CTX;
void sha3_224_init(SHA3_224_CTX *ctx);
void sha3_224_update(SHA3_224_CTX *ctx, const uint8_t *data, size_t datalen);
void sha3_224_finish(SHA3_224_CTX *ctx, uint8_t dgst[SHA3_224_DIGEST_SIZE]);
typedef struct {
uint64_t A[5][5];
uint8_t buf[SHA3_256_BLOCK_SIZE];
int num;
} SHA3_256_CTX;
void sha3_256_init(SHA3_256_CTX *ctx);
void sha3_256_update(SHA3_256_CTX *ctx, const uint8_t *data, size_t datalen);
void sha3_256_finish(SHA3_256_CTX *ctx, uint8_t dgst[SHA3_256_DIGEST_SIZE]);
typedef struct {
uint64_t A[5][5];
uint8_t buf[SHA3_384_BLOCK_SIZE];
int num;
} SHA3_384_CTX;
void sha3_384_init(SHA3_384_CTX *ctx);
void sha3_384_update(SHA3_384_CTX *ctx, const uint8_t *data, size_t datalen);
void sha3_384_finish(SHA3_384_CTX *ctx, uint8_t dgst[SHA3_384_DIGEST_SIZE]);
typedef struct {
uint64_t A[5][5];
uint8_t buf[SHA3_512_BLOCK_SIZE];
int num;
} SHA3_512_CTX;
void sha3_512_init(SHA3_512_CTX *ctx);
void sha3_512_update(SHA3_512_CTX *ctx, const uint8_t *data, size_t datalen);
void sha3_512_finish(SHA3_512_CTX *ctx, uint8_t dgst[SHA3_512_DIGEST_SIZE]);
void sha3_shake128(const uint8_t *in, size_t *inlen, size_t outlen, uint8_t *out);
void sha3_shake256(const uint8_t *in, size_t *inlen, size_t outlen, uint8_t *out);
void sha3_keccak_p(uint8_t state[SHA3_KECCAK_P_SIZE]);
#ifdef __cplusplus
}
#endif
#endif

196
include/gmssl/sm2.h Normal file
View File

@@ -0,0 +1,196 @@
/*
* 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_SM2_H
#define GMSSL_SM2_H
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <gmssl/sm3.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t x[32];
uint8_t y[32];
} SM2_POINT;
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_to_der(const SM2_POINT *a, uint8_t **out, size_t *outlen);
int sm2_point_from_der(SM2_POINT *a, 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);
int sm2_point_mul(SM2_POINT *R, const uint8_t k[32], const SM2_POINT *P);
int sm2_point_mul_generator(SM2_POINT *R, const uint8_t k[32]);
int sm2_point_mul_sum(SM2_POINT *R, const uint8_t k[32], const SM2_POINT *P, const uint8_t s[32]);
int sm2_point_print(FILE *fp, const SM2_POINT *P, int format, int indent);
int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id);
typedef struct {
SM2_POINT public_key;
uint8_t private_key[32];
uint8_t key_usage[4];
} SM2_KEY;
int sm2_keygen(SM2_KEY *key);
int sm2_set_private_key(SM2_KEY *key, const uint8_t private_key[32]);
int sm2_set_public_key(SM2_KEY *key, const uint8_t public_key[64]); // FIXME: 这里是否应该用octets呢这算是椭圆曲线点的一个公开格式了
int sm2_key_print(FILE *fp, const SM2_KEY *key, int format, int indent);
int sm2_public_key_digest(const SM2_KEY *key, uint8_t dgst[32]);
// ECPrivateKey
int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen);
int sm2_private_key_to_pem(const SM2_KEY *key, FILE *fp);
int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen);
int sm2_private_key_from_pem(SM2_KEY *key, FILE *fp);
// AlgorithmIdentifier
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);
// X.509 SubjectPublicKeyInfo
int sm2_public_key_info_to_der(const SM2_KEY *a, uint8_t **out, size_t *outlen);
int sm2_public_key_info_to_pem(const SM2_KEY *a, FILE *fp);
int sm2_public_key_info_from_der(SM2_KEY *a, const uint8_t **in, size_t *inlen);
int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp);
// PKCS #8 PrivateKeyInfo
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_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);
typedef struct {
uint8_t r[32];
uint8_t s[32];
} SM2_SIGNATURE;
int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *outlen);
int sm2_signature_from_der(SM2_SIGNATURE *sig, const uint8_t **in, size_t *inlen);
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);
int sm2_print_signature(FILE *fp, const uint8_t *sig, size_t siglen, int format, int indent);
#define SM2_MAX_SIGNATURE_SIZE 72
int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen);
int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *sig, size_t siglen);
#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)
#define SM2_DEFAULT_ID_GMT09 "1234567812345678"
#define SM2_DEFAULT_ID_GMSSL "anonym@gmssl.org"
#define SM2_DEFAULT_ID SM2_DEFAULT_ID_GMT09
#define SM2_DEFAULT_ID_LENGTH (sizeof(SM2_DEFAULT_ID) - 1)
#define SM2_DEFAULT_ID_BITS (SM2_DEFAULT_ID_LENGTH * 8)
#define SM2_DEFAULT_ID_DIGEST_LENGTH SM3_DIGEST_LENGTH
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);
int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen);
int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id);
int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen);
typedef struct {
SM2_POINT point;
uint8_t hash[32];
uint32_t ciphertext_size;
uint8_t ciphertext[1];
} SM2_CIPHERTEXT;
#define SM2_MAX_PLAINTEXT 256
#define SM2_MAX_PLAINTEXT_SIZE 256
#define SM2_CIPHERTEXT_SIZE(inlen) (sizeof(SM2_CIPHERTEXT)-1+inlen)
#define SM2_MAX_CIPHERTEXT_SIZE 512
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, const SM2_CIPHERTEXT *c, int format, int indent);
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);
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_print_ciphertext(FILE *fp, const uint8_t *c, size_t clen, int format, int indent);
int sm2_ecdh(const SM2_KEY *key, const SM2_POINT *peer_public, SM2_POINT *out);
int sm2_algo_selftest(void);
#ifdef __cplusplus
extern "C" {
#endif
#endif

101
include/gmssl/sm3.h Executable file
View File

@@ -0,0 +1,101 @@
/*
* 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_SM3_H
#define GMSSL_SM3_H
#define SM3_IS_BIG_ENDIAN 1
#define SM3_DIGEST_SIZE 32
#define SM3_BLOCK_SIZE 64
#define SM3_STATE_WORDS 8
#define SM3_HMAC_SIZE (SM3_DIGEST_SIZE)
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t digest[SM3_STATE_WORDS];
uint64_t nblocks;
uint8_t block[SM3_BLOCK_SIZE];
int num;
} SM3_CTX;
void sm3_init(SM3_CTX *ctx);
void sm3_update(SM3_CTX *ctx, const uint8_t *data, size_t datalen);
void sm3_finish(SM3_CTX *ctx, uint8_t dgst[SM3_DIGEST_SIZE]);
void sm3_compress(uint32_t dgst[SM3_STATE_WORDS], const uint8_t block[SM3_BLOCK_SIZE]);
void sm3_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SM3_DIGEST_SIZE]);
typedef struct {
SM3_CTX sm3_ctx;
unsigned char key[SM3_BLOCK_SIZE];
} SM3_HMAC_CTX;
void sm3_hmac_init(SM3_HMAC_CTX *ctx, const uint8_t *key, size_t keylen);
void sm3_hmac_update(SM3_HMAC_CTX *ctx, const uint8_t *data, size_t datalen);
void sm3_hmac_finish(SM3_HMAC_CTX *ctx, uint8_t mac[SM3_HMAC_SIZE]);
void sm3_hmac_reset(SM3_HMAC_CTX *ctx);
void sm3_hmac(const uint8_t *key, size_t keylen,
const uint8_t *data, size_t datalen,
uint8_t mac[SM3_HMAC_SIZE]);
int sm3_hmac_finish_and_verify(SM3_HMAC_CTX *ctx, const uint8_t mac[SM3_HMAC_SIZE]);
#ifdef __cplusplus
}
#endif
#endif

105
include/gmssl/sm4.h Normal file
View File

@@ -0,0 +1,105 @@
/*
* 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_SM4_H
#define GMSSL_SM4_H
#define SM4_KEY_SIZE 16
#define SM4_KEY_LENGTH 16
#define SM4_BLOCK_SIZE 16
#define SM4_IV_LENGTH (SM4_BLOCK_SIZE)
#define SM4_NUM_ROUNDS 32
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t rk[SM4_NUM_ROUNDS];
} SM4_KEY;
void sm4_set_encrypt_key(SM4_KEY *key, const unsigned char user_key[16]);
void sm4_set_decrypt_key(SM4_KEY *key, const unsigned char user_key[16]);
void sm4_encrypt(const SM4_KEY *key, const unsigned char in[16], unsigned char out[16]);
#define sm4_decrypt(key,in,out) sm4_encrypt(key,in,out)
# define SM4_EDE_KEY_LENGTH (SM4_KEY_LENGTH * 3)
typedef struct {
SM4_KEY k1;
SM4_KEY k2;
SM4_KEY k3;
} SM4_EDE_KEY;
void sm4_ede_set_encrypt_key(SM4_EDE_KEY *key, const unsigned char user_key[48]);
void sm4_ede_set_decrypt_key(SM4_EDE_KEY *key, const unsigned char user_key[48]);
void sm4_ede_encrypt(const SM4_EDE_KEY *key, const unsigned char in[16], unsigned char out[16]);
# define sm4_ede_decrypt(key,in,out) sm4_ede_encrypt(key,in,out)
void sm4_cbc_encrypt(const SM4_KEY *key, const uint8_t iv[16], const uint8_t *in, size_t nblocks, uint8_t *out);
void sm4_cbc_decrypt(const SM4_KEY *key, const uint8_t iv[16], const uint8_t *in, size_t nblocks, uint8_t *out);
int sm4_cbc_padding_encrypt(const SM4_KEY *key, const uint8_t iv[16],
const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen);
int sm4_cbc_padding_decrypt(const SM4_KEY *key, const uint8_t iv[16],
const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen);
#ifdef __cplusplus
}
#endif
#endif

96
include/gmssl/sm9.h Normal file
View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2016 - 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_SM9_H
#define GMSSL_SM9_H
#ifdef __cplusplus
extern "C" {
#endif
// set the same value as sm2
#define SM9_MAX_ID_BITS 65535
#define SM9_MAX_ID_SIZE (SM9_MAX_ID_BITS/8)
typedef struct {
uint8_t x[32];
uint8_t y[32];
} SM9_POINT;
typedef struct {
uint8_t x[64];
uint8_t y[64];
} SM9_TWIST_POINT;
typedef struct {
uint8_t ks[32];
SM9_TWIST_POINT Ppubs; // Ppubs = ks * P2
} SM9_SIGN_MASTER_KEY;
typedef struct {
SM9_POINT ds;
} SM9_SIGN_KEY;
typedef struct {
uint8_t h[32];
SM9_TWIST_POINT S;
} SM9_SIGNATURE;
int sm9_sign_setup(SM9_SIGN_MASTER_KEY *msk);
int sm9_sign_keygen(SM9_SIGN_MASTER_KEY *msk, const char *id, size_t idlen, SM9_POINT *ds);
int sm9_do_sign(SM9_SIGN_KEY *key, const uint8_t dgst[32], SM9_SIGNATURE *sig);
int sm9_do_verify(SM9_SIGN_KEY *key, const uint8_t dgst[32], const SM9_SIGNATURE *sig);
# ifdef __cplusplus
}
# endif
# endif

640
include/gmssl/tls.h Normal file
View File

@@ -0,0 +1,640 @@
/*
* Copyright (c) 2020 - 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_TLS_H
#define GMSSL_TLS_H
#include <stdint.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/sm4.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint32_t uint24_t;
void tls_uint8_to_bytes(uint8_t a, uint8_t **out, size_t *outlen);
void tls_uint16_to_bytes(uint16_t a, uint8_t **out, size_t *outlen);
void tls_uint24_to_bytes(uint24_t a, uint8_t **out, size_t *outlen);
void tls_uint32_to_bytes(uint32_t a, uint8_t **out, size_t *outlen);
void tls_array_to_bytes(const uint8_t *data, size_t len, uint8_t **out, size_t *outlen);
void tls_uint8array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen);
void tls_uint16array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen);
void tls_uint24array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen);
int tls_uint8_from_bytes(uint8_t *a, const uint8_t **in, size_t *inlen);
int tls_uint16_from_bytes(uint16_t *a, const uint8_t **in, size_t *inlen);
int tls_uint24_from_bytes(uint24_t *a, const uint8_t **in, size_t *inlen);
int tls_uint32_from_bytes(uint32_t *a, const uint8_t **in, size_t *inlen);
int tls_array_from_bytes(const uint8_t **data, size_t datalen, const uint8_t **in, size_t *inlen);
int tls_uint8array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen);
int tls_uint16array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen);
int tls_uint24array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen);
int tls_array_copy_from_bytes(uint8_t *data, size_t datalen, const uint8_t **in, size_t *inlen);
int tls_uint8array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen);
int tls_uint16array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen);
int tls_uint24array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen);
#define TLCP_VERSION_MAJOR 1
#define TLCP_VERSION_MINOR 1
typedef enum {
TLS_version_tlcp = 0x0101,
TLS_version_ssl2 = 0x0200,
TLS_version_ssl3 = 0x0300,
TLS_version_tls1 = 0x0301,
TLS_version_tls11 = 0x0302,
TLS_version_tls12 = 0x0303,
TLS_version_tls13 = 0x0304,
TLS_version_dtls1 = 0xfeff, // {254, 255}
TLS_version_dtls12 = 0xfefd, // {254, 253}
} TLS_VERSION;
typedef enum {
TLS_cipher_null_with_null_null = 0x0000,
TLS_cipher_sm4_gcm_sm3 = 0x00c6,
TLS_cipher_sm4_ccm_sm3 = 0x00c7,
TLCP_cipher_ecdhe_sm4_cbc_sm3 = 0xe011,
TLCP_cipher_ecdhe_sm4_gcm_sm3 = 0xe051,
TLCP_cipher_ecc_sm4_cbc_sm3 = 0xe013,
TLCP_cipher_ecc_sm4_gcm_sm3 = 0xe053,
TLCP_cipher_ibsdh_sm4_cbc_sm3 = 0xe015,
TLCP_cipher_ibsdh_sm4_gcm_sm3 = 0xe055,
TLCP_cipher_ibc_sm4_cbc_sm3 = 0xe017,
TLCP_cipher_ibc_sm4_gcm_sm3 = 0xe057,
TLCP_cipher_rsa_sm4_cbc_sm3 = 0xe019,
TLCP_cipher_rsa_sm4_gcm_sm3 = 0xe059,
TLCP_cipher_rsa_sm4_cbc_sha256 = 0xe01c,
TLCP_cipher_rsa_sm4_gcm_sha256 = 0xe05a,
GMSSL_cipher_ecdhe_sm2_with_sm4_sm3 = 0xe102,
GMSSL_cipher_ecdhe_sm2_with_sm4_gcm_sm3 = 0xe107,
GMSSL_cipher_ecdhe_sm2_with_sm4_ccm_sm3 = 0xe108,
GMSSL_cipher_ecdhe_sm2_with_zuc_sm3 = 0xe10d,
TLS_cipher_empty_renegotiation_info_scsv = 0x00ff,
} TLS_CIPHER_SUITE;
typedef enum {
TLS_record_change_cipher_spec = 20,
TLS_record_alert = 21,
TLS_record_handshake = 22,
TLS_record_application_data = 23,
TLS_record_heartbeat = 24,
TLS_record_tls12_cid = 25,
} TLS_RECORD_TYPE;
typedef enum {
TLS_handshake_hello_request = 0,
TLS_handshake_client_hello = 1,
TLS_handshake_server_hello = 2,
TLS_handshake_hello_verify_request = 3,
TLS_handshake_new_session_ticket = 4,
TLS_handshake_end_of_early_data = 5,
TLS_handshake_hello_retry_request = 6,
TLS_handshake_encrypted_extensions = 8,
TLS_handshake_certificate = 11,
TLS_handshake_server_key_exchange = 12,
TLS_handshake_certificate_request = 13,
TLS_handshake_server_hello_done = 14,
TLS_handshake_certificate_verify = 15,
TLS_handshake_client_key_exchange = 16,
TLS_handshake_finished = 20,
TLS_handshake_certificate_url = 21,
TLS_handshake_certificate_status = 22,
TLS_handshake_supplemental_data = 23,
TLS_handshake_key_update = 24,
TLS_handshake_compressed_certificate = 25,
TLS_handshake_ekt_key = 26,
TLS_handshake_message_hash = 254,
} TLS_HANDSHAKE_TYPE;
typedef enum {
TLS_compression_null = 0,
TLS_compression_default = 1,
} TLS_COMPRESSION_METHOD;
typedef enum {
TLS_cert_type_rsa_sign = 1,
TLS_cert_type_dss_sign = 2,
TLS_cert_type_rsa_fixed_dh = 3,
TLS_cert_type_dss_fixed_dh = 4,
TLS_cert_type_rsa_ephemeral_dh_RESERVED = 5,
TLS_cert_type_dss_ephemeral_dh_RESERVED = 6,
TLS_cert_type_fortezza_dms_RESERVED = 20,
TLS_cert_type_ecdsa_sign = 64, // also for sm2
TLS_cert_type_rsa_fixed_ecdh = 65,
TLS_cert_type_ecdsa_fixed_ecdh = 66,
TLS_cert_type_gost_sign256 = 67,
TLS_cert_type_gost_sign512 = 68,
TLS_cert_type_ibc_params = 80,
} TLS_CERTIFICATE_TYPE;
typedef enum {
TLS_extension_server_name = 0,
TLS_extension_max_fragment_length = 1,
TLS_extension_client_certificate_url = 2,
TLS_extension_trusted_ca_keys = 3,
TLS_extension_truncated_hmac = 4,
TLS_extension_status_request = 5,
TLS_extension_user_mapping = 6,
TLS_extension_client_authz = 7,
TLS_extension_server_authz = 8,
TLS_extension_cert_type = 9, // 这个是支持服务器证书的类型吗仅仅用CIPHER_SUITE不够吗
TLS_extension_supported_groups = 10, // 必须支持
TLS_extension_ec_point_formats = 11, // 必须支持
TLS_extension_srp = 12,
TLS_extension_signature_algorithms = 13, // 必须支持
TLS_extension_use_srtp = 14,
TLS_extension_heartbeat = 15,
TLS_extension_application_layer_protocol_negotiation= 16,
TLS_extension_status_request_v2 = 17,
TLS_extension_signed_certificate_timestamp = 18,
TLS_extension_client_certificate_type = 19,
TLS_extension_server_certificate_type = 20,
TLS_extension_padding = 21,
TLS_extension_encrypt_then_mac = 22, // 应该支持
TLS_extension_extended_master_secret = 23, // 这个是什么意思?
TLS_extension_token_binding = 24,
TLS_extension_cached_info = 25,
TLS_extension_tls_lts = 26,
TLS_extension_compress_certificate = 27,
TLS_extension_record_size_limit = 28,
TLS_extension_pwd_protect = 29,
TLS_extension_pwd_clear = 30,
TLS_extension_password_salt = 31,
TLS_extension_ticket_pinning = 32,
TLS_extension_tls_cert_with_extern_psk = 33,
TLS_extension_delegated_credentials = 34,
TLS_extension_session_ticket = 35, // 应该支持
TLS_extension_TLMSP = 36,
TLS_extension_TLMSP_proxying = 37,
TLS_extension_TLMSP_delegate = 38,
TLS_extension_supported_ekt_ciphers = 39,
TLS_extension_pre_shared_key = 41,
TLS_extension_early_data = 42,
TLS_extension_supported_versions = 43,
TLS_extension_cookie = 44,
TLS_extension_psk_key_exchange_modes = 46,
TLS_extension_certificate_authorities = 47,
TLS_extension_oid_filters = 48,
TLS_extension_post_handshake_auth = 49,
TLS_extension_signature_algorithms_cert = 50,
TLS_extension_key_share = 51,
TLS_extension_transparency_info = 52,
TLS_extension_connection_id = 53,
TLS_extension_external_id_hash = 55,
TLS_extension_external_session_id = 56,
TLS_extension_quic_transport_parameters = 57,
TLS_extension_ticket_request = 58,
TLS_extension_renegotiation_info = 65281,
} TLS_EXTENSION_TYPE;
typedef enum {
TLS_point_uncompressed = 0,
TLS_point_ansix962_compressed_prime = 1,
TLS_point_ansix962_compressed_char2 = 2,
} TLS_EC_POINT_FORMAT;
typedef enum {
TLS_curve_type_explicit_prime = 1,
TLS_curve_type_explicit_char2 = 2,
TLS_curve_type_named_curve = 3,
} TLS_CURVE_TYPE;
typedef enum {
TLS_curve_secp256k1 = 22,
TLS_curve_secp256r1 = 23,
TLS_curve_secp384r1 = 24,
TLS_curve_secp521r1 = 25,
TLS_curve_brainpoolp256r1 = 26,
TLS_curve_brainpoolp384r1 = 27,
TLS_curve_brainpoolp512r1 = 28,
TLS_curve_x25519 = 29,
TLS_curve_x448 = 99, //30,
TLS_curve_brainpoolp256r1tls13 = 31,
TLS_curve_brainpoolp384r1tls13 = 32,
TLS_curve_brainpoolp512r1tls13 = 33,
TLS_curve_sm2p256v1 = 30,//41, // in gmssl v2, is 30
} TLS_NAMED_CURVE;
typedef enum {
TLS_sig_rsa_pkcs1_sha1 = 0x0201,
TLS_sig_ecdsa_sha1 = 0x0203,
TLS_sig_rsa_pkcs1_sha256 = 0x0401,
TLS_sig_ecdsa_secp256r1_sha256 = 0x0403,
TLS_sig_rsa_pkcs1_sha256_legacy = 0x0420,
TLS_sig_rsa_pkcs1_sha384 = 0x0501,
TLS_sig_ecdsa_secp384r1_sha384 = 0x0503,
TLS_sig_rsa_pkcs1_sha384_legacy = 0x0520,
TLS_sig_rsa_pkcs1_sha512 = 0x0601,
TLS_sig_ecdsa_secp521r1_sha512 = 0x0603,
TLS_sig_rsa_pkcs1_sha512_legacy = 0x0620,
TLS_sig_sm2sig_sm3 = 0x0707,//0x0708, // is 0707 in gmsslv2
TLS_sig_rsa_pss_rsae_sha256 = 0x0804,
TLS_sig_rsa_pss_rsae_sha384 = 0x0805,
TLS_sig_rsa_pss_rsae_sha512 = 0x0806,
TLS_sig_ed25519 = 0x0807,
TLS_sig_ed448 = 0x0808,
TLS_sig_rsa_pss_pss_sha256 = 0x0809,
TLS_sig_rsa_pss_pss_sha384 = 0x080A,
TLS_sig_rsa_pss_pss_sha512 = 0x080B,
TLS_sig_ecdsa_brainpoolP256r1tls13_sha256 = 0x081A,
TLS_sig_ecdsa_brainpoolP384r1tls13_sha384 = 0x081B,
TLS_sig_ecdsa_brainpoolP512r1tls13_sha512 = 0x081C,
} TLS_SIGNATURE_SCHEME;
typedef enum {
TLS_change_cipher_spec = 1,
} TLS_CHANGE_CIPHER_SPEC_TYPE;
typedef enum {
TLS_alert_level_warning = 1,
TLS_alert_level_fatal = 2,
} TLS_ALERT_LEVEL;
typedef enum {
TLS_alert_close_notify = 0,
TLS_alert_unexpected_message = 10,
TLS_alert_bad_record_mac = 20,
TLS_alert_decryption_failed = 21,
TLS_alert_record_overflow = 22,
TLS_alert_decompression_failure = 30,
TLS_alert_handshake_failure = 40,
TLS_alert_no_certificate = 41,
TLS_alert_bad_certificate = 42,
TLS_alert_unsupported_certificate = 43,
TLS_alert_certificate_revoked = 44,
TLS_alert_certificate_expired = 45,
TLS_alert_certificate_unknown = 46,
TLS_alert_illegal_parameter = 47,
TLS_alert_unknown_ca = 48,
TLS_alert_access_denied = 49,
TLS_alert_decode_error = 50,
TLS_alert_decrypt_error = 51,
TLS_alert_export_restriction = 60,
TLS_alert_protocol_version = 70,
TLS_alert_insufficient_security = 71,
TLS_alert_internal_error = 80,
TLS_alert_user_canceled = 90,
TLS_alert_no_renegotiation = 100,
TLS_alert_unsupported_site2site = 200,
TLS_alert_no_area = 201,
TLS_alert_unsupported_areatype = 202,
TLS_alert_bad_ibcparam = 203,
TLS_alert_unsupported_ibcparam = 204,
TLS_alert_identity_need = 205,
} TLS_ALERT_DESCRIPTION;
#define TLS_RECORD_MAX_PLAINDATA_SIZE 16384 // 2^14
#define TLS_RECORD_MAX_DATA_SIZE 18432 // 2^24 + 2048
#define TLS_RECORD_MAX_SIZE 18437 // 5 + (2^24 + 2048)
#define TLS_MAX_RECORD_SIZE 18437 // 5 + (2^24 + 2048)
#define TLS_MAX_SIGNATURE_SIZE SM2_MAX_SIGNATURE_SIZE
#define TLS_MAX_EXTENSIONS_SIZE 512
#define TLS_MAX_CERT_SIZE 1024
#define TLS_MAX_CERTIFICATES_SIZE 2048
#define TLS_MAX_SERVER_CERTS_SIZE 2048
#define TLS_MAX_HANDSHAKES_SIZE 4096
// 应该保留对方的证书
// 我们应该讲这个值编码为一个标准的TLS的结构
typedef struct {
int is_client;
int version;
int cipher_suite;
int compression_method;
uint8_t master_secret[48];
uint8_t server_certs[1600];
size_t server_certs_size;
uint8_t client_cert[1024];
size_t client_cert_size;
} TLS_SESSION;
typedef struct {
int sock;
int is_client;
int version;
int cipher_suite;
uint8_t session_id[32];
size_t session_id_len;
uint8_t master_secret[48];
uint8_t key_block[96];
int do_trace;
uint8_t server_certs[TLS_MAX_CERTIFICATES_SIZE];
size_t server_certs_len;
uint8_t client_certs[TLS_MAX_CERTIFICATES_SIZE];
size_t client_certs_len;
SM3_HMAC_CTX client_write_mac_ctx;
SM3_HMAC_CTX server_write_mac_ctx;
SM4_KEY client_write_enc_key;
SM4_KEY server_write_enc_key;
uint8_t client_seq_num[8];
uint8_t server_seq_num[8];
uint8_t record[TLS_MAX_RECORD_SIZE];
uint8_t handshakes[TLS_MAX_HANDSHAKES_SIZE];
size_t handshakes_len;
} TLS_CONNECT;
// 有可能在连接建立之后客户端还是想获得一些这个连接的有关信息呢比如random中有时间信息
// 服务器的证书一定是需要的吧
// 客户端证书应该是预置的
int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port,
FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key);
int tlcp_accept(TLS_CONNECT *conn, int port,
FILE *server_certs_fp, const SM2_KEY *server_sign_key, const SM2_KEY *server_enc_key,
FILE *client_cacerts_fp, uint8_t *client_cert_verify_buf, size_t client_cert_verify_buflen);
int tls_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen);
int tls_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen);
int tls_seq_num_incr(uint8_t seq_num[8]);
int tls_prf(const uint8_t *secret, size_t secretlen, const char *label,
const uint8_t *seed, size_t seedlen,
const uint8_t *more, size_t morelen,
size_t outlen, uint8_t *out);
int tls_cbc_encrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *enc_key,
const uint8_t seq_num[8], const uint8_t header[5],
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
int tls_cbc_decrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *dec_key,
const uint8_t seq_num[8], const uint8_t header[5],
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
const char *tls_record_type_name(int type);
int tls_record_version(const uint8_t *record);
int tls_record_length(const uint8_t *record);
const char *tls_version_text(int version);
int tls_record_set_version(uint8_t *record, int version);
int tls_record_encrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key,
const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen);
int tls_record_decrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key,
const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen);
int tls_record_send(const uint8_t *record, size_t recordlen, int sock);
int tls_record_recv(uint8_t *record, size_t *recordlen, int sock);
int tls_random_generate(uint8_t random[32]);
int tls_random_print(FILE *fp, const uint8_t random[32], int format, int indent);
int tls_pre_master_secret_generate(uint8_t pre_master_secret[48], int version);
int tls_pre_master_secret_print(FILE *fp, const uint8_t pre_master_secret[48], int format, int indent);
int tls_cipher_suite_in_list(int cipher, const int *list, size_t list_count);
const char *tlcp_cipher_suite_name(int cipher);
const char *tls_cipher_suite_name(int cipher);
const char *tls_compression_method_name(int meth);
int tls_record_set_handshake(uint8_t *record, size_t *recordlen,
int type, const uint8_t *data, size_t datalen);
int tls_record_get_handshake(const uint8_t *record,
int *type, const uint8_t **data, size_t *datalen);
int tls_record_set_handshake_client_hello(uint8_t *record, size_t *recordlen,
int client_version, const uint8_t random[32],
const uint8_t *session_id, size_t session_id_len,
const int *cipher_suites, size_t cipher_suites_count,
const uint8_t *exts, size_t exts_len);
int tls_record_get_handshake_client_hello(const uint8_t *record,
int *client_version, uint8_t random[32],
uint8_t *session_id, size_t *session_id_len,
int *cipher_suites, size_t *cipher_suites_count,
uint8_t *exts, size_t *exts_len);
int tls_client_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent);
int tls_record_set_handshake_server_hello(uint8_t *record, size_t *recordlen,
int server_version, const uint8_t random[32],
const uint8_t *session_id, size_t session_id_len, int cipher_suite,
const uint8_t *exts, size_t exts_len);
int tls_record_get_handshake_server_hello(const uint8_t *record,
int *version, uint8_t random[32], uint8_t *session_id, size_t *session_id_len,
int *cipher_suite, uint8_t *exts, size_t *exts_len);
int tls_server_hello_print(FILE *fp, const uint8_t *server_hello, size_t len, int format, int indent);
int tls_record_set_handshake_certificate(uint8_t *record, size_t *recordlen,
const uint8_t *certs, size_t certslen);
int tls_record_set_handshake_certificate_from_pem(uint8_t *record, size_t *recordlen, FILE *fp);
int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *certs, size_t *certslen);
int tls_certificate_get_subject_names(const uint8_t *certs, size_t certslen, uint8_t *names, size_t *nameslen);
int tls_certificate_get_public_keys(const uint8_t *certs, size_t certslen, SM2_KEY *sign_key, SM2_KEY *enc_key);
int tls_certificate_print(FILE *fp, const uint8_t *certs, size_t certslen, int format, int indent);
int tls_certificate_chain_verify(const uint8_t *certs, size_t certslen, FILE *ca_certs_fp, int depth);
int tls_certificate_get_first(const uint8_t *data, size_t datalen, const uint8_t **cert, size_t *certlen);
int tls_certificate_get_second(const uint8_t *data, size_t datalen, const uint8_t **cert, size_t *certlen);
// 应该把所有TLCP协议的内容放到一起
int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *recordlen,
const uint8_t *sig, size_t siglen);
int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record,
uint8_t *sig, size_t *siglen);
int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *sig, size_t siglen, int format, int indent);
int tls_server_key_exchange_print(FILE *fp, const uint8_t *ske, size_t skelen, int format, int indent);
const char *tls_cert_type_name(int type);
#define TLS_MAX_CERTIFICATE_TYPES 16
#define TLS_MAX_CA_NAMES_SIZE 256
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);
int tls_record_get_handshake_certificate_request(const uint8_t *record,
int *cert_types, size_t *cert_types_count,
uint8_t *ca_names, size_t *ca_names_len);
int tls_certificate_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent);
int tls_record_set_handshake_server_hello_done(uint8_t *record, size_t *recordlen);
int tls_record_get_handshake_server_hello_done(const uint8_t *record);
int tls_server_hello_done_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent);
int tls_record_set_handshake_client_key_exchange_pke(uint8_t *record, size_t *recordlen,
const uint8_t *enced_pms, size_t enced_pms_len);
int tls_record_get_handshake_client_key_exchange_pke(const uint8_t *record,
uint8_t *enced_pms, size_t *enced_pms_len);
int tls_client_key_exchange_pke_print(FILE *fp, const uint8_t *cke, size_t ckelen, int format, int indent);
int tls_client_key_exchange_print(FILE *fp, const uint8_t *cke, size_t ckelen, int format, int indent);
int tls_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen,
const uint8_t *sig, size_t siglen);
int tls_record_get_handshake_certificate_verify(const uint8_t *record,
uint8_t *sig, size_t *siglen);
int tls_certificate_verify_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent);
int tls_record_set_handshake_finished(uint8_t *record, size_t *recordlen,
const uint8_t verify_data[12]);
int tls_record_get_handshake_finished(const uint8_t *record, uint8_t verify_data[12]);
int tls_finished_print(FILE *fp, const uint8_t *a, size_t len, int format, int indent);
const char *tls_handshake_type_name(int type);
int tls_handshake_print(FILE *fp, const uint8_t *handshake, size_t handshakelen, int format, int indent);
const char *tls_alert_level_name(int level);
const char *tls_alert_description_text(int description);
int tls_alert_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent);
int tls_record_set_alert(uint8_t *record, size_t *recordlen,
int alert_level,
int alert_description);
int tls_record_get_alert(const uint8_t *record,
int *alert_level,
int *alert_description);
const char *tls_change_cipher_spec_text(int change_cipher_spec);
int tls_record_set_change_cipher_spec(uint8_t *record, size_t *recordlen);
int tls_record_get_change_cipher_spec(const uint8_t *record);
int tls_change_cipher_spec_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent);
int tls_record_set_application_data(uint8_t *record, size_t *recordlen,
const uint8_t *data, size_t datalen);
int tls_record_get_application_data(uint8_t *record,
const uint8_t **data, size_t *datalen);
int tls_application_data_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent);
int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent);
const char *tls_ec_point_format_name(int format);
const char *tls_curve_type_name(int type);
const char *tls_named_curve_name(int curve);
const char *tls_signature_scheme_name(int scheme);
int tls_sign_server_ecdh_params(const SM2_KEY *server_sign_key,
const uint8_t client_random[32], const uint8_t server_random[32],
int curve, const SM2_POINT *point, uint8_t *sig, size_t *siglen);
int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key,
const uint8_t client_random[32], const uint8_t server_random[32],
int curve, const SM2_POINT *point, const uint8_t *sig, size_t siglen);
int tls_record_set_handshake_server_key_exchange_ecdhe(uint8_t *record, size_t *recordlen,
int curve, const SM2_POINT *point, const uint8_t *sig, size_t siglen);
int tls_record_get_handshake_server_key_exchange_ecdhe(const uint8_t *record,
int *curve, SM2_POINT *point, uint8_t *sig, size_t *siglen);
int tls_server_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t datalen,
int format, int indent);
int tls_record_set_handshake_client_key_exchange_ecdhe(uint8_t *record, size_t *recordlen,
const SM2_POINT *point);
int tls_record_get_handshake_client_key_exchange_ecdhe(const uint8_t *record, SM2_POINT *point);
int tls_client_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t datalen,
int format, int indent);
int tls12_connect(TLS_CONNECT *conn, const char *hostname, int port,
FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key);
int tls12_accept(TLS_CONNECT *conn, int port,
FILE *certs_fp, const SM2_KEY *server_sign_key,
FILE *client_cacerts_fp, uint8_t *handshakes_buf, size_t handshakes_buflen);
int tls_secrets_print(FILE *fp,
const uint8_t *pre_master_secret, size_t pre_master_secret_len,
const uint8_t client_random[32], const uint8_t server_random[32],
const uint8_t master_secret[48],
const uint8_t *key_block, size_t key_block_len,
int format, int indent);
#define tls_trace printf
#ifdef __cplusplus
}
#endif
#endif

1114
include/gmssl/x509.h Normal file

File diff suppressed because it is too large Load Diff

137
include/gmssl/zuc.h Executable file
View File

@@ -0,0 +1,137 @@
/*
* 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_ZUC_H
#define GMSSL_ZUC_H
#include <stdlib.h>
#include <stdint.h>
typedef uint32_t ZUC_BIT;
typedef uint32_t ZUC_UINT5;
typedef uint8_t ZUC_UINT6;
typedef uint32_t ZUC_UINT15;
typedef uint32_t ZUC_UINT31;
typedef uint32_t ZUC_UINT32;
#ifdef __cplusplus
extern "C" {
#endif
# define ZUC_KEY_LENGTH 16
# define ZUC_IV_LENGTH 16
# define ZUC_MAC_LENGTH 4
typedef struct ZUC_KEY_st {
ZUC_UINT31 LFSR[16];
ZUC_UINT32 R1;
ZUC_UINT32 R2;
} ZUC_KEY;
void zuc_set_key(ZUC_KEY *key, const unsigned char user_key[16], const unsigned char iv[16]);
void zuc_generate_keystream(ZUC_KEY *key, size_t nwords, ZUC_UINT32 *words);
ZUC_UINT32 zuc_generate_keyword(ZUC_KEY *key);
typedef struct ZUC_MAC_CTX_st {
ZUC_UINT31 LFSR[16];
ZUC_UINT32 R1;
ZUC_UINT32 R2;
ZUC_UINT32 T;
ZUC_UINT32 K0;
unsigned char buf[4];
int buflen;
} ZUC_MAC_CTX;
void zuc_mac_init(ZUC_MAC_CTX *ctx, const unsigned char key[16], const unsigned char iv[16]);
void zuc_mac_update(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t len);
void zuc_mac_finish(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char mac[4]);
void zuc_eea_encrypt(const ZUC_UINT32 *in, ZUC_UINT32 *out, size_t nbits,
const unsigned char key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
ZUC_BIT direction);
ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits,
const unsigned char user_key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
ZUC_BIT direction);
# define ZUC256_KEY_LENGTH 32
# define ZUC256_IV_LENGTH 23
# define ZUC256_MAC32_LENGTH 4
# define ZUC256_MAC64_LENGTH 8
# define ZUC256_MAC128_LENGTH 16
# define ZUC256_MIN_MAC_LENGTH ZUC256_MAC32_LENGTH
# define ZUC256_MAX_MAC_LENGTH ZUC256_MAC128_LENGTH
typedef ZUC_KEY ZUC256_KEY;
void zuc256_set_key(ZUC256_KEY *key, const unsigned char user_key[32],
const unsigned char iv[23]);
#define zuc256_generate_keystream(k,n,out) zuc_generate_keystream(k,n,out)
#define zuc256_generate_keyword(k) zuc_generate_keyword(k)
typedef struct ZUC256_MAC_CTX_st {
ZUC_UINT31 LFSR[16];
ZUC_UINT32 R1;
ZUC_UINT32 R2;
ZUC_UINT32 T[4];
ZUC_UINT32 K0[4];
unsigned char buf[4];
int buflen;
int macbits;
} ZUC256_MAC_CTX;
void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const unsigned char key[32], const unsigned char iv[23], int macbits);
void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t len);
void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char *mac);
#ifdef __cplusplus
}
#endif
#endif

480
src/aes.c Normal file
View File

@@ -0,0 +1,480 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/aes.h>
#include "bswap.h"
#include "rotate.h"
static const uint8_t S[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
static const uint8_t S_inv[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
static const uint8_t Rcon[11] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
};
static uint32_t sub_word(uint32_t A)
{
return S[(A >> 24) & 0xff] << 24 |
S[(A >> 16) & 0xff] << 16 |
S[(A >> 8) & 0xff] << 8 |
S[A & 0xff];
}
/* (a0,a1,a2,a3) => (a1,a2,a3,a0) */
static uint32_t rot_word(uint32_t A)
{
return ROL32(A, 8);
}
#ifdef CRYPTO_INFO
static void print_rk(const AES_KEY *aes_key)
{
int i;
for (i = 0; i <= aes_key->rounds; i++) {
printf("%08x ", aes_key->rk[4 * i]);
printf("%08x ", aes_key->rk[4 * i + 1]);
printf("%08x ", aes_key->rk[4 * i + 2]);
printf("%08x\n", aes_key->rk[4 * i + 3]);
}
printf("\n");
}
#endif
int aes_set_encrypt_key(AES_KEY *aes_key, const uint8_t *key, size_t keylen)
{
/* Nk: num user key words
* AES-128 Nk = 4 W[44]
* AES-192 Nk = 6 W[52]
* AES-256 Nk = 8 W[60]
*/
uint32_t *W = (uint32_t *)aes_key->rk;
size_t Nk = keylen/sizeof(uint32_t);
int i;
switch (keylen) {
case AES128_KEY_SIZE:
aes_key->rounds = 10;
break;
case AES192_KEY_SIZE:
aes_key->rounds = 12;
break;
case AES256_KEY_SIZE:
aes_key->rounds = 14;
break;
default:
return 0;
}
for (i = 0; i < Nk; i++) {
W[i] = GETU32(key + sizeof(uint32_t) * i);
}
for (; i < 4 * (aes_key->rounds + 1); i++) {
uint32_t T = W[i - 1];
if (i % Nk == 0) {
T = rot_word(T);
T = sub_word(T);
T ^= ((uint32_t)Rcon[i/Nk] << 24);
} else if (Nk == 8 && i % 8 == 4) {
T = sub_word(T);
}
W[i] = W[i - Nk] ^ T;
}
#ifdef CRYPTO_INFO
print_rk(aes_key);
#endif
return 1;
}
int aes_set_decrypt_key(AES_KEY *aes_key, const uint8_t *key, size_t keylen)
{
int ret = 0;
AES_KEY enc_key;
int i;
if (!aes_set_encrypt_key(&enc_key, key, keylen)) {
goto end;
}
for (i = 0; i <= enc_key.rounds; i++) {
aes_key->rk[4*i ] = enc_key.rk[4*(enc_key.rounds - i)];
aes_key->rk[4*i + 1] = enc_key.rk[4*(enc_key.rounds - i) + 1];
aes_key->rk[4*i + 2] = enc_key.rk[4*(enc_key.rounds - i) + 2];
aes_key->rk[4*i + 3] = enc_key.rk[4*(enc_key.rounds - i) + 3];
}
ret = 1;
#ifdef CRYPTO_INFO
print_rk(aes_key);
#endif
end:
memset(&enc_key, 0, sizeof(AES_KEY));
return ret;
}
/*
* |S00 S01 S02 S03| | |
* |S10 S11 S12 S13| xor |W0 W1 W2 W3|
* |S20 S21 S22 S23| | |
* |S30 S31 S32 S33| | |
*/
static void add_round_key(uint8_t state[4][4], const uint32_t *W)
{
int i;
for (i = 0; i < 4; i++) {
state[0][i] ^= (W[i] >> 24) & 0xff;
state[1][i] ^= (W[i] >> 16) & 0xff;
state[2][i] ^= (W[i] >> 8) & 0xff;
state[3][i] ^= (W[i] ) & 0xff;
}
}
static void sub_bytes(uint8_t state[4][4])
{
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
state[i][j] = S[state[i][j]];
}
}
}
static void inv_sub_bytes(uint8_t state[4][4])
{
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
state[i][j] = S_inv[state[i][j]];
}
}
}
/*
* |S00 S01 S02 S03| <<<0 |S00 S01 S02 S03|
* |S10 S11 S12 S13| <<<1 => |S11 S12 S13 S10|
* |S20 S21 S22 S23| <<<2 |S22 S23 S20 S21|
* |S30 S31 S32 S33| <<<3 |S33 S30 S31 S32|
*/
static void shift_rows(uint8_t state[4][4])
{
uint8_t tmp[4][4];
tmp[0][0] = state[0][0];
tmp[0][1] = state[0][1];
tmp[0][2] = state[0][2];
tmp[0][3] = state[0][3];
tmp[1][0] = state[1][1];
tmp[1][1] = state[1][2];
tmp[1][2] = state[1][3];
tmp[1][3] = state[1][0];
tmp[2][0] = state[2][2];
tmp[2][1] = state[2][3];
tmp[2][2] = state[2][0];
tmp[2][3] = state[2][1];
tmp[3][0] = state[3][3];
tmp[3][1] = state[3][0];
tmp[3][2] = state[3][1];
tmp[3][3] = state[3][2];
memcpy(state, tmp, sizeof(tmp));
memset(tmp, 0, sizeof(tmp));
}
/*
* |S00 S01 S02 S03| >>>0 |S00 S01 S02 S03|
* |S10 S11 S12 S13| >>>1 => |S13 S10 S11 S12|
* |S20 S21 S22 S23| >>>2 |S22 S23 S20 S21|
* |S30 S31 S32 S33| >>>3 |S31 S32 S33 S30|
*/
static void inv_shift_rows(uint8_t state[4][4])
{
uint8_t tmp[4][4];
tmp[0][0] = state[0][0];
tmp[0][1] = state[0][1];
tmp[0][2] = state[0][2];
tmp[0][3] = state[0][3];
tmp[1][0] = state[1][3];
tmp[1][1] = state[1][0];
tmp[1][2] = state[1][1];
tmp[1][3] = state[1][2];
tmp[2][0] = state[2][2];
tmp[2][1] = state[2][3];
tmp[2][2] = state[2][0];
tmp[2][3] = state[2][1];
tmp[3][0] = state[3][1];
tmp[3][1] = state[3][2];
tmp[3][2] = state[3][3];
tmp[3][3] = state[3][0];
memcpy(state, tmp, sizeof(tmp));
memset(tmp, 0, sizeof(tmp));
}
/*
* GF(2^8) defSed by f(x) = x^8 + x^4 + x^3 + x + 1
* x^8 == x^4 + x^3 + x + 1 = 0001,1011 = 0x1b
* if A[7] == 0 then 2 * A = (A << 1)
* else 2 * A = (A << 1) xor A
*/
#define x1(a) (a)
static uint8_t x2(uint8_t a) {
return (a >> 7) ? ((a << 1) ^ 0x1b) : (a << 1);
}
static uint8_t x3(uint8_t a) {
return x2(a) ^ x1(a);
}
static uint8_t x9(uint8_t a) {
return x2(x2(x2(a))) ^ x1(a);
}
/* 0x0b = 11 = 8 + 2 + 1 */
static uint8_t xb(uint8_t a) {
return x2(x2(x2(a))) ^ x2(a) ^ x1(a);
}
/* 0x0d = 13 = 8 + 4 + 1 */
static uint8_t xd(uint8_t a) {
return x2(x2(x2(a))) ^ x2(x2(a)) ^ x1(a);
}
/* 0x0e = 14 = 8 + 4 + 2 */
static uint8_t xe(uint8_t a) {
return x2(x2(x2(a))) ^ x2(x2(a)) ^ x2(a);
}
/*
* |2 3 1 1| |S00 S01 S02 S03|
* |1 2 3 1| |S10 S11 S12 S13|
* |1 1 2 3|*|S20 S21 S22 S23|
* |3 1 1 2| |S30 S31 S32 S33|
*/
static void mix_columns(uint8_t S[4][4])
{
uint8_t tmp[4][4];
int i;
/* i-th column */
for (i = 0; i < 4; i++) {
tmp[0][i] = x2(S[0][i]) ^ x3(S[1][i]) ^ x1(S[2][i]) ^ x1(S[3][i]);
tmp[1][i] = x1(S[0][i]) ^ x2(S[1][i]) ^ x3(S[2][i]) ^ x1(S[3][i]);
tmp[2][i] = x1(S[0][i]) ^ x1(S[1][i]) ^ x2(S[2][i]) ^ x3(S[3][i]);
tmp[3][i] = x3(S[0][i]) ^ x1(S[1][i]) ^ x1(S[2][i]) ^ x2(S[3][i]);
}
memcpy(S, tmp, sizeof(tmp));
memset(tmp, 0, sizeof(tmp));
}
/*
* |0E 0B 0D 09| |02 03 01 01| |1 0 0 0|
* |09 0E 0B 0D|*|01 02 03 01| = |0 1 0 0|
* |0D 09 0E 0B| |01 01 02 03| |0 0 1 0|
* |0B 0D 09 0E| |03 01 01 02| |0 0 0 1|
*
*/
static void inv_mix_columns(uint8_t S[4][4])
{
uint8_t tmp[4][4];
int i;
/* i-th column */
for (i = 0; i < 4; i++) {
tmp[0][i] = xe(S[0][i]) ^ xb(S[1][i]) ^ xd(S[2][i]) ^ x9(S[3][i]);
tmp[1][i] = x9(S[0][i]) ^ xe(S[1][i]) ^ xb(S[2][i]) ^ xd(S[3][i]);
tmp[2][i] = xd(S[0][i]) ^ x9(S[1][i]) ^ xe(S[2][i]) ^ xb(S[3][i]);
tmp[3][i] = xb(S[0][i]) ^ xd(S[1][i]) ^ x9(S[2][i]) ^ xe(S[3][i]);
}
memcpy(S, tmp, sizeof(tmp));
memset(tmp, 0, sizeof(tmp));
}
#ifdef CRYPTO_INFO
static void print_state(const uint8_t S[4][4])
{
int i;
for (i = 0; i < 4; i++) {
printf("%02x %02x %02x %02x\n", S[i][0], S[i][1], S[i][2], S[i][3]);
}
printf("\n");
}
#endif
void aes_encrypt(const AES_KEY *key, const uint8_t in[16], uint8_t out[16])
{
uint8_t state[4][4];
int i;
/* fill state columns */
for (i = 0; i < 4; i++) {
state[0][i] = *in++;
state[1][i] = *in++;
state[2][i] = *in++;
state[3][i] = *in++;
}
/* Sitial add round key */
add_round_key(state, key->rk);
/* first n-1 rounds */
for (i = 1; i < key->rounds; i++) {
sub_bytes(state);
shift_rows(state);
mix_columns(state);
add_round_key(state, key->rk + 4*i);
}
/* last round withtmp mix columns */
sub_bytes(state);
shift_rows(state);
add_round_key(state, key->rk + 4*i);
/* tmpput state columns */
for (i = 0; i < 4; i++) {
*out++ = state[0][i];
*out++ = state[1][i];
*out++ = state[2][i];
*out++ = state[3][i];
}
memset(state, 0, sizeof(state));
}
void aes_decrypt(const AES_KEY *aes_key, const uint8_t in[16], uint8_t out[16])
{
uint8_t state[4][4];
int i;
/* fill state columns */
for (i = 0; i < 4; i++) {
state[0][i] = *in++;
state[1][i] = *in++;
state[2][i] = *in++;
state[3][i] = *in++;
}
/* Sitial add round key */
add_round_key(state, aes_key->rk);
/* first n-1 rounds */
for (i = 1; i < aes_key->rounds; i++) {
inv_shift_rows(state);
inv_sub_bytes(state);
add_round_key(state, aes_key->rk + 4*i);
inv_mix_columns(state);
}
/* last round withtmp mix columns */
inv_shift_rows(state);
inv_sub_bytes(state);
add_round_key(state, aes_key->rk + 4*i);
/* tmpput state columns */
for (i = 0; i < 4; i++) {
*out++ = state[0][i];
*out++ = state[1][i];
*out++ = state[2][i];
*out++ = state[3][i];
}
memset(state, 0, sizeof(state));
}

1017
src/asn1.c Normal file

File diff suppressed because it is too large Load Diff

377
src/base64.c Normal file
View File

@@ -0,0 +1,377 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <gmssl/base64.h>
#include <gmssl/error.h>
static unsigned char conv_ascii2bin(unsigned char a);
#define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
/*-
* 64 char lines
* pad input with 0
* left over chars are set to =
* 1 byte => xx==
* 2 bytes => xxx=
* 3 bytes => xxxx
*/
#define BIN_PER_LINE (64/4*3)
#define CHUNKS_PER_LINE (64/4)
#define CHAR_PER_LINE (64+1)
static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz0123456789+/";
/*-
* 0xF0 is a EOLN
* 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
* 0xF2 is EOF
* 0xE0 is ignore at start of line.
* 0xFF is error
*/
#define B64_EOLN 0xF0
#define B64_CR 0xF1
#define B64_EOF 0xF2
#define B64_WS 0xE0
#define B64_ERROR 0xFF
#define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3)
#define B64_BASE64(a) (!B64_NOT_BASE64(a))
static const unsigned char data_ascii2bin[128] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
static unsigned char conv_ascii2bin(unsigned char a)
{
if (a & 0x80)
return B64_ERROR;
return data_ascii2bin[a];
}
int base64_ctx_num(BASE64_CTX *ctx)
{
return ctx->num;
}
void base64_encode_init(BASE64_CTX *ctx)
{
ctx->length = 48;
ctx->num = 0;
ctx->line_num = 0;
}
int base64_encode_update(BASE64_CTX *ctx, const uint8_t *in, int inl, uint8_t *out, int *outl)
{
int i, j;
size_t total = 0;
*outl = 0;
if (inl <= 0)
return 0;
assert(ctx->length <= (int)sizeof(ctx->enc_data));
if (ctx->length - ctx->num > inl) {
memcpy(&(ctx->enc_data[ctx->num]), in, inl);
ctx->num += inl;
return 1;
}
if (ctx->num != 0) {
i = ctx->length - ctx->num;
memcpy(&(ctx->enc_data[ctx->num]), in, i);
in += i;
inl -= i;
j = base64_encode_block(out, ctx->enc_data, ctx->length);
ctx->num = 0;
out += j;
*(out++) = '\n';
*out = '\0';
total = j + 1;
}
while (inl >= ctx->length && total <= INT_MAX) {
j = base64_encode_block(out, in, ctx->length);
in += ctx->length;
inl -= ctx->length;
out += j;
*(out++) = '\n';
*out = '\0';
total += j + 1;
}
if (total > INT_MAX) {
/* Too much output data! */
*outl = 0;
return 0;
}
if (inl != 0)
memcpy(&(ctx->enc_data[0]), in, inl);
ctx->num = inl;
*outl = total;
return 1;
}
void base64_encode_finish(BASE64_CTX *ctx, uint8_t *out, int *outl)
{
unsigned int ret = 0;
if (ctx->num != 0) {
ret = base64_encode_block(out, ctx->enc_data, ctx->num);
out[ret++] = '\n';
out[ret] = '\0';
ctx->num = 0;
}
*outl = ret;
}
int base64_encode_block(unsigned char *t, const unsigned char *f, int dlen)
{
int i, ret = 0;
unsigned long l;
for (i = dlen; i > 0; i -= 3) {
if (i >= 3) {
l = (((unsigned long)f[0]) << 16L) |
(((unsigned long)f[1]) << 8L) | f[2];
*(t++) = conv_bin2ascii(l >> 18L);
*(t++) = conv_bin2ascii(l >> 12L);
*(t++) = conv_bin2ascii(l >> 6L);
*(t++) = conv_bin2ascii(l);
} else {
l = ((unsigned long)f[0]) << 16L;
if (i == 2)
l |= ((unsigned long)f[1] << 8L);
*(t++) = conv_bin2ascii(l >> 18L);
*(t++) = conv_bin2ascii(l >> 12L);
*(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
*(t++) = '=';
}
ret += 4;
f += 3;
}
*t = '\0';
return (ret);
}
void base64_decode_init(BASE64_CTX *ctx)
{
/* Only ctx->num is used during decoding. */
ctx->num = 0;
ctx->length = 0;
ctx->line_num = 0;
ctx->expect_nl = 0;
}
/*-
* -1 for error
* 0 for last line
* 1 for full line
*
* Note: even though base64_decode_update attempts to detect and report end of
* content, the context doesn't currently remember it and will accept more data
* in the next call. Therefore, the caller is responsible for checking and
* rejecting a 0 return value in the middle of content.
*
* Note: even though base64_decode_update has historically tried to detect end of
* content based on line length, this has never worked properly. Therefore,
* we now return 0 when one of the following is true:
* - Padding or B64_EOF was detected and the last block is complete.
* - Input has zero-length.
* -1 is returned if:
* - Invalid characters are detected.
* - There is extra trailing padding, or data after padding.
* - B64_EOF is detected after an incomplete base64 block.
*/
int base64_decode_update(BASE64_CTX *ctx, const uint8_t *in, int inl, uint8_t *out, int *outl)
{
int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
unsigned char *d;
n = ctx->num;
d = ctx->enc_data;
if (n > 0 && d[n - 1] == '=') {
eof++;
if (n > 1 && d[n - 2] == '=')
eof++;
}
/* Legacy behaviour: an empty input chunk signals end of input. */
if (inl == 0) {
rv = 0;
goto end;
}
for (i = 0; i < inl; i++) {
tmp = *(in++);
v = conv_ascii2bin(tmp);
if (v == B64_ERROR) {
rv = -1;
error_print();
goto end;
}
if (tmp == '=') {
eof++;
} else if (eof > 0 && B64_BASE64(v)) {
/* More data after padding. */
rv = -1;
error_print();
goto end;
}
if (eof > 2) {
rv = -1;
error_print();
goto end;
}
if (v == B64_EOF) {
seof = 1;
goto tail;
}
/* Only save valid base64 characters. */
if (B64_BASE64(v)) {
if (n >= 64) {
/*
* We increment n once per loop, and empty the buffer as soon as
* we reach 64 characters, so this can only happen if someone's
* manually messed with the ctx. Refuse to write any more data.
*/
rv = -1;
error_print();
goto end;
}
assert(n < (int)sizeof(ctx->enc_data));
d[n++] = tmp;
}
if (n == 64) {
decoded_len = base64_decode_block(out, d, n);
n = 0;
if (decoded_len < 0 || eof > decoded_len) {
rv = -1;
goto end;
}
ret += decoded_len - eof;
out += decoded_len - eof;
}
}
/*
* Legacy behaviour: if the current line is a full base64-block (i.e., has
* 0 mod 4 base64 characters), it is processed immediately. We keep this
* behaviour as applications may not be calling base64_decode_final properly.
*/
tail:
if (n > 0) {
if ((n & 3) == 0) {
decoded_len = base64_decode_block(out, d, n);
n = 0;
if (decoded_len < 0 || eof > decoded_len) {
error_print();
rv = -1;
goto end;
}
ret += (decoded_len - eof);
} else if (seof) {
/* EOF in the middle of a base64 block. */
error_print();
rv = -1;
goto end;
}
}
rv = seof || (n == 0 && eof) ? 0 : 1;
end:
/* Legacy behaviour. This should probably rather be zeroed on error. */
*outl = ret;
ctx->num = n;
return (rv);
}
int base64_decode_block(unsigned char *t, const unsigned char *f, int n)
{
int i, ret = 0, a, b, c, d;
unsigned long l;
/* trim white space from the start of the line. */
while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
f++;
n--;
}
/*
* strip off stuff at the end of the line ascii2bin values B64_WS,
* B64_EOLN, B64_EOLN and B64_EOF
*/
while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1]))))
n--;
if (n % 4 != 0)
return (-1);
for (i = 0; i < n; i += 4) {
a = conv_ascii2bin(*(f++));
b = conv_ascii2bin(*(f++));
c = conv_ascii2bin(*(f++));
d = conv_ascii2bin(*(f++));
if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
return (-1);
l = ((((unsigned long)a) << 18L) |
(((unsigned long)b) << 12L) |
(((unsigned long)c) << 6L) | (((unsigned long)d)));
*(t++) = (unsigned char)(l >> 16L) & 0xff;
*(t++) = (unsigned char)(l >> 8L) & 0xff;
*(t++) = (unsigned char)(l) & 0xff;
ret += 3;
}
return (ret);
}
int base64_decode_finish(BASE64_CTX *ctx, uint8_t *out, int *outl)
{
int i;
*outl = 0;
if (ctx->num != 0) {
i = base64_decode_block(out, ctx->enc_data, ctx->num);
if (i < 0) {
error_print();
return (-1);
}
ctx->num = 0;
*outl = i;
return (1);
} else
return (1);
}

203
src/block_cipher.c Normal file
View File

@@ -0,0 +1,203 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/oid.h>
#include <gmssl/block_cipher.h>
#include "internal/endian.h"
int block_cipher_encrypt_init(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher,
const uint8_t *user_key, size_t keylen)
{
memset(key, 0, sizeof(BLOCK_CIPHER_KEY));
key->cipher = cipher;
return key->cipher->set_encrypt_key(key, user_key, keylen);
}
int block_cipher_decrypt_init(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher,
const uint8_t *user_key, size_t keylen)
{
memset(key, 0, sizeof(BLOCK_CIPHER_KEY));
key->cipher = cipher;
return key->cipher->set_decrypt_key(key, user_key, keylen);
}
void block_cipher_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out)
{
key->cipher->encrypt(key, in, out);
}
void block_cipher_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out)
{
key->cipher->decrypt(key, in, out);
}
void block_cipher_ecb_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, size_t nblocks, uint8_t *out)
{
while (nblocks--) {
key->cipher->encrypt(key, in, out);
in += key->cipher->block_size;
out += key->cipher->block_size;
}
}
void block_cipher_ecb_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, size_t nblocks, uint8_t *out)
{
while (nblocks--) {
key->cipher->decrypt(key, in, out);
in += key->cipher->block_size;
out += key->cipher->block_size;
}
}
void block_cipher_cbc_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv,
const uint8_t *in, size_t nblocks, uint8_t *out)
{
while (nblocks--) {
gmssl_memxor(out, in, iv, key->cipher->block_size);
key->cipher->encrypt(key, out, out);
iv = out;
in += key->cipher->block_size;
out += key->cipher->block_size;
}
}
void block_cipher_cbc_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv,
const uint8_t *in, size_t nblocks, uint8_t *out)
{
while (nblocks--) {
key->cipher->decrypt(key, in, out);
gmssl_memxor(out, out, iv, key->cipher->block_size);
iv = in;
in += key->cipher->block_size;
out += key->cipher->block_size;
}
}
void block_cipher_ctr_encrypt(const BLOCK_CIPHER_KEY *key, uint8_t *counter,
const uint8_t *in, size_t nblocks, uint8_t *out)
{
size_t block_size = key->cipher->block_size;
uint8_t block[block_size];
uint64_t ctr = GETU64(counter + block_size - sizeof(uint64_t));
while (nblocks--) {
key->cipher->encrypt(key, counter, block);
gmssl_memxor(out, in, block, block_size);
in += block_size;
out += block_size;
ctr++;
PUTU64(counter + block_size - sizeof(uint64_t), ctr);
}
}
static const BLOCK_CIPHER aes_block_cipher_object = {
OID_aes,
AES128_KEY_SIZE,
AES256_KEY_SIZE,
AES_BLOCK_SIZE,
(block_cipher_set_encrypt_key_func)aes_set_encrypt_key,
(block_cipher_set_decrypt_key_func)aes_set_decrypt_key,
(block_cipher_encrypt_func)aes_encrypt,
(block_cipher_decrypt_func)aes_encrypt,
};
const BLOCK_CIPHER *BLOCK_CIPHER_aes(void)
{
return &aes_block_cipher_object;
}
static int set_encrypt_key(BLOCK_CIPHER_KEY *key, const uint8_t *user_key, size_t keylen)
{
if (keylen != SM4_KEY_SIZE) {
return -1;
}
sm4_set_encrypt_key(&key->u.sm4_key, user_key);
return 1;
}
static int set_decrypt_key(BLOCK_CIPHER_KEY *key, const uint8_t *user_key, size_t keylen)
{
if (keylen != SM4_KEY_SIZE) {
return -1;
}
sm4_set_decrypt_key(&key->u.sm4_key, user_key);
return 1;
}
static const BLOCK_CIPHER sm4_block_cipher_object = {
OID_sm4,
SM4_KEY_SIZE,
SM4_KEY_SIZE,
SM4_BLOCK_SIZE,
set_encrypt_key,
set_decrypt_key,
(block_cipher_encrypt_func)sm4_encrypt,
(block_cipher_decrypt_func)sm4_encrypt,
};
const BLOCK_CIPHER *BLOCK_CIPHER_sm4(void)
{
return &sm4_block_cipher_object;
}
const BLOKC_CIPHER *block_cipher_from_name(const char *name)
{
if (strcmp(name, "aes") == 0) {
return BLOCK_CIPHER_aes();
} else if (strcmp(name, "sm4") == 0) {
return BLOCK_CIPHER_sm4();
}
return NULL;
}

56
src/bswap.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef GMSSL_MODES_LCL_H
#define GMSSL_MODES_LCL_H
# if defined(__GNUC__) && __GNUC__>=2
# if defined(__x86_64) || defined(__x86_64__)
# define BSWAP8(x) ({ uint64_t ret_=(x); \
asm ("bswapq %0" \
: "+r"(ret_)); ret_; })
# define BSWAP4(x) ({ uint32_t ret_=(x); \
asm ("bswapl %0" \
: "+r"(ret_)); ret_; })
# elif defined(__aarch64__)
# define BSWAP8(x) ({ uint64_t ret_; \
asm ("rev %0,%1" \
: "=r"(ret_) : "r"(x)); ret_; })
# define BSWAP4(x) ({ uint32_t ret_; \
asm ("rev %w0,%w1" \
: "=r"(ret_) : "r"(x)); ret_; })
# endif
# elif defined(_MSC_VER)
# if _MSC_VER>=1300
# pragma intrinsic(_byteswap_uint64,_byteswap_ulong)
# define BSWAP8(x) _byteswap_uint64((uint64_t)(x))
# define BSWAP4(x) _byteswap_ulong((uint32_t)(x))
# endif
#endif
#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT)
# define GETU32(p) BSWAP4(*(const uint32_t *)(p))
# define PUTU32(p,v) *(uint32_t *)(p) = BSWAP4(v)
# define GETU64(p) BSWAP8(*(const uint64_t *)(p))
# define PUTU64(p,v) *(uint64_t *)(p) = BSWAP8(v)
#else
# define GETU32(p) ((uint32_t)(p)[0]<<24|(uint32_t)(p)[1]<<16|(uint32_t)(p)[2]<<8|(uint32_t)(p)[3])
# define PUTU32(p,v) ((p)[0]=(u8)((v)>>24),(p)[1]=(u8)((v)>>16),(p)[2]=(u8)((v)>>8),(p)[3]=(u8)(v))
# define GETU64(p) ((uint64_t)(p)[0]<<56|(uint64_t)(p)[1]<<48|(uint64_t)(p)[2]<<40|(uint64_t)(p)[3]<<32| \
(uint64_t)(p)[4]<<24|(uint64_t)(p)[5]<<16|(uint64_t)(p)[6]<<8|(uint64_t)(p)[7])
# define PUTU64(p,v) ((p)[0]=(u8)((v)>>56),(p)[1]=(u8)((v)>>48),(p)[2]=(u8)((v)>>40),(p)[3]=(u8)((v)>>32),\
(p)[4]=(u8)((v)>>24),(p)[5]=(u8)((v)>>16),(p)[6]=(u8)((v)>>8),(p)[7]=(u8)(v)
#endif
#define GETU32_LE(p) (*(const uint32_t *)(p))
#define PUTU32_LE(p,a) *(uint32_t *)(p) = (a)
#define PUTU64_LE(p,a) *(uint64_t *)(p) = (a)
#endif

123
src/chacha20.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/chacha20.h>
#include "bswap.h"
#include "rotate.h"
void chacha20_set_key(CHACHA20_STATE *state,
const unsigned char key[CHACHA20_KEY_SIZE],
const unsigned char nonce[CHACHA20_NONCE_SIZE],
uint32_t counter)
{
state->d[ 0] = 0x61707865;
state->d[ 1] = 0x3320646e;
state->d[ 2] = 0x79622d32;
state->d[ 3] = 0x6b206574;
state->d[ 4] = GETU32_LE(key );
state->d[ 5] = GETU32_LE(key + 4);
state->d[ 6] = GETU32_LE(key + 8);
state->d[ 7] = GETU32_LE(key + 12);
state->d[ 8] = GETU32_LE(key + 16);
state->d[ 9] = GETU32_LE(key + 20);
state->d[10] = GETU32_LE(key + 24);
state->d[11] = GETU32_LE(key + 28);
state->d[12] = counter;
state->d[13] = GETU32_LE(nonce);
state->d[14] = GETU32_LE(nonce + 4);
state->d[15] = GETU32_LE(nonce + 8);
}
/* quarter round */
#define QR(A, B, C, D) \
A += B; D ^= A; D = ROL32(D, 16); \
C += D; B ^= C; B = ROL32(B, 12); \
A += B; D ^= A; D = ROL32(D, 8); \
C += D; B ^= C; B = ROL32(B, 7)
/* double round on state 4x4 matrix:
* four column rounds and and four diagonal rounds
*
* 0 1 2 3
* 4 5 6 7
* 8 9 10 11
* 12 13 14 15
*
*/
#define DR(S) \
QR(S[0], S[4], S[ 8], S[12]); \
QR(S[1], S[5], S[ 9], S[13]); \
QR(S[2], S[6], S[10], S[14]); \
QR(S[3], S[7], S[11], S[15]); \
QR(S[0], S[5], S[10], S[15]); \
QR(S[1], S[6], S[11], S[12]); \
QR(S[2], S[7], S[ 8], S[13]); \
QR(S[3], S[4], S[ 9], S[14])
void chacha20_generate_keystream(CHACHA20_STATE *state, unsigned int counts, unsigned char *out)
{
uint32_t working_state[16];
int i;
while (counts-- > 0) {
memcpy(working_state, state->d, sizeof(working_state));
for (i = 0; i < 10; i++) {
DR(working_state);
}
for (i = 0; i < 16; i++) {
working_state[i] += state->d[i];
PUTU32_LE(out, working_state[i]);
out += sizeof(uint32_t);
}
state->d[12]++;
}
}

134
src/cmac.c Normal file
View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/cmac.h>
#include "internal/gf128.h"
/*
CMAC的主体是CBC-MAC或者说是CBC模式
CMAC初始化的时候需要初始化E_K()中分组密码中的密钥编排
用GSK算法通过密钥K生成K1, K2这两个密钥最后是用来和最后一个分组做异或的
*/
int cmac_init(CMAC_CTX *ctx, const BLOCK_CIPHER *cipher, const uint8_t *key, size_t keylen)
{
gf128_t L;
ctx->cipher = cipher;
cipher->set_encrypt_key(&ctx->cipher_key, key, keylen);
/* L = E_K(0^128) */
memset(ctx->temp_block, 0, 16);
cipher->encrypt(&ctx->cipher_key, ctx->temp_block, ctx->temp_block);
L = gf128_from_bytes(ctx->temp_block);
/* K1 = L * 2 over GF(2^128) */
L = gf128_mul2(L);
gf128_to_bytes(L, ctx->k1);
/* K2 = K1 * 2 over GF(2^128) */
L = gf128_mul2(L);
gf128_to_bytes(L, ctx->k2);
memset(&L, 0, sizeof(gf128_t));
return 0;
}
int cmac_update(CMAC_CTX *ctx, const uint8_t *in, size_t inlen)
{
if (ctx->last_block_nbytes) {
unsigned int left = BLOCK_CIPHER_BLOCK_SIZE - ctx->num;
if (inlen < left) {
memcpy(ctx->block + ctx->last_block_nbytes, in, inlen);
ctx->last_block_nbytes += inlen;
return 1;
} else {
memcpy(ctx->block + ctx->last_block_nbytes, in, inlen);
}
}
while (inlen > 16) {
XOR128(block, in);
ctx->cipher->encrypt(ctx->cipher_key, block, block);
}
return 0;
}
// 在Finish的时候我们不应该清空密钥的内容
int cmac_finish(CMAC_CTX *ctx, size_t maclen, uint8_t *mac)
{
if (ctx->last_block_nbytes == 16) {
xor128(ctx->data, ctx->k1);
} else {
ctx->data[ctx->last_block_nbytes] = 0x01;
memset(ctx->data + ctx->last_block_nbytes, 0, 16 - ctx->last_block_nbytes);
xor128(ctx->data, ctx->k2);
}
xor128(cipher, data);
ctx->cipher->encrypt(ctx->cipher_key, ctx->block, ctx->block);
memcpy(out, block, outlen);
return 0;
}
int cmac_finish_and_verify(CMAC_CTX *ctx, const uint8_t *mac, size_t maclen)
{
uint8_t buf[16];
cmac_finish(ctx, maclen, buf);
if (memcmp(buf, mac, maclen) != 0) {
return 0;
}
return 1;
}

1526
src/cms.c Normal file

File diff suppressed because it is too large Load Diff

298
src/ctr.c Normal file
View File

@@ -0,0 +1,298 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* GHASH(H, A, C) = X_{m + n + 1}
* A additional authenticated data, A = A_1, ..., A_{m-1}, A_m^*, nbits(A_m^*) = v
* C ciphertext, C = C_1, ..., C_{n-1}, C_n^*, nbits(C_n^*) = u
* H = E_K(0^128)
*
* X_i = 0 for i = 0
* = (X_{i-1} xor A_i ) * H for i = 1, ..., m-1
* = (X_{m-1} xor (A_m^* || 0^{128-v})) * H for i = m
* = (X_{i-1} xor C_i ) * H for i = m+1, ..., m + n 1
* = (X_{m+n-1} xor (C_m^* || 0^{128-u})) * H for i = m + n
* = (X_{m+n} xor (nbits(A)||nbits(A))) * H for i = m + n + 1
*/
void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen)
{
__uint128_t H;
__uint128_t X;
__uint128_t A;
memset(ctx, 0, sizeof(GHASH_CTX));
/* get H in GF(2^128) as little endian */
ctx->H = H = GETU128_LE(h);
ctx->aadlen = aadlen;
/* process AAD */
X = 0;
while (aadlen >= 16) {
A = GETU128_LE(aad);
X = gf128_add(X, A);
X = gf128_mul(X, H);
aad += 16;
aadlen -= 16;
}
if (aadlen) {
memcpy(ctx->buf, aad, aadlen);
A = GETU128_LE(ctx->block);
X = gf128_add(X, A);
X = gf128_mul(X, H);
}
ctx->H = H;
ctx->X = X;
/* this clean ok? */
H = X = A = 0;
}
void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen)
{
__uint128_t X;
__uint128_t H;
__uint128_t C;
if (!c && clen) {
return 0;
}
ctx->cipherlen += clen;
X = ctx->X;
H = ctx->H;
if (ctx->num) {
unsigned int left = 16 - ctx->num;
if (clen < left) {
memcpy(ctx->block + ctx->num, c, clen);
ctx->num += clen;
return 1;
} else {
memcpy(ctx->block + ctx->num, c, left);
C = GETU128_LE(ctx->block);
X = GF128_ADD(X, C);
X = GF128_MUL(X, H);
c += left;
clen -= left;
}
}
while (clen >= 16) {
C = GETU128_LE(c);
X = gf128_add(X, C);
X = gf128_mul(X, H);
c += 16;
clen -= 16;
}
ctx->num = clen;
if (clen) {
memcpy(ctx->block, c, clen);
}
ctx->X = X;
X = H = C = 0;
}
void ghash_finish(GHASH_CTX *ctx, uint8_t out[16])
{
__uint128_t X = ctx->X;
__uint128_t H = ctx->H;
__uint128_t C;
if (ctx->num < 0) {
return 0;
}
if (ctx->num) {
memset(ctx->block + ctx->num, 0, 16 - ctx->num);
C = GETU128_LE(ctx->block);
X = GF128_ADD(X, C);
X = GF128_MUL(X, H);
}
PUTU64_LE(ctx->block, (uint64_t)ctx->aadlen << 3);
PUTU64_LE(ctx->block + sizeof(uint64_t), (uint64_t)ctx->cipherlen << 3);
C = GETU128_LE(ctx->block);
X = GF128_ADD(X, C);
X = GF128_MUL(X, H);
PUTU128_LE(out, X);
memset(ctx, 0, sizeof(GHASH_CTX));
X = H = C = 0;
}
/*
* GCM(K, IV, A, P)
*
* H = E_K(0^128)
* Y_0 = IV || 0^{31}1 if nbits(IV) == 96
* = GHASH(H, {}, IV) otherwise
* Y_i = Y_{i-1} + 1 for i = 1, ..., n
* C_i = P_i xor E_K(Y_i) for i = 1, ..., n
* C_n^* = P_n^* xor MSB_u(E_K(Y_n))
* T = MSB_t(GHASH(H, A, C) xor E_K(Y_0))
*/
int gcm_init(GCM_CTX *ctx, const BLOCK_CIPEHR *cipher,
const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen,
const uint8_t *aad, size_t aadlen)
{
memset(ctx, 0, sizeof(GCM_CTX));
ctx->cipher = cipher;
/* H = E_K(0^128) */
if (!cipher->set_encrypt_key(ctx->key, key, keylen)) {
return 0;
}
cipher->encrypt(ctx->key, ctx->block, ctx->block);
/* init counter as Y_0 */
if (ivlen == GCM_DEFAULT_IV_SIZE) {
memcpy(ctx->counter, iv, ivlen);
PUTU32(ctx->counter + 12, 1);
} else {
ghash_init(&ctx->ghash_ctx, ctx->block, NULL, 0);
ghash_update(&ctx->ghash_ctx, iv, ivlen);
ghash_finish(&ctx->ghash_ctx, ctx->counter);
}
ghash_init(&ctx->ghash-ctx, ctx->block, aad, aadlen);
return 1;
}
// gcm 加密解密显然是不一样的
int gcm_update(GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out)
{
uint32_t r;
size_t i;
uint8_t *c = out;
size_t clen = inlen;
if (ctx->num) {
uint8_t *k = ctx->block + 16 - ctx->num;
size_t len = inlen < ctx->num ? inlen : ctx->num;
for (i = 0; i < len; i++) {
out[i] = in[i] ^ k[i];
}
in += len;
out += len;
inlen -= len;
ctx->num -= len;
}
/* gcm only use the last 32 bits as counter */
r = GETU32(ctx->counter + 12);
while (inlen >= 16) {
r++;
PUTU32(ctx->counter + 12, r);
ctx->cipher->encrypt(ctx->key, ctx->counter, out);
for (i = 0; i < 16; i++) {
out[i] ^= in[i];
}
in += 16;
out += 16;
inlen -= 16;
}
if (inlen) {
r++;
PUTU32(ctx->counter + 12, r);
ctx->cipher->encrypt(ctx->key, ctx->counter, ctx->block);
for (i = 0; i < inlen; i++) {
out[i] = in[i] ^ ctx->block[i];
}
ctx->num = 16 - inlen;
}
ghash_update(ctx->ghash_ctx, c, inlen);
return 1;
}
int gcm_encrypt_update(GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out)
{
ctr_update(ctx->ctr_ctx, in, inlen, out);
ghash_update(ctx->ghash_ctx, out, inlen);
}
int gcm_encrypt_finish(GCM_CTX *ctx, size_t taglen, uint8_t *tag)
{
int i;
ghash_finish(ctx->ghash_ctx, ctx->block);
for (i = 0; i < ctx->taglen; i++) {
tag[i] = ctx->block[i] ^ ctx->enced_iv[i];
}
memset(ctx, 0, sizeof(GCM_CTX));
}
int gcm_decrypt_finish(GCM_CTX *ctx, const uint8_t *tag, size_t taglen)
{
uint8_t buf[16];
if (taglen != ctx->taglen) {
return 0;
}
gcm_finish(ctx, buf);
if (memcmp(buf, tag, taglen) != 0) {
return 0;
}
return 1;
}

131
src/debug.c Normal file
View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <gmssl/error.h>
void print_der(const uint8_t *in, size_t inlen)
{
size_t i;
for (i = 0; i < inlen; i++) {
printf("%02x ", in[i]);
}
}
void print_bytes(const uint8_t *data, size_t datalen)
{
size_t i;
for (i = 0; i < datalen; i++) {
printf("%02X ", data[i]);
if ((i + 1) % 32 == 0)
printf("\n");
}
printf("\n");
}
void print_nodes(const uint32_t *in, size_t inlen)
{
size_t i;
printf("%u", in[0]);
for (i = 1; i < inlen; i++) {
printf(".%u", in[i]);
}
}
int format_print(FILE *fp, int format, int indent, const char *str, ...)
{
va_list args;
int i;
for (i = 0; i < indent; i++) {
fprintf(fp, " ");
}
va_start(args, str);
vfprintf(fp, str, args);
va_end(args);
return 1;
}
int format_bytes(FILE *fp, int format, int indent, const char *str, const uint8_t *data, size_t datalen)
{
int i;
for (i = 0; i < indent; i++) {
fprintf(fp, " ");
}
fprintf(fp, "%s", str);
if (!datalen) {
fprintf(fp, "(null)\n");
return 1;
}
for (i = 0; i < datalen; i++) {
fprintf(fp, "%02X", data[i]);
}
fprintf(fp, "\n");
return 1;
}
int tls_trace(int format, int indent, const char *str, ...)
{
FILE *fp = stderr;
va_list args;
int i;
for (i = 0; i < indent; i++) {
fprintf(fp, " ");
}
va_start(args, str);
vfprintf(fp, str, args);
va_end(args);
fprintf(fp, "\n");
return 1;
}

267
src/des.c Normal file
View File

@@ -0,0 +1,267 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/des.h>
#include "bswap.h"
/* permuted choice 1 for key schedule, 64 bits to 56 bits */
static unsigned char PC1[56] = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4,
};
/* permuted choice 2 for key schedule, 48 bits to 48 bits */
static unsigned char PC2[48] = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32,
};
/* rotations for every round of key schedule */
static unsigned char S[16] = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
};
/* initial permutation, 64 bits to 64 bits */
static unsigned char IP[64] = {
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7,
};
/* inverse initial permutation, 64 bits to 64 bits */
static unsigned char IP_inv[64] = {
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25,
};
/* expansion permutation, 32 bits to 48 bits */
static unsigned char E[48] = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1,
};
/* eight s-box, 6 bits to 4 bits */
static unsigned char S1[64] = {
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
};
static unsigned char S2[64] = {
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
};
static unsigned char S3[64] = {
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
};
static unsigned char S4[64] = {
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
};
static unsigned char S5[64] = {
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
};
static unsigned char S6[64] = {
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
};
static unsigned char S7[64] = {
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
};
static unsigned char S8[64] = {
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
};
/* permutation, 32 bits to 32 bits */
static unsigned char P[32] = {
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,
};
static uint64_t permute(const unsigned char *table, size_t n, uint64_t A)
{
uint64_t R = 0;
for (size_t i = 0; i < n; i++) {
R |= (A >> (n - table[i])) & 0x01;
}
return R;
}
static uint32_t substitution(const uint64_t A)
{
return (((uint32_t)S1[(A >> 42) & 0x3f]) << 28) |
(((uint32_t)S2[(A >> 36) & 0x3f]) << 24) |
(((uint32_t)S3[(A >> 30) & 0x3f]) << 20) |
(((uint32_t)S4[(A >> 24) & 0x3f]) << 16) |
(((uint32_t)S5[(A >> 18) & 0x3f]) << 12) |
(((uint32_t)S6[(A >> 12) & 0x3f]) << 8) |
(((uint32_t)S7[(A >> 6) & 0x3f]) << 4) |
(((uint32_t)S8[(A ) & 0x3f]) );
}
#define ROL32(A,Si) (((A)<<(Si))|((A)>>(32-(Si))))
void des_set_encrypt_key(DES_KEY *key, const unsigned char user_key[8])
{
uint64_t K;
uint32_t L, R;
int i;
K = GETU64(user_key);
K = permute(PC1, sizeof(PC1), K);
L = K >> 28;
R = K & 0x0fffffff;
for (i = 0; i < 16; i++) {
L = ROL32(L, S[i]);
R = ROL32(R, S[i]);
K = ((uint64_t)L << 28) | R;
key->rk[i] = permute(PC2, sizeof(PC2), K);
}
}
void des_set_decrypt_key(DES_KEY *key, const unsigned char user_key[8])
{
// TODO
}
void des_encrypt(DES_KEY *key, const unsigned char in[DES_BLOCK_SIZE],
unsigned char out[DES_BLOCK_SIZE])
{
uint64_t T;
uint32_t L, R;
int i;
T = GETU64(in);
/* initial permutation */
T = permute(IP, sizeof(IP), T);
L = T >> 32;
R = T & 0xffffffff;
for (i = 0; i < 16; i++) {
/* compute F_{Ki}(R) */
T = permute(E, sizeof(E), R);
T ^= key->rk[i];
T = substitution(T);
T = permute(P, sizeof(P), T);
T ^= L;
L = R;
R = T;
}
T = ((uint64_t)L << 32) | R;
/* inverse initial permutation */
T = permute(IP_inv, sizeof(IP_inv), T);
PUTU64(out, T);
}

527
src/digest.c Normal file
View File

@@ -0,0 +1,527 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <gmssl/sm3.h>
#include <gmssl/oid.h>
#include <gmssl/digest.h>
int digest_nid(const DIGEST *digest)
{
return digest->nid;
}
typedef struct {
int nid;
char *short_name;
char *display_name;
} DIGEST_TABLE;
DIGEST_TABLE digest_table[] = {
{ OID_sm3, "sm3", "SM3" },
{ OID_md5, "md5", "MD5" },
{ OID_sha1, "sha1", "SHA-1" },
{ OID_sha224, "sha224", "SHA-224" },
{ OID_sha256, "sha256", "SHA-256" },
{ OID_sha384, "sha384", "SHA-384" },
{ OID_sha512, "sha512", "SHA-512" },
};
const char *digest_name(const DIGEST *digest)
{
int i;
for (i = 0; i < sizeof(digest_table)/sizeof(digest_table[0]); i++) {
if (digest->nid == digest_table[i].nid) {
return digest_table[i].short_name;
}
}
return NULL;
}
size_t digest_size(const DIGEST *digest)
{
return digest->digest_size;
}
size_t digest_block_size(const DIGEST *digest)
{
return digest->block_size;
}
int digest_ctx_init(DIGEST_CTX *ctx)
{
memset(ctx, 0, sizeof(DIGEST_CTX));
return 1;
}
void digest_ctx_cleanup(DIGEST_CTX *ctx)
{
memset(ctx, 0, sizeof(DIGEST_CTX));
}
int digest_init(DIGEST_CTX *ctx, const DIGEST *algor)
{
ctx->digest = algor;
ctx->digest->init(ctx);
return 1;
}
int digest_update(DIGEST_CTX *ctx, const unsigned char *data, size_t datalen)
{
ctx->digest->update(ctx, data, datalen);
return 1;
}
int digest_finish(DIGEST_CTX *ctx, unsigned char *dgst, size_t *dgstlen)
{
ctx->digest->finish(ctx, dgst);
*dgstlen = ctx->digest->digest_size;
return 1;
}
int digest(const DIGEST *digest, const unsigned char *data, size_t datalen,
unsigned char *dgst, size_t *dgstlen)
{
DIGEST_CTX ctx;
if (!digest_ctx_init(&ctx)
|| !digest_init(&ctx, digest)
|| !digest_update(&ctx, data, datalen)
|| !digest_finish(&ctx, dgst, dgstlen)) {
return 0;
}
digest_ctx_cleanup(&ctx);
return 1;
}
const DIGEST *digest_from_name(const char *name)
{
if (!strcmp(name, "sm3") || !strcmp(name, "SM3")) {
return DIGEST_sm3();
} else if (!strcmp(name, "md5") || !strcmp(name, "MD5")) {
return DIGEST_md5();
} else if (!strcmp(name, "sha1") || !strcmp(name, "SHA1")) {
return DIGEST_sha1();
} else if (!strcmp(name, "sha224") || !strcmp(name, "SHA224")) {
return DIGEST_sha224();
} else if (!strcmp(name, "sha256") || !strcmp(name, "SHA256")) {
return DIGEST_sha256();
} else if (!strcmp(name, "sha384") || !strcmp(name, "SHA384")) {
return DIGEST_sha384();
} else if (!strcmp(name, "sha512") || !strcmp(name, "SHA512")) {
return DIGEST_sha512();
} else if (!strcmp(name, "sha512-224") || !strcmp(name, "SHA512-224")) {
return DIGEST_sha512_224();
} else if (!strcmp(name, "sha512-256") || !strcmp(name, "SHA512-256")) {
return DIGEST_sha512_256();
}
return NULL;
}
static int sm3_digest_init(DIGEST_CTX *ctx)
{
if (!ctx) {
return 0;
}
sm3_init(&ctx->u.sm3_ctx);
return 1;
}
static int sm3_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen)
{
if (!ctx || (!in && inlen != 0)) {
return 0;
}
sm3_update(&ctx->u.sm3_ctx, in, inlen);
return 1;
}
static int sm3_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
if (!ctx || !dgst) {
return 0;
}
sm3_finish(&ctx->u.sm3_ctx, dgst);
return 1;
}
static const DIGEST sm3_digest_object = {
OID_sm3,
SM3_DIGEST_SIZE,
SM3_BLOCK_SIZE,
sizeof(SM3_CTX),
sm3_digest_init,
sm3_digest_update,
sm3_digest_finish,
};
const DIGEST *DIGEST_sm3(void)
{
return &sm3_digest_object;
}
#include <gmssl/md5.h>
static int md5_digest_init(DIGEST_CTX *ctx)
{
if (!ctx) {
return 0;
}
md5_init(&ctx->u.md5_ctx);
return 1;
}
static int md5_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen)
{
if (!ctx || (!in && inlen != 0)) {
return 0;
}
md5_update(&ctx->u.md5_ctx, in, inlen);
return 1;
}
static int md5_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
if (!ctx || !dgst) {
return 0;
}
md5_finish(&ctx->u.md5_ctx, dgst);
return 1;
}
static const DIGEST md5_digest_object = {
OID_md5,
MD5_DIGEST_SIZE,
MD5_BLOCK_SIZE,
sizeof(MD5_CTX),
md5_digest_init,
md5_digest_update,
md5_digest_finish,
};
const DIGEST *DIGEST_md5(void)
{
return &md5_digest_object;
}
#include <gmssl/sha1.h>
static int sha1_digest_init(DIGEST_CTX *ctx)
{
if (!ctx) {
return 0;
}
sha1_init(&ctx->u.sha1_ctx);
return 1;
}
static int sha1_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen)
{
if (!ctx || (!in && inlen != 0)) {
return 0;
}
sha1_update(&ctx->u.sha1_ctx, in, inlen);
return 1;
}
static int sha1_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
if (!ctx || !dgst) {
return 0;
}
sha1_finish(&ctx->u.sha1_ctx, dgst);
return 1;
}
static const DIGEST sha1_digest_object = {
OID_sha1,
SHA1_DIGEST_LENGTH,
SHA1_BLOCK_SIZE,
sizeof(SHA1_CTX),
sha1_digest_init,
sha1_digest_update,
sha1_digest_finish,
};
const DIGEST *DIGEST_sha1(void)
{
return &sha1_digest_object;
}
#include <gmssl/sha2.h>
static int sha224_digest_init(DIGEST_CTX *ctx)
{
if (!ctx) {
return 0;
}
sha224_init(&ctx->u.sha224_ctx);
return 1;
}
static int sha224_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen)
{
if (!ctx || (!in && inlen != 0)) {
return 0;
}
sha224_update(&ctx->u.sha224_ctx, in, inlen);
return 1;
}
static int sha224_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
if (!ctx || !dgst) {
return 0;
}
sha224_finish(&ctx->u.sha224_ctx, dgst);
return 1;
}
static const DIGEST sha224_digest_object = {
OID_sha224,
SHA224_DIGEST_SIZE,
SHA224_BLOCK_SIZE,
sizeof(SHA224_CTX),
sha224_digest_init,
sha224_digest_update,
sha224_digest_finish,
};
const DIGEST *DIGEST_sha224(void)
{
return &sha224_digest_object;
}
static int sha256_digest_init(DIGEST_CTX *ctx)
{
if (!ctx) {
return 0;
}
sha256_init(&ctx->u.sha256_ctx);
return 1;
}
static int sha256_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen)
{
if (!ctx || (!in && inlen != 0)) {
return 0;
}
sha256_update(&ctx->u.sha256_ctx, in, inlen);
return 1;
}
static int sha256_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
if (!ctx || !dgst) {
return 0;
}
sha256_finish(&ctx->u.sha256_ctx, dgst);
return 1;
}
static const DIGEST sha256_digest_object = {
OID_sha256,
SHA256_DIGEST_SIZE,
SHA256_BLOCK_SIZE,
sizeof(SHA256_CTX),
sha256_digest_init,
sha256_digest_update,
sha256_digest_finish,
};
const DIGEST *DIGEST_sha256(void)
{
return &sha256_digest_object;
}
static int sha384_digest_init(DIGEST_CTX *ctx)
{
if (!ctx) {
return 0;
}
sha384_init(&ctx->u.sha384_ctx);
return 1;
}
static int sha384_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen)
{
if (!ctx || (!in && inlen != 0)) {
return 0;
}
sha384_update(&ctx->u.sha384_ctx, in, inlen);
return 1;
}
static int sha384_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
if (!ctx || !dgst) {
return 0;
}
sha384_finish(&ctx->u.sha384_ctx, dgst);
return 1;
}
static const DIGEST sha384_digest_object = {
OID_sha384,
SHA384_DIGEST_SIZE,
SHA384_BLOCK_SIZE,
sizeof(SHA384_CTX),
sha384_digest_init,
sha384_digest_update,
sha384_digest_finish,
};
const DIGEST *DIGEST_sha384(void)
{
return &sha384_digest_object;
}
static int sha512_digest_init(DIGEST_CTX *ctx)
{
if (!ctx) {
return 0;
}
sha512_init(&ctx->u.sha512_ctx);
return 1;
}
static int sha512_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen)
{
if (!ctx || (!in && inlen != 0)) {
return 0;
}
sha512_update(&ctx->u.sha512_ctx, in, inlen);
return 1;
}
static int sha512_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
if (!ctx || !dgst) {
return 0;
}
sha512_finish(&ctx->u.sha512_ctx, dgst);
return 1;
}
static const DIGEST sha512_digest_object = {
OID_sha512,
SHA512_DIGEST_SIZE,
SHA512_BLOCK_SIZE,
sizeof(SHA512_CTX),
sha512_digest_init,
sha512_digest_update,
sha512_digest_finish,
};
const DIGEST *DIGEST_sha512(void)
{
return &sha512_digest_object;
}
static int sha512_224_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
unsigned char buf[SHA512_DIGEST_SIZE];
if (!ctx || !dgst) {
return 0;
}
sha512_finish(&ctx->u.sha512_ctx, buf);
memcpy(dgst, buf, SHA224_DIGEST_SIZE);
memset(buf, 0, sizeof(buf));
return 1;
}
static const DIGEST sha512_224_digest_object = {
OID_sha512_224,
SHA224_DIGEST_SIZE,
SHA512_BLOCK_SIZE,
sizeof(SHA512_CTX),
sha512_digest_init,
sha512_digest_update,
sha512_224_digest_finish,
};
const DIGEST *DIGEST_sha512_224(void)
{
return &sha512_224_digest_object;
}
static int sha512_256_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst)
{
unsigned char buf[SHA512_DIGEST_SIZE];
if (!ctx || !dgst) {
return 0;
}
sha512_finish(&ctx->u.sha512_ctx, buf);
memcpy(dgst, buf, SHA256_DIGEST_SIZE);
memset(buf, 0, sizeof(buf));
return 1;
}
static const DIGEST sha512_256_digest_object = {
OID_sha512_256,
SHA256_DIGEST_SIZE,
SHA512_BLOCK_SIZE,
sizeof(SHA512_CTX),
sha512_digest_init,
sha512_digest_update,
sha512_256_digest_finish,
};
const DIGEST *DIGEST_sha512_256(void)
{
return &sha512_256_digest_object;
}

116
src/endian.h Normal file
View File

@@ -0,0 +1,116 @@
/*
* 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.
*/
#ifndef GMSSL_ENDIAN_H
#define GMSSL_ENDIAN_H
/* Big Endian R/W */
#define GETU16(p) \
((uint16_t)(p)[0] << 8 | \
(uint16_t)(p)[1])
#define GETU32(p) \
((uint32_t)(p)[0] << 24 | \
(uint32_t)(p)[1] << 16 | \
(uint32_t)(p)[2] << 8 | \
(uint32_t)(p)[3])
#define GETU64(p) \
((uint64_t)(p)[0] << 56 | \
(uint64_t)(p)[1] << 48 | \
(uint64_t)(p)[2] << 40 | \
(uint64_t)(p)[3] << 32 | \
(uint64_t)(p)[4] << 24 | \
(uint64_t)(p)[5] << 16 | \
(uint64_t)(p)[6] << 8 | \
(uint64_t)(p)[7])
// 注意PUTU32(buf, val++) 会出错!
#define PUTU16(p,V) \
((p)[0] = (uint8_t)((V) >> 8), \
(p)[1] = (uint8_t)(V))
#define PUTU32(p,V) \
((p)[0] = (uint8_t)((V) >> 24), \
(p)[1] = (uint8_t)((V) >> 16), \
(p)[2] = (uint8_t)((V) >> 8), \
(p)[3] = (uint8_t)(V))
#define PUTU64(p,V) \
((p)[0] = (uint64_t)((V) >> 56), \
(p)[1] = (uint64_t)((V) >> 48), \
(p)[2] = (uint64_t)((V) >> 40), \
(p)[3] = (uint64_t)((V) >> 32), \
(p)[4] = (uint64_t)((V) >> 24), \
(p)[5] = (uint64_t)((V) >> 16), \
(p)[6] = (uint64_t)((V) >> 8), \
(p)[7] = (uint64_t)(V))
/* Little Endian R/W */
#define GETU16_LE(p) (*(const uint16_t *)(p))
#define GETU32_LE(p) (*(const uint32_t *)(p))
#define GETU64_LE(p) (*(const uint64_t *)(p))
#define PUTU16_LE(p,V) *(uint16_t *)(p) = (V)
#define PUTU32_LE(p,V) *(uint32_t *)(p) = (V)
#define PUTU64_LE(p,V) *(uint64_t *)(p) = (V)
/* Rotate */
#define ROL32(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#define ROL64(a,n) (((a)<<(n))|((a)>>(64-(n))))
#define ROR32(a,n) ROL32((a),32-(n))
#define ROR64(a,n) ROL64(a,64-n)
#endif

351
src/ffx.c Normal file
View File

@@ -0,0 +1,351 @@
/* ====================================================================
* Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ffx.h>
#include <openssl/e_os2.h>
#include "../modes/modes_lcl.h"
static uint32_t modulo[] = {
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
1000000000,
};
struct FFX_CTX_st {
EVP_CIPHER_CTX *cctx;
int flag;
};
FFX_CTX *FFX_CTX_new(void)
{
FFX_CTX *ret = NULL;
ret = OPENSSL_zalloc(sizeof(*ret));
return ret;
}
void FFX_CTX_free(FFX_CTX *ctx)
{
if (ctx) {
EVP_CIPHER_CTX_free(ctx->cctx);
}
OPENSSL_free(ctx);
}
int FFX_init(FFX_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key,
int flag)
{
int ret = 0;
EVP_CIPHER_CTX *cctx = NULL;
if (!ctx || !cipher || !key) {
FFXerr(FFX_F_FFX_INIT, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (EVP_CIPHER_mode(cipher) != EVP_CIPH_ECB_MODE) {
FFXerr(FFX_F_FFX_INIT, FFX_R_INVALID_CIPHER_MODE);
return 0;
}
if (EVP_CIPHER_block_size(cipher) != 16) {
FFXerr(FFX_F_FFX_INIT, FFX_R_INVALID_BLOCK_SIZE);
return 0;
}
if (!ctx->cctx) {
if (!(cctx = EVP_CIPHER_CTX_new())) {
FFXerr(FFX_F_FFX_INIT, ERR_R_MALLOC_FAILURE);
goto end;
}
ctx->cctx = cctx;
cctx = NULL;
}
ctx->flag = flag;
if (!EVP_EncryptInit_ex(ctx->cctx, cipher, NULL, key, NULL)) {
FFXerr(FFX_F_FFX_INIT, FFX_R_ENCRYPT_INIT_FAILURE);
goto end;
}
ret = 1;
end:
EVP_CIPHER_CTX_free(cctx);
return ret;
}
int FFX_encrypt(FFX_CTX *ctx, const char *in, char *out, size_t iolen,
unsigned char *tweak, size_t tweaklen)
{
int llen, rlen;
uint32_t lval, rval;
unsigned char pblock[16] = {
0x01, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x0a, 0xff,
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00};
unsigned char qblock[16];
char lbuf[FFX_MAX_DIGITS/2 + 2];
uint64_t yval;
size_t i;
if (!ctx || !in || !out || !tweak) {
FFXerr(FFX_F_FFX_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (iolen < FFX_MIN_DIGITS || iolen > FFX_MAX_DIGITS) {
FFXerr(FFX_F_FFX_ENCRYPT, FFX_R_INVALID_INPUT_LENGTH);
return 0;
}
for (i = 0; i < iolen; i++) {
if (!isdigit(in[i])) {
FFXerr(FFX_F_FFX_ENCRYPT, FFX_R_INVALID_INPUT_DIGIT);
return 0;
}
}
llen = iolen / 2;
rlen = iolen - llen;
if (tweaklen < FFX_MIN_TWEAKLEN || tweaklen > FFX_MAX_TWEAKLEN) {
FFXerr(FFX_F_FFX_ENCRYPT, FFX_R_INVALID_TWEAK_LENGTH);
return 0;
}
memcpy(lbuf, in, llen);
lbuf[llen] = 0;
lval = atoi(lbuf);
rval = atoi(in + llen);
pblock[7] = llen & 0xff;
pblock[8] = iolen & 0xff;
pblock[12] = tweaklen & 0xff;
if (!EVP_Cipher(ctx->cctx, pblock, pblock,
EVP_CIPHER_CTX_block_size(ctx->cctx))) {
FFXerr(FFX_F_FFX_ENCRYPT, ERR_R_EVP_LIB);
return 0;
}
memset(qblock, 0, sizeof(qblock));
memcpy(qblock, tweak, tweaklen);
for (i = 0; i < FFX_NUM_ROUNDS; i += 2) {
unsigned char rblock[16];
size_t j;
qblock[11] = i & 0xff;
memcpy(qblock + 12, &rval, sizeof(rval));
for (j = 0; j < sizeof(rblock); j++) {
rblock[j] = pblock[j] ^ qblock[j];
}
if (!EVP_Cipher(ctx->cctx, rblock, rblock,
EVP_CIPHER_CTX_block_size(ctx->cctx))) {
FFXerr(FFX_F_FFX_ENCRYPT, ERR_R_EVP_LIB);
return 0;
}
yval = *((uint64_t *)rblock) % modulo[llen];
lval = (lval + yval) % modulo[llen];
qblock[11] = (i + 1) & 0xff;
memcpy(qblock + 12, &lval, sizeof(lval));
for (j = 0; j < sizeof(rblock); j++) {
rblock[j] = pblock[j] ^ qblock[j];
}
if (!EVP_Cipher(ctx->cctx, rblock, rblock,
EVP_CIPHER_CTX_block_size(ctx->cctx))) {
FFXerr(FFX_F_FFX_ENCRYPT, ERR_R_EVP_LIB);
return 0;
}
yval = *((uint64_t *)rblock) % modulo[rlen];
rval = (rval + yval) % modulo[rlen];
}
memset(out, '0', iolen);
sprintf(lbuf, "%d", rval);
memcpy(out + rlen - strlen(lbuf), lbuf, strlen(lbuf));
sprintf(lbuf, "%d", lval);
strcpy(out + iolen - strlen(lbuf), lbuf);
return 1;
}
int FFX_decrypt(FFX_CTX *ctx, const char *in, char *out, size_t iolen,
unsigned char *tweak, size_t tweaklen)
{
int llen, rlen;
uint32_t lval, rval;
unsigned char pblock[16] = {
0x01, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x0a, 0xff,
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00};
unsigned char qblock[16];
char lbuf[FFX_MAX_DIGITS/2 + 2];
uint64_t yval;
size_t i;
if (!ctx || !in || !out || !tweak) {
FFXerr(FFX_F_FFX_DECRYPT, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (iolen < FFX_MIN_DIGITS || iolen > FFX_MAX_DIGITS) {
FFXerr(FFX_F_FFX_DECRYPT, FFX_R_INVALID_INPUT_LENGTH);
return 0;
}
for (i = 0; i < iolen; i++) {
if (!isdigit(in[i])) {
FFXerr(FFX_F_FFX_DECRYPT, FFX_R_INVALID_INPUT_DIGIT);
return 0;
}
}
rlen = iolen / 2;
llen = iolen - rlen;
if (tweaklen < FFX_MIN_TWEAKLEN || tweaklen > FFX_MAX_TWEAKLEN) {
FFXerr(FFX_F_FFX_DECRYPT, FFX_R_INVALID_TWEAK_LENGTH);
return 0;
}
memcpy(lbuf, in, llen);
lbuf[llen] = 0;
lval = atoi(lbuf);
rval = atoi(in + llen);
pblock[7] = rlen & 0xff;
pblock[8] = iolen & 0xff;
pblock[12] = tweaklen & 0xff;
if (!EVP_Cipher(ctx->cctx, pblock, pblock,
EVP_CIPHER_CTX_block_size(ctx->cctx))) {
FFXerr(FFX_F_FFX_DECRYPT, ERR_R_EVP_LIB);
return 0;
}
memset(qblock, 0, sizeof(qblock));
memcpy(qblock, tweak, tweaklen);
for (i = FFX_NUM_ROUNDS - 1; i > 0; i -= 2) {
unsigned char rblock[16];
size_t j;
qblock[11] = i & 0xff;
memcpy(qblock + 12, &rval, sizeof(rval));
for (j = 0; j < sizeof(rblock); j++) {
rblock[j] = pblock[j] ^ qblock[j];
}
if (!EVP_Cipher(ctx->cctx, rblock, rblock,
EVP_CIPHER_CTX_block_size(ctx->cctx))) {
FFXerr(FFX_F_FFX_DECRYPT, ERR_R_EVP_LIB);
return 0;
}
yval = *((uint64_t *)rblock) % modulo[llen];
lval = (lval >= yval) ? (lval - yval) : lval + modulo[llen] - yval;
qblock[11] = (i - 1) & 0xff;
memcpy(qblock + 12, &lval, sizeof(lval));
for (j = 0; j < sizeof(rblock); j++) {
rblock[j] = pblock[j] ^ qblock[j];
}
if (!EVP_Cipher(ctx->cctx, rblock, rblock,
EVP_CIPHER_CTX_block_size(ctx->cctx))) {
FFXerr(FFX_F_FFX_DECRYPT, ERR_R_EVP_LIB);
return 0;
}
yval = *((uint64_t *)rblock) % modulo[rlen];
rval = (rval >= yval) ? (rval - yval) : rval + modulo[rlen] - yval;
}
memset(out, '0', iolen);
sprintf(lbuf, "%d", rval);
memcpy(out + rlen - strlen(lbuf), lbuf, strlen(lbuf));
sprintf(lbuf, "%d", lval);
strcpy(out + iolen - strlen(lbuf), lbuf);
return 1;
}
static int luhn_table[10] = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9};
int FFX_compute_luhn(const char *in, size_t inlen)
{
int r = 0;
int i;
for (i = inlen - 1; i >= 0; i--) {
int a;
if (!isdigit(in[i])) {
return -2;
}
a = in[i] - '0';
if (i % 2 != inlen % 2)
a = luhn_table[a];
r += a;
}
r = ((r * 9) % 10) + '0';
return r;
}

250
src/gcm.c Normal file
View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* GHASH(H, A, C) = X_{m + n + 1}
* A additional authenticated data, A = A_1, ..., A_{m-1}, A_m^*, nbits(A_m^*) = v
* C ciphertext, C = C_1, ..., C_{n-1}, C_n^*, nbits(C_n^*) = u
* H = E_K(0^128)
*
* X_i = 0 for i = 0
* = (X_{i-1} xor A_i ) * H for i = 1, ..., m-1
* = (X_{m-1} xor (A_m^* || 0^{128-v})) * H for i = m
* = (X_{i-1} xor C_i ) * H for i = m+1, ..., m + n 1
* = (X_{m+n-1} xor (C_m^* || 0^{128-u})) * H for i = m + n
* = (X_{m+n} xor (nbits(A)||nbits(A))) * H for i = m + n + 1
*/
void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen)
{
__uint128_t H;
__uint128_t X;
__uint128_t A;
memset(ctx, 0, sizeof(GHASH_CTX));
/* get H in GF(2^128) as little endian */
ctx->H = H = GETU128_LE(h);
ctx->aadlen = aadlen;
/* process AAD */
X = 0;
while (aadlen >= 16) {
A = GETU128_LE(aad);
X = gf128_add(X, A);
X = gf128_mul(X, H);
aad += 16;
aadlen -= 16;
}
if (aadlen) {
memcpy(ctx->buf, aad, aadlen);
A = GETU128_LE(ctx->block);
X = gf128_add(X, A);
X = gf128_mul(X, H);
}
ctx->H = H;
ctx->X = X;
/* this clean ok? */
H = X = A = 0;
}
void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen)
{
__uint128_t X;
__uint128_t H;
__uint128_t C;
if (!c && clen) {
return 0;
}
ctx->cipherlen += clen;
X = ctx->X;
H = ctx->H;
if (ctx->num) {
unsigned int left = 16 - ctx->num;
if (clen < left) {
memcpy(ctx->block + ctx->num, c, clen);
ctx->num += clen;
return 1;
} else {
memcpy(ctx->block + ctx->num, c, left);
C = GETU128_LE(ctx->block);
X = GF128_ADD(X, C);
X = GF128_MUL(X, H);
c += left;
clen -= left;
}
}
while (clen >= 16) {
C = GETU128_LE(c);
X = gf128_add(X, C);
X = gf128_mul(X, H);
c += 16;
clen -= 16;
}
ctx->num = clen;
if (clen) {
memcpy(ctx->block, c, clen);
}
ctx->X = X;
X = H = C = 0;
}
void ghash_finish(GHASH_CTX *ctx, uint8_t out[16])
{
__uint128_t X = ctx->X;
__uint128_t H = ctx->H;
__uint128_t C;
if (ctx->num < 0) {
return 0;
}
if (ctx->num) {
memset(ctx->block + ctx->num, 0, 16 - ctx->num);
C = GETU128_LE(ctx->block);
X = GF128_ADD(X, C);
X = GF128_MUL(X, H);
}
PUTU64_LE(ctx->block, (uint64_t)ctx->aadlen << 3);
PUTU64_LE(ctx->block + sizeof(uint64_t), (uint64_t)ctx->cipherlen << 3);
C = GETU128_LE(ctx->block);
X = GF128_ADD(X, C);
X = GF128_MUL(X, H);
PUTU128_LE(out, X);
memset(ctx, 0, sizeof(GHASH_CTX));
X = H = C = 0;
}
/*
* GCM(K, IV, A, P)
*
* H = E_K(0^128)
* Y_0 = IV || 0^{31}1 if nbits(IV) == 96
* = GHASH(H, {}, IV) otherwise
* Y_i = Y_{i-1} + 1 for i = 1, ..., n
* C_i = P_i xor E_K(Y_i) for i = 1, ..., n
* C_n^* = P_n^* xor MSB_u(E_K(Y_n))
* T = MSB_t(GHASH(H, A, C) xor E_K(Y_0))
*/
int gcm_init(GCM_CTX *ctx, const BLOCK_CIPEHR *cipher,
const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen,
const uint8_t *aad, size_t aadlen)
{
memset(ctx, 0, sizeof(GCM_CTX));
ctx->cipher = cipher;
/* H = E_K(0^128) */
if (!cipher->set_encrypt_key(ctx->key, key, keylen)) {
return 0;
}
cipher->encrypt(ctx->key, ctx->block, ctx->block);
/* init counter as Y_0 */
if (ivlen == GCM_DEFAULT_IV_SIZE) {
memcpy(ctx->counter, iv, ivlen);
PUTU32(ctx->counter + 12, 1);
} else {
ghash_init(&ctx->ghash_ctx, ctx->block, NULL, 0);
ghash_update(&ctx->ghash_ctx, iv, ivlen);
ghash_finish(&ctx->ghash_ctx, ctx->counter);
}
ghash_init(&ctx->ghash-ctx, ctx->block, aad, aadlen);
return 1;
}
int gcm_encrypt_update(GCM_CTX *ctx, const uint8_t *in, size_t iolen, uint8_t *out)
{
ctr_update(&ctx->ctr_ctx, in, iolen, out);
ghash_update(&ctx->ghash_ctx, out, iolen);
}
int gcm_decrypt_update(GCM_CTX *ctx, const uint8_t *in, size_t iolen, uint8_t *out)
{
ghash_update(&ctx->ghash_ctx, in, iolen);
}
int gcm_encrypt_finish(GCM_CTX *ctx, size_t taglen, uint8_t *tag)
{
int i;
ghash_finish(ctx->ghash_ctx, ctx->block);
for (i = 0; i < ctx->taglen; i++) {
tag[i] = ctx->block[i] ^ ctx->enced_iv[i];
}
memset(ctx, 0, sizeof(GCM_CTX));
}
int gcm_decrypt_finish(GCM_CTX *ctx, const uint8_t *tag, size_t taglen)
{
uint8_t buf[16];
if (taglen != ctx->taglen) {
return 0;
}
gcm_finish(ctx, buf);
if (memcmp(buf, tag, taglen) != 0) {
return 0;
}
return 1;
}

188
src/gf128.c Normal file
View File

@@ -0,0 +1,188 @@
/*
* 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.
*/
/* GF(2^128) defined by f(x) = x^128 + x^7 + x^2 + x + 1
* A + B mod f(x) = a xor b
* A * 2 mod f(x)
*/
#include "internal/endian.h"
#include "internal/gf128.h"
#ifdef GMSSL_HAVE_UINT128
gf128_t gf128_mul(gf128_t a, gf128_t b)
{
gf128_t r = 0;
gf128_t mask = (gf128_t)1 << 127;
int i;
for (i = 0; i < 128; i++) {
// r = r * 2 over gf(2^128)
if (r & mask)
r = (r << 1) ^ 0x87;
else r <<= 1;
// if b[i] == 1, r = r + a
if (b & mask)
r ^= a;
b <<= 1;
}
return r;
}
gf128_t gf128_add(gf128_t a, gf128_t b)
{
return a ^ b;
}
gf128_t gf128_mul2(gf128_t a)
{
if (a & ((gf128_t)1 << 127))
return (a << 1) ^ 0x87;
else return (a << 1);
}
gf128_t gf128_from_bytes(const uint8_t p[16])
{
uint64_t hi = GETU64(p);
uint64_t lo = GETU64(p + 8);
return (gf128_t)hi << 64 | lo;
}
void gf128_to_bytes(gf128_t a, uint8_t p[16])
{
uint64_t hi = a >> 64;
uint64_t lo = a;
PUTU64(p, hi);
PUTU64(p + 8, lo);
}
#else
gf128_t gf128_from_bytes(const uint8_t p[16])
{
gf128_t r;
r.hi = GETU64(p);
r.lo = GETU64(p + 8);
return r;
}
void gf128_to_bytes(gf128_t a, uint8_t p[16])
{
PUTU64(p, a.hi);
PUTU64(p + 8, a.lo);
}
gf128_t gf128_add(gf128_t a, gf128_t b)
{
gf128_t r;
r.hi = a.hi ^ b.hi;
r.lo = a.lo ^ b.lo;
return r;
}
gf128_t gf128_mul(gf128_t a, gf128_t b)
{
gf128_t r = {0, 0};
uint64_t mask = (uint64_t)1 << 63;
int i;
for (i = 0; i < 64; i++) {
if (r.hi & mask) {
r.hi = r.hi << 1 | r.lo >> 63;
r.lo = (r.lo << 1) ^ 0x87;
} else {
r.hi = a.hi << 1 | a.lo >> 63;
r.lo = a.lo << 1;
}
if (b.hi & mask) {
r.hi ^= a.hi;
r.lo ^= a.lo;
}
b.hi <<= 1;
}
for (i = 0; i < 64; i++) {
if (r.hi & mask) {
r.hi = r.hi << 1 | r.lo >> 63;
r.lo = (r.lo << 1) ^ 0x87;
} else {
r.hi = a.hi << 1 | a.lo >> 63;
r.lo = a.lo << 1;
}
if (b.lo & mask) {
r.hi ^= a.hi;
r.lo ^= a.lo;
}
b.lo <<= 1;
}
return r;
}
gf128_t gf128_mul2(gf128_t a)
{
gf128_t r;
if (a.hi & ((uint64_t)1 << 63)) {
r.hi = a.hi << 1 | a.lo >> 63;
r.lo = a.lo << 1;
r.lo ^= 0x87;
} else {
r.hi = a.hi << 1 | a.lo >> 63;
r.lo = a.lo << 1;
}
return r;
}
#endif

75
src/gf128.h Normal file
View File

@@ -0,0 +1,75 @@
/*
* 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.
*/
/* GF(2^128) defined by f(x) = x^128 + x^7 + x^2 + x + 1
* A + B mod f(x) = a xor b
* A * 2 mod f(x)
*/
#ifndef GMSSL_GF128_H
#define GMSSL_GF128_H
#ifdef GMSSL_HAVE_UINT128
typedef unsigned __int128 gf128_t;
#else
#include <stdint.h>
typedef struct {
uint64_t hi;
uint64_t lo;
} gf128_t;
#endif
gf128_t gf128_add(gf128_t a, gf128_t b);
gf128_t gf128_mul(gf128_t a, gf128_t b);
gf128_t gf128_mul2(gf128_t a);
gf128_t gf128_from_bytes(const uint8_t p[16]);
void gf128_to_bytes(gf128_t a, uint8_t p[16]);
#endif

346
src/hash_drbg.c Normal file
View File

@@ -0,0 +1,346 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/hash_drbg.h>
#include "bswap.h"
static int hash_df(const DIGEST *digest, const uint8_t *in, size_t inlen,
size_t outlen, uint8_t *out)
{
int ret = 0;
DIGEST_CTX ctx;
uint8_t counter;
uint8_t outbits[4];
unsigned char dgst[64];
size_t len;
counter = 0x01;
PUTU32(outbits, (uint32_t)outlen << 3);
digest_ctx_init(&ctx);
while (outlen > 0) {
if (!digest_init(&ctx, digest)
|| !digest_update(&ctx, &counter, sizeof(counter))
|| !digest_update(&ctx, outbits, sizeof(outbits))
|| !digest_update(&ctx, in, inlen)
|| !digest_finish(&ctx, dgst, &len)) {
goto end;
}
if (outlen < len) {
len = outlen;
}
memcpy(out, dgst, len);
out += len;
outlen -= len;
counter++;
}
ret = 1;
end:
digest_ctx_cleanup(&ctx);
memset(dgst, 0, sizeof(dgst));
return ret;
}
int hash_drbg_init(HASH_DRBG *drbg, const DIGEST *digest,
const uint8_t *entropy, size_t entropy_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *personalstr, size_t personalstr_len)
{
int ret = 0;
unsigned char *seed_material = NULL;
size_t seed_material_len;
uint8_t buf[1 + HASH_DRBG_MAX_SEED_SIZE];
uint8_t *p;
memset(drbg, 0, sizeof(HASH_DRBG));
/* set digest */
drbg->digest = digest;
/* set seedlen */
if (digest_size(digest) <= 32) {
drbg->seedlen = HASH_DRBG_SM3_SEED_SIZE;
} else {
drbg->seedlen = HASH_DRBG_SHA512_SEED_SIZE;
}
/* seed_material = entropy_input || nonce || personalization_string */
seed_material_len = entropy_len + nonce_len + personalstr_len;
if (!(seed_material = malloc(seed_material_len))) {
return 0;
}
p = seed_material;
memcpy(p, entropy, entropy_len);
p += entropy_len;
memcpy(p, nonce, nonce_len);
p += nonce_len;
memcpy(p, personalstr, personalstr_len);
/* V = Hash_df (seed_material, seedlen) */
if (!hash_df(drbg->digest, seed_material, seed_material_len, drbg->seedlen,
drbg->V)) {
goto end;
}
/* C = Hash_df ((0x00 || V), seedlen) */
buf[0] = 0x00;
memcpy(buf + 1, drbg->V, drbg->seedlen);
if (!hash_df(drbg->digest, buf, 1 + drbg->seedlen, drbg->seedlen,
drbg->C)) {
goto end;
}
/* reseed_counter = 1 */
drbg->reseed_counter = 1;
ret = 1;
end:
if (seed_material) {
memset(seed_material, 0, seed_material_len);
free(seed_material);
}
memset(buf, 0, sizeof(buf));
return ret;
}
int hash_drbg_reseed(HASH_DRBG *drbg,
const uint8_t *entropy, size_t entropy_len,
const uint8_t *additional, size_t additional_len)
{
int ret = 0;
uint8_t *seed_material = NULL;
size_t seed_material_len;
uint8_t *p;
uint8_t buf[1 + HASH_DRBG_MAX_SEED_SIZE];
/* seed_material = 0x01 || V || entropy_input || additional_input */
seed_material_len = 1 + drbg->seedlen + entropy_len + additional_len;
if (!(seed_material = malloc(seed_material_len))) {
return 0;
}
seed_material[0] = 0x01;
p = seed_material + 1;
memcpy(p, drbg->V, drbg->seedlen);
p += drbg->seedlen;
memcpy(p, entropy, entropy_len);
p += entropy_len;
memcpy(p, additional, additional_len);
/* V = Hash_df(seed_material, seedlen) */
if (!hash_df(drbg->digest, seed_material, seed_material_len, drbg->seedlen,
drbg->V)) {
goto end;
}
/* C = Hash_df((0x00 || V), seedlen) */
buf[0] = 0x00;
memcpy(buf + 1, drbg->V, drbg->seedlen);
if (!hash_df(drbg->digest, buf, 1 + drbg->seedlen, drbg->seedlen,
drbg->C)) {
goto end;
}
/* reseed_counter = 1 */
drbg->reseed_counter = 1;
ret = 1;
end:
if (seed_material) {
memset(seed_material, 0, seed_material_len);
free(seed_material);
}
memset(buf, 0, sizeof(buf));
return ret;
}
/* seedlen is always >= dgstlen
* R0 ... Ru-v .. .. .. Ru-1
* + A0 A1 A2 .. Av-1
*/
static void drbg_add(uint8_t *R, const uint8_t *A, size_t seedlen)
{
int temp = 0, i;
for (i = seedlen - 1; i >= 0; i--) {
temp += R[i] + A[i];
R[i] = temp & 0xff;
temp >>= 8;
}
}
static void drbg_add1(uint8_t *R, size_t seedlen)
{
int temp = 1, i;
for (i = seedlen - 1; i >= 0; i--) {
temp += R[i];
R[i] = temp & 0xff;
temp >>= 8;
}
}
static int drbg_hashgen(HASH_DRBG *drbg, size_t outlen, uint8_t *out)
{
int ret = 0;
DIGEST_CTX ctx;
uint8_t data[HASH_DRBG_MAX_SEED_SIZE];
uint8_t dgst[DIGEST_MAX_SIZE];
size_t len;
digest_ctx_init(&ctx);
/* data = V */
memcpy(data, drbg->V, drbg->seedlen);
while (outlen > 0) {
/* output Hash(data) */
if (!digest_init(&ctx, drbg->digest)
|| !digest_update(&ctx, data, drbg->seedlen)
|| !digest_finish(&ctx, dgst, &len)) {
goto end;
}
if (outlen < len) {
len = outlen;
}
memcpy(out, dgst, len);
out += len;
outlen -= len;
/* data = (data + 1) mod 2^seedlen */
drbg_add1(data, drbg->seedlen);
}
ret = 1;
end:
digest_ctx_cleanup(&ctx);
memset(data, 0, sizeof(data));
return ret;
}
int hash_drbg_generate(HASH_DRBG *drbg,
const uint8_t *additional, size_t additional_len,
size_t outlen, uint8_t *out)
{
int ret = 0;
DIGEST_CTX ctx;
uint8_t prefix;
uint8_t T[HASH_DRBG_MAX_SEED_SIZE];
uint8_t dgst[DIGEST_MAX_SIZE];
size_t dgstlen;
// FIXME: check outlen max value
if (drbg->reseed_counter > HASH_DRBG_RESEED_INTERVAL) {
return 0;
}
digest_ctx_init(&ctx);
if (additional) {
/* w = Hash (0x02 || V || additional_input) */
prefix = 0x02;
if (!digest_init(&ctx, drbg->digest)
|| !digest_update(&ctx, &prefix, 1)
|| !digest_update(&ctx, drbg->V, drbg->seedlen)
|| !digest_update(&ctx, additional, additional_len)
|| !digest_finish(&ctx, dgst, &dgstlen)) {
goto end;
}
/* V = (V + w) mod 2^seedlen */
memset(T, 0, drbg->seedlen - dgstlen);
memcpy(T + drbg->seedlen - dgstlen, dgst, dgstlen);
drbg_add(drbg->V, T, drbg->seedlen);
}
/* (returned_bits) = Hashgen (requested_number_of_bits, V). */
drbg_hashgen(drbg, outlen, out);
/* H = Hash (0x03 || V). */
prefix = 0x03;
if (!digest_init(&ctx, drbg->digest)
|| !digest_update(&ctx, &prefix, 1)
|| !digest_update(&ctx, drbg->V, drbg->seedlen)
|| !digest_finish(&ctx, dgst, &dgstlen)) {
goto end;
}
/* V = (V + H + C + reseed_counter) mod 2^seedlen */
memset(T, 0, drbg->seedlen - dgstlen);
memcpy(T + drbg->seedlen - dgstlen, dgst, dgstlen);
drbg_add(drbg->V, T, drbg->seedlen);
drbg_add(drbg->V, drbg->C, drbg->seedlen);
memset(T, 0, drbg->seedlen - sizeof(uint64_t));
PUTU64(T + drbg->seedlen - sizeof(uint64_t), drbg->reseed_counter);
drbg_add(drbg->V, T, drbg->seedlen);
/* reseed_counter = reseed_counter + 1 */
drbg->reseed_counter++;
ret = 1;
end:
digest_ctx_cleanup(&ctx);
memset(T, 0, sizeof(T));
memset(dgst, 0, sizeof(dgst));
return ret;
}
void hash_drbg_cleanup(HASH_DRBG *drbg)
{
//mem_cleanup(drbg, sizeof(HASH_DRBG));
}

188
src/hex.c Normal file
View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 2014 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <gmssl/error.h>
int OPENSSL_hexchar2int(unsigned char c)
{
switch (c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'a':
case 'A':
return 0x0A;
case 'b': case 'B':
return 0x0B;
case 'c': case 'C':
return 0x0C;
case 'd': case 'D':
return 0x0D;
case 'e': case 'E':
return 0x0E;
case 'f': case 'F':
return 0x0F;
}
return -1;
}
unsigned char *OPENSSL_hexstr2buf(const char *str, size_t *len)
{
unsigned char *hexbuf, *q;
unsigned char ch, cl;
int chi, cli;
const unsigned char *p;
size_t s;
s = strlen(str);
if ((hexbuf = malloc(s >> 1)) == NULL) {
return NULL;
}
for (p = (const unsigned char *)str, q = hexbuf; *p; ) {
ch = *p++;
if (ch == ':')
continue;
cl = *p++;
if (!cl) {
//CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ODD_NUMBER_OF_DIGITS);
free(hexbuf);
return NULL;
}
cli = OPENSSL_hexchar2int(cl);
chi = OPENSSL_hexchar2int(ch);
if (cli < 0 || chi < 0) {
free(hexbuf);
//CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT);
return NULL;
}
*q++ = (unsigned char)((chi << 4) | cli);
}
if (len)
*len = q - hexbuf;
return hexbuf;
}
static int hexchar2int(char c)
{
if ('0' <= c && c <= '9') return c - '0';
else if ('a' <= c && c <= 'f') return c - 'a' + 10;
else if ('A' <= c && c <= 'F') return c - 'A' + 10;
else return -1;
}
int hex2bin(const char *in, size_t inlen, uint8_t *out)
{
int c;
if (inlen % 2) {
error_print();
return -1;
}
while (inlen) {
if ((c = hexchar2int(*in++)) < 0) {
error_print();
return -1;
}
*out = (uint8_t)c << 4;
if ((c = hexchar2int(*in++)) < 0) {
error_print();
return -1;
}
*out |= (uint8_t)c;
inlen -= 2;
out++;
}
return 1;
}
void memxor(void *r, const void *a, size_t len)
{
uint8_t *pr = r;
const uint8_t *pa = a;
size_t i;
for (i = 0; i < len; i++) {
pr[i] ^= pa[i];
}
}
void gmssl_memxor(void *r, const void *a, const void *b, size_t len)
{
uint8_t *pr = r;
const uint8_t *pa = a;
const uint8_t *pb = b;
size_t i;
for (i = 0; i < len; i++) {
pr[i] = pa[i] ^ pb[i];
}
}

162
src/hkdf.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm3.h>
#include <gmssl/hmac.h>
#include <gmssl/error.h>
/*
HKDF-Extract(salt, IKM) -> PRK
salt optional, len(salt) == hash_len is recommended
IKM input key material
PRK output pseudorandom key, len(PRK) = hashLen
PRK = HMAC_hash(salt, IKM)
salt as key?
HKDF-Expand(PRK, info, L) -> OKM
info optional
L output length, L <= 255 * hashLen
OKM output key
N = (L + hashLen - 1)//hashLen
T = T(1) || T(2) || ... | T(N)
OKM = T[0..L-1]
T(0) = empty string (len = 0)
T(1) = HMAC_hash(PRK, T(0) | info | 0x01)
T(2) = HMAC_hash(PRK, T(1) | info | 0x02)
T(3) = HMAC_hash(PRK, T(2) | info | 0x03)
...
*/
int hkdf_extract(const DIGEST *digest, const uint8_t *salt, size_t saltlen,
const uint8_t *ikm, size_t ikmlen,
uint8_t *prk, size_t *prklen)
{
HMAC_CTX hmac_ctx;
if (!salt || saltlen == 0) {
uint8_t zeros[DIGEST_MAX_SIZE] = {0};
if (hmac_init(&hmac_ctx, digest, zeros, digest_size(digest)) != 1) {
error_print();
return -1;
}
} else {
if (hmac_init(&hmac_ctx, digest, salt, saltlen) != 1) {
error_print();
return -1;
}
}
if (hmac_update(&hmac_ctx, ikm, ikmlen) != 1
|| hmac_finish(&hmac_ctx, prk, prklen) != 1) {
error_print();
return -1;
}
return 1;
}
int hkdf_expand(const DIGEST *digest, const uint8_t *prk, size_t prklen,
const uint8_t *info, size_t infolen,
size_t L, uint8_t *okm)
{
HMAC_CTX hmac_ctx;
uint8_t T[HMAC_MAX_SIZE];
uint8_t counter = 0x01;
size_t len;
if (L > 0) {
if (hmac_init(&hmac_ctx, digest, prk, prklen) != 1
|| hmac_update(&hmac_ctx, info, infolen) != 1
|| hmac_update(&hmac_ctx, &counter, 1) != 1
|| hmac_finish(&hmac_ctx, T, &len) != 1) {
error_print();
return -1;
}
counter++;
if (len > L) {
len = L;
}
memcpy(okm, T, len);
okm += len;
L -= len;
}
while (L > 0) {
if (counter == 0) {
error_print();
return -1;
}
if (hmac_init(&hmac_ctx, digest, prk, prklen) != 1
|| hmac_update(&hmac_ctx, T, len) != 1
|| hmac_update(&hmac_ctx, info, infolen) != 1
|| hmac_update(&hmac_ctx, &counter, 1) != 1
|| hmac_finish(&hmac_ctx, T, &len) != 1) {
error_print();
return -1;
}
counter++;
if (len > L) {
len = L;
}
memcpy(okm, T, len);
okm += len;
L -= len;
}
return 1;
}

158
src/hmac.c Normal file
View File

@@ -0,0 +1,158 @@
/*
* 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 <string.h>
#include <gmssl/hmac.h>
#define IPAD 0x36
#define OPAD 0x5C
int hmac_ctx_init(HMAC_CTX *ctx)
{
memset(ctx, 0, sizeof(HMAC_CTX));
return 1;
}
void hmac_ctx_cleanup(HMAC_CTX *ctx)
{
memset(ctx, 0, sizeof(HMAC_CTX));
}
int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, size_t keylen)
{
uint8_t i_key[DIGEST_MAX_BLOCK_SIZE] = {0};
uint8_t o_key[DIGEST_MAX_BLOCK_SIZE] = {0};
size_t blocksize;
int i;
if (!ctx || !digest || !key || !keylen) {
return 0;
}
ctx->digest = digest;
blocksize = digest_block_size(digest);
if (keylen <= blocksize) {
memcpy(i_key, key, keylen);
memcpy(o_key, key, keylen);
} else {
digest_init(&ctx->digest_ctx, digest);
digest_update(&ctx->digest_ctx, key, keylen);
digest_finish(&ctx->digest_ctx, i_key, &keylen);
memcpy(o_key, i_key, keylen);
}
for (i = 0; i < blocksize; i++) {
i_key[i] ^= IPAD;
o_key[i] ^= OPAD;
}
digest_init(&ctx->i_ctx, digest);
digest_update(&ctx->i_ctx, i_key, blocksize);
digest_init(&ctx->o_ctx, digest);
digest_update(&ctx->o_ctx, o_key, blocksize);
memcpy(&ctx->digest_ctx, &ctx->i_ctx, sizeof(DIGEST_CTX));
memset(i_key, 0, sizeof(i_key));
memset(o_key, 0, sizeof(o_key));
return 1;
}
int hmac_update(HMAC_CTX *ctx, const unsigned char *data, size_t datalen)
{
if (!ctx || (!data && datalen != 0)) {
return 0;
}
return digest_update(&ctx->digest_ctx, data, datalen);
}
int hmac_finish(HMAC_CTX *ctx, unsigned char *mac, size_t *maclen)
{
int ret = 0;
size_t i;
size_t blocksize;
if (!digest_finish(&ctx->digest_ctx, mac, maclen)) {
return -1;
}
memcpy(&ctx->digest_ctx, &ctx->o_ctx, sizeof(DIGEST_CTX));
if (!digest_update(&ctx->digest_ctx, mac, *maclen)
|| !digest_finish(&ctx->digest_ctx, mac, maclen)) {
goto end;
}
ret = 1;
end:
return ret;
}
int hmac_reset(HMAC_CTX *ctx)
{
memcpy(&ctx->digest_ctx, &ctx->i_ctx, sizeof(DIGEST_CTX));
return 1;
}
int hmac(const DIGEST *digest, const unsigned char *key, size_t keylen,
const unsigned char *data, size_t datalen,
unsigned char *mac, size_t *maclen)
{
int ret = 0;
HMAC_CTX ctx;
if (!hmac_ctx_init(&ctx)
|| !hmac_init(&ctx, digest, key, keylen)
|| !hmac_update(&ctx, data, datalen)
|| !hmac_finish(&ctx, mac, maclen)) {
goto end;
}
ret = 1;
end:
hmac_ctx_cleanup(&ctx);
return ret;
}

276
src/md5.c Executable file
View File

@@ -0,0 +1,276 @@
/*
* 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.
*/
/* ====================================================================
* Copyright (c) 2014 - 2017 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 <string.h>
#include <gmssl/md5.h>
#include "bswap.h"
static void md5_compress_blocks(uint32_t state[4],
const unsigned char *data, size_t blocks);
void md5_init(MD5_CTX *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xefcdab89;
ctx->state[2] = 0x98badcfe;
ctx->state[3] = 0x10325476;
}
void md5_update(MD5_CTX *ctx, const unsigned char *data, size_t datalen)
{
size_t blocks;
if (ctx->num) {
unsigned int left = MD5_BLOCK_SIZE - ctx->num;
if (datalen < left) {
memcpy(ctx->block + ctx->num, data, datalen);
ctx->num += datalen;
return;
} else {
memcpy(ctx->block + ctx->num, data, left);
md5_compress_blocks(ctx->state, ctx->block, 1);
ctx->nblocks++;
data += left;
datalen -= left;
}
}
blocks = datalen / MD5_BLOCK_SIZE;
md5_compress_blocks(ctx->state, data, blocks);
ctx->nblocks += blocks;
data += MD5_BLOCK_SIZE * blocks;
datalen -= MD5_BLOCK_SIZE * blocks;
ctx->num = datalen;
if (datalen) {
memcpy(ctx->block, data, datalen);
}
}
void md5_finish(MD5_CTX *ctx, unsigned char *dgst)
{
int i;
ctx->block[ctx->num] = 0x80;
if (ctx->num + 9 <= MD5_BLOCK_SIZE) {
memset(ctx->block + ctx->num + 1, 0, MD5_BLOCK_SIZE - ctx->num - 9);
} else {
memset(ctx->block + ctx->num + 1, 0, MD5_BLOCK_SIZE - ctx->num - 1);
md5_compress_blocks(ctx->state, ctx->block, 1);
memset(ctx->block, 0, MD5_BLOCK_SIZE - 8);
}
PUTU64_LE(ctx->block + 56, (ctx->nblocks << 9) + (ctx->num << 3));
md5_compress_blocks(ctx->state, ctx->block, 1);
for (i = 0; i < 4; i++) {
//PUTU32_LE(dgst, ctx->state[i]);
*(uint32_t *)dgst = ctx->state[i];
dgst += sizeof(uint32_t);
}
}
#define ROL32(X, n) (((X) << (n)) | ((X) >> (32-(n))))
#define F(B, C, D) (((B) & (C)) | ((~(B)) & (D)))
#define G(B, C, D) (((B) & (D)) | ((C) & (~(D))))
#define H(B, C, D) ((B) ^ (C) ^ (D))
#define I(B, C, D) ((C) ^ ((B) | (~(D))))
static const uint32_t K[] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
};
static const int S[] = {
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
};
static void md5_compress_blocks(uint32_t state[4],
const unsigned char *data, size_t blocks)
{
uint32_t A;
uint32_t B;
uint32_t C;
uint32_t D;
uint32_t T;
uint32_t W[16];
int g, i;
while (blocks--) {
A = state[0];
B = state[1];
C = state[2];
D = state[3];
for (i = 0; i < 16; i++) {
//W[i] = GETU32_LE(data);
W[i] = *((uint32_t *)data);
data += sizeof(uint32_t);
}
for (i = 0; i < 16; i++) {
T = ROL32(A + F(B, C, D) + W[i] + K[i], S[i]) + B;
A = D;
D = C;
C = B;
B = T;
}
for (; i < 32; i++) {
g = (5 * i + 1) % 16;
T = ROL32(A + G(B, C, D) + W[g] + K[i], S[i]) + B;
A = D;
D = C;
C = B;
B = T;
}
for (; i < 48; i++) {
g = (3 * i + 5) % 16;
T = ROL32(A + H(B, C, D) + W[g] + K[i], S[i]) + B;
A = D;
D = C;
C = B;
B = T;
}
for (; i < 64; i++) {
g = (7 * i) % 16;
T = ROL32(A + I(B, C, D) + W[g] + K[i], S[i]) + B;
A = D;
D = C;
C = B;
B = T;
}
state[0] += A;
state[1] += B;
state[2] += C;
state[3] += D;
}
}
void md5_compress(uint32_t state[4], const unsigned char block[64])
{
return md5_compress_blocks(state, block, 1);
}
void md5_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[MD5_DIGEST_SIZE])
{
MD5_CTX ctx;
md5_init(&ctx);
md5_update(&ctx, data, datalen);
md5_finish(&ctx, dgst);
}

58
src/mem.h Normal file
View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2021 - 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_MEM_H
#define GMSSL_MEM_H
#include <stddef.h> // where size_t from
void memxor(void *r, const void *a, size_t len);
void gmssl_memxor(void *r, const void *a, const void *b, size_t len);
#endif

958
src/oid.c Normal file
View File

@@ -0,0 +1,958 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <gmssl/oid.h>
#include <gmssl/asn1.h>
#include <gmssl/error.h>
/*
asn1_type_from_octets 函数有三种返回值
* -1 说明编码的前缀错误,也就是不属于本类型的字节点
* 0 即 OID_undef说明前缀是匹配的但是我们不识别这个 OID
* >=1 一个被识别出来的 OID
asn1_type_from_octets 函数不识别 type 的编码,如 asn1_sm_oid_from_octets 不识别 DER_sm
但是返回值为 OID_undef而不是 -1
*/
static uint8_t DER_sm[] = { 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01 };
static uint8_t DER_sm1[] = { 0x66 };
static uint8_t DER_ssf33[] = { 0x67 };
static uint8_t DER_sm4[] = { 0x68 };
static uint8_t DER_zuc[] = { 0x86, 0x20 };
static uint8_t DER_sm2[] = { 0x82, 0x2D };
static uint8_t DER_sm2sign[] = { 0x82, 0x2D, 0x01 };
static uint8_t DER_sm2keyagreement[] = { 0x82, 0x2D, 0x02 };
static uint8_t DER_sm2encrypt[] = { 0x82, 0x2D, 0x03 };
static uint8_t DER_sm9[] = { 0x82, 0x2E };
static uint8_t DER_sm9sign[] = { 0x82, 0x2E, 0x01 };
static uint8_t DER_sm9keyagreement[] = { 0x82, 0x2E, 0x02 };
static uint8_t DER_sm9encrypt[] = { 0x82, 0x2E, 0x03 };
static uint8_t DER_sm3[] = { 0x83, 0x11 };
static uint8_t DER_sm3_keyless[] = { 0x83, 0x11, 0x01 };
static uint8_t DER_hmac_sm3[] = { 0x83, 0x11, 0x02 };
static uint8_t DER_sm2sign_with_sm3[] = { 0x83, 0x75 };
static uint8_t DER_rsasign_with_sm3[] = { 0x83, 0x78 };
static const struct {
uint8_t *der;
size_t derlen;
char *name;
char *desc;
} sm_oids[] = {
{ DER_sm1, 1, "sm1", "SM1" },
{ DER_ssf33, 1, "ssf33", "SSF33" },
{ DER_sm4, 1, "sm4", "SM4" },
{ DER_zuc, 2, "zuc", "ZUC" },
{ DER_sm2, 2, "sm2p256v1", "SM2" },
{ DER_sm2sign, 3, "sm2sign", "SM2 Signature Scheme" },
{ DER_sm2keyagreement, 3, "sm2keyagreement", "SM2 Key Agreement" },
{ DER_sm2encrypt, 3, "sm2encrypt", "SM2 Encryption" },
{ DER_sm9, 2, "sm9", "SM9" },
{ DER_sm9sign, 3, "sm9sign", "SM9 Signature Scheme" },
{ DER_sm9keyagreement, 3, "sm9keyagreement", "SM9 Key Agreement" },
{ DER_sm9encrypt, 3, "sm9encrypt", "SM9 Encrpytion" },
{ DER_sm3, 2, "sm3", "SM3" },
{ DER_sm3_keyless, 3, "sm3-keyless", "SM3 without Key" },
{ DER_hmac_sm3, 3, "hmac-sm3", "HMAC-SM3" },
{ DER_sm2sign_with_sm3, 2, "sm2sign-with-sm3", "SM2 Signature with SM3" },
{ DER_rsasign_with_sm3, 2, "rsasign-with-sm3", "RSA Signature with SM3" },
};
const char *asn1_sm_oid_name(int oid)
{
assert(OID_sm1 <= oid && oid <= OID_rsasign_with_sm3);
return sm_oids[oid - OID_sm1].name;
}
const char *asn1_sm_oid_description(int oid)
{
assert(oid >= OID_sm1 && oid <= OID_rsasign_with_sm3);
return sm_oids[oid - OID_sm1].desc;
}
void asn1_sm_oid_to_octets(int oid, uint8_t *out, size_t *outlen)
{
int i = oid - OID_sm1;
assert(i >= 0 && i < sizeof(sm_oids)/sizeof(sm_oids[0]));
if (out) {
memcpy(out, DER_sm, sizeof(DER_sm));
out += sizeof(DER_sm);
memcpy(out, sm_oids[i].der, sm_oids[i].derlen);
out += sm_oids[i].derlen;
}
*outlen = sizeof(DER_sm) + sm_oids[i].derlen;
}
int asn1_sm_oid_from_octets(const uint8_t *in, size_t inlen)
{
int i;
if (inlen < sizeof(DER_sm)
|| memcmp(in, DER_sm, sizeof(DER_sm)) != 0) {
return -1;
}
in += sizeof(DER_sm);
inlen -= sizeof(DER_sm);
for (i = 0; i < sizeof(sm_oids)/sizeof(sm_oids[0]); i++) {
if (sm_oids[i].derlen == inlen
&& memcmp(sm_oids[i].der, in, inlen) == 0) {
return OID_sm1 + i;
}
}
return OID_undef;
}
int asn1_sm_oid_from_name(const char *name)
{
size_t i;
for (i = 0; i < sizeof(sm_oids)/sizeof(sm_oids[0]); i++) {
if (strcmp(name, sm_oids[i].name) == 0) {
return OID_sm1 + i;
}
}
return OID_undef;
}
// FIXME: 支持所有的公钥类型
static const uint8_t DER_x9_62_ecPublicKey[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01 };
const char *asn1_pkey_oid_name(int oid)
{
switch (oid) {
case OID_x9_62_ecPublicKey: return "x9_62_ecPublicKey";
}
return NULL;
}
const char *asn1_pkey_oid_description(int oid)
{
switch (oid) {
case OID_x9_62_ecPublicKey: return "x9_62_ecPublicKey";
}
return NULL;
}
void asn1_pkey_oid_to_octets(int oid, uint8_t *out, size_t *outlen)
{
assert(oid == OID_x9_62_ecPublicKey);
if (out) {
memcpy(out, DER_x9_62_ecPublicKey, sizeof(DER_x9_62_ecPublicKey));
}
*outlen = sizeof(DER_x9_62_ecPublicKey);
}
int asn1_pkey_oid_from_octets(const uint8_t *in, size_t inlen)
{
if (inlen == sizeof(DER_x9_62_ecPublicKey)
&& memcmp(DER_x9_62_ecPublicKey, in, inlen) == 0) {
return OID_x9_62_ecPublicKey;
}
return 0;
}
int asn1_pkey_oid_from_name(const char *name)
{
if (strcmp(name, "x9_62_ecPublicKey") == 0) {
return OID_x9_62_ecPublicKey;
}
return 0;
}
// 本组函数不支持 OID_x9_62_ecPublicKey 的 DER 编解码
// 这个类型应该归为公钥类型还包括RSA、DSA、DH等公钥类型
// 这个错误, 03 01 是 curves prime ,而不是x9_62_ecPublicKey
// x9_62_ecPublicKey 是 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01
static const uint8_t DER_x9_62_curve_prime[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01 };
static const struct {
uint8_t der;
char *name;
} x9_62_curve_oids[] = {
{ 1, "prime192v1" },
{ 2, "prime192v2" },
{ 3, "prime192v3" },
{ 4, "prime239v1" },
{ 5, "prime239v2" },
{ 6, "prime239v3" },
{ 7, "prime256v1" },
};
const char *asn1_x9_62_curve_oid_name(int oid)
{
assert(OID_prime192v1 <= oid && oid <= OID_prime256v1);
return x9_62_curve_oids[oid - OID_prime192v1].name;
}
const char *asn1_x9_62_curve_oid_description(int oid)
{
return asn1_x9_62_curve_oid_name(oid);
}
void asn1_x9_62_curve_oid_to_octets(int oid, uint8_t *out, size_t *outlen)
{
assert(OID_prime192v1 <= oid && oid <= OID_prime256v1);
if (out) {
memcpy(out, DER_x9_62_curve_prime, sizeof(DER_x9_62_curve_prime));
out += sizeof(DER_x9_62_curve_prime);
*out = x9_62_curve_oids[oid - OID_prime192v1].der;
}
(*outlen) = sizeof(DER_x9_62_curve_prime) + 1;
}
int asn1_x9_62_curve_oid_from_octets(const uint8_t *in, size_t inlen)
{
if (inlen < sizeof(DER_x9_62_curve_prime)
|| memcmp(in, DER_x9_62_curve_prime, sizeof(DER_x9_62_curve_prime)) != 0) {
return -1;
}
in += sizeof(DER_x9_62_curve_prime);
inlen -= sizeof(DER_x9_62_curve_prime);
if (inlen == 1 && *in >= 1 && *in <= 7) {
return OID_prime192v1 + *in - 1;
}
return OID_undef;
}
int asn1_x9_62_curve_oid_from_name(const char *name)
{
int i;
for (i = 0; i < sizeof(x9_62_curve_oids)/sizeof(x9_62_curve_oids[0]); i++) {
if (strcmp(name, x9_62_curve_oids[i].name) == 0) {
return OID_prime192v1 + i;
}
}
return OID_undef;
}
static const uint8_t DER_secg_curve[] = { 0x2B, 0x81, 0x04, 0x00 };
static const struct {
uint8_t der;
int oid;
char *name;
} secg_curve_oids[] = {
{ 10, OID_secp256k1, "secp256k1" },
{ 31, OID_secp192k1, "secp192k1" },
{ 32, OID_secp224k1, "secp224k1" },
{ 33, OID_secp224r1, "secp224r1" },
{ 34, OID_secp384r1, "secp384r1" },
{ 35, OID_secp521r1, "secp521r1" },
};
const char *asn1_secg_curve_oid_name(int oid)
{
int i = oid - OID_secp256k1;
if (i < 0 || i >= sizeof(secg_curve_oids)/sizeof(secg_curve_oids[0])) {
fprintf(stderr, "%s %d: i = %d\n", __FILE__, __LINE__, i);
}
assert(i >= 0 && i < sizeof(secg_curve_oids)/sizeof(secg_curve_oids[0]));
return secg_curve_oids[i].name;
}
const char *asn1_secg_curve_oid_description(int oid)
{
return asn1_secg_curve_oid_name(oid);
}
void asn1_secg_curve_oid_to_octets(int oid, uint8_t *out, size_t *outlen)
{
int i = oid - OID_secp256k1;
if (out) {
memcpy(out, DER_secg_curve, sizeof(DER_secg_curve));
out += sizeof(DER_secg_curve);
*out++ = secg_curve_oids[i].der;
}
*outlen = sizeof(DER_secg_curve) + 1;
}
int asn1_secg_curve_oid_from_octets(const uint8_t *in, size_t inlen)
{
if (inlen < sizeof(DER_secg_curve)
|| memcmp(in, DER_secg_curve, sizeof(DER_secg_curve)) != 0) {
return -1;
}
in += sizeof(DER_secg_curve);
inlen -= sizeof(DER_secg_curve);
if (inlen == 1) {
int i;
for (i = 0; i < sizeof(secg_curve_oids)/sizeof(secg_curve_oids[0]); i++) {
if (*in == secg_curve_oids[i].der) {
return secg_curve_oids[i].oid;
}
}
}
return OID_undef;
}
int asn1_secg_curve_oid_from_name(const char *name)
{
uint32_t a;
if (strlen(name) != sizeof("secp256k1")-1
|| *(uint32_t *)name != *(uint32_t *)"secp"
|| name[8] != '1') {
return OID_undef;
}
a = *(uint32_t *)(name + 4);
if (a == *(uint32_t *)"256k") return OID_secp256k1;
else if (a == *(uint32_t *)"192k") return OID_secp192k1;
else if (a == *(uint32_t *)"224k") return OID_secp224k1;
else if (a == *(uint32_t *)"224r") return OID_secp224r1;
else if (a == *(uint32_t *)"384r") return OID_secp384r1;
else if (a == *(uint32_t *)"521r") return OID_secp521r1;
else return OID_undef;
}
static const uint8_t DER_x509[] = { 0x55, 0x04 };
static const struct {
uint8_t der;
char *name;
char *desc;
} x509_oids[] = {
{ 3, "commonName", "Common Name" },
{ 4, "surname", "Surname" },
{ 5, "serialNumber", "Serial Number" },
{ 6, "countryName", "Country" },
{ 7, "localityName", "Locality" },
{ 8, "stateOrProvinceName", "State or Province" },
{ 9, "streetAddress", "Street Address" },
{ 10, "organizationName", "Organization" },
{ 11, "organizationalUnitName", "Organizational Unit" },
{ 12, "title", "Title" },
{ 13, "description", "Description" },
{ 14, "searchGuide", "Search Guide" },
{ 15, "businessCategory", "Business Category" },
{ 16, "postalAddress", "Postal Address" },
{ 17, "postalCode", "Postal Code" },
{ 18, "postOfficeBox", "Post Office Box" },
{ 19, "physicalDeliveryOfficeName", "Physical Delivery Office" },
{ 20, "telephoneNumber", "Telephone Number" },
{ 21, "telexNumber", "Telex Number" },
{ 22, "teletexTerminalIdentifier", "Teletex Terminal Identifier" },
{ 23, "facsimileTelephoneNumber", "Facsimile Telephone Number" },
{ 24, "x121Address", "X121 Address" },
{ 25, "internationaliSDNNumber", "InternationaliSDN Number" },
{ 26, "registeredAddress", "Registered Address" },
{ 27, "destinationIndicator", "Destination Indicator" },
{ 28, "preferredDeliveryMethod", "Preferred Delivery Method" },
{ 29, "presentationAddress", "Presentation Address" },
{ 30, "supportedApplicationContext", "Supported ApplicationContext" },
{ 31, "member", "Member" },
{ 32, "owner", "Owner" },
{ 33, "roleOccupant", "Role Occupant" },
{ 34, "seeAlso", "See Also" },
{ 35, "userPassword", "User Password" },
{ 36, "userCertificate", "User Certificate" },
{ 37, "caCertificate", "CA Certificate" },
{ 38, "authorityRevocationList", "Authority Revocation List" },
{ 39, "certificateRevocationList", "Certificate Revocation List" },
{ 40, "crossCertificatePair", "Cros sCertificate Pair" },
{ 41, "name", "Name" },
{ 42, "givenName", "Given Name" },
{ 43, "initials", "Initials" },
{ 44, "generationQualifier", "Generation Qualifier" },
{ 45, "x500UniqueIdentifier", "X500Unique Identifier" },
{ 46, "dnQualifier", "DN Qualifier" },
{ 47, "enhancedSearchGuide", "Enhanced Search Guide" },
{ 48, "protocolInformation", "Protocol Information" },
{ 49, "distinguishedName", "Distinguished Name" },
{ 50, "uniqueMember", "Unique Member" },
{ 51, "houseIdentifier", "House Identifier" },
{ 52, "supportedAlgorithms", "Supported Algorithms" },
{ 53, "deltaRevocationList", "Delta Revocation List" },
{ 55, "dmdName", "DMD Name" },
{ 65, "pseudonym", "Pseudonym" },
{ 72, "role", "Role" },
};
const char *asn1_x509_oid_name(int oid)
{
int i = oid - OID_at_commonName;
assert(OID_at_role - OID_at_commonName + 1 == sizeof(x509_oids)/sizeof(x509_oids[0]));
if (i < 0 || i >= sizeof(x509_oids)/sizeof(x509_oids[0])) {
fprintf(stderr, "%s %d: oid = %d, i = %d\n", __FILE__, __LINE__, oid, i);
}
assert(i >= 0 && i < sizeof(x509_oids)/sizeof(x509_oids[0]));
return x509_oids[i].name;
}
const char *asn1_x509_oid_description(int oid)
{
int i = oid - OID_at_commonName;
assert(i >= 0 && i < sizeof(x509_oids)/sizeof(x509_oids[0]));
return x509_oids[i].desc;
}
void asn1_x509_oid_to_octets(int oid, uint8_t *out, size_t *outlen)
{
int i = oid - OID_at_commonName;
if (i < 0 || i >= sizeof(x509_oids)/sizeof(x509_oids[0])) {
fprintf(stderr, "%s %d: oid = %d, i = %d\n", __FILE__, __LINE__, oid, i);
}
assert(i >= 0 && i < sizeof(x509_oids)/sizeof(x509_oids[0]));
if (out) {
memcpy(out, DER_x509, sizeof(DER_x509));
out += sizeof(DER_x509);
*out = x509_oids[i].der;
}
*outlen = sizeof(DER_x509) + 1;
}
int asn1_x509_oid_from_octets(const uint8_t *in, size_t inlen)
{
if (inlen < sizeof(DER_x509)
|| memcmp(in, DER_x509, sizeof(DER_x509)) != 0) {
return -1;
}
in += sizeof(DER_x509);
inlen -= sizeof(DER_x509);
if (inlen == 1) {
if (*in >= 3 && *in <= 53)
return OID_at_commonName + *in - 3;
else if (*in == 55)
return OID_at_dmdName;
else if (*in == 65)
return OID_at_pseudonym;
else if (*in == 72)
return OID_at_role;
}
return OID_undef;
}
int asn1_x509_oid_from_name(const char *name)
{
int i;
for (i = 0; i < sizeof(x509_oids)/sizeof(x509_oids[0]); i++) {
if (strcmp(name, x509_oids[i].name) == 0) {
return OID_at_commonName + i;
}
}
return OID_undef;
}
// OIDs for X.509 extension ExtKeyUsage
// kp means "key purpose"
static const uint8_t DER_x509_kp[] = { 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, };
static const struct {
uint8_t der;
char *name;
char *desc;
} x509_kp_oids[] = {
{ 1, "serverAuth", "TLS WWW server authentication" },
{ 2, "clientAuth", "TLS WWW client authentication" },
{ 3, "codeSigning", "Signing of downloadable executable code" },
{ 4, "emailProtection", "Email protection" },
{ 8, "timeStamping", "Binding the hash of an object to a time" },
{ 9, "OCSPSigning", "Signing OCSP responses" },
};
const char *asn1_x509_kp_oid_name(int oid)
{
int i = oid - OID_kp_serverAuth;
assert(i >= 0 && i < sizeof(x509_kp_oids)/sizeof(x509_kp_oids[0]));
return x509_kp_oids[i].name;
}
const char *asn1_x509_kp_oid_description(int oid)
{
int i = oid - OID_kp_serverAuth;
assert(i >= 0 && i < sizeof(x509_kp_oids)/sizeof(x509_kp_oids[0]));
return x509_kp_oids[i].desc;
}
void asn1_x509_kp_oid_to_octets(int oid, uint8_t *out, size_t *outlen)
{
int i = oid - OID_kp_serverAuth;
assert(i >= 0 && i < sizeof(x509_kp_oids)/sizeof(x509_kp_oids[0]));
if (out) {
memcpy(out, DER_x509_kp, sizeof(DER_x509_kp));
out += sizeof(DER_x509_kp);
*out = x509_kp_oids[i].der;
}
*outlen = sizeof(DER_x509_kp) + 1;
}
int asn1_x509_kp_oid_from_octets(const uint8_t *in, size_t inlen)
{
if (inlen < sizeof(DER_x509_kp)
|| memcmp(in, DER_x509_kp, sizeof(DER_x509_kp)) != 0) {
return -1;
}
in += sizeof(DER_x509_kp);
inlen -= sizeof(DER_x509_kp);
if (inlen == 1) {
if (*in >= 1 && *in <= 4)
return OID_kp_serverAuth + *in - 1;
else if (*in == 8)
return OID_kp_timeStamping;
else if (*in == 9)
return OID_kp_OCSPSigning;
}
return OID_undef;
}
int asn1_x509_kp_oid_from_name(const char *name)
{
int i;
assert(i >= 0 && i < sizeof(x509_kp_oids)/sizeof(x509_kp_oids[0]));
for (i = 0; i < sizeof(x509_kp_oids)/sizeof(x509_kp_oids[0]); i++) {
if (strcmp(name, x509_kp_oids[i].name) == 0) {
return OID_kp_serverAuth + i;
}
}
return OID_undef;
}
void asn1_oid_to_octets(int oid, uint8_t *out, size_t *outlen)
{
if (oid <= OID_rsasign_with_sm3) {
asn1_sm_oid_to_octets(oid, out, outlen);
} else if (oid == OID_x9_62_ecPublicKey) {
if (out) // 注意:这里必须验证 out == NULL ?
memcpy(out, DER_x9_62_ecPublicKey, sizeof(DER_x9_62_ecPublicKey));
*outlen = sizeof(DER_x9_62_ecPublicKey);
} else if (oid <= OID_prime256v1) {
asn1_x9_62_curve_oid_to_octets(oid, out, outlen);
} else if (oid <= OID_secp521r1) {
asn1_secg_curve_oid_to_octets(oid, out, outlen);
} else if (oid <= OID_at_role) {
asn1_x509_oid_to_octets(oid, out, outlen);
} else {
error_print("unknown oid %d\n", oid);
assert(0);
}
}
// asn1_oid_from_octets 不返回错误值,只返回 OID_undef
// 但是数据编码仍可能是非法的
// 如果返回 OID_undef需要通过 asn1_oid_nodes_from_octets 判断格式是否正确
int asn1_oid_from_octets(const uint8_t *in, size_t inlen)
{
int ret = OID_undef;
if (inlen == sizeof(DER_x9_62_ecPublicKey)
&& memcmp(DER_x9_62_ecPublicKey, in, inlen) == 0) {
return OID_x9_62_ecPublicKey;
}
if (inlen >= sizeof(DER_x9_62_ecPublicKey)
&& memcmp(in, DER_x9_62_ecPublicKey, sizeof(DER_x9_62_ecPublicKey)) == 0) {
if (inlen == sizeof(DER_x9_62_ecPublicKey))
ret = OID_x9_62_ecPublicKey;
else ret = asn1_x9_62_curve_oid_from_octets(in, inlen);
} else if (inlen > sizeof(DER_sm)
&& memcmp(in, DER_sm, sizeof(DER_sm)) == 0) {
ret = asn1_sm_oid_from_octets(in, inlen);
} else if (inlen > sizeof(DER_secg_curve)
&& memcmp(in, DER_secg_curve, sizeof(DER_secg_curve)) == 0) {
ret = asn1_secg_curve_oid_from_octets(in, inlen);
} else if (inlen > sizeof(DER_x509)
&& memcmp(in, DER_x509, sizeof(DER_x509)) == 0) {
ret = asn1_x509_oid_from_octets(in, inlen);
} else {
/*
int i;
error_print("unknown der\n");
print_der(in, inlen);
printf("\n");
*/
return OID_undef;
}
if (ret < 0) {
error_print("invalid der\n");
}
return ret;
}
// 输出长度不固定,并且被多次重复调用,因此提供 **out 形式的参数
static void uint_to_base128(uint32_t a, uint8_t **out, size_t *outlen)
{
uint8_t buf[5];
int n = 0;
buf[n++] = a & 0x7f;
a >>= 7;
while (a) {
buf[n++] = 0x80 | (a & 0x7f);
a >>= 7;
}
while (n--) {
if (out)
*(*out)++ = buf[n];
(*outlen)++;
}
}
// 实际上我们在解析的时候是不知道具体在哪里结束的
// 解析是有可能出错的如果没有发现最后一个0开头的字节就出错了
// 还有值太大也会出错我们最多读取5个字节
// { 0x81, 0x82 }
// { 0x81, 0x82, 0x83, 0x84, 0x85, 0x06 }
static int uint_from_base128(uint32_t *a, const uint8_t **in, size_t *inlen)
{
uint8_t buf[5];
int n = 0;
int i;
for (;;) {
if ((*inlen)-- < 1 || n >= 5) {
return -1;
}
buf[n] = *(*in)++;
if ((buf[n++] & 0x80) == 0) {
break;
}
}
// 32 - 7*4 = 4, so the first byte should be like 1000bbbb
if (n == 5 && (buf[0] & 0x70)) {
return -1;
}
*a = 0;
for (i = 0; i < n; i++) {
*a = ((*a) << 7) | (buf[i] & 0x7f);
}
return 1;
}
int asn1_oid_nodes_to_octets(const uint32_t *nodes, size_t nodes_count, uint8_t *out, size_t *outlen)
{
if (nodes_count < 2 || nodes_count > 32) {
return -1;
}
if (out)
*out++ = (uint8_t)(nodes[0] * 40 + nodes[1]);
(*outlen) = 1;
nodes += 2;
nodes_count -= 2;
while (nodes_count--) {
uint_to_base128(*nodes++, &out, outlen);
}
return 1;
}
// 因为这个函数总是被asn1函数调用的因此给的输入数据长度是已知的
int asn1_oid_nodes_from_octets(uint32_t *nodes, size_t *nodes_count, const uint8_t *in, size_t inlen)
{
size_t count = 0;
const uint8_t *p = in;
size_t len = inlen;
if (!nodes || !nodes_count || !in || inlen <= 0) {
error_print();
return -1;
}
if (inlen < 1) {
error_print();
return -1;
}
// FIXME: 需要支持 nodes = NULL 吗?
if (nodes) {
*nodes++ = (*in) / 40;
*nodes++ = (*in) % 40;
}
in++;
inlen--;
count += 2;
while (inlen) {
uint32_t val;
if (count > 32) {
return -1;
}
if (uint_from_base128(&val, &in, &inlen) < 0) {
return -1;
}
if (nodes) {
*nodes++ = val;
}
count++;
}
*nodes_count = count;
return 1;
}
// 调用方应提供一个已知的 OID 名字,否则函数会返回错误,而非返回 OID_undef
int asn1_object_identifier_from_name(int *oid, const char *name)
{
if (!oid || !name) {
return -1;
}
if ((*oid = asn1_sm_oid_from_name(name)) != OID_undef)
return 1;
if ((*oid = asn1_x9_62_curve_oid_from_name(name)) != OID_undef)
return 1;
if ((*oid = asn1_secg_curve_oid_from_name(name)) != OID_undef)
return 1;
if ((*oid = asn1_x509_oid_from_name(name)) != OID_undef)
return 1;
return 1;
}
const char *asn1_object_identifier_name(int oid)
{
if (oid < 0) {
return NULL;
} else if (oid == OID_undef) {
return "undef";
} else if (oid <= OID_rsasign_with_sm3) {
return asn1_sm_oid_name(oid);
} else if (oid <= OID_x9_62_ecPublicKey) { // FIXME: 目前单独处理,后续应增加公钥类型 OID 集合
return "x9_62_ecPublicKey";
} else if (oid <= OID_prime256v1) {
return asn1_x9_62_curve_oid_name(oid);
} else if (oid <= OID_secp521r1) {
return asn1_secg_curve_oid_name(oid);
} else if (oid <= OID_at_role) {
return asn1_x509_oid_name(oid);
} else {
// FIXME: 还有后续的一些X.509 OID没有支持
return NULL;
}
}
const char *asn1_object_identifier_description(int oid)
{
if (oid < 0) {
return NULL;
} else if (oid == OID_undef) {
return "<undef>";
} else if (oid <= OID_rsasign_with_sm3) {
return asn1_sm_oid_description(oid);
} else if (oid <= OID_x9_62_ecPublicKey) { // FIXME: 目前单独处理,后续应增加公钥类型 OID 集合
return "x9_62_ecPublicKey";
} else if (oid <= OID_prime256v1) {
return asn1_x9_62_curve_oid_description(oid);
} else if (oid <= OID_secp521r1) {
return asn1_secg_curve_oid_description(oid);
} else if (oid <= OID_at_role) {
return asn1_x509_oid_description(oid);
}
// FIXME: 还有后续的一些X.509 OID没有支持
return NULL;
}
// 测试 oid_nodes 编解码是否正确
// FIXME: 还应该增加一些外部的测试用例
int test_asn1_oid_nodes(void)
{
int oid;
uint8_t octets[64];
uint8_t buf[64];
uint32_t nodes[32];
size_t octetslen, buflen, nodes_count;
for (oid = 1; oid <= OID_at_role; oid++) {
int i;
asn1_oid_to_octets(oid, octets, &octetslen);
asn1_oid_nodes_from_octets(nodes, &nodes_count, octets, octetslen);
asn1_oid_nodes_to_octets(nodes, nodes_count, buf, &buflen);
if (buflen != octetslen || memcmp(octets, buf, buflen) != 0) {
fprintf(stderr, "%s %d: oid = %d error\n", __FILE__, __LINE__, oid);
}
printf("%d : ", oid);
for (i = 0; i < nodes_count; i++) {
printf("%d ", (int)nodes[i]);
}
printf("\n");
}
return 1;
}
int test_asn1_oid(void)
{
uint8_t buf[1024];
uint8_t *p = buf;
size_t len =0;
int oid;
int i;
uint32_t nodes[32];
size_t nodes_count;
test_asn1_oid_nodes();
for (i = 1; i <= OID_at_role; i++) {
int j;
asn1_oid_to_octets(i, buf, &len);
oid = asn1_oid_from_octets(buf, len);
printf("%d %s %s ", oid, asn1_object_identifier_name(oid), asn1_object_identifier_description(oid));
asn1_oid_nodes_from_octets(nodes, &nodes_count, buf, len);
for (j = 0; j < nodes_count; j++) {
printf("%d.", nodes[j]);
}
printf("\n");
}
return 1;
}
int test_asn1_object_identifier_to_der(int oid)
{
uint8_t buf[64] = {0};
const uint8_t *cp = buf;
uint8_t *p = buf;
size_t len = 0, i;
uint32_t nodes[32] = {0};
size_t nodes_count;
int roid;
if (asn1_object_identifier_to_der(oid, NULL, 0, &p, &len) != 1) {
error_print();
return 0;
}
printf("%d : %s : ", oid, asn1_object_identifier_name(oid));
print_der(buf, len);
if (asn1_object_identifier_from_der(&roid, nodes, &nodes_count, &cp, &len) != 1) {
error_print();
return 0;
}
printf(" : ");
print_nodes(nodes, nodes_count);
printf("\n");
if (roid != oid) {
error_print("oid = %d, parsed oid = %d\n", oid, roid);
return -1;
}
if (len != 0) {
error_print();
return -1;
}
return 1;
}
int test_asn1_object_identifier(void)
{
uint8_t buf[2048];
const uint8_t *cp = buf;
uint8_t *p = buf;
size_t len = 0;
uint32_t nodes[32] = {0};
size_t nodes_count;
int oid;
int i;
// 分别测试每个oid分别编解码是否正确
for (oid = 1; oid <= OID_at_role; oid++) {
if (test_asn1_object_identifier_to_der(oid) < 0) {
error_print();
return -1;
}
}
// 将全部oid编码后再解码
for (oid = 1; oid <= OID_at_role; oid++) {
if (asn1_object_identifier_to_der(oid, NULL, 0, &p, &len) != 1) {
error_print();
return -1;
}
}
printf("%s %d: All OIDs encoded length = %zu bytes\n", __FILE__, __LINE__, len);
print_der(buf, len);
printf("\n");
while (len) {
int ret;
if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &cp, &len) <= 0) {
break;
}
printf("%d %s\n", oid, asn1_object_identifier_name(oid));
}
return 1;
}

174
src/pbkdf2.c Normal file
View File

@@ -0,0 +1,174 @@
/*
* 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.
*/
/*
PBKDF2 (P, S, c, dkLen)
Options: PRF underlying pseudorandom function (hLen
denotes the length in octets of the
pseudorandom function output)
Input: P password, an octet string
S salt, an octet string
c iteration count, a positive integer
dkLen intended length in octets of the derived
key, a positive integer, at most
(2^32 - 1) * hLen
Output: DK derived key, a dkLen-octet string
Steps:
1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
stop.
2. Let l be the number of hLen-octet blocks in the derived key,
rounding up, and let r be the number of octets in the last
block:
l = CEIL (dkLen / hLen) ,
r = dkLen - (l - 1) * hLen .
Here, CEIL (x) is the "ceiling" function, i.e. the smallest
integer greater than, or equal to, x.
3. For each block of the derived key apply the function F defined
below to the password P, the salt S, the iteration count c, and
the block index to compute the block:
T_1 = F (P, S, c, 1) ,
T_2 = F (P, S, c, 2) ,
...
T_l = F (P, S, c, l) ,
where the function F is defined as the exclusive-or sum of the
first c iterates of the underlying pseudorandom function PRF
applied to the password P and the concatenation of the salt S
and the block index i:
F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
where
U_1 = PRF (P, S || INT (i)) ,
U_2 = PRF (P, U_1) ,
...
U_c = PRF (P, U_{c-1}) .
Here, INT (i) is a four-octet encoding of the integer i, most
significant octet first.
4. Concatenate the blocks and extract the first dkLen octets to
produce a derived key DK:
DK = T_1 || T_2 || ... || T_l<0..r-1>
5. Output the derived key DK.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/asn1.h>
#include <gmssl/hmac.h>
#include <gmssl/digest.h>
#include <gmssl/error.h>
#include <gmssl/oid.h>
#include "endian.h"
#include "mem.h"
int pbkdf2_genkey(const DIGEST *digest,
const char *pass, size_t passlen,
const uint8_t *salt, size_t saltlen, unsigned int count,
size_t outlen, uint8_t *out)
{
HMAC_CTX ctx;
uint32_t iter = 1;
uint8_t iter_be[4];
uint8_t tmp_block[64];
uint8_t key_block[64];
size_t len;
hmac_init(&ctx, digest, (uint8_t *)pass, passlen);
while (outlen > 0) {
int i;
PUTU32(iter_be, iter);
iter++;
hmac_update(&ctx, salt, saltlen);
hmac_update(&ctx, iter_be, sizeof(iter_be));
hmac_finish(&ctx, tmp_block, &len);
hmac_reset(&ctx);
memcpy(key_block, tmp_block, len);
for (i = 1; i < count; i++) {
hmac_update(&ctx, tmp_block, len);
hmac_finish(&ctx, tmp_block, &len);
hmac_reset(&ctx);
memxor(key_block, tmp_block, len);
}
if (outlen < len) {
memcpy(out, key_block, outlen);
out += outlen;
outlen = 0;
} else {
memcpy(out, key_block, len);
out += len;
outlen -= len;
}
}
memset(&ctx, 0, sizeof(ctx));
memset(key_block, 0, sizeof(key_block));
memset(tmp_block, 0, sizeof(key_block));
return 1;
}

116
src/pem.c Normal file
View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2020 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/error.h>
int pem_write(FILE *fp, const char *name, const uint8_t *data, size_t datalen)
{
int ret = 0;
BASE64_CTX ctx;
uint8_t b64[datalen * 2];
int len;
base64_encode_init(&ctx);
base64_encode_update(&ctx, data, (int)datalen, b64, &len);
base64_encode_finish(&ctx, b64 + len, &len);
ret += fprintf(fp, "-----BEGIN %s-----\n", name);
ret += fprintf(fp, "%s", (char *)b64);
ret += fprintf(fp, "-----END %s-----\n", name);
return ret;
}
int pem_read(FILE *fp, const char *name, uint8_t *data, size_t *datalen)
{
char line[80];
char begin_line[80];
char end_line[80];
int len;
BASE64_CTX ctx;
snprintf(begin_line, sizeof(begin_line), "-----BEGIN %s-----\n", name);
snprintf(end_line, sizeof(end_line), "-----END %s-----\n", name);
if (!fgets(line, sizeof(line), fp)) {
//FIXME: feof 判断是不是文件结束了呢
return 0;
}
if (strcmp(line, begin_line) != 0) {
// FIXME: 这里是不是应该容忍一些错误呢?
error_print();
return -1;
}
*datalen = 0;
base64_decode_init(&ctx);
for (;;) {
if (!fgets(line, sizeof(line), fp)) {
error_print();
return -1;
}
if (strcmp(line, end_line) == 0) {
break;
}
base64_decode_update(&ctx, (uint8_t *)line, strlen(line), data, &len);
data += len;
*datalen += len;
}
base64_decode_finish(&ctx, data, &len);
*datalen += len;
return 1;
}

588
src/pkcs8.c Normal file
View File

@@ -0,0 +1,588 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/sm2.h>
#include <gmssl/pem.h>
#include <gmssl/oid.h>
#include <gmssl/asn1.h>
#include <gmssl/error.h>
#include <gmssl/pbkdf2.h>
#include <gmssl/digest.h>
#include <gmssl/sm4.h>
#include <gmssl/rand.h>
/*
PBKDF2-params ::= SEQUENCE {
salt OCTET STRING,
iterationCount INTEGER (1..MAX),
keyLength INTEGER (1..MAX) OPTIONAL,
prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
}
这里prf的OID一般来说其他地方是用不到的并且除了sm3-hmac之外我们都不支持
*/
int pbkdf2_params_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int keylen,
int prf,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
size_t prflen = 0;
switch (prf) {
case OID_hmac_sm3:
break;
/*
case OID_hmacWithSHA1:
case OID_hmacWithSHA224:
case OID_hmacWithSHA256:
case OID_hmacWithSHA384:
case OID_hmacWithSHA512:
case OID_hmacWithSHA512_224:
case OID_hmacWithSHA512_256:
error_print();
return -1;
*/
default:
error_print();
return -1;
}
if (asn1_octet_string_to_der(salt, saltlen, NULL, &len) != 1
|| asn1_int_to_der(iter, NULL, &len) != 1
|| asn1_int_to_der(keylen, NULL, &len) < 0
|| asn1_object_identifier_to_der(prf, NULL, 0, NULL, &prflen) != 1
|| asn1_null_to_der(NULL, &prflen) != 1
|| asn1_sequence_to_der(NULL, prflen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_octet_string_to_der(salt, saltlen, out, outlen) != 1
|| asn1_int_to_der(iter, out, outlen) != 1
|| asn1_int_to_der(keylen, out, outlen) < 0
|| asn1_sequence_header_to_der(prflen, out, outlen) != 1
|| asn1_object_identifier_to_der(prf, NULL, 0, out, outlen) != 1
|| asn1_null_to_der(out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int pbkdf2_params_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *keylen,
int *prf,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
const uint8_t *algo;
size_t datalen;
size_t algolen;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_octet_string_from_der(salt, saltlen, &data, &datalen) != 1
|| asn1_int_from_der(iter, &data, &datalen) != 1
|| asn1_int_from_der(keylen, &data, &datalen) < 0
|| asn1_sequence_from_der(&algo, &algolen, &data, &datalen) < 0
|| datalen > 0) {
error_print();
return -1;
}
if (*saltlen < 1) {
error_print();
return -1;
}
if (*iter < 1) {
error_print();
return -1;
}
if (algo) {
uint32_t nodes[32];
size_t nodes_count;
if (asn1_object_identifier_from_der(prf, nodes, &nodes_count, &algo, &algolen) != 1
|| asn1_null_from_der(&algo, &algolen) != 1
|| algolen > 0) {
error_print();
return -1;
}
if (*prf != OID_hmac_sm3) {
error_print();
return -1;
}
} else {
//*prf = OID_hmacWithSHA1;
error_print();
return -1;
}
return 1;
}
int pbkdf2_algor_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int keylen,
int prf,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
uint32_t pbkdf2[] = { 1, 2, 840, 113549, 1, 5, 12 };
size_t pbkdf2_count = sizeof(pbkdf2)/sizeof(pbkdf2[0]);
if (asn1_object_identifier_to_der(OID_undef, pbkdf2, pbkdf2_count, NULL, &len) != 1
|| pbkdf2_params_to_der(salt, saltlen, iter, keylen, prf, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(OID_undef, pbkdf2, pbkdf2_count, out, outlen) != 1
|| pbkdf2_params_to_der(salt, saltlen, iter, keylen, prf, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int pbkdf2_algor_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *keylen,
int *prf,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
uint32_t pbkdf2[] = { 1, 2, 840, 113549, 1, 5, 12 };
size_t pbkdf2_count = sizeof(pbkdf2)/sizeof(pbkdf2[0]);
int oid;
uint32_t nodes[32];
size_t nodes_count;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1
|| pbkdf2_params_from_der(salt, saltlen, iter, keylen, prf, &data, &datalen) != 1
|| datalen > 0) {
error_print();
return -1;
}
if (oid != OID_undef || nodes_count != pbkdf2_count
|| memcmp(nodes, pbkdf2, sizeof(pbkdf2)) != 0) {
error_print();
return -1;
}
// FIXME: 检查keylen
return 1;
}
static uint32_t sm4_cbc_nodes[] = { 1, 2, 156, 10197, 1, 104, 2 };
static size_t sm4_cbc_nodes_count = sizeof(sm4_cbc_nodes)/sizeof(sm4_cbc_nodes[0]);
// 这个应该提取到外面和digest_algor, encryption_algor, sign_algor 之类的放到一起
int pbes2_enc_algor_to_der(int cipher, const uint8_t *iv, size_t ivlen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (cipher != OID_sm4_cbc || ivlen != 16) {
error_print();
return -1;
}
if (asn1_object_identifier_to_der(OID_undef, sm4_cbc_nodes, sm4_cbc_nodes_count, NULL, &len) != 1
|| asn1_octet_string_to_der(iv, ivlen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(OID_undef, sm4_cbc_nodes, sm4_cbc_nodes_count, out, outlen) != 1
|| asn1_octet_string_to_der(iv, ivlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int pbes2_enc_algor_from_der(int *cipher, const uint8_t **iv, size_t *ivlen, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
uint32_t nodes[32];
size_t nodes_count;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_object_identifier_from_der(cipher, nodes, &nodes_count, &data, &datalen) != 1
|| asn1_octet_string_from_der(iv, ivlen, &data, &datalen) != 1
|| datalen > 0) {
error_print();
return -1;
}
if (*cipher == OID_undef) {
if (nodes_count == sm4_cbc_nodes_count
&& memcmp(nodes, sm4_cbc_nodes, sizeof(sm4_cbc_nodes)) == 0) {
*cipher = OID_sm4_cbc;
} else {
size_t i;
error_print("unknown cipher oid :");
for (i = 0; i < nodes_count; i++) {
fprintf(stderr, " %d", nodes[i]);
}
fprintf(stderr, "\n");
return -1;
}
}
// FIXME: 检查ivlen
return 1;
}
int pbes2_params_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int prf,
int cipher,
const uint8_t *iv, size_t ivlen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
int keylen = -1;
if (pbkdf2_algor_to_der(salt, saltlen, iter, keylen, prf, NULL, &len) != 1
|| pbes2_enc_algor_to_der(cipher, iv, ivlen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| pbkdf2_algor_to_der(salt, saltlen, iter, keylen, prf, out, outlen) != 1
|| pbes2_enc_algor_to_der(cipher, iv, ivlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int pbes2_params_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *prf,
int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
int keylen;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (pbkdf2_algor_from_der(salt, saltlen, iter, &keylen, prf, &data, &datalen) != 1
|| pbes2_enc_algor_from_der(cipher, iv, ivlen, &data, &datalen) != 1
|| datalen > 0) {
error_print();
return -1;
}
if (keylen >= 0 && keylen != 16) {
error_print("keylen = %d\n", keylen);
return -1;
}
return 1;
}
int pbes2_algor_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int prf,
int cipher,
const uint8_t *iv, size_t ivlen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
uint32_t pbes2[] = { 1, 2, 840, 113549, 1, 5, 13 };
size_t pbes2_count = sizeof(pbes2)/sizeof(pbes2[0]);
if (asn1_object_identifier_to_der(OID_undef, pbes2, pbes2_count, NULL, &len) != 1
|| pbes2_params_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(OID_undef, pbes2, pbes2_count, out, outlen) != 1
|| pbes2_params_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int pbes2_algor_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *prf,
int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
uint32_t pbes2[] = { 1, 2, 840, 113549, 1, 5, 13 };
size_t pbes2_count = sizeof(pbes2)/sizeof(pbes2[0]);
int oid;
uint32_t nodes[32];
size_t nodes_count;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1
|| pbes2_params_from_der(salt, saltlen, iter, prf, cipher, iv, ivlen, &data, &datalen) != 1
|| datalen > 0) {
error_print();
return -1;
}
if (oid != OID_undef) {
error_print();
return -1;
}
if (nodes_count != pbes2_count && memcmp(nodes, pbes2, sizeof(pbes2)) != 0) {
error_print();
return -1;
}
return 1;
}
int pkcs8_enced_private_key_info_to_der(
const uint8_t *salt, size_t saltlen,
int iter,
int prf,
int cipher,
const uint8_t *iv, size_t ivlen,
const uint8_t *enced, size_t encedlen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
pbes2_algor_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, NULL, &len);
asn1_octet_string_to_der(enced, encedlen, NULL, &len);
asn1_sequence_header_to_der(len, out, outlen);
pbes2_algor_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, out, outlen);
asn1_octet_string_to_der(enced, encedlen, out, outlen);
return 1;
}
int pkcs8_enced_private_key_info_from_der(
const uint8_t **salt, size_t *saltlen,
int *iter,
int *prf,
int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **enced, size_t *encedlen,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
const uint8_t *algid;
size_t algidlen;
uint32_t nodes[32];
size_t nodes_count;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (pbes2_algor_from_der(salt, saltlen, iter, prf, cipher, iv, ivlen, &data, &datalen) != 1
|| asn1_octet_string_from_der(enced, encedlen, &data, &datalen) != 1
|| datalen > 0) {
error_print();
return -1;
}
return 1;
}
// output PKCS #8 EncryptedPrivateKeyInfo
int sm2_enced_private_key_info_to_der(const SM2_KEY *sm2, const char *pass, uint8_t **out, size_t *outlen)
{
SM4_KEY sm4_key;
uint8_t salt[16];
int iter = 65536;
int prf = OID_hmac_sm3;
uint8_t key[16];
int cipher = OID_sm4_cbc;
uint8_t iv[16];
uint8_t info[256];
uint8_t *pinfo = info;
size_t infolen = 0;
uint8_t enced[512];
size_t encedlen;
if (rand_bytes(salt, sizeof(salt)) != 1
|| rand_bytes(iv, sizeof(iv)) != 1) {
error_print();
return -1;
}
// SM2_KEY to PKCS8 PrivateKeyInfo
if (sm2_private_key_info_to_der(sm2, &pinfo, &infolen) != 1) {
error_print();
return -1;
}
// password to encryption key
if (pbkdf2_genkey(DIGEST_sm3(), pass, strlen(pass), salt, sizeof(salt), iter, sizeof(key), key) != 1) {
error_print();
return -1;
}
// encrypt PrivateKeyInfo
sm4_set_encrypt_key(&sm4_key, key);
if (sm4_cbc_padding_encrypt(&sm4_key, iv, info, infolen, enced, &encedlen) != 1) {
error_print();
return -1;
}
// encode EncryptedPrivateKeyInfo
if (pkcs8_enced_private_key_info_to_der(salt, sizeof(salt), iter, prf,
cipher, iv, sizeof(iv), enced, encedlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int sm2_enced_private_key_info_from_der(SM2_KEY *sm2, const uint8_t **attrs, size_t *attrslen, const char *pass, const uint8_t **in, size_t *inlen)
{
SM4_KEY sm4_key;
const uint8_t *salt;
size_t saltlen;
int iter;
int prf;
int cipher;
const uint8_t *iv;
size_t ivlen;
const uint8_t *enced;
size_t encedlen;
uint8_t key[16];
uint8_t info[256];
const uint8_t *pinfo = info;
size_t infolen;
if (pkcs8_enced_private_key_info_from_der(&salt, &saltlen, &iter, &prf,
&cipher, &iv, &ivlen, &enced, &encedlen, in, inlen) != 1) {
error_print();
return -1;
}
if (pbkdf2_genkey(DIGEST_sm3(), pass, strlen(pass), salt, saltlen, iter, sizeof(key), key) != 1) {
error_print();
return -1;
}
sm4_set_decrypt_key(&sm4_key, key);
if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced, encedlen, info, &infolen) != 1) {
error_print();
return -1;
}
if (sm2_private_key_info_from_der(sm2, attrs, attrslen, &pinfo, &infolen) != 1
|| infolen > 0) {
error_print();
return -1;
}
return 1;
}
int sm2_enced_private_key_info_to_pem(const SM2_KEY *key, const char *pass, FILE *fp)
{
uint8_t buf[1024];
uint8_t *p = buf;
size_t len = 0;
if (sm2_enced_private_key_info_to_der(key, pass, &p, &len) != 1) {
error_print();
return -1;
}
if (pem_write(fp, "ENCRYPTED PRIVATE KEY", buf, len) <= 0) {
error_print();
return -1;
}
return 1;
}
// TODO: return attributes
int sm2_enced_private_key_info_from_pem(SM2_KEY *key, const char *pass, FILE *fp)
{
uint8_t buf[512];
const uint8_t *cp = buf;
size_t len;
const uint8_t *attrs;
size_t attrslen;
if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len) != 1) {
error_print();
return -1;
}
if (sm2_enced_private_key_info_from_der(key, &attrs, &attrslen, pass, &cp, &len) != 1
|| len > 0) {
error_print();
return -1;
}
return 1;
}

65
src/rand.c Normal file
View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2014 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
int rand_bytes(uint8_t *buf, size_t len)
{
FILE *fp;
if (!(fp = fopen("/dev/urandom", "rb"))) {
error_print();
return -1;
}
fread(buf, 1, len, fp);
return 1;
}

117
src/rc4.c Normal file
View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/rc4.h>
void rc4_set_key(RC4_STATE *state, const unsigned char *key, size_t keylen)
{
int i, j;
unsigned char *s = state->d;
unsigned char k[256];
unsigned char temp;
/* expand key */
for (i = 0; i < keylen; i++) {
k[i] = key[i];
}
for (i = keylen; i < 256; i++) {
k[i] = key[i % keylen];
}
/* init state */
for (i = 0; i < 256; i++) {
s[i] = i;
}
/* shuffle state with key */
j = 0;
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
/* swap(s[i], s[j]) */
temp = s[j];
s[j] = s[i];
s[i] = temp;
}
/* clean expanded temp key */
memset(k, 0, sizeof(k));
}
void rc4_generate_keystream(RC4_STATE *state, size_t outlen, unsigned char *out)
{
int i = 0, j = 0;
unsigned char *s = state->d;
int oi;
int temp;
while (outlen > 0) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
/* swap(s[i], s[j]) */
temp = s[j];
s[j] = s[i];
s[i] = temp;
oi = (s[i] + s[j]) % 256;
*out++ = s[oi];
outlen--;
}
}
unsigned char rc4_generate_keybyte(RC4_STATE *state)
{
unsigned char out[1];
rc4_generate_keystream(state, 1, out);
return out[0];
}

68
src/rotate.h Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* 应该看看Intel Intrisics中是否支持这个指令以及VS是否也支持这个指令
* 这样我们就不需要内联汇编了
*/
/*
* Engage compiler specific rotate intrinsic function if available.
*/
#undef ROL32
#ifndef PEDANTIC
# if defined(_MSC_VER)
# define ROL32(a,n) _lrotl(a,n)
# elif defined(__ICC)
# define ROL32(a,n) _rotl(a,n)
# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
/*
* Some GNU C inline assembler templates. Note that these are
* rotates by *constant* number of bits! But that's exactly
* what we need here...
* <appro@fy.chalmers.se>
*/
# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
# define ROL32(a,n) ({ register unsigned int ret; \
asm ( \
"roll %1,%0" \
: "=r"(ret) \
: "I"(n), "0"((unsigned int)(a)) \
: "cc"); \
ret; \
})
# elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
# define ROL32(a,n) ({ register unsigned int ret; \
asm ( \
"rlwinm %0,%1,%2,0,31" \
: "=r"(ret) \
: "r"(a), "I"(n)); \
ret; \
})
# elif defined(__s390x__)
# define ROL32(a,n) ({ register unsigned int ret; \
asm ("rll %0,%1,%2" \
: "=r"(ret) \
: "r"(a), "I"(n)); \
ret; \
})
# endif
# endif
#endif /* PEDANTIC */
#ifndef ROL32
# define ROL32(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#endif
#define ROR32(a,n) ROL32((a),32-(n))
#define ROL64(a,n) (((a)<<(n))|((a)>>(64-(n))))
#define ROR64(a,n) ROL64(a,64-n)

219
src/sha1.c Executable file
View File

@@ -0,0 +1,219 @@
/* ====================================================================
* Copyright (c) 2014 - 2017 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 <string.h>
#include <gmssl/sha1.h>
#include "bswap.h"
#include "rotate.h"
static void sha1_compress_blocks(uint32_t dgst[5],
const unsigned char *data, size_t blocks);
void sha1_init(SHA1_CTX *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void sha1_update(SHA1_CTX *ctx, const unsigned char *data, size_t datalen)
{
size_t blocks;
if (ctx->num) {
unsigned int left = SHA1_BLOCK_SIZE - ctx->num;
if (datalen < left) {
memcpy(ctx->block + ctx->num, data, datalen);
ctx->num += datalen;
return;
} else {
memcpy(ctx->block + ctx->num, data, left);
sha1_compress_blocks(ctx->state, ctx->block, 1);
ctx->nblocks++;
data += left;
datalen -= left;
}
}
blocks = datalen / SHA1_BLOCK_SIZE;
sha1_compress_blocks(ctx->state, data, blocks);
ctx->nblocks += blocks;
data += SHA1_BLOCK_SIZE * blocks;
datalen -= SHA1_BLOCK_SIZE * blocks;
ctx->num = datalen;
if (datalen) {
memcpy(ctx->block, data, datalen);
}
}
void sha1_finish(SHA1_CTX *ctx, unsigned char *dgst)
{
int i;
ctx->block[ctx->num] = 0x80;
if (ctx->num + 9 <= SHA1_BLOCK_SIZE) {
memset(ctx->block + ctx->num + 1, 0, SHA1_BLOCK_SIZE - ctx->num - 9);
} else {
memset(ctx->block + ctx->num + 1, 0, SHA1_BLOCK_SIZE - ctx->num - 1);
sha1_compress_blocks(ctx->state, ctx->block, 1);
memset(ctx->block, 0, SHA1_BLOCK_SIZE - 8);
}
PUTU32(ctx->block + 56, ctx->nblocks >> 23);
PUTU32(ctx->block + 60, (ctx->nblocks << 9) + (ctx->num << 3));
sha1_compress_blocks(ctx->state, ctx->block, 1);
for (i = 0; i < 5; i++) {
PUTU32(dgst + i*4, ctx->state[i]);
}
}
#define F0(B, C, D) (((B) & (C)) | ((~(B)) & (D)))
#define F1(B, C, D) ((B) ^ (C) ^ (D))
#define F2(B, C, D) (((B) & (C)) | ((B) & (D)) | ((C) & (D)))
#define F3(B, C, D) ((B) ^ (C) ^ (D))
#define K0 0x5A827999
#define K1 0x6ED9EBA1
#define K2 0x8F1BBCDC
#define K3 0xCA62C1D6
static void sha1_compress_blocks(uint32_t state[5],
const unsigned char *data, size_t blocks)
{
uint32_t A;
uint32_t B;
uint32_t C;
uint32_t D;
uint32_t E;
uint32_t T;
uint32_t W[80];
int i;
while (blocks--) {
A = state[0];
B = state[1];
C = state[2];
D = state[3];
E = state[4];
for (i = 0; i < 16; i++) {
W[i] = GETU32(data);
data += 4;
}
for (; i < 80; i++) {
W[i] = ROL32(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
}
/* see https://en.wikipedia.org/wiki/SHA-1#/media/File:SHA-1.svg */
for (i = 0; i < 20; i++) {
T = E + F0(B, C, D) + ROL32(A, 5) + W[i] + K0;
E = D;
D = C;
C = ROL32(B, 30);
B = A;
A = T;
}
for (; i < 40; i++) {
T = E + F1(B, C, D) + ROL32(A, 5) + W[i] + K1;
E = D;
D = C;
C = ROL32(B, 30);
B = A;
A = T;
}
for (; i < 60; i++) {
T = E + F2(B, C, D) + ROL32(A, 5) + W[i] + K2;
E = D;
D = C;
C = ROL32(B, 30);
B = A;
A = T;
}
for (; i < 80; i++) {
T = E + F3(B, C, D) + ROL32(A, 5) + W[i] + K3;
E = D;
D = C;
C = ROL32(B, 30);
B = A;
A = T;
}
state[0] += A;
state[1] += B;
state[2] += C;
state[3] += D;
state[4] += E;
}
}
void sha1_compress(uint32_t state[5], const unsigned char block[64])
{
return sha1_compress_blocks(state, block, 1);
}
void sha1_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA1_DIGEST_LENGTH])
{
SHA1_CTX ctx;
sha1_init(&ctx);
sha1_update(&ctx, data, datalen);
sha1_finish(&ctx, dgst);
memset(&ctx, 0, sizeof(SHA1_CTX));
}

265
src/sha256.c Executable file
View File

@@ -0,0 +1,265 @@
/* ====================================================================
* Copyright (c) 2014 - 2017 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 PARTICAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sha2.h>
#include "bswap.h"
#include "rotate.h"
static void sha256_compress_blocks(uint32_t state[8],
const unsigned char *data, size_t blocks);
void sha256_init(SHA256_CTX *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
void sha256_update(SHA256_CTX *ctx, const unsigned char *data, size_t datalen)
{
size_t blocks;
if (ctx->num) {
unsigned int left = SHA256_BLOCK_SIZE - ctx->num;
if (datalen < left) {
memcpy(ctx->block + ctx->num, data, datalen);
ctx->num += datalen;
return;
} else {
memcpy(ctx->block + ctx->num, data, left);
sha256_compress_blocks(ctx->state, ctx->block, 1);
ctx->nblocks++;
data += left;
datalen -= left;
}
}
blocks = datalen / SHA256_BLOCK_SIZE;
sha256_compress_blocks(ctx->state, data, blocks);
ctx->nblocks += blocks;
data += SHA256_BLOCK_SIZE * blocks;
datalen -= SHA256_BLOCK_SIZE * blocks;
ctx->num = datalen;
if (datalen) {
memcpy(ctx->block, data, datalen);
}
}
void sha256_finish(SHA256_CTX *ctx, unsigned char dgst[SHA256_DIGEST_SIZE])
{
int i;
ctx->block[ctx->num] = 0x80;
if (ctx->num + 9 <= SHA256_BLOCK_SIZE) {
memset(ctx->block + ctx->num + 1, 0, SHA256_BLOCK_SIZE - ctx->num - 9);
} else {
memset(ctx->block + ctx->num + 1, 0, SHA256_BLOCK_SIZE - ctx->num - 1);
sha256_compress_blocks(ctx->state, ctx->block, 1);
memset(ctx->block, 0, SHA256_BLOCK_SIZE - 8);
}
PUTU32(ctx->block + 56, ctx->nblocks >> 23);
PUTU32(ctx->block + 60, (ctx->nblocks << 9) + (ctx->num << 3));
sha256_compress_blocks(ctx->state, ctx->block, 1);
for (i = 0; i < 8; i++) {
PUTU32(dgst, ctx->state[i]);
dgst += sizeof(uint32_t);
}
memset(ctx, 0, sizeof(SHA256_CTX));
}
#define Ch(X, Y, Z) (((X) & (Y)) ^ ((~(X)) & (Z)))
#define Maj(X, Y, Z) (((X) & (Y)) ^ ((X) & (Z)) ^ ((Y) & (Z)))
#define Sigma0(X) (ROR32((X), 2) ^ ROR32((X), 13) ^ ROR32((X), 22))
#define Sigma1(X) (ROR32((X), 6) ^ ROR32((X), 11) ^ ROR32((X), 25))
#define sigma0(X) (ROR32((X), 7) ^ ROR32((X), 18) ^ ((X) >> 3))
#define sigma1(X) (ROR32((X), 17) ^ ROR32((X), 19) ^ ((X) >> 10))
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
};
static void sha256_compress_blocks(uint32_t state[8],
const unsigned char *data, size_t blocks)
{
uint32_t A;
uint32_t B;
uint32_t C;
uint32_t D;
uint32_t E;
uint32_t F;
uint32_t G;
uint32_t H;
uint32_t W[64];
uint32_t T1, T2;
int i;
while (blocks--) {
A = state[0];
B = state[1];
C = state[2];
D = state[3];
E = state[4];
F = state[5];
G = state[6];
H = state[7];
for (i = 0; i < 16; i++) {
W[i] = GETU32(data);
data += 4;
}
for (; i < 64; i++) {
W[i] = sigma1(W[i-2]) + W[i-7] + sigma0(W[i-15]) + W[i-16];
}
for (i = 0; i < 64; i++) {
T1 = H + Sigma1(E) + Ch(E, F, G) + K[i] + W[i];
T2 = Sigma0(A) + Maj(A, B, C);
H = G;
G = F;
F = E;
E = D + T1;
D = C;
C = B;
B = A;
A = T1 + T2;
}
state[0] += A;
state[1] += B;
state[2] += C;
state[3] += D;
state[4] += E;
state[5] += F;
state[6] += G;
state[7] += H;
}
}
void sha256_compress(uint32_t state[8], const unsigned char block[64])
{
sha256_compress_blocks(state, block, 1);
}
void sha256_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA256_DIGEST_SIZE])
{
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx, data, datalen);
sha256_finish(&ctx, dgst);
}
void sha224_init(SHA224_CTX *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->state[0] = 0xc1059ed8;
ctx->state[1] = 0x367cd507;
ctx->state[2] = 0x3070dd17;
ctx->state[3] = 0xf70e5939;
ctx->state[4] = 0xffc00b31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64f98fa7;
ctx->state[7] = 0xbefa4fa4;
}
void sha224_update(SHA224_CTX *ctx, const unsigned char *data, size_t datalen)
{
sha256_update((SHA256_CTX *)ctx, data, datalen);
}
void sha224_finish(SHA224_CTX *ctx, unsigned char dgst[SHA224_DIGEST_SIZE])
{
unsigned char buf[SHA256_DIGEST_SIZE];
sha256_finish((SHA256_CTX *)ctx, buf);
memcpy(dgst, buf, SHA224_DIGEST_SIZE);
memset(buf, 0, sizeof(buf));
}
void sha224_compress(uint32_t state[8], const unsigned char block[64])
{
sha256_compress_blocks(state, block, 1);
}
void sha224_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA224_DIGEST_SIZE])
{
SHA224_CTX ctx;
sha224_init(&ctx);
sha224_update(&ctx, data, datalen);
sha224_finish(&ctx, dgst);
}

271
src/sha512.c Executable file
View File

@@ -0,0 +1,271 @@
/* ====================================================================
* Copyright (c) 2014 - 2017 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 PARTICAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sha2.h>
#include "bswap.h"
#include "rotate.h"
static void sha512_compress_blocks(uint64_t state[8],
const unsigned char *data, size_t blocks);
void sha512_init(SHA512_CTX *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->state[0] = 0x6a09e667f3bcc908;
ctx->state[1] = 0xbb67ae8584caa73b;
ctx->state[2] = 0x3c6ef372fe94f82b;
ctx->state[3] = 0xa54ff53a5f1d36f1;
ctx->state[4] = 0x510e527fade682d1;
ctx->state[5] = 0x9b05688c2b3e6c1f;
ctx->state[6] = 0x1f83d9abfb41bd6b;
ctx->state[7] = 0x5be0cd19137e2179;
}
void sha512_update(SHA512_CTX *ctx, const unsigned char *data, size_t datalen)
{
size_t blocks;
if (ctx->num) {
unsigned int left = SHA512_BLOCK_SIZE - ctx->num;
if (datalen < left) {
memcpy(ctx->block + ctx->num, data, datalen);
ctx->num += datalen;
return;
} else {
memcpy(ctx->block + ctx->num, data, left);
sha512_compress_blocks(ctx->state, ctx->block, 1);
ctx->nblocks++;
data += left;
datalen -= left;
}
}
blocks = datalen / SHA512_BLOCK_SIZE;
sha512_compress_blocks(ctx->state, data, blocks);
ctx->nblocks += blocks;
data += SHA512_BLOCK_SIZE * blocks;
datalen -= SHA512_BLOCK_SIZE * blocks;
ctx->num = datalen;
if (datalen) {
memcpy(ctx->block, data, datalen);
}
}
void sha512_finish(SHA512_CTX *ctx, unsigned char dgst[SHA512_DIGEST_SIZE])
{
int i;
ctx->block[ctx->num] = 0x80;
if (ctx->num + 17 <= SHA512_BLOCK_SIZE) {
memset(ctx->block + ctx->num + 1, 0, SHA512_BLOCK_SIZE - ctx->num - 17);
} else {
memset(ctx->block + ctx->num + 1, 0, SHA512_BLOCK_SIZE - ctx->num - 1);
sha512_compress_blocks(ctx->state, ctx->block, 1);
memset(ctx->block, 0, SHA512_BLOCK_SIZE - 16);
}
PUTU64(ctx->block + 112, ctx->nblocks >> 54);
PUTU64(ctx->block + 120, (ctx->nblocks << 10) + (ctx->num << 3));
sha512_compress_blocks(ctx->state, ctx->block, 1);
for (i = 0; i < 8; i++) {
PUTU64(dgst, ctx->state[i]);
dgst += sizeof(uint64_t);
}
memset(ctx, 0, sizeof(SHA512_CTX));
}
#define Ch(X, Y, Z) (((X) & (Y)) ^ ((~(X)) & (Z)))
#define Maj(X, Y, Z) (((X) & (Y)) ^ ((X) & (Z)) ^ ((Y) & (Z)))
#define Sigma0(X) (ROR64((X), 28) ^ ROR64((X), 34) ^ ROR64((X), 39))
#define Sigma1(X) (ROR64((X), 14) ^ ROR64((X), 18) ^ ROR64((X), 41))
#define sigma0(X) (ROR64((X), 1) ^ ROR64((X), 8) ^ ((X) >> 7))
#define sigma1(X) (ROR64((X), 19) ^ ROR64((X), 61) ^ ((X) >> 6))
static const uint64_t K[80] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
};
static void sha512_compress_blocks(uint64_t state[8],
const unsigned char *data, size_t blocks)
{
uint64_t A;
uint64_t B;
uint64_t C;
uint64_t D;
uint64_t E;
uint64_t F;
uint64_t G;
uint64_t H;
uint64_t W[80];
uint64_t T1, T2;
int i;
while (blocks--) {
A = state[0];
B = state[1];
C = state[2];
D = state[3];
E = state[4];
F = state[5];
G = state[6];
H = state[7];
for (i = 0; i < 16; i++) {
W[i] = GETU64(data);
data += sizeof(uint64_t);
}
for (; i < 80; i++) {
W[i] = sigma1(W[i-2]) + W[i-7] + sigma0(W[i-15]) + W[i-16];
}
for (i = 0; i < 80; i++) {
T1 = H + Sigma1(E) + Ch(E, F, G) + K[i] + W[i];
T2 = Sigma0(A) + Maj(A, B, C);
H = G;
G = F;
F = E;
E = D + T1;
D = C;
C = B;
B = A;
A = T1 + T2;
}
state[0] += A;
state[1] += B;
state[2] += C;
state[3] += D;
state[4] += E;
state[5] += F;
state[6] += G;
state[7] += H;
}
}
void sha512_compress(uint64_t state[8], const unsigned char block[64])
{
sha512_compress_blocks(state, block, 1);
}
void sha512_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA512_DIGEST_SIZE])
{
SHA512_CTX ctx;
sha512_init(&ctx);
sha512_update(&ctx, data, datalen);
sha512_finish(&ctx, dgst);
}
void sha384_init(SHA384_CTX *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->state[0] = 0xcbbb9d5dc1059ed8;
ctx->state[1] = 0x629a292a367cd507;
ctx->state[2] = 0x9159015a3070dd17;
ctx->state[3] = 0x152fecd8f70e5939;
ctx->state[4] = 0x67332667ffc00b31;
ctx->state[5] = 0x8eb44a8768581511;
ctx->state[6] = 0xdb0c2e0d64f98fa7;
ctx->state[7] = 0x47b5481dbefa4fa4;
}
void sha384_update(SHA384_CTX *ctx, const unsigned char *data, size_t datalen)
{
sha512_update((SHA512_CTX *)ctx, data, datalen);
}
void sha384_finish(SHA384_CTX *ctx, unsigned char dgst[SHA384_DIGEST_SIZE])
{
unsigned char buf[SHA512_DIGEST_SIZE];
sha512_finish((SHA512_CTX *)ctx, buf);
memcpy(dgst, buf, SHA384_DIGEST_SIZE);
memset(buf, 0, sizeof(buf));
}
void sha384_compress(uint64_t state[8], const unsigned char block[64])
{
sha512_compress_blocks(state, block, 1);
}
void sha384_digest(const unsigned char *data, size_t datalen,
unsigned char dgst[SHA384_DIGEST_SIZE])
{
SHA384_CTX ctx;
sha384_init(&ctx);
sha384_update(&ctx, data, datalen);
sha384_finish(&ctx, dgst);
}

1665
src/sm2_algo.c Normal file

File diff suppressed because it is too large Load Diff

581
src/sm2_asn1.c Normal file
View File

@@ -0,0 +1,581 @@
/*
* 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 <string.h>
#include <gmssl/sm2.h>
#include <gmssl/oid.h>
#include <gmssl/asn1.h>
#include <gmssl/pem.h>
#include <gmssl/error.h>
void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33])
{
*out++ = (P->y[31] & 0x01) ? 0x03 : 0x02;
memcpy(out, P->x, 32);
}
void sm2_point_to_uncompressed_octets(const SM2_POINT *P, uint8_t out[65])
{
*out++ = 0x04;
memcpy(out, P, 64);
}
int sm2_point_from_octets(SM2_POINT *P, const uint8_t *in, size_t inlen)
{
if ((*in == 0x02 || *in == 0x03) && inlen == 33) {
return sm2_point_from_x(P, in + 1, *in);
} else if (*in == 0x04 && inlen == 65) {
return sm2_point_from_xy(P, in + 1, in + 33);
} else {
error_print();
return -1;
}
}
int sm2_point_to_der(const SM2_POINT *a, uint8_t **out, size_t *outlen)
{
uint8_t buf[65];
sm2_point_to_uncompressed_octets(a, buf);
asn1_octet_string_to_der(buf, sizeof(buf), out, outlen);
return 1;
}
int sm2_point_from_der(SM2_POINT *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
error_print("inlen = %zu\n", *inlen);
if ((ret = asn1_octet_string_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
else error_print();
return ret;
}
if (sm2_point_from_octets(a, data, datalen) != 1) {
error_print();
return -1;
}
error_print("inlen = %zu\n", *inlen);
return 1;
}
int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *outlen)
{
size_t len = 0;
asn1_integer_to_der(sig->r, 32, NULL, &len);
asn1_integer_to_der(sig->s, 32, NULL, &len);
asn1_sequence_header_to_der(len, out, outlen);
asn1_integer_to_der(sig->r, 32, out, outlen);
asn1_integer_to_der(sig->s, 32, out, outlen);
return 1;
}
int sm2_signature_from_der(SM2_SIGNATURE *sig, const uint8_t **in, size_t *inlen)
{
const uint8_t *data, *r, *s;
size_t datalen, rlen, slen;
if (asn1_sequence_from_der(&data, &datalen, in, inlen) < 0
|| asn1_integer_from_der(&r, &rlen, &data, &datalen) < 0
|| asn1_integer_from_der(&s, &slen, &data, &datalen) < 0
|| datalen > 0) {
return -1;
}
if (rlen != 32 || slen != 32) {
return -2;
}
memcpy(sig->r, r, 32);
memcpy(sig->s, s, 32);
return 1;
}
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen)
{
size_t len = 0;
asn1_integer_to_der(c->point.x, 32, NULL, &len);
asn1_integer_to_der(c->point.y, 32, NULL, &len);
asn1_octet_string_to_der(c->hash, 32, NULL, &len);
asn1_octet_string_to_der(c->ciphertext, c->ciphertext_size, NULL, &len);
asn1_sequence_header_to_der(len, out, outlen);
asn1_integer_to_der(c->point.x, 32, out, outlen);
asn1_integer_to_der(c->point.y, 32, out, outlen);
asn1_octet_string_to_der(c->hash, 32, out, outlen);
asn1_octet_string_to_der(c->ciphertext, c->ciphertext_size, out, outlen);
return 1;
}
int sm2_ciphertext_from_der(SM2_CIPHERTEXT *a, const uint8_t **in, size_t *inlen)
{
const uint8_t *data, *x, *y, *hash, *c;
size_t datalen, xlen, ylen, hashlen, clen;
if (asn1_sequence_from_der(&data, &datalen, in, inlen) < 0
|| asn1_integer_from_der(&x, &xlen, &data, &datalen) < 0
|| asn1_integer_from_der(&y, &ylen, &data, &datalen) < 0
|| asn1_octet_string_from_der(&hash, &hashlen, &data, &datalen) < 0
|| asn1_octet_string_from_der(&c, &clen, &data, &datalen) < 0
|| datalen > 0) {
return -1;
}
if (xlen != 32
|| ylen != 32
|| hashlen != 32
|| clen < 1) {
return -1;
}
memcpy(a->point.x, x, 32);
memcpy(a->point.y, y, 32);
memcpy(a->hash, hash, 32);
memcpy(a->ciphertext, c, clen);
a->ciphertext_size = (uint32_t)clen;
return 1;
}
/*
from RFC 5915
ECPrivateKey ::= SEQUENCE {
version INTEGER, -- value MUST be ecPrivkeyVer1(1)
privateKey OCTET STRING, -- big endian encoding of 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
-- SHOULD always include this field, by RFC 5915
}
ECParameters ::= CHOICE {
namedCurve OBJECT IDENTIFIER
}
*/
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;
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, NULL, 0, NULL, &params_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, NULL, 0, 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);
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 *prikey;
const uint8_t *params;
const uint8_t *pubkey;
size_t prikey_len;
size_t params_len;
size_t pubkey_len;
memset(key, 0, sizeof(SM2_KEY));
if ((ret = asn1_sequence_from_der(&data, &datalen, 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, &params, &params_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_set_private_key(key, prikey) != 1) {
error_print();
return -1;
}
if (params) {
int curve_oid;
uint32_t nodes[16];
size_t nodes_count;
if (asn1_object_identifier_from_der(&curve_oid, nodes, &nodes_count, &params, &params_len) != 1
|| params_len > 0) {
error_print();
return -1;
}
if (curve_oid != OID_sm2) {
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) {
error_print();
return -1;
}
}
return 1;
}
/*
AlgorithmIdentifier ::= {
algorithm OBJECT IDENTIFIER { id-ecPublicKey },
parameters OBJECT IDENTIFIER { id-sm2 } }
*/
int sm2_public_key_algor_to_der(uint8_t **out, size_t *outlen)
{
size_t len = 0;
asn1_object_identifier_to_der(OID_x9_62_ecPublicKey, NULL, 0, NULL, &len);
asn1_object_identifier_to_der(OID_sm2, NULL, 0, NULL, &len);
asn1_sequence_header_to_der(len, out, outlen);
asn1_object_identifier_to_der(OID_x9_62_ecPublicKey, NULL, 0, out, outlen);
asn1_object_identifier_to_der(OID_sm2, NULL, 0, out, outlen);
return 1;
}
int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
int oid;
uint32_t nodes[16];
size_t nodes_count = 16;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1
|| oid != OID_x9_62_ecPublicKey) {
error_print();
return -1;
}
if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1
|| oid != OID_sm2) {
error_print();
return -1;
}
if (datalen) {
error_print();
return -1;
}
return 1;
}
/*
from RFC 5208
PrivateKeyInfo ::= SEQUENCE {
version Version { v1(0) },
privateKeyAlgorithm AlgorithmIdentifier,
privateKey OCTET STRING, -- DER-encoding of ECPrivateKey
attributes [0] IMPLICIT SET OF Attribute OPTIONAL
}
*/
int sm2_private_key_info_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen)
{
size_t len = 0;
uint8_t prikey[512];
uint8_t *p = prikey;
size_t prikey_len = 0;
sm2_private_key_to_der(key, &p, &prikey_len);
asn1_int_to_der(0, NULL, &len);
sm2_public_key_algor_to_der(NULL, &len);
asn1_octet_string_to_der(prikey, prikey_len, NULL, &len);
asn1_sequence_header_to_der(len, out, outlen);
asn1_int_to_der(0, out, outlen);
sm2_public_key_algor_to_der(out, outlen);
asn1_octet_string_to_der(prikey, prikey_len, out, outlen);
return 1;
}
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 ret;
const uint8_t *data;
size_t datalen;
int version;
const uint8_t *prikey;
size_t prikeylen;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_int_from_der(&version, &data, &datalen) != 1
|| sm2_public_key_algor_from_der(&data, &datalen) != 1
|| asn1_octet_string_from_der(&prikey, &prikeylen, &data, &datalen) != 1
|| asn1_implicit_set_from_der(0, attrs, attrslen, &data, &datalen) < 0
|| datalen > 0) {
error_print();
return -1;
}
if (version != 0) {
error_print();
return -1;
}
if (sm2_private_key_from_der(key, &prikey, &prikeylen) != 1
|| prikeylen > 0) {
error_print();
return -1;
}
return 1;
}
int sm2_private_key_info_to_pem(const SM2_KEY *key, FILE *fp)
{
uint8_t buf[512];
uint8_t *p = buf;
size_t len = 0;
if (sm2_private_key_info_to_der(key, &p, &len) != 1) {
error_print();
return -1;
}
if (pem_write(fp, "PRIVATE KEY", buf, len) <= 0) {
error_print();
return -1;
}
return 1;
}
int sm2_private_key_info_from_pem(SM2_KEY *key, const uint8_t **attrs, size_t *attrslen, FILE *fp)
{
uint8_t buf[512];
const uint8_t *cp = buf;
size_t len;
if (pem_read(fp, "PRIVATE KEY", buf, &len) != 1) {
error_print();
return -1;
}
if (sm2_private_key_info_from_der(key, attrs, attrslen, &cp, &len) != 1
|| len > 0) {
return -1;
}
return 1;
}
/*
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING -- uncompressed octets of ECPoint
}
*/
int sm2_public_key_info_to_der(const SM2_KEY *a, 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);
return 1;
}
int sm2_public_key_info_from_der(SM2_KEY *a, 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;
if ((ret = asn1_sequence_from_der(&data, &datalen, 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_set_public_key(a, (uint8_t *)&point) != 1) {
error_print();
return -1;
}
return 1;
}
int sm2_private_key_to_pem(const SM2_KEY *a, FILE *fp)
{
uint8_t buf[512];
uint8_t *p = buf;
size_t len = 0;
if (sm2_private_key_to_der(a, &p, &len) != 1) {
error_print();
return -1;
}
if (pem_write(fp, "EC PRIVATE KEY", buf, len) <= 0) {
error_print();
return -1;
}
return 1;
}
int sm2_private_key_from_pem(SM2_KEY *a, FILE *fp)
{
uint8_t buf[512];
const uint8_t *cp = buf;
size_t len;
if (pem_read(fp, "EC PRIVATE KEY", buf, &len) != 1) {
error_print();
return -1;
}
if (sm2_private_key_from_der(a, &cp, &len) != 1
|| len > 0) {
error_print();
return -1;
}
return 1;
}
int sm2_public_key_info_to_pem(const SM2_KEY *a, FILE *fp)
{
uint8_t buf[512];
uint8_t *p = buf;
size_t len = 0;
if (sm2_public_key_info_to_der(a, &p, &len) != 1) {
error_print();
return -1;
}
if (pem_write(fp, "PUBLIC KEY", buf, len) <= 0) {
error_print();
return -1;
}
return 1;
}
int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp)
{
uint8_t buf[512];
const uint8_t *cp = buf;
size_t len;
if (pem_read(fp, "PUBLIC KEY", buf, &len) != 1) {
error_print();
return -1;
}
if (sm2_public_key_info_from_der(a, &cp, &len) != 1
|| len > 0) {
return -1;
}
return 1;
}
int sm2_public_key_digest(const SM2_KEY *sm2_key, uint8_t dgst[32])
{
uint8_t bits[65];
sm2_point_to_uncompressed_octets(&sm2_key->public_key, bits);
sm3_digest(bits, sizeof(bits), dgst);
return 1;
}

277
src/sm2_lib.c Normal file
View File

@@ -0,0 +1,277 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/error.h>
#include "endian.h"
#define SM2_SIGNATURE_MAX_DER_SIZE 77
int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *der, size_t *derlen)
{
SM2_SIGNATURE sig;
uint8_t *p = der;
size_t len = 0;
if (!der && derlen) {
*derlen = SM2_SIGNATURE_MAX_DER_SIZE;
return 1;
}
if (!key || !der || !derlen) {
return -1;
}
sm2_do_sign(key, dgst, &sig);
sm2_signature_to_der(&sig, &p, &len);
*derlen = len;
return 1;
}
int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *der, size_t derlen)
{
int ret;
SM2_SIGNATURE sig;
const uint8_t *p = der;
size_t len = derlen;
if (!key || !der || !derlen) {
error_print();
return -1;
}
if (sm2_signature_from_der(&sig, &p, &len) < 0
|| len > 0) {
error_print();
return -2;
}
if ((ret = sm2_do_verify(key, dgst, &sig)) != 1) {
error_print();
}
return ret;
}
int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
{
size_t clen = SM2_CIPHERTEXT_SIZE(inlen);
size_t cbuf[clen];
SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)cbuf;
sm2_do_encrypt(key, in, inlen, c);
*outlen = 0;
sm2_ciphertext_to_der(c, &out, outlen);
return 1;
}
int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
{
size_t cbuf[inlen];
SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)cbuf;
sm2_ciphertext_from_der(c, &in, &inlen); // FIXME: 检查是否有剩余长度
sm2_do_decrypt(key, c, out, outlen);
return 1;
}
extern void sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks);
int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id)
{
uint8_t zin[] = {
0x00, 0x80,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34,
0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7,
0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92,
0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93,
0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19,
0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94,
0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1,
0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7,
0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C,
0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53,
0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40,
0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x90,
};
if (!id || strcmp(id, "1234567812345678")) {
uint32_t digest[8] = {
0xadadedb5U, 0x0446043fU, 0x08a87aceU, 0xe86d2243U,
0x8e232383U, 0xbfc81fe2U, 0xcf9117c8U, 0x4707011dU,
};
memcpy(&zin[128], pub->x, 32);
memcpy(&zin[160], pub->y, 32);
sm3_compress_blocks(digest, zin, 2);
PUTU32(z , digest[0]);
PUTU32(z + 4, digest[1]);
PUTU32(z + 8, digest[2]);
PUTU32(z + 12, digest[3]);
PUTU32(z + 16, digest[4]);
PUTU32(z + 20, digest[5]);
PUTU32(z + 24, digest[6]);
PUTU32(z + 28, digest[7]);
} else {
SM3_CTX ctx;
uint8_t idbits[2];
size_t len;
len = strlen(id);
idbits[0] = (uint8_t)(len >> 5);
idbits[1] = (uint8_t)(len << 3);
sm3_init(&ctx);
sm3_update(&ctx, idbits, 2);
sm3_update(&ctx, (uint8_t *)id, len);
sm3_update(&ctx, zin + 18, 128);
sm3_update(&ctx, pub->x, 32);
sm3_update(&ctx, pub->y, 32);
sm3_finish(&ctx, z);
}
return 0;
}
int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id)
{
uint8_t z[32];
if (!ctx || !key || !id || strlen(id) > SM2_MAX_ID_SIZE) {
return -1;
}
sm2_compute_z(z, &key->public_key, id);
sm3_init(&ctx->sm3_ctx);
sm3_update(&ctx->sm3_ctx, z, 32);
memcpy(&ctx->key, key, sizeof(SM2_KEY));
return 1;
}
int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
{
sm3_update(&ctx->sm3_ctx, data, datalen);
return 1;
}
int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
{
uint8_t dgst[32];
sm3_finish(&ctx->sm3_ctx, dgst);
sm2_sign(&ctx->key, dgst, sig, siglen);
return 1;
}
int sm2_sign_resume(SM2_SIGN_CTX *ctx)
{
return 0;
}
int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id)
{
uint8_t z[32];
if (!ctx || !key || !id || strlen(id) > SM2_MAX_ID_SIZE) {
return -1;
}
sm2_compute_z(z, &key->public_key, id);
sm3_init(&ctx->sm3_ctx);
sm3_update(&ctx->sm3_ctx, z, 32);
memcpy(&ctx->key, key, sizeof(SM2_KEY));
return 1;
}
int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
{
sm3_update(&ctx->sm3_ctx, data, datalen);
return 1;
}
int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen)
{
int ret;
uint8_t dgst[32];
sm3_finish(&ctx->sm3_ctx, dgst);
ret = sm2_verify(&ctx->key, dgst, sig, siglen);
return ret;
}
int sm2_set_private_key(SM2_KEY *key, const uint8_t private_key[32])
{
memcpy(&key->private_key, private_key, 32);
return 1;
}
// FIXME: 检查公钥是否正确
int sm2_set_public_key(SM2_KEY *key, const uint8_t public_key[64])
{
memcpy(&key->public_key, public_key, 64);
return 1;
}

119
src/sm2_prn.c Normal file
View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/sm2.h>
#include <gmssl/error.h>
int sm2_key_print(FILE *fp, const SM2_KEY *key, int format, int indent)
{
format_print(fp, format, indent, "SM2PrivateKey\n");
indent += 4;
format_bytes(fp, format, indent, "private_key : ", key->private_key, 32);
format_print(fp, format, indent, "public_key\n");
sm2_point_print(fp, &key->public_key, format, indent + 4);
//format_bytes(fp, format, indent + 4, "x : ", (uint8_t *)&key->public_key, 32);
//format_bytes(fp, format, indent + 4, "y : ", (uint8_t *)&key->public_key + 32, 32);
return 1;
}
int sm2_point_print(FILE *fp, const SM2_POINT *P, int format, int indent)
{
format_bytes(fp, format, indent, "x : ", P->x, 32);
format_bytes(fp, format, indent, "y : ", P->y, 32);
return 1;
}
int sm2_print_signature(FILE *fp, const uint8_t *der, size_t derlen, int format, int indent)
{
uint8_t buf[sizeof(SM2_SIGNATURE)] = {0};
SM2_SIGNATURE *sig = (SM2_SIGNATURE *)buf;
const uint8_t *p = der;
int i;
if (sm2_signature_from_der(sig, &p, &derlen) < 0) {
fprintf(stderr, "error: %s %d: invalid signature DER encoding\n", __FILE__, __LINE__);
}
if (derlen > 0) {
fprintf(stderr, "error: %s %d: %zu extra bytes at the end of DER\n", __FILE__, __LINE__, derlen);
}
format_bytes(fp, format, indent, "r : ", sig->r, 32);
format_bytes(fp, format, indent, "s : ", sig->s, 32);
return 1;
}
int sm2_print_ciphertext(FILE *fp, const uint8_t *der, size_t derlen, int format, int indent)
{
uint8_t buf[512 /* derlen */] = {0}; //FIXME: add -std=c99 to CMakeList.txt
SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)buf;
const uint8_t *p = der;
int i;
if (sm2_ciphertext_from_der(c, &p, &derlen) < 0) {
fprintf(stderr, "error: %s %d: invalid ciphertext DER encoding\n", __FILE__, __LINE__);
}
if (derlen > 0) {
fprintf(stderr, "error: %s %d: %zu extra bytes at the end of DER\n", __FILE__, __LINE__, derlen);
}
sm2_ciphertext_print(fp, c, format, indent);
return 1;
}
int sm2_ciphertext_print(FILE *fp, const SM2_CIPHERTEXT *c, int format, int indent)
{
format_bytes(fp, format, indent, "x", c->point.x, 32);
format_bytes(fp, format, indent, "y", c->point.y, 32);
format_bytes(fp, format, indent, "hash", c->hash, 32);
format_bytes(fp, format, indent, "ciphertext", c->ciphertext, c->ciphertext_size);
return 1;
}

506
src/sm3.c Executable file
View File

@@ -0,0 +1,506 @@
/* ====================================================================
* Copyright (c) 2014 - 2017 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 <string.h>
#include <gmssl/sm3.h>
#include "bswap.h"
#include "rotate.h"
#ifdef SM3_SSE3
# include <x86intrin.h>
# include <immintrin.h>
# define _mm_rotl_epi32(X,i) \
_mm_xor_si128(_mm_slli_epi32((X),(i)), _mm_srli_epi32((X),32-(i)))
#endif
void sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks);
void sm3_init(SM3_CTX *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->digest[0] = 0x7380166F;
ctx->digest[1] = 0x4914B2B9;
ctx->digest[2] = 0x172442D7;
ctx->digest[3] = 0xDA8A0600;
ctx->digest[4] = 0xA96F30BC;
ctx->digest[5] = 0x163138AA;
ctx->digest[6] = 0xE38DEE4D;
ctx->digest[7] = 0xB0FB0E4E;
}
#if 0
void sm3_compute_id_digest(uint8_t z[32], const char *id,
const uint8_t x[32], const uint8_t y[32])
{
uint8_t zin[] = {
0x00, 0x80,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34,
0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7,
0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92,
0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93,
0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19,
0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94,
0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1,
0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7,
0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C,
0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53,
0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40,
0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x90,
};
if (!id || strcmp(id, "1234567812345678")) {
unsigned int digest[8] = {
0xadadedb5U, 0x0446043fU, 0x08a87aceU, 0xe86d2243U,
0x8e232383U, 0xbfc81fe2U, 0xcf9117c8U, 0x4707011dU,
};
memcpy(&zin[128], x, 32);
memcpy(&zin[160], y, 32);
sm3_compress_blocks(digest, zin, 2);
PUTU32(z , digest[0]);
PUTU32(z + 4, digest[1]);
PUTU32(z + 8, digest[2]);
PUTU32(z + 12, digest[3]);
PUTU32(z + 16, digest[4]);
PUTU32(z + 20, digest[5]);
PUTU32(z + 24, digest[6]);
PUTU32(z + 28, digest[7]);
} else {
SM3_CTX ctx;
uint8_t idbits[2];
size_t len;
len = strlen(id);
idbits[0] = (uint8_t)(len >> 5);
idbits[1] = (uint8_t)(len << 3);
sm3_init(&ctx);
sm3_update(&ctx, idbits, 2);
sm3_update(&ctx, (uint8_t *)id, len);
sm3_update(&ctx, zin + 18, 128);
sm3_update(&ctx, x, 32);
sm3_update(&ctx, y, 32);
sm3_finish(&ctx, z);
}
}
int sm3_sm2_init(SM3_CTX *ctx, const char *id,
const uint8_t *x, const uint8_t *y)
{
uint8_t z[32];
if ((id && strlen(id) > 65535/8) || !x || !y) {
return 0;
}
sm3_compute_id_digest(z, id, x, y);
sm3_init(ctx);
sm3_update(ctx, z, 32);
return 1;
}
#endif
void sm3_update(SM3_CTX *ctx, const uint8_t *data, size_t data_len)
{
size_t blocks;
if (ctx->num) {
unsigned int left = SM3_BLOCK_SIZE - ctx->num;
if (data_len < left) {
memcpy(ctx->block + ctx->num, data, data_len);
ctx->num += data_len;
return;
} else {
memcpy(ctx->block + ctx->num, data, left);
sm3_compress_blocks(ctx->digest, ctx->block, 1);
ctx->nblocks++;
data += left;
data_len -= left;
}
}
blocks = data_len / SM3_BLOCK_SIZE;
sm3_compress_blocks(ctx->digest, data, blocks);
ctx->nblocks += blocks;
data += SM3_BLOCK_SIZE * blocks;
data_len -= SM3_BLOCK_SIZE * blocks;
ctx->num = data_len;
if (data_len) {
memcpy(ctx->block, data, data_len);
}
}
void sm3_finish(SM3_CTX *ctx, uint8_t *digest)
{
int i;
ctx->block[ctx->num] = 0x80;
if (ctx->num + 9 <= SM3_BLOCK_SIZE) {
memset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 9);
} else {
memset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 1);
sm3_compress(ctx->digest, ctx->block);
memset(ctx->block, 0, SM3_BLOCK_SIZE - 8);
}
PUTU32(ctx->block + 56, ctx->nblocks >> 23);
PUTU32(ctx->block + 60, (ctx->nblocks << 9) + (ctx->num << 3));
sm3_compress(ctx->digest, ctx->block);
for (i = 0; i < 8; i++) {
PUTU32(digest + i*4, ctx->digest[i]);
}
memset(ctx, 0, sizeof(SM3_CTX));
}
#define ROTL(x,n) (((x)<<(n)) | ((x)>>(32-(n))))
#define P0(x) ((x) ^ ROL32((x), 9) ^ ROL32((x),17))
#define P1(x) ((x) ^ ROL32((x),15) ^ ROL32((x),23))
#define FF00(x,y,z) ((x) ^ (y) ^ (z))
#define FF16(x,y,z) (((x)&(y)) | ((x)&(z)) | ((y)&(z)))
#define GG00(x,y,z) ((x) ^ (y) ^ (z))
#define GG16(x,y,z) ((((y)^(z)) & (x)) ^ (z))
#define R(A, B, C, D, E, F, G, H, xx) \
SS1 = ROL32((ROL32(A, 12) + E + K[j]), 7); \
SS2 = SS1 ^ ROL32(A, 12); \
TT1 = FF##xx(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]); \
TT2 = GG##xx(E, F, G) + H + SS1 + W[j]; \
B = ROL32(B, 9); \
H = TT1; \
F = ROL32(F, 19); \
D = P0(TT2); \
j++
#define R8(A, B, C, D, E, F, G, H, xx) \
R(A, B, C, D, E, F, G, H, xx); \
R(H, A, B, C, D, E, F, G, xx); \
R(G, H, A, B, C, D, E, F, xx); \
R(F, G, H, A, B, C, D, E, xx); \
R(E, F, G, H, A, B, C, D, xx); \
R(D, E, F, G, H, A, B, C, xx); \
R(C, D, E, F, G, H, A, B, xx); \
R(B, C, D, E, F, G, H, A, xx)
#define T00 0x79cc4519U
#define T16 0x7a879d8aU
#define K0 0x79cc4519U
#define K1 0xf3988a32U
#define K2 0xe7311465U
#define K3 0xce6228cbU
#define K4 0x9cc45197U
#define K5 0x3988a32fU
#define K6 0x7311465eU
#define K7 0xe6228cbcU
#define K8 0xcc451979U
#define K9 0x988a32f3U
#define K10 0x311465e7U
#define K11 0x6228cbceU
#define K12 0xc451979cU
#define K13 0x88a32f39U
#define K14 0x11465e73U
#define K15 0x228cbce6U
#define K16 0x9d8a7a87U
#define K17 0x3b14f50fU
#define K18 0x7629ea1eU
#define K19 0xec53d43cU
#define K20 0xd8a7a879U
#define K21 0xb14f50f3U
#define K22 0x629ea1e7U
#define K23 0xc53d43ceU
#define K24 0x8a7a879dU
#define K25 0x14f50f3bU
#define K26 0x29ea1e76U
#define K27 0x53d43cecU
#define K28 0xa7a879d8U
#define K29 0x4f50f3b1U
#define K30 0x9ea1e762U
#define K31 0x3d43cec5U
#define K32 0x7a879d8aU
#define K33 0xf50f3b14U
#define K34 0xea1e7629U
#define K35 0xd43cec53U
#define K36 0xa879d8a7U
#define K37 0x50f3b14fU
#define K38 0xa1e7629eU
#define K39 0x43cec53dU
#define K40 0x879d8a7aU
#define K41 0x0f3b14f5U
#define K42 0x1e7629eaU
#define K43 0x3cec53d4U
#define K44 0x79d8a7a8U
#define K45 0xf3b14f50U
#define K46 0xe7629ea1U
#define K47 0xcec53d43U
#define K48 0x9d8a7a87U
#define K49 0x3b14f50fU
#define K50 0x7629ea1eU
#define K51 0xec53d43cU
#define K52 0xd8a7a879U
#define K53 0xb14f50f3U
#define K54 0x629ea1e7U
#define K55 0xc53d43ceU
#define K56 0x8a7a879dU
#define K57 0x14f50f3bU
#define K58 0x29ea1e76U
#define K59 0x53d43cecU
#define K60 0xa7a879d8U
#define K61 0x4f50f3b1U
#define K62 0x9ea1e762U
#define K63 0x3d43cec5U
uint32_t K[64] = {
K0, K1, K2, K3, K4, K5, K6, K7,
K8, K9, K10, K11, K12, K13, K14, K15,
K16, K17, K18, K19, K20, K21, K22, K23,
K24, K25, K26, K27, K28, K29, K30, K31,
K32, K33, K34, K35, K36, K37, K38, K39,
K40, K41, K42, K43, K44, K45, K46, K47,
K48, K49, K50, K51, K52, K53, K54, K55,
K56, K57, K58, K59, K60, K61, K62, K63,
/*
0x79cc4519U, 0xf3988a32U, 0xe7311465U, 0xce6228cbU,
0x9cc45197U, 0x3988a32fU, 0x7311465eU, 0xe6228cbcU,
0xcc451979U, 0x988a32f3U, 0x311465e7U, 0x6228cbceU,
0xc451979cU, 0x88a32f39U, 0x11465e73U, 0x228cbce6U,
0x9d8a7a87U, 0x3b14f50fU, 0x7629ea1eU, 0xec53d43cU,
0xd8a7a879U, 0xb14f50f3U, 0x629ea1e7U, 0xc53d43ceU,
0x8a7a879dU, 0x14f50f3bU, 0x29ea1e76U, 0x53d43cecU,
0xa7a879d8U, 0x4f50f3b1U, 0x9ea1e762U, 0x3d43cec5U,
0x7a879d8aU, 0xf50f3b14U, 0xea1e7629U, 0xd43cec53U,
0xa879d8a7U, 0x50f3b14fU, 0xa1e7629eU, 0x43cec53dU,
0x879d8a7aU, 0x0f3b14f5U, 0x1e7629eaU, 0x3cec53d4U,
0x79d8a7a8U, 0xf3b14f50U, 0xe7629ea1U, 0xcec53d43U,
0x9d8a7a87U, 0x3b14f50fU, 0x7629ea1eU, 0xec53d43cU,
0xd8a7a879U, 0xb14f50f3U, 0x629ea1e7U, 0xc53d43ceU,
0x8a7a879dU, 0x14f50f3bU, 0x29ea1e76U, 0x53d43cecU,
0xa7a879d8U, 0x4f50f3b1U, 0x9ea1e762U, 0x3d43cec5U,
*/
};
void sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks)
{
uint32_t A;
uint32_t B;
uint32_t C;
uint32_t D;
uint32_t E;
uint32_t F;
uint32_t G;
uint32_t H;
uint32_t W[68];
uint32_t SS1, SS2, TT1, TT2;
int j;
#ifdef SM3_SSE3
__m128i X, T, R;
__m128i M = _mm_setr_epi32(0, 0, 0, 0xffffffff);
__m128i V = _mm_setr_epi8(3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12);
#endif
while (blocks--) {
A = digest[0];
B = digest[1];
C = digest[2];
D = digest[3];
E = digest[4];
F = digest[5];
G = digest[6];
H = digest[7];
#ifdef SM3_SSE3
for (j = 0; j < 16; j += 4) {
X = _mm_loadu_si128((__m128i *)(data + j * 4));
X = _mm_shuffle_epi8(X, V);
_mm_storeu_si128((__m128i *)(W + j), X);
}
for (j = 16; j < 68; j += 4) {
/* X = (W[j - 3], W[j - 2], W[j - 1], 0) */
X = _mm_loadu_si128((__m128i *)(W + j - 3));
X = _mm_andnot_si128(M, X);
X = _mm_rotl_epi32(X, 15);
T = _mm_loadu_si128((__m128i *)(W + j - 9));
X = _mm_xor_si128(X, T);
T = _mm_loadu_si128((__m128i *)(W + j - 16));
X = _mm_xor_si128(X, T);
/* P1() */
T = _mm_rotl_epi32(X, (23 - 15));
T = _mm_xor_si128(T, X);
T = _mm_rotl_epi32(T, 15);
X = _mm_xor_si128(X, T);
T = _mm_loadu_si128((__m128i *)(W + j - 13));
T = _mm_rotl_epi32(T, 7);
X = _mm_xor_si128(X, T);
T = _mm_loadu_si128((__m128i *)(W + j - 6));
X = _mm_xor_si128(X, T);
/* W[j + 3] ^= P1(ROL32(W[j + 1], 15)) */
R = _mm_shuffle_epi32(X, 0);
R = _mm_and_si128(R, M);
T = _mm_rotl_epi32(R, 15);
T = _mm_xor_si128(T, R);
T = _mm_rotl_epi32(T, 9);
R = _mm_xor_si128(R, T);
R = _mm_rotl_epi32(R, 6);
X = _mm_xor_si128(X, R);
_mm_storeu_si128((__m128i *)(W + j), X);
}
#else
for (j = 0; j < 16; j++)
W[j] = GETU32(data + j*4);
for (; j < 68; j++)
W[j] = P1(W[j - 16] ^ W[j - 9] ^ ROL32(W[j - 3], 15))
^ ROL32(W[j - 13], 7) ^ W[j - 6];
#endif
j = 0;
#define FULL_UNROLL
#ifdef FULL_UNROLL
R8(A, B, C, D, E, F, G, H, 00);
R8(A, B, C, D, E, F, G, H, 00);
R8(A, B, C, D, E, F, G, H, 16);
R8(A, B, C, D, E, F, G, H, 16);
R8(A, B, C, D, E, F, G, H, 16);
R8(A, B, C, D, E, F, G, H, 16);
R8(A, B, C, D, E, F, G, H, 16);
R8(A, B, C, D, E, F, G, H, 16);
#else
for (; j < 16; j++) {
SS1 = ROL32((ROL32(A, 12) + E + K(j)), 7);
SS2 = SS1 ^ ROL32(A, 12);
TT1 = FF00(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]);
TT2 = GG00(E, F, G) + H + SS1 + W[j];
D = C;
C = ROL32(B, 9);
B = A;
A = TT1;
H = G;
G = ROL32(F, 19);
F = E;
E = P0(TT2);
}
for (; j < 64; j++) {
SS1 = ROL32((ROL32(A, 12) + E + K(j)), 7);
SS2 = SS1 ^ ROL32(A, 12);
TT1 = FF16(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]);
TT2 = GG16(E, F, G) + H + SS1 + W[j];
D = C;
C = ROL32(B, 9);
B = A;
A = TT1;
H = G;
G = ROL32(F, 19);
F = E;
E = P0(TT2);
}
#endif
digest[0] ^= A;
digest[1] ^= B;
digest[2] ^= C;
digest[3] ^= D;
digest[4] ^= E;
digest[5] ^= F;
digest[6] ^= G;
digest[7] ^= H;
data += 64;
}
}
void sm3_compress(uint32_t digest[8], const uint8_t block[64])
{
return sm3_compress_blocks(digest, block, 1);
}
void sm3_digest(const uint8_t *msg, size_t msglen,
uint8_t dgst[SM3_DIGEST_SIZE])
{
SM3_CTX ctx;
sm3_init(&ctx);
sm3_update(&ctx, msg, msglen);
sm3_finish(&ctx, dgst);
}

144
src/sm3_hmac.c Normal file
View File

@@ -0,0 +1,144 @@
/*
* 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 <string.h>
#include <gmssl/sm3.h>
#include <gmssl/error.h>
/**
* HMAC_k(m) = H((k ^ opad) || H((k ^ ipad) || m))
* pseudo-code:
* function hmac(key, message)
* opad = [0x5c * blocksize]
* ipad = [0x36 * blocksize]
* if (length(key) > blocksize) then
* key = hash(key)
* end if
* for i from 0 to length(key) - 1 step 1
* ipad[i] = ipad[i] XOR key[i]
* opad[i] = opad[i] XOR key[i]
* end for
* return hash(opad || hash(ipad || message))
* end function
*/
#define IPAD 0x36
#define OPAD 0x5C
void sm3_hmac_init(SM3_HMAC_CTX *ctx, const uint8_t *key, size_t key_len)
{
int i;
if (key_len <= SM3_BLOCK_SIZE) {
memcpy(ctx->key, key, key_len);
memset(ctx->key + key_len, 0, SM3_BLOCK_SIZE - key_len);
} else {
sm3_init(&ctx->sm3_ctx);
sm3_update(&ctx->sm3_ctx, key, key_len);
sm3_finish(&ctx->sm3_ctx, ctx->key);
memset(ctx->key + SM3_DIGEST_SIZE, 0,
SM3_BLOCK_SIZE - SM3_DIGEST_SIZE);
}
for (i = 0; i < SM3_BLOCK_SIZE; i++) {
ctx->key[i] ^= IPAD;
}
sm3_init(&ctx->sm3_ctx);
sm3_update(&ctx->sm3_ctx, ctx->key, SM3_BLOCK_SIZE);
}
void sm3_hmac_update(SM3_HMAC_CTX *ctx, const uint8_t *data, size_t data_len)
{
sm3_update(&ctx->sm3_ctx, data, data_len);
}
void sm3_hmac_finish(SM3_HMAC_CTX *ctx, uint8_t mac[SM3_HMAC_SIZE])
{
int i;
for (i = 0; i < SM3_BLOCK_SIZE; i++) {
ctx->key[i] ^= (IPAD ^ OPAD);
}
sm3_finish(&ctx->sm3_ctx, mac);
sm3_init(&ctx->sm3_ctx);
sm3_update(&ctx->sm3_ctx, ctx->key, SM3_BLOCK_SIZE);
sm3_update(&ctx->sm3_ctx, mac, SM3_DIGEST_SIZE);
sm3_finish(&ctx->sm3_ctx, mac);
}
int sm3_hmac_finish_and_verify(SM3_HMAC_CTX *ctx, const uint8_t mac[SM3_HMAC_SIZE])
{
uint8_t buf[32];
sm3_hmac_finish(ctx, buf);
if (memcmp(mac, buf, sizeof(buf)) == 0) {
return 1;
} else {
error_print("sm3_hmac verify failure");
return 0;
}
}
void sm3_hmac_reset(SM3_HMAC_CTX *ctx)
{
sm3_init(&ctx->sm3_ctx);
sm3_update(&ctx->sm3_ctx, ctx->key, SM3_BLOCK_SIZE);
// 不应该保留原始密钥而是应该保持这次update之后的状态
// 这样可以降低reset的工作量
}
void sm3_hmac(const uint8_t *data, size_t data_len,
const uint8_t *key, size_t key_len,
uint8_t mac[SM3_HMAC_SIZE])
{
SM3_HMAC_CTX ctx;
sm3_hmac_init(&ctx, key, key_len);
sm3_hmac_update(&ctx, data, data_len);
sm3_hmac_finish(&ctx, mac);
memset(&ctx, 0, sizeof(ctx));
}

208
src/sm4_avx2.c Normal file
View File

@@ -0,0 +1,208 @@
/* ====================================================================
* Copyright (c) 2014 - 2019 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 <gmssl/sm4.h>
#include "internal/bswap.h"
#include "internal/rotate.h"
#include "sm4_lcl.h"
#ifdef SMS4_AVX2
# include <immintrin.h>
# define GET_BLKS(x0, x1, x2, x3, in) \
t0 = _mm256_i32gather_epi32((int *)(in+4*0), vindex_4i, 4); \
t1 = _mm256_i32gather_epi32((int *)(in+4*1), vindex_4i, 4); \
t2 = _mm256_i32gather_epi32((int *)(in+4*2), vindex_4i, 4); \
t3 = _mm256_i32gather_epi32((int *)(in+4*3), vindex_4i, 4); \
x0 = _mm256_shuffle_epi8(t0, vindex_swap); \
x1 = _mm256_shuffle_epi8(t1, vindex_swap); \
x2 = _mm256_shuffle_epi8(t2, vindex_swap); \
x3 = _mm256_shuffle_epi8(t3, vindex_swap)
# define PUT_BLKS(out, x0, x1, x2, x3) \
t0 = _mm256_shuffle_epi8(x0, vindex_swap); \
t1 = _mm256_shuffle_epi8(x1, vindex_swap); \
t2 = _mm256_shuffle_epi8(x2, vindex_swap); \
t3 = _mm256_shuffle_epi8(x3, vindex_swap); \
_mm256_storeu_si256((__m256i *)(out+32*0), t0); \
_mm256_storeu_si256((__m256i *)(out+32*1), t1); \
_mm256_storeu_si256((__m256i *)(out+32*2), t2); \
_mm256_storeu_si256((__m256i *)(out+32*3), t3); \
x0 = _mm256_i32gather_epi32((int *)(out+8*0), vindex_read, 4); \
x1 = _mm256_i32gather_epi32((int *)(out+8*1), vindex_read, 4); \
x2 = _mm256_i32gather_epi32((int *)(out+8*2), vindex_read, 4); \
x3 = _mm256_i32gather_epi32((int *)(out+8*3), vindex_read, 4); \
_mm256_storeu_si256((__m256i *)(out+32*0), x0); \
_mm256_storeu_si256((__m256i *)(out+32*1), x1); \
_mm256_storeu_si256((__m256i *)(out+32*2), x2); \
_mm256_storeu_si256((__m256i *)(out+32*3), x3)
# define _mm256_rotl_epi32(a, i) _mm256_xor_si256( \
_mm256_slli_epi32(a, i), _mm256_srli_epi32(a, 32 - i))
# define INDEX_MASK_TBOX 0xff
# define ROUND_TBOX(x0, x1, x2, x3, x4, i) \
t0 = _mm256_set1_epi32(*(rk + i)); \
t1 = _mm256_xor_si256(x1, x2); \
t2 = _mm256_xor_si256(x3, t0); \
x4 = _mm256_xor_si256(t1, t2); \
t0 = _mm256_and_si256(x4, vindex_mask); \
t0 = _mm256_i32gather_epi32((int *)SMS4_T, t0, 4); \
t0 = _mm256_rotl_epi32(t0, 8); \
x4 = _mm256_srli_epi32(x4, 8); \
x0 = _mm256_xor_si256(x0, t0); \
t0 = _mm256_and_si256(x4, vindex_mask); \
t0 = _mm256_i32gather_epi32((int *)SMS4_T, t0, 4); \
t0 = _mm256_rotl_epi32(t0, 16); \
x4 = _mm256_srli_epi32(x4, 8); \
x0 = _mm256_xor_si256(x0, t0); \
t0 = _mm256_and_si256(x4, vindex_mask); \
t0 = _mm256_i32gather_epi32((int *)SMS4_T, t0, 4); \
t0 = _mm256_rotl_epi32(t0, 24); \
x4 = _mm256_srli_epi32(x4, 8); \
x0 = _mm256_xor_si256(x0, t0); \
t1 = _mm256_i32gather_epi32((int *)SMS4_T, x4, 4); \
x4 = _mm256_xor_si256(x0, t1)
# define INDEX_MASK_DBOX 0xffff
# define ROUND_DBOX(x0, x1, x2, x3, x4, i) \
t0 = _mm256_set1_epi32(*(rk + i)); \
t1 = _mm256_xor_si256(x1, x2); \
t2 = _mm256_xor_si256(x3, t0); \
x4 = _mm256_xor_si256(t1, t2); \
t0 = _mm256_srli_epi32(x4, 16); \
t1 = _mm256_i32gather_epi32((int *)SMS4_D, t0, 4); \
t2 = _mm256_and_si256(x4, vindex_mask); \
t3 = _mm256_i32gather_epi32((int *)SMS4_D, t2, 4); \
t0 = _mm256_rotl_epi32(t3, 16); \
x4 = _mm256_xor_si256(x0, t1); \
x4 = _mm256_xor_si256(x4, t0)
# define ROUND ROUND_TBOX
# define INDEX_MASK INDEX_MASK_TBOX
void sm4_avx2_ecb_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t blocks, const SM4_KEY *key)
{
const int *rk = (int *)key->rk;
__m256i x0, x1, x2, x3, x4;
__m256i t0, t1, t2, t3;
__m256i vindex_4i = _mm256_setr_epi32(0,4,8,12,16,20,24,28);
__m256i vindex_mask = _mm256_set1_epi32(INDEX_MASK);
__m256i vindex_read = _mm256_setr_epi32(0,8,16,24,1,9,17,25);
__m256i vindex_swap = _mm256_setr_epi8(
3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12,
3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12
);
while (blocks >= 8) {
GET_BLKS(x0, x1, x2, x3, in);
ROUNDS(x0, x1, x2, x3, x4);
PUT_BLKS(out, x0, x4, x3, x2);
in += 128;
out += 128;
blocks -= 8;
}
while (blocks--) {
sm4_encrypt(in, out, key);
in += 16;
out += 16;
}
}
void sm4_avx2_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t blocks, const SM4_KEY *key, const unsigned char iv[16])
{
const int *rk = (int *)key->rk;
__m256i x0, x1, x2, x3, x4;
__m256i t0, t1, t2, t3;
__m256i vindex_4i = _mm256_setr_epi32(0,4,8,12,16,20,24,28);
__m256i vindex_mask = _mm256_set1_epi32(INDEX_MASK);
__m256i vindex_read = _mm256_setr_epi32(0,8,16,24,1,9,17,25);
__m256i vindex_swap = _mm256_setr_epi8(
3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12,
3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12
);
__m256i incr = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7);
int c0 = (int)GETU32(iv );
int c1 = (int)GETU32(iv + 4);
int c2 = (int)GETU32(iv + 8);
int c3 = (int)GETU32(iv + 12);
while (blocks >= 8) {
x0 = _mm256_set1_epi32(c0);
x1 = _mm256_set1_epi32(c1);
x2 = _mm256_set1_epi32(c2);
x3 = _mm256_set1_epi32(c3);
x3 = _mm256_add_epi32(x3, incr);
ROUNDS(x0, x1, x2, x3, x4);
GET_BLKS(t0, t1, t2, t3, in);
x0 = _mm256_xor_si256(x0, t0);
x4 = _mm256_xor_si256(x4, t1);
x3 = _mm256_xor_si256(x3, t2);
x2 = _mm256_xor_si256(x2, t3);
PUT_BLKS(out, x0, x4, x3, x2);
c3 += 8;
in += 128;
out += 128;
blocks -= 8;
}
if (blocks) {
unsigned char ctr[16];
memcpy(ctr, iv, 12);
PUTU32(ctr + 12, c3);
sm4_ctr32_encrypt_blocks(in, out, blocks, key, ctr);
}
}
#endif

127
src/sm4_cbc.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2021 - 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 <gmssl/sm4.h>
#include <gmssl/error.h>
#include "mem.h"
void sm4_cbc_encrypt(const SM4_KEY *key, const uint8_t iv[16],
const uint8_t *in, size_t nblocks, uint8_t *out)
{
while (nblocks--) {
gmssl_memxor(out, in, iv, 16);
sm4_encrypt(key, out, out);
iv = out;
in += 16;
out += 16;
}
}
void sm4_cbc_decrypt(const SM4_KEY *key, const uint8_t iv[16],
const uint8_t *in, size_t nblocks, uint8_t *out)
{
while (nblocks--) {
sm4_decrypt(key, in, out);
memxor(out, iv, 16);
iv = in;
in += 16;
out += 16;
}
}
int sm4_cbc_padding_encrypt(const SM4_KEY *key, const uint8_t iv[16],
const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen)
{
uint8_t block[16];
size_t rem = inlen % 16;
int padding = 16 - rem;
if (in) {
memcpy(block, in + inlen - rem, rem);
}
memset(block + rem, padding, padding);
if (inlen/16) {
sm4_cbc_encrypt(key, iv, in, inlen/16, out);
out += inlen - rem;
iv = out - 16;
}
sm4_cbc_encrypt(key, iv, block, 1, out);
*outlen = inlen - rem + 16;
return 1;
}
int sm4_cbc_padding_decrypt(const SM4_KEY *key, const uint8_t iv[16],
const uint8_t *in, size_t inlen,
uint8_t *out, size_t *outlen)
{
uint8_t block[16];
int padding;
if (inlen == 0) {
error_print("warning: input lenght = 0");
return 0;
}
if (inlen%16 != 0 || inlen < 16) {
error_print("invalid cbc ciphertext length");
return -1;
}
if (inlen > 16) {
sm4_cbc_decrypt(key, iv, in, inlen/16 - 1, out);
iv = in + inlen - 32;
}
sm4_cbc_decrypt(key, iv, in + inlen - 16, 1, block);
padding = block[15];
if (padding < 1 || padding > 16) {
error_print();
return -1;
}
memcpy(out + inlen - 16, block, 16 - padding);
*outlen = inlen - padding;
return 1;
}

16540
src/sm4_common.c Normal file

File diff suppressed because it is too large Load Diff

133
src/sm4_enc.c Normal file
View File

@@ -0,0 +1,133 @@
/* ====================================================================
* Copyright (c) 2014 - 2017 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 <gmssl/sm4.h>
#include "bswap.h"
#include "rotate.h"
#include "sm4_lcl.h"
#define L32(x) \
((x) ^ \
ROL32((x), 2) ^ \
ROL32((x), 10) ^ \
ROL32((x), 18) ^ \
ROL32((x), 24))
#define ROUND_SBOX(x0, x1, x2, x3, x4, i) \
x4 = x1 ^ x2 ^ x3 ^ *(rk + i); \
x4 = S32(x4); \
x4 = x0 ^ L32(x4)
#define ROUND_TBOX(x0, x1, x2, x3, x4, i) \
x4 = x1 ^ x2 ^ x3 ^ *(rk + i); \
t0 = ROL32(SM4_T[(uint8_t)x4], 8); \
x4 >>= 8; \
x0 ^= t0; \
t0 = ROL32(SM4_T[(uint8_t)x4], 16); \
x4 >>= 8; \
x0 ^= t0; \
t0 = ROL32(SM4_T[(uint8_t)x4], 24); \
x4 >>= 8; \
x0 ^= t0; \
t1 = SM4_T[x4]; \
x4 = x0 ^ t1
#define ROUND_DBOX(x0, x1, x2, x3, x4, i) \
x4 = x1 ^ x2 ^ x3 ^ *(rk + i); \
x4 = x0 ^ SM4_D[(uint16_t)(x4 >> 16)] ^ \
ROL32(SM4_D[(uint16_t)x4], 16)
#define ROUND ROUND_TBOX
void sm4_encrypt(const SM4_KEY *key, const unsigned char in[16], unsigned char out[16])
{
const uint32_t *rk = key->rk;
uint32_t x0, x1, x2, x3, x4;
uint32_t t0, t1;
x0 = GETU32(in );
x1 = GETU32(in + 4);
x2 = GETU32(in + 8);
x3 = GETU32(in + 12);
ROUNDS(x0, x1, x2, x3, x4);
PUTU32(out , x0);
PUTU32(out + 4, x4);
PUTU32(out + 8, x3);
PUTU32(out + 12, x2);
}
/* caller make sure counter not overflow */
void sm4_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t blocks, const SM4_KEY *key, const unsigned char iv[16])
{
const uint32_t *rk = key->rk;
unsigned int c0 = GETU32(iv );
unsigned int c1 = GETU32(iv + 4);
unsigned int c2 = GETU32(iv + 8);
unsigned int c3 = GETU32(iv + 12);
uint32_t x0, x1, x2, x3, x4;
uint32_t t0, t1;
while (blocks--) {
x0 = c0;
x1 = c1;
x2 = c2;
x3 = c3;
ROUNDS(x0, x1, x2, x3, x4);
PUTU32(out , GETU32(in ) ^ x0);
PUTU32(out + 4, GETU32(in + 4) ^ x4);
PUTU32(out + 8, GETU32(in + 8) ^ x3);
PUTU32(out + 12, GETU32(in + 12) ^ x2);
in += 16;
out += 16;
c3++;
}
}

99
src/sm4_lcl.h Normal file
View File

@@ -0,0 +1,99 @@
/* ====================================================================
* Copyright (c) 2014 - 2019 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_SM4_LCL_H
#define GMSSL_SM4_LCL_H
#include <gmssl/sm4.h>
extern const uint8_t SM4_S[256];
extern const uint32_t SM4_T[256];
extern const uint32_t SM4_D[65536];
#define S32(A) \
((SM4_S[((A) >> 24) ] << 24) ^ \
(SM4_S[((A) >> 16) & 0xff] << 16) ^ \
(SM4_S[((A) >> 8) & 0xff] << 8) ^ \
(SM4_S[((A)) & 0xff]))
#define ROUNDS(x0, x1, x2, x3, x4) \
ROUND(x0, x1, x2, x3, x4, 0); \
ROUND(x1, x2, x3, x4, x0, 1); \
ROUND(x2, x3, x4, x0, x1, 2); \
ROUND(x3, x4, x0, x1, x2, 3); \
ROUND(x4, x0, x1, x2, x3, 4); \
ROUND(x0, x1, x2, x3, x4, 5); \
ROUND(x1, x2, x3, x4, x0, 6); \
ROUND(x2, x3, x4, x0, x1, 7); \
ROUND(x3, x4, x0, x1, x2, 8); \
ROUND(x4, x0, x1, x2, x3, 9); \
ROUND(x0, x1, x2, x3, x4, 10); \
ROUND(x1, x2, x3, x4, x0, 11); \
ROUND(x2, x3, x4, x0, x1, 12); \
ROUND(x3, x4, x0, x1, x2, 13); \
ROUND(x4, x0, x1, x2, x3, 14); \
ROUND(x0, x1, x2, x3, x4, 15); \
ROUND(x1, x2, x3, x4, x0, 16); \
ROUND(x2, x3, x4, x0, x1, 17); \
ROUND(x3, x4, x0, x1, x2, 18); \
ROUND(x4, x0, x1, x2, x3, 19); \
ROUND(x0, x1, x2, x3, x4, 20); \
ROUND(x1, x2, x3, x4, x0, 21); \
ROUND(x2, x3, x4, x0, x1, 22); \
ROUND(x3, x4, x0, x1, x2, 23); \
ROUND(x4, x0, x1, x2, x3, 24); \
ROUND(x0, x1, x2, x3, x4, 25); \
ROUND(x1, x2, x3, x4, x0, 26); \
ROUND(x2, x3, x4, x0, x1, 27); \
ROUND(x3, x4, x0, x1, x2, 28); \
ROUND(x4, x0, x1, x2, x3, 29); \
ROUND(x0, x1, x2, x3, x4, 30); \
ROUND(x1, x2, x3, x4, x0, 31)
#endif

119
src/sm4_setkey.c Normal file
View File

@@ -0,0 +1,119 @@
/* ====================================================================
* Copyright (c) 2014 - 2019 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 <gmssl/sm4.h>
#include "bswap.h"
#include "rotate.h"
#include "sm4_lcl.h"
static uint32_t FK[4] = {
0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc,
};
static uint32_t CK[32] = {
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,
};
#define L32_(x) \
((x) ^ \
ROL32((x), 13) ^ \
ROL32((x), 23))
#define ENC_ROUND(x0, x1, x2, x3, x4, i) \
x4 = x1 ^ x2 ^ x3 ^ *(CK + i); \
x4 = S32(x4); \
x4 = x0 ^ L32_(x4); \
*(rk + i) = x4
#define DEC_ROUND(x0, x1, x2, x3, x4, i) \
x4 = x1 ^ x2 ^ x3 ^ *(CK + i); \
x4 = S32(x4); \
x4 = x0 ^ L32_(x4); \
*(rk + 31 - i) = x4
void sm4_set_encrypt_key(SM4_KEY *key, const unsigned char user_key[16])
{
uint32_t *rk = key->rk;
uint32_t x0, x1, x2, x3, x4;
x0 = GETU32(user_key ) ^ FK[0];
x1 = GETU32(user_key + 4) ^ FK[1];
x2 = GETU32(user_key + 8) ^ FK[2];
x3 = GETU32(user_key + 12) ^ FK[3];
#define ROUND ENC_ROUND
ROUNDS(x0, x1, x2, x3, x4);
#undef ROUND
x0 = x1 = x2 = x3 = x4 = 0;
}
void sm4_set_decrypt_key(SM4_KEY *key, const unsigned char user_key[16])
{
uint32_t *rk = key->rk;
uint32_t x0, x1, x2, x3, x4;
x0 = GETU32(user_key ) ^ FK[0];
x1 = GETU32(user_key + 4) ^ FK[1];
x2 = GETU32(user_key + 8) ^ FK[2];
x3 = GETU32(user_key + 12) ^ FK[3];
#define ROUND DEC_ROUND
ROUNDS(x0, x1, x2, x3, x4);
#undef ROUND
x0 = x1 = x2 = x3 = x4 = 0;
}

75
src/sm9_keygen.c Normal file
View File

@@ -0,0 +1,75 @@
/*
* 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.
*/
int sm9_hash1(bignum_t r, const char *id, size_t idlen, uint8_t hid)
{
bignum_t h;
SM3_CTX ctx1;
SM3_CTX ctx2;
uint8_t prefix[1] = {0x01};
uint8_t ct1[4] = {0x00, 0x00, 0x00, 0x01};
uint8_t ct2[4] = {0x00, 0x00, 0x00, 0x02};
uint8_t buf[64];
sm3_init(&ctx1);
sm3_update(&ctx1, prefix, sizeof(prefix));
sm3_update(&ctx1, id, idlen);
sm3_update(&ctx1, &hid, 1);
memcpy(&ctx2, &ctx1, sizeof(SM3_CTX));
sm3_update(&ctx1, ct1, sizeof(ct1));
sm3_update(&ctx2, ct2, sizeof(ct2));
sm3_finish(&ctx1, buf);
sm3_finish(&ctx2, buf + 32);
}

2032
src/sm9_math.c Normal file

File diff suppressed because it is too large Load Diff

139
src/sm9_sign.c Normal file
View File

@@ -0,0 +1,139 @@
/*
* 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.
*/
int sm9_sign_setup(SM9_SIGN_MASTER_KEY *msk)
{
// rand ks in [1, N-1]
fn_rand(ks);
// Ppubs = ks * P2
twist_point_mul_generator(Ppubs, ks);
}
int sm9_sign_keygen(SM9_SIGN_MASTER_KEY *msk, const char *id, size_t idlen, SM9_POINT *ds)
{
}
int sm9_sign_init(SM3_CTX *ctx)
{
uint8_t prefix[1] = {0x02};
if (!ctx) {
return -1;
}
sm3_init(ctx);
sm3_update(ctx, prefix, sizeof(prefix));
return 0;
}
int sm9_sign_update(SM3_CTX *ctx, const uint8_t *data, size_t datalen)
{
sm3_update(ctx, data, datalen);
return 1;
}
int sm9_sign_finish(SM3_CTX *ctx, SM9_SIGNATURE *sig)
{
fp12_t g;
sm9_pairing(g, SM9_P1, Ppubs);
fn_rand(r);
fp12_pow(w, g, r);
fn_sub(l, r, h);
if (fn_is_zero(l)) {
}
point_mul(S, l, ds);
}
int sm9_verify_init(SM9_SIGN_CTX *ctx)
{
sm3_init(&ctx->sm3_ctx);
sm3_update(&ctx->sm3_ctx, SM9_HASH1_PREFIX, sizeof(SM9_HASH1_PREFIX));
return 0;
}
int sm9_verify_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
{
sm3_update(&ctx->sm3_ctx, data, datalen);
}
int sm9_verify_finish(SM9_SIGN_CTX *ctx, const char *id, size_t idlen, const SM9_SIGNATURE *sig)
{
if (bn_is_zero(h) || bn_cmp(h, SM9_N) >= 0) {
}
if (!point_is_on_curve(S)) {
}
sm9_pairing(g, SM9_P1, Ppubs);
fp12_pow(t, g, h);
sm9_hash1(h1, id, idlen);
twist_point_mul_generator(P, h1);
twist_point_add(P, P, Ppubs);
pairing(u, S, P);
}

936
src/tlcp.c Normal file
View File

@@ -0,0 +1,936 @@
/*
* Copyright (c) 2021 - 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 <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <gmssl/rand.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/sm4.h>
#include <gmssl/pem.h>
#include <gmssl/tls.h>
static const int tlcp_ciphers[] = { TLCP_cipher_ecc_sm4_cbc_sm3 };
static const size_t tlcp_ciphers_count = sizeof(tlcp_ciphers)/sizeof(tlcp_ciphers[0]);
int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *recordlen,
const uint8_t *sig, size_t siglen)
{
int type = TLS_handshake_server_key_exchange;
uint8_t *p = record + 5 + 4;
size_t hslen = 0;
if (!record || !recordlen
|| !sig || !siglen || siglen > 2048) {
error_print();
return -1;
}
if (record[1] != TLCP_VERSION_MAJOR || record[2] != TLCP_VERSION_MINOR) {
error_print();
return -1;
}
tls_array_to_bytes(sig, siglen, &p, &hslen);
tls_record_set_handshake(record, recordlen, type, NULL, hslen);
return 1;
}
int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record,
uint8_t *sig, size_t *siglen)
{
int type;
const uint8_t *p;
size_t len;
if (!record || !sig || !siglen) {
error_print();
return -1;
}
if (tls_record_get_handshake(record, &type, &p, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_server_key_exchange) {
error_print();
return -1;
}
if (record[1] != TLCP_VERSION_MAJOR || record[2] != TLCP_VERSION_MINOR) {
error_print();
return -1;
}
/*
if (tls_uint16array_copy_from_bytes(sig, siglen, *siglen, &p, &len) != 1
|| len > 0) {
error_print();
return -1;
}
*/
// FIXME: check *siglen >= len
memcpy(sig, p, len);
*siglen = len;
return 1;
}
int tlcp_certificate_chain_verify(const uint8_t *data, size_t datalen, FILE *ca_certs_fp, int depth)
{
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;
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) {
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) {
error_print();
return -1;
}
if (x509_name_equ(&sign_cert.tbs_certificate.issuer,
&enc_cert.tbs_certificate.issuer) != 1) {
error_print();
return -1;
}
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) {
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) {
error_print();
return -1;
}
if (tls_certificate_chain_verify(chain, chainlen, ca_certs_fp, depth - 1) != 1) {
error_print();
return -1;
}
} else {
if (x509_certificate_from_pem_by_name(&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;
}
if (x509_certificate_from_pem_by_name(&ca_cert, ca_certs_fp, &enc_cert.tbs_certificate.issuer) != 1
|| x509_certificate_verify_by_certificate(&enc_cert, &ca_cert) != 1) {
error_print();
return -1;
}
}
return 1;
}
int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port,
FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key)
{
uint8_t record[1600];
size_t recordlen;
uint8_t finished[256];
size_t finishedlen;
int type;
const uint8_t *data;
size_t datalen;
uint8_t client_random[32];
uint8_t server_random[32];
const uint8_t *server_enc_cert;
size_t server_enc_cert_len;
SM2_KEY server_enc_key;
SM2_KEY server_sign_key;
SM2_SIGN_CTX verify_ctx; // for server_key_exchange signature verification
SM2_SIGN_CTX sign_ctx; // for certificate_verify signature generation
uint8_t sig[TLS_MAX_SIGNATURE_SIZE];
size_t siglen = sizeof(sig);
uint8_t pre_master_secret[48];
uint8_t enced_pre_master_secret[256];
size_t enced_pre_master_secret_len;
SM3_CTX sm3_ctx;
SM3_CTX tmp_sm3_ctx;
uint8_t sm3_hash[32];
uint8_t verify_data[12];
uint8_t local_verify_data[12];
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr(hostname);
server.sin_family = AF_INET;
server.sin_port = htons(port);
if ((conn->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
error_print();
return -1;
}
if (connect(conn->sock, (struct sockaddr *)&server , sizeof(server)) < 0) {
error_print();
return -1;
}
conn->is_client = 1;
sm3_init(&sm3_ctx);
if (client_sign_key)
sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID);
tls_record_set_version(record, TLS_version_tlcp);
tls_record_set_version(finished, TLS_version_tlcp);
tls_trace(">>>> ClientHello\n");
tls_random_generate(client_random);
if (tls_record_set_handshake_client_hello(record, &recordlen,
TLS_version_tlcp, client_random, NULL, 0,
tlcp_ciphers, tlcp_ciphers_count, NULL, 0) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace("<<<< ServerHello\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_server_hello(record,
&conn->version, server_random, conn->session_id, &conn->session_id_len,
&conn->cipher_suite, NULL, 0) != 1) {
error_print();
return -1;
}
if (conn->version != TLS_version_tlcp) {
error_print();
return -1;
}
if (tls_cipher_suite_in_list(conn->cipher_suite, tlcp_ciphers, tlcp_ciphers_count) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace("<<<< ServerCertificate\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_certificate(record,
conn->server_certs, &conn->server_certs_len) != 1) {
error_print();
return -1;
}
if (tlcp_certificate_chain_verify(conn->server_certs, conn->server_certs_len, ca_certs_fp, 5) != 1) {
error_print();
return -1;
}
if (tls_certificate_get_public_keys(conn->server_certs, conn->server_certs_len,
&server_sign_key, &server_enc_key) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace("<<<< ServerKeyExchange\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
if (tlcp_record_get_handshake_server_key_exchange_pke(record, sig, &siglen) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace("++++ process ServerKeyExchange\n");
if (tls_certificate_get_second(conn->server_certs, conn->server_certs_len,
&server_enc_cert, &server_enc_cert_len) != 1) {
error_print();
return -1;
}
if (sm2_verify_init(&verify_ctx, &server_sign_key, SM2_DEFAULT_ID) != 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) {
error_print();
return -1;
}
if ( sm2_verify_finish(&verify_ctx, sig, siglen) != 1) {
error_print("ServerKeyExchange signature verification failure");
return -1;
}
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp
|| tls_record_get_handshake(record, &type, &data, &datalen) != 1) {
error_print();
return -1;
}
if (type == TLS_handshake_certificate_request) {
tls_trace("<<<< CertificateRequest\n");
int cert_types[TLS_MAX_CERTIFICATE_TYPES];
size_t cert_types_count;;
uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE];
size_t ca_names_len;
if (tls_record_get_handshake_certificate_request(record,
cert_types, &cert_types_count,
ca_names, &ca_names_len) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
} else {
memset(&sign_ctx, 0, sizeof(SM2_SIGN_CTX));
client_sign_key = NULL;
}
tls_trace("<<<< ServerHelloDone\n");
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_server_hello_done(record) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key) {
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace(">>>> ClientCertificate\n");
if (tls_record_set_handshake_certificate_from_pem(record, &recordlen, client_certs_fp) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
}
tls_trace("++++ generate secrets\n");
if (tls_pre_master_secret_generate(pre_master_secret, TLS_version_tlcp) != 1
|| tls_prf(pre_master_secret, 48, "master secret",
client_random, 32, server_random, 32,
48, conn->master_secret) != 1
|| tls_prf(conn->master_secret, 48, "key expansion",
server_random, 32, client_random, 32,
96, conn->key_block) != 1) {
error_print();
return -1;
}
sm3_hmac_init(&conn->client_write_mac_ctx, conn->key_block, 32);
sm3_hmac_init(&conn->server_write_mac_ctx, conn->key_block + 32, 32);
sm4_set_encrypt_key(&conn->client_write_enc_key, conn->key_block + 64);
sm4_set_decrypt_key(&conn->server_write_enc_key, conn->key_block + 80);
format_bytes(stderr, 0, 0, "pre_master_secret : ", pre_master_secret, 48);
format_bytes(stderr, 0, 0, "master_secret : ", conn->master_secret, 48);
format_bytes(stderr, 0, 0, "client_write_mac_key : ", conn->key_block, 32);
format_bytes(stderr, 0, 0, "server_write_mac_key : ", conn->key_block + 32, 32);
format_bytes(stderr, 0, 0, "client_write_enc_key : ", conn->key_block + 64, 16);
format_bytes(stderr, 0, 0, "server_write_enc_key : ", conn->key_block + 80, 16);
format_print(stderr, 0, 0, "\n");
tls_trace(">>>> ClientKeyExchange\n");
if (sm2_encrypt(&server_enc_key, pre_master_secret, 48,
enced_pre_master_secret, &enced_pre_master_secret_len) != 1) {
error_print();
return -1;
}
if (tls_record_set_handshake_client_key_exchange_pke(record, &recordlen,
enced_pre_master_secret, enced_pre_master_secret_len) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
if (client_sign_key) {
tls_trace(">>>> CertificateVerify\n");
sm2_sign_finish(&sign_ctx, sig, &siglen);
if (tls_record_set_handshake_certificate_verify(record, &recordlen, sig, siglen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
}
tls_trace(">>>> [ChangeCipherSpec]\n");
if (tls_record_set_change_cipher_spec(record, &recordlen) !=1) {
error_print();
return -1;
}
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
tls_trace(">>>> Finished\n");
memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(sm3_ctx));
sm3_finish(&tmp_sm3_ctx, sm3_hash);
if (tls_prf(conn->master_secret, 48, "client finished",
sm3_hash, 32, NULL, 0,
sizeof(verify_data), verify_data) != 1) {
error_print();
return -1;
}
if (tls_record_set_handshake_finished(finished, &finishedlen, verify_data) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
sm3_update(&sm3_ctx, finished + 5, finishedlen - 5);
if (tls_record_encrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key,
conn->client_seq_num, finished, finishedlen, record, &recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_trace("<<<< [ChangeCipherSpec]\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
if (tls_record_get_change_cipher_spec(record) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
tls_trace("<<<< Finished\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
if (tls_record_decrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key,
conn->server_seq_num, record, recordlen, finished, &finishedlen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
tls_seq_num_incr(conn->server_seq_num);
if (tls_record_get_handshake_finished(finished, verify_data) != 1) {
error_print();
return -1;
}
sm3_finish(&sm3_ctx, sm3_hash);
if (tls_prf(conn->master_secret, 48, "server finished",
sm3_hash, 32, NULL, 0,
sizeof(local_verify_data), local_verify_data) != 1) {
error_print();
return -1;
}
if (memcmp(local_verify_data, verify_data, 12) != 0) {
error_print("server_finished.verify_data verification failure");
return -1;
}
tls_trace("++++ Connection established\n");
return 1;
}
int tlcp_accept(TLS_CONNECT *conn, int port,
FILE *certs_fp, const SM2_KEY *server_sign_key, const SM2_KEY *server_enc_key,
FILE *client_cacerts_fp, uint8_t *handshakes_buf, size_t handshakes_buflen)
{
uint8_t *handshakes = handshakes_buf;
size_t handshakeslen = 0;
uint8_t record[TLS_MAX_RECORD_SIZE];
size_t recordlen;
uint8_t finished[256];
size_t finishedlen = sizeof(finished);
uint8_t client_random[32];
uint8_t server_random[32];
uint8_t session_id[32];
size_t session_id_len;
int client_ciphers[12] = {0};
size_t client_ciphers_count = sizeof(client_ciphers)/sizeof(client_ciphers[0]);
const uint8_t *server_enc_cert;
size_t server_enc_certlen;
SM2_KEY client_sign_key;
SM2_SIGN_CTX sign_ctx;
uint8_t sig[TLS_MAX_SIGNATURE_SIZE];
size_t siglen = sizeof(sig);
uint8_t enced_pms[256];
size_t enced_pms_len = sizeof(enced_pms);
uint8_t pre_master_secret[48];
size_t pre_master_secret_len = 48;
SM3_CTX sm3_ctx;
SM3_CTX tmp_sm3_ctx;
uint8_t sm3_hash[32];
uint8_t verify_data[12];
uint8_t local_verify_data[12];
size_t i;
int sock;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t client_addrlen;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
error_print();
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
error_print();
return -1;
}
error_print("start listen ...");
listen(sock, 5);
memset(conn, 0, sizeof(*conn));
client_addrlen = sizeof(client_addr);
if ((conn->sock = accept(sock, (struct sockaddr *)&client_addr, &client_addrlen)) < 0) {
error_print();
return -1;
}
error_print("connected\n");
sm3_init(&sm3_ctx);
tls_trace("<<<< ClientHello\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_client_hello(record,
&conn->version, client_random, session_id, &session_id_len,
client_ciphers, &client_ciphers_count, NULL, 0) != 1) {
error_print();
return -1;
}
if (conn->version != TLS_version_tlcp) {
error_print();
return -1;
}
for (i = 0; i < tlcp_ciphers_count; i++) {
if (tls_cipher_suite_in_list(tlcp_ciphers[i], client_ciphers, client_ciphers_count) == 1) {
conn->cipher_suite = tlcp_ciphers[i];
break;
}
}
if (conn->cipher_suite == 0) {
error_print("no common cipher_suite");
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
tls_trace(">>>> ServerHello\n");
tls_random_generate(server_random);
if (tls_record_set_handshake_server_hello(record, &recordlen,
TLS_version_tlcp, server_random, NULL, 0,
conn->cipher_suite, NULL, 0) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
tls_trace(">>>> ServerCertificate\n");
if (tls_record_set_handshake_certificate_from_pem(record, &recordlen, certs_fp) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
if (tls_record_get_handshake_certificate(record, conn->server_certs, &conn->server_certs_len) != 1
|| tls_certificate_get_second(conn->server_certs, conn->server_certs_len,
&server_enc_cert, &server_enc_certlen) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
tls_trace(">>>> ServerKeyExchange\n");
if (sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID) != 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
|| sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) {
error_print();
return -1;
}
if (tlcp_record_set_handshake_server_key_exchange_pke(record, &recordlen, sig, siglen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
if (client_cacerts_fp) {
tls_trace(">>>> CertificateRequest\n");
const int cert_types[] = { TLS_cert_type_ecdsa_sign, };
uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE] = {0};
size_t cert_types_count = sizeof(cert_types)/sizeof(cert_types[0]);
size_t ca_names_len = 0;
if (tls_record_set_handshake_certificate_request(record, &recordlen,
cert_types, cert_types_count,
ca_names, ca_names_len) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
}
tls_trace(">>>> ServerHelloDone\n");
if (tls_record_set_handshake_server_hello_done(record, &recordlen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
if (handshakes) {
tls_trace("<<<< ClientCertificate\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_certificate(record,
conn->client_certs, &conn->client_certs_len) != 1) {
error_print();
return -1;
}
// FIXME: verify client's certificate with ca certs
if (tls_certificate_get_public_keys(conn->client_certs, conn->client_certs_len,
&client_sign_key, NULL) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
tls_trace("<<<< ClientKeyExchange\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
if (tls_record_get_handshake_client_key_exchange_pke(record, enced_pms, &enced_pms_len) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
if (sm2_decrypt(server_enc_key, enced_pms, enced_pms_len,
pre_master_secret, &pre_master_secret_len) != 1) {
error_print();
return -1;
}
if (handshakes) {
tls_trace("<<<< CertificateVerify\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_certificate_verify(record, sig, &siglen) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
sm2_verify_init(&sign_ctx, &client_sign_key, SM2_DEFAULT_ID);
sm2_verify_update(&sign_ctx, handshakes_buf, handshakeslen);
if (sm2_verify_finish(&sign_ctx, sig, siglen) != 1) {
error_print();
return -1;
}
}
tls_trace("++++ generate secrets\n");
if (tls_prf(pre_master_secret, 48, "master secret",
client_random, 32, server_random, 32,
48, conn->master_secret) != 1) {
error_print();
return -1;
}
if (tls_prf(conn->master_secret, 48, "key expansion",
server_random, 32, client_random, 32,
96, conn->key_block) != 1) {
error_print();
return -1;
}
sm3_hmac_init(&conn->client_write_mac_ctx, conn->key_block, 32);
sm3_hmac_init(&conn->server_write_mac_ctx, conn->key_block + 32, 32);
sm4_set_decrypt_key(&conn->client_write_enc_key, conn->key_block + 64);
sm4_set_encrypt_key(&conn->server_write_enc_key, conn->key_block + 80);
format_bytes(stderr, 0, 0, "pre_master_secret : ", pre_master_secret, 48);
format_bytes(stderr, 0, 0, "master_secret : ", conn->master_secret, 48);
format_bytes(stderr, 0, 0, "client_write_mac_key : ", conn->key_block, 32);
format_bytes(stderr, 0, 0, "server_write_mac_key : ", conn->key_block + 32, 32);
format_bytes(stderr, 0, 0, "client_write_enc_key : ", conn->key_block + 64, 16);
format_bytes(stderr, 0, 0, "server_write_enc_key : ", conn->key_block + 80, 16);
format_print(stderr, 0, 0, "\n");
tls_trace("<<<< [ChangeCipherSpec]\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_change_cipher_spec(record) != 1) {
error_print();
return -1;
}
tls_trace("<<<< ClientFinished\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tlcp) {
error_print();
return -1;
}
if (tls_record_decrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key,
conn->client_seq_num, record, recordlen, finished, &finishedlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
if (tls_record_get_handshake_finished(finished, verify_data) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(SM3_CTX));
sm3_update(&sm3_ctx, finished + 5, finishedlen - 5);
sm3_finish(&tmp_sm3_ctx, sm3_hash);
if (tls_prf(conn->master_secret, 48, "client finished", sm3_hash, 32, NULL, 0,
12, local_verify_data) != 1) {
error_print();
return -1;
}
if (memcmp(local_verify_data, verify_data, 12) != 0) {
error_print("client_finished.verify_data verification failure");
return -1;
}
tls_trace(">>>> [ChangeCipherSpec]\n");
if (tls_record_set_change_cipher_spec(record, &recordlen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_trace(">>>> ServerFinished\n");
sm3_finish(&sm3_ctx, sm3_hash);
if (tls_prf(conn->master_secret, 48, "server finished", sm3_hash, 32, NULL, 0,
12, verify_data) != 1) {
error_print();
return -1;
}
if (tls_record_set_handshake_finished(finished, &finishedlen, verify_data) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
if (tls_record_encrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key,
conn->server_seq_num, finished, finishedlen, record, &recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_trace("Connection Established!\n\n");
return 1;
}

1361
src/tls.c Normal file

File diff suppressed because it is too large Load Diff

971
src/tls12.c Normal file
View File

@@ -0,0 +1,971 @@
/*
* Copyright (c) 2021 - 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 <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <gmssl/rand.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/sm4.h>
#include <gmssl/pem.h>
#include <gmssl/tls.h>
static const int tls12_ciphers[] = {
GMSSL_cipher_ecdhe_sm2_with_sm4_sm3,
};
static const size_t tls12_ciphers_count = sizeof(tls12_ciphers)/sizeof(tls12_ciphers[0]);
static const uint8_t tls12_exts[] = {
/* supported_groups */ 0x00,0x0A, 0x00,0x04, 0x00,0x02, 0x00,30,//0x29, // curveSM2
/* ec_point_formats */ 0x00,0x0B, 0x00,0x02, 0x01, 0x00, // uncompressed
/* signature_algors */ 0x00,0x0D, 0x00,0x04, 0x00,0x02, 0x07,0x07,//0x08, // sm2sig_sm3
};
/*
int tls_server_extensions_check(const uint8_t *exts, size_t extslen)
{
return -1;
}
int tls_construct_server_extensions(const uint8_t *client_exts, size_t client_exts_len,
uint8_t *server_exts, size_t *server_exts_len)
{
uint16_t type;
const uint8_t *p;
size_t len;
while (client_exts_len) {
if (tls_uint16_from_bytes(&ext_type, &client_exts, &client_exts_len) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &client_exts, &client_exts_len) != 1) {
error_print();
return -1;
}
}
}
*/
int tls_record_set_handshake_server_key_exchange_ecdhe(uint8_t *record, size_t *recordlen,
int curve, const SM2_POINT *point, const uint8_t *sig, size_t siglen)
{
int type = TLS_handshake_server_key_exchange;
uint8_t *server_ecdh_params = record + 9;
uint8_t *p = server_ecdh_params + 69;
size_t len = 69;
if (!record || !recordlen || !tls_named_curve_name(curve) || !point
|| !sig || !siglen || siglen > TLS_MAX_SIGNATURE_SIZE) {
error_print();
return -1;
}
server_ecdh_params[0] = TLS_curve_type_named_curve;
server_ecdh_params[1] = curve >> 8;
server_ecdh_params[2] = curve;
server_ecdh_params[3] = 65;
sm2_point_to_uncompressed_octets(point, server_ecdh_params + 4);
tls_uint16_to_bytes(TLS_sig_sm2sig_sm3, &p, &len);
tls_uint16array_to_bytes(sig, siglen, &p, &len);
tls_record_set_handshake(record, recordlen, type, NULL, len);
return 1;
}
int tls_record_get_handshake_server_key_exchange_ecdhe(const uint8_t *record,
int *curve, SM2_POINT *point, uint8_t *sig, size_t *siglen)
{
int type;
const uint8_t *p;
size_t len;
uint8_t curve_type;
const uint8_t *octets;
size_t octetslen;
uint16_t sig_alg;
if (!record || !curve || !point || !sig || !siglen) {
error_print();
return -1;
}
if (tls_record_get_handshake(record, &type, &p, &len) != 1
|| type != TLS_handshake_server_key_exchange) {
error_print();
return -1;
}
*curve = 0;
if (tls_uint8_from_bytes(&curve_type, &p, &len) != 1
|| tls_uint16_from_bytes((uint16_t *)curve, &p, &len) != 1
|| tls_uint8array_from_bytes(&octets, &octetslen, &p, &len) != 1
|| tls_uint16_from_bytes(&sig_alg, &p, &len) != 1
|| tls_uint16array_copy_from_bytes(sig, siglen, TLS_MAX_SIGNATURE_SIZE, &p, &len) != 1
|| len > 0) {
error_print();
return -1;
}
if (curve_type != TLS_curve_type_named_curve
|| *curve != TLS_curve_sm2p256v1
|| octetslen != 65
|| sm2_point_from_octets(point, octets, octetslen) != 1) {
error_print();
return -1;
}
if (sig_alg != TLS_sig_sm2sig_sm3) {
error_print();
return -1;
}
return 1;
}
int tls_record_set_handshake_client_key_exchange_ecdhe(uint8_t *record, size_t *recordlen,
const SM2_POINT *point)
{
int type = TLS_handshake_client_key_exchange;
record[9] = 65;
sm2_point_to_uncompressed_octets(point, record + 9 + 1);
tls_record_set_handshake(record, recordlen, type, NULL, 1 + 65);
return 1;
}
int tls_record_get_handshake_client_key_exchange_ecdhe(const uint8_t *record, SM2_POINT *point)
{
int type;
const uint8_t *p;
size_t len;
const uint8_t *octets;
size_t octetslen;
if (tls_record_get_handshake(record, &type, &p, &len) != 1
|| type != TLS_handshake_client_key_exchange) {
error_print();
return -1;
}
if (tls_uint8array_from_bytes(&octets, &octetslen, &p, &len) != 1
|| len > 0) {
error_print();
return -1;
}
if (octetslen != 65
|| sm2_point_from_octets(point, octets, octetslen) != 1) {
error_print();
return -1;
}
return 1;
}
int tls12_record_recv(uint8_t *record, size_t *recordlen, int sock)
{
if (tls_record_recv(record, recordlen, sock) != 1) {
error_print();
return -1;
}
if (tls_record_version(record) != TLS_version_tls12) {
error_print();
return -1;
}
return 1;
}
int tls12_connect(TLS_CONNECT *conn, const char *hostname, int port,
FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key)
{
uint8_t *record = conn->record;
size_t recordlen;
uint8_t finished[256];
size_t finishedlen;
int type;
const uint8_t *data;
size_t datalen;
uint8_t client_random[32];
uint8_t server_random[32];
uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
size_t exts_len;
SM2_KEY server_sign_key;
SM2_SIGN_CTX verify_ctx;
SM2_SIGN_CTX sign_ctx; // for certificate_verify signature generation
uint8_t sig[TLS_MAX_SIGNATURE_SIZE];
size_t siglen = sizeof(sig);
int curve;
SM2_KEY client_ecdh;
SM2_POINT server_ecdh_public;
uint8_t pre_master_secret[64];
SM3_CTX sm3_ctx;
SM3_CTX tmp_sm3_ctx;
uint8_t sm3_hash[32];
uint8_t verify_data[12];
uint8_t local_verify_data[12];
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr(hostname);
server.sin_family = AF_INET;
server.sin_port = htons(port);
sm3_init(&sm3_ctx);
if (client_sign_key)
sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID);
tls_record_set_version(record, TLS_version_tls1);
tls_record_set_version(finished, TLS_version_tls12);
if ((conn->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
error_print();
return -1;
}
if (connect(conn->sock, (struct sockaddr *)&server , sizeof(server)) < 0) {
error_print();
return -1;
}
conn->is_client = 1;
tls_trace(">>>> ClientHello\n");
tls_random_generate(client_random);
if (tls_record_set_handshake_client_hello(record, &recordlen,
TLS_version_tls12, client_random, NULL, 0,
tls12_ciphers, tls12_ciphers_count, tls12_exts, sizeof(tls12_exts)) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace("<<<< ServerHello\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_server_hello(record,
&conn->version, server_random, conn->session_id, &conn->session_id_len,
&conn->cipher_suite, exts, &exts_len) != 1) {
error_print();
return -1;
}
if (conn->version != TLS_version_tls12) {
error_print();
return -1;
}
if (tls_cipher_suite_in_list(conn->cipher_suite, tls12_ciphers, tls12_ciphers_count) != 1) {
error_print();
return -1;
}
// FIXME: check extensions
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace("<<<< ServerCertificate\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_certificate(record, conn->server_certs, &conn->server_certs_len) != 1) {
error_print();
return -1;
}
/*
// FIXME: review cert chain verification
if (tls_certificate_chain_verify(conn->server_certs, conn->server_certs_len, ca_certs_fp, 5) != 1) {
error_print();
return -1;
}
*/
if (tls_certificate_get_public_keys(conn->server_certs, conn->server_certs_len,
&server_sign_key, NULL) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace("<<<< ServerKeyExchange\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
if (tls_record_get_handshake_server_key_exchange_ecdhe(record, &curve, &server_ecdh_public, sig, &siglen) != 1) {
error_print();
return -1;
}
if (curve != TLS_curve_sm2p256v1) {
error_print();
return -1;
}
if (tls_verify_server_ecdh_params(&server_sign_key,
client_random, server_random, curve, &server_ecdh_public, sig, siglen) != 1) {
error_print();
return -1;
}
tls_trace("++++ generate secrets\n");
sm2_keygen(&client_ecdh);
sm2_ecdh(&client_ecdh, &server_ecdh_public, &server_ecdh_public);
memcpy(pre_master_secret, &server_ecdh_public, 32);
tls_prf(pre_master_secret, 32, "master secret",
client_random, 32,
server_random, 32,
48, conn->master_secret);
tls_prf(conn->master_secret, 48, "key expansion",
server_random, 32,
client_random, 32,
96, conn->key_block);
sm3_hmac_init(&conn->client_write_mac_ctx, conn->key_block, 32);
sm3_hmac_init(&conn->server_write_mac_ctx, conn->key_block + 32, 32);
sm4_set_encrypt_key(&conn->client_write_enc_key, conn->key_block + 64);
sm4_set_decrypt_key(&conn->server_write_enc_key, conn->key_block + 80);
tls_secrets_print(stderr, pre_master_secret, 32, client_random, server_random,
conn->master_secret, conn->key_block, 96, 0, 0);
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake(record, &type, &data, &datalen) != 1) {
error_print();
return -1;
}
if (type == TLS_handshake_certificate_request) {
tls_trace("<<<< CertificateRequest\n");
int cert_types[TLS_MAX_CERTIFICATE_TYPES];
size_t cert_types_count;;
uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE];
size_t ca_names_len;
if (tls_record_get_handshake_certificate_request(record,
cert_types, &cert_types_count,
ca_names, &ca_names_len) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
if (tls_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
} else {
memset(&sign_ctx, 0, sizeof(SM2_SIGN_CTX));
client_sign_key = NULL;
}
tls_trace("<<<< ServerHelloDone\n");
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_server_hello_done(record) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key) {
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
tls_trace(">>>> ClientCertificate\n");
if (tls_record_set_handshake_certificate_from_pem(record, &recordlen, client_certs_fp) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
}
tls_trace(">>>> ClientKeyExchange\n");
// 客户端的临时公钥
if (tls_record_set_handshake_client_key_exchange_ecdhe(record, &recordlen,
&client_ecdh.public_key) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (client_sign_key)
sm2_sign_update(&sign_ctx, record + 5, recordlen - 5);
if (client_sign_key) {
tls_trace(">>>> CertificateVerify\n");
sm2_sign_finish(&sign_ctx, sig, &siglen);
if (tls_record_set_handshake_certificate_verify(record, &recordlen, sig, siglen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
}
tls_trace(">>>> [ChangeCipherSpec]\n");
if (tls_record_set_change_cipher_spec(record, &recordlen) !=1) {
error_print();
return -1;
}
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
tls_trace(">>>> Finished\n");
memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(sm3_ctx));
sm3_finish(&tmp_sm3_ctx, sm3_hash);
tls_prf(conn->master_secret, 48, "client finished",
sm3_hash, 32, NULL, 0,
sizeof(verify_data), verify_data);
if (tls_record_set_handshake_finished(finished, &finishedlen, verify_data) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
sm3_update(&sm3_ctx, finished + 5, finishedlen - 5);
if (tls_record_encrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key,
conn->client_seq_num, finished, finishedlen, record, &recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_trace("<<<< [ChangeCipherSpec]\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_change_cipher_spec(record) != 1) {
error_print();
return -1;
}
tls_trace("<<<< Finished\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
if (tls_record_decrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key,
conn->server_seq_num, record, recordlen, finished, &finishedlen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
tls_seq_num_incr(conn->server_seq_num);
if (tls_record_get_handshake_finished(finished, verify_data) != 1) {
error_print();
return -1;
}
sm3_finish(&sm3_ctx, sm3_hash);
tls_prf(conn->master_secret, 48, "server finished",
sm3_hash, 32, NULL, 0,
12, local_verify_data);
if (memcmp(local_verify_data, verify_data, 12) != 0) {
error_print("server_finished.verify_data verification failure");
return -1;
}
tls_trace("++++ Connection established\n");
return 1;
}
// 实际上我们需要好几个比较大的buffer
// 一个是记录的buffer
// 还有就是server端需要一个握手buffer
int tls12_accept(TLS_CONNECT *conn, int port,
FILE *server_certs_fp, const SM2_KEY *server_sign_key,
FILE *client_cacerts_fp, uint8_t *handshakes_buf, size_t handshakes_buflen)
{
uint8_t *handshakes = handshakes_buf;
size_t handshakeslen = 0;
uint8_t *record = conn->record;
size_t recordlen;
uint8_t finished[256];
size_t finishedlen = sizeof(finished);
uint8_t client_random[32];
uint8_t server_random[32];
uint8_t session_id[32];
size_t session_id_len;
int client_ciphers[12] = {0};
size_t client_ciphers_count = sizeof(client_ciphers)/sizeof(client_ciphers[0]);
uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
size_t exts_len;
SM2_KEY client_sign_key;
SM2_KEY server_ecdh;
SM2_POINT client_ecdh_public;
SM2_SIGN_CTX sign_ctx;
uint8_t sig[TLS_MAX_SIGNATURE_SIZE];
size_t siglen = sizeof(sig);
uint8_t pre_master_secret[64];
SM3_CTX sm3_ctx;
SM3_CTX tmp_sm3_ctx;
uint8_t sm3_hash[32];
uint8_t verify_data[12];
uint8_t local_verify_data[12];
size_t i;
int sock;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t client_addrlen;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
error_print();
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
error_print();
return -1;
}
error_print("start listen ...");
listen(sock, 5);
memset(conn, 0, sizeof(*conn));
client_addrlen = sizeof(client_addr);
if ((conn->sock = accept(sock, (struct sockaddr *)&client_addr, &client_addrlen)) < 0) {
error_print();
return -1;
}
error_print("connected\n");
sm3_init(&sm3_ctx);
tls_trace("<<<< ClientHello\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_version(record) != TLS_version_tls1
&& tls_record_version(record) != TLS_version_tls12) {
error_print();
return -1;
}
if (tls_record_get_handshake_client_hello(record,
&conn->version, client_random, session_id, &session_id_len,
client_ciphers, &client_ciphers_count, exts, &exts_len) != 1) {
error_print();
return -1;
}
if (conn->version != TLS_version_tls12) {
error_print();
return -1;
}
for (i = 0; i < tls12_ciphers_count; i++) {
if (tls_cipher_suite_in_list(tls12_ciphers[i], client_ciphers, client_ciphers_count) == 1) {
conn->cipher_suite = tls12_ciphers[i];
break;
}
}
if (conn->cipher_suite == 0) {
error_print("no common cipher_suite");
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
tls_array_to_bytes(record + 5, recordlen - 5, &handshakes, &handshakeslen);
if (handshakes) {
/*
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
*/
}
tls_trace(">>>> ServerHello\n");
tls_random_generate(server_random);
tls_record_set_version(record, conn->version);
if (tls_record_set_handshake_server_hello(record, &recordlen,
conn->version, server_random, NULL, 0,
conn->cipher_suite, exts, exts_len) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
if (handshakes) {
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
}
tls_trace(">>>> ServerCertificate\n");
if (tls_record_set_handshake_certificate_from_pem(record, &recordlen, server_certs_fp) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
if (tls_record_get_handshake_certificate(record, conn->server_certs, &conn->server_certs_len) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
tls_array_to_bytes(record + 5, recordlen - 5, &handshakes, &handshakeslen);
if (handshakes) {
/*
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
*/
}
tls_trace(">>>> ServerKeyExchange\n");
sm2_keygen(&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) {
error_print();
return -1;
}
if (tls_record_set_handshake_server_key_exchange_ecdhe(record, &recordlen,
TLS_curve_sm2p256v1, &server_ecdh.public_key, sig, siglen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
tls_array_to_bytes(record + 5, recordlen - 5, &handshakes, &handshakeslen);
if (handshakes) {
/*
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
*/
}
if (client_cacerts_fp) {
tls_trace(">>>> CertificateRequest\n");
const int cert_types[] = { TLS_cert_type_ecdsa_sign, };
uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE] = {0};
size_t cert_types_count = sizeof(cert_types)/sizeof(cert_types[0]);
size_t ca_names_len = 0;
if (tls_record_set_handshake_certificate_request(record, &recordlen,
cert_types, cert_types_count,
ca_names, ca_names_len) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
tls_array_to_bytes(record + 5, recordlen - 5, &handshakes, &handshakeslen);
if (handshakes) {
/*
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
*/
}
}
tls_trace(">>>> ServerHelloDone\n");
if (tls_record_set_handshake_server_hello_done(record, &recordlen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
tls_array_to_bytes(record + 5, recordlen - 5, &handshakes, &handshakeslen);
if (handshakes) {
/*
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
*/
}
if (handshakes) {
tls_trace("<<<< ClientCertificate\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_version(record) != TLS_version_tls12) {
error_print();
return -1;
}
if (tls_record_get_handshake_certificate(record,
conn->client_certs, &conn->client_certs_len) != 1) {
error_print();
return -1;
}
// FIXME: verify client's certificate with ca certs
if (tls_certificate_get_public_keys(conn->client_certs, conn->client_certs_len,
&client_sign_key, NULL) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
tls_array_to_bytes(record + 5, recordlen - 5, &handshakes, &handshakeslen);
/*
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
*/
}
tls_trace("<<<< ClientKeyExchange\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0);
if (tls_record_get_handshake_client_key_exchange_ecdhe(record, &client_ecdh_public) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
tls_array_to_bytes(record + 5, recordlen - 5, &handshakes, &handshakeslen);
if (handshakes) {
/*
memcpy(handshakes, record + 5, recordlen - 5);
handshakes += recordlen - 5;
handshakeslen += recordlen - 5;
*/
}
tls_trace("++++ generate secrets\n");
sm2_ecdh(&server_ecdh, &client_ecdh_public, (SM2_POINT *)pre_master_secret);
tls_prf(pre_master_secret, 32, "master secret",
client_random, 32, server_random, 32,
48, conn->master_secret);
tls_prf(conn->master_secret, 48, "key expansion",
server_random, 32, client_random, 32,
96, conn->key_block);
sm3_hmac_init(&conn->client_write_mac_ctx, conn->key_block, 32);
sm3_hmac_init(&conn->server_write_mac_ctx, conn->key_block + 32, 32);
sm4_set_decrypt_key(&conn->client_write_enc_key, conn->key_block + 64);
sm4_set_encrypt_key(&conn->server_write_enc_key, conn->key_block + 80);
tls_secrets_print(stderr, pre_master_secret, 32, client_random, server_random,
conn->master_secret, conn->key_block, 96, 0, 0);
if (handshakes) {
tls_trace("<<<< CertificateVerify\n");
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|| tls_record_version(record) != TLS_version_tls12) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_handshake_certificate_verify(record, sig, &siglen) != 1) {
error_print();
return -1;
}
sm3_update(&sm3_ctx, record + 5, recordlen - 5);
sm2_verify_init(&sign_ctx, &client_sign_key, SM2_DEFAULT_ID);
sm2_verify_update(&sign_ctx, handshakes_buf, handshakeslen);
if (sm2_verify_finish(&sign_ctx, sig, siglen) != 1) {
error_print();
return -1;
}
}
tls_trace("<<<< [ChangeCipherSpec]\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_get_change_cipher_spec(record) != 1) {
error_print();
return -1;
}
tls_trace("<<<< ClientFinished\n");
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
error_print();
return -1;
}
if (tls_record_decrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key,
conn->client_seq_num, record, recordlen, finished, &finishedlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
if (tls_record_get_handshake_finished(finished, verify_data) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(SM3_CTX));
sm3_update(&sm3_ctx, finished + 5, finishedlen - 5);
sm3_finish(&tmp_sm3_ctx, sm3_hash);
tls_prf(conn->master_secret, 48, "client finished",
sm3_hash, 32, NULL, 0,
12, local_verify_data);
if (memcmp(local_verify_data, verify_data, 12) != 0) {
error_print("client_finished.verify_data verification failure");
return -1;
}
tls_trace(">>>> [ChangeCipherSpec]\n");
if (tls_record_set_change_cipher_spec(record, &recordlen) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, record, recordlen, 0, 0);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_trace(">>>> ServerFinished\n");
sm3_finish(&sm3_ctx, sm3_hash);
tls_prf(conn->master_secret, 48, "server finished",
sm3_hash, 32, NULL, 0,
12, verify_data);
if (tls_record_set_handshake_finished(finished, &finishedlen, verify_data) != 1) {
error_print();
return -1;
}
tls_record_print(stderr, finished, finishedlen, 0, 0);
if (tls_record_encrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key,
conn->server_seq_num, finished, finishedlen, record, &recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
if (tls_record_send(record, recordlen, conn->sock) != 1) {
error_print();
return -1;
}
tls_trace("Connection Established!\n\n");
return 1;
}

73
src/tls13.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2021 - 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 <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <gmssl/rand.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/sm4.h>
#include <gmssl/pem.h>
#include <gmssl/tls.h>

283
src/tls_cipher.c Normal file
View File

@@ -0,0 +1,283 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <gmssl/tls.h>
#include <gmssl/x509.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
int tls_prf(const uint8_t *secret, size_t secretlen, const char *label,
const uint8_t *seed, size_t seedlen,
const uint8_t *more, size_t morelen,
size_t outlen, uint8_t *out)
{
SM3_HMAC_CTX inited_hmac_ctx;
SM3_HMAC_CTX hmac_ctx;
uint8_t A[32];
uint8_t hmac[32];
size_t len;
if (!secret || !secretlen || !label || !seed || !seedlen
|| (!more && morelen) || !outlen || !out) {
error_print();
return -1;
}
sm3_hmac_init(&inited_hmac_ctx, secret, secretlen);
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
sm3_hmac_update(&hmac_ctx, seed, seedlen);
sm3_hmac_update(&hmac_ctx, more, morelen);
sm3_hmac_finish(&hmac_ctx, A);
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
sm3_hmac_update(&hmac_ctx, seed, seedlen);
sm3_hmac_update(&hmac_ctx, more, morelen);
sm3_hmac_finish(&hmac_ctx, hmac);
len = outlen < sizeof(hmac) ? outlen : sizeof(hmac);
memcpy(out, hmac, len);
out += len;
outlen -= len;
while (outlen) {
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
sm3_hmac_finish(&hmac_ctx, A);
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
sm3_hmac_update(&hmac_ctx, seed, seedlen);
sm3_hmac_update(&hmac_ctx, more, morelen);
sm3_hmac_finish(&hmac_ctx, hmac);
len = outlen < sizeof(hmac) ? outlen : sizeof(hmac);
memcpy(out, hmac, len);
out += len;
outlen -= len;
}
return 1;
}
int tls_cbc_encrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *enc_key,
const uint8_t seq_num[8], const uint8_t header[5],
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
{
SM3_HMAC_CTX hmac_ctx;
uint8_t last_blocks[32 + 16] = {0};
uint8_t *mac, *padding, *iv;
int rem, padding_len;
int i;
if (!inited_hmac_ctx || !enc_key || !seq_num || !header || (!in && inlen) || !out || !outlen) {
error_print();
return -1;
}
if (inlen > (1 << 14)) {
error_print("invalid tls record data length %zu\n", inlen);
return -1;
}
rem = (inlen + 32) % 16;
memcpy(last_blocks, in + inlen - rem, rem);
mac = last_blocks + rem;
memcpy(&hmac_ctx, inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
sm3_hmac_update(&hmac_ctx, seq_num, 8);
sm3_hmac_update(&hmac_ctx, header, 5);
sm3_hmac_update(&hmac_ctx, in, inlen);
sm3_hmac_finish(&hmac_ctx, mac);
padding = mac + 32;
padding_len = 16 - rem - 1;
for (i = 0; i <= padding_len; i++) {
padding[i] = padding_len;
}
iv = out;
if (rand_bytes(iv, 16) != 1) {
error_print();
return -1;
}
out += 16;
if (inlen >= 16) {
sm4_cbc_encrypt(enc_key, iv, in, inlen/16, out);
out += inlen - rem;
iv = out - 16;
}
sm4_cbc_encrypt(enc_key, iv, last_blocks, sizeof(last_blocks)/16, out);
*outlen = 16 + inlen - rem + sizeof(last_blocks);
return 1;
}
int tls_cbc_decrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *dec_key,
const uint8_t seq_num[8], const uint8_t enced_header[5],
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
{
SM3_HMAC_CTX hmac_ctx;
const uint8_t *iv;
const uint8_t *padding;
const uint8_t *mac;
uint8_t header[5];
int padding_len;
int i;
if (!inited_hmac_ctx || !dec_key || !seq_num || !enced_header || !in || !inlen || !out || !outlen) {
error_print();
return -1;
}
if (inlen % 16
|| inlen < (16 + 0 + 32 + 16) // iv + data + mac + padding
|| inlen > (16 + (1<<14) + 32 + 256)) {
error_print("invalid tls cbc ciphertext length %zu\n", inlen);
return -1;
}
iv = in;
in += 16;
inlen -= 16;
sm4_cbc_decrypt(dec_key, iv, in, inlen/16, out);
padding_len = out[inlen - 1];
padding = out + inlen - padding_len - 1;
if (padding < out + 32) {
error_print();
return -1;
}
for (i = 0; i < padding_len; i++) {
if (padding[i] != padding_len) {
error_print("tls ciphertext cbc-padding check failure");
return -1;
}
}
*outlen = inlen - 32 - padding_len - 1;
header[0] = enced_header[0];
header[1] = enced_header[1];
header[2] = enced_header[2];
header[3] = (*outlen) >> 8;
header[4] = (*outlen);
mac = padding - 32;
memcpy(&hmac_ctx, inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
sm3_hmac_update(&hmac_ctx, seq_num, 8);
sm3_hmac_update(&hmac_ctx, header, 5);
sm3_hmac_update(&hmac_ctx, out, *outlen);
if (sm3_hmac_finish_and_verify(&hmac_ctx, mac) != 1) {
error_print("tls ciphertext mac check failure");
return -1;
}
return 1;
}
int tls_sign_server_ecdh_params(const SM2_KEY *server_sign_key,
const uint8_t client_random[32], const uint8_t server_random[32],
int curve, const SM2_POINT *point, uint8_t *sig, size_t *siglen)
{
uint8_t server_ecdh_params[69];
SM2_SIGN_CTX sign_ctx;
if (!server_sign_key || !client_random || !server_random
|| curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen) {
error_print();
return -1;
}
server_ecdh_params[0] = TLS_curve_type_named_curve;
server_ecdh_params[1] = curve >> 8;
server_ecdh_params[2] = curve;
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_update(&sign_ctx, client_random, 32);
sm2_sign_update(&sign_ctx, server_random, 32);
sm2_sign_update(&sign_ctx, server_ecdh_params, 69);
sm2_sign_finish(&sign_ctx, sig, siglen);
return 1;
}
int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key,
const uint8_t client_random[32], const uint8_t server_random[32],
int curve, const SM2_POINT *point, const uint8_t *sig, size_t siglen)
{
int ret;
uint8_t server_ecdh_params[69];
SM2_SIGN_CTX verify_ctx;
if (!server_sign_key || !client_random || !server_random
|| curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen
|| siglen > TLS_MAX_SIGNATURE_SIZE) {
error_print();
return -1;
}
server_ecdh_params[0] = TLS_curve_type_named_curve;
server_ecdh_params[1] = curve >> 8;
server_ecdh_params[2] = curve;
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_update(&verify_ctx, client_random, 32);
sm2_verify_update(&verify_ctx, server_random, 32);
sm2_verify_update(&verify_ctx, server_ecdh_params, 69);
ret = sm2_verify_finish(&verify_ctx, sig, siglen);
if (ret != 1) error_print();
return ret;
}

927
src/tls_trace.c Normal file
View File

@@ -0,0 +1,927 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <gmssl/tls.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
const char *tls_record_type_name(int type)
{
switch (type) {
case TLS_record_change_cipher_spec: return "ChangeCipherSpec";
case TLS_record_alert: return "Alert";
case TLS_record_handshake: return "Handshake";
case TLS_record_application_data: return "ApplicationData";
}
return NULL;
}
const char *tls_version_text(int version)
{
switch(version) {
case TLS_version_tlcp: return "TLCP";
case TLS_version_ssl2: return "SSL 2.0";
case TLS_version_ssl3: return "SSL 3.0";
case TLS_version_tls1: return "TLS 1.0";
case TLS_version_tls11: return "TLS 1.1";
case TLS_version_tls12: return "TLS 1.2";
case TLS_version_tls13: return "TLS 1.3";
case TLS_version_dtls1: return "DTLS 1.0";
case TLS_version_dtls12: return "DTLS 1.2";
}
return NULL;
}
const char *tls_cipher_suite_name(int cipher)
{
switch (cipher) {
case TLCP_cipher_ecdhe_sm4_cbc_sm3: return "TLCP_ECDHE_SM4_CBC_SM3";
case TLCP_cipher_ecdhe_sm4_gcm_sm3: return "TLCP_ECDHE_SM4_GCM_SM3";
case TLCP_cipher_ecc_sm4_cbc_sm3: return "TLCP_ECC_SM4_CBC_SM3";
case TLCP_cipher_ecc_sm4_gcm_sm3: return "TLCP_ECC_SM4_GCM_SM3";
case TLCP_cipher_ibsdh_sm4_cbc_sm3: return "TLCP_IBSDH_SM4_CBC_SM3";
case TLCP_cipher_ibsdh_sm4_gcm_sm3: return "TLCP_IBSDH_SM4_GCM_SM3";
case TLCP_cipher_ibc_sm4_cbc_sm3: return "TLCP_IBC_SM4_CBC_SM3";
case TLCP_cipher_ibc_sm4_gcm_sm3: return "TLCP_IBC_SM4_GCM_SM3";
case TLCP_cipher_rsa_sm4_cbc_sm3: return "TLCP_RSA_SM4_CBC_SM3";
case TLCP_cipher_rsa_sm4_gcm_sm3: return "TLCP_RSA_SM4_GCM_SM3";
case TLCP_cipher_rsa_sm4_cbc_sha256: return "TLCP_RSA_SM4_CBC_SHA256";
case TLCP_cipher_rsa_sm4_gcm_sha256: return "TLCP_RSA_SM4_GCM_SHA256";
case GMSSL_cipher_ecdhe_sm2_with_sm4_sm3: return "GMSSL_ECDHE_SM2_WITH_SM4_SM3";
case GMSSL_cipher_ecdhe_sm2_with_sm4_gcm_sm3: return "GMSSL_ECDHE_SM2_WITH_SM4_GCM_SM3";
case GMSSL_cipher_ecdhe_sm2_with_sm4_ccm_sm3: return "GMSSL_ECDHE_SM2_WITH_SM4_CCM_SM3";
case GMSSL_cipher_ecdhe_sm2_with_zuc_sm3: return "GMSSL_ECDHE_SM2_WITH_ZUC_SM3";
case TLS_cipher_empty_renegotiation_info_scsv: return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
}
return NULL;
}
const char *tls_compression_method_name(int meth)
{
switch (meth) {
case 0: return "no_compression";
}
return NULL;
}
const char *tls_extension_name(int ext)
{
switch (ext) {
case TLS_extension_server_name: return "server_name";
case TLS_extension_max_fragment_length: return "max_fragment_length";
case TLS_extension_client_certificate_url: return "client_certificate_url";
case TLS_extension_trusted_ca_keys: return "trusted_ca_keys";
case TLS_extension_truncated_hmac: return "truncated_hmac";
case TLS_extension_status_request: return "status_request";
case TLS_extension_user_mapping: return "user_mapping";
case TLS_extension_client_authz: return "client_authz";
case TLS_extension_server_authz: return "server_authz";
case TLS_extension_cert_type: return "cert_type";
case TLS_extension_supported_groups: return "supported_groups";
case TLS_extension_ec_point_formats: return "ec_point_formats";
case TLS_extension_srp: return "srp";
case TLS_extension_signature_algorithms: return "signature_algorithms";
case TLS_extension_use_srtp: return "use_srtp";
case TLS_extension_heartbeat: return "heartbeat";
case TLS_extension_application_layer_protocol_negotiation: return "application_layer_protocol_negotiation";
case TLS_extension_status_request_v2: return "status_request_v2";
case TLS_extension_signed_certificate_timestamp: return "signed_certificate_timestamp";
case TLS_extension_client_certificate_type: return "client_certificate_type";
case TLS_extension_server_certificate_type: return "server_certificate_type";
case TLS_extension_padding: return "padding";
case TLS_extension_encrypt_then_mac: return "encrypt_then_mac";
case TLS_extension_extended_master_secret: return "extended_master_secret";
case TLS_extension_token_binding: return "token_binding";
case TLS_extension_cached_info: return "cached_info";
case TLS_extension_tls_lts: return "tls_lts";
case TLS_extension_compress_certificate: return "compress_certificate";
case TLS_extension_record_size_limit: return "record_size_limit";
case TLS_extension_pwd_protect: return "pwd_protect";
case TLS_extension_pwd_clear: return "pwd_clear";
case TLS_extension_password_salt: return "password_salt";
case TLS_extension_ticket_pinning: return "ticket_pinning";
case TLS_extension_tls_cert_with_extern_psk: return "tls_cert_with_extern_psk";
case TLS_extension_delegated_credentials: return "delegated_credentials";
case TLS_extension_session_ticket: return "session_ticket";
case TLS_extension_TLMSP: return "TLMSP";
case TLS_extension_TLMSP_proxying: return "TLMSP_proxying";
case TLS_extension_TLMSP_delegate: return "TLMSP_delegate";
case TLS_extension_supported_ekt_ciphers: return "supported_ekt_ciphers";
case TLS_extension_pre_shared_key: return "pre_shared_key";
case TLS_extension_early_data: return "early_data";
case TLS_extension_supported_versions: return "supported_versions";
case TLS_extension_cookie: return "cookie";
case TLS_extension_psk_key_exchange_modes: return "psk_key_exchange_modes";
case TLS_extension_certificate_authorities: return "certificate_authorities";
case TLS_extension_oid_filters: return "oid_filters";
case TLS_extension_post_handshake_auth: return "post_handshake_auth";
case TLS_extension_signature_algorithms_cert: return "signature_algorithms_cert";
case TLS_extension_key_share: return "key_share";
case TLS_extension_transparency_info: return "transparency_info";
case TLS_extension_connection_id: return "connection_id";
case TLS_extension_external_id_hash: return "external_id_hash";
case TLS_extension_external_session_id: return "external_session_id";
case TLS_extension_quic_transport_parameters: return "quic_transport_parameters";
case TLS_extension_ticket_request: return "ticket_request";
case TLS_extension_renegotiation_info: return "renegotiation_info";
};
return NULL;
}
const char *tls_cert_type_name(int type)
{
switch (type) {
case TLS_cert_type_rsa_sign: return "rsa_sign";
case TLS_cert_type_dss_sign: return "dss_sign";
case TLS_cert_type_rsa_fixed_dh: return "rsa_fixed_dh";
case TLS_cert_type_dss_fixed_dh: return "dss_fixed_dh";
case TLS_cert_type_rsa_ephemeral_dh_RESERVED: return "rsa_ephemeral_dh_RESERVED";
case TLS_cert_type_dss_ephemeral_dh_RESERVED: return "dss_ephemeral_dh_RESERVED";
case TLS_cert_type_fortezza_dms_RESERVED: return "fortezza_dms_RESERVED";
case TLS_cert_type_ecdsa_sign: return "ecdsa_sign";
case TLS_cert_type_rsa_fixed_ecdh: return "rsa_fixed_ecdh_DEPRECATED";
case TLS_cert_type_ecdsa_fixed_ecdh: return "ecdsa_fixed_ecdh_DEPRECATED";
case TLS_cert_type_gost_sign256: return "gost_sign256";
case TLS_cert_type_gost_sign512: return "gost_sign512";
case TLS_cert_type_ibc_params: return "ibc_params";
}
return NULL;
}
const char *tls_handshake_type_name(int type)
{
switch (type) {
case TLS_handshake_hello_request: return "HelloRequest";
case TLS_handshake_client_hello: return "ClientHello";
case TLS_handshake_server_hello: return "ServerHello";
case TLS_handshake_certificate: return "Certificate";
case TLS_handshake_server_key_exchange: return "ServerKeyExchange";
case TLS_handshake_certificate_request: return "CertificateRequest";
case TLS_handshake_server_hello_done: return "ServerHelloDone";
case TLS_handshake_certificate_verify: return "CertificateRequest";
case TLS_handshake_client_key_exchange: return "ClientKeyExchange";
case TLS_handshake_finished: return "Finished";
}
return NULL;
}
const char *tls_alert_level_name(int level)
{
switch (level) {
case TLS_alert_level_warning: return "warning";
case TLS_alert_level_fatal: return "fatal";
}
error_print("unknown alert level %d", level);
return NULL;
}
const char *tls_alert_description_text(int description)
{
switch (description) {
case TLS_alert_close_notify: return "close_notify";
case TLS_alert_unexpected_message: return "unexpected_message";
case TLS_alert_bad_record_mac: return "bad_record_mac";
case TLS_alert_decryption_failed: return "decryption_failed";
case TLS_alert_record_overflow: return "record_overflow";
case TLS_alert_decompression_failure: return "decompression_failure";
case TLS_alert_handshake_failure: return "handshake_failure";
case TLS_alert_no_certificate: return "no_certificate_RESERVED";
case TLS_alert_bad_certificate: return "bad_certificate";
case TLS_alert_unsupported_certificate: return "unsupported_certificate";
case TLS_alert_certificate_revoked: return "certificate_revoked";
case TLS_alert_certificate_expired: return "certificate_expired";
case TLS_alert_certificate_unknown: return "certificate_unknown";
case TLS_alert_illegal_parameter: return "illegal_parameter";
case TLS_alert_unknown_ca: return "unknown_ca";
case TLS_alert_access_denied: return "access_denied";
case TLS_alert_decode_error: return "decode_error";
case TLS_alert_decrypt_error: return "decrypt_error";
case TLS_alert_export_restriction: return "export_restriction_RESERVED";
case TLS_alert_protocol_version: return "protocol_version";
case TLS_alert_insufficient_security: return "insufficient_security";
case TLS_alert_internal_error: return "internal_error";
case TLS_alert_user_canceled: return "user_canceled";
case TLS_alert_no_renegotiation: return "no_renegotiation";
case TLS_alert_unsupported_site2site: return "unsupported_site2site";
case TLS_alert_no_area: return "no_area";
case TLS_alert_unsupported_areatype: return "unsupported_areatype";
case TLS_alert_bad_ibcparam: return "bad_ibcparam";
case TLS_alert_unsupported_ibcparam: return "unsupported_ibcparam";
case TLS_alert_identity_need: return "identity_need";
}
error_print("unknown alert description %d", description);
return NULL;
}
const char *tls_change_cipher_spec_text(int change_cipher_spec)
{
switch (change_cipher_spec) {
case TLS_change_cipher_spec: return "change_cipher_spec";
}
return NULL;
}
const char *tls_ec_point_format_name(int format)
{
switch (format) {
case TLS_point_uncompressed: return "uncompressed";
case TLS_point_ansix962_compressed_prime: return "compressed_prime";
case TLS_point_ansix962_compressed_char2: return "compressed_char2";
}
return NULL;
}
const char *tls_curve_type_name(int type)
{
switch (type) {
case TLS_curve_type_explicit_prime: return "explicit_prime";
case TLS_curve_type_explicit_char2: return "explicit_char2";
case TLS_curve_type_named_curve: return "named_curve";
}
return NULL;
}
const char *tls_named_curve_name(int curve)
{
switch (curve) {
case TLS_curve_secp256k1: return "secp256k1";
case TLS_curve_secp256r1: return "secp256r1";
case TLS_curve_secp384r1: return "secp384r1";
case TLS_curve_secp521r1: return "secp521r1";
case TLS_curve_brainpoolp256r1: return "brainpoolp256r1";
case TLS_curve_brainpoolp384r1: return "brainpoolp384r1";
case TLS_curve_brainpoolp512r1: return "brainpoolp512r1";
case TLS_curve_x25519: return "x25519";
case TLS_curve_x448: return "x448";
case TLS_curve_brainpoolp256r1tls13: return "brainpoolp256r1tls13";
case TLS_curve_brainpoolp384r1tls13: return "brainpoolp384r1tls13";
case TLS_curve_brainpoolp512r1tls13: return "brainpoolp512r1tls13";
case TLS_curve_sm2p256v1: return "sm2p256v1";
}
return NULL;
}
const char *tls_signature_scheme_name(int scheme)
{
switch (scheme) {
case TLS_sig_rsa_pkcs1_sha1: return "rsa_pkcs1_sha1";
case TLS_sig_ecdsa_sha1: return "ecdsa_sha1";
case TLS_sig_rsa_pkcs1_sha256: return "rsa_pkcs1_sha256";
case TLS_sig_ecdsa_secp256r1_sha256: return "ecdsa_secp256r1_sha256";
case TLS_sig_rsa_pkcs1_sha256_legacy: return "rsa_pkcs1_sha256_legacy";
case TLS_sig_rsa_pkcs1_sha384: return "rsa_pkcs1_sha384";
case TLS_sig_ecdsa_secp384r1_sha384: return "ecdsa_secp384r1_sha384";
case TLS_sig_rsa_pkcs1_sha384_legacy: return "rsa_pkcs1_sha384_legacy";
case TLS_sig_rsa_pkcs1_sha512: return "rsa_pkcs1_sha512";
case TLS_sig_ecdsa_secp521r1_sha512: return "ecdsa_secp521r1_sha512";
case TLS_sig_rsa_pkcs1_sha512_legacy: return "rsa_pkcs1_sha512_legacy";
case TLS_sig_sm2sig_sm3: return "sm2sig_sm3";
case TLS_sig_rsa_pss_rsae_sha256: return "rsa_pss_rsae_sha256";
case TLS_sig_rsa_pss_rsae_sha384: return "rsa_pss_rsae_sha384";
case TLS_sig_rsa_pss_rsae_sha512: return "rsa_pss_rsae_sha512";
case TLS_sig_ed25519: return "ed25519";
case TLS_sig_ed448: return "ed448";
case TLS_sig_rsa_pss_pss_sha256: return "rsa_pss_pss_sha256";
case TLS_sig_rsa_pss_pss_sha384: return "rsa_pss_pss_sha384";
case TLS_sig_rsa_pss_pss_sha512: return "rsa_pss_pss_sha512";
case TLS_sig_ecdsa_brainpoolP256r1tls13_sha256: return "ecdsa_brainpoolP256r1tls13_sha256";
case TLS_sig_ecdsa_brainpoolP384r1tls13_sha384: return "ecdsa_brainpoolP384r1tls13_sha384";
case TLS_sig_ecdsa_brainpoolP512r1tls13_sha512: return "ecdsa_brainpoolP512r1tls13_sha512";
}
return NULL;
}
int tls_random_print(FILE *fp, const uint8_t random[32], int format, int indent)
{
int i;
time_t gmt_unix_time = 0;
const uint8_t *cp = random;
size_t len = 4;
tls_uint32_from_bytes((uint32_t *)&gmt_unix_time, &cp, &len);
format_print(fp, format, indent, "Random\n");
indent += 4;
format_print(fp, format, indent, "gmt_unix_time : %s", ctime(&gmt_unix_time));
format_bytes(fp, format, indent, "random : ", random + 4, 28);
return 1;
}
int tls_pre_master_secret_print(FILE *fp, const uint8_t pre_master_secret[48], int format, int indent)
{
int version = ((int)pre_master_secret[0] << 8) | pre_master_secret[1];
format_print(fp, format, indent, "PreMasterSecret\n");
indent += 4;
format_print(fp, format, indent, "version : %s\n", tls_version_text(version));
format_bytes(fp, format, indent, "pre_master_secret : ", pre_master_secret, 48);
return 1;
}
int tls_extension_print(FILE *fp, int type, const uint8_t *data, size_t datalen, int format, int indent)
{
const uint8_t *p;
size_t len;
format_print(fp, format, indent, "%s (%d)\n", tls_extension_name(type), type);
indent += 4;
switch (type) {
case TLS_extension_supported_groups:
if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1
|| datalen
|| len % 2) {
error_print();
return -1;
}
while (len) {
uint16_t curve;
tls_uint16_from_bytes(&curve, &p, &len);
format_print(fp, format, indent, "%s (0x%04x)\n",
tls_named_curve_name(curve), curve);
}
break;
case TLS_extension_ec_point_formats:
if (tls_uint8array_from_bytes(&p, &len, &data, &datalen) != 1
|| datalen) {
error_print();
return -1;
}
while (len) {
uint8_t point_form;
tls_uint8_from_bytes(&point_form, &p, &len);
format_print(fp, format, indent, "%s (%d)\n",
tls_ec_point_format_name(point_form), point_form);
}
break;
case TLS_extension_signature_algorithms:
if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1
|| datalen
|| len % 2) {
error_print();
return -1;
}
while (len) {
uint16_t sig_alg;
tls_uint16_from_bytes(&sig_alg, &p, &len);
format_print(fp, format, indent, "%s (0x%04x)\n",
tls_signature_scheme_name(sig_alg), sig_alg);
}
break;
default:
format_bytes(fp, format, indent, "raw_data : ", data, datalen);
}
return 1;
}
int tls_extensions_print(FILE *fp, const uint8_t *exts, size_t extslen, int format, int indent)
{
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
format_print(fp, format, indent, "Extensions\n");
indent += 4;
while (extslen > 0) {
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
if (tls_extension_print(fp, ext_type, ext_data, ext_datalen, format, indent) != 1) {
error_print();
return -1;
}
}
return 1;
}
int tls_client_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
int ret = -1;
uint16_t version;
const uint8_t *random;
const uint8_t *session_id;
const uint8_t *cipher_suites;
const uint8_t *comp_meths;
const uint8_t *exts;
size_t session_id_len, cipher_suites_len, comp_meths_len, exts_len;
size_t i;
format_print(fp, format, indent, "ClientHello\n"); indent += 4;
if (tls_uint16_from_bytes((uint16_t *)&version, &data, &datalen) != 1) goto end;
format_print(fp, format, indent, "Version : %s (%d.%d)\n",
tls_version_text(version), version >> 8, version & 0xff);
if (tls_array_from_bytes(&random, 32, &data, &datalen) != 1) goto end;
tls_random_print(fp, random, format, indent);
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &data, &datalen) != 1) goto end;
format_bytes(fp, format, indent, "SessionID : ", session_id, session_id_len);
if (tls_uint16array_from_bytes(&cipher_suites, &cipher_suites_len, &data, &datalen) != 1) goto end;
format_print(fp, format, indent, "CipherSuites\n");
while (cipher_suites_len >= 2) {
uint16_t cipher;
if (tls_uint16_from_bytes(&cipher, &cipher_suites, &cipher_suites_len) != 1) goto end;
format_print(fp, format, indent + 4, "%s (0x%04x)\n",
tls_cipher_suite_name(cipher), cipher);
}
if (cipher_suites_len) {
error_print();
return -1;
}
if (tls_uint8array_from_bytes(&comp_meths, &comp_meths_len, &data, &datalen) != 1) goto end;
format_print(fp, format, indent, "CompressionMethods\n");
for (i = 0; i < comp_meths_len; i++) {
format_print(fp, format, indent + 4, "%s (%d)\n",
tls_compression_method_name(comp_meths[i]), comp_meths[i]);
}
if (datalen > 0) {
if (tls_uint16array_from_bytes(&exts, &exts_len, &data, &datalen) != 1) goto end;
tls_extensions_print(fp, exts, exts_len, format, indent);
}
if (datalen > 0) {
error_print();
return -1;
}
ret = 1;
end:
return ret;
}
int tls_server_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
int ret = -1;
uint16_t version;
const uint8_t *random;
const uint8_t *session_id;
uint16_t cipher_suite;
uint8_t comp_meth;
const uint8_t *exts;
size_t session_id_len, cipher_suites_len, comp_meths_len, exts_len;
size_t i;
format_print(fp, format, indent, "ServerHello\n"); indent += 4;
if (tls_uint16_from_bytes(&version, &data, &datalen) != 1) goto bad;
format_print(fp, format, indent, "Version : %s (%d.%d)\n",
tls_version_text(version), version >> 8, version & 0xff);
if (tls_array_from_bytes(&random, 32, &data, &datalen) != 1) goto bad;
tls_random_print(fp, random, format, indent);
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &data, &datalen) != 1) goto bad;
format_bytes(fp, format, indent, "SessionID : ", session_id, session_id_len);
if (tls_uint16_from_bytes(&cipher_suite, &data, &datalen) != 1) goto bad;
format_print(fp, format, indent, "CipherSuite : %s (0x%04x)\n",
tls_cipher_suite_name(cipher_suite), cipher_suite);
if (tls_uint8_from_bytes(&comp_meth, &data, &datalen) != 1) goto bad;
format_print(fp, format, indent, "CompressionMethod : %s (%d)\n",
tls_compression_method_name(comp_meth), comp_meth);
if (datalen > 0) {
if (tls_uint16array_from_bytes(&exts, &exts_len, &data, &datalen) != 1) goto bad;
format_bytes(fp, format, indent, "Extensions : ", exts, exts_len); // FIXME: extensions_print
}
return 1;
bad:
error_print();
return -1;
}
int tls_certificate_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
int ret;
const uint8_t *certs;
size_t certslen;
const uint8_t *der;
size_t derlen;
if (tls_uint24array_from_bytes(&certs, &certslen, &data, &datalen) != 1
|| datalen > 0) {
error_print();
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);
}
return 1;
}
int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
const uint8_t *sig = data;
size_t siglen = datalen;
/*
if (tls_uint16array_from_bytes(&sig, &siglen, &data, &datalen) != 1
|| datalen > 0) {
error_print();
}
*/
format_print(fp, format, indent, "ServerKeyExchange:\n");
indent += 4;
format_bytes(fp, format, indent, "signature : ", sig, siglen);
return 1;
}
int tls_server_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t datalen,
int format, int indent)
{
uint8_t curve_type;
uint16_t curve;
const uint8_t *octets;
size_t octetslen;
uint16_t sig_alg;
const uint8_t *sig;
size_t siglen;
format_print(fp, format, indent, "ServerKeyExchange\n");
indent += 4;
format_print(fp, format, indent, "ServerECDHParams\n");
format_print(fp, format, indent + 4, "curve_params\n");
if (tls_uint8_from_bytes(&curve_type, &data, &datalen) != 1) {
error_print();
return -1;
}
format_print(fp, format, indent + 8, "curve_type : %s (%d)\n",
tls_curve_type_name(curve_type), curve_type);
if (tls_uint16_from_bytes(&curve, &data, &datalen) != 1) {
error_print();
return -1;
}
format_print(fp, format, indent + 8, "named_curve : %s (04%04x)\n",
tls_named_curve_name(curve), curve);
if (tls_uint8array_from_bytes(&octets, &octetslen, &data, &datalen) != 1) {
error_print();
return -1;
}
format_bytes(fp, format, indent + 4, "point : ", octets, octetslen);
if (tls_uint16_from_bytes(&sig_alg, &data, &datalen) != 1) {
error_print();
return -1;
}
format_print(fp, format, indent, "SignatureScheme : %s (04%04x)\n",
tls_signature_scheme_name(sig_alg), sig_alg);
if (tls_uint16array_from_bytes(&sig, &siglen, &data, &datalen) != 1) {
error_print();
return -1;
}
format_bytes(fp, format, indent, "Siganture : ", sig, siglen);
if (datalen > 0) {
error_print();
return -1;
}
return 1;
}
int tls_server_key_exchange_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
int cipher_suite = (format >> 8) & 0xffff;
switch (cipher_suite) {
case TLCP_cipher_ecc_sm4_cbc_sm3:
case TLCP_cipher_ecc_sm4_gcm_sm3:
if (tlcp_server_key_exchange_pke_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLCP_cipher_ecdhe_sm4_cbc_sm3:
case TLCP_cipher_ecdhe_sm4_gcm_sm3:
case GMSSL_cipher_ecdhe_sm2_with_sm4_sm3:
case GMSSL_cipher_ecdhe_sm2_with_sm4_gcm_sm3:
case GMSSL_cipher_ecdhe_sm2_with_sm4_ccm_sm3:
if (tls_server_key_exchange_ecdhe_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
return 1;
}
int tls_certificate_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
const uint8_t *cert_types;
const uint8_t *ca_names;
size_t cert_types_len, ca_names_len, i;
format_print(fp, format, indent, "CertificateRequest\n"); indent += 4;
if (tls_uint8array_from_bytes(&cert_types, &cert_types_len, &data, &datalen) != 1) goto bad;
format_print(fp, format, indent, "cert_types\n");
while (cert_types_len--) {
format_print(fp, format, indent + 4, "%s\n", tls_cert_type_name(*cert_types++));
}
if (tls_uint16array_from_bytes(&ca_names, &ca_names_len, &data, &datalen) != 1) goto bad;
format_bytes(fp, format, indent, "CAnames : ", ca_names, ca_names_len);
return 1;
bad:
error_print();
return -1;
}
int tls_server_hello_done_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
if (datalen > 0) {
error_print();
return -1;
}
return 1;
}
int tls_client_key_exchange_pke_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
const uint8_t *enced_pms;
size_t enced_pms_len;
if (tls_uint16array_from_bytes(&enced_pms, &enced_pms_len, &data, &datalen) != 1) {
error_print();
return -1;
}
format_bytes(fp, format, indent, "EncryptedPreMasterSecret : ", enced_pms, enced_pms_len);
return 1;
}
int tls_client_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t datalen,
int format, int indent)
{
const uint8_t *octets;
size_t octetslen;
format_print(fp, format, indent, "ClientKeyExchange\n");
indent += 4;
if (tls_uint8array_from_bytes(&octets, &octetslen, &data, &datalen) != 1) {
error_print();
return -1;
}
format_bytes(fp, format, indent, "ecdh_Yc : ", octets, octetslen);
if (datalen > 0) {
error_print();
return -1;
}
return 1;
}
int tls_client_key_exchange_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
int cipher_suite = (format >> 8) & 0xffff;
switch (cipher_suite) {
case TLCP_cipher_ecc_sm4_cbc_sm3:
case TLCP_cipher_ecc_sm4_gcm_sm3:
if (tls_client_key_exchange_pke_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLCP_cipher_ecdhe_sm4_cbc_sm3:
case TLCP_cipher_ecdhe_sm4_gcm_sm3:
case GMSSL_cipher_ecdhe_sm2_with_sm4_sm3:
case GMSSL_cipher_ecdhe_sm2_with_sm4_gcm_sm3:
case GMSSL_cipher_ecdhe_sm2_with_sm4_ccm_sm3:
if (tls_client_key_exchange_ecdhe_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
return 1;
}
int tls_certificate_verify_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
format_print(fp, format, indent, "CertificateVerify :\n");
format_bytes(fp, format, indent + 4, "Signature : ", data, datalen);
return 1;
}
int tls_finished_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
format_print(fp, format, indent, "Finished\n");
indent += 4;
format_bytes(fp, format, indent, "verify_data : ", data, datalen);
return 1;
}
int tls_handshake_print(FILE *fp, const uint8_t *handshake, size_t handshakelen, int format, int indent)
{
const uint8_t *cp = handshake;
int type;
const uint8_t *data;
size_t datalen = 0;
format_print(fp, format, indent, "Handshake\n");
indent += 4;
if (tls_uint8_from_bytes((uint8_t *)&type, &cp, &handshakelen) != 1) {
error_print();
return -1;
}
format_print(fp, format, indent, "Type : %s (%d)\n", tls_handshake_type_name(type), type);
if (tls_uint24_from_bytes((uint24_t *)&datalen, &cp, &handshakelen) != 1) {
error_print();
return -1;
}
format_print(fp, format, indent, "Length : %zu\n", datalen);
if (tls_array_from_bytes(&data, datalen, &cp, &handshakelen) != 1) {
error_print();
return -1;
}
switch (type) {
case TLS_handshake_client_hello:
if (tls_client_hello_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_server_hello:
if (tls_server_hello_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_certificate:
if (tls_certificate_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_server_key_exchange:
if (tls_server_key_exchange_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_certificate_request:
if (tls_certificate_request_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_server_hello_done:
if (tls_server_hello_done_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_client_key_exchange:
if (tls_client_key_exchange_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_certificate_verify:
if (tls_certificate_verify_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
case TLS_handshake_finished:
if (tls_finished_print(fp, data, datalen, format, indent) != 1)
{ error_print(); return -1; } break;
default:
error_print();
return -1;
}
return 1;
}
int tls_alert_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
if (datalen != 2) {
error_print();
return -1;
}
format_print(fp, format, indent, "Alert :\n");
indent += 4;
format_print(fp, format, indent, "Level : %s (%d)\n", tls_alert_level_name(data[0]), data[0]);
format_print(fp, format, indent, "Reason : %s (%d)\n", tls_alert_description_text(data[1]), data[1]);
return 1;
}
int tls_change_cipher_spec_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
if (datalen != 1) {
error_print();
return -1;
}
format_print(fp, format, indent, "ChangeCipherSpec\n");
indent += 4;
format_print(fp, format, indent, "type : %s (%d)\n", tls_change_cipher_spec_text(data[0]), data[0]);
return 1;
}
int tls_application_data_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent)
{
format_bytes(fp, format, indent, "ApplicationData : ", data, datalen);
return 1;
}
int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent)
{
const uint8_t *data;
size_t datalen;
int version;
if (!fp || !record || recordlen < 5) {
error_print();
return -1;
}
version = tls_record_version(record);
format_print(fp, format, indent, "Record\n"); indent += 4;
format_print(fp, format, indent, "ContentType : %s (%d)\n", tls_record_type_name(record[0]), record[0]);
format_print(fp, format, indent, "Version : %s (%d.%d)\n", tls_version_text(version), version >> 8, version & 0xff);
format_print(fp, format, indent, "Length : %d\n", tls_record_length(record));
data = record + 5;
datalen = recordlen - 5;
switch (record[0]) {
case TLS_record_handshake:
if (tls_handshake_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLS_record_alert:
if (tls_alert_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLS_record_change_cipher_spec:
if (tls_change_cipher_spec_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLS_record_application_data:
if (tls_application_data_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
fprintf(fp, "\n");
return 1;
}
int tls_secrets_print(FILE *fp,
const uint8_t *pre_master_secret, size_t pre_master_secret_len,
const uint8_t client_random[32], const uint8_t server_random[32],
const uint8_t master_secret[48],
const uint8_t *key_block, size_t key_block_len,
int format, int indent)
{
format_bytes(stderr, format, indent, "pre_master_secret : ", pre_master_secret, pre_master_secret_len);
format_bytes(stderr, format, indent, "client_random : ", client_random, 32);
format_bytes(stderr, format, indent, "server_random : ", server_random, 32);
format_bytes(stderr, format, indent, "master_secret : ", master_secret, 48);
format_bytes(stderr, format, indent, "client_write_mac_key : ", key_block, 32);
format_bytes(stderr, format, indent, "server_write_mac_key : ", key_block + 32, 32);
format_bytes(stderr, format, indent, "client_write_enc_key : ", key_block + 64, 16);
format_bytes(stderr, format, indent, "server_write_enc_key : ", key_block + 80, 16);
format_print(stderr, format, indent, "\n");
return 1;
}

361
src/x509_algor.c Normal file
View File

@@ -0,0 +1,361 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/oid.h>
#include <gmssl/asn1.h>
#include <gmssl/error.h>
static const uint32_t DER_sm3[] = {1, 2, 156, 10197, 1, 401};
static const uint32_t DER_md5[] = {1, 2, 840, 113549, 2, 5};
static const uint32_t DER_sha1[] = {1, 3, 14, 3, 2, 26};
static const uint32_t DER_sha256[] = {2, 16, 840, 1, 101, 3, 4, 2, 1};
static const uint32_t DER_sha384[] = {2, 16, 840, 1, 101, 3, 4, 2, 2};
static const uint32_t DER_sha512[] = {2, 16, 840, 1, 101, 3, 4, 2, 3};
static const uint32_t DER_sha224[] = {2, 16, 840, 1, 101, 3, 4, 2, 4};
static struct {
int oid;
char *name;
const uint32_t *nodes;
size_t nodes_count;
} digest_table[] = {
{ OID_sm3, "sm3", DER_sm3, sizeof(DER_sm3)/sizeof(int) },
{ OID_md5, "md5", DER_md5, sizeof(DER_md5)/sizeof(int) },
{ OID_sha1, "sha1", DER_sha1, sizeof(DER_sha1)/sizeof(int) },
{ OID_sha224, "sha224", DER_sha224, sizeof(DER_sha224)/sizeof(int) },
{ OID_sha256, "sha256", DER_sha256, sizeof(DER_sha256)/sizeof(int) },
{ OID_sha384, "sha384", DER_sha384, sizeof(DER_sha384)/sizeof(int) },
{ OID_sha512, "sha512", DER_sha512, sizeof(DER_sha512)/sizeof(int) },
};
const char *x509_digest_algor_name(int oid)
{
int i;
for (i = 0; i < sizeof(digest_table)/sizeof(digest_table[0]); i++) {
if (oid == digest_table[i].oid) {
return digest_table[i].name;
}
}
return NULL;
}
int x509_digest_algor_to_der(int oid, uint8_t **out, size_t *outlen)
{
size_t len;
if (oid != OID_sm3) {
error_print();
return -1;
}
if (asn1_object_identifier_to_der(oid, NULL, 0, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(oid, NULL, 0, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_digest_algor_from_der(int *oid, uint32_t *nodes, size_t *nodes_count,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return -1;
}
if (asn1_object_identifier_from_der(oid, nodes, nodes_count, &data, &datalen) != 1) {
error_print();
return -1;
}
if (*oid != OID_undef && *oid != OID_sm3) {
error_print();
return -1;
}
if (datalen) {
error_print();
return -1;
}
return 1;
}
static uint32_t sm4_cbc_nodes[] = { 1, 2, 156, 10197, 1, 104, 2 };
static size_t sm4_cbc_nodes_count = sizeof(sm4_cbc_nodes)/sizeof(sm4_cbc_nodes[0]);
int x509_encryption_algor_to_der(int cipher, const uint8_t *iv, size_t ivlen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (cipher != OID_sm4_cbc || ivlen != 16) {
error_print();
return -1;
}
if (asn1_object_identifier_to_der(OID_undef, sm4_cbc_nodes, sm4_cbc_nodes_count, NULL, &len) != 1
|| asn1_octet_string_to_der(iv, ivlen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(OID_undef, sm4_cbc_nodes, sm4_cbc_nodes_count, out, outlen) != 1
|| asn1_octet_string_to_der(iv, ivlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_encryption_algor_from_der(int *cipher,
const uint8_t **iv, size_t *ivlen,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
uint32_t nodes[32];
size_t nodes_count;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_object_identifier_from_der(cipher, nodes, &nodes_count, &data, &datalen) != 1
|| asn1_octet_string_from_der(iv, ivlen, &data, &datalen) != 1
|| datalen > 0) {
error_print();
return -1;
}
if (*cipher == OID_undef) {
if (nodes_count == sm4_cbc_nodes_count
&& memcmp(nodes, sm4_cbc_nodes, sizeof(sm4_cbc_nodes)) == 0) {
*cipher = OID_sm4_cbc;
} else {
size_t i;
error_print("unknown cipher oid :");
for (i = 0; i < nodes_count; i++) {
fprintf(stderr, " %d", nodes[i]);
}
fprintf(stderr, "\n");
return -1;
}
}
// FIXME: 检查ivlen
return 1;
}
int x509_signature_algor_to_der(int oid, uint8_t **out, size_t *outlen)
{
size_t len = 0;
int has_null_obj = 0;
switch (oid) {
// ECDSA/SM2 parameters MUST be omitted
//case OID_ecdsa_with_sha1:
//case OID_ecdsa_with_sha224
//case OID_ecdsa_with_sha256:
//case OID_ecdsa_with_sha384:
//case OID_ecdsa_with_sha512:
case OID_sm2sign_with_sm3:
has_null_obj = 0;
break;
// RSA parameters MUST be ASN1_NULL
//case OID_sha1WithRSAEncryption:
//case OID_sha224WithRSAEncryption:
//case OID_sha256WithRSAEncryption:
//case OID_sha384WithRSAEncryption:
//case OID_sha512WithRSAEncryption:
case OID_rsasign_with_sm3:
has_null_obj = 1;
break;
default:
error_print();
return -1;
}
if (asn1_object_identifier_to_der(oid, NULL, 0, NULL, &len) != 1) {
error_print();
return -1;
}
if (has_null_obj) {
if (asn1_null_to_der(NULL, &len) != 1) {
error_print();
return -1;
}
}
if (asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(oid, NULL, 0, out, outlen) != 1) {
error_print();
return -1;
}
if (has_null_obj) {
if (asn1_null_to_der(out, outlen) != 1) {
error_print();
return -1;
}
}
return 1;
}
int x509_signature_algor_from_der(int *oid, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
uint32_t nodes[32];
size_t nodes_count;
int has_null_obj;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
return ret;
}
if (asn1_object_identifier_from_der(oid, nodes, &nodes_count, &data, &datalen) != 1) {
error_print();
return -1;
}
if ((has_null_obj = asn1_null_from_der(&data, &datalen)) < 0) {
error_print();
return -1;
}
if (datalen > 0) {
error_print("datalen = %zu", datalen);
error_print();
return -1;
}
switch (*oid) {
//case OID_ecdsa_with_sha1:
//case OID_ecdsa_with_sha224
//case OID_ecdsa_with_sha256:
//case OID_ecdsa_with_sha384:
//case OID_ecdsa_with_sha512:
case OID_sm2sign_with_sm3:
if (has_null_obj) {
fprintf(stderr, "WARN: %s %d: AlgorithmIdentifier.parameters SHOULD be omitted for ECDSA/SM2\n", __FILE__, __LINE__);
}
break;
//case OID_sha1WithRSAEncryption:
//case OID_sha224WithRSAEncryption:
//case OID_sha256WithRSAEncryption:
//case OID_sha384WithRSAEncryption:
//case OID_sha512WithRSAEncryption:
case OID_rsasign_with_sm3:
if (!has_null_obj) {
fprintf(stderr, "WARN: %s %d\n: parameters SHOULD be NULL object for RSA", __FILE__, __LINE__);
}
break;
default:
// print unknown OID nodes
error_print();
return -1;
}
return 1;
}
const uint32_t DER_sm2encrypt[] = {1,2,156,10197,1,301,2};
int x509_public_key_encryption_algor_to_der(int algor, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (asn1_object_identifier_to_der(OID_undef, DER_sm2encrypt,
sizeof(DER_sm2encrypt)/sizeof(DER_sm2encrypt[0]), NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(OID_undef, DER_sm2encrypt,
sizeof(DER_sm2encrypt)/sizeof(DER_sm2encrypt[0]), out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_public_key_encryption_algor_from_der(int *algor, uint32_t *nodes, size_t *nodes_count,
const uint8_t *params, size_t *params_len,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_object_identifier_from_der(algor, nodes, nodes_count, &data, &datalen) != 1) {
error_print();
return -1;
}
// FIXME: 我们需要一个读取完整obj的函数
return 1;
}

1377
src/x509_asn1.c Normal file

File diff suppressed because it is too large Load Diff

463
src/x509_crl.c Normal file
View File

@@ -0,0 +1,463 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/crl.h>
const char *crl_reason_text(int reason)
{
switch (reason) {
case X509_cr_unspecified: return "unspecified";
case X509_cr_key_compromise: return "keyCompromise";
case X509_cr_ca_compromise: return "cACompromise";
case X509_cr_affiliation_changed: return "affiliationChanged";
case X509_cr_superseded: return "superseded";
case X509_cr_cessation_of_operation: return "cessationOfOperation";
case X509_cr_certificate_hold: return "certificateHold";
case X509_cr_remove_from_crl: return "removeFromCRL";
case X509_cr_privilege_withdrawn: return "privilegeWithdrawn";
case X509_cr_aa_compromise: return "aACompromise";
}
return NULL;
}
84 typedef struct {
85 uint8_t serial_number[20];
86 size_t serial_number_len;
87 time_t revoke_date;
88 CRL_EXTENSIONS crlEntryExtensions;
89 } CRL_REVOKED_CERT;
int crl_revoked_cert_to_der(const CRL_REVOKED_CERT *a, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (asn1_integer_to_der(a->serial_number, a->serial_number_len, NULL, &len) != 1
|| x509_time_to_der(a->revoke_date, NULL, &len) != 1
|| x509_extension_to_der(a->exts, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_integer_to_der(a->serial_number, a->serial_number_len, out, outlen) != 1
|| x509_time_to_der(a->revoke_date, out, outlen) != 1
|| x509_extension_to_der(a->exts, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int crl_revoked_cert_from_der(CRL_REVOKED_CERT *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_integer_from_der(a->serial_number, &a->serial_number_len, &data, &datalen) != 1
|| x509_time_from_der(&a->revoke_date, &data, &datalen) != 1
|| x509_extensions_from_der(&a->exts, &data, &datalen) != 1
|| datalen) {
error_print();
return -1;
}
return 1;
}
int crl_revoked_cert_print(FILE *fp, const CRL_REVOKED_CERT *a, int format, int indent)
{
return 1;
}
int crl_tbs_cert_list_to_der(const CRL_TBS_CERT_LIST *a, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (asn1_int_to_der(a->version, NULL, &len) != 1
|| x509_algorithm_id_to_der(a->signature_algor, NULL, &len) != 1
|| x509_name_to_der(&a->issuer, NULL, &len) != 1
|| x509_time_to_der(a->this_update, NULL, &len) != 1
|| x509_time_to_der(a->next_update, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_int_to_der(a->version, out, outlen) != 1
|| x509_algorithm_id_to_der(a->signature_algor, out, outlen) != 1
|| x509_name_to_der(&a->issuer, out, outlen) != 1
|| x509_time_to_der(a->next_update, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int crl_tbs_cert_list_from_der(CRL_TBS_CERT_LIST *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (asn1_int_from_der(&a->version, &data, &datalen) != 1
|| x509_algorithm_id_from_der(&a->signature_algor, &data, &datalen) != 1
|| x509_name_from_der(&a->issuer, &data, &datalen) != 1
|| x509_time_from_der(&a->this_update, &data, &datalen) != 1
|| x509_time_from_der(&a->next_update, &data, &datalen) != 1) {
error_print();
return -1;
}
}
int x509_cert_list_to_der(const X509_CERT_LIST *a, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (x509_tbs_cert_list_to_der(&a->tbs_cert_list, NULL, &len) != 1
|| x509_signature_algor_to_der(a->signature_algor, NULL, &len) != 1
|| asn1_bit_string_to_der(a->signature, a->signature_len, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_tbs_cert_list_to_der(&a->tbs_cert_list, out, outlen) != 1
|| x509_signature_algor_to_der(a->signature_algor, out, outlen) != 1
|| asn1_bit_string_to_der(a->signature, a->signature_len, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_cert_list_from_der(X509_CERT_LIST *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t datalen;
const uint8_t *sig;
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
if (ret < 0)
error_print();
return ret;
}
if (x509_tbs_cert_list_from_der(&a->tbs_cert_list, in, inlen) != 1
|| x509_signature_algor_from_der(&a->signature_algor, in, inlen) != 1
|| asn1_bit_string_from_der(&sig, &a->signature_len, in, inlen) != 1
|| a->signature_len <= 0
|| a->signature_len >= X509_MAX_SIGNATURE_SIZE) {
error_print();
return -1;
}
memcpy(a->signature, sig, a->signature_len);
return 1;
}
static const int X509_CRLExtensionOIDs[7] = {
OID_id_ce_authorityKeyIdentifier,
OID_id_ce_issuerAltName,
OID_id_ce_cRLNumber,
OID_id_ce_deltaCRLIndicator,
OID_id_ce_issuingDistributionPoint,
OID_id_ce_freshestCRL,
OID_pe_authorityInfoAccess,
};
void X509_CRLExtensionValue_to_der(const X509_CRLExtensionValue *a, int type, uint8_t **out, size_t *outlen)
{
switch (type) {
case OID_id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier_to_der(&a->u.authorityKeyIdentifier, out, outlen); break;
case OID_id_ce_issuerAltName: X509_GeneralNames_to_der(&a->u.issuerAltName, out, outlen); break;
case OID_id_ce_cRLNumber: ASN1_INTEGER_to_der(&a->u.cRLNumber, out, outlen); break;
case OID_id_ce_deltaCRLIndicator: ASN1_INTEGER_to_der(&a->u.deltaCRLIndicator, out, outlen);
case OID_id_ce_issuingDistributionPoint: X509_IssuingDistributionPoint_to_der(&a->u.issuingDistributionPoint, out, outlen);
case OID_id_ce_freshestCRL: X509_CRLDistributionPoints_to_der(&a->u.freshestCRL, out, outlen);
case OID_pe_authorityInfoAccess: X509_AuthorityInfoAccessSyntax_to_der(&a->u.authorityInfoAccess, out, outlen);
}
}
int X509_CRLExtensionValue_from_der(X509_CRLExtensionValue *a, int type, const uint8_t **in, size_t *inlen)
{
switch (type) {
case OID_id_ce_authorityKeyIdentifier: return AuthorityKeyIdentifier_from_der(&a->u.authorityKeyIdentifier, in, inlen);
case OID_id_ce_issuerAltName: return X509_GeneralNames_from_der(&a->u.issuerAltName, in, inlen);
case OID_id_ce_cRLNumber: return ASN1_INTEGER_from_der(&a->u.cRLNumber, in, inlen);
case OID_id_ce_deltaCRLIndicator: return ASN1_INTEGER_from_der(&a->u.deltaCRLIndicator, in, inlen);
case OID_id_ce_issuingDistributionPoint: return X509_IssuingDistributionPoint_from_der(&a->u.issuingDistributionPoint, in, inlen);
case OID_id_ce_freshestCRL: return X509_CRLDistributionPoints_from_der(&a->u.freshestCRL, in, inlen);
case OID_pe_authorityInfoAccess: return X509_AuthorityInfoAccessSyntax_from_der(&a->u.authorityInfoAccess, in, inlen);
}
}
void X509_CRLExtension_to_der(const X509_CRLExtension *a, uint8_t **out, size_t *outlen)
{
ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen);
ASN1_OBJECT_IDENTIFIER_to_der(&a->extnID, out, outlen);
ASN1_BOOLEAN_to_der(&a->critical, out, outlen);
ASN1_OCTET_STRING_tag_length_to_der(&a->extnValue, out, outlen);
X509_CRLExtensionValue_to_der(&a->extnValue_data, out, outlen);
}
int X509_CRLExtension_from_der(X509_CRLExtension *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t length;
if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) {
return ret;
}
data = ((ASN1_SEQUENCE *)a)->data;
length = ((ASN1_SEQUENCE *)a)->length;
if (ASN1_OBJECT_IDENTIFIER_from_der(&a->extnID, &data, &length) <= 0
|| ASN1_BOOLEAN_from_der(&a->critical, &data, &length) < 0
|| ASN1_OCTET_STRING_from_der(&a->extnValue, &data, &length) <= 0
|| length > 0) {
return -1;
}
data = a->extnValue.data;
length = a->extnValue.length;
if (X509_CRLExtensionValue_from_der(&a->extnValue_data, &data, &length) < 0
|| length > 0) {
return -1;
}
return 1;
}
void X509_CRLExtensions_add(X509_CRLExtensions *a, const X509_CRLExtension *value)
{
size_t length = ((ASN1_SEQUENCE *)a)->length;
assert(a->count < 16);
X509_CRLExtension_copy(&a->values[a->count], value);
X509_CRLExtension_to_der(&a->values[a->count], NULL, &length);
ASN1_SEQUENCE_set((ASN1_SEQUENCE *)a, NULL, length);
a->count++;
}
void X509_CRLExtensions_to_der(const X509_CRLExtensions *a, uint8_t **out, size_t *outlen)
{
int i;
ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen);
for (i = 0; i < a->count; i++) {
X509_CRLExtension_to_der(&a->value[i], out, outlen);
}
}
int X509_CRLExtensions_from_der(X509_CRLExtensions *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t length;
if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) {
return ret;
}
data = ((ASN1_SEQUENCE *)a)->data;
length = ((ASN1_SEQUENCE *)a)->length;
while (length > 0) {
if (a->count >= 16
|| X509_CRLExtension_from_der(&a->values[a->count], &data, &length) <= 0) {
return -1;
}
}
return 1;
}
// 5.2.5. Issuing Distribution Point
/*
-- issuing distribution point extension OID and syntax
id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
IssuingDistributionPoint ::= SEQUENCE {
distributionPoint [0] IMPLICIT DistributionPointName OPTIONAL,
onlyContainsUserCerts [1] IMPLICIT BOOLEAN DEFAULT FALSE,
onlyContainsCACerts [2] IMPLICIT BOOLEAN DEFAULT FALSE,
onlySomeReasons [3] IMPLICIT ReasonFlags OPTIONAL,
indirectCRL [4] IMPLICIT BOOLEAN DEFAULT FALSE,
onlyContainsAttributeCerts [5] IMPLICIT BOOLEAN DEFAULT FALSE }
-- at most one of onlyContainsUserCerts, onlyContainsCACerts,
-- and onlyContainsAttributeCerts may be set to TRUE.
*/
void X509_CRLEntryExtension_to_der(const X509_CRLEntryExtension *a, uint8_t **out, size_t *outlen)
{
ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen);
ASN1_OBJECT_IDENTIFIER_to_der(&a->extnID, out, outlen);
ASN1_BOOLEAN_to_der(&a->critical, out, outlen);
ASN1_OCTET_STRING_tag_length_to_der(&a->extnValue, out, outlen);
X509_CRLEntryExtensionValue_to_der(&a->extnValue_data, out, outlen);
}
int X509_CRLEntryExtension_from_der(X509_CRLEntryExtension *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t length;
if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) {
return ret;
}
data = ((ASN1_SEQUENCE *)a)->data;
length = ((ASN1_SEQUENCE *)a)->length;
if (ASN1_OBJECT_IDENTIFIER_from_der(&a->extnID, &data, &length) <= 0
|| ASN1_BOOLEAN_from_der(&a->critical, &data, &length) < 0
|| ASN1_OCTET_STRING_from_der(&a->extnValue, &data, &length) <= 0
|| length > 0) {
return -1;
}
data = a->extnValue.data;
length = a->extnValue.length;
if (X509_CRLEntryExtensionValue_from_der(&a->extnValue_data, &data, &length) < 0
|| length > 0) {
return -1;
}
return 1;
}
// CRL Entry Extensions
//***********************************************************************************************************
static const int X509_CRLEntryExtensionOIDs[3] = {
OID_id_ce_cRLReasons,
OID_id_ce_invalidityDate,
OID_id_ce_certificateIssuer,
};
void X509_CRLEntryExtensionValue_to_der(const X509_CRLEntryExtensionValue *a, int type, uint8_t **out, size_t *outlen)
{
switch (type) {
case OID_id_ce_cRLReasons: ASN1_ENUMERATED_to_der(&a->u.reasonCode, out, outlen); break;
case OID_id_ce_invalidityDate: X509_GeneralizedTime_to_der(&a->u.invalidityDate, out, outlen); break;
case OID_id_ce_certificateIssuer: X509_GeneralNames_to_der(&a->u.certificateIssuer, out, outlen); break;
}
}
int X509_CRLEntryExtensionValue_from_der(X509_CRLEntryExtensionValue *a, int type, const uint8_t **in, size_t *inlen)
{
switch (type) {
case OID_id_ce_cRLReasons: return ASN1_ENUMERATED_to_der(&a->u.reasonCode, in, inlen);
case OID_id_ce_invalidityDate: return X509_GeneralizedTime_to_der(&a->u.invalidityDate, in, inlen);
case OID_id_ce_certificateIssuer: return X509_GeneralNames_to_der(&a->u.certificateIssuer, in, inlen);
}
}
void X509_CRLEntryExtensions_add(X509_CRLEntryExtensions *a, const X509_CRLEntryExtension *value)
{
size_t length = ((ASN1_SEQUENCE *)a)->length;
assert(a->count < 16);
X509_CRLEntryExtension_copy(&a->values[a->count], value);
X509_CRLEntryExtension_to_der(&a->values[a->count], NULL, &length);
ASN1_SEQUENCE_set((ASN1_SEQUENCE *)a, NULL, length);
a->count++;
}
void X509_CRLEntryExtensions_to_der(const X509_CRLEntryExtensions *a, uint8_t **out, size_t *outlen)
{
int i;
ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen);
for (i = 0; i < a->count; i++) {
X509_CRLEntryExtension_to_der(&a->value[i], out, outlen);
}
}
int X509_CRLEntryExtensions_from_der(X509_CRLExtensions *a, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *data;
size_t length;
if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) {
return ret;
}
data = ((ASN1_SEQUENCE *)a)->data;
length = ((ASN1_SEQUENCE *)a)->length;
while (length > 0) {
if (a->count >= 16
|| X509_CRLEntryExtension_from_der(&a->values[a->count], &data, &length) <= 0) {
return -1;
}
}
return 1;
}

2533
src/x509_ext.c Normal file

File diff suppressed because it is too large Load Diff

240
src/x509_lib.c Normal file
View File

@@ -0,0 +1,240 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
应用应该只调用这个文件中实现的接口
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <gmssl/sm2.h>
#include <gmssl/oid.h>
#include <gmssl/asn1.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
int x509_certificate_set_version(X509_CERTIFICATE *cert, int version)
{
if (version < X509_version_v1 || version > X509_version_v3) {
error_print();
return -1;
}
cert->tbs_certificate.version = version;
return 1;
}
int x509_certificate_set_serial_number(X509_CERTIFICATE *cert, const uint8_t *sn, size_t snlen)
{
if (!cert || !sn || snlen <= 0 || snlen > 20) {
error_print();
return -1;
}
memcpy(cert->tbs_certificate.serial_number, sn, snlen);
cert->tbs_certificate.serial_number_len = snlen;
return 1;
}
int x509_certificate_set_signature_algor_sm2(X509_CERTIFICATE *cert)
{
cert->tbs_certificate.signature_algor = OID_sm2sign_with_sm3;
cert->signature_algor = OID_sm2sign_with_sm3;
return 1;
}
int x509_certificate_set_issuer(X509_CERTIFICATE *cert, const X509_NAME *name)
{
memcpy(&cert->tbs_certificate.issuer, name, sizeof(X509_NAME));
return 1;
}
int x509_certificate_set_subject(X509_CERTIFICATE *cert, const X509_NAME *name)
{
memcpy(&cert->tbs_certificate.subject, name, sizeof(X509_NAME));
return 1;
}
int x509_certificate_set_validity(X509_CERTIFICATE *cert, time_t not_before, int days)
{
if (x509_validity_set_days(&cert->tbs_certificate.validity, not_before, days) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_certificate_set_signature_algor(X509_CERTIFICATE *cert, int oid)
{
cert->tbs_certificate.signature_algor = oid;
return 1;
}
int x509_certificate_set_subject_public_key_info_sm2(X509_CERTIFICATE *cert, const SM2_KEY *sm2_key)
{
X509_PUBLIC_KEY_INFO *pkey_info = &cert->tbs_certificate.subject_public_key_info;
x509_public_key_info_set_sm2(pkey_info, sm2_key);
return 1;
}
int x509_certificate_set_issuer_unique_id(X509_CERTIFICATE *cert, const uint8_t *id, size_t idlen)
{
memcpy(cert->tbs_certificate.issuer_unique_id, id, idlen);
cert->tbs_certificate.issuer_unique_id_len = idlen;
return 1;
}
int x509_certificate_set_subject_unique_id(X509_CERTIFICATE *cert, const uint8_t *id, size_t idlen)
{
memcpy(cert->tbs_certificate.subject_unique_id, id, idlen);
cert->tbs_certificate.subject_unique_id_len = idlen;
return 1;
}
int x509_certificate_set_issuer_unique_id_from_public_key_sm2(X509_CERTIFICATE *cert, const SM2_KEY *sm2_key)
{
uint8_t uniq_id[32];
sm2_public_key_digest(sm2_key, uniq_id);
x509_certificate_set_issuer_unique_id(cert, uniq_id, sizeof(uniq_id));
return 1;
}
int x509_certificate_set_subject_unique_id_from_public_key_sm2(X509_CERTIFICATE *cert, const SM2_KEY *sm2_key)
{
uint8_t uniq_id[32];
sm2_public_key_digest(sm2_key, uniq_id);
x509_certificate_set_subject_unique_id(cert, uniq_id, sizeof(uniq_id));
return 1;
}
int x509_certificate_sign_sm2(X509_CERTIFICATE *cert, const SM2_KEY *key)
{
SM2_SIGN_CTX ctx;
uint8_t buf[1024];
uint8_t *p = buf;
size_t len = 0;
cert->signature_algor = OID_sm2sign_with_sm3;
x509_tbs_certificate_to_der(&cert->tbs_certificate, &p, &len);
if (sm2_sign_init(&ctx, key, SM2_DEFAULT_ID) != 1
|| sm2_sign_update(&ctx, buf, len) != 1
|| sm2_sign_finish(&ctx, cert->signature, &cert->signature_len) != 1) {
error_print();
return -1;
}
memset(&ctx, 0, sizeof(ctx));
return 1;
}
// 这个公钥应该是根据issuer name从签名的CA证书中取得的
int x509_certificate_verify_sm2(const X509_CERTIFICATE *cert, const SM2_KEY *sm2_key)
{
SM2_SIGN_CTX ctx;
uint8_t buf[1024];
uint8_t *p = buf;
size_t len = 0;
x509_tbs_certificate_to_der(&cert->tbs_certificate, &p, &len);
if (sm2_verify_init(&ctx, sm2_key, SM2_DEFAULT_ID) != 1
|| sm2_verify_update(&ctx, buf, len) != 1
|| sm2_verify_finish(&ctx, cert->signature, cert->signature_len) != 1) {
return -1;
}
memset(&ctx, 0, sizeof(ctx));
return 1;
}
int x509_certificate_get_public_key_sm2(const X509_CERTIFICATE *cert, SM2_KEY *sm2_key)
{
*sm2_key = cert->tbs_certificate.subject_public_key_info.sm2_key;
return 1;
}
int x509_certificate_verify_by_certificate(const X509_CERTIFICATE *cert, const X509_CERTIFICATE *cacert)
{
int ret;
SM2_KEY ca_pubkey;
if (x509_name_equ(&cert->tbs_certificate.issuer, &cacert->tbs_certificate.subject) != 1) {
error_print();
return -1;
}
if (x509_certificate_get_public_key(cacert, &ca_pubkey) != 1) {
error_print();
return -1;
}
if ((ret = x509_certificate_verify(cert, &ca_pubkey)) < 0) {
error_print();
return -1;
}
return ret;
}
int x509_certificate_from_pem_by_name(X509_CERTIFICATE *cert, FILE *fp, const X509_NAME *issuer)
{
int ret;
for (;;) {
if ((ret = x509_certificate_from_pem(cert, fp)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (x509_name_equ(&cert->tbs_certificate.subject, issuer) == 1) {
return 1;
}
}
return 0;
}

601
src/zuc_core.c Normal file
View File

@@ -0,0 +1,601 @@
/*
* Copyright (c) 2015 - 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 <stdlib.h>
#include <string.h>
#include <gmssl/zuc.h>
#include "bswap.h"
static const ZUC_UINT15 KD[16] = {
0x44D7,0x26BC,0x626B,0x135E,0x5789,0x35E2,0x7135,0x09AF,
0x4D78,0x2F13,0x6BC4,0x1AF1,0x5E26,0x3C4D,0x789A,0x47AC,
};
static const uint8_t S0[256] = {
0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60,
};
static const uint8_t S1[256] = {
0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2,
};
#define ADD31(a,b) a += (b); a = (a & 0x7fffffff) + (a >> 31)
#define ROT31(a,k) ((((a) << (k)) | ((a) >> (31 - (k)))) & 0x7FFFFFFF)
#define ROT32(a,k) (((a) << (k)) | ((a) >> (32 - (k))))
#define L1(X) \
((X) ^ \
ROT32((X), 2) ^ \
ROT32((X), 10) ^ \
ROT32((X), 18) ^ \
ROT32((X), 24))
#define L2(X) \
((X) ^ \
ROT32((X), 8) ^ \
ROT32((X), 14) ^ \
ROT32((X), 22) ^ \
ROT32((X), 30))
#define LFSRWithInitialisationMode(u) \
V = LFSR[0]; \
ADD31(V, ROT31(LFSR[0], 8)); \
ADD31(V, ROT31(LFSR[4], 20)); \
ADD31(V, ROT31(LFSR[10], 21)); \
ADD31(V, ROT31(LFSR[13], 17)); \
ADD31(V, ROT31(LFSR[15], 15)); \
ADD31(V, (u)); \
{int j; for (j=0; j<15;j++) LFSR[j]=LFSR[j+1];} \
LFSR[15] = V
#define LFSRWithWorkMode() \
{ \
int j; \
uint64_t a = LFSR[0]; \
a += ((uint64_t)LFSR[0]) << 8; \
a += ((uint64_t)LFSR[4]) << 20; \
a += ((uint64_t)LFSR[10]) << 21; \
a += ((uint64_t)LFSR[13]) << 17; \
a += ((uint64_t)LFSR[15]) << 15; \
a = (a & 0x7fffffff) + (a >> 31); \
V = (a & 0x7fffffff) + (a >> 31); \
for (j = 0; j < 15; j++) \
LFSR[j] = LFSR[j+1]; \
LFSR[15] = V; \
}
#define BitReconstruction2(X1,X2) \
X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >> 15); \
X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >> 15)
#define BitReconstruction3(X0,X1,X2) \
X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF); \
BitReconstruction2(X1,X2)
#define BitReconstruction4(X0,X1,X2,X3) \
BitReconstruction3(X0,X1,X2); \
X3 = ((LFSR[2] & 0xFFFF) << 16) | (LFSR[0] >> 15)
#define MAKEU31(k,d,iv) \
(((uint32_t)(k) << 23) | \
((uint32_t)(d) << 8) | \
(uint32_t)(iv))
#define MAKEU32(a, b, c, d) \
(((uint32_t)(a) << 24) | \
((uint32_t)(b) << 16) | \
((uint32_t)(c) << 8) | \
((uint32_t)(d)))
#define F_(X1,X2) \
W1 = R1 + X1; \
W2 = R2 ^ X2; \
U = L1((W1 << 16) | (W2 >> 16)); \
V = L2((W2 << 16) | (W1 >> 16)); \
R1 = MAKEU32( S0[U >> 24], \
S1[(U >> 16) & 0xFF], \
S0[(U >> 8) & 0xFF], \
S1[U & 0xFF]); \
R2 = MAKEU32( S0[V >> 24], \
S1[(V >> 16) & 0xFF], \
S0[(V >> 8) & 0xFF], \
S1[V & 0xFF])
#define F(X0,X1,X2) \
(X0 ^ R1) + R2; \
F_(X1, X2)
void zuc_set_key(ZUC_KEY *key, const unsigned char *user_key, const unsigned char *iv)
{
ZUC_UINT31 *LFSR = key->LFSR;
uint32_t R1, R2;
uint32_t X0, X1, X2;
uint32_t W, W1, W2, U, V;
int i;
for (i = 0; i < 16; i++) {
LFSR[i] = MAKEU31(user_key[i], KD[i], iv[i]);
}
R1 = 0;
R2 = 0;
for (i = 0; i < 32; i++) {
BitReconstruction3(X0, X1, X2);
W = F(X0, X1, X2);
LFSRWithInitialisationMode(W >> 1);
}
BitReconstruction2(X1, X2);
F_(X1, X2);
LFSRWithWorkMode();
key->R1 = R1;
key->R2 = R2;
}
uint32_t zuc_generate_keyword(ZUC_KEY *key)
{
ZUC_UINT31 *LFSR = key->LFSR;
uint32_t R1 = key->R1;
uint32_t R2 = key->R2;
uint32_t X0, X1, X2, X3;
uint32_t W1, W2, U, V;
uint32_t Z;
BitReconstruction4(X0, X1, X2, X3);
Z = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
key->R1 = R1;
key->R2 = R2;
return Z;
}
void zuc_generate_keystream(ZUC_KEY *key, size_t nwords, uint32_t *keystream)
{
ZUC_UINT31 *LFSR = key->LFSR;
uint32_t R1 = key->R1;
uint32_t R2 = key->R2;
uint32_t X0, X1, X2, X3;
uint32_t W1, W2, U, V;
size_t i;
for (i = 0; i < nwords; i ++) {
BitReconstruction4(X0, X1, X2, X3);
keystream[i] = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
}
key->R1 = R1;
key->R2 = R2;
}
void zuc_mac_init(ZUC_MAC_CTX *ctx, const unsigned char key[16], const unsigned char iv[16])
{
memset(ctx, 0, sizeof(*ctx));
zuc_set_key((ZUC_KEY *)ctx, key, iv);
ctx->K0 = zuc_generate_keyword((ZUC_KEY *)ctx);
}
void zuc_mac_update(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t len)
{
ZUC_UINT32 T = ctx->T;
ZUC_UINT32 K0 = ctx->K0;
ZUC_UINT32 K1, M;
ZUC_UINT31 *LFSR = ctx->LFSR;
ZUC_UINT32 R1 = ctx->R1;
ZUC_UINT32 R2 = ctx->R2;
ZUC_UINT32 X0, X1, X2, X3;
ZUC_UINT32 W1, W2, U, V;
size_t i;
if (!data || !len) {
return;
}
if (ctx->buflen) {
size_t num = sizeof(ctx->buf) - ctx->buflen;
if (len < num) {
memcpy(ctx->buf + ctx->buflen, data, len);
ctx->buflen += len;
return;
}
memcpy(ctx->buf + ctx->buflen, data, num);
M = GETU32(ctx->buf);
ctx->buflen = 0;
BitReconstruction4(X0, X1, X2, X3);
K1 = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
for (i = 0; i < 32; i++) {
if (M & 0x80000000) {
T ^= K0;
}
M <<= 1;
K0 = (K0 << 1) | (K1 >> 31);
K1 <<= 1;
}
data += num;
len -= num;
}
while (len >= 4) {
M = GETU32(data);
BitReconstruction4(X0, X1, X2, X3);
K1 = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
for (i = 0; i < 32; i++) {
if (M & 0x80000000) {
T ^= K0;
}
M <<= 1;
K0 = (K0 << 1) | (K1 >> 31);
K1 <<= 1;
}
data += 4;
len -= 4;
}
if (len) {
memcpy(ctx->buf, data, len);
ctx->buflen = len;
}
ctx->R1 = R1;
ctx->R2 = R2;
ctx->K0 = K0;
ctx->T = T;
}
void zuc_mac_finish(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char mac[4])
{
ZUC_UINT32 T = ctx->T;
ZUC_UINT32 K0 = ctx->K0;
ZUC_UINT32 K1, M;
ZUC_UINT31 *LFSR = ctx->LFSR;
ZUC_UINT32 R1 = ctx->R1;
ZUC_UINT32 R2 = ctx->R2;
ZUC_UINT32 X0, X1, X2, X3;
ZUC_UINT32 W1, W2, U, V;
size_t i;
if (!data)
nbits = 0;
if (nbits >= 8) {
zuc_mac_update(ctx, data, nbits/8);
data += nbits/8;
nbits %= 8;
}
T = ctx->T;
K0 = ctx->K0;
LFSR = ctx->LFSR;
R1 = ctx->R1;
R2 = ctx->R2;
if (nbits)
ctx->buf[ctx->buflen] = *data;
if (ctx->buflen || nbits) {
M = GETU32(ctx->buf);
BitReconstruction4(X0, X1, X2, X3);
K1 = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
for (i = 0; i < ctx->buflen * 8 + nbits; i++) {
if (M & 0x80000000) {
T ^= K0;
}
M <<= 1;
K0 = (K0 << 1) | (K1 >> 31);
K1 <<= 1;
}
}
T ^= K0;
BitReconstruction4(X0, X1, X2, X3);
K1 = X3 ^ F(X0, X1, X2);
LFSRWithWorkMode();
T ^= K1;
ctx->T = T;
PUTU32(mac, T);
}
typedef unsigned char ZUC_UINT7;
static const ZUC_UINT7 ZUC256_D[][16] = {
{0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
};
#define ZUC256_MAKEU31(a,b,c,d) \
(((uint32_t)(a) << 23) | \
((uint32_t)(b) << 16) | \
((uint32_t)(c) << 8) | \
(uint32_t)(d))
static void zuc256_set_mac_key(ZUC_KEY *key, const unsigned char K[32],
const unsigned char IV[23], int macbits)
{
ZUC_UINT31 *LFSR = key->LFSR;
uint32_t R1, R2;
uint32_t X0, X1, X2;
uint32_t W, W1, W2, U, V;
const ZUC_UINT7 *D;
int i;
ZUC_UINT6 IV17 = IV[17] >> 2;
ZUC_UINT6 IV18 = ((IV[17] & 0x3) << 4) | (IV[18] >> 4);
ZUC_UINT6 IV19 = ((IV[18] & 0xf) << 2) | (IV[19] >> 6);
ZUC_UINT6 IV20 = IV[19] & 0x3f;
ZUC_UINT6 IV21 = IV[20] >> 2;
ZUC_UINT6 IV22 = ((IV[20] & 0x3) << 4) | (IV[21] >> 4);
ZUC_UINT6 IV23 = ((IV[21] & 0xf) << 2) | (IV[22] >> 6);
ZUC_UINT6 IV24 = IV[22] & 0x3f;
D = macbits/32 < 3 ? ZUC256_D[macbits/32] : ZUC256_D[3];
LFSR[0] = ZUC256_MAKEU31(K[0], D[0], K[21], K[16]);
LFSR[1] = ZUC256_MAKEU31(K[1], D[1], K[22], K[17]);
LFSR[2] = ZUC256_MAKEU31(K[2], D[2], K[23], K[18]);
LFSR[3] = ZUC256_MAKEU31(K[3], D[3], K[24], K[19]);
LFSR[4] = ZUC256_MAKEU31(K[4], D[4], K[25], K[20]);
LFSR[5] = ZUC256_MAKEU31(IV[0], (D[5] | IV17), K[5], K[26]);
LFSR[6] = ZUC256_MAKEU31(IV[1], (D[6] | IV18), K[6], K[27]);
LFSR[7] = ZUC256_MAKEU31(IV[10], (D[7] | IV19), K[7], IV[2]);
LFSR[8] = ZUC256_MAKEU31(K[8], (D[8] | IV20), IV[3], IV[11]);
LFSR[9] = ZUC256_MAKEU31(K[9], (D[9] | IV21), IV[12], IV[4]);
LFSR[10] = ZUC256_MAKEU31(IV[5], (D[10] | IV22), K[10], K[28]);
LFSR[11] = ZUC256_MAKEU31(K[11], (D[11] | IV23), IV[6], IV[13]);
LFSR[12] = ZUC256_MAKEU31(K[12], (D[12] | IV24), IV[7], IV[14]);
LFSR[13] = ZUC256_MAKEU31(K[13], D[13], IV[15], IV[8]);
LFSR[14] = ZUC256_MAKEU31(K[14], (D[14] | (K[31] >> 4)), IV[16], IV[9]);
LFSR[15] = ZUC256_MAKEU31(K[15], (D[15] | (K[31] & 0x0F)), K[30], K[29]);
R1 = 0;
R2 = 0;
for (i = 0; i < 32; i++) {
BitReconstruction3(X0, X1, X2);
W = F(X0, X1, X2);
LFSRWithInitialisationMode(W >> 1);
}
BitReconstruction2(X1, X2);
F_(X1, X2);
LFSRWithWorkMode();
key->R1 = R1;
key->R2 = R2;
}
void zuc256_set_key(ZUC_KEY *key, const unsigned char K[32],
const unsigned char IV[23])
{
zuc256_set_mac_key(key, K, IV, 0);
}
void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const unsigned char key[32],
const unsigned char iv[23], int macbits)
{
if (macbits < 32)
macbits = 32;
else if (macbits > 64)
macbits = 128;
memset(ctx, 0, sizeof(*ctx));
zuc256_set_mac_key((ZUC256_KEY *)ctx, key, iv, macbits);
zuc256_generate_keystream((ZUC256_KEY *)ctx, macbits/32, ctx->T);
zuc256_generate_keystream((ZUC256_KEY *)ctx, macbits/32, ctx->K0);
ctx->macbits = (macbits/32) * 32;
}
void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t len)
{
ZUC_UINT32 K1, M;
size_t n = ctx->macbits / 32;
size_t i, j;
if (!data || !len) {
return;
}
if (ctx->buflen) {
size_t num = sizeof(ctx->buf) - ctx->buflen;
if (len < num) {
memcpy(ctx->buf + ctx->buflen, data, len);
ctx->buflen += len;
return;
}
memcpy(ctx->buf + ctx->buflen, data, num);
M = GETU32(ctx->buf);
ctx->buflen = 0;
K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx);
for (i = 0; i < 32; i++) {
if (M & 0x80000000) {
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
}
}
M <<= 1;
for (j = 0; j < n - 1; j++) {
ctx->K0[j] = (ctx->K0[j] << 1) | (ctx->K0[j + 1] >> 31);
}
ctx->K0[j] = (ctx->K0[j] << 1) | (K1 >> 31);
K1 <<= 1;
}
data += num;
len -= num;
}
while (len >= 4) {
M = GETU32(data);
K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx);
for (i = 0; i < 32; i++) {
if (M & 0x80000000) {
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
}
}
M <<= 1;
for (j = 0; j < n - 1; j++) {
ctx->K0[j] = (ctx->K0[j] << 1) | (ctx->K0[j + 1] >> 31);
}
ctx->K0[j] = (ctx->K0[j] << 1) | (K1 >> 31);
K1 <<= 1;
}
data += 4;
len -= 4;
}
if (len) {
memcpy(ctx->buf, data, len);
ctx->buflen = len;
}
}
void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char *mac)
{
ZUC_UINT32 K1, M;
size_t n = ctx->macbits/32;
size_t i, j;
if (!data)
nbits = 0;
if (nbits >= 8) {
zuc256_mac_update(ctx, data, nbits/8);
data += nbits/8;
nbits %= 8;
}
if (nbits)
ctx->buf[ctx->buflen] = *data;
if (ctx->buflen || nbits) {
M = GETU32(ctx->buf);
K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx);
for (i = 0; i < ctx->buflen * 8 + nbits; i++) {
if (M & 0x80000000) {
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
}
}
M <<= 1;
for (j = 0; j < n - 1; j++) {
ctx->K0[j] = (ctx->K0[j] << 1) | (ctx->K0[j + 1] >> 31);
}
ctx->K0[j] = (ctx->K0[j] << 1) | (K1 >> 31);
K1 <<= 1;
}
}
for (j = 0; j < n; j++) {
ctx->T[j] ^= ctx->K0[j];
PUTU32(mac, ctx->T[j]);
mac += 4;
}
}

82
src/zuc_eea.c Normal file
View File

@@ -0,0 +1,82 @@
/* ====================================================================
* Copyright (c) 2015 - 2019 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 <stdlib.h>
#include <gmssl/zuc.h>
static void zuc_set_eea_key(ZUC_KEY *key, const unsigned char user_key[16],
ZUC_UINT32 count, ZUC_UINT5 bearer, ZUC_BIT direction)
{
unsigned char iv[16] = {0};
iv[0] = iv[8] = count >> 24;
iv[1] = iv[9] = count >> 16;
iv[2] = iv[10] = count >> 8;
iv[3] = iv[11] = count;
iv[4] = iv[12] = ((bearer << 1) | (direction & 1)) << 2;
zuc_set_key(key, user_key, iv);
}
void zuc_eea_encrypt(const ZUC_UINT32 *in, ZUC_UINT32 *out, size_t nbits,
const unsigned char key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
ZUC_BIT direction)
{
ZUC_KEY zuc_key;
size_t nwords = (nbits + 31)/32;
size_t i;
zuc_set_eea_key(&zuc_key, key, count, bearer, direction);
zuc_generate_keystream(&zuc_key, nwords, out);
for (i = 0; i < nwords; i++) {
out[i] ^= in[i];
}
if (nbits % 32 != 0) {
out[nwords - 1] |= (0xffffffff << (32 - (nbits%32)));
}
}

159
src/zuc_eia.c Normal file
View File

@@ -0,0 +1,159 @@
/* ====================================================================
* Copyright (c) 2015 - 2019 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 <stdlib.h>
#include <string.h>
#include <gmssl/zuc.h>
#include "bswap.h"
static void zuc_set_eia_iv(unsigned char iv[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
ZUC_BIT direction)
{
memset(iv, 0, 16);
iv[0] = count >> 24;
iv[1] = iv[9] = count >> 16;
iv[2] = iv[10] = count >> 8;
iv[3] = iv[11] = count;
iv[4] = iv[12] = bearer << 3;
iv[8] = iv[0] ^ (direction << 7);
iv[14] = (direction << 7);
}
#if 1
ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits,
const unsigned char key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
ZUC_BIT direction)
{
ZUC_MAC_CTX ctx;
unsigned char iv[16];
unsigned char mac[4];
zuc_set_eia_iv(iv, count, bearer, direction);
zuc_mac_init(&ctx, key, iv);
zuc_mac_finish(&ctx, (unsigned char *)data, nbits, mac);
return GETU32(mac);
}
#else
#define ZUC_MAC_BUF_WORDS 64
#define GET_WORD(p, i) ((i) % 32) \
? ((*((ZUC_UINT32 *)(p) + (i)/32) << ((i) % 32)) \
| (*((ZUC_UINT32 *)(p) + (i)/32 + 1) >> (32 - ((i) % 32)))) \
: *((ZUC_UINT32 *)(p) + (i)/32)
#define GET_BIT(p, i) \
(((*((ZUC_UINT32 *)(p) + (i)/32)) & (1 << (31 - ((i) % 32)))) ? 1 : 0)
ZUC_UINT32 ZUC_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits,
const unsigned char user_key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
ZUC_BIT direction)
{
ZUC_UINT32 T = 0;
ZUC_KEY key;
unsigned char iv[16];
ZUC_UINT32 buf[ZUC_MAC_BUF_WORDS + 2];
size_t nwords = (nbits + 31)/32;
size_t i;
size_t num = ZUC_MAC_BUF_WORDS;
ZUC_set_eia_iv(iv, count, bearer, direction);
ZUC_set_key(&key, user_key, iv);
if (nwords <= ZUC_MAC_BUF_WORDS) {
ZUC_generate_keystream(&key, nwords + 2, buf);
for (i = 0; i < nbits; i++) {
if (GET_BIT(data, i)) {
T ^= GET_WORD(buf, i);
}
}
T ^= GET_WORD(buf, i);
T ^= buf[nwords + 1];
return T;
} else {
ZUC_generate_keystream(&key, ZUC_MAC_BUF_WORDS + 1, buf);
for (i = 0; i < ZUC_MAC_BUF_WORDS * 32; i++) {
if (GET_BIT(data, i)) {
T ^= GET_WORD(buf, i);
}
}
data += ZUC_MAC_BUF_WORDS;
nwords -= ZUC_MAC_BUF_WORDS;
nbits -= ZUC_MAC_BUF_WORDS * 32;
}
while (nwords > ZUC_MAC_BUF_WORDS) {
buf[0] = buf[ZUC_MAC_BUF_WORDS];
ZUC_generate_keystream(&key, ZUC_MAC_BUF_WORDS, buf + 1);
for (i = 0; i < ZUC_MAC_BUF_WORDS * 32; i ++) {
if (GET_BIT(data, i)) {
T ^= GET_WORD(buf, i);
}
}
data += num;
nwords -= num;
nbits -= ZUC_MAC_BUF_WORDS * 32;
}
buf[0] = buf[ZUC_MAC_BUF_WORDS];
ZUC_generate_keystream(&key, nwords + 1, buf + 1);
for (i = 0; i < nbits; i++) {
if (GET_BIT(data, i)) {
T ^= GET_WORD(buf, i);
}
}
T ^= GET_WORD(buf, i);
T ^= buf[nwords + 1];
return T;
}
#endif

187
tests/aestest.c Normal file
View File

@@ -0,0 +1,187 @@
/*
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/aes.h>
int main(void)
{
int err = 0;
AES_KEY aes_key;
int i;
/* test 1 */
uint8_t key128[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
};
uint32_t rk128[4 * 11] = {
0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c,
0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605,
0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f,
0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b,
0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00,
0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc,
0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd,
0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f,
0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f,
0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e,
0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6,
};
/* test 2 */
uint8_t key192[24] = {
0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
};
uint32_t rk192[4 * 13] = {
0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5,
0x62f8ead2, 0x522c6b7b, 0xfe0c91f7, 0x2402f5a5,
0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2,
0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd,
0xe75fad44, 0xbb095386, 0x485af057, 0x21efb14f,
0xa448f6d9, 0x4d6dce24, 0xaa326360, 0x113b30e6,
0xa25e7ed5, 0x83b1cf9a, 0x27f93943, 0x6a94f767,
0xc0a69407, 0xd19da4e1, 0xec1786eb, 0x6fa64971,
0x485f7032, 0x22cb8755, 0xe26d1352, 0x33f0b7b3,
0x40beeb28, 0x2f18a259, 0x6747d26b, 0x458c553e,
0xa7e1466c, 0x9411f1df, 0x821f750a, 0xad07d753,
0xca400538, 0x8fcc5006, 0x282d166a, 0xbc3ce7b5,
0xe98ba06f, 0x448c773c, 0x8ecc7204, 0x01002202,
};
/* test 3 */
uint8_t key256[32] = {
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
};
uint32_t rk256[4 * 15] = {
0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781,
0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4,
0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde,
0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a,
0xd59aecb8, 0x5bf3c917, 0xfee94248, 0xde8ebe96,
0xb5a9328a, 0x2678a647, 0x98312229, 0x2f6c79b3,
0x812c81ad, 0xdadf48ba, 0x24360af2, 0xfab8b464,
0x98c5bfc9, 0xbebd198e, 0x268c3ba7, 0x09e04214,
0x68007bac, 0xb2df3316, 0x96e939e4, 0x6c518d80,
0xc814e204, 0x76a9fb8a, 0x5025c02d, 0x59c58239,
0xde136967, 0x6ccc5a71, 0xfa256395, 0x9674ee15,
0x5886ca5d, 0x2e2f31d7, 0x7e0af1fa, 0x27cf73c3,
0x749c47ab, 0x18501dda, 0xe2757e4f, 0x7401905a,
0xcafaaae3, 0xe4d59b34, 0x9adf6ace, 0xbd10190d,
0xfe4890d1, 0xe6188d0b, 0x046df344, 0x706c631e,
};
/* test 4 */
unsigned char in1[16] = {
0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d,
0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34,
};
unsigned char out1[16] = {
0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb,
0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32,
};
unsigned char buf[16] = {0};
printf("aes test 1 ");
aes_set_encrypt_key(&aes_key, key128, sizeof(key128));
if (memcmp(&aes_key, rk128, sizeof(rk128)) != 0) {
printf("failed\n");
err++;
} else {
printf("ok\n");
}
printf("aes test 2 ");
aes_set_encrypt_key(&aes_key, key192, sizeof(key192));
if (memcmp(&aes_key, rk192, sizeof(rk192)) != 0) {
printf("failed\n");
err++;
} else {
printf("ok\n");
}
printf("aes test 3 ");
aes_set_encrypt_key(&aes_key, key256, sizeof(key256));
if (memcmp(&aes_key, rk256, sizeof(rk256)) != 0) {
printf("failed\n");
err++;
} else {
printf("ok\n");
}
printf("aes test 4 ");
aes_set_encrypt_key(&aes_key, key128, sizeof(key128));
aes_encrypt(&aes_key, in1, buf);
if (memcmp(buf, out1, sizeof(out1)) != 0) {
printf("failed\n");
err++;
} else {
printf("ok\n");
}
printf("aes test 5 ");
aes_set_decrypt_key(&aes_key, key128, sizeof(key128));
aes_decrypt(&aes_key, buf, buf);
if (memcmp(buf, in1, sizeof(in1)) != 0) {
printf("failed\n");
err++;
} else {
printf("ok\n");
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More