mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Init commit of gmssl-v3
This commit is contained in:
220
.gitignore
vendored
Normal file
220
.gitignore
vendored
Normal 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
201
CMakeLists.txt
Normal 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
16
README.md
Normal 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
91
include/gmssl/aes.h
Normal 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
272
include/gmssl/asn1.h
Normal 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
96
include/gmssl/base64.h
Normal 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
|
||||
115
include/gmssl/block_cipher.h
Normal file
115
include/gmssl/block_cipher.h
Normal 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
97
include/gmssl/chacha20.h
Normal 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
109
include/gmssl/cipher.h
Normal 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
86
include/gmssl/cmac.h
Normal 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
276
include/gmssl/cms.h
Executable 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
122
include/gmssl/crl.h
Normal 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
95
include/gmssl/des.h
Normal 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
138
include/gmssl/digest.h
Normal 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
81
include/gmssl/error.h
Normal 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
100
include/gmssl/gcm.h
Normal 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
118
include/gmssl/hash_drbg.h
Normal 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
68
include/gmssl/hex.h
Normal 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
76
include/gmssl/hkdf.h
Normal 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
86
include/gmssl/hmac.h
Normal 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
85
include/gmssl/md5.h
Executable 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
313
include/gmssl/oid.h
Normal 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
79
include/gmssl/pbkdf2.h
Normal 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
72
include/gmssl/pem.h
Normal 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
167
include/gmssl/pkcs8.h
Normal 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
63
include/gmssl/rand.h
Normal 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
75
include/gmssl/rc4.h
Normal 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
86
include/gmssl/sha1.h
Executable 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
140
include/gmssl/sha2.h
Executable 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
130
include/gmssl/sha3.h
Normal 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
196
include/gmssl/sm2.h
Normal 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
101
include/gmssl/sm3.h
Executable 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
105
include/gmssl/sm4.h
Normal 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
96
include/gmssl/sm9.h
Normal 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
640
include/gmssl/tls.h
Normal 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
1114
include/gmssl/x509.h
Normal file
File diff suppressed because it is too large
Load Diff
137
include/gmssl/zuc.h
Executable file
137
include/gmssl/zuc.h
Executable 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
480
src/aes.c
Normal 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
1017
src/asn1.c
Normal file
File diff suppressed because it is too large
Load Diff
377
src/base64.c
Normal file
377
src/base64.c
Normal 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
203
src/block_cipher.c
Normal 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
56
src/bswap.h
Normal 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
123
src/chacha20.c
Normal 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
134
src/cmac.c
Normal 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;
|
||||
}
|
||||
298
src/ctr.c
Normal file
298
src/ctr.c
Normal 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
131
src/debug.c
Normal 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
267
src/des.c
Normal 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
527
src/digest.c
Normal 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
116
src/endian.h
Normal 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
351
src/ffx.c
Normal 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
250
src/gcm.c
Normal 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
188
src/gf128.c
Normal 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
75
src/gf128.h
Normal 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
346
src/hash_drbg.c
Normal 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
188
src/hex.c
Normal 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
162
src/hkdf.c
Normal 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
158
src/hmac.c
Normal 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
276
src/md5.c
Executable 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
58
src/mem.h
Normal 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
958
src/oid.c
Normal 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
174
src/pbkdf2.c
Normal 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
116
src/pem.c
Normal 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
588
src/pkcs8.c
Normal 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
65
src/rand.c
Normal 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
117
src/rc4.c
Normal 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
68
src/rotate.h
Normal 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
219
src/sha1.c
Executable 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
265
src/sha256.c
Executable 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
271
src/sha512.c
Executable 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
1665
src/sm2_algo.c
Normal file
File diff suppressed because it is too large
Load Diff
581
src/sm2_asn1.c
Normal file
581
src/sm2_asn1.c
Normal 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, ¶ms_len);
|
||||
asn1_explicit_to_der(0, NULL, params_len, NULL, &len);
|
||||
asn1_bit_string_to_der(public_key, sizeof(public_key) * 8, NULL, &pubkey_len);
|
||||
asn1_explicit_to_der(1, NULL, pubkey_len, NULL, &len);
|
||||
|
||||
asn1_sequence_header_to_der(len, out, outlen);
|
||||
asn1_int_to_der(version, out, outlen);
|
||||
asn1_octet_string_to_der(key->private_key, 32, out, outlen);
|
||||
asn1_explicit_header_to_der(0, params_len, out, outlen);
|
||||
asn1_object_identifier_to_der(OID_sm2, 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, ¶ms, ¶ms_len, &data, &datalen) < 0
|
||||
|| asn1_explicit_from_der(1, &pubkey, &pubkey_len, &data, &datalen) < 0
|
||||
|| datalen > 0) {
|
||||
return -1;
|
||||
}
|
||||
if (version != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (prikey_len != 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_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, ¶ms, ¶ms_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
277
src/sm2_lib.c
Normal 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
119
src/sm2_prn.c
Normal 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
506
src/sm3.c
Executable 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
144
src/sm3_hmac.c
Normal 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
208
src/sm4_avx2.c
Normal 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
127
src/sm4_cbc.c
Normal 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
16540
src/sm4_common.c
Normal file
File diff suppressed because it is too large
Load Diff
133
src/sm4_enc.c
Normal file
133
src/sm4_enc.c
Normal 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
99
src/sm4_lcl.h
Normal 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
119
src/sm4_setkey.c
Normal 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
75
src/sm9_keygen.c
Normal 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
2032
src/sm9_math.c
Normal file
File diff suppressed because it is too large
Load Diff
139
src/sm9_sign.c
Normal file
139
src/sm9_sign.c
Normal 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
936
src/tlcp.c
Normal 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;
|
||||
}
|
||||
971
src/tls12.c
Normal file
971
src/tls12.c
Normal 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
73
src/tls13.c
Normal 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
283
src/tls_cipher.c
Normal 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
927
src/tls_trace.c
Normal 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
361
src/x509_algor.c
Normal 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
1377
src/x509_asn1.c
Normal file
File diff suppressed because it is too large
Load Diff
463
src/x509_crl.c
Normal file
463
src/x509_crl.c
Normal 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
2533
src/x509_ext.c
Normal file
File diff suppressed because it is too large
Load Diff
240
src/x509_lib.c
Normal file
240
src/x509_lib.c
Normal 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
601
src/zuc_core.c
Normal 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
82
src/zuc_eea.c
Normal 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
159
src/zuc_eia.c
Normal 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
187
tests/aestest.c
Normal 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
Reference in New Issue
Block a user