diff --git a/.README.assets/image-20241223193812128.png b/.README.assets/image-20241223193812128.png new file mode 100644 index 0000000..b583599 Binary files /dev/null and b/.README.assets/image-20241223193812128.png differ diff --git a/.gitignore b/.gitignore index b795e33..10f11ff 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,5 @@ dmypy.json .pyre/ *.pem .DS_Store + +.idea/ \ No newline at end of file diff --git a/Core/GmSSL-3.1.1/.gitignore b/Core/GmSSL-3.1.1/.gitignore new file mode 100644 index 0000000..a7189d2 --- /dev/null +++ b/Core/GmSSL-3.1.1/.gitignore @@ -0,0 +1,43 @@ + +# generated file +/build* +/demos/*.pem +/demos/.private +/demos/scripts/*.pem +/demos/scripts/*.der +/demos/scripts/*.txt +/demos/scripts/*.bin +/demos/scripts/*.sig + +# Object files +*.o +*.obj + +# All kinds of executables +*.so +*.so.* +*.dylib +*.dylib.* +*.dll +*.dll.* +*.exe +*.pyc +*.exp +*.lib +*.pdb +*.ilk +*.def +*.rc +*.res + +# macOS +.DS_Store +*.tar.gz + +# editor artefacts +.vscode/* +*.swp +.#* +\#*# +*~ + diff --git a/Core/GmSSL-3.1.1/CMakeLists.txt b/Core/GmSSL-3.1.1/CMakeLists.txt new file mode 100644 index 0000000..34acff7 --- /dev/null +++ b/Core/GmSSL-3.1.1/CMakeLists.txt @@ -0,0 +1,412 @@ +cmake_minimum_required(VERSION 3.6) +project(GmSSL C) + +SET(CMAKE_PROJECT_HOMEPAGE_URL "http://gmssl.org") + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +include_directories(include) + +set(src + src/version.c + src/debug.c + src/sm4_common.c + src/sm4_enc.c + src/sm4_modes.c + src/sm4_setkey.c + src/sm3.c + src/sm3_hmac.c + src/sm3_kdf.c + src/sm2_alg.c + src/sm2_key.c + src/sm2_lib.c + src/sm9_alg.c + src/sm9_key.c + src/sm9_lib.c + src/zuc.c + src/zuc_modes.c + src/aes.c + src/aes_modes.c + src/sha256.c + src/sha512.c + src/chacha20.c + src/hash_drbg.c + src/block_cipher.c + src/digest.c + src/hmac.c + src/hkdf.c + src/pbkdf2.c + src/gf128.c + src/gcm.c + src/aead.c + src/pkcs8.c + src/ec.c + src/rsa.c + src/asn1.c + src/hex.c + src/base64.c + src/pem.c + src/x509_alg.c + src/x509_cer.c + src/x509_ext.c + src/x509_req.c + src/x509_crl.c + src/x509_new.c + src/cms.c + src/sdf/sdf.c + src/sdf/sdf_lib.c + src/sdf/sdf_meth.c + src/sdf/sdf_ext.c + src/sdf/sdf_sansec.c + src/skf/skf.c + src/skf/skf_lib.c + src/skf/skf_meth.c + src/skf/skf_ext.c + src/skf/skf_prn.c + src/skf/skf_wisec.c + src/socket.c + src/tls.c + src/tls_ext.c + src/tls_trace.c + src/tlcp.c + src/tls12.c + src/tls13.c + src/file.c +) + +set(tools + tools/gmssl.c + tools/version.c + tools/sm4.c + tools/sm3.c + tools/sm3hmac.c + tools/sm2keygen.c + tools/sm2sign.c + tools/sm2verify.c + tools/sm2encrypt.c + tools/sm2decrypt.c + tools/sm9setup.c + tools/sm9keygen.c + tools/sm9sign.c + tools/sm9verify.c + tools/sm9encrypt.c + tools/sm9decrypt.c + tools/zuc.c + tools/rand.c + tools/pbkdf2.c + tools/certgen.c + tools/certparse.c + tools/certverify.c + tools/certrevoke.c + tools/reqgen.c + tools/reqparse.c + tools/reqsign.c + tools/crlgen.c + tools/crlget.c + tools/crlparse.c + tools/crlverify.c + tools/cmssign.c + tools/cmsverify.c + tools/cmsencrypt.c + tools/cmsdecrypt.c + tools/cmsparse.c + tools/sdfutil.c + tools/skfutil.c + tools/tlcp_client.c + tools/tlcp_server.c + tools/tls12_client.c + tools/tls12_server.c + tools/tls13_client.c + tools/tls13_server.c +) + +set(tests + sm4 + sm3 + sm2 + sm9 + zuc + aes + sha224 + sha256 + sha384 + sha512 + chacha20 + hash_drbg + block_cipher + digest + hmac + hkdf + pbkdf2 + gf128 + gcm + aead + pkcs8 + ec + asn1 + hex + base64 + pem + x509 + x509_oid + x509_alg + x509_str + x509_ext + x509_req + x509_crl + cms + tls + tls13 +) + +set(demos + demo_sm2_encrypt + demo_sm2_keygen + demo_sm2_keyparse + demo_sm2_private_key + demo_sm2_private_key_parse + demo_sm2_public_key + demo_sm2_sign + demo_sm2_sign_ctx + demo_sm3 + demo_sm3_hmac + demo_sm3_kdf + demo_sm4 + demo_sm4_cbc + demo_sm4_cbc_decrypt_update + demo_sm4_cbc_encrypt_update + demo_sm4_cbc_padding + demo_sm4_ctr + demo_sm4_ctr_encrypt_update + demo_sm4_gcm + demo_sm9_encrypt + demo_sm9_keygen + demo_sm9_sign + demo_zuc +) + +include(CheckSymbolExists) + +# when an option has been enabled, `cmake ..` will not refresh the value +# use `cmake .. -DENABLE_XXX=OFF` to disable the option + +option(ENABLE_SM2_ALGOR_ID_ENCODE_NULL "Enable AlgorithmIdenifier with algorithm sm2sign_with_sm3 encode a NULL object as parameters" OFF) +if (ENABLE_SM2_ALGOR_ID_ENCODE_NULL) + message(STATUS "ENABLE_SM2_ALGOR_ID_ENCODE_NULL") + add_definitions(-DSM2_ALGOR_ID_ENCODE_NULL) +endif() + + +option(ENABLE_SM2_PRIVATE_KEY_EXPORT "Enable export un-encrypted SM2 private key" OFF) +if (ENABLE_SM2_PRIVATE_KEY_EXPORT) + message(STATUS "ENABLE_SM2_PRIVATE_KEY_EXPORT") + add_definitions(-DSM2_PRIVATE_KEY_EXPORT) + list(APPEND demos demo_sm2_key_export) +endif() + + +option(ENABLE_TLS_DEBUG "Enable TLS and TLCP print debug message" OFF) +if (ENABLE_TLS_DEBUG) + message(STATUS "ENABLE_TLS_DEBUG") + add_definitions(-DTLS_DEBUG) +endif() + +#option(ENABLE_SM3_AVX_BMI2 "Enable SM3 AVX+BMI2 assembly implementation" OFF) +#if (ENABLE_SM3_AVX_BMI2) +# message(STATUS "ENABLE_SM3_AVX_BMI2") +# add_definitions(-DSM3_AVX_BMI2) +# enable_language(ASM) +# list(APPEND src src/sm3_avx_bmi2.s) +#endif() + + +option(ENABLE_SM4_AESNI_AVX "Enable SM4 AESNI+AVX assembly implementation" OFF) +if (ENABLE_SM4_AESNI_AVX) + message(STATUS "ENABLE_SM4_AESNI_AVX") + add_definitions(-DSM4_AESNI_AVX) + list(APPEND src src/sm4_aesni_avx.c) + list(APPEND tests sm4_aesni_avx) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native") +endif() + + +option(ENABLE_SM2_EXTS "Enable SM2 Extensions" OFF) +if (ENABLE_SM2_EXTS) + message(STATUS "ENABLE_SM4_AESNI_AVX") + list(APPEND src + src/sm2_key_share.c + src/sm2_recover.c + src/sm2_blind.c + src/sm2_ring.c + src/sm2_elgamal.c + src/sm2_commit.c) + list(APPEND tests sm2_key_share sm2_blind sm2_ring sm2_elgamal sm2_commit) +endif() + + +option(ENABLE_BROKEN_CRYPTO "Enable broken crypto algorithms" OFF) +if (ENABLE_BROKEN_CRYPTO) + message(STATUS "ENABLE_BROKEN_CRYPTO") + list(APPEND src src/des.c src/sha1.c src/md5.c src/rc4.c) + list(APPEND tests des sha1 md5 rc4) +endif() + + +option(ENABLE_INTEL_RDRAND "Enable Intel RDRAND instructions" OFF) +option(ENABLE_INTEL_RDSEED "Enable Intel RDSEED instructions" OFF) + +if (ENABLE_INTEL_RDRAND) + include(CheckSourceCompiles) + set(CMAKE_REQUIRED_FLAGS "-rdrand") + check_source_compiles(C + "#include int main(void) { unsigned long long val; _rdrand64_step(&val); return 0; }" + HAVE_INTEL_RDRAND) + if (HAVE_INTEL_RDRAND) + message(STATUS "ENABLE_INTEL_RDRAND") + add_definitions(-DINTEL_RDRAND) + list(APPEND src src/rdrand.c) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mrdrnd") + endif() + if (ENABLE_INTEL_RDSEED) + set(CMAKE_REQUIRED_FLAGS "-rdseed") + check_source_compiles(C + "#include int main(void) { unsigned long long val; _rdseed64_step(&val); return 0; }" + HAVE_INTEL_RDSEED) + if (HAVE_INTEL_RDSEED) + message(STATUS "ENABLE_INTEL_RDSEED") + add_definitions(-DINTEL_RDSEED) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mrdseed") + endif() + endif() +endif() + + +option(ENABLE_GMT_0105_RNG "Enable GM/T 0105 Software RNG" OFF) +if (ENABLE_GMT_0105_RNG) + message(STATUS "ENABLE_GMT_0105_RNG") + list(APPEND src src/sm3_rng.c src/sm4_cbc_mac.c src/sm4_rng.c) + list(APPEND tests sm3_rng sm4_cbc_mac sm4_rng) +endif() + + +check_symbol_exists(getentropy "unistd.h" HAVE_GETENTROPY) +if (WIN32) + list(APPEND src src/rand_win.c src/http_win.c) +elseif (APPLE) + list(APPEND src src/rand_apple.c src/http.c) +elseif (HAVE_GETENTROPY) + list(APPEND src src/rand_unix.c src/http.c) + message(STATUS "have getentropy") +else() + list(APPEND src src/rand.c src/http.c) +endif() + + +option(ENABLE_HTTP_TESTS "Enable HTTP GET/POST related tests" OFF) +if (ENABLE_HTTP_TESTS) + message(STATUS "ENABLE_HTTP_TESTS") + list(APPEND tests http http_crl) +endif() + +# option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +option(BUILD_SHARED_LIBS "Build using shared libraries" ON) + +if (CMAKE_C_COMPILER_ID MATCHES "MSVC") + message(STATUS "CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS") + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) # set before add_library +endif() + +add_library(gmssl ${src}) + + +if (WIN32) + target_link_libraries(gmssl -lws2_32) +elseif (APPLE) + target_link_libraries(gmssl dl) + target_link_libraries(gmssl "-framework Security") + #target_link_libraries(gmssl "-framework CoreFoundation") # rand_apple.c CFRelease() +elseif (MINGW) + target_link_libraries(gmssl PRIVATE wsock32) +else() + target_link_libraries(gmssl dl) +endif() + + +SET_TARGET_PROPERTIES(gmssl PROPERTIES VERSION 3.1 SOVERSION 3) + + +install(TARGETS gmssl ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin) +install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/gmssl DESTINATION include) + +if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "iOS") + + add_library(sdf_dummy SHARED src/sdf/sdf_dummy.c) + set_target_properties(sdf_dummy PROPERTIES VERSION 3.1 SOVERSION 3) + + add_library(skf_dummy SHARED src/skf/skf_dummy.c) + set_target_properties(skf_dummy PROPERTIES VERSION 3.1 SOVERSION 3) + + add_executable(gmssl-bin ${tools}) + target_link_libraries(gmssl-bin LINK_PUBLIC gmssl) + set_target_properties(gmssl-bin PROPERTIES RUNTIME_OUTPUT_NAME gmssl) + if (MINGW) + target_link_libraries(gmssl-bin PRIVATE Ws2_32) + endif() + + enable_testing() + foreach(name ${tests}) + add_test(NAME ${name} COMMAND ${name}test) + add_executable(${name}test tests/${name}test.c) + target_link_libraries (${name}test LINK_PUBLIC gmssl) + endforeach() + + foreach(name ${demos}) + add_executable(${name} demos/src/${name}.c) + target_link_libraries(${name} LINK_PUBLIC gmssl) + endforeach() + + install(TARGETS gmssl-bin RUNTIME DESTINATION bin) +endif() + +if (CMAKE_C_COMPILER_ID MATCHES "MSVC") + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT gmssl-bin) + set(CMAKE_INSTALL_PREFIX "C:/Program Files/GmSSL") # change by `cmake -DCMAKE_INSTALL_PREFIX=C:\path\to\install` + # run `set path=%path%;C:\Program Files\GmSSL\bin` + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + + target_compile_options(gmssl PRIVATE /utf-8) + target_compile_options(gmssl-bin PRIVATE /utf-8) + +# target_compile_options(gmssl PRIVATE /wd4996) +# target_compile_options(gmssl-bin PRIVATE /wd4996) +endif() + + +set(CPACK_PACKAGE_NAME "GmSSL") +set(CPACK_PACKAGE_VENDOR "GmSSL develop team") +set(CPACK_PACKAGE_VERSION "3.1.1") + +set(CPACK_RPM_PACKAGE_GROUP "GmSSL Group") +set(CPACK_PACKAGE_VENDOR "GmSSL Vendor") + +set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) +string(CONCAT CPACK_PACKAGE_DESCRIPTION_SUMMARY + "GmSSL is an open source cryptographic toolbox that supports SM2 / SM3 / SM4 / SM9 " + "and other national secret (national commercial password) algorithm. ") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(CPACK_PACKAGE_CONTACT "https://github.com/guanzhi/GmSSL/issues") +# The general number of package itself. +# Should be incremented when the package content changes for the same version. +# Can be used to distinguish between different builds of the same version. +# Can be overridden by `cmake -DCPACK_NOARCH_PACKAGE_RELEASE=1` +set(CPACK_NOARCH_PACKAGE_RELEASE 1 CACHE STRING "The general release number of package") + +#set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local") +set(CPACK_NSIS_MODIFY_PATH ON) + +include(DebPacking) +include(RpmPacking) +include(CPack) + diff --git a/Core/GmSSL-3.1.1/INSTALL.md b/Core/GmSSL-3.1.1/INSTALL.md new file mode 100644 index 0000000..a66ebad --- /dev/null +++ b/Core/GmSSL-3.1.1/INSTALL.md @@ -0,0 +1,279 @@ +# 编译与安装 + +[TOC] + +## 概述 + +GmSSL当前版本采用CMake构建系统。由于CMake是一个跨平台的编译、安装工具,因此GmSSL可以在大多数主流操作系统上编译、安装和运行。GmSSL项目官方测试了Windows ( +包括Visual Stduio和Cygwin)、Linux、Mac、Android和iOS这几个主流操作系统上的编译,并通过GitHub的CI工作流对提交的最新代码进行自动化的编译测试。 + +和其他基于CMake的开源项目类似,GmSSL的构建过程主要包含配置、编译、测试、安装这几个步骤。以Linux操作系统环境为例,在下载并解压GmSSL源代码后,进入源代码目录,执行如下命令: + +```bash +mkdir build +cd build +cmake .. +make +make test +sudo make install +``` + +就可以完成配置、编译、测试和安装。 + +在执行`make`编译成功后,在`build/bin`目录下会生成项目的可执行文件和库文件。对于密码工具来说,在安装使用之前通过`make test` +进行测试是重要的一步,如果测试失败,那么不应该使用这个软件。在发生某个测试错误后,可以执行`build/bin`下的具体某个测试命令行,如 +`sm4test`,这样可以看到具体的错误打印信息。 + +执行`sudo make install`,安装完成后,可以命令行中调用`gmssl`命令行工具。在Linux和Mac环境下,头文件通常被安装在 +`/usr/local/include/gmssl`目录下,库文件被安装在`/usr/local/lib`目录下。 + +## 项目源代码 + +GmSSL项目的源代码在GitHub中发布和维护。 + +项目在GitHub的主页为:https://github.com/guanzhi/GmSSL + +源代码包含主分支的最新代码和定期发布的Release版本,建议优先采用主分支最新版。 + +### 通过CI判断当前代码状态 + +有时候最新提交的代码可能存在编译错误,通常这些错误会在1-2天内被新的提交修复。如果当前最新代码还没有修复,那么可以通过GitHub的CI状态来选择没有错误的代码。 + +通过GitHub的CI工作流状态可以判断某次提交是否存在编译错误,目前GmSSL项目中配置了如下编译环境: + +* CMake ubuntu-latest +* CMake windows-latest +* CMake macos-latest +* CMake-Android +* CMake-iOS + +通过查看这些CI的状态,可以判断当前代码是否可以在对应操作系统上成功编译。如果当前最新代码无法在某个平台上编译,那么可以选择之前某个通过测试的Commit版本。 + +##配置编译选项 + +在执行`cmake`阶段可以对项目的默认编译配置进行修改,修改是通过设置CMake变量来完成的,可以查看项目源代码中的`CMakeLists.txt`中所有的 +`option`指令来查看可选的配置。例如: + +```cmake +option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) +``` + +表明项目默认生成静态库,不生成动态库。 + +###设置生成动态库或静态库 + +GmSSL的CMake默认生成动态库,可以通过设定CMake变量`BUILD_SHARED_LIBS`为`ON`或者`OFF`来指定生成动态库或静态库。 + +``` +cmake .. -DBUILD_SHARED_LIBS=ON +``` + +### 设置优化的密码算法实现 + +GmSSL包含了针对特定硬件和处理指令集的密码算法优化实现,如针对Intel AVX2等指令集的优化,针对GPU的优化等,这些优化实现在匹配的处理器上的实现速度或安全性会大大超过默认的C语言实现。 + +在配置阶段可以显式地指定采用优化实现,可选的CMake配置变量包括: + +* `ENABLE_SM3_AVX_BMI2` SM3算法的AVX + BMI2指令集实现。 +* `ENABLE_SM3_X8_AVX2` SM3算法的AVX2指令集并行实现。 +* `ENABLE_SM3_X16_AVX512` SM3算法的AVX512指令集并行实现。 +* `ENABLE_SM4_AESNI_AVX` SM4算法的AESNI +AVX指令集实现。 +* `ENABLE_RDRND` 基于Intel RDRND指令的硬件随机数生成器。 +* `ENABLE_GF128_PCLMULQDQ` 基于Intel PCLMULQDQ指令的GCM模式实现。 + +### 编译不安全的密码算法 + +处于教学目的,GmSSL源代码中包含了一组不安全的密码算法,这些算法默认情况下不被编译到二进制文件中,可以通过设置`ENABLE_BROKEN_CRYPTO` +,在配置阶段启用这些算法,在当前`build`目录中执行: + +```bash +cmake .. -DENABLE_BROKEN_CRYPTO=ON +make +``` + +重新编译后,加入GmSSL库文件的算法包括: + +* DES分组密码 +* SHA1哈希函数 +* MD5哈希函数 +* RC4序列密码 + +## 在Visual Studio环境中编译 + +CMake支持通过指定不同的构建系统生成器(Generator),生成不同类型的Makefile。在Windows和Visual Studio环境下,CMake即可以生成常规的Visual +Studio解决方案(.sln)文件,在Visual Studio图形界面中完成编译,也可以生成类似于Linux环境下的Makefile文件,在命令行环境下完成编译和测试。 + +### 生成Makefile编译 + +在安装完Visual Studio之后,在启动菜单栏中会出现Visual Studio菜单目录,其中包含x64 Native Tools Command Prompt for VS +2022等多个终端命令行环境菜单项。 + +```bash +C:\Program Files\Microsoft Visual Studio\2022\Community>cd /path/to/gmssl +mkdir build +cd build +cmake .. -G "NMake Makefiles" +nmake +nmake test +``` + +在编译完成后直接执行安装会报权限错误,这是因为安装过程需要向系统目录中写入文件,而当前打开命令行环境的用户不具备该权限。可以通过右键选择“更多-以管理员身份运行”打开x64 +Native Tools Command Prompt for VS 2022终端,执行 + +``` +nmake install +``` + +那么`gmssl`命令行程序、头文件和库文件分别被写入`C:/Program Files/GmSSL/bin`、`C:/Program Files/GmSSL/include`、 +`C:/Program Files/GmSSL/lib`这几个系统目录中。为了能够直接在命令行环境任意目录下执行`gmssl`命令行程序,需要将其安装目录加入到系统路径中,可以执行: + +```bash +set path=%path%;C:\Program Files\GmSSL\bin +``` + +设置完毕后可以在命令行中执行`path`,查看新的路径是否已经成功加入。 + +### 在Visual Studio图形界面中编译 + +在安装完Visual Studio之后,在启动菜单栏中会出现Visual Studio菜单目录,其中包含x64 Native Tools Command Prompt for VS +2022等多个终端命令行环境菜单项。 + +```bash +C:\Program Files\Microsoft Visual Studio\2022\Community>cd /path/to/gmssl +mkdir build +cd build +cmake .. +``` + +完成后可以看到CMake在`build`目录下生成了一个`GmSSL.sln`文件和大量的`.vcxproj`文件。 + +点击`GmSSL.sln`就打开Visual Studio,点击Visual Studio工具栏上的"本地Windows调试器"按钮,可以启动编译。 + +在Visual Studio界面中可以选择Debug、Release、MinSizeRel等不同配置。 + +### 在Visual Studio中运行测试 + +在解决方案资源管理器中找到`RUN_TESTS`项目,右键菜单选择"调试-启动新实例",即可运行测试,并且在”输出“窗口中看到测试结果。测试完成后会出现RUN_TESTS拒绝访问的对话框。 + +### 选择生成32位或64位程序 + +通过在Visual Studio不同的命令行环境中编译GmSSL,可以生成32位的X86或者64位的X86_64程序,在x64 Native Tools Command Prompt for VS +2022命令行环境下,生成的是64位的程序,在x86 Native Tools Command Prompt for VS 2022命令行环境下,生成的是32位的程序。 + +可以通过Windows操作系统内置的资源管理器来检查编译生成的可执行程序是32位还是64位,在资源管理器的CPU页面中,通过“选择列”增加“平台”列,这样就可以显示每个进程的是32位或64位。可以运行 +`gmssl tlcp_client`或者在某个测试文件中增加循环时间来保持命令行运行一段时间。 + +## 在Cygwin环境中编译 + +Cygwin是Windows上的Linux模拟运行环境。Cygwin提供了Linux Shell和大量Linux命令行工具,也提供了应用程序开发必须的编译工具、头文件和库文件。面向Linux开发的应用通常依赖 +`unistd.h`、`sys/socket.h`等头文件及函数,但是Visual +Studio的C库并没有提供这些POSIX函数实现,因此这些Linux应用没有办法直接在Windows环境下编译。Cygwin通过封装Windows操作系统原生功能,提供了一个POSIX接口层,以及封装这些功能的动态库( +`cygwin1.dll`),并且提供了GCC、CMake等完整的Linux编译工具链,这意味着标准所有Linux环境下的标准头文件都存在,并且代码中依赖GCC编译器的特殊语法都可以被编译器识别(Visual +Studio的`cl`编译器不能完整支持C99语法),因此标准的Linux应用都可以通过Cygwin移植到Windows环境,编译为Windows本地应用。Cygwin提供的Linux +Shell环境意味Shell脚本也是可以使用的。 + +在Cygwin环境下编译生成的可执行程序是原生的Windows程序,和Visual Studio编译的程序的主要区别在于,Cygwin下编译的程序都必须依赖 +`cygwin1.dll`这个动态库,因为应用所有的POSIX函数调用都需要通过这个动态库翻译为Windows本地的系统调用(如WinSock2),因此发布Cygwin的程序不太方便,必须要包含一个较大的 +`cygwin1.dll`库文件。另外如果应用涉及大量的系统调用,那么通过Cygwin中间层会引入一定的开销,理论上会比Visual Studio编译的应用效率略低。 + +总的来说,如果你想在Windows环境下快速尝试一下GmSSL的命令行功能,并且可能需要利用Linux Shell环境下的一些常用工具做实验和测试,或者不太熟悉Visual +Studio开发环境,那么采用Cygwin环境是一个非常方便的选择。 + +### 准备Cygwin环境 + +Cygwin的安装、配置都是通过一个单一的`setup-x86_64.exe`应用程序完成的。在Cygwin的官网 https://www.cygwin.com/ 可以下载这个应用程序。 + +注意,在首次安装的时候可能没有选择所有需要的程序,再次运行`setup-x86_64.exe` +程序可以对环境进行配置和更新。有些工具,例如CMake,官方提供了独立的Windows安装包,在Cygwin环境下没有必要独立安装这些工具,也不建议安装,所有依赖的Linux工具都应该通过Cygwin环境来配置管理。 + +在安装、配置完成之后,可以通过运行`Cygwin64 Terminal`应用,打开一个命令行环境。 + +### 在Cygwin环境中编译GmSSL + +Cygwin环境相对标准的Linux环境有一些细微的差别。首先,在Cygwin命令行环境中,文件系统是一个类似Linux文件系统结构的独立目录,如果源代码已经下载到Windows操作系统中(比如,下载到用户的Download目录),那么需要首先将源代码拷贝到Cygwin文件系统的用户目录中(例如当前用户默认目录 +`~`)。在Cygwin文件系统中,Windows文件系统被映射到`/cygdrive`目录中,Windows当前用户Guan Zhi的下载目录中的`GmSSL-master.zip`文件就被映射到 +`/cygdrive/c/Users/Guan Zhi/Downloads/GmSSL-master.zip`中。 + +```bash +cp "/cygdrive/c/Users/Guan Zhi/Downloads/GmSSL-master.zip" ~/ +``` + +然后可以按照Linux环境下相似的过程编译、安装 + +```bash +unzip GmSSL-master.zip +cd GmSSL-master +mkdir build +cd build +cmake .. +make +make test +make install +``` + +注意,由于在Cygwin环境中用户本身具有系统权限,因此在执行`make install`时不需要`sudo`。 + +在安装完成之后,可以在Cygwin的命令行环境下执行`gmssl`命令行,或者运行源代码`demo`目录下的演示脚本。 + +注意,将`gmssl`等可执行程序直接从Cygwin目录拷贝到Windows文件系统下,在执行时会提示找不到`cygwin1.dll` +的错误,运行或者发布可执行程序时,应处理好对这个动态库的依赖问题。 + +### 存在的问题 + +似乎CMake选项`BUILD_SHARED_LIBS` 不起作用,总会同时生成静态库和动态库。 + +Cygwin的动态库名称比较特殊,是以`cyg`开头的。 + +## 面向iOS/iPhoneOS的交叉编译 + +下载 https://github.com/leetal/ios-cmake ,将`ios.toolchain.cmake`文件复制到`build`目录。 + +```bash +mkdir build; cd build +cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../ios.toolchain.cmake -DPLATFORM=OS64 +cmake --build . --config Release +``` + +如果出现“error: Signing for "gmssl" requires a development team.”错误,可以用Xcode打开工程文件,在Signing配置中设置Development Team。 + +## 面向Android的交叉编译 + +下载Android NDK,执行 + +```bash +mkdir build; cd build +cmake .. -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-23 +make +``` + +## 安装包构建 + +依赖cmake工具包中的cpack工具,生成可发布的安装包。 + +生成的安装包在`build`目录下。 + +### 构建DEB安装包 + +``` +mkdir build; cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +cpack -G DEB +``` + +### 构建RPM安装包 + +``` +mkdir build; cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +cpack -G RPM +``` + +### 构建`.sh`安装脚本 + +``` +mkdir build; cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +cpack -G DEB +make package +``` + diff --git a/Core/GmSSL-3.1.1/LICENSE b/Core/GmSSL-3.1.1/LICENSE new file mode 100644 index 0000000..d9a10c0 --- /dev/null +++ b/Core/GmSSL-3.1.1/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/Core/GmSSL-3.1.1/README.md b/Core/GmSSL-3.1.1/README.md new file mode 100644 index 0000000..e5d5483 --- /dev/null +++ b/Core/GmSSL-3.1.1/README.md @@ -0,0 +1,115 @@ +# GmSSL + +[![CMake](https://github.com/guanzhi/GmSSL/workflows/CMake/badge.svg)](https://github.com/guanzhi/GmSSL/actions/workflows/cmake.yml) +[![CMake-Android](https://github.com/guanzhi/GmSSL/actions/workflows/android-ci.yml/badge.svg)](https://github.com/guanzhi/GmSSL/actions/workflows/android-ci.yml) +[![CMake-iOS](https://github.com/guanzhi/GmSSL/actions/workflows/ios.yml/badge.svg)](https://github.com/guanzhi/GmSSL/actions/workflows/ios.yml) + +GmSSL是由北京大学自主开发的国产商用密码开源库,实现了对国密算法、标准和安全通信协议的全面功能覆盖,支持包括移动端在内的主流操作系统和处理器,支持密码钥匙、密码卡等典型国产密码硬件,提供功能丰富的命令行工具及多种编译语言编程接口。 + +## 主要特性 + +* 超轻量:GmSSL 3 大幅度降低了内存需求和二进制代码体积,不依赖动态内存,可以用于无操作系统的低功耗嵌入式环境(MCU、SOC等) + ,开发者也可以更容易地将国密算法和SSL协议嵌入到现有的项目中。 +* 更合规:GmSSL 3 可以配置为仅包含国密算法和国密协议(TLCP协议),依赖GmSSL 的密码应用更容易满足密码产品型号检测的要求,避免由于混杂非国密算法、不安全算法等导致的安全问题和合规问题。 +* 更安全:TLS 1.3在安全性和通信延迟上相对之前的TLS协议有巨大的提升,GmSSL 3 支持TLS 1.3协议和RFC 8998的国密套件。GmSSL 3 + 默认支持密钥的加密保护,提升了密码算法的抗侧信道攻击能力。 +* 跨平台:GmSSL 3 更容易跨平台,构建系统不再依赖Perl,默认的CMake构建系统可以容易地和Visual Studio、Android + NDK等默认编译工具配合使用,开发者也可以手工编写Makefile在特殊环境中编译、剪裁。 + +## 下载 + +* GmSSL的主分支版本为 [GmSSL-3.1.0](https://github.com/guanzhi/GmSSL/releases/tag/v3.1.0),主要增加跨平台特性,特别是对Windows/Visual + Studio的支持,Windows、Android、iOS平台的开发者需要使用该版本。 + +## 编译与安装 + +GmSSL 3 采用了cmake构建系统。下载源代码后将其解压缩,进入源码目录,执行: + +```bash +mkdir build +cd build +cmake .. +make +make test +sudo make install +``` + +在`make install`完成后,GmSSL会在默认安装目录中安装`gmssl`命令行工具,在头文件目录中创建`gmssl`目录,并且在库目录中安装`libgmssl.a`、 +`libgmssl.so`等库文件。 + +### Visual Studio环境编译 + +在Visual Studio命令提示符下执行: + +```bash +mkdir build +cd build +cmake .. -G "NMake Makefiles" +nmake +``` + +## 主要功能 + +### 密码算法 + +* 分组密码:SM4 (CBC/CTR/GCM), AES (CBC/CTR/GCM) +* 序列密码:ZUC/ZUC-256, ChaCha20, RC4 +* 哈希函数: SM3, SHA-224/256/384/512, SHA-1, MD5 +* 公钥密码:SM2加密/签名, SM9加密/签名 +* MAC算法:HMAC, GHASH +* 密钥导出函数:PBKDF2、HKDF +* 随机数生成器:Intel RDRAND, HASH_DRBG (NIST.SP.800-90A) + +### 证书和数字信封 + +* 数字证书:X.509证书, CRL证书注销列表, CSR (PKCS #10) 证书签名请求 +* 私钥加密:基于SM4/SM3口令加密的PEM格式私钥 (PKCS #8) +* 数字信封:SM2密码消息 (GM/T 0010-2012) + +### SSL协议 + +* TLCP 1.1,支持密码套`TLS_ECC_SM4_CBC_SM3 {0xE0,0x13}` (GB/T 38636-2020、GM/T 0024-2014) +* TLS 1.2,支持密码套件`TLS_ECDHE_SM4_CBC_SM3 {0xE0,0x11}` (GB/T 38636-2020、GM/T 0024-2014) +* TLS 1.3,支持密码套件`TLS_SM4_GCM_SM3 {0x00,0xC6}` (RFC 8998) + +### 多语言接口 + +GmSSL通过子项目提供多种多种编程语言绑定 + +* [GmSSL-Java](https://github.com/GmSSL/GmSSL-Java) 以JNI方式实现的Java语言绑定 +* [GmSSL-PHP](https://github.com/GmSSL/GmSSL-PHP) 以PHP扩展方式实现的PHP语言绑定 +* [GmSSL-Go](https://github.com/GmSSL/GmSSL-Go) 以CGO方式实现的Go语言绑定 +* [GmSSL-Python](https://github.com/GmSSL/GmSSL-Python) 以ctypes方式实现的Python语言绑定 +* [GmSSL-JS](https://github.com/guanzhi/GmSSL-JS) 纯JavaScript实现的国密算法库 + +## 典型应用 + +#### Nginx-with-GmSSL3.0 + +GmSSL支持Nginx的适配,并提供了Docker实现,具体参见[Nginx-with-GmSSL3.0](https://github.com/zhaoxiaomeng/Nginx-with-GmSSLv3) 项目。 + +## Roadmap + +- [X] Add Windows Visual Studio support +- [X] Add Windows Cygwin support +- [X] Add iOS support +- [X] Add Android support +- [x] **Version 3.1.0 release** +- [ ] Add GCC specific optimization +- [ ] Add X86_64 assembly implementation +- [ ] Add GPU implementation +- [ ] Add performance benchmark tool +- [ ] Add GCM cipher suites +- [ ] Release official open interfaces +- [ ] **Version 3.2.0 release** + +## 开发者们 + + + + + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/guanzhi/GmSSL.svg)](https://starchart.cc/guanzhi/GmSSL) + diff --git a/Core/GmSSL-3.1.1/cmake/DebPacking.cmake b/Core/GmSSL-3.1.1/cmake/DebPacking.cmake new file mode 100644 index 0000000..60312bb --- /dev/null +++ b/Core/GmSSL-3.1.1/cmake/DebPacking.cmake @@ -0,0 +1,3 @@ +set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) +set(CPACK_DEBIAN_PACKAGE_RELEASE ${CPACK_NOARCH_PACKAGE_RELEASE}) +set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_VENDOR}) diff --git a/Core/GmSSL-3.1.1/cmake/LinuxPacking.cmake b/Core/GmSSL-3.1.1/cmake/LinuxPacking.cmake new file mode 100644 index 0000000..8645125 --- /dev/null +++ b/Core/GmSSL-3.1.1/cmake/LinuxPacking.cmake @@ -0,0 +1,17 @@ +set(CPACK_PACKAGE_NAME "gmssl") +set(CPACK_PACKAGE_VENDOR "GmSSL develop team") +set(CPACK_PACKAGE_VERSION_MAJOR 3) +set(CPACK_PACKAGE_VERSION_MINOR 0) +set(CPACK_PACKAGE_VERSION_PATCH 0) +set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) +string(CONCAT CPACK_PACKAGE_DESCRIPTION_SUMMARY + "GmSSL is an open source cryptographic toolbox that supports SM2 / SM3 / SM4 / SM9 " + "and other national secret (national commercial password) algorithm. ") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(CPACK_PACKAGE_INSTALL_DIRECTORY /usr) +set(CPACK_PACKAGE_CONTACT "https://github.com/guanzhi/GmSSL/issues") +# The general number of package itself. +# Should be incremented when the package content changes for the same version. +# Can be used to distinguish between different builds of the same version. +# Can be overridden by `cmake -DCPACK_NOARCH_PACKAGE_RELEASE=1` +set(CPACK_NOARCH_PACKAGE_RELEASE 1 CACHE STRING "The general release number of package") diff --git a/Core/GmSSL-3.1.1/cmake/RpmPacking.cmake b/Core/GmSSL-3.1.1/cmake/RpmPacking.cmake new file mode 100644 index 0000000..61aefec --- /dev/null +++ b/Core/GmSSL-3.1.1/cmake/RpmPacking.cmake @@ -0,0 +1,2 @@ +set(CPACK_RPM_FILE_NAME RPM-DEFAULT) +set(CPACK_RPM_PACKAGE_RELEASE ${CPACK_NOARCH_PACKAGE_RELEASE}) diff --git a/Core/GmSSL-3.1.1/demos/certs/crl/Civil Servant ROOT.crl b/Core/GmSSL-3.1.1/demos/certs/crl/Civil Servant ROOT.crl new file mode 100644 index 0000000..a713b43 Binary files /dev/null and b/Core/GmSSL-3.1.1/demos/certs/crl/Civil Servant ROOT.crl differ diff --git a/Core/GmSSL-3.1.1/demos/certs/crl/Device ROOT.crl b/Core/GmSSL-3.1.1/demos/certs/crl/Device ROOT.crl new file mode 100644 index 0000000..0384dfd Binary files /dev/null and b/Core/GmSSL-3.1.1/demos/certs/crl/Device ROOT.crl differ diff --git a/Core/GmSSL-3.1.1/demos/certs/crl/ROOTCA.crl b/Core/GmSSL-3.1.1/demos/certs/crl/ROOTCA.crl new file mode 100644 index 0000000..8200bc0 Binary files /dev/null and b/Core/GmSSL-3.1.1/demos/certs/crl/ROOTCA.crl differ diff --git a/Core/GmSSL-3.1.1/demos/scripts/cademo.sh b/Core/GmSSL-3.1.1/demos/scripts/cademo.sh new file mode 100755 index 0000000..7379651 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/cademo.sh @@ -0,0 +1,44 @@ +#!/bin/bash -x + +set -e + +gmssl sm2keygen -pass 1234 -out rootcakey.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign +gmssl certparse -in rootcacert.pem + +gmssl sm2keygen -pass 1234 -out cakey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN "Sub CA" -key cakey.pem -pass 1234 -out careq.pem +gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem +gmssl certparse -in cacert.pem + +gmssl sm2keygen -pass 1234 -out signkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem +gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem +gmssl certparse -in signcert.pem + +gmssl sm2keygen -pass 1234 -out enckey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key enckey.pem -pass 1234 -out encreq.pem +gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem +gmssl certparse -in enccert.pem + +rm -fr revoked_certs.der +gmssl certrevoke -in signcert.pem -reason keyCompromise -out revoked_certs.der +gmssl certrevoke -in enccert.pem -reason keyCompromise -out revoked_certs.der +gmssl crlgen -in revoked_certs.der -cacert cacert.pem -key cakey.pem -pass 1234 -next_update 20240101000000Z -gen_authority_key_id -crl_num 1 -out crl.der +gmssl crlparse -in crl.der + +rm -fr rootcakey.pem +rm -fr rootcacert.pem +rm -fr cakey.pem +rm -fr careq.pem +rm -fr cacert.pem +rm -fr signkey.pem +rm -fr signreq.pem +rm -fr signcert.pem +rm -fr enckey.pem +rm -fr encreq.pem +rm -fr enccert.pem +rm -fr revoked_certs.der +rm -fr crl.der + +echo "all ok" diff --git a/Core/GmSSL-3.1.1/demos/scripts/certdemo.sh b/Core/GmSSL-3.1.1/demos/scripts/certdemo.sh new file mode 100755 index 0000000..57d4607 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/certdemo.sh @@ -0,0 +1,42 @@ +#!/bin/bash -x + +set -e + +gmssl sm2keygen -pass 1234 -out rootcakey.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \ + -key rootcakey.pem -pass 1234 \ + -out rootcacert.pem \ + -ca -path_len_constraint 6 \ + -key_usage keyCertSign -key_usage cRLSign \ + -crl_http_uri http://pku.edu.cn/ca.crl -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn + +gmssl certparse -in rootcacert.pem + +gmssl sm2keygen -pass 1234 -out cakey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN "Sub CA" -key cakey.pem -pass 1234 -out careq.pem +gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem \ + -crl_http_uri http://pku.edu.cn/ca.crl -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn +gmssl certparse -in cacert.pem + +gmssl sm2keygen -pass 1234 -out signkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem +gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem \ + -crl_http_uri http://github.com/guanzhi/GmSSL/raw/master/demos/certs/SubCA-1.crl +gmssl certparse -in signcert.pem + +gmssl sm2keygen -pass 1234 -out enckey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key enckey.pem -pass 1234 -out encreq.pem +gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem \ + -crl_http_uri http://github.com/guanzhi/GmSSL/raw/master/demos/certs/SubCA-1.crl +gmssl certparse -in enccert.pem + +cat signcert.pem >certs.pem +cat cacert.pem >>certs.pem +gmssl certverify -in certs.pem -cacert rootcacert.pem #-check_crl + +cat signcert.pem >dbl_certs.pem +cat enccert.pem >>dbl_certs.pem +cat cacert.pem >>dbl_certs.pem +gmssl certverify -double_certs -in dbl_certs.pem -cacert rootcacert.pem #-check_crl + +echo ok diff --git a/Core/GmSSL-3.1.1/demos/scripts/certs.sh b/Core/GmSSL-3.1.1/demos/scripts/certs.sh new file mode 100755 index 0000000..fb5fddc --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/certs.sh @@ -0,0 +1,27 @@ +#!/bin/bash -x + +set -e + +cd ../certs + +gmssl certparse -in "rootca/Civil Servant ROOT.pem" +gmssl certverify -in "rootca/Civil Servant ROOT.pem" -cacert "rootca/Civil Servant ROOT.pem" +gmssl crlparse -in "crl/Civil Servant ROOT.crl" +gmssl crlverify -in "crl/Civil Servant ROOT.crl" -cacert "rootca/Civil Servant ROOT.pem" + +gmssl certparse -in "rootca/Device ROOT.pem" +gmssl certverify -in "rootca/Device ROOT.pem" -cacert "rootca/Device ROOT.pem" +gmssl crlparse -in "crl/Device ROOT.crl" +gmssl crlverify -in "crl/Device ROOT.crl" -cacert "rootca/Device ROOT.pem" + +gmssl certparse -in "rootca/ROOTCA.pem" +gmssl certverify -in "rootca/ROOTCA.pem" -cacert "rootca/ROOTCA.pem" +gmssl crlparse -in "crl/ROOTCA.crl" +gmssl crlverify -in "crl/ROOTCA.crl" -cacert "rootca/ROOTCA.pem" # now > next_update + +# The CRL URI of ROOTCA.pem is in Base64 format, not DER +gmssl certverify -in "ca/TJCA.pem" -cacert "rootca/Civil Servant ROOT.pem" #-check_crl +gmssl certverify -in "ca/Taier CA.pem" -cacert "rootca/ROOTCA.pem" #-check_crl +gmssl certverify -in "ca/Ant Financial Certification Authority S1.pem" -cacert "rootca/ROOTCA.pem" #-check_crl + +echo ok diff --git a/Core/GmSSL-3.1.1/demos/scripts/certverify.sh b/Core/GmSSL-3.1.1/demos/scripts/certverify.sh new file mode 100755 index 0000000..40061a2 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/certverify.sh @@ -0,0 +1,125 @@ +#!/bin/bash -x + +set -e + +signcert=ebssec.boc.cn-sign.pem +enccert=ebssec.boc.cn-enc.pem +crl=CFCA_SM2_OCA1.crl +cacert=CFCA_SM2_OCA1.pem +rootcacert=CFCA_CS_SM2_CA.pem + +cat <$signcert +-----BEGIN CERTIFICATE----- +MIICzzCCAnKgAwIBAgIFEzY5M3AwDAYIKoEcz1UBg3UFADAlMQswCQYDVQQGEwJD +TjEWMBQGA1UECgwNQ0ZDQSBTTTIgT0NBMTAeFw0yMTA2MTEwOTA1MjBaFw0yNjA2 +MTkwODE2NTZaMIGRMQswCQYDVQQGEwJDTjEPMA0GA1UECAwG5YyX5LqsMQ8wDQYD +VQQHDAbljJfkuqwxJzAlBgNVBAoMHuS4reWbvemTtuihjOiCoeS7veaciemZkOWF +rOWPuDERMA8GA1UECwwITG9jYWwgUkExDDAKBgNVBAsMA1NTTDEWMBQGA1UEAwwN +ZWJzc2VjLmJvYy5jbjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABPsNUnoZQM9C +SnvC57TbvdfyOTCuPOSlZmPAyxBKFj+Y1QH/xlubHdVf5XqHrO1jCDRi7aN5IKGX +QF1492c803OjggEeMIIBGjAfBgNVHSMEGDAWgBRck1ggWiRzVhAbZFAQ7OmnygdB +ETAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEwMTAvBggrBgEF +BQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wNwYDVR0f +BDAwLjAsoCqgKIYmaHR0cDovL2NybC5jZmNhLmNvbS5jbi9TTTIvY3JsNTYxOC5j +cmwwGAYDVR0RBBEwD4INZWJzc2VjLmJvYy5jbjAOBgNVHQ8BAf8EBAMCBsAwHQYD +VR0OBBYEFJ6oFo/OrKgDhHFORpaq04kX7T1KMB0GA1UdJQQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDATAMBggqgRzPVQGDdQUAA0kAMEYCIQCvhSvbv5h6ERl1YcCLg+fz +9UleQbaPfBYwUjUD2dAHVQIhAMRC4k9S/mSC0UpUvCqh/DQC2Ui8Tccd5G2IgYSs +cnUN +-----END CERTIFICATE----- +EOF + +cat <$enccert +-----BEGIN CERTIFICATE----- +MIICzjCCAnKgAwIBAgIFEzY5M3EwDAYIKoEcz1UBg3UFADAlMQswCQYDVQQGEwJD +TjEWMBQGA1UECgwNQ0ZDQSBTTTIgT0NBMTAeFw0yMTA2MTEwOTA1MjBaFw0yNjA2 +MTkwODE2NTZaMIGRMQswCQYDVQQGEwJDTjEPMA0GA1UECAwG5YyX5LqsMQ8wDQYD +VQQHDAbljJfkuqwxJzAlBgNVBAoMHuS4reWbvemTtuihjOiCoeS7veaciemZkOWF +rOWPuDERMA8GA1UECwwITG9jYWwgUkExDDAKBgNVBAsMA1NTTDEWMBQGA1UEAwwN +ZWJzc2VjLmJvYy5jbjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABMn1q+hbV0i1 +qnKAy7QeZ3ZfAD+gqHX4F5MqIhsarODlWsavf/dcprC0F277zc44aYBB/3ucy4PF +qXaRHQp8PEyjggEeMIIBGjAfBgNVHSMEGDAWgBRck1ggWiRzVhAbZFAQ7OmnygdB +ETAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEwMTAvBggrBgEF +BQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wNwYDVR0f +BDAwLjAsoCqgKIYmaHR0cDovL2NybC5jZmNhLmNvbS5jbi9TTTIvY3JsNTYxOC5j +cmwwGAYDVR0RBBEwD4INZWJzc2VjLmJvYy5jbjAOBgNVHQ8BAf8EBAMCAzgwHQYD +VR0OBBYEFF/a1JHvzLzbpFbBljX7hNxRpj/2MB0GA1UdJQQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDATAMBggqgRzPVQGDdQUAA0gAMEUCIQDCOFi1eZcgiN6t+h6lxLwS +grAh3Jall+ZyA2ePw6xcjwIgNyDvo761dpwJhcyWfyVCAnaTf0Vf4DLWI1K+S7po +Ur8= +-----END CERTIFICATE----- +EOF + +cat <$cacert +-----BEGIN CERTIFICATE----- +MIICNTCCAdmgAwIBAgIFEAAAAAgwDAYIKoEcz1UBg3UFADBYMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRcwFQYDVQQDDA5DRkNBIENTIFNNMiBDQTAeFw0xMzAxMjQwODQ2NDBaFw0z +MzAxMTkwODQ2NDBaMCUxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1DRkNBIFNNMiBP +Q0ExMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEfJqQoo0+JoyCRy0msS2Ym076 +8nV1pSLuK9utS1ij38obWDymq0oMRRwUzDMEQI19Cajo3JUoGFxOvsA+YWu3XKOB +wDCBvTAfBgNVHSMEGDAWgBTkjt3Uo+e2D+4dJ5bNddwlJXJp3TAMBgNVHRMEBTAD +AQH/MGAGA1UdHwRZMFcwVaBToFGkTzBNMQswCQYDVQQGEwJDTjETMBEGA1UECgwK +Q0ZDQSBDUyBDQTEMMAoGA1UECwwDQ1JMMQwwCgYDVQQLDANTTTIxDTALBgNVBAMM +BGNybDEwCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBRck1ggWiRzVhAbZFAQ7OmnygdB +ETAMBggqgRzPVQGDdQUAA0gAMEUCIBVscoZJhUy4eToK4C//LjvhjKK2qpBFac/h +Pr6yYTLzAiEAiyqrqsGUU5vGkDo5bEpmF1EbnY8xovsM9vCx98yBrVM= +-----END CERTIFICATE----- +EOF + +cat <$rootcacert +-----BEGIN CERTIFICATE----- +MIICAzCCAaegAwIBAgIEFy9CWTAMBggqgRzPVQGDdQUAMFgxCzAJBgNVBAYTAkNO +MTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkxFzAVBgNVBAMMDkNGQ0EgQ1MgU00yIENBMB4XDTEyMDgzMTAyMDY1OVoXDTQy +MDgyNDAyMDY1OVowWDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEXMBUGA1UEAwwOQ0ZDQSBDUyBT +TTIgQ0EwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAATuRh26wmtyKNMz+Pmneo3a +Sme+BCjRon8SvAxZBgLSuIxNUewq4kNujeb1I4A0yg7xNcjuOgXglAoQv+Tc+P0V +o10wWzAfBgNVHSMEGDAWgBTkjt3Uo+e2D+4dJ5bNddwlJXJp3TAMBgNVHRMEBTAD +AQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU5I7d1KPntg/uHSeWzXXcJSVyad0w +DAYIKoEcz1UBg3UFAANIADBFAiBhP/rmIvles3RK1FfcmmEeS9RZdu+5lCzxF0nk +cof2QAIhAPVRpqOuceEQHsR77FBe/DgVPqF6lOyoZs0TzTDHrN8c +-----END CERTIFICATE----- +EOF + +gmssl certverify -in $signcert -cacert $cacert +gmssl certverify -in $enccert -cacert $cacert +gmssl certverify -in $cacert -cacert $rootcacert + +chain=chain.pem +cat $signcert >$chain +cat $cacert >>$chain +gmssl certverify -in $chain -cacert $rootcacert + +chain_with_root=chain_with_root.pem +cp $chain $chain_with_root +cat $rootcacert >>$chain_with_root +gmssl certverify -in $chain_with_root -cacert $rootcacert + +double_certs=double_certs.pem +cat $signcert >$double_certs +cat $enccert >>$double_certs +gmssl certverify -in $double_certs -cacert $cacert -double_certs + +double_chain=double_chain.pem +cat $double_certs >$double_chain +cat $cacert >>$double_chain +gmssl certverify -in $double_chain -cacert $rootcacert -double_certs + +gmssl certparse -in $double_chain +gmssl certverify -in $double_chain -cacert $rootcacert -double_certs -check_crl +gmssl crlget -cert $signcert -out $crl +gmssl crlparse -in $crl + +rm -fr $signcert +rm -fr $enccert +rm -fr $crl +rm -fr $cacert +rm -fr $rootcacert +rm -fr $chain +rm -fr $chain_with_root +rm -fr $double_certs +rm -fr $double_chain + +echo ok diff --git a/Core/GmSSL-3.1.1/demos/scripts/cmsdemo.sh b/Core/GmSSL-3.1.1/demos/scripts/cmsdemo.sh new file mode 100755 index 0000000..f50c406 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/cmsdemo.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +gmssl sm2keygen -pass 1234 -out key.pem -pubout keypub.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -key_usage dataEncipherment -days 365 -key key.pem -pass 1234 -out cert.pem + +echo "The plaintext message." >plain.txt + +gmssl cmsencrypt -in plain.txt -rcptcert cert.pem -out enveloped_data.pem +gmssl cmsparse -in enveloped_data.pem +gmssl cmsdecrypt -key key.pem -pass 1234 -cert cert.pem -in enveloped_data.pem + +gmssl cmssign -key key.pem -pass 1234 -cert cert.pem -in plain.txt -out signed_data.pem +gmssl cmsparse -in signed_data.pem +gmssl cmsverify -in signed_data.pem -out signed_data.txt +cat signed_data.txt diff --git a/Core/GmSSL-3.1.1/demos/scripts/pbkdf2demo.sh b/Core/GmSSL-3.1.1/demos/scripts/pbkdf2demo.sh new file mode 100755 index 0000000..9f49cd4 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/pbkdf2demo.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +gmssl pbkdf2 -pass 1234 -salt 1122334455667788 -iter 60000 -outlen 16 diff --git a/Core/GmSSL-3.1.1/demos/scripts/reqdemo.sh b/Core/GmSSL-3.1.1/demos/scripts/reqdemo.sh new file mode 100755 index 0000000..f4e3497 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/reqdemo.sh @@ -0,0 +1,41 @@ +#!/bin/bash -x + +set -e + +# generate self-signed CA certificate +gmssl sm2keygen -pass 1234 -out cakey.pem -pubout pubkey.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN CA -days 365 -key cakey.pem -pass 1234 -out cacert.pem +gmssl certparse -in cacert.pem + +# generate a req and sign by CA certificate +gmssl sm2keygen -pass 1234 -out signkey.pem -pubout pubkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -key signkey.pem -pass 1234 -out signreq.pem +gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem +gmssl certparse -in signcert.pem + +# sign a encryption certificate with the same DN, different KeyUsage extension +gmssl sm2keygen -pass 1234 -out enckey.pem -pubout pubkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -key enckey.pem -pass 1234 -out encreq.pem +gmssl reqsign -in encreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem +gmssl certparse -in enccert.pem + +# 中文 +gmssl sm2keygen -pass 1234 -out alicekey.pem -pubout alicepubkey.pem +gmssl reqgen -O "北京大学" -CN "爱丽丝" -key alicekey.pem -pass 1234 -out alicereq.pem +gmssl reqsign -in alicereq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out alicecert.pem +gmssl certparse -in alicecert.pem + +rm -fr pubkey.pem +rm -fr cacert.pem +rm -fr signkey.pem +rm -fr signreq.pem +rm -fr signcert.pem +rm -fr enckey.pem +rm -fr encreq.pem +rm -fr enccert.pem +rm -fr alicekey.pem +rm -fr alicepubkey.pem +rm -fr alicereq.pem +rm -fr alicecert.pem + +echo ok diff --git a/Core/GmSSL-3.1.1/demos/scripts/sm2demo.sh b/Core/GmSSL-3.1.1/demos/scripts/sm2demo.sh new file mode 100755 index 0000000..2df22e7 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/sm2demo.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +gmssl sm2keygen -pass 1234 -out sm2.pem -pubout sm2pub.pem + +echo hello | gmssl sm2sign -key sm2.pem -pass 1234 -out sm2.sig #-id 1234567812345678 +echo hello | gmssl sm2verify -pubkey sm2pub.pem -sig sm2.sig -id 1234567812345678 + +echo hello | gmssl sm2encrypt -pubkey sm2pub.pem -out sm2.der +gmssl sm2decrypt -key sm2.pem -pass 1234 -in sm2.der diff --git a/Core/GmSSL-3.1.1/demos/scripts/sm3demo.sh b/Core/GmSSL-3.1.1/demos/scripts/sm3demo.sh new file mode 100755 index 0000000..a3a37fe --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/sm3demo.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo -n abc | gmssl sm3 + +gmssl sm2keygen -pass 1234 -out sm2.pem -pubout sm2pub.pem +echo -n abc | gmssl sm3 -pubkey sm2pub.pem -id 1234567812345678 + +echo -n abc | gmssl sm3hmac -key 11223344556677881122334455667788 diff --git a/Core/GmSSL-3.1.1/demos/scripts/sm4demo.sh b/Core/GmSSL-3.1.1/demos/scripts/sm4demo.sh new file mode 100755 index 0000000..6a8426a --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/sm4demo.sh @@ -0,0 +1,111 @@ +#!/bin/bash -x + +set -e + +gmssl sm4 -help + +# CBC +echo hello | gmssl sm4 -cbc -encrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -out ciphertext.bin +gmssl sm4 -cbc -decrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in ciphertext.bin + +# CTR +echo hello | gmssl sm4 -ctr -encrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -out ciphertext.bin +gmssl sm4 -ctr -decrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in ciphertext.bin + +# GCM IV length = 12 +echo hello | gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in ciphertext.bin + +# GCM IV length = 1 +echo hello | gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 11 -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 11 -in ciphertext.bin + +# GCM IV length = 16 +echo hello | gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in ciphertext.bin + +# GCM IV length = 32 +echo hello | gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 1122334455667788112233445566778811223344556677881122334455667788 -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 1122334455667788112233445566778811223344556677881122334455667788 -in ciphertext.bin + +# CBC-SM3-HMAC +echo hello | gmssl sm4 -cbc_sm3_hmac -encrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -out ciphertext.bin +gmssl sm4 -cbc_sm3_hmac -decrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -in ciphertext.bin + +# CTR-SM3-HMAC +echo hello | gmssl sm4 -ctr_sm3_hmac -encrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -out ciphertext.bin +gmssl sm4 -ctr_sm3_hmac -decrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -in ciphertext.bin + +# encrypt/decrypt long text file + +cat <plaintext.txt +-----BEGIN CERTIFICATE----- +MIICzzCCAnKgAwIBAgIFEzY5M3AwDAYIKoEcz1UBg3UFADAlMQswCQYDVQQGEwJD +TjEWMBQGA1UECgwNQ0ZDQSBTTTIgT0NBMTAeFw0yMTA2MTEwOTA1MjBaFw0yNjA2 +MTkwODE2NTZaMIGRMQswCQYDVQQGEwJDTjEPMA0GA1UECAwG5YyX5LqsMQ8wDQYD +VQQHDAbljJfkuqwxJzAlBgNVBAoMHuS4reWbvemTtuihjOiCoeS7veaciemZkOWF +rOWPuDERMA8GA1UECwwITG9jYWwgUkExDDAKBgNVBAsMA1NTTDEWMBQGA1UEAwwN +ZWJzc2VjLmJvYy5jbjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABPsNUnoZQM9C +SnvC57TbvdfyOTCuPOSlZmPAyxBKFj+Y1QH/xlubHdVf5XqHrO1jCDRi7aN5IKGX +QF1492c803OjggEeMIIBGjAfBgNVHSMEGDAWgBRck1ggWiRzVhAbZFAQ7OmnygdB +ETAMBgNVHRMBAf8EAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQEwMTAvBggrBgEF +BQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wNwYDVR0f +BDAwLjAsoCqgKIYmaHR0cDovL2NybC5jZmNhLmNvbS5jbi9TTTIvY3JsNTYxOC5j +cmwwGAYDVR0RBBEwD4INZWJzc2VjLmJvYy5jbjAOBgNVHQ8BAf8EBAMCBsAwHQYD +VR0OBBYEFJ6oFo/OrKgDhHFORpaq04kX7T1KMB0GA1UdJQQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDATAMBggqgRzPVQGDdQUAA0kAMEYCIQCvhSvbv5h6ERl1YcCLg+fz +9UleQbaPfBYwUjUD2dAHVQIhAMRC4k9S/mSC0UpUvCqh/DQC2Ui8Tccd5G2IgYSs +cnUN +-----END CERTIFICATE----- +EOF + +# CBC +gmssl sm4 -cbc -encrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -cbc -decrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in ciphertext.bin + +# CTR +gmssl sm4 -ctr -encrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -ctr -decrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in ciphertext.bin + +# GCM IV length = 12 +gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in ciphertext.bin + +# GCM IV length = 1 +gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 11 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 11 -in ciphertext.bin + +# GCM IV length = 16 +gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 11223344556677881122334455667788 -in ciphertext.bin + +# GCM IV length = 32 +gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 1122334455667788112233445566778811223344556677881122334455667788 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 1122334455667788112233445566778811223344556677881122334455667788 -in ciphertext.bin + +# CBC-SM3-HMAC +gmssl sm4 -cbc_sm3_hmac -encrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -cbc_sm3_hmac -decrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -in ciphertext.bin + +# CTR-SM3-HMAC +gmssl sm4 -ctr_sm3_hmac -encrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -in plaintext.txt -out ciphertext.bin +gmssl sm4 -ctr_sm3_hmac -decrypt \ + -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \ + -iv 11223344556677881122334455667788 -in ciphertext.bin + +rm -fr plaintext.txt +rm -fr ciphertext.bin diff --git a/Core/GmSSL-3.1.1/demos/scripts/sm9demo.sh b/Core/GmSSL-3.1.1/demos/scripts/sm9demo.sh new file mode 100755 index 0000000..88676f4 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/sm9demo.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +gmssl sm9setup -alg sm9sign -pass 1234 -out sign_msk.pem -pubout sign_mpk.pem +gmssl sm9keygen -alg sm9sign -in sign_msk.pem -inpass 1234 -id alice -out alice.pem -outpass 1234 +echo hello | gmssl sm9sign -key alice.pem -pass 1234 -out hello.sig +echo hello | gmssl sm9verify -pubmaster sign_mpk.pem -id alice -sig hello.sig + +gmssl sm9setup -alg sm9encrypt -pass 1234 -out enc_msk.pem -pubout enc_mpk.pem +gmssl sm9keygen -alg sm9encrypt -in enc_msk.pem -inpass 1234 -id bob -out bob.pem -outpass 1234 +echo hello | gmssl sm9encrypt -pubmaster enc_mpk.pem -id bob -out hello.der +gmssl sm9decrypt -key bob.pem -pass 1234 -id bob -in hello.der diff --git a/Core/GmSSL-3.1.1/demos/scripts/tlcp_client.sh b/Core/GmSSL-3.1.1/demos/scripts/tlcp_client.sh new file mode 100755 index 0000000..60e29c7 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/tlcp_client.sh @@ -0,0 +1,7 @@ +#!/bin/bash -x + +# https://ebssec.boc.cn +gmssl tlcp_client -host 123.124.191.183 + +# https://zffw.jxzwfww.gov.cn +gmssl tlcp_client -host 218.87.21.62 diff --git a/Core/GmSSL-3.1.1/demos/scripts/tlcp_server.sh b/Core/GmSSL-3.1.1/demos/scripts/tlcp_server.sh new file mode 100755 index 0000000..9f12980 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/tlcp_server.sh @@ -0,0 +1,46 @@ +#!/bin/bash -x + +gmssl sm2keygen -pass 1234 -out rootcakey.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign -ca +gmssl certparse -in rootcacert.pem + +gmssl sm2keygen -pass 1234 -out cakey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN "Sub CA" -key cakey.pem -pass 1234 -out careq.pem +gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem -ca +gmssl certparse -in cacert.pem + +gmssl sm2keygen -pass 1234 -out signkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem +gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem +gmssl certparse -in signcert.pem + +gmssl sm2keygen -pass 1234 -out enckey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key enckey.pem -pass 1234 -out encreq.pem +gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem +gmssl certparse -in enccert.pem + +cat signcert.pem >double_certs.pem +cat enccert.pem >>double_certs.pem +cat cacert.pem >>double_certs.pem + +sudo gmssl tlcp_server -port 443 -cert double_certs.pem -key signkey.pem -pass 1234 -ex_key enckey.pem -ex_pass 1234 -cacert cacert.pem 1>/dev/null 2>/dev/null & +#sudo gmssl tlcp_server -port 443 -cert double_certs.pem -key signkey.pem -pass 1234 -ex_key enckey.pem -ex_pass 1234 1>/dev/null 2>/dev/null & +sleep 3 + +gmssl sm2keygen -pass 1234 -out clientkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Client -key clientkey.pem -pass 1234 -out clientreq.pem +gmssl reqsign -in clientreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out clientcert.pem +gmssl certparse -in clientcert.pem + +# build and install BabaSSL 8.3.2 +# Download +# ./config enable-ntls; make; sudo make install + +# current /demos/scripts +# /build/bin + +openssl version + +../../build/bin/demo_sm2_key_export clientkey.pem 1234 >clientpkey.pem + +#openssl s_client -enable_ntls -ntls -connect localhost:443 -no_ticket -CAfile rootcacert.pem -sign_cert clientcert.pem -sign_key clientpkey.pem -pass pass:1234 diff --git a/Core/GmSSL-3.1.1/demos/scripts/tlcpdemo.sh b/Core/GmSSL-3.1.1/demos/scripts/tlcpdemo.sh new file mode 100755 index 0000000..8caf982 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/tlcpdemo.sh @@ -0,0 +1,43 @@ +#!/bin/bash -x + +#set -e # which sudo will cause failure on windows + +gmssl sm2keygen -pass 1234 -out rootcakey.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign -ca +gmssl certparse -in rootcacert.pem + +gmssl sm2keygen -pass 1234 -out cakey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN "Sub CA" -key cakey.pem -pass 1234 -out careq.pem +gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -ca -path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem +gmssl certparse -in cacert.pem + +gmssl sm2keygen -pass 1234 -out signkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem +gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem +gmssl certparse -in signcert.pem + +gmssl sm2keygen -pass 1234 -out enckey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key enckey.pem -pass 1234 -out encreq.pem +gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem +gmssl certparse -in enccert.pem + +cat signcert.pem >double_certs.pem +cat enccert.pem >>double_certs.pem +cat cacert.pem >>double_certs.pem + +# If port is already in use, `gmssl` will fail, use `ps aux | grep gmssl` and `sudo kill -9` to kill existing proc +# TODO: check if `gmssl` is failed +which sudo +if [ $? -eq 0 ]; then + SUDO=sudo +fi +$SUDO gmssl tlcp_server -port 443 -cert double_certs.pem -key signkey.pem -pass 1234 -ex_key enckey.pem -ex_pass 1234 -cacert cacert.pem & +1>/dev/null 2>/dev/null & +sleep 3 + +gmssl sm2keygen -pass 1234 -out clientkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Client -key clientkey.pem -pass 1234 -out clientreq.pem +gmssl reqsign -in clientreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out clientcert.pem +gmssl certparse -in clientcert.pem + +gmssl tlcp_client -host 127.0.0.1 -cacert rootcacert.pem -cert clientcert.pem -key clientkey.pem -pass 1234 diff --git a/Core/GmSSL-3.1.1/demos/scripts/tls12demo.sh b/Core/GmSSL-3.1.1/demos/scripts/tls12demo.sh new file mode 100755 index 0000000..00f60a0 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/tls12demo.sh @@ -0,0 +1,34 @@ +#!/bin/bash -x + +gmssl sm2keygen -pass 1234 -out rootcakey.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign -ca +gmssl certparse -in rootcacert.pem + +gmssl sm2keygen -pass 1234 -out cakey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN "Sub CA" -key cakey.pem -pass 1234 -out careq.pem +gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem -ca -path_len_constraint 0 +gmssl certparse -in cacert.pem + +gmssl sm2keygen -pass 1234 -out signkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem +gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem +gmssl certparse -in signcert.pem + +cat signcert.pem >certs.pem +cat cacert.pem >>certs.pem + +# If port is already in use, `gmssl` will fail, use `ps aux | grep gmssl` and `sudo kill -9` to kill existing proc +# TODO: check if `gmssl` is failed +which sudo +if [ $? -eq 0 ]; then + SUDO=sudo +fi +$SUDO gmssl tls12_server -port 4430 -cert certs.pem -key signkey.pem -pass 1234 -cacert cacert.pem & #1>/dev/null 2>/dev/null & +sleep 3 + +gmssl sm2keygen -pass 1234 -out clientkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Client -key clientkey.pem -pass 1234 -out clientreq.pem +gmssl reqsign -in clientreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out clientcert.pem +gmssl certparse -in clientcert.pem + +gmssl tls12_client -host 127.0.0.1 -port 4430 -cacert rootcacert.pem -cert clientcert.pem -key clientkey.pem -pass 1234 diff --git a/Core/GmSSL-3.1.1/demos/scripts/tls13demo.sh b/Core/GmSSL-3.1.1/demos/scripts/tls13demo.sh new file mode 100755 index 0000000..992f336 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/tls13demo.sh @@ -0,0 +1,34 @@ +#!/bin/bash -x + +gmssl sm2keygen -pass 1234 -out rootcakey.pem +gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign -ca +gmssl certparse -in rootcacert.pem + +gmssl sm2keygen -pass 1234 -out cakey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN "Sub CA" -key cakey.pem -pass 1234 -out careq.pem +gmssl reqsign -in careq.pem -days 365 -key_usage keyCertSign -ca -path_len_constraint 0 -cacert rootcacert.pem -key rootcakey.pem -pass 1234 -out cacert.pem +gmssl certparse -in cacert.pem + +gmssl sm2keygen -pass 1234 -out signkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem +gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem +gmssl certparse -in signcert.pem + +cat signcert.pem >certs.pem +cat cacert.pem >>certs.pem + +# If port is already in use, `gmssl` will fail, use `ps aux | grep gmssl` and `sudo kill -9` to kill existing proc +# TODO: check if `gmssl` is failed +which sudo +if [ $? -eq 0 ]; then + SUDO=sudo +fi +$SUDO gmssl tls13_server -port 4433 -cert certs.pem -key signkey.pem -pass 1234 -cacert cacert.pem & # 1>/dev/null 2>/dev/null & +sleep 3 + +gmssl sm2keygen -pass 1234 -out clientkey.pem +gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Client -key clientkey.pem -pass 1234 -out clientreq.pem +gmssl reqsign -in clientreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out clientcert.pem +gmssl certparse -in clientcert.pem + +gmssl tls13_client -host 127.0.0.1 -port 4433 -cacert rootcacert.pem -cert clientcert.pem -key clientkey.pem -pass 1234 diff --git a/Core/GmSSL-3.1.1/demos/scripts/zucdemo.sh b/Core/GmSSL-3.1.1/demos/scripts/zucdemo.sh new file mode 100755 index 0000000..0dc59fd --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/scripts/zucdemo.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +KEY=11223344556677881122334455667788 +IV=11223344556677881122334455667788 + +echo hello | gmssl zuc -key $KEY -iv $IV -out zuc.bin +gmssl zuc -key $KEY -iv $IV -in zuc.bin diff --git a/Core/GmSSL-3.1.1/demos/src/demo_cert_gen.c b/Core/GmSSL-3.1.1/demos/src/demo_cert_gen.c new file mode 100644 index 0000000..790b8ca --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_cert_gen.c @@ -0,0 +1,258 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + + +static int ext_key_usage_set(int *usages, const char *usage_name) +{ + int flag; + if (x509_key_usage_from_name(&flag, usage_name) != 1) { + error_print(); + return -1; + } + *usages |= flag; + return 1; +} + +int main(int argc, char *argv[]) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + // SerialNumber + uint8_t serial[20]; + int serial_len = 12; + + // Issuer, Subject + uint8_t name[256]; + size_t namelen; + char *country = "CN"; + char *state = "Beijing"; + char *locality = "Haidian"; + char *org = "PKU"; + char *org_unit = "CS"; + char *common_name = "ROOTCA"; + + // Validity + int days = 3650; + time_t not_before; + time_t not_after; + + // Private Key + char *keyfile="rootcakey.pem"; //可由/demos/scripts/cert_gen.sh生成 + FILE *keyfp = NULL; + char *pass = "1234"; + SM2_KEY sm2_key; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + uint8_t *cert = NULL; + size_t certlen = 0; + FILE *outfp = stdout; + char *outfile = "rootcacert.pem"; + uint8_t *p; + + // Extensions + uint8_t exts[4096]; + size_t extslen = 0; + + // AuthorityKeyIdentifier + int gen_authority_key_id = 0; + + // SubjectKeyIdentifier + int gen_subject_key_id = 0; + + // KeyUsage + int key_usage = 0; + char *keyusage1="keyCertSign"; + char *keyusage2="cRLSign"; + + // SubjectAltName + uint8_t subject_alt_name[2048]; + size_t subject_alt_name_len = 0; + + // IssuerAltName + uint8_t issuer_alt_name[512]; + size_t issuer_alt_name_len = 0; + + // BasicConstraints + int ca = 1; + int path_len_constraint = 6; + + // ExtKeyUsageSyntax + int ext_key_usages[12]; + size_t ext_key_usages_cnt = 0; + + // CRLDistributionPoints + char *crl_http_uri = "http://pku.edu.cn/ca.crl"; + char *crl_ldap_uri = NULL; + + // InhibitAnyPolicy + int inhibit_any_policy = -1; + + // FreshestCRL + char *ca_issuers_uri = "http://pku.edu.cn/ca.crt"; + char *ocsp_uri = "http://ocsp.pku.edu.cn"; + + + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno)); + goto end; + } + + + if (ext_key_usage_set(&key_usage, keyusage1) != 1) { + fprintf(stderr, "%s: invalid `-key_usage` value '%s'\n", prog, keyusage1); + goto end; + } + + if (ext_key_usage_set(&key_usage, keyusage2) != 1) { + fprintf(stderr, "%s: invalid `-key_usage` value '%s'\n", prog, keyusage2); + goto end; + } + + + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + + + + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load private key failed\n", prog); + goto end; + } + + + + + // Issuer, Subject + if (x509_name_set(name, &namelen, sizeof(name), country, state, locality, org, org_unit, common_name) != 1) { + fprintf(stderr, "%s: set Issuer/Subject Name error\n", prog); + goto end; + } + + // Validity + time(¬_before); + if (x509_validity_add_days(¬_after, not_before, days) != 1) { + fprintf(stderr, "%s: set Validity failure\n", prog); + goto end; + } + + + if (key_usage) { + if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), X509_critical, key_usage) != 1) { + fprintf(stderr, "%s: set KeyUsage extension failure\n", prog); + goto end; + } + } + + + // no SubjectDirectoryAttributes + if (ca >= 0 || path_len_constraint >= 0) { + if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts), + X509_critical, ca, path_len_constraint) != 1) { + fprintf(stderr, "%s: set BasicConstraints extension failure\n", prog); + goto end; + } + } + // no NameConstraints + // no PolicyConstraints + + if (crl_http_uri || crl_ldap_uri) { + if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts), + -1, + crl_http_uri, crl_http_uri ? strlen(crl_http_uri) : 0, + crl_ldap_uri, crl_ldap_uri ? strlen(crl_ldap_uri) : 0) != 1) { + fprintf(stderr, "%s: set CRLDistributionPoints extension failure\n", prog); + return -1; + } + } + + + if (ca_issuers_uri || ocsp_uri) { + if (x509_exts_add_authority_info_access(exts, &extslen, sizeof(exts), 0, + ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0, + ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) { + fprintf(stderr, "%s: set AuthorityInfoAccess extension failure\n", prog); + goto end; + } + } + + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + NULL, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + if (!(cert = malloc(certlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + p = cert; + certlen = 0; + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + &p, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + if (x509_cert_to_pem(cert, certlen, outfp) != 1) { + fprintf(stderr, "%s: output certificate failed\n", prog); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY)); + if (cert) free(cert); + if (keyfp) fclose(keyfp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_cert_sign.c b/Core/GmSSL-3.1.1/demos/src/demo_cert_sign.c new file mode 100644 index 0000000..54d642c --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_cert_sign.c @@ -0,0 +1,353 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static int ext_key_usage_set(int *usages, const char *usage_name) +{ + int flag = 0; + if (x509_key_usage_from_name(&flag, usage_name) != 1) { + return -1; + } + *usages |= flag; + return 1; +} + +int main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + // Input Req/CSR + char *infile = "careq.pem"; + FILE *infp = NULL; + uint8_t req[512]; + size_t reqlen; + char req_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t req_id_len = 0; + + // SerialNumber + uint8_t serial[20]; + int serial_len = 12; + + // Validity + int days = 365; + time_t not_before; + time_t not_after; + + // Subject from Req + const uint8_t *subject; + size_t subject_len; + SM2_KEY subject_public_key; + + // CA certficate and Private Key + uint8_t *cacert = NULL; + char *rootcacert="rootcacert.pem"; + size_t cacertlen; + FILE *keyfp = NULL; + char *rootcakey="rootcakey.pem"; + char *pass = "1234"; + SM2_KEY sm2_key; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + // Issuer from CA certificate + const uint8_t *issuer; + size_t issuer_len; + SM2_KEY issuer_public_key; + + // Output + char *outfile = "cacert.pem"; + FILE *outfp = stdout; + uint8_t *cert = NULL; + size_t certlen = 0; + uint8_t *p; + + // Extensions + uint8_t exts[4096]; + size_t extslen = 0; + + // AuthorityKeyIdentifier + int gen_authority_key_id = 0; + + // SubjectKeyIdentifier + int gen_subject_key_id = 0; + + // KeyUsage + int key_usage = 0; + char *keyusage="keyCertSign"; + + // SubjectAltName + uint8_t subject_alt_name[2048]; + size_t subject_alt_name_len = 0; + + // IssuerAltName + uint8_t issuer_alt_name[512]; + size_t issuer_alt_name_len = 0; + + // BasicConstraints + int ca = -1; + int path_len_constraint = 0; + + // ExtKeyUsageSyntax + int ext_key_usages[12]; + size_t ext_key_usages_cnt = 0; + + // CRLDistributionPoints + char *crl_http_uri = NULL; + char *crl_ldap_uri = NULL; + + // InhibitAnyPolicy + int inhibit_any_policy = -1; + + // FreshestCRL + char *ca_issuers_uri = NULL; + char *ocsp_uri = NULL; + + + + + + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + + + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + + + if (x509_cert_new_from_file(&cacert, &cacertlen, rootcacert) != 1) { + fprintf(stderr, "%s: load ca certificate '%s' failure\n", prog, rootcacert); + goto end; + } + + + if (!(keyfp = fopen(rootcakey, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, rootcakey, strerror(errno)); + goto end; + } + + + if (ext_key_usage_set(&key_usage, keyusage) != 1) { + fprintf(stderr, "%s: invalid `-key_usage` value '%s'\n", prog, keyusage); + goto end; + } + + if (!days) { + fprintf(stderr, "%s: '-days' option required\n", prog); + goto end; + } + if (!cacert) { + fprintf(stderr, "%s: '-cacert' option required\n", prog); + goto end; + } + if (!keyfp) { + fprintf(stderr, "%s: '-key' option required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + goto end; + } + + if (x509_req_from_pem(req, &reqlen, sizeof(req), infp) != 1) { + fprintf(stderr, "%s: parse CSR failure\n", prog); + goto end; + } + if (!req_id_len) { + strcpy(req_id, SM2_DEFAULT_ID); + req_id_len = strlen(SM2_DEFAULT_ID); + } + if (x509_req_verify(req, reqlen, req_id, req_id_len) != 1) { + fprintf(stderr, "%s: signature verification failure\n", prog); + goto end; + } + if (x509_req_get_details(req, reqlen, + NULL, &subject, &subject_len, &subject_public_key, + NULL, NULL, NULL, NULL, NULL) != 1) { + fprintf(stderr, "%s: parse CSR failure\n", prog); + goto end; + } + + if (x509_cert_get_subject(cacert, cacertlen, &issuer, &issuer_len) != 1 + || x509_cert_get_subject_public_key(cacert, cacertlen, &issuer_public_key) != 1) { + fprintf(stderr, "%s: parse CA certificate failure\n", prog); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load private key failure\n", prog); + goto end; + } + if (sm2_public_key_equ(&sm2_key, &issuer_public_key) != 1) { + fprintf(stderr, "%s: private key and CA certificate not match\n", prog); + goto end; + } + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + + if (rand_bytes(serial, serial_len) != 1) { + fprintf(stderr, "%s: random number generator error\n", prog); + goto end; + } + + time(¬_before); + if (x509_validity_add_days(¬_after, not_before, days) != 1) { + fprintf(stderr, "%s: set Validity failure\n", prog); + goto end; + } + + // following code copy from certgen.c + // Extensions + if (gen_authority_key_id) { + if (x509_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sm2_key) != 1) { + fprintf(stderr, "%s: set AuthorityKeyIdentifier extension failure\n", prog); + goto end; + } + } + if (gen_subject_key_id) { + if (x509_exts_add_subject_key_identifier_ex(exts, &extslen, sizeof(exts), -1, &sm2_key) != 1) { + fprintf(stderr, "%s: set SubjectKeyIdentifier extension failure\n", prog); + goto end; + } + } + if (key_usage) { + if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), X509_critical, key_usage) != 1) { + fprintf(stderr, "%s: set KeyUsage extension failure\n", prog); + goto end; + } + } + // no CertificatePolicies + // no PolicyMappings + if (subject_alt_name_len) { + if (x509_exts_add_subject_alt_name(exts, &extslen, sizeof(exts), + -1, subject_alt_name, subject_alt_name_len) != 1) { + fprintf(stderr, "%s: set SubjectAltName extension failure\n", prog); + goto end; + } + } + if (issuer_alt_name_len) { + if (x509_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts), + -1, issuer_alt_name, issuer_alt_name_len) != 1) { + fprintf(stderr, "%s: set IssuerAltName extension failure\n", prog); + goto end; + } + } + // no SubjectDirectoryAttributes + if (ca >= 0 || path_len_constraint >= 0) { + if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts), + X509_critical, ca, path_len_constraint) != 1) { + fprintf(stderr, "%s: set BasicConstraints extension failure\n", prog); + goto end; + } + } + // no NameConstraints + // no PolicyConstraints + if (ext_key_usages_cnt) { + if (x509_exts_add_ext_key_usage(exts, &extslen, sizeof(exts), + -1, ext_key_usages, ext_key_usages_cnt) != 1) { + fprintf(stderr, "%s: set ExtKeyUsage extension failure\n", prog); + goto end; + } + } + if (crl_http_uri || crl_ldap_uri) { + if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts), + -1, + crl_http_uri, crl_http_uri ? strlen(crl_http_uri) : 0, + crl_ldap_uri, crl_ldap_uri ? strlen(crl_ldap_uri) : 0) != 1) { + fprintf(stderr, "%s: set CRLDistributionPoints extension failure\n", prog); + return -1; + } + } + if (inhibit_any_policy >= 0) { + if (x509_exts_add_inhibit_any_policy(exts, &extslen, sizeof(exts), + X509_critical, inhibit_any_policy) != 1) { + fprintf(stderr, "%s: set InhibitAnyPolicy extension failure\n", prog); + goto end; + } + } + if (ca_issuers_uri || ocsp_uri) { + if (x509_exts_add_authority_info_access(exts, &extslen, sizeof(exts), 0, + ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0, + ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) { + fprintf(stderr, "%s: set AuthorityInfoAccess extension failure\n", prog); + goto end; + } + } + + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + &subject_public_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + NULL, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + if (!(cert = malloc(certlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + p = cert; + certlen = 0; + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + &subject_public_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + &p, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + + if (x509_cert_to_pem(cert, certlen, outfp) != 1) { + fprintf(stderr, "%s: output certificate failed\n", prog); + goto end; + } + ret = 0; +end: + gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY)); + if (cert) free(cert); + if (keyfp) fclose(keyfp); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_encrypt.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_encrypt.c new file mode 100644 index 0000000..6c4a441 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_encrypt.c @@ -0,0 +1,39 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM2_KEY sm2_key; + SM2_KEY pub_key; + unsigned char plaintext[SM2_MAX_PLAINTEXT_SIZE]; + unsigned char ciphertext[SM2_MAX_CIPHERTEXT_SIZE]; + size_t len; + + sm2_key_generate(&sm2_key); + memcpy(&pub_key, &sm2_key, sizeof(SM2_POINT)); + + sm2_encrypt(&pub_key, (uint8_t *)"hello world", strlen("hello world"), ciphertext, &len); + format_bytes(stdout, 0, 0, "ciphertext", ciphertext, len); + + if (sm2_decrypt(&sm2_key, ciphertext, len, plaintext, &len) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + plaintext[len] = 0; + printf("plaintext: %s\n", plaintext); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_key_export.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_key_export.c new file mode 100644 index 0000000..8f96c51 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_key_export.c @@ -0,0 +1,64 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +int main(int argc, char **argv) +{ + int ret = -1; + char *prog = argv[0]; + char *keyfile; + char *pass; + FILE *keyfp = NULL; + SM2_KEY sm2_key; + + if (argc < 3) { + fprintf(stderr, "usage: %s \n", prog); + return -1; + } + keyfile = argv[1]; + pass = argv[2]; + + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open file '%s' failure\n", prog, keyfile); + return -1; + } + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load key failure\n", prog); + goto end; + } + if (sm2_private_key_info_to_pem(&sm2_key, stdout) != 1) { + fprintf(stderr, "%s: export failure\n", prog); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + if (keyfp) fclose(keyfp); + return ret; +} + + + + + + + + + + + + diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_keygen.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_keygen.c new file mode 100644 index 0000000..dbabf09 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_keygen.c @@ -0,0 +1,28 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include + +int main(void) +{ + SM2_KEY sm2_key; + + if (sm2_key_generate(&sm2_key) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + sm2_key_print(stdout, 0, 0, "SM2PrivateKey", &sm2_key); + sm2_public_key_print(stdout, 0, 0, "SM2PublicKey", &sm2_key); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_keyparse.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_keyparse.c new file mode 100644 index 0000000..681fcab --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_keyparse.c @@ -0,0 +1,60 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +int main(int argc, char **argv) +{ + char *prog = argv[0]; + char *keyfile; + char *pass; + FILE *keyfp = NULL; + SM2_KEY sm2_key; + + if (argc < 3) { + fprintf(stderr, "usage: %s \n", prog); + return -1; + } + keyfile = argv[1]; + pass = argv[2]; + + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open file '%s' failure\n", prog, keyfile); + return -1; + } + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load key failure\n", prog); + fclose(keyfp); + return -1; + } + + sm2_key_print(stdout, 0, 0, "SM2_KEY", &sm2_key); + + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + fclose(keyfp); + return 0; +} + + + + + + + + + + + + diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_private_key.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_private_key.c new file mode 100644 index 0000000..d64ae24 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_private_key.c @@ -0,0 +1,31 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include + +int main(void) +{ + SM2_KEY sm2_key; + char *password = "123456"; + + if (sm2_key_generate(&sm2_key) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + if (sm2_private_key_info_encrypt_to_pem(&sm2_key, password, stdout) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_private_key_parse.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_private_key_parse.c new file mode 100644 index 0000000..f17e890 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_private_key_parse.c @@ -0,0 +1,42 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include + +int main(void) +{ + SM2_KEY sm2_key; + char *password = "123456"; + unsigned char buf[512]; + unsigned char *p; + size_t len; + + printf("Read SM2 private key file (PEM) from stdin ...\n"); + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, password, stdin) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + p = buf; + len = 0; + if (sm2_private_key_to_der(&sm2_key, &p, &len) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + format_bytes(stdout, 0, 0, "buf", buf, len); + sm2_key_print(stdout, 0, 0, "SM2PrivateKey", &sm2_key); + + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key.c new file mode 100644 index 0000000..710c607 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key.c @@ -0,0 +1,33 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM2_KEY sm2_key; + char *password = "123456"; + + printf("Read SM2 private key file (PEM) from stdin ...\n"); + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, password, stdin) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + // openssl ec -pubin -in sm2pub.pem -text + sm2_public_key_info_to_pem(&sm2_key, stdout); + + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_copy.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_copy.c new file mode 100644 index 0000000..1d18dd3 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_copy.c @@ -0,0 +1,37 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + +int main(void){ + SM2_KEY sm2_key; + SM2_KEY pub_key; + + printf("Read SM2 public key file (PEM) from stdin ...\n"); + + if (sm2_public_key_info_from_pem(&sm2_key, stdin) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + if (sm2_public_key_copy(&pub_key, &sm2_key) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + sm2_public_key_print(stdout, 0, 0, "SM2PublicKey", &pub_key); + + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + gmssl_secure_clear(&pub_key, sizeof(pub_key)); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_digest.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_digest.c new file mode 100644 index 0000000..e1c01ac --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_digest.c @@ -0,0 +1,41 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include + +int main(void){ + SM2_KEY sm2_key; + uint8_t dgst[32]; + int i; + + printf("Read SM2 public key file (PEM) from stdin ...\n"); + + if (sm2_public_key_info_from_pem(&sm2_key, stdin) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + if (sm2_public_key_digest(&sm2_key, dgst) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + for (i = 0; i < sizeof(dgst); i++) { + printf("%02x", dgst[i]); + } + printf("\n"); + + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_equ.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_equ.c new file mode 100644 index 0000000..70073f3 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_equ.c @@ -0,0 +1,43 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + +int main(void){ + SM2_KEY sm2_key; + SM2_KEY pub_key; + + printf("Read SM2 public key1 file (PEM) from stdin ...\n"); + + if (sm2_public_key_info_from_pem(&sm2_key, stdin) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + printf("Read SM2 public key2 file (PEM) from stdin ...\n"); + + if (sm2_public_key_info_from_pem(&pub_key, stdin) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + if (sm2_public_key_equ(&sm2_key, &pub_key) == 1) { + printf("equal\n"); + } else { + printf("not equal\n"); + } + + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + gmssl_secure_clear(&pub_key, sizeof(pub_key)); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_parse.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_parse.c new file mode 100644 index 0000000..463e90e --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_public_key_parse.c @@ -0,0 +1,32 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM2_KEY sm2_key; + + printf("Read SM2 public key file (PEM) from stdin ...\n"); + + if (sm2_public_key_info_from_pem(&sm2_key, stdin) != 1) { + fprintf(stderr, "error\n"); + return 1; + } + + sm2_public_key_print(stdout, 0, 0, "SM2PublicKey", &sm2_key); + + gmssl_secure_clear(&sm2_key, sizeof(sm2_key)); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_sign.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_sign.c new file mode 100644 index 0000000..de0cdf8 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_sign.c @@ -0,0 +1,43 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM2_KEY sm2_key; + SM2_KEY pub_key; + unsigned char dgst[32]; + unsigned char sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + int ret; + + sm3_digest((unsigned char *)"hello world", strlen("hello world"), dgst); + format_bytes(stdout, 0, 0, "to be signed digest", dgst, sizeof(dgst)); + + sm2_key_generate(&sm2_key); + + sm2_sign(&sm2_key, dgst, sig, &siglen); + format_bytes(stdout, 0, 0, "signature", sig, siglen); + + memcpy(&pub_key, &sm2_key, sizeof(SM2_POINT)); + + if ((ret = sm2_verify(&pub_key, dgst, sig, siglen)) != 1) { + fprintf(stderr, "verify failed\n"); + } else { + printf("verify success\n"); + } + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm2_sign_ctx.c b/Core/GmSSL-3.1.1/demos/src/demo_sm2_sign_ctx.c new file mode 100644 index 0000000..965cf7e --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm2_sign_ctx.c @@ -0,0 +1,62 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM2_KEY sm2_key; + SM2_KEY pub_key; + SM2_SIGN_CTX sign_ctx; + unsigned char dgst[32]; + unsigned char sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + int ret; + + sm2_key_generate(&sm2_key); + + memcpy(&pub_key, &sm2_key, sizeof(SM2_POINT)); + + // sign without signer ID (and Z value) + sm2_sign_init(&sign_ctx, &sm2_key, NULL, 0); + sm2_sign_update(&sign_ctx, (unsigned char *)"hello ", strlen("hello ")); + sm2_sign_update(&sign_ctx, (unsigned char *)"world", strlen("world")); + sm2_sign_finish(&sign_ctx, sig, &siglen); + format_bytes(stdout, 0, 0, "signature", sig, siglen); + + // digest and verify + sm3_digest((unsigned char *)"hello world", strlen("hello world"), dgst); + ret = sm2_verify(&pub_key, dgst, sig, siglen); + printf("verify result: %s\n", ret == 1 ? "success" : "failure"); + + // use verify update API + sm2_verify_init(&sign_ctx, &pub_key, NULL, 0); + sm2_verify_update(&sign_ctx, (unsigned char *)"hello world", strlen("hello world")); + ret = sm2_verify_finish(&sign_ctx, sig, siglen); + printf("verify result: %s\n", ret == 1 ? "success" : "failure"); + + // sign use default signer ID + sm2_sign_init(&sign_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH); + sm2_sign_update(&sign_ctx, (unsigned char *)"hello ", strlen("hello ")); + sm2_sign_update(&sign_ctx, (unsigned char *)"world", strlen("world")); + sm2_sign_finish(&sign_ctx, sig, &siglen); + format_bytes(stdout, 0, 0, "signature", sig, siglen); + + sm2_verify_init(&sign_ctx, &pub_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH); + sm2_verify_update(&sign_ctx, (unsigned char *)"hello world", strlen("hello world")); + ret = sm2_verify_finish(&sign_ctx, sig, siglen); + printf("verify result: %s\n", ret == 1 ? "success" : "failure"); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm3.c b/Core/GmSSL-3.1.1/demos/src/demo_sm3.c new file mode 100644 index 0000000..2e876dd --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm3.c @@ -0,0 +1,36 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include + + +int main(int argc, char **argv) +{ + SM3_CTX sm3_ctx; + uint8_t buf[4096]; + size_t len; + uint8_t dgst[32]; + int i; + + sm3_init(&sm3_ctx); + while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) { + sm3_update(&sm3_ctx, buf, len); + } + sm3_finish(&sm3_ctx, dgst); + + for (i = 0; i < sizeof(dgst); i++) { + printf("%02x", dgst[i]); + } + printf("\n"); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm3_hmac.c b/Core/GmSSL-3.1.1/demos/src/demo_sm3_hmac.c new file mode 100644 index 0000000..234ef82 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm3_hmac.c @@ -0,0 +1,51 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include + + +int main(void) +{ + SM3_HMAC_CTX hmac_ctx; + unsigned char key[16] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0xf2,0x03,0x04,0x05,0x06,0x07,0x08, + }; + unsigned char mbuf[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char hmac[32] = {0}; + int i; + + + sm3_hmac_init(&hmac_ctx, key, sizeof(key)); + sm3_hmac_update(&hmac_ctx, mbuf, sizeof(mbuf)); + sm3_hmac_finish(&hmac_ctx, hmac); + + printf("hmac: "); + for (i = 0; i < sizeof(hmac); i++) { + printf("%02X", hmac[i]); + } + printf("\n"); + + memset(hmac, 0, sizeof(hmac)); + sm3_hmac(key, sizeof(key), mbuf, sizeof(mbuf), hmac); + + printf("hmac: "); + for (i = 0; i < sizeof(hmac); i++) { + printf("%02X", hmac[i]); + } + printf("\n"); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm3_kdf.c b/Core/GmSSL-3.1.1/demos/src/demo_sm3_kdf.c new file mode 100644 index 0000000..5c0ecbb --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm3_kdf.c @@ -0,0 +1,37 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include + + +int main(void) +{ + SM3_KDF_CTX kdf_ctx; + unsigned char key[16] = {0}; + unsigned char raw[32] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + int i; + + sm3_kdf_init(&kdf_ctx, sizeof(key)); + sm3_kdf_update(&kdf_ctx, raw, sizeof(raw)); + sm3_kdf_finish(&kdf_ctx, key); + + printf("key: "); + for (i = 0; i < sizeof(key); i++) { + printf("%02X", key[i]); + } + printf("\n"); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4.c new file mode 100644 index 0000000..fbc0fd9 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4.c @@ -0,0 +1,64 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +// sm4 demo1: encrypt and decrypt a block of message (16 bytes) + +#include +#include +#include +#include + + +int main(void) +{ + SM4_KEY sm4_key; + unsigned char key[16] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0xf2,0x03,0x04,0x05,0x06,0x07,0x08, + }; + unsigned char mbuf[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char cbuf[16]; + unsigned char pbuf[16]; + int i; + + printf("key: "); + for (i = 0; i < sizeof(key); i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("plaintext: "); + for (i = 0; i < sizeof(mbuf); i++) { + printf("%02X", mbuf[i]); + } + printf("\n"); + + sm4_set_encrypt_key(&sm4_key, key); + sm4_encrypt(&sm4_key, mbuf, cbuf); + + printf("ciphertext: "); + for (i = 0; i < sizeof(cbuf); i++) { + printf("%02X", cbuf[i]); + } + printf("\n"); + + sm4_set_decrypt_key(&sm4_key, key); + sm4_decrypt(&sm4_key, cbuf, pbuf); + + printf("decrypted: "); + for (i = 0; i < sizeof(pbuf); i++) { + printf("%02X", pbuf[i]); + } + printf("\n"); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc.c new file mode 100644 index 0000000..e1272c2 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc.c @@ -0,0 +1,72 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM4_KEY sm4_key; + unsigned char key[16]; + unsigned char iv[16]; + unsigned char mbuf[32] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char cbuf[32] = {0}; + unsigned char pbuf[32] = {0}; + int i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + + printf("key: "); + for (i = 0; i < sizeof(key); i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("iv: "); + for (i = 0; i < sizeof(iv); i++) { + printf("%02X", iv[i]); + } + printf("\n"); + + printf("plaintext: "); + for (i = 0; i < sizeof(mbuf); i++) { + printf("%02X", mbuf[i]); + } + printf("\n"); + + sm4_set_encrypt_key(&sm4_key, key); + sm4_cbc_encrypt(&sm4_key, iv, mbuf, sizeof(mbuf)/SM4_BLOCK_SIZE, cbuf); + + printf("ciphertext: "); + for (i = 0; i < sizeof(cbuf); i++) { + printf("%02X", cbuf[i]); + } + printf("\n"); + + sm4_set_decrypt_key(&sm4_key, key); + sm4_cbc_decrypt(&sm4_key, iv, cbuf, sizeof(cbuf)/SM4_BLOCK_SIZE, pbuf); + + printf("decrypted: "); + for (i = 0; i < sizeof(pbuf); i++) { + printf("%02X", pbuf[i]); + } + printf("\n"); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_decrypt_update.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_decrypt_update.c new file mode 100644 index 0000000..e32333d --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_decrypt_update.c @@ -0,0 +1,51 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM4_CBC_CTX cbc_ctx; + unsigned char key[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char iv[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char inbuf[1024]; + unsigned char outbuf[1024 + 32]; + size_t inlen; + size_t outlen; + + if (sm4_cbc_decrypt_init(&cbc_ctx, key, iv) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + while ((inlen = fread(inbuf, 1, sizeof(inbuf), stdin)) > 0) { + if (sm4_cbc_decrypt_update(&cbc_ctx, inbuf, inlen, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + } + if (sm4_cbc_decrypt_finish(&cbc_ctx, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_encrypt_update.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_encrypt_update.c new file mode 100644 index 0000000..4e97d62 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_encrypt_update.c @@ -0,0 +1,51 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM4_CBC_CTX cbc_ctx; + unsigned char key[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char iv[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char inbuf[1024]; + unsigned char outbuf[1024 + 32]; + size_t inlen; + size_t outlen; + + if (sm4_cbc_encrypt_init(&cbc_ctx, key, iv) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + while ((inlen = fread(inbuf, 1, sizeof(inbuf), stdin)) > 0) { + if (sm4_cbc_encrypt_update(&cbc_ctx, inbuf, inlen, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + } + if (sm4_cbc_encrypt_finish(&cbc_ctx, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_padding.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_padding.c new file mode 100644 index 0000000..720e248 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4_cbc_padding.c @@ -0,0 +1,105 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM4_KEY sm4_key; + unsigned char key[16]; + unsigned char iv[16]; + unsigned char mbuf[32] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char cbuf[32] = {0}; + unsigned char pbuf[32] = {0}; + size_t mlen1 = 20, mlen2 = 16; + size_t clen1, clen2; + size_t plen1, plen2; + int i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + + printf("key: "); + for (i = 0; i < sizeof(key); i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("iv: "); + for (i = 0; i < sizeof(iv); i++) { + printf("%02X", iv[i]); + } + printf("\n"); + + + printf("sm4_cbc_pading encrypt %zu bytes\n", mlen1); + + printf("plaintext: "); + for (i = 0; i < mlen1; i++) { + printf("%02X", mbuf[i]); + } + printf("\n"); + + sm4_set_encrypt_key(&sm4_key, key); + sm4_cbc_padding_encrypt(&sm4_key, iv, mbuf, mlen1, cbuf, &clen1); + + printf("ciphertext: "); + for (i = 0; i < clen1; i++) { + printf("%02X", cbuf[i]); + } + printf("\n"); + + sm4_set_decrypt_key(&sm4_key, key); + sm4_cbc_padding_decrypt(&sm4_key, iv, cbuf, clen1, pbuf, &plen1); + + printf("decrypted: "); + for (i = 0; i < plen1; i++) { + printf("%02X", pbuf[i]); + } + printf("\n"); + + printf("sm4_cbc_pading encrypt %zu bytes\n", mlen2); + + printf("plaintext: "); + for (i = 0; i < mlen2; i++) { + printf("%02X", mbuf[i]); + } + printf("\n"); + + sm4_set_encrypt_key(&sm4_key, key); + sm4_cbc_padding_encrypt(&sm4_key, iv, mbuf, mlen2, cbuf, &clen2); + + printf("ciphertext: "); + for (i = 0; i < clen2; i++) { + printf("%02X", cbuf[i]); + } + printf("\n"); + + sm4_set_decrypt_key(&sm4_key, key); + sm4_cbc_padding_decrypt(&sm4_key, iv, cbuf, clen2, pbuf, &plen2); + + printf("decrypted: "); + for (i = 0; i < plen2; i++) { + printf("%02X", pbuf[i]); + } + printf("\n"); + + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4_ctr.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4_ctr.c new file mode 100644 index 0000000..53ba8e3 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4_ctr.c @@ -0,0 +1,76 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM4_KEY sm4_key; + unsigned char key[16]; + unsigned char iv[16]; + unsigned char ctr[16]; + unsigned char mbuf[20] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34, + }; + unsigned char cbuf[20] = {0}; + unsigned char pbuf[20] = {0}; + int i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + + printf("key: "); + for (i = 0; i < sizeof(key); i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("ctr: "); + for (i = 0; i < sizeof(iv); i++) { + printf("%02X", iv[i]); + } + printf("\n"); + + sm4_set_encrypt_key(&sm4_key, key); + + printf("sm4 ctr encrypt %zu bytes\n", sizeof(mbuf)); + + printf("plaintext: "); + for (i = 0; i < sizeof(mbuf); i++) { + printf("%02X", mbuf[i]); + } + printf("\n"); + + memcpy(ctr, iv, 16); + sm4_ctr_encrypt(&sm4_key, ctr, mbuf, sizeof(mbuf), cbuf); + + printf("ciphertext: "); + for (i = 0; i < sizeof(cbuf); i++) { + printf("%02X", cbuf[i]); + } + printf("\n"); + + memcpy(ctr, iv, 16); + sm4_ctr_decrypt(&sm4_key, ctr, cbuf, sizeof(cbuf), pbuf); + + printf("decrypted: "); + for (i = 0; i < sizeof(pbuf); i++) { + printf("%02X", pbuf[i]); + } + printf("\n"); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4_ctr_encrypt_update.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4_ctr_encrypt_update.c new file mode 100644 index 0000000..1d580f6 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4_ctr_encrypt_update.c @@ -0,0 +1,51 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM4_CTR_CTX cbc_ctx; + unsigned char key[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char ctr[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char inbuf[1024]; + unsigned char outbuf[1024 + 32]; + size_t inlen; + size_t outlen; + + if (sm4_ctr_encrypt_init(&cbc_ctx, key, ctr) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + while ((inlen = fread(inbuf, 1, sizeof(inbuf), stdin)) > 0) { + if (sm4_ctr_encrypt_update(&cbc_ctx, inbuf, inlen, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + } + if (sm4_ctr_encrypt_finish(&cbc_ctx, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm4_gcm.c b/Core/GmSSL-3.1.1/demos/src/demo_sm4_gcm.c new file mode 100644 index 0000000..e1a8cdd --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm4_gcm.c @@ -0,0 +1,90 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM4_KEY sm4_key; + unsigned char key[16]; + unsigned char iv[16]; + unsigned char aad[20]; + unsigned char mbuf[64] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34, + }; + unsigned char cbuf[64] = {0}; + unsigned char pbuf[64] = {0}; + unsigned char tag[16]; + int i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + + printf("key: "); + for (i = 0; i < sizeof(key); i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("iv: "); + for (i = 0; i < sizeof(iv); i++) { + printf("%02X", iv[i]); + } + printf("\n"); + + sm4_set_encrypt_key(&sm4_key, key); + + printf("sm4 gcm encrypt\n"); + + printf("auth-only data: "); + for (i = 0; i < sizeof(aad); i++) { + printf("%02X", aad[i]); + } + printf("\n"); + + printf("plaintext: "); + for (i = 0; i < sizeof(mbuf); i++) { + printf("%02X", mbuf[i]); + } + printf("\n"); + + sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), mbuf, sizeof(mbuf), cbuf, sizeof(tag), tag); + + printf("ciphertext: "); + for (i = 0; i < sizeof(cbuf); i++) { + printf("%02X", cbuf[i]); + } + printf("\n"); + + printf("mac-tag: "); + for (i = 0; i < sizeof(tag); i++) { + printf("%02X", tag[i]); + } + printf("\n"); + + if (sm4_gcm_decrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), cbuf, sizeof(mbuf), tag, sizeof(tag), pbuf) != 1) { + fprintf(stderr, "sm4 gcm decrypt failed\n"); + return 1; + } + + printf("decrypted: "); + for (i = 0; i < sizeof(pbuf); i++) { + printf("%02X", pbuf[i]); + } + printf("\n"); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm9_encrypt.c b/Core/GmSSL-3.1.1/demos/src/demo_sm9_encrypt.c new file mode 100644 index 0000000..e5d2729 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm9_encrypt.c @@ -0,0 +1,47 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM9_ENC_MASTER_KEY master; + SM9_ENC_MASTER_KEY master_public; + SM9_ENC_KEY key; + const char *id = "Alice"; + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len; + char mbuf[256]; + size_t mlen; + int ret; + + sm9_enc_master_key_generate(&master); + sm9_enc_master_key_extract_key(&master, id, strlen(id), &key); + + sm9_enc_master_public_key_to_der(&master, &p, &len); + sm9_enc_master_public_key_from_der(&master_public, &cp, &len); + + sm9_encrypt(&master_public, id, strlen(id), (uint8_t *)"hello", strlen("hello"), buf, &len); + ret = sm9_decrypt(&key, id, strlen(id), buf, len, (uint8_t *)mbuf, &mlen); + if (ret != 1) { + fprintf(stderr, "decrypt failed\n"); + return 1; + } + mbuf[mlen] = 0; + printf("decrypt result: %s\n", mbuf); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm9_keygen.c b/Core/GmSSL-3.1.1/demos/src/demo_sm9_keygen.c new file mode 100644 index 0000000..0c645ff --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm9_keygen.c @@ -0,0 +1,35 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include + + +int main(void) +{ + SM9_SIGN_MASTER_KEY sign_master; + SM9_SIGN_KEY sign_key; + + sm9_sign_master_key_generate(&sign_master); + + printf("SM9 Master Secret\n"); + sm9_sign_master_key_info_encrypt_to_pem(&sign_master, "P@ssw0rd", stdout); + + printf("SM9 Public Parameters\n"); + sm9_sign_master_public_key_to_pem(&sign_master, stdout); + + sm9_sign_master_key_extract_key(&sign_master, "alice", strlen("alice"), &sign_key); + + printf("SM9 private key for ID '%s'\n", "alice"); + sm9_sign_key_info_encrypt_to_pem(&sign_key, "123456", stdout); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_sm9_sign.c b/Core/GmSSL-3.1.1/demos/src/demo_sm9_sign.c new file mode 100644 index 0000000..f7d5b19 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_sm9_sign.c @@ -0,0 +1,53 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + SM9_SIGN_MASTER_KEY sign_master; + SM9_SIGN_MASTER_KEY sign_master_public; + SM9_SIGN_KEY sign_key; + SM9_SIGN_CTX sign_ctx; + const char *id = "Alice"; + uint8_t sig[SM9_SIGNATURE_SIZE]; + size_t siglen; + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len; + int ret; + + sm9_sign_master_key_generate(&sign_master); + + sm9_sign_master_key_extract_key(&sign_master, id, strlen(id), &sign_key); + + sm9_sign_init(&sign_ctx); + sm9_sign_update(&sign_ctx, (uint8_t *)"hello world", strlen("hello world")); + sm9_sign_finish(&sign_ctx, &sign_key, sig, &siglen); + + format_bytes(stdout, 0, 0, "signature", sig, siglen); + + + sm9_sign_master_public_key_to_der(&sign_master, &p, &len); + sm9_sign_master_public_key_from_der(&sign_master_public, &cp, &len); + + sm9_verify_init(&sign_ctx); + sm9_verify_update(&sign_ctx, (uint8_t *)"hello world", strlen("hello world")); + ret = sm9_verify_finish(&sign_ctx, sig, siglen, &sign_master_public, id, strlen(id)); + printf("verify %s\n", ret == 1 ? "success" : "failure"); + + + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_wget.c b/Core/GmSSL-3.1.1/demos/src/demo_wget.c new file mode 100644 index 0000000..b131731 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_wget.c @@ -0,0 +1,33 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + uint8_t buf[65536]; + uint8_t *content; + size_t contentlen; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return 1; + } + if (http_get(argv[1], buf, sizeof(buf), &content, &contentlen) != 1) { + error_print(); + return -1; + } + fwrite(content, contentlen, 1, stdout); + return 0; +} diff --git a/Core/GmSSL-3.1.1/demos/src/demo_zuc.c b/Core/GmSSL-3.1.1/demos/src/demo_zuc.c new file mode 100644 index 0000000..6838ce1 --- /dev/null +++ b/Core/GmSSL-3.1.1/demos/src/demo_zuc.c @@ -0,0 +1,50 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include + + +int main(void) +{ + ZUC_CTX zuc_ctx; + unsigned char key[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char iv[16] = { + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + }; + unsigned char inbuf[1024]; + unsigned char outbuf[1024 + 32]; + size_t inlen; + size_t outlen; + + if (zuc_encrypt_init(&zuc_ctx, key, iv) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + while ((inlen = fread(inbuf, 1, sizeof(inbuf), stdin)) > 0) { + if (zuc_encrypt_update(&zuc_ctx, inbuf, inlen, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + } + if (zuc_encrypt_finish(&zuc_ctx, outbuf, &outlen) != 1) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return 1; + } + fwrite(outbuf, 1, outlen, stdout); + + return 0; +} diff --git a/Core/GmSSL-3.1.1/docs/tools/sm3.md b/Core/GmSSL-3.1.1/docs/tools/sm3.md new file mode 100644 index 0000000..7523b51 --- /dev/null +++ b/Core/GmSSL-3.1.1/docs/tools/sm3.md @@ -0,0 +1,89 @@ +### SM3命令 + +SM3是国密密码杂凑算法标准,由国家密码管理局于2010年12月公布。SM3的输出杂凑值长度为256比特(32字节) +,与国际标准SHA-256等长。SM3设计安全性为128比特,安全性与256比特椭圆曲线/SM2、SM4/SMS4、AES-128等同。 + +#### 计算SM3杂凑值 + +可以通过`gmssl sm3`命令计算输入消息或者文件的SM3杂凑值,`sm3`命令支持从标准输入(stdin)或者从文件中读取数据,以及支持向标准输出( +stdout)或者文件中输出杂凑值。 + +下面的例子中,在类UNIX操作系统终端环境中,`sm3`命令通过管道从标准输入中读取消息字符串并将杂凑值以十六进制数字的格式打印出来。 + +```shell +$ echo -n abc | gmssl sm3 +66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0 +``` + +由于SM3的杂凑值长度为32字节,因此输出的数字长度为64个字符。SM3的标准中给出了一个基本测试向量,当输入的消息为ASCII字符串`"abc"` +,也就是以十六进制表示的字节序列`616263`时,SM3计算得到的杂凑值为`66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0` +。因此可以验证,`sm3`命令的计算结果是正确的。 + +需要注意的是,终端环境通常会自动在字符串后面添加换行符,例如在类UNIX环境中,字符串会被自动添加一个字节`0a`,在Windows环境下,字符串会被自动添加两个字节 +`0d0a`。在这种情况下,`sm3`命令读取到的字节序列就是`6162620a`或者`6162630d0a`,因此不可能计算出正确的杂凑值。在上面的例子中,必须通过 +`echo`命令的`-n`参数去掉默认添加的换行符,才能生成正确的SM3杂凑值。 + +在Windows终端环境中,`echo`命令不支持`-n`选项,可以通过`set`命令来实现相同的效果。 + +```shell +C:\> echo |set/p="abc" | gmssl sm3 +66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0 +``` + +#### 输出二进制杂凑值 + +默认情况下`sm3`命令会输出杂凑值的十六进制数字串,但是也可以通过在命令行中添加`-bin` +选项来强制指定输出二进制数据。在下面的例子中,计算字符串的SM3杂凑值并将二进制数据写入文件中,可以通过`ls`命令验证输出杂凑值的文件大小为32字节。 + +```shell +$ echo -n abc | gmssl sm3 -bin > abc.sm3 + +$ ls -al abc.sm3 +-rw-r--r-- 1 guanzhi staff 32 2 23 14:59 abc.sm3 + 0 2 32 abc.sm3 +``` + +命令`sm3`也支持通过`-hex`选项来显式指定输出十六进制数字串。 + +#### 文件输入输出 + +`sm3` 命令支持将文件路径作为参数,选项`-in`和`-out`分别用于指定输入文件路径和输出文件路径。下面的例子中计算一个压缩包文件的SM3杂凑值。 + +```shell +$ gmssl sm3 -in GmSSL-master.zip -out GmSSL-master.zip.sm3 +``` + +SM3杂凑值可以作为文件的高安全校验值。如果可以通过可靠的方式获得一个文件的SM3杂凑值(比如通过下载文件的HTTPS官网),那么就可以通过这个SM3杂凑值来验证获得文件的完整性。用户下载文件后,可以计算这个文件的SM3杂凑值,和官网上公布的杂凑值进行对比,验证文件是完全正确的。 + +#### 计算SM2签名杂凑值 + +在SM2数字签名算法标准中,被签名的SM3杂凑值是通过被签名消息、签名方的SM2公钥、签名方的ID字符串共同生成的。如果第三方的SM2签名系统(如硬件的SM2签名机)只支持对SM3杂凑值的签名,不支持对SM2签名算法中的SM3杂凑值生成功能,那么可以用 +`sm3`命令的`-pubkey`和`-id`选项来生成符合SM2签名要求的杂凑值。其中`-pubkey`选项指定签名方的公钥PEM文件,`-id` +选项指定签名方的ID字符串。下面的例子给出了一个完整的SM2密钥生成和杂凑值计算过程。 + +```shell +$ gmssl sm2keygen -out sm2key.pem -pubout sm2pubkey.pem -pass P@ssw0rd +$ cat sm2pubkey.pem +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEcG1XVf03Fx1N11K0U8e5ICACpv0X +xBXZm34MjTfdLz1zUHowuC023Pl/8Eq3ZWdgYQdlgdtAe0UM2Sps6K1X5A== +-----END PUBLIC KEY----- + +$ echo -n "abc" | gmssl sm3 -pubkey sm2pubkey.pem -id Alice +e5978b292934966db0f9604d63a3e020a5acb1194df67f2285f42203b5af9efd +``` + +在第一个命令中,我们用`sm2keygen`生成了一对新的SM2私钥和公钥,其中公钥文件为`sm2pubkey.pem`。这是一个文本类型的文件,因此通过`cat` +可以看到这个文件的内容。在最后的`sm3`命令中,增加了`-pubkey`和`-id`参数,可以看到输出的杂凑值不同于`"abc"`的杂凑值。 + +注意,如果应用没有显示指定如何分配、获得签名方的ID,那么SM2标准指定使用默认的ID字符串`"1234567812345678"`,也就是字节序列 +`31323334353637383132333435363738`。在指定`-pubkey`选项但是没有指定`-id`选项时,`sm3`命令会使用这个默认的ID字符串。 + +``` +$ echo -n "abc" | gmssl sm3 -pubkey sm2pubkey.pem +9192b2f04f4b14b6e71e68f59ed0936500999231305c651763422a12f8a3b689 +$ echo -n "abc" | gmssl sm3 -pubkey sm2pubkey.pem -id 1234567812345678 +9192b2f04f4b14b6e71e68f59ed0936500999231305c651763422a12f8a3b689 +``` + +注意,在SM2中使用长度为0的ID字符串是合法的,但是`sm3`命令不支持长度为0的字符串作为输入。可以通过C函数接口来处理长度为0的ID字符串。 \ No newline at end of file diff --git a/Core/GmSSL-3.1.1/include/gmssl/aead.h b/Core/GmSSL-3.1.1/include/gmssl/aead.h new file mode 100644 index 0000000..1bc13b5 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/aead.h @@ -0,0 +1,108 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_AEAD_H +#define GMSSL_AEAD_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + SM4_CBC_CTX enc_ctx; + SM3_HMAC_CTX mac_ctx; + uint8_t mac[SM3_HMAC_SIZE]; + size_t maclen; +} SM4_CBC_SM3_HMAC_CTX; + +#define SM4_CBC_SM3_HMAC_KEY_SIZE 48 +#define SM4_CBC_SM3_HMAC_IV_SIZE 16 + +_gmssl_export int sm4_cbc_sm3_hmac_encrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen); +_gmssl_export int sm4_cbc_sm3_hmac_encrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_cbc_sm3_hmac_encrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, + uint8_t *out, size_t *outlen); +_gmssl_export int sm4_cbc_sm3_hmac_decrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen); +_gmssl_export int sm4_cbc_sm3_hmac_decrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_cbc_sm3_hmac_decrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, + uint8_t *out, size_t *outlen); + + +typedef struct { + SM4_CTR_CTX enc_ctx; + SM3_HMAC_CTX mac_ctx; + uint8_t mac[SM3_HMAC_SIZE]; + size_t maclen; +} SM4_CTR_SM3_HMAC_CTX; + +#define SM4_CTR_SM3_HMAC_KEY_SIZE 48 +#define SM4_CTR_SM3_HMAC_IV_SIZE 16 + +_gmssl_export int sm4_ctr_sm3_hmac_encrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen); +_gmssl_export int sm4_ctr_sm3_hmac_encrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_ctr_sm3_hmac_encrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, + uint8_t *out, size_t *outlen); +_gmssl_export int sm4_ctr_sm3_hmac_decrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen); +_gmssl_export int sm4_ctr_sm3_hmac_decrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_ctr_sm3_hmac_decrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, + uint8_t *out, size_t *outlen); + + +typedef struct { + SM4_CTR_CTX enc_ctx; + GHASH_CTX mac_ctx; + uint8_t Y[16]; // E(K, Y_0) + size_t taglen; + uint8_t mac[16]; + size_t maclen; +} SM4_GCM_CTX; + +#define SM4_GCM_KEY_SIZE 16 +#define SM4_GCM_DEFAULT_TAG_SIZE 16 + +_gmssl_export int sm4_gcm_encrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen); +_gmssl_export int sm4_gcm_encrypt_update(SM4_GCM_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_gcm_encrypt_finish(SM4_GCM_CTX *ctx, + uint8_t *out, size_t *outlen); +_gmssl_export int sm4_gcm_decrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen); +_gmssl_export int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_gcm_decrypt_finish(SM4_GCM_CTX *ctx, + uint8_t *out, size_t *outlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/aes.h b/Core/GmSSL-3.1.1/include/gmssl/aes.h new file mode 100644 index 0000000..e43b27a --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/aes.h @@ -0,0 +1,90 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_AES_H +#define GMSSL_AES_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#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 + + +typedef struct { + uint32_t rk[4 * (AES_MAX_ROUNDS + 1)]; + size_t rounds; +} AES_KEY; + +int aes_set_encrypt_key(AES_KEY *key, const uint8_t *raw_key, size_t raw_key_len); +int aes_set_decrypt_key(AES_KEY *key, const uint8_t *raw_key, size_t raw_key_len); +void aes_encrypt(const AES_KEY *key, const uint8_t in[AES_BLOCK_SIZE], uint8_t out[AES_BLOCK_SIZE]); +void aes_decrypt(const AES_KEY *key, const uint8_t in[AES_BLOCK_SIZE], uint8_t out[AES_BLOCK_SIZE]); + + +void aes_cbc_encrypt(const AES_KEY *key, const uint8_t iv[AES_BLOCK_SIZE], + const uint8_t *in, size_t nblocks, uint8_t *out); +void aes_cbc_decrypt(const AES_KEY *key, const uint8_t iv[AES_BLOCK_SIZE], + const uint8_t *in, size_t nblocks, uint8_t *out); +int aes_cbc_padding_encrypt(const AES_KEY *key, const uint8_t iv[AES_BLOCK_SIZE], + const uint8_t *in, size_t inlen, + uint8_t *out, size_t *outlen); +int aes_cbc_padding_decrypt(const AES_KEY *key, const uint8_t iv[AES_BLOCK_SIZE], + const uint8_t *in, size_t inlen, + uint8_t *out, size_t *outlen); + +void aes_ctr_encrypt(const AES_KEY *key, uint8_t ctr[AES_BLOCK_SIZE], + const uint8_t *in, size_t inlen, uint8_t *out); +#define aes_ctr_decrypt(key,ctr,in,inlen,out) aes_ctr_encrypt(key,ctr,in,inlen,out) + + +#define AES_GCM_IV_MIN_SIZE 1 +#define AES_GCM_IV_MAX_SIZE ((uint64_t)(1 << (64-3))) +#define AES_GCM_IV_DEFAULT_BITS 96 +#define AES_GCM_IV_DEFAULT_SIZE 12 + +#define AES_GCM_MIN_AAD_SIZE 0 +#define AES_GCM_MAX_AAD_SIZE ((uint64_t)(1 << (64-3))) + +#define AES_GCM_MIN_PLAINTEXT_SIZE 0 +#define AES_GCM_MAX_PLAINTEXT_SIZE ((((uint64_t)1 << 39) - 256) >> 3) + +#define AES_GCM_MAX_TAG_SIZE 16 + +int aes_gcm_encrypt(const AES_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + uint8_t *out, size_t taglen, uint8_t *tag); +int aes_gcm_decrypt(const AES_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + const uint8_t *tag, size_t taglen, uint8_t *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/api.h b/Core/GmSSL-3.1.1/include/gmssl/api.h new file mode 100644 index 0000000..d8fd184 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/api.h @@ -0,0 +1,23 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_API_H +#define GMSSL_API_H + + +#ifdef WIN32 +#define _gmssl_export __declspec(dllexport) +#elif defined(__GNUC__) +// use -fvisibility=hidden to change the "default" behavior +#define _gmssl_export __attribute__((visibility("default"))) +#else +#define _gmssl_export +#endif + +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/asn1.h b/Core/GmSSL-3.1.1/include/gmssl/asn1.h new file mode 100644 index 0000000..49c0b0b --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/asn1.h @@ -0,0 +1,301 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_ASN1_H +#define GMSSL_ASN1_H + +#include +#include +#include + +#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)) + + +#define ASN1_FMT_FULL 0x01 + + +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, // 0x0A + ASN1_TAG_EMBEDDED = 11, // 0x0B + ASN1_TAG_UTF8String = 12, // 0x0C + ASN1_TAG_RELATIVE_OID = 13, // 0x0D + ASN1_TAG_NumericString = 18, // 0x12 + ASN1_TAG_PrintableString = 19, // 0x13, printable subset of ascii + ASN1_TAG_TeletexString = 20, // 0x14, T61String + ASN1_TAG_VideotexString = 21, // 0x15 + ASN1_TAG_IA5String = 22, // 0x16, 7-bit ascii + ASN1_TAG_UTCTime = 23, // 0x17 + ASN1_TAG_GeneralizedTime = 24, // 0x18 + ASN1_TAG_GraphicString = 25, // 0x19 + ASN1_TAG_VisibleString = 26, // 0x20 + ASN1_TAG_GeneralString = 27, // 0x21 + ASN1_TAG_UniversalString = 28, // 0x22 + ASN1_TAG_CHARACTER_STRING = 29, // 0x23 + ASN1_TAG_BMPString = 30, // 0x24, 2-byte unicode with zeros + ASN1_TAG_SEQUENCE = 0x30, + ASN1_TAG_SET = 0x31, + ASN1_TAG_EXPLICIT = 0xa0, +}; + + +const char *asn1_tag_name(int tag); +int asn1_tag_is_cstring(int tag); +int asn1_tag_to_der(int tag, uint8_t **out, size_t *outlen); +int asn1_tag_from_der(int *tag, const uint8_t **in, size_t *inlen); +int asn1_tag_from_der_readonly(int *tag, const uint8_t **in, size_t *inlen); // read the next tag without changing *in,*inlen +int asn1_length_to_der(size_t dlen, uint8_t **out, size_t *outlen); +int asn1_length_from_der(size_t *dlen, const uint8_t **in, size_t *inlen); +int asn1_length_is_zero(size_t len); +int asn1_length_le(size_t len1, size_t len2); // less than +int asn1_data_to_der(const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_data_from_der(const uint8_t **d, size_t dlen, const uint8_t **in, size_t *inlen); + +int asn1_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int asn1_nonempty_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_nonempty_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int asn1_any_type_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int asn1_any_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen); // 调用方应保证a,alen为TLV +int asn1_any_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen); // 该函数会检查输入是否为TLV + +#define ASN1_TRUE 0xff +#define ASN1_FALSE 0x00 + +const char *asn1_boolean_name(int val); +int asn1_boolean_from_name(int *val, const char *name); +int asn1_boolean_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen); +int asn1_boolean_from_der_ex(int tag, int *val, const uint8_t **in, size_t *inlen); +#define asn1_boolean_to_der(val,out,outlen) asn1_boolean_to_der_ex(ASN1_TAG_BOOLEAN,val,out,outlen) +#define asn1_boolean_from_der(val,in,inlen) asn1_boolean_from_der_ex(ASN1_TAG_BOOLEAN,val,in,inlen) +#define asn1_implicit_boolean_to_der(i,val,out,outlen) asn1_boolean_to_der_ex(ASN1_TAG_IMPLICIT(i),val,out,outlen) +#define asn1_implicit_boolean_from_der(i,val,in,inlen) asn1_boolean_from_der_ex(ASN1_TAG_IMPLICIT(i),val,in,inlen) + +// asn1_integer_ 不支持负数编解码 +int asn1_integer_to_der_ex(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_integer_from_der_ex(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +#define asn1_integer_to_der(d,dlen,out,outlen) asn1_integer_to_der_ex(ASN1_TAG_INTEGER,d,dlen,out,outlen) +#define asn1_integer_from_der(d,dlen,in,inlen) asn1_integer_from_der_ex(ASN1_TAG_INTEGER,d,dlen,in,inlen) +#define asn1_implicit_integer_to_der(i,d,dlen,out,outlen) asn1_integer_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_integer_from_der(i,d,dlen,in,inlen) asn1_integer_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) + +// asn1_int_ 只支持小的无符号整数的编解码,不支持负数 +int asn1_int_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen); // 当 val == -1 时,不输出,返回 0 +int asn1_int_from_der_ex(int tag, int *val, const uint8_t **in, size_t *inlen); // 不支持负数,返回0时 *val 设置为 -1 +#define asn1_int_to_der(val,out,outlen) asn1_int_to_der_ex(ASN1_TAG_INTEGER,val,out,outlen) +#define asn1_int_from_der(val,in,inlen) asn1_int_from_der_ex(ASN1_TAG_INTEGER,val,in,inlen) +#define asn1_implicit_int_to_der(i,val,out,outlen) asn1_int_to_der_ex(ASN1_TAG_IMPLICIT(i),val,out,outlen) +#define asn1_implicit_int_from_der(i,val,in,inlen) asn1_int_from_der_ex(ASN1_TAG_IMPLICIT(i),val,in,inlen) + +// 比特长度不必须为8的整数倍 +int asn1_bit_string_to_der_ex(int tag, const uint8_t *d, size_t nbits, uint8_t **out, size_t *outlen); +int asn1_bit_string_from_der_ex(int tag, const uint8_t **d, size_t *nbits, const uint8_t **in, size_t *inlen); +#define asn1_bit_string_to_der(d,nbits,out,outlen) asn1_bit_string_to_der_ex(ASN1_TAG_BIT_STRING,d,nbits,out,outlen) +#define asn1_bit_string_from_der(d,nbits,in,inlen) asn1_bit_string_from_der_ex(ASN1_TAG_BIT_STRING,d,nbits,in,inlen) +#define asn1_implicit_bit_string_to_der(i,d,nbits,out,outlen) asn1_bit_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,nbits,out,outlen) +#define asn1_implicit_bit_string_from_der(i,d,nbits,in,inlen) asn1_bit_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,nbits,in,inlen) + +// 比特长度必须为8的整数倍,因此使用字节长度 +int asn1_bit_octets_to_der_ex(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_bit_octets_from_der_ex(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +#define asn1_bit_octets_to_der(d,dlen,out,outlen) asn1_bit_octets_to_der_ex(ASN1_TAG_BIT_STRING,d,dlen,out,outlen) +#define asn1_bit_octets_from_der(d,dlen,in,inlen) asn1_bit_octets_from_der_ex(ASN1_TAG_BIT_STRING,d,dlen,in,inlen) +#define asn1_implicit_bit_octets_to_der(i,d,dlen,out,outlen) asn1_bit_octets_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_bit_octets_from_der(i,d,dlen,in,inlen) asn1_bit_octets_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) + +// bits == -1 不编码,只支持较少的比特数量 +int asn1_bits_to_der_ex(int tag, int bits, uint8_t **out, size_t *outlen); +int asn1_bits_from_der_ex(int tag, int *bits, const uint8_t **in, size_t *inlen); +#define asn1_bits_to_der(bits,out,outlen) asn1_bits_to_der_ex(ASN1_TAG_BIT_STRING,bits,out,outlen) +#define asn1_bits_from_der(bits,in,inlen) asn1_bits_from_der_ex(ASN1_TAG_BIT_STRING,bits,in,inlen) +#define asn1_implicit_bits_to_der(i,bits,out,outlen) asn1_bits_to_der_ex(ASN1_TAG_IMPLICIT(i),bits,out,outlen) +#define asn1_implicit_bits_from_der(i,bits,in,inlen) asn1_bits_from_der_ex(ASN1_TAG_IMPLICIT(i),bits,in,inlen) +// names[i]对应第i个比特 +int asn1_bits_print(FILE *fp, int fmt, int ind, const char *label, const char **names, size_t names_cnt, int bits); + +#define asn1_octet_string_to_der_ex(tag,d,dlen,out,outlen) asn1_type_to_der(tag,d,dlen,out,outlen) +#define asn1_octet_string_from_der_ex(tag,d,dlen,in,inlen) asn1_type_from_der(tag,d,dlen,in,inlen) +#define asn1_octet_string_to_der(d,dlen,out,outlen) asn1_type_to_der(ASN1_TAG_OCTET_STRING,d,dlen,out,outlen) +#define asn1_octet_string_from_der(d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_OCTET_STRING,d,dlen,in,inlen) +#define asn1_implicit_octet_string_to_der(i,d,dlen,out,outlen) asn1_type_to_der(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_octet_string_from_der(i,d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) + +const char *asn1_null_name(void); +int asn1_null_to_der(uint8_t **out, size_t *outlen); +int asn1_null_from_der(const uint8_t **in, size_t *inlen); + +#define ASN1_OID_MIN_NODES 2 +#define ASN1_OID_MAX_NODES 32 +#define ASN1_OID_MIN_OCTETS 1 +#define ASN1_OID_MAX_OCTETS (1 + (ASN1_OID_MAX_NODES - 2) * 5) +int asn1_object_identifier_to_octets(const uint32_t *nodes, size_t nodes_cnt, uint8_t *out, size_t *outlen); +int asn1_object_identifier_from_octets(uint32_t *nodes, size_t *nodes_cnt, const uint8_t *in, size_t inlen); + +int asn1_object_identifier_to_der_ex(int tag, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen); +int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen); +#define asn1_object_identifier_to_der(nodes,nodes_cnt,out,outlen) asn1_object_identifier_to_der_ex(ASN1_TAG_OBJECT_IDENTIFIER,nodes,nodes_cnt,out,outlen) +#define asn1_object_identifier_from_der(nodes,nodes_cnt,in,inlen) asn1_object_identifier_from_der_ex(ASN1_TAG_OBJECT_IDENTIFIER,nodes,nodes_cnt,in,inlen) +#define asn1_implicit_object_identifier_to_der(i,nodes,nodes_cnt,out,outlen) asn1_object_identifier_to_der_ex(ASN1_TAG_IMPLICIT(i),nodes,nodes_cnt,out,outlen) +#define asn1_implicit_object_identifier_from_der(i,nodes,nodes_cnt,in,inlen) asn1_object_identifier_from_der_ex(ASN1_TAG_IMPLICIT(i),nodes,nodes_cnt,in,inlen) +int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt); +int asn1_object_identifier_print(FILE *fp, int fmt, int ind, const char *label, const char *name, + const uint32_t *nodes, size_t nodes_cnt); + +typedef struct { + int oid; + char *name; + uint32_t *nodes; + size_t nodes_cnt; + int flags; + char *description; +} ASN1_OID_INFO; + +const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t count, const char *name); +const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t count, int oid); +// 如果一个正确解析的OID并不在infos列表中,那么仍然返回1,但是调用方必须检查返回的info是否为空 +int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_t *nodes_cnt, + const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen); +int asn1_oid_info_from_der(const ASN1_OID_INFO **info, + const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen); + +#define asn1_enumerated_to_der_ex(tag,val,out,outlen) asn1_int_to_der_ex(tag,val,out,outlen) +#define asn1_enumerated_from_der_ex(tag,val,in,inlen) asn1_int_from_der_ex(tag,val,in,inlen) +#define asn1_enumerated_to_der(val,out,outlen) asn1_int_to_der_ex(ASN1_TAG_ENUMERATED,val,out,outlen) +#define asn1_enumerated_from_der(val,in,inlen) asn1_int_from_der_ex(ASN1_TAG_ENUMERATED,val,in,inlen) +#define asn1_implicit_enumerated_to_der(i,val,out,outlen) asn1_int_to_der_ex(ASN1_TAG_IMPLICIT(i),val,out,outlen) +#define asn1_implicit_enumerated_from_der(i,val,in,inlen) asn1_int_from_der_ex(ASN1_TAG_IMPLICIT(i),val,in,inlen) + +int asn1_string_is_utf8_string(const char *d, size_t dlen); +int asn1_utf8_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_utf8_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen); +#define asn1_utf8_string_to_der(d,dlen,out,outlen) asn1_utf8_string_to_der_ex(ASN1_TAG_UTF8String,d,dlen,out,outlen) +#define asn1_utf8_string_from_der(d,dlen,in,inlen) asn1_utf8_string_from_der_ex(ASN1_TAG_UTF8String,d,dlen,in,inlen) +#define asn1_implicit_utf8_string_to_der(i,d,dlen,out,outlen) asn1_utf8_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_utf8_string_from_der(i,d,dlen,in,inlen) asn1_utf8_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) + +int asn1_string_is_printable_string(const char *d, size_t dlen); +int asn1_printable_string_case_ignore_match(const char *a, size_t alen, const char *b, size_t blen); +int asn1_printable_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_printable_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen); +#define asn1_printable_string_to_der(d,dlen,out,outlen) asn1_printable_string_to_der_ex(ASN1_TAG_PrintableString,d,dlen,out,outlen) +#define asn1_printable_string_from_der(d,dlen,in,inlen) asn1_printable_string_from_der_ex(ASN1_TAG_PrintableString,d,dlen,in,inlen) +#define asn1_implicit_printable_string_to_der(i,d,dlen,out,outlen) asn1_printable_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_printable_string_from_der(i,d,dlen,in,inlen) asn1_printable_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) + +int asn1_string_is_ia5_string(const char *d, size_t dlen); +int asn1_ia5_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen); +int asn1_ia5_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen); +#define asn1_ia5_string_to_der(d,dlen,out,outlen) asn1_ia5_string_to_der_ex(ASN1_TAG_IA5String,d,dlen,out,outlen) +#define asn1_ia5_string_from_der(d,dlen,in,inlen) asn1_ia5_string_from_der_ex(ASN1_TAG_IA5String,d,dlen,in,inlen) +#define asn1_implicit_ia5_string_to_der(i,d,dlen,out,outlen) asn1_ia5_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_ia5_string_from_der(i,d,dlen,in,inlen) asn1_ia5_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) + +int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen); + +#define ASN1_UTC_TIME_STRLEN (sizeof("YYMMDDHHMMSSZ")-1) +#define ASN1_GENERALIZED_TIME_STRLEN (sizeof("YYYYMMDDHHMMSSZ")-1) +#define ASN1_GENERALIZED_TIME_MAX_SIZE (2 + ASN1_GENERALIZED_TIME_STRLEN) + +int asn1_time_to_str(int utc_time, time_t timestamp, char *str); +int asn1_time_from_str(int utc_time, time_t *timestamp, const char *str); + +int asn1_utc_time_to_der_ex(int tag, time_t tv, uint8_t **out, size_t *outlen); +int asn1_utc_time_from_der_ex(int tag, time_t *tv, const uint8_t **in, size_t *inlen); +#define asn1_utc_time_to_der(tv,out,outlen) asn1_utc_time_to_der_ex(ASN1_TAG_UTCTime,tv,out,outlen) +#define asn1_utc_time_from_der(tv,in,inlen) asn1_utc_time_from_der_ex(ASN1_TAG_UTCTime,tv,in,inlen) +#define asn1_implicit_utc_time_to_der(i,tv,out,outlen) asn1_utc_time_to_der_ex(ASN1_TAG_IMPLICIT(i),tv,out,outlen) +#define asn1_implicit_utc_time_from_der(i,tv,in,inlen) asn1_utc_time_from_der_ex(ASN1_TAG_IMPLICIT(i),tv,in,inlen) + +int asn1_generalized_time_to_der_ex(int tag, time_t tv, uint8_t **out, size_t *outlen); +int asn1_generalized_time_from_der_ex(int tag, time_t *tv, const uint8_t **in, size_t *inlen); +#define asn1_generalized_time_to_der(tv,out,outlen) asn1_generalized_time_to_der_ex(ASN1_TAG_GeneralizedTime,tv,out,outlen) +#define asn1_generalized_time_from_der(tv,in,inlen) asn1_generalized_time_from_der_ex(ASN1_TAG_GeneralizedTime,tv,in,inlen) +#define asn1_implicit_generalized_time_to_der(i,tv,out,outlen) asn1_generalized_time_to_der_ex(ASN1_TAG_IMPLICIT(i),tv,out,outlen) +#define asn1_implicit_generalized_time_from_der(i,tv,in,inlen) asn1_generalized_time_from_der_ex(ASN1_TAG_IMPLICIT(i),tv,in,inlen) + +// BasicConstraints might be an empty sequence in entity certificates +#define asn1_sequence_to_der(d,dlen,out,outlen) asn1_type_to_der(ASN1_TAG_SEQUENCE,d,dlen,out,outlen) +#define asn1_sequence_from_der(d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_SEQUENCE,d,dlen,in,inlen) +#define asn1_implicit_sequence_to_der(i,d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_EXPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_sequence_from_der(i,d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_EXPLICIT(i),d,dlen,in,inlen) + +#define asn1_sequence_of_to_der(d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_SEQUENCE,d,dlen,out,outlen) +#define asn1_sequence_of_from_der(d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_SEQUENCE,d,dlen,in,inlen) +int asn1_sequence_of_int_to_der(const int *nums, size_t nums_cnt, uint8_t **out, size_t *outlen); +int asn1_sequence_of_int_from_der(int *nums, size_t *nums_cnt, size_t max_nums, const uint8_t **in, size_t *inlen); +int asn1_sequence_of_int_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +#define asn1_set_to_der(d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_SET,d,dlen,out,outlen) +#define asn1_set_from_der(d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_SET,d,dlen,in,inlen) +#define asn1_implicit_set_to_der(i,d,dlen,out,outlen) asn1_type_to_der(ASN1_TAG_EXPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_set_from_der(i,d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_EXPLICIT(i),d,dlen,in,inlen) + +#define asn1_set_of_to_der(d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_SET,d,dlen,out,outlen) +#define asn1_set_of_from_der(d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_SET,d,dlen,in,inlen) + +#define asn1_implicit_to_der(i,d,dlen,out,outlen) asn1_type_to_der(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) +#define asn1_implicit_from_der(i,d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) + +int asn1_header_to_der(int tag, size_t dlen, uint8_t **out, size_t *outlen); +#define asn1_implicit_header_to_der(i,dlen,out,outlen) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),dlen,out,outlen) + +#define asn1_octet_string_header_to_der(dlen,out,outlen) asn1_header_to_der(ASN1_TAG_OCTET_STRING,dlen,out,outlen) + +#define asn1_sequence_header_to_der_ex(tag,dlen,out,outlen) asn1_header_to_der(tag,dlen,out,outlen) +#define asn1_sequence_header_to_der(dlen,out,outlen) asn1_header_to_der(ASN1_TAG_SEQUENCE,dlen,out,outlen) +#define asn1_implicit_sequence_header_to_der(i,dlen,out,outlen) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),dlen,out,outlen) + +#define asn1_set_header_to_der(dlen,out,outlen) asn1_header_to_der(ASN1_TAG_SET,dlen,out,outlen) +#define asn1_implicit_set_header_to_der(i,dlen,out,outlen) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),dlen,out,outlen) + +#define asn1_explicit_header_to_der(i,dlen,out,outlen) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),dlen,out,outlen) + +#define asn1_explicit_to_der(i,d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_EXPLICIT(i),d,dlen,out,outlen) +#define asn1_explicit_from_der(i,d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_EXPLICIT(i),d,dlen,in,inlen) + +// d,dlen 是 SEQUENCE OF, SET OF 中的值 +int asn1_types_get_count(const uint8_t *d, size_t dlen, int tag, size_t *cnt); +int asn1_types_get_item_by_index(const uint8_t *d, size_t dlen, int tag, + int index, const uint8_t **item_d, size_t *item_dlen); + + + + + +int asn1_check(int expr); + + +#if __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/base64.h b/Core/GmSSL-3.1.1/include/gmssl/base64.h new file mode 100644 index 0000000..e981aef --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/base64.h @@ -0,0 +1,72 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_BASE64_H +#define GMSSL_BASE64_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +BASE64 Public API + + BASE64_CTX + base64_encode_init + base64_encode_update + base64_encode_finish + base64_decode_init + base64_decode_update + base64_decode_finish + +*/ + + +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 diff --git a/Core/GmSSL-3.1.1/include/gmssl/block_cipher.h b/Core/GmSSL-3.1.1/include/gmssl/block_cipher.h new file mode 100644 index 0000000..e928663 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/block_cipher.h @@ -0,0 +1,74 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + + +#ifndef GMSSL_BLOCK_CIPHER_H +#define GMSSL_BLOCK_CIPHER_H + + +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define BLOCK_CIPHER_BLOCK_SIZE 16 +#define BLOCK_CIPHER_MIN_KEY_SIZE 16 +#define BLOCK_CIPHER_MAX_KEY_SIZE 32 + + +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 void (*block_cipher_set_encrypt_key_func)(BLOCK_CIPHER_KEY *key, const uint8_t *raw_key); +typedef void (*block_cipher_set_decrypt_key_func)(BLOCK_CIPHER_KEY *key, const uint8_t *raw_key); +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_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; +}; + +const BLOCK_CIPHER *BLOCK_CIPHER_sm4(void); +const BLOCK_CIPHER *BLOCK_CIPHER_aes128(void); + +const BLOCK_CIPHER *block_cipher_from_name(const char *name); +const char *block_cipher_name(const BLOCK_CIPHER *cipher); +int block_cipher_set_encrypt_key(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key); +int block_cipher_set_decrypt_key(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key); +int block_cipher_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out); +int block_cipher_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/chacha20.h b/Core/GmSSL-3.1.1/include/gmssl/chacha20.h new file mode 100644 index 0000000..6021575 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/chacha20.h @@ -0,0 +1,57 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +/* RFC 8439 "ChaCha20 and Poly1305 for IETF Protocols" */ + +#ifndef GMSSL_CHACHA20_H +#define GMSSL_CHACHA20_H + +#define CHACHA20_IS_BIG_ENDIAN 0 + +#include +#include + +#include + +#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_init(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, + size_t counts, uint8_t *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/cms.h b/Core/GmSSL-3.1.1/include/gmssl/cms.h new file mode 100644 index 0000000..e52e057 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/cms.h @@ -0,0 +1,552 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +/* +References: + 1. GM/T 0010-2012 SM2 Cryptography Message Syntax Specification + 2. RFC 2315 PKCS #7 Cryptographic Message Syntax Version 1.5 + 3. RFC 5652 Cryptographic Message Syntax (CMS) +*/ + +#ifndef GMSSL_CMS_H +#define GMSSL_CMS_H + + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + CMS_version_v1 = 1, +}; + + +/* +ContentType: + OID_cms_data + OID_cms_signed_data + OID_cms_enveloped_data + OID_cms_signed_and_enveloped_data + OID_cms_encrypted_data + OID_cms_key_agreement_info +*/ +const char *cms_content_type_name(int oid); +int cms_content_type_from_name(const char *name); +int cms_content_type_to_der(int oid, uint8_t **out, size_t *outlen); +int cms_content_type_from_der(int *oid, const uint8_t **in, size_t *inlen); + +/* +ContentInfo ::= SEQUENCE { + contentType OBJECT IDENTIFIER, + content [0] EXPLICIT ANY OPTIONAL } +*/ +int cms_content_info_header_to_der( + int content_type, size_t content_len, + uint8_t **out, size_t *outlen); +int cms_content_info_to_der( + int content_type, + const uint8_t *content, size_t content_len, + uint8_t **out, size_t *outlen); +int cms_content_info_from_der( + int *content_type, + const uint8_t **content, size_t *content_len, // 这里获得的是完整的TLV + const uint8_t **in, size_t *inlen); +int cms_content_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +Data ::= OCTET STRING +*/ +#define cms_data_to_der(d,dlen,out,outlen) asn1_octet_string_to_der(d,dlen,out,outlen) +#define cms_data_from_der(d,dlen,in,inlen) asn1_octet_string_from_der(d,dlen,in,inlen) +#define cms_data_print(fp,fmt,ind,label,d,dlen) format_bytes(fp,fmt,ind,label,d,dlen) + +/* +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 } +*/ +int cms_enced_content_info_to_der( + int content_type, + int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen); +int cms_enced_content_info_from_der( + int *content_type, + int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, + const uint8_t **enced_content, size_t *enced_content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen); +int cms_enced_content_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int cms_enced_content_info_encrypt_to_der( + int enc_algor, + const uint8_t *key, size_t keylen, + const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen); +int cms_enced_content_info_decrypt_from_der( + int *enc_algor, + const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen); + +/* +EncryptedData ::= SEQUENCE { + version INTEGER (1), + encryptedContentInfo EncryptedContentInfo } +*/ +int cms_encrypted_data_to_der( + int version, + int content_type, + int enc_algor, const uint8_t *iv, size_t ivlen, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen); +int cms_encrypted_data_from_der( + int *version, + int *content_type, + int *enc_algor, const uint8_t **iv, size_t *ivlen, + const uint8_t **enced_content, size_t *enced_content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen); +int cms_encrypted_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int cms_encrypted_data_encrypt_to_der( + int enc_algor, + const uint8_t *key, size_t keylen, + const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen); +int cms_encrypted_data_decrypt_from_der( + int *enc_algor, + const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen); + +/* +IssuerAndSerialNumber ::= SEQUENCE { + isser Name, + serialNumber INTEGER } +*/ +int cms_issuer_and_serial_number_to_der( + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + uint8_t **out, size_t *outlen); +int cms_issuer_and_serial_number_from_der( + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len, + const uint8_t **in, size_t *inlen); +int cms_issuer_and_serial_number_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +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, } +*/ +int cms_signer_info_to_der( + int version, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + int digest_algor, + const uint8_t *authed_attrs, size_t authed_attrs_len, + int signature_algor, + 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( + int *version, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len, + int *digest_algor, + const uint8_t **authed_attrs, size_t *authed_attrs_len, + int *signature_algor, + 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, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int cms_signer_info_sign_to_der( + const SM3_CTX *sm3_ctx, const SM2_KEY *sm2_key, + const uint8_t *issuer, size_t issuer_len, + 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 SM3_CTX *sm3_ctx, const uint8_t *certs, size_t certslen, + const uint8_t **cert, size_t *certlen, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial, size_t *serial_len, + const uint8_t **authed_attrs, size_t *authed_attrs_len, + const uint8_t **unauthed_attrs, size_t *unauthed_attrs_len, + const uint8_t **in, size_t *inlen); +/* +SignerInfos ::= SET OF SignerInfo; +*/ +int cms_signer_infos_add_signer_info( + uint8_t *d, size_t *dlen, size_t maxlen, + const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, + const uint8_t *issuer, size_t issuer_len, + 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); +#define cms_signer_infos_to_der(d,dlen,out,outlen) asn1_set_to_der(d,dlen,out,outlen) +#define cms_signer_infos_from_der(d,dlen,in,inlen) asn1_set_from_der(d,dlen,in,inlen) +int cms_signer_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int cms_digest_algors_to_der(const int *digest_algors, size_t digest_algors_cnt, uint8_t **out, size_t *outlen); +int cms_digest_algors_from_der(int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + const uint8_t **in, size_t *inlen); +int cms_digest_algors_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +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 } +*/ +int cms_signed_data_to_der( + int version, + const int *digest_algors, size_t digest_algors_cnt, + const int content_type, const uint8_t *content, const size_t content_len, + const uint8_t *certs, size_t certs_len, + const uint8_t *crls, const size_t crls_len, + const uint8_t *signer_infos, size_t signer_infos_len, + uint8_t **out, size_t *outlen); +int cms_signed_data_from_der( + int *version, + int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + 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, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +typedef struct { + uint8_t *certs; + size_t certs_len; + SM2_KEY *sign_key; +} CMS_CERTS_AND_KEY; + +int cms_signed_data_sign_to_der( + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + int content_type, const uint8_t *data, size_t datalen, // 当OID_cms_data时为raw data + const uint8_t *crls, size_t crls_len, // 可以为空 + uint8_t **out, size_t *outlen); +int cms_signed_data_verify_from_der( + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, + int *content_type, const uint8_t **content, size_t *content_len, // 是否应该返回raw data呢? + 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); + + +/* +RecipientInfo ::= SEQUENCE { + version INTEGER (1), + issuerAndSerialNumber IssuerAndSerialNumber, + keyEncryptionAlgorithm AlgorithmIdentifier, + encryptedKey OCTET STRING -- DER-encoding of SM2Cipher +} +由于encryptedKey的类型为SM2Cipher, 而SM2Cipher中有2个INTEGER,因此长度是不固定的。 +因此不能预先确定输出长度 +*/ +int cms_recipient_info_to_der( + int version, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + int public_key_enc_algor, + const uint8_t *enced_key, size_t enced_key_len, + uint8_t **out, size_t *outlen); +int cms_recipient_info_from_der( + int *version, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len, + int *pke_algor, const uint8_t **params, size_t *params_len,// SM2加密只使用SM3,没有默认参数,但是ECIES可能有 + const uint8_t **enced_key, size_t *enced_key_len, + const uint8_t **in, size_t *inlen); +int cms_recipient_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +int cms_recipient_info_encrypt_to_der( + const SM2_KEY *public_key, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + const uint8_t *in, size_t inlen, + uint8_t **out, size_t *outlen); +int cms_recipient_info_decrypt_from_der( + const SM2_KEY *sm2_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, + uint8_t *out, size_t *outlen, size_t maxlen, + const uint8_t **in, size_t *inlen); + +int cms_recipient_infos_add_recipient_info( + uint8_t *d, size_t *dlen, size_t maxlen, + const SM2_KEY *public_key, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + const uint8_t *in, size_t inlen); +#define cms_recipient_infos_to_der(d,dlen,out,outlen) asn1_set_to_der(d,dlen,out,outlen) +#define cms_recipient_infos_from_der(d,dlen,in,inlen) asn1_set_from_der(d,dlen,in,inlen) +int cms_recipient_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +EnvelopedData ::= SEQUENCE { + version Version, + recipientInfos SET OF RecipientInfo, + encryptedContentInfo EncryptedContentInfo } +*/ +int cms_enveloped_data_to_der( + int version, + const uint8_t *rcpt_infos, size_t rcpt_infos_len, + int content_type, + int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen); +int cms_enveloped_data_from_der( + int *version, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **enced_content_info, size_t *enced_content_info_len, + const uint8_t **in, size_t *inlen); +int cms_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int cms_enveloped_data_encrypt_to_der( + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen); +int cms_enveloped_data_decrypt_from_der( + const SM2_KEY *sm2_key, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen); + +/* +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 } +*/ +int cms_signed_and_enveloped_data_to_der( + int version, + const uint8_t *rcpt_infos, size_t rcpt_infos_len, + const int *digest_algors, size_t digest_algors_cnt, + int content_type, + int enc_algor, const uint8_t *iv, size_t ivlen, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_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, + uint8_t **out, size_t *outlen); +int cms_signed_and_enveloped_data_from_der( + int *version, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + const uint8_t **enced_content_info, size_t *enced_content_info_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_and_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int cms_signed_and_enveloped_data_encipher_to_der( + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *signers_crls, size_t signers_crls_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen); +int cms_signed_and_enveloped_data_decipher_from_der( + const SM2_KEY *rcpt_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **prcpt_infos, size_t *prcpt_infos_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **certs, size_t *certs_len, + const uint8_t **crls, size_t *crls_len, + const uint8_t **psigner_infos, size_t *psigner_infos_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, + const uint8_t **in, size_t *inlen); + +/* +KeyAgreementInfo ::= SEQUENCE { + version INTEGER (1), + tempPublicKeyR SM2PublicKey, + userCertificate Certificate, + userID OCTET STRING } +*/ +int cms_key_agreement_info_to_der( + int version, + const SM2_KEY *temp_public_key_r, + const uint8_t *user_cert, size_t user_cert_len, + const uint8_t *user_id, size_t user_id_len, + uint8_t **out, size_t *outlen); +int cms_key_agreement_info_from_der( + int *version, + SM2_KEY *temp_public_key_r, + const uint8_t **user_cert, size_t *user_cert_len, + const uint8_t **user_id, size_t *user_id_len, + const uint8_t **in, size_t *inlen); +int cms_key_agreement_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + + +// 下面是公开API +// 公开API的设计考虑: +// 1. 不需要调用其他函数 +// 2. 在逻辑上容易理解 +// 3. 将cms,cmslen看做对象 + + +// 生成ContentInfo, type == data +int cms_set_data(uint8_t *cms, size_t *cmslen, + const uint8_t *d, size_t dlen); + +int cms_encrypt( + uint8_t *cms, size_t *cmslen, // 输出的ContentInfo (type encryptedData) + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, // 对称加密算法、密钥和IV + int content_type, const uint8_t *content, size_t content_len, // 待加密的输入数据 + const uint8_t *shared_info1, size_t shared_info1_len, // 附加信息 + const uint8_t *shared_info2, size_t shared_info2_len); + +int cms_decrypt( + const uint8_t *cms, size_t cmslen, // 输入的ContentInfo (type encryptedData) + int *enc_algor, const uint8_t *key, size_t keylen, // 解密密钥(我们不知道解密算法) + int *content_type, uint8_t *content, size_t *content_len, // 输出的解密数据类型及数据 + const uint8_t **shared_info1, size_t *shared_info1_len, // 附加信息 + const uint8_t **shared_info2, size_t *shared_info2_len); + +int cms_sign( + uint8_t *cms, size_t *cms_len, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, // 签名者的签名私钥和证书 + int content_type, const uint8_t *content, size_t content_len, // 待签名的输入数据 + const uint8_t *crls, size_t crls_len); + +int cms_verify( + const uint8_t *cms, size_t cms_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_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); + +int cms_envelop( + uint8_t *cms, size_t *cms_len, + const uint8_t *rcpt_certs, size_t rcpt_certs_len, // 接收方证书,注意这个参数的类型可以容纳多个证书,但是只有在一个接受者时对调用方最方便 + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, // 对称加密算法及参数 + int content_type, const uint8_t *content, size_t content_len, // 待加密的输入数据 + const uint8_t *shared_info1, size_t shared_info1_len, // 附加输入信息 + const uint8_t *shared_info2, size_t shared_info2_len); + +int cms_deenvelop( + const uint8_t *cms, size_t cms_len, + const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, // 接收方的解密私钥和对应的证书,注意只需要一个解密方 + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, // 解析得到,用于显示 + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len); + +int cms_sign_and_envelop( + uint8_t *cms, size_t *cms_len, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *signers_crls, size_t signers_crls_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len); + +int cms_deenvelop_and_verify( + const uint8_t *cms, size_t cms_len, + const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, + const uint8_t *extra_signer_certs, size_t extra_signer_certs_len, + const uint8_t *extra_signer_crls, size_t extra_signer_crls_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **signer_infos, size_t *signer_infos_len, + const uint8_t **signer_certs, size_t *signer_certs_len, + const uint8_t **signer_crls, size_t *signer_crls_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len); + +// 生成ContentInfo, type == keyAgreementInfo +int cms_set_key_agreement_info( + uint8_t *cms, size_t *cms_len, + const SM2_KEY *temp_public_key_r, + const uint8_t *user_cert, size_t user_cert_len, + const uint8_t *user_id, size_t user_id_len); + +#define PEM_CMS "CMS" +int cms_to_pem(const uint8_t *cms, size_t cms_len, FILE *fp); +int cms_from_pem(uint8_t *cms, size_t *cms_len, size_t maxlen, FILE *fp); + + +int cms_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/des.h b/Core/GmSSL-3.1.1/include/gmssl/des.h new file mode 100644 index 0000000..c79d281 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/des.h @@ -0,0 +1,58 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +/* FIPS PUB 46-3 "Data Encryption Standard (DES)" */ + +#ifndef GMSSL_DES_H +#define GMSSL_DES_H + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define DES_KEY_BITS 56 +#define DES_BLOCK_BITS 64 +#define DES_KEY_SIZE ((DES_KEY_BITS)/7) +#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 + +#define DES_EDE_KEY_SIZE (DES_KEY_SIZE * 3) + +typedef struct { + uint64_t rk[DES_ROUNDS]; +} DES_KEY; + +void des_set_encrypt_key(DES_KEY *key, const uint8_t raw_key[DES_KEY_SIZE]); +void des_set_decrypt_key(DES_KEY *key, const uint8_t raw_key[DES_KEY_SIZE]); +void des_encrypt(DES_KEY *key, const uint8_t in[DES_BLOCK_SIZE], uint8_t out[DES_BLOCK_SIZE]); + + +typedef struct { + DES_KEY K[3]; +} DES_EDE_KEY; + +void des_ede_set_encrypt_key(DES_EDE_KEY *key, const uint8_t raw_key[DES_EDE_KEY_SIZE]); +void des_ede_set_decrypt_key(DES_EDE_KEY *key, const uint8_t raw_key[DES_EDE_KEY_SIZE]); +void des_ede_encrypt(DES_EDE_KEY *key, const uint8_t in[DES_BLOCK_SIZE], uint8_t out[DES_BLOCK_SIZE]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/digest.h b/Core/GmSSL-3.1.1/include/gmssl/digest.h new file mode 100644 index 0000000..18a9d69 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/digest.h @@ -0,0 +1,87 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_DIGEST_H +#define GMSSL_DIGEST_H + + +#include +#include +#include +#ifdef ENABLE_BROKEN_CRYPTO +#include +#include +#endif +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct DIGEST DIGEST; +typedef struct DIGEST_CTX DIGEST_CTX; + + +#define DIGEST_MAX_SIZE 64 +#define DIGEST_MAX_BLOCK_SIZE (1024/8) + + +struct DIGEST_CTX { + union { + SM3_CTX sm3_ctx; +#ifdef ENABLE_BROKEN_CRYPTO + MD5_CTX md5_ctx; + SHA1_CTX sha1_ctx; +#endif + SHA224_CTX sha224_ctx; + SHA256_CTX sha256_ctx; + SHA384_CTX sha384_ctx; + SHA512_CTX sha512_ctx; + } u; + const DIGEST *digest; +}; + +struct DIGEST { + int oid; + size_t digest_size; + size_t block_size; + size_t ctx_size; + int (*init)(DIGEST_CTX *ctx); + int (*update)(DIGEST_CTX *ctx, const uint8_t *data, size_t datalen); + int (*finish)(DIGEST_CTX *ctx, uint8_t *dgst); +}; + +const DIGEST *DIGEST_sm3(void); +#ifdef ENABLE_BROKEN_CRYPTO +const DIGEST *DIGEST_md5(void); +const DIGEST *DIGEST_sha1(void); +#endif +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); +const char *digest_name(const DIGEST *digest); +int digest_init(DIGEST_CTX *ctx, const DIGEST *algor); +int digest_update(DIGEST_CTX *ctx, const uint8_t *data, size_t datalen); +int digest_finish(DIGEST_CTX *ctx, uint8_t *dgst, size_t *dgstlen); +int digest(const DIGEST *digest, const uint8_t *data, size_t datalen, uint8_t *dgst, size_t *dgstlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/dylib.h b/Core/GmSSL-3.1.1/include/gmssl/dylib.h new file mode 100644 index 0000000..c2aefaa --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/dylib.h @@ -0,0 +1,54 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_DYLIB_H +#define GMSSL_DYLIB_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef WIN32 + +#include + +typedef HMODULE dylib_handle_t; + +#define dylib_load_library(so_path) LoadLibraryA(so_path) +#define dylib_get_function(handle,name) GetProcAddress(handle,name) +#define dylib_close_library(handle) +#define dylib_error_str() "" + + +#else + +#include + +typedef void *dylib_handle_t; + +#define dylib_load_library(so_path) dlopen(so_path,RTLD_LAZY) +#define dylib_get_function(handle,name) dlsym(handle,name) +#define dylib_close_library(handle) dlclose(handle) +#define dylib_error_str() dlerror() + + +#endif + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/ec.h b/Core/GmSSL-3.1.1/include/gmssl/ec.h new file mode 100644 index 0000000..2dc1c00 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/ec.h @@ -0,0 +1,64 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_EC_H +#define GMSSL_EC_H + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +NamedCurve: + OID_sm2 + OID_prime192v1 + OID_prime256v1 + OID_secp256k1 + OID_secp384r1 + OID_secp521r1 +*/ +const char *ec_named_curve_name(int curve); +int ec_named_curve_from_name(const char *name); +int ec_named_curve_to_der(int curve, uint8_t **out, size_t *outlen); +int ec_named_curve_from_der(int *curve, const uint8_t **in, size_t *inlen); + +/* +ECPoint ::= OCTET STRING -- uncompressed point +*/ +int ec_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +ECPrivateKey ::= SEQUENCE { + version INTEGER, -- value MUST be (1) + privateKey OCTET STRING, -- big endian encoding of integer + parameters [0] EXPLICIT OBJECT IDENTIFIER OPTIONAL, -- namedCurve + publicKey [1] EXPLICIT BIT STRING OPTIONAL -- ECPoint +} +*/ + +enum { + EC_private_key_version = 1, +}; + +int ec_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/endian.h b/Core/GmSSL-3.1.1/include/gmssl/endian.h new file mode 100644 index 0000000..8f4345c --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/endian.h @@ -0,0 +1,78 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#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] = (uint8_t)((V) >> 56), \ + (p)[1] = (uint8_t)((V) >> 48), \ + (p)[2] = (uint8_t)((V) >> 40), \ + (p)[3] = (uint8_t)((V) >> 32), \ + (p)[4] = (uint8_t)((V) >> 24), \ + (p)[5] = (uint8_t)((V) >> 16), \ + (p)[6] = (uint8_t)((V) >> 8), \ + (p)[7] = (uint8_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 diff --git a/Core/GmSSL-3.1.1/include/gmssl/error.h b/Core/GmSSL-3.1.1/include/gmssl/error.h new file mode 100644 index 0000000..a5902ef --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/error.h @@ -0,0 +1,67 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_ERROR_H +#define GMSSL_ERROR_H + + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define GMSSL_FMT_BIN 1 +#define GMSSL_FMT_HEX 2 +#define GMSSL_FMT_DER 4 +#define GMSSL_FMT_PEM 8 + + + +#define DEBUG 1 + +#define warning_print() \ + do { if (DEBUG) fprintf(stderr, "%s:%d:%s():\n",__FILE__, __LINE__, __func__); } while (0) + +#define error_print() \ + do { if (DEBUG) fprintf(stderr, "%s:%d:%s():\n",__FILE__, __LINE__, __func__); } while (0) + +#define error_print_msg(fmt, ...) \ + do { if (DEBUG) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0) + +#define error_puts(str) \ + do { if (DEBUG) fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, __func__, str); } while (0) + + +void print_der(const uint8_t *in, size_t inlen); +void print_bytes(const uint8_t *in, size_t inlen); +void print_nodes(const uint32_t *in, size_t inlen); + +#define FMT_CARRAY 0x80 + + +int format_print(FILE *fp, int format, int indent, const char *str, ...); +int format_bytes(FILE *fp, int format, int indent, const char *str, const uint8_t *data, size_t datalen); +int format_string(FILE *fp, int format, int indent, const char *str, const uint8_t *data, size_t datalen); + + + +//int tls_trace(int format, int indent, const char *str, ...); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/file.h b/Core/GmSSL-3.1.1/include/gmssl/file.h new file mode 100644 index 0000000..435c37c --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/file.h @@ -0,0 +1,29 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_FILE_H +#define GMSSL_FILE_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +int file_size(FILE *fp, size_t *size); +int file_read_all(const char *file, uint8_t **out, size_t *outlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/gcm.h b/Core/GmSSL-3.1.1/include/gmssl/gcm.h new file mode 100644 index 0000000..97c62fc --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/gcm.h @@ -0,0 +1,73 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_GCM_H +#define GMSSL_GCM_H + + +#include +#include +#include +#include +#include + + +#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 GHASH_SIZE (16) + + +#define GCM_IS_LITTLE_ENDIAN 1 + + +void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, + const uint8_t *c, size_t clen, uint8_t out[16]); + +typedef struct { + gf128_t H; + gf128_t X; + size_t aadlen; + size_t clen; + uint8_t block[16]; + size_t 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]); + + +int gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + uint8_t *out, size_t taglen, uint8_t *tag); + +int gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + const uint8_t *tag, size_t taglen, uint8_t *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/gf128.h b/Core/GmSSL-3.1.1/include/gmssl/gf128.h new file mode 100644 index 0000000..8263e4a --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/gf128.h @@ -0,0 +1,53 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +/* 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 + + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +//typedef unsigned __int128 gf128_t; + +typedef struct { + uint64_t hi; + uint64_t lo; +} gf128_t; + + +// Note: send by value is comptabile with uint128_t and sse2 +gf128_t gf128_from_hex(const char *s); +int gf128_equ_hex(gf128_t a, const char *s); +gf128_t gf128_zero(void); +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]); +int gf128_print(FILE *fp, int fmt ,int ind, const char *label, gf128_t a); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/hash_drbg.h b/Core/GmSSL-3.1.1/include/gmssl/hash_drbg.h new file mode 100644 index 0000000..db6d187 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/hash_drbg.h @@ -0,0 +1,79 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +/* 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 +#include +#include + + +/* 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); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/hex.h b/Core/GmSSL-3.1.1/include/gmssl/hex.h new file mode 100644 index 0000000..9917618 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/hex.h @@ -0,0 +1,32 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_HEX_H +#define GMSSL_HEX_H + + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +int hex_to_bytes(const char *in, size_t inlen, uint8_t *out, size_t *outlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/hkdf.h b/Core/GmSSL-3.1.1/include/gmssl/hkdf.h new file mode 100644 index 0000000..bbefded --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/hkdf.h @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +// RFC 5869 + +#ifndef GMSSL_HKDF_H +#define GMSSL_HKDF_H + +#include +#include +#include + + +#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 *opt_info, size_t opt_infolen, + size_t L, uint8_t *okm); + +int sm3_hkdf_extract(const uint8_t *salt, size_t saltlen, + const uint8_t *ikm, size_t ikmlen, + uint8_t *prk, size_t *prklen); + +int sm3_hkdf_expand(const uint8_t *prk, size_t prklen, + const uint8_t *opt_info, size_t opt_infolen, + size_t L, uint8_t *okm); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/hmac.h b/Core/GmSSL-3.1.1/include/gmssl/hmac.h new file mode 100644 index 0000000..670586a --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/hmac.h @@ -0,0 +1,47 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_HMAC_H +#define GMSSL_HMAC_H + +#include +#include + + +#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 uint8_t *key, size_t keylen); +int hmac_update(HMAC_CTX *ctx, const uint8_t *data, size_t datalen); +int hmac_finish(HMAC_CTX *ctx, uint8_t *mac, size_t *maclen); + +int hmac(const DIGEST *md, const uint8_t *key, size_t keylen, + const uint8_t *data, size_t dlen, + uint8_t *mac, size_t *maclen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/http.h b/Core/GmSSL-3.1.1/include/gmssl/http.h new file mode 100644 index 0000000..cda8ad7 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/http.h @@ -0,0 +1,29 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_HTTP_H +#define GMSSL_HTTP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +int http_parse_uri(const char *uri, char host[128], int *port, char path[256]); +int http_parse_response(char *buf, size_t buflen, uint8_t **content, size_t *contentlen, size_t *left); +int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/md5.h b/Core/GmSSL-3.1.1/include/gmssl/md5.h new file mode 100644 index 0000000..dc4b91d --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/md5.h @@ -0,0 +1,48 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_MD5_H +#define GMSSL_MD5_H + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MD5_IS_BIG_ENDIAN 0 + +#define MD5_DIGEST_SIZE 16 +#define MD5_BLOCK_SIZE 64 +#define MD5_STATE_WORDS (MD5_BLOCK_SIZE/sizeof(uint32_t)) + +typedef struct { + uint32_t state[MD5_STATE_WORDS]; + uint64_t nblocks; + uint8_t block[MD5_BLOCK_SIZE]; + size_t num; +} 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_digest(const uint8_t *data, size_t datalen, uint8_t dgst[MD5_DIGEST_SIZE]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/mem.h b/Core/GmSSL-3.1.1/include/gmssl/mem.h new file mode 100644 index 0000000..9a57eb7 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/mem.h @@ -0,0 +1,27 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_MEM_H +#define GMSSL_MEM_H + +#include +#include // 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); + +int gmssl_secure_memcmp(const volatile void * volatile in_a, const volatile void * volatile in_b, size_t len); +void gmssl_secure_clear(void *ptr, size_t len); + +int mem_is_zero(const uint8_t *buf, size_t len); // FIXME: uint8_t * to void * + +#endif + diff --git a/Core/GmSSL-3.1.1/include/gmssl/oid.h b/Core/GmSSL-3.1.1/include/gmssl/oid.h new file mode 100644 index 0000000..f733676 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/oid.h @@ -0,0 +1,215 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_OID_H +#define GMSSL_OID_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + OID_undef = 0, + + // 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_ec_public_key, // X9.62 ecPublicKey + OID_prime192v1, + OID_prime256v1, + OID_secp256k1, + OID_secp192k1, + OID_secp224k1, + OID_secp224r1, + OID_secp384r1, + OID_secp521r1, + + OID_at_name, + OID_at_surname, + OID_at_given_name, + OID_at_initials, + OID_at_generation_qualifier, + OID_at_common_name, + OID_at_locality_name, + OID_at_state_or_province_name, + OID_at_organization_name, + OID_at_organizational_unit_name, + OID_at_title, + OID_at_dn_qualifier, + OID_at_country_name, + OID_at_serial_number, + OID_at_pseudonym, + OID_domain_component, + OID_email_address, + + // Cert Extensions + OID_ce_authority_key_identifier, + OID_ce_subject_key_identifier, + OID_ce_key_usage, + OID_ce_certificate_policies, + OID_ce_policy_mappings, + OID_ce_subject_alt_name, + OID_ce_issuer_alt_name, + OID_ce_subject_directory_attributes, + OID_ce_basic_constraints, + OID_ce_name_constraints, + OID_ce_policy_constraints, + OID_ce_ext_key_usage, + OID_ce_crl_distribution_points, + OID_ce_inhibit_any_policy, + OID_ce_freshest_crl, + OID_netscape_cert_type, + OID_netscape_cert_comment, + OID_ct_precertificate_scts, + + OID_ad_ca_issuers, + OID_ad_ocsp, + + // CRL Extensions + //OID_ce_authority_key_identifier, + //OID_ce_issuer_alt_name, + OID_ce_crl_number, + OID_ce_delta_crl_indicator, + OID_ce_issuing_distribution_point, + //OID_ce_freshest_crl, + OID_pe_authority_info_access, + + // CRL Entry Extensions + OID_ce_crl_reasons, + OID_ce_invalidity_date, + OID_ce_certificate_issuer, + + // X.509 KeyPropuseID + OID_any_extended_key_usage, + OID_kp_server_auth, + OID_kp_client_auth, + OID_kp_code_signing, + OID_kp_email_protection, + OID_kp_time_stamping, + OID_kp_ocsp_signing, + + OID_qt_cps, + OID_qt_unotice, + + OID_md5, + OID_sha1, + OID_sha224, + OID_sha256, + OID_sha384, + OID_sha512, + OID_sha512_224, + OID_sha512_256, + + + OID_hmac_sha1, + OID_hmac_sha224, + OID_hmac_sha256, + OID_hmac_sha384, + OID_hmac_sha512, + OID_hmac_sha512_224, + OID_hmac_sha512_256, + + OID_pbkdf2, // {pkcs-5 12} + OID_pbes2, // {pkcs-5 13} + + + + OID_sm4_ecb, // 1 2 156 10197 1 104 1 + OID_sm4_cbc, // 1 2 156 10197 1 104 2 + + OID_aes, + OID_aes128_cbc, + OID_aes192_cbc, + OID_aes256_cbc, + + OID_aes128, // 没有OID + + OID_ecdsa_with_sha1, + OID_ecdsa_with_sha224, + OID_ecdsa_with_sha256, + OID_ecdsa_with_sha384, + OID_ecdsa_with_sha512, + + OID_rsasign_with_md5, + OID_rsasign_with_sha1, + OID_rsasign_with_sha224, + OID_rsasign_with_sha256, + OID_rsasign_with_sha384, + OID_rsasign_with_sha512, + + OID_rsa_encryption, + OID_rsaes_oaep, + + OID_any_policy, + + OID_cms_data, + OID_cms_signed_data, + OID_cms_enveloped_data, + OID_cms_signed_and_enveloped_data, + OID_cms_encrypted_data, + OID_cms_key_agreement_info, +}; + +// {iso(1) org(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7)} +#define oid_pkix 1,3,6,1,5,5,7 + +#define oid_pe oid_pkix,1 +#define oid_qt oid_pkix,2 +#define oid_kp oid_pkix,3 +#define oid_ad oid_pkix,48 + +// {iso(1) member-body(2) us(840) rsadsi(113549)} +#define oid_rsadsi 1,2,840,113549 +#define oid_pkcs oid_rsadsi,1 +#define oid_pkcs5 oid_pkcs,5 + +// {iso(1) member-body(2) us(840) ansi-x962(10045)} +#define oid_x9_62 1,2,840,10045 + + + +#define oid_at 2,5,4 +#define oid_ce 2,5,29 + + +#define oid_sm 1,2,156,10197 +#define oid_sm_algors oid_sm,1 +#define oid_sm2_cms oid_sm,6,1,4,2 + + + + + +#define oid_cnt(nodes) (sizeof(nodes)/sizeof((nodes)[0])) + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/pbkdf2.h b/Core/GmSSL-3.1.1/include/gmssl/pbkdf2.h new file mode 100644 index 0000000..20aabb5 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/pbkdf2.h @@ -0,0 +1,54 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_PBKDF2_H +#define GMSSL_PBKDF2_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +PBKDF2 Public API + + PBKDF2_MIN_ITER + PBKDF2_DEFAULT_SALT_SIZE + PBKDF2_MAX_SALT_SIZE + + pbkdf2_hmac_sm3_genkey +*/ + + +#define PBKDF2_MIN_ITER 10000 +#define PBKDF2_MAX_ITER (INT_MAX) +#define PBKDF2_MAX_SALT_SIZE 64 +#define PBKDF2_DEFAULT_SALT_SIZE 8 + + +int pbkdf2_genkey(const DIGEST *digest, + const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, size_t iter, + size_t outlen, uint8_t *out); + +int pbkdf2_hmac_sm3_genkey( + const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, size_t iter, + size_t outlen, uint8_t *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/pem.h b/Core/GmSSL-3.1.1/include/gmssl/pem.h new file mode 100644 index 0000000..cdaaabb --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/pem.h @@ -0,0 +1,33 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_PEM_H +#define GMSSL_PEM_H + + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +int pem_read(FILE *fp, const char *name, uint8_t *out, size_t *outlen, size_t maxlen); +int pem_write(FILE *fp, const char *name, const uint8_t *in, size_t inlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/pkcs8.h b/Core/GmSSL-3.1.1/include/gmssl/pkcs8.h new file mode 100644 index 0000000..9233b5c --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/pkcs8.h @@ -0,0 +1,169 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +// RFC 5208: PKCS #8: Private-Key Information Syntax Specification version 1.2 + + +#ifndef GMSSL_PKCS8_H +#define GMSSL_PKCS8_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} + +PBKDF2-params ::= SEQUENCE { + salt CHOICE { + specified OCTET STRING, + otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} + }, + iterationCount INTEGER (1..MAX), + keyLength INTEGER (1..MAX) OPTIONAL, -- 这个参数可以由函数指定 + prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 +} + +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, int prf, + uint8_t **out, size_t *outlen); +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 pbkdf2_params_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +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 pbkdf2_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +/* +id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} + +PBES2-params ::= SEQUENCE { + keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, -- id-PBKDF2 + encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}} + +PBES2-Encs: + AES-CBC-Pad [RFC2898] + RC5-CBC-Pad + DES-CBC-Pad legacy + DES-EDE3-CBC-Pad legacy + RC2-CBC-Pad legacy +*/ + +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_enc_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +int pbes2_params_to_der( + const uint8_t *salt, size_t saltlen, + int iter, + int keylen, + 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 *keylen, + int *prf, + int *cipher, + const uint8_t **iv, size_t *ivlen, + const uint8_t **in, size_t *inlen); +int pbes2_params_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +int pbes2_algor_to_der( + const uint8_t *salt, size_t saltlen, + int iter, + int keylen, + 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 *keylen, + int *prf, + int *cipher, + const uint8_t **iv, size_t *ivlen, + const uint8_t **in, size_t *inlen); +int pbes2_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +from [RFC 5208] + +EncryptedPrivateKeyInfo ::= SEQUENCE { + encryptionAlgorithm EncryptionAlgorithmIdentifier, + encryptedData OCTET STRING } + +encryptionAlgorithm: + id-PBES2 + +PrivateKeyInfo ::= SEQUENCE { + version INTEGER { v1(0) }, + privateKeyAlgorithm AlgorithmIdentifier, + privateKey OCTET STRING, + attributes [0] Attributes OPTIONAL } +*/ + +int pkcs8_enced_private_key_info_to_der( + const uint8_t *salt, size_t saltlen, + int iter, + int keylen, + 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 *keylen, + 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 pkcs8_enced_private_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/rand.h b/Core/GmSSL-3.1.1/include/gmssl/rand.h new file mode 100644 index 0000000..86f5b05 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/rand.h @@ -0,0 +1,31 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_RAND_H +#define GMSSL_RAND_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define RAND_BYTES_MAX_SIZE (256) + +_gmssl_export int rand_bytes(uint8_t *buf, size_t buflen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/rc4.h b/Core/GmSSL-3.1.1/include/gmssl/rc4.h new file mode 100644 index 0000000..a6a523c --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/rc4.h @@ -0,0 +1,40 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_RC4_H +#define GMSSL_RC4_H + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define RC4_MIN_KEY_BITS 40 +#define RC4_STATE_NUM_WORDS 256 + + +typedef struct { + uint8_t d[RC4_STATE_NUM_WORDS]; +} RC4_STATE; + +void rc4_init(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 diff --git a/Core/GmSSL-3.1.1/include/gmssl/rdrand.h b/Core/GmSSL-3.1.1/include/gmssl/rdrand.h new file mode 100644 index 0000000..61e034a --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/rdrand.h @@ -0,0 +1,33 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_RDRAND_H +#define GMSSL_RDRAND_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +int rdrand_bytes(uint8_t *buf, size_t buflen); + +#ifdef INTEL_RDSEED +int rdseed_bytes(uint8_t *buf, size_t buflen); +#endif + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/rsa.h b/Core/GmSSL-3.1.1/include/gmssl/rsa.h new file mode 100644 index 0000000..4d170c4 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/rsa.h @@ -0,0 +1,56 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_RSA_H +#define GMSSL_RSA_H + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- n + publicExponent INTEGER -- e +} + +RSAPrivateKey ::= SEQUENCE { + version INTEGER, -- 0 + modulus INTEGER, -- n + publicExponent INTEGER, -- e + privateExponent INTEGER, -- d + prime1 INTEGER, -- p + prime2 INTEGER, -- q + exponent1 INTEGER, -- d mod (p-1) + exponent2 INTEGER, -- d mod (q-1) + coefficient INTEGER -- q^-1 mod p +} +*/ + + +int rsa_public_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sdf.h b/Core/GmSSL-3.1.1/include/gmssl/sdf.h new file mode 100644 index 0000000..77cf6a0 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sdf.h @@ -0,0 +1,69 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SDF_H +#define GMSSL_SDF_H + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* +SDF Public API + + sdf_load_library + sdf_unload_library + + SDF_DEVICE + sdf_open_device + sdf_close_device + sdf_print_device_info + sdf_rand_bytes + sdf_load_sign_key + + SDF_KEY + sdf_sign + sdf_release_key +*/ + +typedef struct { + void *handle; + char issuer[41]; + char name[17]; + char serial[17]; +} SDF_DEVICE; + +typedef struct { + SM2_KEY public_key; + void *session; + int index; +} SDF_KEY; + + +int sdf_load_library(const char *so_path, const char *vendor); +int sdf_open_device(SDF_DEVICE *dev); +int sdf_print_device_info(FILE *fp, int fmt, int ind, const char *lable, SDF_DEVICE *dev); +int sdf_rand_bytes(SDF_DEVICE *dev, uint8_t *buf, size_t len); +int sdf_load_sign_key(SDF_DEVICE *dev, SDF_KEY *key, int index, const char *pass); +int sdf_sign(SDF_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen); +int sdf_release_key(SDF_KEY *key); +int sdf_close_device(SDF_DEVICE *dev); +void sdf_unload_library(void); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sha1.h b/Core/GmSSL-3.1.1/include/gmssl/sha1.h new file mode 100644 index 0000000..38aef90 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sha1.h @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SHA1_H +#define GMSSL_SHA1_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SHA1_IS_BIG_ENDIAN 1 + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 +#define SHA1_STATE_WORDS (SHA1_DIGEST_SIZE/sizeof(uint32_t)) + + +typedef struct { + uint32_t state[SHA1_STATE_WORDS]; + uint64_t nblocks; + uint8_t block[SHA1_BLOCK_SIZE]; + size_t num; +} 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_SIZE]); +void sha1_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SHA1_DIGEST_SIZE]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sha2.h b/Core/GmSSL-3.1.1/include/gmssl/sha2.h new file mode 100644 index 0000000..744e7dc --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sha2.h @@ -0,0 +1,102 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_SHA2_H +#define GMSSL_SHA2_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SHA2_IS_BIG_ENDIAN 1 + + +#define SHA224_DIGEST_SIZE 28 +#define SHA224_BLOCK_SIZE 64 +#define SHA224_STATE_WORDS 8 + +typedef struct { + uint32_t state[SHA224_STATE_WORDS]; + uint64_t nblocks; + uint8_t block[SHA224_BLOCK_SIZE]; + size_t num; +} SHA224_CTX; + +void sha224_init(SHA224_CTX *ctx); +void sha224_update(SHA224_CTX *ctx, const uint8_t* data, size_t datalen); +void sha224_finish(SHA224_CTX *ctx, uint8_t dgst[SHA224_DIGEST_SIZE]); +void sha224_digest(const uint8_t *data, size_t datalen, + uint8_t dgst[SHA224_DIGEST_SIZE]); + + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 +#define SHA256_STATE_WORDS 8 + +typedef struct { + uint32_t state[SHA256_STATE_WORDS]; + uint64_t nblocks; + uint8_t block[SHA256_BLOCK_SIZE]; + size_t num; +} SHA256_CTX; + +void sha256_init(SHA256_CTX *ctx); +void sha256_update(SHA256_CTX *ctx, const uint8_t* data, size_t datalen); +void sha256_finish(SHA256_CTX *ctx, uint8_t dgst[SHA256_DIGEST_SIZE]); +void sha256_digest(const uint8_t *data, size_t datalen, + uint8_t dgst[SHA256_DIGEST_SIZE]); + + +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 +#define SHA384_STATE_WORDS 8 + +typedef struct { + uint64_t state[SHA384_STATE_WORDS]; + uint64_t nblocks; + uint8_t block[SHA384_BLOCK_SIZE]; + size_t num; +} SHA384_CTX; + +void sha384_init(SHA384_CTX *ctx); +void sha384_update(SHA384_CTX *ctx, const uint8_t* data, size_t datalen); +void sha384_finish(SHA384_CTX *ctx, uint8_t dgst[SHA384_DIGEST_SIZE]); +void sha384_digest(const uint8_t *data, size_t datalen, + uint8_t dgst[SHA384_DIGEST_SIZE]); + + +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 +#define SHA512_STATE_WORDS 8 + +typedef struct { + uint64_t state[SHA512_STATE_WORDS]; + uint64_t nblocks; + uint8_t block[SHA512_BLOCK_SIZE]; + size_t num; +} SHA512_CTX; + +void sha512_init(SHA512_CTX *ctx); +void sha512_update(SHA512_CTX *ctx, const uint8_t* data, size_t datalen); +void sha512_finish(SHA512_CTX *ctx, uint8_t dgst[SHA512_DIGEST_SIZE]); +void sha512_digest(const uint8_t *data, size_t datalen, + uint8_t dgst[SHA512_DIGEST_SIZE]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sha3.h b/Core/GmSSL-3.1.1/include/gmssl/sha3.h new file mode 100644 index 0000000..cb546cc --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sha3.h @@ -0,0 +1,92 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_SHA3_H +#define GMSSL_SHA3_H + + +#include +#include +#include + + +#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 diff --git a/Core/GmSSL-3.1.1/include/gmssl/skf.h b/Core/GmSSL-3.1.1/include/gmssl/skf.h new file mode 100644 index 0000000..2f23de8 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/skf.h @@ -0,0 +1,116 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SKF_H +#define GMSSL_SKF_H + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +SKF Public API + + skf_load_library + skf_unload_library + skf_list_devices + skf_print_device_info + + SKF_DEVICE + skf_open_device + skf_close_deivce + skf_set_label + skf_change_authkey + skf_list_apps + skf_create_app + skf_delete_app + skf_change_app_admin_pin + skf_change_app_user_pin + skf_unblock_user_pin + skf_list_objects + skf_import_object + skf_export_object + skf_delete_object + skf_list_containers + skf_create_container + skf_delete_container + skf_import_sign_cert + skf_export_sign_cert + skf_rand_bytes + skf_load_sign_key + + SKF_KEY + skf_sign + skf_release_key +*/ + +typedef struct { + void *handle; + char manufacturer[65]; + char issuer[65]; + char label[33]; + char serial[33]; + uint8_t hardware_version[2]; + uint8_t firmware_version[2]; +} SKF_DEVICE; + +typedef struct { + SM2_KEY public_key; + void *app_handle; + char app_name[65]; + void *container_handle; + char container_name[65]; +} SKF_KEY; + +int skf_load_library(const char *so_path, const char *vendor); +void skf_unload_library(void); + +int skf_list_devices(FILE *fp, int fmt, int ind, const char *label); +int skf_print_device_info(FILE *fp, int fmt, int ind, const char *devname); +int skf_open_device(SKF_DEVICE *dev, const char *devname, const uint8_t authkey[16]); +int skf_set_label(SKF_DEVICE *dev, const char *label); +int skf_change_authkey(SKF_DEVICE *dev, const uint8_t authkey[16]); +int skf_close_device(SKF_DEVICE *dev); + +int skf_list_apps(SKF_DEVICE *dev, int fmt, int ind, const char *label, FILE *fp); +int skf_create_app(SKF_DEVICE *dev, const char *appname, const char *admin_pin, const char *user_pin); +int skf_delete_app(SKF_DEVICE *dev, const char *appname); +int skf_change_app_admin_pin(SKF_DEVICE *dev, const char *appname, const char *oid_pin, const char *new_pin); +int skf_change_app_user_pin(SKF_DEVICE *dev, const char *appname, const char *oid_pin, const char *new_pin); +int skf_unblock_user_pin(SKF_DEVICE *dev, const char *appname, const char *admin_pin, const char *new_user_pin); + +int skf_list_objects(FILE *fp, int fmt, int ind, const char *label, SKF_DEVICE *dev, const char *appname, const char *pin); +int skf_import_object(SKF_DEVICE *dev, const char *appname, const char *pin, const char *objname, const uint8_t *data, size_t datalen); +int skf_export_object(SKF_DEVICE *dev, const char *appname, const char *pin, const char *objname, uint8_t *out, size_t *outlen); +int skf_delete_object(SKF_DEVICE *dev, const char *appname, const char *pin, const char *objname); + +int skf_list_containers(FILE *fp, int fmt, int ind, const char *label, SKF_DEVICE *dev, const char *appname, const char *pin); +int skf_create_container(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name); +int skf_delete_container(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name); +int skf_import_sign_cert(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name, const uint8_t *cert, size_t certlen); +int skf_export_sign_cert(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name, uint8_t *cert, size_t *certlen); + +int skf_rand_bytes(SKF_DEVICE *dev, uint8_t *buf, size_t len); +int skf_load_sign_key(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name, SKF_KEY *key); +int skf_sign(SKF_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen); +int skf_release_key(SKF_KEY *key); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm2.h b/Core/GmSSL-3.1.1/include/gmssl/sm2.h new file mode 100644 index 0000000..1d39fde --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm2.h @@ -0,0 +1,382 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_SM2_H +#define GMSSL_SM2_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +SM2 Public API + + SM2_DEFAULT_ID + SM2_MAX_ID_LENGTH + SM2_MAX_SIGNATURE_SIZE + SM2_MAX_PLAINTEXT_SIZE + SM2_MAX_CIPHERTEXT_SIZE + + SM2_KEY + sm2_key_generate + sm2_private_key_info_encrypt_to_der + sm2_private_key_info_decrypt_from_der + sm2_private_key_info_encrypt_to_pem + sm2_private_key_info_decrypt_from_pem + sm2_public_key_info_to_der + sm2_public_key_info_from_der + sm2_public_key_info_to_pem + sm2_public_key_info_from_pem + + sm2_sign + sm2_verify + sm2_encrypt + sm2_decrypt + sm2_ecdh + + SM2_SIGN_CTX + sm2_sign_init + sm2_sign_update + sm2_sign_finish + sm2_verify_init + sm2_verify_update + sm2_verify_finish +*/ + +typedef uint64_t SM2_BN[8]; + +int sm2_bn_is_zero(const SM2_BN a); +int sm2_bn_is_one(const SM2_BN a); +int sm2_bn_is_odd(const SM2_BN a); +int sm2_bn_cmp(const SM2_BN a, const SM2_BN b); +int sm2_bn_from_hex(SM2_BN r, const char hex[64]); +int sm2_bn_from_asn1_integer(SM2_BN r, const uint8_t *d, size_t dlen); +int sm2_bn_equ_hex(const SM2_BN a, const char *hex); +int sm2_bn_print(FILE *fp, int fmt, int ind, const char *label, const SM2_BN a); +int sm2_bn_rshift(SM2_BN ret, const SM2_BN a, unsigned int nbits); + +void sm2_bn_to_bytes(const SM2_BN a, uint8_t out[32]); +void sm2_bn_from_bytes(SM2_BN r, const uint8_t in[32]); +void sm2_bn_to_hex(const SM2_BN a, char hex[64]); +void sm2_bn_to_bits(const SM2_BN a, char bits[256]); +void sm2_bn_set_word(SM2_BN r, uint32_t a); +void sm2_bn_add(SM2_BN r, const SM2_BN a, const SM2_BN b); +void sm2_bn_sub(SM2_BN ret, const SM2_BN a, const SM2_BN b); +int sm2_bn_rand_range(SM2_BN r, const SM2_BN range); + +#define sm2_bn_init(r) memset((r),0,sizeof(SM2_BN)) +#define sm2_bn_set_zero(r) memset((r),0,sizeof(SM2_BN)) +#define sm2_bn_set_one(r) sm2_bn_set_word((r),1) +#define sm2_bn_copy(r,a) memcpy((r),(a),sizeof(SM2_BN)) +#define sm2_bn_clean(r) memset((r),0,sizeof(SM2_BN)) + + +// GF(p) +typedef SM2_BN SM2_Fp; + +void sm2_fp_add(SM2_Fp r, const SM2_Fp a, const SM2_Fp b); +void sm2_fp_sub(SM2_Fp r, const SM2_Fp a, const SM2_Fp b); +void sm2_fp_mul(SM2_Fp r, const SM2_Fp a, const SM2_Fp b); +void sm2_fp_exp(SM2_Fp r, const SM2_Fp a, const SM2_Fp e); +void sm2_fp_dbl(SM2_Fp r, const SM2_Fp a); +void sm2_fp_tri(SM2_Fp r, const SM2_Fp a); +void sm2_fp_div2(SM2_Fp r, const SM2_Fp a); +void sm2_fp_neg(SM2_Fp r, const SM2_Fp a); +void sm2_fp_sqr(SM2_Fp r, const SM2_Fp a); +void sm2_fp_inv(SM2_Fp r, const SM2_Fp a); +int sm2_fp_rand(SM2_Fp r); + +int sm2_fp_sqrt(SM2_Fp r, const SM2_Fp a); + +#define sm2_fp_init(r) sm2_bn_init(r) +#define sm2_fp_set_zero(r) sm2_bn_set_zero(r) +#define sm2_fp_set_one(r) sm2_bn_set_one(r) +#define sm2_fp_copy(r,a) sm2_bn_copy(r,a) +#define sm2_fp_clean(r) sm2_bn_clean(r) + +// GF(n) +typedef SM2_BN SM2_Fn; + +void sm2_fn_add(SM2_Fn r, const SM2_Fn a, const SM2_Fn b); +void sm2_fn_sub(SM2_Fn r, const SM2_Fn a, const SM2_Fn b); +void sm2_fn_mul(SM2_Fn r, const SM2_Fn a, const SM2_Fn b); +void sm2_fn_mul_word(SM2_Fn r, const SM2_Fn a, uint32_t b); +void sm2_fn_exp(SM2_Fn r, const SM2_Fn a, const SM2_Fn e); +void sm2_fn_neg(SM2_Fn r, const SM2_Fn a); +void sm2_fn_sqr(SM2_Fn r, const SM2_Fn a); +void sm2_fn_inv(SM2_Fn r, const SM2_Fn a); +int sm2_fn_rand(SM2_Fn r); + +#define sm2_fn_init(r) sm2_bn_init(r) +#define sm2_fn_set_zero(r) sm2_bn_set_zero(r) +#define sm2_fn_set_one(r) sm2_bn_set_one(r) +#define sm2_fn_copy(r,a) sm2_bn_copy(r,a) +#define sm2_fn_clean(r) sm2_bn_clean(r) + + +typedef struct { + SM2_BN X; + SM2_BN Y; + SM2_BN Z; +} SM2_JACOBIAN_POINT; + +void sm2_jacobian_point_init(SM2_JACOBIAN_POINT *R); +void sm2_jacobian_point_set_xy(SM2_JACOBIAN_POINT *R, const SM2_BN x, const SM2_BN y); +void sm2_jacobian_point_get_xy(const SM2_JACOBIAN_POINT *P, SM2_BN x, SM2_BN y); +void sm2_jacobian_point_neg(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P); +void sm2_jacobian_point_dbl(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P); +void sm2_jacobian_point_add(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P, const SM2_JACOBIAN_POINT *Q); +void sm2_jacobian_point_sub(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P, const SM2_JACOBIAN_POINT *Q); +void sm2_jacobian_point_mul(SM2_JACOBIAN_POINT *R, const SM2_BN k, const SM2_JACOBIAN_POINT *P); +void sm2_jacobian_point_to_bytes(const SM2_JACOBIAN_POINT *P, uint8_t out[64]); +void sm2_jacobian_point_from_bytes(SM2_JACOBIAN_POINT *P, const uint8_t in[64]); +void sm2_jacobian_point_mul_generator(SM2_JACOBIAN_POINT *R, const SM2_BN k); +void sm2_jacobian_point_mul_sum(SM2_JACOBIAN_POINT *R, const SM2_BN t, const SM2_JACOBIAN_POINT *P, const SM2_BN s); +void sm2_jacobian_point_from_hex(SM2_JACOBIAN_POINT *P, const char hex[64 * 2]); // for testing only + +int sm2_jacobian_point_is_at_infinity(const SM2_JACOBIAN_POINT *P); +int sm2_jacobian_point_is_on_curve(const SM2_JACOBIAN_POINT *P); +int sm2_jacobian_point_equ_hex(const SM2_JACOBIAN_POINT *P, const char hex[128]); // for testing only +int sm2_jacobian_point_print(FILE *fp, int fmt, int ind, const char *label, const SM2_JACOBIAN_POINT *P); + +#define sm2_jacobian_point_set_infinity(R) sm2_jacobian_point_init(R) +#define sm2_jacobian_point_copy(R, P) memcpy((R), (P), sizeof(SM2_JACOBIAN_POINT)) + +typedef uint8_t sm2_bn_t[32]; + +typedef struct { + uint8_t x[32]; + uint8_t y[32]; +} SM2_POINT; + +#define sm2_point_init(P) memset((P),0,sizeof(SM2_POINT)) +#define sm2_point_set_infinity(P) sm2_point_init(P) +int sm2_point_from_octets(SM2_POINT *P, const uint8_t *in, size_t inlen); +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_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_is_at_infinity(const SM2_POINT *P); +int sm2_point_add(SM2_POINT *R, const SM2_POINT *P, const SM2_POINT *Q); +int sm2_point_sub(SM2_POINT *R, const SM2_POINT *P, const SM2_POINT *Q); +int sm2_point_neg(SM2_POINT *R, const SM2_POINT *P); +int sm2_point_dbl(SM2_POINT *R, 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]); // R = k * P + s * G + +/* +RFC 5480 Elliptic Curve Cryptography Subject Public Key Information +ECPoint ::= OCTET STRING +*/ +#define SM2_POINT_MAX_SIZE (2 + 65) +int sm2_point_to_der(const SM2_POINT *P, uint8_t **out, size_t *outlen); +int sm2_point_from_der(SM2_POINT *P, const uint8_t **in, size_t *inlen); +int sm2_point_print(FILE *fp, int fmt, int ind, const char *label, const SM2_POINT *P); +int sm2_point_from_hash(SM2_POINT *R, const uint8_t *data, size_t datalen); + + +typedef struct { + SM2_POINT public_key; + uint8_t private_key[32]; +} SM2_KEY; + + +_gmssl_export int sm2_key_generate(SM2_KEY *key); +int sm2_key_set_private_key(SM2_KEY *key, const uint8_t private_key[32]); // key->public_key will be replaced +int sm2_key_set_public_key(SM2_KEY *key, const SM2_POINT *public_key); // key->private_key will be cleared // FIXME: support octets as input? +int sm2_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *key); + +int sm2_public_key_equ(const SM2_KEY *sm2_key, const SM2_KEY *pub_key); +//int sm2_public_key_copy(SM2_KEY *sm2_key, const SM2_KEY *pub_key); // do we need this? +int sm2_public_key_digest(const SM2_KEY *key, uint8_t dgst[32]); +int sm2_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *pub_key); + +/* +from RFC 5915 + +ECPrivateKey ::= SEQUENCE { + version INTEGER, -- value MUST be (1) + privateKey OCTET STRING, -- big endian encoding of integer 这里不是以INTEGER编码的,因此长度固定 + parameters [0] EXPLICIT ECParameters OPTIONAL, + -- ONLY namedCurve OID is permitted, by RFC 5480 + -- MUST always include this field, by RFC 5915 + publicKey [1] EXPLICIT BIT STRING OPTIONAL -- compressed_point + -- SHOULD always include this field, by RFC 5915 } + +ECParameters ::= CHOICE { namedCurve OBJECT IDENTIFIER } +*/ +#define SM2_PRIVATE_KEY_DEFAULT_SIZE 120 // generated +#define SM2_PRIVATE_KEY_BUF_SIZE 512 // MUST >= SM2_PRIVATE_KEY_DEFAULT_SIZE + +int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen); +int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen); +int sm2_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +int sm2_private_key_to_pem(const SM2_KEY *key, FILE *fp); +int sm2_private_key_from_pem(SM2_KEY *key, FILE *fp); + +/* +AlgorithmIdentifier ::= { + algorithm OBJECT IDENTIFIER { id-ecPublicKey }, + parameters OBJECT IDENTIFIER { id-sm2 } } +*/ +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); + +/* +SubjectPublicKeyInfo from RFC 5280 + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING -- uncompressed octets of ECPoint } +*/ +_gmssl_export int sm2_public_key_info_to_der(const SM2_KEY *a, uint8_t **out, size_t *outlen); +_gmssl_export int sm2_public_key_info_from_der(SM2_KEY *a, const uint8_t **in, size_t *inlen); +_gmssl_export int sm2_public_key_info_to_pem(const SM2_KEY *a, FILE *fp); +_gmssl_export int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp); + +/* +PKCS #8 PrivateKeyInfo 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 } +*/ +enum { + PKCS8_private_key_info_version = 0, +}; + + +int sm2_private_key_info_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen); +int sm2_private_key_info_from_der(SM2_KEY *key, const uint8_t **attrs, size_t *attrslen, const uint8_t **in, size_t *inlen); +int sm2_private_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +int sm2_private_key_info_to_pem(const SM2_KEY *key, FILE *fp); +// FIXME: #define default buffer size for sm2_private_key_info_from_pem +int sm2_private_key_info_from_pem(SM2_KEY *key, FILE *fp); + +/* +EncryptedPrivateKeyInfo ::= SEQUENCE { + encryptionAlgorithm EncryptionAlgorithmIdentifier, -- id-PBES2 + encryptedData OCTET STRING } +*/ +_gmssl_export int sm2_private_key_info_encrypt_to_der(const SM2_KEY *key, + const char *pass, uint8_t **out, size_t *outlen); +_gmssl_export int sm2_private_key_info_decrypt_from_der(SM2_KEY *key, const uint8_t **attrs, size_t *attrs_len, + const char *pass, const uint8_t **in, size_t *inlen); +_gmssl_export int sm2_private_key_info_encrypt_to_pem(const SM2_KEY *key, const char *pass, FILE *fp); +// FIXME: #define default buffer size +_gmssl_export int sm2_private_key_info_decrypt_from_pem(SM2_KEY *key, const char *pass, FILE *fp); + + +typedef struct { + uint8_t r[32]; + uint8_t s[32]; +} SM2_SIGNATURE; + +int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig); +int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig); +int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig); + + +#define SM2_MIN_SIGNATURE_SIZE 8 +#define SM2_MAX_SIGNATURE_SIZE 72 +int sm2_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_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen); +_gmssl_export int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen); +_gmssl_export int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *sig, size_t siglen); + +enum { + SM2_signature_compact_size = 70, + SM2_signature_typical_size = 71, + SM2_signature_max_size = 72, +}; +int sm2_sign_fixlen(const SM2_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig); + +#define SM2_DEFAULT_ID "1234567812345678" +#define SM2_DEFAULT_ID_LENGTH (sizeof(SM2_DEFAULT_ID) - 1) // LENGTH for string and SIZE for bytes +#define SM2_DEFAULT_ID_BITS (SM2_DEFAULT_ID_LENGTH * 8) +#define SM2_MAX_ID_BITS 65535 +#define SM2_MAX_ID_LENGTH (SM2_MAX_ID_BITS/8) + +int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id, size_t idlen); + + +typedef struct { + SM3_CTX sm3_ctx; + SM2_KEY key; +} SM2_SIGN_CTX; + +_gmssl_export int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen); +_gmssl_export int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +_gmssl_export int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); +int sm2_sign_finish_fixlen(SM2_SIGN_CTX *ctx, size_t siglen, uint8_t *sig); + +_gmssl_export int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen); +_gmssl_export int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +_gmssl_export int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen); + +/* +SM2Cipher ::= SEQUENCE { + XCoordinate INTEGER, + YCoordinate INTEGER, + HASH OCTET STRING SIZE(32), + CipherText OCTET STRING } +*/ +#define SM2_MIN_PLAINTEXT_SIZE 1 // re-compute SM2_MIN_CIPHERTEXT_SIZE when modify +#define SM2_MAX_PLAINTEXT_SIZE 255 // re-compute SM2_MAX_CIPHERTEXT_SIZE when modify + +typedef struct { + SM2_POINT point; + uint8_t hash[32]; + uint8_t ciphertext_size; + uint8_t ciphertext[SM2_MAX_PLAINTEXT_SIZE]; +} SM2_CIPHERTEXT; + +int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out); +int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen); + +#define SM2_MIN_CIPHERTEXT_SIZE 45 // depends on SM2_MIN_PLAINTEXT_SIZE +#define SM2_MAX_CIPHERTEXT_SIZE 366 // depends on SM2_MAX_PLAINTEXT_SIZE +int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen); +int sm2_ciphertext_from_der(SM2_CIPHERTEXT *c, const uint8_t **in, size_t *inlen); +int sm2_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen); +_gmssl_export int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); + +enum { + SM2_ciphertext_compact_point_size = 68, + SM2_ciphertext_typical_point_size = 69, + SM2_ciphertext_max_point_size = 70, +}; +int sm2_do_encrypt_fixlen(const SM2_KEY *key, const uint8_t *in, size_t inlen, int point_size, SM2_CIPHERTEXT *out); +int sm2_encrypt_fixlen(const SM2_KEY *key, const uint8_t *in, size_t inlen, int point_size, uint8_t *out, size_t *outlen); + + +int sm2_do_ecdh(const SM2_KEY *key, const SM2_POINT *peer_public, SM2_POINT *out); +_gmssl_export int sm2_ecdh(const SM2_KEY *key, const uint8_t *peer_public, size_t peer_public_len, SM2_POINT *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm2_blind.h b/Core/GmSSL-3.1.1/include/gmssl/sm2_blind.h new file mode 100644 index 0000000..db34aff --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm2_blind.h @@ -0,0 +1,49 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +#ifndef GMSSL_SM2_BLIND_H +#define GMSSL_SM2_BLIND_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + SM3_CTX sm3_ctx; + SM2_KEY public_key; + uint8_t blind_factor_a[32]; + uint8_t blind_factor_b[32]; + uint8_t sig_r[32]; +} SM2_BLIND_SIGN_CTX; + + +#define SM2_BLIND_SIGN_MAX_COMMITLEN 65 + +int sm2_blind_sign_commit(SM2_Fn k, uint8_t *commit, size_t *commitlen); +int sm2_blind_sign_init(SM2_BLIND_SIGN_CTX *ctx, const SM2_KEY *public_key, const char *id, size_t idlen); +int sm2_blind_sign_update(SM2_BLIND_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int sm2_blind_sign_finish(SM2_BLIND_SIGN_CTX *ctx, const uint8_t *commit, size_t commitlen, uint8_t blinded_sig_r[32]); +int sm2_blind_sign(const SM2_KEY *key, const SM2_Fn k, const uint8_t blinded_sig_r[32], uint8_t blinded_sig_s[32]); +int sm2_blind_sign_unblind(SM2_BLIND_SIGN_CTX *ctx, const uint8_t blinded_sig_s[32], uint8_t *sig, size_t *siglen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm2_commit.h b/Core/GmSSL-3.1.1/include/gmssl/sm2_commit.h new file mode 100644 index 0000000..6df8958 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm2_commit.h @@ -0,0 +1,40 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +#ifndef GMSSL_SM2_COMMIT_H +#define GMSSL_SM2_COMMIT_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +int sm2_commit_generate(const uint8_t x[32], uint8_t r[32], uint8_t commit[65], size_t *commitlen); +int sm2_commit_open(const uint8_t x[32], const uint8_t r[32], const uint8_t *commit, size_t commitlen); +int sm2_commit_vector_generate(const sm2_bn_t *x, size_t count, uint8_t r[32], uint8_t commit[65], size_t *commitlen); +int sm2_commit_vector_open(const sm2_bn_t *x, size_t count, const uint8_t r[32], const uint8_t *commit, size_t commitlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm2_elgamal.h b/Core/GmSSL-3.1.1/include/gmssl/sm2_elgamal.h new file mode 100644 index 0000000..e9ee7a9 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm2_elgamal.h @@ -0,0 +1,67 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_SM2_ELGAMAL_H +#define GMSSL_SM2_ELGAMAL_H + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SM2_PRE_COMPUTE_MAX_OFFSETS 6 + +typedef struct { + uint16_t offset[SM2_PRE_COMPUTE_MAX_OFFSETS]; + uint8_t offset_count; + uint8_t x_coordinate[32]; +} SM2_PRE_COMPUTE; + +int sm2_elgamal_decrypt_pre_compute(SM2_PRE_COMPUTE table[1<<16]); +int sm2_elgamal_solve_ecdlp(const SM2_PRE_COMPUTE table[1<<16], const SM2_POINT *point, uint32_t *private); + + +typedef struct { + SM2_POINT C1; + SM2_POINT C2; +} SM2_ELGAMAL_CIPHERTEXT; + +int sm2_elgamal_do_encrypt(const SM2_KEY *pub_key, uint32_t in, SM2_ELGAMAL_CIPHERTEXT *out); +int sm2_elgamal_do_decrypt(const SM2_KEY *key, const SM2_ELGAMAL_CIPHERTEXT *in, uint32_t *out); + +int sm2_elgamal_ciphertext_add(SM2_ELGAMAL_CIPHERTEXT *r, + const SM2_ELGAMAL_CIPHERTEXT *a, + const SM2_ELGAMAL_CIPHERTEXT *b, + const SM2_KEY *pub_key); +int sm2_elgamal_cipehrtext_sub(SM2_ELGAMAL_CIPHERTEXT *r, + const SM2_ELGAMAL_CIPHERTEXT *a, const SM2_ELGAMAL_CIPHERTEXT *b, + const SM2_KEY *pub_key); +int sm2_elgamal_cipehrtext_neg(SM2_ELGAMAL_CIPHERTEXT *r, + const SM2_ELGAMAL_CIPHERTEXT *a, const SM2_KEY *pub_key); +int sm2_elgamal_ciphertext_scalar_mul(SM2_ELGAMAL_CIPHERTEXT *R, + const uint8_t scalar[32], const SM2_ELGAMAL_CIPHERTEXT *A, + const SM2_KEY *pub_key); + +int sm2_elgamal_ciphertext_to_der(const SM2_ELGAMAL_CIPHERTEXT *c, uint8_t **out, size_t *outlen); +int sm2_elgamal_ciphertext_from_der(SM2_ELGAMAL_CIPHERTEXT *c, const uint8_t **in, size_t *inlen); + +int sm2_elgamal_encrypt(const SM2_KEY *pub_key, uint32_t in, uint8_t *out, size_t *outlen); +int sm2_elgamal_decrypt(SM2_KEY *key, const uint8_t *in, size_t inlen, uint32_t *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm2_key_share.h b/Core/GmSSL-3.1.1/include/gmssl/sm2_key_share.h new file mode 100644 index 0000000..7288d32 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm2_key_share.h @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +// SM2 Key Shamir Secret Sharing + + +#ifndef GMSSL_SM2_KEY_SHARE_H +#define GMSSL_SM2_KEY_SHARE_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SM2_KEY_MAX_SHARES 12 // 12! = 479001600 < 2^31 = 2147483648 + + +typedef struct { + SM2_KEY key; + size_t index; + size_t total_cnt; +} SM2_KEY_SHARE; + +int sm2_key_split(const SM2_KEY *key, size_t recover_cnt, size_t total_cnt, SM2_KEY_SHARE *shares); +int sm2_key_recover(SM2_KEY *key, const SM2_KEY_SHARE *shares, size_t shares_cnt); +int sm2_key_share_encrypt_to_file(const SM2_KEY_SHARE *share, const char *pass, const char *path_prefix); +int sm2_key_share_decrypt_from_file(SM2_KEY_SHARE *share, const char *pass, const char *file); +int sm2_key_share_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY_SHARE *share); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm2_recover.h b/Core/GmSSL-3.1.1/include/gmssl/sm2_recover.h new file mode 100644 index 0000000..92d2c01 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm2_recover.h @@ -0,0 +1,31 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_SM2_RECOVER_H +#define GMSSL_SM2_RECOVER_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int sm2_signature_to_public_key_points(const SM2_SIGNATURE *sig, const uint8_t dgst[32], + SM2_POINT points[4], size_t *points_cnt); +int sm2_signature_conjugate(const SM2_SIGNATURE *sig, SM2_SIGNATURE *new_sig); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm2_ring.h b/Core/GmSSL-3.1.1/include/gmssl/sm2_ring.h new file mode 100644 index 0000000..6ce4e49 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm2_ring.h @@ -0,0 +1,63 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_SM2_RING_H +#define GMSSL_SM2_RING_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef uint8_t sm2_bn_t[32]; + +int sm2_ring_do_sign(const SM2_KEY *sign_key, const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], uint8_t r[32], sm2_bn_t *s); +int sm2_ring_do_verify(const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], const uint8_t r[32], const sm2_bn_t *s); +int sm2_ring_signature_to_der(const sm2_bn_t r, const sm2_bn_t *s, size_t s_cnt, uint8_t **out, size_t *outlen); +int sm2_ring_signature_from_der(sm2_bn_t r, sm2_bn_t *s, size_t *s_cnt, const uint8_t **in, size_t *inlen); +int sm2_ring_sign(const SM2_KEY *sign_key, const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], uint8_t *sig, size_t *siglen); +int sm2_ring_verify(const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], const uint8_t *sig, size_t siglen); + + +#define SM2_RING_SIGN_MAX_SIGNERS 32 +typedef struct { + int state; + SM3_CTX sm3_ctx; + SM2_KEY sign_key; + SM2_POINT public_keys[SM2_RING_SIGN_MAX_SIGNERS]; + size_t public_keys_count; + char *id; + size_t idlen; +} SM2_RING_SIGN_CTX; + +int sm2_ring_sign_init(SM2_RING_SIGN_CTX *ctx, const SM2_KEY *sign_key, const char *id, size_t idlen); +int sm2_ring_sign_add_signer(SM2_RING_SIGN_CTX *ctx, const SM2_KEY *public_key); +int sm2_ring_sign_update(SM2_RING_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int sm2_ring_sign_finish(SM2_RING_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); +int sm2_ring_verify_init(SM2_RING_SIGN_CTX *ctx, const char *id, size_t idlen); +int sm2_ring_verify_add_signer(SM2_RING_SIGN_CTX *ctx, const SM2_KEY *public_key); +int sm2_ring_verify_update(SM2_RING_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int sm2_ring_verify_finish(SM2_RING_SIGN_CTX *ctx, uint8_t *sig, size_t siglen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm3.h b/Core/GmSSL-3.1.1/include/gmssl/sm3.h new file mode 100644 index 0000000..ba02da8 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm3.h @@ -0,0 +1,89 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SM3_H +#define GMSSL_SM3_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +SM3 Public API + + SM3_DIGEST_SIZE + SM3_HMAC_SIZE + + SM3_CTX + sm3_init + sm3_update + sm3_finish + + SM3_HMAC_CTX + sm3_hmac_init + sm3_hmac_update + sm3_hmac_finish + + sm3_digest + sm3_hmac +*/ + +#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) + + +typedef struct { + uint32_t digest[SM3_STATE_WORDS]; + uint64_t nblocks; + uint8_t block[SM3_BLOCK_SIZE]; + size_t 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_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SM3_DIGEST_SIZE]); + +void sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks); + +typedef struct { + SM3_CTX sm3_ctx; + uint8_t 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(const uint8_t *key, size_t keylen, + const uint8_t *data, size_t datalen, + uint8_t mac[SM3_HMAC_SIZE]); + + +typedef struct { + SM3_CTX sm3_ctx; + size_t outlen; +} SM3_KDF_CTX; + +void sm3_kdf_init(SM3_KDF_CTX *ctx, size_t outlen); +void sm3_kdf_update(SM3_KDF_CTX *ctx, const uint8_t *data, size_t datalen); +void sm3_kdf_finish(SM3_KDF_CTX *ctx, uint8_t *out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm3_rng.h b/Core/GmSSL-3.1.1/include/gmssl/sm3_rng.h new file mode 100644 index 0000000..418ddf3 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm3_rng.h @@ -0,0 +1,42 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_SM3_RNG_H +#define GMSSL_SM3_RNG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SM3_RNG_MAX_RESEED_COUNTER (1<<20) +#define SM3_RNG_MAX_RESEED_SECONDS 600 + + +typedef struct { + uint8_t V[55]; + uint8_t C[55]; + uint32_t reseed_counter; + time_t last_reseed_time; +} SM3_RNG; + +int sm3_rng_init(SM3_RNG *rng, const uint8_t *nonce, size_t nonce_len, + const uint8_t *label, size_t label_len); +int sm3_rng_reseed(SM3_RNG *rng, const uint8_t *addin, size_t addin_len); +int sm3_rng_generate(SM3_RNG *rng, const uint8_t *addin, size_t addin_len, + uint8_t *out, size_t outlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm3_x8_avx2.h b/Core/GmSSL-3.1.1/include/gmssl/sm3_x8_avx2.h new file mode 100644 index 0000000..f3674c2 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm3_x8_avx2.h @@ -0,0 +1,33 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_SM3_X8_AVX2_H +#define GMSSL_SM3_X8_AVX2_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + __m256i digest[8]; +} SM3_X8_CTX; + +void sm3_x8_init(SM3_X8_CTX *ctx); +void sm3_x8_compress_blocks(__m256i digest[8], const uint8_t *data, size_t datalen); +void sm3_x8_digest(const uint8_t *data, size_t datalen, uint8_t dgst[8][32]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm4.h b/Core/GmSSL-3.1.1/include/gmssl/sm4.h new file mode 100644 index 0000000..d4c4678 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm4.h @@ -0,0 +1,142 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SM4_H +#define GMSSL_SM4_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +SM4 Public API + + SM4_KEY_SIZE + SM4_BLOCK_SIZE + + SM4_CBC_CTX + sm4_cbc_encrypt_init + sm4_cbc_encrypt_update + sm4_cbc_encrypt_finish + sm4_cbc_decrypt_init + sm4_cbc_decrypt_update + sm4_cbc_decrypt_finish + + SM4_CTR_CTX + sm4_ctr_encrypt_init + sm4_ctr_encrypt_update + sm4_ctr_encrypt_finish + sm4_ctr_decrypt_init + sm4_ctr_decrypt_update + sm4_ctr_decrypt_finish +*/ + +#define SM4_KEY_SIZE (16) +#define SM4_BLOCK_SIZE (16) +#define SM4_NUM_ROUNDS (32) + + +typedef struct { + uint32_t rk[SM4_NUM_ROUNDS]; +} SM4_KEY; + +void sm4_set_encrypt_key(SM4_KEY *key, const uint8_t raw_key[SM4_KEY_SIZE]); +void sm4_set_decrypt_key(SM4_KEY *key, const uint8_t raw_key[SM4_KEY_SIZE]); +void sm4_encrypt(const SM4_KEY *key, const uint8_t in[SM4_BLOCK_SIZE], uint8_t out[SM4_BLOCK_SIZE]); +#define sm4_decrypt(key,in,out) sm4_encrypt(key,in,out) + + +void sm4_cbc_encrypt(const SM4_KEY *key, const uint8_t iv[SM4_BLOCK_SIZE], + const uint8_t *in, size_t nblocks, uint8_t *out); +void sm4_cbc_decrypt(const SM4_KEY *key, const uint8_t iv[SM4_BLOCK_SIZE], + const uint8_t *in, size_t nblocks, uint8_t *out); +int sm4_cbc_padding_encrypt(const SM4_KEY *key, const uint8_t iv[SM4_BLOCK_SIZE], + 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[SM4_BLOCK_SIZE], + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); + + +void sm4_ctr_encrypt(const SM4_KEY *key, uint8_t ctr[SM4_BLOCK_SIZE], + const uint8_t *in, size_t inlen, uint8_t *out); +#define sm4_ctr_decrypt(key,ctr,in,inlen,out) sm4_ctr_encrypt(key,ctr,in,inlen,out) + + +#define SM4_GCM_IV_MIN_SIZE 1 +#define SM4_GCM_IV_MAX_SIZE (((uint64_t)1 << (64-3)) - 1) // 2305843009213693951 + +#define SM4_GCM_IV_DEFAULT_BITS 96 +#define SM4_GCM_IV_DEFAULT_SIZE 12 + +//#define NIST_SP800_GCM_MAX_IV_SIZE (((uint64_t)1 << (64-3)) - 1) // 2305843009213693951 + +#define SM4_GCM_MAX_IV_SIZE 64 +#define SM4_GCM_MIN_IV_SIZE 1 +#define SM4_GCM_DEFAULT_IV_SIZE 12 + +#define SM4_GCM_MIN_AAD_SIZE 0 +#define SM4_GCM_MAX_AAD_SIZE (((uint64_t)1 << (64-3)) - 1) // 2305843009213693951 + +#define SM4_GCM_MIN_PLAINTEXT_SIZE 0 +#define SM4_GCM_MAX_PLAINTEXT_SIZE ((((uint64_t)1 << 39) - 256) >> 3) // 68719476704 + +#define SM4_GCM_MAX_TAG_SIZE 16 +#define SM4_GCM_MIN_TAG_SIZE 12 +// For certain applications (voice or video), tag may be 64 or 32 bits +// see NIST Special Publication 800-38D, Appendix C for more details + + +int sm4_gcm_encrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + uint8_t *out, size_t taglen, uint8_t *tag); +int sm4_gcm_decrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + const uint8_t *tag, size_t taglen, uint8_t *out); + + +typedef struct { + SM4_KEY sm4_key; + uint8_t iv[SM4_BLOCK_SIZE]; + uint8_t block[SM4_BLOCK_SIZE]; + size_t block_nbytes; +} SM4_CBC_CTX; + +int sm4_cbc_encrypt_init(SM4_CBC_CTX *ctx, const uint8_t key[SM4_KEY_SIZE], const uint8_t iv[SM4_BLOCK_SIZE]); +int sm4_cbc_encrypt_update(SM4_CBC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +int sm4_cbc_encrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen); + +int sm4_cbc_decrypt_init(SM4_CBC_CTX *ctx, const uint8_t key[SM4_KEY_SIZE], const uint8_t iv[SM4_BLOCK_SIZE]); +int sm4_cbc_decrypt_update(SM4_CBC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +int sm4_cbc_decrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen); + + +typedef struct { + SM4_KEY sm4_key; + uint8_t ctr[SM4_BLOCK_SIZE]; + uint8_t block[SM4_BLOCK_SIZE]; + size_t block_nbytes; +} SM4_CTR_CTX; + +int sm4_ctr_encrypt_init(SM4_CTR_CTX *ctx, const uint8_t key[SM4_KEY_SIZE], const uint8_t ctr[SM4_BLOCK_SIZE]); +int sm4_ctr_encrypt_update(SM4_CTR_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +int sm4_ctr_encrypt_finish(SM4_CTR_CTX *ctx, uint8_t *out, size_t *outlen); + +#define sm4_ctr_decrypt_init(ctx,key,ctr) sm4_ctr_encrypt_init(ctx,key,ctr) +#define sm4_ctr_decrypt_update(ctx,in,inlen,out,outlen) sm4_ctr_encrypt_update(ctx,in,inlen,out,outlen) +#define sm4_ctr_decrypt_finish(ctx,out,outlen) sm4_ctr_encrypt_finish(ctx,out,outlen) + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm4_cbc_mac.h b/Core/GmSSL-3.1.1/include/gmssl/sm4_cbc_mac.h new file mode 100644 index 0000000..e803c8d --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm4_cbc_mac.h @@ -0,0 +1,35 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_SM4_CBC_MAC_H +#define GMSSL_SM4_CBC_MAC_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + SM4_KEY key; + uint8_t iv[16]; + size_t ivlen; +} SM4_CBC_MAC_CTX; + +void sm4_cbc_mac_init(SM4_CBC_MAC_CTX *ctx, const uint8_t key[16]); +void sm4_cbc_mac_update(SM4_CBC_MAC_CTX *ctx, const uint8_t *data, size_t datalen); +void sm4_cbc_mac_finish(SM4_CBC_MAC_CTX *ctx, uint8_t mac[16]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm4_cl.h b/Core/GmSSL-3.1.1/include/gmssl/sm4_cl.h new file mode 100644 index 0000000..5f1ca13 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm4_cl.h @@ -0,0 +1,55 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_SM4_CL_H +#define GMSSL_SM4_CL_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + + +#ifdef APPLE +#include +#else +#include +#endif + + +typedef struct { + uint32_t rk[32]; + cl_context context; + cl_command_queue queue; + cl_program program; + cl_kernel kernel; + cl_mem mem_rk; + cl_mem mem_io; + size_t workgroup_size; +} SM4_CL_CTX; + + +int sm4_cl_set_encrypt_key(SM4_CL_CTX *ctx, const uint8_t key[16]); +int sm4_cl_set_decrypt_key(SM4_CL_CTX *ctx, const uint8_t key[16]); +int sm4_cl_encrypt(SM4_CL_CTX *ctx, const uint8_t *in, size_t nblocks, uint8_t *out); +void sm4_cl_cleanup(SM4_CL_CTX *ctx); + +int test_sm4_cl_encrypt(void); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm4_rng.h b/Core/GmSSL-3.1.1/include/gmssl/sm4_rng.h new file mode 100644 index 0000000..67e86dc --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm4_rng.h @@ -0,0 +1,43 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_SM4_RNG_H +#define GMSSL_SM4_RNG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SM4_RNG_MAX_RESEED_COUNTER (1<<20) +#define SM4_RNG_MAX_RESEED_SECONDS 600 + +typedef struct { + uint8_t V[16]; + uint8_t K[16]; + uint32_t reseed_counter; + time_t last_reseed_time; +} SM4_RNG; + + +int sm4_rng_init(SM4_RNG *rng, const uint8_t *nonce, size_t nonce_len, + const uint8_t *label, size_t label_len); +int sm4_rng_update(SM4_RNG *rng, const uint8_t seed[32]); +int sm4_rng_reseed(SM4_RNG *rng, const uint8_t *addin, size_t addin_len); +int sm4_rng_generate(SM4_RNG *rng, const uint8_t *addin, size_t addin_len, + uint8_t *out, size_t outlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/sm9.h b/Core/GmSSL-3.1.1/include/gmssl/sm9.h new file mode 100644 index 0000000..bda9189 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/sm9.h @@ -0,0 +1,561 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +#ifndef GMSSL_SM9_H +#define GMSSL_SM9_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* +SM9 Public API + + SM9_SIGNATURE_SIZE + SM9_MAX_PLAINTEXT_SIZE + SM9_MAX_CIPHERTEXT_SIZE + + SM9_SIGN_MASTER_KEY + sm9_sign_master_key_generate + sm9_sign_master_key_extract_key + sm9_sign_master_key_info_encrypt_to_der + sm9_sign_master_key_info_decrypt_from_der + sm9_sign_master_key_info_encrypt_to_pem + sm9_sign_master_key_info_decrypt_from_pem + sm9_sign_master_public_key_to_der + sm9_sign_master_public_key_from_der + sm9_sign_master_public_key_to_pem + sm9_sign_master_public_key_from_pem + + SM9_SIGN_KEY + sm9_sign_key_info_encrypt_to_der + sm9_sign_key_info_decrypt_from_der + sm9_sign_key_info_encrypt_to_pem + sm9_sign_key_info_decrypt_from_pem + + SM9_SIGN_CTX + sm9_sign_init + sm9_sign_update + sm9_sign_finish + sm9_verify_init + sm9_verify_update + sm9_verify_finish + + SM9_ENC_MASTER_KEY + sm9_enc_master_key_generate + sm9_enc_master_key_extract_key + sm9_enc_master_key_info_encrypt_to_der + sm9_enc_master_key_info_decrypt_from_der + sm9_enc_master_key_info_encrypt_to_pem + sm9_enc_master_key_info_decrypt_from_pem + sm9_enc_master_public_key_to_der + sm9_enc_master_public_key_from_der + sm9_enc_master_public_key_to_pem + sm9_enc_master_public_key_from_pem + + SM9_ENC_KEY + sm9_enc_key_info_encrypt_to_der + sm9_enc_key_info_decrypt_from_der + sm9_enc_key_info_encrypt_to_pem + sm9_enc_key_info_decrypt_from_pem + + sm9_encrypt + sm9_decrypt +*/ + +#define SM9_HEX_SEP '\n' + +typedef uint64_t sm9_bn_t[8]; + +#define sm9_bn_init(r) sm9_bn_set_zero(r) +#define sm9_bn_clean(r) sm9_bn_set_zero(r) + +void sm9_bn_set_zero(sm9_bn_t r); +void sm9_bn_set_one(sm9_bn_t r); +int sm9_bn_is_zero(const sm9_bn_t a); +int sm9_bn_is_one(const sm9_bn_t a); +void sm9_bn_set_word(sm9_bn_t r, uint32_t a); +void sm9_bn_copy(sm9_bn_t r, const sm9_bn_t a); +int sm9_bn_rand_range(sm9_bn_t r, const sm9_bn_t range); +int sm9_bn_equ(const sm9_bn_t a, const sm9_bn_t b); +int sm9_bn_cmp(const sm9_bn_t a, const sm9_bn_t b); +void sm9_bn_add(sm9_bn_t r, const sm9_bn_t a, const sm9_bn_t b); +void sm9_bn_sub(sm9_bn_t ret, const sm9_bn_t a, const sm9_bn_t b); +void sm9_bn_to_bits(const sm9_bn_t a, char bits[256]); +void sm9_bn_to_bytes(const sm9_bn_t a, uint8_t out[32]); +void sm9_bn_from_bytes(sm9_bn_t r, const uint8_t in[32]); +void sm9_bn_to_hex(const sm9_bn_t a, char hex[64]); +int sm9_bn_from_hex(sm9_bn_t r, const char hex[64]); +int sm9_bn_print(FILE *fp, int fmt, int ind, const char *label, const sm9_bn_t a); +void sm9_print_bn(const char *prefix, const sm9_bn_t a); // 标准打印格式 + + +typedef sm9_bn_t sm9_fp_t; + +#define sm9_fp_init(r) sm9_fp_set_zero(r) +#define sm9_fp_clean(f) sm9_fp_set_zero(r) +#define sm9_fp_set_zero(r) sm9_bn_set_zero(r) +#define sm9_fp_set_one(r) sm9_bn_set_one(r) +#define sm9_fp_copy(r,a) sm9_bn_copy((r),(a)) +#define sm9_fp_rand(r) sm9_bn_rand_range((r), SM9_P) +#define sm9_fp_is_zero(a) sm9_bn_is_zero(a) +#define sm9_fp_is_one(a) sm9_bn_is_one(a) +#define sm9_fp_equ(a,b) sm9_bn_equ((a),(b)) +#define sm9_fp_to_bytes(a,buf) sm9_bn_to_bytes((a),(buf)) +#define sm9_fp_to_hex(a,s) sm9_bn_to_hex((a),(s)) +#define sm9_fp_print(fp,fmt,ind,label,a) sm9_bn_print(fp,fmt,ind,label,a) + +void sm9_fp_add(sm9_fp_t r, const sm9_fp_t a, const sm9_fp_t b); +void sm9_fp_sub(sm9_fp_t r, const sm9_fp_t a, const sm9_fp_t b); +void sm9_fp_dbl(sm9_fp_t r, const sm9_fp_t a); +void sm9_fp_tri(sm9_fp_t r, const sm9_fp_t a); +void sm9_fp_neg(sm9_fp_t r, const sm9_fp_t a); +void sm9_fp_mul(sm9_fp_t r, const sm9_fp_t a, const sm9_fp_t b); +void sm9_fp_sqr(sm9_fp_t r, const sm9_fp_t a); +void sm9_fp_pow(sm9_fp_t r, const sm9_fp_t a, const sm9_bn_t e); +void sm9_fp_inv(sm9_fp_t r, const sm9_fp_t a); +void sm9_fp_div2(sm9_fp_t r, const sm9_fp_t a); +int sm9_fp_from_bytes(sm9_fp_t r, const uint8_t buf[32]); +int sm9_fp_from_hex(sm9_fp_t r, const char hex[64]); + + +typedef sm9_bn_t sm9_fn_t; + +#define sm9_fn_init(r) sm9_fn_set_zero(r) +#define sm9_fn_clean(f) sm9_fn_set_zero(r) +#define sm9_fn_set_zero(r) sm9_bn_set_zero(r) +#define sm9_fn_set_one(r) sm9_bn_set_one(r) +#define sm9_fn_copy(r,a) sm9_bn_copy((r),(a)) +#define sm9_fn_rand(r) sm9_bn_rand_range((r), SM9_N) +#define sm9_fn_is_zero(a) sm9_bn_is_zero(a) +#define sm9_fn_is_one(a) sm9_bn_is_one(a) +#define sm9_fn_equ(a,b) sm9_bn_equ((a),(b)) +#define sm9_fn_to_bytes(a,out) sm9_bn_to_bytes((a),(out)) +#define sm9_fn_to_hex(a,s) sm9_bn_to_hex((a),(s)) +#define sm9_fn_print(fp,fmt,ind,label,a) sm9_bn_print(fp,fmt,ind,label,a) + +void sm9_fn_add(sm9_fn_t r, const sm9_fn_t a, const sm9_fn_t b); +void sm9_fn_sub(sm9_fn_t r, const sm9_fn_t a, const sm9_fn_t b); +void sm9_fn_mul(sm9_fn_t r, const sm9_fn_t a, const sm9_fn_t b); +void sm9_fn_pow(sm9_fn_t r, const sm9_fn_t a, const sm9_bn_t e); +void sm9_fn_inv(sm9_fn_t r, const sm9_fn_t a); +void sm9_fn_from_hash(sm9_fn_t h, const uint8_t Ha[40]); +int sm9_fn_from_bytes(sm9_fn_t a, const uint8_t in[32]); +int sm9_fn_from_hex(sm9_fn_t r, const char hex[64]); + + +typedef uint64_t sm9_barrett_bn_t[9]; + +int sm9_barrett_bn_cmp(const sm9_barrett_bn_t a, const sm9_barrett_bn_t b); +void sm9_barrett_bn_add(sm9_barrett_bn_t r, const sm9_barrett_bn_t a, const sm9_barrett_bn_t b); +void sm9_barrett_bn_sub(sm9_barrett_bn_t ret, const sm9_barrett_bn_t a, const sm9_barrett_bn_t b); + + +typedef sm9_fp_t sm9_fp2_t[2]; +extern const sm9_fp2_t SM9_FP2_ZERO; +extern const sm9_fp2_t SM9_FP2_ONE; +extern const sm9_fp2_t SM9_FP2_U; + +#define sm9_fp2_init(a) sm9_fp2_set_zero(a) +#define sm9_fp2_clean(a) sm9_fp2_set_zero(a) +#define sm9_fp2_set_zero(a) sm9_fp2_copy((a), SM9_FP2_ZERO) +#define sm9_fp2_set_one(a) sm9_fp2_copy((a), SM9_FP2_ONE) +#define sm9_fp2_set_u(a) sm9_fp2_copy((a), SM9_FP2_U) +#define sm9_fp2_is_zero(a) sm9_fp2_equ((a), SM9_FP2_ZERO) +#define sm9_fp2_is_one(a) sm9_fp2_equ((a), SM9_FP2_ONE) + +void sm9_fp2_set_fp(sm9_fp2_t r, const sm9_fp_t a); +void sm9_fp2_set(sm9_fp2_t r, const sm9_fp_t a0, const sm9_fp_t a1); +void sm9_fp2_copy(sm9_fp2_t r, const sm9_fp2_t a); +int sm9_fp2_rand(sm9_fp2_t r); +int sm9_fp2_equ(const sm9_fp2_t a, const sm9_fp2_t b); +void sm9_fp2_add(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b); +void sm9_fp2_dbl(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_tri(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_sub(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b); +void sm9_fp2_neg(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_mul(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b); +void sm9_fp2_mul_u(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b); +void sm9_fp2_mul_fp(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp_t k); +void sm9_fp2_sqr(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_sqr_u(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_inv(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_div(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b); +void sm9_fp2_div2(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_to_hex(const sm9_fp2_t a, char hex[129]); +int sm9_fp2_from_hex(sm9_fp2_t r, const char hex[129]); +int sm9_fp2_print(FILE *fp, int fmt, int ind, const char *label, const sm9_fp2_t a); + + +typedef sm9_fp2_t sm9_fp4_t[2]; +extern const sm9_fp4_t SM9_FP4_ZERO; +extern const sm9_fp4_t SM9_FP4_ONE; +extern const sm9_fp4_t SM9_FP4_U; +extern const sm9_fp4_t SM9_FP4_V; + +#define sm9_fp4_init(a) sm9_fp4_set_zero(a) +#define sm9_fp4_clean(a) sm9_fp4_set_zero(a) +#define sm9_fp4_set_zero(a) sm9_fp4_copy((a), SM9_FP4_ZERO) +#define sm9_fp4_set_one(a) sm9_fp4_copy((a), SM9_FP4_ONE) +#define sm9_fp4_is_zero(a) sm9_fp4_equ((a), SM9_FP4_ZERO) +#define sm9_fp4_is_one(a) sm9_fp4_equ((a), SM9_FP4_ONE) + +void sm9_fp4_set_u(sm9_fp4_t r); +void sm9_fp4_set_v(sm9_fp4_t r); +void sm9_fp4_set_fp(sm9_fp4_t r, const sm9_fp_t a); +void sm9_fp4_set_fp2(sm9_fp4_t r, const sm9_fp2_t a); +void sm9_fp4_set(sm9_fp4_t r, const sm9_fp2_t a0, const sm9_fp2_t a1); +void sm9_fp4_copy(sm9_fp4_t r, const sm9_fp4_t a); +int sm9_fp4_rand(sm9_fp4_t r); +int sm9_fp4_equ(const sm9_fp4_t a, const sm9_fp4_t b); +void sm9_fp4_add(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b); +void sm9_fp4_dbl(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_sub(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b); +void sm9_fp4_neg(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_mul(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b); +void sm9_fp4_mul_fp(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp_t k); +void sm9_fp4_mul_fp2(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp2_t b0); +void sm9_fp4_mul_v(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b); +void sm9_fp4_sqr(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_sqr_v(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_inv(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_to_bytes(const sm9_fp4_t a, uint8_t buf[128]); +int sm9_fp4_from_bytes(sm9_fp4_t r, const uint8_t buf[128]); +void sm9_fp4_to_hex(const sm9_fp4_t a, char hex[259]); +int sm9_fp4_from_hex(sm9_fp4_t r, const char hex[259]); + + +typedef sm9_fp4_t sm9_fp12_t[3]; + +#define sm9_fp12_init(r) sm9_fp12_set_zero(a) +#define sm9_fp12_clean(r) sm9_fp12_set_zero(a) + +void sm9_fp12_set_zero(sm9_fp12_t r); +void sm9_fp12_set_one(sm9_fp12_t r); +void sm9_fp12_set_u(sm9_fp12_t r); +void sm9_fp12_set_v(sm9_fp12_t r); +void sm9_fp12_set_w(sm9_fp12_t r); +void sm9_fp12_set_w_sqr(sm9_fp12_t r); +void sm9_fp12_set_fp(sm9_fp12_t r, const sm9_fp_t a); +void sm9_fp12_set_fp2(sm9_fp12_t r, const sm9_fp2_t a); +void sm9_fp12_set_fp4(sm9_fp12_t r, const sm9_fp4_t a); +void sm9_fp12_set(sm9_fp12_t r, const sm9_fp4_t a0, const sm9_fp4_t a1, const sm9_fp4_t a2); +void sm9_fp12_copy(sm9_fp12_t r, const sm9_fp12_t a); +int sm9_fp12_rand(sm9_fp12_t r); +int sm9_fp12_is_one(const sm9_fp12_t a); +int sm9_fp12_is_zero(const sm9_fp12_t a); +int sm9_fp12_equ(const sm9_fp12_t a, const sm9_fp12_t b); +void sm9_fp12_add(sm9_fp12_t r, const sm9_fp12_t a, const sm9_fp12_t b); +void sm9_fp12_dbl(sm9_fp12_t r, const sm9_fp12_t a); +void sm9_fp12_tri(sm9_fp12_t r, const sm9_fp12_t a); +void sm9_fp12_sub(sm9_fp12_t r, const sm9_fp12_t a, const sm9_fp12_t b); +void sm9_fp12_neg(sm9_fp12_t r, const sm9_fp12_t a); +void sm9_fp12_mul(sm9_fp12_t r, const sm9_fp12_t a, const sm9_fp12_t b); +void sm9_fp12_sqr(sm9_fp12_t r, const sm9_fp12_t a); +void sm9_fp12_inv(sm9_fp12_t r, const sm9_fp12_t a); +void sm9_fp12_pow(sm9_fp12_t r, const sm9_fp12_t a, const sm9_bn_t k); +void sm9_fp12_to_bytes(const sm9_fp12_t a, uint8_t buf[32 * 12]); +int sm9_fp12_from_bytes(sm9_fp12_t r, const uint8_t in[32 * 12]); +void sm9_fp12_to_hex(const sm9_fp12_t a, char hex[65 * 12]); +int sm9_fp12_from_hex(sm9_fp12_t r, const char hex[65 * 12]); // 这个明显是不对的 +void sm9_fp12_print(const char *prefix, const sm9_fp12_t a); + + +void sm9_fp2_conjugate(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp2_frobenius(sm9_fp2_t r, const sm9_fp2_t a); +void sm9_fp4_frobenius(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_conjugate(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_frobenius2(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp4_frobenius3(sm9_fp4_t r, const sm9_fp4_t a); +void sm9_fp12_frobenius(sm9_fp12_t r, const sm9_fp12_t x); +void sm9_fp12_frobenius2(sm9_fp12_t r, const sm9_fp12_t x); +void sm9_fp12_frobenius3(sm9_fp12_t r, const sm9_fp12_t x); +void sm9_fp12_frobenius6(sm9_fp12_t r, const sm9_fp12_t x); + + +typedef struct { + sm9_fp_t X; + sm9_fp_t Y; + sm9_fp_t Z; +} SM9_POINT; + +#define sm9_point_init(R) sm9_point_set_infinity(R) +#define sm9_point_clean(R) sm9_point_set_infinity(R) + +void sm9_point_set_infinity(SM9_POINT *R); +void sm9_point_copy(SM9_POINT *R, const SM9_POINT *P); +void sm9_point_get_xy(const SM9_POINT *P, sm9_fp_t x, sm9_fp_t y); +int sm9_point_is_at_infinity(const SM9_POINT *P); +int sm9_point_equ(const SM9_POINT *P, const SM9_POINT *Q); +int sm9_point_is_on_curve(const SM9_POINT *P); +void sm9_point_dbl(SM9_POINT *R, const SM9_POINT *P); +void sm9_point_add(SM9_POINT *R, const SM9_POINT *P, const SM9_POINT *Q); +void sm9_point_neg(SM9_POINT *R, const SM9_POINT *P); +void sm9_point_sub(SM9_POINT *R, const SM9_POINT *P, const SM9_POINT *Q); +void sm9_point_mul(SM9_POINT *R, const sm9_bn_t k, const SM9_POINT *P); +void sm9_point_mul_generator(SM9_POINT *R, const sm9_bn_t k); +void sm9_point_from_hex(SM9_POINT *R, const char hex[65 * 2]); +int sm9_point_to_uncompressed_octets(const SM9_POINT *P, uint8_t octets[65]); +int sm9_point_from_uncompressed_octets(SM9_POINT *P, const uint8_t octets[65]); +int sm9_point_print(FILE *fp, int fmt, int ind, const char *label, const SM9_POINT *P); + + +typedef struct { + sm9_fp2_t X; + sm9_fp2_t Y; + sm9_fp2_t Z; +} SM9_TWIST_POINT; + +#define sm9_twist_point_copy(R, P) memcpy((R), (P), sizeof(SM9_TWIST_POINT)) + +int sm9_twist_point_to_uncompressed_octets(const SM9_TWIST_POINT *P, uint8_t octets[129]); +int sm9_twist_point_from_uncompressed_octets(SM9_TWIST_POINT *P, const uint8_t octets[129]); + + +void sm9_twist_point_from_hex(SM9_TWIST_POINT *R, const char hex[65 * 4]); +int sm9_twist_point_is_at_infinity(const SM9_TWIST_POINT *P); +void sm9_twist_point_set_infinity(SM9_TWIST_POINT *R); +void sm9_twist_point_get_xy(const SM9_TWIST_POINT *P, sm9_fp2_t x, sm9_fp2_t y); + +int sm9_twist_point_equ(const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q); +int sm9_twist_point_is_on_curve(const SM9_TWIST_POINT *P); +void sm9_twist_point_neg(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P); +void sm9_twist_point_dbl(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P); +void sm9_twist_point_add(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q); +void sm9_twist_point_sub(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q); +void sm9_twist_point_add_full(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q); +void sm9_twist_point_mul(SM9_TWIST_POINT *R, const sm9_bn_t k, const SM9_TWIST_POINT *P); +void sm9_twist_point_mul_generator(SM9_TWIST_POINT *R, const sm9_bn_t k); +int sm9_twist_point_print(FILE *fp, int fmt, int ind, const char *label, const SM9_TWIST_POINT *P); + + + +void sm9_eval_g_tangent(sm9_fp12_t num, sm9_fp12_t den, const SM9_TWIST_POINT *P, const SM9_POINT *Q); +void sm9_eval_g_line(sm9_fp12_t num, sm9_fp12_t den, const SM9_TWIST_POINT *T, const SM9_TWIST_POINT *P, const SM9_POINT *Q); +void sm9_twist_point_pi1(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P); +void sm9_twist_point_pi2(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P); +void sm9_twist_point_neg_pi2(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P); +void sm9_final_exponent_hard_part(sm9_fp12_t r, const sm9_fp12_t f); +void sm9_final_exponent(sm9_fp12_t r, const sm9_fp12_t f); +void sm9_pairing(sm9_fp12_t r, const SM9_TWIST_POINT *Q, const SM9_POINT *P); + + +/* private key extract algorithms */ +#define SM9_HID_SIGN 0x01 +#define SM9_HID_EXCH 0x02 +#define SM9_HID_ENC 0x03 + +#define SM9_HASH1_PREFIX 0x01 +#define SM9_HASH2_PREFIX 0x02 + +int sm9_hash1(sm9_bn_t h1, const char *id, size_t idlen, uint8_t hid); + + +const char *sm9_oid_name(int oid); +int sm9_oid_from_name(const char *name); +int sm9_oid_to_der(int oid, uint8_t **out, size_t *outlen); +int sm9_oid_from_der(int *oid, const uint8_t **in, size_t *inlen); +int sm9_algor_to_der(int alg, int params, uint8_t **out, size_t *outlen); +int sm9_algor_from_der(int *alg, int *params, const uint8_t **in, size_t *inlen); + + +#define PEM_SM9_SIGN_MASTER_KEY "ENCRYPTED SM9 SIGN MASTER KEY" +#define PEM_SM9_SIGN_MASTER_PUBLIC_KEY "SM9 SIGN MASTER PUBLIC KEY" +#define PEM_SM9_SIGN_PRIVATE_KEY "ENCRYPTED SM9 SIGN PRIVATE KEY" +#define PEM_SM9_ENC_MASTER_KEY "ENCRYPTED SM9 ENC MASTER KEY" +#define PEM_SM9_ENC_MASTER_PUBLIC_KEY "SM9 ENC MASTER PUBLIC KEY" +#define PEM_SM9_ENC_PRIVATE_KEY "ENCRYPTED SM9 ENC PRIVATE KEY" + + +#define SM9_MAX_ID_SIZE (SM2_MAX_ID_SIZE) + +/* +SM9SignMasterKey ::= SEQUENCE { + ks INTEGER, + Ppubs BIT STRING -- uncompressed octets of twisted point } + +SM9SignMasterPublicKey ::= SEQUENCE { + Ppubs BIT STRING -- uncompressed octets of twisted point } + +SM9SignPrivateKey ::= SEQUENCE { + ds BIT STRING, -- uncompressed octets of ECPoint + Ppubs BIT STRING -- uncompressed octets of twisted point } +*/ +typedef struct { + SM9_TWIST_POINT Ppubs; // Ppubs = ks * P2 + sm9_fn_t ks; +} SM9_SIGN_MASTER_KEY; + +typedef struct { + SM9_TWIST_POINT Ppubs; + SM9_POINT ds; +} SM9_SIGN_KEY; + +int sm9_sign_master_key_generate(SM9_SIGN_MASTER_KEY *master); +int sm9_sign_master_key_extract_key(SM9_SIGN_MASTER_KEY *master, const char *id, size_t idlen, SM9_SIGN_KEY *key); + +// algorthm,parameters = sm9,sm9sign +#define SM9_SIGN_MASTER_KEY_MAX_SIZE 171 +int sm9_sign_master_key_to_der(const SM9_SIGN_MASTER_KEY *msk, uint8_t **out, size_t *outlen); +int sm9_sign_master_key_from_der(SM9_SIGN_MASTER_KEY *msk, const uint8_t **in, size_t *inlen); +int sm9_sign_master_key_info_encrypt_to_der(const SM9_SIGN_MASTER_KEY *msk, const char *pass, uint8_t **out, size_t *outlen); +int sm9_sign_master_key_info_decrypt_from_der(SM9_SIGN_MASTER_KEY *msk, const char *pass, const uint8_t **in, size_t *inlen); +int sm9_sign_master_key_info_encrypt_to_pem(const SM9_SIGN_MASTER_KEY *msk, const char *pass, FILE *fp); +int sm9_sign_master_key_info_decrypt_from_pem(SM9_SIGN_MASTER_KEY *msk, const char *pass, FILE *fp); +int sm9_sign_master_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_SIGN_MASTER_KEY *msk); + +#define SM9_SIGN_MASTER_PUBLIC_KEY_SIZE 136 +int sm9_sign_master_public_key_to_der(const SM9_SIGN_MASTER_KEY *mpk, uint8_t **out, size_t *outlen); +int sm9_sign_master_public_key_from_der(SM9_SIGN_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen); +int sm9_sign_master_public_key_to_pem(const SM9_SIGN_MASTER_KEY *mpk, FILE *fp); +int sm9_sign_master_public_key_from_pem(SM9_SIGN_MASTER_KEY *mpk, FILE *fp); +int sm9_sign_master_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_SIGN_MASTER_KEY *mpk); + +// algorithm,parameters = sm9sign, +#define SM9_SIGN_KEY_SIZE 204 +int sm9_sign_key_to_der(const SM9_SIGN_KEY *key, uint8_t **out, size_t *outlen); +int sm9_sign_key_from_der(SM9_SIGN_KEY *key, const uint8_t **in, size_t *inlen); +int sm9_sign_key_info_encrypt_to_der(const SM9_SIGN_KEY *key, const char *pass, uint8_t **out, size_t *outlen); +int sm9_sign_key_info_decrypt_from_der(SM9_SIGN_KEY *key, const char *pass, const uint8_t **in, size_t *inlen); +int sm9_sign_key_info_encrypt_to_pem(const SM9_SIGN_KEY *key, const char *pass, FILE *fp); +int sm9_sign_key_info_decrypt_from_pem(SM9_SIGN_KEY *key, const char *pass, FILE *fp); +int sm9_sign_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_SIGN_KEY *key); + +/* +from GM/T 0080-2020 SM9 Cryptographic Alagorithm Application Specification +SM9Signature ::= SEQUENCE { + h OCTET STRING, + S BIT STRING -- uncompressed octets of ECPoint } +*/ +typedef struct { + sm9_fn_t h; + SM9_POINT S; +} SM9_SIGNATURE; + +int sm9_do_sign(const SM9_SIGN_KEY *key, const SM3_CTX *sm3_ctx, SM9_SIGNATURE *sig); +int sm9_do_verify(const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen, const SM3_CTX *sm3_ctx, const SM9_SIGNATURE *sig); + +#define SM9_SIGNATURE_SIZE 104 +int sm9_signature_to_der(const SM9_SIGNATURE *sig, uint8_t **out, size_t *outlen); +int sm9_signature_from_der(SM9_SIGNATURE *sig, const uint8_t **in, size_t *inlen); +int sm9_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen); + +typedef struct { + SM3_CTX sm3_ctx; +} SM9_SIGN_CTX; + +int sm9_sign_init(SM9_SIGN_CTX *ctx); +int sm9_sign_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int sm9_sign_finish(SM9_SIGN_CTX *ctx, const SM9_SIGN_KEY *key, uint8_t *sig, size_t *siglen); +int sm9_verify_init(SM9_SIGN_CTX *ctx); +int sm9_verify_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int sm9_verify_finish(SM9_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen, + const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen); + + +/* +SM9EncMasterKey ::= SEQUENCE { + de INTEGER, + Ppube BIT STRING -- uncompressed octets of ECPoint } + +SM9EncMasterPublicKey ::= SEQUENCE { + Ppube BIT STRING -- uncompressed octets of ECPoint } + +SM9EncPrivateKey ::= SEQUENCE { + de BIT STRING, -- uncompressed octets of twisted point + Ppube BIT STRING -- uncompressed octets of ECPoint } +*/ + +typedef struct { + SM9_POINT Ppube; // Ppube = ke * P1 + sm9_fn_t ke; +} SM9_ENC_MASTER_KEY; + +typedef struct { + SM9_POINT Ppube; + SM9_TWIST_POINT de; +} SM9_ENC_KEY; + +int sm9_enc_master_key_generate(SM9_ENC_MASTER_KEY *master); +int sm9_enc_master_key_extract_key(SM9_ENC_MASTER_KEY *master, const char *id, size_t idlen, SM9_ENC_KEY *key); + +// algorithm,parameters = sm9,sm9encrypt +#define SM9_ENC_MASTER_KEY_MAX_SIZE 105 +int sm9_enc_master_key_to_der(const SM9_ENC_MASTER_KEY *msk, uint8_t **out, size_t *outlen); +int sm9_enc_master_key_from_der(SM9_ENC_MASTER_KEY *msk, const uint8_t **in, size_t *inlen); +int sm9_enc_master_key_info_encrypt_to_der(const SM9_ENC_MASTER_KEY *msk, const char *pass, uint8_t **out, size_t *outlen); +int sm9_enc_master_key_info_decrypt_from_der(SM9_ENC_MASTER_KEY *msk, const char *pass, const uint8_t **in, size_t *inlen); +int sm9_enc_master_key_info_encrypt_to_pem(const SM9_ENC_MASTER_KEY *msk, const char *pass, FILE *fp); +int sm9_enc_master_key_info_decrypt_from_pem(SM9_ENC_MASTER_KEY *msk, const char *pass, FILE *fp); +int sm9_enc_master_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_ENC_MASTER_KEY *msk); + +#define SM9_ENC_MASTER_PUBLIC_KEY_SIZE 70 +int sm9_enc_master_public_key_to_der(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen); +int sm9_enc_master_public_key_from_der(SM9_ENC_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen); +int sm9_enc_master_public_key_to_pem(const SM9_ENC_MASTER_KEY *mpk, FILE *fp); +int sm9_enc_master_public_key_from_pem(SM9_ENC_MASTER_KEY *mpk, FILE *fp); +int sm9_enc_master_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_ENC_MASTER_KEY *mpk); + +// algorithm,parameters = sm9encrypt, +#define SM9_ENC_KEY_SIZE 204 +int sm9_enc_key_to_der(const SM9_ENC_KEY *key, uint8_t **out, size_t *outlen); +int sm9_enc_key_from_der(SM9_ENC_KEY *key, const uint8_t **in, size_t *inlen); +int sm9_enc_key_info_encrypt_to_der(const SM9_ENC_KEY *key, const char *pass, uint8_t **out, size_t *outlen); +int sm9_enc_key_info_decrypt_from_der(SM9_ENC_KEY *key, const char *pass, const uint8_t **in, size_t *inlen); +int sm9_enc_key_info_encrypt_to_pem(const SM9_ENC_KEY *key, const char *pass, FILE *fp); +int sm9_enc_key_info_decrypt_from_pem(SM9_ENC_KEY *key, const char *pass, FILE *fp); +int sm9_enc_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_ENC_KEY *key); + +#define SM9_MAX_PRIVATE_KEY_SIZE (SM9_SIGN_KEY_SIZE) // MAX(SIGN_MASTER_KEY, SIGN_KEY, ENC_MASTER_KEY, ENC_KEY) +#define SM9_MAX_PRIVATE_KEY_INFO_SIZE 512 +#define SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE 1024 + +/* +from GM/T 0080-2020 SM9 Cryptographic Alagorithm Application Specification +SM9Cipher ::= SEQUENCE { + EnType INTEGER, -- 0 for XOR + C1 BIT STRING, -- uncompressed octets of ECPoint + C3 OCTET STRING, -- 32 bytes HMAC-SM3 tag + CipherText OCTET STRING } +*/ + +int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, size_t klen, uint8_t *kbuf, SM9_POINT *C); +int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const SM9_POINT *C, size_t klen, uint8_t *kbuf); +int sm9_do_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, SM9_POINT *C1, uint8_t *c2, uint8_t c3[SM3_HMAC_SIZE]); +int sm9_do_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, + const SM9_POINT *C1, const uint8_t *c2, size_t c2len, const uint8_t c3[SM3_HMAC_SIZE], uint8_t *out); + +#define SM9_MAX_PLAINTEXT_SIZE 255 +#define SM9_MAX_CIPHERTEXT_SIZE 367 // calculated in test_sm9_ciphertext() +int sm9_ciphertext_to_der(const SM9_POINT *C1, const uint8_t *c2, size_t c2len, + const uint8_t c3[SM3_HMAC_SIZE], uint8_t **out, size_t *outlen); +int sm9_ciphertext_from_der(SM9_POINT *C1, const uint8_t **c2, size_t *c2len, + const uint8_t **c3, const uint8_t **in, size_t *inlen); +int sm9_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen); +int sm9_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +int sm9_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/socket.h b/Core/GmSSL-3.1.1/include/gmssl/socket.h new file mode 100644 index 0000000..e5c5d92 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/socket.h @@ -0,0 +1,73 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SOCKET_H +#define GMSSL_SOCKET_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef WIN32 +#pragma comment (lib, "Ws2_32.lib") +#pragma comment (lib, "Mswsock.lib") +#pragma comment (lib, "AdvApi32.lib") + +#include + +typedef SOCKET tls_socket_t; +typedef int tls_ret_t; +typedef int tls_socklen_t; + + +#define tls_socket_send(sock,buf,len,flags) send(sock,buf,(int)(len),flags) +#define tls_socket_recv(sock,buf,len,flags) recv(sock,buf,(int)(len),flags) +#define tls_socket_close(sock) closesocket(sock) + + +#else + +#include +#include +#include +#include +#include +#include +#include + +typedef int tls_socket_t; +typedef ssize_t tls_ret_t; +typedef socklen_t tls_socklen_t; + + +#define tls_socket_send(sock,buf,len,flags) send(sock,buf,len,flags) +#define tls_socket_recv(sock,buf,len,flags) recv(sock,buf,len,flags) +#define tls_socket_close(sock) close(sock) + +#endif + +int tls_socket_lib_init(void); +int tls_socket_lib_cleanup(void); +int tls_socket_create(tls_socket_t *sock, int af, int type, int protocl); +int tls_socket_connect(tls_socket_t sock, const struct sockaddr_in *addr); +int tls_socket_bind(tls_socket_t sock, const struct sockaddr_in *addr); +int tls_socket_listen(tls_socket_t sock, int backlog); +int tls_socket_accept(tls_socket_t sock, struct sockaddr_in *addr, tls_socket_t *conn_sock); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/tls.h b/Core/GmSSL-3.1.1/include/gmssl/tls.h new file mode 100644 index 0000000..4d39ac9 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/tls.h @@ -0,0 +1,875 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_TLS_H +#define GMSSL_TLS_H + + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +TLS Public API + + TLS_PROTOCOL + TLS_protocol_tlcp + TLS_protocol_tls12 + TLS_protocol_tls13 + + TLS_CIPHER_SUITE + TLS_cipher_ecc_sm4_cbc_sm3 + TLS_cipher_ecc_sm4_gcm_sm3 + TLS_cipher_ecdhe_sm4_cbc_sm3 + TLS_cipher_ecdhe_sm4_gcm_sm3 + TLS_cipher_sm4_gcm_sm3 + + TLS_CTX + tls_ctx_init + tls_ctx_set_cipher_suites + tls_ctx_set_ca_certificates + tls_ctx_set_certificate_and_key + tls_ctx_set_tlcp_server_certificate_and_keys + tls_ctx_cleanup + + TLS_CONNECT + tls_init + tls_set_socket + tls_do_handshake + tls_send + tls_recv + tls_shutdown + tls_cleanup +*/ + +typedef uint32_t uint24_t; + +#define tls_uint8_size() 1 +#define tls_uint16_size() 2 +#define tls_uint24_size() 3 + +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_length_is_zero(size_t len); + + +typedef enum { + TLS_protocol_tlcp = 0x0101, + TLS_protocol_ssl2 = 0x0200, + TLS_protocol_ssl3 = 0x0300, + TLS_protocol_tls1 = 0x0301, + TLS_protocol_tls11 = 0x0302, + TLS_protocol_tls12 = 0x0303, + TLS_protocol_tls13 = 0x0304, + TLS_protocol_dtls1 = 0xfeff, // {254, 255} + TLS_protocol_dtls12 = 0xfefd, // {254, 253} +} TLS_PROTOCOL; + +const char *tls_protocol_name(int proto); + + +typedef enum { + TLS_cipher_null_with_null_null = 0x0000, + + // TLS 1.3, RFC 8998 + TLS_cipher_sm4_gcm_sm3 = 0x00c6, + TLS_cipher_sm4_ccm_sm3 = 0x00c7, + + // TLCP, GB/T 38636-2020, GM/T 0024-2012 + TLS_cipher_ecdhe_sm4_cbc_sm3 = 0xe011, // 可以让TLSv1.2使用这个 + TLS_cipher_ecdhe_sm4_gcm_sm3 = 0xe051, + TLS_cipher_ecc_sm4_cbc_sm3 = 0xe013, + TLS_cipher_ecc_sm4_gcm_sm3 = 0xe053, + TLS_cipher_ibsdh_sm4_cbc_sm3 = 0xe015, + TLS_cipher_ibsdh_sm4_gcm_sm3 = 0xe055, + TLS_cipher_ibc_sm4_cbc_sm3 = 0xe017, + TLS_cipher_ibc_sm4_gcm_sm3 = 0xe057, + TLS_cipher_rsa_sm4_cbc_sm3 = 0xe019, + TLS_cipher_rsa_sm4_gcm_sm3 = 0xe059, + TLS_cipher_rsa_sm4_cbc_sha256 = 0xe01c, + TLS_cipher_rsa_sm4_gcm_sha256 = 0xe05a, + + // TLS 1.3 RFC 8446 + TLS_cipher_aes_128_gcm_sha256 = 0x1301, // Mandatory-to-implement + TLS_cipher_aes_256_gcm_sha384 = 0x1302, // SHOULD implement + TLS_cipher_chacha20_poly1305_sha256 = 0x1303, // SHOULD implement + TLS_cipher_aes_128_ccm_sha256 = 0x1304, + TLS_cipher_aes_128_ccm_8_sha256 = 0x1305, + + TLS_cipher_empty_renegotiation_info_scsv = 0x00ff, +} TLS_CIPHER_SUITE; + +const char *tls_cipher_suite_name(int cipher); +int tls_cipher_suites_select(const uint8_t *client_ciphers, size_t client_ciphers_len, + const int *server_ciphers, size_t server_ciphers_cnt, int *selected_cipher); +int tls_cipher_suite_in_list(int cipher, const int *list, size_t list_count); + + +typedef enum { + TLS_compression_null = 0, + TLS_compression_default = 1, +} TLS_COMPRESSION_METHOD; + +const char *tls_compression_method_name(int meth); + + +typedef enum { + TLS_record_invalid = 0, // TLS 1.3 + TLS_record_change_cipher_spec = 20, // 0x14 + TLS_record_alert = 21, // 0x15 + TLS_record_handshake = 22, // 0x16 + TLS_record_application_data = 23, // 0x17 + TLS_record_heartbeat = 24, // 0x18 + TLS_record_tls12_cid = 25, // 0x19 +} TLS_RECORD_TYPE; + +const char *tls_record_type_name(int 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; + +const char *tls_handshake_type_name(int type); + + +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; + +const char *tls_cert_type_name(int type); +int tls_cert_type_from_oid(int oid); + +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, + 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; + +const char *tls_extension_name(int ext); + + +typedef enum { + TLS_point_uncompressed = 0, + TLS_point_ansix962_compressed_prime = 1, + TLS_point_ansix962_compressed_char2 = 2, +} TLS_EC_POINT_FORMAT; + +const char *tls_ec_point_format_name(int format); + + +typedef enum { + TLS_curve_type_explicit_prime = 1, + TLS_curve_type_explicit_char2 = 2, + TLS_curve_type_named_curve = 3, +} TLS_CURVE_TYPE; + +const char *tls_curve_type_name(int type); + + +// 与其支持v2,还不如直接修改v2,让v2和v3兼容 + +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 = 30, + TLS_curve_brainpoolp256r1tls13 = 31, + TLS_curve_brainpoolp384r1tls13 = 32, + TLS_curve_brainpoolp512r1tls13 = 33, + TLS_curve_sm2p256v1 = 41, // GmSSLv2: 30 +} TLS_NAMED_CURVE; + +const char *tls_named_curve_name(int 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 = 0x0708, // GmSSLv2: 0x0707 + 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; + +const char *tls_signature_scheme_name(int 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; + +const char *tls_alert_level_name(int 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_extension = 110, + 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; + +const char *tls_alert_description_text(int description); + + +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 tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32]); +int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32], + const char *label, const uint8_t *context, size_t context_len, + size_t outlen, uint8_t *out); +int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32]); + +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); +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_seq_num_incr(uint8_t seq_num[8]); +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 protocol); +int tls_pre_master_secret_print(FILE *fp, const uint8_t pre_master_secret[48], int format, int indent); + +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); + + +typedef struct { + uint8_t type; + uint8_t protocol[2]; + uint8_t data_length[2]; +} TLS_RECORD_HEADER; + +#define TLS_RECORD_HEADER_SIZE (1 + tls_uint16_size() + tls_uint16_size()) // 5 +#define TLS_MAX_PLAINTEXT_SIZE (1 << 14) // 16384 +#define TLS_MAX_COMPRESSED_SIZE ((1 << 14) + 1024) // 17408 +#define TLS_MAX_CIPHERTEXT_SIZE ((1 << 14) + 2048) // 18432 +#define TLS_MAX_RECORD_SIZE (TLS_RECORD_HEADER_SIZE + TLS_MAX_CIPHERTEXT_SIZE) // 18437 + +#define tls_record_type(record) ((record)[0]) +#define tls_record_header(record) ((record)+0) +#define tls_record_protocol(record) (((uint16_t)((record)[1]) << 8) | (record)[2]) +#define tls_record_data(record) ((record)+TLS_RECORD_HEADER_SIZE) +#define tls_record_data_length(record) (((uint16_t)((record)[3]) << 8) | (record)[4]) +#define tls_record_length(record) (TLS_RECORD_HEADER_SIZE + tls_record_data_length(record)) + +int tls_record_set_type(uint8_t *record, int type); +int tls_record_set_protocol(uint8_t *record, int protocol); +int tls_record_set_data_length(uint8_t *record, size_t length); +int tls_record_set_data(uint8_t *record, const uint8_t *data, size_t datalen); + +// 握手消息ServerKeyExchange, ClientKeyExchange的解析依赖当前密码套件 +#define tls_format_set_cipher_suite(fmt,cipher) do {(fmt)|=((cipher)<<8);} while (0) +int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent); +int tlcp_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent); + +int tls_record_send(const uint8_t *record, size_t recordlen, tls_socket_t sock); +int tls_record_recv(uint8_t *record, size_t *recordlen, tls_socket_t sock); +int tls12_record_recv(uint8_t *record, size_t *recordlen, tls_socket_t sock); + + +// Handshake +typedef struct { + uint8_t type; + uint8_t length[3]; +} TLS_HANDSHAKE_HEADER; + +#define TLS_HANDSHAKE_HEADER_SIZE 4 +#define TLS_MAX_HANDSHAKE_DATA_SIZE (TLS_MAX_PLAINTEXT_SIZE - TLS_HANDSHAKE_HEADER_SIZE) + +#define tls_handshake_data(p) ((p) + TLS_HANDSHAKE_HEADER_SIZE) +//#define tls_handshake_data_length(p) + + +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_handshake_print(FILE *fp, const uint8_t *handshake, size_t handshakelen, int format, int indent); + +// HelloRequest +int tls_hello_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); + +// ClientHello, ServerHello +#define TLS_MIN_SESSION_ID_SIZE 0 +#define TLS_MAX_SESSION_ID_SIZE 32 + +int tls_record_set_handshake_client_hello(uint8_t *record, size_t *recordlen, + int client_protocol, 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_protocol, const uint8_t **random, + const uint8_t **session_id, size_t *session_id_len, + const uint8_t **cipher_suites, size_t *cipher_suites_len, + const 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_protocol, 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 *protocol, const uint8_t **random, const uint8_t **session_id, size_t *session_id_len, + int *cipher_suite, const 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); + +// Extensions +int tls_ec_point_formats_ext_to_bytes(const int *formats, size_t formats_cnt, + uint8_t **out, size_t *outlen); +int tls_process_client_ec_point_formats(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen); +int tls_process_server_ec_point_formats(const uint8_t *ext_data, size_t ext_datalen); + +int tls_supported_groups_ext_to_bytes(const int *groups, size_t groups_cnt, + uint8_t **out, size_t *outlen); +int tls_process_client_supported_groups(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen); +int tls_process_server_supported_groups(const uint8_t *ext_data, size_t ext_datalen); + +int tls_signature_algorithms_ext_to_bytes_ex(int ext_type, const int *algs, size_t algs_cnt, + uint8_t **out, size_t *outlen); +int tls_signature_algorithms_ext_to_bytes(const int *algs, size_t algs_cnt, + uint8_t **out, size_t *outlen); +int tls13_signature_algorithms_cert_ext_to_bytes(const int *algs, size_t algs_cnt, + uint8_t **out, size_t *outlen); +int tls_process_client_signature_algorithms(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen); +int tls_process_server_signature_algors(const uint8_t *ext_data, size_t ext_datalen); + +int tls13_supported_versions_ext_to_bytes(int handshake_type, const int *protos, size_t protos_cnt, + uint8_t **out, size_t *outlen); +int tls13_process_client_supported_versions(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen); + +int tls13_process_server_supported_versions(const uint8_t *ext_data, size_t ext_datalen); + +int tls13_key_share_entry_to_bytes(const SM2_POINT *point, uint8_t **out, size_t *outlen); +int tls13_client_key_share_ext_to_bytes(const SM2_POINT *point, uint8_t **out, size_t *outlen); +int tls13_server_key_share_ext_to_bytes(const SM2_POINT *point, uint8_t **out, size_t *outlen); +int tls13_process_client_key_share(const uint8_t *ext_data, size_t ext_datalen, + const SM2_KEY *server_ecdhe_key, SM2_POINT *client_ecdhe_public, + uint8_t **out, size_t *outlen); +int tls13_process_server_key_share(const uint8_t *ext_data, size_t ext_datalen, SM2_POINT *point); + + +int tls13_certificate_authorities_ext_to_bytes(const uint8_t *ca_names, size_t ca_names_len, + uint8_t **out, size_t *outlen); + +int tls_ext_from_bytes(int *type, const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen); +int tls_process_client_exts(const uint8_t *exts, size_t extslen, uint8_t *out, size_t *outlen, size_t maxlen); +int tls_process_server_exts(const uint8_t *exts, size_t extslen, + int *ec_point_format, int *supported_group, int *signature_algor); + + +// Certificate +int tls_record_set_handshake_certificate(uint8_t *record, size_t *recordlen, + const uint8_t *certs, size_t certslen); +// 这个函数比较特殊,是直接解析了证书链,而不是返回指针 +// 应该提供一个独立的解析函数来解析TLS的证书链 +int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *certs, size_t *certslen); + +// ServerKeyExchange +int tls_server_key_exchange_print(FILE *fp, const uint8_t *ske, size_t skelen, int format, int indent); + +#define TLS_MAX_SIGNATURE_SIZE SM2_MAX_SIGNATURE_SIZE +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, const 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 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, + const 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); + + + +// CertificateRequest +#define TLS_MAX_CERTIFICATE_TYPES 256 +#define TLS_MAX_CA_NAMES_SIZE (TLS_MAX_HANDSHAKE_DATA_SIZE - tls_uint8_size() - tls_uint16_size()) + +int tls_authorities_from_certs(uint8_t *ca_names, size_t *ca_names_len, size_t maxlen, const uint8_t *certs, size_t certslen); +int tls_authorities_issued_certificate(const uint8_t *ca_names, size_t ca_namelen, const uint8_t *certs, size_t certslen); +int tls_cert_types_accepted(const uint8_t *types, size_t types_len, const uint8_t *client_certs, size_t client_certs_len); + +int tls_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen, + const uint8_t *cert_types, size_t cert_types_len, + const uint8_t *ca_names, size_t ca_names_len); +int tls_record_get_handshake_certificate_request(const uint8_t *record, + const uint8_t **cert_types, size_t *cert_types_len, + const 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); + + +// ServerHelloDone +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); + +// ClientKeyExchange +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, + const 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_client_key_exchange_ecdhe(uint8_t *record, size_t *recordlen, + const SM2_POINT *point); // 这里不应该支持SM2_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); + +// CertificateVerify +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, + const uint8_t **sig, size_t *siglen); +int tls_certificate_verify_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent); + +typedef enum { + TLS_client_verify_client_hello = 0, + TLS_client_verify_server_hello = 1, + TLS_client_verify_server_certificate = 2, + TLS_client_verify_server_key_exchange = 3, + TLS_client_verify_cert_request = 4, + TLS_client_verify_server_hello_done = 5, + TLS_client_verify_client_certificate = 6, + TLS_client_verify_client_key_exchange = 7, +} TLS_CLIENT_VERIFY_INDEX; + +typedef struct { + TLS_CLIENT_VERIFY_INDEX index; + uint8_t *handshake[8]; // Record data only, no record header + size_t handshake_len[8]; +} TLS_CLIENT_VERIFY_CTX; + +int tls_client_verify_init(TLS_CLIENT_VERIFY_CTX *ctx); +int tls_client_verify_update(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *handshake, size_t handshake_len); +int tls_client_verify_finish(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *sig, size_t siglen, const SM2_KEY *public_key); +void tls_client_verify_cleanup(TLS_CLIENT_VERIFY_CTX *ctx); + +// Finished +// FIXME: 支持TLS 1.3 提供MIN, MAX或TLS12, TLS13, TLCP... +#define TLS_VERIFY_DATA_SIZE 12 // TLS 1.3或者其他版本支持更长的verify_data +#define TLS_FINISHED_RECORD_SIZE (TLS_RECORD_HEADER_SIZE + TLS_HANDSHAKE_HEADER_SIZE + TLS_VERIFY_DATA_SIZE) // 21 +#define TLS_MAX_PADDING_SIZE (1 + 255) +#define TLS_MAC_SIZE SM3_HMAC_SIZE +#define TLS_FINISHED_RECORD_BUF_SIZE (TLS_FINISHED_RECORD_SIZE + TLS_MAC_SIZE + TLS_MAX_PADDING_SIZE) // 309 + + +int tls_record_set_handshake_finished(uint8_t *record, size_t *recordlen, + const uint8_t *verify_data, size_t verify_data_len); +int tls_record_get_handshake_finished(const uint8_t *record, + const uint8_t **verify_data, size_t *verify_data_len); +int tls_finished_print(FILE *fp, const uint8_t *a, size_t len, int format, int indent); + + +// Alert +typedef struct { + uint8_t level; + uint8_t description; +} TLS_ALERT; + +#define TLS_ALERT_RECORD_SIZE (TLS_RECORD_HEADER_SIZE + 2) + +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); +int tls_alert_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); + + +// ChangeCipherSpec +typedef struct { + uint8_t type; +} TLS_CHANGE_CIPHER_SPEC; + +const char *tls_change_cipher_spec_text(int change_cipher_spec); +int tls_change_cipher_spec_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); +int tls_record_set_change_cipher_spec(uint8_t *record, size_t *recordlen); +int tls_record_get_change_cipher_spec(const uint8_t *record); + +// ApplicationData +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); + + + +enum { + TLS_server_mode = 0, + TLS_client_mode = 1, +}; + +#define TLS_MAX_CIPHER_SUITES_COUNT 64 + +typedef struct { + int protocol; + int is_client; + int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT]; + size_t cipher_suites_cnt; + uint8_t *cacerts; + size_t cacertslen; + uint8_t *certs; + size_t certslen; + SM2_KEY signkey; + SM2_KEY kenckey; + int verify_depth; +} TLS_CTX; + +int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client); +int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cipher_suites_cnt); +int tls_ctx_set_ca_certificates(TLS_CTX *ctx, const char *cacertsfile, int depth); +int tls_ctx_set_certificate_and_key(TLS_CTX *ctx, const char *chainfile, + const char *keyfile, const char *keypass); +int tls_ctx_set_tlcp_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile, + const char *signkeyfile, const char *signkeypass, + const char *kenckeyfile, const char *kenckeypass); +void tls_ctx_cleanup(TLS_CTX *ctx); + + + +#define TLS_MAX_CERTIFICATES_SIZE 2048 +#define TLS_DEFAULT_VERIFY_DEPTH 4 +#define TLS_MAX_VERIFY_DEPTH 5 + + +typedef struct { + int protocol; + int is_client; + int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT]; + size_t cipher_suites_cnt; + tls_socket_t sock; + + uint8_t enced_record[TLS_MAX_RECORD_SIZE]; + size_t enced_record_len; + + + uint8_t record[TLS_MAX_RECORD_SIZE]; + + // 其实这个就不太对了,还是应该有一个完整的密文记录 + uint8_t databuf[TLS_MAX_PLAINTEXT_SIZE]; + uint8_t *data; + size_t datalen; + + int cipher_suite; + uint8_t session_id[32]; + size_t session_id_len; + 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; + uint8_t ca_certs[2048]; + size_t ca_certs_len; + + SM2_KEY sign_key; + SM2_KEY kenc_key; + + int verify_result; + + uint8_t master_secret[48]; + uint8_t key_block[96]; + + 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 client_write_iv[12]; // tls13 + uint8_t server_write_iv[12]; // tls13 + BLOCK_CIPHER_KEY client_write_key; + BLOCK_CIPHER_KEY server_write_key; + +} TLS_CONNECT; + + +#define TLS_MAX_EXTENSIONS_SIZE 512 // 这个应该再考虑一下数值,是否可以用其他的缓冲区装载? + + +int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx); +int tls_set_socket(TLS_CONNECT *conn, tls_socket_t sock); +int tls_do_handshake(TLS_CONNECT *conn); +int tls_send(TLS_CONNECT *conn, const uint8_t *in, size_t inlen, size_t *sentlen); +int tls_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen); +int tls_shutdown(TLS_CONNECT *conn); +void tls_cleanup(TLS_CONNECT *conn); + +int tlcp_do_connect(TLS_CONNECT *conn); +int tlcp_do_accept(TLS_CONNECT *conn); +int tls12_do_connect(TLS_CONNECT *conn); +int tls12_do_accept(TLS_CONNECT *conn); + + +#define TLS13_SM2_ID "TLSv1.3+GM+Cipher+Suite" +#define TLS13_SM2_ID_LENGTH (sizeof(TLS13_SM2_ID)-1) + +int tls13_do_connect(TLS_CONNECT *conn); +int tls13_do_accept(TLS_CONNECT *conn); + +int tls_send_alert(TLS_CONNECT *conn, int alert); +int tls_send_warning(TLS_CONNECT *conn, int alert); + +int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *sentlen); +int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen); + + +int tls13_connect(TLS_CONNECT *conn, const char *hostname, int port, FILE *server_cacerts_fp, + FILE *client_certs_fp, const SM2_KEY *client_sign_key); +int tls13_accept(TLS_CONNECT *conn, int port, + FILE *server_certs_fp, const SM2_KEY *server_sign_key, + FILE *client_cacerts_fp); + + +int tls13_supported_versions_ext_print(FILE *fp, int fmt, int ind, int handshake_type, const uint8_t *data, size_t datalen); +int tls13_key_share_ext_print(FILE *fp, int fmt, int ind, int handshake_type, const uint8_t *data, size_t datalen); + + +int tls_process_client_hello_exts(const uint8_t *exts, size_t extslen, uint8_t *out, size_t *outlen, size_t maxlen); +int tls_process_server_hello_exts(const uint8_t *exts, size_t extslen, + int *ec_point_format, int *supported_group, int *signature_algor); + + +int tls13_encrypted_extensions_print(FILE *fp, int fmt, int ind, const uint8_t *data, size_t datalen); + +int tls13_extension_print(FILE *fp, int fmt, int ind, + int handshake_type, int ext_type, const uint8_t *ext_data, size_t ext_datalen); +int tls13_extensions_print(FILE *fp, int fmt, int ind, + int handshake_type, const uint8_t *exts, size_t extslen); + +int tls13_certificate_print(FILE *fp, int fmt, int ind, const uint8_t *cert, size_t certlen); +int tls13_certificate_request_print(FILE *fp, int fmt, int ind, const uint8_t *cert, size_t certlen); +int tls13_certificate_verify_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen); +int tls13_record_print(FILE *fp, int format, int indent, const uint8_t *record, size_t recordlen); + + +int tls13_gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12], + const uint8_t seq_num[8], int record_type, + const uint8_t *in, size_t inlen, size_t padding_len, // TLSInnerPlaintext.content + uint8_t *out, size_t *outlen); // TLSCiphertext.encrypted_record +int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12], + const uint8_t seq_num[8], const uint8_t *in, size_t inlen, + int *record_type, uint8_t *out, size_t *outlen); + + +#ifdef TLS_DEBUG +# define tls_trace(s) fprintf(stderr,(s)) +# define tls_record_trace(fp,rec,reclen,fmt,ind) tls_record_print(fp,rec,reclen,fmt,ind) +# define tlcp_record_trace(fp,rec,reclen,fmt,ind) tlcp_record_print(fp,rec,reclen,fmt,ind) +# define tls12_record_trace(fp,rec,reclen,fmt,ind) tls12_record_print(fp,rec,reclen,fmt,ind) +# define tls13_record_trace(fp,rec,reclen,fmt,ind) tls13_record_print(fp,fmt,ind,rec,reclen) +#else +# define tls_trace(s) +# define tls_record_trace(fp,rec,reclen,fmt,ind) +# define tlcp_record_trace(fp,rec,reclen,fmt,ind) +# define tls12_record_trace(fp,rec,reclen,fmt,ind) +# define tls13_record_trace(fp,rec,reclen,fmt,ind) +#endif + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/version.h b/Core/GmSSL-3.1.1/include/gmssl/version.h new file mode 100644 index 0000000..be56ada --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/version.h @@ -0,0 +1,32 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_VERSION_H +#define GMSSL_VERSION_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// Also update CPACK_PACKAGE_VERSION in CMakeLists.txt +#define GMSSL_VERSION_NUM 30101 +#define GMSSL_VERSION_STR "GmSSL 3.1.1" + +_gmssl_export int gmssl_version_num(void); +_gmssl_export const char *gmssl_version_str(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/x509.h b/Core/GmSSL-3.1.1/include/gmssl/x509.h new file mode 100644 index 0000000..1b57971 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/x509.h @@ -0,0 +1,16 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_X509_H +#define GMSSL_X509_H + +#include + +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/x509_alg.h b/Core/GmSSL-3.1.1/include/gmssl/x509_alg.h new file mode 100644 index 0000000..e764b3f --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/x509_alg.h @@ -0,0 +1,68 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_X509_ALG_H +#define GMSSL_X509_ALG_H + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY } +*/ + +const char *x509_digest_algor_name(int oid); +int x509_digest_algor_from_name(const char *name); +int x509_digest_algor_from_der(int *oid, const uint8_t **in, size_t *inlen); +int x509_digest_algor_to_der(int oid, uint8_t **out, size_t *outlen); +int x509_digest_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +const char *x509_encryption_algor_name(int oid); +int x509_encryption_algor_from_name(const char *name); +int x509_encryption_algor_from_der(int *oid, const uint8_t **iv, size_t *ivlen, const uint8_t **in, size_t *inlen); +int x509_encryption_algor_to_der(int oid, const uint8_t *iv, size_t ivlen, uint8_t **out, size_t *outlen); +int x509_encryption_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +const char *x509_signature_algor_name(int oid); +int x509_signature_algor_from_name(const char *name); +int x509_signature_algor_from_der(int *oid, const uint8_t **in, size_t *inlen); +int x509_signature_algor_to_der(int oid, uint8_t **out, size_t *outlen); +int x509_signature_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +const char *x509_public_key_encryption_algor_name(int oid); +int x509_public_key_encryption_algor_from_name(const char *name); +int x509_public_key_encryption_algor_from_der(int *oid, const uint8_t **params, size_t *params_len, const uint8_t **in, size_t *inlen); +int x509_public_key_encryption_algor_to_der(int oid, uint8_t **out, size_t *outlen); +int x509_public_key_encryption_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +const char *x509_public_key_algor_name(int oid); +int x509_public_key_algor_from_name(const char *name); +int x509_public_key_algor_to_der(int oid, int curve, uint8_t **out, size_t *outlen); +int x509_public_key_algor_from_der(int *oid, int *curve_or_null, const uint8_t **in, size_t *inlen); +int x509_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/x509_cer.h b/Core/GmSSL-3.1.1/include/gmssl/x509_cer.h new file mode 100644 index 0000000..f8d3857 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/x509_cer.h @@ -0,0 +1,390 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_X509_CER_H +#define GMSSL_X509_CER_H + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +enum X509_Version { + X509_version_v1 = 0, + X509_version_v2 = 1, + X509_version_v3 = 2, +}; + +const char *x509_version_name(int version); +int x509_explicit_version_to_der(int index, int version, uint8_t **out, size_t *outlen); +int x509_explicit_version_from_der(int index, int *version, const uint8_t **in, size_t *inlen); + +/* +Time ::= CHOICE { + utcTime UTCTime, + generalTime GeneralizedTime } +*/ +#define X509_MAX_UTC_TIME 2524607999 // "20491231235959Z" +#define X509_MAX_GENERALIZED_TIME 253402300799 // "99991231235959Z" +int x509_time_to_der(time_t a, uint8_t **out, size_t *outlen); +int x509_time_from_der(time_t *a, const uint8_t **in, size_t *inlen); + +/* +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time } +*/ +#define X509_VALIDITY_MIN_DAYS 1 +#define X509_VALIDITY_MAX_DAYS 3653 +#define X509_VALIDITY_MAX_SECONDS (X509_VALIDITY_MAX_DAYS * 86400) +int x509_validity_add_days(time_t *not_after, time_t not_before, int days); +int x509_validity_to_der(time_t not_before, time_t not_after, uint8_t **out, size_t *outlen); +int x509_validity_from_der(time_t *not_before, time_t *not_after, const uint8_t **in, size_t *inlen); +int x509_validity_check(time_t not_before, time_t not_after, time_t now, int max_secs); +int x509_validity_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +DirectoryString or DirectoryName + +DirectoryName ::= CHOICE { + teletexString TeletexString (SIZE (1..MAX)), + printableString PrintableString (SIZE (1..MAX)), + universalString UniversalString (SIZE (1..MAX)), + utf8String UTF8String (SIZE (1..MAX)), + bmpString BMPString (SIZE (1..MAX)), +} +*/ +int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen); +int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen); +int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen); + +/* +AttributeTypeAndValue ::= SEQUENCE { + type OBJECT IDENTIFIER, + value ANY -- DEFINED BY AttributeType } + +id-at + OID_at_name name DirectoryName 1..ub-name + OID_at_surname surname DirectoryName 1..ub-name + OID_at_given_name givenName DirectoryName 1..ub-name + OID_at_initials initials DirectoryName 1..ub-name + OID_at_generation_qualifier generationQualifier DirectoryName 1..ub-name + OID_at_common_name commonName DirectoryName 1..ub-common-name + OID_at_locality_name localityName DirectoryName 1..ub-locality-name + OID_at_state_or_province_name stateOrProvinceName DirectoryName 1..ub-state-name + OID_at_organization_name organizationName DirectoryName 1..ub-organization-name + OID_at_organizational_unit_name organizationalUnitName DirectoryName 1..ub-organizational-unit-name + OID_at_title title DirectoryName 1..ub-title + OID_at_dn_qualifier dnQualifier PrintableString N/A + OID_at_country_name countryName PrintableString 2..2 + OID_at_serial_number serialNumber PrintableString 1..ub-serial-number + OID_at_pseudonym pseudonym DirectoryName 1..ub-pseudonym + OID_domain_component domainComponent IA5String N/A +*/ +const char *x509_name_type_name(int oid); +int x509_name_type_from_name(const char *name); +int x509_name_type_from_der(int *oid, const uint8_t **in, size_t *inlen); +int x509_name_type_to_der(int oid, uint8_t **out, size_t *outlen); + +#define X509_ub_name 32768 +#define X509_ub_common_name 64 +#define X509_ub_locality_name 128 +#define X509_ub_state_name 128 +#define X509_ub_organization_name 64 +#define X509_ub_organizational_unit_name 64 +#define X509_ub_title 64 +#define X509_ub_serial_number 64 +#define X509_ub_pseudonym 128 + +int x509_attr_type_and_value_check(int oid, int tag, const uint8_t *val, size_t vlen); +int x509_attr_type_and_value_to_der(int oid, int tag, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen); +int x509_attr_type_and_value_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, const uint8_t **in, size_t *inlen); +int x509_attr_type_and_value_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue +*/ +int x509_rdn_to_der(int oid, int tag, const uint8_t *val, size_t vlen, const uint8_t *more, size_t mlen, uint8_t **out, size_t *outlen); +int x509_rdn_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, const uint8_t **more, size_t *mlen, const uint8_t **in, size_t *inlen); +int x509_rdn_check(const uint8_t *d, size_t dlen); +int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +Name ::= SEQUENCE OF RelativeDistinguishedName +*/ +int x509_name_add_rdn(uint8_t *d, size_t *dlen, size_t maxlen, int oid, int tag, const uint8_t *val, size_t vlen, const uint8_t *more, size_t mlen); +int x509_name_add_country_name(uint8_t *d, size_t *dlen, size_t maxlen, const char val[2] ); // val: PrintableString SIZE(2) +int x509_name_add_state_or_province_name(uint8_t *d, size_t *dlen, size_t maxlen, int tag, const uint8_t *val, size_t vlen); +int x509_name_add_locality_name(uint8_t *d, size_t *dlen, size_t maxlen, int tag, const uint8_t *val, size_t vlen); +int x509_name_add_organization_name(uint8_t *d, size_t *dlen, size_t maxlen, int tag, const uint8_t *val, size_t vlen); +int x509_name_add_organizational_unit_name(uint8_t *d, size_t *dlen, size_t maxlen, int tag, const uint8_t *val, size_t vlen); +int x509_name_add_common_name(uint8_t *d, size_t *dlen, size_t maxlen, int tag, const uint8_t *val, size_t vlen); +int x509_name_add_domain_component(uint8_t *d, size_t *dlen, size_t maxlen, const char *val, size_t vlen); // val: IA5String + +int x509_name_set(uint8_t *d, size_t *dlen, size_t maxlen, + const char country[2], const char *state, const char *locality, + const char *org, const char *org_unit, const char *common_name); + +#define x509_name_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) +#define x509_name_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) +int x509_name_check(const uint8_t *d, size_t dlen); +int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen); +int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen); +int x509_name_equ(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen); + +int x509_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING } + +algorithm.algorithm = OID_ec_public_key; +algorithm.parameters = OID_sm2; +subjectPublicKey = ECPoint +*/ +#define x509_public_key_info_to_der(key,out,outlen) sm2_public_key_info_to_der(key,out,outlen) +#define x509_public_key_info_from_der(key,in,inlen) sm2_public_key_info_from_der(key,in,inlen) +int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING -- contains the DER encoding of an ASN.1 value + +id-ce: + OID_ce_authority_key_identifier + OID_ce_subject_key_identifier + OID_ce_key_usage + OID_ce_certificate_policies + OID_ce_policy_mappings + OID_ce_subject_alt_name + OID_ce_issuer_alt_name + OID_ce_subject_directory_attributes + OID_ce_basic_constraints + OID_ce_name_constraints + OID_ce_policy_constraints + OID_ce_ext_key_usage + OID_ce_crl_distribution_points + OID_ce_inhibit_any_policy + OID_ce_freshest_crl + OID_netscape_cert_comment +*/ +const char *x509_ext_id_name(int oid); +int x509_ext_id_from_name(const char *name); +int x509_ext_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_count, const uint8_t **in, size_t *inlen); +int x509_ext_id_to_der(int oid, uint8_t **out, size_t *outlen); + +int x509_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen); +int x509_ext_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, int *critical, const uint8_t **val, size_t *vlen, const uint8_t **in, size_t *inlen); +int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +[3] EXPLICIT SEQUENCE OF Extension + */ +int x509_explicit_exts_to_der(int index, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_explicit_exts_from_der(int index, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +#define x509_exts_to_der(d,dlen,out,outlen) x509_explicit_exts_to_der(3,d,dlen,out,outlen) +#define x509_exts_from_der(d,dlen,in,inlen) x509_explicit_exts_from_der(3,d,dlen,in,inlen) + +int x509_exts_get_ext_by_oid(const uint8_t *d, size_t dlen, int oid, + int *critical, const uint8_t **val, size_t *vlen); +int x509_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +TBSCertificate ::= SEQUENCE { + version [0] EXPLICIT INTEGER DEFAULT v1, + serialNumber INTEGER, + siganture AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPulbicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL, -- If present, must be v2,v3 + subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL, -- If present, must be v2,v3 + extensions [3] EXPLICIT Extensions OPTIONAL -- If present, must be v3 } +*/ +#define X509_SERIAL_NUMBER_MIN_LEN 1 +#define X509_SERIAL_NUMBER_MAX_LEN 20 +#define X509_UNIQUE_ID_MIN_LEN 32 +#define X509_UNIQUE_ID_MAX_LEN 32 + +int x509_tbs_cert_to_der( + int version, + const uint8_t *serial, size_t serial_len, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t not_before, time_t not_after, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *issuer_unique_id, size_t issuer_unique_id_len, + const uint8_t *subject_unique_id, size_t subject_unique_id_len, + const uint8_t *exts, size_t exts_len, + uint8_t **out, size_t *outlen); +int x509_tbs_cert_from_der( + int *version, + const uint8_t **serial, size_t *serial_len, + int *signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *not_before, time_t *not_after, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **issuer_unique_id, size_t *issuer_unique_id_len, + const uint8_t **subject_unique_id, size_t *subject_unique_id_len, + const uint8_t **exts, size_t *exts_len, + const uint8_t **in, size_t *inlen); +int x509_tbs_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING } +*/ +int x509_certificate_to_der( + const uint8_t *tbs, size_t tbslen, + int signature_algor, + const uint8_t *sig, size_t siglen, + uint8_t **out, size_t *outlen); +int x509_certificate_from_der( + const uint8_t **tbs, size_t *tbslen, + int *signature_algor, + const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen); + +int x509_signed_from_der( + const uint8_t **tbs, size_t *tbslen, + int *signature_algor, + const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen); +int x509_signed_verify(const uint8_t *a, size_t alen, const SM2_KEY *pub_key, + const char *signer_id, size_t signer_id_len); +int x509_signed_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen, + const char *signer_id, size_t signer_id_len); + +// x509_cert functions +int x509_cert_sign_to_der( + int version, + const uint8_t *serial, size_t serial_len, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t not_before, time_t not_after, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *issuer_unique_id, size_t issuer_unique_id_len, + const uint8_t *subject_unique_id, size_t subject_unique_id_len, + const uint8_t *exts, size_t exts_len, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen); + +int x509_cert_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen); +int x509_cert_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen); +int x509_cert_to_pem(const uint8_t *a, size_t alen, FILE *fp); +int x509_cert_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp); +int x509_cert_from_pem_by_subject(uint8_t *a, size_t *alen, size_t maxlen, const uint8_t *name, size_t namelen, FILE *fp); +int x509_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen); + +int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen, + const char *signer_id, size_t signer_id_len); + +int x509_cert_get_details(const uint8_t *a, size_t alen, + int *version, + const uint8_t **serial_number, size_t *serial_number_len, + int *inner_signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *not_before, time_t *not_after, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **issuer_unique_id, size_t *issuer_unique_id_len, + const uint8_t **subject_unique_id, size_t *subject_unique_id_len, + const uint8_t **extensions, size_t *extensions_len, + int *signature_algor, + const uint8_t **signature, size_t *signature_len); + + +typedef enum { + X509_cert_server_auth, + X509_cert_client_auth, + X509_cert_server_key_encipher, + X509_cert_client_key_encipher, + X509_cert_ca, + X509_cert_root_ca, + X509_cert_crl_sign, +} X509_CERT_TYPE; + +int x509_cert_check(const uint8_t *cert, size_t certlen, int cert_type, int *path_len_constraint); + +/* +IssuerAndSerialNumber ::= SEQUENCE { + isser Name, + serialNumber INTEGER } +*/ +int x509_cert_get_issuer_and_serial_number(const uint8_t *a, size_t alen, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len); +int x509_cert_get_issuer(const uint8_t *a, size_t alen, const uint8_t **name, size_t *namelen); +int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **subj, size_t *subj_len); +int x509_cert_get_subject_public_key(const uint8_t *a, size_t alen, SM2_KEY *public_key); +int x509_cert_get_exts(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen); + +int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp); +int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp); +int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt); +int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen); +int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen); +int x509_certs_get_last(const uint8_t *d, size_t dlen, const uint8_t **cert, size_t *certlen); + +int x509_certs_get_cert_by_subject_and_key_identifier(const uint8_t *d, size_t dlen, + const uint8_t *subject, size_t subject_len, + const uint8_t *key_id, size_t key_id_len, + const uint8_t **cert, size_t *certlen); +int x509_certs_get_cert_by_issuer_and_serial_number( + const uint8_t *certs, size_t certs_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + const uint8_t **cert, size_t *cert_len); + +typedef enum { + X509_cert_chain_server, + X509_cert_chain_client, +} X509_CERT_CHAIN_TYPE; + +#define X509_MAX_VERIFY_DEPTH 6 +int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result); +int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result); +int x509_certs_get_subjects(const uint8_t *certs, size_t certslen, uint8_t *names, size_t *nameslen); +int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +int x509_cert_new_from_file(uint8_t **out, size_t *outlen, const char *file); +int x509_certs_new_from_file(uint8_t **out, size_t *outlen, const char *file); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/x509_crl.h b/Core/GmSSL-3.1.1/include/gmssl/x509_crl.h new file mode 100644 index 0000000..76a9e94 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/x509_crl.h @@ -0,0 +1,309 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#ifndef GMSSL_X509_CRL_H +#define GMSSL_X509_CRL_H + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +CRLReason ::= ENUMERATED +*/ +typedef enum { + X509_cr_unspecified = 0, + X509_cr_key_compromise = 1, + X509_cr_ca_compromise = 2 , + X509_cr_affiliation_changed = 3, + X509_cr_superseded = 4, + X509_cr_cessation_of_operation = 5, + X509_cr_certificate_hold = 6, + X509_cr_not_assigned = 7, + X509_cr_remove_from_crl = 8, + X509_cr_privilege_withdrawn = 9, + X509_cr_aa_compromise = 10, +} X509_CRL_REASON; + +const char *x509_crl_reason_name(int reason); +int x509_crl_reason_from_name(int *reason, const char *name); +int x509_crl_reason_to_der(int reason, uint8_t **out, size_t *outlen); +int x509_crl_reason_from_der(int *reason, const uint8_t **in, size_t *inlen); +int x509_implicit_crl_reason_from_der(int index, int *reason, const uint8_t **in, size_t *inlen); + +/* +CRL Entry Extensions: + OID_ce_crl_reasons ENUMERATED non-critical + OID_ce_invalidity_date GeneralizedTime non-critical + OID_ce_certificate_issuer GeneralNames MUST critical +*/ +const char *x509_crl_entry_ext_id_name(int oid); +int x509_crl_entry_ext_id_from_name(const char *name); +int x509_crl_entry_ext_id_to_der(int oid, uint8_t **out, size_t *outlen); +int x509_crl_entry_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen); + +int x509_crl_entry_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen); +int x509_crl_entry_ext_from_der(int *oid, int *critical, const uint8_t **val, size_t *vlen, const uint8_t **in, size_t *inlen); +int x509_crl_entry_ext_critical_check(int oid, int critical); +int x509_crl_entry_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_crl_reason_ext_to_der(int critical, int reason, uint8_t **out, size_t *outlen); +int x509_invalidity_date_ext_to_der(int critical, time_t date, uint8_t **out, size_t *outlen); +int x509_cert_issuer_ext_to_der(int critical, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_crl_entry_ext_from_der_ex(int *oid, int *critical, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen); + +int x509_crl_entry_exts_to_der( + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen); +int x509_crl_entry_exts_from_der( + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen); +int x509_crl_entry_exts_get(const uint8_t *d, size_t dlen, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len); +int x509_crl_entry_exts_check(const uint8_t *d, size_t dlen); +int x509_crl_entry_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +RevokedCertificate ::= SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL } +*/ +int x509_revoked_cert_to_der( + const uint8_t *serial, size_t serial_len, time_t revoke_date, + const uint8_t *crl_entry_exts, size_t crl_entry_exts_len, + uint8_t **out, size_t *outlen); +int x509_revoked_cert_from_der( + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len, + const uint8_t **in, size_t *inlen); +int x509_revoked_cert_to_der_ex( + const uint8_t *serial, size_t serial_len, time_t revoke_date, + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen); +int x509_revoked_cert_from_der_ex( + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen); +int x509_revoked_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_cert_revoke_to_der(const uint8_t *cert, size_t certlen, + time_t revoke_date, int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen); + +/* +RevokedCertificates ::= SEQUENCE OF RevokedCertificate +*/ +int x509_revoked_certs_find_revoked_cert_by_serial_number(const uint8_t *d, size_t dlen, + const uint8_t *serial, size_t serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len); +int x509_revoked_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +CRL Extensions: + OID_ce_authority_key_identifier AuthorityKeyIdentifier critical or non-critical + OID_ce_issuer_alt_name GeneralNames SHOULD non-critical + OID_ce_crl_number INTEGER MUST non-critical + OID_ce_delta_crl_indicator INTEGER MUST critical + OID_ce_issuing_distribution_point IssuingDistributionPoint critical + OID_ce_freshest_crl CRLDistributionPoints MUST non-critical + OID_pe_authority_info_access AccessDescriptions MUST non-critical +*/ +const char *x509_crl_ext_id_name(int oid); +int x509_crl_ext_id_from_name(const char *name); +int x509_crl_ext_id_to_der(int oid, uint8_t **out, size_t *outlen); +int x509_crl_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen); +int x509_crl_ext_id_from_der_ex(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen); + +/* +IssuingDistributionPoint ::= SEQUENCE { + distributionPoint [0] EXPLICIT 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 } +*/ +int x509_issuing_distribution_point_to_der( + const char *dist_point_uri, size_t dist_point_uri_len, + int only_contains_user_certs, + int only_contains_ca_certs, + int only_some_reasons, + int indirect_crl, + int only_contains_attr_certs, + uint8_t **out, size_t *outlen); +int x509_issuing_distribution_point_from_der( + int *dist_point_choice, const uint8_t **dist_point, size_t *dist_point_len, + int *only_contains_user_certs, + int *only_contains_ca_certs, + int *only_some_reasons, + int *indirect_crl, + int *only_contains_attr_certs, + const uint8_t **in, size_t *inlen); +int x509_issuing_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_crl_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen); +int x509_crl_ext_from_der_ex(int *oid, uint32_t *nodes, size_t *nodes_cnt, + int *critical, const uint8_t **val, size_t *vlen, + const uint8_t **in, size_t *inlen); +int x509_crl_ext_critical_check(int oid, int critical); +int x509_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +int x509_crl_exts_add_authority_key_identifier( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len); +int x509_crl_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + const SM2_KEY *public_key); +int x509_crl_exts_add_issuer_alt_name( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *d, size_t dlen); +int x509_crl_exts_add_crl_number_ex( + uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, int num); +int x509_crl_exts_add_crl_number( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + int num); +int x509_crl_exts_add_delta_crl_indicator( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + int num); +int x509_crl_exts_add_issuing_distribution_point( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const char *dist_point_uri, size_t dist_point_uri_len, + int only_contains_user_certs, + int only_contains_ca_certs, + int only_some_reasons, + int indirect_crl, + int only_contains_attr_certs); +int x509_crl_exts_add_freshest_crl( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *http_uri, size_t http_urilen, + const char *ldap_uri, size_t ldap_urilen); +int x509_crl_exts_add_authority_info_acess( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *ca_issuers_uri, size_t ca_issuers_urilen, + const char *ocsp_uri, size_t ocsp_urilen); + +#define x509_crl_exts_to_der(d,dlen,out,outlen) x509_explicit_exts_to_der(0,d,dlen,out,outlen) +#define x509_crl_exts_from_der(d,dlen,in,inlen) x509_explicit_exts_from_der(0,d,dlen,in,inlen) +int x509_crl_exts_check(const uint8_t *d, size_t dlen); +int x509_crl_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +TBSCertList ::= SEQUENCE { + version INTEGER OPTIONAL, -- if present, MUST be v2 + signature AlgorithmIdentifier, + issuer Name, + thisUpdate Time, + nextUpdate Time OPTIONAL, + revokedCertificates RevokedCertificates OPTIONAL, + crlExtensions [0] EXPLICIT Extensions OPTIONAL, -- if present, MUST be v2 } +*/ +int x509_tbs_crl_to_der( + int version, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t this_update, + time_t next_update, + const uint8_t *revoked_certs, size_t revoked_certs_len, + const uint8_t *exts, size_t exts_len, + uint8_t **out, size_t *outlen); +int x509_tbs_crl_from_der( + int *version, + int *signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, + time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + const uint8_t **exts, size_t *exts_len, + const uint8_t **in, size_t *inlen); +int x509_tbs_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +CertificateList ::= SEQUENCE { + tbsCertList TBSCertList, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING } +*/ +int x509_crl_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen); +int x509_crl_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen); +int x509_crl_to_pem(const uint8_t *a, size_t alen, FILE *fp); +int x509_crl_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp); +int x509_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen); + + +int x509_crl_sign_to_der( + int version, int sig_alg, + const uint8_t *issuer, size_t issuer_len, + time_t this_update, time_t next_update, + const uint8_t *revoked_certs, size_t revoked_certs_len, + const uint8_t *crl_exts, size_t crl_exts_len, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen); +int x509_crl_from_der_ex( + int *version, + int *inner_sig_alg, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + const uint8_t **exts, size_t *exts_len, + int *sig_alg, const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen); +int x509_crl_check(const uint8_t *a, size_t alen, time_t now); +int x509_crl_verify(const uint8_t *a, size_t alen, + const SM2_KEY *sign_pub_key, const char *signer_id, size_t signer_id_len); +int x509_crl_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen, + const char *signer_id, size_t signer_id_len); +int x509_crl_get_details(const uint8_t *crl, size_t crl_len, + int *version, + int *inner_sig_alg, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, + time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + const uint8_t **exts, size_t *exts_len, + int *signature_algor, + const uint8_t **sig, size_t *siglen); +int x509_crl_get_issuer(const uint8_t *crl, size_t crl_len, + const uint8_t **issuer, size_t *issuer_len); +int x509_crl_get_revoked_certs(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen); +int x509_crl_find_revoked_cert_by_serial_number(const uint8_t *a, size_t alen, + const uint8_t *serial, size_t serial_len, time_t *revoke_date, + const uint8_t **entry_exts, size_t *entry_exts_len); + +int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_crl_new_from_uri(uint8_t **crl, size_t *crl_len, const char *uri, size_t urilen); +int x509_crl_new_from_cert(uint8_t **crl, size_t *crl_len, const uint8_t *cert, size_t certlen); +int x509_cert_check_crl(const uint8_t *cert, size_t certlen, const uint8_t *cacert, size_t cacertlen, + const char *ca_signer_id, size_t ca_signer_id_len); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/x509_ext.h b/Core/GmSSL-3.1.1/include/gmssl/x509_ext.h new file mode 100644 index 0000000..0765fd8 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/x509_ext.h @@ -0,0 +1,641 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_X509_EXT_H +#define GMSSL_X509_EXT_H + + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +enum { + X509_non_critical = 0, + X509_critical = 1, +}; + +/* +Extensions: + + 1. AuthorityKeyIdentifier SEQUENCE AuthorityKeyIdentifier MUST non-critical + 2. SubjectKeyIdentifier OCTET STRING MUST non-critical + 3. KeyUsage BIT STRING SHOULD critical + 4. CertificatePolicies SEQUENCE OF SEQUENCE CertificatePolicies + 5. PolicyMappings SEQUENCE OF SEQUENCE PolicyMappings SHOULD critical + 6. SubjectAltName SEQUENCE OF SEQUENCE GeneralNames SHOULD non-critical + 7. IssuerAltName SEQUENCE OF SEQUENCE GeneralNames SHOULD non-critical + 8. SubjectDirectoryAttributes SEQUENCE OF SEQUENCE Attributes MUST non-critical + 9. BasicConstraints SEQUENCE BasicConstraints CA: MUST critical, End-entity: MAY critical or non-critical + 10. NameConstraints SEQUENCE NameConstraints + 11. PolicyConstraints SEQUENCE PolicyConstraints MUST critical + 12. ExtKeyUsageSyntax SEQUENCE OF OBJECT IDENTIFIER MAY critical or non-critical + 13. CRLDistributionPoints SEQUENCE OF SEQUENCE DistributionPoints + 14. InhibitAnyPolicy INTEGER MUST critical + 15. FreshestCRL SEQUENCE OF SEQUENCE DistributionPoints MUST non-critical +*/ + +int x509_exts_add_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len); +int x509_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + const SM2_KEY *public_key); +int x509_exts_add_subject_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_exts_add_subject_key_identifier_ex(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const SM2_KEY *subject_key); +int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int bits); +int x509_exts_add_certificate_policies(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_exts_add_policy_mappings(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_exts_add_subject_alt_name(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_exts_add_issuer_alt_name(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_exts_add_subject_directory_attributes(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_exts_add_name_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const uint8_t *permitted_subtrees, size_t permitted_subtrees_len, + const uint8_t *excluded_subtrees, size_t excluded_subtrees_len); +int x509_exts_add_policy_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + int require_explicit_policy, int inhibit_policy_mapping); +int x509_exts_add_basic_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int ca, int path_len_constraint); +int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const int *key_purposes, size_t key_purposes_cnt); +int x509_exts_add_crl_distribution_points_ex(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int oid, + const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen); +int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen); +int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int skip_certs); +int x509_exts_add_freshest_crl(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_exts_add_authority_info_access(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *ca_issuers_uri, size_t ca_issuers_urilen, // ca_issuers_uri is the URI (http://examaple.com/subCA.crt) of DER-encoded CA cert + const char *ocsp_uri, size_t ocsp_urilen); + +int x509_exts_add_sequence(uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, const uint8_t *d, size_t dlen); + +/* +OtherName ::= SEQUENCE { + type-id OBJECT IDENTIFIER, -- known oid from x509_rdn_oid such as OID_at_common_name, or oid nodes + value [0] EXPLICIT ANY DEFINED BY type-id } +*/ +int x509_other_name_to_der( + const uint32_t *nodes, size_t nodes_count, + const uint8_t *value, size_t value_len, + uint8_t **out, size_t *outlen); +int x509_other_name_from_der( + uint32_t *nodes, size_t *nodes_count, + const uint8_t **value, size_t *valuelen, + const uint8_t **in, size_t *inlen); +int x509_other_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +EDIPartyName ::= SEQUENCE { + nameAssigner [0] EXPLICIT DirectoryString OPTIONAL, + partyName [1] EXPLICIT DirectoryString } +*/ +int x509_edi_party_name_to_der( + int assigner_tag, const uint8_t *assigner, size_t assigner_len, + int party_name_tag, const uint8_t *party_name, size_t party_name_len, + uint8_t **out, size_t *outlen); +int x509_edi_party_name_from_der( + int *assigner_tag, const uint8_t **assigner, size_t *assigner_len, + int *party_name_tag, const uint8_t **party_name, size_t *party_name_len, + const uint8_t **in, size_t *inlen); +int x509_edi_party_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +GeneralName ::= CHOICE { + otherName [0] IMPLICIT OtherName, -- Only in GeneralName + rfc822Name [1] IMPLICIT IA5String, + dNSName [2] IMPLICIT IA5String, + x400Address [3] IMPLICIT ORAddress, + directoryName [4] IMPLICIT Name, -- SEQENCE OF + ediPartyName [5] IMPLICIT EDIPartyName, -- Only in GeneralName + uniformResourceIdentifier [6] IMPLICIT IA5String, + iPAddress [7] IMPLICIT OCTET STRING, -- 4 bytes or string? + registeredID [8] IMPLICIT OBJECT IDENTIFIER } +*/ +typedef enum { + X509_gn_other_name = 0, + X509_gn_rfc822_name = 1, + X509_gn_dns_name = 2, + X509_gn_x400_address = 3, + X509_gn_directory_name = 4, + X509_gn_edi_party_name = 5, + X509_gn_uniform_resource_identifier = 6, + X509_gn_ip_address = 7, + X509_gn_registered_id = 8, +} X509_GENERAL_NAME_CHOICE; + +int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int x509_general_name_print(FILE *fp, int fmt, int ind, const char *label, int choice, const uint8_t *d, size_t dlen); + +/* +GeneralNames ::= SEQUENCE OF GeneralName +*/ +#define x509_general_names_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) +#define x509_general_names_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) +int x509_general_names_add_general_name(uint8_t *gns, size_t *gnslen, size_t maxlen, + int choice, const uint8_t *d, size_t dlen); +int x509_general_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_general_names_add_other_name(uint8_t *gns, size_t *gnslen, size_t maxlen, + const uint32_t *nodes, size_t nodes_count, + const uint8_t *value, size_t value_len); +#define x509_general_names_add_rfc822_name(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_rfc822_name,(uint8_t*)s,strlen(s)) +#define x509_general_names_add_dns_name(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_dns_name,(uint8_t*)s,strlen(s)) +#define x509_general_names_add_x400_address(a,alen,maxlen,d,dlen) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_x400_address,d,dlen) +#define x509_general_names_add_directory_name(a,alen,maxlen,d,dlen) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_directory_name,d,dlen) +int x509_general_names_add_edi_party_name(uint8_t *gns, size_t *gnslen, size_t maxlen, + int assigner_tag, const uint8_t *assigner, size_t assigner_len, + int party_name_tag, const uint8_t *party_name, size_t party_name_len); +#define x509_general_names_add_uniform_resource_identifier(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_uniform_resource_identifier,(uint8_t*)s,strlen(s)) +#define x509_general_names_add_ip_address(a,alen,maxlen,s) x509_general_names_add_general_name(a,alen,maxlen,X509_gn_ip_address,(uint8_t*)s,strlen(s)) +int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t maxlen, + const uint32_t *nodes, size_t nodes_cnt); + +int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen, uint8_t **out, size_t *outlen); +#define x509_uri_as_general_names_to_der(uri,urilen,out,outlen) x509_uri_as_general_names_to_der_ex(ASN1_TAG_SEQUENCE,uri,urilen,out,outlen) + +/* +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] IMPLICIT OCTET STRING OPTIONAL, + authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL, + authorityCertSerialNumber [2] IMPLICIT INTEGER OPTIONAL } +*/ +int x509_authority_key_identifier_to_der( + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + uint8_t **out, size_t *outlen); +int x509_authority_key_identifier_from_der( + const uint8_t **keyid, size_t *keyid_len, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial, size_t *serial_len, + const uint8_t **in, size_t *inlen); +int x509_authority_key_identifier_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +SubjectKeyIdentifier ::= OCTET STRING +*/ +#define X509_SUBJECT_KEY_IDENTIFIER_MIN_LEN 16 +#define X509_SUBJECT_KEY_IDENTIFIER_MAX_LEN 64 + +/* +KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), -- recent renamed contentCommitment + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) } +*/ +#define X509_KU_DIGITAL_SIGNATURE (1 << 0) +#define X509_KU_NON_REPUDIATION (1 << 1) +#define X509_KU_KEY_ENCIPHERMENT (1 << 2) +#define X509_KU_DATA_ENCIPHERMENT (1 << 3) +#define X509_KU_KEY_AGREEMENT (1 << 4) +#define X509_KU_KEY_CERT_SIGN (1 << 5) +#define X509_KU_CRL_SIGN (1 << 6) +#define X509_KU_ENCIPHER_ONLY (1 << 7) +#define X509_KU_DECIPHER_ONLY (1 << 8) + +const char *x509_key_usage_name(int flag); +int x509_key_usage_from_name(int *flag, const char *name); +#define x509_key_usage_to_der(bits,out,outlen) asn1_bits_to_der(bits,out,outlen) +#define x509_key_usage_from_der(bits,in,inlen) asn1_bits_from_der(bits,in,inlen) +int x509_key_usage_check(int bits, int cert_type); +int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, int bits); + +/* +DisplayText ::= CHOICE { + ia5String IA5String (SIZE (1..200)), + visibleString VisibleString (SIZE (1..200)), + bmpString BMPString (SIZE (1..200)), + utf8String UTF8String (SIZE (1..200)) +} +*/ +#define X509_DISPLAY_TEXT_MIN_LEN 1 +#define X509_DISPLAY_TEXT_MAX_LEN 200 + +int x509_display_text_check(int tag, const uint8_t *d, size_t dlen); +int x509_display_text_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_display_text_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int x509_display_text_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen); + +/* +NoticeReference ::= SEQUENCE { + organization DisplayText, + noticeNumbers SEQUENCE OF INTEGER } + +UserNotice ::= SEQUENCE { + noticeRef NoticeReference OPTIONAL, + explicitText DisplayText OPTIONAL } +*/ +#define X509_MAX_NOTICE_NUMBERS 32 + +int x509_notice_reference_to_der( + int org_tag, const uint8_t *org, size_t org_len, + const int *notice_numbers, size_t notice_numbers_cnt, + uint8_t **out, size_t *outlen); +int x509_notice_reference_from_der( + int *org_tag, const uint8_t **org, size_t *org_len, + int *notice_numbers, size_t *notice_numbers_cnt, size_t max_notice_numbers, + const uint8_t **in, size_t *inlen); +int x509_notice_reference_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_user_notice_to_der( + int notice_ref_org_tag, const uint8_t *notice_ref_org, size_t notice_ref_org_len, + const int *notice_ref_notice_numbers, size_t notice_ref_notice_numbers_cnt, + int explicit_text_tag, const uint8_t *explicit_text, size_t explicit_text_len, + uint8_t **out, size_t *outlen); +int x509_user_notice_from_der( + int *notice_ref_org_tag, const uint8_t **notice_ref_org, size_t *notice_ref_org_len, + int *notice_ref_notice_numbers, size_t *notice_ref_notice_numbers_cnt, size_t max_notice_ref_notice_numbers, + int *explicit_text_tag, const uint8_t **explicit_text, size_t *explicit_text_len, + const uint8_t **in, size_t *inlen); +int x509_user_notice_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +PolicyQualifierInfo ::= SEQUENCE { + policyQualifierId PolicyQualifierId, + qualifier ANY DEFINED BY policyQualifierId } + +id-qt + OID_qt_cps + OID_qt_unotice + + switch(policyQualifierId) + case id-qt-cps : qualifier ::= IA5String + case id-qt-unotice : qualifier ::= UserNotice +*/ +const char *x509_qualifier_id_name(int oid); +int x509_qualifier_id_from_name(const char *name); +int x509_qualifier_id_from_der(int *oid, const uint8_t **in, size_t *inlen); +int x509_qualifier_id_to_der(int oid, uint8_t **out, size_t *outlen); + +int x509_policy_qualifier_info_to_der( + int oid, + const uint8_t *qualifier, size_t qualifier_len, + uint8_t **out, size_t *outlen); +int x509_policy_qualifier_info_from_der( + int *oid, + const uint8_t **qualifier, size_t *qualifier_len, + const uint8_t **in, size_t *inlen); +int x509_policy_qualifier_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +#define x509_policy_qualifier_infos_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) +#define x509_policy_qualifier_infos_from_der(d,dlen,in,ineln) asn1_sequence_from_der(d,dlen,in,inlen) +int x509_policy_qualifier_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +PolicyInformation ::= SEQUENCE { + policyIdentifier CertPolicyId, + policyQualifiers SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo OPTIONAL } + +CertPolicyId ::= OBJECT IDENTIFIER -- undefined + + OID_any_policy +*/ +char *x509_cert_policy_id_name(int oid); +int x509_cert_policy_id_from_name(const char *name); +int x509_cert_policy_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen); +int x509_cert_policy_id_to_der(int oid, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen); + +int x509_policy_information_to_der( + int policy_oid, const uint32_t *policy_nodes, size_t policy_nodes_cnt, + const uint8_t *qualifiers, size_t qualifiers_len, + uint8_t **out, size_t *outlen); +int x509_policy_information_from_der( + int *policy_oid, uint32_t *policy_nodes, size_t *policy_nodes_cnt, + const uint8_t **qualifiers, size_t *qualifiers_len, + const uint8_t **in, size_t *inlen); +int x509_policy_information_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation +*/ +int x509_certificate_policies_add_policy_information(uint8_t *d, size_t *dlen, size_t maxlen, + int policy_oid, const uint32_t *policy_nodes, size_t policy_nodes_cnt, + const uint8_t *qualifiers, size_t qualifiers_len); +int x509_certificate_policies_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +#define x509_certificate_policies_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) +#define x509_certificate_policies_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) + +/* +PolicyMapping ::= SEQUENCE { + issuerDomainPolicy CertPolicyId, -- id-anyPolicy or other undefined + subjectDomainPolicy CertPolicyId } +*/ +int x509_policy_mapping_to_der( + int issuer_policy_oid, const uint32_t *issuer_policy_nodes, size_t issuer_policy_nodes_cnt, + int subject_policy_oid, const uint32_t *subject_policy_nodes, size_t subject_policy_nodes_cnt, + uint8_t **out, size_t *outlen); +int x509_policy_mapping_from_der( + int *issuer_policy_oid, uint32_t *issuer_policy_nodes, size_t *issuer_policy_nodes_cnt, + int *subject_policy_oid, uint32_t *subject_policy_nodes, size_t *subject_policy_nodes_cnt, + const uint8_t **in, size_t *inlen); +int x509_policy_mapping_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +PolicyMappings ::= SEQUENCE OF PolicyMapping +*/ +int x509_policy_mappings_add_policy_mapping(uint8_t *d, size_t *dlen, size_t maxlen, + int issuer_policy_oid, const uint32_t *issuer_policy_nodes, size_t issuer_policy_nodes_cnt, + int subject_policy_oid, const uint32_t *subject_policy_nodes, size_t subject_policy_nodes_cnt); +int x509_policy_mappings_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +#define x509_policy_mappings_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) +#define x509_policy_mappings_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) + +/* +SubjectAltName ::= GeneralNames +*/ +#define x509_subject_alt_name_print(fp,fmt,ind,label,d,dlen) x509_general_names_print(fp,fmt,ind,label,d,dlen) + +/* +IssuerAltName ::= GeneralNames +*/ +#define x509_issuer_alt_name_print(fp,fmt,ind,label,d,dlen) x509_general_names_print(fp,fmt,ind,label,d,dlen) + +/* +SubjectDirectoryAttributes ::= SEQUENCE OF Attribute + +Attribute ::= SEQUENCE { + type OBJECT IDENTIFIER, + values SET OF ANY } +*/ +int x509_attribute_to_der( + const uint32_t *nodes, size_t nodes_cnt, + const uint8_t *values, size_t values_len, + uint8_t **out, size_t *outlen); +int x509_attribute_from_der( + int *oid, uint32_t *nodes, size_t *nodes_cnt, + const uint8_t **values, size_t *values_len, + const uint8_t **in, size_t *inlen); +int x509_attribute_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_attributes_add_attribute(uint8_t *d, size_t *dlen, size_t maxlen, + const uint32_t *nodes, size_t nodes_cnt, + const uint8_t *values, size_t values_len); +int x509_attributes_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +#define x509_attributes_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) +#define x509_attributes_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) + +/* +BasicConstraints ::= SEQUENCE { + cA BOOLEAN DEFAULT FALSE, + pathLenConstraint INTEGER (0..MAX) OPTIONAL } +*/ +#define X509_MAX_PATH_LEN_CONSTRAINT 6 +int x509_basic_constraints_to_der(int ca, int path_len_cons, uint8_t **out, size_t *outlen); +int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t **in, size_t *inlen); +int x509_basic_constraints_check(int ca, int path_len_cons, int cert_type); +int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +GeneralSubtree ::= SEQUENCE { + base GeneralName, + minimum [0] IMPLICIT BaseDistance DEFAULT 0, + maximum [1] IMPLICIT BaseDistance OPTIONAL } + +BaseDistance ::= INTEGER (0..MAX) +*/ +int x509_general_subtree_to_der( + int base_choice, const uint8_t *base, size_t base_len, + int minimum, int maximum, + uint8_t **out, size_t *outlen); +int x509_general_subtree_from_der( + int *base_choice, const uint8_t **base, size_t *base_len, + int *minimum, int *maximum, + const uint8_t **in, size_t *inlen); +int x509_general_subtree_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree +*/ +int x509_general_subtrees_add_general_subtree(uint8_t *d, size_t *dlen, size_t maxlen, + int base_choice, const uint8_t *base, size_t base_len, + int minimum, int maximum); +int x509_general_subtrees_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +#define x509_general_subtrees_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) +#define x509_general_subtrees_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) + +/* +NameConstraints ::= SEQUENCE { + permittedSubtrees [0] GeneralSubtrees OPTIONAL, + excludedSubtrees [1] GeneralSubtrees OPTIONAL } +*/ +int x509_name_constraints_to_der( + const uint8_t *permitted_subtrees, size_t permitted_subtrees_len, + const uint8_t *excluded_subtrees, size_t excluded_subtrees_len, + uint8_t **out, size_t *outlen); +int x509_name_constraints_from_der( + const uint8_t **permitted_subtrees, size_t *permitted_subtrees_len, + const uint8_t **excluded_subtrees, size_t *excluded_subtrees_len, + const uint8_t **in, size_t *inlen); +int x509_name_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +PolicyConstraints ::= SEQUENCE { + requireExplicitPolicy [0] IMPLICIT SkipCerts OPTIONAL, + inhibitPolicyMapping [1] IMPLICIT SkipCerts OPTIONAL +} + +SkipCerts ::= INTEGER (0..MAX) +*/ +int x509_policy_constraints_to_der(int require_explicit_policy, int inhibit_policy_mapping, uint8_t **out, size_t *outlen); +int x509_policy_constraints_from_der(int *require_explicit_policy, int *inhibit_policy_mapping, const uint8_t **in, size_t *inlen); +int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + +KeyPurposeId: + OID_any_extended_key_usage + id-kp + OID_kp_server_auth + OID_kp_client_auth + OID_kp_code_signing + OID_kp_email_protection + OID_kp_time_stamping + OID_kp_ocsp_signing +*/ +#define X509_MAX_KEY_PURPOSES 7 +const char *x509_key_purpose_name(int oid); +const char *x509_key_purpose_text(int oid); +int x509_key_purpose_from_name(const char *name); +int x509_key_purpose_from_der(int *oid, const uint8_t **in, size_t *inlen); +int x509_key_purpose_to_der(int oid, uint8_t **out, size_t *outlen); + +int x509_ext_key_usage_to_der(const int *oids, size_t oids_cnt, uint8_t **out, size_t *outlen); +int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, const uint8_t **in, size_t *inlen); +int x509_ext_key_usage_check(const int *oids, size_t oids_cnt, int cert_type); +int x509_ext_key_usage_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +ReasonFlags ::= BIT STRING { + unused (0), + keyCompromise (1), + cACompromise (2), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5), + certificateHold (6), + privilegeWithdrawn (7), + aACompromise (8) } +*/ +#define X509_RF_UNUSED (1 << 0) +#define X509_RF_KEY_COMPROMISE (1 << 1) +#define X509_RF_CA_COMPROMISE (1 << 2) +#define X509_RF_AFFILIATION_CHANGED (1 << 3) +#define X509_RF_SUPERSEDED (1 << 4) +#define X509_RF_CESSATION_OF_OPERATION (1 << 5) +#define X509_RF_CERTIFICATE_HOLD (1 << 6) +#define X509_RF_PRIVILEGE_WITHDRAWN (1 << 7) +#define X509_RF_AA_COMPROMISE (1 << 8) + +const char *x509_revoke_reason_flag_name(int flag); +int x509_revoke_reason_flag_from_name(int *flag, const char *name); +#define x509_revoke_reason_flags_to_der(bits,out,outlen) asn1_bits_to_der(bits,out,outlen) +#define x509_revoke_reason_flags_from_der(bits,in,inlen) asn1_bits_from_der(bits,in,inlen) +int x509_revoke_reason_flags_print(FILE *fp, int fmt, int ind, const char *label, int bits); + +/* +DistributionPointName ::= CHOICE { + fullName [0] IMPLICIT GeneralNames, -- SEQUENCE OF + nameRelativeToCRLIssuer [1] IMPLICIT RelativeDistinguishedName } -- SET OF +*/ +enum { + X509_full_name = 0, + X509_name_relative_to_crl_issuer = 1, +}; + +int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen, uint8_t **out, size_t *outlen); +int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int x509_uri_as_distribution_point_name_from_der(const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen); +int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label,const uint8_t *a, size_t alen); + +int x509_uri_as_explicit_distribution_point_name_to_der(int index, const char *uri, size_t urilen, uint8_t **out, size_t *outlen); +int x509_uri_as_explicit_distribution_point_name_from_der(int index, const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen); + +/* +DistributionPoint ::= SEQUENCE { + distributionPoint [0] EXPLICIT DistributionPointName OPTIONAL, + reasons [1] IMPLICIT ReasonFlags OPTIONAL, + cRLIssuer [2] IMPLICIT GeneralNames OPTIONAL } +*/ +int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen, + int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len, + uint8_t **out, size_t *outlen); +int x509_uri_as_distribution_point_from_der(const char **uri, size_t *urilen, + int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len, + const uint8_t **in, size_t *inlen); +int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +DistributionPoints ::= SEQUENCE OF DistributionPoint +*/ +int x509_uri_as_distribution_points_to_der(const char *uri, size_t urilen, + int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len, + uint8_t **out, size_t *outlen); +int x509_uri_as_distribution_points_from_der(const char **uri, size_t *urilen, + int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len, + const uint8_t **in, size_t *inlen); +int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +/* +CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint +*/ +#define x509_crl_distribution_points_to_der(d,dlen,out,outlen) x509_distribution_points_to_der(d,dlen,out,outlen) +#define x509_crl_distribution_points_from_der(d,dlen,in,inlen) x509_distribution_points_from_der(d,dlen,in,inlen) +#define x509_crl_distribution_points_print(fp,fmt,ind,label,d,dlen) x509_distribution_points_print(fp,fmt,ind,label,d,dlen) + + +/* +InhibitAnyPolicy ::= SkipCerts +SkipCerts ::= INTEGER (0..MAX) +*/ +#define x509_inhibit_any_policy_to_der(val,out,outlen) asn1_int_to_der(val,out,outlen) +#define x509_inhibit_any_policy_from_der(val,in,inlen) asn1_int_from_der(val,in,inlen) + +/* +FreshestCRL ::= CRLDistributionPoints + */ +#define x509_freshest_crl_to_der(d,dlen,out,outlen) x509_crl_distribution_points_to_der(d,dlen,out,outlen) +#define x509_freshest_crl_from_der(d,dlen,in,inlen) x509_crl_distribution_points_from_der(d,dlen,in,inlen) +#define x509_freshest_crl_print(fp,fmt,ind,label,d,dlen) x509_crl_distribution_points_print(fp,fmt,ind,label,d,dlen) + +/* +Netscape-Defined Certificate Extensions +https://docs.oracle.com/cd/E19957-01/816-5533-10/ext.htm#1023061 + +NetscapeCertType ::= BIT STRING + + bit 0: SSL Client certificate + bit 1: SSL Server certificate + bit 2: S/MIME certificate + bit 3: Object-signing certificate + bit 4: Reserved for future use + bit 5: SSL CA certificate + bit 6: S/MIME CA certificate + bit 7: Object-signing CA certificate + +NetscapeCertComment ::= IA5String +*/ +int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label, int bits); + +int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type, + int *path_len_constraints); + +/* +AuthorityInfoAccessSyntax ::= SEQUENCE OF AccessDescription + +AccessDescription ::= SEQUENCE { + accessMethod OBJECT IDENTIFIER, + accessLocation GeneralName } + +accessMethods: + OID_ad_ca_issuers + OID_ad_ocsp +*/ +const char *x509_access_method_name(int oid); +int x509_access_method_from_name(const char *name); +int x509_access_method_to_der(int oid, uint8_t **out, size_t *outlen); +int x509_access_method_from_der(int *oid, const uint8_t **in, size_t *inlen); + +int x509_access_description_to_der(int oid, const char *uri, size_t urilen, uint8_t **out, size_t *outlen); +int x509_access_description_from_der(int *oid, const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen); +int x509_access_description_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_authority_info_access_to_der( + const char *ca_issuers_uri, size_t ca_issuers_urilen, + const char *ocsp_uri, size_t ocsp_urilen, + uint8_t **out, size_t *outlen); +int x509_authority_info_access_from_der( + const char **ca_issuers_uri, size_t *ca_issuers_urilen, + const char **ocsp_uri, size_t *ocsp_urilen, + const uint8_t **in, size_t *inlen); +int x509_authority_info_access_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/Core/GmSSL-3.1.1/include/gmssl/x509_req.h b/Core/GmSSL-3.1.1/include/gmssl/x509_req.h new file mode 100644 index 0000000..43536ae --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/x509_req.h @@ -0,0 +1,81 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_X509_REQ_H +#define GMSSL_X509_REQ_H + + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +from RFC 2986 + +CertificationRequestInfo ::= SEQUENCE { + version INTEGER { v1(0) }, + subject Name, + subjectPKInfo SubjectPublicKeyInfo, + attributes [0] IMPLICIT SET OF Attribute } +*/ +int x509_request_info_to_der(int version, const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, const uint8_t *attrs, size_t attrs_len, + uint8_t **out, size_t *outlen); +int x509_request_info_from_der(int *version, const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, const uint8_t **attrs, size_t *attrs_len, + const uint8_t **in, size_t *inlen); +int x509_request_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +/* +CertificationRequest ::= SEQUENCE { + certificationRequestInfo CertificationRequestInfo, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING } +*/ +int x509_req_sign_to_der( + int version, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *attrs, size_t attrs_len, + int signature_algor, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen); +int x509_req_verify(const uint8_t *req, size_t reqlen, + const char *signer_id, size_t signer_id_len); +int x509_req_get_details(const uint8_t *req, size_t reqlen, + int *verison, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **attributes, size_t *attributes_len, + int *signature_algor, + const uint8_t **signature, size_t *signature_len); +int x509_req_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen); +int x509_req_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen); +int x509_req_to_pem(const uint8_t *req, size_t reqlen, FILE *fp); +int x509_req_from_pem(uint8_t *req, size_t *reqlen, size_t maxlen, FILE *fp); +int x509_req_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *req, size_t reqlen); + +int x509_req_new_from_pem(uint8_t **req, size_t *reqlen, FILE *fp); +int x509_req_new_from_file(uint8_t **req, size_t *reqlen, const char *file); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/include/gmssl/zuc.h b/Core/GmSSL-3.1.1/include/gmssl/zuc.h new file mode 100644 index 0000000..20db893 --- /dev/null +++ b/Core/GmSSL-3.1.1/include/gmssl/zuc.h @@ -0,0 +1,147 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_ZUC_H +#define GMSSL_ZUC_H + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +ZUC Public API + + ZUC_KEY_SIZE + ZUC_IV_SIZE + ZUC_MAC_SIZE + + ZUC_CTX + zuc_encrypt_init + zuc_encrypt_update + zuc_encrypt_finish + zuc_decrypt_init + zuc_decrypt_update + zuc_decrypt_finish + + ZUC_MAC_CTX + zuc_mac_init + zuc_mac_update + zuc_mac_finish + + zuc_eea_encrypt + zuc_eia_generate_mac +*/ + + +# define ZUC_KEY_SIZE 16 +# define ZUC_IV_SIZE 16 +# define ZUC_MAC_SIZE 4 + +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; + +typedef struct { + ZUC_UINT31 LFSR[16]; + ZUC_UINT32 R1; + ZUC_UINT32 R2; +} ZUC_STATE; + +void zuc_init(ZUC_STATE *state, const uint8_t key[ZUC_KEY_SIZE], const uint8_t iv[ZUC_IV_SIZE]); +void zuc_generate_keystream(ZUC_STATE *state, size_t nwords, ZUC_UINT32 *words); +ZUC_UINT32 zuc_generate_keyword(ZUC_STATE *state); +void zuc_encrypt(ZUC_STATE *state, const uint8_t *in, size_t inlen, uint8_t *out); + +typedef struct ZUC_MAC_CTX_st { + ZUC_UINT31 LFSR[16]; + ZUC_UINT32 R1; + ZUC_UINT32 R2; + ZUC_UINT32 T; + ZUC_UINT32 K0; + uint8_t buf[4]; + size_t buflen; +} ZUC_MAC_CTX; + +void zuc_mac_init(ZUC_MAC_CTX *ctx, const uint8_t key[ZUC_KEY_SIZE], const uint8_t iv[ZUC_IV_SIZE]); +void zuc_mac_update(ZUC_MAC_CTX *ctx, const uint8_t *data, size_t len); +void zuc_mac_finish(ZUC_MAC_CTX *ctx, const uint8_t *data, size_t nbits, uint8_t mac[ZUC_MAC_SIZE]); + +#define ZUC_EEA_ENCRYPT_NWORDS(nbits) ((nbits + 31)/32) +#define ZUC_EEA_ENCRYPT_NBYTES(nbits) (ZUC_EEA_ENCRYPT_NWORDS(nbits)*4) +void zuc_eea_encrypt(const ZUC_UINT32 *in, ZUC_UINT32 *out, size_t nbits, + const uint8_t key[ZUC_KEY_SIZE], ZUC_UINT32 count, ZUC_UINT5 bearer, + ZUC_BIT direction); +ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits, + const uint8_t key[ZUC_KEY_SIZE], ZUC_UINT32 count, ZUC_UINT5 bearer, + ZUC_BIT direction); + + +# define ZUC256_KEY_SIZE 32 +# define ZUC256_IV_SIZE 23 +# define ZUC256_MAC32_SIZE 4 +# define ZUC256_MAC64_SIZE 8 +# define ZUC256_MAC128_SIZE 16 +# define ZUC256_MIN_MAC_SIZE ZUC256_MAC32_SIZE +# define ZUC256_MAX_MAC_SIZE ZUC256_MAC128_SIZE + +typedef ZUC_STATE ZUC256_STATE; + +void zuc256_init(ZUC256_STATE *state, const uint8_t key[ZUC256_KEY_SIZE], const uint8_t iv[ZUC256_IV_SIZE]); +#define zuc256_generate_keystream(state,nwords,words) zuc_generate_keystream(state,nwords,words) +#define zuc256_generate_keyword(state) zuc_generate_keyword(state) + + +typedef struct ZUC256_MAC_CTX_st { + ZUC_UINT31 LFSR[16]; + ZUC_UINT32 R1; + ZUC_UINT32 R2; + ZUC_UINT32 T[4]; + ZUC_UINT32 K0[4]; + uint8_t buf[4]; + size_t buflen; + int macbits; +} ZUC256_MAC_CTX; + +void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const uint8_t key[ZUC256_KEY_SIZE], + const uint8_t iv[ZUC256_IV_SIZE], int macbits); +void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t len); +void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t nbits, uint8_t mac[ZUC_MAC_SIZE]); + + +// Public API + +typedef struct { + ZUC_STATE zuc_state; + uint8_t block[4]; + size_t block_nbytes; +} ZUC_CTX; + +int zuc_encrypt_init(ZUC_CTX *ctx, const uint8_t key[ZUC_KEY_SIZE], const uint8_t iv[ZUC_IV_SIZE]); +int zuc_encrypt_update(ZUC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +int zuc_encrypt_finish(ZUC_CTX *ctx, uint8_t *out, size_t *outlen); + +#define zuc_decrypt_init(ctx,key,iv) zuc_encrypt_init(ctx,key,iv) +#define zuc_decrypt_update(ctx,in,inlen,out,outlen) zuc_encrypt_update(ctx,in,inlen,out,outlen) +#define zuc_decrypt_finish(ctx,out,outlen) zuc_encrypt_finish(ctx,out,outlen) + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/src/aead.c b/Core/GmSSL-3.1.1/src/aead.c new file mode 100644 index 0000000..7dcbe73 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/aead.c @@ -0,0 +1,534 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +int sm4_cbc_sm3_hmac_encrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen) +{ + if (!ctx || !key || !iv || (!aad && aadlen)) { + error_print(); + return -1; + } + if (keylen != 48 || ivlen != 16) { + error_print(); + return -1; + } + memset(ctx, 0, sizeof(*ctx)); + if (sm4_cbc_encrypt_init(&ctx->enc_ctx, key, iv) != 1) { + error_print(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +int sm4_cbc_sm3_hmac_encrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_cbc_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + return 1; +} + +int sm4_cbc_sm3_hmac_encrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_cbc_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + sm3_hmac_finish(&ctx->mac_ctx, out + *outlen); + *outlen += SM3_HMAC_SIZE; + return 1; +} + +int sm4_cbc_sm3_hmac_decrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen) +{ + if (!ctx || !key || !iv || (!aad && aadlen)) { + error_print(); + return -1; + } + if (keylen != 48 || ivlen != 16) { + error_print(); + return -1; + } + memset(ctx, 0, sizeof(*ctx)); + if (sm4_cbc_decrypt_init(&ctx->enc_ctx, key, iv) != 1) { + error_print(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +int sm4_cbc_sm3_hmac_decrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t len; + + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen > SM3_HMAC_SIZE) { + error_print(); + return -1; + } + + if (ctx->maclen < SM3_HMAC_SIZE) { + len = SM3_HMAC_SIZE - ctx->maclen; + if (inlen <= len) { + memcpy(ctx->mac + ctx->maclen, in, inlen); + ctx->maclen += inlen; + return 1; + } else { + memcpy(ctx->mac + ctx->maclen, in, len); + ctx->maclen += len; + in += len; + inlen -= len; + } + } + + if (inlen <= SM3_HMAC_SIZE) { + uint8_t tmp[SM3_HMAC_SIZE]; + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, inlen); + if (sm4_cbc_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + len = SM3_HMAC_SIZE - inlen; + memcpy(tmp, ctx->mac + inlen, len); + memcpy(tmp + len, in, inlen); + memcpy(ctx->mac, tmp, SM3_HMAC_SIZE); + } else { + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, SM3_HMAC_SIZE); + if (sm4_cbc_decrypt_update(&ctx->enc_ctx, ctx->mac, SM3_HMAC_SIZE, out, outlen) != 1) { + error_print(); + return -1; + } + out += *outlen; + + inlen -= SM3_HMAC_SIZE; + sm3_hmac_update(&ctx->mac_ctx, in, inlen); + if (sm4_cbc_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { + error_print(); + return -1; + } + *outlen += len; + memcpy(ctx->mac, in + inlen, SM3_HMAC_SIZE); + } + return 1; +} + +int sm4_cbc_sm3_hmac_decrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[SM3_HMAC_SIZE]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen != SM3_HMAC_SIZE) { + error_print(); + return -1; + } + sm3_hmac_finish(&ctx->mac_ctx, mac); + if (sm4_cbc_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + if (memcmp(mac, ctx->mac, SM3_HMAC_SIZE) != 0) { + error_print(); + return -1; + } + memset(ctx->mac, 0, SM3_HMAC_SIZE); + ctx->maclen = 0; + return 1; +} + +int sm4_ctr_sm3_hmac_encrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen) +{ + if (!ctx || !key || !iv || (!aad && aadlen)) { + error_print(); + return -1; + } + if (keylen != 48 || ivlen != 16) { + error_print(); + return -1; + } + memset(ctx, 0, sizeof(*ctx)); + if (sm4_ctr_encrypt_init(&ctx->enc_ctx, key, iv) != 1) { + error_print(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +int sm4_ctr_sm3_hmac_encrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + return 1; +} + +int sm4_ctr_sm3_hmac_encrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + sm3_hmac_finish(&ctx->mac_ctx, out + *outlen); + *outlen += SM3_HMAC_SIZE; + return 1; +} + +int sm4_ctr_sm3_hmac_decrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen) +{ + if (!ctx || !key || !iv || (!aad && aadlen)) { + error_print(); + return -1; + } + if (keylen != 48 || ivlen != 16) { + error_print(); + return -1; + } + memset(ctx, 0, sizeof(*ctx)); + if (sm4_ctr_decrypt_init(&ctx->enc_ctx, key, iv) != 1) { + error_print(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +int sm4_ctr_sm3_hmac_decrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t len; + + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen > SM3_HMAC_SIZE) { + error_print(); + return -1; + } + + if (ctx->maclen < SM3_HMAC_SIZE) { + len = SM3_HMAC_SIZE - ctx->maclen; + if (inlen <= len) { + memcpy(ctx->mac + ctx->maclen, in, inlen); + ctx->maclen += inlen; + return 1; + } else { + memcpy(ctx->mac + ctx->maclen, in, len); + ctx->maclen += len; + in += len; + inlen -= len; + } + } + + if (inlen <= SM3_HMAC_SIZE) { + uint8_t tmp[SM3_HMAC_SIZE]; + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + len = SM3_HMAC_SIZE - inlen; + memcpy(tmp, ctx->mac + inlen, len); + memcpy(tmp + len, in, inlen); + memcpy(ctx->mac, tmp, SM3_HMAC_SIZE); + } else { + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, SM3_HMAC_SIZE); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, SM3_HMAC_SIZE, out, outlen) != 1) { + error_print(); + return -1; + } + out += *outlen; + + inlen -= SM3_HMAC_SIZE; + sm3_hmac_update(&ctx->mac_ctx, in, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { + error_print(); + return -1; + } + *outlen += len; + memcpy(ctx->mac, in + inlen, SM3_HMAC_SIZE); + } + return 1; +} + +int sm4_ctr_sm3_hmac_decrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[SM3_HMAC_SIZE]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen != SM3_HMAC_SIZE) { + error_print(); + return -1; + } + sm3_hmac_finish(&ctx->mac_ctx, mac); + if (sm4_ctr_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + if (memcmp(mac, ctx->mac, SM3_HMAC_SIZE) != 0) { + error_print(); + return -1; + } + memset(ctx->mac, 0, SM3_HMAC_SIZE); + ctx->maclen = 0; + return 1; +} + +static void ctr_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + +int sm4_gcm_encrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen) +{ + uint8_t H[16] = {0}; + uint8_t Y[16]; + + if (!ctx || !key || !iv || (!aad && aadlen)) { + error_print(); + return -1; + } + if (keylen != 16) { + error_print(); + return -1; + } + if (ivlen < SM4_GCM_MIN_IV_SIZE || ivlen > SM4_GCM_MAX_IV_SIZE) { + error_print(); + return -1; + } + if (taglen < 8 || taglen > 16) { + error_print(); + return -1; + } + + memset(ctx, 0, sizeof(*ctx)); + ctx->taglen = taglen; + + if (sm4_ctr_encrypt_init(&ctx->enc_ctx, key, H) != 1) { + error_print(); + return -1; + } + + sm4_encrypt(&ctx->enc_ctx.sm4_key, H, H); + + ghash_init(&ctx->mac_ctx, H, aad, aadlen); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + sm4_encrypt(&ctx->enc_ctx.sm4_key, Y, ctx->Y); + + ctr_incr(Y); + memcpy(ctx->enc_ctx.ctr, Y, 16); + + gmssl_secure_clear(H, sizeof(H)); + gmssl_secure_clear(Y, sizeof(Y)); + return 1; +} + +int sm4_gcm_encrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + ghash_update(&ctx->mac_ctx, out, *outlen); + return 1; +} + +int sm4_gcm_encrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[16]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + ghash_update(&ctx->mac_ctx, out, *outlen); + ghash_finish(&ctx->mac_ctx, mac); + + gmssl_memxor(mac, mac, ctx->Y, ctx->taglen); + memcpy(out + *outlen, mac, ctx->taglen); + *outlen += ctx->taglen; + + return 1; +} + +int sm4_gcm_decrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen) +{ + return sm4_gcm_encrypt_init(ctx, key, keylen, iv, ivlen, aad, aadlen, taglen); +} + +int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t len; + + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen > ctx->taglen) { + error_print(); + return -1; + } + + if (ctx->maclen < ctx->taglen) { + len = ctx->taglen - ctx->maclen; + if (inlen <= len) { + memcpy(ctx->mac + ctx->maclen, in, inlen); + ctx->maclen += inlen; + return 1; + } else { + memcpy(ctx->mac + ctx->maclen, in, len); + ctx->maclen += len; + in += len; + inlen -= len; + } + } + + if (inlen <= ctx->taglen) { + uint8_t tmp[GHASH_SIZE]; + ghash_update(&ctx->mac_ctx, ctx->mac, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + len = ctx->taglen - inlen; + memcpy(tmp, ctx->mac + inlen, len); + memcpy(tmp + len, in, inlen); + memcpy(ctx->mac, tmp, GHASH_SIZE); + } else { + ghash_update(&ctx->mac_ctx, ctx->mac, ctx->taglen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, ctx->taglen, out, outlen) != 1) { + error_print(); + return -1; + } + out += *outlen; + + inlen -= ctx->taglen; + ghash_update(&ctx->mac_ctx, in, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { + error_print(); + return -1; + } + *outlen += len; + memcpy(ctx->mac, in + inlen, GHASH_SIZE); + } + return 1; +} + +int sm4_gcm_decrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[GHASH_SIZE]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen != ctx->taglen) { + error_print(); + return -1; + } + ghash_finish(&ctx->mac_ctx, mac); + if (sm4_ctr_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + + gmssl_memxor(mac, mac, ctx->Y, ctx->taglen); + if (memcmp(mac, ctx->mac, ctx->taglen) != 0) { + error_print(); + return -1; + } + memset(ctx->mac, 0, GHASH_SIZE); + ctx->maclen = 0; + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/aes.c b/Core/GmSSL-3.1.1/src/aes.c new file mode 100644 index 0000000..004db05 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/aes.c @@ -0,0 +1,443 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +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) +{ + size_t 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); + size_t 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; + size_t 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]; + } + aes_key->rounds = enc_key.rounds; + 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]; + size_t 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]; + size_t 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)); +} diff --git a/Core/GmSSL-3.1.1/src/aes_modes.c b/Core/GmSSL-3.1.1/src/aes_modes.c new file mode 100644 index 0000000..89e5a6e --- /dev/null +++ b/Core/GmSSL-3.1.1/src/aes_modes.c @@ -0,0 +1,208 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include + + +void aes_cbc_encrypt(const AES_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); + aes_encrypt(key, out, out); + iv = out; + in += 16; + out += 16; + } +} + +void aes_cbc_decrypt(const AES_KEY *key, const uint8_t iv[16], + const uint8_t *in, size_t nblocks, uint8_t *out) +{ + while (nblocks--) { + aes_decrypt(key, in, out); + memxor(out, iv, 16); + iv = in; + in += 16; + out += 16; + } +} + +int aes_cbc_padding_encrypt(const AES_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 - inlen % 16; + + if (in) { + memcpy(block, in + inlen - rem, rem); + } + memset(block + rem, padding, padding); + if (inlen/16) { + aes_cbc_encrypt(key, iv, in, inlen/16, out); + out += inlen - rem; + iv = out - 16; + } + aes_cbc_encrypt(key, iv, block, 1, out); + *outlen = inlen - rem + 16; + return 1; +} + +int aes_cbc_padding_decrypt(const AES_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 len = sizeof(block); + int padding; + + if (inlen == 0) { + error_print(); + return 0; + } + if (inlen%16 != 0 || inlen < 16) { + error_print(); + return -1; + } + if (inlen > 16) { + aes_cbc_decrypt(key, iv, in, inlen/16 - 1, out); + iv = in + inlen - 32; + } + aes_cbc_decrypt(key, iv, in + inlen - 16, 1, block); + padding = block[15]; + if (padding < 1 || padding > 16) { + error_print(); + return -1; + } + len -= padding; + memcpy(out + inlen - 16, block, len); + *outlen = inlen - padding; + return 1; +} + +static void ctr_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + +void aes_ctr_encrypt(const AES_KEY *key, uint8_t ctr[16], const uint8_t *in, size_t inlen, uint8_t *out) +{ + uint8_t block[16]; + size_t len; + + while (inlen) { + len = inlen < 16 ? inlen : 16; + aes_encrypt(key, ctr, block); + gmssl_memxor(out, in, block, len); + ctr_incr(ctr); + in += len; + out += len; + inlen -= len; + } +} + +int aes_gcm_encrypt(const AES_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + uint8_t *out, size_t taglen, uint8_t *tag) +{ + const uint8_t *pin = in; + uint8_t *pout = out; + size_t left = inlen; + uint8_t H[16] = {0}; + uint8_t Y[16]; + uint8_t T[16]; + + if (taglen > AES_GCM_MAX_TAG_SIZE) { + error_print(); + return -1; + } + + aes_encrypt(key, H, H); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + aes_encrypt(key, Y, T); + + while (left) { + uint8_t block[16]; + size_t len = left < 16 ? left : 16; + ctr_incr(Y); + aes_encrypt(key, Y, block); + gmssl_memxor(pout, pin, block, len); + pin += len; + pout += len; + left -= len; + } + + ghash(H, aad, aadlen, out, inlen, H); + gmssl_memxor(tag, T, H, taglen); + return 1; +} + +int aes_gcm_decrypt(const AES_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + const uint8_t *tag, size_t taglen, uint8_t *out) +{ + const uint8_t *pin = in; + uint8_t *pout = out; + size_t left = inlen; + uint8_t H[16] = {0}; + uint8_t Y[16]; + uint8_t T[16]; + + aes_encrypt(key, H, H); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + ghash(H, aad, aadlen, in, inlen, H); + aes_encrypt(key, Y, T); + gmssl_memxor(T, T, H, taglen); + if (memcmp(T, tag, taglen) != 0) { + error_print(); + return -1; + } + + while (left) { + uint8_t block[16]; + size_t len = left < 16 ? left : 16; + ctr_incr(Y); + aes_encrypt(key, Y, block); + gmssl_memxor(pout, pin, block, len); + pin += len; + pout += len; + left -= len; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/asn1.c b/Core/GmSSL-3.1.1/src/asn1.c new file mode 100644 index 0000000..515cba2 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/asn1.c @@ -0,0 +1,1937 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +// https://www.obj-sys.com/asn1tutorial/node128.html + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *asn1_tag_index[] = { + "[0]", "[1]", "[2]", "[3]", "[4]", "[5]", "[6]", "[7]", "[8]", "[9]", + "[10]", "[11]", "[12]", "[13]", "[14]", "[15]", "[16]", "[17]", "[18]", "[19]", + "[20]", "[21]", "[22]", "[23]", "[24]", "[25]", "[26]", "[27]", "[28]", "[29]", + "[30]", "[31]", +}; + +const char *asn1_tag_name(int tag) +{ + if (tag < 0 || tag > 0xff) { + error_print(); + return NULL; + } + + switch (tag & 0xc0) { + case ASN1_TAG_CONTENT_SPECIFIC: return asn1_tag_index[tag & 0xe0]; + case ASN1_TAG_APPLICATION: return "Application"; + case ASN1_TAG_PRIVATE: return "Private"; + } + + switch (tag) { + case ASN1_TAG_BOOLEAN: return "BOOLEAN"; + case ASN1_TAG_INTEGER: return "INTEGER"; + case ASN1_TAG_BIT_STRING: return "BIT STRING"; + case ASN1_TAG_OCTET_STRING: return "OCTET STRING"; + case ASN1_TAG_NULL: return "NULL"; + case ASN1_TAG_OBJECT_IDENTIFIER: return "OBJECT IDENTIFIER"; + case ASN1_TAG_ObjectDescriptor: return "ObjectDescriptor"; + case ASN1_TAG_EXTERNAL: return "EXTERNAL"; + case ASN1_TAG_REAL: return "REAL"; + case ASN1_TAG_ENUMERATED: return "ENUMERATED"; + case ASN1_TAG_EMBEDDED: return "EMBEDDED"; + case ASN1_TAG_UTF8String: return "UTF8String"; + case ASN1_TAG_RELATIVE_OID: return "RELATIVE_OID"; + case ASN1_TAG_NumericString: return "NumericString"; + case ASN1_TAG_PrintableString: return "PrintableString"; + case ASN1_TAG_TeletexString: return "TeletexString"; + case ASN1_TAG_VideotexString: return "VideotexString"; + case ASN1_TAG_IA5String: return "IA5String"; + case ASN1_TAG_UTCTime: return "UTCTime"; + case ASN1_TAG_GeneralizedTime: return "GeneralizedTime"; + case ASN1_TAG_GraphicString: return "GraphicString"; + case ASN1_TAG_VisibleString: return "VisibleString"; + case ASN1_TAG_GeneralString: return "GeneralString"; + case ASN1_TAG_UniversalString: return "UniversalString"; + case ASN1_TAG_CHARACTER_STRING: return "CHARACTER STRING"; + case ASN1_TAG_BMPString: return "BMPString"; + case ASN1_TAG_SEQUENCE: return "SEQUENCE"; + case ASN1_TAG_SET: return "SET"; + case ASN1_TAG_EXPLICIT: return "EXPLICIT"; + } + + error_print(); + return NULL; +} + +// not in-use +int asn1_tag_is_cstring(int tag) +{ + switch (tag) { + case ASN1_TAG_UTF8String: + case ASN1_TAG_NumericString: + case ASN1_TAG_PrintableString: + case ASN1_TAG_TeletexString: + case ASN1_TAG_IA5String: + case ASN1_TAG_GeneralString: + return 1; + } + return 0; +} + +// not in-use +int asn1_tag_to_der(int tag, uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + if (out && *out) { + *(*out)++ = (uint8_t)tag; + } + (*outlen)++; + return 1; +} + +// not in-use +int asn1_tag_from_der(int *tag, const uint8_t **in, size_t *inlen) +{ + if (!tag || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (*inlen == 0) { + return 0; + } + *tag = *(*in)++; + (*inlen)--; + return 1; +} + +int asn1_tag_from_der_readonly(int *tag, const uint8_t **in, size_t *inlen) +{ + if (!tag || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (*inlen == 0) { + return 0; + } + *tag = **in; + return 1; +} + +int asn1_length_to_der(size_t len, uint8_t **out, size_t *outlen) +{ + if (len > INT_MAX) { + error_print(); + return -1; + } + if (!outlen) { + error_print(); + return -1; + } + + if (len < 128) { + if (out && *out) { + *(*out)++ = (uint8_t)len; + } + (*outlen)++; + + } else { + uint8_t buf[4]; + int nbytes; + + if (len < 256) nbytes = 1; + else if (len < 65536) nbytes = 2; + else if (len < (1 << 24)) nbytes = 3; + else nbytes = 4; + PUTU32(buf, (uint32_t)len); + + if (out && *out) { + *(*out)++ = 0x80 + nbytes; + memcpy(*out, buf + 4 - nbytes, nbytes); + (*out) += nbytes; + } + (*outlen) += 1 + nbytes; + } + return 1; +} + +int asn1_length_from_der(size_t *len, const uint8_t **in, size_t *inlen) +{ + if (!len || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + if (*inlen == 0) { + error_print(); + return -1; + } + + if (**in < 128) { + *len = *(*in)++; + (*inlen)--; + + } else { + uint8_t buf[4] = {0}; + int nbytes = *(*in)++ & 0x7f; + (*inlen)--; + + if (nbytes < 1 || nbytes > 4) { + error_print(); + return -1; + } + if (*inlen < nbytes) { + error_print(); + return -1; + } + + memcpy(buf + 4 - nbytes, *in, nbytes); + *len = (size_t)GETU32(buf); + *in += nbytes; + *inlen -= nbytes; + } + + // check if the left input is enough for reading (d,dlen) + if (*inlen < *len) { + error_print(); + return -2; // 特殊错误值用于 test_asn1_length() 的测试 // TODO: 修改 asn1test.c 的测试向量 + } + return 1; +} + +// asn1_data_to_der do not check the validity of data +int asn1_data_to_der(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + if (datalen == 0) { + return 0; + } + if (out && *out) { + if (!data) { + error_print(); + return -1; + } + memcpy(*out, data, datalen); + *out += datalen; + } + *outlen += datalen; + return 1; +} + +// not in-use +int asn1_data_from_der(const uint8_t **data, size_t datalen, const uint8_t **in, size_t *inlen) +{ + if (!data || !datalen || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (*inlen < datalen) { + error_print(); + return -1; + } + *data = *in; + *in += datalen; + *inlen -= datalen; + return 1; +} + +int asn1_header_to_der(int tag, size_t dlen, uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + + if (out && *out) { + *(*out)++ = (uint8_t)tag; + } + (*outlen)++; + + (void)asn1_length_to_der(dlen, out, outlen); + return 1; +} + +int asn1_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + + if (!d) { + if (dlen) { + error_print(); + return -1; + } + return 0; + } + + // tag + if (out && *out) { + *(*out)++ = (uint8_t)tag; + } + (*outlen)++; + + // length + (void)asn1_length_to_der(dlen, out, outlen); + + // data + if (out && *out) { + memcpy(*out, d, dlen); + *out += dlen; + } + *outlen += dlen; + + return 1; +} + +int asn1_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + if (!d || !dlen || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + // tag + if (*inlen == 0 || **in != tag) { + *d = NULL; + *dlen = 0; + return 0; + } + (*in)++; + (*inlen)--; + + // length + if (asn1_length_from_der(dlen, in, inlen) != 1) { + error_print(); + return -1; + } + + // data + *d = *in; + *in += *dlen; + *inlen -= *dlen; + return 1; +} + +int asn1_nonempty_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + + if (d && dlen == 0) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(tag, d, dlen, out, outlen)) != 1) { + if (ret) error_print(); + return ret; + } + return 1; +} + +int asn1_nonempty_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_type_from_der(tag, d, dlen, in, inlen)) != 1) { + if (ret) error_print(); + return ret; + } + if (*dlen == 0) { + error_print(); + return -1; + } + return 1; +} + +int asn1_any_type_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + if (!tag || !d || !dlen || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + if (*inlen == 0) { + *tag = - 1; + *d = NULL; + *dlen = 0; + return 0; + } + + *tag = *(*in)++; + (*inlen)--; + + if (asn1_length_from_der(dlen, in, inlen) != 1) { + error_print(); + return -1; + } + + *d = *in; + *in += *dlen; + *inlen -= *dlen; + return 1; +} + +// we need to check this is an asn.1 type +int asn1_any_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + + if (!a) { + if (a) { + error_print(); + return -1; + } + return 0; + } + + if (out && *out) { + memcpy(*out, a, alen); + *out += alen; + } + *outlen += alen; + + return 1; +} + +int asn1_any_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + int ret; + int tag; + const uint8_t *d; + size_t dlen; + + if (!a || !alen || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + *a = *in; + *alen = *inlen; + + if ((ret = asn1_any_type_from_der(&tag, &d, &dlen, in, inlen)) != 1) { + if (ret) error_print(); + return ret; + } + *alen -= *inlen; + + return 1; +} + +const char *asn1_boolean_name(int val) +{ + switch (val) { + case 1: return "true"; + case 0: return "false"; + } + return NULL; +} + +int asn1_boolean_from_name(int *val, const char *name) +{ + if (strcmp(name, "true") == 0) { + *val = 1; + return 1; + } else if (strcmp(name, "false") == 0) { + *val = 0; + return 1; + } + *val = -1; + return -1; +} + +int asn1_boolean_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + + if (val < 0) { + return 0; + } + + if (out && *out) { + *(*out)++ = tag; + *(*out)++ = 0x01; + *(*out)++ = val ? 0xff : 0x00; + } + (*outlen) += 3; + return 1; +} + +int asn1_boolean_from_der_ex(int tag, int *val, const uint8_t **in, size_t *inlen) +{ + if (!val || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (*inlen == 0 || (*in)[0] != tag) { + *val = -1; + return 0; + } + + if (*inlen < 3) { + error_print(); + return -1; + } + if ((*in)[1] != 0x01) { + error_print(); + return -1; + } + + if ((*in)[2] != ASN1_TRUE && (*in)[2] != ASN1_FALSE) { + error_print(); + return -1; + } + *val = ((*in)[2] == ASN1_TRUE) ? 1 : 0; + *in += 3; + *inlen -= 3; + return 1; +} + +int asn1_integer_to_der_ex(int tag, const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + + if (!a) { + return 0; + } + if (alen <= 0 || alen > INT_MAX) { + error_print(); + return -1; + } + + if (out && *out) + *(*out)++ = tag; + (*outlen)++; + + while (*a == 0 && alen > 1) { + a++; + alen--; + } + + if (a[0] & 0x80) { + asn1_length_to_der(alen + 1, out, outlen); + if (out && *out) { + *(*out)++ = 0x00; + memcpy(*out, a, alen); + (*out) += alen; + } + (*outlen) += 1 + alen; + } else { + asn1_length_to_der(alen, out ,outlen); + if (out && *out) { + memcpy(*out, a, alen); + (*out) += alen; + } + (*outlen) += alen; + } + + return 1; +} + +int asn1_integer_from_der_ex(int tag, const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + size_t len; + + if (!a || !alen || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + // tag + if (*inlen == 0 || **in != tag) { + *a = NULL; + *alen = 0; + return 0; + } + (*in)++; + (*inlen)--; + + // length (not zero) + if (asn1_length_from_der(&len, in, inlen) != 1) { + error_print(); + return -1; + } + if (len == 0) { + error_print(); + return -1; + } + + // check if ASN1_INTEGER is negative + if (**in & 0x80) { + error_print(); + return -1; + } + + // remove leading zero + if (**in == 0 && len > 1) { + (*in)++; + (*inlen)--; + len--; + + // the following bit should be one + if (((**in) & 0x80) == 0) { + error_print(); + return -1; + } + } + + // no leading zeros + if (**in == 0 && len > 1) { + error_print(); + return -1; + } + + // return integer bytes + *a = *in; + *alen = len; + *in += len; + *inlen -= len; + + return 1; +} + +int asn1_int_to_der_ex(int tag, int a, uint8_t **out, size_t *outlen) +{ + uint8_t buf[4] = {0}; + size_t len = 0; + + if (a == -1) { + return 0; + } + + while (a > 0) { + buf[3 - len] = a & 0xff; + a >>= 8; + len++; + } + if (!len) { + len = 1; + } + + if (asn1_integer_to_der_ex(tag, buf + 4 - len, len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int asn1_int_from_der_ex(int tag, int *a, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + size_t i; + + if (!a || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + if ((ret = asn1_integer_from_der_ex(tag, &p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *a = -1; + return ret; + } + if (len > sizeof(*a)) { + error_print(); + return -1; + } + + *a = 0; + for (i = 0; i < len; i++) { + *a = ((*a) << 8) | p[i]; + } + if (*a < 0) { + error_print(); + return -1; + } + return 1; +} + +int asn1_bit_string_to_der_ex(int tag, const uint8_t *bits, size_t nbits, uint8_t **out, size_t *outlen) +{ + size_t nbytes = (nbits + 7) / 8; + size_t unused_nbits = nbytes * 8 - nbits; + + if (!outlen) { + error_print(); + return -1; + } + + if (!bits) { + if (nbits) { + error_print(); + return -1; + } + return 0; + } + + // tag + if (out && *out) { + *(*out)++ = tag; + } + (*outlen)++; + + // length + (void)asn1_length_to_der(nbytes + 1, out, outlen); + + // unused num of bits + if (out && *out) { + *(*out)++ = (uint8_t)unused_nbits; + } + (*outlen)++; + + // bits + if (out && *out) { + memcpy(*out, bits, nbytes); + *out += nbytes; + } + *outlen += nbytes; + + return 1; +} + +int asn1_bit_string_from_der_ex(int tag, const uint8_t **bits, size_t *nbits, const uint8_t **in, size_t *inlen) +{ + size_t len; + int unused_bits; + + if (!bits || !nbits || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + // tag + if (*inlen == 0 || **in != tag) { + *bits = NULL; + *nbits = 0; + return 0; + } + (*in)++; + (*inlen)--; + + // length (min == 2) + if (asn1_length_from_der(&len, in, inlen) != 1) { + error_print(); + return -1; + } + if (len < 2) { + error_print(); + return -1; + } + + // unused_bits counter + unused_bits = **in; + if (unused_bits > 7) { + error_print(); + return -1; + } + (*in)++; + (*inlen)--; + len--; + + // return bits + *bits = *in; + *nbits = (len << 3) - unused_bits; + *in += len; + *inlen -= len; + + return 1; +} + +int asn1_bit_octets_to_der_ex(int tag, const uint8_t *octs, size_t nocts, uint8_t **out, size_t *outlen) +{ + int ret; + if ((ret = asn1_bit_string_to_der_ex(tag, octs, nocts << 3, out, outlen)) != 1) { + if (ret) error_print(); + return ret; + } + return 1; +} + +int asn1_bit_octets_from_der_ex(int tag, const uint8_t **octs, size_t *nocts, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *bits; + size_t nbits; + + if (!octs || !nocts) { + error_print(); + return -1; + } + + if ((ret = asn1_bit_string_from_der_ex(tag, &bits, &nbits, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *octs = NULL; + *nocts = 0; + } + return ret; + } + + if (nbits % 8) { + error_print(); + return -1; + } + *octs = bits; + *nocts = nbits >> 3; + return 1; +} + +int asn1_bits_to_der_ex(int tag, int bits, uint8_t **out, size_t *outlen) +{ + size_t nbits = 0; + uint8_t mask = 0x80; + uint8_t buf[4] = {0}; + int i = 0; + + if (bits < 0) { + return 0; + } + while (bits > 0) { + if (bits & 1) + buf[i] |= mask; + mask >>= 1; + bits >>= 1; + nbits++; + if (nbits % 8 == 0) { + i++; + mask = 0x80; + } + } + if (!nbits) { + nbits = 1; + } + + if (asn1_bit_string_to_der_ex(tag, buf, nbits, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int asn1_bits_from_der_ex(int tag, int *bits, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + uint8_t c; + size_t nbits; + size_t i; + + if (!bits) { + error_print(); + return -1; + } + + if ((ret = asn1_bit_string_from_der_ex(tag, &p, &nbits, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *bits = -1; + return ret; + } + + if (nbits > 31) { + error_print(); + return -1; + } + + *bits = 0; + for (i = 0; i < nbits; i++) { + if (i % 8 == 0) { + c = *p++; + } + *bits |= ((c & 0x80) >> 7) << i; + c <<= 1; + } + return 1; +} + +int asn1_bits_print(FILE *fp, int fmt, int ind, const char *label, const char **names, size_t names_cnt, int bits) +{ + size_t i; + format_print(fp, fmt, ind, "%s: ", label); + + for (i = 0; i < names_cnt; i++) { + if (bits & 0x01) + fprintf(fp, "%s%s", names[i], bits >> 1 ? "," : ""); + bits >>= 1; + } + fprintf(fp, "\n"); + if (bits) { + error_print(); + return -1; + } + return 1; +} + +const char *asn1_null_name(void) +{ + return "null"; +} + +int asn1_null_to_der(uint8_t **out, size_t *outlen) +{ + if (!outlen) { + error_print(); + return -1; + } + if (out && *out) { + *(*out)++ = ASN1_TAG_NULL; + *(*out)++ = 0x00; + } + *outlen += 2; + return 1; +} + +int asn1_null_from_der(const uint8_t **in, size_t *inlen) +{ + if (!in || !(*in) || !inlen) { + error_print(); + return -1; + } + + // tag + if (*inlen == 0 || **in != ASN1_TAG_NULL) { + return 0; + } + (*in)++; + (*inlen)--; + + // value + if (*inlen < 1) { + error_print(); + return -1; + } + if (**in != 0x00) { + error_print(); + return -1; + } + (*in)++; + (*inlen)--; + return 1; +} + +static void asn1_oid_node_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) { + *(*out)++ = buf[n]; + } + (*outlen)++; + } +} + +static int asn1_oid_node_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) { + error_print(); + 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)) { + error_print(); + return -1; + } + + *a = 0; + for (i = 0; i < n; i++) { + *a = ((*a) << 7) | (buf[i] & 0x7f); + } + + return 1; +} + +int asn1_object_identifier_to_octets(const uint32_t *nodes, size_t nodes_cnt, uint8_t *out, size_t *outlen) +{ + if (!nodes || !outlen) { + error_print(); + return -1; + } + if (nodes_cnt < ASN1_OID_MIN_NODES || nodes_cnt > ASN1_OID_MAX_NODES) { + error_print(); + return -1; + } + if (out) { + *out++ = (uint8_t)(nodes[0] * 40 + nodes[1]); + } + (*outlen) = 1; + nodes += 2; + nodes_cnt -= 2; + + while (nodes_cnt--) { + asn1_oid_node_to_base128(*nodes++, &out, outlen); + } + return 1; +} + +int asn1_object_identifier_from_octets(uint32_t *nodes, size_t *nodes_cnt, const uint8_t *in, size_t inlen) +{ + if (!nodes_cnt || !in || !inlen) { + error_print(); + return -1; + } + + if (nodes) { + *nodes++ = (*in) / 40; + *nodes++ = (*in) % 40; + } + in++; + inlen--; + *nodes_cnt = 2; + + while (inlen) { + uint32_t val; + if (*nodes_cnt > ASN1_OID_MAX_NODES) { + error_print(); + return -1; + } + if (asn1_oid_node_from_base128(&val, &in, &inlen) < 0) { + error_print(); + return -1; + } + if (nodes) { + *nodes++ = val; + } + (*nodes_cnt)++; + } + + return 1; +} + +int asn1_object_identifier_to_der_ex(int tag, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen) +{ + uint8_t octets[ASN1_OID_MAX_OCTETS]; + size_t octetslen = 0; + + if (!outlen) { + error_print(); + return -1; + } + if (!nodes) { + if (nodes_cnt) { + error_print(); + return -1; + } + return 0; + } + + if (asn1_object_identifier_to_octets(nodes, nodes_cnt, octets, &octetslen) != 1) { + error_print(); + return -1; + } + + if (out && *out) { + *(*out)++ = tag; + } + (*outlen)++; + + (void)asn1_length_to_der(octetslen, out, outlen); + + if (out && *out) { + memcpy(*out, octets, octetslen); + *out += octetslen; + } + *outlen += octetslen; + return 1; +} + +int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_cnt, + const uint8_t **in, size_t *inlen) +{ + size_t len; + + // unlike _from_octets(), _from_der() require output buffer + if (!nodes || !nodes_cnt || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + // tag + if (*inlen == 0 || **in != tag) { + *nodes_cnt = 0; + return 0; + } + (*in)++; + (*inlen)--; + + // length (not zero) + if (asn1_length_from_der(&len, in, inlen) != 1) { + error_print(); + return -1; + } + if (len < ASN1_OID_MIN_OCTETS) { + error_print(); + return -1; + } + + // parse OID + if (asn1_object_identifier_from_octets(nodes, nodes_cnt, *in, len) != 1) { + error_print(); + return -1; + } + *in += len; + *inlen -= len; + + return 1; +} + +int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt) +{ + if (!a || a_cnt < ASN1_OID_MIN_NODES || a_cnt > ASN1_OID_MAX_NODES + || !b || b_cnt < ASN1_OID_MIN_NODES || b_cnt > ASN1_OID_MAX_NODES) { + error_print(); + return 0; // _equ() should return 1 or 0 + } + if (a_cnt != b_cnt || memcmp(a, b, b_cnt * sizeof(uint32_t))) { + return 0; + } + return 1; +} + +int asn1_object_identifier_print(FILE *fp, int format, int indent, const char *label, const char *name, + const uint32_t *nodes, size_t nodes_cnt) +{ + size_t i; + format_print(fp, format, indent, "%s: %s", label, name ? name : "(unknown)"); + if (nodes) { + fprintf(fp, " ("); + for (i = 0; i < nodes_cnt - 1; i++) { + fprintf(fp, "%d.", (int)nodes[i]); + } + fprintf(fp, "%d)", nodes[i]); + } + fprintf(fp, "\n"); + return 1; +} + +const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t infos_cnt, const char *name) +{ + size_t i; + + if (!infos || !infos_cnt || !name) { + error_print(); + return NULL; + } + for (i = 0; i < infos_cnt; i++) { + if (strcmp(infos[i].name, name) == 0) { + return &infos[i]; + } + } + return NULL; +} + +const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t infos_cnt, int oid) +{ + size_t i; + + if (!infos || !infos_cnt || oid < 0) { + error_print(); + return NULL; + } + for (i = 0; i < infos_cnt; i++) { + if (infos[i].oid == oid) { + return &infos[i]; + } + } + return NULL; +} + +int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_t *nodes_cnt, + const ASN1_OID_INFO *infos, size_t infos_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + size_t i; + + if (!info) { + error_print(); + return -1; + } + if ((ret = asn1_object_identifier_from_der(nodes, nodes_cnt, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *info = NULL; + return ret; + } + + for (i = 0; i < infos_cnt; i++) { + if (*nodes_cnt == infos[i].nodes_cnt + && memcmp(nodes, infos[i].nodes, (*nodes_cnt) * sizeof(int)) == 0) { + *info = &infos[i]; + return 1; + } + } + + // OID with correct encoding but in the (infos, infos_cnt) list + *info = NULL; + return 1; +} + +int asn1_oid_info_from_der(const ASN1_OID_INFO **info, const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen) +{ + int ret; + uint32_t nodes[ASN1_OID_MAX_NODES]; + size_t nodes_cnt; + + if ((ret = asn1_oid_info_from_der_ex(info, nodes, &nodes_cnt, infos, count, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*info == NULL) { + asn1_object_identifier_print(stderr, 0, 0, "Unknown OID", NULL, nodes, nodes_cnt); + error_print(); + return -1; + } + return 1; +} + +/* +utf-8 character encoding + 1-byte: 0xxxxxxx + 2-byte: 110xxxxx 10xxxxxx + 3-byte: 1110xxxx 10xxxxxx 10xxxxxx + 4-byte: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx +*/ +static int asn1_utf8char_from_bytes(uint32_t *c, const uint8_t **pin, size_t *pinlen) +{ + uint32_t utf8char; + const uint8_t *in = *pin; + size_t inlen = *pinlen; + uint32_t utf8char_len, i; + + if (!inlen) { + return 0; + } + + if ((in[0] & 0x80) == 0x00) { + utf8char_len = 1; + } else if ((in[0] & 0xe0) == 0xc0) { + utf8char_len = 2; + } else if ((in[0] & 0xf0) == 0xe0) { + utf8char_len = 3; + } else if ((in[0] & 0xf8) == 0xf0) { + utf8char_len = 4; + } else { + //error_print(); // disable error_print for _is_ compare + return -1; + } + + if (inlen < utf8char_len) { + //error_print(); // disable error_print for _is_ compare + return -1; + } + + utf8char = in[0]; + for (i = 1; i < utf8char_len; i++) { + if ((in[i] & 0x60) != 0x80) { + //error_print(); // disable error_print for _is_ compare + return -1; + } + utf8char = (utf8char << 8) | in[i]; + } + + *c = utf8char; + (*pin) += utf8char_len; + (*pinlen) -= utf8char_len; + return 1; +} + + +int asn1_string_is_utf8_string(const char *a, size_t alen) +{ + uint32_t utf8char; + + if (!a || !alen) { + return 0; + } + while (alen) { + if (asn1_utf8char_from_bytes(&utf8char, (const uint8_t **)&a, &alen) != 1) { + return 0; + } + } + return 1; +} + +int asn1_utf8_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + if (asn1_string_is_utf8_string(d, dlen) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen)) != 1) { + if (ret) error_print(); + return ret; + } + return 1; +} + +int asn1_utf8_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*a == NULL || *alen == 0) { + error_print(); + return -1; + } + if (asn1_string_is_utf8_string(*a, *alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +static int asn1_char_is_printable(int a) +{ + if (('0' <= a && a <= '9') + || ('a' <= a && a <= 'z') + || ('A' <= a && a <= 'Z')) { + return 1; + } + + switch (a) { + case ' ': case '\'': case '(': case ')': + case '+': case ',': case '-': case '.': + case '/': case ':': case '=': case '?': + return 1; + } + return 0; +} + +int asn1_string_is_printable_string(const char *a, size_t alen) +{ + size_t i; + for (i = 0; i < alen; i++) { + if (asn1_char_is_printable(a[i]) != 1) { + return 0; + } + } + return 1; +} + +int asn1_printable_string_case_ignore_match(const char *a, size_t alen, + const char *b, size_t blen) +{ + // remove leading and suffix space chars + while (alen && *a == ' ') { + a++; + alen--; + } + while (alen && a[alen - 1] == ' ') { + alen--; + } + + // remove leading and suffix space chars + while (blen && *b == ' ') { + b++; + blen--; + } + while (blen && b[blen - 1] == ' ') { + blen--; + } + + if (alen != blen) { + return 0; + } + // case insensitive compare + while (alen--) { + if (toupper(*a) != toupper(*b)) { + return 0; + } + } + return 1; +} + +int asn1_printable_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + if (asn1_string_is_printable_string(d, dlen) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen)) != 1) { + if (ret) error_print(); + return ret; + } + return 1; +} + +int asn1_printable_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*a == NULL || *alen == 0) { + error_print(); + return -1; + } + if (asn1_string_is_printable_string(*a, *alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int asn1_string_is_ia5_string(const char *a, size_t alen) +{ + size_t i; + for (i = 0; i < alen; i++) { + if (!isascii(a[i])) { + return 0; + } + } + return 1; +} + +int asn1_ia5_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + if (asn1_string_is_ia5_string(d, dlen) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen)) != 1) { + if (ret) error_print(); + return ret; + } + return 1; +} + +int asn1_ia5_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*a == NULL || *alen == 0) { + error_print(); + return -1; + } + if (asn1_string_is_ia5_string(*a, *alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen) +{ + format_print(fp, fmt, ind, "%s: ", label); + while (dlen--) { + fprintf(fp, "%c", *d++); + } + fprintf(fp, "\n"); + return 1; +} + +static int is_leap_year(int year) { + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0; +} + +#define val(c) ((c)-'0') + +int asn1_time_from_str(int utc_time, time_t *timestamp, const char *str) +{ + int time_str_len[2] = { 15, 13 }; + int days_per_year[2] = { 365, 366 }; + int days_per_month[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; + int year, month, day, hour, minute, second; + const char *p = str; + int i; + + utc_time &= 1; + for (i = 0; i < time_str_len[utc_time] - 1; i++) { + if (!('0' <= str[i] && str[i] <= '9')) { + error_print(); + return -1; + } + } + if (str[i] != 'Z') { + error_print(); + return -1; + } + + if (utc_time) { + year = val(p[0]) * 10 + val(p[1]); + if (year <= 50) { + year += 2000; + } else { + year += 1900; + } + p += 2; + } else { + year = val(p[0]) * 1000 + val(str[1]) * 100 + val(str[2]) * 10 + val(str[3]); + p += 4; + } + if (is_leap_year(year)) { + days_per_month[2] = 29; + } + month = val(p[0]) * 10 + val(p[1]); p += 2; + day = val(p[0]) * 10 + val(p[1]); p += 2; + hour = val(p[0]) * 10 + val(p[1]); p += 2; + minute = val(p[0]) * 10 + val(p[1]); p += 2; + second = val(p[0]) * 10 + val(p[1]); p += 2; + + if (year < 1970 + || month < 1 || month > 12 + || day < 1 || day > days_per_month[month] + || hour < 0 || hour > 23 + || minute < 0 || minute > 59 + || second < 0 || second > 59) { + error_print(); + return -1; + } + + day--; + + while (year-- > 1970) { + day += days_per_year[is_leap_year(year)]; + } + while (month-- > 1) { + day += days_per_month[month]; + } + *timestamp = (time_t)day * 86400 + hour * 3600 + minute * 60 + second; + + return 1; +} + +int asn1_time_to_str(int utc_time, time_t timestamp, char *str) +{ + int days_per_month[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; + int days_per_year[2] = { 365, 366 }; + int max_year[2] = { 9999, 2050 }; + int year, month, second, hour, minute; + time_t day; + char *p = str; + + utc_time &= 1; + day = timestamp / 86400; + second = timestamp % 86400; + + // In UTCTime, year in [1951, 2050], YY <= 50, year = 20YY; YY > 50, year = 19YY + // For Validity, year SHOULD <= 2049 (NOT 2050) + for (year = 1970; year <= max_year[utc_time]; year++) { + if (day < days_per_year[is_leap_year(year)]) { + break; + } + day -= days_per_year[is_leap_year(year)]; + } + if (year > max_year[utc_time]) { + error_print(); + return -1; + } + + day++; + + if (is_leap_year(year)) { + days_per_month[2] = 29; + } + for (month = 1; month <= 12; month++) { + if (day <= days_per_month[month]) { + break; + } + day -= days_per_month[month]; + } + + hour = second / 3600; + second %= 3600; + minute = second / 60; + second %= 60; + + if (utc_time) { + memset(p, '0', 12); + } else { + memset(p, '0', 14); + p[0] += (year / 100) / 10; + p[1] += (year / 100) % 10; + p += 2; + } + + year %= 100; + p[0] += year / 10; + p[1] += year % 10; + p[2] += month / 10; + p[3] += month % 10; + p[4] += (int)day / 10; + p[5] += day % 10; + p[6] += hour / 10; + p[7] += hour % 10; + p[8] += minute / 10; + p[9] += minute % 10; + p[10] += second / 10; + p[11] += second % 10; + p[12] = 'Z'; + + return 1; +} + +int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen) +{ + char buf[ASN1_UTC_TIME_STRLEN + 1] = {0}; + int utc_time = 1; + + if (!outlen) { + error_print(); + return -1; + } + if (a == -1) { + return 0; + } + + if (asn1_time_to_str(utc_time, a, buf) != 1) { + error_print(); + return -1; + } + + if (out && *out) { + *(*out)++ = tag; + } + (*outlen)++; + asn1_length_to_der(ASN1_UTC_TIME_STRLEN, out, outlen); + if (out && *out) { + memcpy(*out, buf, ASN1_UTC_TIME_STRLEN); + (*out) += ASN1_UTC_TIME_STRLEN; + } + *outlen += ASN1_UTC_TIME_STRLEN; + + return 1; +} + +int asn1_utc_time_from_der_ex(int tag, time_t *t, const uint8_t **in, size_t *inlen) +{ + size_t len; + + if (!t || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + // tag + if (*inlen == 0 || **in != tag) { + *t = -1; + return 0; + } + (*in)++; + (*inlen)--; + + // length + if (asn1_length_from_der(&len, in, inlen) != 1) { + error_print(); + return -1; + } + + if (len == sizeof("YYMMDDHHMMSSZ")-1) { + char buf[sizeof("YYMMDDHHMMSSZ")-1]; + memcpy(buf, *in, len); + if (asn1_time_from_str(1, t, buf) != 1) { + error_print(); + return -1; + } + } else if (len == sizeof("YYMMDDHHMMSS+HHMM")-1) { + char buf[sizeof("YYMMDDHHMMSS+HHMM")-1]; + memcpy(buf, *in, len); + // this format is not supported yet + error_print(); + return -1; + } else { + error_print(); + return -1; + } + + *in += len; + *inlen -= len; + return 1; +} + +int asn1_generalized_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen) +{ + char buf[ASN1_GENERALIZED_TIME_STRLEN + 1] = {0}; + int utc_time = 0; + + if (!outlen) { + error_print(); + return -1; + } + if (a == -1) { + return 0; + } + + if (asn1_time_to_str(utc_time, a, buf) != 1) { + error_print(); + return -1; + } + + if (out && *out) + *(*out)++ = tag; + (*outlen)++; + asn1_length_to_der(ASN1_GENERALIZED_TIME_STRLEN, out, outlen); + if (out && *out) { + memcpy(*out, buf, ASN1_GENERALIZED_TIME_STRLEN); + (*out) += ASN1_GENERALIZED_TIME_STRLEN; + } + *outlen += ASN1_GENERALIZED_TIME_STRLEN; + + return 1; +} + +int asn1_generalized_time_from_der_ex(int tag, time_t *t, const uint8_t **in, size_t *inlen) +{ + size_t len; + + if (!t || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + // tag + if (*inlen == 0 || **in != tag) { + *t = -1; + return 0; + } + (*in)++; + (*inlen)--; + + // length + if (asn1_length_from_der(&len, in, inlen) != 1) { + error_print(); + return -1; + } + + if (len == sizeof("YYYYMMDDHHMMSSZ")-1) { + char buf[sizeof("YYYYMMDDHHMMSSZ")-1]; + memcpy(buf, *in, len); + if (asn1_time_from_str(0, t, buf) != 1) { + error_print(); + return -1; + } + } else if (len == sizeof("YYYYMMDDHHMMSS+HHMM")-1) { + char buf[sizeof("YYYYMMDDHHMMSS+HHMM")-1]; + memcpy(buf, *in, len); + error_print(); + return -1; + } else { + error_print(); + return -1; + } + + *in += len; + *inlen -= len; + return 1; +} + +int asn1_sequence_of_int_to_der(const int *nums, size_t nums_cnt, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + size_t i; + + if (!nums || !nums_cnt || !outlen) { + error_print(); + return -1; + } + + for (i = 0; i < nums_cnt; i++) { + if (asn1_int_to_der(nums[i], NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < nums_cnt; i++) { + if (asn1_int_to_der(nums[i], out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int asn1_sequence_of_int_from_der(int *nums, size_t *nums_cnt, size_t max_nums, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if (!nums || !nums_cnt || !max_nums) { + error_print(); + return -1; + } + + *nums_cnt = 0; + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + while (dlen) { + int num; + if (*nums_cnt > max_nums) { + error_print(); + return -1; + } + if (asn1_int_from_der(&num, &d, &dlen) != 1) { + error_print(); + return -1; + } + *nums++ = num; + (*nums_cnt)++; + } + return 1; +} + +int asn1_sequence_of_int_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int val; + format_print(fp, fmt, ind, "%s: ", label); + while (dlen) { + if (asn1_int_from_der(&val, &d, &dlen) != 1) { + error_print(); + return -1; + } + fprintf(fp, "%d%s", val, dlen ? "," : ""); + } + fprintf(fp, "\n"); + return 1; +} + +int asn1_types_get_count(const uint8_t *d, size_t dlen, int tag, size_t *cnt) +{ + int item_tag; + const uint8_t *item_d; + size_t item_dlen; + + if (!d || !cnt) { + error_print(); + return -1; + } + *cnt = 0; + while (dlen) { + if (asn1_any_type_from_der(&item_tag, &item_d, &item_dlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (item_tag != tag) { + error_print(); + return -1; + } + (*cnt)++; + } + return 1; +} + +int asn1_types_get_item_by_index(const uint8_t *d, size_t dlen, int tag, + int index, const uint8_t **item_d, size_t *item_dlen) +{ + int a_tag; + const uint8_t *a_d; + size_t a_dlen; + int i = 0; + + if (!d || !item_d || !item_dlen) { + error_print(); + return -1; + } + + while (dlen) { + if (asn1_any_type_from_der(&a_tag, &a_d, &a_dlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (a_tag != tag) { + error_print(); + return -1; + } + if (i++ == index) { + *item_d = d; + *item_dlen = dlen; + return 1; // do not check the following + } + } + + error_print(); + return -1; +} + +int asn1_check(int expr) +{ + if (expr) + return 1; + error_print(); + return -1; +} + +int asn1_length_is_zero(size_t len) +{ + if (len) { + error_print(); + return -1; + } + return 1; +} + +int asn1_length_le(size_t len1, size_t len2) +{ + if (len1 > len2) { + error_print(); + format_print(stderr, 0, 0, "%s: %zu <= %zu failed\n", __FUNCTION__, len1, len2); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/base64.c b/Core/GmSSL-3.1.1/src/base64.c new file mode 100644 index 0000000..4957747 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/base64.c @@ -0,0 +1,378 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + +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 = (int)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); +} diff --git a/Core/GmSSL-3.1.1/src/block_cipher.c b/Core/GmSSL-3.1.1/src/block_cipher.c new file mode 100644 index 0000000..0db0fa8 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/block_cipher.c @@ -0,0 +1,82 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +int block_cipher_set_encrypt_key(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key) +{ + memset(key, 0, sizeof(BLOCK_CIPHER_KEY)); + cipher->set_encrypt_key(key, raw_key); + key->cipher = cipher; + return 1; +} + +int block_cipher_set_decrypt_key(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key) +{ + memset(key, 0, sizeof(BLOCK_CIPHER_KEY)); + cipher->set_decrypt_key(key, raw_key); + key->cipher = cipher; + return 1; +} + +int block_cipher_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out) +{ + key->cipher->encrypt(key, in, out); + return 1; +} + +int block_cipher_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t *out) +{ + key->cipher->decrypt(key, in, out); + return 1; +} + +static const BLOCK_CIPHER sm4_block_cipher_object = { + OID_sm4, + SM4_KEY_SIZE, + SM4_BLOCK_SIZE, + (block_cipher_set_encrypt_key_func)sm4_set_encrypt_key, + (block_cipher_set_decrypt_key_func)sm4_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; +} + +static int aes128_set_encrypt_key(AES_KEY *aes_key, const uint8_t key[16]) { + return aes_set_encrypt_key(aes_key, key, 16); +} + +static int aes128_set_decrypt_key(AES_KEY *aes_key, const uint8_t key[16]) { + return aes_set_decrypt_key(aes_key, key, 16); +} + +static const BLOCK_CIPHER aes128_block_cipher_object = { + OID_aes128, + AES128_KEY_SIZE, + AES_BLOCK_SIZE, + (block_cipher_set_encrypt_key_func)aes128_set_encrypt_key, + (block_cipher_set_decrypt_key_func)aes128_set_decrypt_key, + (block_cipher_encrypt_func)aes_encrypt, + (block_cipher_decrypt_func)aes_encrypt, +}; + +const BLOCK_CIPHER *BLOCK_CIPHER_aes128(void) { + return &aes128_block_cipher_object; +} diff --git a/Core/GmSSL-3.1.1/src/chacha20.c b/Core/GmSSL-3.1.1/src/chacha20.c new file mode 100644 index 0000000..424e61e --- /dev/null +++ b/Core/GmSSL-3.1.1/src/chacha20.c @@ -0,0 +1,85 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include + + +void chacha20_init(CHACHA20_STATE *state, + const uint8_t key[CHACHA20_KEY_SIZE], + const uint8_t 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, size_t counts, uint8_t *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]++; + } +} diff --git a/Core/GmSSL-3.1.1/src/cms.c b/Core/GmSSL-3.1.1/src/cms.c new file mode 100644 index 0000000..7d738f0 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/cms.c @@ -0,0 +1,2485 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static uint32_t oid_cms_data[] = { oid_sm2_cms,1 }; +static uint32_t oid_cms_signed_data[] = { oid_sm2_cms,2 }; +static uint32_t oid_cms_enveloped_data[] = { oid_sm2_cms,3 }; +static uint32_t oid_cms_signed_and_enveloped_data[] = { oid_sm2_cms,4 }; +static uint32_t oid_cms_encrypted_data[] = { oid_sm2_cms,5 }; +static uint32_t oid_cms_key_agreement_info[] = { oid_sm2_cms,6 }; +#define OID_CMS_CONUNT (sizeof(oid_cms_data)/sizeof(int)) + +static const ASN1_OID_INFO cms_content_types[] = { + { OID_cms_data, "data", oid_cms_data, OID_CMS_CONUNT }, + { OID_cms_signed_data, "signedData", oid_cms_signed_data, OID_CMS_CONUNT }, + { OID_cms_enveloped_data, "envelopedData", oid_cms_enveloped_data, OID_CMS_CONUNT }, + { OID_cms_signed_and_enveloped_data, "signedAndEnvelopedData", oid_cms_signed_and_enveloped_data, OID_CMS_CONUNT }, + { OID_cms_encrypted_data, "encryptedData", oid_cms_encrypted_data, OID_CMS_CONUNT }, + { OID_cms_key_agreement_info, "keyAgreementInfo", oid_cms_key_agreement_info, OID_CMS_CONUNT } +}; + +static const size_t cms_content_types_count = + sizeof(cms_content_types)/sizeof(cms_content_types[0]); + +const char *cms_content_type_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(cms_content_types, cms_content_types_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int cms_content_type_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(cms_content_types, cms_content_types_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int cms_content_type_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + + if (oid == -1) { + return 0; + } + if (!(info = asn1_oid_info_from_oid(cms_content_types, cms_content_types_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_content_type_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + + if ((ret = asn1_oid_info_from_der(&info, cms_content_types, cms_content_types_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + +/* +static int cms_content_info_data_header_to_der(size_t dlen, uint8_t **out, size_t *outlen) +{ + uint8_t d[1]; + size_t len = 0; + size_t content_len = 0; + if (asn1_octet_string_to_der(p, dlen, NULL, &content_len) != 1 + || cms_content_type_to_der(OID_cms_data, out, outlen) != 1 + || asn1_explicit_header_to_der(0, content_len, out, outlen) < 0 + || asn1_octet_string_to_der(dlen, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} +*/ + +int cms_content_info_header_to_der(int content_type, size_t content_len, uint8_t **out, size_t *outlen) +{ + size_t len = content_len; // 注意:由于header_to_der没有输出数据,因此需要加上数据的长度,header length 才是正确的值 + /* + if (content_type == OID_cms_data) { + return cms_content_info_data_header_to_der(content_len, out, outlen); + } + */ + + if (cms_content_type_to_der(content_type, NULL, &len) != 1 + || asn1_explicit_header_to_der(0, content_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || cms_content_type_to_der(content_type, out, outlen) != 1 + || asn1_explicit_header_to_der(0, content_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +static int cms_content_info_data_to_der(const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + size_t content_len = 0; + if (asn1_octet_string_to_der(d, dlen, NULL, &content_len) != 1 + || cms_content_type_to_der(OID_cms_data, NULL, &len) != 1 + || asn1_explicit_to_der(0, d, content_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || cms_content_type_to_der(OID_cms_data, out, outlen) != 1 + || asn1_explicit_header_to_der(0, content_len, out, outlen) != 1 + || asn1_octet_string_to_der(d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_content_info_to_der( + int content_type, const uint8_t *content, size_t content_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (content_type == OID_cms_data) { + return cms_content_info_data_to_der(content, content_len, out, outlen); + } + if (cms_content_type_to_der(content_type, NULL, &len) != 1 + || asn1_explicit_to_der(0, content, content_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || cms_content_type_to_der(content_type, out, outlen) != 1 + || asn1_explicit_to_der(0, content, content_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int cms_content_info_from_der( + int *content_type, + const uint8_t **content, size_t *content_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (cms_content_type_from_der(content_type, &d, &dlen) != 1 + || asn1_explicit_from_der(0, content, content_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_content_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + int content_type; + const uint8_t *content; + size_t content_len; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (cms_content_type_from_der(&content_type, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "contentType: %s\n", cms_content_type_name(content_type)); + + /* + if (content_type == OID_cms_data) { + if (asn1_octet_string_from_der(&p, &len, &content, &content_len) != 1) goto err; + } else { + if (asn1_sequence_from_der(&p, &len, &content, &content_len) != 1) goto err; + } + */ + + //format_bytes(stderr, 0, 0, "content", d, dlen); + + if ((ret = asn1_explicit_from_der(0, &content, &content_len, &d, &dlen)) < 0) { error_print(); goto err; } + if (ret == 0) { error_print(); goto err; } + + if (content_type == OID_cms_data) { + if (asn1_octet_string_from_der(&p, &len, &content, &content_len) != 1 + || asn1_length_is_zero(content_len) != 1) { + error_print(); + return -1; + } + format_bytes(fp, fmt, ind, "content", p, len); + return 1; + } + + + if (asn1_sequence_from_der(&p, &len, &content, &content_len) != 1) { error_print(); goto err; } + + switch (content_type) { + //case OID_cms_data: format_bytes(fp, fmt, ind, "content", p, len); break; + case OID_cms_signed_data: cms_signed_data_print(fp, fmt, ind, "content", p, len); break; + case OID_cms_enveloped_data: cms_enveloped_data_print(fp, fmt, ind, "content", p, len); break; + case OID_cms_signed_and_enveloped_data: cms_signed_and_enveloped_data_print(fp, fmt, ind, "content", p, len); break; + case OID_cms_encrypted_data: cms_encrypted_data_print(fp, fmt, ind, "content", p, len); break; + case OID_cms_key_agreement_info: cms_key_agreement_info_print(fp, fmt, ind, "content", p, len); break; + } + if (asn1_length_is_zero(content_len) != 1) goto err; + + + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_enced_content_info_to_der( + int content_type, + int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (cms_content_type_to_der(content_type, NULL, &len) != 1 + || x509_encryption_algor_to_der(enc_algor, enc_iv, enc_iv_len, NULL, &len) != 1 + || asn1_implicit_octet_string_to_der(0, enced_content, enced_content_len, NULL, &len) < 0 + || asn1_implicit_octet_string_to_der(1, shared_info1, shared_info1_len, NULL, &len) < 0 + || asn1_implicit_octet_string_to_der(2, shared_info2, shared_info2_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || cms_content_type_to_der(content_type, out, outlen) != 1 + || x509_encryption_algor_to_der(enc_algor, enc_iv, enc_iv_len, out, outlen) != 1 + || asn1_implicit_octet_string_to_der(0, enced_content, enced_content_len, out, outlen) < 0 + || asn1_implicit_octet_string_to_der(1, shared_info1, shared_info1_len, out, outlen) < 0 + || asn1_implicit_octet_string_to_der(2, shared_info2, shared_info2_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int cms_enced_content_info_from_der( + int *content_type, + int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, + const uint8_t **enced_content, size_t *enced_content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (cms_content_type_from_der(content_type, &d, &dlen) != 1 + || x509_encryption_algor_from_der(enc_algor, enc_iv, enc_iv_len, &d, &dlen) != 1 + || asn1_implicit_octet_string_from_der(0, enced_content, enced_content_len, &d, &dlen) < 0 + || asn1_implicit_octet_string_from_der(1, shared_info1, shared_info1_len, &d, &dlen) < 0 + || asn1_implicit_octet_string_from_der(2, shared_info2, shared_info2_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_enced_content_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (cms_content_type_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "contentType: %s\n", cms_content_type_name(val)); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_encryption_algor_print(fp, fmt, ind, "contentEncryptionAlgorithm", p, len); + if ((ret = asn1_implicit_octet_string_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "encryptedContent", p, len); + if ((ret = asn1_implicit_octet_string_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "sharedInfo1", p, len); + if ((ret = asn1_implicit_octet_string_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "sharedInfo2", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_enced_content_info_encrypt_to_der( + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen) +{ + int ret; + SM4_KEY sm4_key; + uint8_t* enced_content = NULL; + size_t enced_content_len = 100; // FIXME: why 100? + + if (!(enced_content = malloc(32 + content_len))) { + error_print(); + return -1; + } + + + + if (enc_algor != OID_sm4_cbc || keylen != 16 || ivlen != 16) { + error_print(); + if (enced_content) free(enced_content); + return -1; + } + + sm4_set_encrypt_key(&sm4_key, key); + if (sm4_cbc_padding_encrypt(&sm4_key, iv, content, content_len, + enced_content, &enced_content_len) != 1) { + if (enced_content) free(enced_content); + memset(&sm4_key, 0, sizeof(SM4_KEY)); + error_print(); + return -1; + } + memset(&sm4_key, 0, sizeof(SM4_KEY)); + + if ((ret = cms_enced_content_info_to_der(content_type, + enc_algor, iv, ivlen, enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen)) != 1) { + if (enced_content) free(enced_content); + if (ret < 0) error_print(); + return ret; + } + + free(enced_content); //FIXME: use goto end to clean enced_content + return 1; +} + +// 这个函数显然是有问题的,调用方根本不知道应该准备多大的buffer +// 应该为content_len 输出给一个maxlen 的最大buffer值 +int cms_enced_content_info_decrypt_from_der( + int *enc_algor, const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **shared_info1, size_t *shared_info1_len,// 支持可选null输出 + const uint8_t **shared_info2, size_t *shared_info2_len,// 支持可选null输出 + const uint8_t **in, size_t *inlen) +{ + SM4_KEY sm4_key; + const uint8_t *iv; + size_t ivlen; + const uint8_t *enced_content; + size_t enced_content_len; + + if (cms_enced_content_info_from_der(content_type, + enc_algor, &iv, &ivlen, &enced_content, &enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + in, inlen) != 1 + || asn1_check(*enc_algor == OID_sm4_cbc) != 1 + || asn1_check(ivlen == SM4_BLOCK_SIZE) != 1 + || asn1_check(keylen == SM4_KEY_SIZE) != 1) { + error_print(); + return -1; + } + + sm4_set_decrypt_key(&sm4_key, key); + if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_content, enced_content_len, + content, content_len) != 1) { + memset(&sm4_key, 0, sizeof(SM4_KEY)); + return -1; + } + memset(&sm4_key, 0, sizeof(SM4_KEY)); + + return 1; +} + +int cms_encrypted_data_to_der( + int version, + int content_type, + int enc_algor, const uint8_t *iv, size_t ivlen, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (version != 1) { + error_print(); + return -1; + } + if (asn1_int_to_der(version, NULL, &len) != 1 + || cms_enced_content_info_to_der( + content_type, + enc_algor, iv, ivlen, + enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || cms_enced_content_info_to_der( + content_type, + enc_algor, iv, ivlen, + enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_encrypted_data_from_der( + int *version, + int *content_type, + int *enc_algor, const uint8_t **iv, size_t *ivlen, + const uint8_t **enced_content, size_t *enced_content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || cms_enced_content_info_from_der( + content_type, + enc_algor, iv, ivlen, + enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (*version != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_encrypted_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_enced_content_info_print(fp, fmt, ind, "encryptedContentInfo", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_encrypted_data_encrypt_to_der( + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_int_to_der(CMS_version_v1, NULL, &len) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_encrypted_data_decrypt_from_der( + int *enc_algor, const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen) +{ + int ret, version; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(&version, &d, &dlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || cms_enced_content_info_decrypt_from_der( + enc_algor, key, keylen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_issuer_and_serial_number_to_der( + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_sequence_to_der(issuer, issuer_len, NULL, &len) != 1 + || asn1_integer_to_der(serial_number, serial_number_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_sequence_to_der(issuer, issuer_len, out, outlen) != 1 + || asn1_integer_to_der(serial_number, serial_number_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_issuer_and_serial_number_from_der( + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_sequence_from_der(issuer, issuer_len, &d, &dlen) != 1 + || asn1_integer_from_der(serial_number, serial_number_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_issuer_and_serial_number_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "issuer", p, len); + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "serialNumber", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_signer_info_to_der( + int version, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + int digest_algor, + const uint8_t *authed_attrs, size_t authed_attrs_len, + int signature_algor, + 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) +{ + size_t len = 0; + if (version != 1) { + error_print(); + return -1; + } + + if (asn1_int_to_der(version, NULL, &len) != 1 + || cms_issuer_and_serial_number_to_der( + issuer, issuer_len, + serial_number, serial_number_len, NULL, &len) != 1 + || x509_digest_algor_to_der(digest_algor, NULL, &len) != 1 + || asn1_implicit_set_to_der(0, authed_attrs, authed_attrs_len, NULL, &len) < 0 + || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 + || asn1_octet_string_to_der(enced_digest, enced_digest_len, NULL, &len) != 1 + || asn1_implicit_set_to_der(1, unauthed_attrs, unauthed_attrs_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || cms_issuer_and_serial_number_to_der( + issuer, issuer_len, + serial_number, serial_number_len, out, outlen) != 1 + || x509_digest_algor_to_der(digest_algor, out, outlen) != 1 + || asn1_implicit_set_to_der(0, authed_attrs, authed_attrs_len, out, outlen) < 0 + || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 + || asn1_octet_string_to_der(enced_digest, enced_digest_len, out, outlen) != 1 + || asn1_implicit_set_to_der(1, unauthed_attrs, unauthed_attrs_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int cms_signer_info_from_der( + int *version, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len, + int *digest_algor, + const uint8_t **authed_attrs, size_t *authed_attrs_len, + int *signature_algor, + 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 ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || cms_issuer_and_serial_number_from_der(issuer, issuer_len, + serial_number, serial_number_len, &d, &dlen) != 1 + || x509_digest_algor_from_der(digest_algor, &d, &dlen) != 1 + || asn1_implicit_set_from_der(0, authed_attrs, authed_attrs_len, &d, &dlen) < 0 + || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 + || asn1_octet_string_from_der(enced_digest, enced_digest_len, &d, &dlen) != 1 + || asn1_implicit_set_from_der(1, unauthed_attrs, unauthed_attrs_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signer_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_issuer_and_serial_number_print(fp, fmt, ind, "issuerAndSerialNumber", p, len); + if (x509_digest_algor_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "digestAlgorithm: %s\n", x509_digest_algor_name(val)); + if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_attributes_print(fp, fmt, ind, "authenticatedAttributes", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "digestEncryptionAlgorithm", p, len); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "encryptedDigest", p, len); + if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_attributes_print(fp, fmt, ind, "unauthenticatedAttributes", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_signer_info_sign_to_der( + const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, + const uint8_t *issuer, size_t issuer_len, + 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) +{ + SM3_CTX ctx = *sm3_ctx; + int fixed_outlen = 1; + uint8_t dgst[SM3_DIGEST_SIZE]; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen = SM2_signature_typical_size; + + sm3_update(&ctx, authed_attrs, authed_attrs_len); + sm3_finish(&ctx, dgst); + + if (sm2_sign_fixlen(sign_key, dgst, siglen, sig) != 1) { + error_print(); + return -1; + } + if (cms_signer_info_to_der(CMS_version_v1, + issuer, issuer_len, serial_number, serial_number_len, + OID_sm3, authed_attrs, authed_attrs_len, + OID_sm2sign_with_sm3, sig, siglen, + unauthed_attrs, unauthed_attrs_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signer_info_verify_from_der( + const SM3_CTX *ctx, const uint8_t *certs, size_t certslen, + const uint8_t **cert, size_t *certlen, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial, size_t *serial_len, + const uint8_t **authed_attrs, size_t *authed_attrs_len, + const uint8_t **unauthed_attrs, size_t *unauthed_attrs_len, + const uint8_t **in, size_t *inlen) +{ + int version; + int digest_algor; + int signature_algor; + const uint8_t *sig; + size_t siglen; + SM2_KEY public_key; + SM3_CTX sm3_ctx = *ctx; + uint8_t dgst[32]; + + if (cms_signer_info_from_der(&version, + issuer, issuer_len, + serial, serial_len, + &digest_algor, authed_attrs, authed_attrs_len, + &signature_algor, &sig, &siglen, + unauthed_attrs, unauthed_attrs_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || asn1_check(digest_algor == OID_sm3) != 1 + || asn1_check(signature_algor == OID_sm2sign_with_sm3) != 1) { + error_print(); + return -1; + } + if (x509_certs_get_cert_by_issuer_and_serial_number(certs, certslen, + *issuer, *issuer_len, *serial, *serial_len, cert, certlen) != 1 + || x509_cert_get_subject_public_key(*cert, *certlen, &public_key) != 1) { + error_print(); + return -1; + } + + sm3_update(&sm3_ctx, *authed_attrs, *authed_attrs_len); + sm3_finish(&sm3_ctx, dgst); + + if (sm2_verify(&public_key, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signer_infos_add_signer_info( + uint8_t *d, size_t *dlen, size_t maxlen, + const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, + const uint8_t *issuer, size_t issuer_len, + 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) +{ + size_t len = *dlen; + d += *dlen; + if (cms_signer_info_sign_to_der(sm3_ctx, sign_key, + issuer, issuer_len, serial_number, serial_number_len, + authed_attrs, authed_attrs_len, + unauthed_attrs, unauthed_attrs_len, + NULL, &len) != 1 + || asn1_length_le(len, maxlen) != 1 + || cms_signer_info_sign_to_der(sm3_ctx, sign_key, + issuer, issuer_len, serial_number, serial_number_len, + authed_attrs, authed_attrs_len, + unauthed_attrs, unauthed_attrs_len, + &d, dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signer_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + cms_signer_info_print(fp, fmt, ind, "SignerInfo", p, len); + } + return 1; +} + +int cms_digest_algors_to_der(const int *digest_algors, size_t digest_algors_cnt, + uint8_t **out, size_t *outlen) +{ + size_t len = 0, i; + for (i = 0; i < digest_algors_cnt; i++) { + if (x509_digest_algor_to_der(digest_algors[i], NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_set_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < digest_algors_cnt; i++) { + if (x509_digest_algor_to_der(digest_algors[i], out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int cms_digest_algors_from_der(int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_set_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + + *digest_algors_cnt = 0; + while (dlen) { + if (*digest_algors_cnt > max_digest_algors) { + error_print(); + return -1; + } + if (x509_digest_algor_from_der(digest_algors, &d, &dlen) != 1) { + error_print(); + return -1; + } + digest_algors++; + (*digest_algors_cnt)++; + } + return 1; +} + +int cms_digest_algors_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (x509_digest_algor_from_der(&oid, &d, &dlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "%s\n", x509_digest_algor_name(oid)); + } + return 1; +} + +int cms_signed_data_to_der( + int version, + const int *digest_algors, size_t digest_algors_cnt, + const int content_type, const uint8_t *content, const size_t content_len, + const uint8_t *certs, size_t certs_len, + const uint8_t *crls, const size_t crls_len, + const uint8_t *signer_infos, size_t signer_infos_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_int_to_der(version, NULL, &len) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, NULL, &len) != 1 + || cms_content_info_to_der(content_type, content, content_len, NULL, &len) != 1 + || asn1_implicit_set_to_der(0, certs, certs_len, NULL, &len) < 0 + || asn1_implicit_set_to_der(1, crls, crls_len, NULL, &len) < 0 + || cms_signer_infos_to_der(signer_infos, signer_infos_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, out, outlen) != 1 + || cms_content_info_to_der(content_type, content, content_len, out, outlen) != 1 + || asn1_implicit_set_to_der(0, certs, certs_len, out, outlen) < 0 + || asn1_implicit_set_to_der(1, crls, crls_len, out, outlen) < 0 + || cms_signer_infos_to_der(signer_infos, signer_infos_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signed_data_from_der( + int *version, + int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + 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 ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || cms_digest_algors_from_der(digest_algors, digest_algors_cnt, max_digest_algors, &d, &dlen) != 1 + || cms_content_info_from_der(content_type, content, content_len, &d, &dlen) != 1 + || asn1_implicit_set_from_der(0, certs, certs_len, &d, &dlen) < 0 + || asn1_implicit_set_from_der(1, crls, crls_len, &d, &dlen) < 0 + || asn1_set_from_der(signer_infos, signer_infos_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (*version != CMS_version_v1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signed_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_digest_algors_print(fp, fmt, ind, "digestAlgorithms", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_content_info_print(fp, fmt, ind, "contentInfo", p, len); + if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_certs_print(fp, fmt, ind, "certificates", p, len); + if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_signer_infos_print(fp, fmt, ind, "signerInfos", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +static int cms_implicit_signers_certs_to_der(int index, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + uint8_t **out, size_t *outlen) +{ + size_t i; + size_t len = 0; + for (i = 0; i < signers_cnt; i++) { + if (asn1_data_to_der(signers[i].certs, signers[i].certs_len, NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_implicit_header_to_der(index, len, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < signers_cnt; i++) { + if (asn1_data_to_der(signers[i].certs, signers[i].certs_len, out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int cms_signed_data_sign_to_der( + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + int content_type, const uint8_t *data, size_t datalen, + const uint8_t *crls, size_t crls_len, + uint8_t **out, size_t *outlen) +{ + int digest_algors[] = { OID_sm3 }; + size_t digest_algors_cnt = sizeof(digest_algors)/sizeof(int); + uint8_t content_header[256]; + size_t content_header_len; + size_t certs_len = 0; + uint8_t signer_infos[512]; + size_t signer_infos_len = 0; + SM3_CTX sm3_ctx; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + uint8_t *p; + size_t len = 0; + size_t i; + + + // 当content_type == OID_cms_data 时,data是raw data,被封装为OCTET STRING编码输出 + // 而content_type为其他类型时,data均为TLV的DER数据 + // 在to_der/from_der 中已经处理,但是计算哈希值时也需要做处理 + p = content_header; + content_header_len = 0; + if (content_type == OID_cms_data) { + size_t content_len = 0; + if (asn1_octet_string_to_der(data, datalen, NULL, &content_len) != 1 + || cms_content_info_header_to_der(content_type, content_len, &p, &content_header_len) != 1 + || asn1_octet_string_header_to_der(datalen, &p, &content_header_len) != 1) { + error_print(); + return -1; + } + } else { + if (cms_content_info_header_to_der(content_type, datalen, &p, &content_header_len) != 1) { + error_print(); + return -1; + } + } + + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, content_header, content_header_len); + sm3_update(&sm3_ctx, data, datalen); + + for (i = 0; i < signers_cnt; i++) { + if (x509_cert_get_issuer_and_serial_number( + signers[i].certs, signers[i].certs_len, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || cms_signer_infos_add_signer_info( + signer_infos, &signer_infos_len, sizeof(signer_infos), + &sm3_ctx, signers->sign_key, + issuer, issuer_len, serial, serial_len, + NULL, 0, NULL, 0) != 1) { + error_print(); + return -1; + } + } + + if (asn1_int_to_der(CMS_version_v1, NULL, &len) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, NULL, &len) != 1 + || cms_content_info_to_der(content_type, data, datalen, NULL, &len) != 1 + || cms_implicit_signers_certs_to_der(0, signers, signers_cnt, NULL, &len) < 0 + || asn1_implicit_set_to_der(1, crls, crls_len, NULL, &len) < 0 + || asn1_set_to_der(signer_infos, signer_infos_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, out, outlen) != 1 + || cms_content_info_to_der(content_type, data, datalen, out, outlen) != 1 + || cms_implicit_signers_certs_to_der(0, signers, signers_cnt, out, outlen) < 0 + || asn1_implicit_set_to_der(1, crls, crls_len, out, outlen) < 0 + || asn1_set_to_der(signer_infos, signer_infos_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signed_data_verify_from_der( + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_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 **psigner_infos, size_t *psigner_infos_len, + const uint8_t **in, size_t *inlen) +{ + int version; + int digest_algors[4]; + size_t digest_algors_cnt; + SM3_CTX sm3_ctx; + uint8_t content_info_header[128]; + size_t content_info_header_len; + uint8_t *p = content_info_header; + const uint8_t *signer_infos; + size_t signer_infos_len; + + if (cms_signed_data_from_der( + &version, + digest_algors, &digest_algors_cnt, sizeof(digest_algors)/sizeof(int), + content_type, content, content_len, + certs, certs_len, + crls, crls_len, + &signer_infos, &signer_infos_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || asn1_check(digest_algors[0] == OID_sm3) != 1 + || asn1_check(digest_algors_cnt == 1) != 1) { + error_print(); + return -1; + } + *psigner_infos = signer_infos; + *psigner_infos_len = signer_infos_len; + + content_info_header_len = 0; + if (cms_content_info_header_to_der(*content_type, *content_len, + &p, &content_info_header_len) != 1) { + error_print(); + return -1; + } + sm3_init(&sm3_ctx); + + sm3_update(&sm3_ctx, content_info_header, content_info_header_len); + sm3_update(&sm3_ctx, *content, *content_len); + + while (signer_infos_len) { + const uint8_t *cert; + size_t certlen; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + const uint8_t *authed_attrs; + size_t authed_attrs_len; + const uint8_t *unauthed_attrs; + size_t unauthed_attrs_len; + + if (cms_signer_info_verify_from_der( + &sm3_ctx, *certs, *certs_len, + &cert, &certlen, + &issuer, &issuer_len, + &serial, &serial_len, + &authed_attrs, &authed_attrs_len, + &unauthed_attrs, &unauthed_attrs_len, + &signer_infos, &signer_infos_len) != 1) { + + error_print(); + return -1; + } + } + return 1; +} + +int cms_recipient_info_to_der( + int version, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + int public_key_enc_algor, + const uint8_t *enced_key, size_t enced_key_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (version != 1) { + error_print(); + return -1; + } + if (asn1_int_to_der(version, NULL, &len) != 1 + || cms_issuer_and_serial_number_to_der(issuer, issuer_len, + serial_number, serial_number_len, NULL, &len) != 1 + || x509_public_key_encryption_algor_to_der(public_key_enc_algor, NULL, &len) != 1 + || asn1_octet_string_to_der(enced_key, enced_key_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || cms_issuer_and_serial_number_to_der(issuer, issuer_len, + serial_number, serial_number_len, out, outlen) != 1 + || x509_public_key_encryption_algor_to_der(public_key_enc_algor, out, outlen) != 1 + || asn1_octet_string_to_der(enced_key, enced_key_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_recipient_info_from_der( + int *version, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len, + int *pke_algor, const uint8_t **params, size_t *params_len,// SM2加密只使用SM3,没有默认参数,但是ECIES可能有 + const uint8_t **enced_key, size_t *enced_key_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || cms_issuer_and_serial_number_from_der(issuer, issuer_len, + serial_number, serial_number_len, &d, &dlen) != 1 + || x509_public_key_encryption_algor_from_der(pke_algor, params, params_len, &d, &dlen) != 1 + || asn1_octet_string_from_der(enced_key, enced_key_len, &d, &dlen) != 1 + // || asn1_length_is_zero(dlen) != 1 + ) { + error_print(); + return -1; + } + if (*version != 1) { + error_print(); + return -1; + } + if (*pke_algor != OID_sm2encrypt) { + error_print(); + return -1; + } + if (*params || *params_len) { + error_print(); + return -1; + } + return 1; +} + +int cms_recipient_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_issuer_and_serial_number_print(fp, fmt, ind, "issuerAndSerialNumber", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_encryption_algor_print(fp, fmt, ind, "keyEncryptionAlgorithm", p, len); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "encryptedKey", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_recipient_info_encrypt_to_der( + const SM2_KEY *public_key, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial_number, size_t serial_number_len, + const uint8_t *in, size_t inlen, + uint8_t **out, size_t *outlen) +{ + int pke_algor = OID_sm2encrypt; + uint8_t enced_key[SM2_MAX_CIPHERTEXT_SIZE]; + size_t enced_key_len; + int fixed_outlen = 1; + + if (pke_algor != OID_sm2encrypt) { + error_print(); + return -1; + } + + if (sm2_encrypt_fixlen(public_key, in, inlen, SM2_ciphertext_typical_point_size, + enced_key, &enced_key_len) != 1) { + error_print(); + return -1; + } + if (cms_recipient_info_to_der(CMS_version_v1, + issuer, issuer_len, serial_number, serial_number_len, + pke_algor, enced_key, enced_key_len, + out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_recipient_info_decrypt_from_der( + const SM2_KEY *sm2_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, + uint8_t *out, size_t *outlen, size_t maxlen, + const uint8_t **in, size_t *inlen) +{ + int version; + int pke_algor; + const uint8_t *params; + size_t params_len; + const uint8_t *enced_key; + size_t enced_key_len; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + uint8_t outbuf[SM2_MAX_PLAINTEXT_SIZE]; + + if (cms_recipient_info_from_der(&version, + &issuer, &issuer_len, &serial, &serial_len, + &pke_algor, ¶ms, ¶ms_len, + &enced_key, &enced_key_len, + in, inlen) != 1) { + error_print(); + return -1; + } + if (issuer_len != rcpt_issuer_len + || memcmp(issuer, rcpt_issuer, rcpt_issuer_len) != 0 + || serial_len != rcpt_serial_len + || memcmp(serial, rcpt_serial, serial_len) != 0) { + error_print(); + return 0; + } + if (pke_algor != OID_sm2encrypt || params || params_len) { + error_print(); + return -1; + } + if (sm2_decrypt(sm2_key, enced_key, enced_key_len, outbuf, outlen) != 1) { + error_print(); + return -1; + } + if (maxlen < *outlen) { + error_print(); + return -1; + } + memcpy(out, outbuf, *outlen); + return 1; +} + +int cms_recipient_infos_add_recipient_info( + uint8_t *d, size_t *dlen, size_t maxlen, + const SM2_KEY *public_key, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + const uint8_t *in, size_t inlen) +{ + size_t len = *dlen; + d += *dlen; + + if (cms_recipient_info_encrypt_to_der( + public_key, + issuer, issuer_len, + serial, serial_len, + in, inlen, + NULL, &len) != 1 + || asn1_length_le(len, maxlen) != 1 + || cms_recipient_info_encrypt_to_der( + public_key, + issuer, issuer_len, + serial, serial_len, + in, inlen, + &d, dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_recipient_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + cms_recipient_info_print(fp, fmt, ind, "RecipientInfo", p, len); + } + return 1; +} + +int cms_enveloped_data_to_der( + int version, + const uint8_t *rcpt_infos, size_t rcpt_infos_len, + int content_type, + int enc_algor, const uint8_t *iv, size_t ivlen, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_int_to_der(version, NULL, &len) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, NULL, &len) != 1 + || cms_enced_content_info_to_der(content_type, + enc_algor, iv, ivlen, + enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, out, outlen) != 1 + || cms_enced_content_info_to_der(content_type, + enc_algor, iv, ivlen, + enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_enveloped_data_from_der( + int *version, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **enced_content_info, size_t *enced_content_info_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || asn1_set_from_der(rcpt_infos, rcpt_infos_len, &d, &dlen) != 1 + || asn1_any_from_der(enced_content_info, enced_content_info_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_recipient_infos_print(fp, fmt, ind, "recipientInfos", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_enced_content_info_print(fp, fmt, ind, "encryptedContentInfo", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_enveloped_data_encrypt_to_der( + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen) +{ + uint8_t rcpt_infos[1024]; // 到底需要多大? + size_t rcpt_infos_len = 0; + uint8_t *p = rcpt_infos; + size_t len = 0; + + while (rcpt_certs_len) { + const uint8_t *cert; + size_t certlen; + SM2_KEY public_key; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + + if (asn1_any_from_der(&cert, &certlen, &rcpt_certs, &rcpt_certs_len) != 1 + || x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) { + error_print(); + return -1; + } + if (cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, NULL, &len) != 1 + || asn1_length_le(len, sizeof(rcpt_infos)) != 1 + || cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, &p, &rcpt_infos_len) != 1) { + error_print(); + return -1; + } + } + len = 0; + if (asn1_int_to_der(CMS_version_v1, NULL, &len) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, NULL, &len) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, out, outlen) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_enveloped_data_decrypt_from_der( + const SM2_KEY *sm2_key, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **recipient_infos, size_t *recipient_infos_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **in, size_t *inlen) +{ + int ret = 0; + int version; + const uint8_t *rcpt_infos; + size_t rcpt_infos_len; + const uint8_t *enced_content_info; + size_t enced_content_info_len; + int enc_algor; + uint8_t key[32]; + size_t keylen; + + if (cms_enveloped_data_from_der( + &version, &rcpt_infos, &rcpt_infos_len, + &enced_content_info, &enced_content_info_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1) { + return -1; + } + *recipient_infos = rcpt_infos; + *recipient_infos_len = rcpt_infos_len; + + while (rcpt_infos_len) { + if ((ret = cms_recipient_info_decrypt_from_der( + sm2_key, + issuer, issuer_len, + serial, serial_len, + key, &keylen, sizeof(key), + &rcpt_infos, &rcpt_infos_len)) < 0) { + error_print(); + return -1; + } else if (ret) { + break; + } + } + if (!ret) { + error_print(); + return -1; + } + + if (cms_enced_content_info_decrypt_from_der( + &enc_algor, key, keylen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &enced_content_info, &enced_content_info_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signed_and_enveloped_data_to_der( + int version, + const uint8_t *rcpt_infos, size_t rcpt_infos_len, + const int *digest_algors, size_t digest_algors_cnt, + int content_type, + int enc_algor, const uint8_t *iv, size_t ivlen, + const uint8_t *enced_content, size_t enced_content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_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, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_int_to_der(version, NULL, &len) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, NULL, &len) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, NULL, &len) != 1 + || cms_enced_content_info_to_der(content_type, + enc_algor, iv, ivlen, + enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1 + || asn1_implicit_set_to_der(0, certs, certs_len, NULL, &len) < 0 + || asn1_implicit_set_to_der(1, crls, crls_len, NULL, &len) < 0 + || asn1_set_to_der(signer_infos, signer_infos_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, out, outlen) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, out, outlen) != 1 + || cms_enced_content_info_to_der(content_type, + enc_algor, iv, ivlen, + enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen) != 1 + || asn1_implicit_set_to_der(0, certs, certs_len, out, outlen) < 0 + || asn1_implicit_set_to_der(1, crls, crls_len, out, outlen) < 0 + || asn1_set_to_der(signer_infos, signer_infos_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signed_and_enveloped_data_from_der( + int *version, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + const uint8_t **enced_content_info, size_t *enced_content_info_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 ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || asn1_set_from_der(rcpt_infos, rcpt_infos_len, &d, &dlen) != 1 + || cms_digest_algors_from_der(digest_algors, digest_algors_cnt, max_digest_algors, &d, &dlen) != 1 + || asn1_any_from_der(enced_content_info, enced_content_info_len, &d, &dlen) != 1 + || asn1_implicit_set_from_der(0, certs, certs_len, &d, &dlen) < 0 + || asn1_implicit_set_from_der(1, crls, crls_len, &d, &dlen) < 0 + || asn1_set_from_der(signer_infos, signer_infos_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signed_and_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_recipient_infos_print(fp, fmt, ind, "recipientInfos", p, len); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_digest_algors_print(fp, fmt, ind, "digestAlgorithms", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_enced_content_info_print(fp, fmt, ind, "encryptedContentInfo", p, len); + if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_certs_print(fp, fmt, ind, "certificates", p, len); + if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_crls_print(fp, fmt, ind, "crls", p, len); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_signer_infos_print(fp, fmt, ind, "signerInfos", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_signed_and_enveloped_data_encipher_to_der( + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *signers_crls, size_t signers_crls_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len, + uint8_t **out, size_t *outlen) +{ + uint8_t rcpt_infos[512]; + size_t rcpt_infos_len = 0; + int digest_algors[] = { OID_sm3 }; + size_t digest_algors_cnt = sizeof(digest_algors)/sizeof(int); + uint8_t content_info_header[256]; + size_t content_info_header_len = 0; + uint8_t signer_infos[512]; + size_t signer_infos_len = 0; + SM3_CTX sm3_ctx; + const uint8_t *issuer; + const uint8_t *serial; + size_t issuer_len; + size_t serial_len; + uint8_t *p; + size_t len = 0; + size_t i; + + p = rcpt_infos; + while (rcpt_certs_len) { + const uint8_t *cert; + size_t certlen; + SM2_KEY public_key; + + if (asn1_any_from_der(&cert, &certlen, &rcpt_certs, &rcpt_certs_len) != 1 + || x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1 + || cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, NULL, &len) != 1 + || asn1_length_le(len, sizeof(rcpt_infos)) != 1 + || cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, &p, &rcpt_infos_len) != 1) { + error_print(); + return -1; + } + } + + p = content_info_header; + if (cms_content_info_header_to_der(content_type, content_len, + &p, &content_info_header_len) != 1) { + error_print(); + return -1; + } + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, content_info_header, content_info_header_len); + sm3_update(&sm3_ctx, content, content_len); + + for (i = 0; i < signers_cnt; i++) { + if (x509_cert_get_issuer_and_serial_number( + signers[i].certs, signers[i].certs_len, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || cms_signer_infos_add_signer_info( + signer_infos, &signer_infos_len, sizeof(signer_infos), + &sm3_ctx, signers->sign_key, + issuer, issuer_len, serial, serial_len, + NULL, 0, NULL, 0) != 1) { + error_print(); + return -1; + } + } + + len = 0; + if (asn1_int_to_der(CMS_version_v1, NULL, &len) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, NULL, &len) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, NULL, &len) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1 + || cms_implicit_signers_certs_to_der(0, signers, signers_cnt, NULL, &len) != 1 + || asn1_implicit_set_to_der(1, signers_crls, signers_crls_len, NULL, &len) < 0 + || asn1_set_to_der(signer_infos, signer_infos_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, out, outlen) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, out, outlen) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen) != 1 + || cms_implicit_signers_certs_to_der(0, signers, signers_cnt, out, outlen) != 1 + || asn1_implicit_set_to_der(1, signers_crls, signers_crls_len, out, outlen) != 1 + || asn1_set_to_der(signer_infos, signer_infos_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_signed_and_enveloped_data_decipher_from_der( + const SM2_KEY *rcpt_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **prcpt_infos, size_t *prcpt_infos_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **certs, size_t *certs_len, + const uint8_t **crls, size_t *crls_len, + const uint8_t **psigner_infos, size_t *psigner_infos_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + int version; + const uint8_t *rcpt_infos; + size_t rcpt_infos_len; + int digest_algors[4]; + size_t digest_algors_cnt; + const uint8_t *enced_content_info; + size_t enced_content_info_len; + const uint8_t *signer_infos; + size_t signer_infos_len; + int enc_algor; + uint8_t key[32]; + size_t keylen; + SM3_CTX sm3_ctx; + uint8_t content_info_header[128]; + size_t content_info_header_len = 0; + uint8_t *p = content_info_header; + + if (cms_signed_and_enveloped_data_from_der( + &version, + &rcpt_infos, &rcpt_infos_len, + digest_algors, &digest_algors_cnt, sizeof(digest_algors)/sizeof(int), + &enced_content_info, &enced_content_info_len, + certs, certs_len, + crls, crls_len, + &signer_infos, &signer_infos_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || asn1_check(digest_algors[0] == OID_sm3) != 1) { + error_print(); + return -1; + } + *prcpt_infos = rcpt_infos; + *prcpt_infos_len = rcpt_infos_len; + *psigner_infos = signer_infos; + *psigner_infos_len = signer_infos_len; + + while (rcpt_infos_len) { + if ((ret = cms_recipient_info_decrypt_from_der( + rcpt_key, + rcpt_issuer, rcpt_issuer_len, + rcpt_serial, rcpt_serial_len, + key, &keylen, sizeof(key), + &rcpt_infos, &rcpt_infos_len)) < 0) { + error_print(); + return -1; + } else if (ret) { + break; + } + } + if (!ret) { + error_print(); + return -1; + } + + if (cms_enced_content_info_decrypt_from_der( + &enc_algor, key, keylen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &enced_content_info, &enced_content_info_len) != 1) { + error_print(); + return -1; + } + + if (cms_content_info_header_to_der(*content_type, *content_len, + &p, &content_info_header_len) != 1) { + error_print(); + return -1; + } + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, content_info_header, content_info_header_len); + sm3_update(&sm3_ctx, content, *content_len); + + while (signer_infos_len) { + const uint8_t *cert; + size_t certlen; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + const uint8_t *authed_attrs; + size_t authed_attrs_len; + const uint8_t *unauthed_attrs; + size_t unauthed_attrs_len; + + if (cms_signer_info_verify_from_der( + &sm3_ctx, *certs, *certs_len, + &cert, &certlen, + &issuer, &issuer_len, + &serial, &serial_len, + &authed_attrs, &authed_attrs_len, + &unauthed_attrs, &unauthed_attrs_len, + &signer_infos, &signer_infos_len) != 1) { + error_print(); + return -1; + } + } + + return 1; +} + +int cms_key_agreement_info_to_der( + int version, + const SM2_KEY *temp_public_key_r, + const uint8_t *user_cert, size_t user_cert_len, + const uint8_t *user_id, size_t user_id_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_int_to_der(version, NULL, &len) != 1 + || sm2_public_key_info_to_der(temp_public_key_r, NULL, &len) != 1 + || x509_cert_to_der(user_cert, user_cert_len, NULL, &len) != 1 + || asn1_octet_string_to_der(user_id, user_id_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || sm2_public_key_info_to_der(temp_public_key_r, out, outlen) != 1 + || x509_cert_to_der(user_cert, user_cert_len, out, outlen) != 1 + || asn1_octet_string_to_der(user_id, user_id_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_key_agreement_info_from_der( + int *version, + SM2_KEY *temp_public_key_r, + const uint8_t **user_cert, size_t *user_cert_len, + const uint8_t **user_id, size_t *user_id_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || sm2_public_key_info_from_der(temp_public_key_r, &d, &dlen) != 1 + || x509_cert_from_der(user_cert, user_cert_len, &d, &dlen) != 1 + || asn1_octet_string_from_der(user_id, user_id_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_key_agreement_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int val; + SM2_KEY pub_key; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (sm2_public_key_info_from_der(&pub_key, &d, &dlen) != 1) goto err; + sm2_public_key_print(fp, fmt, ind, "tempPublicKeyR", &pub_key); + if (x509_cert_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_cert_print(fp, fmt, ind, "certificate", p, len); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_string(fp, fmt, ind, "userID", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int cms_set_data(uint8_t *cms, size_t *cmslen, const uint8_t *d, size_t dlen) +{ + int oid = OID_cms_data; + size_t len = 0; + + if (asn1_octet_string_to_der(d, dlen, NULL, &len) < 0) { + error_print(); + return -1; + } + *cmslen = 0; + if (!cms) { + uint8_t data[1]; + if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) { + error_print(); + return -1; + } + return 1; + } + if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1 + || asn1_octet_string_to_der(d, dlen, &cms, cmslen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int cms_encrypt(uint8_t *cms, size_t *cmslen, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len) +{ + int oid = OID_cms_encrypted_data; + size_t len = 0; + + if (cms_encrypted_data_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1) { + error_print(); + return -1; + } + *cmslen = 0; + if (!cms) { + uint8_t data[1]; + if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) { + error_print(); + return -1; + } + return 1; + } + if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1 + || cms_encrypted_data_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_decrypt(const uint8_t *cms, size_t cmslen, + int *enc_algor, const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len) +{ + int cms_type; + const uint8_t *cms_content; + size_t cms_content_len; + + if (cms_content_info_from_der(&cms_type, &cms_content, &cms_content_len, &cms, &cmslen) != 1 + || asn1_check(cms_type == OID_cms_encrypted_data) != 1 + || asn1_check(cms_content && cms_content_len) != 1 + || asn1_length_is_zero(cmslen) != 1) { + error_print(); + return -1; + } + if (cms_encrypted_data_decrypt_from_der( + enc_algor, key, keylen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_sign(uint8_t *cms, size_t *cmslen, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *crls, size_t crls_len) +{ + int oid = OID_cms_signed_data; + size_t len = 0; + + if (cms_signed_data_sign_to_der( + signers, signers_cnt, + content_type, content, content_len, + crls, crls_len, + NULL, &len) != 1) { + error_print(); + return -1; + } + *cmslen = 0; + if (!cms) { + uint8_t data[1]; + if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) { + error_print(); + return -1; + } + return 1; + } + if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1 + || cms_signed_data_sign_to_der( + signers, signers_cnt, + content_type, content, content_len, + crls, crls_len, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_verify(const uint8_t *cms, size_t cmslen, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_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) +{ + int cms_type; + const uint8_t *cms_content; + size_t cms_content_len; + + if (cms_content_info_from_der(&cms_type, &cms_content, &cms_content_len, &cms, &cmslen) != 1 + || asn1_length_is_zero(cmslen) != 1) { + error_print(); + return -1; + } + if (cms_type != OID_cms_signed_data) { + error_print(); + return -1; + } + if (cms_content_len <= 0) { + error_print(); + return -1; + } + + if (cms_signed_data_verify_from_der( + extra_certs, extra_certs_len, + extra_crls, extra_crls_len, + content_type, content, content_len, + certs, certs_len, + crls, crls_len, + signer_infos, signer_infos_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_envelop( + uint8_t *cms, size_t *cmslen, + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len) +{ + int oid = OID_cms_enveloped_data; + size_t len = 0; + + if (cms_enveloped_data_encrypt_to_der( + rcpt_certs, rcpt_certs_len, + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1) { + error_print(); + return -1; + } + *cmslen = 0; + if (!cms) { + uint8_t data[1]; + if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) { + error_print(); + return -1; + } + return 1; + } + if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1 + || cms_enveloped_data_encrypt_to_der( + rcpt_certs, rcpt_certs_len, + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_deenvelop(const uint8_t *cms, size_t cmslen, + const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len) +{ + int cms_type; + const uint8_t *cms_content; + size_t cms_content_len; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + SM2_KEY public_key; + + if (cms_content_info_from_der(&cms_type, &cms_content, &cms_content_len, &cms, &cmslen) != 1 + || asn1_check(cms_type == OID_cms_enveloped_data) != 1 + || asn1_check(cms_content && cms_content_len) != 1 + || asn1_length_is_zero(cmslen) != 1) { + error_print(); + return -1; + } + + if (x509_cert_get_issuer_and_serial_number(rcpt_cert, rcpt_cert_len, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject_public_key(rcpt_cert, rcpt_cert_len, + &public_key) != 1) { + error_print(); + return -1; + } + if (memcmp(&public_key, rcpt_key, sizeof(SM2_POINT)) != 0) { + error_print(); + return -1; + } + + if (cms_enveloped_data_decrypt_from_der( + rcpt_key, issuer, issuer_len, serial, serial_len, + content_type, content, content_len, + rcpt_infos, rcpt_infos_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_sign_and_envelop(uint8_t *cms, size_t *cmslen, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *crls, size_t crls_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len) +{ + int oid = OID_cms_signed_and_enveloped_data; + size_t len = 0; + + if (cms_signed_and_enveloped_data_encipher_to_der( + signers, signers_cnt, + rcpt_certs, rcpt_certs_len, + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + crls, crls_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + NULL, &len) != 1) { + error_print(); + return -1; + } + *cmslen = 0; + if (!cms) { + uint8_t data[1]; + if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) { + error_print(); + return -1; + } + return 1; + } + if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1 + || cms_signed_and_enveloped_data_encipher_to_der( + signers, signers_cnt, + rcpt_certs, rcpt_certs_len, + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + crls, crls_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_deenvelop_and_verify(const uint8_t *cms, size_t cmslen, + const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **signer_infos, size_t *signer_infos_len, + const uint8_t **certs, size_t *certs_len, + const uint8_t **crls, size_t *crls_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len) +{ + const uint8_t *rcpt_issuer; + size_t rcpt_issuer_len; + const uint8_t *rcpt_serial; + size_t rcpt_serial_len; + SM2_KEY public_key; + int cms_type; + const uint8_t *cms_content; + size_t cms_content_len; + + if (cms_content_info_from_der(&cms_type, &cms_content, &cms_content_len, &cms, &cmslen) != 1 + || asn1_check(cms_type == OID_cms_signed_and_enveloped_data) != 1 + || asn1_check(cms_content && cms_content_len) != 1 + || asn1_length_is_zero(cmslen) != 1) { + error_print(); + return -1; + } + + if (x509_cert_get_issuer_and_serial_number(rcpt_cert, rcpt_cert_len, + &rcpt_issuer, &rcpt_issuer_len, + &rcpt_serial, &rcpt_serial_len) != 1 + || x509_cert_get_subject_public_key(rcpt_cert, rcpt_cert_len, + &public_key) != 1) { + error_print(); + return -1; + } + if (memcmp(&public_key, rcpt_key, sizeof(SM2_POINT)) != 0) { + error_print(); + return -1; + } + + if (cms_signed_and_enveloped_data_decipher_from_der( + rcpt_key, + rcpt_issuer, rcpt_issuer_len, + rcpt_serial, rcpt_serial_len, + content_type, content, content_len, + rcpt_infos, rcpt_infos_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + certs, certs_len, + crls, crls_len, + signer_infos, signer_infos_len, + extra_certs, extra_certs_len, + extra_crls, extra_crls_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_set_key_agreement_info( + uint8_t *cms, size_t *cmslen, + const SM2_KEY *temp_public_key_r, + const uint8_t *user_cert, size_t user_cert_len, + const uint8_t *user_id, size_t user_id_len) +{ + int oid = OID_cms_key_agreement_info; + size_t len = 0; + + if (cms_key_agreement_info_to_der(CMS_version_v1, temp_public_key_r, + user_cert, user_cert_len, user_id, user_id_len, NULL, &len) != 1) { + error_print(); + return -1; + } + *cmslen = 0; + if (!cms) { + uint8_t data[1]; + if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) { + error_print(); + return -1; + } + return 1; + } + if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1 + || cms_key_agreement_info_to_der(CMS_version_v1, temp_public_key_r, + user_cert, user_cert_len, user_id, user_id_len, &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_to_pem(const uint8_t *cms, size_t cms_len, FILE *fp) +{ + if (pem_write(fp, PEM_CMS, cms, cms_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_from_pem(uint8_t *cms, size_t *cms_len, size_t maxlen, FILE *fp) +{ + int ret; + if ((ret = pem_read(fp, PEM_CMS, cms, cms_len, maxlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + + return 1; +} + +int cms_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + const uint8_t *d; + size_t dlen; + + + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1) goto err; + + + cms_content_info_print(fp, fmt, ind, label, d, dlen); + //if (asn1_length_is_zero(alen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + diff --git a/Core/GmSSL-3.1.1/src/debug.c b/Core/GmSSL-3.1.1/src/debug.c new file mode 100644 index 0000000..1e929fd --- /dev/null +++ b/Core/GmSSL-3.1.1/src/debug.c @@ -0,0 +1,112 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + +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; + + if (datalen > 4096) { + error_print(); + return -1; + } + + 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 format_string(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + while (ind--) { + fprintf(fp, " "); + } + fprintf(fp, "%s: ", label); + while (dlen--) { + fprintf(fp, "%c", *d++); + } + 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; +} + diff --git a/Core/GmSSL-3.1.1/src/des.c b/Core/GmSSL-3.1.1/src/des.c new file mode 100644 index 0000000..0aab160 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/des.c @@ -0,0 +1,229 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +/* 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) & 0xffffffff; + 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 & 0xffffffff; + } + + T = ((uint64_t)L << 32) | R; + + /* inverse initial permutation */ + T = permute(IP_inv, sizeof(IP_inv), T); + + PUTU64(out, T); +} diff --git a/Core/GmSSL-3.1.1/src/digest.c b/Core/GmSSL-3.1.1/src/digest.c new file mode 100644 index 0000000..ba23d07 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/digest.c @@ -0,0 +1,504 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include + + +typedef struct { + int oid; + char *short_name; + char *display_name; +} DIGEST_TABLE; + +DIGEST_TABLE digest_table[] = { + { OID_sm3, "sm3", "SM3" }, +#ifdef ENABLE_BROKEN_CRYPTO + { OID_md5, "md5", "MD5" }, + { OID_sha1, "sha1", "SHA-1" }, +#endif + { 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->oid == digest_table[i].oid) { + return digest_table[i].short_name; + } + } + return NULL; +} + +int digest_init(DIGEST_CTX *ctx, const DIGEST *algor) +{ + memset(ctx, 0, sizeof(DIGEST_CTX)); + if (algor == NULL) { + error_print(); + return -1; + } + ctx->digest = algor; + ctx->digest->init(ctx); + return 1; +} + +int digest_update(DIGEST_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (data == NULL || datalen == 0) { + return 0; + } + ctx->digest->update(ctx, data, datalen); + return 1; +} + +int digest_finish(DIGEST_CTX *ctx, uint8_t *dgst, size_t *dgstlen) +{ + if (dgst == NULL || dgstlen == NULL) { + error_print(); + return -1; + } + ctx->digest->finish(ctx, dgst); + *dgstlen = ctx->digest->digest_size; + return 1; +} + +int digest(const DIGEST *digest, const uint8_t *data, size_t datalen, + uint8_t *dgst, size_t *dgstlen) +{ + DIGEST_CTX ctx; + if (digest_init(&ctx, digest) != 1 + || digest_update(&ctx, data, datalen) < 0 + || digest_finish(&ctx, dgst, dgstlen) != 1) { + error_print(); + return -1; + } + memset(&ctx, 0, sizeof(DIGEST_CTX)); + return 1; +} + +const DIGEST *digest_from_name(const char *name) +{ + if (!strcmp(name, "sm3") || !strcmp(name, "SM3")) { + return DIGEST_sm3(); +#ifdef ENABLE_BROKEN_CRYPTO + } else if (!strcmp(name, "md5") || !strcmp(name, "MD5")) { + return DIGEST_md5(); + } else if (!strcmp(name, "sha1") || !strcmp(name, "SHA1")) { + return DIGEST_sha1(); +#endif + } 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) { + error_print(); + return -1; + } + sm3_init(&ctx->u.sm3_ctx); + return 1; +} + +static int sm3_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) +{ + if (!ctx || (!in && inlen != 0)) { + error_print(); + return -1; + } + sm3_update(&ctx->u.sm3_ctx, in, inlen); + return 1; +} + +static int sm3_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) +{ + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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; +} + +#ifdef ENABLE_BROKEN_CRYPTO + +#include + +static int md5_digest_init(DIGEST_CTX *ctx) +{ + if (!ctx) { + error_print(); + return -1; + } + md5_init(&ctx->u.md5_ctx); + return 1; +} + +static int md5_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) +{ + if (!ctx || (!in && inlen != 0)) { + error_print(); + return -1; + } + md5_update(&ctx->u.md5_ctx, in, inlen); + return 1; +} + +static int md5_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) +{ + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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 + +static int sha1_digest_init(DIGEST_CTX *ctx) +{ + if (!ctx) { + error_print(); + return -1; + } + sha1_init(&ctx->u.sha1_ctx); + return 1; +} + +static int sha1_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) +{ + if (!ctx || (!in && inlen != 0)) { + error_print(); + return -1; + } + sha1_update(&ctx->u.sha1_ctx, in, inlen); + return 1; +} + +static int sha1_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) +{ + if (!ctx || !dgst) { + error_print(); + return -1; + } + sha1_finish(&ctx->u.sha1_ctx, dgst); + return 1; +} + +static const DIGEST sha1_digest_object = { + OID_sha1, + SHA1_DIGEST_SIZE, + SHA1_BLOCK_SIZE, + sizeof(SHA1_CTX), + sha1_digest_init, + sha1_digest_update, + sha1_digest_finish, +}; + +const DIGEST *DIGEST_sha1(void) +{ + return &sha1_digest_object; +} +#endif + +#include + +static int sha224_digest_init(DIGEST_CTX *ctx) +{ + if (!ctx) { + error_print(); + return -1; + } + sha224_init(&ctx->u.sha224_ctx); + return 1; +} + +static int sha224_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) +{ + if (!ctx || (!in && inlen != 0)) { + error_print(); + return -1; + } + sha224_update(&ctx->u.sha224_ctx, in, inlen); + return 1; +} + +static int sha224_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) +{ + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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) { + error_print(); + return -1; + } + sha256_init(&ctx->u.sha256_ctx); + return 1; +} + +static int sha256_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) +{ + if (!ctx || (!in && inlen != 0)) { + error_print(); + return -1; + } + sha256_update(&ctx->u.sha256_ctx, in, inlen); + return 1; +} + +static int sha256_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) +{ + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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) { + error_print(); + return -1; + } + sha384_init(&ctx->u.sha384_ctx); + return 1; +} + +static int sha384_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) +{ + if (!ctx || (!in && inlen != 0)) { + error_print(); + return -1; + } + sha384_update(&ctx->u.sha384_ctx, in, inlen); + return 1; +} + +static int sha384_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) +{ + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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) { + error_print(); + return -1; + } + sha512_init(&ctx->u.sha512_ctx); + return 1; +} + +static int sha512_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) +{ + if (!ctx || (!in && inlen != 0)) { + error_print(); + return -1; + } + sha512_update(&ctx->u.sha512_ctx, in, inlen); + return 1; +} + +static int sha512_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) +{ + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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, uint8_t *dgst) +{ + uint8_t buf[SHA512_DIGEST_SIZE]; + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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, uint8_t *dgst) +{ + uint8_t buf[SHA512_DIGEST_SIZE]; + if (!ctx || !dgst) { + error_print(); + return -1; + } + 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; +} diff --git a/Core/GmSSL-3.1.1/src/ec.c b/Core/GmSSL-3.1.1/src/ec.c new file mode 100644 index 0000000..f8bb034 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/ec.c @@ -0,0 +1,140 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +#define oid_sm_scheme 1,2,156,10197,1 +static uint32_t oid_sm2[] = { oid_sm_scheme,301 }; + +#define oid_x9_62_curves oid_x9_62,3 +#define oid_x9_62_prime_curves oid_x9_62_curves,1 +static uint32_t oid_prime192v1[] = { oid_x9_62_prime_curves,1 }; +static uint32_t oid_prime256v1[] = { oid_x9_62_prime_curves,7 }; // NIST P-256 + +#define oid_secg_curve 1,3,132,0 +static uint32_t oid_secp256k1[] = { oid_secg_curve,10 }; +static uint32_t oid_secp384r1[] = { oid_secg_curve,34 }; // NIST P-384 +static uint32_t oid_secp521r1[] = { oid_secg_curve,35 }; // NIST P-521 + + +static const ASN1_OID_INFO ec_named_curves[] = { + { OID_sm2, "sm2p256v1", oid_sm2, sizeof(oid_sm2)/sizeof(int), 0, "SM2" }, + { OID_prime192v1, "prime192v1", oid_prime192v1, sizeof(oid_prime192v1)/sizeof(int), 0, }, + { OID_prime256v1, "prime256v1", oid_prime256v1, sizeof(oid_prime256v1)/sizeof(int), 0, "NIST P-256" }, + { OID_secp256k1, "secp256k1", oid_secp256k1, sizeof(oid_secp256k1)/sizeof(int) }, + { OID_secp384r1, "secp384r1", oid_secp384r1, sizeof(oid_secp384r1)/sizeof(int), 0, "NIST P-384" }, + { OID_secp521r1, "secp521r1", oid_secp521r1, sizeof(oid_secp521r1)/sizeof(int), 0, "NIST P-521" } +}; + +static const int ec_named_curves_count = + sizeof(ec_named_curves)/sizeof(ec_named_curves[0]); + +const char *ec_named_curve_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(ec_named_curves, ec_named_curves_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int ec_named_curve_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(ec_named_curves, ec_named_curves_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int ec_named_curve_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(ec_named_curves, ec_named_curves_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int ec_named_curve_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + if ((ret = asn1_oid_info_from_der(&info, ec_named_curves, ec_named_curves_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + +int ec_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, label, p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int ec_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *a; + size_t alen; + const uint8_t *p; + size_t len; + int val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "privateKey", p, len); + if ((ret = asn1_explicit_from_der(0, &a, &alen, &d, &dlen)) < 0) goto err; + else if (ret) { + if (ec_named_curve_from_der(&val, &a, &alen) != 1) goto err; + format_print(fp, fmt, ind, "parameters: %s\n", ec_named_curve_name(val)); + if (asn1_length_is_zero(alen) != 1) goto err; + } + format_print(fp, fmt, ind, "publicKey\n"); + ind += 4; + if ((ret = asn1_explicit_from_der(1, &a, &alen, &d, &dlen)) < 0) goto err; + else if (ret) { + if (asn1_bit_octets_from_der(&p, &len, &a, &alen) != 1) goto err; + format_bytes(fp, fmt, ind, "ECPoint", p, len); + if (asn1_length_is_zero(alen) != 1) goto err; + } + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/src/file.c b/Core/GmSSL-3.1.1/src/file.c new file mode 100644 index 0000000..c9327a6 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/file.c @@ -0,0 +1,63 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +int file_size(FILE *fp, size_t *size) +{ + int fd; + struct stat st; + +#ifdef WIN32 + fd = _fileno(fp); +#else + fd = fileno(fp); +#endif + if (fstat(fd, &st) < 0) { + error_print(); + return -1; + } + *size = st.st_size; + return 1; +} + +int file_read_all(const char *file, uint8_t **out, size_t *outlen) +{ + int ret = -1; + FILE *fp = NULL; + size_t fsize; + uint8_t *buf = NULL; + + if (!(fp = fopen(file, "rb")) + || file_size(fp, &fsize) != 1 + || (buf = malloc(fsize)) == NULL) { + error_print(); + goto end; + } + if (fread(buf, 1, fsize, fp) != fsize) { + error_print(); + goto end; + } + *out = buf; + *outlen = fsize; + buf = NULL; + ret = 1; +end: + if (fp) fclose(fp); + if (buf) free(buf); + return ret; +} + diff --git a/Core/GmSSL-3.1.1/src/gcm.c b/Core/GmSSL-3.1.1/src/gcm.c new file mode 100644 index 0000000..b052aea --- /dev/null +++ b/Core/GmSSL-3.1.1/src/gcm.c @@ -0,0 +1,206 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * 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(C))) * H for i = m + n + 1 + */ +void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, const uint8_t *c, size_t clen, uint8_t out[16]) +{ + gf128_t H = gf128_from_bytes(h); + gf128_t X = gf128_zero(); + gf128_t L; + + PUTU64(out, (uint64_t)aadlen << 3); + PUTU64(out + 8, (uint64_t)clen << 3); + L = gf128_from_bytes(out); + + while (aadlen) { + gf128_t A; + if (aadlen >= 16) { + A = gf128_from_bytes(aad); + aad += 16; + aadlen -= 16; + } else { + memset(out, 0, 16); + memcpy(out, aad, aadlen); + A = gf128_from_bytes(out); + aadlen = 0; + } + X = gf128_add(X, A); + X = gf128_mul(X, H); + } + + while (clen) { + gf128_t C; + if (clen >= 16) { + C = gf128_from_bytes(c); + c += 16; + clen -= 16; + } else { + memset(out, 0, 16); + memcpy(out, c, clen); + C = gf128_from_bytes(out); + clen = 0; + } + X = gf128_add(X, C); + X = gf128_mul(X, H); + } + + X = gf128_add(X, L); + H = gf128_mul(X, H); + gf128_to_bytes(H, out); +} + + +void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen) +{ + gf128_t A; + + memset(ctx, 0, sizeof(*ctx)); + ctx->H = gf128_from_bytes(h); + ctx->X = gf128_zero(); + ctx->aadlen = aadlen; + ctx->clen = 0; + + while (aadlen) { + if (aadlen >= 16) { + A = gf128_from_bytes(aad); + aad += 16; + aadlen -= 16; + } else { + memset(ctx->block, 0, 16); + memcpy(ctx->block, aad, aadlen); + A = gf128_from_bytes(ctx->block); + aadlen = 0; + } + ctx->X = gf128_add(ctx->X, A); + ctx->X = gf128_mul(ctx->X, ctx->H); + } +} + +void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen) +{ + gf128_t C; + + assert(ctx->num < 16); + + ctx->clen += clen; + + if (ctx->num) { + size_t left = 16 - ctx->num; + if (clen < left) { + memcpy(ctx->block + ctx->num, c, clen); + ctx->num += clen; + return; + } else { + memcpy(ctx->block + ctx->num, c, left); + C = gf128_from_bytes(ctx->block); + ctx->X = gf128_add(ctx->X, C); + ctx->X = gf128_mul(ctx->X, ctx->H); + c += left; + clen -= left; + } + } + + while (clen >= 16) { + C = gf128_from_bytes(c); + ctx->X = gf128_add(ctx->X, C); + ctx->X = gf128_mul(ctx->X, ctx->H); + c += 16; + clen -= 16; + } + + ctx->num = clen; + if (clen) { + memcpy(ctx->block, c, clen); + } +} + +void ghash_finish(GHASH_CTX *ctx, uint8_t out[16]) +{ + gf128_t C; + gf128_t L; + + if (ctx->num) { + memset(ctx->block + ctx->num, 0, 16 - ctx->num); + C = gf128_from_bytes(ctx->block); + ctx->X = gf128_add(ctx->X, C); + ctx->X = gf128_mul(ctx->X, ctx->H); + } + + PUTU64(ctx->block, (uint64_t)ctx->aadlen << 3); + PUTU64(ctx->block + 8, (uint64_t)ctx->clen << 3); + L = gf128_from_bytes(ctx->block); + + ctx->X = gf128_add(ctx->X, L); + ctx->H = gf128_mul(ctx->X, ctx->H); + gf128_to_bytes(ctx->H, out); + + gmssl_secure_clear(ctx, sizeof(*ctx)); +} + +int gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + uint8_t *out, size_t taglen, uint8_t *tag) +{ + if (key->cipher == BLOCK_CIPHER_sm4()) { + if (sm4_gcm_encrypt(&(key->u.sm4_key), iv, ivlen, aad, aadlen, in, inlen, out, taglen, tag) != 1) { + error_print(); + return -1; + } + } else if (key->cipher == BLOCK_CIPHER_aes128()) { + if (aes_gcm_encrypt(&(key->u.aes_key), iv, ivlen, aad, aadlen, in, inlen, out, taglen, tag) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + const uint8_t *tag, size_t taglen, uint8_t *out) +{ + if (key->cipher == BLOCK_CIPHER_sm4()) { + if (sm4_gcm_decrypt(&(key->u.sm4_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out) != 1) { + error_print(); + return -1; + } + } else if (key->cipher == BLOCK_CIPHER_aes128()) { + if (aes_gcm_decrypt(&(key->u.aes_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out) != 1) { + error_print(); + return -1; + } + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/gf128.c b/Core/GmSSL-3.1.1/src/gf128.c new file mode 100644 index 0000000..8f39969 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/gf128.c @@ -0,0 +1,177 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +/* 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 +#include +#include +#include +#include +#include +#include + + +gf128_t gf128_zero(void) +{ + uint8_t zero[16] = {0}; + return gf128_from_bytes(zero); +} + +gf128_t gf128_from_hex(const char *s) +{ + uint8_t bin[16]; + size_t len; + hex_to_bytes(s, strlen(s), bin, &len); + return gf128_from_bytes(bin); +} + +int gf128_equ_hex(gf128_t a, const char *s) +{ + uint8_t bin1[16]; + uint8_t bin2[16]; + size_t len; + hex_to_bytes(s, strlen(s), bin1, &len); + gf128_to_bytes(a, bin2); + return memcmp(bin1, bin2, sizeof(bin1)) == 0; +} + +void gf128_print_bits(gf128_t a) +{ + int i; + for (i = 0; i < 64; i++) { + printf("%d", (int)(a.hi % 2)); + a.hi >>= 1; + } + for (i = 0; i < 64; i++) { + printf("%d", (int)(a.lo % 2)); + a.lo >>= 1; + } + printf("\n"); +} + +int gf128_print(FILE *fp, int fmt, int ind, const char *label, gf128_t a) +{ + uint8_t be[16]; + int i; + + printf("%s: ", label); + gf128_to_bytes(a, be); + for (i = 0; i < 16; i++) { + printf("%02x", be[i]); + } + printf("\n"); + return 1; +} + +static uint64_t reverse_bits(uint64_t a) +{ + uint64_t r = 0; + int i; + + for (i = 0; i < 63; i++) { + r |= a & 1; + r <<= 1; + a >>= 1; + } + r |= a & 1; + return r; +} + +gf128_t gf128_from_bytes(const uint8_t p[16]) +{ + gf128_t r; + + r.lo = GETU64(p); + r.hi = GETU64(p + 8); + + r.lo = reverse_bits(r.lo); + r.hi = reverse_bits(r.hi); + return r; +} + +void gf128_to_bytes(gf128_t a, uint8_t p[16]) +{ + a.lo = reverse_bits(a.lo); + a.hi = reverse_bits(a.hi); + PUTU64(p, a.lo); + PUTU64(p + 8, a.hi); +} + +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); + r.lo ^= 0x87; + } else { + r.hi = r.hi << 1 | r.lo >> 63; + r.lo = r.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 = r.hi << 1 | r.lo >> 63; + r.lo = r.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; +} diff --git a/Core/GmSSL-3.1.1/src/gf128_avx.c b/Core/GmSSL-3.1.1/src/gf128_avx.c new file mode 100644 index 0000000..09502db --- /dev/null +++ b/Core/GmSSL-3.1.1/src/gf128_avx.c @@ -0,0 +1,225 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +/* 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 +#include +#include +#include +#include +#include +#include +#include + +#include + + +gf128_t gf128_zero(void) +{ + uint8_t zero[16] = {0}; + return gf128_from_bytes(zero); +} + +gf128_t gf128_from_hex(const char *s) +{ + uint8_t bin[16]; + size_t len; + hex_to_bytes(s, strlen(s), bin, &len); + return gf128_from_bytes(bin); +} + +int gf128_equ_hex(gf128_t a, const char *s) +{ + uint8_t bin1[16]; + uint8_t bin2[16]; + size_t len; + hex_to_bytes(s, strlen(s), bin1, &len); + gf128_to_bytes(a, bin2); + return memcmp(bin1, bin2, sizeof(bin1)) == 0; +} + +void gf128_print_bits(gf128_t a) +{ + int i; + for (i = 0; i < 64; i++) { + printf("%d", (int)(a.hi % 2)); + a.hi >>= 1; + } + for (i = 0; i < 64; i++) { + printf("%d", (int)(a.lo % 2)); + a.lo >>= 1; + } + printf("\n"); +} + +int gf128_print(FILE *fp, int fmt, int ind, const char *label, gf128_t a) +{ + uint8_t be[16]; + int i; + + printf("%s: ", label); + gf128_to_bytes(a, be); + for (i = 0; i < 16; i++) { + printf("%02x", be[i]); + } + printf("\n"); + return 1; +} + + +static uint64_t reverse_bits(uint64_t a) +{ + uint64_t r = 0; + int i; + + for (i = 0; i < 63; i++) { + r |= a & 1; + r <<= 1; + a >>= 1; + } + r |= a & 1; + return r; +} + +gf128_t gf128_from_bytes(const uint8_t p[16]) +{ + gf128_t r; + + r.lo = GETU64(p); + r.hi = GETU64(p + 8); + + r.lo = reverse_bits(r.lo); + r.hi = reverse_bits(r.hi); + return r; +} + +void gf128_to_bytes(gf128_t a, uint8_t p[16]) +{ + a.lo = reverse_bits(a.lo); + a.hi = reverse_bits(a.hi); + PUTU64(p, a.lo); + PUTU64(p + 8, a.hi); +} + +gf128_t gf128_add(gf128_t ga, gf128_t gb) +{ + uint8_t r[16], a[16], b[16]; + + gf128_to_bytes(ga, a); + gf128_to_bytes(gb, b); + + __m128i a1 = _mm_loadu_si128((const __m128i*)a); + __m128i b1 = _mm_loadu_si128((const __m128i*)b); + __m128i T0 = _mm_xor_si128(a1, b1); + + _mm_storeu_si128((__m128i*)r, T0); + + return gf128_from_bytes(r); +} + + +gf128_t gf128_mul(gf128_t ga, gf128_t gb) +{ + const __m128i MASK = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + __m128i a1, b1; + __m128i T0, T1, T2, T3, T4, T5; + uint8_t r[16], a[16], b[16]; + + gf128_to_bytes(ga, a); + gf128_to_bytes(gb, b); + + a1 = _mm_loadu_si128((const __m128i*)a); + b1 = _mm_loadu_si128((const __m128i*)b); + + a1 = _mm_shuffle_epi8(a1, MASK); + b1 = _mm_shuffle_epi8(b1, MASK); + + T0 = _mm_clmulepi64_si128(a1, b1, 0x00); + T1 = _mm_clmulepi64_si128(a1, b1, 0x01); + T2 = _mm_clmulepi64_si128(a1, b1, 0x10); + T3 = _mm_clmulepi64_si128(a1, b1, 0x11); + + T1 = _mm_xor_si128(T1, T2); + T2 = _mm_slli_si128(T1, 8); + T1 = _mm_srli_si128(T1, 8); + T0 = _mm_xor_si128(T0, T2); + T3 = _mm_xor_si128(T3, T1); + + T4 = _mm_srli_epi32(T0, 31); + T0 = _mm_slli_epi32(T0, 1); + + T5 = _mm_srli_epi32(T3, 31); + T3 = _mm_slli_epi32(T3, 1); + + T2 = _mm_srli_si128(T4, 12); + T5 = _mm_slli_si128(T5, 4); + T4 = _mm_slli_si128(T4, 4); + T0 = _mm_or_si128(T0, T4); + T3 = _mm_or_si128(T3, T5); + T3 = _mm_or_si128(T3, T2); + + T4 = _mm_slli_epi32(T0, 31); + T5 = _mm_slli_epi32(T0, 30); + T2 = _mm_slli_epi32(T0, 25); + + T4 = _mm_xor_si128(T4, T5); + T4 = _mm_xor_si128(T4, T2); + T5 = _mm_srli_si128(T4, 4); + T3 = _mm_xor_si128(T3, T5); + T4 = _mm_slli_si128(T4, 12); + T0 = _mm_xor_si128(T0, T4); + T3 = _mm_xor_si128(T3, T0); + + T4 = _mm_srli_epi32(T0, 1); + T1 = _mm_srli_epi32(T0, 2); + T2 = _mm_srli_epi32(T0, 7); + T3 = _mm_xor_si128(T3, T1); + T3 = _mm_xor_si128(T3, T2); + T3 = _mm_xor_si128(T3, T4); + + T3 = _mm_shuffle_epi8(T3, MASK); + _mm_storeu_si128((__m128i*)r, T3); + return gf128_from_bytes(r); +} + +gf128_t gf128_mul2(gf128_t ga) +{ + const __m128i MASK = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + __m128i MASK1 = _mm_set_epi8(0xe1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + __m128i MASK2 = _mm_set_epi8(0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + __m128i a1; + __m128i T0, T1, T2, T3, T4, T5; + uint8_t r[16], a[16]; + + gf128_to_bytes(ga, a); + a1 = _mm_loadu_si128((const __m128i*)a); + a1 = _mm_shuffle_epi8(a1, MASK); + + T0 = _mm_srli_epi64(a1,1); + + T1 = _mm_slli_epi64(a1,63); + T2 = _mm_shuffle_epi32(T1,0x0C); + + T3 = _mm_shuffle_epi32(T1,0x40); + T4 = _mm_cmpeq_epi8(T3,MASK2); + T3 = _mm_and_si128(T4,MASK1); + + T5 = _mm_xor_si128(T0,T2); + T5 = _mm_xor_si128(T5,T3); + + T5 = _mm_shuffle_epi8(T5, MASK); + _mm_storeu_si128((__m128i*)r, T5); + return gf128_from_bytes(r); +} diff --git a/Core/GmSSL-3.1.1/src/hash_drbg.c b/Core/GmSSL-3.1.1/src/hash_drbg.c new file mode 100644 index 0000000..ea06bcf --- /dev/null +++ b/Core/GmSSL-3.1.1/src/hash_drbg.c @@ -0,0 +1,299 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +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); + + while (outlen > 0) { + if (digest_init(&ctx, digest) != 1 + || digest_update(&ctx, &counter, sizeof(counter)) != 1 + || digest_update(&ctx, outbits, sizeof(outbits)) != 1 + || digest_update(&ctx, in, inlen) != 1 + || digest_finish(&ctx, dgst, &len) != 1) { + goto end; + } + + if (outlen < len) { + len = outlen; + } + memcpy(out, dgst, len); + out += len; + outlen -= len; + + counter++; + } + + ret = 1; +end: + memset(&ctx, 0, sizeof(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->digest_size <= 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; + while (seedlen--) { + temp += R[seedlen] + A[seedlen]; + R[seedlen] = temp & 0xff; + temp >>= 8; + } +} + +static void drbg_add1(uint8_t *R, size_t seedlen) +{ + int temp = 1; + while (seedlen--) { + temp += R[seedlen]; + R[seedlen] = 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; + + /* data = V */ + memcpy(data, drbg->V, drbg->seedlen); + + while (outlen > 0) { + + /* output Hash(data) */ + if (digest_init(&ctx, drbg->digest) != 1 + || digest_update(&ctx, data, drbg->seedlen) != 1 + || digest_finish(&ctx, dgst, &len) != 1) { + 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: + memset(&ctx, 0, sizeof(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; + } + + if (additional) { + /* w = Hash (0x02 || V || additional_input) */ + prefix = 0x02; + if (digest_init(&ctx, drbg->digest) != 1 + || digest_update(&ctx, &prefix, 1) != 1 + || digest_update(&ctx, drbg->V, drbg->seedlen) != 1 + || digest_update(&ctx, additional, additional_len) != 1 + || digest_finish(&ctx, dgst, &dgstlen) != 1) { + 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) != 1 + || digest_update(&ctx, &prefix, 1) != 1 + || digest_update(&ctx, drbg->V, drbg->seedlen) != 1 + || digest_finish(&ctx, dgst, &dgstlen) != 1) { + 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: + memset(&ctx, 0, sizeof(ctx)); + memset(T, 0, sizeof(T)); + memset(dgst, 0, sizeof(dgst)); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/hex.c b/Core/GmSSL-3.1.1/src/hex.c new file mode 100644 index 0000000..68bde97 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/hex.c @@ -0,0 +1,219 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include + +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_msg("hex %s len = %zu\n", in, inlen); + return -1; + } + + while (inlen) { + if ((c = hexchar2int(*in++)) < 0) { + error_print_msg("%d", 5); + 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; +} + +int hex_to_bytes(const char *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + *outlen = inlen/2; + return hex2bin(in, inlen, out); +} + + +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]; + } +} + + +// Note: comments and code from OpenSSL crypto/cryptlib.c:CRYPTO_memcmp() +/* volatile unsigned char* pointers are there because + * 1. Accessing a variable declared volatile via a pointer + * that lacks a volatile qualifier causes undefined behavior. + * 2. When the variable itself is not volatile the compiler is + * not required to keep all those reads and can convert + * this into canonical memcmp() which doesn't read the whole block. + * Pointers to volatile resolve the first problem fully. The second + * problem cannot be resolved in any Standard-compliant way but this + * works the problem around. Compilers typically react to + * pointers to volatile by preserving the reads and writes through them. + * The latter is not required by the Standard if the memory pointed to + * is not volatile. + * Pointers themselves are volatile in the function signature to work + * around a subtle bug in gcc 4.6+ which causes writes through + * pointers to volatile to not be emitted in some rare, + * never needed in real life, pieces of code. + */ +int gmssl_secure_memcmp(const volatile void * volatile in_a, const volatile void * volatile in_b, size_t len) +{ + size_t i; + const volatile unsigned char *a = in_a; + const volatile unsigned char *b = in_b; + unsigned char x = 0; + + for (i = 0; i < len; i++) { + x |= a[i] ^ b[i]; + } + + return x; +} + +/* + * Pointer to memset is volatile so that compiler must de-reference + * the pointer and can't assume that it points to any function in + * particular (such as memset, which it then might further "optimize") + */ +typedef void *(*memset_t)(void *, int, size_t); + +static volatile memset_t memset_func = memset; + +void gmssl_secure_clear(void *ptr, size_t len) +{ + memset_func(ptr, 0, len); +} + +int mem_is_zero(const uint8_t *buf, size_t len) +{ + int ret = 1; + size_t i; + for (i = 0; i < len; i++) { + if (buf[i]) ret = 0; + } + return ret; +} + + + + + diff --git a/Core/GmSSL-3.1.1/src/hkdf.c b/Core/GmSSL-3.1.1/src/hkdf.c new file mode 100644 index 0000000..b5514e5 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/hkdf.c @@ -0,0 +1,205 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + +/* + +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->digest_size) != 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 *opt_info, size_t opt_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, opt_info, opt_infolen) < 0 + || 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, opt_info, opt_infolen) < 0 + || 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; +} + +/* +int sm3_hkdf_extract(const uint8_t *salt, size_t saltlen, + const uint8_t *ikm, size_t ikmlen, + uint8_t *prk, size_t *prklen) +{ + SM3_HMAC_CTX hmac_ctx; + + if (!salt || saltlen == 0) { + uint8_t zeros[SM3_HMAC_SIZE] = {0}; + if (sm3_hmac_init(&hmac_ctx, zeros, SM3_HMAC_SIZE) != 1) { + error_print(); + return -1; + } + } else { + if (sm3_hmac_init(&hmac_ctx, salt, saltlen) != 1) { + error_print(); + return -1; + } + } + + if (sm3_hmac_update(&hmac_ctx, ikm, ikmlen) != 1 + || sm3_hmac_finish(&hmac_ctx, prk) != 1) { + error_print(); + return -1; + } + *prklen = SM3_HMAC_SIZE; + return 1; +} + +int sm3_hkdf_expand(const uint8_t *prk, size_t prklen, + const uint8_t *opt_info, size_t opt_infolen, + size_t L, uint8_t *okm) +{ + SM3_HMAC_CTX hmac_ctx; + uint8_t T[SM3_HMAC_SIZE]; + uint8_t counter = 0x01; + size_t len; + + if (L > 0) { + if (sm3_hmac_init(&hmac_ctx, prk, prklen) != 1 + || sm3_hmac_update(&hmac_ctx, opt_info, opt_infolen) < 0 + || sm3_hmac_update(&hmac_ctx, &counter, 1) != 1 + || sm3_hmac_finish(&hmac_ctx, T) != 1) { + error_print(); + return -1; + } + counter++; + len = SM3_HMAC_SIZE; + if (len > L) { + len = L; + } + memcpy(okm, T, len); + okm += len; + L -= len; + } + while (L > 0) { + if (counter == 0) { + error_print(); + return -1; + } + if (sm3_hmac_init(&hmac_ctx, digest, prk, prklen) != 1 + || sm3_hmac_update(&hmac_ctx, T, len) != 1 + || sm3_hmac_update(&hmac_ctx, opt_info, opt_infolen) < 0 + || sm3_hmac_update(&hmac_ctx, &counter, 1) != 1 + || sm3_hmac_finish(&hmac_ctx, T) != 1) { + error_print(); + return -1; + } + counter++; + len = SM3_HMAC_SIZE; + if (len > L) { + len = L; + } + memcpy(okm, T, len); + okm += len; + L -= len; + } + return 1; +} +*/ diff --git a/Core/GmSSL-3.1.1/src/hmac.c b/Core/GmSSL-3.1.1/src/hmac.c new file mode 100644 index 0000000..03dce8e --- /dev/null +++ b/Core/GmSSL-3.1.1/src/hmac.c @@ -0,0 +1,129 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include + + +#define IPAD 0x36 +#define OPAD 0x5C + + +int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const uint8_t *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) { + error_print(); + return -1; + } + + ctx->digest = digest; + + blocksize = digest->block_size; + 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 uint8_t *data, size_t datalen) +{ + if (ctx == NULL) { + error_print(); + return -1; + } + if (data == NULL || datalen == 0) { + return 0; + } + if (digest_update(&ctx->digest_ctx, data, datalen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int hmac_finish(HMAC_CTX *ctx, uint8_t *mac, size_t *maclen) +{ + if (ctx == NULL || maclen == NULL) { + error_print(); + return -1; + } + if (digest_finish(&ctx->digest_ctx, mac, maclen) != 1) { + error_print(); + return -1; + } + memcpy(&ctx->digest_ctx, &ctx->o_ctx, sizeof(DIGEST_CTX)); + if (digest_update(&ctx->digest_ctx, mac, *maclen) != 1 + || digest_finish(&ctx->digest_ctx, mac, maclen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int hmac_finish_and_verify(HMAC_CTX *ctx, const uint8_t *mac, size_t maclen) +{ + uint8_t hmac[64]; + size_t hmaclen; + + if (hmac_finish(ctx, hmac, &hmaclen) != 1) { + error_print(); + return -1; + } + if (maclen != hmaclen + || memcmp(hmac, mac, maclen) != 0) { + error_print(); + return -1; + } + return 1; +} + +int hmac(const DIGEST *digest, const uint8_t *key, size_t keylen, + const uint8_t *data, size_t datalen, + uint8_t *mac, size_t *maclen) +{ + int ret = 0; + HMAC_CTX ctx; + + if (hmac_init(&ctx, digest, key, keylen) != 1 + || hmac_update(&ctx, data, datalen) != 1 + || hmac_finish(&ctx, mac, maclen) != 1) { + goto end; + } + ret = 1; + +end: + memset(&ctx, 0, sizeof(ctx)); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/http.c b/Core/GmSSL-3.1.1/src/http.c new file mode 100644 index 0000000..ce24c4f --- /dev/null +++ b/Core/GmSSL-3.1.1/src/http.c @@ -0,0 +1,185 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +int http_parse_uri(const char *uri, char host[128], int *port, char path[256]) +{ + if (!uri || !host || !port || !path) { + error_print(); + return -1; + } + + *host = 0; + *port = 80; + *path++ = '/'; + *path = 0; + + if (sscanf(uri, "http://%127[^:]:%i/%254[^\n]", host, port, path) == 3); + else if (sscanf(uri, "http://%127[^/]/%254[^\n]", host, path) == 2); + else if (sscanf(uri, "http://%127[^:]:%i[^/][^\n]", host, port) == 2); + else if (sscanf(uri, "http://%127[^/][^\n]", host) == 1); + else { + error_print(); + return -1; + } + if (!host[0] || strchr(host, '/') || strchr(host, ':')) { + error_print(); + return -1; + } + if (*port <= 0) { + error_print(); + return -1; + } + + return 1; +} + +static int socket_recv_all(int sock, uint8_t *buf, size_t len) +{ + size_t n; + while (len) { + if ((n = recv(sock, buf, len, 0)) <= 0) { + error_print(); + return -1; + } + buf += n; + len -= n; + } + return 1; +} + +int http_parse_response(char *buf, size_t buflen, uint8_t **content, size_t *contentlen, size_t *left) +{ + char *ok = "HTTP/1.1 200 OK\r\n"; + char *p; + size_t headerlen; + + if (buflen < strlen(ok) || memcmp(buf, ok, strlen(ok)) != 0) { + error_print(); + return -1; + } + if (buf[buflen] != 0) { + error_print(); + return -1; + } + if (!(p = strstr(buf, "\r\n\r\n"))) { + error_print(); + return -1; + } + *content = (uint8_t *)(p + 4); + headerlen = *content - (uint8_t *)buf; + *p = 0; + + if (!(p = strstr(buf, "\r\nContent-Length: "))) { + error_print(); + return -1; + } + p += strlen("\r\nContent-Length: "); + *contentlen = atoi(p); + if (*contentlen <= 0 || *contentlen > INT_MAX) { + error_print(); + return -1; + } + + buflen -= headerlen; + if (buflen < *contentlen) + *left = *contentlen - buflen; + else *left = 0; + + return 1; +} + + +#define HTTP_GET_TEMPLATE "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "\r\n\r\n" + +int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen) +{ + int ret = -1; + char host[128]; + int port; + char path[256]; + struct hostent *hp; + struct sockaddr_in server; + tls_socket_t sock; + char get[sizeof(HTTP_GET_TEMPLATE) + sizeof(host) + sizeof(path)]; + int getlen; + char response[1024]; + uint8_t *p; + size_t len; + size_t left; + + // parse uri and compose request + if (http_parse_uri(uri, host, &port, path) != 1) { + error_print(); + return -1; + } + if ((getlen = snprintf(get, sizeof(get), HTTP_GET_TEMPLATE, path, host)) <= 0) { + error_print(); + return -1; + } + + // connect and send request + if (!(hp = gethostbyname(host))) { + error_print(); + return -1; + } + server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]); + server.sin_family = AF_INET; + server.sin_port = htons(port); + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + error_print(); + return -1; + } + if (connect(sock, (struct sockaddr *)&server , sizeof(server)) < 0) { + error_print(); + goto end; + } + if (send(sock, get, strlen(get), 0) != getlen) { + error_print(); + goto end; + } + if ((len = recv(sock, response, sizeof(response) - 1, 0)) <= 0) { + error_print(); + goto end; + } + response[len] = 0; + + // process response header and retrieve left + if (http_parse_response(response, len, &p, contentlen, &left) != 1) { + error_print(); + goto end; + } + if (!buf || buflen < *contentlen) { + ret = 0; + goto end; + } + memcpy(buf, p, *contentlen - left); + if (left) { + if (socket_recv_all(sock, buf + *contentlen - left, left) != 1) { + error_print(); + goto end; + } + } + ret = 1; + +end: + close(sock); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/http_win.c b/Core/GmSSL-3.1.1/src/http_win.c new file mode 100644 index 0000000..5a2f647 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/http_win.c @@ -0,0 +1,203 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +int http_parse_uri(const char *uri, char host[128], int *port, char path[256]) +{ + if (!uri || !host || !port || !path) { + error_print(); + return -1; + } + + *host = 0; + *port = 80; + *path++ = '/'; + *path = 0; + + if (sscanf(uri, "http://%127[^:]:%i/%254[^\n]", host, port, path) == 3); + else if (sscanf(uri, "http://%127[^/]/%254[^\n]", host, path) == 2); + else if (sscanf(uri, "http://%127[^:]:%i[^/][^\n]", host, port) == 2); + else if (sscanf(uri, "http://%127[^/][^\n]", host) == 1); + else { + error_print(); + return -1; + } + if (!host[0] || strchr(host, '/') || strchr(host, ':')) { + error_print(); + return -1; + } + if (*port <= 0) { + error_print(); + return -1; + } + + return 1; +} + +static int socket_recv_all(tls_socket_t sock, uint8_t *buf, size_t len) +{ + size_t n; + while (len) { + if ((n = tls_socket_recv(sock, buf, len, 0)) <= 0) { + error_print(); + return -1; + } + buf += n; + len -= n; + } + return 1; +} + +int http_parse_response(char *buf, size_t buflen, uint8_t **content, size_t *contentlen, size_t *left) +{ + char *ok = "HTTP/1.1 200 OK\r\n"; + char *p; + size_t headerlen; + + if (buflen < strlen(ok) || memcmp(buf, ok, strlen(ok)) != 0) { + error_print(); + return -1; + } + if (buf[buflen] != 0) { + error_print(); + return -1; + } + if (!(p = strstr(buf, "\r\n\r\n"))) { + error_print(); + return -1; + } + *content = (uint8_t *)(p + 4); + headerlen = *content - (uint8_t *)buf; + *p = 0; + + if (!(p = strstr(buf, "\r\nContent-Length: "))) { + error_print(); + return -1; + } + p += strlen("\r\nContent-Length: "); + *contentlen = atoi(p); + if (*contentlen <= 0 || *contentlen > INT_MAX) { + error_print(); + return -1; + } + + buflen -= headerlen; + if (buflen < *contentlen) + *left = *contentlen - buflen; + else *left = 0; + + return 1; +} + + +#define HTTP_GET_TEMPLATE "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "\r\n\r\n" + +int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen) +{ + int ret = -1; + char host[128]; + int port; + char path[256]; + struct hostent *hp; + struct sockaddr_in server; + tls_socket_t sock; + char get[sizeof(HTTP_GET_TEMPLATE) + sizeof(host) + sizeof(path)]; + int getlen; + char response[1024]; + uint8_t *p; + size_t len; + size_t left; + + // WIN32 + WORD wVersion; + WSADATA wsaData; + wVersion = MAKEWORD(2, 2); + int err; + int sock_inited = 0; + + // parse uri and compose request + if (http_parse_uri(uri, host, &port, path) != 1) { + error_print(); + return -1; + } + if ((getlen = snprintf(get, sizeof(get), HTTP_GET_TEMPLATE, path, host)) <= 0) { + error_print(); + return -1; + } + + // WIN32 + if ((err = WSAStartup(wVersion, &wsaData)) != 0) { + fprintf(stderr, "WSAStartup error %d\n", err); + return -1; + } + + // connect and send request + if (!(hp = gethostbyname(host))) { + error_print(); + goto end; + } + server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]); + server.sin_family = AF_INET; + server.sin_port = htons(port); + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + error_print(); + fprintf(stderr, "%s %d: open socket error : %u\n", __FILE__, __LINE__, WSAGetLastError()); + goto end; + } + sock_inited = 1; + + if (connect(sock, (struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) { + error_print(); + fprintf(stderr, "%s %d: connect error : %u\n", __FILE__, __LINE__, WSAGetLastError()); + goto end; + } + if (tls_socket_send(sock, get, strlen(get), 0) != getlen) { + error_print(); + goto end; + } + if ((len = tls_socket_recv(sock, response, sizeof(response) - 1, 0)) <= 0) { + error_print(); + goto end; + } + response[len] = 0; + + // process response header and retrieve left + if (http_parse_response(response, len, &p, contentlen, &left) != 1) { + error_print(); + goto end; + } + if (!buf || buflen < *contentlen) { + ret = 0; + goto end; + } + memcpy(buf, p, *contentlen - left); + if (left) { + if (socket_recv_all(sock, buf + *contentlen - left, left) != 1) { + error_print(); + goto end; + } + } + ret = 1; + +end: + if (sock_inited) tls_socket_close(sock); + WSACleanup(); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/md5.c b/Core/GmSSL-3.1.1/src/md5.c new file mode 100644 index 0000000..f7b3a02 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/md5.c @@ -0,0 +1,181 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include + + +#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); + 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_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; + + ctx->num &= 0x3f; + if (ctx->num) { + size_t 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->num &= 0x3f; + ctx->block[ctx->num] = 0x80; + + if (ctx->num <= MD5_BLOCK_SIZE - 9) { + 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]); + dgst += sizeof(uint32_t); + } +} + +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); + memset(&ctx, 0, sizeof(ctx)); +} diff --git a/Core/GmSSL-3.1.1/src/pbkdf2.c b/Core/GmSSL-3.1.1/src/pbkdf2.c new file mode 100644 index 0000000..7f31e99 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/pbkdf2.c @@ -0,0 +1,188 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +/* + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int pbkdf2_genkey(const DIGEST *digest, + const char *pass, size_t passlen, + const uint8_t *salt, size_t saltlen, size_t count, + size_t outlen, uint8_t *out) +{ + HMAC_CTX ctx; + HMAC_CTX ctx_tmpl; + 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_tmpl, digest, (uint8_t *)pass, passlen); + + while (outlen > 0) { + size_t i; + + PUTU32(iter_be, iter); + iter++; + + ctx = ctx_tmpl; + hmac_update(&ctx, salt, saltlen); + hmac_update(&ctx, iter_be, sizeof(iter_be)); + hmac_finish(&ctx, tmp_block, &len); + memcpy(key_block, tmp_block, len); + + for (i = 1; i < count; i++) { + ctx = ctx_tmpl; + hmac_update(&ctx, tmp_block, len); + hmac_finish(&ctx, tmp_block, &len); + 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; +} + +int pbkdf2_hmac_sm3_genkey( + const char *pass, size_t passlen, + const uint8_t *salt, size_t saltlen, size_t count, + size_t outlen, uint8_t *out) +{ + SM3_HMAC_CTX ctx; + SM3_HMAC_CTX ctx_tmpl; + uint32_t iter = 1; + uint8_t iter_be[4]; + uint8_t tmp_block[SM3_DIGEST_SIZE]; + uint8_t key_block[SM3_DIGEST_SIZE]; + // TODO: a bug in 3.0.0 is fixied. How to update release version 3.0.0 ? A test is also required! + + sm3_hmac_init(&ctx_tmpl, (uint8_t *)pass, passlen); + + while (outlen > 0) { + size_t i; + + PUTU32(iter_be, iter); + iter++; + + ctx = ctx_tmpl; + sm3_hmac_update(&ctx, salt, saltlen); + sm3_hmac_update(&ctx, iter_be, sizeof(iter_be)); + sm3_hmac_finish(&ctx, tmp_block); + memcpy(key_block, tmp_block, SM3_DIGEST_SIZE); + + for (i = 1; i < count; i++) { + ctx = ctx_tmpl; + sm3_hmac_update(&ctx, tmp_block, SM3_DIGEST_SIZE); + sm3_hmac_finish(&ctx, tmp_block); + memxor(key_block, tmp_block, SM3_DIGEST_SIZE); + } + + if (outlen < SM3_DIGEST_SIZE) { + memcpy(out, key_block, outlen); + out += outlen; + outlen = 0; + } else { + memcpy(out, key_block, SM3_DIGEST_SIZE); + out += SM3_DIGEST_SIZE; + outlen -= SM3_DIGEST_SIZE; + } + } + + memset(&ctx, 0, sizeof(ctx)); + memset(key_block, 0, sizeof(key_block)); + memset(tmp_block, 0, sizeof(key_block)); + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/pem.c b/Core/GmSSL-3.1.1/src/pem.c new file mode 100644 index 0000000..64a401a --- /dev/null +++ b/Core/GmSSL-3.1.1/src/pem.c @@ -0,0 +1,127 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static int remove_newline(char *line) +{ + size_t len; + len = strlen(line); + + if (len >= 2) { + if (line[len - 2] == '\r' && line[len - 1] == '\n') { + line[len - 2] = line[len - 1] = 0; + return 1; + } + } + if (len) { + if (line[len - 1] == '\n') { + line[len - 1] = 0; + return 1; + } + } + return 0; // No newline found, might not be an error +} + +int pem_write(FILE *fp, const char *name, const uint8_t *data, size_t datalen) +{ + BASE64_CTX ctx; + uint8_t out[168]; + int inlen, outlen; + + if (!datalen) { + error_print(); + return -1; + } + if (datalen > INT_MAX) { + error_print(); + return -1; + } + + fprintf(fp, "-----BEGIN %s-----\n", name); + base64_encode_init(&ctx); + while (datalen) { + inlen = datalen < 48 ? (int)datalen : 48; + base64_encode_update(&ctx, data, inlen, out, &outlen); + fwrite(out, 1, outlen, fp); + data += inlen; + datalen -= inlen; + } + base64_encode_finish(&ctx, out, &outlen); + fwrite(out, 1, outlen, fp); + fprintf(fp, "-----END %s-----\n", name); + + return 1; +} + +int pem_read(FILE *fp, const char *name, uint8_t *data, size_t *datalen, size_t maxlen) +{ + char line[80]; + char begin_line[80]; + char end_line[80]; + int len; + BASE64_CTX ctx; + + snprintf(begin_line, sizeof(begin_line), "-----BEGIN %s-----", name); + snprintf(end_line, sizeof(end_line), "-----END %s-----", name); + + if (feof(fp)) { + error_print(); + return 0; + } + + if (!fgets(line, sizeof(line), fp)) { + if (feof(fp)) { + error_print(); + return 0; + } else { + error_print(); + return -1; + } + } + remove_newline(line); + + if (strcmp(line, begin_line) != 0) { + fprintf(stderr, "%s %d: %s\n", __FILE__, __LINE__, line); + fprintf(stderr, "%s %d: %s\n", __FILE__, __LINE__, begin_line); + error_print(); + return -1; + } + + *datalen = 0; + + base64_decode_init(&ctx); + + for (;;) { + if (!fgets(line, sizeof(line), fp)) { + error_print(); + return -1; + } + remove_newline(line); + + if (strcmp(line, end_line) == 0) { + break; + } + + base64_decode_update(&ctx, (uint8_t *)line, (int)strlen(line), data, &len); + data += len; + *datalen += len; + } + + base64_decode_finish(&ctx, data, &len); + *datalen += len; + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/pkcs8.c b/Core/GmSSL-3.1.1/src/pkcs8.c new file mode 100644 index 0000000..8ff193b --- /dev/null +++ b/Core/GmSSL-3.1.1/src/pkcs8.c @@ -0,0 +1,454 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const uint32_t oid_hmac_sm3[] = { oid_sm_algors,401,2 }; +static const size_t oid_hmac_sm3_cnt = sizeof(oid_hmac_sm3)/sizeof(oid_hmac_sm3[0]); + +char *pbkdf2_prf_name(int oid) +{ + switch (oid) { + case OID_hmac_sm3: return "hmac-sm3"; + } + return NULL; +} + +int pbkdf2_prf_from_name(const char *name) +{ + if (strcmp(name, "hmac-sm3") == 0) { + return OID_hmac_sm3; + } + return 0; +} + +int pbkdf2_prf_to_der(int oid, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (oid == -1) + return 0; + + if (oid != OID_hmac_sm3) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(oid_hmac_sm3, oid_hmac_sm3_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_hmac_sm3, oid_hmac_sm3_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pbkdf2_prf_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + uint32_t nodes[32]; + size_t nodes_cnt; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1 + || asn1_object_identifier_equ(nodes, nodes_cnt, oid_hmac_sm3, oid_hmac_sm3_cnt) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + *oid = OID_hmac_sm3; + return 1; +} + +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; + 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 + || pbkdf2_prf_to_der(prf, NULL, &len) < 0 + || 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 + || pbkdf2_prf_to_der(prf, out, outlen) < 0) { + 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 *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_octet_string_from_der(salt, saltlen, &d, &dlen) != 1 + || asn1_int_from_der(iter, &d, &dlen) != 1 + || asn1_int_from_der(keylen, &d, &dlen) < 0 + || pbkdf2_prf_from_der(prf, &d, &dlen) < 0 + || asn1_check(*saltlen > 0) != 1 + || asn1_check(*iter > 0) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pbkdf2_params_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + int val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "salt", p, len); + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "iterationCount: %d\n", val); + if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "keyLength: %d\n", val); + if ((ret = pbkdf2_prf_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "prf: %s\n", pbkdf2_prf_name(val)); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +static const uint32_t oid_pbkdf2[] = { oid_pkcs5,12 }; +static const size_t oid_pbkdf2_cnt = sizeof(oid_pbkdf2)/sizeof(oid_pbkdf2[0]); + +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; + if (asn1_object_identifier_to_der(oid_pbkdf2, oid_pbkdf2_cnt, 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_pbkdf2, oid_pbkdf2_cnt, 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 *d; + size_t dlen; + uint32_t nodes[32]; + size_t nodes_cnt; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1 + || asn1_object_identifier_equ(nodes, nodes_cnt, oid_pbkdf2, oid_pbkdf2_cnt) != 1 + || pbkdf2_params_from_der(salt, saltlen, iter, keylen, prf, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pbkdf2_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1 + || asn1_object_identifier_equ(nodes, nodes_cnt, oid_pbkdf2, oid_pbkdf2_cnt) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "algorithm: %s\n", "pbkdf2"); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + pbkdf2_params_print(fp, fmt, ind, "parameters", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int pbes2_enc_algor_to_der(int oid, const uint8_t *iv, size_t ivlen, uint8_t **out, size_t *outlen) +{ + if (oid != OID_sm4_cbc) { + error_print(); + return -1; + } + if (x509_encryption_algor_to_der(oid, iv, ivlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pbes2_enc_algor_from_der(int *oid, const uint8_t **iv, size_t *ivlen, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = x509_encryption_algor_from_der(oid, iv, ivlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*oid != OID_sm4_cbc) { + error_print(); + return -1; + } + return 1; +} + +int pbes2_enc_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return x509_encryption_algor_print(fp, fmt, ind, label, d, dlen); +} + +int pbes2_params_to_der( + const uint8_t *salt, size_t saltlen, int iter, int keylen, int prf, + int cipher, const uint8_t *iv, size_t ivlen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + 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 *keylen, int *prf, + int *cipher, const uint8_t **iv, size_t *ivlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (pbkdf2_algor_from_der(salt, saltlen, iter, keylen, prf, &d, &dlen) != 1 + || pbes2_enc_algor_from_der(cipher, iv, ivlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pbes2_params_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + pbkdf2_algor_print(fp, fmt, ind, "keyDerivationFunc", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + pbes2_enc_algor_print(fp, fmt, ind, "encryptionScheme", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static const uint32_t oid_pbes2[] = { oid_pkcs5,13 }; +static const size_t oid_pbes2_cnt = sizeof(oid_pbes2)/sizeof(oid_pbes2[0]); + +int pbes2_algor_to_der( + const uint8_t *salt, size_t saltlen, int iter, int keylen, int prf, + int cipher, const uint8_t *iv, size_t ivlen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_object_identifier_to_der(oid_pbes2, oid_pbes2_cnt, NULL, &len) != 1 + || pbes2_params_to_der(salt, saltlen, iter, keylen, prf, cipher, iv, ivlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_pbes2, oid_pbes2_cnt, out, outlen) != 1 + || pbes2_params_to_der(salt, saltlen, iter, keylen, 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 *keylen, int *prf, + int *cipher, const uint8_t **iv, size_t *ivlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + uint32_t nodes[32]; + size_t nodes_cnt; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1 + || asn1_object_identifier_equ(nodes, nodes_cnt, oid_pbes2, oid_pbes2_cnt) != 1 + || pbes2_params_from_der(salt, saltlen, iter, keylen, prf, cipher, iv, ivlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pbes2_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1 + || asn1_object_identifier_equ(nodes, nodes_cnt, oid_pbes2, oid_pbes2_cnt) != 1) + goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", "pbes2"); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + pbes2_params_print(fp, fmt, ind, "parameters", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int pkcs8_enced_private_key_info_to_der( + const uint8_t *salt, size_t saltlen, int iter, int keylen, 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; + if (pbes2_algor_to_der(salt, saltlen, iter, keylen, prf, cipher, iv, ivlen, NULL, &len) != 1 + || asn1_octet_string_to_der(enced, encedlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || pbes2_algor_to_der(salt, saltlen, iter, keylen, prf, cipher, iv, ivlen, out, outlen) != 1 + || asn1_octet_string_to_der(enced, encedlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pkcs8_enced_private_key_info_from_der( + const uint8_t **salt, size_t *saltlen, int *iter, int *keylen, 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 *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (pbes2_algor_from_der(salt, saltlen, iter, keylen, prf, cipher, iv, ivlen, &d, &dlen) != 1 + || asn1_octet_string_from_der(enced, encedlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int pkcs8_enced_private_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + pbes2_algor_print(fp, fmt, ind, "encryptionAlgorithm", p, len); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "encryptedData", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/src/rand.c b/Core/GmSSL-3.1.1/src/rand.c new file mode 100644 index 0000000..e155aef --- /dev/null +++ b/Core/GmSSL-3.1.1/src/rand.c @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + +#define RAND_MAX_BUF_SIZE 4096 + +int rand_bytes(uint8_t *buf, size_t len) +{ + FILE *fp; + if (!buf) { + error_print(); + return -1; + } + if (len > RAND_MAX_BUF_SIZE) { + error_print(); + return -1; + } + if (!len) { + return 0; + } + + if (!(fp = fopen("/dev/urandom", "rb"))) { + error_print(); + return -1; + } + if (fread(buf, 1, len, fp) != len) { + error_print(); + fclose(fp); + return -1; + } + fclose(fp); + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/rand_apple.c b/Core/GmSSL-3.1.1/src/rand_apple.c new file mode 100644 index 0000000..1b249dd --- /dev/null +++ b/Core/GmSSL-3.1.1/src/rand_apple.c @@ -0,0 +1,34 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include // clang -framework Security + + +int rand_bytes(uint8_t *buf, size_t len) +{ + int errCode; + if ((errCode = SecRandomCopyBytes(kSecRandomDefault, len, buf)) != errSecSuccess) { + error_print(); + fprintf(stderr, "%s:%d: SecRandomCopyBytes() return OSStatus = %d\n", __FILE__, __LINE__, errCode); + /* + CFStringRef errStr; + errStr = SecCopyErrorMessageString(errCode, NULL); + fprintf(stderr, "error: %s\n", CFStringGetCStringPtr(errStr, kCFStringEncodingMacRoman)); + CFRelease(errStr); // -framework CoreFoundation + */ + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/rand_unix.c b/Core/GmSSL-3.1.1/src/rand_unix.c new file mode 100644 index 0000000..9f741dd --- /dev/null +++ b/Core/GmSSL-3.1.1/src/rand_unix.c @@ -0,0 +1,41 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include // in Linux +#ifdef APPLE +#include // in Apple +#endif +#include +#include + + +#define RAND_MAX_BUF_SIZE 256 // requirement of getentropy() + +int rand_bytes(uint8_t *buf, size_t len) +{ + if (!buf) { + error_print(); + return -1; + } + if (!len || len > RAND_MAX_BUF_SIZE) { + error_print(); + return -1; + } + if (getentropy(buf, len) != 0) { + error_print(); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/rand_win.c b/Core/GmSSL-3.1.1/src/rand_win.c new file mode 100644 index 0000000..69fe9e5 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/rand_win.c @@ -0,0 +1,48 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +int rand_bytes(uint8_t *buf, size_t len) +{ + HCRYPTPROV hCryptProv; + int ret = -1; + + if (!buf) { + error_print(); + return -1; + } + if (len > INT_MAX) { + error_print(); + return -1; + } + if (CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT|CRYPT_SILENT) != TRUE) { + error_print(); + return -1; + } + if (CryptGenRandom(hCryptProv, (DWORD)len, buf) != TRUE) { + error_print(); + goto end; + } + ret = 1; +end: + if (CryptReleaseContext(hCryptProv, 0) != TRUE) { + error_print(); + ret = -1; + } + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/rc4.c b/Core/GmSSL-3.1.1/src/rc4.c new file mode 100644 index 0000000..e3ae13e --- /dev/null +++ b/Core/GmSSL-3.1.1/src/rc4.c @@ -0,0 +1,83 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include + +void rc4_init(RC4_STATE *state, const uint8_t *key, size_t keylen) +{ + int i, j; + uint8_t *s = state->d; + uint8_t k[256] = {0}; + uint8_t temp; + + if (keylen > sizeof(k)) { + keylen = sizeof(k); + } + + /* expand key */ + for (i = 0; i < (int)keylen; i++) { + k[i] = key[i]; + } + for (; 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, uint8_t *out) +{ + int i = 0, j = 0; + uint8_t *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--; + } +} + +uint8_t rc4_generate_keybyte(RC4_STATE *state) +{ + uint8_t out[1]; + rc4_generate_keystream(state, 1, out); + return out[0]; +} diff --git a/Core/GmSSL-3.1.1/src/rdrand.c b/Core/GmSSL-3.1.1/src/rdrand.c new file mode 100644 index 0000000..708ca6e --- /dev/null +++ b/Core/GmSSL-3.1.1/src/rdrand.c @@ -0,0 +1,53 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + +int rdrand_bytes(uint8_t *buf, size_t buflen) +{ + unsigned long long val; + uint8_t *p = (uint8_t *)&val; + + while (buflen) { + size_t len = buflen >= sizeof(val) ? sizeof(val) : buflen; + if (_rdrand64_step(&val) != 1) { + error_print(); + return -1; + } + memcpy(buf, p, len); + buf += len; + buflen -= len; + } + return 1; +} + +#ifdef INTEL_RDSEED +int rdseed_bytes(uint8_t *buf, size_t buflen) +{ + unsigned long long val; + uint8_t *p = (uint8_t *)&val; + + while (buflen) { + size_t len = buflen >= sizeof(val) ? sizeof(val) : buflen; + if (_rdseed64_step(&val) != 1) { + error_print(); + return -1; + } + memcpy(buf, p, len); + buf += len; + buflen -= len; + } + return 1; +} +#endif diff --git a/Core/GmSSL-3.1.1/src/rsa.c b/Core/GmSSL-3.1.1/src/rsa.c new file mode 100644 index 0000000..a09ef5a --- /dev/null +++ b/Core/GmSSL-3.1.1/src/rsa.c @@ -0,0 +1,42 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include + + +int rsa_public_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + const uint8_t *d; + size_t dlen; + const uint8_t *p; + size_t len; + int val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1) goto err; + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "modulus", p, len); + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "publicExponent: %d\n",val); + if (asn1_length_is_zero(dlen) != 1) goto err; + if (asn1_length_is_zero(alen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf.c b/Core/GmSSL-3.1.1/src/sdf/sdf.c new file mode 100755 index 0000000..183b3ba --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf.c @@ -0,0 +1,213 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include "sdf.h" +#include "sdf_ext.h" + + + +static const uint8_t zeros[ECCref_MAX_LEN - 32] = {0}; + +static int SDF_ECCrefPublicKey_to_SM2_KEY(const ECCrefPublicKey *ref, SM2_KEY *sm2_key) +{ + SM2_POINT point; + + if (ref->bits != 256) { + error_print(); + return -1; + } + if (memcmp(ref->x, zeros, sizeof(zeros)) != 0 + || memcmp(ref->y, zeros, sizeof(zeros)) != 0) { + error_print(); + return -1; + } + + if (sm2_point_from_xy(&point, ref->x + ECCref_MAX_LEN - 32, ref->y + ECCref_MAX_LEN - 32) != 1 + || sm2_key_set_public_key(sm2_key, &point) != 1) { + error_print(); + return -1; + } + return SDR_OK; +} + +static int SDF_ECCSignature_to_SM2_SIGNATURE(const ECCSignature *ref, SM2_SIGNATURE *sig) +{ + if (memcmp(ref->r, zeros, sizeof(zeros)) != 0 + || memcmp(ref->s, zeros, sizeof(zeros)) != 0) { + error_print(); + return -1; + } + memset(sig, 0, sizeof(SM2_SIGNATURE)); + memcpy(sig->r, ref->r + ECCref_MAX_LEN - 32, 32); + memcpy(sig->s, ref->s + ECCref_MAX_LEN - 32, 32); + return SDR_OK; +} + +int sdf_load_library(const char *so_path, const char *vendor) +{ + if (SDF_LoadLibrary((char *)so_path, (char *)vendor) != SDR_OK) { + error_print(); + return -1; + } + return 1; +} + +void sdf_unload_library(void) +{ + SDF_UnloadLibrary(); +} + +int sdf_open_device(SDF_DEVICE *dev) +{ + int ret = -1; + void *hDevice = NULL; + void *hSession = NULL; + DEVICEINFO devInfo; + + if (SDF_OpenDevice(&hDevice) != SDR_OK + || SDF_OpenSession(hDevice, &hSession) != SDR_OK + || SDF_GetDeviceInfo(hSession, &devInfo) != SDR_OK) { + error_print(); + goto end; + } + + memset(dev, 0, sizeof(SDF_DEVICE)); + dev->handle = hDevice; + hDevice = NULL; + memcpy(dev->issuer, devInfo.IssuerName, 40); + memcpy(dev->name, devInfo.DeviceName, 16); + memcpy(dev->serial, devInfo.DeviceSerial, 16); + ret = 1; +end: + if (hSession) SDF_CloseSession(hSession); + if (hDevice) SDF_CloseDevice(hDevice); + return ret; +} + +int sdf_print_device_info(FILE *fp, int fmt, int ind, const char *lable, SDF_DEVICE *dev) +{ + int ret = -1; + void *hSession = NULL; + DEVICEINFO devInfo; + + if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK + || SDF_GetDeviceInfo(hSession, &devInfo) != SDR_OK) { + error_print(); + goto end; + } + SDF_PrintDeviceInfo(fp, &devInfo); + ret = 1; +end: + if (hSession) SDF_CloseSession(hSession); + return ret; +} + +int sdf_rand_bytes(SDF_DEVICE *dev, uint8_t *buf, size_t len) +{ + int ret = -1; + void *hSession = NULL; + + if (!dev || !buf || !len) { + error_print(); + return -1; + } + if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK + || SDF_GenerateRandom(hSession, (unsigned int)len, buf) != SDR_OK) { + error_print(); + goto end; + } + ret = 1; +end: + if (hSession) SDF_CloseSession(hSession); + return ret; +} + +int sdf_load_sign_key(SDF_DEVICE *dev, SDF_KEY *key, int index, const char *pass) +{ + int ret = -1; + void *hSession = NULL; + ECCrefPublicKey eccPublicKey; + SM2_KEY public_key; + + if (!dev || !key || !pass) { + error_print(); + return -1; + } + if (SDF_OpenSession(dev->handle, &hSession) != SDR_OK + || SDF_ExportSignPublicKey_ECC(hSession, index, &eccPublicKey) != SDR_OK + || SDF_ECCrefPublicKey_to_SM2_KEY(&eccPublicKey, &public_key) != SDR_OK + || SDF_GetPrivateKeyAccessRight(hSession, index, (unsigned char *)pass, (unsigned int)strlen(pass)) != SDR_OK) { + error_print(); + goto end; + } + + memset(key, 0, sizeof(SDF_KEY)); + key->public_key = public_key; + key->session = hSession; + key->index = index; + hSession = NULL; + ret = 1; +end: + if (hSession) SDF_CloseSession(hSession); + return ret; +} + +int sdf_sign(SDF_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen) +{ + ECCSignature ecc_sig; + SM2_SIGNATURE sm2_sig; + + if (!key || !dgst || !sig || !siglen) { + error_print(); + return -1; + } + if (SDF_InternalSign_ECC(key->session, key->index, (unsigned char *)dgst, 32, &ecc_sig) != SDR_OK + || SDF_ECCSignature_to_SM2_SIGNATURE(&ecc_sig, &sm2_sig) != SDR_OK) { + error_print(); + return -1; + } + + + + + *siglen = 0; + if (sm2_signature_to_der(&sm2_sig, &sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sdf_release_key(SDF_KEY *key) +{ + if (SDF_ReleasePrivateKeyAccessRight(key->session, key->index) != SDR_OK + || SDF_CloseSession(key->session) != SDR_OK) { + error_print(); + return -1; + } + memset(key, 0, sizeof(SDF_KEY)); + return 1; +} + +int sdf_close_device(SDF_DEVICE *dev) +{ + if (SDF_CloseDevice(dev->handle) != SDR_OK) { + error_print(); + return -1; + } + memset(dev, 0, sizeof(SDF_DEVICE)); + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf.h b/Core/GmSSL-3.1.1/src/sdf/sdf.h new file mode 100755 index 0000000..af56440 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf.h @@ -0,0 +1,465 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/* + * SDF API is a cryptographic API for PCI-E cards defined in standard + * GM/T 0018-2012: Interface Specifications of Cryptography Device Application + * + * Note: this header file follows the specification of GM/T 0018-2012. As we + * know, some vendors provide header files with some differences, especially + * the definations of data structures. So be sure to check the file provided by + * vendors and compare with this one. + * + * The implementations of SDF API from different vendors might have different + * behaviors on the same function. The comments in this file will show + * information and warnings on these issues. If the application developer use + * the GmSSL implementation, see `crypto/gmapi/sdf_lcl.h` for more information. + */ + +#ifndef HEADER_SDF_H +#define HEADER_SDF_H + +#include +#include "../sgd.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#pragma pack(1) +typedef struct DeviceInfo_st { + unsigned char IssuerName[40]; + unsigned char DeviceName[16]; + unsigned char DeviceSerial[16]; /* 8-char date + + * 3-char batch num + + * 5-char serial num + */ + unsigned int DeviceVersion; + unsigned int StandardVersion; + unsigned int AsymAlgAbility[2]; /* AsymAlgAbility[0] = algors + * AsymAlgAbility[1] = modulus lens + */ + unsigned int SymAlgAbility; + unsigned int HashAlgAbility; + unsigned int BufferSize; +} DEVICEINFO; + +typedef struct RSArefPublicKey_st { + unsigned int bits; + unsigned char m[RSAref_MAX_LEN]; + unsigned char e[RSAref_MAX_LEN]; +} RSArefPublicKey; + +typedef struct RSArefPrivateKey_st { + unsigned int bits; + unsigned char m[RSAref_MAX_LEN]; + unsigned char e[RSAref_MAX_LEN]; + unsigned char d[RSAref_MAX_LEN]; + unsigned char prime[2][RSAref_MAX_PLEN]; + unsigned char pexp[2][RSAref_MAX_PLEN]; + unsigned char coef[RSAref_MAX_PLEN]; +} RSArefPrivateKey; + +typedef struct ECCrefPublicKey_st { + unsigned int bits; + unsigned char x[ECCref_MAX_LEN]; + unsigned char y[ECCref_MAX_LEN]; +} ECCrefPublicKey; + +typedef struct ECCrefPrivateKey_st { + unsigned int bits; + unsigned char K[ECCref_MAX_LEN]; +} ECCrefPrivateKey; + +typedef struct ECCCipher_st { + unsigned char x[ECCref_MAX_LEN]; + unsigned char y[ECCref_MAX_LEN]; + unsigned char M[32]; + unsigned int L; + unsigned char C[1]; +} ECCCipher; + +typedef struct ECCSignature_st { + unsigned char r[ECCref_MAX_LEN]; + unsigned char s[ECCref_MAX_LEN]; +} ECCSignature; + +typedef struct SDF_ENVELOPEDKEYBLOB { + unsigned long Version; + unsigned long ulSymmAlgID; + ECCCipher ECCCipehrBlob; + ECCrefPublicKey PubKey; + unsigned char cbEncryptedPrivKey[64]; +} EnvelopedKeyBlob, *PEnvelopedKeyBlob; +#pragma pack() + +int SDF_OpenDevice( + void **phDeviceHandle); + +int SDF_CloseDevice( + void *hDeviceHandle); + +int SDF_OpenSession( + void *hDeviceHandle, + void **phSessionHandle); + +int SDF_CloseSession( + void *hSessionHandle); + +int SDF_GetDeviceInfo( + void *hSessionHandle, + DEVICEINFO *pstDeviceInfo); + +int SDF_GenerateRandom( + void *hSessionHandle, + unsigned int uiLength, + unsigned char *pucRandom); + +int SDF_GetPrivateKeyAccessRight( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength); + +int SDF_ReleasePrivateKeyAccessRight( + void *hSessionHandle, + unsigned int uiKeyIndex); + +int SDF_ExportSignPublicKey_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey); + +int SDF_ExportEncPublicKey_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey); + +int SDF_GenerateKeyPair_RSA( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + RSArefPrivateKey *pucPrivateKey); + +int SDF_GenerateKeyWithIPK_RSA( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle); + +int SDF_GenerateKeyWithEPK_RSA( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle); + +int SDF_ImportKeyWithISK_RSA( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle); + +int SDF_ExchangeDigitEnvelopeBaseOnRSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDEInput, + unsigned int uiDELength, + unsigned char *pucDEOutput, + unsigned int *puiDELength); + +int SDF_ExportSignPublicKey_ECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey); + +int SDF_ExportEncPublicKey_ECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey); + +int SDF_GenerateKeyPair_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKeyBits, + ECCrefPublicKey *pucPublicKey, + ECCrefPrivateKey *pucPrivateKey); + +int SDF_GenerateKeyWithIPK_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + ECCCipher *pucKey, + void **phKeyHandle); + +int SDF_GenerateKeyWithEPK_ECC( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucKey, + void **phKeyHandle); + +int SDF_ImportKeyWithISK_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + ECCCipher *pucKey, + void **phKeyHandle); + +int SDF_GenerateAgreementDataWithECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + void **phAgreementHandle); + +int SDF_GenerateKeyWithECC( + void *hSessionHandle, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void *hAgreementHandle, + void **phKeyHandle); + +int SDF_GenerateAgreementDataAndKeyWithECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void **phKeyHandle); + +int SDF_ExchangeDigitEnvelopeBaseOnECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucEncDataIn, + ECCCipher *pucEncDataOut); + +int SDF_GenerateKeyWithKEK( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle); + +int SDF_ImportKeyWithKEK( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle); + +int SDF_DestroyKey( + void *hSessionHandle, + void *hKeyHandle); + +int SDF_ExternalPublicKeyOperation_RSA( + void *hSessionHandle, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength); + +int SDF_InternalPublicKeyOperation_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength); + +int SDF_InternalPrivateKeyOperation_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength); + +int SDF_ExternalVerify_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + ECCSignature *pucSignature); + +int SDF_InternalSign_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature); + +int SDF_InternalVerify_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature); + +int SDF_ExternalEncrypt_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucData, + unsigned int uiDataLength, + ECCCipher *pucEncData); + +int SDF_InternalEncrypt_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiAlgID, + unsigned char *pucData, + unsigned int uiDataLength, + ECCCipher *pucEncData); + +int SDF_InternalDecrypt_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiAlgID, + ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *uiDataLength); + +int SDF_Encrypt( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucEncData, + unsigned int *puiEncDataLength); + +int SDF_Decrypt( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucEncData, + unsigned int uiEncDataLength, + unsigned char *pucData, + unsigned int *puiDataLength); + +int SDF_CalculateMAC( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucMAC, + unsigned int *puiMACLength); + +int SDF_HashInit( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucID, + unsigned int uiIDLength); + +int SDF_HashUpdate( + void *hSessionHandle, + unsigned char *pucData, + unsigned int uiDataLength); + +int SDF_HashFinal(void *hSessionHandle, + unsigned char *pucHash, + unsigned int *puiHashLength); + +int SDF_CreateFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, /* max 128-byte */ + unsigned int uiFileSize); + +int SDF_ReadFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int *puiReadLength, + unsigned char *pucBuffer); + +int SDF_WriteFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int uiWriteLength, + unsigned char *pucBuffer); + +int SDF_DeleteFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen); + +#define SDR_OK 0x0 +#define SDR_BASE 0x01000000 +#define SDR_UNKNOWERR (SDR_BASE + 0x00000001) +#define SDR_NOTSUPPORT (SDR_BASE + 0x00000002) +#define SDR_COMMFAIL (SDR_BASE + 0x00000003) +#define SDR_HARDFAIL (SDR_BASE + 0x00000004) +#define SDR_OPENDEVICE (SDR_BASE + 0x00000005) +#define SDR_OPENSESSION (SDR_BASE + 0x00000006) +#define SDR_PARDENY (SDR_BASE + 0x00000007) +#define SDR_KEYNOTEXIST (SDR_BASE + 0x00000008) +#define SDR_ALGNOTSUPPORT (SDR_BASE + 0x00000009) +#define SDR_ALGMODNOTSUPPORT (SDR_BASE + 0x0000000A) +#define SDR_PKOPERR (SDR_BASE + 0x0000000B) +#define SDR_SKOPERR (SDR_BASE + 0x0000000C) +#define SDR_SIGNERR (SDR_BASE + 0x0000000D) +#define SDR_VERIFYERR (SDR_BASE + 0x0000000E) +#define SDR_SYMOPERR (SDR_BASE + 0x0000000F) +#define SDR_STEPERR (SDR_BASE + 0x00000010) +#define SDR_FILESIZEERR (SDR_BASE + 0x00000011) +#define SDR_FILENOEXIST (SDR_BASE + 0x00000012) +#define SDR_FILEOFSERR (SDR_BASE + 0x00000013) +#define SDR_KEYTYPEERR (SDR_BASE + 0x00000014) +#define SDR_KEYERR (SDR_BASE + 0x00000015) +#define SDR_ENCDATAERR (SDR_BASE + 0x00000016) +#define SDR_RANDERR (SDR_BASE + 0x00000017) +#define SDR_PRKRERR (SDR_BASE + 0x00000018) +#define SDR_MACERR (SDR_BASE + 0x00000019) +#define SDR_FILEEXSITS (SDR_BASE + 0x0000001A) +#define SDR_FILEWERR (SDR_BASE + 0x0000001B) +#define SDR_NOBUFFER (SDR_BASE + 0x0000001C) +#define SDR_INARGERR (SDR_BASE + 0x0000001D) +#define SDR_OUTARGERR (SDR_BASE + 0x0000001E) + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_dummy.c b/Core/GmSSL-3.1.1/src/sdf/sdf_dummy.c new file mode 100755 index 0000000..eb213e0 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_dummy.c @@ -0,0 +1,729 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include "../sgd.h" +#include "sdf.h" + +static char *deviceHandle = "SDF Device Handle"; +static char *sessionHandle = "SDF Session Handle"; +static char *keyHandle = "SDF Key Handle"; +static char *agreementHandle = "SDF Agreement Handle"; + +unsigned char rsaPublicKeyBuf[516] = { + 0x00,0x04,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,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,0x00,0x00,0xd5,0x43,0xbf,0x24,0xd2,0x69,0x56,0x21,0x20,0x57,0x8a,0xd8, + 0x67,0x4f,0xbd,0xd5,0xf5,0x3a,0xf5,0x9e,0xa5,0x87,0x52,0x39,0x47,0xc3,0xce,0x32, + 0x56,0xb6,0x06,0x2d,0xdc,0x8d,0xc2,0x18,0x53,0x5c,0xb0,0xcb,0xb6,0xe8,0x7c,0x82, + 0x97,0x38,0xbb,0x85,0x45,0x2e,0xc8,0x24,0x08,0x96,0x9e,0xb0,0x00,0xaf,0xd9,0xa7, + 0x1f,0x50,0x7f,0xc4,0x93,0x14,0x74,0x9a,0x43,0x8e,0x04,0x95,0xa0,0xd6,0xd9,0xdd, + 0xb4,0x97,0xb3,0x52,0x93,0xe4,0xbe,0xd1,0x1f,0x8c,0xf9,0xcd,0xe1,0xae,0x54,0xae, + 0x72,0xdf,0x94,0xe3,0x15,0x6a,0x5c,0x99,0xd6,0x80,0x46,0x94,0xad,0xb3,0x76,0x95, + 0x4e,0x14,0x8f,0x8f,0xe5,0x55,0xf1,0x3f,0xd0,0xd3,0x96,0x01,0xf6,0x94,0x3e,0x61, + 0xc1,0x8e,0xb3,0x89,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,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,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,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,0x01,0x00,0x01,}; +unsigned char rsaPrivateKeyBuf[1412] = { + 0x00,0x04,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,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,0x00,0x00,0xd5,0x43,0xbf,0x24,0xd2,0x69,0x56,0x21,0x20,0x57,0x8a,0xd8, + 0x67,0x4f,0xbd,0xd5,0xf5,0x3a,0xf5,0x9e,0xa5,0x87,0x52,0x39,0x47,0xc3,0xce,0x32, + 0x56,0xb6,0x06,0x2d,0xdc,0x8d,0xc2,0x18,0x53,0x5c,0xb0,0xcb,0xb6,0xe8,0x7c,0x82, + 0x97,0x38,0xbb,0x85,0x45,0x2e,0xc8,0x24,0x08,0x96,0x9e,0xb0,0x00,0xaf,0xd9,0xa7, + 0x1f,0x50,0x7f,0xc4,0x93,0x14,0x74,0x9a,0x43,0x8e,0x04,0x95,0xa0,0xd6,0xd9,0xdd, + 0xb4,0x97,0xb3,0x52,0x93,0xe4,0xbe,0xd1,0x1f,0x8c,0xf9,0xcd,0xe1,0xae,0x54,0xae, + 0x72,0xdf,0x94,0xe3,0x15,0x6a,0x5c,0x99,0xd6,0x80,0x46,0x94,0xad,0xb3,0x76,0x95, + 0x4e,0x14,0x8f,0x8f,0xe5,0x55,0xf1,0x3f,0xd0,0xd3,0x96,0x01,0xf6,0x94,0x3e,0x61, + 0xc1,0x8e,0xb3,0x89,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,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,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,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,0x01,0x00,0x01,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,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,0x1e,0xd9,0x55,0xe4,0xf5,0xaa,0xd7,0x12,0xa3,0xa3,0x06,0x2a, + 0x97,0x87,0x29,0x66,0xb1,0xba,0x7d,0x9d,0x1d,0x44,0x9d,0xd8,0x3b,0x51,0x4f,0x9a, + 0x68,0x80,0x9c,0x14,0x36,0x3b,0x2b,0x40,0x69,0x8e,0x96,0xe4,0x60,0xe8,0xf0,0x59, + 0xd3,0x96,0x19,0x4a,0x05,0xdf,0xe6,0x83,0x8f,0xda,0x79,0xc9,0xeb,0xcf,0x84,0x24, + 0x70,0x9b,0x2c,0x5f,0xf7,0x56,0xe2,0xe0,0xc7,0xfb,0x67,0x92,0xd2,0xf6,0x59,0x19, + 0xe9,0xdd,0xb4,0x54,0x52,0x0d,0xf8,0xda,0x64,0x67,0xe0,0xb9,0xe6,0x52,0x08,0xff, + 0x28,0x06,0x89,0x5c,0x2b,0xd5,0x6e,0x21,0xe1,0x6d,0x1d,0xe3,0xf8,0x1e,0x0f,0x20, + 0x9f,0x0a,0x60,0xd1,0xff,0x4e,0xa2,0x45,0xa1,0xee,0x96,0x90,0xc0,0xc4,0xa8,0x25, + 0x5a,0xe8,0xe8,0xa1,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,0xf5,0xde,0x0d,0x0c,0xc5,0x03,0x53,0x44,0xfa,0x70,0xc7,0x44, + 0x63,0xf8,0x57,0x7e,0x49,0x76,0xe4,0x7a,0x76,0x01,0x7d,0xda,0x65,0xaa,0x9d,0xbe, + 0xfe,0x24,0x9b,0x48,0xf9,0xa8,0x18,0x42,0x47,0xf3,0x1a,0x1e,0x61,0xe9,0xb8,0xb3, + 0x07,0xee,0xfd,0x83,0x2e,0xf2,0xf8,0xb9,0x1f,0x9a,0xee,0xeb,0x21,0xd0,0xc0,0x13, + 0xa2,0x31,0x33,0xe7,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,0xde,0x0d,0xba,0xf3,0x62,0x8f,0x75,0x16,0xe6,0x87,0x72,0xba, + 0x12,0x6a,0x43,0x5c,0xde,0x22,0x60,0xea,0xef,0x7a,0x7e,0xb6,0x28,0x16,0x4f,0xda, + 0xe7,0xb8,0xfe,0x48,0x17,0x65,0x1a,0x73,0x38,0x98,0xdb,0xa2,0xda,0x50,0xc8,0x81, + 0x53,0x07,0x1d,0x0e,0xa7,0x3f,0x48,0x57,0xea,0x5b,0x34,0x64,0x9f,0x0a,0x8b,0x36, + 0x7e,0x08,0xef,0x0f,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,0xa8,0xd9,0xe6,0x7c,0x6e,0x90,0xea,0x0e,0xe5,0x2f,0xae,0xa9, + 0xf9,0x3e,0x04,0x58,0x66,0x7b,0x90,0x4d,0xc9,0xdd,0x1c,0x61,0x70,0x90,0xcb,0xe4, + 0xef,0x04,0x94,0xe0,0x79,0x14,0x48,0x14,0xbc,0xf4,0xe7,0x6b,0x16,0x33,0x3c,0xf5, + 0x36,0xed,0x9a,0x8d,0x0d,0x21,0x30,0x4f,0x72,0xb5,0x24,0x7f,0xb6,0xa9,0x76,0x40, + 0x05,0x93,0x64,0xe1,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,0x85,0x35,0x31,0x68,0x9e,0x40,0xb7,0x1a,0x34,0xd3,0x1e,0x84, + 0xf7,0x55,0x1d,0xf2,0x11,0x24,0x08,0x86,0x07,0x81,0xb1,0x8f,0xee,0xfe,0x6b,0x8b, + 0x43,0xa5,0x5b,0x8d,0xbd,0xd3,0x1e,0x09,0xee,0xf2,0xec,0x17,0x86,0xe6,0x1d,0x52, + 0x4f,0x8f,0x9d,0xe3,0xd3,0x7b,0x08,0x18,0x0d,0x74,0x07,0x3b,0x31,0x99,0x6e,0xa8, + 0x12,0xf5,0xa3,0x0b,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,0x23,0x60,0x23,0xc4,0x44,0x67,0x91,0xb7,0xde,0x06,0x9a,0x17, + 0x49,0x3a,0x8e,0x66,0xb4,0x54,0x61,0x4b,0xc4,0x9e,0xf8,0xe6,0xbc,0xf8,0x87,0xef, + 0x06,0xb5,0x40,0x4b,0xab,0xaf,0xf0,0xa0,0x46,0x43,0xc5,0xbd,0xec,0xff,0x57,0xfd, + 0x51,0x8a,0x6b,0x7b,0x32,0xee,0xeb,0x2f,0x81,0xd0,0xa0,0xa2,0x09,0x18,0xab,0x5c, + 0x85,0x1b,0x0f,0x57,}; +unsigned char eccPublicKeyBuf[132] = { + 0x00,0x01,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,0x0e,0x42,0x92,0x4a,0x1b,0x01,0xb6,0x64,0x89,0x97,0xfb,0x67, + 0x3f,0xa5,0xa6,0xc4,0xc4,0x82,0xa2,0xfa,0xe6,0x96,0xc9,0x0a,0x37,0xf2,0x44,0x6c, + 0xac,0x37,0x85,0x67,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,0xf8,0xbb,0x32,0x55,0xe2,0x47,0x34,0x9a,0xc9,0xb5,0xdb,0xc7, + 0x17,0x4a,0xd9,0x84,0xbf,0xc5,0x3e,0x99,0x92,0xc6,0xd8,0x2d,0x6f,0xea,0xff,0x79, + 0x6b,0xde,0x3d,0x37,}; +unsigned char eccPrivateKeyBuf[68] = { + 0x00,0x01,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,0xe6,0x51,0x2e,0xf8,0xca,0x14,0x84,0xa2,0xd9,0x76,0xc9,0x0d, + 0x37,0x1d,0xf1,0x95,0x49,0xbe,0x83,0x8e,0x70,0x09,0x1d,0x81,0xbd,0x6e,0xd9,0x5c, + 0xad,0x02,0x19,0x44,}; + + +#define SDF_TRACE() fprintf(stderr, "SDF_Dummy->%s\n", __FUNCTION__) + +int SDF_OpenDevice( + void **phDeviceHandle) +{ + if (!phDeviceHandle /* || !(*phDeviceHandle) */) + return SDR_INARGERR; + + *phDeviceHandle = deviceHandle; + return SDR_OK; +} + +int SDF_CloseDevice( + void *hDeviceHandle) +{ + return SDR_OK; +} + +int SDF_OpenSession( + void *hDeviceHandle, + void **phSessionHandle) +{ + if (!phSessionHandle /* || !(*phSessionHandle) */) + return SDR_INARGERR; + *phSessionHandle = sessionHandle; + return SDR_OK; +} + +int SDF_CloseSession( + void *hSessionHandle) +{ + return SDR_OK; +} + +#define SDF_DEV_DATE "20140101" +#define SDF_DEV_BATCH_NUM "001" +#define SDF_DEV_SERIAL_NUM "00123" +#define SDF_DEV_SERIAL SDF_DEV_DATE \ + SDF_DEV_BATCH_NUM \ + SDF_DEV_SERIAL_NUM + +int SDF_GetDeviceInfo( + void *hSessionHandle, + DEVICEINFO *pstDeviceInfo) +{ + if (!pstDeviceInfo) + return SDR_INARGERR; + memset(pstDeviceInfo, 0, sizeof(*pstDeviceInfo)); + strncpy((char *)pstDeviceInfo->IssuerName, "GmSSL Project (http://gmssl.org)", + sizeof(pstDeviceInfo->IssuerName)); + strncpy((char *)pstDeviceInfo->DeviceName, "Dummy SDF", + sizeof(pstDeviceInfo->DeviceName)); + strncpy((char *)pstDeviceInfo->DeviceSerial, SDF_DEV_SERIAL, + sizeof(pstDeviceInfo->DeviceSerial)); + pstDeviceInfo->DeviceVersion = 1; + pstDeviceInfo->StandardVersion = 1; + pstDeviceInfo->AsymAlgAbility[0] = SGD_RSA_SIGN|SGD_RSA_ENC| + SGD_SM2_1|SGD_SM2_2|SGD_SM2_3; + pstDeviceInfo->AsymAlgAbility[1] = 256|512|1024|2048|4096; + pstDeviceInfo->SymAlgAbility = SGD_SM1|SGD_SSF33|SGD_SM4|SGD_ZUC| + SGD_ECB|SGD_CBC|SGD_CFB|SGD_OFB|SGD_MAC; + pstDeviceInfo->HashAlgAbility = SGD_SM3|SGD_SHA1|SGD_SHA256; + pstDeviceInfo->BufferSize = 256*1024; + return SDR_OK; +} + +int SDF_GenerateRandom( + void *hSessionHandle, + unsigned int uiLength, + unsigned char *pucRandom) +{ + return SDR_OK; +} + +int SDF_GetPrivateKeyAccessRight( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength) +{ + return SDR_OK; +} + +int SDF_ReleasePrivateKeyAccessRight( + void *hSessionHandle, + unsigned int uiKeyIndex) +{ + return SDR_OK; +} + +int SDF_ExportSignPublicKey_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey) +{ + if (!pucPublicKey) + return SDR_INARGERR; + memcpy(pucPublicKey, rsaPublicKeyBuf, sizeof(*pucPublicKey)); + return SDR_OK; +} + +int SDF_ExportEncPublicKey_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey) +{ + if (!pucPublicKey) + return SDR_INARGERR; + memcpy(pucPublicKey, rsaPublicKeyBuf, sizeof(*pucPublicKey)); + return SDR_OK; +} + +int SDF_GenerateKeyPair_RSA( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + RSArefPrivateKey *pucPrivateKey) +{ + if (!pucPublicKey || !pucPrivateKey) + return SDR_INARGERR; + memcpy(pucPublicKey, rsaPublicKeyBuf, sizeof(*pucPublicKey)); + memcpy(pucPrivateKey, rsaPrivateKeyBuf, sizeof(*pucPrivateKey)); + return SDR_OK; +} + +int SDF_GenerateKeyWithIPK_RSA( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle) +{ + if (!puiKeyLength) + return SDR_INARGERR; + *puiKeyLength = 2048/8; + if (phKeyHandle && *phKeyHandle) + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_GenerateKeyWithEPK_RSA( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle) +{ + if (!puiKeyLength) + return SDR_INARGERR; + *puiKeyLength = 2048/8; + if (phKeyHandle && *phKeyHandle) + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_ImportKeyWithISK_RSA( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle) +{ + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_ExchangeDigitEnvelopeBaseOnRSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDEInput, + unsigned int uiDELength, + unsigned char *pucDEOutput, + unsigned int *puiDELength) +{ + if (!puiDELength) + return SDR_INARGERR; + *puiDELength = 2048/8; + return SDR_OK; +} + +int SDF_ExportSignPublicKey_ECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey) +{ + if (!pucPublicKey) + return SDR_INARGERR; + memcpy(pucPublicKey, eccPublicKeyBuf, sizeof(*pucPublicKey)); + return SDR_OK; +} + +int SDF_ExportEncPublicKey_ECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey) +{ + if (!pucPublicKey) + return SDR_INARGERR; + memcpy(pucPublicKey, eccPublicKeyBuf, sizeof(*pucPublicKey)); + return SDR_OK; +} + +int SDF_GenerateKeyPair_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKeyBits, + ECCrefPublicKey *pucPublicKey, + ECCrefPrivateKey *pucPrivateKey) +{ + if (!pucPublicKey || !pucPublicKey) + return SDR_INARGERR; + memcpy(pucPublicKey, eccPublicKeyBuf, sizeof(*pucPublicKey)); + memcpy(pucPrivateKey, eccPrivateKeyBuf, sizeof(*pucPrivateKey)); + return SDR_OK; +} + +int SDF_GenerateKeyWithIPK_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + ECCCipher *pucKey, + void **phKeyHandle) +{ + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_GenerateKeyWithEPK_ECC( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucKey, + void **phKeyHandle) +{ + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_ImportKeyWithISK_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + ECCCipher *pucKey, + void **phKeyHandle) +{ + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +/* 6.3.14 */ +int SDF_GenerateAgreementDataWithECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + void **phAgreementHandle) +{ + // any output public key ? + if (!phAgreementHandle || !(*phAgreementHandle)) + return SDR_INARGERR; + *phAgreementHandle = agreementHandle; + return SDR_OK; +} + +/* 6.3.15 */ +int SDF_GenerateKeyWithECC( + void *hSessionHandle, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void *hAgreementHandle, + void **phKeyHandle) +{ + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +/* 6.3.16 */ +int SDF_GenerateAgreementDataAndKeyWithECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void **phKeyHandle) +{ + // any output + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_ExchangeDigitEnvelopeBaseOnECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucEncDataIn, + ECCCipher *pucEncDataOut) +{ + return SDR_OK; +} + +int SDF_GenerateKeyWithKEK( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle) +{ + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_ImportKeyWithKEK( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle) +{ + if (!phKeyHandle || !(*phKeyHandle)) + return SDR_INARGERR; + *phKeyHandle = keyHandle; + return SDR_OK; +} + +int SDF_DestroyKey( + void *hSessionHandle, + void *hKeyHandle) +{ + return SDR_OK; +} + +int SDF_ExternalPublicKeyOperation_RSA( + void *hSessionHandle, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength) +{ + if (!puiOutputLength) + return SDR_INARGERR; + *puiOutputLength = 2048/8; + return SDR_OK; +} + +int SDF_ExternalPrivateKeyOperation_RSA( + void *hSessionHandle, + RSArefPrivateKey *pucPrivateKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength) +{ + if (!puiOutputLength) + return SDR_INARGERR; + *puiOutputLength = 2048/8; + return SDR_OK; +} + +int SDF_InternalPrivateKeyOperation_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength) +{ + if (!puiOutputLength) + return SDR_INARGERR; + *puiOutputLength = 2048/8; + return SDR_OK; +} + +int SDF_ExternalVerify_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + ECCSignature *pucSignature) +{ + return SDR_OK; +} + +int SDF_InternalSign_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature) +{ + return SDR_OK; +} + +int SDF_InternalVerify_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature) +{ + return SDR_OK; +} + +int SDF_ExternalEncrypt_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucData, + unsigned int uiDataLength, + ECCCipher *pucEncData) +{ + if (!pucEncData) + return SDR_INARGERR; + pucEncData->L = uiDataLength; + return SDR_OK; +} + +int SDF_Encrypt( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucEncData, + unsigned int *puiEncDataLength) +{ + if (!puiEncDataLength) + return SDR_INARGERR; + *puiEncDataLength = uiDataLength; + return SDR_OK; +} + +int SDF_Decrypt( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucEncData, + unsigned int uiEncDataLength, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + if (!puiDataLength) + return SDR_INARGERR; + *puiDataLength = uiEncDataLength; + return SDR_OK; +} + +int SDF_CalculateMAC( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucMAC, + unsigned int *puiMACLength) +{ + if (!puiMACLength) + return SDR_INARGERR; + *puiMACLength = 16; /* CBC-MAC length */ + return SDR_OK; +} + +int SDF_HashInit( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucID, + unsigned int uiIDLength) +{ + return SDR_OK; +} + +int SDF_HashUpdate( + void *hSessionHandle, + unsigned char *pucData, + unsigned int uiDataLength) +{ + return SDR_OK; +} + +int SDF_HashFinal(void *hSessionHandle, + unsigned char *pucHash, + unsigned int *puiHashLength) +{ + if (!puiHashLength) + return SDR_INARGERR; + *puiHashLength = 32; + return SDR_OK; +} + +int SDF_CreateFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiFileSize) +{ + return SDR_OK; +} + +int SDF_ReadFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int *puiReadLength, + unsigned char *pucBuffer) +{ + if (!puiReadLength) + return SDR_INARGERR; + return SDR_OK; +} + +int SDF_WriteFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int uiWriteLength, + unsigned char *pucBuffer) +{ + return SDR_OK; +} + +int SDF_DeleteFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen) +{ + return SDR_OK; +} diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_ext.c b/Core/GmSSL-3.1.1/src/sdf/sdf_ext.c new file mode 100755 index 0000000..03ce5c2 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_ext.c @@ -0,0 +1,262 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include "sdf_int.h" +#include "sdf_sansec.h" + + +#define SDFerr(a,b) + + +typedef struct { + ULONG id; + char *name; +} table_item_t; + +static table_item_t sdf_cipher_caps[] = { + { SGD_SM1_ECB, "sm1-ecb" }, + { SGD_SM1_CBC, "sm1-cbc" }, + { SGD_SM1_CFB, "sm1-cfb" }, + { SGD_SM1_OFB, "sm1-ofb128" }, + { SGD_SM1_MAC, "cbcmac-sm1" }, + { SGD_SSF33_ECB, "ssf33-ecb" }, + { SGD_SSF33_CBC, "ssf33-cbc" }, + { SGD_SSF33_CFB, "ssf33-cfb" }, + { SGD_SSF33_OFB, "ssf33-ofb128" }, + { SGD_SSF33_MAC, "cbcmac-ssf33" }, + { SGD_SM4_ECB, "sms4-ecb" }, + { SGD_SM4_CBC, "sms4-cbc" }, + { SGD_SM4_CFB, "sms4-cfb" }, + { SGD_SM4_OFB, "sms4-ofb128" }, + { SGD_SM4_MAC, "cbcmac-sms4" }, + { SGD_ZUC_EEA3, "zuc_128eea3" }, + { SGD_ZUC_EIA3, "zuc_128eia3" } +}; + +static table_item_t sdf_digest_caps[] = { + { SGD_SM3, "sm3" }, + { SGD_SHA1, "sha1" }, + { SGD_SHA256, "sha256" }, +}; + +static table_item_t sdf_pkey_caps[] = { + { SGD_RSA_SIGN, "rsa" }, + { SGD_RSA_ENC, "rsaEncryption" }, + { SGD_SM2_1, "sm2sign" }, + { SGD_SM2_2, "sm2exchange" }, + { SGD_SM2_3, "sm2encrypt" } +}; + +int SDF_PrintDeviceInfo(FILE *fp, const DEVICEINFO *pstDeviceInfo) +{ + size_t i, n; + DEVICEINFO buf; + DEVICEINFO *devInfo = &buf; + int fmt = 0, ind = 4; + + memcpy(devInfo, pstDeviceInfo, sizeof(DEVICEINFO)); + devInfo->IssuerName[39] = 0; + devInfo->DeviceName[15] = 0; + devInfo->DeviceSerial[15] = 0; + + format_print(fp, fmt, ind, "%-18s: %s\n", "Device Name", devInfo->DeviceName); + format_print(fp, fmt, ind, "%-18s: %s\n", "Serial Number", devInfo->DeviceSerial); + format_print(fp, fmt, ind, "%-18s: %s\n", "Issuer", devInfo->IssuerName); + format_print(fp, fmt, ind, "%-18s: %u\n", "Hardware Version", devInfo->DeviceVersion); + format_print(fp, fmt, ind, "%-18s: %u\n", "Standard Version", devInfo->StandardVersion); + format_print(fp, fmt, ind, "%-18s: ", "Public Key Algors"); + for (i = n = 0; i < sizeof(sdf_pkey_caps)/sizeof(sdf_pkey_caps[0]); i++) { + if ((devInfo->AsymAlgAbility[0] & sdf_pkey_caps[i].id) == + sdf_pkey_caps[i].id) { + format_print(fp, fmt, 0, "%s%s", n ? "," : "", sdf_pkey_caps[i].name); + n++; + } + } + format_print(fp, fmt, 0, "\n"); + + format_print(fp, fmt, ind, "%-18s: ", "Ciphers"); + for (i = n = 0; i < sizeof(sdf_cipher_caps)/sizeof(sdf_cipher_caps[0]); i++) { + if ((devInfo->SymAlgAbility & sdf_cipher_caps[i].id) == + sdf_cipher_caps[i].id) { + format_print(fp, fmt, 0, "%s%s", n ? "," : "", sdf_cipher_caps[i].name); + n++; + } + } + format_print(fp, fmt, 0, "\n"); + + format_print(fp, fmt, ind, "%-18s: ", "Digests"); + for (i = n = 0; i < sizeof(sdf_digest_caps)/sizeof(sdf_digest_caps[0]); i++) { + if ((devInfo->HashAlgAbility & sdf_digest_caps[i].id) == + sdf_digest_caps[i].id) { + format_print(fp, fmt, 0, "%s%s", n ? "," : "", sdf_digest_caps[i].name); + n++; + } + } + format_print(fp, fmt, 0, "\n"); + return SDR_OK; +} + +int SDF_PrintRSAPublicKey(FILE *fp, const RSArefPublicKey *blob) +{ + int fmt = 0, ind = 4; + (void)format_print(fp, fmt, ind, "bits: %d\n", blob->bits); + (void)format_bytes(fp, fmt, ind, "m", blob->m, sizeof(blob->m)); + (void)format_bytes(fp, fmt, ind, "e", blob->e, sizeof(blob->e)); + return SDR_OK; +} + +int SDF_PrintRSAPrivateKey(FILE *fp, const RSArefPrivateKey *blob) +{ + int fmt = 0, ind = 4; + (void)format_print(fp, fmt, ind, "bits: %d", blob->bits); + (void)format_bytes(fp, fmt, ind, "m", blob->m, sizeof(blob->m)); + (void)format_bytes(fp, fmt, ind, "e", blob->e, sizeof(blob->e)); + (void)format_bytes(fp, fmt, ind, "d", blob->d, sizeof(blob->d)); + (void)format_bytes(fp, fmt, ind, "prime[0]", blob->prime[0], sizeof(blob->prime[0])); + (void)format_bytes(fp, fmt, ind, "prime[1]", blob->prime[1], sizeof(blob->prime[1])); + (void)format_bytes(fp, fmt, ind, "pexp[0]", blob->pexp[0], sizeof(blob->pexp[0])); + (void)format_bytes(fp, fmt, ind, "pexp[1]", blob->pexp[1], sizeof(blob->pexp[1])); + (void)format_bytes(fp, fmt, ind, "coef", blob->coef, sizeof(blob->coef)); + return SDR_OK; +} + +int SDF_PrintECCPublicKey(FILE *fp, const ECCrefPublicKey *blob) +{ + int fmt = 0, ind = 4; + (void)format_print(fp, fmt, ind, "bits: %d", blob->bits); + (void)format_bytes(fp, fmt, ind, "x", blob->x, sizeof(blob->x)); + (void)format_bytes(fp, fmt, ind, "y", blob->y, sizeof(blob->y)); + return SDR_OK; +} + +int SDF_PrintECCPrivateKey(FILE *fp, const ECCrefPrivateKey *blob) +{ + int fmt = 0, ind = 4; + (void)format_print(fp, fmt, ind, "bits: %d", blob->bits); + (void)format_bytes(fp, fmt, ind, "K", blob->K, sizeof(blob->K)); + return SDR_OK; +} + +int SDF_PrintECCCipher(FILE *fp, const ECCCipher *blob) +{ + int fmt = 0, ind = 4; + (void)format_bytes(fp, fmt, ind, "x", blob->x, sizeof(blob->x)); + (void)format_bytes(fp, fmt, ind, "y", blob->y, sizeof(blob->y)); + (void)format_bytes(fp, fmt, ind, "M", blob->M, sizeof(blob->M)); + (void)format_print(fp, fmt, ind, "L: %d", blob->L); + (void)format_bytes(fp, fmt, ind, "C", blob->C, sizeof(blob->C)); + return SDR_OK; +} + +int SDF_PrintECCSignature(FILE *fp, const ECCSignature *blob) +{ + int fmt = 0, ind = 4; + (void)format_bytes(fp, fmt, ind, "r", blob->r, sizeof(blob->r)); + (void)format_bytes(fp, fmt, ind, "s", blob->s, sizeof(blob->s)); + return SDR_OK; +} + +int SDF_ImportKey( + void *hSessionHandle, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle) +{ + (void)hSessionHandle; + (void)pucKey; + (void)uiKeyLength; + (void)phKeyHandle; + SDFerr(SDF_F_SDF_IMPORTKEY, SDF_R_NOT_IMPLEMENTED); + return SDR_NOTSUPPORT; +} + +int SDF_NewECCCipher(ECCCipher **cipher, size_t ulDataLen) +{ + ECCCipher *ecc_cipher = NULL; + size_t len; + + if (!cipher) { + SDFerr(SDF_F_SDF_NEWECCCIPHER, ERR_R_PASSED_NULL_PARAMETER); + return SDR_INARGERR; + } + + if (!ulDataLen || ulDataLen > INT_MAX) { + SDFerr(SDF_F_SDF_NEWECCCIPHER, + SDF_R_INVALID_SM2_CIPHERTEXT_LENGTH); + return SDR_INARGERR; + } + + len = sizeof(ECCCipher) - 1 + ulDataLen; + if (len < sizeof(SANSEC_ECCCipher)) { + len = sizeof(SANSEC_ECCCipher); + } + + if (!(ecc_cipher = malloc(len))) { + SDFerr(SDF_F_SDF_NEWECCCIPHER, ERR_R_MALLOC_FAILURE); + return SDR_NOBUFFER; + } + memset(ecc_cipher, 0, sizeof(*ecc_cipher)); + + ecc_cipher->L = (unsigned int)ulDataLen; + + *cipher = ecc_cipher; + return SDR_OK; +} + +int SDF_FreeECCCipher(ECCCipher *cipher) +{ + free(cipher); + return SDR_OK; +} + +const char *SDF_GetErrorReason(int err) +{ + switch (err) { + case SDR_OK: return "SDR_OK"; + case SDR_BASE: return "SDR_BASE"; + case SDR_UNKNOWERR: return "SDR_UNKNOWERR"; + case SDR_NOTSUPPORT: return "SDR_NOTSUPPORT"; + case SDR_COMMFAIL: return "SDR_COMMFAIL"; + case SDR_HARDFAIL: return "SDR_HARDFAIL"; + case SDR_OPENDEVICE: return "SDR_OPENDEVICE"; + case SDR_OPENSESSION: return "SDR_OPENSESSION"; + case SDR_PARDENY: return "SDR_PARDENY"; + case SDR_KEYNOTEXIST: return "SDR_KEYNOTEXIST"; + case SDR_ALGNOTSUPPORT: return "SDR_ALGNOTSUPPORT"; + case SDR_ALGMODNOTSUPPORT: return "SDR_ALGMODNOTSUPPORT"; + case SDR_PKOPERR: return "SDR_PKOPERR"; + case SDR_SKOPERR: return "SDR_SKOPERR"; + case SDR_SIGNERR: return "SDR_SIGNERR"; + case SDR_VERIFYERR: return "SDR_VERIFYERR"; + case SDR_SYMOPERR: return "SDR_SYMOPERR"; + case SDR_STEPERR: return "SDR_STEPERR"; + case SDR_FILESIZEERR: return "SDR_FILESIZEERR"; + case SDR_FILENOEXIST: return "SDR_FILENOEXIST"; + case SDR_FILEOFSERR: return "SDR_FILEOFSERR"; + case SDR_KEYTYPEERR: return "SDR_KEYTYPEERR"; + case SDR_KEYERR: return "SDR_KEYERR"; + case SDR_ENCDATAERR: return "SDR_ENCDATAERR"; + case SDR_RANDERR: return "SDR_RANDERR"; + case SDR_PRKRERR: return "SDR_PRKRERR"; + case SDR_MACERR: return "SDR_MACERR"; + case SDR_FILEEXSITS: return "SDR_FILEEXSITS"; + case SDR_FILEWERR: return "SDR_FILEWERR"; + case SDR_NOBUFFER: return "SDR_NOBUFFER"; + case SDR_INARGERR: return "SDR_INARGERR"; + case SDR_OUTARGERR: return "SDR_OUTARGERR"; + } + return "(unknown)"; +} diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_ext.h b/Core/GmSSL-3.1.1/src/sdf/sdf_ext.h new file mode 100755 index 0000000..242fe5e --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_ext.h @@ -0,0 +1,54 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef SDFUTIL_SDF_EXT_H +#define SDFUTIL_SDF_EXT_H + + +#include +#include +#include "../sgd.h" +#include "sdf.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SDF_MIN_KEY_INDEX 1 /* defined by GM/T 0018 */ +#define SDF_MAX_KEY_INDEX 32 /* defined by GmSSL */ +#define SDF_MIN_PASSWORD_LENGTH 8 /* defined by GM/T 0018 */ +#define SDF_MAX_PASSWORD_LENGTH 255 /* defined by GmSSL */ +#define SDF_MAX_FILE_SIZE (256 * 1024) + + + +int SDF_LoadLibrary(char *so_path, char *vendor); +int SDF_UnloadLibrary(void); +int SDF_ImportKey(void *hSessionHandle, unsigned char *pucKey, + unsigned int uiKeyLength, void **phKeyHandle); + +int SDF_PrintDeviceInfo(FILE *fp, const DEVICEINFO *devInfo); +int SDF_PrintRSAPublicKey(FILE *fp, const RSArefPublicKey *ref); +int SDF_PrintRSAPrivateKey(FILE *fp, const RSArefPrivateKey *ref); +int SDF_PrintECCPublicKey(FILE *fp, const ECCrefPublicKey *ref); +int SDF_PrintECCPrivateKey(FILE *fp, const ECCrefPrivateKey *ref); +int SDF_NewECCCipher(ECCCipher **cipher, size_t ulDataLen); // FIMXE: 和GmSSL的内存使用方式不同 +int SDF_FreeECCCipher(ECCCipher *cipher); +int SDF_PrintECCCipher(FILE *out, ECCCipher *cipher); +int SDF_PrintECCSignature(FILE *out, ECCSignature *sig); +const char *SDF_GetErrorReason(int err); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_int.h b/Core/GmSSL-3.1.1/src/sdf/sdf_int.h new file mode 100755 index 0000000..eae0db4 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_int.h @@ -0,0 +1,425 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef SDFUTIL_SDF_METH_H +#define SDFUTIL_SDF_METH_H + + +#include +#include "sdf.h" + + +typedef int (*SDF_OpenDevice_FuncPtr)( + void **phDeviceHandle); + +typedef int (*SDF_CloseDevice_FuncPtr)( + void *hDeviceHandle); + +typedef int (*SDF_OpenSession_FuncPtr)( + void *hDeviceHandle, + void **phSessionHandle); + +typedef int (*SDF_CloseSession_FuncPtr)( + void *hSessionHandle); + +typedef int (*SDF_GetDeviceInfo_FuncPtr)( + void *hSessionHandle, + DEVICEINFO *pstDeviceInfo); + +typedef int (*SDF_GenerateRandom_FuncPtr)( + void *hSessionHandle, + unsigned int uiLength, + unsigned char *pucRandom); + +typedef int (*SDF_GetPrivateKeyAccessRight_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength); + +typedef int (*SDF_ReleasePrivateKeyAccessRight_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex); + +typedef int (*SDF_ExportSignPublicKey_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey); + +typedef int (*SDF_ExportEncPublicKey_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey); + +typedef int (*SDF_GenerateKeyPair_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + RSArefPrivateKey *pucPrivateKey); + +typedef int (*SDF_GenerateKeyWithIPK_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle); + +typedef int (*SDF_GenerateKeyWithEPK_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle); + +typedef int (*SDF_ImportKeyWithISK_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle); + +typedef int (*SDF_ExchangeDigitEnvelopeBaseOnRSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDEInput, + unsigned int uiDELength, + unsigned char *pucDEOutput, + unsigned int *puiDELength); + +typedef int (*SDF_ExportSignPublicKey_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey); + +typedef int (*SDF_ExportEncPublicKey_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey); + +typedef int (*SDF_GenerateKeyPair_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKeyBits, + ECCrefPublicKey *pucPublicKey, + ECCrefPrivateKey *pucPrivateKey); + +typedef int (*SDF_GenerateKeyWithIPK_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + ECCCipher *pucKey, + void **phKeyHandle); + +typedef int (*SDF_GenerateKeyWithEPK_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucKey, + void **phKeyHandle); + +typedef int (*SDF_ImportKeyWithISK_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiISKIndex, + ECCCipher *pucKey, + void **phKeyHandle); + +typedef int (*SDF_GenerateAgreementDataWithECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + void **phAgreementHandle); + +typedef int (*SDF_GenerateKeyWithECC_FuncPtr)( + void *hSessionHandle, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void *hAgreementHandle, + void **phKeyHandle); + +typedef int (*SDF_GenerateAgreementDataAndKeyWithECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void **phKeyHandle); + +typedef int (*SDF_ExchangeDigitEnvelopeBaseOnECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucEncDataIn, + ECCCipher *pucEncDataOut); + +typedef int (*SDF_GenerateKeyWithKEK_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle); + +typedef int (*SDF_ImportKeyWithKEK_FuncPtr)( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle); + +typedef int (*SDF_DestroyKey_FuncPtr)( + void *hSessionHandle, + void *hKeyHandle); + +typedef int (*SDF_ExternalPublicKeyOperation_RSA_FuncPtr)( + void *hSessionHandle, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength); + +typedef int (*SDF_InternalPublicKeyOperation_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength); + +typedef int (*SDF_InternalPrivateKeyOperation_RSA_FuncPtr)( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength); + +typedef int (*SDF_ExternalVerify_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + ECCSignature *pucSignature); + +typedef int (*SDF_InternalSign_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature); + +typedef int (*SDF_InternalVerify_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature); + +typedef int (*SDF_ExternalEncrypt_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucData, + unsigned int uiDataLength, + ECCCipher *pucEncData); + +typedef int (*SDF_ExternalDecrypt_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPrivateKey *pucPrivateKey, + ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength); + +typedef int (*SDF_InternalEncrypt_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiAlgID, + unsigned char *pucData, + unsigned int uiDataLength, + ECCCipher *pucEncData); + +typedef int (*SDF_InternalDecrypt_ECC_FuncPtr)( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiAlgID, + ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength); + +typedef int (*SDF_Encrypt_FuncPtr)( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucEncData, + unsigned int *puiEncDataLength); + +typedef int (*SDF_Decrypt_FuncPtr)( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucEncData, + unsigned int uiEncDataLength, + unsigned char *pucData, + unsigned int *puiDataLength); + +typedef int (*SDF_CalculateMAC_FuncPtr)( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucMAC, + unsigned int *puiMACLength); + +typedef int (*SDF_HashInit_FuncPtr)( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucID, + unsigned int uiIDLength); + +typedef int (*SDF_HashUpdate_FuncPtr)( + void *hSessionHandle, + unsigned char *pucData, + unsigned int uiDataLength); + +typedef int (*SDF_HashFinal_FuncPtr)(void *hSessionHandle, + unsigned char *pucHash, + unsigned int *puiHashLength); + +typedef int (*SDF_CreateObject_FuncPtr)( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiFileSize); + +typedef int (*SDF_ReadObject_FuncPtr)( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int *puiReadLength, + unsigned char *pucBuffer); + +typedef int (*SDF_WriteObject_FuncPtr)( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int uiWriteLength, + unsigned char *pucBuffer); + +typedef int (*SDF_DeleteObject_FuncPtr)( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen); + +typedef struct sdf_method_st { + char *name; + dylib_handle_t dso; + + SDF_OpenDevice_FuncPtr OpenDevice; + SDF_CloseDevice_FuncPtr CloseDevice; + SDF_OpenSession_FuncPtr OpenSession; + SDF_CloseSession_FuncPtr CloseSession; + SDF_GetDeviceInfo_FuncPtr GetDeviceInfo; + SDF_GenerateRandom_FuncPtr GenerateRandom; + SDF_GetPrivateKeyAccessRight_FuncPtr GetPrivateKeyAccessRight; + SDF_ReleasePrivateKeyAccessRight_FuncPtr ReleasePrivateKeyAccessRight; + SDF_ExportSignPublicKey_RSA_FuncPtr ExportSignPublicKey_RSA; + SDF_ExportEncPublicKey_RSA_FuncPtr ExportEncPublicKey_RSA; + SDF_GenerateKeyPair_RSA_FuncPtr GenerateKeyPair_RSA; + SDF_GenerateKeyWithIPK_RSA_FuncPtr GenerateKeyWithIPK_RSA; + SDF_GenerateKeyWithEPK_RSA_FuncPtr GenerateKeyWithEPK_RSA; + SDF_ImportKeyWithISK_RSA_FuncPtr ImportKeyWithISK_RSA; + SDF_ExchangeDigitEnvelopeBaseOnRSA_FuncPtr ExchangeDigitEnvelopeBaseOnRSA; + SDF_ExportSignPublicKey_ECC_FuncPtr ExportSignPublicKey_ECC; + SDF_ExportEncPublicKey_ECC_FuncPtr ExportEncPublicKey_ECC; + SDF_GenerateKeyPair_ECC_FuncPtr GenerateKeyPair_ECC; + SDF_GenerateKeyWithIPK_ECC_FuncPtr GenerateKeyWithIPK_ECC; + SDF_GenerateKeyWithEPK_ECC_FuncPtr GenerateKeyWithEPK_ECC; + SDF_ImportKeyWithISK_ECC_FuncPtr ImportKeyWithISK_ECC; + SDF_GenerateAgreementDataWithECC_FuncPtr GenerateAgreementDataWithECC; + SDF_GenerateKeyWithECC_FuncPtr GenerateKeyWithECC; + SDF_GenerateAgreementDataAndKeyWithECC_FuncPtr GenerateAgreementDataAndKeyWithECC; + SDF_ExchangeDigitEnvelopeBaseOnECC_FuncPtr ExchangeDigitEnvelopeBaseOnECC; + SDF_GenerateKeyWithKEK_FuncPtr GenerateKeyWithKEK; + SDF_ImportKeyWithKEK_FuncPtr ImportKeyWithKEK; + SDF_DestroyKey_FuncPtr DestroyKey; + SDF_ExternalPublicKeyOperation_RSA_FuncPtr ExternalPublicKeyOperation_RSA; + SDF_InternalPublicKeyOperation_RSA_FuncPtr InternalPublicKeyOperation_RSA; + SDF_InternalPrivateKeyOperation_RSA_FuncPtr InternalPrivateKeyOperation_RSA; + SDF_ExternalVerify_ECC_FuncPtr ExternalVerify_ECC; + SDF_InternalSign_ECC_FuncPtr InternalSign_ECC; + SDF_InternalVerify_ECC_FuncPtr InternalVerify_ECC; + SDF_ExternalEncrypt_ECC_FuncPtr ExternalEncrypt_ECC; + SDF_ExternalDecrypt_ECC_FuncPtr ExternalDecrypt_ECC; + SDF_InternalEncrypt_ECC_FuncPtr InternalEncrypt_ECC; + SDF_InternalDecrypt_ECC_FuncPtr InternalDecrypt_ECC; + SDF_Encrypt_FuncPtr Encrypt; + SDF_Decrypt_FuncPtr Decrypt; + SDF_CalculateMAC_FuncPtr CalculateMAC; + SDF_HashInit_FuncPtr HashInit; + SDF_HashUpdate_FuncPtr HashUpdate; + SDF_HashFinal_FuncPtr HashFinal; + SDF_CreateObject_FuncPtr CreateObject; + SDF_ReadObject_FuncPtr ReadObject; + SDF_WriteObject_FuncPtr WriteObject; + SDF_DeleteObject_FuncPtr DeleteObject; +} SDF_METHOD; + +SDF_METHOD *SDF_METHOD_load_library(const char *so_path); +void SDF_METHOD_free(SDF_METHOD *meth); + + +typedef struct sdf_vendor_st { + char *name; + unsigned int (*cipher_vendor2std)(unsigned int vendor_id); + unsigned int (*cipher_std2vendor)(unsigned int std_id); + unsigned int (*cipher_cap)(unsigned int vendor_cap); + unsigned int (*digest_vendor2std)(unsigned int vendor_id); + unsigned int (*digest_std2vendor)(unsigned int std_id); + unsigned int (*digest_cap)(unsigned int vendor_cap); + unsigned int (*pkey_vendor2std)(unsigned int vendor_id); + unsigned int (*pkey_std2vendor)(unsigned int std_id); + unsigned int (*pkey_cap)(unsigned int vendor_cap); + int (*encode_ecccipher)(const ECCCipher *a, void *buf); + int (*decode_ecccipher)(ECCCipher *a, const void *buf); + unsigned long (*get_error_reason)(int err); +} SDF_VENDOR; + + +#endif diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_lib.c b/Core/GmSSL-3.1.1/src/sdf/sdf_lib.c new file mode 100755 index 0000000..46c5fb0 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_lib.c @@ -0,0 +1,1468 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include "sdf_ext.h" +#include "sdf_int.h" + +SDF_METHOD *sdf_method = NULL; +SDF_VENDOR *sdf_vendor = NULL; +extern SDF_VENDOR sdf_sansec; + + +#define SDFerr(reason) fprintf(stderr,"sdfutil: %s %d: %s %s\n", __FILE__, __LINE__, __FUNCTION__, reason) + + +#define SDF_R_LOAD_LIBRARY_FAILURE "SDF_R_LOAD_LIBRARY_FAILURE" +#define SDF_R_NOT_INITIALIZED "SDF_R_NOT_INITIALIZED" +#define SDF_R_NOT_SUPPORTED_ECC_ALGOR "SDF_R_NOT_SUPPORTED_ECC_ALGOR" +#define SDF_R_NOT_SUPPORTED_CIPHER_ALGOR "SDF_R_NOT_SUPPORTED_CIPHER_ALGOR" +#define SDF_R_BUFFER_TOO_SMALL "SDF_R_BUFFER_TOO_SMALL" +#define SDF_R_NOT_SUPPORTED_PKEY_ALGOR "SDF_R_NOT_SUPPORTED_PKEY_ALGOR" +#define SDF_R_NOT_SUPPORTED_DIGEST_ALGOR "SDF_R_NOT_SUPPORTED_DIGEST_ALGOR" +#define ERR_R_SDF_LIB "ERR_R_SDF_LIB" + + + +int SDF_LoadLibrary(char *so_path, char *vendor) +{ + if (sdf_method) { + SDF_METHOD_free(sdf_method); + sdf_method = NULL; + } + + if (!(sdf_method = SDF_METHOD_load_library(so_path))) { + SDFerr(SDF_R_LOAD_LIBRARY_FAILURE); + return SDR_BASE; + } + + if (vendor) { + if (strcmp(vendor, sdf_sansec.name) == 0) { + sdf_vendor = &sdf_sansec; + } + } + + return SDR_OK; +} + +int SDF_UnloadLibrary(void) +{ + SDF_METHOD_free(sdf_method); + sdf_method = NULL; + sdf_vendor = NULL; + return SDR_OK; +} + +int SDF_OpenDevice( + void **phDeviceHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->OpenDevice) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->OpenDevice( + phDeviceHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_CloseDevice( + void *hDeviceHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->CloseDevice) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->CloseDevice( + hDeviceHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_OpenSession( + void *hDeviceHandle, + void **phSessionHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->OpenSession) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->OpenSession( + hDeviceHandle, + phSessionHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_CloseSession( + void *hSessionHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->CloseSession) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->CloseSession( + hSessionHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GetDeviceInfo( + void *hSessionHandle, + DEVICEINFO *pstDeviceInfo) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GetDeviceInfo) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GetDeviceInfo( + hSessionHandle, + pstDeviceInfo)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateRandom( + void *hSessionHandle, + unsigned int uiLength, + unsigned char *pucRandom) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateRandom) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateRandom( + hSessionHandle, + uiLength, + pucRandom)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GetPrivateKeyAccessRight( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GetPrivateKeyAccessRight) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GetPrivateKeyAccessRight( + hSessionHandle, + uiKeyIndex, + pucPassword, + uiPwdLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ReleasePrivateKeyAccessRight( + void *hSessionHandle, + unsigned int uiKeyIndex) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ReleasePrivateKeyAccessRight) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ReleasePrivateKeyAccessRight( + hSessionHandle, + uiKeyIndex)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExportSignPublicKey_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExportSignPublicKey_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ExportSignPublicKey_RSA( + hSessionHandle, + uiKeyIndex, + pucPublicKey)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExportEncPublicKey_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExportEncPublicKey_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ExportEncPublicKey_RSA( + hSessionHandle, + uiKeyIndex, + pucPublicKey)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyPair_RSA( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + RSArefPrivateKey *pucPrivateKey) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyPair_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateKeyPair_RSA( + hSessionHandle, + uiKeyBits, + pucPublicKey, + pucPrivateKey)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyWithIPK_RSA( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyWithIPK_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateKeyWithIPK_RSA( + hSessionHandle, + uiIPKIndex, + uiKeyBits, + pucKey, + puiKeyLength, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyWithEPK_RSA( + void *hSessionHandle, + unsigned int uiKeyBits, + RSArefPublicKey *pucPublicKey, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyWithEPK_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateKeyWithEPK_RSA( + hSessionHandle, + uiKeyBits, + pucPublicKey, + pucKey, + puiKeyLength, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ImportKeyWithISK_RSA( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ImportKeyWithISK_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ImportKeyWithISK_RSA( + hSessionHandle, + uiISKIndex, + pucKey, + uiKeyLength, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExchangeDigitEnvelopeBaseOnRSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDEInput, + unsigned int uiDELength, + unsigned char *pucDEOutput, + unsigned int *puiDELength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExchangeDigitEnvelopeBaseOnRSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ExchangeDigitEnvelopeBaseOnRSA( + hSessionHandle, + uiKeyIndex, + pucPublicKey, + pucDEInput, + uiDELength, + pucDEOutput, + puiDELength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExportSignPublicKey_ECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExportSignPublicKey_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ExportSignPublicKey_ECC( + hSessionHandle, + uiKeyIndex, + pucPublicKey)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExportEncPublicKey_ECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + ECCrefPublicKey *pucPublicKey) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExportEncPublicKey_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ExportEncPublicKey_ECC( + hSessionHandle, + uiKeyIndex, + pucPublicKey)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyPair_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKeyBits, + ECCrefPublicKey *pucPublicKey, + ECCrefPrivateKey *pucPrivateKey) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyPair_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->pkey_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_ECC_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->GenerateKeyPair_ECC( + hSessionHandle, + uiAlgID, + uiKeyBits, + pucPublicKey, + pucPrivateKey)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyWithIPK_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiKeyBits, + ECCCipher *pucKey, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyWithIPK_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateKeyWithIPK_ECC( + hSessionHandle, + uiIPKIndex, + uiKeyBits, + pucKey, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyWithEPK_ECC( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucKey, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyWithEPK_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->cipher_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->GenerateKeyWithEPK_ECC( + hSessionHandle, + uiKeyBits, + uiAlgID, + pucPublicKey, + pucKey, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ImportKeyWithISK_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + ECCCipher *pucKey, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ImportKeyWithISK_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ImportKeyWithISK_ECC( + hSessionHandle, + uiISKIndex, + pucKey, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateAgreementDataWithECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + void **phAgreementHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateAgreementDataWithECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateAgreementDataWithECC( + hSessionHandle, + uiISKIndex, + uiKeyBits, + pucSponsorID, + uiSponsorIDLength, + pucSponsorPublicKey, + pucSponsorTmpPublicKey, + phAgreementHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyWithECC( + void *hSessionHandle, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void *hAgreementHandle, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyWithECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateKeyWithECC( + hSessionHandle, + pucResponseID, + uiResponseIDLength, + pucResponsePublicKey, + pucResponseTmpPublicKey, + hAgreementHandle, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateAgreementDataAndKeyWithECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiKeyBits, + unsigned char *pucResponseID, + unsigned int uiResponseIDLength, + unsigned char *pucSponsorID, + unsigned int uiSponsorIDLength, + ECCrefPublicKey *pucSponsorPublicKey, + ECCrefPublicKey *pucSponsorTmpPublicKey, + ECCrefPublicKey *pucResponsePublicKey, + ECCrefPublicKey *pucResponseTmpPublicKey, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateAgreementDataAndKeyWithECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->GenerateAgreementDataAndKeyWithECC( + hSessionHandle, + uiISKIndex, + uiKeyBits, + pucResponseID, + uiResponseIDLength, + pucSponsorID, + uiSponsorIDLength, + pucSponsorPublicKey, + pucSponsorTmpPublicKey, + pucResponsePublicKey, + pucResponseTmpPublicKey, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExchangeDigitEnvelopeBaseOnECC( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + ECCCipher *pucEncDataIn, + ECCCipher *pucEncDataOut) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExchangeDigitEnvelopeBaseOnECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->cipher_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->ExchangeDigitEnvelopeBaseOnECC( + hSessionHandle, + uiKeyIndex, + uiAlgID, + pucPublicKey, + pucEncDataIn, + pucEncDataOut)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_GenerateKeyWithKEK( + void *hSessionHandle, + unsigned int uiKeyBits, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int *puiKeyLength, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->GenerateKeyWithKEK) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->cipher_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->GenerateKeyWithKEK( + hSessionHandle, + uiKeyBits, + uiAlgID, + uiKEKIndex, + pucKey, + puiKeyLength, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ImportKeyWithKEK( + void *hSessionHandle, + unsigned int uiAlgID, + unsigned int uiKEKIndex, + unsigned char *pucKey, + unsigned int uiKeyLength, + void **phKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ImportKeyWithKEK) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->cipher_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->ImportKeyWithKEK( + hSessionHandle, + uiAlgID, + uiKEKIndex, + pucKey, + uiKeyLength, + phKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_DestroyKey( + void *hSessionHandle, + void *hKeyHandle) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->DestroyKey) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->DestroyKey( + hSessionHandle, + hKeyHandle)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExternalPublicKeyOperation_RSA( + void *hSessionHandle, + RSArefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExternalPublicKeyOperation_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ExternalPublicKeyOperation_RSA( + hSessionHandle, + pucPublicKey, + pucDataInput, + uiInputLength, + pucDataOutput, + puiOutputLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_InternalPublicKeyOperation_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->InternalPublicKeyOperation_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->InternalPublicKeyOperation_RSA( + hSessionHandle, + uiKeyIndex, + pucDataInput, + uiInputLength, + pucDataOutput, + puiOutputLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_InternalPrivateKeyOperation_RSA( + void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucDataInput, + unsigned int uiInputLength, + unsigned char *pucDataOutput, + unsigned int *puiOutputLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->InternalPrivateKeyOperation_RSA) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->InternalPrivateKeyOperation_RSA( + hSessionHandle, + uiKeyIndex, + pucDataInput, + uiInputLength, + pucDataOutput, + puiOutputLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExternalVerify_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucDataInput, + unsigned int uiInputLength, + ECCSignature *pucSignature) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExternalVerify_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->pkey_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_PKEY_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->ExternalVerify_ECC( + hSessionHandle, + uiAlgID, + pucPublicKey, + pucDataInput, + uiInputLength, + pucSignature)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_InternalSign_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->InternalSign_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->InternalSign_ECC( + hSessionHandle, + uiISKIndex, + pucData, + uiDataLength, + pucSignature)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_InternalVerify_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + ECCSignature *pucSignature) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->InternalVerify_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->InternalVerify_ECC( + hSessionHandle, + uiIPKIndex, + pucData, + uiDataLength, + pucSignature)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ExternalEncrypt_ECC( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucData, + unsigned int uiDataLength, + ECCCipher *pucEncData) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ExternalEncrypt_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->pkey_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_PKEY_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->ExternalEncrypt_ECC( + hSessionHandle, + uiAlgID, + pucPublicKey, + pucData, + uiDataLength, + pucEncData)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_InternalEncrypt_ECC( + void *hSessionHandle, + unsigned int uiIPKIndex, + unsigned int uiAlgID, + unsigned char *pucData, + unsigned int uiDataLength, + ECCCipher *pucEncData) +{ + int ret = SDR_UNKNOWERR; + ECCCipher *buf = pucEncData; + + if (!sdf_method || !sdf_method->InternalEncrypt_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (pucEncData->L < uiDataLength) { + SDFerr(SDF_R_BUFFER_TOO_SMALL); + return SDR_NOBUFFER; + } + + if (sdf_vendor && sdf_vendor->decode_ecccipher) { + if (SDF_NewECCCipher(&buf, uiDataLength) != SDR_OK) { + SDFerr(ERR_R_SDF_LIB); + return SDR_UNKNOWERR; + } + } + + if (sdf_vendor && sdf_vendor->pkey_std2vendor) { + if (!(uiAlgID = sdf_vendor->pkey_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_PKEY_ALGOR); + ret = SDR_ALGNOTSUPPORT; + goto end; + } + } + + if ((ret = sdf_method->InternalEncrypt_ECC( + hSessionHandle, + uiIPKIndex, + uiAlgID, + pucData, + uiDataLength, + buf)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + goto end; + } + + if (sdf_vendor && sdf_vendor->decode_ecccipher) { + if (!sdf_vendor->decode_ecccipher(pucEncData, buf)) { + SDFerr(ERR_R_SDF_LIB); + ret = SDR_UNKNOWERR; + goto end; + } + } + + /* + { + int i; + unsigned char *p = (unsigned char *)pucEncData; + for (i = 0; i < sizeof(ECCCipher) -1 + uiDataLength; i++) { + printf("%02x", p[i]); + } + printf("\n"); + } + */ + + ret = SDR_OK; + +end: + if (sdf_vendor && sdf_vendor->decode_ecccipher && buf) { + SDF_FreeECCCipher(buf); + } + return ret; +} + +int SDF_InternalDecrypt_ECC( + void *hSessionHandle, + unsigned int uiISKIndex, + unsigned int uiAlgID, + ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *uiDataLength) +{ + int ret = SDR_UNKNOWERR; + ECCCipher *buf = pucEncData; + + if (!sdf_method || !sdf_method->InternalDecrypt_ECC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor && sdf_vendor->pkey_std2vendor) { + if (!(uiAlgID = sdf_vendor->pkey_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_PKEY_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if (sdf_vendor && sdf_vendor->encode_ecccipher) { + if (SDF_NewECCCipher(&buf, pucEncData->L) != SDR_OK) { + SDFerr(ERR_R_SDF_LIB); + return SDR_UNKNOWERR; + } + + if (!sdf_vendor->encode_ecccipher(pucEncData, buf)) { + SDFerr(ERR_R_SDF_LIB); + ret = SDR_UNKNOWERR; + goto end; + } + } + + if ((ret = sdf_method->InternalDecrypt_ECC( + hSessionHandle, + uiISKIndex, + uiAlgID, + buf, + pucData, + uiDataLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + goto end; + } + +end: + if (sdf_vendor && sdf_vendor->encode_ecccipher && buf) { + SDF_FreeECCCipher(buf); + } + return ret; +} + +int SDF_Encrypt( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucEncData, + unsigned int *puiEncDataLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->Encrypt) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->cipher_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->Encrypt( + hSessionHandle, + hKeyHandle, + uiAlgID, + pucIV, + pucData, + uiDataLength, + pucEncData, + puiEncDataLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_Decrypt( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucEncData, + unsigned int uiEncDataLength, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->Decrypt) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->cipher_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->Decrypt( + hSessionHandle, + hKeyHandle, + uiAlgID, + pucIV, + pucEncData, + uiEncDataLength, + pucData, + puiDataLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_CalculateMAC( + void *hSessionHandle, + void *hKeyHandle, + unsigned int uiAlgID, + unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucMAC, + unsigned int *puiMACLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->CalculateMAC) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->cipher_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->CalculateMAC( + hSessionHandle, + hKeyHandle, + uiAlgID, + pucIV, + pucData, + uiDataLength, + pucMAC, + puiMACLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_HashInit( + void *hSessionHandle, + unsigned int uiAlgID, + ECCrefPublicKey *pucPublicKey, + unsigned char *pucID, + unsigned int uiIDLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->HashInit) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if (sdf_vendor) { + if (!(uiAlgID = sdf_vendor->digest_std2vendor(uiAlgID))) { + SDFerr(SDF_R_NOT_SUPPORTED_DIGEST_ALGOR); + return SDR_ALGNOTSUPPORT; + } + } + + if ((ret = sdf_method->HashInit( + hSessionHandle, + uiAlgID, + pucPublicKey, + pucID, + uiIDLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_HashUpdate( + void *hSessionHandle, + unsigned char *pucData, + unsigned int uiDataLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->HashUpdate) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->HashUpdate( + hSessionHandle, + pucData, + uiDataLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_HashFinal( + void *hSessionHandle, + unsigned char *pucHash, + unsigned int *puiHashLength) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->HashFinal) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->HashFinal( + hSessionHandle, + pucHash, + puiHashLength)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_CreateFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiFileSize) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->CreateObject) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->CreateObject( + hSessionHandle, + pucFileName, + uiNameLen, + uiFileSize)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_ReadFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int *puiReadLength, + unsigned char *pucBuffer) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->ReadObject) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->ReadObject( + hSessionHandle, + pucFileName, + uiNameLen, + uiOffset, + puiReadLength, + pucBuffer)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_WriteFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen, + unsigned int uiOffset, + unsigned int uiWriteLength, + unsigned char *pucBuffer) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->WriteObject) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->WriteObject( + hSessionHandle, + pucFileName, + uiNameLen, + uiOffset, + uiWriteLength, + pucBuffer)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} + +int SDF_DeleteFile( + void *hSessionHandle, + unsigned char *pucFileName, + unsigned int uiNameLen) +{ + int ret = SDR_UNKNOWERR; + + if (!sdf_method || !sdf_method->DeleteObject) { + SDFerr(SDF_R_NOT_INITIALIZED); + return SDR_NOTSUPPORT; + } + + if ((ret = sdf_method->DeleteObject( + hSessionHandle, + pucFileName, + uiNameLen)) != SDR_OK) { + SDFerr(SDF_GetErrorReason(ret)); + return ret; + } + + return SDR_OK; +} diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_meth.c b/Core/GmSSL-3.1.1/src/sdf/sdf_meth.c new file mode 100755 index 0000000..e4b77a3 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_meth.c @@ -0,0 +1,104 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include "sdf_int.h" + +#define SDFerr(a,b) + +#define SDF_METHOD_BIND_FUNCTION_EX(func,name) \ + sdf->func = (SDF_##func##_FuncPtr)dylib_get_function(sdf->dso, "SDF_"#name) + +#define SDF_METHOD_BIND_FUNCTION(func) \ + SDF_METHOD_BIND_FUNCTION_EX(func,func) + +SDF_METHOD *SDF_METHOD_load_library(const char *so_path) +{ + SDF_METHOD *ret = NULL; + SDF_METHOD *sdf = NULL; + + if (!(sdf = malloc(sizeof(*sdf)))) { + SDFerr(SDF_F_SDF_METHOD_LOAD_LIBRARY, ERR_R_MALLOC_FAILURE); + goto end; + } + memset(sdf, 0, sizeof(*sdf)); + + if (!(sdf->dso = dylib_load_library(so_path))) { + fprintf(stderr, "%s %d: %s\n", __FILE__, __LINE__, dylib_error_str()); + goto end; + } + + SDF_METHOD_BIND_FUNCTION(OpenDevice); + SDF_METHOD_BIND_FUNCTION(CloseDevice); + SDF_METHOD_BIND_FUNCTION(OpenSession); + SDF_METHOD_BIND_FUNCTION(CloseSession); + SDF_METHOD_BIND_FUNCTION(GetDeviceInfo); + SDF_METHOD_BIND_FUNCTION(GenerateRandom); + SDF_METHOD_BIND_FUNCTION(GetPrivateKeyAccessRight); + SDF_METHOD_BIND_FUNCTION(ReleasePrivateKeyAccessRight); + SDF_METHOD_BIND_FUNCTION(ExportSignPublicKey_RSA); + SDF_METHOD_BIND_FUNCTION(ExportEncPublicKey_RSA); + SDF_METHOD_BIND_FUNCTION(GenerateKeyPair_RSA); + SDF_METHOD_BIND_FUNCTION(GenerateKeyWithIPK_RSA); + SDF_METHOD_BIND_FUNCTION(GenerateKeyWithEPK_RSA); + SDF_METHOD_BIND_FUNCTION(ImportKeyWithISK_RSA); + SDF_METHOD_BIND_FUNCTION(ExchangeDigitEnvelopeBaseOnRSA); + SDF_METHOD_BIND_FUNCTION(ExportSignPublicKey_ECC); + SDF_METHOD_BIND_FUNCTION(ExportEncPublicKey_ECC); + SDF_METHOD_BIND_FUNCTION(GenerateKeyPair_ECC); + SDF_METHOD_BIND_FUNCTION(GenerateKeyWithIPK_ECC); + SDF_METHOD_BIND_FUNCTION(GenerateKeyWithEPK_ECC); + SDF_METHOD_BIND_FUNCTION(ImportKeyWithISK_ECC); + SDF_METHOD_BIND_FUNCTION(GenerateAgreementDataWithECC); + SDF_METHOD_BIND_FUNCTION(GenerateKeyWithECC); + SDF_METHOD_BIND_FUNCTION(GenerateAgreementDataAndKeyWithECC); + SDF_METHOD_BIND_FUNCTION(ExchangeDigitEnvelopeBaseOnECC); + SDF_METHOD_BIND_FUNCTION(GenerateKeyWithKEK); + SDF_METHOD_BIND_FUNCTION(ImportKeyWithKEK); + SDF_METHOD_BIND_FUNCTION(DestroyKey); + SDF_METHOD_BIND_FUNCTION(ExternalPublicKeyOperation_RSA); + //SDF_METHOD_BIND_FUNCTION(InternalPublicKeyOperation_RSA); + SDF_METHOD_BIND_FUNCTION(InternalPrivateKeyOperation_RSA); + SDF_METHOD_BIND_FUNCTION(ExternalVerify_ECC); + SDF_METHOD_BIND_FUNCTION(InternalSign_ECC); + SDF_METHOD_BIND_FUNCTION(InternalVerify_ECC); + SDF_METHOD_BIND_FUNCTION(ExternalEncrypt_ECC); + //SDF_METHOD_BIND_FUNCTION(ExternalDecrypt_ECC); + SDF_METHOD_BIND_FUNCTION(InternalEncrypt_ECC); + SDF_METHOD_BIND_FUNCTION(InternalDecrypt_ECC); + SDF_METHOD_BIND_FUNCTION(Encrypt); + SDF_METHOD_BIND_FUNCTION(Decrypt); + SDF_METHOD_BIND_FUNCTION(CalculateMAC); + SDF_METHOD_BIND_FUNCTION(HashInit); + SDF_METHOD_BIND_FUNCTION(HashUpdate); + SDF_METHOD_BIND_FUNCTION(HashFinal); + SDF_METHOD_BIND_FUNCTION_EX(CreateObject,CreateFile); + SDF_METHOD_BIND_FUNCTION_EX(ReadObject,ReadFile); + SDF_METHOD_BIND_FUNCTION_EX(WriteObject,WriteFile); + SDF_METHOD_BIND_FUNCTION_EX(DeleteObject,DeleteFile); + + ret = sdf; + sdf = NULL; + +end: + SDF_METHOD_free(sdf); + return ret; +} + +void SDF_METHOD_free(SDF_METHOD *meth) +{ + if (meth) dylib_close_library(meth->dso); + free(meth); +} + + diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_sansec.c b/Core/GmSSL-3.1.1/src/sdf/sdf_sansec.c new file mode 100755 index 0000000..52b7218 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_sansec.c @@ -0,0 +1,266 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include "sdf.h" +#include "sdf_int.h" +#include "sdf_sansec.h" + + +#define SDFerr(a,b) + +typedef struct { + unsigned int std_id; + unsigned int vendor_id; +} SDF_ALGOR_PAIR; + +static SDF_ALGOR_PAIR sansec_ciphers[] = { + { SGD_SM1, SANSEC_SM1 }, + { SGD_SM1_ECB, SANSEC_SM1_ECB }, + { SGD_SM1_CBC, SANSEC_SM1_CBC }, + { SGD_SM1_CFB, SANSEC_SM1_CFB }, + { SGD_SM1_OFB, SANSEC_SM1_OFB }, + { SGD_SM1_MAC, SANSEC_SM1_MAC }, + { SGD_SM4, SANSEC_SM4 }, + { SGD_SM4_ECB, SANSEC_SM4_ECB }, + { SGD_SM4_CBC, SANSEC_SM4_CBC }, + { SGD_SM4_CFB, SANSEC_SM4_CFB }, + { SGD_SM4_OFB, SANSEC_SM4_OFB }, + { SGD_SM4_MAC, SANSEC_SM4_MAC }, + { SGD_SSF33, SANSEC_SSF33 }, + { SGD_SSF33_ECB, SANSEC_SSF33_ECB }, + { SGD_SSF33_CBC, SANSEC_SSF33_CBC }, + { SGD_SSF33_CFB, SANSEC_SSF33_CFB }, + { SGD_SSF33_OFB, SANSEC_SSF33_OFB }, + { SGD_SSF33_MAC, SANSEC_SSF33_MAC }, + { 0, SANSEC_AES }, + { 0, SANSEC_AES_ECB }, + { 0, SANSEC_AES_CBC }, + { 0, SANSEC_AES_CFB }, + { 0, SANSEC_AES_OFB }, + { 0, SANSEC_AES_MAC }, + { 0, SANSEC_DES }, + { 0, SANSEC_DES_ECB }, + { 0, SANSEC_DES_CBC }, + { 0, SANSEC_DES_CFB }, + { 0, SANSEC_DES_OFB }, + { 0, SANSEC_DES_MAC }, + { 0, SANSEC_3DES }, + { 0, SANSEC_3DES_ECB }, + { 0, SANSEC_3DES_CBC }, + { 0, SANSEC_3DES_CFB }, + { 0, SANSEC_3DES_OFB }, + { 0, SANSEC_3DES_MAC }, +}; + +static unsigned int sansec_cipher_vendor2std(unsigned int vendor_id) +{ + size_t i; + for (i = 0; i < sizeof(sansec_ciphers)/sizeof(sansec_ciphers[0]); i++) { + if (vendor_id == sansec_ciphers[i].vendor_id) { + return sansec_ciphers[i].std_id; + } + } + return 0; +} + +static unsigned int sansec_cipher_std2vendor(unsigned int std_id) +{ + size_t i; + for (i = 0; i < sizeof(sansec_ciphers)/sizeof(sansec_ciphers[0]); i++) { + if (std_id == sansec_ciphers[i].std_id) { + return sansec_ciphers[i].vendor_id; + } + } + return 0; +} + +static unsigned int sansec_cipher_cap(unsigned int vendor_cap) +{ + unsigned int std_cap = 0; + size_t i; + + for (i = 0; i < sizeof(sansec_ciphers)/sizeof(sansec_ciphers[0]); i++) { + if (vendor_cap & sansec_ciphers[i].vendor_id) { + std_cap |= sansec_ciphers[i].std_id; + } + } + + return std_cap; +} + +static SDF_ALGOR_PAIR sansec_digests[] = { + { SGD_SM3, SANSEC_SM3 }, + { SGD_SHA1, SANSEC_SHA1 }, + { SGD_SHA256, SANSEC_SHA256 }, + { 0, SANSEC_SHA512 }, + { 0, SANSEC_SHA384 }, + { 0, SANSEC_SHA224 }, + { 0, SANSEC_MD5 }, +}; + +static unsigned int sansec_digest_vendor2std(unsigned int vendor_id) +{ + size_t i; + for (i = 0; i < sizeof(sansec_digests)/sizeof(sansec_digests[0]); i++) { + if (vendor_id == sansec_digests[i].vendor_id) { + return sansec_digests[i].std_id; + } + } + return 0; +} + +static unsigned int sansec_digest_std2vendor(unsigned int std_id) +{ + size_t i; + for (i = 0; i < sizeof(sansec_digests)/sizeof(sansec_digests[0]); i++) { + if (std_id == sansec_digests[i].std_id) { + return sansec_digests[i].vendor_id; + } + } + return 0; +} + +static unsigned int sansec_digest_cap(unsigned int vendor_cap) +{ + unsigned int std_cap = 0; + size_t i; + + for (i = 0; i < sizeof(sansec_digests)/sizeof(sansec_digests[0]); i++) { + if (vendor_cap & sansec_digests[i].vendor_id) { + std_cap |= sansec_digests[i].std_id; + } + } + + return std_cap; +} + +static SDF_ALGOR_PAIR sansec_pkeys[] = { + { SGD_RSA,SANSEC_RSA }, + { SGD_RSA_SIGN,SANSEC_RSA_SIGN }, + { SGD_RSA_ENC,SANSEC_RSA_ENC }, + { SGD_SM2,SANSEC_SM2 }, + { SGD_SM2_1,SANSEC_SM2_1 }, + { SGD_SM2_2,SANSEC_SM2_2 }, + { SGD_SM2_3,SANSEC_SM2_3 }, +}; + +static unsigned int sansec_pkey_vendor2std(unsigned int vendor_id) +{ + size_t i; + for (i = 0; i < sizeof(sansec_pkeys)/sizeof(sansec_pkeys[0]); i++) { + if (vendor_id == sansec_pkeys[i].vendor_id) { + return sansec_pkeys[i].std_id; + } + } + return 0; +} + +static unsigned int sansec_pkey_std2vendor(unsigned int std_id) +{ + size_t i; + for (i = 0; i < sizeof(sansec_pkeys)/sizeof(sansec_pkeys[0]); i++) { + if (std_id == sansec_pkeys[i].std_id) { + return sansec_pkeys[i].vendor_id; + } + } + return 0; +} + +static unsigned int sansec_pkey_cap(unsigned int vendor_cap) +{ + unsigned int std_cap = 0; + size_t i; + + for (i = 0; i < sizeof(sansec_pkeys)/sizeof(sansec_pkeys[0]); i++) { + if (vendor_cap & sansec_pkeys[i].vendor_id) { + std_cap |= sansec_pkeys[i].std_id; + } + } + + return std_cap; +} + +static int sansec_encode_ecccipher(const ECCCipher *ec, void *vendor) +{ + int ret; + SANSEC_ECCCipher *sansec = vendor; + ret = sizeof(SANSEC_ECCCipher); + + if (ec->L > sizeof(sansec->C)) { + SDFerr(SDF_F_SANSEC_ENCODE_ECCCIPHER, + SDF_R_INVALID_SANSEC_ECCCIPHER_LENGTH); + return 0; + } + + if (vendor) { + sansec->clength = ec->L; + memcpy(sansec->x, ec->x, sizeof(ec->x)); + memcpy(sansec->y, ec->y, sizeof(ec->y)); + memcpy(sansec->M, ec->M, sizeof(ec->M)); + memset(sansec->M + sizeof(ec->M), 0, sizeof(sansec->M) - sizeof(ec->M)); + memcpy(sansec->C, ec->C, ec->L); + memset(sansec->C + ec->L, 0, sizeof(sansec->C) - ec->L); + } + + return ret; +} + +static int sansec_decode_ecccipher(ECCCipher *ec, const void *vendor) +{ + int ret; + const SANSEC_ECCCipher *sansec = vendor; + ret = sizeof(ECCCipher) -1 + sansec->clength; + + if (sansec->clength > sizeof(sansec->C)) { + SDFerr(SDF_F_SANSEC_DECODE_ECCCIPHER, + SDF_R_INVALID_SANSEC_ECCCIPHER_LENGTH); + return 0; + } + + if (ec) { + memcpy(ec->x, sansec->x, sizeof(ec->x)); + memcpy(ec->y, sansec->y, sizeof(ec->y)); + memcpy(ec->M, sansec->M, sizeof(ec->M)); + ec->L = sansec->clength; + memcpy(ec->C, sansec->C, sansec->clength); + } + + return ret; +} + +static unsigned long sansec_get_error_reason(int err) +{ +/* + size_t i = 0; + for (i = 0; i < OSSL_NELEM(sansec_errors); i++) { + if (err == sansec_errors[i].err) { + return sansec_errors[i].reason; + } + } +*/ + return 0; +} + +SDF_VENDOR sdf_sansec = { + "sansec", + sansec_cipher_vendor2std, + sansec_cipher_std2vendor, + sansec_cipher_cap, + sansec_digest_vendor2std, + sansec_digest_std2vendor, + sansec_digest_cap, + sansec_pkey_vendor2std, + sansec_pkey_std2vendor, + sansec_pkey_cap, + sansec_encode_ecccipher, + sansec_decode_ecccipher, + sansec_get_error_reason, +}; diff --git a/Core/GmSSL-3.1.1/src/sdf/sdf_sansec.h b/Core/GmSSL-3.1.1/src/sdf/sdf_sansec.h new file mode 100755 index 0000000..aced93d --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sdf/sdf_sansec.h @@ -0,0 +1,153 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef SDFUTIL_SDF_SANSEC_H +#define SDFUTIL_SDF_SANSEC_H + +#include "../sgd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SANSEC_SM1 (SGD_SM1) +#define SANSEC_SM1_ECB (SANSEC_SM1|SGD_ECB) +#define SANSEC_SM1_CBC (SANSEC_SM1|SGD_CBC) +#define SANSEC_SM1_CFB (SANSEC_SM1|SGD_CFB) +#define SANSEC_SM1_OFB (SANSEC_SM1|SGD_OFB) +#define SANSEC_SM1_MAC (SANSEC_SM1|SGD_MAC) + +#define SANSEC_SM4 0x00002000 +#define SANSEC_SM4_ECB (SANSEC_SM4|SGD_ECB) +#define SANSEC_SM4_CBC (SANSEC_SM4|SGD_CBC) +#define SANSEC_SM4_CFB (SANSEC_SM4|SGD_CFB) +#define SANSEC_SM4_OFB (SANSEC_SM4|SGD_OFB) +#define SANSEC_SM4_MAC (SANSEC_SM4|SGD_MAC) + +#define SANSEC_SSF33 (SGD_SSF33) +#define SANSEC_SSF33_ECB (SANSEC_SSF33|SGD_ECB) +#define SANSEC_SSF33_CBC (SANSEC_SSF33|SGD_CBC) +#define SANSEC_SSF33_CFB (SANSEC_SSF33|SGD_CFB) +#define SANSEC_SSF33_OFB (SANSEC_SSF33|SGD_OFB) +#define SANSEC_SSF33_MAC (SANSEC_SSF33|SGD_MAC) + +#define SANSEC_AES 0x00000400 +#define SANSEC_AES_ECB (SANSEC_AES|SGD_ECB) +#define SANSEC_AES_CBC (SANSEC_AES|SGD_CBC) +#define SANSEC_AES_CFB (SANSEC_AES|SGD_CFB) +#define SANSEC_AES_OFB (SANSEC_AES|SGD_OFB) +#define SANSEC_AES_MAC (SANSEC_AES|SGD_MAC) + +#define SANSEC_DES 0x00004000 +#define SANSEC_DES_ECB (SANSEC_DES|SGD_ECB) +#define SANSEC_DES_CBC (SANSEC_DES|SGD_CBC) +#define SANSEC_DES_CFB (SANSEC_DES|SGD_CFB) +#define SANSEC_DES_OFB (SANSEC_DES|SGD_OFB) +#define SANSEC_DES_MAC (SANSEC_DES|SGD_MAC) + +#define SANSEC_3DES 0x00000800 +#define SANSEC_3DES_ECB (SANSEC_3DES|SGD_ECB) +#define SANSEC_3DES_CBC (SANSEC_3DES|SGD_CBC) +#define SANSEC_3DES_CFB (SANSEC_3DES|SGD_CFB) +#define SANSEC_3DES_OFB (SANSEC_3DES|SGD_OFB) +#define SANSEC_3DES_MAC (SANSEC_3DES|SGD_MAC) + +#define SANSEC_SM3 (SGD_SM3) +#define SANSEC_SHA1 (SGD_SHA1) +#define SANSEC_SHA256 (SGD_SHA256) +#define SANSEC_SHA512 0x00000008 +#define SANSEC_SHA384 0x00000010 +#define SANSEC_SHA224 0x00000020 +#define SANSEC_MD5 0x00000080 + +#define SANSEC_RSA (SGD_RSA) +#define SANSEC_RSA_SIGN (SGD_RSA_SIGN) +#define SANSEC_RSA_ENC 0x00010200 +#define SANSEC_SM2 (SGD_SM2) +#define SANSEC_SM2_1 (SGD_SM2_1) +#define SANSEC_SM2_2 (SGD_SM2_2) +#define SANSEC_SM2_3 (SGD_SM2_3) + +#define SANSEC_BASE (SDR_BASE + 0x00010000) +#define SANSEC_INVALID_USER (SANSEC_BASE + 0x00000001) +#define SANSEC_INVALID_AUTHENCODE (SANSEC_BASE + 0x00000002) +#define SANSEC_PROTOCOL_VERSION_ERROR (SANSEC_BASE + 0x00000003) +#define SANSEC_INVALID_COMMAND (SANSEC_BASE + 0x00000004) +#define SANSEC_INVALID_PARAMETERS (SANSEC_BASE + 0x00000005) +#define SANSEC_FILE_ALREADY_EXIST (SANSEC_BASE + 0x00000006) +#define SANSEC_SYNC_ERROR (SANSEC_BASE + 0x00000007) +#define SANSEC_SYNC_LOGIN_ERROR (SANSEC_BASE + 0x00000008) +#define SANSEC_SOCKET_TIMEOUT (SANSEC_BASE + 0x00000100) +#define SANSEC_CONNECT_ERROR (SANSEC_BASE + 0x00000101) +#define SANSEC_SET_SOCKET_OPTION_ERROR (SANSEC_BASE + 0x00000102) +#define SANSEC_SOCKET_SEND_ERROR (SANSEC_BASE + 0x00000104) +#define SANSEC_SOCKET_RECV_ERROR (SANSEC_BASE + 0x00000105) +#define SANSEC_SOCKET_RECV_0 (SANSEC_BASE + 0x00000106) +#define SANSEC_SEM_TIMEOUT (SANSEC_BASE + 0x00000200) +#define SANSEC_NO_AVAILABLE_HSM (SANSEC_BASE + 0x00000201) +#define SANSEC_NO_AVAILABLE_CSM (SANSEC_BASE + 0x00000202) +#define SANSEC_CONFIG_ERROR (SANSEC_BASE + 0x00000301) +#define SANSEC_CARD_BASE (SDR_BASE + 0x00020000) +#define SANSEC_CARD_UNKNOW_ERROR (SANSEC_CARD_BASE + 0x00000001) +#define SANSEC_CARD_NOT_SUPPORTED (SANSEC_CARD_BASE + 0x00000002) +#define SANSEC_CARD_COMMMUCATION_FAILED (SANSEC_CARD_BASE + 0x00000003) +#define SANSEC_CARD_HARDWARE_FAILURE (SANSEC_CARD_BASE + 0x00000004) +#define SANSEC_CARD_OPEN_DEVICE_FAILED (SANSEC_CARD_BASE + 0x00000005) +#define SANSEC_CARD_OPEN_SESSION_FAILED (SANSEC_CARD_BASE + 0x00000006) +#define SANSEC_CARD_PRIVATE_KEY_ACCESS_DENYED (SANSEC_CARD_BASE + 0x00000007) +#define SANSEC_CARD_KEY_NOT_EXIST (SANSEC_CARD_BASE + 0x00000008) +#define SANSEC_CARD_ALGOR_NOT_SUPPORTED (SANSEC_CARD_BASE + 0x00000009) +#define SANSEC_CARD_ALG_MODE_NOT_SUPPORTED (SANSEC_CARD_BASE + 0x00000010) +#define SANSEC_CARD_PUBLIC_KEY_OPERATION_ERROR (SANSEC_CARD_BASE + 0x00000011) +#define SANSEC_CARD_PRIVATE_KEY_OPERATION_ERROR (SANSEC_CARD_BASE + 0x00000012) +#define SANSEC_CARD_SIGN_ERROR (SANSEC_CARD_BASE + 0x00000013) +#define SANSEC_CARD_VERIFY_ERROR (SANSEC_CARD_BASE + 0x00000014) +#define SANSEC_CARD_SYMMETRIC_ALGOR_ERROR (SANSEC_CARD_BASE + 0x00000015) +#define SANSEC_CARD_STEP_ERROR (SANSEC_CARD_BASE + 0x00000016) +#define SANSEC_CARD_FILE_SIZE_ERROR (SANSEC_CARD_BASE + 0x00000017) +#define SANSEC_CARD_FILE_NOT_EXIST (SANSEC_CARD_BASE + 0x00000018) +#define SANSEC_CARD_FILE_OFFSET_ERROR (SANSEC_CARD_BASE + 0x00000019) +#define SANSEC_CARD_KEY_TYPE_ERROR (SANSEC_CARD_BASE + 0x00000020) +#define SANSEC_CARD_KEY_ERROR (SANSEC_CARD_BASE + 0x00000021) +#define SANSEC_CARD_BUFFER_TOO_SMALL (SANSEC_CARD_BASE + 0x00000101) +#define SANSEC_CARD_DATA_PADDING_ERROR (SANSEC_CARD_BASE + 0x00000102) +#define SANSEC_CARD_DATA_SIZE (SANSEC_CARD_BASE + 0x00000103) +#define SANSEC_CARD_CRYPTO_NOT_INITED (SANSEC_CARD_BASE + 0x00000104) +#define SANSEC_CARD_MANAGEMENT_DENYED (SANSEC_CARD_BASE + 0x00001001) +#define SANSEC_CARD_OPERATION_DENYED (SANSEC_CARD_BASE + 0x00001002) +#define SANSEC_CARD_DEVICE_STATUS_ERROR (SANSEC_CARD_BASE + 0x00001003) +#define SANSEC_CARD_LOGIN_ERROR (SANSEC_CARD_BASE + 0x00001011) +#define SANSEC_CARD_USERID_ERROR (SANSEC_CARD_BASE + 0x00001012) +#define SANSEC_CARD_PARAMENT_ERROR (SANSEC_CARD_BASE + 0x00001013) +#define SANSEC_CARD_MANAGEMENT_DENYED_05 (SANSEC_CARD_BASE + 0x00000801) +#define SANSEC_CARD_OPERATION_DENYED_05 (SANSEC_CARD_BASE + 0x00000802) +#define SANSEC_CARD_DEVICE_STATUS_ERROR_05 (SANSEC_CARD_BASE + 0x00000803) +#define SANSEC_CARD_LOGIN_ERROR_05 (SANSEC_CARD_BASE + 0x00000811) +#define SANSEC_CARD_USERID_ERROR_05 (SANSEC_CARD_BASE + 0x00000812) +#define SANSEC_CARD_PARAMENT_ERROR_05 (SANSEC_CARD_BASE + 0x00000813) +#define SANSEC_CARD_READER_BASE (SDR_BASE + 0x00030000) +#define SANSEC_CARD_READER_PIN_ERROR (SANSEC_CARD_READER_BASE + 0x000063CE) +#define SANSEC_CARD_READER_NO_CARD (SANSEC_CARD_READER_BASE + 0x0000FF01) +#define SANSEC_CARD_READER_CARD_INSERT (SANSEC_CARD_READER_BASE + 0x0000FF02) +#define SANSEC_CARD_READER_CARD_INSERT_TYPE (SANSEC_CARD_READER_BASE + 0x0000FF03) + +#pragma pack(1) +typedef struct { + unsigned int clength; + unsigned char x[ECCref_MAX_LEN]; + unsigned char y[ECCref_MAX_LEN]; + unsigned char C[136]; + unsigned char M[ECCref_MAX_LEN]; +} SANSEC_ECCCipher; +#pragma pack() + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/src/sgd.h b/Core/GmSSL-3.1.1/src/sgd.h new file mode 100644 index 0000000..a602fe8 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sgd.h @@ -0,0 +1,372 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/* + * this header file is based on the standard GM/T 0006-2012 + * Cryptographic Application Identifier Criterion Specification + */ + +#ifndef SDFUTIL_SGD_H +#define SDFUTIL_SGD_H + + +#include + + +/* block cipher modes */ +#define SGD_ECB 0x01 +#define SGD_CBC 0x02 +#define SGD_CFB 0x04 +#define SGD_OFB 0x08 +#define SGD_MAC 0x10 + +/* stream cipher modes */ +#define SGD_EEA3 0x01 +#define SGD_EIA3 0x02 + +/* ciphers */ +#define SGD_SM1 0x00000100 +#define SGD_SSF33 0x00000200 +#define SGD_SM4 0x00000400 +#define SGD_ZUC 0x00000800 + +/* ciphers with modes */ +#define SGD_SM1_ECB (SGD_SM1|SGD_ECB) +#define SGD_SM1_CBC (SGD_SM1|SGD_CBC) +#define SGD_SM1_CFB (SGD_SM1|SGD_CFB) +#define SGD_SM1_OFB (SGD_SM1|SGD_OFB) +#define SGD_SM1_MAC (SGD_SM1|SGD_MAC) +#define SGD_SSF33_ECB (SGD_SSF33|SGD_ECB) +#define SGD_SSF33_CBC (SGD_SSF33|SGD_CBC) +#define SGD_SSF33_CFB (SGD_SSF33|SGD_CFB) +#define SGD_SSF33_OFB (SGD_SSF33|SGD_OFB) +#define SGD_SSF33_MAC (SGD_SSF33|SGD_MAC) +#define SGD_SM4_ECB (SGD_SM4|SGD_ECB) +#define SGD_SM4_CBC (SGD_SM4|SGD_CBC) +#define SGD_SM4_CFB (SGD_SM4|SGD_CFB) +#define SGD_SM4_OFB (SGD_SM4|SGD_OFB) +#define SGD_SM4_MAC (SGD_SM4|SGD_MAC) +#define SGD_ZUC_EEA3 (SGD_ZUC|SGD_EEA3) +#define SGD_ZUC_EIA3 (SGD_ZUC|SGD_EIA3) + +/* public key usage */ +#define SGD_PK_SIGN 0x0100 // FIXME: correct? +#define SGD_PK_DH 0x0200 // FIXME: correct? +#define SGD_PK_ENC 0x0400 // FIXME: correct? + +/* public key types */ +#define SGD_RSA 0x00010000 +#define SGD_RSA_SIGN (SGD_RSA|SGD_PK_SIGN) // FIXME: correct? +#define SGD_RSA_ENC (SGD_RSA|SGD_PK_ENC) // FIXME: correct? +#define SGD_SM2 0x00020100 +#define SGD_SM2_1 0x00020200 +#define SGD_SM2_2 0x00020400 +#define SGD_SM2_3 0x00020800 + +/* hash */ +#define SGD_SM3 0x00000001 +#define SGD_SHA1 0x00000002 +#define SGD_SHA256 0x00000004 +#define SGD_HASH_FROM 0x00000008 +#define SGD_HASH_TO 0x000000FF + +/* signatue schemes */ +#define SGD_SM3_RSA (SGD_SM3|SGD_RSA) +#define SGD_SHA1_RSA (SGD_SHA1|SGD_RSA) +#define SGD_SHA256_RSA (SGD_SHA256|SGD_RSA) +#define SGD_SM3_SM2 (SGD_SM3|SGD_SM2) +#define SGD_SIG_FROM 0x00040000 +#define SGD_SIG_TO 0x800000FF + +/* data types */ +typedef char SGD_CHAR; +typedef char SGD_INT8; +typedef int16_t SGD_INT16; +typedef int32_t SGD_INT32; +typedef int64_t SGD_INT64; +typedef unsigned char SGD_UCHAR; +typedef uint8_t SGD_UINT8; +typedef uint16_t SGD_UINT16; +typedef uint32_t SGD_UINT32; +typedef uint64_t SGD_UINT64; +typedef uint32_t SGD_RV; +typedef void * SGD_OBJ; +typedef int32_t SGD_BOOL; + +#define SGD_TRUE 0x00000001 +#define SGD_FALSE 0x00000000 + +#define SGD_KEY_INDEX 0x00000101 +#define SGD_SECRET_KEY 0x00000102 +#define SGD_PUBLIC_KEY_SIGN 0x00000103 +#define SGD_PUBLIC_KEY_ENCRYPT 0x00000104 +#define SGD_PRIVATE_KEY_SIGN 0x00000105 +#define SGD_PRIVATE_KEY_ENCRYPT 0x00000106 +#define SGD_KEY_COMPONENT 0x00000107 +#define SGD_PASSWORD 0x00000108 +#define SGD_PUBLIC_KEY_CERT 0x00000109 +#define SGD_ATTRIBUTE_CERT 0x1000010A +#define SGD_SIGNATURE_DATA 0x10000111 +#define SGD_ENVELOPE_DATA 0x10000112 +#define SGD_RANDOM_DATA 0x10000113 +#define SGD_PLAIN_DATA 0x10000114 +#define SGD_CIPHER_DATA 0x10000115 +#define SGD_DIGEST_DATA 0x10000116 +#define SGD_USER_DATA 0x10000117 + +/* certificate */ +#define SGD_CERT_VERSION 0x00000001 +#define SGD_CERT_SERIAL 0x00000002 +#define SGD_CERT_ISSUER 0x00000005 +#define SGD_CERT_VALID_TIME 0x00000006 +#define SGD_CERT_SUBJECT 0x00000007 +#define SGD_CERT_DER_PUBLIC_KEY 0x00000008 +#define SGD_CERT_DER_EXTENSIONS 0x00000009 +#define SGD_EXT_AUTHORITYKEYIDENTIFIER_INFO 0x00000011 +#define SGD_EXT_SUBJECTKEYIDENTIFIER_INFO 0x00000012 +#define SGD_EXT_KEYUSAGE_INFO 0x00000013 +#define SGD_EXT_PRIVATEKEYUSAGEPERIOD_INFO 0x00000014 +#define SGD_EXT_CERTIFICATEPOLICIES_INFO 0x00000015 +#define SGD_EXT_POLICYMAPPINGS_INFO 0x00000016 +#define SGD_EXT_BASICCONSTRAINTS_INFO 0x00000017 +#define SGD_EXT_POLICYCONSTRAINTS_INFO 0x00000018 +#define SGD_EXT_EXTKEYUSAGE_INFO 0x00000019 +#define SGD_EXT_CRLDISTRIBUTIONPOINTS_INFO 0x0000001A +#define SGD_EXT_NETSCAPE_CERT_TYPE_INFO 0x0000001B +#define SGD_EXT_SELFDEFINED_EXTENSION_INFO 0x0000001C +#define SGD_CERT_ISSUER_CN 0x00000021 +#define SGD_CERT_ISSUER_O 0x00000022 +#define SGD_CERT_ISSUER_OU 0x00000023 +#define SGD_CERT_SUBJECT_CN 0x00000031 +#define SGD_CERT_SUBJECT_O 0x00000032 +#define SGD_CERT_SUBJECT_OU 0x00000033 +#define SGD_CERT_SUBJECT_EMAIL 0x00000034 +#define SGD_CERT_NOTBEFORE_TIME 0x00000035 +#define SGD_CERT_NOTAFTER_TIME 0x00000036 + +/* timestamp info */ +#define SGD_TIME_OF_STAMP 0x00000201 +#define SGD_CN_OF_TSSIGNER 0x00000202 /* Common Name of TS Signer */ +#define SGD_ORININAL_DATA 0x00000203 +#define SGD_CERT_OF_TSSSERVER 0x00000204 +#define SGD_GERTCHAIN_OF_TSSERVER 0x00000205 +#define SGD_SOURCE_OF_TIME 0x00000206 +#define SGD_TIME_PRECISION 0x00000207 +#define SGD_RESPONSE_TYPE 0x00000208 +#define SGD_SUBJECT_COUNTRY_OF_TSSIGNER 0x00000209 +#define SGD_SUBJECT_ORGNIZATION_OF_TSSIGNER 0x0000020A +#define SGD_SUJECT_CITY_OF_TSSIGNER 0x0000020B +#define SGD_SUBJECT_EMAIL_OF_TSSIGNER 0x0000020C + +/* single sign-on */ +#define SGD_SP_ID 0x00000001 +#define SGD_SP_USER_ID 0x00000002 +#define SGD_IDP_ID 0x00000003 +#define SGD_IDP_USER_ID 0x00000004 + +/* data encoding */ +#define SGD_ENCODING_RAW 0x00000000 +#define SGD_ENCODING_DER 0x01000000 +#define SGD_ENCODING_BASE64 0x02000000 +#define SGD_ENCODING_PEM 0x03000000 +#define SGD_ENCODING_TXT 0x04000000 + +/* APIs */ +#define SGD_PROTOCOL_CSP 1 /* Microsoft CryptoAPI */ +#define SGD_PROTOCOL_PKCS11 2 /* PKCS#11 */ +#define SGD_PROTOCOL_SDS 3 /* SDF API */ +#define SGD_PROTOCOL_UKEY 4 /* SKF API */ +#define SGD_PROTOCOL_CNG 5 /* Microsoft CryptoAPI Next Gen */ +#define SGD_PROTOCOL_GCS 6 /* */ + +/* certificate validation */ +#define SGD_CRL_VERIFY 1 +#define SGD_OCSP_VEIFY 2 + +/* role */ +#define SGD_ROLE_SUPER_MANAGER 0x00000001 +#define SGD_ROLE_MANAGER 0x00000002 +#define SGD_ROLE_AUDIT_MANAGER 0x00000003 +#define SGD_ROLE_AUDITOR 0x00000004 +#define SGD_ROLE_OPERATOR 0x00000005 +#define SGD_ROLE_USER 0x00000006 + +/* user operations */ +#define SGD_OPERATION_SIGNIN 0x00000001 +#define SGD_OPERATION_SIGNOUT 0x00000002 +#define SGD_OPERATION_CREATE 0x00000003 +#define SGD_OPERATION_DELETE 0x00000004 +#define SGD_OPERATION_MODIFY 0x00000005 +#define SGD_OPERATION_CHG_PWD 0x00000006 +#define SGD_OPERATION_AUTHORIZATION 0x00000007 + +/* user operation results */ +#define SGD_OPERATION_SUCCESS 0x00000000 + +/* key types */ +#define SGD_MAIN_KEY 0x00000101 +#define SGD_DEVICE_KEYS 0x00000102 +#define SGD_USER_KEYS 0x00000103 +#define SGD_KEY 0x00000104 +#define SGD_SESSION_KEY 0x00000105 +#define SGD_PRIKEY_PASSWD 0x00000106 +#define SGD_COMPARTITION_KEY 0x00000107 + +/* key operations */ +#define SGD_KEY_GENERATION 0x00000101 +#define SGD_KEY_DISPENSE 0x00000102 +#define SGD_KEY_IMPORT 0x00000103 +#define SGD_KEY_EXPORT 0x00000104 +#define SGD_KEY_DIVISION 0x00000105 +#define SGD_KEY_COMPOSE 0x00000106 +#define SGD_KEY_RENEWAL 0x00000107 +#define SGD_KEY_BACKUP 0x00000108 +#define SGD_KEY_RESTORE 0x00000109 +#define SGD_KEY_DESTORY 0x0000010A + +/* system operations */ +#define SGD_SYSTEM_INIT 0x00000201 +#define SGD_SYSTEM_START 0x00000202 +#define SGD_SYSTEM_SHUT 0x00000203 +#define SGD_SYSTEM_RESTART 0x00000204 +#define SGD_SYSTEM_QUERY 0x00000205 +#define SGD_SYSTEM_BACKUP 0x00000206 +#define SGD_SYSTEM_RESTORE 0x00000207 + +/* device info */ +#define SGD_DEVICE_SORT 0x00000201 +#define SGD_DEVICE_TYPE 0x00000202 +#define SGD_DEVICE_NAME 0x00000203 +#define SGD_DEVICE_MANUFACTURER 0x00000204 +#define SGD_DEVICE_HARDWARE_VERSION 0x00000205 +#define SGD_DEVICE_SOFTWARE_VERSION 0x00000206 +#define SGD_DEVICE_STANDARD_VERSION 0x00000207 +#define SGD_DEVICE_SERIAL_NUMBER 0x00000208 +#define SGD_DEVICE_SUPPORT_SYMM_ALG 0x00000209 +#define SGD_DEVICE_SUPPORT_PKEY_ALG 0x0000020A +#define SGD_DEVICE_SUPPORT_HASH_ALG 0x0000020B +#define SGD_DEVICE_SUPPORT_STORAGE_SPACE 0x0000020C +#define SGD_DEVICE_SUPPORT_FREE_SPACE 0x0000020D +#define SGD_DEVICE_RUNTIME 0x0000020E +#define SGD_DEVICE_USED_TIMES 0x0000020F +#define SGD_DEVICE_LOCATION 0x00000210 +#define SGD_DEVICE_DESCRIPTION 0x00000211 +#define SGD_DEVICE_MANAGER_INFO 0x00000212 +#define SGD_DEVICE_MAX_DATA_SIZE 0x00000213 + +/* device types */ +#define SGD_DEVICE_SORT_SJ 0x02000000 /* Server */ +#define SGD_DEVICE_SORT_SK 0x03000000 /* PCI-E Card */ +#define SGD_DEVICE_SORT_SM 0x04000000 /* USB-Key and SmartCard */ + +/* device functionality */ +#define SGD_DEVICE_SORT_FE 0x00000100 /* encryption */ +#define SGD_DEVICE_SORT_FA 0x00000200 /* authentication */ +#define SGD_DEVICE_SORT_FM 0x00000300 /* key management */ + +/* device status */ +#define SGD_STATUS_INIT 0x00000201 +#define SGD_STATUS_READY 0x00000202 +#define SGD_STATUS_EXCEPTION 0x00000203 + +#ifdef WIN32 +#include +#else +typedef signed char INT8; +typedef signed short INT16; +typedef signed int INT32; +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef long BOOL; +typedef UINT8 BYTE; +typedef UINT8 CHAR; +typedef INT16 SHORT; +typedef UINT16 USHORT; +# ifndef SGD_NATIVE_LONG +typedef INT32 LONG; +typedef UINT32 ULONG; +# else +typedef long LONG; +typedef unsigned long ULONG; +# endif +typedef UINT32 UINT; +typedef UINT16 WORD; +typedef UINT32 DWORD; +typedef UINT32 FLAGS; +typedef CHAR * LPSTR; +typedef void * HANDLE; +#endif + + +typedef HANDLE DEVHANDLE; +typedef HANDLE HAPPLICATION; +typedef HANDLE HSESSION; +typedef HANDLE HCONTAINER; + +#ifndef FALSE +#define FALSE 0x00000000 +#endif + +#ifndef TRUE +#define TRUE 0x00000001 +#endif + +#ifdef WIN32 +#define DEVAPI __stdcall +#else +#define DEVAPI +#endif + +#ifndef ADMIN_TYPE +#define ADMIN_TYPE 0 +#endif + +#ifndef USER_TYPE +#define USER_TYPE 1 +#endif + +#define MAX_RSA_MODULUS_LEN 256 +#define MAX_RSA_EXPONENT_LEN 4 +#define ECC_MAX_XCOORDINATE_BITS_LEN 512 +#define ECC_MAX_YCOORDINATE_BITS_LEN 512 +#define ECC_MAX_MODULUS_BITS_LEN 512 + +#define MAX_IV_LEN 32 + +#define MAX_FILE_NAME_SIZE 32 +#define MAX_FILE_CONTAINER_NAME_SIZE 64 + +#define SECURE_NEVER_ACCOUNT 0x00000000 +#define SECURE_ADM_ACCOUNT 0x00000001 +#define SECURE_USER_ACCOUNT 0x00000010 +#define SECURE_ANYONE_ACCOUNT 0x000000FF + + +/* SDF */ + +#define RSAref_MAX_BITS 2048 +#define RSAref_MAX_LEN ((RSAref_MAX_BITS + 7) / 8) +#define RSAref_MAX_PBITS ((RSAref_MAX_BITS + 1) / 2) +#define RSAref_MAX_PLEN ((RSAref_MAX_PBITS + 7)/ 8) + +#ifdef SGD_MAX_ECC_BITS_256 +#define ECCref_MAX_BITS 256 +#else +#define ECCref_MAX_BITS 512 +#endif +#define ECCref_MAX_LEN ((ECCref_MAX_BITS+7) / 8) + + +/* SAF */ +#define SGD_MAX_COUNT 64 +#define SGD_MAX_NAME_SIZE 256 + + +#endif diff --git a/Core/GmSSL-3.1.1/src/sha1.c b/Core/GmSSL-3.1.1/src/sha1.c new file mode 100644 index 0000000..7154f0b --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sha1.c @@ -0,0 +1,171 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include + + +#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_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; + + ctx->num &= 0x3f; + if (ctx->num) { + size_t 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; + if (blocks) { + 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->num &= 0x3f; + ctx->block[ctx->num] = 0x80; + + if (ctx->num <= SHA1_BLOCK_SIZE - 9) { + 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]); + } +} + +void sha1_digest(const unsigned char *data, size_t datalen, + unsigned char dgst[SHA1_DIGEST_SIZE]) +{ + SHA1_CTX ctx; + sha1_init(&ctx); + sha1_update(&ctx, data, datalen); + sha1_finish(&ctx, dgst); + memset(&ctx, 0, sizeof(ctx)); +} diff --git a/Core/GmSSL-3.1.1/src/sha256.c b/Core/GmSSL-3.1.1/src/sha256.c new file mode 100644 index 0000000..fa8f3bd --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sha256.c @@ -0,0 +1,217 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include + + +#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_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; + + ctx->num &= 0x3f; + if (ctx->num) { + size_t 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; + if (blocks) { + 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->num &= 0x3f; + ctx->block[ctx->num] = 0x80; + + if (ctx->num <= SHA256_BLOCK_SIZE - 9) { + 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); + } +} + +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); + memset(&ctx, 0, sizeof(ctx)); +} + + +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]) +{ + uint8_t buf[SHA256_DIGEST_SIZE]; + sha256_finish((SHA256_CTX *)ctx, buf); + memcpy(dgst, buf, SHA224_DIGEST_SIZE); + memset(buf, 0, sizeof(buf)); +} + +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); + memset(&ctx, 0, sizeof(ctx)); +} diff --git a/Core/GmSSL-3.1.1/src/sha512.c b/Core/GmSSL-3.1.1/src/sha512.c new file mode 100644 index 0000000..8f38f4b --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sha512.c @@ -0,0 +1,234 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +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) { + size_t 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; + if (blocks) { + 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); + } +} + +#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); + memset(&ctx, 0, sizeof(ctx)); +} + + +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); + memset(&ctx, 0, sizeof(ctx)); +} + diff --git a/Core/GmSSL-3.1.1/src/skf/skf.c b/Core/GmSSL-3.1.1/src/skf/skf.c new file mode 100755 index 0000000..08fed46 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf.c @@ -0,0 +1,781 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include "../sgd.h" +#include "skf.h" +#include "skf_ext.h" +#include "skf_int.h" + + +int skf_load_library(const char *so_path, const char *vendor) +{ + if (SKF_LoadLibrary((LPSTR)so_path, (LPSTR)vendor) != SAR_OK) { + error_print(); + return -1; + } + return 1; +} + +void skf_unload_library(void) +{ + SKF_UnloadLibrary(); +} + + +static int skf_open_app(SKF_DEVICE *dev, const char *appname, const char *pin, HAPPLICATION *phApp) +{ + int ret = 0; + HAPPLICATION hApp = NULL; + ULONG ulPINType = USER_TYPE; + ULONG numRetry; + + if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK) { + error_print(); + return -1; + } + if (SKF_VerifyPIN(hApp, ulPINType, (CHAR *)pin, &numRetry) != SAR_OK) { + fprintf(stderr, "Invalid user PIN, retry count = %u\n", numRetry); + error_print(); + goto end; + } + *phApp = hApp; + hApp = NULL; + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +static const uint8_t zeros[ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32] = {0}; + +static int SKF_ECCPUBLICKEYBLOB_to_SM2_KEY(const ECCPUBLICKEYBLOB *blob, SM2_KEY *sm2_key) +{ + SM2_POINT point; + + if (blob->BitLen != 256) { + error_print(); + return -1; + } + if (memcmp(blob->XCoordinate, zeros, sizeof(zeros)) != 0 + || memcmp(blob->YCoordinate, zeros, sizeof(zeros)) != 0) { + error_print(); + return -1; + } + if (sm2_point_from_xy(&point, + blob->XCoordinate + ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32, + blob->YCoordinate + ECC_MAX_YCOORDINATE_BITS_LEN/8 - 32) != 1 + || sm2_key_set_public_key(sm2_key, &point) != 1) { + error_print(); + return -1; + } + return SAR_OK; +} + +static int SKF_ECCSIGNATUREBLOB_to_SM2_SIGNATURE(const ECCSIGNATUREBLOB *blob, SM2_SIGNATURE *sig) +{ + if (memcmp(blob->r, zeros, sizeof(zeros)) != 0 + || memcmp(blob->s, zeros, sizeof(zeros)) != 0) { + error_print(); + return -1; + } + memset(sig, 0, sizeof(SM2_SIGNATURE)); + memcpy(sig->r, blob->r + ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32, 32); + memcpy(sig->s, blob->s + ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32, 32); + return SAR_OK; +} + +int skf_rand_bytes(SKF_DEVICE *dev, uint8_t *buf, size_t len) +{ + if (SKF_GenRandom(dev->handle, buf, (ULONG)len) != SAR_OK) { + error_print(); + return -1; + } + return 1; +} + +int skf_load_sign_key(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name, SKF_KEY *key) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + HCONTAINER hContainer = NULL; + ULONG containerType = 0; + BOOL bSign = SGD_TRUE; + ECCPUBLICKEYBLOB publicKeyBlob; + ULONG ulBlobLen = sizeof(ECCPUBLICKEYBLOB); + SM2_KEY public_key; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_OpenContainer(hApp, (LPSTR)container_name, &hContainer) != SAR_OK + || SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { + error_print(); + goto end; + } + if (containerType != SKF_CONTAINER_TYPE_ECC) { + error_print(); + goto end; + } + if (SKF_ExportPublicKey(hContainer, bSign, (BYTE *)&publicKeyBlob, &ulBlobLen) != SAR_OK) { + error_print(); + goto end; + } + if (ulBlobLen != sizeof(ECCPUBLICKEYBLOB)) { + error_print(); + goto end; + } + if (SKF_ECCPUBLICKEYBLOB_to_SM2_KEY(&publicKeyBlob, &public_key) != SAR_OK) { + error_print(); + goto end; + } + memset(key, 0, sizeof(SKF_KEY)); + key->public_key = public_key; + key->app_handle = hApp; + hApp = NULL; + strncpy(key->app_name, appname, 64); + key->container_handle = hContainer; + hContainer = NULL; + strncpy(key->container_name, container_name, 64); + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + if (hContainer) SKF_CloseContainer(hContainer); + return ret; +} + +int skf_sign(SKF_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen) +{ + ECCSIGNATUREBLOB sigBlob; + SM2_SIGNATURE sm2_sig; + + if (SKF_ECCSignData(key->container_handle, (BYTE *)dgst, 32, &sigBlob) != SAR_OK) { + error_print(); + return -1; + } + if (SKF_ECCSIGNATUREBLOB_to_SM2_SIGNATURE(&sigBlob, &sm2_sig) != SAR_OK) { + error_print(); + return -1; + } + *siglen = 0; + if (sm2_signature_to_der(&sm2_sig, &sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int skf_release_key(SKF_KEY *key) +{ + if (key->app_handle) { + if (SKF_ClearSecureState(key->app_handle) != SAR_OK + || SKF_CloseApplication(key->app_handle) != SAR_OK) { + error_print(); + return -1; + } + key->app_handle = NULL; + } + if (key->container_handle) { + if (SKF_CloseContainer(key->container_handle) != SAR_OK) { + error_print(); + return -1; + } + } + memset(key, 0, sizeof(SKF_KEY)); + return 1; +} + +int skf_close_device(SKF_DEVICE *dev) +{ + if (SKF_UnlockDev(dev->handle) != SAR_OK + || SKF_DisConnectDev(dev->handle) != SAR_OK) { + error_print(); + return -1; + } + memset(dev, 0, sizeof(SKF_DEVICE)); + return 1; +} + + + + + + + +int skf_list_devices(FILE *fp, int fmt, int ind, const char *label) +{ + int ret = -1; + BOOL bPresent = TRUE; + char *nameList = NULL; + ULONG nameListLen = 0; + const char *name; + int i; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (SKF_EnumDev(bPresent, NULL, &nameListLen) != SAR_OK) { + error_print(); + return -1; + } + if (nameListLen == 0) { + return 0; + } + if (!(nameList = malloc(nameListLen))) { + error_print(); + return -1; + } + if (SKF_EnumDev(bPresent, (LPSTR)nameList, &nameListLen) != SAR_OK) { + error_print(); + goto end; + } + for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { + (void)format_print(fp, fmt, ind, "%s\n", name); + } + ret = 1; +end: + free(nameList); + return ret; +} + +int skf_print_device_info(FILE *fp, int fmt, int ind, const char *devname) +{ + int ret = 0; + DEVHANDLE hDev = NULL; + ULONG devState = 0; + LPSTR devStateName = NULL; + DEVINFO devInfo = {{0,0}}; + + format_print(fp, fmt, ind, "%s\n", devname); + ind += 4; + + if (SKF_GetDevState((LPSTR)devname, &devState) != SAR_OK + || SKF_GetDevStateName(devState, &devStateName) != SAR_OK + || SKF_ConnectDev((LPSTR)devname, &hDev) != SAR_OK + || SKF_GetDevInfo(hDev, &devInfo) != SAR_OK) { + error_print(); + goto end; + } + + (void)format_print(fp, fmt, ind, "DeviceState: %s\n", (char *)devStateName); + //(void)SKF_PrintDevInfo(fp, fmt, ind, "DeviceInfo", &devInfo); + ret = 1; +end: + if (hDev) SKF_DisConnectDev(hDev); + return ret; +} + +int skf_set_label(SKF_DEVICE *dev, const char *label) +{ + if (SKF_SetLabel(dev->handle, (LPSTR)label) != SAR_OK) { + error_print(); + return -1; + } + return 1; +} + +int skf_open_device(SKF_DEVICE *dev, const char *devname, const uint8_t authkey[16]) +{ + DEVHANDLE hDev = NULL; + DEVINFO devInfo = {{0,0}}; + ULONG ulTimeOut = 0xffffffff; + BYTE authRand[16] = {0}; + BYTE authData[16] = {0}; + ULONG authRandLen = SKF_AUTHRAND_LENGTH; + ULONG authDataLen = sizeof(authData); + BLOCKCIPHERPARAM encParam = {{0}, 0, 0, 0}; + + if (SKF_OpenDevice((LPSTR)devname, (BYTE *)authkey, &devInfo, &hDev) != SAR_OK + || SKF_LockDev(hDev, ulTimeOut) != SAR_OK) { + error_print(); + return -1; + } + memset(dev, 0, sizeof(SKF_DEVICE)); + dev->handle = hDev; + hDev = NULL; + + return 1; +} + +int skf_change_authkey(SKF_DEVICE *dev, const uint8_t authkey[16]) +{ + if (SKF_ChangeDevAuthKey(dev->handle, (BYTE *)authkey, 16) != SAR_OK) { + error_print(); + return -1; + } + return 1; +} + +int skf_list_apps(SKF_DEVICE *dev, int fmt, int ind, const char *label, FILE *fp) +{ + int ret = 0; + HAPPLICATION hApp = NULL; + char *nameList = NULL; + ULONG nameListLen = 0; + const char *name; + int i; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (SKF_EnumApplication(dev->handle, NULL, &nameListLen) != SAR_OK) { + error_print(); + return -1; + } + if (nameListLen <= 1) { + return 0; + } + if (!(nameList = malloc(nameListLen))) { + error_print(); + return -1; + } + if (SKF_EnumApplication(dev->handle, (LPSTR)nameList, &nameListLen) != SAR_OK) { + error_print(); + goto end; + } + for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { + ULONG adminMaxRetry; + ULONG adminMinRetry; + ULONG userMaxRetry; + ULONG userMinRetry; + BOOL adminDefaultPin; + BOOL userDefaultPin; + + if (SKF_OpenApplication(dev->handle, (LPSTR)name, &hApp) != SAR_OK + || SKF_GetPINInfo(hApp, ADMIN_TYPE, &adminMaxRetry, &adminMinRetry, &adminDefaultPin) != SAR_OK + || SKF_GetPINInfo(hApp, USER_TYPE, &userMaxRetry, &userMinRetry, &userDefaultPin) != SAR_OK + || SKF_CloseApplication(hApp) != SAR_OK) { + error_print(); + goto end; + } + hApp = NULL; + + (void)format_print(fp, fmt, ind, "Application %d:\n", i); + (void)format_print(fp, fmt, ind + 4, "ApplicationName", name); + (void)format_print(fp, fmt, ind + 4, "AdminPinMaxRetry: %s\n", adminMaxRetry); + (void)format_print(fp, fmt, ind + 4, "AdminPinMinRetry: %u\n", adminMinRetry); + (void)format_print(fp, fmt, ind + 4, "AdminDefaultPin: %s\n", adminDefaultPin ? "True" : "False"); + (void)format_print(fp, fmt, ind + 4, "UserPinMaxRetry: %u\n", userMaxRetry); + (void)format_print(fp, fmt, ind + 4, "UserPinMinRetry: %u\n", userMinRetry); + (void)format_print(fp, fmt, ind + 4, "UserDefaultPin: %s\n", userDefaultPin ? "True" : "False"); + } + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_create_app(SKF_DEVICE *dev, const char *appname, const char *admin_pin, const char *user_pin) +{ + int ret = 0; + HAPPLICATION hApp = NULL; + ULONG appRights = SECURE_ANYONE_ACCOUNT; + + if (SKF_CreateApplication(dev->handle, (LPSTR)appname, + (CHAR *)admin_pin, SKF_DEFAULT_ADMIN_PIN_RETRY_COUNT, + (CHAR *)user_pin, SKF_DEFAULT_USER_PIN_RETRY_COUNT, + appRights, &hApp) != SAR_OK) { + error_print(); + return -1; + } + if (SKF_CloseApplication(hApp) != SAR_OK) { + error_print(); + return -1; + } + return 1; +} + +int skf_delete_app(SKF_DEVICE *dev, const char *appname) +{ + if (SKF_DeleteApplication(dev->handle, (LPSTR)appname) != SAR_OK) { + error_print(); + return -1; + } + return 1; +} + +int skf_change_app_admin_pin(SKF_DEVICE *dev, const char *appname, const char *oid_pin, const char *new_pin) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + ULONG ulPINType = ADMIN_TYPE; + ULONG ulRetryCount = 0; + + if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK + || SKF_ChangePIN(hApp, ulPINType, (CHAR *)oid_pin, (CHAR *)new_pin, &ulRetryCount) != SAR_OK) { + fprintf(stderr, "Retry Count = %u\n", ulRetryCount); + error_print(); + goto end; + } + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_change_app_user_pin(SKF_DEVICE *dev, const char *appname, const char *oid_pin, const char *new_pin) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + ULONG ulPINType = USER_TYPE; + ULONG ulRetryCount = 0; + + if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK + || SKF_ChangePIN(hApp, ulPINType, (CHAR *)oid_pin, (CHAR *)new_pin, &ulRetryCount) != SAR_OK) { + fprintf(stderr, "Retry Count = %u\n", ulRetryCount); + goto end; + } + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_unblock_user_pin(SKF_DEVICE *dev, const char *appname, const char *admin_pin, const char *new_user_pin) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + ULONG ulRetryCount = 0; + + if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK + || SKF_UnblockPIN(hApp, (CHAR *)admin_pin, (CHAR *)new_user_pin, &ulRetryCount) != SAR_OK) { + fprintf(stderr, "Invalid admin PIN, retry count = %u\n", ulRetryCount); + error_print(); + goto end; + } + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_list_objects(FILE *fp, int fmt, int ind, const char *label, + SKF_DEVICE *dev, const char *appname, const char *pin) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + char *nameList = NULL; + ULONG nameListLen = 0; + const char *name; + int i; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_EnumFiles(hApp, NULL, &nameListLen) != SAR_OK) { + error_print(); + goto end; + } + if (nameListLen <= 1) { + ret = 0; + goto end; + } + if (!(nameList = malloc(nameListLen))) { + error_print(); + goto end; + } + if (SKF_EnumFiles(hApp, (LPSTR)nameList, &nameListLen) != SAR_OK) { + error_print(); + goto end; + } + for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { + FILEATTRIBUTE fileInfo; + + if (SKF_GetFileInfo(hApp, (LPSTR)name, &fileInfo) != SAR_OK) { + error_print(); + goto end; + } + format_print(fp, fmt, ind, "Object:\n"); + format_print(fp, fmt, ind + 4, "Name: %s\n", (char *)&(fileInfo.FileName)); + format_print(fp, fmt, ind + 4, "Size: %u\n", fileInfo.FileSize); + format_print(fp, fmt, ind + 4, "ReadRights: %08X\n", fileInfo.ReadRights); + format_print(fp, fmt, ind + 4, "WriteRights: %08X\n", fileInfo.WriteRights); + } + + ret = 1; + +end: + if (hApp) SKF_CloseApplication(hApp); + if (nameList) free(nameList); + return ret; +} + +int skf_import_object(SKF_DEVICE *dev, const char *appname, const char *pin, + const char *objname, const uint8_t *data, size_t datalen) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + ULONG ulReadRights = SECURE_ANYONE_ACCOUNT; + ULONG ulWriteRights = SECURE_USER_ACCOUNT; + + if (!dev || !appname || !pin || !objname || !data || !datalen) { + error_print(); + return -1; + } + if (datalen > SKF_MAX_FILE_SIZE) { + error_print(); + return -1; + } + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_CreateFile(hApp, (LPSTR)objname, (ULONG)datalen, ulReadRights, ulWriteRights) != SAR_OK + || SKF_WriteFile(hApp, (LPSTR)objname, 0, (BYTE *)data, (ULONG)datalen) != SAR_OK) { + error_print(); + goto end; + } + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_export_object(SKF_DEVICE *dev, const char *appname, const char *pin, + const char *objname, uint8_t *out, size_t *outlen) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + FILEATTRIBUTE fileInfo; + ULONG ulen; + + if (!dev || !appname || !pin || !objname || !outlen) { + error_print(); + return -1; + } + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_GetFileInfo(hApp, (LPSTR)objname, &fileInfo) != SAR_OK) { + error_print(); + goto end; + } + if (fileInfo.FileSize > SKF_MAX_FILE_SIZE) { + error_print(); + goto end; + } + if (!out) { + *outlen = (size_t)fileInfo.FileSize; + ret = 1; + goto end; + } + ulen = fileInfo.FileSize; + if (SKF_ReadFile(hApp, (LPSTR)objname, 0, fileInfo.FileSize, out, &ulen) != SAR_OK) { + goto end; + } + if (ulen != fileInfo.FileSize) { + error_print(); + goto end; + } + *outlen = ulen; + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_delete_object(SKF_DEVICE *dev, const char *appname, const char *pin, const char *objname) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_DeleteFile(hApp, (LPSTR)objname) != SAR_OK) { + error_print(); + goto end; + } + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_list_containers(FILE *fp, int fmt, int ind, const char *label, + SKF_DEVICE *dev, const char *appname, const char *pin) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + HCONTAINER hContainer = NULL; + char *nameList = NULL; + ULONG nameListLen = 0; + const char *name; + int i; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_EnumContainer(hApp, NULL, &nameListLen) != SAR_OK) { + error_print(); + goto end; + } + if (nameListLen <= 1) { + ret = 0; + goto end; + } + if (!(nameList = malloc(nameListLen))) { + error_print(); + goto end; + } + if (SKF_EnumContainer(hApp, (LPSTR)nameList, &nameListLen) != SAR_OK) { + error_print(); + goto end; + } + for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { + ULONG containerType; + LPSTR containerTypeName; + + if (SKF_OpenContainer(hApp, (LPSTR)name, &hContainer) != SAR_OK + || SKF_GetContainerType(hContainer, &containerType) != SAR_OK + || SKF_GetContainerTypeName(containerType, &containerTypeName) != SAR_OK + || SKF_CloseContainer(hContainer) != SAR_OK) { + error_print(); + goto end; + } + hContainer = NULL; + (void)format_print(fp, fmt, ind, "Container:\n"); + (void)format_print(fp, fmt, ind + 4, "Name: %s\n", name); + (void)format_print(fp, fmt, ind + 4, "Type: %s\n", (char *)containerTypeName); + } + ret = 1; + +end: + if (hContainer) SKF_CloseContainer(hContainer); + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_create_container(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + HCONTAINER hContainer = NULL; + ECCPUBLICKEYBLOB publicKey = {0, {0}, {0}}; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_CreateContainer(hApp, (LPSTR)container_name, &hContainer) != SAR_OK + || SKF_GenECCKeyPair(hContainer, SGD_SM2_1, &publicKey) != SAR_OK) { + error_print(); + goto end; + } + ret = 1; +end: + if (hContainer) SKF_CloseContainer(hContainer); + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_delete_container(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_DeleteContainer(hApp, (LPSTR)container_name) != SAR_OK) { + error_print(); + goto end; + } + ret = 1; +end: + if (hApp) SKF_CloseApplication(hApp); + return 1; +} + +int skf_import_sign_cert(SKF_DEVICE *dev, const char *appname, const char *pin, + const char *container_name, const uint8_t *cert, size_t certlen) +{ + int ret = 0; + HAPPLICATION hApp = NULL; + HCONTAINER hContainer = NULL; + ULONG containerType; + BOOL bSign = SGD_TRUE; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { + error_print(); + goto end; + } + if (containerType == SKF_CONTAINER_TYPE_UNDEF) { + error_print(); + goto end; + } + if (containerType != SKF_CONTAINER_TYPE_ECC) { + error_print(); + goto end; + } + // FIXME: 判断导入证书的类型是否为签名证书 + if (SKF_ImportCertificate(hContainer, bSign, (BYTE *)cert, (ULONG)certlen) != SAR_OK) { + error_print(); + goto end; + } + ret = 1; +end: + if (hContainer) SKF_CloseContainer(hContainer); + if (hApp) SKF_CloseApplication(hApp); + return ret; +} + +int skf_export_sign_cert(SKF_DEVICE *dev, const char *appname, const char *pin, + const char *container_name, uint8_t *cert, size_t *certlen) +{ + int ret = -1; + HAPPLICATION hApp = NULL; + HCONTAINER hContainer = NULL; + ULONG containerType; + BOOL bSign = SGD_TRUE; + ULONG ulCertLen = 0; + + if (skf_open_app(dev, appname, pin, &hApp) != 1) { + error_print(); + return -1; + } + if (SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { + error_print(); + goto end; + } + if (containerType != SKF_CONTAINER_TYPE_ECC) { + error_print(); + goto end; + } + if (SKF_ExportCertificate(hContainer, bSign, (BYTE *)cert, &ulCertLen) != SAR_OK) { + error_print(); + goto end; + } + ret = 1; +end: + if (hContainer) SKF_CloseContainer(hContainer); + if (hApp) SKF_CloseApplication(hApp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/skf/skf.h b/Core/GmSSL-3.1.1/src/skf/skf.h new file mode 100755 index 0000000..4be3524 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf.h @@ -0,0 +1,709 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/* This header file is from the official specification with minor + * modification. + */ + +#ifndef SKFUTIL_SKF_H +#define SKFUTIL_SKF_H + + +#include "../sgd.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(1) +typedef struct Struct_Version{ + BYTE major; + BYTE minor; +} VERSION; + +typedef struct Struct_DEVINFO { + VERSION Version; + CHAR Manufacturer[64]; + CHAR Issuer[64]; + CHAR Label[32]; + CHAR SerialNumber[32]; + VERSION HWVersion; + VERSION FirmwareVersion; + ULONG AlgSymCap; + ULONG AlgAsymCap; + ULONG AlgHashCap; + ULONG DevAuthAlgId; + ULONG TotalSpace; + ULONG FreeSpace; + ULONG MaxECCBufferSize; + ULONG MaxBufferSize; + BYTE Reserved[64]; +} DEVINFO, *PDEVINFO; + +typedef struct Struct_RSAPUBLICKEYBLOB { + ULONG AlgID; + ULONG BitLen; + BYTE Modulus[MAX_RSA_MODULUS_LEN]; + BYTE PublicExponent[MAX_RSA_EXPONENT_LEN]; +} RSAPUBLICKEYBLOB, *PRSAPUBLICKEYBLOB; + +typedef struct Struct_RSAPRIVATEKEYBLOB { + ULONG AlgID; + ULONG BitLen; + BYTE Modulus[MAX_RSA_MODULUS_LEN]; + BYTE PublicExponent[MAX_RSA_EXPONENT_LEN]; + BYTE PrivateExponent[MAX_RSA_MODULUS_LEN]; + BYTE Prime1[MAX_RSA_MODULUS_LEN/2]; + BYTE Prime2[MAX_RSA_MODULUS_LEN/2]; + BYTE Prime1Exponent[MAX_RSA_MODULUS_LEN/2]; + BYTE Prime2Exponent[MAX_RSA_MODULUS_LEN/2]; + BYTE Coefficient[MAX_RSA_MODULUS_LEN/2]; +} RSAPRIVATEKEYBLOB, *PRSAPRIVATEKEYBLOB; + +typedef struct Struct_ECCPUBLICKEYBLOB { + ULONG BitLen; + BYTE XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8]; + BYTE YCoordinate[ECC_MAX_YCOORDINATE_BITS_LEN/8]; +} ECCPUBLICKEYBLOB, *PECCPUBLICKEYBLOB; + +typedef struct Struct_ECCPRIVATEKEYBLOB { + ULONG BitLen; + BYTE PrivateKey[ECC_MAX_MODULUS_BITS_LEN/8]; +} ECCPRIVATEKEYBLOB, *PECCPRIVATEKEYBLOB; + +typedef struct Struct_ECCCIPHERBLOB { + BYTE XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8]; + BYTE YCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8]; + BYTE HASH[32]; + ULONG CipherLen; + BYTE Cipher[1]; +} ECCCIPHERBLOB, *PECCCIPHERBLOB; + +typedef struct Struct_ECCSIGNATUREBLOB { + BYTE r[ECC_MAX_XCOORDINATE_BITS_LEN/8]; + BYTE s[ECC_MAX_XCOORDINATE_BITS_LEN/8]; +} ECCSIGNATUREBLOB, *PECCSIGNATUREBLOB; + +typedef struct Struct_BLOCKCIPHERPARAM { + BYTE IV[MAX_IV_LEN]; + ULONG IVLen; + ULONG PaddingType; + ULONG FeedBitLen; +} BLOCKCIPHERPARAM, *PBLOCKCIPHERPARAM; + +typedef struct SKF_ENVELOPEDKEYBLOB { + ULONG Version; + ULONG ulSymmAlgID; + ULONG ulBits; + BYTE cbEncryptedPriKey[64]; + ECCPUBLICKEYBLOB PubKey; + ECCCIPHERBLOB ECCCipherBlob; +} ENVELOPEDKEYBLOB, *PENVELOPEDKEYBLOB; + +typedef struct Struct_FILEATTRIBUTE { + CHAR FileName[MAX_FILE_NAME_SIZE]; + ULONG FileSize; + ULONG ReadRights; + ULONG WriteRights; +} FILEATTRIBUTE, *PFILEATTRIBUTE; +#pragma pack() + +/* 7.1.2 */ +ULONG DEVAPI SKF_WaitForDevEvent( + LPSTR szDevName, + ULONG *pulDevNameLen, + ULONG *pulEvent); + +/* 7.1.3 */ +ULONG DEVAPI SKF_CancelWaitForDevEvent( + void); + +/* 7.1.4 */ +ULONG DEVAPI SKF_EnumDev( + BOOL bPresent, + LPSTR szNameList, + ULONG *pulSize); + +/* 7.1.5 */ +ULONG DEVAPI SKF_ConnectDev( + LPSTR szName, + DEVHANDLE *phDev); + +/* 7.1.6 */ +ULONG DEVAPI SKF_DisConnectDev( + DEVHANDLE hDev); + +/* 7.1.7 */ +ULONG DEVAPI SKF_GetDevState( + LPSTR szDevName, + ULONG *pulDevState); + +/* 7.1.8 */ +ULONG DEVAPI SKF_SetLabel( + DEVHANDLE hDev, + LPSTR szLabel); + +/* 7.1.9 */ +ULONG DEVAPI SKF_GetDevInfo( + DEVHANDLE hDev, + DEVINFO *pDevInfo); + +/* 7.1.10 */ +ULONG DEVAPI SKF_LockDev( + DEVHANDLE hDev, + ULONG ulTimeOut); + +/* 7.1.11 */ +ULONG DEVAPI SKF_UnlockDev( + DEVHANDLE hDev); + +/* 7.1.12 */ +ULONG DEVAPI SKF_Transmit( + DEVHANDLE hDev, + BYTE *pbCommand, + ULONG ulCommandLen, + BYTE *pbData, + ULONG *pulDataLen); + +/* 7.2.2 */ +ULONG DEVAPI SKF_ChangeDevAuthKey( + DEVHANDLE hDev, + BYTE *pbKeyValue, + ULONG ulKeyLen); + +/* 7.2.3 */ +ULONG DEVAPI SKF_DevAuth( + DEVHANDLE hDev, + BYTE *pbAuthData, + ULONG ulLen); + +/* 7.2.4 */ +ULONG DEVAPI SKF_ChangePIN( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szOldPin, + LPSTR szNewPin, + ULONG *pulRetryCount); + +/* 7.2.5 */ +LONG DEVAPI SKF_GetPINInfo( + HAPPLICATION hApplication, + ULONG ulPINType, + ULONG *pulMaxRetryCount, + ULONG *pulRemainRetryCount, + BOOL *pbDefaultPin); + +/* 7.2.6 */ +ULONG DEVAPI SKF_VerifyPIN( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szPIN, + ULONG *pulRetryCount); + +/* 7.2.7 */ +ULONG DEVAPI SKF_UnblockPIN( + HAPPLICATION hApplication, + LPSTR szAdminPIN, + LPSTR szNewUserPIN, + ULONG *pulRetryCount); + +/* 7.2.8 */ +ULONG DEVAPI SKF_ClearSecureState( + HAPPLICATION hApplication); + +/* 7.3.2 */ +ULONG DEVAPI SKF_CreateApplication( + DEVHANDLE hDev, + LPSTR szAppName, + LPSTR szAdminPin, + DWORD dwAdminPinRetryCount, + LPSTR szUserPin, + DWORD dwUserPinRetryCount, + DWORD dwCreateFileRights, + HAPPLICATION *phApplication); + +/* 7.3.3 */ +ULONG DEVAPI SKF_EnumApplication( + DEVHANDLE hDev, + LPSTR szAppName, + ULONG *pulSize); + +/* 7.3.4 */ +ULONG DEVAPI SKF_DeleteApplication( + DEVHANDLE hDev, + LPSTR szAppName); + +/* 7.3.5 */ +ULONG DEVAPI SKF_OpenApplication( + DEVHANDLE hDev, + LPSTR szAppName, + HAPPLICATION *phApplication); + +/* 7.3.6 */ +ULONG DEVAPI SKF_CloseApplication( + HAPPLICATION hApplication); + +/* 7.4.2 */ +ULONG DEVAPI SKF_CreateFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulFileSize, + ULONG ulReadRights, + ULONG ulWriteRights); + +/* 7.4.3 */ +ULONG DEVAPI SKF_DeleteFile( + HAPPLICATION hApplication, + LPSTR szFileName); + +/* 7.4.4 */ +ULONG DEVAPI SKF_EnumFiles( + HAPPLICATION hApplication, + LPSTR szFileList, + ULONG *pulSize); + +/* 7.4.5 */ +ULONG DEVAPI SKF_GetFileInfo( + HAPPLICATION hApplication, + LPSTR szFileName, + FILEATTRIBUTE *pFileInfo); + +/* 7.4.6 */ +ULONG DEVAPI SKF_ReadFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + ULONG ulSize, + BYTE *pbOutData, + ULONG *pulOutLen); + +/* 7.4.7 */ +ULONG DEVAPI SKF_WriteFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + BYTE *pbData, + ULONG ulSize); + +/* 7.5.2 */ +ULONG DEVAPI SKF_CreateContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer); + +/* 7.5.3 */ +ULONG DEVAPI SKF_DeleteContainer( + HAPPLICATION hApplication, + LPSTR szContainerName); + +/* 7.5.4 */ +ULONG DEVAPI SKF_OpenContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer); + +/* 7.5.5 */ +ULONG DEVAPI SKF_CloseContainer( + HCONTAINER hContainer); + +/* 7.5.6 */ +ULONG DEVAPI SKF_EnumContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + ULONG *pulSize); + +/* 7.5.7 */ +ULONG DEVAPI SKF_GetContainerType( + HCONTAINER hContainer, + ULONG *pulContainerType); + +/* 7.5.8 */ +ULONG DEVAPI SKF_ImportCertificate( + HCONTAINER hContainer, + BOOL bExportSignKey, + BYTE *pbCert, + ULONG ulCertLen); + +/* 7.5.9 */ +ULONG DEVAPI SKF_ExportCertificate( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbCert, + ULONG *pulCertLen); + +/* 7.6.2 */ +ULONG DEVAPI SKF_GenRandom( + DEVHANDLE hDev, + BYTE *pbRandom, + ULONG ulRandomLen); + +/* 7.6.3 */ +ULONG DEVAPI SKF_GenExtRSAKey( + DEVHANDLE hDev, + ULONG ulBitsLen, + RSAPRIVATEKEYBLOB *pBlob); + +/* 7.6.4 */ +ULONG DEVAPI SKF_GenRSAKeyPair( + HCONTAINER hContainer, + ULONG ulBitsLen, + RSAPUBLICKEYBLOB *pBlob); + +/* 7.6.5 */ +ULONG DEVAPI SKF_ImportRSAKeyPair( + HCONTAINER hContainer, + ULONG ulSymAlgId, + BYTE *pbWrappedKey, + ULONG ulWrappedKeyLen, + BYTE *pbEncryptedData, + ULONG ulEncryptedDataLen); + +/* 7.6.6 */ +ULONG DEVAPI SKF_RSASignData( + HCONTAINER hContainer, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG *pulSignLen); + +/* 7.6.7 */ +ULONG DEVAPI SKF_RSAVerify( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG ulSignLen); + +/* 7.6.8 */ +ULONG DEVAPI SKF_RSAExportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + RSAPUBLICKEYBLOB *pPubKey, + BYTE *pbData, + ULONG *pulDataLen, + HANDLE *phSessionKey); + +/* 7.6.9 */ +ULONG DEVAPI SKF_ExtRSAPubKeyOperation( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen); + +/* 7.6.10 */ +ULONG DEVAPI SKF_ExtRSAPriKeyOperation( + DEVHANDLE hDev, + RSAPRIVATEKEYBLOB *pRSAPriKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen); + +/* 7.6.11 */ +ULONG DEVAPI SKF_GenECCKeyPair( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pBlob); + +/* 7.6.12 */ +ULONG DEVAPI SKF_ImportECCKeyPair( + HCONTAINER hContainer, + ENVELOPEDKEYBLOB *pEnvelopedKeyBlob); + +/* 7.6.13 */ +ULONG DEVAPI SKF_ECCSignData( + HCONTAINER hContainer, + BYTE *pbDigest, + ULONG ulDigestLen, + ECCSIGNATUREBLOB *pSignature); + +#ifdef SKF_HAS_ECCDECRYPT +ULONG DEVAPI SKF_ECCDecrypt( + HCONTAINER hContainer, + ECCCIPHERBLOB *pCipherBlob, + BYTE *pbPlainText, + ULONG *pulPlainTextLen); +#endif + +/* 7.6.14 */ +ULONG DEVAPI SKF_ECCVerify( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature); + +/* 7.6.15 */ +ULONG DEVAPI SKF_ECCExportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pPubKey, + ECCCIPHERBLOB *pData, + HANDLE *phSessionKey); + +/* 7.6.16 */ +ULONG DEVAPI SKF_ExtECCEncrypt( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbPlainText, + ULONG ulPlainTextLen, + ECCCIPHERBLOB *pCipherText); + +/* 7.6.17 */ +ULONG DEVAPI SKF_ExtECCDecrypt( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + ECCCIPHERBLOB *pCipherText, + BYTE *pbPlainText, + ULONG *pulPlainTextLen); + +/* 7.6.18 */ +ULONG DEVAPI SKF_ExtECCSign( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature); + +/* 7.6.19 */ +ULONG DEVAPI SKF_ExtECCVerify( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature); + +/* 7.6.20 */ +ULONG DEVAPI SKF_GenerateAgreementDataWithECC( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phAgreementHandle); + +/* 7.6.21 */ +ULONG DEVAPI SKF_GenerateAgreementDataAndKeyWithECC( + HANDLE hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pSponsorECCPubKeyBlob, + ECCPUBLICKEYBLOB *pSponsorTempECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + BYTE *pbSponsorID, + ULONG ulSponsorIDLen, + HANDLE *phKeyHandle); + +/* 7.6.22 */ +ULONG DEVAPI SKF_GenerateKeyWithECC( + HANDLE hAgreementHandle, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phKeyHandle); + +/* 7.6.23 */ +ULONG DEVAPI SKF_ExportPublicKey( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbBlob, + ULONG *pulBlobLen); + +/* 7.6.24 */ +ULONG DEVAPI SKF_ImportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + BYTE *pbWrapedData, + ULONG ulWrapedLen, + HANDLE *phKey); + +/* 7.6.25 */ +ULONG DEVAPI SKF_SetSymmKey( + DEVHANDLE hDev, + BYTE *pbKey, + ULONG ulAlgID, + HANDLE *phKey); + +/* 7.6.26 */ +ULONG DEVAPI SKF_EncryptInit( + HANDLE hKey, + BLOCKCIPHERPARAM EncryptParam); + +/* 7.6.27 */ +ULONG DEVAPI SKF_Encrypt( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen); + +/* 7.6.28 */ +ULONG DEVAPI SKF_EncryptUpdate( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen); + +/* 7.6.29 */ +ULONG DEVAPI SKF_EncryptFinal( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG *pulEncryptedDataLen); + +/* 7.6.30 */ +ULONG DEVAPI SKF_DecryptInit( + HANDLE hKey, + BLOCKCIPHERPARAM DecryptParam); + +/* 7.6.31 */ +ULONG DEVAPI SKF_Decrypt( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen); + +/* 7.6.32 */ +ULONG DEVAPI SKF_DecryptUpdate( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen); + +/* 7.6.33 */ +ULONG DEVAPI SKF_DecryptFinal( + HANDLE hKey, + BYTE *pbDecryptedData, + ULONG *pulDecryptedDataLen); + +/* 7.6.34 */ +ULONG DEVAPI SKF_DigestInit( + DEVHANDLE hDev, + ULONG ulAlgID, + ECCPUBLICKEYBLOB *pPubKey, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phHash); + +/* 7.6.35 */ +ULONG DEVAPI SKF_Digest( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbHashData, + ULONG *pulHashLen); + +/* 7.6.36 */ +ULONG DEVAPI SKF_DigestUpdate( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen); + +/* 7.6.37 */ +ULONG DEVAPI SKF_DigestFinal( + HANDLE hHash, + BYTE *pHashData, + ULONG *pulHashLen); + +/* 7.6.38 */ +ULONG DEVAPI SKF_MacInit( + HANDLE hKey, + BLOCKCIPHERPARAM *pMacParam, + HANDLE *phMac); + +/* 7.6.39 */ +ULONG DEVAPI SKF_Mac( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbMacData, + ULONG *pulMacLen); + +/* 7.6.40 */ +ULONG DEVAPI SKF_MacUpdate( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen); + +/* 7.6.41 */ +ULONG DEVAPI SKF_MacFinal( + HANDLE hMac, + BYTE *pbMacData, + ULONG *pulMacDataLen); + +/* 7.6.42 */ +ULONG DEVAPI SKF_CloseHandle( + HANDLE hHandle); + + +#define SAR_OK 0x00000000 +#define SAR_FAIL 0x0A000001 +#define SAR_UNKNOWNERR 0x0A000002 +#define SAR_NOTSUPPORTYETERR 0x0A000003 +#define SAR_FILEERR 0x0A000004 +#define SAR_INVALIDHANDLEERR 0x0A000005 +#define SAR_INVALIDPARAMERR 0x0A000006 +#define SAR_READFILEERR 0x0A000007 +#define SAR_WRITEFILEERR 0x0A000008 +#define SAR_NAMELENERR 0x0A000009 +#define SAR_KEYUSAGEERR 0x0A00000A +#define SAR_MODULUSLENERR 0x0A00000B +#define SAR_NOTINITIALIZEERR 0x0A00000C +#define SAR_OBJERR 0x0A00000D +#define SAR_MEMORYERR 0x0A00000E +#define SAR_TIMEOUTERR 0x0A00000F +#define SAR_INDATALENERR 0x0A000010 +#define SAR_INDATAERR 0x0A000011 +#define SAR_GENRANDERR 0x0A000012 +#define SAR_HASHOBJERR 0x0A000013 +#define SAR_HASHERR 0x0A000014 +#define SAR_GENRSAKEYERR 0x0A000015 +#define SAR_RSAMODULUSLENERR 0x0A000016 +#define SAR_CSPIMPRTPUBKEYERR 0x0A000017 +#define SAR_RSAENCERR 0x0A000018 +#define SAR_RSADECERR 0x0A000019 +#define SAR_HASHNOTEQUALERR 0x0A00001A +#define SAR_KEYNOTFOUNTERR 0x0A00001B +#define SAR_CERTNOTFOUNTERR 0x0A00001C +#define SAR_NOTEXPORTERR 0x0A00001D +#define SAR_DECRYPTPADERR 0x0A00001E +#define SAR_MACLENERR 0x0A00001F +#define SAR_BUFFER_TOO_SMALL 0x0A000020 +#define SAR_KEYINFOTYPEERR 0x0A000021 +#define SAR_NOT_EVENTERR 0x0A000022 +#define SAR_DEVICE_REMOVED 0x0A000023 +#define SAR_PIN_INCORRECT 0x0A000024 +#define SAR_PIN_LOCKED 0x0A000025 +#define SAR_PIN_INVALID 0x0A000026 +#define SAR_PIN_LEN_RANGE 0x0A000027 +#define SAR_USER_ALREADY_LOGGED_IN 0x0A000028 +#define SAR_USER_PIN_NOT_INITIALIZED 0x0A000029 +#define SAR_USER_TYPE_INVALID 0x0A00002A +#define SAR_APPLICATION_NAME_INVALID 0x0A00002B +#define SAR_APPLICATION_EXISTS 0x0A00002C +#define SAR_USER_NOT_LOGGED_IN 0x0A00002D +#define SAR_APPLICATION_NOT_EXISTS 0x0A00002E +#define SAR_FILE_ALREADY_EXIST 0x0A00002F +#define SAR_NO_ROOM 0x0A000030 +#define SAR_FILE_NOT_EXIST 0x0A000031 +#define SAR_REACH_MAX_CONTAINER_COUNT 0x0A000032 + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/src/skf/skf_dummy.c b/Core/GmSSL-3.1.1/src/skf/skf_dummy.c new file mode 100755 index 0000000..d84b10f --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_dummy.c @@ -0,0 +1,907 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include "skf.h" +#include "skf_ext.h" + +static char *hDeviceHandle = "hDeviceHandle"; +static char *hApplication = "hApplication"; +static char *hContainer = "hContainer"; +static char *hAgreementHandle = "AgreementHandle"; +static char *hKeyHandle = "KeyHandle"; +static char *hHashHandle = "HashHandle"; +static char *hMacHandle = "MacHandle"; + +static char *sm2cert_pemstr = "-----BEGIN CERTIFICATE-----\n" +"MIICHDCCAcOgAwIBAgIBIzAKBggqgRzPVQGDdTBRMQswCQYDVQQGEwJDTjELMAkG\n" +"A1UECAwCQkoxCzAJBgNVBAcMAkJKMQwwCgYDVQQKDANQS1UxCzAJBgNVBAsMAkNT\n" +"MQ0wCwYDVQQDDARHTUNBMB4XDTE3MDYxODA4NDMyN1oXDTE4MDYxODA4NDMyN1ow\n" +"UzELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJKMQwwCgYDVQQKDANQS1UxDTALBgNV\n" +"BAsMBFNpZ24xGjAYBgNVBAMMEWNsaWVudEBwa3UuZWR1LmNuMFkwEwYHKoZIzj0C\n" +"AQYIKoEcz1UBgi0DQgAEzsZMPwnZFCD75xb8IT02XJCyOShTaEL8o/iQ6ksmG2Ce\n" +"MKSPGUcRtlSAU/1hQcFv4j59Csdr03lXiDRfdD72AKOBiTCBhjAJBgNVHRMEAjAA\n" +"MAsGA1UdDwQEAwIHgDAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg\n" +"Q2VydGlmaWNhdGUwHQYDVR0OBBYEFHbwURtb+xQrmxma7NnHe300//yuMB8GA1Ud\n" +"IwQYMBaAFMJhPpIHIHmrPQdEsiK3SaZ60qiPMAoGCCqBHM9VAYN1A0cAMEQCIBhO\n" +"uu7R3uMpVcy2r+t/OGYRs7JpQMnNwhGy9dwTm+h8AiA9y4o0fkRLQfuT3RPClX2o\n" +"B5vw09GcQVzsjKxhGgHLZw==\n" +"-----END CERTIFICATE-----\n"; + +static char *sm2key_pemstr = "-----BEGIN EC PRIVATE KEY-----\n" +"MHcCAQEEIAMbqE0bEEoGoicBgR0VISmbbuInWUBMQBtZBFVPD0+aoAoGCCqBHM9V\n" +"AYItoUQDQgAEzsZMPwnZFCD75xb8IT02XJCyOShTaEL8o/iQ6ksmG2CeMKSPGUcR\n" +"tlSAU/1hQcFv4j59Csdr03lXiDRfdD72AA==\n" +"-----END EC PRIVATE KEY-----\n"; + +#define devNameList "DummyDev1\0DummyDev2\0" +#define appNameList "App1\0App2\0" +#define fileNameList "File1\0File2\0" +#define containerNameList "Container1\0Container2\0" + + +ULONG DEVAPI SKF_WaitForDevEvent( + LPSTR szDevName, + ULONG *pulDevNameLen, + ULONG *pulEvent) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_CancelWaitForDevEvent( + void) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumDev(BOOL bPresent, + LPSTR szNameList, + ULONG *pulSize) +{ + if (!pulSize) + return SAR_INVALIDPARAMERR; + *pulSize = sizeof(devNameList); + if (szNameList) + memcpy(szNameList, devNameList, sizeof(devNameList)); + return SAR_OK; +} + +ULONG DEVAPI SKF_ConnectDev( + LPSTR szName, + DEVHANDLE *phDev) +{ + if (!phDev) + return SAR_INVALIDPARAMERR; + *phDev = hDeviceHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_DisConnectDev( + DEVHANDLE hDev) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_GetDevState( + LPSTR szDevName, + ULONG *pulDevState) +{ + if (!pulDevState) + return SAR_INVALIDPARAMERR; + *pulDevState = SKF_DEV_STATE_PRESENT; + return SAR_OK; +} + +ULONG DEVAPI SKF_SetLabel( + DEVHANDLE hDev, + LPSTR szLabel) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_GetDevInfo(DEVHANDLE hDev, + DEVINFO *pDevInfo) +{ + DEVINFO devInfo; + + if (!pDevInfo) { + return SAR_INVALIDPARAMERR; + } + + memset(&devInfo, 0, sizeof(devInfo)); + devInfo.Version.major = 1; + devInfo.Version.minor = 0; + strcpy((char *)&devInfo.Manufacturer, "GmSSL Project (http://gmssl.org)"); + strcpy((char *)&devInfo.Issuer, "GmSSL Project (http://gmssl.org)"); + strcpy((char *)&devInfo.Label, "SKF Dummy Token"); + strcpy((char *)&devInfo.SerialNumber, "1"); + devInfo.HWVersion.major = 1; + devInfo.HWVersion.minor = 0; + devInfo.FirmwareVersion.major = 1; + devInfo.FirmwareVersion.minor = 0; + devInfo.AlgSymCap = SGD_SM1|SGD_SSF33|SGD_SM4|SGD_ECB|SGD_CBC|SGD_CFB|SGD_OFB; + devInfo.AlgAsymCap = SGD_RSA|SGD_SM2|SGD_PK_SIGN|SGD_PK_ENC; + devInfo.AlgHashCap = SGD_SM3|SGD_SHA1|SGD_SHA256; + devInfo.DevAuthAlgId = SGD_SM4_ECB; + devInfo.TotalSpace = 64*1024; + devInfo.FreeSpace = 32*1024; + devInfo.MaxECCBufferSize = 100; + devInfo.MaxBufferSize = 128; + + memcpy(pDevInfo, &devInfo, sizeof(DEVINFO)); + return SAR_OK; +} + +ULONG DEVAPI SKF_LockDev( + DEVHANDLE hDev, + ULONG ulTimeOut) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_UnlockDev( + DEVHANDLE hDev) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_Transmit( + DEVHANDLE hDev, + BYTE *pbCommand, + ULONG ulCommandLen, + BYTE *pbData, + ULONG *pulDataLen) +{ + if (!pulDataLen) + return SAR_INVALIDPARAMERR; + *pulDataLen = ulCommandLen; + return SAR_OK; +} + +ULONG DEVAPI SKF_ChangeDevAuthKey( + DEVHANDLE hDev, + BYTE *pbKeyValue, + ULONG ulKeyLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_DevAuth( + DEVHANDLE hDev, + BYTE *pbAuthData, + ULONG ulLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_ChangePIN( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szOldPin, + LPSTR szNewPin, + ULONG *pulRetryCount) +{ + if (!pulRetryCount) + return SAR_INVALIDPARAMERR; + *pulRetryCount = 100; + return SAR_OK; +} + +LONG DEVAPI SKF_GetPINInfo( + HAPPLICATION hApplication, + ULONG ulPINType, + ULONG *pulMaxRetryCount, + ULONG *pulRemainRetryCount, + BOOL *pbDefaultPin) +{ + if (!pulMaxRetryCount || !pulRemainRetryCount || !pbDefaultPin) + return SAR_INVALIDPARAMERR; + *pulMaxRetryCount = 100; + *pulRemainRetryCount = 100; + *pbDefaultPin = TRUE; + return SAR_OK; +} + +ULONG DEVAPI SKF_VerifyPIN( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szPIN, + ULONG *pulRetryCount) +{ + if (!pulRetryCount) + return SAR_INVALIDPARAMERR; + *pulRetryCount = 100; + return SAR_OK; +} + +ULONG DEVAPI SKF_UnblockPIN( + HAPPLICATION hApplication, + LPSTR szAdminPIN, + LPSTR szNewUserPIN, + ULONG *pulRetryCount) +{ + if (!pulRetryCount) + return SAR_INVALIDPARAMERR; + *pulRetryCount = 100; + return SAR_OK; +} + +ULONG DEVAPI SKF_ClearSecureState( + HAPPLICATION hApplication) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_CreateApplication( + DEVHANDLE hDev, + LPSTR szAppName, + LPSTR szAdminPin, + DWORD dwAdminPinRetryCount, + LPSTR szUserPin, + DWORD dwUserPinRetryCount, + DWORD dwCreateFileRights, + HAPPLICATION *phApplication) +{ + if (!phApplication) + return SAR_INVALIDPARAMERR; + *phApplication = hApplication; + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumApplication(DEVHANDLE hDev, + LPSTR szAppName, + ULONG *pulSize) +{ + if (!pulSize) + return SAR_INVALIDPARAMERR; + *pulSize = sizeof(appNameList); + if (szAppName) + memcpy(szAppName, appNameList, sizeof(appNameList)); + return SAR_OK; +} + +ULONG DEVAPI SKF_DeleteApplication( + DEVHANDLE hDev, + LPSTR szAppName) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_OpenApplication( + DEVHANDLE hDev, + LPSTR szAppName, + HAPPLICATION *phApplication) +{ + if (!phApplication) + return SAR_INVALIDPARAMERR; + *phApplication = hApplication; + return SAR_OK; +} + +ULONG DEVAPI SKF_CloseApplication( + HAPPLICATION hApplication) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_CreateFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulFileSize, + ULONG ulReadRights, + ULONG ulWriteRights) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_DeleteFile( + HAPPLICATION hApplication, + LPSTR szFileName) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumFiles( + HAPPLICATION hApplication, + LPSTR szFileList, + ULONG *pulSize) +{ + if (!pulSize) + return SAR_INVALIDPARAMERR; + *pulSize = sizeof(fileNameList); + if (szFileList) + memcpy(szFileList, fileNameList, sizeof(fileNameList)); + return SAR_OK; +} + +ULONG DEVAPI SKF_GetFileInfo( + HAPPLICATION hApplication, + LPSTR szFileName, + FILEATTRIBUTE *pFileInfo) +{ + if (!pFileInfo) + return SAR_INVALIDPARAMERR; + strcpy((char *)pFileInfo->FileName, "FileName"); + pFileInfo->FileSize = 1024; + pFileInfo->ReadRights = SECURE_ANYONE_ACCOUNT; + return SAR_OK; +} + +ULONG DEVAPI SKF_ReadFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + ULONG ulSize, + BYTE *pbOutData, + ULONG *pulOutLen) +{ + if (!pbOutData || !pulOutLen) + return SAR_INVALIDPARAMERR; + memset(pbOutData, 'x', ulSize); + *pulOutLen = ulSize; + return SAR_OK; +} + +ULONG DEVAPI SKF_WriteFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + BYTE *pbData, + ULONG ulSize) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_CreateContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer) +{ + if (!phContainer) + return SAR_INVALIDPARAMERR; + *phContainer = hContainer; + return SAR_OK; +} + +ULONG DEVAPI SKF_DeleteContainer( + HAPPLICATION hApplication, + LPSTR szContainerName) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + ULONG *pulSize) +{ + if (!pulSize) + return SAR_INVALIDPARAMERR; + *pulSize = sizeof(containerNameList); + if (szContainerName) + memcpy(szContainerName, containerNameList, sizeof(containerNameList)); + return SAR_OK; +} + +ULONG DEVAPI SKF_OpenContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer) +{ + if (!phContainer) + return SAR_INVALIDPARAMERR; + *phContainer = hContainer; + return SAR_OK; +} + +ULONG DEVAPI SKF_CloseContainer( + HCONTAINER hContainer) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_GetContainerType( + HCONTAINER hContainer, + ULONG *pulContainerType) +{ + if (!pulContainerType) + return SAR_INVALIDPARAMERR; + *pulContainerType = SKF_CONTAINER_TYPE_ECC; + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportCertificate( + HCONTAINER hContainer, + BOOL bExportSignKey, + BYTE *pbCert, + ULONG ulCertLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportCertificate( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbCert, + ULONG *pulCertLen) +{ + *pulCertLen = (ULONG)strlen(sm2cert_pemstr); + memcpy(pbCert, sm2cert_pemstr, *pulCertLen); + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportPublicKey( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbBlob, + ULONG *pulBlobLen) +{ + if (!pulBlobLen) + return SAR_INVALIDPARAMERR; + *pulBlobLen = 2048/8; + return SAR_OK; +} + +ULONG DEVAPI SKF_GenRandom( + DEVHANDLE hDev, + BYTE *pbRandom, + ULONG ulRandomLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_GenExtRSAKey( + DEVHANDLE hDev, + ULONG ulBitsLen, + RSAPRIVATEKEYBLOB *pBlob) +{ + if (!pBlob) + return SAR_INVALIDPARAMERR; + return SAR_OK; +} + +ULONG DEVAPI SKF_GenRSAKeyPair( + HCONTAINER hContainer, + ULONG ulBitsLen, + RSAPUBLICKEYBLOB *pBlob) +{ + if (!pBlob) + return SAR_INVALIDPARAMERR; + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportRSAKeyPair( + HCONTAINER hContainer, + ULONG ulSymAlgId, + BYTE *pbWrappedKey, + ULONG ulWrappedKeyLen, + BYTE *pbEncryptedData, + ULONG ulEncryptedDataLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_RSASignData( + HCONTAINER hContainer, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG *pulSignLen) +{ + if (!pulSignLen) + return SAR_INVALIDPARAMERR; + *pulSignLen = 2048/8; + return SAR_OK; +} + +ULONG DEVAPI SKF_RSAVerify( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG ulSignLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_RSAExportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + RSAPUBLICKEYBLOB *pPubKey, + BYTE *pbData, + ULONG *pulDataLen, + HANDLE *phSessionKey) +{ + if (!pulDataLen || !phSessionKey) + return SAR_INVALIDPARAMERR; + *pulDataLen = 2048/8; + *phSessionKey = hKeyHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtRSAPubKeyOperation( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen) +{ + if (!pulOutputLen) + return SAR_INVALIDPARAMERR; + *pulOutputLen = 2048/8; + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtRSAPriKeyOperation( + DEVHANDLE hDev, + RSAPRIVATEKEYBLOB *pRSAPriKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen) +{ + if (!pulOutputLen) + return SAR_INVALIDPARAMERR; + *pulOutputLen = 2048/8; + return SAR_OK; +} + +ULONG DEVAPI SKF_GenECCKeyPair( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pBlob) +{ + if (!pBlob) + return SAR_INVALIDPARAMERR; + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportECCKeyPair( + HCONTAINER hContainer, + ENVELOPEDKEYBLOB *pEnvelopedKeyBlob) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_ECCSignData( + HCONTAINER hContainer, + BYTE *pbDigest, + ULONG ulDigestLen, + ECCSIGNATUREBLOB *pSignature) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_ECCVerify( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_ECCExportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pPubKey, + ECCCIPHERBLOB *pData, + HANDLE *phSessionKey) +{ + if (!phSessionKey) + return SAR_INVALIDPARAMERR; + *phSessionKey = hKeyHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCEncrypt( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbPlainText, + ULONG ulPlainTextLen, + ECCCIPHERBLOB *pCipherText) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCDecrypt( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + ECCCIPHERBLOB *pCipherText, + BYTE *pbPlainText, + ULONG *pulPlainTextLen) +{ + if (!pulPlainTextLen) + return SAR_INVALIDPARAMERR; + *pulPlainTextLen = 1; + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCSign( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature) +{ + if (!pSignature) + return SAR_INVALIDPARAMERR; + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCVerify( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_GenerateAgreementDataWithECC( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phAgreementHandle) +{ + if (!phAgreementHandle) + return SAR_INVALIDPARAMERR; + *phAgreementHandle = hAgreementHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_GenerateAgreementDataAndKeyWithECC( + HANDLE hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pSponsorECCPubKeyBlob, + ECCPUBLICKEYBLOB *pSponsorTempECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + BYTE *pbSponsorID, + ULONG ulSponsorIDLen, + HANDLE *phKeyHandle) +{ + if (!phKeyHandle) + return SAR_INVALIDPARAMERR; + *phKeyHandle = hKeyHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_GenerateKeyWithECC( + HANDLE hAgreementHandle, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phKeyHandle) +{ + if (!phKeyHandle) + return SAR_INVALIDPARAMERR; + *phKeyHandle = hKeyHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + BYTE *pbWrapedData, + ULONG ulWrapedLen, + HANDLE *phKey) +{ + if (!phKey) + return SAR_INVALIDPARAMERR; + *phKey = hKeyHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_SetSymmKey( + DEVHANDLE hDev, + BYTE *pbKey, + ULONG ulAlgID, + HANDLE *phKey) +{ + if (!phKey) + return SAR_INVALIDPARAMERR; + *phKey = hKeyHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_EncryptInit( + HANDLE hKey, + BLOCKCIPHERPARAM EncryptParam) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_Encrypt( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen) +{ + if (!pulEncryptedLen) + return SAR_INVALIDPARAMERR; + *pulEncryptedLen = ulDataLen; + return SAR_OK; +} + +ULONG DEVAPI SKF_EncryptUpdate( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen) +{ + if (!pulEncryptedLen) + return SAR_INVALIDPARAMERR; + *pulEncryptedLen = ulDataLen; + return SAR_OK; +} + +ULONG DEVAPI SKF_EncryptFinal( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG *pulEncryptedDataLen) +{ + if (!pulEncryptedDataLen) + return SAR_INVALIDPARAMERR; + *pulEncryptedDataLen = 0; + return SAR_OK; +} + +ULONG DEVAPI SKF_DecryptInit( + HANDLE hKey, + BLOCKCIPHERPARAM DecryptParam) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_Decrypt( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen) +{ + if (!pulDataLen) + return SAR_INVALIDPARAMERR; + *pulDataLen = ulEncryptedLen; + return SAR_OK; +} + +ULONG DEVAPI SKF_DecryptUpdate( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen) +{ + if (!pulDataLen) + return SAR_INVALIDPARAMERR; + *pulDataLen = ulEncryptedLen; + return SAR_OK; +} + +ULONG DEVAPI SKF_DecryptFinal( + HANDLE hKey, + BYTE *pbDecryptedData, + ULONG *pulDecryptedDataLen) +{ + if (!pulDecryptedDataLen) + return SAR_INVALIDPARAMERR; + *pulDecryptedDataLen = 0; + return SAR_OK; +} + +ULONG DEVAPI SKF_DigestInit( + DEVHANDLE hDev, + ULONG ulAlgID, + ECCPUBLICKEYBLOB *pPubKey, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phHash) +{ + if (!phHash) + return SAR_INVALIDPARAMERR; + *phHash = hHashHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_Digest( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbHashData, + ULONG *pulHashLen) +{ + if (!pulHashLen) + return SAR_INVALIDPARAMERR; + *pulHashLen = 32; + return SAR_OK; +} + +ULONG DEVAPI SKF_DigestUpdate( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_DigestFinal( + HANDLE hHash, + BYTE *pbHashData, + ULONG *pulHashLen) +{ + if (!pulHashLen) + return SAR_INVALIDPARAMERR; + *pulHashLen = 32; + return SAR_OK; +} + +ULONG DEVAPI SKF_MacInit( + HANDLE hKey, + BLOCKCIPHERPARAM *pMacParam, + HANDLE *phMac) +{ + if (!phMac) + return SAR_INVALIDPARAMERR; + *phMac = hMacHandle; + return SAR_OK; +} + +ULONG DEVAPI SKF_Mac( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbMacData, + ULONG *pulMacLen) +{ + if (!pulMacLen) + return SAR_INVALIDPARAMERR; + *pulMacLen = 16; + return SAR_OK; +} + +ULONG DEVAPI SKF_MacUpdate( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen) +{ + return SAR_OK; +} + +ULONG DEVAPI SKF_MacFinal( + HANDLE hMac, + BYTE *pbMacData, + ULONG *pulMacDataLen) +{ + if (!pulMacDataLen) + return SAR_INVALIDPARAMERR; + *pulMacDataLen = 16; + return SAR_OK; +} + +ULONG DEVAPI SKF_CloseHandle( + HANDLE hHandle) +{ + return SAR_OK; +} diff --git a/Core/GmSSL-3.1.1/src/skf/skf_ext.c b/Core/GmSSL-3.1.1/src/skf/skf_ext.c new file mode 100755 index 0000000..c76dc38 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_ext.c @@ -0,0 +1,568 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include "skf_int.h" +#include "skf_ext.h" +#include "skf.h" + + +#define SKFerr(f,e) + +ULONG DEVAPI SKF_NewECCCipher(ULONG ulCipherLen, ECCCIPHERBLOB **cipherBlob) +{ + ECCCIPHERBLOB *ret = NULL; + + if (!(ret = malloc(sizeof(ECCCIPHERBLOB) - 1 + ulCipherLen))) { + SKFerr(SKF_F_SKF_NEWECCCIPHER, ERR_R_MALLOC_FAILURE); + return SAR_MEMORYERR; + } + + ret->CipherLen = ulCipherLen; + *cipherBlob = ret; + return SAR_OK; +} + +ULONG DEVAPI SKF_NewEnvelopedKey(ULONG ulCipherLen, ENVELOPEDKEYBLOB **envelopedKeyBlob) +{ + ENVELOPEDKEYBLOB *ret = NULL; + + if (!(ret = malloc(sizeof(ENVELOPEDKEYBLOB) - 1 + ulCipherLen))) { + SKFerr(SKF_F_SKF_NEWENVELOPEDKEY, ERR_R_MALLOC_FAILURE); + return SAR_MEMORYERR; + } + + ret->ECCCipherBlob.CipherLen = ulCipherLen; + *envelopedKeyBlob = ret; + return SAR_OK; +} + +ULONG DEVAPI SKF_OpenDevice(LPSTR devName, BYTE authKey[16], DEVINFO *devInfo, DEVHANDLE *phDev) +{ + ULONG rv; + DEVHANDLE hDev = NULL; + HANDLE hKey = NULL; + ULONG ulTimeOut = 0xffffffff; + BYTE authRand[16] = {0}; + BYTE authData[16] = {0}; + ULONG authRandLen = SKF_AUTHRAND_LENGTH; + ULONG authDataLen = sizeof(authData); + BLOCKCIPHERPARAM encParam = {{0}, 0, 0, 0}; + + if ((rv = SKF_ConnectDev((LPSTR)devName, &hDev)) != SAR_OK + || (rv = SKF_GetDevInfo(hDev, devInfo)) != SAR_OK + || (rv = SKF_LockDev(hDev, ulTimeOut)) != SAR_OK + || (rv = SKF_GenRandom(hDev, authRand, authRandLen)) != SAR_OK + || (rv = SKF_SetSymmKey(hDev, authKey, devInfo->DevAuthAlgId, &hKey)) != SAR_OK + || (rv = SKF_EncryptInit(hKey, encParam)) != SAR_OK + || (rv = SKF_Encrypt(hKey, authRand, sizeof(authRand), authData, &authDataLen)) != SAR_OK + || (rv =SKF_DevAuth(hDev, authData, authDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_OPENDEVICE, ERR_R_SKF_LIB); + goto end; + } + *phDev = hDev; + hDev = NULL; + +end: + //OPENSSL_cleanse(authRand, sizeof(authRand)); + //OPENSSL_cleanse(authData, sizeof(authData)); + if (hKey && (rv = SKF_CloseHandle(hKey)) != SAR_OK) { + SKFerr(SKF_F_SKF_OPENDEVICE, ERR_R_SKF_LIB); + } + if (hDev && (rv = SKF_DisConnectDev(hDev)) != SAR_OK) { + SKFerr(SKF_F_SKF_OPENDEVICE, ERR_R_SKF_LIB); + } + return rv; +} + +ULONG DEVAPI SKF_CloseDevice(DEVHANDLE hDev) +{ + ULONG rv; + if ((rv = SKF_UnlockDev(hDev)) != SAR_OK) { + SKFerr(SKF_F_SKF_CLOSEDEVICE, ERR_R_SKF_LIB); + } + if ((rv = SKF_DisConnectDev(hDev)) != SAR_OK) { + SKFerr(SKF_F_SKF_CLOSEDEVICE, ERR_R_SKF_LIB); + } + return rv; +} + +#if 0 +ULONG DEVAPI SKF_ImportECCPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, + EC_KEY *ec_key, ULONG symmAlgId) +{ + int ret = 0; + ULONG rv; + ULONG containerType; + ECCPRIVATEKEYBLOB eccPriKeyBlob; + BYTE symmKey[16]; + HANDLE hSymmKey = NULL; + BLOCKCIPHERPARAM encParam; + ULONG encedPriKeyLen; + SKF_PUBLICKEYBLOB signPubKeyBlob; + ULONG signPubKeyLen = sizeof(signPubKeyBlob); + ENVELOPEDKEYBLOB envelopedKeyBlob; + + /* check container type */ + if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + return rv; + } + if (containerType != SKF_CONTAINER_TYPE_ECC) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, SKF_R_CONTAINER_TYPE_NOT_MATCH); + return SAR_FAIL; + } + + /* get private key and public key */ + if (!EC_KEY_get_ECCPRIVATEKEYBLOB(ec_key, &eccPriKeyBlob) + || !EC_KEY_get_ECCPUBLICKEYBLOB(ec_key, &(envelopedKeyBlob.PubKey))) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_GMAPI_LIB); + rv = SAR_FAIL; + goto end; + } + + /* set Version, ulSymmAlgID, ulBits */ + envelopedKeyBlob.Version = SKF_ENVELOPEDKEYBLOB_VERSION; + envelopedKeyBlob.ulSymmAlgID = symmAlgId; + envelopedKeyBlob.ulBits = eccPriKeyBlob.BitLen; + + /* encrypt private key with random generated symmkey */ + if (!rand_bytes(symmKey, sizeof(symmKey))) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + rv = SAR_FAIL; + goto end; + } + if ((rv = SKF_SetSymmKey(hDev, symmKey, symmAlgId, &hSymmKey)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + encParam.IVLen = 0; + encParam.PaddingType = SKF_NO_PADDING; + if ((rv = SKF_EncryptInit(hSymmKey, encParam)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + encedPriKeyLen = sizeof(envelopedKeyBlob.cbEncryptedPriKey); + if ((rv = SKF_Encrypt(hSymmKey, + eccPriKeyBlob.PrivateKey, sizeof(eccPriKeyBlob.PrivateKey), + (BYTE *)&(envelopedKeyBlob.cbEncryptedPriKey), &encedPriKeyLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + if (encedPriKeyLen != sizeof(eccPriKeyBlob.PrivateKey)) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + rv = SAR_FAIL; + goto end; + } + + /* encrypt symmKey */ + if ((rv = SKF_ExportPublicKey(hContainer, TRUE, + (BYTE *)&signPubKeyBlob, &signPubKeyLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + if (signPubKeyLen != sizeof(ECCPUBLICKEYBLOB)) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + rv = SAR_FAIL; + goto end; + } + if ((rv = SKF_ExtECCEncrypt(hDev, (ECCPUBLICKEYBLOB *)&signPubKeyBlob, + symmKey, sizeof(symmKey), &(envelopedKeyBlob.ECCCipherBlob))) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + + ret = 1; +end: + OPENSSL_cleanse(&eccPriKeyBlob, sizeof(eccPriKeyBlob)); + OPENSSL_cleanse(symmKey, sizeof(symmKey)); + if (hSymmKey && SKF_CloseHandle(hSymmKey) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); + ret = 0; + } + return ret; +} + +ULONG DEVAPI SKF_ImportRSAPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, + RSA *rsa, ULONG symmAlgId) +{ + ULONG rv; + ULONG containerType; + RSAPRIVATEKEYBLOB rsaPriKeyBlob; + unsigned char symmKey[16]; + RSAPUBLICKEYBLOB rsaPubKeyBlob; + ULONG rsaPubKeyLen = sizeof(rsaPubKeyBlob); + BYTE wrappedKey[MAX_RSA_MODULUS_LEN]; + ULONG wrappedKeyLen = sizeof(wrappedKey); + EVP_CIPHER_CTX *cctx = NULL; + unsigned char *p; + int len; + BYTE encedPriKey[sizeof(RSAPRIVATEKEYBLOB) + 16*2]; + ULONG encedPriKeyLen = sizeof(encedPriKey); + + + if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); + return rv; + } + if (containerType != SKF_CONTAINER_TYPE_RSA) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); + return SAR_FAIL; + } + + if (!RSA_get_RSAPRIVATEKEYBLOB(rsa, &rsaPriKeyBlob)) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + + /* generate symmkey */ + /* wrap symmkey with signing public key */ + if (!rand_bytes(symmKey, sizeof(symmKey))) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + if ((rv = SKF_ExportPublicKey(hContainer, SGD_TRUE, + (BYTE *)&rsaPubKeyBlob, &rsaPubKeyLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + if (!(rsa = RSA_new_from_RSAPUBLICKEYBLOB(&rsaPubKeyBlob))) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + if ((len = RSA_public_encrypt(sizeof(symmKey), symmKey, wrappedKey, + rsa, RSA_PKCS1_PADDING)) != rsaPriKeyBlob.BitLen / 8) { + goto end; + } + wrappedKeyLen = (ULONG)len; + + /* encrypt private key with symmkey in ECB mode */ + if (!(cctx = EVP_CIPHER_CTX_new())) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EVP_EncryptInit_ex(cctx, EVP_sms4_ecb(), NULL, symmKey, NULL)) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_EVP_LIB); + goto end; + } + p = encedPriKey; + if (!EVP_EncryptUpdate(cctx, p, &len, (unsigned char *)&rsaPriKeyBlob, + sizeof(RSAPRIVATEKEYBLOB))) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_EVP_LIB); + goto end; + } + p += len; + if (!EVP_EncryptFinal_ex(cctx, p, &len)) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_EVP_LIB); + goto end; + } + p += len; + encedPriKeyLen = p - encedPriKey; + + /* import */ + if ((rv = SKF_ImportRSAKeyPair(hContainer, symmAlgId, wrappedKey, wrappedKeyLen, + encedPriKey, encedPriKeyLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); + goto end; + } + +end: + OPENSSL_cleanse(&rsaPriKeyBlob, sizeof(rsaPriKeyBlob)); + OPENSSL_cleanse(symmKey, sizeof(symmKey)); + OPENSSL_cleanse(wrappedKey, sizeof(wrappedKey)); + EVP_CIPHER_CTX_free(cctx); + return rv; +} + +ULONG DEVAPI SKF_ImportPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, + EVP_PKEY *pkey, ULONG symmAlgId) +{ + ULONG rv; + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_EC: + if ((rv = SKF_ImportECCPrivateKey(hDev, hContainer, + EVP_PKEY_get0_EC_KEY(pkey), symmAlgId)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTPRIVATEKEY, ERR_R_SKF_LIB); + return rv; + } + break; + case EVP_PKEY_RSA: + if ((rv = SKF_ImportRSAPrivateKey(hDev, hContainer, + EVP_PKEY_get0_RSA(pkey), symmAlgId)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTPRIVATEKEY, ERR_R_SKF_LIB); + return rv; + } + break; + default: + SKFerr(SKF_F_SKF_IMPORTPRIVATEKEY, + SKF_R_UNSUPPORTED_PRIVATE_KEY_TYPE); + return SAR_FAIL; + } + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportECCPublicKey(HCONTAINER hContainer, BOOL bSign, EC_KEY **ec_key) +{ + ULONG rv; + ULONG containerType; + BYTE pubKeyBlob[sizeof(SKF_PUBLICKEYBLOB)]; + ECCPUBLICKEYBLOB *pubKey = (ECCPUBLICKEYBLOB *)pubKeyBlob; + ULONG pubKeyLen = sizeof(SKF_PUBLICKEYBLOB); + + if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, ERR_R_SKF_LIB); + return rv; + } + if (containerType != SKF_CONTAINER_TYPE_ECC) { + SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, SKF_R_CONTAINER_TYPE_NOT_MATCH); + return SAR_FAIL; + } + + if ((rv = SKF_ExportPublicKey(hContainer, bSign, + pubKeyBlob, &pubKeyLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, ERR_R_SKF_LIB); + return rv; + } + if (pubKeyLen != sizeof(ECCPUBLICKEYBLOB)) { + SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, ERR_R_SKF_LIB); + return SAR_FAIL; + } + + if (!(*ec_key = EC_KEY_new_from_ECCPUBLICKEYBLOB(pubKey))) { + SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, SKF_R_INVALID_ECC_PUBLIC_KEY); + return SAR_FAIL; + } + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportRSAPublicKey(HCONTAINER hContainer, BOOL bSign, RSA **rsa) +{ + ULONG rv; + ULONG containerType; + BYTE pubKeyBlob[sizeof(SKF_PUBLICKEYBLOB)]; + RSAPUBLICKEYBLOB *pubKey = (RSAPUBLICKEYBLOB *)pubKeyBlob; + ULONG pubKeyLen = sizeof(SKF_PUBLICKEYBLOB); + + if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, ERR_R_SKF_LIB); + return rv; + } + if (containerType != SKF_CONTAINER_TYPE_RSA) { + SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, SKF_R_CONTAINER_TYPE_NOT_MATCH); + return SAR_FAIL; + } + + if ((rv = SKF_ExportPublicKey(hContainer, bSign, + pubKeyBlob, &pubKeyLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, ERR_R_SKF_LIB); + return rv; + } + if (pubKeyLen != sizeof(RSAPUBLICKEYBLOB)) { + SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, ERR_R_SKF_LIB); + return SAR_FAIL; + } + + if (!(*rsa = RSA_new_from_RSAPUBLICKEYBLOB(pubKey))) { + SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, SKF_R_INVALID_RSA_PUBLIC_KEY); + return SAR_FAIL; + } + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportEVPPublicKey(HCONTAINER hContainer, BOOL bSign, EVP_PKEY **pp) +{ + ULONG rv; + ULONG containerType; + EVP_PKEY *pkey = NULL; + + if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_SKF_LIB); + return rv; + } + + if (!(pkey = EVP_PKEY_new())) { + SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_MALLOC_FAILURE); + return SAR_MEMORYERR; + } + + if (containerType == SKF_CONTAINER_TYPE_ECC) { + EC_KEY *ec_key = NULL; + if ((rv = SKF_ExportECCPublicKey(hContainer, bSign, + &ec_key)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_SKF_LIB); + goto end; + } + if (!EVP_PKEY_assign_EC_KEY(pkey, ec_key)) { + EC_KEY_free(ec_key); + rv = SAR_FAIL; + goto end; + } + + } else if (containerType == SKF_CONTAINER_TYPE_RSA) { + RSA *rsa = NULL; + if ((rv = SKF_ExportRSAPublicKey(hContainer, bSign, + &rsa)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_SKF_LIB); + goto end; + } + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + RSA_free(rsa); + rv = SAR_FAIL; + goto end; + } + + } else { + SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, SKF_R_INVALID_CONTAINER_TYPE); + rv = SAR_FAIL; + goto end; + } + + *pp = pkey; + pkey = NULL; + rv = SAR_OK; + +end: + EVP_PKEY_free(pkey); + return rv; +} +#endif + +/* +ULONG DEVAPI SKF_ImportX509Certificate(HCONTAINER hContainer, BOOL bSign, X509 *x509) +{ + int ret = 0; + ULONG containerType; + unsigned char *cert = NULL; + unsigned char *p; + int len; + + if (SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { + return 0; + } + if (containerType == SKF_CONTAINER_TYPE_UNDEF) { + return 0; + } + + switch (EVP_PKEY_id(X509_get0_pubkey(x509))) { + case EVP_PKEY_EC: + if (containerType != SKF_CONTAINER_TYPE_ECC) { + goto end; + } + if (!EC_KEY_is_sm2p256v1(EVP_PKEY_get0_EC_KEY(X509_get0_pubkey(x509)))) { + goto end; + } + break; + + case EVP_PKEY_RSA: + if (containerType != SKF_CONTAINER_TYPE_RSA) { + goto end; + } + break; + default: + goto end; + } + + if (X509_get_key_usage(x509) & (KU_DIGITAL_SIGNATURE| + KU_NON_REPUDIATION|KU_KEY_CERT_SIGN|KU_CRL_SIGN)) { + bSign = SGD_TRUE; + } else if (X509_get_key_usage(x509) & (KU_KEY_ENCIPHERMENT| + KU_DATA_ENCIPHERMENT|KU_KEY_AGREEMENT|KU_ENCIPHER_ONLY)) { + bSign = SGD_FALSE; + } else { + goto end; + } + + if ((len = i2d_X509(x509, NULL)) <= 0 + || !(p = cert = malloc(len)) + || (len = i2d_X509(x509, &p)) <= 0) { + goto end; + } + + if (SKF_ImportCertificate(hContainer, bSign, cert, (ULONG)len) != SAR_OK) { + goto end; + } + + ret = 1; +end: + X509_free(x509); + OPENSSL_free(cert); + return ret; +} + +ULONG DEVAPI SKF_ImportX509CertificateByKeyUsage(HCONTAINER hContainer, X509 *x509) +{ + ULONG rv; + BOOL bSign; + + if (X509_get_key_usage(x509) & (KU_DIGITAL_SIGNATURE| + KU_NON_REPUDIATION|KU_KEY_CERT_SIGN|KU_CRL_SIGN)) { + bSign = SGD_TRUE; + } else if (X509_get_key_usage(x509) & (KU_KEY_ENCIPHERMENT| + KU_DATA_ENCIPHERMENT|KU_KEY_AGREEMENT|KU_ENCIPHER_ONLY)) { + bSign = SGD_FALSE; + } else { + SKFerr(SKF_F_SKF_IMPORTX509CERTIFICATEBYKEYUSAGE, + SKF_R_UNKNOWN_CERTIFICATE_KEYUSAGE); + return SAR_FAIL; + } + + if ((rv = SKF_ImportX509Certificate(hContainer, bSign, x509)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTX509CERTIFICATEBYKEYUSAGE, ERR_R_SKF_LIB); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportX509Certificate(HCONTAINER hContainer, BOOL bSign, X509 **px509) +{ + ULONG rv = SAR_FAIL; + BYTE *pbCert = NULL; + ULONG ulCertLen; + const unsigned char *p; + X509 *x509 = NULL; + + ulCertLen = SKF_MAX_CERTIFICATE_SIZE; + if (!(pbCert = malloc(ulCertLen))) { + SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, ERR_R_MALLOC_FAILURE); + rv = SAR_MEMORYERR; + goto end; + } + if ((rv = SKF_ExportCertificate(hContainer, bSign, + pbCert, &ulCertLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, ERR_R_SKF_LIB); + goto end; + } + + p = pbCert; + if (!(x509 = d2i_X509(NULL, &p, (long)ulCertLen))) { + SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, + SKF_R_PARSE_CERTIFICATE_FAILURE); + goto end; + } + if (p - pbCert != ulCertLen) { + SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, + SKF_R_PARSE_CERTIFICATE_FAILURE); + goto end; + } + + *px509 = x509; + x509 = NULL; + rv = SAR_OK; + +end: + OPENSSL_free(pbCert); + X509_free(x509); + return rv; +} +*/ diff --git a/Core/GmSSL-3.1.1/src/skf/skf_ext.h b/Core/GmSSL-3.1.1/src/skf/skf_ext.h new file mode 100755 index 0000000..7040cec --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_ext.h @@ -0,0 +1,94 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef SKFUTIL_SKF_EXT_H +#define SKFUTIL_SKF_EXT_H + + +#include +#include "skf.h" + + +#define SKF_NO_PADDING 0 +#define SKF_PKCS5_PADDING 1 + +#define SKF_DEV_STATE_ABSENT 0x00000000 +#define SKF_DEV_STATE_PRESENT 0x00000001 +#define SKF_DEV_STATE_UNKNOW 0x00000010 + +#define SKF_CONTAINER_TYPE_UNDEF 0 +#define SKF_CONTAINER_TYPE_RSA 1 +#define SKF_CONTAINER_TYPE_ECC 2 + +#define SKF_ENVELOPEDKEYBLOB_VERSION 1 +#define SKF_AUTHKEY_LENGTH 16 +#define SKF_AUTHRAND_LENGTH 16 +#define SKF_MAX_FILE_SIZE (256*1024) +#define SKF_MAX_CERTIFICATE_SIZE (8*1024) + + +#define SKF_DEFAULT_ADMIN_PIN_RETRY_COUNT 6 +#define SKF_DEFAULT_USER_PIN_RETRY_COUNT 6 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + union { + ECCPUBLICKEYBLOB ecc; + RSAPUBLICKEYBLOB rsa; + } u; +} SKF_PUBLICKEYBLOB; +#define SKF_MAX_PUBLICKEYBOLB_LENGTH sizeof(SKF_PUBLICKEYBLOB) + +typedef struct { + char *name; + unsigned char *buf; + int offset; + int length; +} SKF_FILE_OP_PARAMS; + + +ULONG DEVAPI SKF_LoadLibrary(LPSTR so_path, LPSTR vendor); +ULONG DEVAPI SKF_UnloadLibrary(void); +ULONG DEVAPI SKF_OpenDevice(LPSTR devName, BYTE authKey[16], DEVINFO *devInfo, DEVHANDLE *phDev); +ULONG DEVAPI SKF_CloseDevice(DEVHANDLE hDev); +ULONG DEVAPI SKF_GetDevStateName(ULONG ulDevState, LPSTR *szName); +ULONG DEVAPI SKF_GetContainerTypeName(ULONG ulContainerType, LPSTR *szName); +ULONG DEVAPI SKF_GetAlgorName(ULONG ulAlgID, LPSTR *szName); +ULONG DEVAPI SKF_PrintDevInfo(FILE *fp, const DEVINFO *devInfo); +ULONG DEVAPI SKF_PrintRSAPublicKey(FILE *fp, const RSAPUBLICKEYBLOB *blob); +ULONG DEVAPI SKF_PrintRSAPrivateKey(FILE *fp, const RSAPRIVATEKEYBLOB *blob); +ULONG DEVAPI SKF_PrintECCPublicKey(FILE *fp, const ECCPUBLICKEYBLOB *blob); +ULONG DEVAPI SKF_PrintECCPrivateKey(FILE *fp, const ECCPRIVATEKEYBLOB *blob); +ULONG DEVAPI SKF_PrintECCCipher(FILE *fp, const ECCCIPHERBLOB *blob); +ULONG DEVAPI SKF_PrintECCSignature(FILE *fp, const ECCSIGNATUREBLOB *blob); +ULONG DEVAPI SKF_GetErrorString(ULONG ulError, LPSTR *szErrorStr); +ULONG DEVAPI SKF_NewECCCipher(ULONG ulCipherLen, ECCCIPHERBLOB **cipherBlob); +ULONG DEVAPI SKF_NewEnvelopedKey(ULONG ulCipherLen, ENVELOPEDKEYBLOB **envelopedKeyBlob); + +/* +ULONG DEVAPI SKF_ImportECCPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, EC_KEY *ec_key, ULONG symmAlgId); +ULONG DEVAPI SKF_ImportRSAPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, RSA *rsa, ULONG symmAlgId); +ULONG DEVAPI SKF_ImportPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, EVP_PKEY *pkey, ULONG symmAlgId); +ULONG DEVAPI SKF_ExportECCPublicKey(HCONTAINER hContainer, BOOL bSign, EC_KEY **pp); +ULONG DEVAPI SKF_ExportRSAPublicKey(HCONTAINER hContainer, BOOL bSign, RSA **pp); +ULONG DEVAPI SKF_ExportEVPPublicKey(HCONTAINER hContainer, BOOL bSign, EVP_PKEY **pp); +ULONG DEVAPI SKF_ImportX509CertificateByKeyUsage(HCONTAINER hContainer, X509 *x509); +ULONG DEVAPI SKF_ImportX509Certificate(HCONTAINER hContainer, BOOL bSign, X509 *x509); +ULONG DEVAPI SKF_ExportX509Certificate(HCONTAINER hContainer, BOOL bSign, X509 **px509); +*/ + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Core/GmSSL-3.1.1/src/skf/skf_int.h b/Core/GmSSL-3.1.1/src/skf/skf_int.h new file mode 100755 index 0000000..89a74d4 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_int.h @@ -0,0 +1,581 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef SKFUTIL_SKF_INT_H +#define SKFUTIL_SKF_INT_H + +#include +#include "../sgd.h" +#include "skf.h" + + + +typedef ULONG (DEVAPI *SKF_WaitForDevEvent_FuncPtr)( + LPSTR szDevName, + ULONG *pulDevNameLen, + ULONG *pulEvent); + +typedef ULONG (DEVAPI *SKF_CancelWaitForDevEvent_FuncPtr)( + void); + +typedef ULONG (DEVAPI *SKF_EnumDev_FuncPtr)( + BOOL bPresent, + LPSTR szNameList, + ULONG *pulSize); + +typedef ULONG (DEVAPI *SKF_ConnectDev_FuncPtr)( + LPSTR szName, + DEVHANDLE *phDev); + +typedef ULONG (DEVAPI *SKF_DisConnectDev_FuncPtr)( + DEVHANDLE hDev); + +typedef ULONG (DEVAPI *SKF_GetDevState_FuncPtr)( + LPSTR szDevName, + ULONG *pulDevState); + +typedef ULONG (DEVAPI *SKF_SetLabel_FuncPtr)( + DEVHANDLE hDev, + LPSTR szLabel); + +typedef ULONG (DEVAPI *SKF_GetDevInfo_FuncPtr)( + DEVHANDLE hDev, + DEVINFO *pDevInfo); + +typedef ULONG (DEVAPI *SKF_LockDev_FuncPtr)( + DEVHANDLE hDev, + ULONG ulTimeOut); + +typedef ULONG (DEVAPI *SKF_UnlockDev_FuncPtr)( + DEVHANDLE hDev); + +typedef ULONG (DEVAPI *SKF_Transmit_FuncPtr)( + DEVHANDLE hDev, + BYTE *pbCommand, + ULONG ulCommandLen, + BYTE *pbData, + ULONG *pulDataLen); + +typedef ULONG (DEVAPI *SKF_ChangeDevAuthKey_FuncPtr)( + DEVHANDLE hDev, + BYTE *pbKeyValue, + ULONG ulKeyLen); + +typedef ULONG (DEVAPI *SKF_DevAuth_FuncPtr)( + DEVHANDLE hDev, + BYTE *pbAuthData, + ULONG ulLen); + +typedef ULONG (DEVAPI *SKF_ChangePIN_FuncPtr)( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szOldPin, + LPSTR szNewPin, + ULONG *pulRetryCount); + +typedef LONG (DEVAPI *SKF_GetPINInfo_FuncPtr)( + HAPPLICATION hApplication, + ULONG ulPINType, + ULONG *pulMaxRetryCount, + ULONG *pulRemainRetryCount, + BOOL *pbDefaultPin); + +typedef ULONG (DEVAPI *SKF_VerifyPIN_FuncPtr)( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szPIN, + ULONG *pulRetryCount); + +typedef ULONG (DEVAPI *SKF_UnblockPIN_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szAdminPIN, + LPSTR szNewUserPIN, + ULONG *pulRetryCount); + +typedef ULONG (DEVAPI *SKF_ClearSecureState_FuncPtr)( + HAPPLICATION hApplication); + +typedef ULONG (DEVAPI *SKF_CreateApplication_FuncPtr)( + DEVHANDLE hDev, + LPSTR szAppName, + LPSTR szAdminPin, + DWORD dwAdminPinRetryCount, + LPSTR szUserPin, + DWORD dwUserPinRetryCount, + DWORD dwCreateFileRights, + HAPPLICATION *phApplication); + +typedef ULONG (DEVAPI *SKF_EnumApplication_FuncPtr)( + DEVHANDLE hDev, + LPSTR szAppName, + ULONG *pulSize); + +typedef ULONG (DEVAPI *SKF_DeleteApplication_FuncPtr)( + DEVHANDLE hDev, + LPSTR szAppName); + +typedef ULONG (DEVAPI *SKF_OpenApplication_FuncPtr)( + DEVHANDLE hDev, + LPSTR szAppName, + HAPPLICATION *phApplication); + +typedef ULONG (DEVAPI *SKF_CloseApplication_FuncPtr)( + HAPPLICATION hApplication); + +typedef ULONG (DEVAPI *SKF_CreateObject_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulFileSize, + ULONG ulReadRights, + ULONG ulWriteRights); + +typedef ULONG (DEVAPI *SKF_DeleteObject_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szFileName); + +typedef ULONG (DEVAPI *SKF_EnumObjects_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szFileList, + ULONG *pulSize); + +typedef ULONG (DEVAPI *SKF_GetObjectInfo_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szFileName, + FILEATTRIBUTE *pFileInfo); + +typedef ULONG (DEVAPI *SKF_ReadObject_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + ULONG ulSize, + BYTE *pbOutData, + ULONG *pulOutLen); + +typedef ULONG (DEVAPI *SKF_WriteObject_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + BYTE *pbData, + ULONG ulSize); + +typedef ULONG (DEVAPI *SKF_CreateContainer_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer); + +typedef ULONG (DEVAPI *SKF_DeleteContainer_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szContainerName); + +typedef ULONG (DEVAPI *SKF_EnumContainer_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szContainerName, + ULONG *pulSize); + +typedef ULONG (DEVAPI *SKF_OpenContainer_FuncPtr)( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer); + +typedef ULONG (DEVAPI *SKF_CloseContainer_FuncPtr)( + HCONTAINER hContainer); + +typedef ULONG (DEVAPI *SKF_GetContainerType_FuncPtr)( + HCONTAINER hContainer, + ULONG *pulContainerType); + +typedef ULONG (DEVAPI *SKF_ImportCertificate_FuncPtr)( + HCONTAINER hContainer, + BOOL bExportSignKey, + BYTE *pbCert, + ULONG ulCertLen); + +typedef ULONG (DEVAPI *SKF_ExportCertificate_FuncPtr)( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbCert, + ULONG *pulCertLen); + +typedef ULONG (DEVAPI *SKF_ExportPublicKey_FuncPtr)( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbBlob, + ULONG *pulBlobLen); + +typedef ULONG (DEVAPI *SKF_GenRandom_FuncPtr)( + DEVHANDLE hDev, + BYTE *pbRandom, + ULONG ulRandomLen); + +typedef ULONG (DEVAPI *SKF_GenExtRSAKey_FuncPtr)( + DEVHANDLE hDev, + ULONG ulBitsLen, + RSAPRIVATEKEYBLOB *pBlob); + +typedef ULONG (DEVAPI *SKF_GenRSAKeyPair_FuncPtr)( + HCONTAINER hContainer, + ULONG ulBitsLen, + RSAPUBLICKEYBLOB *pBlob); + +typedef ULONG (DEVAPI *SKF_ImportRSAKeyPair_FuncPtr)( + HCONTAINER hContainer, + ULONG ulSymAlgId, + BYTE *pbWrappedKey, + ULONG ulWrappedKeyLen, + BYTE *pbEncryptedData, + ULONG ulEncryptedDataLen); + +typedef ULONG (DEVAPI *SKF_RSASignData_FuncPtr)( + HCONTAINER hContainer, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG *pulSignLen); + +typedef ULONG (DEVAPI *SKF_RSAVerify_FuncPtr)( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG ulSignLen); + +typedef ULONG (DEVAPI *SKF_RSAExportSessionKey_FuncPtr)( + HCONTAINER hContainer, + ULONG ulAlgId, + RSAPUBLICKEYBLOB *pPubKey, + BYTE *pbData, + ULONG *pulDataLen, + HANDLE *phSessionKey); + +typedef ULONG (DEVAPI *SKF_ExtRSAPubKeyOperation_FuncPtr)( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen); + +typedef ULONG (DEVAPI *SKF_ExtRSAPriKeyOperation_FuncPtr)( + DEVHANDLE hDev, + RSAPRIVATEKEYBLOB *pRSAPriKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen); + +typedef ULONG (DEVAPI *SKF_GenECCKeyPair_FuncPtr)( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pBlob); + +typedef ULONG (DEVAPI *SKF_ImportECCKeyPair_FuncPtr)( + HCONTAINER hContainer, + ENVELOPEDKEYBLOB *pEnvelopedKeyBlob); + +typedef ULONG (DEVAPI *SKF_ECCSignData_FuncPtr)( + HCONTAINER hContainer, + BYTE *pbDigest, + ULONG ulDigestLen, + ECCSIGNATUREBLOB *pSignature); + +typedef ULONG (DEVAPI *SKF_ECCVerify_FuncPtr)( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature); + +typedef ULONG (DEVAPI *SKF_ECCExportSessionKey_FuncPtr)( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pPubKey, + ECCCIPHERBLOB *pData, + HANDLE *phSessionKey); + +typedef ULONG (DEVAPI *SKF_ExtECCEncrypt_FuncPtr)( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbPlainText, + ULONG ulPlainTextLen, + ECCCIPHERBLOB *pCipherText); + +typedef ULONG (DEVAPI *SKF_ECCDecrypt_FuncPtr)( + HCONTAINER hContainer, + ECCCIPHERBLOB *pCipherText, + BYTE *pbPlainText, + ULONG *pulPlainTextLen); + +typedef ULONG (DEVAPI *SKF_ExtECCDecrypt_FuncPtr)( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + ECCCIPHERBLOB *pCipherText, + BYTE *pbPlainText, + ULONG *pulPlainTextLen); + +typedef ULONG (DEVAPI *SKF_ExtECCSign_FuncPtr)( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature); + +typedef ULONG (DEVAPI *SKF_ExtECCVerify_FuncPtr)( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature); + +typedef ULONG (DEVAPI *SKF_GenerateAgreementDataWithECC_FuncPtr)( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phAgreementHandle); + +typedef ULONG (DEVAPI *SKF_GenerateAgreementDataAndKeyWithECC_FuncPtr)( + HANDLE hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pSponsorECCPubKeyBlob, + ECCPUBLICKEYBLOB *pSponsorTempECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + BYTE *pbSponsorID, + ULONG ulSponsorIDLen, + HANDLE *phKeyHandle); + +typedef ULONG (DEVAPI *SKF_GenerateKeyWithECC_FuncPtr)( + HANDLE hAgreementHandle, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phKeyHandle); + +typedef ULONG (DEVAPI *SKF_ImportSessionKey_FuncPtr)( + HCONTAINER hContainer, + ULONG ulAlgId, + BYTE *pbWrapedData, + ULONG ulWrapedLen, + HANDLE *phKey); + +typedef ULONG (DEVAPI *SKF_SetSymmKey_FuncPtr)( + DEVHANDLE hDev, + BYTE *pbKey, + ULONG ulAlgID, + HANDLE *phKey); + +typedef ULONG (DEVAPI *SKF_EncryptInit_FuncPtr)( + HANDLE hKey, + BLOCKCIPHERPARAM EncryptParam); + +typedef ULONG (DEVAPI *SKF_Encrypt_FuncPtr)( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen); + +typedef ULONG (DEVAPI *SKF_EncryptUpdate_FuncPtr)( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen); + +typedef ULONG (DEVAPI *SKF_EncryptFinal_FuncPtr)( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG *pulEncryptedDataLen); + +typedef ULONG (DEVAPI *SKF_DecryptInit_FuncPtr)( + HANDLE hKey, + BLOCKCIPHERPARAM DecryptParam); + +typedef ULONG (DEVAPI *SKF_Decrypt_FuncPtr)( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen); + +typedef ULONG (DEVAPI *SKF_DecryptUpdate_FuncPtr)( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen); + +typedef ULONG (DEVAPI *SKF_DecryptFinal_FuncPtr)( + HANDLE hKey, + BYTE *pbDecryptedData, + ULONG *pulDecryptedDataLen); + +typedef ULONG (DEVAPI *SKF_DigestInit_FuncPtr)( + DEVHANDLE hDev, + ULONG ulAlgID, + ECCPUBLICKEYBLOB *pPubKey, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phHash); + +typedef ULONG (DEVAPI *SKF_Digest_FuncPtr)( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbHashData, + ULONG *pulHashLen); + +typedef ULONG (DEVAPI *SKF_DigestUpdate_FuncPtr)( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen); + +typedef ULONG (DEVAPI *SKF_DigestFinal_FuncPtr)( + HANDLE hHash, + BYTE *pHashData, + ULONG *pulHashLen); + +typedef ULONG (DEVAPI *SKF_MacInit_FuncPtr)( + HANDLE hKey, + BLOCKCIPHERPARAM *pMacParam, + HANDLE *phMac); + +typedef ULONG (DEVAPI *SKF_Mac_FuncPtr)( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbMacData, + ULONG *pulMacLen); + +typedef ULONG (DEVAPI *SKF_MacUpdate_FuncPtr)( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen); + +typedef ULONG (DEVAPI *SKF_MacFinal_FuncPtr)( + HANDLE hMac, + BYTE *pbMacData, + ULONG *pulMacDataLen); + +typedef ULONG (DEVAPI *SKF_CloseHandle_FuncPtr)( + HANDLE hHandle); + + +typedef struct skf_method_st { + char *name; + dylib_handle_t dso; + + SKF_WaitForDevEvent_FuncPtr WaitForDevEvent; + SKF_CancelWaitForDevEvent_FuncPtr CancelWaitForDevEvent; + SKF_EnumDev_FuncPtr EnumDev; + SKF_ConnectDev_FuncPtr ConnectDev; + SKF_DisConnectDev_FuncPtr DisConnectDev; + SKF_GetDevState_FuncPtr GetDevState; + SKF_SetLabel_FuncPtr SetLabel; + SKF_GetDevInfo_FuncPtr GetDevInfo; + SKF_LockDev_FuncPtr LockDev; + SKF_UnlockDev_FuncPtr UnlockDev; + SKF_Transmit_FuncPtr Transmit; + SKF_ChangeDevAuthKey_FuncPtr ChangeDevAuthKey; + SKF_DevAuth_FuncPtr DevAuth; + SKF_ChangePIN_FuncPtr ChangePIN; + SKF_GetPINInfo_FuncPtr GetPINInfo; + SKF_VerifyPIN_FuncPtr VerifyPIN; + SKF_UnblockPIN_FuncPtr UnblockPIN; + SKF_ClearSecureState_FuncPtr ClearSecureState; + SKF_CreateApplication_FuncPtr CreateApplication; + SKF_EnumApplication_FuncPtr EnumApplication; + SKF_DeleteApplication_FuncPtr DeleteApplication; + SKF_OpenApplication_FuncPtr OpenApplication; + SKF_CloseApplication_FuncPtr CloseApplication; + SKF_CreateObject_FuncPtr CreateObject; + SKF_DeleteObject_FuncPtr DeleteObject; + SKF_EnumObjects_FuncPtr EnumObjects; + SKF_GetObjectInfo_FuncPtr GetObjectInfo; + SKF_ReadObject_FuncPtr ReadObject; + SKF_WriteObject_FuncPtr WriteObject; + SKF_CreateContainer_FuncPtr CreateContainer; + SKF_DeleteContainer_FuncPtr DeleteContainer; + SKF_EnumContainer_FuncPtr EnumContainer; + SKF_OpenContainer_FuncPtr OpenContainer; + SKF_CloseContainer_FuncPtr CloseContainer; + SKF_GetContainerType_FuncPtr GetContainerType; + SKF_ImportCertificate_FuncPtr ImportCertificate; + SKF_ExportCertificate_FuncPtr ExportCertificate; + SKF_ExportPublicKey_FuncPtr ExportPublicKey; + SKF_GenRandom_FuncPtr GenRandom; + SKF_GenExtRSAKey_FuncPtr GenExtRSAKey; + SKF_GenRSAKeyPair_FuncPtr GenRSAKeyPair; + SKF_ImportRSAKeyPair_FuncPtr ImportRSAKeyPair; + SKF_RSASignData_FuncPtr RSASignData; + SKF_RSAVerify_FuncPtr RSAVerify; + SKF_RSAExportSessionKey_FuncPtr RSAExportSessionKey; + SKF_ExtRSAPubKeyOperation_FuncPtr ExtRSAPubKeyOperation; + SKF_ExtRSAPriKeyOperation_FuncPtr ExtRSAPriKeyOperation; + SKF_GenECCKeyPair_FuncPtr GenECCKeyPair; + SKF_ImportECCKeyPair_FuncPtr ImportECCKeyPair; + SKF_ECCSignData_FuncPtr ECCSignData; + SKF_ECCVerify_FuncPtr ECCVerify; + SKF_ECCExportSessionKey_FuncPtr ECCExportSessionKey; + SKF_ExtECCEncrypt_FuncPtr ExtECCEncrypt; + SKF_ExtECCDecrypt_FuncPtr ExtECCDecrypt; + SKF_ECCDecrypt_FuncPtr ECCDecrypt; + SKF_ExtECCSign_FuncPtr ExtECCSign; + SKF_ExtECCVerify_FuncPtr ExtECCVerify; + SKF_GenerateAgreementDataWithECC_FuncPtr GenerateAgreementDataWithECC; + SKF_GenerateAgreementDataAndKeyWithECC_FuncPtr GenerateAgreementDataAndKeyWithECC; + SKF_GenerateKeyWithECC_FuncPtr GenerateKeyWithECC; + SKF_ImportSessionKey_FuncPtr ImportSessionKey; + SKF_SetSymmKey_FuncPtr SetSymmKey; + SKF_EncryptInit_FuncPtr EncryptInit; + SKF_Encrypt_FuncPtr Encrypt; + SKF_EncryptUpdate_FuncPtr EncryptUpdate; + SKF_EncryptFinal_FuncPtr EncryptFinal; + SKF_DecryptInit_FuncPtr DecryptInit; + SKF_Decrypt_FuncPtr Decrypt; + SKF_DecryptUpdate_FuncPtr DecryptUpdate; + SKF_DecryptFinal_FuncPtr DecryptFinal; + SKF_DigestInit_FuncPtr DigestInit; + SKF_Digest_FuncPtr Digest; + SKF_DigestUpdate_FuncPtr DigestUpdate; + SKF_DigestFinal_FuncPtr DigestFinal; + SKF_MacInit_FuncPtr MacInit; + SKF_Mac_FuncPtr Mac; + SKF_MacUpdate_FuncPtr MacUpdate; + SKF_MacFinal_FuncPtr MacFinal; + SKF_CloseHandle_FuncPtr CloseHandle; +} SKF_METHOD; + +SKF_METHOD *SKF_METHOD_load_library(const char *so_path); +void SKF_METHOD_free(SKF_METHOD *meth); + + +typedef struct skf_vendor_st { + char *name; + unsigned int authrand_length; + ULONG (*get_cipher_algor)(ULONG vendor_id); + ULONG (*get_cipher_cap)(ULONG vendor_cap); + ULONG (*get_digest_algor)(ULONG vendor_id); + ULONG (*get_digest_cap)(ULONG vendor_cap); + ULONG (*get_pkey_algor)(ULONG vendor_id); + ULONG (*get_pkey_cap)(ULONG vendor_cap); + unsigned long (*get_error_reason)(ULONG err); +} SKF_VENDOR; + +typedef struct { + ULONG err; + unsigned long reason; +} SKF_ERR_REASON; + +#endif diff --git a/Core/GmSSL-3.1.1/src/skf/skf_lib.c b/Core/GmSSL-3.1.1/src/skf/skf_lib.c new file mode 100755 index 0000000..1656e57 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_lib.c @@ -0,0 +1,2738 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include "skf_int.h" + + + +SKF_METHOD *skf_method = NULL; +SKF_VENDOR *skf_vendor = NULL; +extern SKF_VENDOR skf_wisec; + + +#define SKFerr(f,e) + + +ULONG DEVAPI SKF_LoadLibrary(LPSTR so_path, LPSTR vendor) +{ + if (skf_method) { + SKF_METHOD_free(skf_method); + skf_method = NULL; + } + + if (!(skf_method = SKF_METHOD_load_library((char *)so_path))) { + SKFerr(SKF_F_SKF_LOADLIBRARY, SKF_R_LOAD_LIBRARY_FAILURE); + return SAR_FAIL; + } + + if (vendor) { + if (strcmp((char *)vendor, skf_wisec.name) == 0) { + skf_vendor = &skf_wisec; + } else { + SKFerr(SKF_F_SKF_LOADLIBRARY, SKF_R_UNKNOWN_VENDOR); + return SAR_FAIL; + } + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_UnloadLibrary(void) +{ + SKF_METHOD_free(skf_method); + skf_method = NULL; + skf_vendor = NULL; + return SAR_OK; +} + +/* +static SKF_ERR_REASON skf_errors[] = { + { SAR_OK, SKF_R_SUCCESS }, + { SAR_FAIL, SKF_R_FAILURE }, + { SAR_UNKNOWNERR, SKF_R_UNKNOWN_ERROR }, + { SAR_NOTSUPPORTYETERR, SKF_R_OPERATION_NOT_SUPPORTED }, + { SAR_FILEERR, SKF_R_FILE_ERROR }, + { SAR_INVALIDHANDLEERR, SKF_R_INVALID_HANDLE }, + { SAR_INVALIDPARAMERR, SKF_R_INVALID_PARAMETER }, + { SAR_READFILEERR, SKF_R_READ_FILE_FAILURE }, + { SAR_WRITEFILEERR, SKF_R_WRITE_FILE_FAILURE }, + { SAR_NAMELENERR, SKF_R_INVALID_NAME_LENGTH }, + { SAR_KEYUSAGEERR, SKF_R_INVALID_KEY_USAGE }, + { SAR_MODULUSLENERR, SKF_R_INVALID_MODULUS_LENGTH }, + { SAR_NOTINITIALIZEERR, SKF_R_NOT_INITIALIZED }, + { SAR_OBJERR, SKF_R_INVALID_OBJECT }, + { SAR_MEMORYERR, SKF_R_MEMORY_ERROR }, + { SAR_TIMEOUTERR, SKF_R_TIMEOUT }, + { SAR_INDATALENERR, SKF_R_INVALID_INPUT_LENGTH }, + { SAR_INDATAERR, SKF_R_INVALID_INPUT_VALUE }, + { SAR_GENRANDERR, SKF_R_RANDOM_GENERATION_FAILED }, + { SAR_HASHOBJERR, SKF_R_INVALID_DIGEST_HANDLE }, + { SAR_HASHERR, SKF_R_DIGEST_ERROR }, + { SAR_GENRSAKEYERR, SKF_R_RSA_KEY_GENERATION_FAILURE }, + { SAR_RSAMODULUSLENERR, SKF_R_INVALID_RSA_MODULUS_LENGTH }, + { SAR_CSPIMPRTPUBKEYERR, SKF_R_CSP_IMPORT_PUBLIC_KEY_ERROR }, + { SAR_RSAENCERR, SKF_R_RSA_ENCRYPTION_FAILURE }, + { SAR_RSADECERR, SKF_R_RSA_DECRYPTION_FAILURE }, + { SAR_HASHNOTEQUALERR, SKF_R_HASH_NOT_EQUAL }, + { SAR_KEYNOTFOUNTERR, SKF_R_KEY_NOT_FOUND }, + { SAR_CERTNOTFOUNTERR, SKF_R_CERTIFICATE_NOT_FOUND }, + { SAR_NOTEXPORTERR, SKF_R_EXPORT_FAILED }, + { SAR_DECRYPTPADERR, SKF_R_DECRYPT_INVALID_PADDING }, + { SAR_MACLENERR, SKF_R_INVALID_MAC_LENGTH }, + { SAR_BUFFER_TOO_SMALL, SKF_R_BUFFER_TOO_SMALL }, + { SAR_KEYINFOTYPEERR, SKF_R_INVALID_KEY_INFO_TYPE }, + { SAR_NOT_EVENTERR, SKF_R_NO_EVENT }, + { SAR_DEVICE_REMOVED, SKF_R_DEVICE_REMOVED }, + { SAR_PIN_INCORRECT, SKF_R_PIN_INCORRECT }, + { SAR_PIN_LOCKED, SKF_R_PIN_LOCKED }, + { SAR_PIN_INVALID, SKF_R_INVALID_PIN }, + { SAR_PIN_LEN_RANGE, SKF_R_INVALID_PIN_LENGTH }, + { SAR_USER_ALREADY_LOGGED_IN, SKF_R_USER_ALREADY_LOGGED_IN }, + { SAR_USER_PIN_NOT_INITIALIZED, SKF_R_USER_PIN_NOT_INITIALIZED }, + { SAR_USER_TYPE_INVALID, SKF_R_INVALID_USER_TYPE }, + { SAR_APPLICATION_NAME_INVALID, SKF_R_INVALID_APPLICATION_NAME }, + { SAR_APPLICATION_EXISTS, SKF_R_APPLICATION_ALREADY_EXIST }, + { SAR_USER_NOT_LOGGED_IN, SKF_R_USER_NOT_LOGGED_IN }, + { SAR_APPLICATION_NOT_EXISTS, SKF_R_APPLICATION_NOT_EXIST }, + { SAR_FILE_ALREADY_EXIST, SKF_R_FILE_ALREADY_EXIST }, + { SAR_NO_ROOM, SKF_R_NO_SPACE }, + { SAR_FILE_NOT_EXIST, SKF_R_FILE_NOT_EXIST }, +}; +*/ + +static unsigned long skf_get_error_reason(ULONG ulError) +{ +/* + int i; + for (i = 0; i < OSSL_NELEM(skf_errors); i++) { + if (ulError == skf_errors[i].err) { + return skf_errors[i].reason; + } + } + if (skf_vendor) { + return skf_vendor->get_error_reason(ulError); + } +*/ + return 0; +} + +ULONG DEVAPI SKF_GetErrorString(ULONG ulError, LPSTR *szErrorStr) +{ + unsigned long reason; + + if ((reason = skf_get_error_reason(ulError)) != 0) { + //*szErrorStr = (LPSTR)ERR_reason_error_string(reason); + } else { + *szErrorStr = (LPSTR)"(unknown)"; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_WaitForDevEvent( + LPSTR szDevName, + ULONG *pulDevNameLen, + ULONG *pulEvent) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_WAITFORDEVEVENT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->WaitForDevEvent) { + SKFerr(SKF_F_SKF_WAITFORDEVEVENT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->WaitForDevEvent( + szDevName, + pulDevNameLen, + pulEvent)) != SAR_OK) { + SKFerr(SKF_F_SKF_WAITFORDEVEVENT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_CancelWaitForDevEvent( + void) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CANCELWAITFORDEVEVENT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->CancelWaitForDevEvent) { + SKFerr(SKF_F_SKF_CANCELWAITFORDEVEVENT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_method->CancelWaitForDevEvent) { + return skf_method->CancelWaitForDevEvent(); + } + + if ((rv = skf_method->CancelWaitForDevEvent()) != SAR_OK) { + SKFerr(SKF_F_SKF_CANCELWAITFORDEVEVENT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumDev( + BOOL bPresent, + LPSTR szNameList, + ULONG *pulSize) +{ + ULONG rv; + + + // check output of all enum functions !!!! + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENUMDEV, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->EnumDev) { + SKFerr(SKF_F_SKF_ENUMDEV, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (szNameList) { + memset(szNameList, 0, *pulSize); + } + + if ((rv = skf_method->EnumDev( + bPresent, + szNameList, + pulSize)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENUMDEV, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ConnectDev( + LPSTR szName, + DEVHANDLE *phDev) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CONNECTDEV, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ConnectDev) { + SKFerr(SKF_F_SKF_CONNECTDEV, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ConnectDev( + szName, + phDev)) != SAR_OK) { + SKFerr(SKF_F_SKF_CONNECTDEV, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DisConnectDev( + DEVHANDLE hDev) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DISCONNECTDEV, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DisConnectDev) { + SKFerr(SKF_F_SKF_DISCONNECTDEV, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DisConnectDev( + hDev)) != SAR_OK) { + SKFerr(SKF_F_SKF_DISCONNECTDEV, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GetDevState( + LPSTR szDevName, + ULONG *pulDevState) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GETDEVSTATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GetDevState) { + SKFerr(SKF_F_SKF_GETDEVSTATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->GetDevState( + szDevName, + pulDevState)) != SAR_OK) { + SKFerr(SKF_F_SKF_GETDEVSTATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_SetLabel( + DEVHANDLE hDev, + LPSTR szLabel) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_SETLABEL, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->SetLabel) { + SKFerr(SKF_F_SKF_SETLABEL, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->SetLabel( + hDev, + szLabel)) != SAR_OK) { + SKFerr(SKF_F_SKF_SETLABEL, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GetDevInfo( + DEVHANDLE hDev, + DEVINFO *pDevInfo) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GETDEVINFO, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GetDevInfo) { + SKFerr(SKF_F_SKF_GETDEVINFO, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + memset(pDevInfo, 0, sizeof(DEVINFO)); + + if ((rv = skf_method->GetDevInfo( + hDev, + pDevInfo)) != SAR_OK) { + SKFerr(SKF_F_SKF_GETDEVINFO, skf_get_error_reason(rv)); + printf("rv = %8x\n", rv); + return rv; + } + + if (skf_vendor) { + pDevInfo->AlgSymCap = skf_vendor->get_cipher_cap(pDevInfo->AlgSymCap); + pDevInfo->AlgAsymCap = skf_vendor->get_pkey_cap(pDevInfo->AlgAsymCap); + pDevInfo->AlgHashCap = skf_vendor->get_digest_cap(pDevInfo->AlgHashCap); + pDevInfo->DevAuthAlgId = skf_vendor->get_cipher_cap(pDevInfo->DevAuthAlgId); + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_LockDev( + DEVHANDLE hDev, + ULONG ulTimeOut) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_LOCKDEV, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->LockDev) { + SKFerr(SKF_F_SKF_LOCKDEV, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->LockDev( + hDev, + ulTimeOut)) != SAR_OK) { + SKFerr(SKF_F_SKF_LOCKDEV, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_UnlockDev( + DEVHANDLE hDev) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_UNLOCKDEV, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->UnlockDev) { + SKFerr(SKF_F_SKF_UNLOCKDEV, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->UnlockDev( + hDev)) != SAR_OK) { + SKFerr(SKF_F_SKF_UNLOCKDEV, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_Transmit( + DEVHANDLE hDev, + BYTE *pbCommand, + ULONG ulCommandLen, + BYTE *pbData, + ULONG *pulDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_TRANSMIT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->Transmit) { + SKFerr(SKF_F_SKF_TRANSMIT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->Transmit( + hDev, + pbCommand, + ulCommandLen, + pbData, + pulDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_TRANSMIT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ChangeDevAuthKey( + DEVHANDLE hDev, + BYTE *pbKeyValue, + ULONG ulKeyLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CHANGEDEVAUTHKEY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ChangeDevAuthKey) { + SKFerr(SKF_F_SKF_CHANGEDEVAUTHKEY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ChangeDevAuthKey( + hDev, + pbKeyValue, + ulKeyLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_CHANGEDEVAUTHKEY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DevAuth( + DEVHANDLE hDev, + BYTE *pbAuthData, + ULONG ulLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DEVAUTH, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DevAuth) { + SKFerr(SKF_F_SKF_DEVAUTH, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DevAuth( + hDev, + pbAuthData, + ulLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_DEVAUTH, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ChangePIN( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szOldPin, + LPSTR szNewPin, + ULONG *pulRetryCount) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CHANGEPIN, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ChangePIN) { + SKFerr(SKF_F_SKF_CHANGEPIN, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ChangePIN( + hApplication, + ulPINType, + szOldPin, + szNewPin, + pulRetryCount)) != SAR_OK) { + SKFerr(SKF_F_SKF_CHANGEPIN, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +LONG DEVAPI SKF_GetPINInfo( + HAPPLICATION hApplication, + ULONG ulPINType, + ULONG *pulMaxRetryCount, + ULONG *pulRemainRetryCount, + BOOL *pbDefaultPin) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GETPININFO, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GetPINInfo) { + SKFerr(SKF_F_SKF_GETPININFO, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->GetPINInfo( + hApplication, + ulPINType, + pulMaxRetryCount, + pulRemainRetryCount, + pbDefaultPin)) != SAR_OK) { + SKFerr(SKF_F_SKF_GETPININFO, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_VerifyPIN( + HAPPLICATION hApplication, + ULONG ulPINType, + LPSTR szPIN, + ULONG *pulRetryCount) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_VERIFYPIN, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->VerifyPIN) { + SKFerr(SKF_F_SKF_VERIFYPIN, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->VerifyPIN( + hApplication, + ulPINType, + szPIN, + pulRetryCount)) != SAR_OK) { + SKFerr(SKF_F_SKF_VERIFYPIN, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_UnblockPIN( + HAPPLICATION hApplication, + LPSTR szAdminPIN, + LPSTR szNewUserPIN, + ULONG *pulRetryCount) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_UNBLOCKPIN, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->UnblockPIN) { + SKFerr(SKF_F_SKF_UNBLOCKPIN, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->UnblockPIN( + hApplication, + szAdminPIN, + szNewUserPIN, + pulRetryCount)) != SAR_OK) { + SKFerr(SKF_F_SKF_UNBLOCKPIN, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ClearSecureState( + HAPPLICATION hApplication) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CLEARSECURESTATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ClearSecureState) { + SKFerr(SKF_F_SKF_CLEARSECURESTATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ClearSecureState( + hApplication)) != SAR_OK) { + SKFerr(SKF_F_SKF_CLEARSECURESTATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_CreateApplication( + DEVHANDLE hDev, + LPSTR szAppName, + LPSTR szAdminPin, + DWORD dwAdminPinRetryCount, + LPSTR szUserPin, + DWORD dwUserPinRetryCount, + DWORD dwCreateFileRights, + HAPPLICATION *phApplication) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CREATEAPPLICATION, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->CreateApplication) { + SKFerr(SKF_F_SKF_CREATEAPPLICATION, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->CreateApplication( + hDev, + szAppName, + szAdminPin, + dwAdminPinRetryCount, + szUserPin, + dwUserPinRetryCount, + dwCreateFileRights, + phApplication)) != SAR_OK) { + SKFerr(SKF_F_SKF_CREATEAPPLICATION, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumApplication( + DEVHANDLE hDev, + LPSTR szAppName, + ULONG *pulSize) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENUMAPPLICATION, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->EnumApplication) { + SKFerr(SKF_F_SKF_ENUMAPPLICATION, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->EnumApplication( + hDev, + szAppName, + pulSize)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENUMAPPLICATION, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DeleteApplication( + DEVHANDLE hDev, + LPSTR szAppName) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DELETEAPPLICATION, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DeleteApplication) { + SKFerr(SKF_F_SKF_DELETEAPPLICATION, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DeleteApplication( + hDev, + szAppName)) != SAR_OK) { + SKFerr(SKF_F_SKF_DELETEAPPLICATION, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_OpenApplication( + DEVHANDLE hDev, + LPSTR szAppName, + HAPPLICATION *phApplication) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_OPENAPPLICATION, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->OpenApplication) { + SKFerr(SKF_F_SKF_OPENAPPLICATION, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->OpenApplication( + hDev, + szAppName, + phApplication)) != SAR_OK) { + SKFerr(SKF_F_SKF_OPENAPPLICATION, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_CloseApplication( + HAPPLICATION hApplication) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CLOSEAPPLICATION, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->CloseApplication) { + SKFerr(SKF_F_SKF_CLOSEAPPLICATION, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->CloseApplication( + hApplication)) != SAR_OK) { + SKFerr(SKF_F_SKF_CLOSEAPPLICATION, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_CreateFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulFileSize, + ULONG ulReadRights, + ULONG ulWriteRights) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CREATEFILE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->CreateObject) { + SKFerr(SKF_F_SKF_CREATEFILE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->CreateObject( + hApplication, + szFileName, + ulFileSize, + ulReadRights, + ulWriteRights)) != SAR_OK) { + SKFerr(SKF_F_SKF_CREATEFILE, skf_get_error_reason(rv)); + + //LPSTR str = NULL; + //printf("error = %08X\n", rv); + //SKF_GetErrorString(rv, &str); + //printf("error = %s\n", (char *)str); + + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DeleteFile( + HAPPLICATION hApplication, + LPSTR szFileName) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DELETEFILE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DeleteObject) { + SKFerr(SKF_F_SKF_DELETEFILE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DeleteObject( + hApplication, + szFileName)) != SAR_OK) { + SKFerr(SKF_F_SKF_DELETEFILE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumFiles( + HAPPLICATION hApplication, + LPSTR szFileList, + ULONG *pulSize) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENUMFILES, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->EnumObjects) { + SKFerr(SKF_F_SKF_ENUMFILES, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->EnumObjects( + hApplication, + szFileList, + pulSize)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENUMFILES, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GetFileInfo( + HAPPLICATION hApplication, + LPSTR szFileName, + FILEATTRIBUTE *pFileInfo) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GETFILEINFO, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GetObjectInfo) { + SKFerr(SKF_F_SKF_GETFILEINFO, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + memset(pFileInfo, 0, sizeof(FILEATTRIBUTE)); + + if ((rv = skf_method->GetObjectInfo( + hApplication, + szFileName, + pFileInfo)) != SAR_OK) { + SKFerr(SKF_F_SKF_GETFILEINFO, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ReadFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + ULONG ulSize, + BYTE *pbOutData, + ULONG *pulOutLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_READFILE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ReadObject) { + SKFerr(SKF_F_SKF_READFILE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ReadObject( + hApplication, + szFileName, + ulOffset, + ulSize, + pbOutData, + pulOutLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_READFILE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_WriteFile( + HAPPLICATION hApplication, + LPSTR szFileName, + ULONG ulOffset, + BYTE *pbData, + ULONG ulSize) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_WRITEFILE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->WriteObject) { + SKFerr(SKF_F_SKF_WRITEFILE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->WriteObject( + hApplication, + szFileName, + ulOffset, + pbData, + ulSize)) != SAR_OK) { + SKFerr(SKF_F_SKF_WRITEFILE, skf_get_error_reason(rv)); + + printf("error = %08X\n", rv); + + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_CreateContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CREATECONTAINER, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->CreateContainer) { + SKFerr(SKF_F_SKF_CREATECONTAINER, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->CreateContainer( + hApplication, + szContainerName, + phContainer)) != SAR_OK) { + SKFerr(SKF_F_SKF_CREATECONTAINER, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DeleteContainer( + HAPPLICATION hApplication, + LPSTR szContainerName) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DELETECONTAINER, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DeleteContainer) { + SKFerr(SKF_F_SKF_DELETECONTAINER, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DeleteContainer( + hApplication, + szContainerName)) != SAR_OK) { + SKFerr(SKF_F_SKF_DELETECONTAINER, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_EnumContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + ULONG *pulSize) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENUMCONTAINER, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->EnumContainer) { + SKFerr(SKF_F_SKF_ENUMCONTAINER, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->EnumContainer( + hApplication, + szContainerName, + pulSize)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENUMCONTAINER, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_OpenContainer( + HAPPLICATION hApplication, + LPSTR szContainerName, + HCONTAINER *phContainer) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_OPENCONTAINER, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->OpenContainer) { + SKFerr(SKF_F_SKF_OPENCONTAINER, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->OpenContainer( + hApplication, + szContainerName, + phContainer)) != SAR_OK) { + SKFerr(SKF_F_SKF_OPENCONTAINER, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_CloseContainer( + HCONTAINER hContainer) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CLOSECONTAINER, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->CloseContainer) { + SKFerr(SKF_F_SKF_CLOSECONTAINER, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->CloseContainer( + hContainer)) != SAR_OK) { + SKFerr(SKF_F_SKF_CLOSECONTAINER, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GetContainerType( + HCONTAINER hContainer, + ULONG *pulContainerType) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GETCONTAINERTYPE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GetContainerType) { + SKFerr(SKF_F_SKF_GETCONTAINERTYPE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->GetContainerType( + hContainer, + pulContainerType)) != SAR_OK) { + SKFerr(SKF_F_SKF_GETCONTAINERTYPE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportCertificate( + HCONTAINER hContainer, + BOOL bExportSignKey, + BYTE *pbCert, + ULONG ulCertLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_IMPORTCERTIFICATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ImportCertificate) { + SKFerr(SKF_F_SKF_IMPORTCERTIFICATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ImportCertificate( + hContainer, + bExportSignKey, + pbCert, + ulCertLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTCERTIFICATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportCertificate( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbCert, + ULONG *pulCertLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXPORTCERTIFICATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExportCertificate) { + SKFerr(SKF_F_SKF_EXPORTCERTIFICATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExportCertificate( + hContainer, + bSignFlag, + pbCert, + pulCertLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTCERTIFICATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExportPublicKey( + HCONTAINER hContainer, + BOOL bSignFlag, + BYTE *pbBlob, + ULONG *pulBlobLen) +{ + ULONG rv; + + // TODO: check the output length, clear the memmory. + // if pbBlob is NULL, return the length + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXPORTPUBLICKEY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExportPublicKey) { + SKFerr(SKF_F_SKF_EXPORTPUBLICKEY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExportPublicKey( + hContainer, + bSignFlag, + pbBlob, + pulBlobLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXPORTPUBLICKEY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GenRandom( + DEVHANDLE hDev, + BYTE *pbRandom, + ULONG ulRandomLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GENRANDOM, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GenRandom) { + SKFerr(SKF_F_SKF_GENRANDOM, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->GenRandom( + hDev, + pbRandom, + ulRandomLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_GENRANDOM, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GenExtRSAKey( + DEVHANDLE hDev, + ULONG ulBitsLen, + RSAPRIVATEKEYBLOB *pBlob) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GENEXTRSAKEY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GenExtRSAKey) { + SKFerr(SKF_F_SKF_GENEXTRSAKEY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->GenExtRSAKey( + hDev, + ulBitsLen, + pBlob)) != SAR_OK) { + SKFerr(SKF_F_SKF_GENEXTRSAKEY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GenRSAKeyPair( + HCONTAINER hContainer, + ULONG ulBitsLen, + RSAPUBLICKEYBLOB *pBlob) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GENRSAKEYPAIR, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GenRSAKeyPair) { + SKFerr(SKF_F_SKF_GENRSAKEYPAIR, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + memset(pBlob, 0, sizeof(RSAPUBLICKEYBLOB)); + if ((rv = skf_method->GenRSAKeyPair( + hContainer, + ulBitsLen, + pBlob)) != SAR_OK) { + SKFerr(SKF_F_SKF_GENRSAKEYPAIR, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportRSAKeyPair( + HCONTAINER hContainer, + ULONG ulSymAlgId, + BYTE *pbWrappedKey, + ULONG ulWrappedKeyLen, + BYTE *pbEncryptedData, + ULONG ulEncryptedDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_IMPORTRSAKEYPAIR, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ImportRSAKeyPair) { + SKFerr(SKF_F_SKF_IMPORTRSAKEYPAIR, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulSymAlgId = skf_vendor->get_cipher_algor(ulSymAlgId))) { + SKFerr(SKF_F_SKF_IMPORTRSAKEYPAIR, + SKF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->ImportRSAKeyPair( + hContainer, + ulSymAlgId, + pbWrappedKey, + ulWrappedKeyLen, + pbEncryptedData, + ulEncryptedDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTRSAKEYPAIR, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_RSASignData( + HCONTAINER hContainer, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG *pulSignLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_RSASIGNDATA, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->RSASignData) { + SKFerr(SKF_F_SKF_RSASIGNDATA, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->RSASignData( + hContainer, + pbData, + ulDataLen, + pbSignature, + pulSignLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_RSASIGNDATA, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_RSAVerify( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbSignature, + ULONG ulSignLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_RSAVERIFY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->RSAVerify) { + SKFerr(SKF_F_SKF_RSAVERIFY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->RSAVerify( + hDev, + pRSAPubKeyBlob, + pbData, + ulDataLen, + pbSignature, + ulSignLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_RSAVERIFY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_RSAExportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + RSAPUBLICKEYBLOB *pPubKey, + BYTE *pbData, + ULONG *pulDataLen, + HANDLE *phSessionKey) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_RSAEXPORTSESSIONKEY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->RSAExportSessionKey) { + SKFerr(SKF_F_SKF_RSAEXPORTSESSIONKEY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgId = skf_vendor->get_cipher_algor(ulAlgId))) { + SKFerr(SKF_F_SKF_RSAEXPORTSESSIONKEY, + SKF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->RSAExportSessionKey( + hContainer, + ulAlgId, + pPubKey, + pbData, + pulDataLen, + phSessionKey)) != SAR_OK) { + SKFerr(SKF_F_SKF_RSAEXPORTSESSIONKEY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtRSAPubKeyOperation( + DEVHANDLE hDev, + RSAPUBLICKEYBLOB *pRSAPubKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXTRSAPUBKEYOPERATION, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExtRSAPubKeyOperation) { + SKFerr(SKF_F_SKF_EXTRSAPUBKEYOPERATION, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExtRSAPubKeyOperation( + hDev, + pRSAPubKeyBlob, + pbInput, + ulInputLen, + pbOutput, + pulOutputLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXTRSAPUBKEYOPERATION, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtRSAPriKeyOperation( + DEVHANDLE hDev, + RSAPRIVATEKEYBLOB *pRSAPriKeyBlob, + BYTE *pbInput, + ULONG ulInputLen, + BYTE *pbOutput, + ULONG *pulOutputLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXTRSAPRIKEYOPERATION, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExtRSAPriKeyOperation) { + SKFerr(SKF_F_SKF_EXTRSAPRIKEYOPERATION, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExtRSAPriKeyOperation( + hDev, + pRSAPriKeyBlob, + pbInput, + ulInputLen, + pbOutput, + pulOutputLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXTRSAPRIKEYOPERATION, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GenECCKeyPair( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pBlob) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GENECCKEYPAIR, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GenECCKeyPair) { + SKFerr(SKF_F_SKF_GENECCKEYPAIR, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgId = skf_vendor->get_pkey_algor(ulAlgId))) { + SKFerr(SKF_F_SKF_GENECCKEYPAIR, + SKF_R_NOT_SUPPORTED_PKEY_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + memset(pBlob, 0, sizeof(ECCPUBLICKEYBLOB)); + if ((rv = skf_method->GenECCKeyPair( + hContainer, + ulAlgId, + pBlob)) != SAR_OK) { + SKFerr(SKF_F_SKF_GENECCKEYPAIR, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportECCKeyPair( + HCONTAINER hContainer, + ENVELOPEDKEYBLOB *pEnvelopedKeyBlob) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_IMPORTECCKEYPAIR, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ImportECCKeyPair) { + SKFerr(SKF_F_SKF_IMPORTECCKEYPAIR, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ImportECCKeyPair( + hContainer, + pEnvelopedKeyBlob)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTECCKEYPAIR, skf_get_error_reason(rv)); + printf("%s %d: error = %08X\n", __FILE__, __LINE__, rv); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ECCSignData( + HCONTAINER hContainer, + BYTE *pbDigest, + ULONG ulDigestLen, + ECCSIGNATUREBLOB *pSignature) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ECCSIGNDATA, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ECCSignData) { + SKFerr(SKF_F_SKF_ECCSIGNDATA, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ECCSignData( + hContainer, + pbDigest, + ulDigestLen, + pSignature)) != SAR_OK) { + SKFerr(SKF_F_SKF_ECCSIGNDATA, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ECCVerify( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ECCVERIFY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ECCVerify) { + SKFerr(SKF_F_SKF_ECCVERIFY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ECCVerify( + hDev, + pECCPubKeyBlob, + pbData, + ulDataLen, + pSignature)) != SAR_OK) { + SKFerr(SKF_F_SKF_ECCVERIFY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ECCExportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pPubKey, + ECCCIPHERBLOB *pData, + HANDLE *phSessionKey) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ECCEXPORTSESSIONKEY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ECCExportSessionKey) { + SKFerr(SKF_F_SKF_ECCEXPORTSESSIONKEY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgId = skf_vendor->get_cipher_algor(ulAlgId))) { + SKFerr(SKF_F_SKF_ECCEXPORTSESSIONKEY, + SKF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->ECCExportSessionKey( + hContainer, + ulAlgId, + pPubKey, + pData, + phSessionKey)) != SAR_OK) { + SKFerr(SKF_F_SKF_ECCEXPORTSESSIONKEY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ECCDecrypt( + HCONTAINER hContainer, + ECCCIPHERBLOB *pCipherText, + BYTE *pbPlainText, + ULONG *pulPlainTextLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ECCDECRYPT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ECCDecrypt) { + SKFerr(SKF_F_SKF_ECCDECRYPT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ECCDecrypt( + hContainer, + pCipherText, + pbPlainText, + pulPlainTextLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_ECCDECRYPT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCEncrypt( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbPlainText, + ULONG ulPlainTextLen, + ECCCIPHERBLOB *pCipherText) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXTECCENCRYPT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExtECCEncrypt) { + SKFerr(SKF_F_SKF_EXTECCENCRYPT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExtECCEncrypt( + hDev, + pECCPubKeyBlob, + pbPlainText, + ulPlainTextLen, + pCipherText)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXTECCENCRYPT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCDecrypt( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + ECCCIPHERBLOB *pCipherText, + BYTE *pbPlainText, + ULONG *pulPlainTextLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXTECCDECRYPT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExtECCDecrypt) { + SKFerr(SKF_F_SKF_EXTECCDECRYPT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExtECCDecrypt( + hDev, + pECCPriKeyBlob, + pCipherText, + pbPlainText, + pulPlainTextLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXTECCDECRYPT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCSign( + DEVHANDLE hDev, + ECCPRIVATEKEYBLOB *pECCPriKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXTECCSIGN, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExtECCSign) { + SKFerr(SKF_F_SKF_EXTECCSIGN, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExtECCSign( + hDev, + pECCPriKeyBlob, + pbData, + ulDataLen, + pSignature)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXTECCSIGN, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ExtECCVerify( + DEVHANDLE hDev, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + BYTE *pbData, + ULONG ulDataLen, + ECCSIGNATUREBLOB *pSignature) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_EXTECCVERIFY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ExtECCVerify) { + SKFerr(SKF_F_SKF_EXTECCVERIFY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->ExtECCVerify( + hDev, + pECCPubKeyBlob, + pbData, + ulDataLen, + pSignature)) != SAR_OK) { + SKFerr(SKF_F_SKF_EXTECCVERIFY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GenerateAgreementDataWithECC( + HCONTAINER hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phAgreementHandle) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAWITHECC, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GenerateAgreementDataWithECC) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAWITHECC, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgId = skf_vendor->get_cipher_algor(ulAlgId))) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAWITHECC, + SKF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->GenerateAgreementDataWithECC( + hContainer, + ulAlgId, + pTempECCPubKeyBlob, + pbID, + ulIDLen, + phAgreementHandle)) != SAR_OK) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAWITHECC, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GenerateAgreementDataAndKeyWithECC( + HANDLE hContainer, + ULONG ulAlgId, + ECCPUBLICKEYBLOB *pSponsorECCPubKeyBlob, + ECCPUBLICKEYBLOB *pSponsorTempECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + BYTE *pbSponsorID, + ULONG ulSponsorIDLen, + HANDLE *phKeyHandle) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAANDKEYWITHECC, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GenerateAgreementDataAndKeyWithECC) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAANDKEYWITHECC, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgId = skf_vendor->get_cipher_algor(ulAlgId))) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAANDKEYWITHECC, + SKF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->GenerateAgreementDataAndKeyWithECC( + hContainer, + ulAlgId, + pSponsorECCPubKeyBlob, + pSponsorTempECCPubKeyBlob, + pTempECCPubKeyBlob, + pbID, + ulIDLen, + pbSponsorID, + ulSponsorIDLen, + phKeyHandle)) != SAR_OK) { + SKFerr(SKF_F_SKF_GENERATEAGREEMENTDATAANDKEYWITHECC, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GenerateKeyWithECC( + HANDLE hAgreementHandle, + ECCPUBLICKEYBLOB *pECCPubKeyBlob, + ECCPUBLICKEYBLOB *pTempECCPubKeyBlob, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phKeyHandle) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_GENERATEKEYWITHECC, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->GenerateKeyWithECC) { + SKFerr(SKF_F_SKF_GENERATEKEYWITHECC, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->GenerateKeyWithECC( + hAgreementHandle, + pECCPubKeyBlob, + pTempECCPubKeyBlob, + pbID, + ulIDLen, + phKeyHandle)) != SAR_OK) { + SKFerr(SKF_F_SKF_GENERATEKEYWITHECC, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_ImportSessionKey( + HCONTAINER hContainer, + ULONG ulAlgId, + BYTE *pbWrapedData, + ULONG ulWrapedLen, + HANDLE *phKey) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_IMPORTSESSIONKEY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->ImportSessionKey) { + SKFerr(SKF_F_SKF_IMPORTSESSIONKEY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgId = skf_vendor->get_cipher_algor(ulAlgId))) { + SKFerr(SKF_F_SKF_IMPORTSESSIONKEY, + SKF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->ImportSessionKey( + hContainer, + ulAlgId, + pbWrapedData, + ulWrapedLen, + phKey)) != SAR_OK) { + SKFerr(SKF_F_SKF_IMPORTSESSIONKEY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_SetSymmKey( + DEVHANDLE hDev, + BYTE *pbKey, + ULONG ulAlgID, + HANDLE *phKey) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_SETSYMMKEY, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->SetSymmKey) { + SKFerr(SKF_F_SKF_SETSYMMKEY, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgID = skf_vendor->get_cipher_algor(ulAlgID))) { + SKFerr(SKF_F_SKF_SETSYMMKEY, + SKF_R_NOT_SUPPORTED_CIPHER_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->SetSymmKey( + hDev, + pbKey, + ulAlgID, + phKey)) != SAR_OK) { + SKFerr(SKF_F_SKF_SETSYMMKEY, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_EncryptInit( + HANDLE hKey, + BLOCKCIPHERPARAM EncryptParam) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENCRYPTINIT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->EncryptInit) { + SKFerr(SKF_F_SKF_ENCRYPTINIT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->EncryptInit( + hKey, + EncryptParam)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENCRYPTINIT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_Encrypt( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENCRYPT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->Encrypt) { + SKFerr(SKF_F_SKF_ENCRYPT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->Encrypt( + hKey, + pbData, + ulDataLen, + pbEncryptedData, + pulEncryptedLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENCRYPT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_EncryptUpdate( + HANDLE hKey, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbEncryptedData, + ULONG *pulEncryptedLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENCRYPTUPDATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->EncryptUpdate) { + SKFerr(SKF_F_SKF_ENCRYPTUPDATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->EncryptUpdate( + hKey, + pbData, + ulDataLen, + pbEncryptedData, + pulEncryptedLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENCRYPTUPDATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_EncryptFinal( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG *pulEncryptedDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_ENCRYPTFINAL, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->EncryptFinal) { + SKFerr(SKF_F_SKF_ENCRYPTFINAL, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->EncryptFinal( + hKey, + pbEncryptedData, + pulEncryptedDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_ENCRYPTFINAL, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DecryptInit( + HANDLE hKey, + BLOCKCIPHERPARAM DecryptParam) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DECRYPTINIT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DecryptInit) { + SKFerr(SKF_F_SKF_DECRYPTINIT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DecryptInit( + hKey, + DecryptParam)) != SAR_OK) { + SKFerr(SKF_F_SKF_DECRYPTINIT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_Decrypt( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DECRYPT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->Decrypt) { + SKFerr(SKF_F_SKF_DECRYPT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->Decrypt( + hKey, + pbEncryptedData, + ulEncryptedLen, + pbData, + pulDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_DECRYPT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DecryptUpdate( + HANDLE hKey, + BYTE *pbEncryptedData, + ULONG ulEncryptedLen, + BYTE *pbData, + ULONG *pulDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DECRYPTUPDATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DecryptUpdate) { + SKFerr(SKF_F_SKF_DECRYPTUPDATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DecryptUpdate( + hKey, + pbEncryptedData, + ulEncryptedLen, + pbData, + pulDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_DECRYPTUPDATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DecryptFinal( + HANDLE hKey, + BYTE *pbDecryptedData, + ULONG *pulDecryptedDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DECRYPTFINAL, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DecryptFinal) { + SKFerr(SKF_F_SKF_DECRYPTFINAL, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DecryptFinal( + hKey, + pbDecryptedData, + pulDecryptedDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_DECRYPTFINAL, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DigestInit( + DEVHANDLE hDev, + ULONG ulAlgID, + ECCPUBLICKEYBLOB *pPubKey, + BYTE *pbID, + ULONG ulIDLen, + HANDLE *phHash) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DIGESTINIT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DigestInit) { + SKFerr(SKF_F_SKF_DIGESTINIT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if (skf_vendor) { + if (!(ulAlgID = skf_vendor->get_digest_algor(ulAlgID))) { + SKFerr(SKF_F_SKF_DIGESTINIT, + SKF_R_NOT_SUPPORTED_DIGEST_ALGOR); + return SAR_NOTSUPPORTYETERR; + } + } + + if ((rv = skf_method->DigestInit( + hDev, + ulAlgID, + pPubKey, + pbID, + ulIDLen, + phHash)) != SAR_OK) { + SKFerr(SKF_F_SKF_DIGESTINIT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_Digest( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbHashData, + ULONG *pulHashLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DIGEST, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->Digest) { + SKFerr(SKF_F_SKF_DIGEST, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->Digest( + hHash, + pbData, + ulDataLen, + pbHashData, + pulHashLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_DIGEST, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DigestUpdate( + HANDLE hHash, + BYTE *pbData, + ULONG ulDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DIGESTUPDATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DigestUpdate) { + SKFerr(SKF_F_SKF_DIGESTUPDATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DigestUpdate( + hHash, + pbData, + ulDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_DIGESTUPDATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_DigestFinal( + HANDLE hHash, + BYTE *pHashData, + ULONG *pulHashLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_DIGESTFINAL, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->DigestFinal) { + SKFerr(SKF_F_SKF_DIGESTFINAL, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->DigestFinal( + hHash, + pHashData, + pulHashLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_DIGESTFINAL, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_MacInit( + HANDLE hKey, + BLOCKCIPHERPARAM *pMacParam, + HANDLE *phMac) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_MACINIT, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->MacInit) { + SKFerr(SKF_F_SKF_MACINIT, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->MacInit( + hKey, + pMacParam, + phMac)) != SAR_OK) { + SKFerr(SKF_F_SKF_MACINIT, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_Mac( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen, + BYTE *pbMacData, + ULONG *pulMacLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_MAC, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->Mac) { + SKFerr(SKF_F_SKF_MAC, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->Mac( + hMac, + pbData, + ulDataLen, + pbMacData, + pulMacLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_MAC, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_MacUpdate( + HANDLE hMac, + BYTE *pbData, + ULONG ulDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_MACUPDATE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->MacUpdate) { + SKFerr(SKF_F_SKF_MACUPDATE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->MacUpdate( + hMac, + pbData, + ulDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_MACUPDATE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_MacFinal( + HANDLE hMac, + BYTE *pbMacData, + ULONG *pulMacDataLen) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_MACFINAL, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->MacFinal) { + SKFerr(SKF_F_SKF_MACFINAL, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->MacFinal( + hMac, + pbMacData, + pulMacDataLen)) != SAR_OK) { + SKFerr(SKF_F_SKF_MACFINAL, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_CloseHandle( + HANDLE hHandle) +{ + ULONG rv; + + if (!skf_method) { + SKFerr(SKF_F_SKF_CLOSEHANDLE, + SKF_R_SKF_METHOD_NOT_INITIALIZED); + return SAR_NOTINITIALIZEERR; + } + + if (!skf_method->CloseHandle) { + SKFerr(SKF_F_SKF_CLOSEHANDLE, + SKF_R_FUNCTION_NOT_SUPPORTED); + return SAR_NOTSUPPORTYETERR; + } + + if ((rv = skf_method->CloseHandle( + hHandle)) != SAR_OK) { + SKFerr(SKF_F_SKF_CLOSEHANDLE, skf_get_error_reason(rv)); + return rv; + } + + return SAR_OK; +} + diff --git a/Core/GmSSL-3.1.1/src/skf/skf_meth.c b/Core/GmSSL-3.1.1/src/skf/skf_meth.c new file mode 100755 index 0000000..5a9b49c --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_meth.c @@ -0,0 +1,137 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include "skf.h" +#include "skf_ext.h" +#include "skf_int.h" + +#define SKFerr(e,r) + +#define SKF_METHOD_BIND_FUNCTION_EX(func,name) \ + skf->func = (SKF_##func##_FuncPtr)dylib_get_function(skf->dso, "SKF_"#name) + +#define SKF_METHOD_BIND_FUNCTION(func) \ + SKF_METHOD_BIND_FUNCTION_EX(func,func) + + +SKF_METHOD *SKF_METHOD_load_library(const char *so_path) +{ + SKF_METHOD *ret = NULL; + SKF_METHOD *skf = NULL; + + if (!(skf = malloc(sizeof(*skf)))) { + SKFerr(SKF_F_SKF_METHOD_LOAD_LIBRARY, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!(skf->dso = dylib_load_library(so_path))) { + SKFerr(SKF_F_SKF_METHOD_LOAD_LIBRARY, SKF_R_DSO_LOAD_FAILURE); + goto end; + } + + SKF_METHOD_BIND_FUNCTION(WaitForDevEvent); + SKF_METHOD_BIND_FUNCTION(CancelWaitForDevEvent); + SKF_METHOD_BIND_FUNCTION(EnumDev); + SKF_METHOD_BIND_FUNCTION(ConnectDev); + SKF_METHOD_BIND_FUNCTION(DisConnectDev); + SKF_METHOD_BIND_FUNCTION(GetDevState); + SKF_METHOD_BIND_FUNCTION(SetLabel); + SKF_METHOD_BIND_FUNCTION(GetDevInfo); + SKF_METHOD_BIND_FUNCTION(LockDev); + SKF_METHOD_BIND_FUNCTION(UnlockDev); + SKF_METHOD_BIND_FUNCTION(Transmit); + SKF_METHOD_BIND_FUNCTION(ChangeDevAuthKey); + SKF_METHOD_BIND_FUNCTION(DevAuth); + SKF_METHOD_BIND_FUNCTION(ChangePIN); + SKF_METHOD_BIND_FUNCTION(GetPINInfo); + SKF_METHOD_BIND_FUNCTION(VerifyPIN); + SKF_METHOD_BIND_FUNCTION(UnblockPIN); + SKF_METHOD_BIND_FUNCTION(ClearSecureState); + SKF_METHOD_BIND_FUNCTION(CreateApplication); + SKF_METHOD_BIND_FUNCTION(EnumApplication); + SKF_METHOD_BIND_FUNCTION(DeleteApplication); + SKF_METHOD_BIND_FUNCTION(OpenApplication); + SKF_METHOD_BIND_FUNCTION(CloseApplication); + SKF_METHOD_BIND_FUNCTION_EX(CreateObject,CreateFile); + SKF_METHOD_BIND_FUNCTION_EX(DeleteObject,DeleteFile); + SKF_METHOD_BIND_FUNCTION_EX(EnumObjects,EnumFiles); + SKF_METHOD_BIND_FUNCTION_EX(GetObjectInfo,GetFileInfo); + SKF_METHOD_BIND_FUNCTION_EX(ReadObject,ReadFile); + SKF_METHOD_BIND_FUNCTION_EX(WriteObject,WriteFile); + SKF_METHOD_BIND_FUNCTION(CreateContainer); + SKF_METHOD_BIND_FUNCTION(DeleteContainer); + SKF_METHOD_BIND_FUNCTION(EnumContainer); + SKF_METHOD_BIND_FUNCTION(OpenContainer); + SKF_METHOD_BIND_FUNCTION(CloseContainer); + SKF_METHOD_BIND_FUNCTION(GetContainerType); + SKF_METHOD_BIND_FUNCTION(ImportCertificate); + SKF_METHOD_BIND_FUNCTION(ExportCertificate); + SKF_METHOD_BIND_FUNCTION(ExportPublicKey); + SKF_METHOD_BIND_FUNCTION(GenRandom); + SKF_METHOD_BIND_FUNCTION(GenExtRSAKey); + SKF_METHOD_BIND_FUNCTION(GenRSAKeyPair); + SKF_METHOD_BIND_FUNCTION(ImportRSAKeyPair); + SKF_METHOD_BIND_FUNCTION(RSASignData); + SKF_METHOD_BIND_FUNCTION(RSAVerify); + SKF_METHOD_BIND_FUNCTION(RSAExportSessionKey); + SKF_METHOD_BIND_FUNCTION(ExtRSAPubKeyOperation); + SKF_METHOD_BIND_FUNCTION(ExtRSAPriKeyOperation); + SKF_METHOD_BIND_FUNCTION(GenECCKeyPair); + SKF_METHOD_BIND_FUNCTION(ImportECCKeyPair); + SKF_METHOD_BIND_FUNCTION(ECCSignData); + SKF_METHOD_BIND_FUNCTION(ECCVerify); + SKF_METHOD_BIND_FUNCTION(ECCExportSessionKey); + SKF_METHOD_BIND_FUNCTION(ExtECCEncrypt); + SKF_METHOD_BIND_FUNCTION(ExtECCDecrypt); + SKF_METHOD_BIND_FUNCTION(ExtECCSign); + SKF_METHOD_BIND_FUNCTION(ExtECCVerify); + SKF_METHOD_BIND_FUNCTION(GenerateAgreementDataWithECC); + SKF_METHOD_BIND_FUNCTION(GenerateAgreementDataAndKeyWithECC); + SKF_METHOD_BIND_FUNCTION(GenerateKeyWithECC); + SKF_METHOD_BIND_FUNCTION(ImportSessionKey); + SKF_METHOD_BIND_FUNCTION(SetSymmKey); + SKF_METHOD_BIND_FUNCTION(EncryptInit); + SKF_METHOD_BIND_FUNCTION(Encrypt); + SKF_METHOD_BIND_FUNCTION(EncryptUpdate); + SKF_METHOD_BIND_FUNCTION(EncryptFinal); + SKF_METHOD_BIND_FUNCTION(DecryptInit); + SKF_METHOD_BIND_FUNCTION(Decrypt); + SKF_METHOD_BIND_FUNCTION(DecryptUpdate); + SKF_METHOD_BIND_FUNCTION(DecryptFinal); + SKF_METHOD_BIND_FUNCTION(DigestInit); + SKF_METHOD_BIND_FUNCTION(Digest); + SKF_METHOD_BIND_FUNCTION(DigestUpdate); + SKF_METHOD_BIND_FUNCTION(DigestFinal); + SKF_METHOD_BIND_FUNCTION(MacInit); + SKF_METHOD_BIND_FUNCTION(Mac); + SKF_METHOD_BIND_FUNCTION(MacUpdate); + SKF_METHOD_BIND_FUNCTION(MacFinal); + SKF_METHOD_BIND_FUNCTION(CloseHandle); +#ifdef SKF_HAS_ECCDECRYPT + SKF_METHOD_BIND_FUNCTION(ECCDecrypt); +#endif + + ret = skf; + skf = NULL; + +end: + SKF_METHOD_free(skf); + return ret; +} + +void SKF_METHOD_free(SKF_METHOD *meth) +{ + if (meth) + free(meth->dso); + free(meth); +} diff --git a/Core/GmSSL-3.1.1/src/skf/skf_prn.c b/Core/GmSSL-3.1.1/src/skf/skf_prn.c new file mode 100755 index 0000000..8ceaba3 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_prn.c @@ -0,0 +1,286 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include "skf.h" +#include "skf_int.h" +#include "skf_ext.h" + + + +static char *skf_algor_name(ULONG ulAlgID) +{ + switch (ulAlgID) { + case SGD_SM1_ECB: return "sm1-ecb"; + case SGD_SM1_CBC: return "sm1-cbc"; + case SGD_SM1_CFB: return "sm1-cfb"; + case SGD_SM1_OFB: return "sm1-ofb128"; + case SGD_SM1_MAC: return "sm1-mac"; + case SGD_SM4_ECB: return "sms4-ecb"; + case SGD_SM4_CBC: return "sms4-cbc"; + case SGD_SM4_CFB: return "sms4-cfb"; + case SGD_SM4_OFB: return "sms4-ofb128"; + case SGD_SM4_MAC: return "sms4-mac"; + case SGD_SSF33_ECB: return "ssf33-ecb"; + case SGD_SSF33_CBC: return "ssf33-cbc"; + case SGD_SSF33_CFB: return "ssf33-cfb"; + case SGD_SSF33_OFB: return "ssf33-ofb128"; + case SGD_SSF33_MAC: return "ssf33-mac"; + case SGD_RSA: return "rsa"; + case SGD_SM2_1: return "sm2sign"; + case SGD_SM2_2: return "sm2encrypt"; + case SGD_SM2_3: return "sm2keyagreement"; + case SGD_SM3: return "sm3"; + case SGD_SHA1: return "sha1"; + case SGD_SHA256: return "sha256"; + } + return NULL; +} + +ULONG DEVAPI SKF_GetDevStateName(ULONG ulDevState, LPSTR *szDevStateName) +{ + if (!szDevStateName) { + return SAR_INDATALENERR; + } + + switch (ulDevState) { + case SKF_DEV_STATE_ABSENT: + *szDevStateName = (LPSTR)"Absent"; + break; + case SKF_DEV_STATE_PRESENT: + *szDevStateName = (LPSTR)"Present"; + break; + case SKF_DEV_STATE_UNKNOW: + *szDevStateName = (LPSTR)"Unknown"; + break; + default: + *szDevStateName = (LPSTR)"(Error)"; + return SAR_INDATALENERR; + } + + return SAR_OK; +} + +ULONG DEVAPI SKF_GetContainerTypeName(ULONG ulContainerType, LPSTR *szName) +{ + switch (ulContainerType) { + case SKF_CONTAINER_TYPE_UNDEF: + *szName = (LPSTR)"(undef)"; + break; + case SKF_CONTAINER_TYPE_RSA: + *szName = (LPSTR)"RSA"; + break; + case SKF_CONTAINER_TYPE_ECC: + *szName = (LPSTR)"EC"; + break; + default: + *szName = (LPSTR)"(unknown)"; + } + /* always success for help functions */ + return SAR_OK; +} + +typedef struct { + ULONG id; + char *name; +} table_item_t; + +static table_item_t skf_cipher_caps[] = { + { SGD_SM1_ECB, "sm1-ecb" }, + { SGD_SM1_CBC, "sm1-cbc" }, + { SGD_SM1_CFB, "sm1-cfb" }, + { SGD_SM1_OFB, "sm1-ofb128" }, + { SGD_SM1_MAC, "cbcmac-sm1" }, + { SGD_SSF33_ECB, "ssf33-ecb" }, + { SGD_SSF33_CBC, "ssf33-cbc" }, + { SGD_SSF33_CFB, "ssf33-cfb" }, + { SGD_SSF33_OFB, "ssf33-ofb128" }, + { SGD_SSF33_MAC, "cbcmac-ssf33" }, + { SGD_SM4_ECB, "sms4-ecb" }, + { SGD_SM4_CBC, "sms4-cbc" }, + { SGD_SM4_CFB, "sms4-cfb" }, + { SGD_SM4_OFB, "sms4-ofb128" }, + { SGD_SM4_MAC, "cbcmac-sms4" }, + { SGD_ZUC_EEA3, "zuc_128eea3" }, + { SGD_ZUC_EIA3, "zuc_128eia3" } +}; + +static table_item_t skf_digest_caps[] = { + { SGD_SM3, "sm3" }, + { SGD_SHA1, "sha1" }, + { SGD_SHA256, "sha256" }, +}; + +static table_item_t skf_pkey_caps[] = { + { SGD_RSA_SIGN, "rsa" }, + { SGD_RSA_ENC, "rsaEncryption" }, + { SGD_SM2_1, "sm2sign" }, + { SGD_SM2_2, "sm2exchange" }, + { SGD_SM2_3, "sm2encrypt" } +}; + +ULONG DEVAPI SKF_PrintDevInfo(FILE *fp, const DEVINFO *devInfo) +{ + size_t i, n; + int fmt = 0, ind = 4; + + format_print(fp, fmt, ind, "Version: %d.%d\n", devInfo->Version.major, devInfo->Version.minor); + format_print(fp, fmt, ind, "Manufacturer: %s\n", devInfo->Manufacturer); + format_print(fp, fmt, ind, "Issuer: %s\n", devInfo->Issuer); + format_print(fp, fmt, ind, "Label: %s\n", devInfo->Label); + format_bytes(fp, fmt, ind, "SerialNumber", devInfo->SerialNumber, strlen((char *)devInfo->SerialNumber)); + format_print(fp, fmt, ind, "FirmwareVersion: %d.%d\n", devInfo->HWVersion.major, devInfo->HWVersion.minor); + + format_print(fp, fmt, ind, "Ciphers: "); + for (i = n = 0; i < sizeof(skf_cipher_caps)/sizeof(skf_cipher_caps[0]); i++) { + if ((devInfo->AlgSymCap & skf_cipher_caps[i].id) == + skf_cipher_caps[i].id) { + format_print(fp, fmt, 0, "%s%s", n ? "," : "", skf_cipher_caps[i].name); + n++; + } + } + format_print(fp, fmt, 0, "\n"); + + format_print(fp, fmt, ind, "Public Keys: "); + for (i = n = 0; i < sizeof(skf_pkey_caps)/sizeof(skf_pkey_caps[0]); i++) { + if ((devInfo->AlgAsymCap & skf_pkey_caps[i].id) == + skf_pkey_caps[i].id) { + format_print(fp, fmt, 0, "%s%s", n ? "," : "", skf_pkey_caps[i].name); + n++; + } + } + format_print(fp, fmt, 0, "\n"); + + format_print(fp, fmt, ind, "Digests: "); + for (i = n = 0; i < sizeof(skf_digest_caps)/sizeof(skf_digest_caps[0]); i++) { + if ((devInfo->AlgHashCap & skf_digest_caps[i].id) == + skf_digest_caps[i].id) { + format_print(fp, fmt, 0, "%s%s", n ? "," : "", skf_digest_caps[i].name); + n++; + } + } + format_print(fp, fmt, 0, "\n"); + + format_print(fp, fmt, ind, "AuthCipher"); + for (i = 0; i < sizeof(skf_cipher_caps)/sizeof(skf_cipher_caps[0]); i++) { + if (devInfo->DevAuthAlgId == skf_cipher_caps[i].id) { + format_print(fp, fmt, 0, "%s\n", skf_cipher_caps[i].name); + break; + } + } + if (i == sizeof(skf_cipher_caps)/sizeof(skf_cipher_caps[0])) { + format_print(fp, fmt, 0, "(unknown)\n"); + } + format_print(fp, fmt, 0, "\n"); + + + + if (devInfo->TotalSpace == UINT_MAX) + format_print(fp, fmt, ind, "Total Sapce: %s\n", "(unlimited)"); + else format_print(fp, fmt, ind, "Total Sapce: %u\n", devInfo->TotalSpace); + + if (devInfo->FreeSpace == UINT_MAX) + format_print(fp, fmt, ind, "Free Space: %s\n", "(unlimited)"); + else format_print(fp, fmt, ind, "Free Space: %u\n", devInfo->FreeSpace); + + if (devInfo->MaxECCBufferSize == UINT_MAX) + format_print(fp, fmt, ind, "MAX ECC Input: %s\n", "(unlimited)"); + else format_print(fp, fmt, ind, "MAX ECC Input: %u\n", devInfo->MaxECCBufferSize); + + if (devInfo->MaxBufferSize == UINT_MAX) + format_print(fp, fmt, ind, "MAX Cipher Input: %s\n", "(unlimited)"); + else format_print(fp, fmt, ind, "MAX Cipher Input: %u\n", devInfo->MaxBufferSize); + + return SAR_OK; +} + +ULONG DEVAPI SKF_PrintRSAPublicKey(FILE *fp, const RSAPUBLICKEYBLOB *blob) +{ + int fmt = 0, ind = 4; + format_print(fp, fmt, ind, "AlgID: %s\n", skf_algor_name(blob->AlgID)); + format_print(fp, fmt, ind, "BitLen: %u\n", blob->BitLen); + format_bytes(fp, fmt, ind, "Modulus", blob->Modulus, MAX_RSA_MODULUS_LEN); + format_bytes(fp, fmt, ind, "PublicExponent", blob->PublicExponent, MAX_RSA_EXPONENT_LEN); + return SAR_OK; +} + +ULONG DEVAPI SKF_PrintRSAPrivateKey(FILE *fp, const RSAPRIVATEKEYBLOB *blob) +{ + int fmt = 0, ind = 4; + format_print(fp, fmt, ind, "AlgID: %s\n", skf_algor_name(blob->AlgID)); + format_print(fp, fmt, ind, "BitLen: %u\n", blob->BitLen); + format_bytes(fp, fmt, ind, "Modulus", blob->Modulus, MAX_RSA_MODULUS_LEN); + format_bytes(fp, fmt, ind, "PublicExponent", blob->PublicExponent, MAX_RSA_EXPONENT_LEN); + format_bytes(fp, fmt, ind, "PrivateExponent", blob->PrivateExponent, MAX_RSA_MODULUS_LEN); + format_bytes(fp, fmt, ind, "Prime1", blob->Prime1, MAX_RSA_MODULUS_LEN/2); + format_bytes(fp, fmt, ind, "Prime2", blob->Prime2, MAX_RSA_MODULUS_LEN/2); + format_bytes(fp, fmt, ind, "Prime1Exponent", blob->Prime1Exponent, MAX_RSA_MODULUS_LEN/2); + format_bytes(fp, fmt, ind, "Prime2Exponent", blob->Prime2Exponent, MAX_RSA_MODULUS_LEN/2); + format_bytes(fp, fmt, ind, "Coefficient", blob->Coefficient, MAX_RSA_MODULUS_LEN/2); + return SAR_OK; +} + +ULONG DEVAPI SKF_PrintECCPublicKey(FILE *fp, const ECCPUBLICKEYBLOB *blob) +{ + int fmt = 0, ind = 4; + format_print(fp, fmt, ind, "BitLen: %u\n", blob->BitLen); + format_bytes(fp, fmt, ind, "XCoordinate", blob->XCoordinate, ECC_MAX_XCOORDINATE_BITS_LEN/8); + format_bytes(fp, fmt, ind, "YCoordinate", blob->YCoordinate, ECC_MAX_XCOORDINATE_BITS_LEN/8); + return SAR_OK; +} + +ULONG DEVAPI SKF_PrintECCPrivateKey(FILE *fp, const ECCPRIVATEKEYBLOB *blob) +{ + int fmt = 0, ind = 4; + format_print(fp, fmt, ind, "BitLen: %u\n", blob->BitLen); + format_bytes(fp, fmt, ind, "PrivateKey", blob->PrivateKey, ECC_MAX_MODULUS_BITS_LEN/8); + return SAR_OK; +} + +ULONG DEVAPI SKF_PrintECCCipher(FILE *fp, const ECCCIPHERBLOB *blob) +{ + int fmt = 0, ind = 4; + format_bytes(fp, fmt, ind, "XCoordinate", blob->XCoordinate, ECC_MAX_XCOORDINATE_BITS_LEN/8); + format_bytes(fp, fmt, ind, "YCoordinate", blob->YCoordinate, ECC_MAX_XCOORDINATE_BITS_LEN/8); + format_bytes(fp, fmt, ind, "HASH", blob->HASH, 32); + format_print(fp, fmt, ind, "CipherLen: %u\n", blob->CipherLen); + format_bytes(fp, fmt, ind, "Cipher", blob->Cipher, blob->CipherLen); + return SAR_OK; +} + +ULONG DEVAPI SKF_PrintECCSignature(FILE *fp, const ECCSIGNATUREBLOB *blob) +{ + int fmt = 0, ind = 4; + format_bytes(fp, fmt, ind, "r", blob->r, ECC_MAX_XCOORDINATE_BITS_LEN/8); + format_bytes(fp, fmt, ind, "s", blob->s, ECC_MAX_XCOORDINATE_BITS_LEN/8); + return SAR_OK; +} + +ULONG DEVAPI SKF_GetAlgorName(ULONG ulAlgID, LPSTR *szName) +{ + char *name; + if ((name = skf_algor_name(ulAlgID)) != NULL) { + *szName = (LPSTR)&name; + return SAR_OK; + } + return SAR_FAIL; +} + +ULONG DEVAPI SKF_PrintErrorString(FILE *fp, ULONG ulError) +{ + LPSTR str = NULL; + SKF_GetErrorString(ulError, &str); + fprintf(fp, "SKF Error: %s\n", (char *)str); + return SAR_OK; +} diff --git a/Core/GmSSL-3.1.1/src/skf/skf_wisec.c b/Core/GmSSL-3.1.1/src/skf/skf_wisec.c new file mode 100755 index 0000000..df12a86 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_wisec.c @@ -0,0 +1,146 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include "skf_int.h" +#include "skf_wisec.h" + + +typedef struct { + ULONG std_id; + ULONG vendor_id; +} SKF_ALGOR_PAIR; + +static SKF_ALGOR_PAIR wisec_ciphers[] = { + { SGD_SM1, WISEC_SM1 }, + { SGD_SM1_ECB, WISEC_SM1_ECB }, + { SGD_SM1_CBC, WISEC_SM1_CBC }, + { SGD_SM1_CFB, WISEC_SM1_CFB }, + { SGD_SM1_OFB, WISEC_SM1_OFB }, + { SGD_SM1_MAC, WISEC_SM1_MAC }, + { SGD_SM4, WISEC_SM4 }, + { SGD_SM4_ECB, WISEC_SM4_ECB }, + { SGD_SM4_CBC, WISEC_SM4_CBC }, + { SGD_SM4_CFB, WISEC_SM4_CFB }, + { SGD_SM4_OFB, WISEC_SM4_OFB }, + { SGD_SM4_MAC, WISEC_SM4_MAC }, + { SGD_SSF33, WISEC_SSF33 }, + { SGD_SSF33_ECB, WISEC_SSF33_ECB }, + { SGD_SSF33_CBC, WISEC_SSF33_CBC }, + { SGD_SSF33_CFB, WISEC_SSF33_CFB }, + { SGD_SSF33_OFB, WISEC_SSF33_OFB }, + { SGD_SSF33_MAC, WISEC_SSF33_MAC }, +}; + +static ULONG wisec_get_cipher_algor(ULONG vendor_id) +{ + size_t i; + for (i = 0; i < sizeof(wisec_ciphers)/sizeof(wisec_ciphers[0]); i++) { + if (vendor_id == wisec_ciphers[i].vendor_id) { + return wisec_ciphers[i].std_id; + } + } + return 0; +} + +static ULONG wisec_get_cipher_cap(ULONG vendor_cap) +{ + ULONG std_cap = 0; + size_t i; + for (i = 0; i < sizeof(wisec_ciphers)/sizeof(wisec_ciphers[0]); i++) { + if (vendor_cap & wisec_ciphers[i].vendor_id) { + std_cap |= wisec_ciphers[i].std_id; + } + } + return std_cap; +} + +static SKF_ALGOR_PAIR wisec_digests[] = { + { SGD_SM3, WISEC_SM3 }, + { SGD_SHA1, WISEC_SHA1 }, + { SGD_SHA256, WISEC_SHA256 }, +}; + +static ULONG wisec_get_digest_algor(ULONG vendor_id) +{ + size_t i; + for (i = 0; i < sizeof(wisec_digests)/sizeof(wisec_digests[0]); i++) { + if (vendor_id == wisec_digests[i].vendor_id) { + return wisec_digests[i].std_id; + } + } + return 0; +} + +static ULONG wisec_get_digest_cap(ULONG vendor_cap) +{ + ULONG std_cap = 0; + size_t i; + for (i = 0; i < sizeof(wisec_digests)/sizeof(wisec_digests[0]); i++) { + if (vendor_cap & wisec_digests[i].vendor_id) { + std_cap |= wisec_digests[i].std_id; + } + } + return std_cap; +} + +static SKF_ALGOR_PAIR wisec_pkeys[] = { + { SGD_RSA, WISEC_RSA }, + { SGD_RSA_SIGN, WISEC_RSA_SIGN }, + { SGD_RSA_ENC, WISEC_RSA_ENC }, + { SGD_SM2, WISEC_SM2 }, + { SGD_SM2_1, WISEC_SM2_1 }, + { SGD_SM2_2, WISEC_SM2_2 }, + { SGD_SM2_3, WISEC_SM2_3 }, +}; + +static ULONG wisec_get_pkey_algor(ULONG vendor_id) +{ + size_t i; + for (i = 0; i < sizeof(wisec_pkeys)/sizeof(wisec_pkeys[0]); i++) { + if (vendor_id == wisec_pkeys[i].vendor_id) { + return wisec_pkeys[i].std_id; + } + } + return 0; +} + +static ULONG wisec_get_pkey_cap(ULONG vendor_cap) +{ + ULONG std_cap = 0; + size_t i; + for (i = 0; i < sizeof(wisec_pkeys)/sizeof(wisec_pkeys[0]); i++) { + if (vendor_cap & wisec_pkeys[i].vendor_id) { + std_cap |= wisec_pkeys[i].std_id; + } + } + return std_cap; +} + +static unsigned long wisec_get_error_reason(ULONG err) +{ + return 0; +} + +SKF_VENDOR skf_wisec = { + "wisec", + 16, + wisec_get_cipher_algor, + wisec_get_cipher_cap, + wisec_get_digest_algor, + wisec_get_digest_cap, + wisec_get_pkey_algor, + wisec_get_pkey_cap, + wisec_get_error_reason, +}; diff --git a/Core/GmSSL-3.1.1/src/skf/skf_wisec.h b/Core/GmSSL-3.1.1/src/skf/skf_wisec.h new file mode 100755 index 0000000..d90b7dd --- /dev/null +++ b/Core/GmSSL-3.1.1/src/skf/skf_wisec.h @@ -0,0 +1,117 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef HEADER_SKF_WISEC_H +#define HEADER_SKF_WISEC_H + +#include "skf.h" + + +#define WISEC_SM1 (SGD_SM1) +#define WISEC_SM1_ECB (SGD_SM1_ECB) +#define WISEC_SM1_CBC (SGD_SM1_CBC) +#define WISEC_SM1_CFB (SGD_SM1_CFB) +#define WISEC_SM1_OFB (SGD_SM1_OFB) +#define WISEC_SM1_MAC (SGD_SM1_MAC) + +#define WISEC_SSF33 (SGD_SSF33) +#define WISEC_SSF33_ECB (SGD_SSF33_ECB) +#define WISEC_SSF33_CBC (SGD_SSF33_CBC) +#define WISEC_SSF33_CFB (SGD_SSF33_CFB) +#define WISEC_SSF33_OFB (SGD_SSF33_OFB) +#define WISEC_SSF33_MAC (SGD_SSF33_MAC) + +#define WISEC_SM4 (SGD_SM4) +#define WISEC_SM4_ECB (WISEC_SM4|SGD_ECB) +#define WISEC_SM4_CBC (WISEC_SM4|SGD_CBC) +#define WISEC_SM4_CFB (WISEC_SM4|SGD_CFB) +#define WISEC_SM4_OFB (WISEC_SM4|SGD_OFB) +#define WISEC_SM4_MAC (WISEC_SM4|SGD_MAC) + +#define WISEC_AES 0x00000800 +#define WISEC_128 0x00000000 +#define WISEC_192 0x00000010 +#define WISEC_256 0x00000020 +#define WISEC_AES128 (WISEC_AES|WISEC_128) +#define WISEC_AES192 (WISEC_AES|WISEC_192) +#define WISEC_AES256 (WISEC_AES|WISEC_256) +#define WISEC_AES128_ECB (WISEC_AES128|SGD_ECB) +#define WISEC_AES128_CBC (WISEC_AES128|SGD_CBC) +#define WISEC_AES128_CFB (WISEC_AES128|SGD_CFB) +#define WISEC_AES128_OFB (WISEC_AES128|SGD_OFB) +#define WISEC_AES128_MAC (WISEC_AES128|SGD_MAC) +#define WISEC_AES192_ECB (WISEC_AES192|SGD_ECB) +#define WISEC_AES192_CBC (WISEC_AES192|SGD_CBC) +#define WISEC_AES192_CFB (WISEC_AES192|SGD_CFB) +#define WISEC_AES192_OFB (WISEC_AES192|SGD_OFB) +#define WISEC_AES192_MAC (WISEC_AES192|SGD_MAC) +#define WISEC_AES256_ECB (WISEC_AES256|SGD_ECB) +#define WISEC_AES256_CBC (WISEC_AES256|SGD_CBC) +#define WISEC_AES256_CFB (WISEC_AES256|SGD_CFB) +#define WISEC_AES256_OFB (WISEC_AES256|SGD_OFB) +#define WISEC_AES256_MAC (WISEC_AES256|SGD_MAC) + +#define WISEC_DES 0x00001000 +#define WISEC_DES_ECB (WISEC_DES|SGD_ECB) +#define WISEC_DES_CBC (WISEC_DES|SGD_CBC) +#define WISEC_DES_CFB (WISEC_DES|SGD_CFB) +#define WISEC_DES_OFB (WISEC_DES|SGD_OFB) +#define WISEC_DES_MAC (WISEC_DES|SGD_MAC) + +#define WISEC_D3DES 0x00001010 +#define WISEC_D3DES_ECB (WISEC_D3DES|SGD_ECB) +#define WISEC_D3DES_CBC (WISEC_D3DES|SGD_CBC) +#define WISEC_D3DES_CFB (WISEC_D3DES|SGD_CFB) +#define WISEC_D3DES_OFB (WISEC_D3DES|SGD_OFB) +#define WISEC_D3DES_MAC (WISEC_D3DES|SGD_MAC) + +#define WISEC_T3DES 0x00001020 +#define WISEC_T3DES_ECB (WISEC_T3DES|SGD_ECB) +#define WISEC_T3DES_CBC (WISEC_T3DES|SGD_CBC) +#define WISEC_T3DES_CFB (WISEC_T3DES|SGD_CFB) +#define WISEC_T3DES_OFB (WISEC_T3DES|SGD_OFB) +#define WISEC_T3DES_MAC (WISEC_T3DES|SGD_MAC) + +#define WISEC_SM3 (SGD_SM3) +#define WISEC_SHA1 (SGD_SHA1) +#define WISEC_SHA256 (SGD_SHA256) + +#define WISEC_RSA (SGD_RSA) +#define WISEC_RSA_SIGN (SGD_RSA_SIGN) +#define WISEC_RSA_ENC (SGD_RSA_ENC) +#define WISEC_SM2 (SGD_SM2) +#define WISEC_SM2_1 (SGD_SM2_1) +#define WISEC_SM2_2 (SGD_SM2_2) +#define WISEC_SM2_3 (SGD_SM2_3) + + +#define WISEC_AUTH_BLOCKED 0x0A000033 +#define WISEC_CERTNOUSAGEERR 0x0A000034 +#define WISEC_INVALIDCONTAINERERR 0x0A000035 +#define WISEC_CONTAINER_NOT_EXISTS 0x0A000036 +#define WISEC_CONTAINER_EXISTS 0x0A000037 +#define WISEC_CERTUSAGEERR 0x0A000038 +#define WISEC_KEYNOUSAGEERR 0x0A000039 +#define WISEC_FILEATTRIBUTEERR 0x0A00003A +#define WISEC_DEVNOAUTH 0x0A00003B + +/* +ULONG DEVAPI SKFE_SetSN(DEVHANDLE hDev, CHAR *SN, UINT SNLen); +ULONG DEVAPI SKFE_GenExtECCKey(DEVHANDLE hDev, PECCPRIVATEKEYBLOB pPriBlob, PECCPUBLICKEYBLOB pPubBlob); +ULONG DEVAPI SKF_ECCDecrypt(HCONTAINER hContainer, PECCCIPHERBLOB pCipherText, BYTE *pbPlainText,ULONG *pulPlainTextLen); +ULONG DEVAPI SKF_GenerateKey(HCONTAINER hContainer, ULONG ulAlgId, HANDLE *phSessionKey) ; +ULONG DEVAPI SKF_ECCExportSessionKeyByHandle(HANDLE phSessionKey, ECCPUBLICKEYBLOB *pPubKey,PECCCIPHERBLOB pData); +ULONG DEVAPI SKF_RSAExportSessionKeyByHandle(HANDLE phSessionKey, RSAPUBLICKEYBLOB*pPubKey,BYTE *pbData, ULONG *pulDataLen); +ULONG DEVAPI SKF_PrvKeyDecrypt(HCONTAINER hContainer, PECCCIPHERBLOB pCipherText, BYTE *pbData, ULONG *pbDataLen); +ULONG DEVAPI SKF_PrvKeyDecrypt(HCONTAINER hContainer, ULONG ulType, PECCCIPHERBLOB pCipherText, BYTE *pbData, ULONG *pbDataLen); +ULONG DEVAPI SKF_RSAPrvKeyDecrypt(HCONTAINER hContainer, BYTE *pCipherData, ULONG pCipherDataLen, BYTE *pbData, ULONG *pbDataLen); +*/ + +#endif diff --git a/Core/GmSSL-3.1.1/src/sm2_alg.c b/Core/GmSSL-3.1.1/src/sm2_alg.c new file mode 100644 index 0000000..7b2c2e7 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_alg.c @@ -0,0 +1,1351 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define sm2_print_bn(label,a) sm2_bn_print(stderr,0,0,label,a) // 这个不应该放在这里,应该放在测试文件中 + + + +const SM2_BN SM2_P = { + 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, +}; + +const SM2_BN SM2_B = { + 0x4d940e93, 0xddbcbd41, 0x15ab8f92, 0xf39789f5, + 0xcf6509a7, 0x4d5a9e4b, 0x9d9f5e34, 0x28e9fa9e, +}; + +const SM2_JACOBIAN_POINT _SM2_G = { + { + 0x334c74c7, 0x715a4589, 0xf2660be1, 0x8fe30bbf, + 0x6a39c994, 0x5f990446, 0x1f198119, 0x32c4ae2c, + }, + { + 0x2139f0a0, 0x02df32e5, 0xc62a4740, 0xd0a9877c, + 0x6b692153, 0x59bdcee3, 0xf4f6779c, 0xbc3736a2, + }, + { + 1, 0, 0, 0, 0, 0, 0, 0, + }, +}; +const SM2_JACOBIAN_POINT *SM2_G = &_SM2_G; + +const SM2_BN SM2_N = { + 0x39d54123, 0x53bbf409, 0x21c6052b, 0x7203df6b, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, +}; + +// u = (p - 1)/4, u + 1 = (p + 1)/4 +const SM2_BN SM2_U_PLUS_ONE = { + 0x00000000, 0x40000000, 0xc0000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xbfffffff, 0x3fffffff, +}; + +const SM2_BN SM2_ONE = {1,0,0,0,0,0,0,0}; +const SM2_BN SM2_TWO = {2,0,0,0,0,0,0,0}; +const SM2_BN SM2_THREE = {3,0,0,0,0,0,0,0}; + + + +int sm2_bn_check(const SM2_BN a) +{ + int err = 0; + int i; + for (i = 0; i < 8; i++) { + if (a[i] > 0xffffffff) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + err++; + } + } + if (err) + return -1; + else return 1; +} + +int sm2_bn_is_zero(const SM2_BN a) +{ + int i; + for (i = 0; i < 8; i++) { + if (a[i] != 0) + return 0; + } + return 1; +} + +int sm2_bn_is_one(const SM2_BN a) +{ + int i; + if (a[0] != 1) + return 0; + for (i = 1; i < 8; i++) { + if (a[i] != 0) + return 0; + } + return 1; +} + +void sm2_bn_to_bytes(const SM2_BN a, uint8_t out[32]) +{ + int i; + uint8_t *p = out; + + /* + fprintf(stderr, "sm2_bn_to_bytes:\n"); + for (i = 0; i < 8; i++) { + fprintf(stderr, "%016lx ", a[i]); + } + fprintf(stderr, "\n"); + */ + + for (i = 7; i >= 0; i--) { + uint32_t ai = (uint32_t)a[i]; + PUTU32(out, ai); + out += sizeof(uint32_t); + } + + /* + for (i = 0; i < 32; i++) { + fprintf(stderr, "%02X ", p[i]); + } + */ + +} + +void sm2_bn_from_bytes(SM2_BN r, const uint8_t in[32]) +{ + int i; + for (i = 7; i >= 0; i--) { + r[i] = GETU32(in); + in += sizeof(uint32_t); + } +} + +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; +} + +static int hex2bin(const char *in, size_t inlen, uint8_t *out) +{ + int c; + if (inlen % 2) + return -1; + + while (inlen) { + if ((c = hexchar2int(*in++)) < 0) + return -1; + *out = (uint8_t)c << 4; + if ((c = hexchar2int(*in++)) < 0) + return -1; + *out |= (uint8_t)c; + inlen -= 2; + out++; + } + return 1; +} + +void sm2_bn_to_hex(const SM2_BN a, char hex[64]) +{ + int i; + for (i = 7; i >= 0; i--) { + int len; + len = sprintf(hex, "%08x", (uint32_t)a[i]); + assert(len == 8); + hex += 8; + } +} + +int sm2_bn_from_hex(SM2_BN r, const char hex[64]) +{ + uint8_t buf[32]; + if (hex2bin(hex, 64, buf) < 0) + return -1; + sm2_bn_from_bytes(r, buf); + return 1; +} + +int sm2_bn_from_asn1_integer(SM2_BN r, const uint8_t *d, size_t dlen) +{ + uint8_t buf[32] = {0}; + if (!d || dlen == 0) { + error_print(); + return -1; + } + if (dlen > sizeof(buf)) { + error_print(); + return -1; + } + memcpy(buf + sizeof(buf) - dlen, d, dlen); + sm2_bn_from_bytes(r, buf); + return 1; +} + +int sm2_bn_print(FILE *fp, int fmt, int ind, const char *label, const SM2_BN a) +{ + int ret = 0, i; + format_print(fp, fmt, ind, "%s: ", label); + + for (i = 7; i >= 0; i--) { + if (a[i] >= ((uint64_t)1 << 32)) { + printf("bn_print check failed\n"); + } + ret += fprintf(fp, "%08x", (uint32_t)a[i]); + } + ret += fprintf(fp, "\n"); + return ret; +} + +void sm2_bn_to_bits(const SM2_BN a, char bits[256]) +{ + int i, j; + uint64_t w; + for (i = 7; i >= 0; i--) { + w = a[i]; + for (j = 0; j < 32; j++) { + *bits++ = (w & 0x80000000) ? '1' : '0'; + w <<= 1; + } + } +} + +int sm2_bn_cmp(const SM2_BN a, const SM2_BN b) +{ + int i; + for (i = 7; i >= 0; i--) { + if (a[i] > b[i]) + return 1; + if (a[i] < b[i]) + return -1; + } + return 0; +} + +int sm2_bn_equ_hex(const SM2_BN a, const char *hex) +{ + char buf[65] = {0}; + char *p = buf; + int i; + + for (i = 7; i >= 0; i--) { + sprintf(p, "%08x", (uint32_t)a[i]); + p += 8; + } + return (strcmp(buf, hex) == 0); +} + +int sm2_bn_is_odd(const SM2_BN a) +{ + return a[0] & 0x01; +} + +void sm2_bn_set_word(SM2_BN r, uint32_t a) +{ + int i; + r[0] = a; + for (i = 1; i < 8; i++) { + r[i] = 0; + } +} + +int sm2_bn_rshift(SM2_BN ret, const SM2_BN a, unsigned int nbits) +{ + SM2_BN r; + int i; + + if (nbits > 31) { + error_print(); + return -1; + } + if (nbits == 0) { + sm2_bn_copy(ret, a); + } + + for (i = 0; i < 7; i++) { + r[i] = a[i] >> nbits; + r[i] |= (a[i+1] << (32 - nbits)) & 0xffffffff; + } + r[i] = a[i] >> nbits; + sm2_bn_copy(ret, r); + return 1; +} + +void sm2_bn_add(SM2_BN r, const SM2_BN a, const SM2_BN b) +{ + int i; + r[0] = a[0] + b[0]; + + for (i = 1; i < 8; i++) { + r[i] = a[i] + b[i] + (r[i-1] >> 32); + } + for (i = 0; i < 7; i++) { + r[i] &= 0xffffffff; + } +} + +void sm2_bn_sub(SM2_BN ret, const SM2_BN a, const SM2_BN b) +{ + int i; + SM2_BN r; + r[0] = ((uint64_t)1 << 32) + a[0] - b[0]; + for (i = 1; i < 7; i++) { + r[i] = 0xffffffff + a[i] - b[i] + (r[i - 1] >> 32); + r[i - 1] &= 0xffffffff; + } + r[i] = a[i] - b[i] + (r[i - 1] >> 32) - 1; + r[i - 1] &= 0xffffffff; + sm2_bn_copy(ret, r); +} + +int sm2_bn_rand_range(SM2_BN r, const SM2_BN range) +{ + uint8_t buf[32]; + do { + if (rand_bytes(buf, sizeof(buf)) != 1) { + error_print(); + return -1; + } + sm2_bn_from_bytes(r, buf); + } while (sm2_bn_cmp(r, range) >= 0); + return 1; +} + +int sm2_fp_rand(SM2_Fp r) +{ + if (sm2_bn_rand_range(r, SM2_P) != 1) { + error_print(); + return -1; + } + return 1; +} + +void sm2_fp_add(SM2_Fp r, const SM2_Fp a, const SM2_Fp b) +{ + sm2_bn_add(r, a, b); + if (sm2_bn_cmp(r, SM2_P) >= 0) { + sm2_bn_sub(r, r, SM2_P); + } +} + +void sm2_fp_sub(SM2_Fp r, const SM2_Fp a, const SM2_Fp b) +{ + if (sm2_bn_cmp(a, b) >= 0) { + sm2_bn_sub(r, a, b); + } else { + SM2_BN t; + sm2_bn_sub(t, SM2_P, b); + sm2_bn_add(r, t, a); + } +} + +void sm2_fp_dbl(SM2_Fp r, const SM2_Fp a) +{ + sm2_fp_add(r, a, a); +} + +void sm2_fp_tri(SM2_Fp r, const SM2_Fp a) +{ + SM2_BN t; + sm2_fp_dbl(t, a); + sm2_fp_add(r, t, a); +} + +void sm2_fp_div2(SM2_Fp r, const SM2_Fp a) +{ + int i; + sm2_bn_copy(r, a); + if (r[0] & 0x01) { + sm2_bn_add(r, r, SM2_P); + } + for (i = 0; i < 7; i++) { + r[i] = (r[i] >> 1) | ((r[i + 1] & 0x01) << 31); + } + r[i] >>= 1; +} + +void sm2_fp_neg(SM2_Fp r, const SM2_Fp a) +{ + if (sm2_bn_is_zero(a)) { + sm2_bn_copy(r, a); + } else { + sm2_bn_sub(r, SM2_P, a); + } +} + +void sm2_fp_mul(SM2_Fp r, const SM2_Fp a, const SM2_Fp b) +{ + int i, j; + uint64_t s[16] = {0}; + SM2_BN d = {0}; + uint64_t u; + + // s = a * b + for (i = 0; i < 8; i++) { + u = 0; + for (j = 0; j < 8; j++) { + u = s[i + j] + a[i] * b[j] + u; + s[i + j] = u & 0xffffffff; + u >>= 32; + } + s[i + 8] = u; + } + + r[0] = s[0] + s[ 8] + s[ 9] + s[10] + s[11] + s[12] + ((s[13] + s[14] + s[15]) << 1); + r[1] = s[1] + s[ 9] + s[10] + s[11] + s[12] + s[13] + ((s[14] + s[15]) << 1); + r[2] = s[2]; + r[3] = s[3] + s[ 8] + s[11] + s[12] + s[14] + s[15] + (s[13] << 1); + r[4] = s[4] + s[ 9] + s[12] + s[13] + s[15] + (s[14] << 1); + r[5] = s[5] + s[10] + s[13] + s[14] + (s[15] << 1); + r[6] = s[6] + s[11] + s[14] + s[15]; + r[7] = s[7] + s[ 8] + s[ 9] + s[10] + s[11] + s[15] + ((s[12] + s[13] + s[14] + s[15]) << 1); + + for (i = 1; i < 8; i++) { + r[i] += r[i - 1] >> 32; + r[i - 1] &= 0xffffffff; + } + + d[2] = s[8] + s[9] + s[13] + s[14]; + d[3] = d[2] >> 32; + d[2] &= 0xffffffff; + sm2_bn_sub(r, r, d); + + // max times ? + while (sm2_bn_cmp(r, SM2_P) >= 0) { + sm2_bn_sub(r, r, SM2_P); + } +} + +void sm2_fp_sqr(SM2_Fp r, const SM2_Fp a) +{ + sm2_fp_mul(r, a, a); +} + +void sm2_fp_exp(SM2_Fp r, const SM2_Fp a, const SM2_Fp e) +{ + SM2_BN t; + uint32_t w; + int i, j; + + sm2_bn_set_one(t); + for (i = 7; i >= 0; i--) { + w = (uint32_t)e[i]; + for (j = 0; j < 32; j++) { + sm2_fp_sqr(t, t); + if (w & 0x80000000) + sm2_fp_mul(t, t, a); + w <<= 1; + } + } + + sm2_bn_copy(r, t); +} + +void sm2_fp_inv(SM2_Fp r, const SM2_Fp a) +{ + SM2_BN a1; + SM2_BN a2; + SM2_BN a3; + SM2_BN a4; + SM2_BN a5; + int i; + + sm2_fp_sqr(a1, a); + sm2_fp_mul(a2, a1, a); + sm2_fp_sqr(a3, a2); + sm2_fp_sqr(a3, a3); + sm2_fp_mul(a3, a3, a2); + sm2_fp_sqr(a4, a3); + sm2_fp_sqr(a4, a4); + sm2_fp_sqr(a4, a4); + sm2_fp_sqr(a4, a4); + sm2_fp_mul(a4, a4, a3); + sm2_fp_sqr(a5, a4); + for (i = 1; i < 8; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a4); + for (i = 0; i < 8; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a4); + for (i = 0; i < 4; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a3); + sm2_fp_sqr(a5, a5); + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a2); + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a); + sm2_fp_sqr(a4, a5); + sm2_fp_mul(a3, a4, a1); + sm2_fp_sqr(a5, a4); + for (i = 1; i< 31; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a4, a5, a4); + sm2_fp_sqr(a4, a4); + sm2_fp_mul(a4, a4, a); + sm2_fp_mul(a3, a4, a2); + for (i = 0; i < 33; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(r, a4, a5); + + sm2_bn_clean(a1); + sm2_bn_clean(a2); + sm2_bn_clean(a3); + sm2_bn_clean(a4); + sm2_bn_clean(a5); +} + +int sm2_fp_sqrt(SM2_Fp r, const SM2_Fp a) +{ + SM2_BN u; + SM2_BN y; // temp result, prevent call sm2_fp_sqrt(a, a) + + // r = a^((p + 1)/4) when p = 3 (mod 4) + sm2_bn_add(u, SM2_P, SM2_ONE); + sm2_bn_rshift(u, u, 2); + sm2_fp_exp(y, a, u); + + // check r^2 == a + sm2_fp_sqr(u, y); + if (sm2_bn_cmp(u, a) != 0) { + error_print(); + return -1; + } + + sm2_bn_copy(r, y); + return 1; +} + +void sm2_fn_add(SM2_Fn r, const SM2_Fn a, const SM2_Fn b) +{ + sm2_bn_add(r, a, b); + if (sm2_bn_cmp(r, SM2_N) >= 0) { + sm2_bn_sub(r, r, SM2_N); + } +} + +void sm2_fn_sub(SM2_Fn r, const SM2_Fn a, const SM2_Fn b) +{ + if (sm2_bn_cmp(a, b) >= 0) { + sm2_bn_sub(r, a, b); + } else { + SM2_BN t; + sm2_bn_add(t, a, SM2_N); + sm2_bn_sub(r, t, b); + } +} + +void sm2_fn_neg(SM2_Fn r, const SM2_Fn a) +{ + if (sm2_bn_is_zero(a)) { + sm2_bn_copy(r, a); + } else { + sm2_bn_sub(r, SM2_N, a); + } +} + +/* bn288 only used in barrett reduction */ +static int sm2_bn288_cmp(const uint64_t a[9], const uint64_t b[9]) +{ + int i; + for (i = 8; i >= 0; i--) { + if (a[i] > b[i]) + return 1; + if (a[i] < b[i]) + return -1; + } + return 0; +} + +static void sm2_bn288_add(uint64_t r[9], const uint64_t a[9], const uint64_t b[9]) +{ + int i; + r[0] = a[0] + b[0]; + for (i = 1; i < 9; i++) { + r[i] = a[i] + b[i] + (r[i-1] >> 32); + } + for (i = 0; i < 8; i++) { + r[i] &= 0xffffffff; + } +} + +static void sm2_bn288_sub(uint64_t ret[9], const uint64_t a[9], const uint64_t b[9]) +{ + int i; + uint64_t r[9]; + + r[0] = ((uint64_t)1 << 32) + a[0] - b[0]; + for (i = 1; i < 8; i++) { + r[i] = 0xffffffff + a[i] - b[i] + (r[i - 1] >> 32); + r[i - 1] &= 0xffffffff; + } + r[i] = a[i] - b[i] + (r[i - 1] >> 32) - 1; + r[i - 1] &= 0xffffffff; + + for (i = 0; i < 9; i++) { + ret[i] = r[i]; + } +} + +void sm2_fn_mul(SM2_BN ret, const SM2_BN a, const SM2_BN b) +{ + SM2_BN r; + static const uint64_t mu[9] = { + 0xf15149a0, 0x12ac6361, 0xfa323c01, 0x8dfc2096, 1, 1, 1, 1, 1, + }; + + uint64_t s[18]; + uint64_t zh[9]; + uint64_t zl[9]; + uint64_t q[9]; + uint64_t w; + int i, j; + + /* z = a * b */ + for (i = 0; i < 8; i++) { + s[i] = 0; + } + for (i = 0; i < 8; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + a[i] * b[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + + /* zl = z mod (2^32)^9 = z[0..8] + * zh = z // (2^32)^7 = z[7..15] */ + for (i = 0; i < 9; i++) { + zl[i] = s[i]; + zh[i] = s[7 + i]; + } + //printf("zl = "); for (i = 8; i >= 0; i--) printf("%08x", (uint32_t)zl[i]); printf("\n"); + //printf("zh = "); for (i = 8; i >= 0; i--) printf("%08x", (uint32_t)zh[i]); printf("\n"); + + /* q = zh * mu // (2^32)^9 */ + for (i = 0; i < 9; i++) { + s[i] = 0; + } + for (i = 0; i < 9; i++) { + w = 0; + for (j = 0; j < 9; j++) { + w += s[i + j] + zh[i] * mu[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 9] = w; + } + for (i = 0; i < 8; i++) { + q[i] = s[9 + i]; + } + //printf("q = "); for (i = 7; i >= 0; i--) printf("%08x", (uint32_t)q[i]); printf("\n"); + + /* q = q * n mod (2^32)^9 */ + for (i = 0; i < 17; i++) { + s[i] = 0; + } + for (i = 0; i < 8; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + q[i] * SM2_N[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + for (i = 0; i < 9; i++) { + q[i] = s[i]; + } + //printf("qn = "); for (i = 8; i >= 0; i--) printf("%08x ", (uint32_t)q[i]); printf("\n"); + + /* r = zl - q (mod (2^32)^9) */ + + if (sm2_bn288_cmp(zl, q)) { + sm2_bn288_sub(zl, zl, q); + } else { + uint64_t c[9] = {0,0,0,0,0,0,0,0,0x100000000}; + sm2_bn288_sub(q, c, q); + sm2_bn288_add(zl, q, zl); + } + //printf("zl = "); for (i = 8; i >= 0; i--) printf("%08x ", (uint32_t)zl[i]); printf("\n"); + for (i = 0; i < 8; i++) { + r[i] = zl[i]; + } + r[7] += zl[8] << 32; + + /* while r >= p do: r = r - n */ + while (sm2_bn_cmp(r, SM2_N) >= 0) { + sm2_bn_sub(r, r, SM2_N); + //printf("r-n = "); for (i = 7; i >= 0; i--) printf("%16llx ", r[i]); printf("\n"); + } + sm2_bn_copy(ret, r); +} + +void sm2_fn_mul_word(SM2_Fn r, const SM2_Fn a, uint32_t b) +{ + SM2_Fn t; + sm2_bn_set_word(t, b); + sm2_fn_mul(r, a, t); +} + +void sm2_fn_sqr(SM2_BN r, const SM2_BN a) +{ + sm2_fn_mul(r, a, a); +} + +void sm2_fn_exp(SM2_BN r, const SM2_BN a, const SM2_BN e) +{ + SM2_BN t; + uint32_t w; + int i, j; + + sm2_bn_set_one(t); + for (i = 7; i >= 0; i--) { + w = (uint32_t)e[i]; + for (j = 0; j < 32; j++) { + sm2_fn_sqr(t, t); + if (w & 0x80000000) { + sm2_fn_mul(t, t, a); + } + w <<= 1; + } + } + sm2_bn_copy(r, t); +} + +void sm2_fn_inv(SM2_BN r, const SM2_BN a) +{ + SM2_BN e; + sm2_bn_sub(e, SM2_N, SM2_TWO); + sm2_fn_exp(r, a, e); +} + +int sm2_fn_rand(SM2_BN r) +{ + if (sm2_bn_rand_range(r, SM2_N) != 1) { + error_print(); + return -1; + } + return 1; +} + + + +void sm2_jacobian_point_init(SM2_JACOBIAN_POINT *R) +{ + memset(R, 0, sizeof(SM2_JACOBIAN_POINT)); + R->X[0] = 1; + R->Y[0] = 1; +} + +int sm2_jacobian_point_is_at_infinity(const SM2_JACOBIAN_POINT *P) +{ + return sm2_bn_is_zero(P->Z); +} + +void sm2_jacobian_point_set_xy(SM2_JACOBIAN_POINT *R, const SM2_BN x, const SM2_BN y) +{ + sm2_bn_copy(R->X, x); + sm2_bn_copy(R->Y, y); + sm2_bn_set_one(R->Z); +} + +void sm2_jacobian_point_get_xy(const SM2_JACOBIAN_POINT *P, SM2_BN x, SM2_BN y) +{ + if (sm2_bn_is_one(P->Z)) { + sm2_bn_copy(x, P->X); + if (y) { + sm2_bn_copy(y, P->Y); + } + } else { + SM2_BN z_inv; + sm2_fp_inv(z_inv, P->Z); + if (y) { + sm2_fp_mul(y, P->Y, z_inv); + } + sm2_fp_sqr(z_inv, z_inv); + sm2_fp_mul(x, P->X, z_inv); + if (y) { + sm2_fp_mul(y, y, z_inv); + } + } +} + +int sm2_jacobian_pointpoint_print(FILE *fp, int fmt, int ind, const char *label, const SM2_JACOBIAN_POINT *P) +{ + int len = 0; + SM2_BN x; + SM2_BN y; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + sm2_jacobian_point_get_xy(P, x, y); + + sm2_bn_print(fp, fmt, ind, "x", x); + sm2_bn_print(fp, fmt, ind, "y", y); + + return 1; +} + +int sm2_jacobian_point_is_on_curve(const SM2_JACOBIAN_POINT *P) +{ + SM2_BN t0; + SM2_BN t1; + SM2_BN t2; + + if (sm2_bn_is_one(P->Z)) { + sm2_fp_sqr(t0, P->Y); + sm2_fp_add(t0, t0, P->X); + sm2_fp_add(t0, t0, P->X); + sm2_fp_add(t0, t0, P->X); + sm2_fp_sqr(t1, P->X); + sm2_fp_mul(t1, t1, P->X); + sm2_fp_add(t1, t1, SM2_B); + } else { + sm2_fp_sqr(t0, P->Y); + sm2_fp_sqr(t1, P->Z); + sm2_fp_sqr(t2, t1); + sm2_fp_mul(t1, t1, t2); + sm2_fp_mul(t1, t1, SM2_B); + sm2_fp_mul(t2, t2, P->X); + sm2_fp_add(t0, t0, t2); + sm2_fp_add(t0, t0, t2); + sm2_fp_add(t0, t0, t2); + sm2_fp_sqr(t2, P->X); + sm2_fp_mul(t2, t2, P->X); + sm2_fp_add(t1, t1, t2); + } + + if (sm2_bn_cmp(t0, t1) != 0) { + error_print(); + return -1; + } + return 1; +} + +void sm2_jacobian_point_neg(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P) +{ + sm2_bn_copy(R->X, P->X); + sm2_fp_neg(R->Y, P->Y); + sm2_bn_copy(R->Z, P->Z); +} + +void sm2_jacobian_point_dbl(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P) +{ + const uint64_t *X1 = P->X; + const uint64_t *Y1 = P->Y; + const uint64_t *Z1 = P->Z; + SM2_BN T1; + SM2_BN T2; + SM2_BN T3; + SM2_BN X3; + SM2_BN Y3; + SM2_BN Z3; + //printf("X1 = "); print_bn(X1); + //printf("Y1 = "); print_bn(Y1); + //printf("Z1 = "); print_bn(Z1); + + if (sm2_jacobian_point_is_at_infinity(P)) { + sm2_jacobian_point_copy(R, P); + return; + } + + sm2_fp_sqr(T1, Z1); //printf("T1 = Z1^2 = "); print_bn(T1); + sm2_fp_sub(T2, X1, T1); //printf("T2 = X1 - T1 = "); print_bn(T2); + sm2_fp_add(T1, X1, T1); //printf("T1 = X1 + T1 = "); print_bn(T1); + sm2_fp_mul(T2, T2, T1); //printf("T2 = T2 * T1 = "); print_bn(T2); + sm2_fp_tri(T2, T2); //printf("T2 = 3 * T2 = "); print_bn(T2); + sm2_fp_dbl(Y3, Y1); //printf("Y3 = 2 * Y1 = "); print_bn(Y3); + sm2_fp_mul(Z3, Y3, Z1); //printf("Z3 = Y3 * Z1 = "); print_bn(Z3); + sm2_fp_sqr(Y3, Y3); //printf("Y3 = Y3^2 = "); print_bn(Y3); + sm2_fp_mul(T3, Y3, X1); //printf("T3 = Y3 * X1 = "); print_bn(T3); + sm2_fp_sqr(Y3, Y3); //printf("Y3 = Y3^2 = "); print_bn(Y3); + sm2_fp_div2(Y3, Y3); //printf("Y3 = Y3/2 = "); print_bn(Y3); + sm2_fp_sqr(X3, T2); //printf("X3 = T2^2 = "); print_bn(X3); + sm2_fp_dbl(T1, T3); //printf("T1 = 2 * T1 = "); print_bn(T1); + sm2_fp_sub(X3, X3, T1); //printf("X3 = X3 - T1 = "); print_bn(X3); + sm2_fp_sub(T1, T3, X3); //printf("T1 = T3 - X3 = "); print_bn(T1); + sm2_fp_mul(T1, T1, T2); //printf("T1 = T1 * T2 = "); print_bn(T1); + sm2_fp_sub(Y3, T1, Y3); //printf("Y3 = T1 - Y3 = "); print_bn(Y3); + + sm2_bn_copy(R->X, X3); + sm2_bn_copy(R->Y, Y3); + sm2_bn_copy(R->Z, Z3); + + //printf("X3 = "); print_bn(R->X); + //printf("Y3 = "); print_bn(R->Y); + //printf("Z3 = "); print_bn(R->Z); + +} + +void sm2_jacobian_point_add(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P, const SM2_JACOBIAN_POINT *Q) +{ + const uint64_t *X1 = P->X; + const uint64_t *Y1 = P->Y; + const uint64_t *Z1 = P->Z; + const uint64_t *x2 = Q->X; + const uint64_t *y2 = Q->Y; + SM2_BN T1; + SM2_BN T2; + SM2_BN T3; + SM2_BN T4; + SM2_BN X3; + SM2_BN Y3; + SM2_BN Z3; + + if (sm2_jacobian_point_is_at_infinity(Q)) { + sm2_jacobian_point_copy(R, P); + return; + } + + if (sm2_jacobian_point_is_at_infinity(P)) { + sm2_jacobian_point_copy(R, Q); + return; + } + + assert(sm2_bn_is_one(Q->Z)); + + sm2_fp_sqr(T1, Z1); + sm2_fp_mul(T2, T1, Z1); + sm2_fp_mul(T1, T1, x2); + sm2_fp_mul(T2, T2, y2); + sm2_fp_sub(T1, T1, X1); + sm2_fp_sub(T2, T2, Y1); + if (sm2_bn_is_zero(T1)) { + if (sm2_bn_is_zero(T2)) { + SM2_JACOBIAN_POINT _Q, *Q = &_Q; + sm2_jacobian_point_set_xy(Q, x2, y2); + + sm2_jacobian_point_dbl(R, Q); + return; + } else { + sm2_jacobian_point_set_infinity(R); + return; + } + } + sm2_fp_mul(Z3, Z1, T1); + sm2_fp_sqr(T3, T1); + sm2_fp_mul(T4, T3, T1); + sm2_fp_mul(T3, T3, X1); + sm2_fp_dbl(T1, T3); + sm2_fp_sqr(X3, T2); + sm2_fp_sub(X3, X3, T1); + sm2_fp_sub(X3, X3, T4); + sm2_fp_sub(T3, T3, X3); + sm2_fp_mul(T3, T3, T2); + sm2_fp_mul(T4, T4, Y1); + sm2_fp_sub(Y3, T3, T4); + + sm2_bn_copy(R->X, X3); + sm2_bn_copy(R->Y, Y3); + sm2_bn_copy(R->Z, Z3); +} + +void sm2_jacobian_point_sub(SM2_JACOBIAN_POINT *R, const SM2_JACOBIAN_POINT *P, const SM2_JACOBIAN_POINT *Q) +{ + SM2_JACOBIAN_POINT _T, *T = &_T; + sm2_jacobian_point_neg(T, Q); + sm2_jacobian_point_add(R, P, T); +} + +void sm2_jacobian_point_mul(SM2_JACOBIAN_POINT *R, const SM2_BN k, const SM2_JACOBIAN_POINT *P) +{ + char bits[257] = {0}; + SM2_JACOBIAN_POINT _Q, *Q = &_Q; + SM2_JACOBIAN_POINT _T, *T = &_T; + int i; + + // FIXME: point_add need affine, so we can not use point_add + if (!sm2_bn_is_one(P->Z)) { + SM2_BN x; + SM2_BN y; + sm2_jacobian_point_get_xy(P, x, y); + sm2_jacobian_point_set_xy(T, x, y); + P = T; + } + + sm2_jacobian_point_set_infinity(Q); + sm2_bn_to_bits(k, bits); + for (i = 0; i < 256; i++) { + sm2_jacobian_point_dbl(Q, Q); + if (bits[i] == '1') { + sm2_jacobian_point_add(Q, Q, P); + } + } + sm2_jacobian_point_copy(R, Q); +} + +void sm2_jacobian_point_to_bytes(const SM2_JACOBIAN_POINT *P, uint8_t out[64]) +{ + SM2_BN x; + SM2_BN y; + sm2_jacobian_point_get_xy(P, x, y); + sm2_bn_to_bytes(x, out); + sm2_bn_to_bytes(y, out + 32); +} + +void sm2_jacobian_point_from_bytes(SM2_JACOBIAN_POINT *P, const uint8_t in[64]) +{ + sm2_bn_from_bytes(P->X, in); + sm2_bn_from_bytes(P->Y, in + 32); + sm2_bn_set_word(P->Z, 1); + /* should we check if sm2_jacobian_point_is_on_curve */ +} + +void sm2_jacobian_point_mul_generator(SM2_JACOBIAN_POINT *R, const SM2_BN k) +{ + sm2_jacobian_point_mul(R, k, SM2_G); +} + +/* R = t * P + s * G */ +void sm2_jacobian_point_mul_sum(SM2_JACOBIAN_POINT *R, const SM2_BN t, const SM2_JACOBIAN_POINT *P, const SM2_BN s) +{ + SM2_JACOBIAN_POINT _sG, *sG = &_sG; + SM2_BN x; + SM2_BN y; + + /* T = s * G */ + sm2_jacobian_point_mul_generator(sG, s); + + // R = t * P + sm2_jacobian_point_mul(R, t, P); + sm2_jacobian_point_get_xy(R, x, y); + sm2_jacobian_point_set_xy(R, x, y); + + // R = R + T + sm2_jacobian_point_add(R, sG, R); +} + +void sm2_jacobian_point_from_hex(SM2_JACOBIAN_POINT *P, const char hex[64 * 2]) +{ + sm2_bn_from_hex(P->X, hex); + sm2_bn_from_hex(P->Y, hex + 64); + sm2_bn_set_one(P->Z); +} + +int sm2_jacobian_point_equ_hex(const SM2_JACOBIAN_POINT *P, const char hex[128]) +{ + SM2_BN x; + SM2_BN y; + SM2_JACOBIAN_POINT _T, *T = &_T; + + sm2_jacobian_point_get_xy(P, x, y); + sm2_jacobian_point_from_hex(T, hex); + + return (sm2_bn_cmp(x, T->X) == 0) && (sm2_bn_cmp(y, T->Y) == 0); +} + +int sm2_point_is_on_curve(const SM2_POINT *P) +{ + SM2_JACOBIAN_POINT T; + sm2_jacobian_point_from_bytes(&T, (const uint8_t *)P); + return sm2_jacobian_point_is_on_curve(&T); +} + +int sm2_point_is_at_infinity(const SM2_POINT *P) +{ + return mem_is_zero((uint8_t *)P, sizeof(SM2_POINT)); +} + +int sm2_point_from_x(SM2_POINT *P, const uint8_t x[32], int y) +{ + SM2_BN _x, _y, _g, _z; + sm2_bn_from_bytes(_x, x); + + // g = x^3 - 3x + b = (x^2 - 3)*x + b + sm2_fp_sqr(_g, _x); + sm2_fp_sub(_g, _g, SM2_THREE); + sm2_fp_mul(_g, _g, _x); + sm2_fp_add(_g, _g, SM2_B); + + // y = g^(u + 1) mod p, u = (p - 3)/4 + sm2_fp_exp(_y, _g, SM2_U_PLUS_ONE); + + // z = y^2 mod p + sm2_fp_sqr(_z, _y); + if (sm2_bn_cmp(_z, _g)) { + error_print(); + return -1; + } + + if ((y == 0x02 && sm2_bn_is_odd(_y)) || ((y == 0x03) && !sm2_bn_is_odd(_y))) { + sm2_fp_neg(_y, _y); + } + + sm2_bn_to_bytes(_x, P->x); + sm2_bn_to_bytes(_y, P->y); + + sm2_bn_clean(_x); + sm2_bn_clean(_y); + sm2_bn_clean(_g); + sm2_bn_clean(_z); + + if (sm2_point_is_on_curve(P) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_point_from_xy(SM2_POINT *P, const uint8_t x[32], const uint8_t y[32]) +{ + memcpy(P->x, x, 32); + memcpy(P->y, y, 32); + return sm2_point_is_on_curve(P); +} + +int sm2_point_add(SM2_POINT *R, const SM2_POINT *P, const SM2_POINT *Q) +{ + SM2_JACOBIAN_POINT P_; + SM2_JACOBIAN_POINT Q_; + + sm2_jacobian_point_from_bytes(&P_, (uint8_t *)P); + sm2_jacobian_point_from_bytes(&Q_, (uint8_t *)Q); + sm2_jacobian_point_add(&P_, &P_, &Q_); + sm2_jacobian_point_to_bytes(&P_, (uint8_t *)R); + + return 1; +} + +int sm2_point_sub(SM2_POINT *R, const SM2_POINT *P, const SM2_POINT *Q) +{ + SM2_JACOBIAN_POINT P_; + SM2_JACOBIAN_POINT Q_; + + sm2_jacobian_point_from_bytes(&P_, (uint8_t *)P); + sm2_jacobian_point_from_bytes(&Q_, (uint8_t *)Q); + sm2_jacobian_point_sub(&P_, &P_, &Q_); + sm2_jacobian_point_to_bytes(&P_, (uint8_t *)R); + + return 1; +} + +int sm2_point_neg(SM2_POINT *R, const SM2_POINT *P) +{ + SM2_JACOBIAN_POINT P_; + + sm2_jacobian_point_from_bytes(&P_, (uint8_t *)P); + sm2_jacobian_point_neg(&P_, &P_); + sm2_jacobian_point_to_bytes(&P_, (uint8_t *)R); + + return 1; +} + +int sm2_point_dbl(SM2_POINT *R, const SM2_POINT *P) +{ + SM2_JACOBIAN_POINT P_; + + sm2_jacobian_point_from_bytes(&P_, (uint8_t *)P); + sm2_jacobian_point_dbl(&P_, &P_); + sm2_jacobian_point_to_bytes(&P_, (uint8_t *)R); + + return 1; +} + +int sm2_point_mul(SM2_POINT *R, const uint8_t k[32], const SM2_POINT *P) +{ + SM2_BN _k; + SM2_JACOBIAN_POINT _P; + + sm2_bn_from_bytes(_k, k); + sm2_jacobian_point_from_bytes(&_P, (uint8_t *)P); + sm2_jacobian_point_mul(&_P, _k, &_P); + sm2_jacobian_point_to_bytes(&_P, (uint8_t *)R); + + sm2_bn_clean(_k); + return 1; +} + +int sm2_point_mul_generator(SM2_POINT *R, const uint8_t k[32]) +{ + SM2_BN _k; + SM2_JACOBIAN_POINT _R; + + sm2_bn_from_bytes(_k, k); + sm2_jacobian_point_mul_generator(&_R, _k); + sm2_jacobian_point_to_bytes(&_R, (uint8_t *)R); + + sm2_bn_clean(_k); + return 1; +} + +int sm2_point_mul_sum(SM2_POINT *R, const uint8_t k[32], const SM2_POINT *P, const uint8_t s[32]) +{ + SM2_BN _k; + SM2_JACOBIAN_POINT _P; + SM2_BN _s; + + sm2_bn_from_bytes(_k, k); + sm2_jacobian_point_from_bytes(&_P, (uint8_t *)P); + sm2_bn_from_bytes(_s, s); + sm2_jacobian_point_mul_sum(&_P, _k, &_P, _s); + sm2_jacobian_point_to_bytes(&_P, (uint8_t *)R); + + sm2_bn_clean(_k); + sm2_bn_clean(_s); + return 1; +} + +int sm2_point_print(FILE *fp, int fmt, int ind, const char *label, const SM2_POINT *P) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + format_bytes(fp, fmt, ind, "x", P->x, 32); + format_bytes(fp, fmt, ind, "y", P->y, 32); + return 1; +} + +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) { + if (sm2_point_from_x(P, in + 1, *in) != 1) { + error_print(); + return -1; + } + } else if (*in == 0x04 && inlen == 65) { + if (sm2_point_from_xy(P, in + 1, in + 33) != 1) { + error_print(); + return -1; + } + } else { + error_print(); + return -1; + } + return 1; +} + +int sm2_point_to_der(const SM2_POINT *P, uint8_t **out, size_t *outlen) +{ + uint8_t octets[65]; + if (!P) { + return 0; + } + sm2_point_to_uncompressed_octets(P, octets); + if (asn1_octet_string_to_der(octets, sizeof(octets), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_point_from_der(SM2_POINT *P, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_octet_string_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (dlen != 65) { + error_print(); + return -1; + } + if (sm2_point_from_octets(P, d, dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_point_from_hash(SM2_POINT *R, const uint8_t *data, size_t datalen) +{ + SM2_BN u; + SM2_Fp x; + SM2_Fp y; + SM2_Fp s; + SM2_Fp s_; + uint8_t dgst[32]; + + // u = (p + 1)/4 + sm2_bn_add(u, SM2_P, SM2_ONE); + sm2_bn_rshift(u, u, 2); + + do { + sm3_digest(data, datalen, dgst); + + sm2_bn_from_bytes(x, dgst); + if (sm2_bn_cmp(x, SM2_P) >= 0) { + sm2_bn_sub(x, x, SM2_P); + } + + // s = y^2 = x^3 + a*x + b + sm2_fp_sqr(s, x); + sm2_fp_sub(s, s, SM2_THREE); + sm2_fp_mul(s, s, x); + sm2_fp_add(s, s, SM2_B); + + // y = s^((p+1)/4) = (sqrt(s) (mod p)) + sm2_fp_exp(y, s, u); + sm2_fp_sqr(s_, y); + + data = dgst; + datalen = sizeof(dgst); + + } while (sm2_bn_cmp(s, s_) != 0); + + sm2_bn_to_bytes(x, R->x); + sm2_bn_to_bytes(y, R->y); + return 1; +} + diff --git a/Core/GmSSL-3.1.1/src/sm2_blind.c b/Core/GmSSL-3.1.1/src/sm2_blind.c new file mode 100644 index 0000000..02ea7aa --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_blind.c @@ -0,0 +1,174 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern SM2_BN SM2_N; +extern SM2_BN SM2_ONE; + +int sm2_blind_sign_commit(SM2_Fn k, uint8_t *commit, size_t *commitlen) +{ + SM2_POINT K; + uint8_t k_bytes[32]; + + sm2_fn_rand(k); // FIXME: check return + sm2_bn_to_bytes(k, k_bytes); + + // commitment = k * G + sm2_point_mul_generator(&K, k_bytes); + sm2_point_to_compressed_octets(&K, commit); + *commitlen = 33; + gmssl_secure_clear(k_bytes, sizeof(k_bytes)); + + return 1; +} + +int sm2_blind_sign_init(SM2_BLIND_SIGN_CTX *ctx, const SM2_KEY *public_key, const char *id, size_t idlen) +{ + ctx->public_key = *public_key; + sm3_init(&ctx->sm3_ctx); + if (id) { + uint8_t z[SM3_DIGEST_SIZE]; + if (idlen <= 0 || idlen > SM2_MAX_ID_LENGTH) { + error_print(); + return -1; + } + sm2_compute_z(z, &public_key->public_key, id, idlen); + sm3_update(&ctx->sm3_ctx, z, sizeof(z)); + } + return 1; +} + +int sm2_blind_sign_update(SM2_BLIND_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (!ctx) { + error_print(); + return -1; + } + if (data && datalen > 0) { + sm3_update(&ctx->sm3_ctx, data, datalen); + } + return 1; +} + +int sm2_blind_sign_finish(SM2_BLIND_SIGN_CTX *ctx, + const uint8_t *commit, size_t commitlen, + uint8_t blinded_sig_r[32]) +{ + int ret = -1; + SM2_Fn a; + SM2_Fn b; + SM2_POINT K; + SM2_Fn e; + SM2_Fn r; + uint8_t dgst[32]; + + sm3_finish(&ctx->sm3_ctx, dgst); + sm2_bn_from_bytes(e, dgst); + if (sm2_bn_cmp(e, SM2_N) >= 0) { + sm2_bn_sub(e, e, SM2_N); + } + + //FIXME: return value of sm2_fn_rand() + sm2_fn_rand(a); + sm2_bn_to_bytes(a, ctx->blind_factor_a); + sm2_fn_rand(b); + sm2_bn_to_bytes(b, ctx->blind_factor_b); + + if (sm2_point_from_octets(&K, commit, commitlen) != 1) { + error_print(); + goto end; + } + // K'(x1, y1) = a * K + b * G + if (sm2_point_mul_sum(&K, ctx->blind_factor_a, &K, ctx->blind_factor_b) != 1) { + error_print(); + goto end; + } + sm2_bn_from_bytes(r, K.x); + if (sm2_bn_cmp(r, SM2_N) >= 0) { + sm2_bn_sub(r, r, SM2_N); + } + + // r = x1 + e (mod n) + sm2_fn_add(r, r, e); + sm2_bn_to_bytes(r, ctx->sig_r); + + // r' = a^-1 * (r + b) + sm2_fn_add(r, r, b); + sm2_fn_inv(a, a); + sm2_fn_mul(r, r, a); + + sm2_bn_to_bytes(r, blinded_sig_r); + ret = 1; + +end: + gmssl_secure_clear(a, sizeof(a)); + gmssl_secure_clear(b, sizeof(b)); + return ret; +} + +int sm2_blind_sign(const SM2_KEY *key, const SM2_Fn k, const uint8_t blinded_r[32], uint8_t blinded_s[32]) +{ + SM2_Fn x; + SM2_Fn r; + SM2_Fn s; + + sm2_bn_from_bytes(x, key->private_key); + sm2_bn_from_bytes(r, blinded_r); + + // s = (1 + x)^-1 * (k - r * x) (mod n) + sm2_fn_mul(r, r, x); + sm2_fn_sub(s, k, r); + sm2_fn_add(x, x, SM2_ONE); + sm2_fn_inv(x, x); + sm2_fn_mul(s, s, x); + sm2_bn_to_bytes(s, blinded_s); + + gmssl_secure_clear(x, sizeof(x)); + gmssl_secure_clear(r, sizeof(r)); + gmssl_secure_clear(s, sizeof(s)); + return 1; +} + +int sm2_blind_sign_unblind(SM2_BLIND_SIGN_CTX *ctx, const uint8_t blinded_sig_s[32], uint8_t *sig, size_t *siglen) +{ + SM2_Fn a; + SM2_Fn b; + SM2_Fn s; + SM2_SIGNATURE signature; + + sm2_bn_from_bytes(a, ctx->blind_factor_a); + sm2_bn_from_bytes(b, ctx->blind_factor_b); + sm2_bn_from_bytes(s, blinded_sig_s); + + // s = a * s' + b + sm2_fn_mul(s, s, a); + sm2_fn_add(s, s, b); + + memcpy(signature.r, ctx->sig_r, 32); + sm2_bn_to_bytes(s, signature.s); + + + *siglen = 0; + sm2_signature_to_der(&signature, &sig, siglen); + + gmssl_secure_clear(a, sizeof(a)); + gmssl_secure_clear(b, sizeof(b)); + gmssl_secure_clear(ctx, sizeof(*ctx)); + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm2_commit.c b/Core/GmSSL-3.1.1/src/sm2_commit.c new file mode 100644 index 0000000..8bd1470 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_commit.c @@ -0,0 +1,172 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SM2_COMMIT_SEED "GmSSL SM2 Pederson Commitment Generator H" + + +// C = rG + xH +int sm2_commit_generate(const uint8_t x[32], uint8_t r[32], uint8_t commit[65], size_t *commitlen) +{ + SM2_POINT H; + SM2_POINT C; + SM2_BN r_; + + if (sm2_point_from_hash(&H, (uint8_t *)SM2_COMMIT_SEED, sizeof(SM2_COMMIT_SEED)-1) != 1) { + error_print(); + return -1; + } + + do { + sm2_fn_rand(r_); + } while (sm2_bn_is_zero(r_)); + + sm2_bn_to_bytes(r_, r); + gmssl_secure_clear(r_, sizeof(r_)); + + // C = xH + rG + sm2_point_mul_sum(&C, x, &H, r); + + sm2_point_to_compressed_octets(&C, commit); + *commitlen = 33; + return 1; +} + +int sm2_commit_open(const uint8_t x[32], const uint8_t r[32], const uint8_t *commit, size_t commitlen) +{ + SM2_POINT H; + SM2_POINT C; + SM2_POINT C_; + + if (sm2_point_from_octets(&C, commit, commitlen) != 1) { + error_print(); + return -1; + } + + if (sm2_point_from_hash(&H, (uint8_t *)SM2_COMMIT_SEED, sizeof(SM2_COMMIT_SEED)-1) != 1) { + error_print(); + return -1; + } + + // C' = xH + rG + if (sm2_point_mul_sum(&C_, x, &H, r) != 1) { + error_print(); + return -1; + } + + if (memcmp(&C, &C_, sizeof(SM2_POINT)) != 0) { + error_print(); + return 0; + } + return 1; +} + +// C = r*G + x1*H1 + x2*H2 + ... +int sm2_commit_vector_generate(const sm2_bn_t *x, size_t count, uint8_t r[32], uint8_t commit[65], size_t *commitlen) +{ + SM2_POINT H; + SM2_POINT C; + SM2_Fn r_; + size_t i; + + if (count < 1) { + error_print(); + return -1; + } + + if (sm2_point_from_hash(&H, (uint8_t *)SM2_COMMIT_SEED, sizeof(SM2_COMMIT_SEED)-1) != 1) { + error_print(); + return -1; + } + + do { + sm2_fn_rand(r_); + } while (sm2_bn_is_zero(r_)); + + sm2_bn_to_bytes(r_, r); + gmssl_secure_clear(r_, sizeof(r_)); + + if (sm2_point_mul_sum(&C, x[0], &H, r) != 1) { + error_print(); + return -1; + } + + for (i = 1; i < count; i++) { + SM2_POINT xH; + + if (sm2_point_from_hash(&H, (uint8_t *)&H, sizeof(H)) != 1 + || sm2_point_mul(&xH, x[i], &H) != 1 + || sm2_point_add(&C, &C, &xH) != 1) { + error_print(); + return -1; + } + } + + sm2_point_to_compressed_octets(&C, commit); + *commitlen = 33; + return 1; +} + +int sm2_commit_vector_open(const sm2_bn_t *x, size_t count, const uint8_t r[32], const uint8_t *commit, size_t commitlen) +{ + SM2_POINT H; + SM2_POINT C; + SM2_POINT C_; + size_t i; + + if (count < 1) { + error_print(); + return -1; + } + + if (sm2_point_from_octets(&C, commit, commitlen) != 1) { + error_print(); + return -1; + } + + if (sm2_point_from_hash(&H, (uint8_t *)SM2_COMMIT_SEED, sizeof(SM2_COMMIT_SEED)-1) != 1) { + error_print(); + return -1; + } + + if (sm2_point_mul_sum(&C_, x[0], &H, r) != 1) { + error_print(); + return -1; + } + + for (i = 1; i< count; i++) { + SM2_POINT xH; + + if (sm2_point_from_hash(&H, (uint8_t *)&H, sizeof(H)) != 1 + || sm2_point_mul(&xH, x[i], &H) != 1 + || sm2_point_add(&C_, &C_, &xH) != 1) { + error_print(); + return -1; + } + } + + if (memcmp(&C, &C_, sizeof(SM2_POINT)) != 0) { + error_print(); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm2_elgamal.c b/Core/GmSSL-3.1.1/src/sm2_elgamal.c new file mode 100644 index 0000000..afbd21d --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_elgamal.c @@ -0,0 +1,412 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern const SM2_JACOBIAN_POINT *SM2_G; + + + +// generate baby-step table +int sm2_elgamal_decrypt_pre_compute(SM2_PRE_COMPUTE table[1<<16]) +{ + SM2_JACOBIAN_POINT P; + SM2_BN x; + uint32_t i, j; + + memset(table, 0, sizeof(SM2_PRE_COMPUTE) * (1<<16)); + + sm2_jacobian_point_set_infinity(&P); + for (i = 0; i < (1<<16); i++) { + sm2_jacobian_point_add(&P, &P, SM2_G); + sm2_jacobian_point_get_xy(&P, x, NULL); + sm2_bn_to_bytes(x, table[i].x_coordinate); + + j = ((uint16_t)table[i].x_coordinate[30] << 8) | table[i].x_coordinate[31]; + assert(table[j].offset_count <= SM2_PRE_COMPUTE_MAX_OFFSETS); + + table[j].offset[ table[j].offset_count ] = (uint16_t)i; + (table[j].offset_count)++; + } + return 1; +} + +static int sm2_pre_compute_get_offset(const SM2_PRE_COMPUTE table[1<<16], const uint8_t x[32], uint16_t *offset) +{ + uint32_t i = ((uint16_t)x[30] << 8) | x[31]; + uint16_t j; + uint8_t w; + + for (w = 0; w < table[i].offset_count; w++) { + j = table[i].offset[w]; + if (memcmp(x, table[j].x_coordinate, 32) == 0) { + *offset = j; + return 1; + } + } + return 0; +} + +// run gaint-step +int sm2_elgamal_solve_ecdlp(const SM2_PRE_COMPUTE table[1<<16], const SM2_POINT *point, uint32_t *private) +{ + int ret = 0; + SM2_JACOBIAN_POINT P; + SM2_JACOBIAN_POINT Q; + SM2_BN k; + SM2_BN x; + uint8_t x_bytes[32]; + uint8_t Q_bytes[64]; + uint32_t i; + uint16_t j; + + sm2_jacobian_point_from_bytes(&P, (uint8_t *)point); + + // Q = -[2^16]G + sm2_bn_set_word(k, 65536); + sm2_jacobian_point_mul_generator(&Q, k); + sm2_jacobian_point_neg(&Q, &Q); + + // Q to Affine + sm2_jacobian_point_to_bytes(&Q, Q_bytes); + sm2_jacobian_point_from_bytes(&Q, Q_bytes); + + for (i = 0; i < (1<<16); i++) { + // P - i*(kG) == O ==> d = i*k + if (sm2_jacobian_point_is_at_infinity(&P)) { + *private = (i << 16); + ret = 1; + goto ok; + } + + sm2_jacobian_point_get_xy(&P, x, NULL); + sm2_bn_to_bytes(x, x_bytes); + if (sm2_pre_compute_get_offset(table, x_bytes, &j) == 1) { + // P - i*(kG) == j*G ==> d = j + i*k + *private = (i<<16) + j + 1; // table[0] is 1*G, so j + 1 + ret = 1; + goto ok; + } + sm2_jacobian_point_add(&P, &P, &Q); + } + printf("gaint steps failed\n"); + +ok: + i = j = 0; + gmssl_secure_clear(x, sizeof(x)); + return ret; +} + +int sm2_elgamal_do_encrypt(const SM2_KEY *pub_key, uint32_t in, SM2_ELGAMAL_CIPHERTEXT *out) +{ + int ret = -1; + SM2_Fn k; + SM2_Fn m; + uint8_t k_bytes[32]; + uint8_t m_bytes[32]; + + if (!pub_key || !out) { + error_print(); + return -1; + } + + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); + sm2_bn_to_bytes(k, k_bytes); + + // C1 = k * G + if (sm2_point_mul_generator(&out->C1, k_bytes) != 1) { + error_print(); + goto end; + } + + // C2 = k * P + m * G + sm2_bn_set_word(m, in); + sm2_bn_to_bytes(m, m_bytes); + if (sm2_point_mul_sum(&out->C2, k_bytes, &pub_key->public_key, m_bytes) != 1) { + error_print(); + goto end; + } + ret = 1; + +end: + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(m, sizeof(m)); + gmssl_secure_clear(k_bytes, sizeof(k_bytes)); + gmssl_secure_clear(m_bytes, sizeof(m_bytes)); + return ret; +} + +// M = m*G = -x*C1 + C2 +int sm2_elgamal_do_decrypt(const SM2_KEY *key, const SM2_ELGAMAL_CIPHERTEXT *in, uint32_t *out) +{ + static SM2_PRE_COMPUTE *table = NULL; + SM2_POINT M; + + if (!key || !in || !out) { + error_print(); + return -1; + } + + sm2_point_mul(&M, key->private_key, &in->C1); + sm2_point_sub(&M, &in->C2, &M); + + if (!table) { + if (!(table = malloc(sizeof(SM2_PRE_COMPUTE) * (1<<16)))) { + error_print(); + return -1; + } + sm2_elgamal_decrypt_pre_compute(table); + } + + if (sm2_elgamal_solve_ecdlp(table, &M, out) != 1) { + error_print(); + return -1; + } + return 1; +} + +// (A1, A2) = (k1*G, m1*G + k1*P) +// (B1, B2) = (k2*G, m2*G + k2*P) +// (R1, R2) = (A1 + B1 + k*G, A2 + B2 + k*P) +int sm2_elgamal_ciphertext_add(SM2_ELGAMAL_CIPHERTEXT *r, + const SM2_ELGAMAL_CIPHERTEXT *a, + const SM2_ELGAMAL_CIPHERTEXT *b, + const SM2_KEY *pub_key) +{ + SM2_Fn k; + uint8_t k_bytes[32]; + SM2_POINT R; + + if (!r || !a || !b || !pub_key) { + error_print(); + return -1; + } + + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); + sm2_bn_to_bytes(k, k_bytes); + + // R1 = A1 + B1 + k*G + sm2_point_add(&r->C1, &a->C1, &b->C1); + sm2_point_mul_generator(&R, k_bytes); + sm2_point_add(&r->C1, &r->C1, &R); + + // R2 = A2 + B2 + k*P + sm2_point_add(&r->C2, &a->C2, &b->C2); + sm2_point_mul(&R, k_bytes, &pub_key->public_key); + sm2_point_add(&r->C2, &r->C2, &R); + + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(k_bytes, sizeof(k_bytes)); + return 1; +} + +int sm2_elgamal_cipehrtext_sub(SM2_ELGAMAL_CIPHERTEXT *r, + const SM2_ELGAMAL_CIPHERTEXT *a, const SM2_ELGAMAL_CIPHERTEXT *b, + const SM2_KEY *pub_key) +{ + SM2_Fn k; + uint8_t k_bytes[32]; + SM2_POINT R; + + if (!r || !a || !b || !pub_key) { + error_print(); + return -1; + } + + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); + sm2_bn_to_bytes(k, k_bytes); + + // R1 = A1 - B1 + k*G + sm2_point_sub(&r->C1, &a->C1, &b->C1); + sm2_point_mul_generator(&R, k_bytes); + sm2_point_add(&r->C1, &a->C1, &R); + + // R2 = A2 - B2 + k*P + sm2_point_sub(&r->C2, &a->C2, &b->C2); + sm2_point_mul(&R, k_bytes, &pub_key->public_key); + sm2_point_add(&r->C2, &r->C2, &R); + + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(k_bytes, sizeof(k_bytes)); + return 1; +} + +int sm2_elgamal_cipehrtext_neg(SM2_ELGAMAL_CIPHERTEXT *r, + const SM2_ELGAMAL_CIPHERTEXT *a, const SM2_KEY *pub_key) +{ + SM2_Fn k; + uint8_t k_bytes[32]; + SM2_POINT R; + + if (!r || !a || !pub_key) { + error_print(); + return -1; + } + + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); + sm2_bn_to_bytes(k, k_bytes); + + // R1 = -A1 + k*G = -r*G + k*G + sm2_point_mul_generator(&R, k_bytes); + sm2_point_sub(&r->C1, &R, &a->C1); + + // R2 = -A2 + k*P = -m*G -r*P + k*P + sm2_point_mul(&R, k_bytes, &pub_key->public_key); + sm2_point_sub(&r->C2, &R, &a->C2); + + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(k_bytes, sizeof(k_bytes)); + return 1; +} + +// s * (C1, C2) := (s*C1 + r*G, s*C2 + r*P) +int sm2_elgamal_ciphertext_scalar_mul(SM2_ELGAMAL_CIPHERTEXT *R, + const uint8_t scalar[32], const SM2_ELGAMAL_CIPHERTEXT *A, + const SM2_KEY *pub_key) +{ + SM2_Fn k; + uint8_t k_bytes[32]; + SM2_POINT kP; + + if (!R || !scalar || !A || !pub_key) { + error_print(); + return -1; + } + + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); + sm2_bn_to_bytes(k, k_bytes); + + // R1 = s*C1 + k*G + sm2_point_mul_sum(&R->C1, scalar, &A->C1, k_bytes); + + // R2 = s*C2 + r*P + sm2_point_mul(&kP, k_bytes, &pub_key->public_key); + sm2_point_mul(&R->C2, scalar, &A->C2); + sm2_point_add(&R->C2, &R->C2, &kP); + + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(k_bytes, sizeof(k_bytes)); + return 1; +} + +int sm2_elgamal_ciphertext_to_der(const SM2_ELGAMAL_CIPHERTEXT *c, uint8_t **out, size_t *outlen) +{ + uint8_t c1[65]; + uint8_t c2[65]; + size_t len; + + sm2_point_to_uncompressed_octets(&c->C1, c1); + sm2_point_to_uncompressed_octets(&c->C2, c2); + + if (asn1_octet_string_to_der(c1, sizeof(c1), NULL, &len) != 1 + || asn1_octet_string_to_der(c2, sizeof(c2), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_octet_string_to_der(c1, sizeof(c1), out, outlen) != 1 + || asn1_octet_string_to_der(c2, sizeof(c2), out, outlen) != 1) { + error_print(); + return -1; + } + + return 1; +} + +int sm2_elgamal_ciphertext_from_der(SM2_ELGAMAL_CIPHERTEXT *c, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *c1; + size_t c1len; + const uint8_t *c2; + size_t c2len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + error_print(); + return -1; + } + if (asn1_octet_string_from_der(&c1, &c1len, &d, &dlen) != 1 + || asn1_octet_string_from_der(&c2, &c2len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (sm2_point_from_octets(&c->C1, c1, c1len) != 1 + || sm2_point_from_octets(&c->C2, c2, c2len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_elgamal_encrypt(const SM2_KEY *pub_key, uint32_t in, uint8_t *out, size_t *outlen) +{ + SM2_ELGAMAL_CIPHERTEXT C; + + if (sm2_elgamal_do_encrypt(pub_key, in, &C) != 1) { + error_print(); + return -1; + } + *outlen = 0; + if (sm2_elgamal_ciphertext_to_der(&C, &out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_elgamal_decrypt(SM2_KEY *key, const uint8_t *in, size_t inlen, uint32_t *out) +{ + SM2_ELGAMAL_CIPHERTEXT C; + + if (sm2_elgamal_ciphertext_from_der(&C, &in, &inlen) != 1 + || asn1_length_is_zero(inlen) != 1) { + error_print(); + return -1; + } + if (sm2_elgamal_do_decrypt(key, &C, out) != 1) { + error_print(); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm2_key.c b/Core/GmSSL-3.1.1/src/sm2_key.c new file mode 100644 index 0000000..e376d6b --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_key.c @@ -0,0 +1,691 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern const SM2_BN SM2_N; + + +int sm2_key_generate(SM2_KEY *key) +{ + SM2_BN x; + SM2_BN y; + SM2_JACOBIAN_POINT _P, *P = &_P; + + if (!key) { + error_print(); + return -1; + } + memset(key, 0, sizeof(SM2_KEY)); + + do { + if (sm2_bn_rand_range(x, SM2_N) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(x)); + sm2_bn_to_bytes(x, key->private_key); + + sm2_jacobian_point_mul_generator(P, x); + sm2_jacobian_point_get_xy(P, x, y); + sm2_bn_to_bytes(x, key->public_key.x); + sm2_bn_to_bytes(y, key->public_key.y); + + return 1; +} + +int sm2_key_set_private_key(SM2_KEY *key, const uint8_t private_key[32]) +{ + SM2_BN bn; + + sm2_bn_from_bytes(bn, private_key); + + if (sm2_bn_is_zero(bn) + || sm2_bn_cmp(bn, SM2_N) >= 0) { + gmssl_secure_clear(bn, sizeof(bn)); + error_print(); + return -1; + } + + memcpy(&key->private_key, private_key, 32); + + if (sm2_point_mul_generator(&key->public_key, private_key) != 1) { + gmssl_secure_clear(bn, sizeof(bn)); + gmssl_secure_clear(key, sizeof(SM2_KEY)); + error_print(); + return -1; + } + + gmssl_secure_clear(bn, sizeof(bn)); + return 1; +} + +int sm2_key_set_public_key(SM2_KEY *key, const SM2_POINT *public_key) +{ + if (!key || !public_key) { + error_print(); + return -1; + } + if (sm2_point_is_on_curve(public_key) != 1) { + error_print(); + return -1; + } + gmssl_secure_clear(key, sizeof(SM2_KEY)); + key->public_key = *public_key; + return 1; +} + +int sm2_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *key) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + sm2_public_key_print(fp, fmt, ind, "publicKey", key); + format_bytes(fp, fmt, ind, "privateKey", key->private_key, 32); + return 1; +} + +int sm2_public_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen) +{ + uint8_t buf[65]; + size_t len = 0; + + if (!key) { + return 0; + } + sm2_point_to_uncompressed_octets(&key->public_key, buf); + if (asn1_bit_octets_to_der(buf, sizeof(buf), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_public_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + SM2_POINT P; + + if ((ret = asn1_bit_octets_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (dlen != 65) { + error_print(); + return -1; + } + if (sm2_point_from_octets(&P, d, dlen) != 1 + || sm2_key_set_public_key(key, &P) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *pub_key) +{ + return sm2_point_print(fp, fmt, ind, label, &pub_key->public_key); +} + +int sm2_public_key_algor_to_der(uint8_t **out, size_t *outlen) +{ + if (x509_public_key_algor_to_der(OID_ec_public_key, OID_sm2, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen) +{ + int ret; + int oid; + int curve; + + if ((ret = x509_public_key_algor_from_der(&oid, &curve, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (oid != OID_ec_public_key) { + error_print(); + return -1; + } + if (curve != OID_sm2) { + error_print(); + return -1; + } + return 1; +} + +#define SM2_PRIVATE_KEY_DER_SIZE 121 +int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + uint8_t params[64]; + uint8_t pubkey[128]; + uint8_t *params_ptr = params; + uint8_t *pubkey_ptr = pubkey; + size_t params_len = 0; + size_t pubkey_len = 0; + + if (!key) { + error_print(); + return -1; + } + if (ec_named_curve_to_der(OID_sm2, ¶ms_ptr, ¶ms_len) != 1 + || sm2_public_key_to_der(key, &pubkey_ptr, &pubkey_len) != 1) { + error_print(); + return -1; + } + if (asn1_int_to_der(EC_private_key_version, NULL, &len) != 1 + || asn1_octet_string_to_der(key->private_key, 32, NULL, &len) != 1 + || asn1_explicit_to_der(0, params, params_len, NULL, &len) != 1 + || asn1_explicit_to_der(1, pubkey, pubkey_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(EC_private_key_version, out, outlen) != 1 + || asn1_octet_string_to_der(key->private_key, 32, out, outlen) != 1 + || asn1_explicit_to_der(0, params, params_len, out, outlen) != 1 + || asn1_explicit_to_der(1, pubkey, pubkey_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int ver; + const uint8_t *prikey; + const uint8_t *params; + const uint8_t *pubkey; + size_t prikey_len, params_len, pubkey_len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(&ver, &d, &dlen) != 1 + || asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1 + || asn1_explicit_from_der(0, ¶ms, ¶ms_len, &d, &dlen) != 1 + || asn1_explicit_from_der(1, &pubkey, &pubkey_len, &d, &dlen) != 1 + || asn1_check(ver == EC_private_key_version) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (params) { + int curve; + if (ec_named_curve_from_der(&curve, ¶ms, ¶ms_len) != 1 + || asn1_check(curve == OID_sm2) != 1 + || asn1_length_is_zero(params_len) != 1) { + error_print(); + return -1; + } + } + if (asn1_check(prikey_len == 32) != 1 + || sm2_key_set_private_key(key, prikey) != 1) { + error_print(); + return -1; + } + + // check if the public key is correct + if (pubkey) { + SM2_KEY tmp_key; + if (sm2_public_key_from_der(&tmp_key, &pubkey, &pubkey_len) != 1 + || asn1_length_is_zero(pubkey_len) != 1) { + error_print(); + return -1; + } + if (sm2_public_key_equ(key, &tmp_key) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int sm2_private_key_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return ec_private_key_print(fp, fmt, ind, label, d, dlen); +} + +#define SM2_PRIVATE_KEY_INFO_DER_SIZE 150 + +int sm2_private_key_info_to_der(const SM2_KEY *sm2_key, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + uint8_t prikey[SM2_PRIVATE_KEY_DER_SIZE]; + uint8_t *p = prikey; + size_t prikey_len = 0; + + if (sm2_private_key_to_der(sm2_key, &p, &prikey_len) != 1) { + error_print(); + return -1; + } + if (asn1_int_to_der(PKCS8_private_key_info_version, NULL, &len) != 1 + || sm2_public_key_algor_to_der(NULL, &len) != 1 + || asn1_octet_string_to_der(prikey, prikey_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(PKCS8_private_key_info_version, out, outlen) != 1 + || sm2_public_key_algor_to_der(out, outlen) != 1 + || asn1_octet_string_to_der(prikey, prikey_len, out, outlen) != 1) { + memset(prikey, 0, sizeof(prikey)); + error_print(); + return -1; + } + memset(prikey, 0, sizeof(prikey)); + return 1; +} + +int sm2_private_key_info_from_der(SM2_KEY *sm2_key, const uint8_t **attrs, size_t *attrslen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int version; + const uint8_t *prikey; + size_t prikey_len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(&version, &d, &dlen) != 1 + || sm2_public_key_algor_from_der(&d, &dlen) != 1 + || asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1 + || asn1_implicit_set_from_der(0, attrs, attrslen, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (asn1_check(version == PKCS8_private_key_info_version) != 1 + || sm2_private_key_from_der(sm2_key, &prikey, &prikey_len) != 1 + || asn1_length_is_zero(prikey_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_private_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + int val; + const uint8_t *prikey; + size_t prikey_len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_algor_print(fp, fmt, ind, "privateKeyAlgorithm", p, len); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + if (asn1_sequence_from_der(&prikey, &prikey_len, &p, &len) != 1) goto err; + ec_private_key_print(fp, fmt, ind + 4, "privateKey", prikey, prikey_len); + if (asn1_length_is_zero(len) != 1) goto err; + if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + else if (ret) format_bytes(fp, fmt, ind, "attributes", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +#ifdef SM2_PRIVATE_KEY_EXPORT +int sm2_private_key_info_to_pem(const SM2_KEY *key, FILE *fp) +{ + int ret = -1; + uint8_t buf[SM2_PRIVATE_KEY_INFO_DER_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (!key || !fp) { + error_print(); + return -1; + } + if (sm2_private_key_info_to_der(key, &p, &len) != 1) { + error_print(); + goto end; + } + if (len != sizeof(buf)) { + error_print(); + goto end; + } + if (pem_write(fp, "PRIVATE KEY", buf, len) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + gmssl_secure_clear(buf, sizeof(buf)); + return ret; +} + +int sm2_private_key_info_from_pem(SM2_KEY *sm2_key, FILE *fp) +{ + uint8_t buf[512]; + const uint8_t *cp = buf; + size_t len; + const uint8_t *attrs; + size_t attrs_len; + + if (pem_read(fp, "PRIVATE KEY", buf, &len, sizeof(buf)) != 1 + || sm2_private_key_info_from_der(sm2_key, &attrs, &attrs_len, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (attrs_len) { + error_print(); + } + return 1; +} +#endif + +int sm2_public_key_info_to_der(const SM2_KEY *pub_key, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (sm2_public_key_algor_to_der(NULL, &len) != 1 + || sm2_public_key_to_der(pub_key, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || sm2_public_key_algor_to_der(out, outlen) != 1 + || sm2_public_key_to_der(pub_key, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_public_key_info_from_der(SM2_KEY *pub_key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (sm2_public_key_algor_from_der(&d, &dlen) != 1 + || sm2_public_key_from_der(pub_key, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +#ifdef SM2_PRIVATE_KEY_EXPORT + +// FIXME: side-channel of Base64 +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, sizeof(buf)) != 1) { + error_print(); + return -1; + } + if (sm2_private_key_from_der(a, &cp, &len) != 1 + || len > 0) { + error_print(); + return -1; + } + return 1; +} +#endif + +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, sizeof(buf)) != 1) { + error_print(); + return -1; + } + if (sm2_public_key_info_from_der(a, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_public_key_equ(const SM2_KEY *sm2_key, const SM2_KEY *pub_key) +{ + if (memcmp(sm2_key, pub_key, sizeof(SM2_POINT)) == 0) { + return 1; + } + return 0; +} + +int sm2_public_key_copy(SM2_KEY *sm2_key, const SM2_KEY *pub_key) +{ + return sm2_key_set_public_key(sm2_key, &pub_key->public_key); +} + +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; +} + +int sm2_private_key_info_encrypt_to_der(const SM2_KEY *sm2_key, const char *pass, + uint8_t **out, size_t *outlen) +{ + int ret = -1; + uint8_t pkey_info[SM2_PRIVATE_KEY_INFO_DER_SIZE]; + uint8_t *p = pkey_info; + size_t pkey_info_len = 0; + uint8_t salt[16]; + int iter = 65536; + uint8_t iv[16]; + uint8_t key[16]; + SM4_KEY sm4_key; + uint8_t enced_pkey_info[sizeof(pkey_info) + 32]; + size_t enced_pkey_info_len; + + if (!sm2_key || !pass || !outlen) { + error_print(); + return -1; + } + if (sm2_private_key_info_to_der(sm2_key, &p, &pkey_info_len) != 1 + || rand_bytes(salt, sizeof(salt)) != 1 + || rand_bytes(iv, sizeof(iv)) != 1 + || pbkdf2_genkey(DIGEST_sm3(), pass, strlen(pass), + salt, sizeof(salt), iter, sizeof(key), key) != 1) { + error_print(); + goto end; + } + /* + if (pkey_info_len != sizeof(pkey_info)) { + error_print(); + goto end; + } + */ + sm4_set_encrypt_key(&sm4_key, key); + if (sm4_cbc_padding_encrypt( + &sm4_key, iv, pkey_info, pkey_info_len, + enced_pkey_info, &enced_pkey_info_len) != 1 + || pkcs8_enced_private_key_info_to_der( + salt, sizeof(salt), iter, sizeof(key), OID_hmac_sm3, + OID_sm4_cbc, iv, sizeof(iv), + enced_pkey_info, enced_pkey_info_len, out, outlen) != 1) { + error_print(); + goto end; + } + + ret = 1; +end: + gmssl_secure_clear(pkey_info, sizeof(pkey_info)); + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); + return ret; +} + +int sm2_private_key_info_decrypt_from_der(SM2_KEY *sm2, + const uint8_t **attrs, size_t *attrs_len, + const char *pass, const uint8_t **in, size_t *inlen) +{ + int ret = -1; + const uint8_t *salt; + size_t saltlen; + int iter; + int keylen; + int prf; + int cipher; + const uint8_t *iv; + size_t ivlen; + uint8_t key[16]; + SM4_KEY sm4_key; + const uint8_t *enced_pkey_info; + size_t enced_pkey_info_len; + uint8_t pkey_info[256]; + const uint8_t *cp = pkey_info; + size_t pkey_info_len; + + if (!sm2 || !attrs || !attrs_len || !pass || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (pkcs8_enced_private_key_info_from_der(&salt, &saltlen, &iter, &keylen, &prf, + &cipher, &iv, &ivlen, &enced_pkey_info, &enced_pkey_info_len, in, inlen) != 1 + || asn1_check(keylen == -1 || keylen == 16) != 1 + || asn1_check(prf == - 1 || prf == OID_hmac_sm3) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == 16) != 1 + || asn1_length_le(enced_pkey_info_len, sizeof(pkey_info)) != 1) { + error_print(); + return -1; + } + if (pbkdf2_genkey(DIGEST_sm3(), pass, strlen(pass), salt, saltlen, iter, sizeof(key), key) != 1) { + error_print(); + goto end; + } + sm4_set_decrypt_key(&sm4_key, key); + if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_pkey_info, enced_pkey_info_len, + pkey_info, &pkey_info_len) != 1 + || sm2_private_key_info_from_der(sm2, attrs, attrs_len, &cp, &pkey_info_len) != 1 + || asn1_length_is_zero(pkey_info_len) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(pkey_info, sizeof(pkey_info)); + return ret; +} + +int sm2_private_key_info_encrypt_to_pem(const SM2_KEY *sm2_key, const char *pass, FILE *fp) +{ + uint8_t buf[1024]; + uint8_t *p = buf; + size_t len = 0; + + if (!fp) { + error_print(); + return -1; + } + if (sm2_private_key_info_encrypt_to_der(sm2_key, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, "ENCRYPTED PRIVATE KEY", buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_private_key_info_decrypt_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 attrs_len; + + if (!key || !pass || !fp) { + error_print(); + return -1; + } + if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len, sizeof(buf)) != 1 + || sm2_private_key_info_decrypt_from_der(key, &attrs, &attrs_len, pass, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm2_key_share.c b/Core/GmSSL-3.1.1/src/sm2_key_share.c new file mode 100644 index 0000000..0c8abfd --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_key_share.c @@ -0,0 +1,215 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +extern SM2_BN SM2_N; + +int sm2_key_share_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY_SHARE *share) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + format_print(fp, fmt, ind, "%zu/%zu\n", share->index, share->total_cnt); + format_print(fp, fmt, ind, "key", &share->key); + return 1; +} + + +// y = f(x) +static void eval_univariate_poly(SM2_Fn y, const SM2_Fn *coeffs, size_t coeffs_cnt, uint32_t x) +{ + sm2_bn_set_zero(y); + while (coeffs_cnt--) { + sm2_fn_mul_word(y, y, x); + sm2_fn_add(y, y, coeffs[coeffs_cnt]); + } +} + +int sm2_key_split(const SM2_KEY *key, size_t recover_cnt, size_t total_cnt, SM2_KEY_SHARE *shares) +{ + SM2_Fn coeffs[SM2_KEY_MAX_SHARES]; + SM2_Fn y; + uint8_t y_bytes[32]; + size_t i; + + if (!key || !shares) { + error_print(); + return -1; + } + if (!total_cnt || total_cnt > SM2_KEY_MAX_SHARES) { + error_print(); + return -1; + } + if (!recover_cnt || recover_cnt > total_cnt) { + error_print(); + return -1; + } + // try to access mem + memset(shares, 0, sizeof(SM2_KEY_SHARE) * total_cnt); + + for (i = 1; i < recover_cnt; i++) { + if (sm2_fn_rand(coeffs[i]) != 1) { + error_print(); + return -1; + } + } + sm2_bn_from_bytes(coeffs[0], key->private_key); + + for (i = 0; i < total_cnt; i++) { + uint32_t x = (uint32_t)(i + 1); + eval_univariate_poly(y, coeffs, recover_cnt, x); + sm2_bn_to_bytes(y, y_bytes); + sm2_key_set_private_key(&(shares[i].key), y_bytes); + shares[i].index = i; + shares[i].total_cnt = total_cnt; + } + + gmssl_secure_clear(coeffs, sizeof(coeffs)); + gmssl_secure_clear(y, sizeof(y)); + gmssl_secure_clear(y_bytes, sizeof(y_bytes)); + return 1; +} + +int sm2_key_recover(SM2_KEY *key, const SM2_KEY_SHARE *shares, size_t shares_cnt) +{ + SM2_Fn s; + uint8_t s_bytes[32]; + int x_i; + SM2_Fn y_i; + size_t i, j, k, n; + + if (!shares || !shares_cnt || !key) { + error_print(); + return -1; + } + + k = shares_cnt; + n = shares[0].total_cnt; + + if (n > SM2_KEY_MAX_SHARES) { + error_print(); + return -1; + } + for (i = 0; i < k; i++) { + if (shares[i].total_cnt != n + || shares[i].index >= n) { + error_print(); + return -1; + } + } + + sm2_bn_set_zero(s); + + for (i = 0; i < k; i++) { + // delta_i + SM2_Fn d; + int num = 1; + int den = 1; + int sign = 1; + + x_i = (int)(shares[i].index + 1); + + for (j = 0; j < k; j++) { + if (i != j) { + int x_j = (int)(shares[j].index + 1); + num *= -x_j; + den *= x_i - x_j; + } + } + if (num < 0) { + num = -num; + sign = -sign; + } + if (den < 0) { + den = -den; + sign = -sign; + } + + // delta_i = Fn( num / den ) + sm2_bn_set_word(d, den); + sm2_fn_inv(d, d); + sm2_fn_mul_word(d, d, num); + if (sign < 0) { + sm2_fn_neg(d, d); + } + + // s += delta_i * y_i + sm2_bn_from_bytes(y_i, shares[i].key.private_key); + if (sm2_bn_cmp(y_i, SM2_N) >= 0) { + gmssl_secure_clear(y_i, sizeof(y_i)); + gmssl_secure_clear(s, sizeof(s)); + error_print(); + return -1; + } + sm2_fn_mul(y_i, y_i, d); + sm2_fn_add(s, s, y_i); + } + + sm2_bn_to_bytes(s, s_bytes); + sm2_key_set_private_key(key, s_bytes); + + gmssl_secure_clear(y_i, sizeof(y_i)); + gmssl_secure_clear(s, sizeof(s)); + gmssl_secure_clear(s_bytes, sizeof(s_bytes)); + return 1; +} + +int sm2_key_share_encrypt_to_file(const SM2_KEY_SHARE *share, const char *pass, const char *path_prefix) +{ + int ret; + char *path = NULL; + FILE *fp = NULL; + int len; + + if (!share || !pass || !path_prefix) { + error_print(); + return -1; + } + if (!share->total_cnt || share->total_cnt > 12 || share->index >= share->total_cnt) { + sm2_key_share_print(stderr, 0, 0, "share", share); + error_print(); + return -1; + } + if ((len = snprintf(NULL, 0, "%s-%zu-of-%zu.pem", path_prefix, share->index + 1, share->total_cnt)) <= 0) { + error_print(); + return -1; + } + if (!(path = malloc(len + 1))) { + error_print(); + return -1; + } + snprintf(path, len+1, "%s-%zu-of-%zu.pem", path_prefix, share->index + 1, share->total_cnt); + + + if (!(fp = fopen(path, "wb"))) { + error_print(); + goto end; + } + if (sm2_private_key_info_encrypt_to_pem(&share->key, pass, fp) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + if (path) free(path); + if (fp) fclose(fp); + return ret; +} + +int sm2_key_share_decrypt_from_file(SM2_KEY_SHARE *share, const char *pass, const char *file) +{ + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/src/sm2_lib.c b/Core/GmSSL-3.1.1/src/sm2_lib.c new file mode 100644 index 0000000..10cd8f5 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_lib.c @@ -0,0 +1,938 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern const SM2_BN SM2_N; +extern const SM2_BN SM2_ONE; + +int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig) +{ + SM2_JACOBIAN_POINT _P, *P = &_P; + SM2_BN d; + SM2_BN d_inv; + SM2_BN e; + SM2_BN k; + SM2_BN x; + SM2_BN t; + SM2_BN r; + SM2_BN s; + + //fprintf(stderr, "sm2_do_sign\n"); + sm2_bn_from_bytes(d, key->private_key); + + // compute (d + 1)^-1 (mod n) + sm2_fn_add(d_inv, d, SM2_ONE); //sm2_bn_print(stderr, 0, 4, "(1+d)", d_inv); + if (sm2_bn_is_zero(d_inv)) { + error_print(); + return -1; + } + sm2_fn_inv(d_inv, d_inv); //sm2_bn_print(stderr, 0, 4, "(1+d)^-1", d_inv); + + // e = H(M) + sm2_bn_from_bytes(e, dgst); //sm2_bn_print(stderr, 0, 4, "e", e); + +retry: + // rand k in [1, n - 1] + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k); + + // (x, y) = kG + sm2_jacobian_point_mul_generator(P, k); + sm2_jacobian_point_get_xy(P, x, NULL); + //sm2_bn_print(stderr, 0, 4, "x", x); + + // r = e + x (mod n) + if (sm2_bn_cmp(e, SM2_N) >= 0) { + sm2_bn_sub(e, e, SM2_N); + } + if (sm2_bn_cmp(x, SM2_N) >= 0) { + sm2_bn_sub(x, x, SM2_N); + } + sm2_fn_add(r, e, x); //sm2_bn_print(stderr, 0, 4, "r = e + x (mod n)", r); + + // if r == 0 or r + k == n re-generate k + sm2_bn_add(t, r, k); + if (sm2_bn_is_zero(r) || sm2_bn_cmp(t, SM2_N) == 0) { + //sm2_bn_print(stderr, 0, 4, "r + k", t); + goto retry; + } + + // s = ((1 + d)^-1 * (k - r * d)) mod n + sm2_fn_mul(t, r, d); //sm2_bn_print(stderr, 0, 4, "r*d", t); + sm2_fn_sub(k, k, t); //sm2_bn_print(stderr, 0, 4, "k-r*d", k); + sm2_fn_mul(s, d_inv, k); //sm2_bn_print(stderr, 0, 4, "s = ((1 + d)^-1 * (k - r * d)) mod n", s); + + // check s != 0 + if (sm2_bn_is_zero(s)) { + goto retry; + } + + sm2_bn_to_bytes(r, sig->r); //sm2_bn_print_bn(stderr, 0, 4, "r", r); + sm2_bn_to_bytes(s, sig->s); //sm2_bn_print_bn(stderr, 0, 4, "s", s); + + gmssl_secure_clear(d, sizeof(d)); + gmssl_secure_clear(d_inv, sizeof(d_inv )); + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(t, sizeof(t)); + return 1; +} + +int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig) +{ + SM2_JACOBIAN_POINT _P, *P = &_P; + SM2_JACOBIAN_POINT _R, *R = &_R; + SM2_BN r; + SM2_BN s; + SM2_BN e; + SM2_BN x; + SM2_BN t; + + // parse public key + sm2_jacobian_point_from_bytes(P, (const uint8_t *)&key->public_key); + //sm2_jacobian_point_print(stderr, 0, 4, "P", P); + + // parse signature values + sm2_bn_from_bytes(r, sig->r); //sm2_bn_print(stderr, 0, 4, "r", r); + sm2_bn_from_bytes(s, sig->s); //sm2_bn_print(stderr, 0, 4, "s", s); + + // check r, s in [1, n-1] + if (sm2_bn_is_zero(r) == 1 + || sm2_bn_cmp(r, SM2_N) >= 0 + || sm2_bn_is_zero(s) == 1 + || sm2_bn_cmp(s, SM2_N) >= 0) { + error_print(); + return -1; + } + + // e = H(M) + sm2_bn_from_bytes(e, dgst); //sm2_bn_print(stderr, 0, 4, "e = H(M)", e); + + // t = r + s (mod n), check t != 0 + sm2_fn_add(t, r, s); //sm2_bn_print(stderr, 0, 4, "t = r + s (mod n)", t); + if (sm2_bn_is_zero(t)) { + error_print(); + return -1; + } + + // Q = s * G + t * P + sm2_jacobian_point_mul_sum(R, t, P, s); + sm2_jacobian_point_get_xy(R, x, NULL); + //sm2_bn_print(stderr, 0, 4, "x", x); + + // r' = e + x (mod n) + if (sm2_bn_cmp(e, SM2_N) >= 0) { + sm2_bn_sub(e, e, SM2_N); + } + if (sm2_bn_cmp(x, SM2_N) >= 0) { + sm2_bn_sub(x, x, SM2_N); + } + sm2_fn_add(e, e, x); //sm2_bn_print(stderr, 0, 4, "e + x (mod n)", e); + + // check if r == r' + if (sm2_bn_cmp(e, r) != 0) { + error_print(); + return -1; + } + return 1; +} + +int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (!sig) { + return 0; + } + if (asn1_integer_to_der(sig->r, 32, NULL, &len) != 1 + || asn1_integer_to_der(sig->s, 32, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(sig->r, 32, out, outlen) != 1 + || asn1_integer_to_der(sig->s, 32, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_signature_from_der(SM2_SIGNATURE *sig, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *r; + size_t rlen; + const uint8_t *s; + size_t slen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&r, &rlen, &d, &dlen) != 1 + || asn1_integer_from_der(&s, &slen, &d, &dlen) != 1 + || asn1_length_le(rlen, 32) != 1 + || asn1_length_le(slen, 32) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(sig, 0, sizeof(*sig)); + memcpy(sig->r + 32 - rlen, r, rlen); + memcpy(sig->s + 32 - slen, s, slen); + return 1; +} + +int sm2_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + SM2_SIGNATURE sig; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + if (sm2_signature_from_der(&sig, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + format_bytes(fp, fmt, ind, "r", sig.r, 32); + format_bytes(fp, fmt, ind, "s", sig.s, 32); + return 1; +} + +int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sigbuf, size_t *siglen) +{ + SM2_SIGNATURE sig; + + if (!key || !dgst || !sigbuf || !siglen) { + error_print(); + return -1; + } + + if (sm2_do_sign(key, dgst, &sig) != 1) { + error_print(); + return -1; + } + + *siglen = 0; + if (sm2_signature_to_der(&sig, &sigbuf, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_sign_fixlen(const SM2_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig) +{ + unsigned int trys = 200; // 200 trys is engouh + uint8_t buf[SM2_MAX_SIGNATURE_SIZE]; + size_t len; + + switch (siglen) { + case SM2_signature_compact_size: + case SM2_signature_typical_size: + case SM2_signature_max_size: + break; + default: + error_print(); + return -1; + } + + while (trys--) { + if (sm2_sign(key, dgst, buf, &len) != 1) { + error_print(); + return -1; + } + if (len == siglen) { + memcpy(sig, buf, len); + return 1; + } + } + + // might caused by bad randomness + error_print(); + return -1; +} + +int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *sigbuf, size_t siglen) +{ + SM2_SIGNATURE sig; + + if (!key || !dgst || !sigbuf || !siglen) { + error_print(); + return -1; + } + + if (sm2_signature_from_der(&sig, &sigbuf, &siglen) != 1 + || asn1_length_is_zero(siglen) != 1) { + error_print(); + return -1; + } + if (sm2_do_verify(key, dgst, &sig) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id, size_t idlen) +{ + SM3_CTX ctx; + uint8_t zin[18 + 32 * 6] = { + 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, + }; + + if (!z || !pub || !id) { + error_print(); + return -1; + } + + memcpy(&zin[18 + 32 * 4], pub->x, 32); + memcpy(&zin[18 + 32 * 5], pub->y, 32); + + sm3_init(&ctx); + if (strcmp(id, SM2_DEFAULT_ID) == 0) { + sm3_update(&ctx, zin, sizeof(zin)); + } else { + uint8_t idbits[2]; + idbits[0] = (uint8_t)(idlen >> 5); + idbits[1] = (uint8_t)(idlen << 3); + sm3_update(&ctx, idbits, 2); + sm3_update(&ctx, (uint8_t *)id, idlen); + sm3_update(&ctx, zin + 18, 32 * 6); + } + sm3_finish(&ctx, z); + return 1; +} + +int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen) +{ + if (!ctx || !key) { + error_print(); + return -1; + } + ctx->key = *key; + sm3_init(&ctx->sm3_ctx); + + if (id) { + uint8_t z[SM3_DIGEST_SIZE]; + if (idlen <= 0 || idlen > SM2_MAX_ID_LENGTH) { + error_print(); + return -1; + } + sm2_compute_z(z, &key->public_key, id, idlen); + sm3_update(&ctx->sm3_ctx, z, sizeof(z)); + } + return 1; +} + +int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (!ctx) { + error_print(); + return -1; + } + if (data && datalen > 0) { + 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[SM3_DIGEST_SIZE]; + + if (!ctx || !sig || !siglen) { + error_print(); + return -1; + } + sm3_finish(&ctx->sm3_ctx, dgst); + if (sm2_sign(&ctx->key, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_sign_finish_fixlen(SM2_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) +{ + uint8_t dgst[SM3_DIGEST_SIZE]; + + if (!ctx || !sig || !siglen) { + error_print(); + return -1; + } + sm3_finish(&ctx->sm3_ctx, dgst); + if (sm2_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen) +{ + if (!ctx || !key) { + error_print(); + return -1; + } + memset(ctx, 0, sizeof(*ctx)); + ctx->key.public_key = key->public_key; + sm3_init(&ctx->sm3_ctx); + + if (id) { + uint8_t z[SM3_DIGEST_SIZE]; + if (idlen <= 0 || idlen > SM2_MAX_ID_LENGTH) { + error_print(); + return -1; + } + sm2_compute_z(z, &key->public_key, id, idlen); + sm3_update(&ctx->sm3_ctx, z, sizeof(z)); + } + return 1; +} + +int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (!ctx) { + error_print(); + return -1; + } + if (data && datalen > 0) { + sm3_update(&ctx->sm3_ctx, data, datalen); + } + return 1; +} + +int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen) +{ + uint8_t dgst[SM3_DIGEST_SIZE]; + + if (!ctx || !sig) { + error_print(); + return -1; + } + sm3_finish(&ctx->sm3_ctx, dgst); + if (sm2_verify(&ctx->key, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_kdf(const uint8_t *in, size_t inlen, size_t outlen, uint8_t *out) +{ + SM3_CTX ctx; + uint8_t counter_be[4]; + uint8_t dgst[SM3_DIGEST_SIZE]; + uint32_t counter = 1; + size_t len; + + while (outlen) { + PUTU32(counter_be, counter); + counter++; + + sm3_init(&ctx); + sm3_update(&ctx, in, inlen); + sm3_update(&ctx, counter_be, sizeof(counter_be)); + sm3_finish(&ctx, dgst); + + len = outlen < SM3_DIGEST_SIZE ? outlen : SM3_DIGEST_SIZE; + memcpy(out, dgst, len); + out += len; + outlen -= len; + } + + memset(&ctx, 0, sizeof(SM3_CTX)); + memset(dgst, 0, sizeof(dgst)); + return 1; +} + +static int all_zero(const uint8_t *buf, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + if (buf[i]) { + return 0; + } + } + return 1; +} + +int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out) +{ + SM2_BN k; + SM2_JACOBIAN_POINT _P, *P = &_P; + SM2_JACOBIAN_POINT _C1, *C1 = &_C1; + SM2_JACOBIAN_POINT _kP, *kP = &_kP; + uint8_t x2y2[64]; + SM3_CTX sm3_ctx; + + if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE)) { + error_print(); + return -1; + } + + sm2_jacobian_point_from_bytes(P, (uint8_t *)&key->public_key); + + // S = h * P, check S != O + // for sm2 curve, h == 1 and S == P + // SM2_POINT can not present point at infinity, do do nothing here + +retry: + // rand k in [1, n - 1] + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k); + + // output C1 = k * G = (x1, y1) + sm2_jacobian_point_mul_generator(C1, k); + sm2_jacobian_point_to_bytes(C1, (uint8_t *)&out->point); + + // k * P = (x2, y2) + sm2_jacobian_point_mul(kP, k, P); + sm2_jacobian_point_to_bytes(kP, x2y2); + + // t = KDF(x2 || y2, inlen) + sm2_kdf(x2y2, 64, inlen, out->ciphertext); + + // if t is all zero, retry + if (all_zero(out->ciphertext, inlen)) { + goto retry; + } + + // output C2 = M xor t + gmssl_memxor(out->ciphertext, out->ciphertext, in, inlen); + out->ciphertext_size = (uint32_t)inlen; + + // output C3 = Hash(x2 || m || y2) + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, x2y2, 32); + sm3_update(&sm3_ctx, in, inlen); + sm3_update(&sm3_ctx, x2y2 + 32, 32); + sm3_finish(&sm3_ctx, out->hash); + + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(kP, sizeof(SM2_JACOBIAN_POINT)); + gmssl_secure_clear(x2y2, sizeof(x2y2)); + return 1; +} + +int sm2_do_encrypt_fixlen(const SM2_KEY *key, const uint8_t *in, size_t inlen, int point_size, SM2_CIPHERTEXT *out) +{ + unsigned int trys = 200; + SM2_BN k; + SM2_JACOBIAN_POINT _P, *P = &_P; + SM2_JACOBIAN_POINT _C1, *C1 = &_C1; + SM2_JACOBIAN_POINT _kP, *kP = &_kP; + uint8_t x2y2[64]; + SM3_CTX sm3_ctx; + + if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE)) { + error_print(); + return -1; + } + + switch (point_size) { + case SM2_ciphertext_compact_point_size: + case SM2_ciphertext_typical_point_size: + case SM2_ciphertext_max_point_size: + break; + default: + error_print(); + return -1; + } + + sm2_jacobian_point_from_bytes(P, (uint8_t *)&key->public_key); + + // S = h * P, check S != O + // for sm2 curve, h == 1 and S == P + // SM2_POINT can not present point at infinity, do do nothing here + +retry: + // rand k in [1, n - 1] + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k); + + // output C1 = k * G = (x1, y1) + sm2_jacobian_point_mul_generator(C1, k); + sm2_jacobian_point_to_bytes(C1, (uint8_t *)&out->point); + + // check fixlen + if (trys) { + size_t len = 0; + asn1_integer_to_der(out->point.x, 32, NULL, &len); + asn1_integer_to_der(out->point.y, 32, NULL, &len); + if (len != point_size) { + trys--; + goto retry; + } + } else { + gmssl_secure_clear(k, sizeof(k)); + error_print(); + return -1; + } + + // k * P = (x2, y2) + sm2_jacobian_point_mul(kP, k, P); + sm2_jacobian_point_to_bytes(kP, x2y2); + + // t = KDF(x2 || y2, inlen) + sm2_kdf(x2y2, 64, inlen, out->ciphertext); + + // if t is all zero, retry + if (all_zero(out->ciphertext, inlen)) { + goto retry; + } + + // output C2 = M xor t + gmssl_memxor(out->ciphertext, out->ciphertext, in, inlen); + out->ciphertext_size = (uint32_t)inlen; + + // output C3 = Hash(x2 || m || y2) + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, x2y2, 32); + sm3_update(&sm3_ctx, in, inlen); + sm3_update(&sm3_ctx, x2y2 + 32, 32); + sm3_finish(&sm3_ctx, out->hash); + + gmssl_secure_clear(k, sizeof(k)); + gmssl_secure_clear(kP, sizeof(SM2_JACOBIAN_POINT)); + gmssl_secure_clear(x2y2, sizeof(x2y2)); + return 1; +} + +int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen) +{ + int ret = -1; + SM2_BN d; + SM2_JACOBIAN_POINT _C1, *C1 = &_C1; + uint8_t x2y2[64]; + SM3_CTX sm3_ctx; + uint8_t hash[32]; + + // check C1 is on sm2 curve + sm2_jacobian_point_from_bytes(C1, (uint8_t *)&in->point); + if (!sm2_jacobian_point_is_on_curve(C1)) { + error_print(); + return -1; + } + + // check if S = h * C1 is point at infinity + // this will not happen, as SM2_POINT can not present point at infinity + + // d * C1 = (x2, y2) + sm2_bn_from_bytes(d, key->private_key); + sm2_jacobian_point_mul(C1, d, C1); + + // t = KDF(x2 || y2, klen) and check t is not all zeros + sm2_jacobian_point_to_bytes(C1, x2y2); + sm2_kdf(x2y2, 64, in->ciphertext_size, out); + if (all_zero(out, in->ciphertext_size)) { + error_print(); + goto end; + } + + // M = C2 xor t + gmssl_memxor(out, out, in->ciphertext, in->ciphertext_size); + *outlen = in->ciphertext_size; + + // u = Hash(x2 || M || y2) + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, x2y2, 32); + sm3_update(&sm3_ctx, out, in->ciphertext_size); + sm3_update(&sm3_ctx, x2y2 + 32, 32); + sm3_finish(&sm3_ctx, hash); + + // check if u == C3 + if (memcmp(in->hash, hash, sizeof(hash)) != 0) { + error_print(); + goto end; + } + ret = 1; + +end: + gmssl_secure_clear(d, sizeof(d)); + gmssl_secure_clear(C1, sizeof(SM2_JACOBIAN_POINT)); + gmssl_secure_clear(x2y2, sizeof(x2y2)); + return ret; +} + +int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *C, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (!C) { + return 0; + } + if (asn1_integer_to_der(C->point.x, 32, NULL, &len) != 1 + || asn1_integer_to_der(C->point.y, 32, NULL, &len) != 1 + || asn1_octet_string_to_der(C->hash, 32, NULL, &len) != 1 + || asn1_octet_string_to_der(C->ciphertext, C->ciphertext_size, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(C->point.x, 32, out, outlen) != 1 + || asn1_integer_to_der(C->point.y, 32, out, outlen) != 1 + || asn1_octet_string_to_der(C->hash, 32, out, outlen) != 1 + || asn1_octet_string_to_der(C->ciphertext, C->ciphertext_size, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_ciphertext_from_der(SM2_CIPHERTEXT *C, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *x; + const uint8_t *y; + const uint8_t *hash; + const uint8_t *c; + size_t xlen, ylen, hashlen, clen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&x, &xlen, &d, &dlen) != 1 + || asn1_length_le(xlen, 32) != 1) { + error_print(); + return -1; + } + if (asn1_integer_from_der(&y, &ylen, &d, &dlen) != 1 + || asn1_length_le(ylen, 32) != 1) { + error_print(); + return -1; + } + if (asn1_octet_string_from_der(&hash, &hashlen, &d, &dlen) != 1 + || asn1_check(hashlen == 32) != 1) { + error_print(); + return -1; + } + if (asn1_octet_string_from_der(&c, &clen, &d, &dlen) != 1 + // || asn1_length_is_zero(clen) == 1 + || asn1_length_le(clen, SM2_MAX_PLAINTEXT_SIZE) != 1) { + error_print(); + return -1; + } + if (asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(C, 0, sizeof(SM2_CIPHERTEXT)); + memcpy(C->point.x + 32 - xlen, x, xlen); + memcpy(C->point.y + 32 - ylen, y, ylen); + if (sm2_point_is_on_curve(&C->point) != 1) { + error_print(); + return -1; + } + memcpy(C->hash, hash, hashlen); + memcpy(C->ciphertext, c, clen); + C->ciphertext_size = (uint8_t)clen; + return 1; +} + +int sm2_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + uint8_t buf[512] = {0}; + SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)buf; + + if (sm2_ciphertext_from_der(c, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + format_bytes(fp, fmt, ind, "XCoordinate", c->point.x, 32); + format_bytes(fp, fmt, ind, "YCoordinate", c->point.y, 32); + format_bytes(fp, fmt, ind, "HASH", c->hash, 32); + format_bytes(fp, fmt, ind, "CipherText", c->ciphertext, c->ciphertext_size); + return 1; +} + +int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + SM2_CIPHERTEXT C; + + if (!key || !in || !out || !outlen) { + error_print(); + return -1; + } + if (!inlen) { + error_print(); + return -1; + } + + if (sm2_do_encrypt(key, in, inlen, &C) != 1) { + error_print(); + return -1; + } + *outlen = 0; + if (sm2_ciphertext_to_der(&C, &out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_encrypt_fixlen(const SM2_KEY *key, const uint8_t *in, size_t inlen, int point_size, uint8_t *out, size_t *outlen) +{ + SM2_CIPHERTEXT C; + + if (!key || !in || !out || !outlen) { + error_print(); + return -1; + } + if (!inlen) { + error_print(); + return -1; + } + + if (sm2_do_encrypt_fixlen(key, in, inlen, point_size, &C) != 1) { + error_print(); + return -1; + } + *outlen = 0; + if (sm2_ciphertext_to_der(&C, &out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + SM2_CIPHERTEXT C; + + if (!key || !in || !out || !outlen) { + error_print(); + return -1; + } + if (sm2_ciphertext_from_der(&C, &in, &inlen) != 1 + || asn1_length_is_zero(inlen) != 1) { + error_print(); + return -1; + } + if (sm2_do_decrypt(key, &C, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_do_ecdh(const SM2_KEY *key, const SM2_POINT *peer_public, SM2_POINT *out) +{ + /* + if (sm2_point_is_on_curve(peer_public) != 1) { + error_print(); + return -1; + } + */ + if (sm2_point_mul(out, key->private_key, peer_public) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_ecdh(const SM2_KEY *key, const uint8_t *peer_public, size_t peer_public_len, SM2_POINT *out) +{ + SM2_POINT point; + + if (!key || !peer_public || !peer_public_len || !out) { + error_print(); + return -1; + } + if (sm2_point_from_octets(&point, peer_public, peer_public_len) != 1) { + error_print(); + return -1; + } + if (sm2_do_ecdh(key, &point, out) != 1) { + error_print(); + return -1; + } + return 1; +} + + +// (x1, y1) = k * G +// r = e + x1 +// s = (k - r * d)/(1 + d) = (k +r - r * d - r)/(1 + d) = (k + r - r(1 +d))/(1 + d) = (k + r)/(1 + d) - r +// = -r + (k + r)*(1 + d)^-1 +// = -r + (k + r) * d' + +int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig) +{ + SM2_JACOBIAN_POINT R; + SM2_BN e; + SM2_BN k; + SM2_BN x1; + SM2_BN r; + SM2_BN s; + + // e = H(M) + sm2_bn_from_bytes(e, dgst); + if (sm2_bn_cmp(e, SM2_N) >= 0) { + sm2_bn_sub(e, e, SM2_N); + } + + // rand k in [1, n - 1] + do { + if (sm2_fn_rand(k) != 1) { + error_print(); + return -1; + } + } while (sm2_bn_is_zero(k)); + + // (x1, y1) = kG + sm2_jacobian_point_mul_generator(&R, k); + sm2_jacobian_point_get_xy(&R, x1, NULL); + + // r = e + x1 (mod n) + sm2_fn_add(r, e, x1); + + // s = (k + r) * d' - r + sm2_bn_add(s, k, r); + sm2_fn_mul(s, s, d); + sm2_fn_sub(s, s, r); + + sm2_bn_to_bytes(r, sig->r); + sm2_bn_to_bytes(s, sig->s); + return 1; +} + diff --git a/Core/GmSSL-3.1.1/src/sm2_recover.c b/Core/GmSSL-3.1.1/src/sm2_recover.c new file mode 100644 index 0000000..291498d --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_recover.c @@ -0,0 +1,138 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include + + +extern SM2_BN SM2_P; +extern SM2_BN SM2_B; +extern SM2_BN SM2_N; +extern SM2_BN SM2_THREE; + +// r = H(Z||M) + x1 (mod n) +// x1 = r - H(Z||M) (mod n) or (r - H(Z||M) (mod n)) + n +// y1 = sqrt(x1^3 + a*x1 + b) +// R = (x1, y1) or (x1, -y1) +// P = (r + s)^-1 * R - (r + s)^-1 * s * G +int sm2_signature_to_public_key_points(const SM2_SIGNATURE *sig, const uint8_t dgst[32], + SM2_POINT points[4], size_t *points_cnt) +{ + SM2_BN SM2_P_SUB_N; + SM2_JACOBIAN_POINT P; + SM2_JACOBIAN_POINT R; + + SM2_Fp r; + SM2_Fp s; + SM2_Fp e; + SM2_Fn u; + SM2_Fn v; + SM2_Fp x1; + SM2_Fp y1; + + // FIXME: check r, s + sm2_bn_from_bytes(r, sig->r); + sm2_bn_from_bytes(s, sig->s); + + // u = (r + s)^-1, v = -(r + s)^-1 * s + sm2_fn_add(u, r, s); + sm2_fn_inv(u, u); + sm2_fn_mul(v, u, s); + sm2_fn_neg(v, v); + + // e = H(Z||M) (mod n) + sm2_bn_from_bytes(e, dgst); + if (sm2_bn_cmp(e, SM2_N) >= 0) { + sm2_bn_sub(e, e, SM2_N); + } + + // x1 = r - e (mod n) + sm2_fn_sub(x1, r, e); + + // y1 = sqrt(x1^3 + a*x + b) = sqrt((x1^2 + a)*x1 + b) + sm2_fp_sqr(y1, x1); + sm2_fp_sub(y1, y1, SM2_THREE); + sm2_fp_mul(y1, y1, x1); + sm2_fp_add(y1, y1, SM2_B); + + if (sm2_fp_sqrt(y1, y1) != 1) { + error_print(); + return -1; + } + sm2_jacobian_point_set_xy(&R, x1, y1); + + // P = u * R + v * G + sm2_jacobian_point_mul_sum(&P, u, &R, v); + sm2_jacobian_point_to_bytes(&P, (uint8_t *)&points[0]); + + // P' = u * (-R) + v * G + sm2_jacobian_point_neg(&R, &R); + sm2_jacobian_point_mul_sum(&P, u, &R, v); + sm2_jacobian_point_to_bytes(&P, (uint8_t *)&points[1]); + *points_cnt = 2; + + // if x1 in [n, p-1], x1 (mod n) in [0, p-n-1] + // ==> if x1 (mod n) in [0, p-n-1], x1 == (x1 (mod n) + n) (mod p) + sm2_bn_sub(SM2_P_SUB_N, SM2_P, SM2_N); + + if (sm2_bn_cmp(x1, SM2_P_SUB_N) < 0) { + + // x1' = x1 (mod n) + n + sm2_bn_add(x1, x1, SM2_N); + + // y1' = sqrt(x1'^3 + a*x' + b) + sm2_fp_sqr(y1, x1); + sm2_fp_sub(y1, y1, SM2_THREE); + sm2_fp_mul(y1, y1, x1); + sm2_fp_add(y1, y1, SM2_B); + if (sm2_fp_sqrt(y1, y1) != 1) { + error_print(); + return -1; + } + sm2_jacobian_point_set_xy(&R, x1, y1); + + // P = u * R + v * G + sm2_jacobian_point_mul_sum(&P, u, &R, v); + sm2_jacobian_point_to_bytes(&P, (uint8_t *)&points[2]); + // P' = u * (-R) + v * G + sm2_jacobian_point_neg(&R, &R); + sm2_jacobian_point_mul_sum(&P, u, &R, v); + sm2_jacobian_point_to_bytes(&P, (uint8_t *)&points[3]); + *points_cnt = 4; + } + + return 1; +} + +// verify the xR of R = s * G + (s + r) * P +// so (-r, -s) is also a valid SM2 signature +int sm2_signature_conjugate(const SM2_SIGNATURE *sig, SM2_SIGNATURE *new_sig) +{ + SM2_Fn r; + SM2_Fn s; + + // FIXME: check r,s + sm2_bn_from_bytes(r, sig->r); + sm2_bn_from_bytes(s, sig->s); + sm2_fn_neg(r, r); + sm2_fn_neg(s, s); + sm2_bn_to_bytes(r, new_sig->r); + sm2_bn_to_bytes(s, new_sig->s); + + return 1; +} + +// TODO: Add API to support sig,siglen + + + diff --git a/Core/GmSSL-3.1.1/src/sm2_ring.c b/Core/GmSSL-3.1.1/src/sm2_ring.c new file mode 100644 index 0000000..a0adeaf --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm2_ring.c @@ -0,0 +1,580 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + + +extern SM2_BN SM2_N; +extern SM2_BN SM2_ONE; + + +static int compare_point(const void *P, const void *Q) +{ + const uint8_t *p = (uint8_t *)P; + const uint8_t *q = (uint8_t *)Q; + int i, r; + for (i = 0; i < sizeof(SM2_POINT); i++) { + r = p[i] - q[i]; + if (r) { + return r; + } + } + return 0; +} + +static int sm2_ring_sort_public_keys(SM2_POINT *points, size_t points_cnt) +{ + qsort(points, points_cnt, sizeof(SM2_POINT), compare_point); + return 1; +} + +int sm2_ring_signature_to_der(const sm2_bn_t r, const sm2_bn_t *s, size_t s_cnt, uint8_t **out, size_t *outlen) +{ + size_t i, len = 0; + uint8_t *p = *out; + + if (asn1_integer_to_der(r, 32, NULL, &len) != 1) { + error_print(); + return -1; + } + for (i = 0; i < s_cnt; i++) { + if (asn1_integer_to_der(s[i], 32, NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(r, 32, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < s_cnt; i++) { + if (asn1_integer_to_der(s[i], 32, out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +// FIXME: support when s_vec == NULL +int sm2_ring_signature_from_der(sm2_bn_t r0, sm2_bn_t *s_vec, size_t *s_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *p; + size_t len; + uint8_t *s = (uint8_t *)&s_vec[0]; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1 + || asn1_length_le(len, 32) != 1) { + error_print(); + return -1; + } + memset(r0, 0, 32); + memcpy(r0 + 32 - len, p, len); + + *s_cnt = 0; + while (dlen) { + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1 + || asn1_length_le(len, 32) != 1) { + error_print(); + return -1; + } + memset(s, 0, 32 - len); + memcpy(s + 32 - len, p, len); + s += 32; + + (*s_cnt)++; + } + return 1; +} + +int sm2_ring_do_sign(const SM2_KEY *sign_key, + const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], uint8_t r0[32], sm2_bn_t *s_vec) +{ + size_t i; + size_t sign_index = public_keys_cnt; // assign an invalid value + + SM2_JACOBIAN_POINT R; + SM2_JACOBIAN_POINT P; + SM2_Fn e; + SM2_Fn k; + SM2_Fp x; + SM2_Fn r; + SM2_Fn s; + SM2_Fn t; + SM2_Fn d; + + // e = H(M) (mod n) + sm2_bn_from_bytes(e, dgst); + if (sm2_bn_cmp(e, SM2_N) >= 0) { + sm2_bn_sub(e, e, SM2_N); + } + + // find signer's index + for (i = 0; i < public_keys_cnt; i++) { + if (memcmp(&public_keys[i], &(sign_key->public_key), sizeof(SM2_POINT)) == 0) { + sign_index = i; + break; + } + } + if (sign_index >= public_keys_cnt) { + error_print(); + return -1; + } + + // k[i] = rand(1, n-1), r[i], s[i] will be computed at the last step + sm2_fn_rand(k); + + // R[i+1] = k[i] * G + sm2_jacobian_point_mul_generator(&R, k); + sm2_jacobian_point_get_xy(&R, x, NULL); + + // i = i + 1 (mod N) + for (i = (i + 1) % public_keys_cnt; i != sign_index; i = (i + 1) % public_keys_cnt) { + + // r[i] = x[i] + e (mod n) + sm2_fn_add(r, x, e); + + // output r[0] + if (i == 0) { + sm2_bn_to_bytes(r, r0); + } + + // s[i] = rand(1, n-1) + sm2_fn_rand(s); + sm2_bn_to_bytes(s, s_vec[i]); + + // R[i+1] = k[i] * G = (s[i] + r[i]) * P[i] + s[i] * G + sm2_fn_add(t, s, r); + sm2_jacobian_point_from_bytes(&P, (const uint8_t *)&public_keys[i]); + sm2_jacobian_point_mul_sum(&R, t, &P, s); + sm2_jacobian_point_get_xy(&R, x, NULL); + } + + // r[i] = x[i] + e (mod n) + sm2_fn_add(r, x, e); + if (i == 0) { + sm2_bn_to_bytes(r, r0); + } + + // s[i] = (k[i] - r[i] * d)/(1 + d) + sm2_bn_from_bytes(d, sign_key->private_key); + sm2_fn_mul(r, r, d); + sm2_fn_sub(s, k, r); + sm2_fn_add(d, d, SM2_ONE); + sm2_fn_inv(d, d); + sm2_fn_mul(s, s, d); + sm2_bn_to_bytes(s, s_vec[i]); + + // cleanup + memset(d, 0, sizeof(d)); + memset(k, 0, sizeof(k)); + memset(r, 0, sizeof(r)); + return 1; +} + +int sm2_ring_do_verify(const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], const uint8_t r0[32], const sm2_bn_t *s_vec) +{ + SM2_JACOBIAN_POINT P; + SM2_JACOBIAN_POINT R; + SM2_Fn r; + SM2_Fn r_; + SM2_Fn s; + SM2_Fn e; + SM2_Fn t; + SM2_Fn x; + size_t i; + + sm2_bn_from_bytes(e, dgst); + if (sm2_bn_cmp(e, SM2_N) >= 0) { + sm2_bn_sub(e, e, SM2_N); + } + + sm2_bn_from_bytes(r, r0); + + for (i = 0; i < public_keys_cnt; i++) { + sm2_bn_from_bytes(s, s_vec[i]); + + // R(x, y) = k * G = s * G + (s + r) * P + sm2_fn_add(t, s, r); + sm2_jacobian_point_from_bytes(&P, (const uint8_t *)&public_keys[i]); + sm2_jacobian_point_mul_sum(&R, t, &P, s); + sm2_jacobian_point_get_xy(&R, x, NULL); + + // r = e + x (mod n) + sm2_fn_add(r, x, e); + } + + sm2_bn_from_bytes(r_, r0); + if (sm2_bn_cmp(r_, r) != 0) { + return 0; + } + return 1; +} + +int sm2_ring_sign(const SM2_KEY *sign_key, + const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], uint8_t *sig, size_t *siglen) +{ + sm2_bn_t r; + sm2_bn_t s[SM2_RING_SIGN_MAX_SIGNERS]; + + if (!public_keys_cnt || public_keys_cnt > sizeof(s)/sizeof(s[0])) { + error_print(); + return -1; + } + if (sm2_ring_do_sign(sign_key, public_keys, public_keys_cnt, dgst, r, s) != 1) { + error_print(); + return -1; + } + + *siglen = 0; + if (sm2_ring_signature_to_der(r, s, public_keys_cnt, &sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_ring_verify(const SM2_POINT *public_keys, size_t public_keys_cnt, + const uint8_t dgst[32], const uint8_t *sig, size_t siglen) +{ + int ret; + sm2_bn_t r; + sm2_bn_t s[SM2_RING_SIGN_MAX_SIGNERS]; + size_t s_cnt; + + if (!public_keys_cnt || public_keys_cnt > sizeof(s)/sizeof(s[0])) { + error_print(); + return -1; + } + if (sm2_ring_signature_from_der(r, s, &s_cnt, &sig, &siglen) != 1 + || asn1_length_is_zero(siglen) != 1) { + error_print(); + return -1; + } + if (s_cnt != public_keys_cnt) { + error_print(); + return -1; + } + + if ((ret = sm2_ring_do_verify(public_keys, public_keys_cnt, dgst, r, s)) < 0) { + error_print(); + return -1; + } + return ret; +} + +int sm2_ring_sign_init(SM2_RING_SIGN_CTX *ctx, const SM2_KEY *sign_key, const char *id, size_t idlen) +{ + sm3_init(&ctx->sm3_ctx); + ctx->sign_key = *sign_key; + ctx->public_keys[0] = sign_key->public_key; + ctx->public_keys_count = 1; + if (!(ctx->id = malloc(idlen + 1))) { + error_print(); + return -1; + } + memcpy(ctx->id, id, idlen); + ctx->id[idlen] = 0; + ctx->idlen = idlen; + ctx->state = 0; + return 1; +} + +int sm2_ring_sign_add_signer(SM2_RING_SIGN_CTX *ctx, const SM2_KEY *public_key) +{ + if (ctx->state) { + error_print(); + return -1; + } + if (ctx->public_keys_count >= SM2_RING_SIGN_MAX_SIGNERS) { + error_print(); + return -1; + } + ctx->public_keys[ctx->public_keys_count++] = public_key->public_key; + return 1; +} + +int sm2_ring_sign_update(SM2_RING_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (!ctx->state) { + SM2_POINT point = ctx->public_keys[0]; + uint8_t z[32]; + size_t i; + + for (i = 1; i < ctx->public_keys_count; i++) { + sm2_point_add(&point, &point, &ctx->public_keys[i]); + } + sm2_compute_z(z, &point, ctx->id, ctx->idlen); + sm3_update(&ctx->sm3_ctx, z, sizeof(z)); + ctx->state = 1; + } + if (data && datalen) { + sm3_update(&ctx->sm3_ctx, data, datalen); + } + return 1; +} + +int sm2_ring_sign_finish(SM2_RING_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) +{ + uint8_t dgst[32]; + + sm3_finish(&ctx->sm3_ctx, dgst); + + if (sm2_ring_sort_public_keys(ctx->public_keys, ctx->public_keys_count) != 1) { + error_print(); + return -1; + } + if (sm2_ring_sign(&ctx->sign_key, ctx->public_keys, ctx->public_keys_count, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm2_ring_verify_init(SM2_RING_SIGN_CTX *ctx, const char *id, size_t idlen) +{ + sm3_init(&ctx->sm3_ctx); + ctx->public_keys_count = 0; + if (!(ctx->id = malloc(idlen + 1))) { + error_print(); + return -1; + } + memcpy(ctx->id, id, idlen); + ctx->id[idlen] = 0; + ctx->idlen = idlen; + ctx->state = 0; + return 1; +} + +int sm2_ring_verify_add_signer(SM2_RING_SIGN_CTX *ctx, const SM2_KEY *public_key) +{ + if (ctx->state) { + error_print(); + return -1; + } + if (ctx->public_keys_count >= SM2_RING_SIGN_MAX_SIGNERS) { + error_print(); + return -1; + } + ctx->public_keys[ctx->public_keys_count++] = public_key->public_key; + return 1; +} + +int sm2_ring_verify_update(SM2_RING_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (!ctx->state) { + SM2_POINT point = ctx->public_keys[0]; + uint8_t z[32]; + size_t i; + + for (i = 1; i < ctx->public_keys_count; i++) { + sm2_point_add(&point, &point, &ctx->public_keys[i]); + } + sm2_compute_z(z, &point, ctx->id, ctx->idlen); + sm3_update(&ctx->sm3_ctx, z, sizeof(z)); + ctx->state = 1; + } + if (data && datalen) { + sm3_update(&ctx->sm3_ctx, data, datalen); + } + return 1; +} + +int sm2_ring_verify_finish(SM2_RING_SIGN_CTX *ctx, uint8_t *sig, size_t siglen) +{ + uint8_t dgst[32]; + int ret; + + sm3_finish(&ctx->sm3_ctx, dgst); + + if (sm2_ring_sort_public_keys(ctx->public_keys, ctx->public_keys_count) != 1) { + error_print(); + return -1; + } + if ((ret = sm2_ring_verify(ctx->public_keys, ctx->public_keys_count, dgst, sig, siglen)) != 1) { + error_print(); + return -1; + } + return ret; +} + +static int test_sm2_ring_do_sign(void) +{ + SM2_KEY sign_key; + SM2_POINT public_keys[5]; + size_t public_keys_count = sizeof(public_keys)/sizeof(public_keys[0]); + size_t sign_index, i; + uint8_t dgst[32]; + uint8_t r[32]; + uint8_t s[sizeof(public_keys)/sizeof(public_keys[0])][32]; + + for (sign_index = 0; sign_index < 5; sign_index++) { + + for (i = 0; i < public_keys_count; i++) { + SM2_KEY key; + sm2_key_generate(&key); + memcpy(&public_keys[i], &(key.public_key), sizeof(SM2_POINT)); + + if (i == sign_index) { + memcpy(&sign_key, &key, sizeof(SM2_KEY)); + } + } + if (sm2_ring_do_sign(&sign_key, public_keys, public_keys_count, dgst, r, s) != 1) { + error_print(); + return -1; + } + if (sm2_ring_do_verify(public_keys, public_keys_count, dgst, r, s) != 1) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_sm2_ring_sign(void) +{ + SM2_KEY sign_key; + SM2_POINT public_keys[5]; + size_t public_keys_count = sizeof(public_keys)/sizeof(public_keys[0]); + size_t sign_index = 2, i; + uint8_t dgst[32]; + uint8_t sig[9 + (2 + 33) * (1 + sizeof(public_keys)/sizeof(public_keys[0]))]; + size_t siglen = 0; + + for (i = 0; i < public_keys_count; i++) { + SM2_KEY key; + sm2_key_generate(&key); + memcpy(&public_keys[i], &(key.public_key), sizeof(SM2_POINT)); + + if (i == sign_index) { + memcpy(&sign_key, &key, sizeof(SM2_KEY)); + } + } + if (sm2_ring_sign(&sign_key, public_keys, public_keys_count, dgst, sig, &siglen) != 1) { + error_print(); + return -1; + } + if (sm2_ring_verify(public_keys, 5, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_sm2_ring_sign_crosscheck(void) +{ + SM2_KEY sign_key; + SM2_POINT public_key; + uint8_t dgst[32]; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen = 0; + + sm2_key_generate(&sign_key); + public_key = sign_key.public_key; + + if (sm2_ring_sign(&sign_key, &public_key, 1, dgst, sig, &siglen) != 1) { + error_print(); + return -1; + } + if (sm2_ring_verify(&public_key, 1, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_sm2_ring_sign_update(void) +{ + SM2_KEY keys[5]; + SM2_RING_SIGN_CTX sign_ctx; + SM2_RING_SIGN_CTX verify_ctx; + size_t public_keys_count = sizeof(keys)/sizeof(keys[0]); + char *id = "Alice"; + uint8_t msg[128] = {0}; + uint8_t sig[9 + (2 + 33) * (1 + sizeof(keys)/sizeof(keys[0]))]; + size_t siglen = 0; + size_t i; + + for (i = 0; i < public_keys_count; i++) { + sm2_key_generate(&keys[i]); + } + + if (sm2_ring_sign_init(&sign_ctx, &keys[0], id, strlen(id)) != 1) { + error_print(); + return -1; + } + for (i = 1; i < public_keys_count; i++) { + if (sm2_ring_sign_add_signer(&sign_ctx, &keys[i]) != 1) { + error_print(); + return -1; + } + } + if (sm2_ring_sign_update(&sign_ctx, msg, 32) != 1 + || sm2_ring_sign_update(&sign_ctx, msg + 32, 32) != 1 + || sm2_ring_sign_update(&sign_ctx, msg + 64, 64) != 1 + || sm2_ring_sign_finish(&sign_ctx, sig, &siglen) != 1) { + error_print(); + return -1; + } + + if (sm2_ring_verify_init(&verify_ctx, id, strlen(id)) != 1) { + error_print(); + return -1; + } + for (i = 0; i < public_keys_count; i++) { + if (sm2_ring_verify_add_signer(&verify_ctx, &keys[i]) != 1) { + error_print(); + return -1; + } + } + if (sm2_ring_verify_update(&verify_ctx, msg, sizeof(msg)) != 1) { + error_print(); + return -1; + } + if (sm2_ring_verify_finish(&verify_ctx, sig, siglen) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_sm2_ring() +{ + if (test_sm2_ring_do_sign() != 1) { error_print(); return -1; } + if (test_sm2_ring_sign() != 1) { error_print(); return -1; } + if (test_sm2_ring_sign_crosscheck() != 1) { error_print(); return -1; } + if (test_sm2_ring_sign_update() != 1) { error_print(); return -1; } + return 1; +} + diff --git a/Core/GmSSL-3.1.1/src/sm3.c b/Core/GmSSL-3.1.1/src/sm3.c new file mode 100644 index 0000000..a82f901 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm3.c @@ -0,0 +1,377 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include + + +#ifdef SM3_SSE3 +# include +# include + +# define _mm_rotl_epi32(X,i) \ + _mm_xor_si128(_mm_slli_epi32((X),(i)), _mm_srli_epi32((X),32-(i))) +#endif + + +#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 + +static 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, + */ +}; + +#ifndef SM3_AVX_BMI2 +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; + } +} +#endif + +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; +} + +void sm3_update(SM3_CTX *ctx, const uint8_t *data, size_t data_len) +{ + size_t blocks; + + ctx->num &= 0x3f; + if (ctx->num) { + size_t 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; + if (blocks) { + 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->num &= 0x3f; + ctx->block[ctx->num] = 0x80; + + if (ctx->num <= SM3_BLOCK_SIZE - 9) { + 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_blocks(ctx->digest, ctx->block, 1); + 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_blocks(ctx->digest, ctx->block, 1); + for (i = 0; i < 8; i++) { + PUTU32(digest + i*4, ctx->digest[i]); + } +} + +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); + memset(&ctx, 0, sizeof(ctx)); +} diff --git a/Core/GmSSL-3.1.1/src/sm3_hmac.c b/Core/GmSSL-3.1.1/src/sm3_hmac.c new file mode 100644 index 0000000..76011a7 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm3_hmac.c @@ -0,0 +1,86 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include + +/** + * 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); + memset(ctx, 0, sizeof(*ctx)); +} + +void sm3_hmac(const uint8_t *key, size_t key_len, + const uint8_t *data, size_t data_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); +} diff --git a/Core/GmSSL-3.1.1/src/sm3_kdf.c b/Core/GmSSL-3.1.1/src/sm3_kdf.c new file mode 100644 index 0000000..a2f46bf --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm3_kdf.c @@ -0,0 +1,54 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include + + +void sm3_kdf_init(SM3_KDF_CTX *ctx, size_t outlen) +{ + sm3_init(&ctx->sm3_ctx); + ctx->outlen = outlen; +} + +void sm3_kdf_update(SM3_KDF_CTX *ctx, const uint8_t *data, size_t datalen) +{ + sm3_update(&ctx->sm3_ctx, data, datalen); +} + +void sm3_kdf_finish(SM3_KDF_CTX *ctx, uint8_t *out) +{ + SM3_CTX sm3_ctx; + size_t outlen = ctx->outlen; + uint8_t counter_be[4]; + uint8_t dgst[SM3_DIGEST_SIZE]; + uint32_t counter = 1; + size_t len; + + while (outlen) { + PUTU32(counter_be, counter); + counter++; + + sm3_ctx = ctx->sm3_ctx; + sm3_update(&sm3_ctx, counter_be, sizeof(counter_be)); + sm3_finish(&sm3_ctx, dgst); + + len = outlen < SM3_DIGEST_SIZE ? outlen : SM3_DIGEST_SIZE; + memcpy(out, dgst, len); + out += len; + outlen -= len; + } + + memset(&sm3_ctx, 0, sizeof(SM3_CTX)); + memset(dgst, 0, sizeof(dgst)); +} diff --git a/Core/GmSSL-3.1.1/src/sm3_rng.c b/Core/GmSSL-3.1.1/src/sm3_rng.c new file mode 100644 index 0000000..599a91c --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm3_rng.c @@ -0,0 +1,215 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +// see GM/T 0105-2021 Design Guide for Software-based Random Number Generators + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const uint8_t num[4] = { 0, 1, 2, 3 }; + +typedef struct { + SM3_CTX sm3_ctx[2]; +} SM3_DF_CTX; + +// sm3_df(in) := ( sm3(be32(1) || be32(440) || in) || +// sm3(b332(2) || be32(440) || in) )[0:55] +static void sm3_df_init(SM3_DF_CTX *df_ctx) +{ + uint8_t counter[4] = {0, 0, 0, 1}; + uint8_t seedlen[4] = {0, 0, 440/256, 440%256}; + + sm3_init(&df_ctx->sm3_ctx[0]); + sm3_update(&df_ctx->sm3_ctx[0], counter, 4); + sm3_update(&df_ctx->sm3_ctx[0], seedlen, 4); + counter[3] = 2; + sm3_init(&df_ctx->sm3_ctx[1]); + sm3_update(&df_ctx->sm3_ctx[1], counter, 4); + sm3_update(&df_ctx->sm3_ctx[1], seedlen, 4); +} + +static void sm3_df_update(SM3_DF_CTX *df_ctx, const uint8_t *data, size_t datalen) +{ + if (data && datalen) { + sm3_update(&df_ctx->sm3_ctx[0], data, datalen); + sm3_update(&df_ctx->sm3_ctx[1], data, datalen); + } +} + +static void sm3_df_finish(SM3_DF_CTX *df_ctx, uint8_t out[55]) +{ + uint8_t buf[32]; + sm3_finish(&df_ctx->sm3_ctx[0], out); + sm3_finish(&df_ctx->sm3_ctx[1], buf); + memcpy(out + 32, buf, 55 - 32); +} + +int sm3_rng_init(SM3_RNG *rng, const uint8_t *nonce, size_t nonce_len, + const uint8_t *label, size_t label_len) +{ + SM3_DF_CTX df_ctx; + uint8_t entropy[512]; + + // get_entropy, 512-byte might be too long for some system RNGs + if (rand_bytes(entropy, 256) != 1 + || rand_bytes(entropy + 256, 256) != 1) { + error_print(); + return -1; + } + + // V = sm3_df(entropy || nonce || label) + sm3_df_init(&df_ctx); + sm3_df_update(&df_ctx, entropy, sizeof(entropy)); + sm3_df_update(&df_ctx, nonce, nonce_len); + sm3_df_update(&df_ctx, label, label_len); + sm3_df_finish(&df_ctx, rng->V); + + // C = sm3_df(0x00 || V) + sm3_df_init(&df_ctx); + sm3_df_update(&df_ctx, &num[0], 1); + sm3_df_update(&df_ctx, rng->V, 55); + sm3_df_finish(&df_ctx, rng->C); + + // reseed_counter = 1, last_ressed_time = now() + rng->reseed_counter = 1; + rng->last_reseed_time = time(NULL); + + gmssl_secure_clear(&df_ctx, sizeof(df_ctx)); + gmssl_secure_clear(entropy, sizeof(entropy)); + return 1; +} + +int sm3_rng_reseed(SM3_RNG *rng, const uint8_t *addin, size_t addin_len) +{ + SM3_DF_CTX df_ctx; + uint8_t entropy[512]; + + // get_entropy, 512-byte might be too long for some system RNGs + if (rand_bytes(entropy, 256) != 1 + || rand_bytes(entropy + 256, 256) != 1) { + error_print(); + return -1; + } + + // V = sm3_df(0x01 || entropy || V || appin) + sm3_df_init(&df_ctx); + sm3_df_update(&df_ctx, &num[1], 1); + sm3_df_update(&df_ctx, entropy, sizeof(entropy)); + sm3_df_update(&df_ctx, rng->V, 55); + sm3_df_update(&df_ctx, addin, addin_len); + sm3_df_finish(&df_ctx, rng->V); + + // C = sm3_df(0x00 || V) + sm3_df_init(&df_ctx); + sm3_df_update(&df_ctx, &num[0], 1); + sm3_df_update(&df_ctx, rng->V, 55); + sm3_df_finish(&df_ctx, rng->C); + + // reseed_counter = 1, last_ressed_time = now() + rng->reseed_counter = 1; + rng->last_reseed_time = time(NULL); + + gmssl_secure_clear(&df_ctx, sizeof(df_ctx)); + gmssl_secure_clear(entropy, sizeof(entropy)); + return 1; +} + +static void be_add(uint8_t r[55], const uint8_t *a, size_t alen) +{ + int i, j, carry = 0; + + for (i = 54, j = (int)(alen - 1); j >= 0; i--, j--) { + carry += r[i] + a[j]; + r[i] = carry & 0xff; + carry >>= 8; + } + for (; i >= 0; i--) { + carry += r[i]; + r[i] = carry & 0xff; + carry >>= 8; + } +} + +int sm3_rng_generate(SM3_RNG *rng, const uint8_t *addin, size_t addin_len, + uint8_t *out, size_t outlen) +{ + SM3_CTX sm3_ctx; + uint8_t H[32]; + uint8_t counter[4]; + + if (!outlen || outlen > 32) { + error_print(); + return -1; + } + + if (rng->reseed_counter > SM3_RNG_MAX_RESEED_COUNTER + || time(NULL) - rng->last_reseed_time > SM3_RNG_MAX_RESEED_SECONDS) { + if (sm3_rng_reseed(rng, addin, addin_len) != 1) { + error_print(); + return -1; + } + if (addin) { + addin = NULL; + } + } + + if (addin && addin_len) { + uint8_t W[32]; + + // W = sm3(0x02 || V || addin) + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, &num[2], 1); + sm3_update(&sm3_ctx, rng->V, 55); + sm3_update(&sm3_ctx, addin, addin_len); + sm3_finish(&sm3_ctx, W); + + // V = (V + W) mod 2^440 + be_add(rng->V, W, 32); + + gmssl_secure_clear(W, sizeof(W)); + } + + // output sm3(V) + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, rng->V, 55); + if (outlen < 32) { + uint8_t buf[32]; + sm3_finish(&sm3_ctx, buf); + memcpy(out, buf, outlen); + } else { + sm3_finish(&sm3_ctx, out); + } + + // H = sm3(0x03 || V) + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, &num[3], 1); + sm3_update(&sm3_ctx, rng->V, 55); + sm3_finish(&sm3_ctx, H); + + // V = (V + H + C + reseed_counter) mod 2^440 + be_add(rng->V, H, 32); + be_add(rng->V, rng->C, 55); + counter[0] = (rng->reseed_counter >> 24) & 0xff; + counter[1] = (rng->reseed_counter >> 16) & 0xff; + counter[2] = (rng->reseed_counter >> 8) & 0xff; + counter[3] = (rng->reseed_counter ) & 0xff; + be_add(rng->V, counter, 4); + + (rng->reseed_counter)++; + + gmssl_secure_clear(&sm3_ctx, sizeof(sm3_ctx)); + gmssl_secure_clear(H, sizeof(H)); + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm3_x8_avx2.c b/Core/GmSSL-3.1.1/src/sm3_x8_avx2.c new file mode 100644 index 0000000..cb71cc6 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm3_x8_avx2.c @@ -0,0 +1,324 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define ROLT(x,n) _mm256_or_si256(_mm256_slli_epi32((x), (n)), _mm256_srli_epi32((x), (32-(n)))) +#define P0(x) _mm256_xor_si256((x), _mm256_xor_si256(ROLT((x), 9), ROLT((x), 17))) +#define P1(x) _mm256_xor_si256((x), _mm256_xor_si256(ROLT((x), 15), ROLT((x), 23))) + +#define FF00(x,y,z) _mm256_xor_si256((x), _mm256_xor_si256((y), (z))) +#define FF16(x,y,z) _mm256_or_si256(_mm256_and_si256((x), (y)), _mm256_or_si256(_mm256_and_si256((x), (z)), _mm256_and_si256((y), (z)))) +#define GG00(x,y,z) _mm256_xor_si256((x), _mm256_xor_si256((y), (z))) +#define GG16(x,y,z) _mm256_xor_si256(_mm256_and_si256(_mm256_xor_si256((y), (z)), (x)), (z)) + + +static uint32_t K[64] = { + 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, +}; + +static int _mm256_print(FILE *fp, int fmt, int ind, const char *label, __m256i a) +{ + uint32_t arr[8]; + int i; + + _mm256_storeu_si256((__m256i *)arr, a); + + format_print(fp, fmt, ind, "%s: ", label); + for (i = 0; i < 7; i++) { + fprintf(fp, "%08X ", arr[i]); + } + fprintf(fp, "%08X\n", arr[i]); + return 1; +} + +void sm3_x8_init(SM3_X8_CTX *ctx) +{ + ctx->digest[0] = _mm256_set1_epi32(0x7380166F); + ctx->digest[1] = _mm256_set1_epi32(0x4914B2B9); + ctx->digest[2] = _mm256_set1_epi32(0x172442D7); + ctx->digest[3] = _mm256_set1_epi32(0xDA8A0600); + ctx->digest[4] = _mm256_set1_epi32(0xA96F30BC); + ctx->digest[5] = _mm256_set1_epi32(0x163138AA); + ctx->digest[6] = _mm256_set1_epi32(0xE38DEE4D); + ctx->digest[7] = _mm256_set1_epi32(0xB0FB0E4E); +} + +void sm3_x8_compress_blocks(__m256i digest[8], const uint8_t *data, size_t datalen) +{ + __m256i A; + __m256i B; + __m256i C; + __m256i D; + __m256i E; + __m256i F; + __m256i G; + __m256i H; + __m256i SS1, SS2, TT1, TT2; + uint32_t W[68][8]; + size_t nblocks = datalen/SM3_BLOCK_SIZE; + int j; + + memset(W, 0, sizeof(W)); + + A = digest[0]; + B = digest[1]; + C = digest[2]; + D = digest[3]; + E = digest[4]; + F = digest[5]; + G = digest[6]; + H = digest[7]; + + /* + format_print(stderr, 0, 0, "state %d\n", 0); + _mm256_print(stderr, 0, 4, "A", A); + _mm256_print(stderr, 0, 4, "B", B); + _mm256_print(stderr, 0, 4, "C", C); + _mm256_print(stderr, 0, 4, "D", D); + _mm256_print(stderr, 0, 4, "E", E); + _mm256_print(stderr, 0, 4, "F", F); + _mm256_print(stderr, 0, 4, "G", G); + _mm256_print(stderr, 0, 4, "H", H); + */ + + while (nblocks--) { + + TT1 = _mm256_setr_epi32( + datalen*0, datalen*1, datalen*2, datalen*3, + datalen*4, datalen*5, datalen*6, datalen*7); + TT2 = _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); + + for (j = 0; j < 16; j++) { + SS1 = _mm256_i32gather_epi32(data + 4*j, TT1, 1); + SS1 = _mm256_shuffle_epi8(SS1, TT2); + _mm256_storeu_si256((__m256i *)W[j], SS1); + } + + for (; j < 68; j++) { + // SS1 = ROLT((ROLT(A, 12) + E + K(j)), 7); + SS1 = _mm256_loadu_si256((__m256i *)W[j - 16]); + SS2 = _mm256_loadu_si256((__m256i *)W[j - 9]); + SS1 = _mm256_xor_si256(SS1, SS2); + SS2 = _mm256_loadu_si256((__m256i *)W[j - 3]); + SS2 = ROLT(SS2, 15); + SS1 = _mm256_xor_si256(SS1, SS2); + + // P1(x) = (x) ^ ROLT((x),15) ^ ROLT((x),23) + TT1 = ROLT(SS1, 15); + TT2 = ROLT(SS1, 23); + SS1 = _mm256_xor_si256(SS1, TT1); + SS1 = _mm256_xor_si256(SS1, TT2); + + // ^ (W[j - 13] >>> 7) ^ W[j - 6] + SS2 = _mm256_loadu_si256((__m256i *)W[j - 13]); + SS2 = ROLT(SS2, 7); + SS1 = _mm256_xor_si256(SS1, SS2); + SS2 = _mm256_loadu_si256((__m256i *)W[j - 6]); + SS1 = _mm256_xor_si256(SS1, SS2); + + _mm256_storeu_si256((__m256i *)&W[j], SS1); + } + + + for (j = 0; j < 16; j++) { + //SS1 = ROLT((ROLT(A, 12) + E + K(j)), 7); + SS2 = ROLT(A, 12); + SS1 = _mm256_add_epi32(SS2, E); + SS1 = _mm256_add_epi32(SS1, _mm256_set1_epi32(K[j])); + SS1 = ROLT(SS1, 7); + + //SS2 = SS1 ^ ROLT(A, 12); + SS2 = _mm256_xor_si256(SS2, SS1); + + //TT1 = FF00(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]); + TT2 = _mm256_loadu_si256((__m256i *)W[j]); + TT1 = _mm256_xor_si256(TT2, _mm256_loadu_si256((__m256i *)W[j + 4])); + TT1 = _mm256_add_epi32(TT1, FF00(A, B, C)); + TT1 = _mm256_add_epi32(TT1, D); + TT1 = _mm256_add_epi32(TT1, SS2); + + //TT2 = GG00(E, F, G) + H + SS1 + W[j]; + TT2 = _mm256_add_epi32(TT2, GG00(E, F, G)); + TT2 = _mm256_add_epi32(TT2, H); + TT2 = _mm256_add_epi32(TT2, SS1); + + D = C; + C = ROLT(B, 9); + B = A; + A = TT1; + H = G; + G = ROLT(F, 19); + F = E; + E = P0(TT2); + + /* + format_print(stderr, 0, 0, "state %d\n", j+1); + _mm256_print(stderr, 0, 4, "A", A); + _mm256_print(stderr, 0, 4, "B", B); + _mm256_print(stderr, 0, 4, "C", C); + _mm256_print(stderr, 0, 4, "D", D); + _mm256_print(stderr, 0, 4, "E", E); + _mm256_print(stderr, 0, 4, "F", F); + _mm256_print(stderr, 0, 4, "G", G); + _mm256_print(stderr, 0, 4, "H", H); + */ + } + + + for (; j < 64; j++) { + //SS1 = ROLT((ROLT(A, 12) + E + K(j)), 7); + SS2 = ROLT(A, 12); + SS1 = _mm256_add_epi32(SS2, E); + SS1 = _mm256_add_epi32(SS1, _mm256_set1_epi32(K[j])); + SS1 = ROLT(SS1, 7); + + //SS2 = SS1 ^ ROLT(A, 12); + SS2 = _mm256_xor_si256(SS2, SS1); + + //TT1 = FF16(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]); + TT2 = _mm256_loadu_si256((__m256i *)W[j]); + TT1 = _mm256_xor_si256(TT2, _mm256_loadu_si256((__m256i *)W[j + 4])); + TT1 = _mm256_add_epi32(TT1, FF16(A, B, C)); + TT1 = _mm256_add_epi32(TT1, D); + TT1 = _mm256_add_epi32(TT1, SS2); + + // TT2 = GG16(E, F, G) + H + SS1 + W[j]; + TT2 = _mm256_add_epi32(TT2, GG16(E, F, G)); + TT2 = _mm256_add_epi32(TT2, H); + TT2 = _mm256_add_epi32(TT2, SS1); + + D = C; + C = ROLT(B, 9); + B = A; + A = TT1; + H = G; + G = ROLT(F, 19); + F = E; + E = P0(TT2); + + /* + format_print(stderr, 0, 0, "state %d\n", j+1); + _mm256_print(stderr, 0, 4, "A", A); + _mm256_print(stderr, 0, 4, "B", B); + _mm256_print(stderr, 0, 4, "C", C); + _mm256_print(stderr, 0, 4, "D", D); + _mm256_print(stderr, 0, 4, "E", E); + _mm256_print(stderr, 0, 4, "F", F); + _mm256_print(stderr, 0, 4, "G", G); + _mm256_print(stderr, 0, 4, "H", H); + */ + } + + _mm256_storeu_si256((__m256i *)&digest[0], _mm256_xor_si256(A, _mm256_loadu_si256((__m256i *)&digest[0]))); + _mm256_storeu_si256((__m256i *)&digest[1], _mm256_xor_si256(B, _mm256_loadu_si256((__m256i *)&digest[1]))); + _mm256_storeu_si256((__m256i *)&digest[2], _mm256_xor_si256(C, _mm256_loadu_si256((__m256i *)&digest[2]))); + _mm256_storeu_si256((__m256i *)&digest[3], _mm256_xor_si256(D, _mm256_loadu_si256((__m256i *)&digest[3]))); + _mm256_storeu_si256((__m256i *)&digest[4], _mm256_xor_si256(E, _mm256_loadu_si256((__m256i *)&digest[4]))); + _mm256_storeu_si256((__m256i *)&digest[5], _mm256_xor_si256(F, _mm256_loadu_si256((__m256i *)&digest[5]))); + _mm256_storeu_si256((__m256i *)&digest[6], _mm256_xor_si256(G, _mm256_loadu_si256((__m256i *)&digest[6]))); + _mm256_storeu_si256((__m256i *)&digest[7], _mm256_xor_si256(H, _mm256_loadu_si256((__m256i *)&digest[7]))); + + data += SM3_BLOCK_SIZE; + } +} + +void sm3_x8_digest(const uint8_t *data, size_t datalen, uint8_t dgst[8][32]) +{ + SM3_X8_CTX ctx; + __m256i vindex, a, b; + uint8_t block[8][SM3_BLOCK_SIZE]; + size_t nblocks = datalen/SM3_BLOCK_SIZE; + size_t rem = datalen % 64; + int i; + + + sm3_x8_init(&ctx); + + sm3_x8_compress_blocks(ctx.digest, data, datalen); + data += SM3_BLOCK_SIZE * nblocks; + + memset(block, 0, sizeof(block)); + for (i = 0; i < 8; i++) { + memcpy(block[i], data, rem); + block[i][rem] = 0x80; + data += datalen; + } + if (SM3_BLOCK_SIZE - rem < 9) { + sm3_x8_compress_blocks(ctx.digest, &block[0][0], SM3_BLOCK_SIZE); + memset(block, 0, sizeof(block)); + } + + for (i = 0; i < 8; i++) { + *((uint64_t *)(block[i] + 56)) = _bswap64(datalen << 3); + } + sm3_x8_compress_blocks(ctx.digest, &block[0][0], SM3_BLOCK_SIZE); + + vindex = _mm256_setr_epi32(0,1*32,2*32,3*32,4*32,5*32,6*32,7*32); + b = _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); + for (i = 0; i < 8; i++) { + a = _mm256_i32gather_epi32((uint8_t *)&ctx + 4*i, vindex, 1); + a = _mm256_shuffle_epi8(a, b); + _mm256_storeu_si256((__m256i *)dgst[i], a); + } + + gmssl_secure_clear(&ctx, sizeof(ctx)); + gmssl_secure_clear(block, sizeof(block)); +} + +static int test_sm3_x8_avx2(void) +{ + uint8_t data[8][96] = {0}; + uint8_t dgst[8][32]; + uint8_t dgst2[8][32] = {{0}}; + int i; + + rand_bytes(data[0], sizeof(data)); + for (i = 0; i < 8; i++) { + sm3_digest(data[i], sizeof(data)/8, dgst[i]); + } + sm3_x8_digest(&data[0][0], sizeof(data)/8, dgst2); + + if (memcmp(dgst2, dgst, sizeof(dgst)) != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm4_aesni_avx.c b/Core/GmSSL-3.1.1/src/sm4_aesni_avx.c new file mode 100644 index 0000000..ee75142 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_aesni_avx.c @@ -0,0 +1,190 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +// modify from https://github.com/mjosaarinen/sm4ni +// 2018-04-20 Markku-Juhani O. Saarinen +/* +MIT License + +Copyright (c) 2018 Markku-Juhani O. Saarinen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include + + +void sm4_aesni_avx_encrypt(const uint32_t rk[32], const uint8_t in[16 * 4], uint8_t out[16 * 4]) +{ + // nibble mask + const __m128i c0f __attribute__((aligned(0x10))) = { + 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F }; + + // flip all bytes in all 32-bit words + const __m128i flp __attribute__((aligned(0x10))) = { + 0x0405060700010203, 0x0C0D0E0F08090A0B }; + + // inverse shift rows + const __m128i shr __attribute__((aligned(0x10))) = { + 0x0B0E0104070A0D00, 0x0306090C0F020508 }; + + // Affine transform 1 (low and high hibbles) + const __m128i m1l __attribute__((aligned(0x10))) = { + 0x9197E2E474720701, 0xC7C1B4B222245157 }; + const __m128i m1h __attribute__((aligned(0x10))) = { + 0xE240AB09EB49A200, 0xF052B91BF95BB012 }; + + // Affine transform 2 (low and high hibbles) + const __m128i m2l __attribute__((aligned(0x10))) = { + 0x5B67F2CEA19D0834, 0xEDD14478172BBE82 }; + const __m128i m2h __attribute__((aligned(0x10))) = { + 0xAE7201DD73AFDC00, 0x11CDBE62CC1063BF }; + + // left rotations of 32-bit words by 8-bit increments + const __m128i r08 __attribute__((aligned(0x10))) = { + 0x0605040702010003, 0x0E0D0C0F0A09080B }; + const __m128i r16 __attribute__((aligned(0x10))) = { + 0x0504070601000302, 0x0D0C0F0E09080B0A }; + const __m128i r24 __attribute__((aligned(0x10))) = { + 0x0407060500030201, 0x0C0F0E0D080B0A09 }; + + const uint32_t *cp32; + __m128i x, y, t0, t1, t2, t3; + uint32_t k, *p32, v[4] __attribute__((aligned(0x10))); + int i; + + cp32 = (const uint32_t *)in; + t0 = _mm_set_epi32(cp32[12], cp32[ 8], cp32[ 4], cp32[ 0]); + t0 = _mm_shuffle_epi8(t0, flp); + t1 = _mm_set_epi32(cp32[13], cp32[ 9], cp32[ 5], cp32[ 1]); + t1 = _mm_shuffle_epi8(t1, flp); + t2 = _mm_set_epi32(cp32[14], cp32[10], cp32[ 6], cp32[ 2]); + t2 = _mm_shuffle_epi8(t2, flp); + t3 = _mm_set_epi32(cp32[15], cp32[11], cp32[ 7], cp32[ 3]); + t3 = _mm_shuffle_epi8(t3, flp); + + for (i = 0; i < 32; i++) { + + k = rk[i]; + x = t1 ^ t2 ^ t3 ^ _mm_set_epi32(k, k, k, k); + + y = _mm_and_si128(x, c0f); // inner affine + y = _mm_shuffle_epi8(m1l, y); + x = _mm_srli_epi64(x, 4); + x = _mm_and_si128(x, c0f); + x = _mm_shuffle_epi8(m1h, x) ^ y; + + x = _mm_shuffle_epi8(x, shr); // inverse MixColumns + x = _mm_aesenclast_si128(x, c0f); // AESNI instruction + + y = _mm_andnot_si128(x, c0f); // outer affine + y = _mm_shuffle_epi8(m2l, y); + x = _mm_srli_epi64(x, 4); + x = _mm_and_si128(x, c0f); + x = _mm_shuffle_epi8(m2h, x) ^ y; + + // 4 parallel L1 linear transforms + y = x ^ _mm_shuffle_epi8(x, r08) ^ _mm_shuffle_epi8(x, r16); + y = _mm_slli_epi32(y, 2) ^ _mm_srli_epi32(y, 30); + x = x ^ y ^ _mm_shuffle_epi8(x, r24); + + // rotate registers + x ^= t0; + t0 = t1; + t1 = t2; + t2 = t3; + t3 = x; + } + + p32 = (uint32_t *)out; + + _mm_store_si128((__m128i *) v, _mm_shuffle_epi8(t3, flp)); + p32[ 0] = v[0]; + p32[ 4] = v[1]; + p32[ 8] = v[2]; + p32[12] = v[3]; + + _mm_store_si128((__m128i *) v, _mm_shuffle_epi8(t2, flp)); + p32[ 1] = v[0]; + p32[ 5] = v[1]; + p32[ 9] = v[2]; + p32[13] = v[3]; + + _mm_store_si128((__m128i *) v, _mm_shuffle_epi8(t1, flp)); + p32[ 2] = v[0]; + p32[ 6] = v[1]; + p32[10] = v[2]; + p32[14] = v[3]; + + _mm_store_si128((__m128i *) v, _mm_shuffle_epi8(t0, flp)); + p32[ 3] = v[0]; + p32[ 7] = v[1]; + p32[11] = v[2]; + p32[15] = v[3]; +} + +static void ctr_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + +void sm4_ctr_encrypt(const SM4_KEY *key, uint8_t ctr[16], const uint8_t *in, size_t inlen, uint8_t *out) +{ + uint8_t blocks[64]; + size_t len, i; + + while (inlen >= 64) { + memcpy(blocks, ctr, 16); ctr_incr(ctr); + memcpy(blocks + 16, ctr, 16); ctr_incr(ctr); + memcpy(blocks + 32, ctr, 16); ctr_incr(ctr); + memcpy(blocks + 48, ctr, 16); ctr_incr(ctr); + sm4_aesni_avx_encrypt(key->rk, blocks, blocks); + gmssl_memxor(out, in, blocks, 64); + in += 64; + out += 64; + inlen -= 64; + } + + while (inlen) { + len = inlen < 16 ? inlen : 16; + sm4_encrypt(key, ctr, blocks); + gmssl_memxor(out, in, blocks, len); + ctr_incr(ctr); + in += len; + out += len; + inlen -= len; + } + + memset(blocks, 0, sizeof(blocks)); +} diff --git a/Core/GmSSL-3.1.1/src/sm4_cbc_mac.c b/Core/GmSSL-3.1.1/src/sm4_cbc_mac.c new file mode 100644 index 0000000..e754f41 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_cbc_mac.c @@ -0,0 +1,49 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +void sm4_cbc_mac_init(SM4_CBC_MAC_CTX *ctx, const uint8_t key[16]) +{ + sm4_set_encrypt_key(&ctx->key, key); + memset(ctx->iv, 0, 16); + ctx->ivlen = 0; +} + +void sm4_cbc_mac_update(SM4_CBC_MAC_CTX *ctx, const uint8_t *data, size_t datalen) +{ + while (datalen) { + size_t ivleft = 16 - ctx->ivlen; + size_t len = datalen < ivleft ? datalen : ivleft; + gmssl_memxor(ctx->iv + ctx->ivlen, ctx->iv + ctx->ivlen, data, len); + ctx->ivlen += len; + if (ctx->ivlen >= 16) { + sm4_encrypt(&ctx->key, ctx->iv, ctx->iv); + ctx->ivlen = 0; + } + data += len; + datalen -= len; + } +} + +void sm4_cbc_mac_finish(SM4_CBC_MAC_CTX *ctx, uint8_t mac[16]) +{ + if (ctx->ivlen) { + sm4_encrypt(&ctx->key, ctx->iv, ctx->iv); + } + memcpy(mac, ctx->iv, 16); +} diff --git a/Core/GmSSL-3.1.1/src/sm4_cl.c b/Core/GmSSL-3.1.1/src/sm4_cl.c new file mode 100644 index 0000000..b60732f --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_cl.c @@ -0,0 +1,365 @@ +#include +#include +#include +#include +#include + + +#define MACOS +#ifdef MACOS +#include +#else +#include +#endif + + +static char *clErrorString(cl_uint err) +{ + switch (err) { + case CL_SUCCESS: return "CL_SUCCESS!"; + case CL_DEVICE_NOT_FOUND: return "CL_DEVICE_NOT_FOUND"; + case CL_DEVICE_NOT_AVAILABLE: return "CL_DEVICE_NOT_AVAILABLE"; + case CL_COMPILER_NOT_AVAILABLE: return "CL_COMPILER_NOT_AVAILABLE"; + case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "CL_MEM_OBJECT_ALLOCATION_FAILURE"; + case CL_OUT_OF_RESOURCES: return "CL_OUT_OF_RESOURCES"; + case CL_OUT_OF_HOST_MEMORY: return "CL_OUT_OF_HOST_MEMORY"; + case CL_PROFILING_INFO_NOT_AVAILABLE: return "CL_PROFILING_INFO_NOT_AVAILABLE"; + case CL_MEM_COPY_OVERLAP: return "CL_MEM_COPY_OVERLAP"; + case CL_IMAGE_FORMAT_MISMATCH: return "CL_IMAGE_FORMAT_MISMATCH"; + case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "CL_IMAGE_FORMAT_NOT_SUPPORTED"; + case CL_BUILD_PROGRAM_FAILURE: return "CL_BUILD_PROGRAM_FAILURE"; + case CL_MAP_FAILURE: return "CL_MAP_FAILURE"; + case CL_INVALID_VALUE: return "CL_INVALID_VALUE"; + case CL_INVALID_DEVICE_TYPE: return "CL_INVALID_DEVICE_TYPE"; + case CL_INVALID_PLATFORM: return "CL_INVALID_PLATFORM"; + case CL_INVALID_DEVICE: return "CL_INVALID_DEVICE"; + case CL_INVALID_CONTEXT: return "CL_INVALID_CONTEXT"; + case CL_INVALID_QUEUE_PROPERTIES: return "CL_INVALID_QUEUE_PROPERTIES"; + case CL_INVALID_COMMAND_QUEUE: return "CL_INVALID_COMMAND_QUEUE"; + case CL_INVALID_HOST_PTR: return "CL_INVALID_HOST_PTR"; + case CL_INVALID_MEM_OBJECT: return "CL_INVALID_MEM_OBJECT"; + case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"; + case CL_INVALID_IMAGE_SIZE: return "CL_INVALID_IMAGE_SIZE"; + case CL_INVALID_SAMPLER: return "CL_INVALID_SAMPLER"; + case CL_INVALID_BINARY: return "CL_INVALID_BINARY"; + case CL_INVALID_BUILD_OPTIONS: return "CL_INVALID_BUILD_OPTIONS"; + case CL_INVALID_PROGRAM: return "CL_INVALID_PROGRAM"; + case CL_INVALID_PROGRAM_EXECUTABLE: return "CL_INVALID_PROGRAM_EXECUTABLE"; + case CL_INVALID_KERNEL_NAME: return "CL_INVALID_KERNEL_NAME"; + case CL_INVALID_KERNEL_DEFINITION: return "CL_INVALID_KERNEL_DEFINITION"; + case CL_INVALID_KERNEL: return "CL_INVALID_KERNEL"; + case CL_INVALID_ARG_INDEX: return "CL_INVALID_ARG_INDEX"; + case CL_INVALID_ARG_VALUE: return "CL_INVALID_ARG_VALUE"; + case CL_INVALID_ARG_SIZE: return "CL_INVALID_ARG_SIZE"; + case CL_INVALID_KERNEL_ARGS: return "CL_INVALID_KERNEL_ARGS"; + case CL_INVALID_WORK_DIMENSION: return "CL_INVALID_WORK_DIMENSION"; + case CL_INVALID_WORK_GROUP_SIZE: return "CL_INVALID_WORK_GROUP_SIZE"; + case CL_INVALID_WORK_ITEM_SIZE: return "CL_INVALID_WORK_ITEM_SIZE"; + case CL_INVALID_GLOBAL_OFFSET: return "CL_INVALID_GLOBAL_OFFSET"; + case CL_INVALID_EVENT_WAIT_LIST: return "CL_INVALID_EVENT_WAIT_LIST"; + case CL_INVALID_EVENT: return "CL_INVALID_EVENT"; + case CL_INVALID_OPERATION: return "CL_INVALID_OPERATION"; + case CL_INVALID_GL_OBJECT: return "CL_INVALID_GL_OBJECT"; + case CL_INVALID_BUFFER_SIZE: return "CL_INVALID_BUFFER_SIZE"; + case CL_INVALID_MIP_LEVEL: return "CL_INVALID_MIP_LEVEL"; + } + return NULL; +} + +static const char *sm4_cl_src; + +typedef struct { + uint32_t rk[32]; + cl_context context; + cl_command_queue queue; + cl_program program; + cl_kernel kernel; + cl_mem mem_rk; + cl_mem mem_io; + size_t workgroup_size; +} SM4_CL_CTX; + +#define cl_error_print(e) \ + do { fprintf(stderr, "%s: %d: %s()\n",__FILE__,__LINE__,clErrorString(e)); } while (0) + + +void sm4_cl_cleanup(SM4_CL_CTX *ctx) +{ + clReleaseContext(ctx->context); + clReleaseCommandQueue(ctx->queue); + clReleaseProgram(ctx->program); + clReleaseKernel(ctx->kernel); +} + +static int sm4_cl_set_key(SM4_CL_CTX *ctx, const uint8_t key[16], int enc) +{ + cl_platform_id platform; + cl_device_id device; + cl_uint device_cnt; + cl_int err; + char sval[256]; + size_t slen; + cl_command_queue_properties queue_prop = 0; + const char *build_opts = NULL; + + memset(ctx, 0, sizeof(*ctx)); + + + if ((err = clGetPlatformIDs(1, &platform, NULL)) != CL_SUCCESS) { + cl_error_print(err); + return -1; + } + if ((err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, &device_cnt)) != CL_SUCCESS) { + cl_error_print(err); + return -1; + } + if (!(ctx->context = clCreateContext(NULL, 1, &device, NULL, NULL, &err))) { + cl_error_print(err); + return -1; + } + if (!(ctx->queue = clCreateCommandQueue(ctx->context, device, queue_prop, &err))) { + cl_error_print(err); + goto end; + } + if (!(ctx->program = clCreateProgramWithSource(ctx->context, 1, (const char **)&sm4_cl_src, NULL, &err))) { + cl_error_print(err); + goto end; + } + if ((err = clBuildProgram(ctx->program, 1, &device, build_opts, NULL, NULL)) != CL_SUCCESS) { + char *log = NULL; + size_t loglen; + + cl_error_print(err); + + if ((err = clGetProgramBuildInfo(ctx->program, device, CL_PROGRAM_BUILD_LOG, sizeof(log), NULL, &loglen)) != CL_SUCCESS) { + cl_error_print(err); + goto end; + } + if (!(log = (char *)malloc(loglen))) { + goto end; + } + if ((err = clGetProgramBuildInfo(ctx->program, device, CL_PROGRAM_BUILD_LOG, sizeof(log), NULL, &loglen)) != CL_SUCCESS) { + cl_error_print(err); + free(log); + goto end; + } + fprintf(stderr, "%s %d: %s\n", __FILE__, __LINE__, log); + free(log); + goto end; + } + if (!(ctx->kernel = clCreateKernel(ctx->program, "sm4_encrypt", &err))) { + cl_error_print(err); + goto end; + } + if ((err = clGetKernelWorkGroupInfo(ctx->kernel, device, CL_KERNEL_WORK_GROUP_SIZE, + sizeof(ctx->workgroup_size), &ctx->workgroup_size, NULL)) != CL_SUCCESS) { + cl_error_print(err); + goto end; + } + + if (enc) { + sm4_set_encrypt_key((SM4_KEY *)ctx->rk, key); + } else { + sm4_set_decrypt_key((SM4_KEY *)ctx->rk, key); + } + + if (!(ctx->mem_rk = clCreateBuffer(ctx->context, CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, sizeof(SM4_KEY), ctx->rk, &err))) { + cl_error_print(err); + goto end; + } + if ((err = clSetKernelArg(ctx->kernel, 0, sizeof(cl_mem), &ctx->mem_rk)) != CL_SUCCESS) { + cl_error_print(err); + goto end; + } + + return 1; + + +end: + return -1; +} + +int sm4_cl_set_encrypt_key(SM4_CL_CTX *ctx, const uint8_t key[16]) +{ + return sm4_cl_set_key(ctx, key, 1); +} + +int sm4_cl_set_decrypt_key(SM4_CL_CTX *ctx, const uint8_t key[16]) +{ + return sm4_cl_set_key(ctx, key, 0); +} + +int sm4_cl_encrypt(SM4_CL_CTX *ctx, const uint8_t *in, size_t nblocks, uint8_t *out) +{ + int ret = -1; + cl_mem mem; + cl_int err; + size_t len = 16 * nblocks; + cl_uint dim = 1; + void *p; + + if (out != in) + memcpy(out, in, len); + + if (!(mem = clCreateBuffer(ctx->context, CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, len, out, &err))) { + cl_error_print(err); + return -1; + } + if ((err = clSetKernelArg(ctx->kernel, 1, sizeof(cl_mem), &mem)) != CL_SUCCESS) { + cl_error_print(err); + goto end; + } + if ((err = clEnqueueNDRangeKernel(ctx->queue, ctx->kernel, dim, NULL, &nblocks, &ctx->workgroup_size, 0, NULL, NULL)) != CL_SUCCESS) { + cl_error_print(err); + goto end; + } + if (!(p = clEnqueueMapBuffer(ctx->queue, mem, CL_TRUE, 0, 0, len, 0, NULL, NULL, &err))) { + cl_error_print(err); + goto end; + } + if (p != out) { + fprintf(stderr, "%s %d: shit\n", __FILE__, __LINE__); + goto end; + } + ret = 1; +end: + clReleaseMemObject(mem); + return ret; +} + +int test_sm4_cl_encrypt(void) +{ + const uint8_t key[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + const uint8_t plaintext[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + const uint8_t ciphertext[16] = { + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, + }; + + int ret = -1; + SM4_CL_CTX ctx; + size_t nblocks = 1024; + uint8_t *buf = NULL; + size_t i; + + + if (!(buf = (uint8_t *)malloc(16 * nblocks))) { + error_print(); + return -1; + } + for (i = 0; i < nblocks; i++) { + memcpy(buf + 16 * i, plaintext, 16); + } + + if (sm4_cl_set_encrypt_key(&ctx, key) != 1) { + error_print(); + goto end; + } + if (sm4_cl_encrypt(&ctx, buf, nblocks, buf) != 1) { + error_print(); + goto end; + } + + for (i = 0; i < nblocks; i++) { + if (memcmp(buf + 16 * i, ciphertext, 16) != 0) { + error_print(); + goto end; + } + } + + ret = 1; +end: + if (buf) free(buf); + sm4_cl_cleanup(&ctx); + return ret; +} + + +#define KERNEL(...) #__VA_ARGS__ +const char *sm4_cl_src = KERNEL( + +__constant unsigned char SBOX[256] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48, +}; + + +__kernel void sm4_encrypt(__global const unsigned int *rkey, __global unsigned char *data) +{ + __local unsigned char S[256]; + __local unsigned int rk[32]; + + unsigned int x0, x1, x2, x3, x4, i, t; + uint global_id = get_global_id(0); + __global unsigned char *p = data + 16 * global_id; + __global unsigned int *in = (__global unsigned int *)p; + __global unsigned int *out = (__global unsigned int *)p; + + if (get_local_id(0) == 0) { + for (i = 0; i < 256; i++) { + S[i] = SBOX[i]; + } + for (i = 0; i < 32; i++) { + rk[i] = rkey[i]; + } + } + + x0 = (in[0] >> 24) | ((in[0] >> 8) & 0xff00) | ((in[0] << 8) & 0xff0000) | (in[0] << 24); + x1 = (in[1] >> 24) | ((in[1] >> 8) & 0xff00) | ((in[1] << 8) & 0xff0000) | (in[1] << 24); + x2 = (in[2] >> 24) | ((in[2] >> 8) & 0xff00) | ((in[2] << 8) & 0xff0000) | (in[2] << 24); + x3 = (in[3] >> 24) | ((in[3] >> 8) & 0xff00) | ((in[3] << 8) & 0xff0000) | (in[3] << 24); + + for (i = 0; i < 31; i++) { + x4 = x1 ^ x2 ^ x3 ^ rk[i]; + x4 = (S[x4 >> 24] << 24) ^ (S[(x4 >> 16) & 0xff] << 16) ^ (S[(x4 >> 8) & 0xff] << 8) ^ S[x4 & 0xff]; + + x4 = x0 ^ (x4 ^ + ((x4 << 2) | (x4 >> (32 - 2))) ^ + ((x4 << 10) | (x4 >> (32 - 10))) ^ + ((x4 << 18) | (x4 >> (32 - 18))) ^ + ((x4 << 24) | (x4 >> (32 - 24)))); + + t = x0; + x0 = x1; + x1 = x2; + x2 = x3; + x3 = x4; + x4 = t; + } + x4 = x1 ^ x2 ^ x3 ^ rk[i]; + x4 = (S[x4 >> 24] << 24) ^ (S[(x4 >> 16) & 0xff] << 16) ^ (S[(x4 >> 8) & 0xff] << 8) ^ S[x4 & 0xff]; + + x4 = x0 ^ (x4 ^ + ((x4 << 2) | (x4 >> (32 - 2))) ^ + ((x4 << 10) | (x4 >> (32 - 10))) ^ + ((x4 << 18) | (x4 >> (32 - 18))) ^ + ((x4 << 24) | (x4 >> (32 - 24)))); + + out[0] = (x4 >> 24) | ((x4 >> 8) & 0xff00) | ((x4 << 8) & 0xff0000) | (x4 << 24); + out[1] = (x3 >> 24) | ((x3 >> 8) & 0xff00) | ((x3 << 8) & 0xff0000) | (x3 << 24); + out[2] = (x2 >> 24) | ((x2 >> 8) & 0xff00) | ((x2 << 8) & 0xff0000) | (x2 << 24); + out[3] = (x1 >> 24) | ((x1 >> 8) & 0xff00) | ((x1 << 8) & 0xff0000) | (x1 << 24); +} + +); + diff --git a/Core/GmSSL-3.1.1/src/sm4_common.c b/Core/GmSSL-3.1.1/src/sm4_common.c new file mode 100644 index 0000000..276623c --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_common.c @@ -0,0 +1,114 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include "sm4_lcl.h" + + +const uint8_t SM4_S[256] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48, +}; + +const uint32_t SM4_T[256] = { + 0x8ed55b5bU, 0xd0924242U, 0x4deaa7a7U, 0x06fdfbfbU, + 0xfccf3333U, 0x65e28787U, 0xc93df4f4U, 0x6bb5dedeU, + 0x4e165858U, 0x6eb4dadaU, 0x44145050U, 0xcac10b0bU, + 0x8828a0a0U, 0x17f8efefU, 0x9c2cb0b0U, 0x11051414U, + 0x872bacacU, 0xfb669d9dU, 0xf2986a6aU, 0xae77d9d9U, + 0x822aa8a8U, 0x46bcfafaU, 0x14041010U, 0xcfc00f0fU, + 0x02a8aaaaU, 0x54451111U, 0x5f134c4cU, 0xbe269898U, + 0x6d482525U, 0x9e841a1aU, 0x1e061818U, 0xfd9b6666U, + 0xec9e7272U, 0x4a430909U, 0x10514141U, 0x24f7d3d3U, + 0xd5934646U, 0x53ecbfbfU, 0xf89a6262U, 0x927be9e9U, + 0xff33ccccU, 0x04555151U, 0x270b2c2cU, 0x4f420d0dU, + 0x59eeb7b7U, 0xf3cc3f3fU, 0x1caeb2b2U, 0xea638989U, + 0x74e79393U, 0x7fb1ceceU, 0x6c1c7070U, 0x0daba6a6U, + 0xedca2727U, 0x28082020U, 0x48eba3a3U, 0xc1975656U, + 0x80820202U, 0xa3dc7f7fU, 0xc4965252U, 0x12f9ebebU, + 0xa174d5d5U, 0xb38d3e3eU, 0xc33ffcfcU, 0x3ea49a9aU, + 0x5b461d1dU, 0x1b071c1cU, 0x3ba59e9eU, 0x0cfff3f3U, + 0x3ff0cfcfU, 0xbf72cdcdU, 0x4b175c5cU, 0x52b8eaeaU, + 0x8f810e0eU, 0x3d586565U, 0xcc3cf0f0U, 0x7d196464U, + 0x7ee59b9bU, 0x91871616U, 0x734e3d3dU, 0x08aaa2a2U, + 0xc869a1a1U, 0xc76aadadU, 0x85830606U, 0x7ab0cacaU, + 0xb570c5c5U, 0xf4659191U, 0xb2d96b6bU, 0xa7892e2eU, + 0x18fbe3e3U, 0x47e8afafU, 0x330f3c3cU, 0x674a2d2dU, + 0xb071c1c1U, 0x0e575959U, 0xe99f7676U, 0xe135d4d4U, + 0x661e7878U, 0xb4249090U, 0x360e3838U, 0x265f7979U, + 0xef628d8dU, 0x38596161U, 0x95d24747U, 0x2aa08a8aU, + 0xb1259494U, 0xaa228888U, 0x8c7df1f1U, 0xd73bececU, + 0x05010404U, 0xa5218484U, 0x9879e1e1U, 0x9b851e1eU, + 0x84d75353U, 0x00000000U, 0x5e471919U, 0x0b565d5dU, + 0xe39d7e7eU, 0x9fd04f4fU, 0xbb279c9cU, 0x1a534949U, + 0x7c4d3131U, 0xee36d8d8U, 0x0a020808U, 0x7be49f9fU, + 0x20a28282U, 0xd4c71313U, 0xe8cb2323U, 0xe69c7a7aU, + 0x42e9ababU, 0x43bdfefeU, 0xa2882a2aU, 0x9ad14b4bU, + 0x40410101U, 0xdbc41f1fU, 0xd838e0e0U, 0x61b7d6d6U, + 0x2fa18e8eU, 0x2bf4dfdfU, 0x3af1cbcbU, 0xf6cd3b3bU, + 0x1dfae7e7U, 0xe5608585U, 0x41155454U, 0x25a38686U, + 0x60e38383U, 0x16acbabaU, 0x295c7575U, 0x34a69292U, + 0xf7996e6eU, 0xe434d0d0U, 0x721a6868U, 0x01545555U, + 0x19afb6b6U, 0xdf914e4eU, 0xfa32c8c8U, 0xf030c0c0U, + 0x21f6d7d7U, 0xbc8e3232U, 0x75b3c6c6U, 0x6fe08f8fU, + 0x691d7474U, 0x2ef5dbdbU, 0x6ae18b8bU, 0x962eb8b8U, + 0x8a800a0aU, 0xfe679999U, 0xe2c92b2bU, 0xe0618181U, + 0xc0c30303U, 0x8d29a4a4U, 0xaf238c8cU, 0x07a9aeaeU, + 0x390d3434U, 0x1f524d4dU, 0x764f3939U, 0xd36ebdbdU, + 0x81d65757U, 0xb7d86f6fU, 0xeb37dcdcU, 0x51441515U, + 0xa6dd7b7bU, 0x09fef7f7U, 0xb68c3a3aU, 0x932fbcbcU, + 0x0f030c0cU, 0x03fcffffU, 0xc26ba9a9U, 0xba73c9c9U, + 0xd96cb5b5U, 0xdc6db1b1U, 0x375a6d6dU, 0x15504545U, + 0xb98f3636U, 0x771b6c6cU, 0x13adbebeU, 0xda904a4aU, + 0x57b9eeeeU, 0xa9de7777U, 0x4cbef2f2U, 0x837efdfdU, + 0x55114444U, 0xbdda6767U, 0x2c5d7171U, 0x45400505U, + 0x631f7c7cU, 0x50104040U, 0x325b6969U, 0xb8db6363U, + 0x220a2828U, 0xc5c20707U, 0xf531c4c4U, 0xa88a2222U, + 0x31a79696U, 0xf9ce3737U, 0x977aededU, 0x49bff6f6U, + 0x992db4b4U, 0xa475d1d1U, 0x90d34343U, 0x5a124848U, + 0x58bae2e2U, 0x71e69797U, 0x64b6d2d2U, 0x70b2c2c2U, + 0xad8b2626U, 0xcd68a5a5U, 0xcb955e5eU, 0x624b2929U, + 0x3c0c3030U, 0xce945a5aU, 0xab76ddddU, 0x867ff9f9U, + 0xf1649595U, 0x5dbbe6e6U, 0x35f2c7c7U, 0x2d092424U, + 0xd1c61717U, 0xd66fb9b9U, 0xdec51b1bU, 0x94861212U, + 0x78186060U, 0x30f3c3c3U, 0x897cf5f5U, 0x5cefb3b3U, + 0xd23ae8e8U, 0xacdf7373U, 0x794c3535U, 0xa0208080U, + 0x9d78e5e5U, 0x56edbbbbU, 0x235e7d7dU, 0xc63ef8f8U, + 0x8bd45f5fU, 0xe7c82f2fU, 0xdd39e4e4U, 0x68492121U, +}; diff --git a/Core/GmSSL-3.1.1/src/sm4_enc.c b/Core/GmSSL-3.1.1/src/sm4_enc.c new file mode 100644 index 0000000..360d553 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_enc.c @@ -0,0 +1,88 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#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 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++; + } +} diff --git a/Core/GmSSL-3.1.1/src/sm4_lcl.h b/Core/GmSSL-3.1.1/src/sm4_lcl.h new file mode 100644 index 0000000..ddf039f --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_lcl.h @@ -0,0 +1,60 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SM4_LCL_H +#define GMSSL_SM4_LCL_H + +#include + +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 diff --git a/Core/GmSSL-3.1.1/src/sm4_modes.c b/Core/GmSSL-3.1.1/src/sm4_modes.c new file mode 100644 index 0000000..ec8e1f0 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_modes.c @@ -0,0 +1,400 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include + +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_encrypt(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 - inlen % 16; + + 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]; + size_t len = sizeof(block); + int padding; + + if (inlen == 0) { + error_puts("warning: input lenght = 0"); + return 0; + } + if (inlen%16 != 0 || inlen < 16) { + error_puts("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; + } + len -= padding; + memcpy(out + inlen - 16, block, len); + *outlen = inlen - padding; + return 1; +} + +static void ctr_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + +#ifndef SM4_AESNI_AVX +void sm4_ctr_encrypt(const SM4_KEY *key, uint8_t ctr[16], const uint8_t *in, size_t inlen, uint8_t *out) +{ + uint8_t block[16]; + size_t len; + + while (inlen) { + len = inlen < 16 ? inlen : 16; + sm4_encrypt(key, ctr, block); + gmssl_memxor(out, in, block, len); + ctr_incr(ctr); + in += len; + out += len; + inlen -= len; + } +} +#endif + +int sm4_gcm_encrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + uint8_t *out, size_t taglen, uint8_t *tag) +{ + const uint8_t *pin = in; + uint8_t *pout = out; + size_t left = inlen; + uint8_t H[16] = {0}; + uint8_t Y[16]; + uint8_t T[16]; + + if (taglen > SM4_GCM_MAX_TAG_SIZE) { + error_print(); + return -1; + } + + sm4_encrypt(key, H, H); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + sm4_encrypt(key, Y, T); + + while (left) { + uint8_t block[16]; + size_t len = left < 16 ? left : 16; + ctr_incr(Y); + sm4_encrypt(key, Y, block); + gmssl_memxor(pout, pin, block, len); + pin += len; + pout += len; + left -= len; + } + + ghash(H, aad, aadlen, out, inlen, H); + gmssl_memxor(tag, T, H, taglen); + return 1; +} + +int sm4_gcm_decrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + const uint8_t *tag, size_t taglen, uint8_t *out) +{ + const uint8_t *pin = in; + uint8_t *pout = out; + size_t left = inlen; + uint8_t H[16] = {0}; + uint8_t Y[16]; + uint8_t T[16]; + + sm4_encrypt(key, H, H); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + ghash(H, aad, aadlen, in, inlen, H); + sm4_encrypt(key, Y, T); + gmssl_memxor(T, T, H, taglen); + if (memcmp(T, tag, taglen) != 0) { + error_print(); + return -1; + } + + while (left) { + uint8_t block[16]; + size_t len = left < 16 ? left : 16; + ctr_incr(Y); + sm4_encrypt(key, Y, block); + gmssl_memxor(pout, pin, block, len); + pin += len; + pout += len; + left -= len; + } + return 1; +} + +int sm4_cbc_encrypt_init(SM4_CBC_CTX *ctx, + const uint8_t key[SM4_BLOCK_SIZE], const uint8_t iv[SM4_BLOCK_SIZE]) +{ + sm4_set_encrypt_key(&ctx->sm4_key, key); + memcpy(ctx->iv, iv, SM4_BLOCK_SIZE); + memset(ctx->block, 0, SM4_BLOCK_SIZE); + ctx->block_nbytes = 0; + return 1; +} + +int sm4_cbc_encrypt_update(SM4_CBC_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t left; + size_t nblocks; + size_t len; + + if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + *outlen = 0; + if (ctx->block_nbytes) { + left = SM4_BLOCK_SIZE - ctx->block_nbytes; + if (inlen < left) { + memcpy(ctx->block + ctx->block_nbytes, in, inlen); + ctx->block_nbytes += inlen; + return 1; + } + memcpy(ctx->block + ctx->block_nbytes, in, left); + sm4_cbc_encrypt(&ctx->sm4_key, ctx->iv, ctx->block, 1, out); + memcpy(ctx->iv, out, SM4_BLOCK_SIZE); + in += left; + inlen -= left; + out += SM4_BLOCK_SIZE; + *outlen += SM4_BLOCK_SIZE; + } + if (inlen >= SM4_BLOCK_SIZE) { + nblocks = inlen / SM4_BLOCK_SIZE; + len = nblocks * SM4_BLOCK_SIZE; + sm4_cbc_encrypt(&ctx->sm4_key, ctx->iv, in, nblocks, out); + memcpy(ctx->iv, out + len - SM4_BLOCK_SIZE, SM4_BLOCK_SIZE); + in += len; + inlen -= len; + out += len; + *outlen += len; + } + if (inlen) { + memcpy(ctx->block, in, inlen); + } + ctx->block_nbytes = inlen; + return 1; +} + +int sm4_cbc_encrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + if (sm4_cbc_padding_encrypt(&ctx->sm4_key, ctx->iv, ctx->block, ctx->block_nbytes, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm4_cbc_decrypt_init(SM4_CBC_CTX *ctx, + const uint8_t key[SM4_BLOCK_SIZE], const uint8_t iv[SM4_BLOCK_SIZE]) +{ + sm4_set_decrypt_key(&ctx->sm4_key, key); + memcpy(ctx->iv, iv, SM4_BLOCK_SIZE); + memset(ctx->block, 0, SM4_BLOCK_SIZE); + ctx->block_nbytes = 0; + return 1; +} + +int sm4_cbc_decrypt_update(SM4_CBC_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t left, len, nblocks; + + if (ctx->block_nbytes > SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + + *outlen = 0; + if (ctx->block_nbytes) { + left = SM4_BLOCK_SIZE - ctx->block_nbytes; + if (inlen <= left) { + memcpy(ctx->block + ctx->block_nbytes, in, inlen); + ctx->block_nbytes += inlen; + return 1; + } + memcpy(ctx->block + ctx->block_nbytes, in, left); + sm4_cbc_decrypt(&ctx->sm4_key, ctx->iv, ctx->block, 1, out); + memcpy(ctx->iv, ctx->block, SM4_BLOCK_SIZE); + in += left; + inlen -= left; + out += SM4_BLOCK_SIZE; + *outlen += SM4_BLOCK_SIZE; + } + if (inlen > SM4_BLOCK_SIZE) { + nblocks = (inlen-1) / SM4_BLOCK_SIZE; + len = nblocks * SM4_BLOCK_SIZE; + sm4_cbc_decrypt(&ctx->sm4_key, ctx->iv, in, nblocks, out); + memcpy(ctx->iv, in + len - SM4_BLOCK_SIZE, SM4_BLOCK_SIZE); + in += len; + inlen -= len; + out += len; + *outlen += len; + } + memcpy(ctx->block, in, inlen); + ctx->block_nbytes = inlen; + return 1; +} + +int sm4_cbc_decrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (ctx->block_nbytes != SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + if (sm4_cbc_padding_decrypt(&ctx->sm4_key, ctx->iv, ctx->block, SM4_BLOCK_SIZE, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm4_ctr_encrypt_init(SM4_CTR_CTX *ctx, + const uint8_t key[SM4_BLOCK_SIZE], const uint8_t ctr[SM4_BLOCK_SIZE]) +{ + sm4_set_encrypt_key(&ctx->sm4_key, key); + memcpy(ctx->ctr, ctr, SM4_BLOCK_SIZE); + memset(ctx->block, 0, SM4_BLOCK_SIZE); + ctx->block_nbytes = 0; + return 1; +} + +int sm4_ctr_encrypt_update(SM4_CTR_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t left; + size_t nblocks; + size_t len; + + if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + *outlen = 0; + if (ctx->block_nbytes) { + left = SM4_BLOCK_SIZE - ctx->block_nbytes; + if (inlen < left) { + memcpy(ctx->block + ctx->block_nbytes, in, inlen); + ctx->block_nbytes += inlen; + return 1; + } + memcpy(ctx->block + ctx->block_nbytes, in, left); + sm4_ctr_encrypt(&ctx->sm4_key, ctx->ctr, ctx->block, SM4_BLOCK_SIZE, out); + in += left; + inlen -= left; + out += SM4_BLOCK_SIZE; + *outlen += SM4_BLOCK_SIZE; + } + if (inlen >= SM4_BLOCK_SIZE) { + nblocks = inlen / SM4_BLOCK_SIZE; + len = nblocks * SM4_BLOCK_SIZE; + sm4_ctr_encrypt(&ctx->sm4_key, ctx->ctr, in, len, out); + in += len; + inlen -= len; + out += len; + *outlen += len; + } + if (inlen) { + memcpy(ctx->block, in, inlen); + } + ctx->block_nbytes = inlen; + return 1; +} + +int sm4_ctr_encrypt_finish(SM4_CTR_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + sm4_ctr_encrypt(&ctx->sm4_key, ctx->ctr, ctx->block, ctx->block_nbytes, out); + *outlen = ctx->block_nbytes; + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm4_rng.c b/Core/GmSSL-3.1.1/src/sm4_rng.c new file mode 100644 index 0000000..ed11596 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_rng.c @@ -0,0 +1,258 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +// see GM/T 0105-2021 Design Guide for Software-based Random Number Generators + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* +u8[16] R0, R1 + +(R0,R1) = sm4_df(in): + + L = nbytes(in) + N = 32 -- nbytes(R0||R1) + S = be32(L) || be32(N) || in || 0x80 || 0x00^*, nbytes(S) = 0 (mod 16) + K = 0x000102030405060708090a0b0c0d0e0f + + T = CBC_MAC(K, be32(0) || 0x00^12 || S) = CBC_MAC(K, be32(0) || 0x00^12 || be32(L) || be32(N) || in || 0x80) + X = CBC_MAC(K, be32(1) || 0x00^12 || S) = CBC_MAC(K, be32(1) || 0x00^12 || be32(L) || be32(N) || in || 0x80) + K = T + + R0 = sm4(K, X) + R1 = sm4(K, R0) +*/ + +typedef struct { + SM4_CBC_MAC_CTX cbc_mac_ctx[2]; + uint32_t len; + uint32_t len_check; +} SM4_DF_CTX; + +static void sm4_df_init(SM4_DF_CTX *df_ctx, size_t len) +{ + const uint8_t key[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + uint8_t prefix[16] = {0}; + uint8_t Lbuf[4] = {0}; + uint8_t Nbuf[4] = {0}; + + Lbuf[0] = (len >> 24) & 0xff; + Lbuf[1] = (len >> 16) & 0xff; + Lbuf[2] = (len >> 8) & 0xff; + Lbuf[3] = len & 0xff; + + Nbuf[3] = 32; + + sm4_cbc_mac_init(&df_ctx->cbc_mac_ctx[0], key); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[0], prefix, 16); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[0], Lbuf, 4); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[0], Nbuf, 4); + + prefix[3] = 1; + sm4_cbc_mac_init(&df_ctx->cbc_mac_ctx[1], key); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[1], prefix, 16); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[1], Lbuf, 4); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[1], Nbuf, 4); + + df_ctx->len = (uint32_t)len; + df_ctx->len_check = 0; +} + +static void sm4_df_update(SM4_DF_CTX *df_ctx, const uint8_t *data, size_t datalen) +{ + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[0], data, datalen); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[1], data, datalen); + df_ctx->len_check += datalen; +} + +static void sm4_df_finish(SM4_DF_CTX *df_ctx, uint8_t out[32]) +{ + const uint8_t suffix[1] = {0x80}; + uint8_t K[16]; + uint8_t X[16]; + SM4_KEY sm4_key; + + assert(df_ctx->len == df_ctx->len_check); + + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[0], suffix, 1); + sm4_cbc_mac_finish(&df_ctx->cbc_mac_ctx[0], K); + sm4_cbc_mac_update(&df_ctx->cbc_mac_ctx[1], suffix, 1); + sm4_cbc_mac_finish(&df_ctx->cbc_mac_ctx[1], X); + + sm4_set_encrypt_key(&sm4_key, K); + sm4_encrypt(&sm4_key, X, out); + sm4_encrypt(&sm4_key, out, out + 16); + + gmssl_secure_clear(K, sizeof(K)); + gmssl_secure_clear(X, sizeof(X)); + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); +} + +static void be_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + + +int sm4_rng_update(SM4_RNG *rng, const uint8_t seed[32]) +{ + SM4_KEY sm4_key; + + sm4_set_encrypt_key(&sm4_key, rng->K); + be_incr(rng->V); + sm4_encrypt(&sm4_key, rng->V, rng->K); + be_incr(rng->V); + sm4_encrypt(&sm4_key, rng->V, rng->V); + + memxor(rng->K, seed, 16); + memxor(rng->V, seed + 16, 16); + + return 1; +} + +int sm4_rng_init(SM4_RNG *rng, const uint8_t *nonce, size_t nonce_len, + const uint8_t *label, size_t label_len) +{ + SM4_DF_CTX df_ctx; + uint8_t entropy[512]; + uint8_t seed[32]; + + // get_entropy, 512-byte might be too long for some system RNGs + if (rand_bytes(entropy, 256) != 1 + || rand_bytes(entropy + 256, 256) != 1) { + error_print(); + return -1; + } + + // seed = sm4_df(entropy || nonce || label) + sm4_df_init(&df_ctx, sizeof(entropy) + nonce_len + label_len); + sm4_df_update(&df_ctx, entropy, sizeof(entropy)); + sm4_df_update(&df_ctx, nonce, nonce_len); + sm4_df_update(&df_ctx, label, label_len); + sm4_df_finish(&df_ctx, seed); + + memset(rng->K, 0, 16); + memset(rng->V, 0, 16); + + // (K, V) = sm3_rng_update(seed, K, V) + sm4_rng_update(rng, seed); + + // reseed_counter = 1, last_ressed_time = now() + rng->reseed_counter = 1; + rng->last_reseed_time = time(NULL); + + gmssl_secure_clear(&df_ctx, sizeof(df_ctx)); + gmssl_secure_clear(entropy, sizeof(entropy)); + gmssl_secure_clear(seed, sizeof(seed)); + return 1; +} + +int sm4_rng_reseed(SM4_RNG *rng, const uint8_t *addin, size_t addin_len) +{ + SM4_DF_CTX df_ctx; + uint8_t entropy[512]; + uint8_t seed[32]; + + // get_entropy, 512-byte might be too long for some system RNGs + if (rand_bytes(entropy, 256) != 1 + || rand_bytes(entropy + 256, 256) != 1) { + error_print(); + return -1; + } + + // seed = sm4_df(entropy || addin) + sm4_df_init(&df_ctx, sizeof(entropy) + addin_len); + sm4_df_update(&df_ctx, entropy, sizeof(entropy)); + sm4_df_update(&df_ctx, addin, addin_len); + sm4_df_finish(&df_ctx, seed); + + sm4_rng_update(rng, seed); + + rng->reseed_counter = 1; + rng->last_reseed_time = time(NULL); + + gmssl_secure_clear(&df_ctx, sizeof(df_ctx)); + gmssl_secure_clear(entropy, sizeof(entropy)); + return 1; +} + + +#define SM4_RNG_MAX_RESEED_COUNTER (1<<20) +#define SM4_RNG_MAX_RESEED_SECONDS 600 + +int sm4_rng_generate(SM4_RNG *rng, const uint8_t *addin, size_t addin_len, + uint8_t *out, size_t outlen) +{ + uint8_t seed[32] = {0}; + SM4_KEY sm4_key; + + if (!outlen || outlen > 16) { + error_print(); + return -1; + } + + if (rng->reseed_counter > SM4_RNG_MAX_RESEED_COUNTER + || time(NULL) - rng->last_reseed_time > SM4_RNG_MAX_RESEED_SECONDS) { + if (sm4_rng_reseed(rng, addin, addin_len) != 1) { + error_print(); + return -1; + } + if (addin) { + addin = NULL; + } + } + + if (addin && addin_len) { + // seed = sm4_df(addin) + SM4_DF_CTX df_ctx; + sm4_df_init(&df_ctx, addin_len); + sm4_df_update(&df_ctx, addin, addin_len); + sm4_df_finish(&df_ctx, seed); + gmssl_secure_clear(&df_ctx, sizeof(df_ctx)); + + // rng_update(seed) + sm4_rng_update(rng, seed); + } + + // V = (V + 1) mod 2^128 + be_incr(rng->V); + + // output sm4(K, V)[0:outlen] + sm4_set_encrypt_key(&sm4_key, rng->K); + if (outlen < 16) { + uint8_t buf[16]; + sm4_encrypt(&sm4_key, rng->V, buf); + memcpy(out, buf, outlen); + } else { + sm4_encrypt(&sm4_key, rng->V, out); + } + + // (K, V) = update(seed, (K, V)) + sm4_rng_update(rng, seed); + + // reseed_counter++ + (rng->reseed_counter)++; + + + gmssl_secure_clear(seed, sizeof(seed)); + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm4_setkey.c b/Core/GmSSL-3.1.1/src/sm4_setkey.c new file mode 100644 index 0000000..3612e36 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm4_setkey.c @@ -0,0 +1,79 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#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 uint8_t 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 uint8_t 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; +} diff --git a/Core/GmSSL-3.1.1/src/sm9_alg.c b/Core/GmSSL-3.1.1/src/sm9_alg.c new file mode 100644 index 0000000..0da0f18 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm9_alg.c @@ -0,0 +1,2450 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +const sm9_bn_t SM9_ZERO = {0,0,0,0,0,0,0,0}; +const sm9_bn_t SM9_ONE = {1,0,0,0,0,0,0,0}; +static const sm9_bn_t SM9_TWO = {2,0,0,0,0,0,0,0}; +static const sm9_bn_t SM9_FIVE = {5,0,0,0,0,0,0,0}; + + +// p = b640000002a3a6f1d603ab4ff58ec74521f2934b1a7aeedbe56f9b27e351457d +// n = b640000002a3a6f1d603ab4ff58ec74449f2934b18ea8beee56ee19cd69ecf25 +// mu_p = 2^512 // p = 167980e0beb5759a655f73aebdcd1312af2665f6d1e36081c71188f90d5c22146 +// mu_n = 2^512 // n +const sm9_bn_t SM9_P = {0xe351457d, 0xe56f9b27, 0x1a7aeedb, 0x21f2934b, 0xf58ec745, 0xd603ab4f, 0x02a3a6f1, 0xb6400000}; +const sm9_bn_t SM9_N = {0xd69ecf25, 0xe56ee19c, 0x18ea8bee, 0x49f2934b, 0xf58ec744, 0xd603ab4f, 0x02a3a6f1, 0xb6400000}; +static const sm9_bn_t SM9_P_MINUS_ONE = {0xe351457c, 0xe56f9b27, 0x1a7aeedb, 0x21f2934b, 0xf58ec745, 0xd603ab4f, 0x02a3a6f1, 0xb6400000}; +static const sm9_bn_t SM9_N_MINUS_ONE = {0xd69ecf24, 0xe56ee19c, 0x18ea8bee, 0x49f2934b, 0xf58ec744, 0xd603ab4f, 0x02a3a6f1, 0xb6400000}; +static const sm9_barrett_bn_t SM9_MU_P = {0xd5c22146, 0x71188f90, 0x1e36081c, 0xf2665f6d, 0xdcd1312a, 0x55f73aeb, 0xeb5759a6, 0x67980e0b, 0x00000001}; +static const sm9_barrett_bn_t SM9_MU_N = {0xdfc97c2f, 0x74df4fd4, 0xc9c073b0, 0x9c95d85e, 0xdcd1312c, 0x55f73aeb, 0xeb5759a6, 0x67980e0b, 0x00000001}; +static const sm9_barrett_bn_t SM9_MU_N_MINUS_ONE = {0xdfc97c31, 0x74df4fd4, 0xc9c073b0, 0x9c95d85e, 0xdcd1312c, 0x55f73aeb, 0xeb5759a6, 0x67980e0b, 0x00000001}; + + +// P1.X 0x93DE051D62BF718FF5ED0704487D01D6E1E4086909DC3280E8C4E4817C66DDDD +// P1.Y 0x21FE8DDA4F21E607631065125C395BBC1C1C00CBFA6024350C464CD70A3EA616 +const SM9_POINT _SM9_P1 = { + {0x7c66dddd, 0xe8c4e481, 0x09dc3280, 0xe1e40869, 0x487d01d6, 0xf5ed0704, 0x62bf718f, 0x93de051d}, + {0x0a3ea616, 0x0c464cd7, 0xfa602435, 0x1c1c00cb, 0x5c395bbc, 0x63106512, 0x4f21e607, 0x21fe8dda}, + {1,0,0,0,0,0,0,0} +}; +const SM9_POINT *SM9_P1 = &_SM9_P1; + + +/* + X : [0x3722755292130b08d2aab97fd34ec120ee265948d19c17abf9b7213baf82d65bn, + 0x85aef3d078640c98597b6027b441a01ff1dd2c190f5e93c454806c11d8806141n], + Y : [0xa7cf28d519be3da65f3170153d278ff247efba98a71a08116215bba5c999a7c7n, + 0x17509b092e845c1266ba0d262cbee6ed0736a96fa347c8bd856dc76b84ebeb96n], + Z : [1n, 0n], +*/ +const SM9_TWIST_POINT _SM9_P2 = { + {{0xAF82D65B, 0xF9B7213B, 0xD19C17AB, 0xEE265948, 0xD34EC120, 0xD2AAB97F, 0x92130B08, 0x37227552}, + {0xD8806141, 0x54806C11, 0x0F5E93C4, 0xF1DD2C19, 0xB441A01F, 0x597B6027, 0x78640C98, 0x85AEF3D0}}, + {{0xC999A7C7, 0x6215BBA5, 0xA71A0811, 0x47EFBA98, 0x3D278FF2, 0x5F317015, 0x19BE3DA6, 0xA7CF28D5}, + {0x84EBEB96, 0x856DC76B, 0xA347C8BD, 0x0736A96F, 0x2CBEE6ED, 0x66BA0D26, 0x2E845C12, 0x17509B09}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, +}; +const SM9_TWIST_POINT *SM9_P2 = &_SM9_P2; + + +const SM9_TWIST_POINT _SM9_Ppubs = { + {{0x96EA5E32, 0x8F14D656, 0x386A92DD, 0x414D2177, 0x24A3B573, 0x6CE843ED, 0x152D1F78, 0x29DBA116}, + {0x1B94C408, 0x0AB1B679, 0x5E392CFB, 0x1CE0711C, 0x41B56501, 0xE48AFF4B, 0x3084F733, 0x9F64080B}}, + {{0xB4E3216D, 0x0E75C05F, 0x5CDFF073, 0x1006E85F, 0xB7A46F74, 0x1A7CE027, 0xDDA532DA, 0x41E00A53}, + {0xD0EF1C25, 0xE89E1408, 0x1A77F335, 0xAD3E2FDB, 0x47E3A0CB, 0xB57329F4, 0xABEA0112, 0x69850938}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, +}; +const SM9_TWIST_POINT *SM9_Ppubs = &_SM9_Ppubs; + + +void sm9_bn_set_zero(sm9_bn_t r) +{ + sm9_bn_copy(r, SM9_ZERO); +} + +void sm9_bn_set_one(sm9_bn_t r) +{ + sm9_bn_copy(r, SM9_ONE); +} + +int sm9_bn_is_zero(const sm9_bn_t a) +{ + return (sm9_bn_cmp(a, SM9_ZERO) == 0); +} + +int sm9_bn_is_one(const sm9_bn_t a) +{ + return (sm9_bn_cmp(a, SM9_ONE) == 0); +} + +void sm9_bn_to_bytes(const sm9_bn_t a, uint8_t out[32]) +{ + int i; + for (i = 7; i >= 0; i--) { + PUTU32(out, (uint32_t)a[i]); + out += sizeof(uint32_t); + } +} + +void sm9_bn_from_bytes(sm9_bn_t r, const uint8_t in[32]) +{ + int i; + for (i = 7; i >= 0; i--) { + r[i] = GETU32(in); + in += sizeof(uint32_t); + } +} + +int sm9_bn_from_hex(sm9_bn_t r, const char hex[64]) +{ + uint8_t buf[32]; + size_t len; + if (hex_to_bytes(hex, 64, buf, &len) < 0) { + return -1; + } + sm9_bn_from_bytes(r, buf); + return 1; +} + +void sm9_bn_to_hex(const sm9_bn_t a, char hex[64]) +{ + int i; + for (i = 7; i >= 0; i--) { + (void)sprintf(hex + 8*(7-i), "%08x", (uint32_t)a[i]); + //hex += 8; + } +} + +void sm9_print_bn(const char *prefix, const sm9_bn_t a) +{ + char hex[65] = {0}; + sm9_bn_to_hex(a, hex); + printf("%s\n%s\n", prefix, hex); +} + +void sm9_bn_to_bits(const sm9_bn_t a, char bits[256]) +{ + int i, j; + for (i = 7; i >= 0; i--) { + uint32_t w = (uint32_t)a[i]; + for (j = 0; j < 32; j++) { + *bits++ = (w & 0x80000000) ? '1' : '0'; + w <<= 1; + } + } +} + +int sm9_bn_cmp(const sm9_bn_t a, const sm9_bn_t b) +{ + int i; + for (i = 7; i >= 0; i--) { + if (a[i] > b[i]) + return 1; + if (a[i] < b[i]) + return -1; + } + return 0; +} + + + + +void sm9_bn_copy(sm9_bn_t r, const sm9_bn_t a) +{ + memcpy(r, a, sizeof(sm9_bn_t)); +} + +void sm9_bn_set_word(sm9_bn_t r, uint32_t a) +{ + sm9_bn_set_zero(r); + r[0] = a; +} + +void sm9_bn_add(sm9_bn_t r, const sm9_bn_t a, const sm9_bn_t b) +{ + int i; + r[0] = a[0] + b[0]; + for (i = 1; i < 8; i++) { + r[i] = a[i] + b[i] + (r[i-1] >> 32); + } + for (i = 0; i < 7; i++) { + r[i] &= 0xffffffff; + } +} + +void sm9_bn_sub(sm9_bn_t ret, const sm9_bn_t a, const sm9_bn_t b) +{ + int i; + sm9_bn_t r; + r[0] = ((uint64_t)1 << 32) + a[0] - b[0]; + for (i = 1; i < 7; i++) { + r[i] = 0xffffffff + a[i] - b[i] + (r[i - 1] >> 32); + r[i - 1] &= 0xffffffff; + } + r[i] = a[i] - b[i] + (r[i - 1] >> 32) - 1; + r[i - 1] &= 0xffffffff; + sm9_bn_copy(ret, r); +} + +int sm9_bn_rand_range(sm9_bn_t r, const sm9_bn_t range) +{ + uint8_t buf[256]; + + do { + rand_bytes(buf, sizeof(buf)); + sm9_bn_from_bytes(r, buf); + } while (sm9_bn_cmp(r, range) >= 0); + return 1; +} + +int sm9_bn_equ(const sm9_bn_t a, const sm9_bn_t b) +{ + int i; + for (i = 0; i < 8; i++) { + if (a[i] != b[i]) + return 0; + } + return 1; +} + +void sm9_fp_add(sm9_fp_t r, const sm9_fp_t a, const sm9_fp_t b) +{ + sm9_bn_add(r, a, b); + if (sm9_bn_cmp(r, SM9_P) >= 0) { + sm9_bn_sub(r, r, SM9_P); + } +} + +void sm9_fp_sub(sm9_fp_t r, const sm9_fp_t a, const sm9_fp_t b) +{ + if (sm9_bn_cmp(a, b) >= 0) { + sm9_bn_sub(r, a, b); + } else { + sm9_bn_t t; + sm9_bn_sub(t, SM9_P, b); + sm9_bn_add(r, t, a); + } +} + +void sm9_fp_dbl(sm9_fp_t r, const sm9_fp_t a) +{ + sm9_fp_add(r, a, a); +} + +void sm9_fp_tri(sm9_fp_t r, const sm9_fp_t a) +{ + sm9_fp_t t; + sm9_fp_dbl(t, a); + sm9_fp_add(r, t, a); +} + +void sm9_fp_div2(sm9_fp_t r, const sm9_fp_t a) +{ + int i; + sm9_bn_copy(r, a); + if (r[0] & 0x01) { + sm9_bn_add(r, r, SM9_P); + } + for (i = 0; i < 7; i++) { + r[i] = (r[i] >> 1) | ((r[i + 1] & 0x01) << 31); + } + r[i] >>= 1; +} + +void sm9_fp_neg(sm9_fp_t r, const sm9_fp_t a) +{ + if (sm9_bn_is_zero(a)) { + sm9_bn_copy(r, a); + } else { + sm9_bn_sub(r, SM9_P, a); + } +} + +int sm9_bn_print(FILE *fp, int fmt, int ind, const char *label, const sm9_bn_t a) +{ + uint8_t buf[32]; + sm9_bn_to_bytes(a, buf); + format_bytes(fp, fmt, ind, label, buf, sizeof(buf)); + return 1; +} + +int sm9_barrett_bn_cmp(const sm9_barrett_bn_t a, const sm9_barrett_bn_t b) +{ + int i; + for (i = 8; i >= 0; i--) { + if (a[i] > b[i]) + return 1; + if (a[i] < b[i]) + return -1; + } + return 0; +} + +void sm9_barrett_bn_add(sm9_barrett_bn_t r, const sm9_barrett_bn_t a, const sm9_barrett_bn_t b) +{ + int i; + r[0] = a[0] + b[0]; + for (i = 1; i < 9; i++) { + r[i] = a[i] + b[i] + (r[i-1] >> 32); + } + for (i = 0; i < 8; i++) { + r[i] &= 0xffffffff; + } +} + +void sm9_barrett_bn_sub(sm9_barrett_bn_t ret, const sm9_barrett_bn_t a, const sm9_barrett_bn_t b) +{ + sm9_barrett_bn_t r; + int i; + r[0] = ((uint64_t)1 << 32) + a[0] - b[0]; + for (i = 1; i < 8; i++) { + r[i] = 0xffffffff + a[i] - b[i] + (r[i - 1] >> 32); + r[i - 1] &= 0xffffffff; + } + r[i] = a[i] - b[i] + (r[i - 1] >> 32) - 1; + r[i - 1] &= 0xffffffff; + for (i = 0; i < 9; i++) { + ret[i] = r[i]; + } +} + +void sm9_fp_mul(sm9_fp_t r, const sm9_fp_t a, const sm9_fp_t b) +{ + uint64_t s[18]; + sm9_barrett_bn_t zh, zl, q; + uint64_t w; + int i, j; + + /* z = a * b */ + for (i = 0; i < 8; i++) { + s[i] = 0; + } + for (i = 0; i < 8; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + a[i] * b[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + + /* zl = z mod (2^32)^9 = z[0..8] + * zh = z // (2^32)^7 = z[7..15] */ + for (i = 0; i < 9; i++) { + zl[i] = s[i]; + zh[i] = s[7 + i]; + } + + /* q = zh * mu // (2^32)^9 */ + for (i = 0; i < 9; i++) { + s[i] = 0; + } + for (i = 0; i < 9; i++) { + w = 0; + for (j = 0; j < 9; j++) { + w += s[i + j] + zh[i] * SM9_MU_P[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 9] = w; + } + for (i = 0; i < 9; i++) { + q[i] = s[9 + i]; + } + + /* q = q * p mod (2^32)^9 */ + for (i = 0; i < 8; i++) { + s[i] = 0; + } + w = 0; + for (j = 0; j < 8; j++) { + w += s[j] + q[0] * SM9_P[j]; + s[j] = w & 0xffffffff; + w >>= 32; + } + s[8] = w; + for (i = 1; i < 9; i++) { + w = 0; + for (j = 0; i + j < 9; j++) { + w += s[i + j] + q[i] * SM9_P[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + } + for (i = 0; i < 9; i++) { + q[i] = s[i]; + } + + /* r = zl - q (mod (2^32)^9) */ + + if (sm9_barrett_bn_cmp(zl, q)) { + sm9_barrett_bn_sub(zl, zl, q); + } else { + sm9_barrett_bn_t c = {0,0,0,0,0,0,0,0,0x100000000}; + sm9_barrett_bn_sub(q, c, q); + sm9_barrett_bn_add(zl, q, zl); + } + + + for (i = 0; i < 8; i++) { + r[i] = zl[i]; + } + + r[7] += (zl[8] << 32); + + /* while r >= p do: r = r - p */ + while (sm9_bn_cmp(r, SM9_P) >= 0) { + + sm9_bn_sub(r, r, SM9_P); + } +} + +void sm9_fp_sqr(sm9_fp_t r, const sm9_fp_t a) +{ + sm9_fp_mul(r, a, a); +} + +void sm9_fp_pow(sm9_fp_t r, const sm9_fp_t a, const sm9_bn_t e) +{ + sm9_fp_t t; + uint32_t w; + int i, j; + + assert(sm9_bn_cmp(e, SM9_P_MINUS_ONE) < 0); + + sm9_bn_set_one(t); + for (i = 7; i >= 0; i--) { + w = (uint32_t)e[i]; + for (j = 0; j < 32; j++) { + sm9_fp_sqr(t, t); + if (w & 0x80000000) + sm9_fp_mul(t, t, a); + w <<= 1; + } + } + sm9_bn_copy(r, t); +} + +void sm9_fp_inv(sm9_fp_t r, const sm9_fp_t a) +{ + sm9_fp_t e; + sm9_bn_sub(e, SM9_P, SM9_TWO); + sm9_fp_pow(r, a, e); +} + +int sm9_fp_from_bytes(sm9_fp_t r, const uint8_t buf[32]) +{ + sm9_bn_from_bytes(r, buf); + if (sm9_bn_cmp(r, SM9_P) >= 0) { + error_print(); + return -1; + } + return 1; +} + +int sm9_fp_from_hex(sm9_fp_t r, const char hex[64]) +{ + if (sm9_bn_from_hex(r, hex) != 1) { + error_print(); + return -1; + } + if (sm9_bn_cmp(r, SM9_P) >= 0) { + error_print(); + return -1; + } + return 1; +} + + +const sm9_fp2_t SM9_FP2_ZERO = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}; +const sm9_fp2_t SM9_FP2_ONE = {{1,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}; +const sm9_fp2_t SM9_FP2_U = {{0,0,0,0,0,0,0,0},{1,0,0,0,0,0,0,0}}; +static const sm9_fp2_t SM9_FP2_5U = {{0,0,0,0,0,0,0,0},{5,0,0,0,0,0,0,0}}; + +int sm9_fp2_equ(const sm9_fp2_t a, const sm9_fp2_t b) +{ + return (gmssl_secure_memcmp(a, b, sizeof(sm9_fp2_t)) == 0); +} + +void sm9_fp2_copy(sm9_fp2_t r, const sm9_fp2_t a) +{ + memcpy(r, a, sizeof(sm9_fp2_t)); +} + +int sm9_fp2_rand(sm9_fp2_t r) +{ + if (sm9_fp_rand(r[0]) != 1 + || sm9_fp_rand(r[1]) != 1) { + error_print(); + return -1; + } + return 1; +} + +void sm9_fp2_to_bytes(const sm9_fp2_t a, uint8_t buf[64]) +{ + sm9_fp_to_bytes(a[1], buf); + sm9_fp_to_bytes(a[0], buf + 32); +} + +int sm9_fp2_from_bytes(sm9_fp2_t r, const uint8_t buf[64]) +{ + if (sm9_fp_from_bytes(r[1], buf) != 1 + || sm9_fp_from_bytes(r[0], buf + 32) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_fp2_from_hex(sm9_fp2_t r, const char hex[129]) +{ + if (sm9_fp_from_hex(r[1], hex) != 1 + || sm9_fp_from_hex(r[0], hex + 65) != 1) { + error_print(); + return -1; + } + /* + if (hex[64] != SM9_HEX_SEP) { + error_print(); + return -1; + } + */ + return 1; +} + +void sm9_fp2_to_hex(const sm9_fp2_t a, char hex[129]) +{ + sm9_fp_to_hex(a[1], hex); + hex[64] = SM9_HEX_SEP; + sm9_fp_to_hex(a[0], hex + 65); +} + +void sm9_fp2_set_fp(sm9_fp2_t r, const sm9_fp_t a) +{ + sm9_fp_copy(r[0], a); + sm9_fp_set_zero(r[1]); +} + +void sm9_fp2_set(sm9_fp2_t r, const sm9_fp_t a0, const sm9_fp_t a1) +{ + sm9_fp_copy(r[0], a0); + sm9_fp_copy(r[1], a1); +} + +void sm9_fp2_add(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b) +{ + sm9_fp_add(r[0], a[0], b[0]); + sm9_fp_add(r[1], a[1], b[1]); +} + +void sm9_fp2_dbl(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp_dbl(r[0], a[0]); + sm9_fp_dbl(r[1], a[1]); +} + +void sm9_fp2_tri(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp_tri(r[0], a[0]); + sm9_fp_tri(r[1], a[1]); +} + +void sm9_fp2_sub(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b) +{ + sm9_fp_sub(r[0], a[0], b[0]); + sm9_fp_sub(r[1], a[1], b[1]); +} + +void sm9_fp2_neg(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp_neg(r[0], a[0]); + sm9_fp_neg(r[1], a[1]); +} + +void sm9_fp2_mul(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b) +{ + sm9_fp_t r0, r1, t; + + // r0 = a0 * b0 - 2 * a1 * b1 + sm9_fp_mul(r0, a[0], b[0]); + sm9_fp_mul(t, a[1], b[1]); + sm9_fp_dbl(t, t); + sm9_fp_sub(r0, r0, t); + + // r1 = a0 * b1 + a1 * b0 + sm9_fp_mul(r1, a[0], b[1]); + sm9_fp_mul(t, a[1], b[0]); + sm9_fp_add(r1, r1, t); + + sm9_fp_copy(r[0], r0); + sm9_fp_copy(r[1], r1); +} + +void sm9_fp2_mul_u(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b) +{ + sm9_fp_t r0, r1, t; + + // r0 = -2 * (a0 * b1 + a1 * b0) + sm9_fp_mul(r0, a[0], b[1]); + sm9_fp_mul(t, a[1], b[0]); + sm9_fp_add(r0, r0, t); + sm9_fp_dbl(r0, r0); + sm9_fp_neg(r0, r0); + + // r1 = a0 * b0 - 2 * a1 * b1 + sm9_fp_mul(r1, a[0], b[0]); + sm9_fp_mul(t, a[1], b[1]); + sm9_fp_dbl(t, t); + sm9_fp_sub(r1, r1, t); + + sm9_fp_copy(r[0], r0); + sm9_fp_copy(r[1], r1); +} + +void sm9_fp2_mul_fp(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp_t k) +{ + sm9_fp_mul(r[0], a[0], k); + sm9_fp_mul(r[1], a[1], k); +} + +void sm9_fp2_sqr(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp_t r0, r1, t; + + // a0^2 - 2 * a1^2 + sm9_fp_sqr(r0, a[0]); + sm9_fp_sqr(t, a[1]); + sm9_fp_dbl(t, t); + sm9_fp_sub(r0, r0, t); + + // r1 = 2 * a0 * a1 + sm9_fp_mul(r1, a[0], a[1]); + sm9_fp_dbl(r1, r1); + + sm9_bn_copy(r[0], r0); + sm9_bn_copy(r[1], r1); +} + +void sm9_fp2_sqr_u(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp_t r0, r1, t; + + // r0 = -4 * a0 * a1 + sm9_fp_mul(r0, a[0], a[1]); + sm9_fp_dbl(r0, r0); + sm9_fp_dbl(r0, r0); + sm9_fp_neg(r0, r0); + + // r1 = a0^2 - 2 * a1^2 + sm9_fp_sqr(r1, a[0]); + sm9_fp_sqr(t, a[1]); + sm9_fp_dbl(t, t); + sm9_fp_sub(r1, r1, t); + + sm9_fp_copy(r[0], r0); + sm9_fp_copy(r[1], r1); + +} + +void sm9_fp2_inv(sm9_fp2_t r, const sm9_fp2_t a) +{ + if (sm9_fp_is_zero(a[0])) { + // r0 = 0 + sm9_fp_set_zero(r[0]); + // r1 = -(2 * a1)^-1 + sm9_fp_dbl(r[1], a[1]); + sm9_fp_inv(r[1], r[1]); + sm9_fp_neg(r[1], r[1]); + + } else if (sm9_fp_is_zero(a[1])) { + /* r1 = 0 */ + sm9_fp_set_zero(r[1]); + /* r0 = a0^-1 */ + sm9_fp_inv(r[0], a[0]); + + } else { + sm9_fp_t k, t; + + // k = (a[0]^2 + 2 * a[1]^2)^-1 + sm9_fp_sqr(k, a[0]); + sm9_fp_sqr(t, a[1]); + sm9_fp_dbl(t, t); + sm9_fp_add(k, k, t); + sm9_fp_inv(k, k); + + // r[0] = a[0] * k + sm9_fp_mul(r[0], a[0], k); + + // r[1] = -a[1] * k + sm9_fp_mul(r[1], a[1], k); + sm9_fp_neg(r[1], r[1]); + } +} + +void sm9_fp2_div(sm9_fp2_t r, const sm9_fp2_t a, const sm9_fp2_t b) +{ + sm9_fp2_t t; + sm9_fp2_inv(t, b); + sm9_fp2_mul(r, a, t); +} + +void sm9_fp2_div2(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp_div2(r[0], a[0]); + sm9_fp_div2(r[1], a[1]); +} + +int sm9_fp2_print(FILE *fp, int fmt, int ind, const char *label, const sm9_fp2_t a) +{ + return 1; +} + + +const sm9_fp4_t SM9_FP4_ZERO = {{{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}, {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}}; +const sm9_fp4_t SM9_FP4_ONE = {{{1,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}, {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}}; +const sm9_fp4_t SM9_FP4_U = {{{0,0,0,0,0,0,0,0},{1,0,0,0,0,0,0,0}}, {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}}; +const sm9_fp4_t SM9_FP4_V = {{{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}, {{1,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}}}; + +int sm9_fp4_equ(const sm9_fp4_t a, const sm9_fp4_t b) +{ + return (gmssl_secure_memcmp(a, b, sizeof(sm9_fp4_t)) == 0); +} + +int sm9_fp4_rand(sm9_fp4_t r) +{ + if (sm9_fp2_rand(r[1]) != 1 + || sm9_fp2_rand(r[0]) != 1) { + error_print(); + return -1; + } + return 1; +} + +void sm9_fp4_copy(sm9_fp4_t r, const sm9_fp4_t a) +{ + memcpy(r, a, sizeof(sm9_fp4_t)); +} + +void sm9_fp4_to_bytes(const sm9_fp4_t a, uint8_t buf[128]) +{ + sm9_fp2_to_bytes(a[1], buf); + sm9_fp2_to_bytes(a[0], buf + 64); +} + +int sm9_fp4_from_bytes(sm9_fp4_t r, const uint8_t buf[128]) +{ + if (sm9_fp2_from_bytes(r[1], buf) != 1 + || sm9_fp2_from_bytes(r[0], buf + 64) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_fp4_from_hex(sm9_fp4_t r, const char hex[65 * 4]) +{ + if (sm9_fp2_from_hex(r[1], hex) != 1 + || hex[129] != SM9_HEX_SEP + || sm9_fp2_from_hex(r[0], hex + 130) != 1) { + error_print(); + return -1; + } + return 1; +} + +void sm9_fp4_to_hex(const sm9_fp4_t a, char hex[259]) +{ + sm9_fp2_to_hex(a[1], hex); + hex[129] = SM9_HEX_SEP; + sm9_fp2_to_hex(a[0], hex + 130); +} + +void sm9_fp4_set_fp(sm9_fp4_t r, const sm9_fp_t a) +{ + sm9_fp2_set_fp(r[0], a); + sm9_fp2_set_zero(r[1]); +} + +void sm9_fp4_set_fp2(sm9_fp4_t r, const sm9_fp2_t a) +{ + sm9_fp2_copy(r[0], a); + sm9_fp2_set_zero(r[1]); +} + +void sm9_fp4_set(sm9_fp4_t r, const sm9_fp2_t a0, const sm9_fp2_t a1) +{ + sm9_fp2_copy(r[0], a0); + sm9_fp2_copy(r[1], a1); +} + +void sm9_fp4_set_u(sm9_fp4_t r) +{ + sm9_fp2_set_u(r[0]); + sm9_fp2_set_zero(r[1]); +} + +void sm9_fp4_set_v(sm9_fp4_t r) +{ + sm9_fp2_set_zero(r[0]); + sm9_fp2_set_one(r[1]); +} + +void sm9_fp4_add(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b) +{ + sm9_fp2_add(r[0], a[0], b[0]); + sm9_fp2_add(r[1], a[1], b[1]); +} + +void sm9_fp4_dbl(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_dbl(r[0], a[0]); + sm9_fp2_dbl(r[1], a[1]); +} + +void sm9_fp4_sub(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b) +{ + sm9_fp2_sub(r[0], a[0], b[0]); + sm9_fp2_sub(r[1], a[1], b[1]); +} + +void sm9_fp4_neg(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_neg(r[0], a[0]); + sm9_fp2_neg(r[1], a[1]); +} + +void sm9_fp4_mul(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b) +{ + sm9_fp2_t r0, r1, t; + + sm9_fp2_mul(r0, a[0], b[0]); + sm9_fp2_mul_u(t, a[1], b[1]); + sm9_fp2_add(r0, r0, t); + + sm9_fp2_mul(r1, a[0], b[1]); + sm9_fp2_mul(t, a[1], b[0]); + sm9_fp2_add(r1, r1, t); + + sm9_fp2_copy(r[0], r0); + sm9_fp2_copy(r[1], r1); +} + +void sm9_fp4_mul_fp(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp_t k) +{ + sm9_fp2_mul_fp(r[0], a[0], k); + sm9_fp2_mul_fp(r[1], a[1], k); +} + +void sm9_fp4_mul_fp2(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp2_t b0) +{ + sm9_fp2_mul(r[0], a[0], b0); + sm9_fp2_mul(r[1], a[1], b0); +} + +void sm9_fp4_mul_v(sm9_fp4_t r, const sm9_fp4_t a, const sm9_fp4_t b) +{ + sm9_fp2_t r0, r1, t; + + sm9_fp2_mul_u(r0, a[0], b[1]); + sm9_fp2_mul_u(t, a[1], b[0]); + sm9_fp2_add(r0, r0, t); + + sm9_fp2_mul(r1, a[0], b[0]); + sm9_fp2_mul_u(t, a[1], b[1]); + sm9_fp2_add(r1, r1, t); + + sm9_fp2_copy(r[0], r0); + sm9_fp2_copy(r[1], r1); +} + +void sm9_fp4_sqr(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_t r0, r1, t; + + sm9_fp2_sqr(r0, a[0]); + sm9_fp2_sqr_u(t, a[1]); + sm9_fp2_add(r0, r0, t); + + sm9_fp2_mul(r1, a[0], a[1]); + sm9_fp2_dbl(r1, r1); + sm9_fp2_copy(r[0], r0); + sm9_fp2_copy(r[1], r1); +} + +void sm9_fp4_sqr_v(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_t r0, r1, t; + + sm9_fp2_mul_u(t, a[0], a[1]); + sm9_fp2_dbl(r0, t); + + sm9_fp2_sqr(r1, a[0]); + sm9_fp2_sqr_u(t, a[1]); + sm9_fp2_add(r1, r1, t); + + sm9_fp2_copy(r[0], r0); + sm9_fp2_copy(r[1], r1); +} + +void sm9_fp4_inv(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_t r0, r1, k; + + sm9_fp2_sqr_u(k, a[1]); + sm9_fp2_sqr(r0, a[0]); + sm9_fp2_sub(k, k, r0); + sm9_fp2_inv(k, k); + + sm9_fp2_mul(r0, a[0], k); + sm9_fp2_neg(r0, r0); + + sm9_fp2_mul(r1, a[1], k); + + sm9_fp2_copy(r[0], r0); + sm9_fp2_copy(r[1], r1); +} + +void sm9_fp12_copy(sm9_fp12_t r, const sm9_fp12_t a) +{ + sm9_fp4_copy(r[0], a[0]); + sm9_fp4_copy(r[1], a[1]); + sm9_fp4_copy(r[2], a[2]); +} + +int sm9_fp12_rand(sm9_fp12_t r) +{ + if (sm9_fp4_rand(r[0]) != 1 + || sm9_fp4_rand(r[1]) != 1 + || sm9_fp4_rand(r[2]) != 1) { + error_print(); + return -1; + } + return 1; +} + +void sm9_fp12_set_zero(sm9_fp12_t r) +{ + sm9_fp4_set_zero(r[0]); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_zero(r[2]); +} + +void sm9_fp12_set_one(sm9_fp12_t r) +{ + sm9_fp4_set_one(r[0]); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_zero(r[2]); +} + +int sm9_fp12_is_one(const sm9_fp12_t a) +{ + return sm9_fp4_is_one(a[0]) + && sm9_fp4_is_zero(a[1]) + && sm9_fp4_is_zero(a[2]); +} + +int sm9_fp12_is_zero(const sm9_fp12_t a) +{ + return sm9_fp4_is_zero(a[0]) + && sm9_fp4_is_zero(a[1]) + && sm9_fp4_is_zero(a[2]); +} + +int sm9_fp12_from_hex(sm9_fp12_t r, const char hex[65 * 12 - 1]) +{ + if (sm9_fp4_from_hex(r[2], hex) != 1 + || hex[65 * 4 - 1] != SM9_HEX_SEP + || sm9_fp4_from_hex(r[1], hex + 65 * 4) != 1 + || hex[65 * 4 - 1] != SM9_HEX_SEP + || sm9_fp4_from_hex(r[0], hex + 65 * 8) != 1) { + error_print(); + return -1; + } + return 1; +} + +void sm9_fp12_to_hex(const sm9_fp12_t a, char hex[65 * 12 - 1]) +{ + sm9_fp4_to_hex(a[2], hex); + hex[65 * 4 - 1] = SM9_HEX_SEP; + sm9_fp4_to_hex(a[1], hex + 65 * 4); + hex[65 * 8 - 1] = SM9_HEX_SEP; + sm9_fp4_to_hex(a[0], hex + 65 * 8); +} + +void sm9_fp12_print(const char *prefix, const sm9_fp12_t a) +{ + char hex[65 * 12]; + sm9_fp12_to_hex(a, hex); + printf("%s\n%s\n", prefix, hex); +} + +void sm9_fp12_set(sm9_fp12_t r, const sm9_fp4_t a0, const sm9_fp4_t a1, const sm9_fp4_t a2) +{ + sm9_fp4_copy(r[0], a0); + sm9_fp4_copy(r[1], a1); + sm9_fp4_copy(r[2], a2); +} + +void sm9_fp12_set_fp(sm9_fp12_t r, const sm9_fp_t a) +{ + sm9_fp4_set_fp(r[0], a); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_zero(r[2]); +} + +void sm9_fp12_set_fp2(sm9_fp12_t r, const sm9_fp2_t a) +{ + sm9_fp4_set_fp2(r[0], a); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_zero(r[2]); +} + +void sm9_fp12_set_fp4(sm9_fp12_t r, const sm9_fp4_t a) +{ + sm9_fp4_copy(r[0], a); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_zero(r[2]); +} + +void sm9_fp12_set_u(sm9_fp12_t r) +{ + sm9_fp4_set_u(r[0]); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_zero(r[2]); +} + +void sm9_fp12_set_v(sm9_fp12_t r) +{ + sm9_fp4_set_v(r[0]); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_zero(r[2]); +} + +void sm9_fp12_set_w(sm9_fp12_t r) +{ + sm9_fp4_set_zero(r[0]); + sm9_fp4_set_one(r[1]); + sm9_fp4_set_zero(r[2]); +} + +void sm9_fp12_set_w_sqr(sm9_fp12_t r) +{ + sm9_fp4_set_zero(r[0]); + sm9_fp4_set_zero(r[1]); + sm9_fp4_set_one(r[2]); +} + +int sm9_fp12_equ(const sm9_fp12_t a, const sm9_fp12_t b) +{ + return sm9_fp4_equ(a[0], b[0]) + && sm9_fp4_equ(a[1], b[1]) + && sm9_fp4_equ(a[2], b[2]); +} + +void sm9_fp12_add(sm9_fp12_t r, const sm9_fp12_t a, const sm9_fp12_t b) +{ + sm9_fp4_add(r[0], a[0], b[0]); + sm9_fp4_add(r[1], a[1], b[1]); + sm9_fp4_add(r[2], a[2], b[2]); +} + +void sm9_fp12_dbl(sm9_fp12_t r, const sm9_fp12_t a) +{ + sm9_fp4_dbl(r[0], a[0]); + sm9_fp4_dbl(r[1], a[1]); + sm9_fp4_dbl(r[2], a[2]); +} + +void sm9_fp12_tri(sm9_fp12_t r, const sm9_fp12_t a) +{ + sm9_fp12_t t; + sm9_fp12_dbl(t, a); + sm9_fp12_add(r, t, a); +} + +void sm9_fp12_sub(sm9_fp12_t r, const sm9_fp12_t a, const sm9_fp12_t b) +{ + sm9_fp4_sub(r[0], a[0], b[0]); + sm9_fp4_sub(r[1], a[1], b[1]); + sm9_fp4_sub(r[2], a[2], b[2]); +} + +void sm9_fp12_neg(sm9_fp12_t r, const sm9_fp12_t a) +{ + sm9_fp4_neg(r[0], a[0]); + sm9_fp4_neg(r[1], a[1]); + sm9_fp4_neg(r[2], a[2]); +} + +void sm9_fp12_mul(sm9_fp12_t r, const sm9_fp12_t a, const sm9_fp12_t b) +{ + sm9_fp4_t r0, r1, r2, t; + + sm9_fp4_mul(r0, a[0], b[0]); + sm9_fp4_mul_v(t, a[1], b[2]); + sm9_fp4_add(r0, r0, t); + sm9_fp4_mul_v(t, a[2], b[1]); + sm9_fp4_add(r0, r0, t); + + sm9_fp4_mul(r1, a[0], b[1]); + sm9_fp4_mul(t, a[1], b[0]); + sm9_fp4_add(r1, r1, t); + sm9_fp4_mul_v(t, a[2], b[2]); + sm9_fp4_add(r1, r1, t); + + sm9_fp4_mul(r2, a[0], b[2]); + sm9_fp4_mul(t, a[1], b[1]); + sm9_fp4_add(r2, r2, t); + sm9_fp4_mul(t, a[2], b[0]); + sm9_fp4_add(r2, r2, t); + + sm9_fp4_copy(r[0], r0); + sm9_fp4_copy(r[1], r1); + sm9_fp4_copy(r[2], r2); +} + +// void sm9_fp12_sqr(sm9_fp12_t r, const sm9_fp12_t a) +// { +// sm9_fp4_t r0, r1, r2, t; + +// sm9_fp4_sqr(r0, a[0]); +// sm9_fp4_mul_v(t, a[1], a[2]); +// sm9_fp4_dbl(t, t); +// sm9_fp4_add(r0, r0, t); + +// sm9_fp4_mul(r1, a[0], a[1]); +// sm9_fp4_dbl(r1, r1); +// sm9_fp4_sqr_v(t, a[2]); +// sm9_fp4_add(r1, r1, t); + +// sm9_fp4_mul(r2, a[0], a[2]); +// sm9_fp4_dbl(r2, r2); +// sm9_fp4_sqr(t, a[1]); +// sm9_fp4_add(r2, r2, t); + +// sm9_fp4_copy(r[0], r0); +// sm9_fp4_copy(r[1], r1); +// sm9_fp4_copy(r[2], r2); +// } + +void sm9_fp4_div2(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_div2(r[0], a[0]); + sm9_fp2_div2(r[1], a[1]); +} + +void sm9_fp2_a_mul_u(sm9_fp2_t r, sm9_fp2_t a) { + sm9_fp_t r0, a0, a1; + + sm9_fp_copy(a0, a[0]); + sm9_fp_copy(a1, a[1]); + + //r0 = -2 * a1 + sm9_fp_dbl(r0, a1); + sm9_fp_neg(r0, r0); + sm9_fp_copy(r[0], r0); + + //r1 = a0 + sm9_fp_copy(r[1], a0); +} + +void sm9_fp4_a_mul_v(sm9_fp4_t r, sm9_fp4_t a) { + sm9_fp2_t r0, a0, a1; + + sm9_fp2_copy(a0, a[0]); + sm9_fp2_copy(a1, a[1]); + + //r0 = a1 * u + sm9_fp2_a_mul_u(r0, a1); + sm9_fp2_copy(r[0], r0); + + //r1 = a0 + sm9_fp2_copy(r[1], a0); +} + +void sm9_fp12_sqr(sm9_fp12_t r, const sm9_fp12_t a) +{ + sm9_fp4_t h0, h1, h2, t; + sm9_fp4_t s0, s1, s2, s3; + + sm9_fp4_sqr(h0, a[0]); + sm9_fp4_sqr(h1, a[2]); + sm9_fp4_add(s0, a[2], a[0]); + + sm9_fp4_sub(t, s0, a[1]); + sm9_fp4_sqr(s1, t); + + sm9_fp4_add(t, s0, a[1]); + sm9_fp4_sqr(s0, t); + + sm9_fp4_mul(s2, a[1], a[2]); + sm9_fp4_dbl(s2, s2); + + sm9_fp4_add(s3, s0, s1); + sm9_fp4_div2(s3, s3); + + sm9_fp4_sub(t, s3, h1); + sm9_fp4_sub(h2, t, h0); + + sm9_fp4_a_mul_v(h1, h1); + sm9_fp4_add(h1, h1, s0); + sm9_fp4_sub(h1, h1, s2); + sm9_fp4_sub(h1, h1, s3); + + sm9_fp4_a_mul_v(s2, s2); + sm9_fp4_add(h0, h0, s2); + + sm9_fp4_copy(r[0], h0); + sm9_fp4_copy(r[1], h1); + sm9_fp4_copy(r[2], h2); +} + +void sm9_fp12_inv(sm9_fp12_t r, const sm9_fp12_t a) +{ + if (sm9_fp4_is_zero(a[2])) { + sm9_fp4_t k, t; + + sm9_fp4_sqr(k, a[0]); + sm9_fp4_mul(k, k, a[0]); + sm9_fp4_sqr_v(t, a[1]); + sm9_fp4_mul(t, t, a[1]); + sm9_fp4_add(k, k, t); + sm9_fp4_inv(k, k); + + sm9_fp4_sqr(r[2], a[1]); + sm9_fp4_mul(r[2], r[2], k); + + sm9_fp4_mul(r[1], a[0], a[1]); + sm9_fp4_mul(r[1], r[1], k); + sm9_fp4_neg(r[1], r[1]); + + sm9_fp4_sqr(r[0], a[0]); + sm9_fp4_mul(r[0], r[0], k); + + } else { + sm9_fp4_t t0, t1, t2, t3; + + sm9_fp4_sqr(t0, a[1]); + sm9_fp4_mul(t1, a[0], a[2]); + sm9_fp4_sub(t0, t0, t1); + + sm9_fp4_mul(t1, a[0], a[1]); + sm9_fp4_sqr_v(t2, a[2]); + sm9_fp4_sub(t1, t1, t2); + + sm9_fp4_sqr(t2, a[0]); + sm9_fp4_mul_v(t3, a[1], a[2]); + sm9_fp4_sub(t2, t2, t3); + + sm9_fp4_sqr(t3, t1); + sm9_fp4_mul(r[0], t0, t2); + sm9_fp4_sub(t3, t3, r[0]); + sm9_fp4_inv(t3, t3); + sm9_fp4_mul(t3, a[2], t3); + + sm9_fp4_mul(r[0], t2, t3); + + sm9_fp4_mul(r[1], t1, t3); + sm9_fp4_neg(r[1], r[1]); + + sm9_fp4_mul(r[2], t0, t3); + } +} + +void sm9_fp12_pow(sm9_fp12_t r, const sm9_fp12_t a, const sm9_bn_t k) +{ + char kbits[257]; + sm9_fp12_t t; + int i; + + assert(sm9_bn_cmp(k, SM9_P_MINUS_ONE) < 0); + sm9_fp12_set_zero(t); + + sm9_bn_to_bits(k, kbits); + sm9_fp12_set_one(t); + for (i = 0; i < 256; i++) { + sm9_fp12_sqr(t, t); + if (kbits[i] == '1') { + sm9_fp12_mul(t, t, a); + } + } + sm9_fp12_copy(r, t); +} + +void sm9_fp2_conjugate(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp_copy(r[0], a[0]); + sm9_fp_neg (r[1], a[1]); + +} + +void sm9_fp2_frobenius(sm9_fp2_t r, const sm9_fp2_t a) +{ + sm9_fp2_conjugate(r, a); +} + +// beta = 0x6c648de5dc0a3f2cf55acc93ee0baf159f9d411806dc5177f5b21fd3da24d011 +// alpha1 = 0x3f23ea58e5720bdb843c6cfa9c08674947c5c86e0ddd04eda91d8354377b698b +// alpha2 = 0xf300000002a3a6f2780272354f8b78f4d5fc11967be65334 +// alpha3 = 0x6c648de5dc0a3f2cf55acc93ee0baf159f9d411806dc5177f5b21fd3da24d011 +// alpha4 = 0xf300000002a3a6f2780272354f8b78f4d5fc11967be65333 +// alpha5 = 0x2d40a38cf6983351711e5f99520347cc57d778a9f8ff4c8a4c949c7fa2a96686 +static const sm9_fp2_t SM9_BETA = {{0xda24d011, 0xf5b21fd3, 0x06dc5177, 0x9f9d4118, 0xee0baf15, 0xf55acc93, 0xdc0a3f2c, 0x6c648de5}, {0}}; +static const sm9_fp_t SM9_ALPHA1 = {0x377b698b, 0xa91d8354, 0x0ddd04ed, 0x47c5c86e, 0x9c086749, 0x843c6cfa, 0xe5720bdb, 0x3f23ea58}; +static const sm9_fp_t SM9_ALPHA2 = {0x7be65334, 0xd5fc1196, 0x4f8b78f4, 0x78027235, 0x02a3a6f2, 0xf3000000, 0x0, 0x0 }; +static const sm9_fp_t SM9_ALPHA3 = {0xda24d011, 0xf5b21fd3, 0x06dc5177, 0x9f9d4118, 0xee0baf15, 0xf55acc93, 0xdc0a3f2c, 0x6c648de5}; +static const sm9_fp_t SM9_ALPHA4 = {0x7be65333, 0xd5fc1196, 0x4f8b78f4, 0x78027235, 0x02a3a6f2, 0xf3000000, 0x0, 0x0 }; +static const sm9_fp_t SM9_ALPHA5 = {0xa2a96686, 0x4c949c7f, 0xf8ff4c8a, 0x57d778a9, 0x520347cc, 0x711e5f99, 0xf6983351, 0x2d40a38c}; + + +void sm9_fp4_frobenius(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_conjugate(r[0], a[0]); + sm9_fp2_conjugate(r[1], a[1]); + sm9_fp2_mul(r[1], r[1], SM9_BETA); +} + +void sm9_fp4_conjugate(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_copy(r[0], a[0]); + sm9_fp2_neg(r[1], a[1]); +} + +void sm9_fp4_frobenius2(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp4_conjugate(r, a); +} + +void sm9_fp4_frobenius3(sm9_fp4_t r, const sm9_fp4_t a) +{ + sm9_fp2_conjugate(r[0], a[0]); + sm9_fp2_conjugate(r[1], a[1]); + sm9_fp2_mul(r[1], r[1], SM9_BETA); + sm9_fp2_neg(r[1], r[1]); +} + +void sm9_fp12_frobenius(sm9_fp12_t r, const sm9_fp12_t x) +{ + const sm9_fp2_t *xa = x[0]; + const sm9_fp2_t *xb = x[1]; + const sm9_fp2_t *xc = x[2]; + sm9_fp4_t ra; + sm9_fp4_t rb; + sm9_fp4_t rc; + + sm9_fp2_conjugate(ra[0], xa[0]); + sm9_fp2_conjugate(ra[1], xa[1]); + sm9_fp2_mul_fp(ra[1], ra[1], SM9_ALPHA3); + + sm9_fp2_conjugate(rb[0], xb[0]); + sm9_fp2_mul_fp(rb[0], rb[0], SM9_ALPHA1); + sm9_fp2_conjugate(rb[1], xb[1]); + sm9_fp2_mul_fp(rb[1], rb[1], SM9_ALPHA4); + + sm9_fp2_conjugate(rc[0], xc[0]); + sm9_fp2_mul_fp(rc[0], rc[0], SM9_ALPHA2); + sm9_fp2_conjugate(rc[1], xc[1]); + sm9_fp2_mul_fp(rc[1], rc[1], SM9_ALPHA5); + + sm9_fp12_set(r, ra, rb, rc); +} + +void sm9_fp12_frobenius2(sm9_fp12_t r, const sm9_fp12_t x) +{ + sm9_fp4_t a; + sm9_fp4_t b; + sm9_fp4_t c; + + sm9_fp4_conjugate(a, x[0]); + sm9_fp4_conjugate(b, x[1]); + sm9_fp4_mul_fp(b, b, SM9_ALPHA2); + sm9_fp4_conjugate(c, x[2]); + sm9_fp4_mul_fp(c, c, SM9_ALPHA4); + + sm9_fp4_copy(r[0], a); + sm9_fp4_copy(r[1], b); + sm9_fp4_copy(r[2], c); +} + +void sm9_fp12_frobenius3(sm9_fp12_t r, const sm9_fp12_t x) +{ + const sm9_fp2_t *xa = x[0]; + const sm9_fp2_t *xb = x[1]; + const sm9_fp2_t *xc = x[2]; + sm9_fp4_t ra; + sm9_fp4_t rb; + sm9_fp4_t rc; + + sm9_fp2_conjugate(ra[0], xa[0]); + sm9_fp2_conjugate(ra[1], xa[1]); + sm9_fp2_mul(ra[1], ra[1], SM9_BETA); + sm9_fp2_neg(ra[1], ra[1]); + + sm9_fp2_conjugate(rb[0], xb[0]); + sm9_fp2_mul(rb[0], rb[0], SM9_BETA); + sm9_fp2_conjugate(rb[1], xb[1]); + + sm9_fp2_conjugate(rc[0], xc[0]); + sm9_fp2_neg(rc[0], rc[0]); + sm9_fp2_conjugate(rc[1], xc[1]); + sm9_fp2_mul(rc[1], rc[1], SM9_BETA); + + sm9_fp4_copy(r[0], ra); + sm9_fp4_copy(r[1], rb); + sm9_fp4_copy(r[2], rc); +} + +void sm9_fp12_frobenius6(sm9_fp12_t r, const sm9_fp12_t x) +{ + sm9_fp4_t a; + sm9_fp4_t b; + sm9_fp4_t c; + + sm9_fp4_copy(a, x[0]); + sm9_fp4_copy(b, x[1]); + sm9_fp4_copy(c, x[2]); + + sm9_fp4_conjugate(a, a); + sm9_fp4_conjugate(b, b); + sm9_fp4_neg(b, b); + sm9_fp4_conjugate(c, c); + + sm9_fp4_copy(r[0], a); + sm9_fp4_copy(r[1], b); + sm9_fp4_copy(r[2], c); +} + + + +void sm9_point_from_hex(SM9_POINT *R, const char hex[65 * 2]) +{ + sm9_bn_from_hex(R->X, hex); + sm9_bn_from_hex(R->Y, hex + 65); + sm9_bn_set_one(R->Z); +} + +int sm9_point_is_at_infinity(const SM9_POINT *P) { + return sm9_fp_is_zero(P->Z); +} + +void sm9_point_set_infinity(SM9_POINT *R) { + sm9_fp_set_one(R->X); + sm9_fp_set_one(R->Y); + sm9_fp_set_zero(R->Z); +} + +void sm9_point_copy(SM9_POINT *R, const SM9_POINT *P) +{ + *R = *P; +} + +void sm9_point_get_xy(const SM9_POINT *P, sm9_fp_t x, sm9_fp_t y) +{ + sm9_fp_t z_inv; + + assert(!sm9_fp_is_zero(P->Z)); + + if (sm9_fp_is_one(P->Z)) { + sm9_fp_copy(x, P->X); + sm9_fp_copy(y, P->Y); + } + + sm9_fp_inv(z_inv, P->Z); + if (y) + sm9_fp_mul(y, P->Y, z_inv); + sm9_fp_sqr(z_inv, z_inv); + sm9_fp_mul(x, P->X, z_inv); + if (y) + sm9_fp_mul(y, y, z_inv); +} + +int sm9_point_equ(const SM9_POINT *P, const SM9_POINT *Q) +{ + sm9_fp_t t1, t2, t3, t4; + sm9_fp_sqr(t1, P->Z); + sm9_fp_sqr(t2, Q->Z); + sm9_fp_mul(t3, P->X, t2); + sm9_fp_mul(t4, Q->X, t1); + if (!sm9_fp_equ(t3, t4)) { + return 0; + } + sm9_fp_mul(t1, t1, P->Z); + sm9_fp_mul(t2, t2, Q->Z); + sm9_fp_mul(t3, P->Y, t2); + sm9_fp_mul(t4, Q->Y, t1); + return sm9_fp_equ(t3, t4); +} + +int sm9_point_is_on_curve(const SM9_POINT *P) +{ + sm9_fp_t t0, t1, t2; + if (sm9_fp_is_one(P->Z)) { + sm9_fp_sqr(t0, P->Y); + sm9_fp_sqr(t1, P->X); + sm9_fp_mul(t1, t1, P->X); + sm9_fp_add(t1, t1, SM9_FIVE); + } else { + sm9_fp_sqr(t0, P->X); + sm9_fp_mul(t0, t0, P->X); + sm9_fp_sqr(t1, P->Z); + sm9_fp_sqr(t2, t1); + sm9_fp_mul(t1, t1, t2); + sm9_fp_mul(t1, t1, SM9_FIVE); + sm9_fp_add(t1, t0, t1); + sm9_fp_sqr(t0, P->Y); + } + if (sm9_fp_equ(t0, t1) != 1) { + error_print(); + return 0; + } + return 1; +} + +void sm9_point_dbl(SM9_POINT *R, const SM9_POINT *P) +{ + const uint64_t *X1 = P->X; + const uint64_t *Y1 = P->Y; + const uint64_t *Z1 = P->Z; + sm9_fp_t X3, Y3, Z3, T1, T2, T3; + + if (sm9_point_is_at_infinity(P)) { + sm9_point_copy(R, P); + return; + } + + sm9_fp_sqr(T2, X1); + sm9_fp_tri(T2, T2); + sm9_fp_dbl(Y3, Y1); + sm9_fp_mul(Z3, Y3, Z1); + sm9_fp_sqr(Y3, Y3); + sm9_fp_mul(T3, Y3, X1); + sm9_fp_sqr(Y3, Y3); + sm9_fp_div2(Y3, Y3); + sm9_fp_sqr(X3, T2); + sm9_fp_dbl(T1, T3); + sm9_fp_sub(X3, X3, T1); + sm9_fp_sub(T1, T3, X3); + sm9_fp_mul(T1, T1, T2); + sm9_fp_sub(Y3, T1, Y3); + + sm9_fp_copy(R->X, X3); + sm9_fp_copy(R->Y, Y3); + sm9_fp_copy(R->Z, Z3); +} + +void sm9_point_add(SM9_POINT *R, const SM9_POINT *P, const SM9_POINT *Q) +{ + sm9_fp_t x; + sm9_fp_t y; + sm9_point_get_xy(Q, x, y); + + const uint64_t *X1 = P->X; + const uint64_t *Y1 = P->Y; + const uint64_t *Z1 = P->Z; + const uint64_t *x2 = x; + const uint64_t *y2 = y; + sm9_fp_t X3, Y3, Z3, T1, T2, T3, T4; + + if (sm9_point_is_at_infinity(Q)) { + sm9_point_copy(R, P); + return; + } + if (sm9_point_is_at_infinity(P)) { + sm9_point_copy(R, Q); + return; + } + + sm9_fp_sqr(T1, Z1); + sm9_fp_mul(T2, T1, Z1); + sm9_fp_mul(T1, T1, x2); + sm9_fp_mul(T2, T2, y2); + sm9_fp_sub(T1, T1, X1); + sm9_fp_sub(T2, T2, Y1); + + if (sm9_fp_is_zero(T1)) { + if (sm9_fp_is_zero(T2)) { + sm9_point_dbl(R, Q); + return; + } else { + sm9_point_set_infinity(R); + return; + } + } + + sm9_fp_mul(Z3, Z1, T1); + sm9_fp_sqr(T3, T1); + sm9_fp_mul(T4, T3, T1); + sm9_fp_mul(T3, T3, X1); + sm9_fp_dbl(T1, T3); + sm9_fp_sqr(X3, T2); + sm9_fp_sub(X3, X3, T1); + sm9_fp_sub(X3, X3, T4); + sm9_fp_sub(T3, T3, X3); + sm9_fp_mul(T3, T3, T2); + sm9_fp_mul(T4, T4, Y1); + sm9_fp_sub(Y3, T3, T4); + + sm9_fp_copy(R->X, X3); + sm9_fp_copy(R->Y, Y3); + sm9_fp_copy(R->Z, Z3); +} + +void sm9_point_neg(SM9_POINT *R, const SM9_POINT *P) +{ + sm9_fp_copy(R->X, P->X); + sm9_fp_neg(R->Y, P->Y); + sm9_fp_copy(R->Z, P->Z); +} + +void sm9_point_sub(SM9_POINT *R, const SM9_POINT *P, const SM9_POINT *Q) +{ + SM9_POINT _T, *T = &_T; + sm9_point_neg(T, Q); + sm9_point_add(R, P, T); +} + +void sm9_point_mul(SM9_POINT *R, const sm9_bn_t k, const SM9_POINT *P) +{ + char kbits[257]; + SM9_POINT _Q, *Q = &_Q; + int i; + + sm9_bn_to_bits(k, kbits); + sm9_point_set_infinity(Q); + for (i = 0; i < 256; i++) { + sm9_point_dbl(Q, Q); + if (kbits[i] == '1') { + sm9_point_add(Q, Q, P); + } + } + sm9_point_copy(R, Q); +} + +void sm9_point_mul_generator(SM9_POINT *R, const sm9_bn_t k) +{ + sm9_point_mul(R, k, SM9_P1); +} + + +int sm9_point_print(FILE *fp, int fmt, int ind, const char *label, const SM9_POINT *P) +{ + uint8_t buf[65]; + sm9_point_to_uncompressed_octets(P, buf); + format_bytes(fp, fmt, ind, label, buf, sizeof(buf)); + return 1; +} + +int sm9_twist_point_print(FILE *fp, int fmt, int ind, const char *label, const SM9_TWIST_POINT *P) +{ + uint8_t buf[129]; + sm9_twist_point_to_uncompressed_octets(P, buf); + format_bytes(fp, fmt, ind, label, buf, sizeof(buf)); + return 1; +} + +void sm9_twist_point_from_hex(SM9_TWIST_POINT *R, const char hex[65 * 4]) +{ + sm9_fp2_from_hex(R->X, hex); + sm9_fp2_from_hex(R->Y, hex + 65 * 2); + sm9_fp2_set_one(R->Z); +} + +int sm9_twist_point_is_at_infinity(const SM9_TWIST_POINT *P) +{ + return sm9_fp2_is_zero(P->Z); +} + +void sm9_twist_point_set_infinity(SM9_TWIST_POINT *R) +{ + sm9_fp2_set_one(R->X); + sm9_fp2_set_one(R->Y); + sm9_fp2_set_zero(R->Z); +} + +void sm9_twist_point_get_xy(const SM9_TWIST_POINT *P, sm9_fp2_t x, sm9_fp2_t y) +{ + sm9_fp2_t z_inv; + + assert(!sm9_fp2_is_zero(P->Z)); + + if (sm9_fp2_is_one(P->Z)) { + sm9_fp2_copy(x, P->X); + sm9_fp2_copy(y, P->Y); + } + + sm9_fp2_inv(z_inv, P->Z); + if (y) + sm9_fp2_mul(y, P->Y, z_inv); + sm9_fp2_sqr(z_inv, z_inv); + sm9_fp2_mul(x, P->X, z_inv); + if (y) + sm9_fp2_mul(y, y, z_inv); +} + + +int sm9_twist_point_equ(const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q) +{ + sm9_fp2_t t1, t2, t3, t4; + + sm9_fp2_sqr(t1, P->Z); + sm9_fp2_sqr(t2, Q->Z); + sm9_fp2_mul(t3, P->X, t2); + sm9_fp2_mul(t4, Q->X, t1); + if (!sm9_fp2_equ(t3, t4)) { + return 0; + } + sm9_fp2_mul(t1, t1, P->Z); + sm9_fp2_mul(t2, t2, Q->Z); + sm9_fp2_mul(t3, P->Y, t2); + sm9_fp2_mul(t4, Q->Y, t1); + return sm9_fp2_equ(t3, t4); +} + +int sm9_twist_point_is_on_curve(const SM9_TWIST_POINT *P) +{ + sm9_fp2_t t0, t1, t2; + + if (sm9_fp2_is_one(P->Z)) { + sm9_fp2_sqr(t0, P->Y); + sm9_fp2_sqr(t1, P->X); + sm9_fp2_mul(t1, t1, P->X); + sm9_fp2_add(t1, t1, SM9_FP2_5U); + + } else { + sm9_fp2_sqr(t0, P->X); + sm9_fp2_mul(t0, t0, P->X); + sm9_fp2_sqr(t1, P->Z); + sm9_fp2_sqr(t2, t1); + sm9_fp2_mul(t1, t1, t2); + sm9_fp2_mul(t1, t1, SM9_FP2_5U); + sm9_fp2_add(t1, t0, t1); + sm9_fp2_sqr(t0, P->Y); + } + + return sm9_fp2_equ(t0, t1); +} + +void sm9_twist_point_neg(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P) +{ + sm9_fp2_copy(R->X, P->X); + sm9_fp2_neg(R->Y, P->Y); + sm9_fp2_copy(R->Z, P->Z); +} + +void sm9_twist_point_dbl(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P) +{ + const sm9_fp_t *X1 = P->X; + const sm9_fp_t *Y1 = P->Y; + const sm9_fp_t *Z1 = P->Z; + sm9_fp2_t X3, Y3, Z3, T1, T2, T3; + + if (sm9_twist_point_is_at_infinity(P)) { + sm9_twist_point_copy(R, P); + return; + } + sm9_fp2_sqr(T2, X1); + sm9_fp2_tri(T2, T2); + sm9_fp2_dbl(Y3, Y1); + sm9_fp2_mul(Z3, Y3, Z1); + sm9_fp2_sqr(Y3, Y3); + sm9_fp2_mul(T3, Y3, X1); + sm9_fp2_sqr(Y3, Y3); + sm9_fp2_div2(Y3, Y3); + sm9_fp2_sqr(X3, T2); + sm9_fp2_dbl(T1, T3); + sm9_fp2_sub(X3, X3, T1); + sm9_fp2_sub(T1, T3, X3); + sm9_fp2_mul(T1, T1, T2); + sm9_fp2_sub(Y3, T1, Y3); + + sm9_fp2_copy(R->X, X3); + sm9_fp2_copy(R->Y, Y3); + sm9_fp2_copy(R->Z, Z3); +} + +void sm9_twist_point_add(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q) +{ + const sm9_fp_t *X1 = P->X; + const sm9_fp_t *Y1 = P->Y; + const sm9_fp_t *Z1 = P->Z; + const sm9_fp_t *x2 = Q->X; + const sm9_fp_t *y2 = Q->Y; + sm9_fp2_t X3, Y3, Z3, T1, T2, T3, T4; + + if (sm9_twist_point_is_at_infinity(Q)) { + sm9_twist_point_copy(R, P); + return; + } + if (sm9_twist_point_is_at_infinity(P)) { + sm9_twist_point_copy(R, Q); + return; + } + + sm9_fp2_sqr(T1, Z1); + sm9_fp2_mul(T2, T1, Z1); + sm9_fp2_mul(T1, T1, x2); + sm9_fp2_mul(T2, T2, y2); + sm9_fp2_sub(T1, T1, X1); + sm9_fp2_sub(T2, T2, Y1); + if (sm9_fp2_is_zero(T1)) { + if (sm9_fp2_is_zero(T2)) { + sm9_twist_point_dbl(R, Q); + return; + } else { + sm9_twist_point_set_infinity(R); + return; + } + } + sm9_fp2_mul(Z3, Z1, T1); + sm9_fp2_sqr(T3, T1); + sm9_fp2_mul(T4, T3, T1); + sm9_fp2_mul(T3, T3, X1); + sm9_fp2_dbl(T1, T3); + sm9_fp2_sqr(X3, T2); + sm9_fp2_sub(X3, X3, T1); + sm9_fp2_sub(X3, X3, T4); + sm9_fp2_sub(T3, T3, X3); + sm9_fp2_mul(T3, T3, T2); + sm9_fp2_mul(T4, T4, Y1); + sm9_fp2_sub(Y3, T3, T4); + + sm9_fp2_copy(R->X, X3); + sm9_fp2_copy(R->Y, Y3); + sm9_fp2_copy(R->Z, Z3); +} + +void sm9_twist_point_sub(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q) +{ + SM9_TWIST_POINT _T, *T = &_T; + sm9_twist_point_neg(T, Q); + sm9_twist_point_add_full(R, P, T); +} + +void sm9_twist_point_add_full(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P, const SM9_TWIST_POINT *Q) +{ + const sm9_fp_t *X1 = P->X; + const sm9_fp_t *Y1 = P->Y; + const sm9_fp_t *Z1 = P->Z; + const sm9_fp_t *X2 = Q->X; + const sm9_fp_t *Y2 = Q->Y; + const sm9_fp_t *Z2 = Q->Z; + sm9_fp2_t T1, T2, T3, T4, T5, T6, T7, T8; + + if (sm9_twist_point_is_at_infinity(Q)) { + sm9_twist_point_copy(R, P); + return; + } + if (sm9_twist_point_is_at_infinity(P)) { + sm9_twist_point_copy(R, Q); + return; + } + + sm9_fp2_sqr(T1, Z1); + sm9_fp2_sqr(T2, Z2); + sm9_fp2_mul(T3, X2, T1); + sm9_fp2_mul(T4, X1, T2); + sm9_fp2_add(T5, T3, T4); + sm9_fp2_sub(T3, T3, T4); + sm9_fp2_mul(T1, T1, Z1); + sm9_fp2_mul(T1, T1, Y2); + sm9_fp2_mul(T2, T2, Z2); + sm9_fp2_mul(T2, T2, Y1); + sm9_fp2_add(T6, T1, T2); + sm9_fp2_sub(T1, T1, T2); + + if (sm9_fp2_is_zero(T1) && sm9_fp2_is_zero(T3)) { + sm9_twist_point_dbl(R, P); + return; + } + if (sm9_fp2_is_zero(T1) && sm9_fp2_is_zero(T6)) { + sm9_twist_point_set_infinity(R); + return; + } + + sm9_fp2_sqr(T6, T1); + sm9_fp2_mul(T7, T3, Z1); + sm9_fp2_mul(T7, T7, Z2); + sm9_fp2_sqr(T8, T3); + sm9_fp2_mul(T5, T5, T8); + sm9_fp2_mul(T3, T3, T8); + sm9_fp2_mul(T4, T4, T8); + sm9_fp2_sub(T6, T6, T5); + sm9_fp2_sub(T4, T4, T6); + sm9_fp2_mul(T1, T1, T4); + sm9_fp2_mul(T2, T2, T3); + sm9_fp2_sub(T1, T1, T2); + + sm9_fp2_copy(R->X, T6); + sm9_fp2_copy(R->Y, T1); + sm9_fp2_copy(R->Z, T7); +} + +void sm9_twist_point_mul(SM9_TWIST_POINT *R, const sm9_bn_t k, const SM9_TWIST_POINT *P) +{ + SM9_TWIST_POINT _Q, *Q = &_Q; + char kbits[256]; + int i; + + sm9_bn_to_bits(k, kbits); + sm9_twist_point_set_infinity(Q); + for (i = 0; i < 256; i++) { + sm9_twist_point_dbl(Q, Q); + if (kbits[i] == '1') { + sm9_twist_point_add_full(Q, Q, P); + } + } + sm9_twist_point_copy(R, Q); +} + +void sm9_twist_point_mul_generator(SM9_TWIST_POINT *R, const sm9_bn_t k) +{ + sm9_twist_point_mul(R, k, SM9_P2); +} + +void sm9_eval_g_tangent(sm9_fp12_t num, sm9_fp12_t den, const SM9_TWIST_POINT *P, const SM9_POINT *Q) +{ + sm9_fp_t x; + sm9_fp_t y; + sm9_point_get_xy(Q, x, y); + + const sm9_fp_t *XP = P->X; + const sm9_fp_t *YP = P->Y; + const sm9_fp_t *ZP = P->Z; + const uint64_t *xQ = x; + const uint64_t *yQ = y; + + sm9_fp_t *a0 = num[0][0]; + sm9_fp_t *a1 = num[0][1]; + sm9_fp_t *a4 = num[2][0]; + sm9_fp_t *b1 = den[0][1]; + + sm9_fp2_t t0; + sm9_fp2_t t1; + sm9_fp2_t t2; + + + sm9_fp12_set_zero(num); + sm9_fp12_set_zero(den); + + sm9_fp2_sqr(t0, ZP); + sm9_fp2_mul(t1, t0, ZP); + sm9_fp2_mul(b1, t1, YP); + + sm9_fp2_mul_fp(t2, b1, yQ); + sm9_fp2_neg(a1, t2); + + sm9_fp2_sqr(t1, XP); + sm9_fp2_mul(t0, t0, t1); + sm9_fp2_mul_fp(t0, t0, xQ); + sm9_fp2_tri(t0, t0); + sm9_fp2_div2(a4, t0); + + sm9_fp2_mul(t1, t1, XP); + sm9_fp2_tri(t1, t1); + sm9_fp2_div2(t1, t1); + sm9_fp2_sqr(t0, YP); + sm9_fp2_sub(a0, t0, t1); +} + +void sm9_eval_g_line(sm9_fp12_t num, sm9_fp12_t den, const SM9_TWIST_POINT *T, const SM9_TWIST_POINT *P, const SM9_POINT *Q) +{ + sm9_fp_t x; + sm9_fp_t y; + sm9_point_get_xy(Q, x, y); + + const sm9_fp_t *XT = T->X; + const sm9_fp_t *YT = T->Y; + const sm9_fp_t *ZT = T->Z; + const sm9_fp_t *XP = P->X; + const sm9_fp_t *YP = P->Y; + const sm9_fp_t *ZP = P->Z; + const uint64_t *xQ = x; + const uint64_t *yQ = y; + + sm9_fp_t *a0 = num[0][0]; + sm9_fp_t *a1 = num[0][1]; + sm9_fp_t *a4 = num[2][0]; + sm9_fp_t *b1 = den[0][1]; + + sm9_fp2_t T0, T1, T2, T3, T4; + + + sm9_fp12_set_zero(num); + sm9_fp12_set_zero(den); + + sm9_fp2_sqr(T0, ZP); + sm9_fp2_mul(T1, T0, XT); + sm9_fp2_mul(T0, T0, ZP); + sm9_fp2_sqr(T2, ZT); + sm9_fp2_mul(T3, T2, XP); + sm9_fp2_mul(T2, T2, ZT); + sm9_fp2_mul(T2, T2, YP); + sm9_fp2_sub(T1, T1, T3); + sm9_fp2_mul(T1, T1, ZT); + sm9_fp2_mul(T1, T1, ZP); + sm9_fp2_mul(T4, T1, T0); + sm9_fp2_copy(b1, T4); + sm9_fp2_mul(T1, T1, YP); + sm9_fp2_mul(T3, T0, YT); + sm9_fp2_sub(T3, T3, T2); + sm9_fp2_mul(T0, T0, T3); + sm9_fp2_mul_fp(T0, T0, xQ); + sm9_fp2_copy(a4, T0); + sm9_fp2_mul(T3, T3, XP); + sm9_fp2_mul(T3, T3, ZP); + sm9_fp2_sub(T1, T1, T3); + sm9_fp2_copy(a0, T1); + sm9_fp2_mul_fp(T2, T4, yQ); + sm9_fp2_neg(T2, T2); + sm9_fp2_copy(a1, T2); +} + +void sm9_twist_point_pi1(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P) +{ + //const c = 0x3f23ea58e5720bdb843c6cfa9c08674947c5c86e0ddd04eda91d8354377b698bn; + const sm9_fp_t c = { + 0x377b698b, 0xa91d8354, 0x0ddd04ed, 0x47c5c86e, + 0x9c086749, 0x843c6cfa, 0xe5720bdb, 0x3f23ea58, + }; + sm9_fp2_conjugate(R->X, P->X); + sm9_fp2_conjugate(R->Y, P->Y); + sm9_fp2_conjugate(R->Z, P->Z); + sm9_fp2_mul_fp(R->Z, R->Z, c); + +} + +void sm9_twist_point_pi2(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P) +{ + //c = 0xf300000002a3a6f2780272354f8b78f4d5fc11967be65334 + const sm9_fp_t c = { + 0x7be65334, 0xd5fc1196, 0x4f8b78f4, 0x78027235, + 0x02a3a6f2, 0xf3000000, 0, 0, + }; + sm9_fp2_copy(R->X, P->X); + sm9_fp2_copy(R->Y, P->Y); + sm9_fp2_mul_fp(R->Z, P->Z, c); +} + +void sm9_twist_point_neg_pi2(SM9_TWIST_POINT *R, const SM9_TWIST_POINT *P) +{ + // c = 0xf300000002a3a6f2780272354f8b78f4d5fc11967be65334 + const sm9_fp_t c = { + 0x7be65334, 0xd5fc1196, 0x4f8b78f4, 0x78027235, + 0x02a3a6f2, 0xf3000000, 0, 0, + }; + sm9_fp2_copy(R->X, P->X); + sm9_fp2_neg(R->Y, P->Y); + sm9_fp2_mul_fp(R->Z, P->Z, c); +} + + +void sm9_final_exponent_hard_part(sm9_fp12_t r, const sm9_fp12_t f) +{ + // a2 = 0xd8000000019062ed0000b98b0cb27659 + // a3 = 0x2400000000215d941 + const sm9_bn_t a2 = {0xcb27659, 0x0000b98b, 0x019062ed, 0xd8000000, 0, 0, 0, 0}; + const sm9_bn_t a3 = {0x215d941, 0x40000000, 0x2, 0, 0, 0, 0, 0}; + const sm9_bn_t nine = {9,0,0,0,0,0,0,0}; + sm9_fp12_t t0, t1, t2, t3; + + sm9_fp12_pow(t0, f, a3); + sm9_fp12_inv(t0, t0); + sm9_fp12_frobenius(t1, t0); + sm9_fp12_mul(t1, t0, t1); + + sm9_fp12_mul(t0, t0, t1); + sm9_fp12_frobenius(t2, f); + sm9_fp12_mul(t3, t2, f); + sm9_fp12_pow(t3, t3, nine); + + sm9_fp12_mul(t0, t0, t3); + sm9_fp12_sqr(t3, f); + sm9_fp12_sqr(t3, t3); + sm9_fp12_mul(t0, t0, t3); + sm9_fp12_sqr(t2, t2); + sm9_fp12_mul(t2, t2, t1); + sm9_fp12_frobenius2(t1, f); + sm9_fp12_mul(t1, t1, t2); + + sm9_fp12_pow(t2, t1, a2); + sm9_fp12_mul(t0, t2, t0); + sm9_fp12_frobenius3(t1, f); + sm9_fp12_mul(t1, t1, t0); + + sm9_fp12_copy(r, t1); +} + +void sm9_final_exponent(sm9_fp12_t r, const sm9_fp12_t f) +{ + sm9_fp12_t t0; + sm9_fp12_t t1; + + sm9_fp12_frobenius6(t0, f); + sm9_fp12_inv(t1, f); + sm9_fp12_mul(t0, t0, t1); + sm9_fp12_frobenius2(t1, t0); + sm9_fp12_mul(t0, t0, t1); + sm9_final_exponent_hard_part(t0, t0); + + sm9_fp12_copy(r, t0); +} + +void sm9_pairing(sm9_fp12_t r, const SM9_TWIST_POINT *Q, const SM9_POINT *P) { + const char *abits = "00100000000000000000000000000000000000010000101100020200101000020"; + + SM9_TWIST_POINT _T, *T = &_T; + SM9_TWIST_POINT _Q1, *Q1 = &_Q1; + SM9_TWIST_POINT _Q2, *Q2 = &_Q2; + + sm9_fp12_t f_num; + sm9_fp12_t f_den; + sm9_fp12_t g_num; + sm9_fp12_t g_den; + int i; + + sm9_twist_point_copy(T, Q); + + sm9_fp12_set_one(f_num); + sm9_fp12_set_one(f_den); + + for (i = 0; i < strlen(abits); i++) { + sm9_fp12_sqr(f_num, f_num); + sm9_fp12_sqr(f_den, f_den); + sm9_eval_g_tangent(g_num, g_den, T, P); + sm9_fp12_mul(f_num, f_num, g_num); + sm9_fp12_mul(f_den, f_den, g_den); + + sm9_twist_point_dbl(T, T); + + if (abits[i] == '1') { + sm9_eval_g_line(g_num, g_den, T, Q, P); + sm9_fp12_mul(f_num, f_num, g_num); + sm9_fp12_mul(f_den, f_den, g_den); + sm9_twist_point_add_full(T, T, Q); + } else if (abits[i] == '2') { + sm9_twist_point_neg(Q1, Q); + sm9_eval_g_line(g_num, g_den, T, Q1, P); + sm9_fp12_mul(f_num, f_num, g_num); + sm9_fp12_mul(f_den, f_den, g_den); + sm9_twist_point_add_full(T, T, Q1); + } + } + + sm9_twist_point_pi1(Q1, Q); + sm9_twist_point_neg_pi2(Q2, Q); + + sm9_eval_g_line(g_num, g_den, T, Q1, P); + sm9_fp12_mul(f_num, f_num, g_num); + sm9_fp12_mul(f_den, f_den, g_den); + sm9_twist_point_add_full(T, T, Q1); + + sm9_eval_g_line(g_num, g_den, T, Q2, P); + sm9_fp12_mul(f_num, f_num, g_num); + sm9_fp12_mul(f_den, f_den, g_den); + sm9_twist_point_add_full(T, T, Q2); + + sm9_fp12_inv(f_den, f_den); + sm9_fp12_mul(r, f_num, f_den); + + sm9_final_exponent(r, r); +} + +void sm9_fn_add(sm9_fn_t r, const sm9_fn_t a, const sm9_fn_t b) +{ + sm9_bn_add(r, a, b); + if (sm9_bn_cmp(r, SM9_N) >= 0) { + sm9_bn_sub(r, r, SM9_N); + } +} + +void sm9_fn_sub(sm9_fn_t r, const sm9_fn_t a, const sm9_fn_t b) +{ + if (sm9_bn_cmp(a, b) >= 0) { + sm9_bn_sub(r, a, b); + } else { + sm9_bn_t t; + sm9_bn_sub(t, SM9_N, b); + sm9_bn_add(r, t, a); + } +} + +void sm9_fn_mul(sm9_fn_t r, const sm9_fn_t a, const sm9_fn_t b) +{ + uint64_t s[18]; + sm9_barrett_bn_t zh, zl, q; + uint64_t w; + int i, j; + + /* z = a * b */ + for (i = 0; i < 8; i++) { + s[i] = 0; + } + for (i = 0; i < 8; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + a[i] * b[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + + /* zl = z mod (2^32)^9 = z[0..8] + * zh = z // (2^32)^7 = z[7..15] */ + for (i = 0; i < 9; i++) { + zl[i] = s[i]; + zh[i] = s[7 + i]; + } + + /* q = zh * mu // (2^32)^9 */ + for (i = 0; i < 18; i++) { + s[i] = 0; + } + for (i = 0; i < 9; i++) { + w = 0; + for (j = 0; j < 9; j++) { + w += s[i + j] + zh[i] * SM9_MU_N[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 9] = w; + } + for (i = 0; i < 9; i++) { + q[i] = s[9 + i]; + } + + /* q = q * n mod (2^32)^9 */ + for (i = 0; i < 18; i++) { + s[i] = 0; + } + for (i = 0; i < 9; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + q[i] * SM9_N[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + for (i = 0; i < 9; i++) { + q[i] = s[i]; + } + + /* r = zl - q (mod (2^32)^9) */ + + if (sm9_barrett_bn_cmp(zl, q)) { + sm9_barrett_bn_sub(zl, zl, q); + } else { + sm9_barrett_bn_t c = {0,0,0,0,0,0,0,0,0x100000000}; + sm9_barrett_bn_sub(q, c, q); + sm9_barrett_bn_add(zl, q, zl); + } + + + for (i = 0; i < 8; i++) { + r[i] = zl[i]; + } + + r[7] += (zl[8] << 32); + + /* while r >= n do: r = r - n */ + while (sm9_bn_cmp(r, SM9_N) >= 0) { + sm9_bn_sub(r, r, SM9_N); + } +} + +void sm9_fn_pow(sm9_fn_t r, const sm9_fn_t a, const sm9_bn_t e) +{ + sm9_fn_t t; + uint32_t w; + int i, j; + + assert(sm9_bn_cmp(e, SM9_N_MINUS_ONE) < 0); + + sm9_bn_set_one(t); + for (i = 7; i >= 0; i--) { + w = (uint32_t)e[i]; + for (j = 0; j < 32; j++) { + sm9_fn_mul(t, t, t); + if (w & 0x80000000) + sm9_fn_mul(t, t, a); + w <<= 1; + } + } + sm9_bn_copy(r, t); +} + +void sm9_fn_inv(sm9_fn_t r, const sm9_fn_t a) +{ + sm9_fn_t e; + sm9_bn_sub(e, SM9_N, SM9_TWO); + sm9_fn_pow(r, a, e); +} + + +// for H1() and H2() +// h = (Ha mod (n-1)) + 1; h in [1, n-1], n is the curve order, Ha is 40 bytes from hash +void sm9_fn_from_hash(sm9_fn_t h, const uint8_t Ha[40]) +{ + uint64_t s[18] = {0}; + sm9_barrett_bn_t zh, zl, q; + uint64_t w; + int i, j; + + /* s = Ha -> int */ + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 4; j++) { + s[i] <<= 8; + s[i] += Ha[4 * (9-i) + j]; + } + } + + /* zl = z mod (2^32)^9 = z[0..8] + * zh = z // (2^32)^7 = z[7..15] */ + for (i = 0; i < 9; i++) { + zl[i] = s[i]; + zh[i] = s[7 + i]; + } + + /* q = zh * mu // (2^32)^9 */ + for (i = 0; i < 18; i++) { + s[i] = 0; + } + for (i = 0; i < 9; i++) { + w = 0; + for (j = 0; j < 9; j++) { + w += s[i + j] + zh[i] * SM9_MU_N_MINUS_ONE[j]; // + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 9] = w; + } + for (i = 0; i < 9; i++) { + q[i] = s[9 + i]; + } + + /* q = q * p mod (2^32)^9 */ + for (i = 0; i < 18; i++) { + s[i] = 0; + } + for (i = 0; i < 9; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + q[i] * SM9_N_MINUS_ONE[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + for (i = 0; i < 9; i++) { + q[i] = s[i]; + } + + /* h = zl - q (mod (2^32)^9) */ + + if (sm9_barrett_bn_cmp(zl, q)) { + sm9_barrett_bn_sub(zl, zl, q); + } else { + sm9_barrett_bn_t c = {0,0,0,0,0,0,0,0,0x100000000}; + sm9_barrett_bn_sub(q, c, q); + sm9_barrett_bn_add(zl, q, zl); + } + + for (i = 0; i < 8; i++) { + h[i] = zl[i]; + } + + h[7] += (zl[8] << 32); + + /* while h >= (n-1) do: h = h - (n-1) */ + while (sm9_bn_cmp(h, SM9_N_MINUS_ONE) >= 0) { + sm9_bn_sub(h, h, SM9_N_MINUS_ONE); + } + + sm9_fn_add(h, h, SM9_ONE); +} + +void sm9_fp12_to_bytes(const sm9_fp12_t a, uint8_t buf[32 * 12]) +{ + sm9_fp4_to_bytes(a[2], buf); + sm9_fp4_to_bytes(a[1], buf + 32 * 4); + sm9_fp4_to_bytes(a[0], buf + 32 * 8); +} + +int sm9_fn_from_bytes(sm9_fn_t a, const uint8_t in[32]) +{ + sm9_bn_from_bytes(a, in); + return 1; +} + +int sm9_point_to_uncompressed_octets(const SM9_POINT *P, uint8_t octets[65]) +{ + sm9_fp_t x; + sm9_fp_t y; + sm9_point_get_xy(P, x, y); + octets[0] = 0x04; + sm9_bn_to_bytes(x, octets + 1); + sm9_bn_to_bytes(y, octets + 32 + 1); + return 1; +} + +int sm9_point_from_uncompressed_octets(SM9_POINT *P, const uint8_t octets[65]) +{ + if (octets[0] != 0x04) { + error_print(); + return -1; + } + memset(P, 0, sizeof(*P)); + sm9_bn_from_bytes(P->X, octets + 1); + sm9_bn_from_bytes(P->Y, octets + 32 + 1); + sm9_fp_set_one(P->Z); + if (!sm9_point_is_on_curve(P)) { + error_print(); + return -1; + } + return 1; +} + +int sm9_twist_point_to_uncompressed_octets(const SM9_TWIST_POINT *P, uint8_t octets[129]) +{ + octets[0] = 0x04; + sm9_fp2_t x; + sm9_fp2_t y; + sm9_twist_point_get_xy(P, x, y); + sm9_fp2_to_bytes(x, octets + 1); + sm9_fp2_to_bytes(y, octets + 32 * 2 + 1); + return 1; +} + +int sm9_twist_point_from_uncompressed_octets(SM9_TWIST_POINT *P, const uint8_t octets[129]) +{ + assert(octets[0] == 0x04); + sm9_fp2_from_bytes(P->X, octets + 1); + sm9_fp2_from_bytes(P->Y, octets + 32 * 2 + 1); + sm9_fp2_set_one(P->Z); + if (!sm9_twist_point_is_on_curve(P)) return -1; + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/sm9_key.c b/Core/GmSSL-3.1.1/src/sm9_key.c new file mode 100644 index 0000000..931c30c --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm9_key.c @@ -0,0 +1,1157 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern const sm9_bn_t SM9_ZERO; +extern const sm9_bn_t SM9_N; + +// generate h1 in [1, n-1] +int sm9_hash1(sm9_bn_t h1, const char *id, size_t idlen, uint8_t hid) +{ + SM3_CTX ctx; + uint8_t prefix[1] = { SM9_HASH1_PREFIX }; + uint8_t ct1[4] = {0x00, 0x00, 0x00, 0x01}; + uint8_t ct2[4] = {0x00, 0x00, 0x00, 0x02}; + uint8_t Ha[64]; + + sm3_init(&ctx); + sm3_update(&ctx, prefix, sizeof(prefix)); + sm3_update(&ctx, (uint8_t *)id, idlen); + sm3_update(&ctx, &hid, 1); + sm3_update(&ctx, ct1, sizeof(ct1)); + sm3_finish(&ctx, Ha); + + sm3_init(&ctx); + sm3_update(&ctx, prefix, sizeof(prefix)); + sm3_update(&ctx, (uint8_t *)id, idlen); + sm3_update(&ctx, &hid, 1); + sm3_update(&ctx, ct2, sizeof(ct2)); + sm3_finish(&ctx, Ha + 32); + + sm9_fn_from_hash(h1, Ha); + return 1; +} + +int sm9_sign_master_key_to_der(const SM9_SIGN_MASTER_KEY *msk, uint8_t **out, size_t *outlen) +{ + uint8_t ks[32]; + uint8_t Ppubs[1 + 32 * 4]; + size_t len = 0; + + sm9_fn_to_bytes(msk->ks, ks); + sm9_twist_point_to_uncompressed_octets(&msk->Ppubs, Ppubs); + + if (asn1_integer_to_der(ks, sizeof(ks), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(ks, sizeof(ks), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), out, outlen) != 1) { + gmssl_secure_clear(ks, sizeof(ks)); + error_print(); + return -1; + } + gmssl_secure_clear(ks, sizeof(ks)); + return 1; +} + +int sm9_sign_master_key_from_der(SM9_SIGN_MASTER_KEY *msk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *ks; + size_t kslen; + const uint8_t *Ppubs; + size_t Ppubslen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&ks, &kslen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppubs, &Ppubslen, &d, &dlen) != 1 + || asn1_check(kslen == 32) != 1 + || asn1_check(Ppubslen == 1 + 32 * 4) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(msk, 0, sizeof(*msk)); + if (sm9_fn_from_bytes(msk->ks, ks) != 1 + || sm9_twist_point_from_uncompressed_octets(&msk->Ppubs, Ppubs) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_public_key_to_der(const SM9_SIGN_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) +{ + uint8_t Ppubs[1 + 32 * 4]; + size_t len = 0; + + sm9_twist_point_to_uncompressed_octets(&mpk->Ppubs, Ppubs); + if (asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_public_key_from_der(SM9_SIGN_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *Ppubs; + size_t Ppubslen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&Ppubs, &Ppubslen, &d, &dlen) != 1 + || asn1_check(Ppubslen == 1 + 32 * 4) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(mpk, 0, sizeof(*mpk)); + if (sm9_twist_point_from_uncompressed_octets(&mpk->Ppubs, Ppubs) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_key_to_der(const SM9_SIGN_KEY *key, uint8_t **out, size_t *outlen) +{ + uint8_t ds[65]; + uint8_t Ppubs[129]; + size_t len = 0; + + sm9_point_to_uncompressed_octets(&key->ds, ds); + sm9_twist_point_to_uncompressed_octets(&key->Ppubs, Ppubs); + + if (asn1_bit_octets_to_der(ds, sizeof(ds), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(ds, sizeof(ds), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), out, outlen) != 1) { + gmssl_secure_clear(ds, sizeof(ds)); + error_print(); + return -1; + } + gmssl_secure_clear(ds, sizeof(ds)); + return 1; +} + +int sm9_sign_key_from_der(SM9_SIGN_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *ds; + size_t dslen; + const uint8_t *Ppubs; + size_t Ppubslen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&ds, &dslen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppubs, &Ppubslen, &d, &dlen) != 1 + || asn1_check(dslen == 65) != 1 + || asn1_check(Ppubslen == 129) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(key, 0, sizeof(*key)); + if (sm9_point_from_uncompressed_octets(&key->ds, ds) != 1 + || sm9_twist_point_from_uncompressed_octets(&key->Ppubs, Ppubs) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_key_to_der(const SM9_ENC_MASTER_KEY *msk, uint8_t **out, size_t *outlen) +{ + uint8_t ke[32]; + uint8_t Ppube[1 + 32 * 2]; + size_t len = 0; + + sm9_fn_to_bytes(msk->ke, ke); + sm9_point_to_uncompressed_octets(&msk->Ppube, Ppube); + + if (asn1_integer_to_der(ke, sizeof(ke), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(ke, sizeof(ke), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), out, outlen) != 1) { + gmssl_secure_clear(ke, sizeof(ke)); + error_print(); + return -1; + } + gmssl_secure_clear(ke, sizeof(ke)); + return 1; +} + +int sm9_enc_master_key_from_der(SM9_ENC_MASTER_KEY *msk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *ke; + size_t kelen; + const uint8_t *Ppube; + size_t Ppubelen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&ke, &kelen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppube, &Ppubelen, &d, &dlen) != 1 + || asn1_check(kelen == 32) != 1 + || asn1_check(Ppubelen == 1 + 32 * 2) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(msk, 0, sizeof(*msk)); + if (sm9_fn_from_bytes(msk->ke, ke) != 1 + || sm9_point_from_uncompressed_octets(&msk->Ppube, Ppube) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_public_key_to_der(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) +{ + uint8_t Ppube[1 + 32 * 2]; + size_t len = 0; + + sm9_point_to_uncompressed_octets(&mpk->Ppube, Ppube); + + if (asn1_bit_octets_to_der(Ppube, sizeof(Ppube), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_public_key_from_der(SM9_ENC_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *Ppube; + size_t Ppubelen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&Ppube, &Ppubelen, &d, &dlen) != 1 + || asn1_check(Ppubelen == 1 + 32 * 2) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(mpk, 0, sizeof(*mpk)); + if (sm9_point_from_uncompressed_octets(&mpk->Ppube, Ppube) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_key_to_der(const SM9_ENC_KEY *key, uint8_t **out, size_t *outlen) +{ + uint8_t de[129]; + uint8_t Ppube[65]; + size_t len = 0; + + sm9_twist_point_to_uncompressed_octets(&key->de, de); + sm9_point_to_uncompressed_octets(&key->Ppube, Ppube); + + if (asn1_bit_octets_to_der(de, sizeof(de), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(de, sizeof(de), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), out, outlen) != 1) { + gmssl_secure_clear(de, sizeof(de)); + error_print(); + return -1; + } + gmssl_secure_clear(de, sizeof(de)); + return 1; +} + +int sm9_enc_key_from_der(SM9_ENC_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *de; + size_t delen; + const uint8_t *Ppube; + size_t Ppubelen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&de, &delen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppube, &Ppubelen, &d, &dlen) != 1 + || asn1_check(delen == 129) != 1 + || asn1_check(Ppubelen == 65) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(key, 0, sizeof(*key)); + if (sm9_twist_point_from_uncompressed_octets(&key->de, de) != 1 + || sm9_point_from_uncompressed_octets(&key->Ppube, Ppube) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_key_generate(SM9_SIGN_MASTER_KEY *msk) +{ + if (!msk) { + error_print(); + return -1; + } + // k = rand(1, n-1) + if (sm9_fn_rand(msk->ks) != 1) { + error_print(); + return -1; + } + // Ppubs = k * P2 in E'(F_p^2) + sm9_twist_point_mul_generator(&msk->Ppubs, msk->ks); + return 1; +} + +int sm9_enc_master_key_generate(SM9_ENC_MASTER_KEY *msk) +{ + // k = rand(1, n-1) + if (sm9_fn_rand(msk->ke) != 1) { + error_print(); + return -1; + } + // Ppube = ke * P1 in E(F_p) + sm9_point_mul_generator(&msk->Ppube, msk->ke); + return 1; +} + +int sm9_sign_master_key_extract_key(SM9_SIGN_MASTER_KEY *msk, const char *id, size_t idlen, SM9_SIGN_KEY *key) +{ + sm9_fn_t t; + + // t1 = H1(ID || hid, N) + ks + sm9_hash1(t, id, idlen, SM9_HID_SIGN); + sm9_fn_add(t, t, msk->ks); + if (sm9_fn_is_zero(t)) { + // 这是一个严重问题,意味着整个msk都需要作废了 + error_print(); + return -1; + } + + // t2 = ks * t1^-1 + sm9_fn_inv(t, t); + sm9_fn_mul(t, t, msk->ks); + + // ds = t2 * P1 + sm9_point_mul_generator(&key->ds, t); + key->Ppubs = msk->Ppubs; + + return 1; +} + +int sm9_enc_master_key_extract_key(SM9_ENC_MASTER_KEY *msk, const char *id, size_t idlen, + SM9_ENC_KEY *key) +{ + sm9_fn_t t; + + // t1 = H1(ID || hid, N) + ke + sm9_hash1(t, id, idlen, SM9_HID_ENC); + sm9_fn_add(t, t, msk->ke); + if (sm9_fn_is_zero(t)) { + error_print(); + return -1; + } + + // t2 = ke * t1^-1 + sm9_fn_inv(t, t); + sm9_fn_mul(t, t, msk->ke); + + // de = t2 * P2 + sm9_twist_point_mul_generator(&key->de, t); + key->Ppube = msk->Ppube; + + return 1; +} + + +#define OID_SM9 oid_sm_algors,302 +static uint32_t oid_sm9[] = { OID_SM9 }; +static uint32_t oid_sm9sign[] = { OID_SM9,1 }; +static uint32_t oid_sm9keyagreement[] = { OID_SM9,2 }; +static uint32_t oid_sm9encrypt[] = { OID_SM9,3 }; + +static const ASN1_OID_INFO sm9_oids[] = { + { OID_sm9, "sm9", oid_sm9, sizeof(oid_sm9)/sizeof(int) }, + { OID_sm9sign, "sm9sign", oid_sm9sign, sizeof(oid_sm9sign)/sizeof(int) }, + { OID_sm9keyagreement, "sm9keyagreement", oid_sm9keyagreement, sizeof(oid_sm9keyagreement)/sizeof(int) }, + { OID_sm9encrypt, "sm9encrypt", oid_sm9encrypt, sizeof(oid_sm9encrypt)/sizeof(int) }, +}; + +static const int sm9_oids_count = sizeof(sm9_oids)/sizeof(sm9_oids[0]); + + +const char *sm9_oid_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(sm9_oids, sm9_oids_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int sm9_oid_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(sm9_oids, sm9_oids_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int sm9_oid_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (oid == -1) { + // TODO: 检查其他的oid_to_der是否支持这个default == -1 的特性 + return 0; + } + if (!(info = asn1_oid_info_from_oid(sm9_oids, sm9_oids_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_oid_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + + if ((ret = asn1_oid_info_from_der(&info, sm9_oids, sm9_oids_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + +int sm9_algor_to_der(int alg, int params, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (sm9_oid_to_der(alg, NULL, &len) != 1 + || sm9_oid_to_der(params, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || sm9_oid_to_der(alg, out, outlen) != 1 + || sm9_oid_to_der(params, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int sm9_algor_from_der(int *alg, int *params, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (sm9_oid_from_der(alg, &d, &dlen) != 1 + || sm9_oid_from_der(params, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +static int sm9_private_key_info_to_der(int alg, int params, const uint8_t *prikey, size_t prikey_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (prikey_len > SM9_MAX_PRIVATE_KEY_SIZE) { + error_print(); + return -1; + } + if (asn1_int_to_der(PKCS8_private_key_info_version, NULL, &len) != 1 + || sm9_algor_to_der(alg, params, NULL, &len) != 1 + || asn1_octet_string_to_der(prikey, prikey_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(PKCS8_private_key_info_version, out, outlen) != 1 + || sm9_algor_to_der(alg, params, out, outlen) != 1 + || asn1_octet_string_to_der(prikey, prikey_len, out, outlen) != 1) { + error_print(); + return -1; + } + //printf("alg %s params %s prikey_len %zu: SM9_PRIVATE_KEY_INFO_SIZE %zu\n", sm9_oid_name(alg), sm9_oid_name(params), prikey_len, *outlen); + return 1; +} + +static int sm9_private_key_info_from_der(int *alg, int *params, const uint8_t **prikey, size_t *prikey_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int ver; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else error_print(); + return ret; + } + if (asn1_int_from_der(&ver, &d, &dlen) != 1 + || sm9_algor_from_der(alg, params, &d, &dlen) != 1 + || asn1_octet_string_from_der(prikey, prikey_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (ver != PKCS8_private_key_info_version) { + error_print(); + return -1; + } + if (*prikey_len > SM9_MAX_PRIVATE_KEY_SIZE) { + error_print(); + return -1; + } + return 1; +} + +static int sm9_private_key_info_encrypt_to_der(int alg, int params, const uint8_t *prikey, size_t prikey_len, + const char *pass, uint8_t **out, size_t *outlen) +{ + int ret = -1; + uint8_t pkey_info[SM9_MAX_PRIVATE_KEY_INFO_SIZE]; + uint8_t *p = pkey_info; + size_t pkey_info_len = 0; + uint8_t salt[16]; + int iter = 65536; + uint8_t iv[16]; + uint8_t key[16]; + SM4_KEY sm4_key; + uint8_t enced_pkey_info[sizeof(pkey_info) + 16]; // cbc-padding of pkey_info + size_t enced_pkey_info_len; + + if (sm9_private_key_info_to_der(alg, params, prikey, prikey_len, &p, &pkey_info_len) != 1 + || rand_bytes(salt, sizeof(salt)) != 1 + || rand_bytes(iv, sizeof(iv)) != 1 + || pbkdf2_hmac_sm3_genkey(pass, strlen(pass), salt, sizeof(salt), iter, sizeof(key), key) != 1) { + error_print(); + goto end; + } + sm4_set_encrypt_key(&sm4_key, key); + if (sm4_cbc_padding_encrypt(&sm4_key, iv, pkey_info, pkey_info_len, enced_pkey_info, &enced_pkey_info_len) != 1 + || pkcs8_enced_private_key_info_to_der(salt, sizeof(salt), iter, sizeof(key), + OID_hmac_sm3, OID_sm4_cbc, iv, sizeof(iv), + enced_pkey_info, enced_pkey_info_len, out, outlen) != 1) { + error_print(); + goto end; + } + //printf("SM9_ENCED_PRIVATE_KEY_INFO_SIZE %zu\n", *outlen); + ret = 1; +end: + gmssl_secure_clear(pkey_info, sizeof(pkey_info)); + gmssl_secure_clear(salt, sizeof(salt)); + gmssl_secure_clear(iv, sizeof(iv)); + gmssl_secure_clear(key, sizeof(key)); + return ret; +} + +static int sm9_private_key_info_decrypt_from_der(int *alg, int *params, uint8_t *prikey, size_t *prikey_len, + const char *pass, const uint8_t **in, size_t *inlen) +{ + int ret = -1; + const uint8_t *salt; + size_t saltlen; + int iter; + int keylen; + int prf; + int cipher; + const uint8_t *iv; + size_t ivlen; + uint8_t key[16]; + SM4_KEY sm4_key; + const uint8_t *enced_pkey_info; + size_t enced_pkey_info_len; + uint8_t pkey_info[SM9_MAX_PRIVATE_KEY_INFO_SIZE]; + const uint8_t *cp = pkey_info; + size_t pkey_info_len; + const uint8_t *cp_prikey; + + if (pkcs8_enced_private_key_info_from_der(&salt, &saltlen, &iter, &keylen, &prf, + &cipher, &iv, &ivlen, &enced_pkey_info, &enced_pkey_info_len, in, inlen) != 1 + || asn1_check(keylen == -1 || keylen == 16) != 1 + || asn1_check(prf == - 1 || prf == OID_hmac_sm3) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == 16) != 1 + || asn1_length_le(enced_pkey_info_len, sizeof(pkey_info)) != 1) { + error_print(); + return -1; + } + if (pbkdf2_genkey(DIGEST_sm3(), pass, strlen(pass), salt, saltlen, iter, sizeof(key), key) != 1) { + error_print(); + goto end; + } + sm4_set_decrypt_key(&sm4_key, key); + if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_pkey_info, enced_pkey_info_len, + pkey_info, &pkey_info_len) != 1 + || sm9_private_key_info_from_der(alg, params, &cp_prikey, prikey_len, // 注意这里的是const uint8_t *,必须拷贝到外面 + &cp, &pkey_info_len) != 1 + || asn1_length_is_zero(pkey_info_len) != 1) { + error_print(); + goto end; + } + memcpy(prikey, cp_prikey, *prikey_len); + ret = 1; +end: + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(pkey_info, sizeof(pkey_info)); + return ret; +} + + + +int sm9_sign_master_key_info_encrypt_to_der(const SM9_SIGN_MASTER_KEY *msk, const char *pass, uint8_t **out, size_t *outlen) +{ + uint8_t buf[SM9_SIGN_MASTER_KEY_MAX_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_sign_master_key_to_der(msk, &p, &len) != 1 + || sm9_private_key_info_encrypt_to_der(OID_sm9, OID_sm9sign, buf, len, pass, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + + +int sm9_sign_master_key_info_decrypt_from_der(SM9_SIGN_MASTER_KEY *msk, const char *pass, const uint8_t **in, size_t *inlen) +{ + int ret = -1; + int alg, params; + uint8_t prikey[SM9_MAX_PRIVATE_KEY_SIZE]; + size_t prikey_len; + const uint8_t *cp = prikey; + + if (sm9_private_key_info_decrypt_from_der(&alg, ¶ms, prikey, &prikey_len, pass, in, inlen) != 1) { + error_print(); + goto end; + } + if (alg != OID_sm9) { + error_print(); + goto end; + } + if (params != OID_sm9sign) { + error_print(); + goto end; + } + if (sm9_sign_master_key_from_der(msk, &cp, &prikey_len) != 1 + || asn1_length_is_zero(prikey_len) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + gmssl_secure_clear(prikey, sizeof(prikey)); + return ret; +} + +int sm9_sign_master_key_info_encrypt_to_pem(const SM9_SIGN_MASTER_KEY *msk, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_sign_master_key_info_encrypt_to_der(msk, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, PEM_SM9_SIGN_MASTER_KEY, buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_key_info_decrypt_from_pem(SM9_SIGN_MASTER_KEY *msk, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, PEM_SM9_SIGN_MASTER_KEY, buf, &len, sizeof(buf)) != 1 + || sm9_sign_master_key_info_decrypt_from_der(msk, pass, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_public_key_to_pem(const SM9_SIGN_MASTER_KEY *mpk, FILE *fp) +{ + uint8_t buf[SM9_SIGN_MASTER_PUBLIC_KEY_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_sign_master_public_key_to_der(mpk, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, PEM_SM9_SIGN_MASTER_PUBLIC_KEY, buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_public_key_from_pem(SM9_SIGN_MASTER_KEY *mpk, FILE *fp) +{ + uint8_t buf[512]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, PEM_SM9_SIGN_MASTER_PUBLIC_KEY, buf, &len, sizeof(buf)) != 1 + || sm9_sign_master_public_key_from_der(mpk, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_key_info_encrypt_to_der(const SM9_SIGN_KEY *key, const char *pass, uint8_t **out, size_t *outlen) +{ + uint8_t buf[SM9_SIGN_KEY_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_sign_key_to_der(key, &p, &len) != 1 + || sm9_private_key_info_encrypt_to_der(OID_sm9sign, -1, buf, len, pass, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_key_info_decrypt_from_der(SM9_SIGN_KEY *key, const char *pass, const uint8_t **in, size_t *inlen) +{ + int ret = -1; + int alg, params; + uint8_t prikey[512]; + size_t prikey_len; + const uint8_t *cp = prikey; + + if (sm9_private_key_info_decrypt_from_der(&alg, ¶ms, prikey, &prikey_len, pass, in, inlen) != 1) { + error_print(); + goto end; + } + if (alg != OID_sm9sign) { + error_print(); + goto end; + } + if (params != -1) { + error_print(); + goto end; + } + if (sm9_sign_key_from_der(key, &cp, &prikey_len) != 1 + || asn1_length_is_zero(prikey_len) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + gmssl_secure_clear(prikey, sizeof(prikey)); + return ret; +} + +int sm9_sign_key_info_encrypt_to_pem(const SM9_SIGN_KEY *key, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_sign_key_info_encrypt_to_der(key, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, PEM_SM9_SIGN_PRIVATE_KEY, buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_key_info_decrypt_from_pem(SM9_SIGN_KEY *key, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, PEM_SM9_SIGN_PRIVATE_KEY, buf, &len, sizeof(buf)) != 1 + || sm9_sign_key_info_decrypt_from_der(key, pass, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_key_info_encrypt_to_der(const SM9_ENC_MASTER_KEY *msk, const char *pass, uint8_t **out, size_t *outlen) +{ + uint8_t buf[256]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_enc_master_key_to_der(msk, &p, &len) != 1 + || sm9_private_key_info_encrypt_to_der(OID_sm9, OID_sm9encrypt, buf, len, pass, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_key_info_decrypt_from_der(SM9_ENC_MASTER_KEY *msk, const char *pass, const uint8_t **in, size_t *inlen) +{ + int ret = -1; + int alg, params; + uint8_t prikey[512]; + size_t prikey_len; + const uint8_t *cp = prikey; + + if (sm9_private_key_info_decrypt_from_der(&alg, ¶ms, prikey, &prikey_len, pass, in, inlen) != 1) { + error_print(); + goto end; + } + if (alg != OID_sm9) { + error_print(); + goto end; + } + if (params != OID_sm9encrypt) { + error_print(); + goto end; + } + if (sm9_enc_master_key_from_der(msk, &cp, &prikey_len) != 1 + || asn1_length_is_zero(prikey_len) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + gmssl_secure_clear(prikey, sizeof(prikey)); + return 1; +} + +int sm9_enc_master_key_info_encrypt_to_pem(const SM9_ENC_MASTER_KEY *msk, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_enc_master_key_info_encrypt_to_der(msk, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, PEM_SM9_ENC_MASTER_KEY, buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_key_info_decrypt_from_pem(SM9_ENC_MASTER_KEY *msk, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, PEM_SM9_ENC_MASTER_KEY, buf, &len, sizeof(buf)) != 1 + || sm9_enc_master_key_info_decrypt_from_der(msk, pass, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_public_key_to_pem(const SM9_ENC_MASTER_KEY *mpk, FILE *fp) +{ + uint8_t buf[1024]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_enc_master_public_key_to_der(mpk, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, PEM_SM9_ENC_MASTER_PUBLIC_KEY, buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_public_key_from_pem(SM9_ENC_MASTER_KEY *mpk, FILE *fp) +{ + uint8_t buf[512]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, PEM_SM9_ENC_MASTER_PUBLIC_KEY, buf, &len, sizeof(buf)) != 1 + || sm9_enc_master_public_key_from_der(mpk, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_key_info_encrypt_to_der(const SM9_ENC_KEY *key, const char *pass, uint8_t **out, size_t *outlen) +{ + uint8_t buf[1024]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_enc_key_to_der(key, &p, &len) != 1 + || sm9_private_key_info_encrypt_to_der(OID_sm9encrypt, -1, buf, len, pass, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_key_info_decrypt_from_der(SM9_ENC_KEY *key, const char *pass, const uint8_t **in, size_t *inlen) +{ + int ret = -1; + int alg, params; + uint8_t prikey[512]; + size_t prikey_len; + const uint8_t *cp = prikey; + + if (sm9_private_key_info_decrypt_from_der(&alg, ¶ms, prikey, &prikey_len, pass, in, inlen) != 1) { + error_print(); + goto end; + } + if (alg != OID_sm9encrypt) { + error_print(); + goto end; + } + if (params != -1) { + error_print(); + goto end; + } + if (sm9_enc_key_from_der(key, &cp, &prikey_len) != 1 + || asn1_length_is_zero(prikey_len) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + gmssl_secure_clear(prikey, sizeof(prikey)); + return ret; +} + +int sm9_enc_key_info_encrypt_to_pem(const SM9_ENC_KEY *key, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + uint8_t *p = buf; + size_t len = 0; + + if (sm9_enc_key_info_encrypt_to_der(key, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, PEM_SM9_ENC_PRIVATE_KEY, buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_key_info_decrypt_from_pem(SM9_ENC_KEY *key, const char *pass, FILE *fp) +{ + uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, PEM_SM9_ENC_PRIVATE_KEY, buf, &len, sizeof(buf)) != 1 + || sm9_enc_key_info_decrypt_from_der(key, pass, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_SIGN_MASTER_KEY *msk) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + sm9_fn_print(fp, fmt, ind, "ks", msk->ks); + sm9_twist_point_print(fp, fmt, ind, "Ppubs", &msk->Ppubs); + return 1; +} + +int sm9_sign_master_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_SIGN_MASTER_KEY *mpk) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + sm9_twist_point_print(fp, fmt, ind, "Ppubs", &mpk->Ppubs); + return 1; +} + +int sm9_sign_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_SIGN_KEY *key) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + sm9_point_print(fp, fmt, ind, "ds", &key->ds); + sm9_twist_point_print(fp, fmt, ind, "Ppubs", &key->Ppubs); + return 1; +} + +int sm9_enc_master_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_ENC_MASTER_KEY *msk) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + sm9_fn_print(fp, fmt, ind, "ke", msk->ke); + sm9_point_print(fp, fmt, ind, "Ppube", &msk->Ppube); + return 1; +} + +int sm9_enc_master_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_ENC_MASTER_KEY *mpk) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + sm9_point_print(fp, fmt, ind, "Ppube", &mpk->Ppube); + return 1; +} + +int sm9_enc_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_ENC_KEY *key) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + sm9_twist_point_print(fp, fmt, ind, "de", &key->de); + sm9_point_print(fp, fmt, ind, "Ppube", &key->Ppube); + return 1; +} + +int sm9_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen) +{ + const uint8_t *d; + size_t dlen; + const uint8_t *p; + size_t len; + + if (asn1_sequence_from_der(&d, &dlen, &sig, &siglen) != 1 + || asn1_length_is_zero(siglen) != 1) { + error_print(); + return -1; + } + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "h", p, len); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "S", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int sm9_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + const uint8_t *d; + size_t dlen; + int val; + const uint8_t *p; + size_t len; + + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "EnType: %d\n", val); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "C1", p, len); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "C3", p, len); + if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "CipherText", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/src/sm9_lib.c b/Core/GmSSL-3.1.1/src/sm9_lib.c new file mode 100644 index 0000000..597368a --- /dev/null +++ b/Core/GmSSL-3.1.1/src/sm9_lib.c @@ -0,0 +1,514 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern const sm9_bn_t SM9_ZERO; +extern const sm9_bn_t SM9_N; +extern const SM9_POINT *SM9_P1; +extern const SM9_TWIST_POINT *SM9_P2; + + +int sm9_signature_to_der(const SM9_SIGNATURE *sig, uint8_t **out, size_t *outlen) +{ + uint8_t hbuf[32]; + uint8_t Sbuf[65]; + size_t len = 0; + + sm9_fn_to_bytes(sig->h, hbuf); + sm9_point_to_uncompressed_octets(&sig->S, Sbuf); + + if (asn1_octet_string_to_der(hbuf, sizeof(hbuf), NULL, &len) != 1 + || asn1_bit_octets_to_der(Sbuf, sizeof(Sbuf), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_octet_string_to_der(hbuf, sizeof(hbuf), out, outlen) != 1 + || asn1_bit_octets_to_der(Sbuf, sizeof(Sbuf), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_signature_from_der(SM9_SIGNATURE *sig, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *h; + size_t hlen; + const uint8_t *S; + size_t Slen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_octet_string_from_der(&h, &hlen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&S, &Slen, &d, &dlen) != 1 + || asn1_check(hlen == 32) != 1 + || asn1_check(Slen == 65) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (sm9_fn_from_bytes(sig->h, h) != 1 + || sm9_point_from_uncompressed_octets(&sig->S, S) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_init(SM9_SIGN_CTX *ctx) +{ + const uint8_t prefix[1] = { SM9_HASH2_PREFIX }; + sm3_init(&ctx->sm3_ctx); + sm3_update(&ctx->sm3_ctx, prefix, sizeof(prefix)); + return 1; +} + +int sm9_sign_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + sm3_update(&ctx->sm3_ctx, data, datalen); + return 1; +} + +int sm9_sign_finish(SM9_SIGN_CTX *ctx, const SM9_SIGN_KEY *key, uint8_t *sig, size_t *siglen) +{ + SM9_SIGNATURE signature; + + if (sm9_do_sign(key, &ctx->sm3_ctx, &signature) != 1) { + error_print(); + return -1; + } + *siglen = 0; + if (sm9_signature_to_der(&signature, &sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_do_sign(const SM9_SIGN_KEY *key, const SM3_CTX *sm3_ctx, SM9_SIGNATURE *sig) +{ + sm9_fn_t r; + sm9_fp12_t g; + uint8_t wbuf[32 * 12]; + SM3_CTX ctx = *sm3_ctx; + SM3_CTX tmp_ctx; + uint8_t ct1[4] = {0,0,0,1}; + uint8_t ct2[4] = {0,0,0,2}; + uint8_t Ha[64]; + + // A1: g = e(P1, Ppubs) + sm9_pairing(g, &key->Ppubs, SM9_P1); + + do { + // A2: rand r in [1, N-1] + if (sm9_fn_rand(r) != 1) { + error_print(); + return -1; + } + //sm9_fn_from_hex(r, "00033C8616B06704813203DFD00965022ED15975C662337AED648835DC4B1CBE"); // for testing + + // A3: w = g^r + sm9_fp12_pow(g, g, r); + sm9_fp12_to_bytes(g, wbuf); + + // A4: h = H2(M || w, N) + sm3_update(&ctx, wbuf, sizeof(wbuf)); + tmp_ctx = ctx; + sm3_update(&ctx, ct1, sizeof(ct1)); + sm3_finish(&ctx, Ha); + sm3_update(&tmp_ctx, ct2, sizeof(ct2)); + sm3_finish(&tmp_ctx, Ha + 32); + sm9_fn_from_hash(sig->h, Ha); + + // A5: l = (r - h) mod N, if l = 0, goto A2 + sm9_fn_sub(r, r, sig->h); + + } while (sm9_fn_is_zero(r)); + + // A6: S = l * dsA + sm9_point_mul(&sig->S, r, &key->ds); + + gmssl_secure_clear(&r, sizeof(r)); + gmssl_secure_clear(&g, sizeof(g)); + gmssl_secure_clear(wbuf, sizeof(wbuf)); + gmssl_secure_clear(&tmp_ctx, sizeof(tmp_ctx)); + gmssl_secure_clear(Ha, sizeof(Ha)); + + return 1; +} + +int sm9_verify_init(SM9_SIGN_CTX *ctx) +{ + const uint8_t prefix[1] = { SM9_HASH2_PREFIX }; + sm3_init(&ctx->sm3_ctx); + sm3_update(&ctx->sm3_ctx, prefix, sizeof(prefix)); + return 1; +} + +int sm9_verify_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + sm3_update(&ctx->sm3_ctx, data, datalen); + return 1; +} + +int sm9_verify_finish(SM9_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen, + const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen) +{ + int ret; + SM9_SIGNATURE signature; + + if (sm9_signature_from_der(&signature, &sig, &siglen) != 1 + || asn1_length_is_zero(siglen) != 1) { + error_print(); + return -1; + } + + if ((ret = sm9_do_verify(mpk, id, idlen, &ctx->sm3_ctx, &signature)) < 0) { + error_print(); + return -1; + } + return ret; +} + +int sm9_do_verify(const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen, + const SM3_CTX *sm3_ctx, const SM9_SIGNATURE *sig) +{ + sm9_fn_t h1; + sm9_fn_t h2; + sm9_fp12_t g; + sm9_fp12_t t; + sm9_fp12_t u; + sm9_fp12_t w; + SM9_TWIST_POINT P; + uint8_t wbuf[32 * 12]; + SM3_CTX ctx = *sm3_ctx; + SM3_CTX tmp_ctx; + uint8_t ct1[4] = {0,0,0,1}; + uint8_t ct2[4] = {0,0,0,2}; + uint8_t Ha[64]; + + // B1: check h in [1, N-1] + + // B2: check S in G1 + + // B3: g = e(P1, Ppubs) + sm9_pairing(g, &mpk->Ppubs, SM9_P1); + + // B4: t = g^h + sm9_fp12_pow(t, g, sig->h); + + // B5: h1 = H1(ID || hid, N) + sm9_hash1(h1, id, idlen, SM9_HID_SIGN); + + // B6: P = h1 * P2 + Ppubs + sm9_twist_point_mul_generator(&P, h1); + sm9_twist_point_add_full(&P, &P, &mpk->Ppubs); + + // B7: u = e(S, P) + sm9_pairing(u, &P, &sig->S); + + // B8: w = u * t + sm9_fp12_mul(w, u, t); + sm9_fp12_to_bytes(w, wbuf); + + // B9: h2 = H2(M || w, N), check h2 == h + sm3_update(&ctx, wbuf, sizeof(wbuf)); + tmp_ctx = ctx; + sm3_update(&ctx, ct1, sizeof(ct1)); + sm3_finish(&ctx, Ha); + sm3_update(&tmp_ctx, ct2, sizeof(ct2)); + sm3_finish(&tmp_ctx, Ha + 32); + sm9_fn_from_hash(h2, Ha); + if (sm9_fn_equ(h2, sig->h) != 1) { + return 0; + } + + return 1; +} + +int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, + size_t klen, uint8_t *kbuf, SM9_POINT *C) +{ + sm9_fn_t r; + sm9_fp12_t w; + uint8_t wbuf[32 * 12]; + uint8_t cbuf[65]; + SM3_KDF_CTX kdf_ctx; + + // A1: Q = H1(ID||hid,N) * P1 + Ppube + sm9_hash1(r, id, idlen, SM9_HID_ENC); + sm9_point_mul(C, r, SM9_P1); + sm9_point_add(C, C, &mpk->Ppube); + + do { + // A2: rand r in [1, N-1] + if (sm9_fn_rand(r) != 1) { + error_print(); + return -1; + } + + // A3: C1 = r * Q + sm9_point_mul(C, r, C); + sm9_point_to_uncompressed_octets(C, cbuf); + + // A4: g = e(Ppube, P2) + sm9_pairing(w, SM9_P2, &mpk->Ppube); + + // A5: w = g^r + sm9_fp12_pow(w, w, r); + sm9_fp12_to_bytes(w, wbuf); + + // A6: K = KDF(C || w || ID_B, klen), if K == 0, goto A2 + sm3_kdf_init(&kdf_ctx, klen); + sm3_kdf_update(&kdf_ctx, cbuf + 1, 64); + sm3_kdf_update(&kdf_ctx, wbuf, sizeof(wbuf)); + sm3_kdf_update(&kdf_ctx, (uint8_t *)id, idlen); + sm3_kdf_finish(&kdf_ctx, kbuf); + + } while (mem_is_zero(kbuf, klen) == 1); + + gmssl_secure_clear(&r, sizeof(r)); + gmssl_secure_clear(&w, sizeof(w)); + gmssl_secure_clear(wbuf, sizeof(wbuf)); + gmssl_secure_clear(&kdf_ctx, sizeof(kdf_ctx)); + + // A7: output (K, C) + return 1; +} + +int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const SM9_POINT *C, + size_t klen, uint8_t *kbuf) +{ + sm9_fp12_t w; + uint8_t wbuf[32 * 12]; + uint8_t cbuf[65]; + SM3_KDF_CTX kdf_ctx; + + // B1: check C in G1 + sm9_point_to_uncompressed_octets(C, cbuf); + + // B2: w = e(C, de); + sm9_pairing(w, &key->de, C); + sm9_fp12_to_bytes(w, wbuf); + + // B3: K = KDF(C || w || ID, klen) + sm3_kdf_init(&kdf_ctx, klen); + sm3_kdf_update(&kdf_ctx, cbuf + 1, 64); + sm3_kdf_update(&kdf_ctx, wbuf, sizeof(wbuf)); + sm3_kdf_update(&kdf_ctx, (uint8_t *)id, idlen); + sm3_kdf_finish(&kdf_ctx, kbuf); + + if (mem_is_zero(kbuf, klen)) { + error_print(); + return -1; + } + + gmssl_secure_clear(&w, sizeof(w)); + gmssl_secure_clear(wbuf, sizeof(wbuf)); + gmssl_secure_clear(&kdf_ctx, sizeof(kdf_ctx)); + + // B4: output K + return 1; +} + +int sm9_do_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, + SM9_POINT *C1, uint8_t *c2, uint8_t c3[SM3_HMAC_SIZE]) +{ + SM3_HMAC_CTX hmac_ctx; + uint8_t K[SM9_MAX_PLAINTEXT_SIZE + 32]; + + if (sm9_kem_encrypt(mpk, id, idlen, sizeof(K), K, C1) != 1) { + error_print(); + return -1; + } + gmssl_memxor(c2, K, in, inlen); + + //sm3_hmac(K + inlen, 32, c2, inlen, c3); + sm3_hmac_init(&hmac_ctx, K + inlen, SM3_HMAC_SIZE); + sm3_hmac_update(&hmac_ctx, c2, inlen); + sm3_hmac_finish(&hmac_ctx, c3); + gmssl_secure_clear(&hmac_ctx, sizeof(hmac_ctx)); + return 1; +} + +int sm9_do_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, + const SM9_POINT *C1, const uint8_t *c2, size_t c2len, const uint8_t c3[SM3_HMAC_SIZE], + uint8_t *out) +{ + SM3_HMAC_CTX hmac_ctx; + uint8_t k[SM9_MAX_PLAINTEXT_SIZE + SM3_HMAC_SIZE]; + uint8_t mac[SM3_HMAC_SIZE]; + + if (c2len > SM9_MAX_PLAINTEXT_SIZE) { + error_print(); + return -1; + } + + if (sm9_kem_decrypt(key, id, idlen, C1, sizeof(k), k) != 1) { + error_print(); + return -1; + } + //sm3_hmac(k + c2len, SM3_HMAC_SIZE, c2, c2len, mac); + sm3_hmac_init(&hmac_ctx, k + c2len, SM3_HMAC_SIZE); + sm3_hmac_update(&hmac_ctx, c2, c2len); + sm3_hmac_finish(&hmac_ctx, mac); + gmssl_secure_clear(&hmac_ctx, sizeof(hmac_ctx)); + + if (gmssl_secure_memcmp(c3, mac, sizeof(mac)) != 0) { + error_print(); + return -1; + } + gmssl_memxor(out, k, c2, c2len); + return 1; +} + +#define SM9_ENC_TYPE_XOR 0 +#define SM9_ENC_TYPE_ECB 1 +#define SM9_ENC_TYPE_CBC 2 +#define SM9_ENC_TYPE_OFB 4 +#define SM9_ENC_TYPE_CFB 8 + +/* +SM9Cipher ::= SEQUENCE { + EnType INTEGER, -- 0 for XOR + C1 BIT STRING, -- uncompressed octets of ECPoint + C3 OCTET STRING, -- 32 bytes HMAC-SM3 tag + CipherText OCTET STRING, +} +*/ +int sm9_ciphertext_to_der(const SM9_POINT *C1, const uint8_t *c2, size_t c2len, + const uint8_t c3[SM3_HMAC_SIZE], uint8_t **out, size_t *outlen) +{ + int en_type = SM9_ENC_TYPE_XOR; + uint8_t c1[65]; + size_t len = 0; + + if (sm9_point_to_uncompressed_octets(C1, c1) != 1) { + error_print(); + return -1; + } + if (asn1_int_to_der(en_type, NULL, &len) != 1 + || asn1_bit_octets_to_der(c1, sizeof(c1), NULL, &len) != 1 + || asn1_octet_string_to_der(c3, SM3_HMAC_SIZE, NULL, &len) != 1 + || asn1_octet_string_to_der(c2, c2len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(en_type, out, outlen) != 1 + || asn1_bit_octets_to_der(c1, sizeof(c1), out, outlen) != 1 + || asn1_octet_string_to_der(c3, SM3_HMAC_SIZE, out, outlen) != 1 + || asn1_octet_string_to_der(c2, c2len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_ciphertext_from_der(SM9_POINT *C1, const uint8_t **c2, size_t *c2len, + const uint8_t **c3, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int en_type; + const uint8_t *c1; + size_t c1len; + size_t c3len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(&en_type, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&c1, &c1len, &d, &dlen) != 1 + || asn1_octet_string_from_der(c3, &c3len, &d, &dlen) != 1 + || asn1_octet_string_from_der(c2, c2len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (en_type != SM9_ENC_TYPE_XOR) { + error_print(); + return -1; + } + if (c1len != 65) { + error_print(); + return -1; + } + if (c3len != SM3_HMAC_SIZE) { + error_print(); + return -1; + } + if (sm9_point_from_uncompressed_octets(C1, c1) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + SM9_POINT C1; + uint8_t c2[SM9_MAX_PLAINTEXT_SIZE]; + uint8_t c3[SM3_HMAC_SIZE]; + + if (inlen > SM9_MAX_PLAINTEXT_SIZE) { + error_print(); + return -1; + } + + if (sm9_do_encrypt(mpk, id, idlen, in, inlen, &C1, c2, c3) != 1) { + error_print(); + return -1; + } + *outlen = 0; + if (sm9_ciphertext_to_der(&C1, c2, inlen, c3, &out, outlen) != 1) { // FIXME: when out == NULL + error_print(); + return -1; + } + return 1; +} + +int sm9_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + SM9_POINT C1; + const uint8_t *c2; + size_t c2len; + const uint8_t *c3; + + if (sm9_ciphertext_from_der(&C1, &c2, &c2len, &c3, &in, &inlen) != 1 + || asn1_length_is_zero(inlen) != 1) { + error_print(); + return -1; + } + *outlen = c2len; + if (!out) { + return 1; + } + if (sm9_do_decrypt(key, id, idlen, &C1, c2, c2len, c3, out) != 1) { + error_print(); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/socket.c b/Core/GmSSL-3.1.1/src/socket.c new file mode 100644 index 0000000..6c4840b --- /dev/null +++ b/Core/GmSSL-3.1.1/src/socket.c @@ -0,0 +1,169 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +#ifdef WIN32 +int tls_socket_lib_init(void) +{ + WORD wVersion = MAKEWORD(2, 2); + WSADATA wsaData; + int err; + + if ((err = WSAStartup(wVersion, &wsaData)) != 0) { + fprintf(stderr, "WSAStartup() return error %d\n", err); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_lib_cleanup(void) +{ + if (WSACleanup() != 0) { + fprintf(stderr, "WSACleanup() return error %d\n", WSAGetLastError()); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_create(tls_socket_t *sock, int af, int type, int protocol) +{ + if (!sock) { + error_print(); + return -1; + } + if ((*sock = socket(af, type, protocol)) == INVALID_SOCKET) { + fprintf(stderr, "%s %d: socket error: %d\n", __FILE__, __LINE__, WSAGetLastError()); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_connect(tls_socket_t sock, const struct sockaddr_in *addr) +{ + int addr_len = (int)sizeof(struct sockaddr_in); + if (connect(sock, (const struct sockaddr *)addr, addr_len) == SOCKET_ERROR) { + fprintf(stderr, "%s %d: socket error: %d\n", __FILE__, __LINE__, WSAGetLastError()); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_bind(tls_socket_t sock, const struct sockaddr_in *addr) +{ + int addr_len = (int)sizeof(struct sockaddr_in); + if (bind(sock, (const struct sockaddr *)addr, addr_len) == SOCKET_ERROR) { + fprintf(stderr, "%s %d: socket bind error: %u\n", __FILE__, __LINE__, WSAGetLastError()); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_listen(tls_socket_t sock, int backlog) +{ + if (listen(sock, backlog) == SOCKET_ERROR) { + fprintf(stderr, "%s %d: socket listen error: %u\n", __FILE__, __LINE__, WSAGetLastError()); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_accept(tls_socket_t sock, struct sockaddr_in *addr, tls_socket_t *conn_sock) +{ + int addr_len = (int)sizeof(struct sockaddr_in); + if ((*conn_sock = accept(sock, (struct sockaddr *)addr, &addr_len)) == INVALID_SOCKET) { + fprintf(stderr, "%s %d: accept error: %u\n", __FILE__, __LINE__, WSAGetLastError()); + error_print(); + return -1; + } + return 1; +} + +#else + +int tls_socket_lib_init(void) +{ + return 1; +} + +int tls_socket_lib_cleanup(void) +{ + return 1; +} + +int tls_socket_create(tls_socket_t *sock, int af, int type, int protocol) +{ + if (!sock) { + error_print(); + return -1; + } + if ((*sock = socket(af, type, protocol)) == -1) { + fprintf(stderr, "%s %d: socket error: %s\n", __FILE__, __LINE__, strerror(errno)); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_connect(tls_socket_t sock, const struct sockaddr_in *addr) +{ + socklen_t addr_len = sizeof(struct sockaddr_in); + if (connect(sock, (const struct sockaddr *)addr, addr_len) == -1) { + fprintf(stderr, "%s %d: socket error: %s\n", __FILE__, __LINE__, strerror(errno)); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_bind(tls_socket_t sock, const struct sockaddr_in *addr) +{ + socklen_t addr_len = (socklen_t)sizeof(struct sockaddr_in); + if (bind(sock, (const struct sockaddr *)addr, addr_len) == -1) { + fprintf(stderr, "%s %d: socket bind error: %s\n", __FILE__, __LINE__, strerror(errno)); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_listen(tls_socket_t sock, int backlog) +{ + if (listen(sock, backlog) == -1) { + fprintf(stderr, "%s %d: socket listen error: %s\n", __FILE__, __LINE__, strerror(errno)); + error_print(); + return -1; + } + return 1; +} + +int tls_socket_accept(tls_socket_t sock, struct sockaddr_in *addr, tls_socket_t *conn_sock) +{ + socklen_t addr_len = (socklen_t)sizeof(struct sockaddr_in); + if ((*conn_sock = accept(sock, (struct sockaddr *)addr, &addr_len)) == -1) { + fprintf(stderr, "%s %d: accept: %s\n", __FILE__, __LINE__, strerror(errno)); + error_print(); + return -1; + } + return 1; +} +#endif diff --git a/Core/GmSSL-3.1.1/src/tlcp.c b/Core/GmSSL-3.1.1/src/tlcp.c new file mode 100644 index 0000000..014734f --- /dev/null +++ b/Core/GmSSL-3.1.1/src/tlcp.c @@ -0,0 +1,1006 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const int tlcp_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3 }; +static const size_t tlcp_ciphers_count = sizeof(tlcp_ciphers)/sizeof(tlcp_ciphers[0]); + +void printbyte(uint8_t *ptr, int len, char *name) { + fprintf(stderr, "%s", name); + for (int i = 0; i < len; i++) { + if (i % 16 == 0) + fprintf(stderr, "\n"); + fprintf(stderr, "0x%02X ", ptr[i]); + } + fprintf(stderr, "\n"); +} + +int tlcp_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent) +{ + // 目前只支持TLCP的ECC公钥加密套件,因此不论用哪个套件解析都是一样的 + // 如果未来支持ECDHE套件,可以将函数改为宏,直接传入 (conn->cipher_suite << 8) + format |= tlcp_ciphers[0] << 8; + return tls_record_print(fp, record, recordlen, format, indent); +} + +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; + size_t len = 0; + + if (!record || !recordlen || !sig || !siglen) { + error_print(); + return -1; + } + if (siglen > SM2_MAX_SIGNATURE_SIZE) { + error_print(); + return -1; + } + if (tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + return -1; + } + p = tls_handshake_data(tls_record_data(record)); + // 注意TLCP的ServerKeyExchange中的签名值需要封装在uint16array中 + // 但是CertificateVerify中直接装载签名值DER + tls_uint16array_to_bytes(sig, siglen, &p, &len); + tls_record_set_handshake(record, recordlen, type, NULL, len); + return 1; +} + +int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record, + const 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 (tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + return -1; + } + if (tls_uint16array_from_bytes(sig, siglen, &p, &len) != 1) { + error_print(); + return -1; + } + if (len) { + error_print(); + return -1; + } + 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; + size_t siglen; + + format_print(fp, format, indent, "ServerKeyExchange\n"); + indent += 4; + if (tls_uint16array_from_bytes(&sig, &siglen, &data, &datalen) != 1) { + error_print(); + return -1; + } + format_bytes(fp, format, indent, "signature", sig, siglen); + if (datalen) { + error_print(); + return -1; + } + return 1; +} + +int tlcp_do_connect(TLS_CONNECT *conn) +{ + int ret = -1; + uint8_t *record = conn->record; + uint8_t finished_record[TLS_FINISHED_RECORD_BUF_SIZE]; + size_t recordlen, finished_record_len; + + uint8_t client_random[32]; + uint8_t server_random[32]; + int protocol; + int cipher_suite; + const uint8_t *random; + const uint8_t *session_id; + size_t session_id_len; + const uint8_t *exts; + size_t exts_len; + + SM2_KEY server_sign_key; + SM2_KEY server_enc_key; + SM2_SIGN_CTX verify_ctx; + SM2_SIGN_CTX sign_ctx; + const uint8_t *sig; + size_t siglen; + uint8_t pre_master_secret[48]; + uint8_t enced_pre_master_secret[SM2_MAX_CIPHERTEXT_SIZE]; + size_t enced_pre_master_secret_len; + SM3_CTX sm3_ctx; + SM3_CTX tmp_sm3_ctx; + uint8_t sm3_hash[32]; + const uint8_t *verify_data; + size_t verify_data_len; + uint8_t local_verify_data[12]; + + int handshake_type; + const uint8_t *server_enc_cert; + size_t server_enc_cert_len; + uint8_t server_enc_cert_lenbuf[3]; + const uint8_t *cp; + uint8_t *p; + size_t len; + + int depth = 5; + int alert = 0; + int verify_result; + + + // 初始化记录缓冲 + tls_record_set_protocol(record, TLS_protocol_tlcp); + tls_record_set_protocol(finished_record, TLS_protocol_tlcp); + + // 准备Finished Context(和ClientVerify) + sm3_init(&sm3_ctx); + + // send ClientHello + tls_random_generate(client_random); + if (tls_record_set_handshake_client_hello(record, &recordlen, + TLS_protocol_tlcp, client_random, NULL, 0, + tlcp_ciphers, tlcp_ciphers_count, NULL, 0) != 1) { + error_print(); + goto end; + } + tls_trace("send ClientHello\n"); + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // recv ServerHello + tls_trace("recv ServerHello\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + if (tls_record_get_handshake_server_hello(record, + &protocol, &random, &session_id, &session_id_len, &cipher_suite, + &exts, &exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (protocol != TLS_protocol_tlcp) { + tls_send_alert(conn, TLS_alert_protocol_version); + error_print(); + goto end; + } + if (tls_cipher_suite_in_list(cipher_suite, tlcp_ciphers, tlcp_ciphers_count) != 1) { + tls_send_alert(conn, TLS_alert_handshake_failure); + error_print(); + goto end; + } + if (exts) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + memcpy(server_random, random, 32); + memcpy(conn->session_id, session_id, session_id_len); + conn->cipher_suite = cipher_suite; + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // recv ServerCertificate + tls_trace("recv ServerCertificate\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + + if (tls_record_get_handshake_certificate(record, + conn->server_certs, &conn->server_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // verify ServerCertificate + if (conn->ca_certs_len) { + // 只有提供了CA证书才验证服务器证书链 + // FIXME: 逻辑需要再检查 + if (x509_certs_verify_tlcp(conn->server_certs, conn->server_certs_len, X509_cert_chain_server, + conn->ca_certs, conn->ca_certs_len, depth, &verify_result) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + } + + // recv ServerKeyExchange + tls_trace("recv ServerKeyExchange\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tlcp_record_get_handshake_server_key_exchange_pke(record, &sig, &siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // verify ServerKeyExchange + if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cp, &len) != 1 + || x509_cert_get_subject_public_key(cp, len, &server_sign_key) != 1 + || x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1, &server_enc_cert, &server_enc_cert_len) != 1 + || x509_cert_get_subject_public_key(server_enc_cert, server_enc_cert_len, &server_enc_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + p = server_enc_cert_lenbuf; len = 0; + tls_uint24_to_bytes((uint24_t)server_enc_cert_len, &p, &len); + if (sm2_verify_init(&verify_ctx, &server_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 + || sm2_verify_update(&verify_ctx, client_random, 32) != 1 + || sm2_verify_update(&verify_ctx, server_random, 32) != 1 + || sm2_verify_update(&verify_ctx, server_enc_cert_lenbuf, 3) != 1 + || sm2_verify_update(&verify_ctx, server_enc_cert, server_enc_cert_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (sm2_verify_finish(&verify_ctx, sig, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + + // recv CertificateRequest or ServerHelloDone + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp + || tls_record_get_handshake(record, &handshake_type, &cp, &len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (handshake_type == TLS_handshake_certificate_request) { + const uint8_t *cert_types; + size_t cert_types_len; + const uint8_t *ca_names; + size_t ca_names_len; + + // recv CertificateRequest + tls_trace("recv CertificateRequest\n"); + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate_request(record, + &cert_types, &cert_types_len, &ca_names, &ca_names_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if(!conn->client_certs_len) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_cert_types_accepted(cert_types, cert_types_len, conn->client_certs, conn->client_certs_len) != 1 + || tls_authorities_issued_certificate(ca_names, ca_names_len, conn->client_certs, conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unsupported_certificate); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // recv ServerHelloDone + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + } else { + // 这个得处理一下 + conn->client_certs_len = 0; + gmssl_secure_clear(&conn->sign_key, sizeof(SM2_KEY)); + //client_sign_key = NULL; + } + tls_trace("recv ServerHelloDone\n"); + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_server_hello_done(record) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // send ClientCertificate + if (conn->client_certs_len) { + tls_trace("send ClientCertificate\n"); + if (tls_record_set_handshake_certificate(record, &recordlen, conn->client_certs, conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + } + + // generate MASTER_SECRET + tls_trace("generate secrets\n"); + if (tls_pre_master_secret_generate(pre_master_secret, TLS_protocol_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(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + 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, 48, + client_random, server_random, + conn->master_secret, + conn->key_block, 96, + 0, 4); + */ + + // send ClientKeyExchange + tls_trace("send ClientKeyExchange\n"); + if (sm2_encrypt(&server_enc_key, pre_master_secret, 48, + enced_pre_master_secret, &enced_pre_master_secret_len) != 1 + || tls_record_set_handshake_client_key_exchange_pke(record, &recordlen, + enced_pre_master_secret, enced_pre_master_secret_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // send CertificateVerify + if (conn->client_certs_len) { + tls_trace("send CertificateVerify\n"); + + SM3_CTX cert_verify_sm3_ctx = sm3_ctx; + uint8_t cert_verify_hash[SM3_DIGEST_SIZE]; + uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE]; + + sm3_finish(&cert_verify_sm3_ctx, cert_verify_hash); + if (sm2_sign_init(&sign_ctx, &conn->sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 + || sm2_sign_update(&sign_ctx, cert_verify_hash, SM3_DIGEST_SIZE) != 1 + || sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_set_handshake_certificate_verify(record, &recordlen, sigbuf, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + } + + // send [ChangeCipherSpec] + tls_trace("send [ChangeCipherSpec]\n"); + if (tls_record_set_change_cipher_spec(record, &recordlen) !=1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + // send Client Finished + tls_trace("send 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(local_verify_data), local_verify_data) != 1 + || tls_record_set_handshake_finished(finished_record, &finished_record_len, + local_verify_data, sizeof(local_verify_data)) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); + sm3_update(&sm3_ctx, finished_record + 5, finished_record_len - 5); + + // encrypt Client Finished + tls_trace("encrypt Finished\n"); + if (tls_record_encrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key, + conn->client_seq_num, finished_record, finished_record_len, record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + tls_seq_num_incr(conn->client_seq_num); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + // [ChangeCipherSpec] + tls_trace("recv [ChangeCipherSpec]\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_change_cipher_spec(record) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + + // Finished + tls_trace("recv Finished\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (recordlen > sizeof(finished_record)) { + error_print(); // 解密可能导致 finished_record 溢出 + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + tls_trace("decrypt Finished\n"); + if (tls_record_decrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key, + conn->server_seq_num, record, recordlen, finished_record, &finished_record_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); + tls_seq_num_incr(conn->server_seq_num); + if (tls_record_get_handshake_finished(finished_record, &verify_data, &verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (verify_data_len != sizeof(local_verify_data)) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + 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(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + fprintf(stderr, "Connection established!\n"); + + + conn->protocol = TLS_protocol_tlcp; + conn->cipher_suite = cipher_suite; + + ret = 1; + +end: + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret)); + return ret; +} + +int tlcp_do_accept(TLS_CONNECT *conn) +{ + int ret = -1; + + int client_verify = 0; + + uint8_t *record = conn->record; + uint8_t finished_record[TLS_FINISHED_RECORD_BUF_SIZE]; // 解密可能导致前面的record被覆盖 + size_t recordlen, finished_record_len; + const int server_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3 }; // 未来应该支持GCM/CBC两个套件 + + // ClientHello, ServerHello + uint8_t client_random[32]; + uint8_t server_random[32]; + int protocol; + const uint8_t *random; + const uint8_t *session_id; // TLCP服务器忽略客户端SessionID,也不主动设置SessionID + size_t session_id_len; + const uint8_t *client_ciphers; + size_t client_ciphers_len; + const uint8_t *exts; + size_t exts_len; + + // ServerKeyExchange + const uint8_t *server_enc_cert; + size_t server_enc_cert_len; + uint8_t server_enc_cert_lenbuf[3]; + SM2_SIGN_CTX sign_ctx; + uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + // ClientCertificate, CertificateVerify + SM2_KEY client_sign_key; + SM2_SIGN_CTX verify_ctx; + const uint8_t *sig; + const int verify_depth = 5; + int verify_result; + + // ClientKeyExchange + const uint8_t *enced_pms; + size_t enced_pms_len; + uint8_t pre_master_secret[SM2_MAX_PLAINTEXT_SIZE]; // sm2_decrypt 保证输出不会溢出 + size_t pre_master_secret_len; + + // Finished + SM3_CTX sm3_ctx; + SM3_CTX tmp_sm3_ctx; + uint8_t sm3_hash[32]; + uint8_t local_verify_data[12]; + const uint8_t *verify_data; + size_t verify_data_len; + + uint8_t *p; + const uint8_t *cp; + size_t len; + + + // 服务器端如果设置了CA + if (conn->ca_certs_len) + client_verify = 1; + + // 初始化Finished和客户端验证环境 + sm3_init(&sm3_ctx); + + + // recv ClientHello + tls_trace("recv ClientHello\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + if (tls_record_get_handshake_client_hello(record, + &protocol, &random, &session_id, &session_id_len, + &client_ciphers, &client_ciphers_len, + &exts, &exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (protocol != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + memcpy(client_random, random, 32); + if (tls_cipher_suites_select(client_ciphers, client_ciphers_len, + server_ciphers, sizeof(server_ciphers)/sizeof(server_ciphers[0]), + &conn->cipher_suite) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_insufficient_security); + goto end; + } + if (exts) { + // 忽略客户端扩展错误可以兼容错误的TLCP客户端实现 + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // send ServerHello + tls_trace("send ServerHello\n"); + tls_random_generate(server_random); + if (tls_record_set_handshake_server_hello(record, &recordlen, + TLS_protocol_tlcp, server_random, NULL, 0, + conn->cipher_suite, NULL, 0) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // send ServerCertificate + tls_trace("send ServerCertificate\n"); + if (tls_record_set_handshake_certificate(record, &recordlen, + conn->server_certs, conn->server_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // send ServerKeyExchange + tls_trace("send ServerKeyExchange\n"); + if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1, + &server_enc_cert, &server_enc_cert_len) != 1) { + error_print(); + goto end; + } + p = server_enc_cert_lenbuf; len = 0; + tls_uint24_to_bytes((uint24_t)server_enc_cert_len, &p, &len); + if (sm2_sign_init(&sign_ctx, &conn->sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 + || sm2_sign_update(&sign_ctx, client_random, 32) != 1 + || sm2_sign_update(&sign_ctx, server_random, 32) != 1 + || sm2_sign_update(&sign_ctx, server_enc_cert_lenbuf, 3) != 1 + || sm2_sign_update(&sign_ctx, server_enc_cert, server_enc_cert_len) != 1 + || sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tlcp_record_set_handshake_server_key_exchange_pke(record, &recordlen, sigbuf, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // send CertificateRequest + if (client_verify) { + const uint8_t cert_types[] = { TLS_cert_type_ecdsa_sign }; + uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE] = {0}; // TODO: 根据客户端验证CA证书列计算缓冲大小,或直接输出到record缓冲 + size_t ca_names_len = 0; + + tls_trace("send CertificateRequest\n"); + if (tls_authorities_from_certs(ca_names, &ca_names_len, sizeof(ca_names), + conn->ca_certs, conn->ca_certs_len) != 1) { + error_print(); + goto end; + } + if (tls_record_set_handshake_certificate_request(record, &recordlen, + cert_types, sizeof(cert_types), + ca_names, ca_names_len) != 1) { + error_print(); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + } + + // send ServerHelloDone + tls_trace("send ServerHelloDone\n"); + tls_record_set_handshake_server_hello_done(record, &recordlen); + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // recv ClientCertificate + if (conn->ca_certs_len) { + tls_trace("recv ClientCertificate\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate(record, conn->client_certs, &conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (x509_certs_verify(conn->client_certs, conn->client_certs_len, X509_cert_chain_client, + conn->ca_certs, conn->ca_certs_len, verify_depth, &verify_result) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + } + + // ClientKeyExchange + tls_trace("recv ClientKeyExchange\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_client_key_exchange_pke(record, &enced_pms, &enced_pms_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (sm2_decrypt(&conn->kenc_key, enced_pms, enced_pms_len, + pre_master_secret, &pre_master_secret_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + if (pre_master_secret_len != 48) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + + // recv CertificateVerify + if (client_verify) { + tls_trace("recv CertificateVerify\n"); + SM3_CTX cert_verify_sm3_ctx = sm3_ctx; + uint8_t cert_verify_hash[SM3_DIGEST_SIZE]; + + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + tls_send_alert(conn, TLS_alert_unexpected_message); + error_print(); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate_verify(record, &sig, &siglen) != 1) { + tls_send_alert(conn, TLS_alert_unexpected_message); + error_print(); + goto end; + } + if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len, 0, &cp, &len) != 1 + || x509_cert_get_subject_public_key(cp, len, &client_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + + sm3_finish(&cert_verify_sm3_ctx, cert_verify_hash); + if (sm2_verify_init(&verify_ctx, &client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 + || sm2_verify_update(&verify_ctx, cert_verify_hash, SM3_DIGEST_SIZE) != 1 + || sm2_verify_finish(&verify_ctx, sig, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + } + + // generate secrets + 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 + || tls_prf(conn->master_secret, 48, "key expansion", + server_random, 32, client_random, 32, + 96, conn->key_block) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + 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, 48, + client_random, server_random, + conn->master_secret, + conn->key_block, 96, + 0, 4); + */ + + // recv [ChangeCipherSpec] + tls_trace("recv [ChangeCipherSpec]\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_change_cipher_spec(record) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + + // recv ClientFinished + tls_trace("recv Finished\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != TLS_protocol_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (recordlen > sizeof(finished_record)) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + + // decrypt ClientFinished + tls_trace("decrypt Finished\n"); + if (tls_record_decrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key, + conn->client_seq_num, record, recordlen, finished_record, &finished_record_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); + tls_seq_num_incr(conn->client_seq_num); + if (tls_record_get_handshake_finished(finished_record, &verify_data, &verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + if (verify_data_len != sizeof(local_verify_data)) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + + // verify ClientFinished + memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(SM3_CTX)); + sm3_update(&sm3_ctx, finished_record + 5, finished_record_len - 5); + sm3_finish(&tmp_sm3_ctx, sm3_hash); + if (tls_prf(conn->master_secret, 48, "client finished", sm3_hash, 32, NULL, 0, + sizeof(local_verify_data), local_verify_data) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { + error_puts("client_finished.verify_data verification failure"); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + + // send [ChangeCipherSpec] + tls_trace("send [ChangeCipherSpec]\n"); + if (tls_record_set_change_cipher_spec(record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + // send ServerFinished + tls_trace("send Finished\n"); + 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 + || tls_record_set_handshake_finished(finished_record, &finished_record_len, + local_verify_data, sizeof(local_verify_data)) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); + if (tls_record_encrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key, + conn->server_seq_num, finished_record, finished_record_len, record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls_trace("encrypt Finished\n"); + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + tls_seq_num_incr(conn->server_seq_num); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + conn->protocol = TLS_protocol_tlcp; + + fprintf(stderr, "Connection Established!\n\n"); + ret = 1; + +end: + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret)); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/tls.c b/Core/GmSSL-3.1.1/src/tls.c new file mode 100644 index 0000000..bd094eb --- /dev/null +++ b/Core/GmSSL-3.1.1/src/tls.c @@ -0,0 +1,2307 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +void tls_uint8_to_bytes(uint8_t a, uint8_t **out, size_t *outlen) +{ + if (out && *out) { + *(*out)++ = a; + } + (*outlen)++; +} + +void tls_uint16_to_bytes(uint16_t a, uint8_t **out, size_t *outlen) +{ + if (out && *out) { + *(*out)++ = (uint8_t)(a >> 8); + *(*out)++ = (uint8_t)a; + } + *outlen += 2; +} + +void tls_uint24_to_bytes(uint24_t a, uint8_t **out, size_t *outlen) +{ + if (out && *out) { + *(*out)++ = (uint8_t)(a >> 16); + *(*out)++ = (uint8_t)(a >> 8); + *(*out)++ = (uint8_t)(a); + } + (*outlen) += 3; +} + +void tls_uint32_to_bytes(uint32_t a, uint8_t **out, size_t *outlen) +{ + if (out && *out) { + *(*out)++ = (uint8_t)(a >> 24); + *(*out)++ = (uint8_t)(a >> 16); + *(*out)++ = (uint8_t)(a >> 8); + *(*out)++ = (uint8_t)(a ); + } + (*outlen) += 4; +} + +void tls_array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) +{ + if (out && *out) { + if (data) { + memcpy(*out, data, datalen); + } + *out += datalen; + } + *outlen += datalen; +} + +/* +这几个函数要区分data = NULL, datalen = 0 和 data = NULL, datalen != 0的情况 +前者意味着数据为空,因此输出的就是一个长度 +后者意味着数据不为空,只是我们不想输出数据,只输出头部的长度,并且更新整个的输出长度。 这种情况应该避免! + +*/ + +void tls_uint8array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) +{ + tls_uint8_to_bytes((uint8_t)datalen, out, outlen); + tls_array_to_bytes(data, datalen, out, outlen); +} + +void tls_uint16array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) +{ + tls_uint16_to_bytes((uint16_t)datalen, out, outlen); + tls_array_to_bytes(data, datalen, out, outlen); +} + +void tls_uint24array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) +{ + tls_uint24_to_bytes((uint24_t)datalen, out, outlen); + tls_array_to_bytes(data, datalen, out, outlen); +} + +int tls_uint8_from_bytes(uint8_t *a, const uint8_t **in, size_t *inlen) +{ + if (*inlen < 1) { + error_print(); + return -1; + } + *a = *(*in)++; + (*inlen)--; + return 1; +} + +int tls_uint16_from_bytes(uint16_t *a, const uint8_t **in, size_t *inlen) +{ + if (*inlen < 2) { + error_print(); + return -1; + } + *a = *(*in)++; + *a <<= 8; + *a |= *(*in)++; + *inlen -= 2; + return 1; +} + +int tls_uint24_from_bytes(uint24_t *a, const uint8_t **in, size_t *inlen) +{ + if (*inlen < 3) { + error_print(); + return -1; + } + *a = *(*in)++; + *a <<= 8; + *a |= *(*in)++; + *a <<= 8; + *a |= *(*in)++; + *inlen -= 3; + return 1; +} + +int tls_uint32_from_bytes(uint32_t *a, const uint8_t **in, size_t *inlen) +{ + if (*inlen < 4) { + error_print(); + return -1; + } + *a = *(*in)++; + *a <<= 8; + *a |= *(*in)++; + *a <<= 8; + *a |= *(*in)++; + *a <<= 8; + *a |= *(*in)++; + *inlen -= 4; + return 1; +} + +int tls_array_from_bytes(const uint8_t **data, size_t datalen, const uint8_t **in, size_t *inlen) +{ + if (*inlen < datalen) { + error_print(); + return -1; + } + *data = *in; + *in += datalen; + *inlen -= datalen; + return 1; +} + +int tls_uint8array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) +{ + uint8_t len; + if (tls_uint8_from_bytes(&len, in, inlen) != 1 + || tls_array_from_bytes(data, len, in, inlen) != 1) { + error_print(); + return -1; + } + if (!len) { + *data = NULL; + } + *datalen = len; + return 1; +} + +int tls_uint16array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) +{ + uint16_t len; + if (tls_uint16_from_bytes(&len, in, inlen) != 1 + || tls_array_from_bytes(data, len, in, inlen) != 1) { + error_print(); + return -1; + } + if (!len) { + *data = NULL; + } + *datalen = len; + return 1; +} + +int tls_uint24array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) +{ + uint24_t len; + if (tls_uint24_from_bytes(&len, in, inlen) != 1 + || tls_array_from_bytes(data, len, in, inlen) != 1) { + error_print(); + return -1; + } + if (!len) { + *data = NULL; + } + *datalen = len; + return 1; +} + +int tls_length_is_zero(size_t len) +{ + if (len) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_set_type(uint8_t *record, int type) +{ + if (!tls_record_type_name(type)) { + error_print(); + return -1; + } + record[0] = (uint8_t)type; + return 1; +} + +int tls_record_set_protocol(uint8_t *record, int protocol) +{ + if (!tls_protocol_name(protocol)) { + error_print(); + return -1; + } + record[1] = (uint8_t)(protocol >> 8); + record[2] = (uint8_t)(protocol); + return 1; +} + +int tls_record_set_length(uint8_t *record, size_t length) +{ + uint8_t *p = record + 3; + size_t len; + if (length > TLS_MAX_CIPHERTEXT_SIZE) { + error_print(); + return -1; + } + tls_uint16_to_bytes((uint16_t)length, &p, &len); + return 1; +} + +int tls_record_set_data(uint8_t *record, const uint8_t *data, size_t datalen) +{ + if (tls_record_set_length(record, datalen) != 1) { + error_print(); + return -1; + } + memcpy(tls_record_data(record), data, datalen); + 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_msg("invalid tls record data length %zu\n", inlen); + return -1; + } + if ((((size_t)header[3]) << 8) + header[4] != inlen) { + error_print(); + 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] = (uint8_t)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; + uint8_t hmac[32]; + 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_msg("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_puts("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] = (uint8_t)((*outlen) >> 8); + header[4] = (uint8_t)(*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); + sm3_hmac_finish(&hmac_ctx, hmac); + if (gmssl_secure_memcmp(mac, hmac, sizeof(hmac)) != 0) { + error_puts("tls ciphertext mac check failure\n"); + return -1; + } + return 1; +} + +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) +{ + if (tls_cbc_encrypt(hmac_ctx, cbc_key, seq_num, in, + in + 5, inlen - 5, + out + 5, outlen) != 1) { + error_print(); + return -1; + } + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = (uint8_t)((*outlen) >> 8); + out[4] = (uint8_t)(*outlen); + (*outlen) += 5; + return 1; +} + +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) +{ + if (tls_cbc_decrypt(hmac_ctx, cbc_key, seq_num, in, + in + 5, inlen - 5, + out + 5, outlen) != 1) { + error_print(); + return -1; + } + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = (uint8_t)((*outlen) >> 8); + out[4] = (uint8_t)(*outlen); + (*outlen) += 5; + + return 1; +} + +int tls_random_generate(uint8_t random[32]) +{ + uint32_t gmt_unix_time = (uint32_t)time(NULL); + uint8_t *p = random; + size_t len = 0; + tls_uint32_to_bytes(gmt_unix_time, &p, &len); + if (rand_bytes(random + 4, 28) != 1) { + error_print(); + return -1; + } + return 1; +} + +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_pre_master_secret_generate(uint8_t pre_master_secret[48], int protocol) +{ + if (!tls_protocol_name(protocol)) { + error_print(); + return -1; + } + pre_master_secret[0] = (uint8_t)(protocol >> 8); + pre_master_secret[1] = (uint8_t)(protocol); + if (rand_bytes(pre_master_secret + 2, 46) != 1) { + error_print(); + return -1; + } + return 1; +} + +// 用于设置CertificateRequest +int tls_cert_type_from_oid(int oid) +{ + switch (oid) { + case OID_sm2sign_with_sm3: + case OID_ecdsa_with_sha1: + case OID_ecdsa_with_sha224: + case OID_ecdsa_with_sha256: + case OID_ecdsa_with_sha512: + return TLS_cert_type_ecdsa_sign; + case OID_rsasign_with_sm3: + case OID_rsasign_with_md5: + case OID_rsasign_with_sha1: + case OID_rsasign_with_sha224: + case OID_rsasign_with_sha256: + case OID_rsasign_with_sha384: + case OID_rsasign_with_sha512: + return TLS_cert_type_rsa_sign; + } + // TLS_cert_type_xxx 中没有为0的值 + return 0; +} + +// 这两个函数没有对应的TLCP版本 +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] = (uint8_t)(curve >> 8); + server_ecdh_params[2] = (uint8_t)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_DEFAULT_ID_LENGTH); + sm2_sign_update(&sign_ctx, client_random, 32); + sm2_sign_update(&sign_ctx, server_random, 32); + sm2_sign_update(&sign_ctx, server_ecdh_params, 69); + 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 > SM2_MAX_SIGNATURE_SIZE) { + error_print(); + return -1; + } + server_ecdh_params[0] = TLS_curve_type_named_curve; + server_ecdh_params[1] = (uint8_t)(curve >> 8); + server_ecdh_params[2] = (uint8_t)(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_DEFAULT_ID_LENGTH); + sm2_verify_update(&verify_ctx, client_random, 32); + sm2_verify_update(&verify_ctx, server_random, 32); + sm2_verify_update(&verify_ctx, server_ecdh_params, 69); + ret = sm2_verify_finish(&verify_ctx, sig, siglen); + if (ret != 1) error_print(); + return ret; +} + +int tls_record_set_handshake(uint8_t *record, size_t *recordlen, + int type, const uint8_t *data, size_t datalen) +{ + size_t handshakelen; + + if (!record || !recordlen) { + error_print(); + return -1; + } + // 由于ServerHelloDone没有负载数据,因此允许 data,datalen = NULL,0 + if (datalen > TLS_MAX_PLAINTEXT_SIZE - TLS_HANDSHAKE_HEADER_SIZE) { + error_print(); + return -1; + } + if (!tls_protocol_name(tls_record_protocol(record))) { + error_print(); + return -1; + } + if (!tls_handshake_type_name(type)) { + error_print(); + return -1; + } + handshakelen = TLS_HANDSHAKE_HEADER_SIZE + datalen; + record[0] = TLS_record_handshake; + record[3] = (uint8_t)(handshakelen >> 8); + record[4] = (uint8_t)(handshakelen); + record[5] = (uint8_t)(type); + record[6] = (uint8_t)(datalen >> 16); + record[7] = (uint8_t)(datalen >> 8); + record[8] = (uint8_t)(datalen); + if (data) { + memcpy(tls_handshake_data(tls_record_data(record)), data, datalen); + } + *recordlen = TLS_RECORD_HEADER_SIZE + handshakelen; + return 1; +} + +int tls_record_get_handshake(const uint8_t *record, + int *type, const uint8_t **data, size_t *datalen) +{ + const uint8_t *handshake; + size_t handshake_len; + uint24_t handshake_datalen; + + if (!record || !type || !data || !datalen) { + error_print(); + return -1; + } + if (!tls_protocol_name(tls_record_protocol(record))) { + error_print(); + return -1; + } + if (tls_record_type(record) != TLS_record_handshake) { + error_print(); + return -1; + } + handshake = tls_record_data(record); + handshake_len = tls_record_data_length(record); + + if (handshake_len < TLS_HANDSHAKE_HEADER_SIZE) { + error_print(); + return -1; + } + if (handshake_len > TLS_MAX_PLAINTEXT_SIZE) { + // 不支持证书长度超过记录长度的特殊情况 + error_print(); + return -1; + } + + if (!tls_handshake_type_name(handshake[0])) { + error_print(); + return -1; + } + *type = handshake[0]; + + handshake++; + handshake_len--; + if (tls_uint24_from_bytes(&handshake_datalen, &handshake, &handshake_len) != 1) { + error_print(); + return -1; + } + if (handshake_len != handshake_datalen) { + error_print(); + return -1; + } + *data = handshake; + *datalen = handshake_datalen; + + if (*datalen == 0) { + *data = NULL; + } + return 1; +} + +int tls_record_set_handshake_client_hello(uint8_t *record, size_t *recordlen, + int protocol, 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) +{ + uint8_t type = TLS_handshake_client_hello; + uint8_t *p; + size_t len; + + if (!record || !recordlen || !random || !cipher_suites || !cipher_suites_count) { + error_print(); + return -1; + } + if (session_id) { + if (!session_id_len + || session_id_len < TLS_MAX_SESSION_ID_SIZE + || session_id_len > TLS_MAX_SESSION_ID_SIZE) { + error_print(); + return -1; + } + } + if (cipher_suites_count > TLS_MAX_CIPHER_SUITES_COUNT) { + error_print(); + return -1; + } + if (exts && !exts_len) { + error_print(); + return -1; + } + + + p = tls_handshake_data(tls_record_data(record)); + len = 0; + + if (!tls_protocol_name(protocol)) { + error_print(); + return -1; + } + tls_uint16_to_bytes((uint16_t)protocol, &p, &len); + tls_array_to_bytes(random, 32, &p, &len); + tls_uint8array_to_bytes(session_id, session_id_len, &p, &len); + tls_uint16_to_bytes((uint16_t)(cipher_suites_count * 2), &p, &len); + while (cipher_suites_count--) { + if (!tls_cipher_suite_name(*cipher_suites)) { + error_print(); + return -1; + } + tls_uint16_to_bytes((uint16_t)*cipher_suites, &p, &len); + cipher_suites++; + } + tls_uint8_to_bytes(1, &p, &len); + tls_uint8_to_bytes((uint8_t)TLS_compression_null, &p, &len); + if (exts) { + size_t tmp_len = len; + if (protocol < TLS_protocol_tls12) { + error_print(); + return -1; + } + tls_uint16array_to_bytes(exts, exts_len, NULL, &tmp_len); + if (tmp_len > TLS_MAX_HANDSHAKE_DATA_SIZE) { + error_print(); + return -1; + } + tls_uint16array_to_bytes(exts, exts_len, &p, &len); + } + if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_get_handshake_client_hello(const uint8_t *record, + int *protocol, const uint8_t **random, + const uint8_t **session_id, size_t *session_id_len, + const uint8_t **cipher_suites, size_t *cipher_suites_len, + const uint8_t **exts, size_t *exts_len) +{ + int type; + const uint8_t *p; + size_t len; + uint16_t ver; + const uint8_t *comp_meths; + size_t comp_meths_len; + + if (!record || !protocol || !random + || !session_id || !session_id_len + || !cipher_suites || !cipher_suites_len + || !exts || !exts_len) { + error_print(); + return -1; + } + if (tls_record_get_handshake(record, &type, &p, &len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_client_hello) { + error_print(); + return -1; + } + if (tls_uint16_from_bytes(&ver, &p, &len) != 1 + || tls_array_from_bytes(random, 32, &p, &len) != 1 + || tls_uint8array_from_bytes(session_id, session_id_len, &p, &len) != 1 + || tls_uint16array_from_bytes(cipher_suites, cipher_suites_len, &p, &len) != 1 + || tls_uint8array_from_bytes(&comp_meths, &comp_meths_len, &p, &len) != 1) { + error_print(); + return -1; + } + + if (!tls_protocol_name(ver)) { + error_print(); + return -1; + } + *protocol = ver; + + if (*session_id) { + if (*session_id_len == 0 + || *session_id_len < TLS_MIN_SESSION_ID_SIZE + || *session_id_len > TLS_MAX_SESSION_ID_SIZE) { + error_print(); + return -1; + } + } + + if (!cipher_suites) { + error_print(); + return -1; + } + if (*cipher_suites_len % 2) { + error_print(); + return -1; + } + + if (len) { + if (tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1) { + error_print(); + return -1; + } + if (*exts == NULL) { + error_print(); + return -1; + } + } else { + *exts = NULL; + *exts_len = 0; + } + if (len) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_set_handshake_server_hello(uint8_t *record, size_t *recordlen, + int protocol, 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) +{ + uint8_t type = TLS_handshake_server_hello; + uint8_t *p; + size_t len; + + if (!record || !recordlen || !random) { + error_print(); + return -1; + } + if (session_id) { + if (session_id_len == 0 + || session_id_len < TLS_MIN_SESSION_ID_SIZE + || session_id_len > TLS_MAX_SESSION_ID_SIZE) { + error_print(); + return -1; + } + } + if (!tls_protocol_name(protocol)) { + error_print(); + return -1; + } + if (!tls_cipher_suite_name(cipher_suite)) { + error_print(); + return -1; + } + + p = tls_handshake_data(tls_record_data(record)); + len = 0; + + tls_uint16_to_bytes((uint16_t)protocol, &p, &len); + tls_array_to_bytes(random, 32, &p, &len); + tls_uint8array_to_bytes(session_id, session_id_len, &p, &len); + tls_uint16_to_bytes((uint16_t)cipher_suite, &p, &len); + tls_uint8_to_bytes((uint8_t)TLS_compression_null, &p, &len); + if (exts) { + if (protocol < TLS_protocol_tls12) { + error_print(); + return -1; + } + tls_uint16array_to_bytes(exts, exts_len, &p, &len); + } + if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_get_handshake_server_hello(const uint8_t *record, + int *protocol, const uint8_t **random, const uint8_t **session_id, size_t *session_id_len, + int *cipher_suite, const uint8_t **exts, size_t *exts_len) +{ + int type; + const uint8_t *p; + size_t len; + uint16_t ver; + uint16_t cipher; + uint8_t comp_meth; + + if (!record || !protocol || !random || !session_id || !session_id_len + || !cipher_suite || !exts || !exts_len) { + error_print(); + return -1; + } + if (tls_record_get_handshake(record, &type, &p, &len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_server_hello) { + error_print(); + return -1; + } + if (tls_uint16_from_bytes(&ver, &p, &len) != 1 + || tls_array_from_bytes(random, 32, &p, &len) != 1 + || tls_uint8array_from_bytes(session_id, session_id_len, &p, &len) != 1 + || tls_uint16_from_bytes(&cipher, &p, &len) != 1 + || tls_uint8_from_bytes(&comp_meth, &p, &len) != 1) { + error_print(); + return -1; + } + + if (!tls_protocol_name(ver)) { + error_print(); + return -1; + } + if (ver < tls_record_protocol(record)) { + error_print(); + return -1; + } + *protocol = ver; + + if (*session_id) { + if (*session_id == 0 + || *session_id_len < TLS_MIN_SESSION_ID_SIZE + || *session_id_len > TLS_MAX_SESSION_ID_SIZE) { + error_print(); + return -1; + } + } + + if (!tls_cipher_suite_name(cipher)) { + error_print(); + return -1; + } + *cipher_suite = cipher; + + if (comp_meth != TLS_compression_null) { + error_print(); + return -1; + } + + if (len) { + if (tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1) { + error_print(); + return -1; + } + if (*exts == NULL) { + error_print(); + return -1; + } + } else { + *exts = NULL; + *exts_len = 0; + } + if (len) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_set_handshake_certificate(uint8_t *record, size_t *recordlen, + const uint8_t *certs, size_t certslen) +{ + int type = TLS_handshake_certificate; + uint8_t *data; + size_t datalen; + uint8_t *p; + size_t len; + + if (!record || !recordlen || !certs || !certslen) { + error_print(); + return -1; + } + data = tls_handshake_data(tls_record_data(record)); + p = data + tls_uint24_size(); + datalen = tls_uint24_size(); + len = 0; + + while (certslen) { + const uint8_t *cert; + size_t certlen; + + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + tls_uint24array_to_bytes(cert, certlen, NULL, &datalen); + if (datalen > TLS_MAX_HANDSHAKE_DATA_SIZE) { + error_print(); + return -1; + } + tls_uint24array_to_bytes(cert, certlen, &p, &len); + } + tls_uint24_to_bytes((uint24_t)len, &data, &len); + tls_record_set_handshake(record, recordlen, type, NULL, datalen); + return 1; +} + +int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *certs, size_t *certslen) +{ + int type; + const uint8_t *data; + size_t datalen; + const uint8_t *cp; + size_t len; + + if (tls_record_get_handshake(record, &type, &data, &datalen) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_certificate) { + error_print(); + return -1; + } + if (tls_uint24array_from_bytes(&cp, &len, &data, &datalen) != 1) { + error_print(); + return -1; + } + + *certslen = 0; + while (len) { + const uint8_t *a; + size_t alen; + const uint8_t *cert; + size_t certlen; + + if (tls_uint24array_from_bytes(&a, &alen, &cp, &len) != 1) { + error_print(); + return -1; + } + if (x509_cert_from_der(&cert, &certlen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1 + || x509_cert_to_der(cert, certlen, &certs, certslen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int tls_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen, + const uint8_t *cert_types, size_t cert_types_len, + const uint8_t *ca_names, size_t ca_names_len) +{ + int type = TLS_handshake_certificate_request; + uint8_t *p; + size_t len =0; + size_t datalen = 0; + + if (!record || !recordlen) { + error_print(); + return -1; + } + if (cert_types) { + if (cert_types_len == 0 || cert_types_len > TLS_MAX_CERTIFICATE_TYPES) { + error_print(); + return -1; + } + } + if (ca_names) { + if (ca_names_len == 0 || ca_names_len > TLS_MAX_CA_NAMES_SIZE) { + error_print(); + return -1; + } + } + tls_uint8array_to_bytes(cert_types, cert_types_len, NULL, &datalen); + tls_uint16array_to_bytes(ca_names, ca_names_len, NULL, &datalen); + if (datalen > TLS_MAX_HANDSHAKE_DATA_SIZE) { + error_print(); + return -1; + } + p = tls_handshake_data(tls_record_data(record)); + tls_uint8array_to_bytes(cert_types, cert_types_len, &p, &len); + tls_uint16array_to_bytes(ca_names, ca_names_len, &p, &len); + tls_record_set_handshake(record, recordlen, type, NULL, datalen); + return 1; +} + +int tls_record_get_handshake_certificate_request(const uint8_t *record, + const uint8_t **cert_types, size_t *cert_types_len, + const uint8_t **ca_names, size_t *ca_names_len) +{ + int type; + const uint8_t *cp; + size_t len; + size_t i; + + if (!record || !cert_types || !cert_types_len || !ca_names || !ca_names_len) { + error_print(); + return -1; + } + if (tls_record_get_handshake(record, &type, &cp, &len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_certificate_request) { + error_print(); + return -1; + } + if (tls_uint8array_from_bytes(cert_types, cert_types_len, &cp, &len) != 1 + || tls_uint16array_from_bytes(ca_names, ca_names_len, &cp, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + if (*cert_types == NULL) { + error_print(); + return -1; + } + for (i = 0; i < *cert_types_len; i++) { + if (!tls_cert_type_name((*cert_types)[i])) { + error_print(); + return -1; + } + } + if (*ca_names) { + const uint8_t *names = *ca_names; + size_t nameslen = *ca_names_len; + while (nameslen) { + if (tls_uint16array_from_bytes(&cp, &len, &names, &nameslen) != 1) { + error_print(); + return -1; + } + } + } + return 1; +} + +int tls_record_set_handshake_server_hello_done(uint8_t *record, size_t *recordlen) +{ + int type = TLS_handshake_server_hello_done; + if (!record || !recordlen) { + error_print(); + return -1; + } + tls_record_set_handshake(record, recordlen, type, NULL, 0); + return 1; +} + +int tls_record_get_handshake_server_hello_done(const uint8_t *record) +{ + int type; + const uint8_t *p; + size_t len; + + if (!record) { + error_print(); + return -1; + } + if (tls_record_get_handshake(record, &type, &p, &len) != 1 + || type != TLS_handshake_server_hello_done) { + error_print(); + return -1; + } + if (p != NULL || len != 0) { + error_print(); + return -1; + } + return 1; +} + +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 type = TLS_handshake_client_key_exchange; + uint8_t *p; + size_t len = 0; + + if (!record || !recordlen || !enced_pms || !enced_pms_len) { + error_print(); + return -1; + } + if (enced_pms_len > TLS_MAX_HANDSHAKE_DATA_SIZE - tls_uint16_size()) { + error_print(); + return -1; + } + p = tls_handshake_data(tls_record_data(record)); + tls_uint16array_to_bytes(enced_pms, enced_pms_len, &p, &len); + tls_record_set_handshake(record, recordlen, type, NULL, len); + return 1; +} + +int tls_record_get_handshake_client_key_exchange_pke(const uint8_t *record, + const uint8_t **enced_pms, size_t *enced_pms_len) +{ + int type; + const uint8_t *cp; + size_t len; + + if (!record || !enced_pms || !enced_pms_len) { + error_print(); + return -1; + } + if (tls_record_get_handshake(record, &type, &cp, &len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_client_key_exchange) { + error_print(); + return -1; + } + if (tls_uint16array_from_bytes(enced_pms, enced_pms_len, &cp, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen, + const uint8_t *sig, size_t siglen) +{ + int type = TLS_handshake_certificate_verify; + uint8_t *p; + size_t len = 0; + + if (!record || !recordlen || !sig || !siglen) { + error_print(); + return -1; + } + if (siglen > TLS_MAX_SIGNATURE_SIZE) { + error_print(); + return -1; + } + p = tls_handshake_data(tls_record_data(record)); + tls_uint16array_to_bytes(sig, siglen, &p, &len); + tls_record_set_handshake(record, recordlen, type, NULL, len); + return 1; +} + +int tls_record_get_handshake_certificate_verify(const uint8_t *record, + const uint8_t **sig, size_t *siglen) +{ + int type; + const uint8_t *cp; + size_t len; + + if (!record || !sig || !siglen) { + error_print(); + return -1; + } + if (tls_record_get_handshake(record, &type, &cp, &len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_certificate_verify) { + error_print(); + return -1; + } + if (tls_uint16array_from_bytes(sig, siglen, &cp, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_set_handshake_finished(uint8_t *record, size_t *recordlen, + const uint8_t *verify_data, size_t verify_data_len) +{ + int type = TLS_handshake_finished; + + if (!record || !recordlen || !verify_data || !verify_data_len) { + error_print(); + return -1; + } + if (verify_data_len != 12 && verify_data_len != 32) { + error_print(); + return -1; + } + tls_record_set_handshake(record, recordlen, type, verify_data, verify_data_len); + return 1; +} + +int tls_record_get_handshake_finished(const uint8_t *record, const uint8_t **verify_data, size_t *verify_data_len) +{ + int type; + + if (!record || !verify_data || !verify_data_len) { + error_print(); + return -1; + } + if (tls_record_get_handshake(record, &type, verify_data, verify_data_len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_finished) { + error_print(); + return -1; + } + if (*verify_data == NULL || *verify_data_len == 0) { + error_print(); + return -1; + } + if (*verify_data_len != 12 && *verify_data_len != 32) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_set_alert(uint8_t *record, size_t *recordlen, + int alert_level, + int alert_description) +{ + if (!record || !recordlen) { + error_print(); + return -1; + } + if (!tls_alert_level_name(alert_level)) { + error_print(); + return -1; + } + if (!tls_alert_description_text(alert_description)) { + error_print(); + return -1; + } + record[0] = TLS_record_alert; + record[3] = 0; // length + record[4] = 2; // length + record[5] = (uint8_t)alert_level; + record[6] = (uint8_t)alert_description; + *recordlen = TLS_RECORD_HEADER_SIZE + 2; + return 1; +} + +int tls_record_get_alert(const uint8_t *record, + int *alert_level, + int *alert_description) +{ + if (!record || !alert_level || !alert_description) { + error_print(); + return -1; + } + if (tls_record_type(record) != TLS_record_alert) { + error_print(); + return -1; + } + if (record[3] != 0 || record[4] != 2) { + error_print(); + return -1; + } + *alert_level = record[5]; + *alert_description = record[6]; + if (!tls_alert_level_name(*alert_level)) { + error_print(); + return -1; + } + if (!tls_alert_description_text(*alert_description)) { + error_puts("warning"); + return -1; + } + return 1; +} + +int tls_record_set_change_cipher_spec(uint8_t *record, size_t *recordlen) +{ + if (!record || !recordlen) { + error_print(); + return -1; + } + record[0] = TLS_record_change_cipher_spec; + record[3] = 0; + record[4] = 1; + record[5] = TLS_change_cipher_spec; + *recordlen = TLS_RECORD_HEADER_SIZE + 1; + return 1; +} + +int tls_record_get_change_cipher_spec(const uint8_t *record) +{ + if (!record) { + error_print(); + return -1; + } + if (tls_record_type(record) != TLS_record_change_cipher_spec) { + error_print(); + return -1; + } + if (record[3] != 0 || record[4] != 1) { + error_print(); + return -1; + } + if (record[5] != TLS_change_cipher_spec) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_set_application_data(uint8_t *record, size_t *recordlen, + const uint8_t *data, size_t datalen) +{ + if (!record || !recordlen || !data || !datalen) { + error_print(); + return -1; + } + record[0] = TLS_record_application_data; + record[3] = (datalen >> 8) & 0xff; + record[4] = datalen & 0xff; + memcpy(tls_record_data(record), data, datalen); + *recordlen = TLS_RECORD_HEADER_SIZE + datalen; + return 1; +} + +int tls_record_get_application_data(uint8_t *record, + const uint8_t **data, size_t *datalen) +{ + if (!record || !data || !datalen) { + error_print(); + return -1; + } + if (tls_record_type(record) != TLS_record_application_data) { + error_print(); + return -1; + } + *datalen = ((size_t)record[3] << 8) | record[4]; + *data = *datalen ? record + TLS_RECORD_HEADER_SIZE : 0; + return 1; +} + +int tls_cipher_suite_in_list(int cipher, const int *list, size_t list_count) +{ + size_t i; + if (!list || !list_count) { + error_print(); + return -1; + } + for (i = 0; i < list_count; i++) { + if (cipher == list[i]) { + return 1; + } + } + return 0; +} + +int tls_record_send(const uint8_t *record, size_t recordlen, tls_socket_t sock) +{ + tls_ret_t r; + + if (!record) { + error_print(); + return -1; + } + if (recordlen < TLS_RECORD_HEADER_SIZE) { + error_print(); + return -1; + } + if (tls_record_length(record) != recordlen) { + error_print(); + return -1; + } + if ((r = tls_socket_send(sock, record, recordlen, 0)) < 0) { + perror("tls_record_send"); + error_print(); + return -1; + } else if (r != recordlen) { + error_print(); + return -1; + } + return 1; +} + +int tls_record_do_recv(uint8_t *record, size_t *recordlen, tls_socket_t sock) +{ + tls_ret_t r; + size_t len; + + len = 5; + while (len) { + if ((r = tls_socket_recv(sock, record + 5 - len, len, 0)) < 0) { + perror("tls_record_do_recv"); + error_print(); + return -1; + } + if (r == 0) { + perror("tls_record_do_recv"); + error_print(); + return 0; + } + + len -= r; + } + if (!tls_record_type_name(tls_record_type(record))) { + error_print(); + return -1; + } + if (!tls_protocol_name(tls_record_protocol(record))) { + error_print(); + return -1; + } + len = (size_t)record[3] << 8 | record[4]; + *recordlen = 5 + len; + if (*recordlen > TLS_MAX_RECORD_SIZE) { + // 这里只检查是否超过最大长度,握手协议的长度检查由上层协议完成 + error_print(); + return -1; + } + while (len) { + if ((r = recv(sock, record + *recordlen - len, (int)len, 0)) < 0) { // winsock2 recv() use int + perror("tls_record_do_recv"); + error_print(); + return -1; + } + len -= r; + } + return 1; +} + +int tls_record_recv(uint8_t *record, size_t *recordlen, tls_socket_t sock) +{ +retry: + if (tls_record_do_recv(record, recordlen, sock) != 1) { + error_print(); + return -1; + } + + if (tls_record_type(record) == TLS_record_alert) { + int level; + int alert; + if (tls_record_get_alert(record, &level, &alert) != 1) { + error_print(); + return -1; + } + tls_record_trace(stderr, record, *recordlen, 0, 0); + if (level == TLS_alert_level_warning) { + // 忽略Warning,读取下一个记录 + error_puts("Warning record received!\n"); + goto retry; + } + if (alert == TLS_alert_close_notify) { + // close_notify是唯一需要提供反馈的Fatal Alert,其他直接中止连接 + uint8_t alert_record[TLS_ALERT_RECORD_SIZE]; + size_t alert_record_len; + tls_record_set_type(alert_record, TLS_record_alert); + tls_record_set_protocol(alert_record, tls_record_protocol(record)); + tls_record_set_alert(alert_record, &alert_record_len, TLS_alert_level_fatal, TLS_alert_close_notify); + + tls_trace("send Alert close_notifiy\n"); + tls_record_trace(stderr, alert_record, alert_record_len, 0, 0); + tls_record_send(alert_record, alert_record_len, sock); + } + // 返回错误0通知调用方不再做任何处理(无需再发送Alert) + return 0; + } + return 1; +} + +int tls_seq_num_incr(uint8_t seq_num[8]) +{ + int i; + for (i = 7; i > 0; i--) { + seq_num[i]++; + if (seq_num[i]) break; + } + // FIXME: 检查溢出 + return 1; +} + +int tls_compression_methods_has_null_compression(const uint8_t *meths, size_t methslen) +{ + if (!meths || !methslen) { + error_print(); + return -1; + } + while (methslen--) { + if (*meths++ == TLS_compression_null) { + return 1; + } + } + error_print(); + return -1; +} + +int tls_send_alert(TLS_CONNECT *conn, int alert) +{ + uint8_t record[5 + 2]; + size_t recordlen; + + if (!conn) { + error_print(); + return -1; + } + tls_record_set_protocol(record, conn->protocol == TLS_protocol_tls13 ? TLS_protocol_tls12 : conn->protocol); + tls_record_set_alert(record, &recordlen, TLS_alert_level_fatal, alert); + + if (tls_record_send(record, sizeof(record), conn->sock) != 1) { + error_print(); + return -1; + } + tls_record_trace(stderr, record, sizeof(record), 0, 0); + return 1; +} + +int tls_alert_level(int alert) +{ + switch (alert) { + case TLS_alert_bad_certificate: + case TLS_alert_unsupported_certificate: + case TLS_alert_certificate_revoked: + case TLS_alert_certificate_expired: + case TLS_alert_certificate_unknown: + return 0; + case TLS_alert_user_canceled: + case TLS_alert_no_renegotiation: + return TLS_alert_level_warning; + } + return TLS_alert_level_fatal; +} + +int tls_send_warning(TLS_CONNECT *conn, int alert) +{ + uint8_t record[5 + 2]; + size_t recordlen; + + if (!conn) { + error_print(); + return -1; + } + if (tls_alert_level(alert) == TLS_alert_level_fatal) { + error_print(); + return -1; + } + tls_record_set_protocol(record, conn->protocol == TLS_protocol_tls13 ? TLS_protocol_tls12 : conn->protocol); + tls_record_set_alert(record, &recordlen, TLS_alert_level_warning, alert); + + if (tls_record_send(record, sizeof(record), conn->sock) != 1) { + error_print(); + return -1; + } + tls_record_trace(stderr, record, sizeof(record), 0, 0); + return 1; +} + +int tls_send(TLS_CONNECT *conn, const uint8_t *in, size_t inlen, size_t *sentlen) +{ + const SM3_HMAC_CTX *hmac_ctx; + const SM4_KEY *enc_key; + uint8_t *seq_num; + uint8_t *record; + size_t datalen; + + if (!conn) { + error_print(); + return -1; + } + if (!in || !inlen || !sentlen) { + error_print(); + return -1; + } + + if (inlen > TLS_MAX_PLAINTEXT_SIZE) { + inlen = TLS_MAX_PLAINTEXT_SIZE; + } + + if (conn->is_client) { + hmac_ctx = &conn->client_write_mac_ctx; + enc_key = &conn->client_write_enc_key; + seq_num = conn->client_seq_num; + } else { + hmac_ctx = &conn->server_write_mac_ctx; + enc_key = &conn->server_write_enc_key; + seq_num = conn->server_seq_num; + } + record = conn->record; + + tls_trace("send ApplicationData\n"); + + if (tls_record_set_type(record, TLS_record_application_data) != 1 + || tls_record_set_protocol(record, conn->protocol) != 1 + || tls_record_set_length(record, inlen) != 1) { + error_print(); + return -1; + } + + if (tls_cbc_encrypt(hmac_ctx, enc_key, seq_num, tls_record_header(record), + in, inlen, tls_record_data(record), &datalen) != 1) { + error_print(); + return -1; + } + if (tls_record_set_length(record, datalen) != 1) { + error_print(); + return -1; + } + tls_seq_num_incr(seq_num); + if (tls_record_send(record, tls_record_length(record), conn->sock) != 1) { + error_print(); + return -1; + } + *sentlen = inlen; + tls_record_trace(stderr, record, tls_record_length(record), 0, 0); + return 1; +} + +int tls_do_recv(TLS_CONNECT *conn) +{ + int ret; + const SM3_HMAC_CTX *hmac_ctx; + const SM4_KEY *dec_key; + uint8_t *seq_num; + + uint8_t *record = conn->record; + size_t recordlen; + + if (conn->is_client) { + hmac_ctx = &conn->server_write_mac_ctx; + dec_key = &conn->server_write_enc_key; + seq_num = conn->server_seq_num; + } else { + hmac_ctx = &conn->client_write_mac_ctx; + dec_key = &conn->client_write_enc_key; + seq_num = conn->client_seq_num; + } + + tls_trace("recv ApplicationData\n"); + if ((ret = tls_record_recv(record, &recordlen, conn->sock)) != 1) { + if (ret < 0) error_print(); + return ret; + } + + tls_record_trace(stderr, record, recordlen, 0, 0); + if (tls_cbc_decrypt(hmac_ctx, dec_key, seq_num, record, + tls_record_data(record), tls_record_data_length(record), + conn->databuf, &conn->datalen) != 1) { + error_print(); + return -1; + } + conn->data = conn->databuf; + tls_seq_num_incr(seq_num); + + tls_record_set_data(record, conn->data, conn->datalen); + tls_trace("decrypt ApplicationData\n"); + tls_record_trace(stderr, record, tls_record_length(record), 0, 0); + return 1; +} + +int tls_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen) +{ + if (!conn || !out || !outlen || !recvlen) { + error_print(); + return -1; + } + if (conn->datalen == 0) { + int ret; + if ((ret = tls_do_recv(conn)) != 1) { + if (ret) error_print(); + return ret; + } + } + *recvlen = outlen <= conn->datalen ? outlen : conn->datalen; + memcpy(out, conn->data, *recvlen); + conn->data += *recvlen; + conn->datalen -= *recvlen; + return 1; +} + +int tls_shutdown(TLS_CONNECT *conn) +{ + size_t recordlen; + if (!conn) { + error_print(); + return -1; + } + tls_trace("send Alert close_notify\n"); + if (tls_send_alert(conn, TLS_alert_close_notify) != 1) { + error_print(); + return -1; + } + tls_trace("recv Alert close_notify\n"); + + if (tls_record_do_recv(conn->record, &recordlen, conn->sock) != 1) { + error_print(); + return -1; + } + tls_record_trace(stderr, conn->record, recordlen, 0, 0); + + return 1; +} + +int tls_authorities_from_certs(uint8_t *names, size_t *nameslen, size_t maxlen, const uint8_t *certs, size_t certslen) +{ + const uint8_t *cert; + size_t certlen; + const uint8_t *name; + size_t namelen; + + *nameslen = 0; + while (certslen) { + size_t alen = 0; + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1 + || x509_cert_get_subject(cert, certlen, &name, &namelen) != 1 + || asn1_sequence_to_der(name, namelen, NULL, &alen) != 1) { + error_print(); + return -1; + } + if (tls_uint16_size() + alen > maxlen) { + error_print(); + return -1; + } + if (alen > UINT16_MAX) { + error_print(); + return -1; + } + tls_uint16_to_bytes((uint16_t)alen, &names, nameslen); + if (asn1_sequence_to_der(name, namelen, &names, nameslen) != 1) { + error_print(); + return -1; + } + maxlen -= alen; + } + return 1; +} + +int tls_authorities_issued_certificate(const uint8_t *ca_names, size_t ca_names_len, const uint8_t *certs, size_t certslen) +{ + const uint8_t *cert; + size_t certlen; + const uint8_t *issuer; + size_t issuer_len; + + if (x509_certs_get_last(certs, certslen, &cert, &certlen) != 1 + || x509_cert_get_issuer(cert, certlen, &issuer, &issuer_len) != 1) { + error_print(); + return -1; + } + while (ca_names_len) { + const uint8_t *p; + size_t len; + const uint8_t *name; + size_t namelen; + + if (tls_uint16array_from_bytes(&p, &len, &ca_names, &ca_names_len) != 1) { + error_print(); + return -1; + } + if (asn1_sequence_from_der(&name, &namelen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (x509_name_equ(name, namelen, issuer, issuer_len) == 1) { + return 1; + } + } + error_print(); + return 0; +} + +int tls_cert_types_accepted(const uint8_t *types, size_t types_len, const uint8_t *client_certs, size_t client_certs_len) +{ + const uint8_t *cert; + size_t certlen; + int sig_alg; + size_t i; + + if (x509_certs_get_cert_by_index(client_certs, client_certs_len, 0, &cert, &certlen) != 1) { + error_print(); + return -1; + } + if ((sig_alg = tls_cert_type_from_oid(OID_sm2sign_with_sm3)) < 0) { + error_print(); + return -1; + } + for (i = 0; i < types_len; i++) { + if (sig_alg == types[i]) { + return 1; + } + } + return 0; +} + +int tls_client_verify_init(TLS_CLIENT_VERIFY_CTX *ctx) +{ + if (!ctx) { + error_print(); + return -1; + } + memset(ctx, 0, sizeof(TLS_CLIENT_VERIFY_CTX)); + return 1; +} + +int tls_client_verify_update(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *handshake, size_t handshake_len) +{ + uint8_t *buf; + if (!ctx || !handshake || !handshake_len) { + error_print(); + return -1; + } + if (ctx->index < 0 || ctx->index > 7) { + error_print(); + return -1; + } + if (!(buf = malloc(handshake_len))) { + error_print(); + return -1; + } + memcpy(buf, handshake, handshake_len); + ctx->handshake[ctx->index] = buf; + ctx->handshake_len[ctx->index] = handshake_len; + ctx->index++; + return 1; +} + +int tls_client_verify_finish(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *sig, size_t siglen, const SM2_KEY *public_key) +{ + int ret; + SM2_SIGN_CTX sm2_ctx; + int i; + + if (!ctx || !sig || !siglen || !public_key) { + error_print(); + return -1; + } + + if (ctx->index != 8) { + error_print(); + return -1; + } + if (sm2_verify_init(&sm2_ctx, public_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + for (i = 0; i < 8; i++) { + if (sm2_verify_update(&sm2_ctx, ctx->handshake[i], ctx->handshake_len[i]) != 1) { + error_print(); + return -1; + } + } + if ((ret = sm2_verify_finish(&sm2_ctx, sig, siglen)) < 0) { + error_print(); + return -1; + } + return ret; +} + +void tls_client_verify_cleanup(TLS_CLIENT_VERIFY_CTX *ctx) +{ + if (ctx) { + int i; + for (i = 0; i< ctx->index; i++) { + if (ctx->handshake[i]) { + free(ctx->handshake[i]); + ctx->handshake[i] = NULL; + ctx->handshake_len[i] = 0; + } + } + } +} + +int tls_cipher_suites_select(const uint8_t *client_ciphers, size_t client_ciphers_len, + const int *server_ciphers, size_t server_ciphers_cnt, + int *selected_cipher) +{ + if (!client_ciphers || !client_ciphers_len + || !server_ciphers || !server_ciphers_cnt || !selected_cipher) { + error_print(); + return -1; + } + while (server_ciphers_cnt--) { + const uint8_t *p = client_ciphers; + size_t len = client_ciphers_len; + while (len) { + uint16_t cipher; + if (tls_uint16_from_bytes(&cipher, &p, &len) != 1) { + error_print(); + return -1; + } + if (cipher == *server_ciphers) { + *selected_cipher = *server_ciphers; + return 1; + } + } + server_ciphers++; + } + return 0; +} + +void tls_ctx_cleanup(TLS_CTX *ctx) +{ + if (ctx) { + gmssl_secure_clear(&ctx->signkey, sizeof(SM2_KEY)); + gmssl_secure_clear(&ctx->kenckey, sizeof(SM2_KEY)); + if (ctx->certs) free(ctx->certs); + if (ctx->cacerts) free(ctx->cacerts); + memset(ctx, 0, sizeof(TLS_CTX)); + } +} + +int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client) +{ + if (!ctx) { + error_print(); + return -1; + } + memset(ctx, 0, sizeof(*ctx)); + + switch (protocol) { + case TLS_protocol_tlcp: + case TLS_protocol_tls12: + case TLS_protocol_tls13: + ctx->protocol = protocol; + break; + default: + error_print(); + return -1; + } + ctx->is_client = is_client ? 1 : 0; + return 1; +} + +int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cipher_suites_cnt) +{ + size_t i; + + if (!ctx || !cipher_suites || !cipher_suites_cnt) { + error_print(); + return -1; + } + if (cipher_suites_cnt < 1 || cipher_suites_cnt > TLS_MAX_CIPHER_SUITES_COUNT) { + error_print(); + return -1; + } + for (i = 0; i < cipher_suites_cnt; i++) { + if (!tls_cipher_suite_name(cipher_suites[i])) { + error_print(); + return -1; + } + } + for (i = 0; i < cipher_suites_cnt; i++) { + ctx->cipher_suites[i] = cipher_suites[i]; + } + ctx->cipher_suites_cnt = cipher_suites_cnt; + return 1; +} + +int tls_ctx_set_ca_certificates(TLS_CTX *ctx, const char *cacertsfile, int depth) +{ + if (!ctx || !cacertsfile) { + error_print(); + return -1; + } + if (depth < 0 || depth > TLS_MAX_VERIFY_DEPTH) { + error_print(); + return -1; + } + if (!tls_protocol_name(ctx->protocol)) { + error_print(); + return -1; + } + if (ctx->cacerts) { + error_print(); + return -1; + } + if (x509_certs_new_from_file(&ctx->cacerts, &ctx->cacertslen, cacertsfile) != 1) { + error_print(); + return -1; + } + if (ctx->cacertslen == 0) { + error_print(); + return -1; + } + + ctx->verify_depth = depth; + return 1; +} + +int tls_ctx_set_certificate_and_key(TLS_CTX *ctx, const char *chainfile, + const char *keyfile, const char *keypass) +{ + int ret = -1; + uint8_t *certs = NULL; + size_t certslen; + FILE *keyfp = NULL; + SM2_KEY key; + const uint8_t *cert; + size_t certlen; + SM2_KEY public_key; + + if (!ctx || !chainfile || !keyfile || !keypass) { + error_print(); + return -1; + } + if (!tls_protocol_name(ctx->protocol)) { + error_print(); + return -1; + } + if (ctx->certs) { + error_print(); + return -1; + } + + if (x509_certs_new_from_file(&certs, &certslen, chainfile) != 1) { + error_print(); + goto end; + } + if (!(keyfp = fopen(keyfile, "r"))) { + error_print(); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&key, keypass, keyfp) != 1) { + error_print(); + goto end; + } + if (x509_certs_get_cert_by_index(certs, certslen, 0, &cert, &certlen) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) { + error_print(); + return -1; + } + if (sm2_public_key_equ(&key, &public_key) != 1) { + error_print(); + return -1; + } + ctx->certs = certs; + ctx->certslen = certslen; + ctx->signkey = key; + certs = NULL; + ret = 1; + +end: + gmssl_secure_clear(&key, sizeof(key)); + if (certs) free(certs); + if (keyfp) fclose(keyfp); + return ret; +} + +int tls_ctx_set_tlcp_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile, + const char *signkeyfile, const char *signkeypass, + const char *kenckeyfile, const char *kenckeypass) +{ + int ret = -1; + uint8_t *certs = NULL; + size_t certslen; + FILE *signkeyfp = NULL; + FILE *kenckeyfp = NULL; + SM2_KEY signkey; + SM2_KEY kenckey; + + const uint8_t *cert; + size_t certlen; + SM2_KEY public_key; + + if (!ctx || !chainfile || !signkeyfile || !signkeypass || !kenckeyfile || !kenckeypass) { + error_print(); + return -1; + } + if (!tls_protocol_name(ctx->protocol)) { + error_print(); + return -1; + } + if (ctx->certs) { + error_print(); + return -1; + } + + if (x509_certs_new_from_file(&certs, &certslen, chainfile) != 1) { + error_print(); + return -1; + } + + if (!(signkeyfp = fopen(signkeyfile, "r"))) { + error_print(); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&signkey, signkeypass, signkeyfp) != 1) { + error_print(); + goto end; + } + if (x509_certs_get_cert_by_index(certs, certslen, 0, &cert, &certlen) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1 + || sm2_public_key_equ(&signkey, &public_key) != 1) { + error_print(); + goto end; + } + + if (!(kenckeyfp = fopen(kenckeyfile, "r"))) { + error_print(); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&kenckey, kenckeypass, kenckeyfp) != 1) { + error_print(); + goto end; + } + if (x509_certs_get_cert_by_index(certs, certslen, 1, &cert, &certlen) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1 + || sm2_public_key_equ(&kenckey, &public_key) != 1) { + error_print(); + goto end; + } + + ctx->certs = certs; + ctx->certslen = certslen; + ctx->signkey = signkey; + ctx->kenckey = kenckey; + certs = NULL; + ret = 1; + +end: + gmssl_secure_clear(&signkey, sizeof(signkey)); + gmssl_secure_clear(&kenckey, sizeof(kenckey)); + if (certs) free(certs); + if (signkeyfp) fclose(signkeyfp); + if (kenckeyfp) fclose(kenckeyfp); + return ret; +} + +int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx) +{ + size_t i; + memset(conn, 0, sizeof(*conn)); + + conn->protocol = ctx->protocol; + conn->is_client = ctx->is_client; + for (i = 0; i < ctx->cipher_suites_cnt; i++) { + conn->cipher_suites[i] = ctx->cipher_suites[i]; + } + conn->cipher_suites_cnt = ctx->cipher_suites_cnt; + + + if (ctx->certslen > TLS_MAX_CERTIFICATES_SIZE) { + error_print(); + return -1; + } + if (conn->is_client) { + memcpy(conn->client_certs, ctx->certs, ctx->certslen); + conn->client_certs_len = ctx->certslen; + } else { + memcpy(conn->server_certs, ctx->certs, ctx->certslen); + conn->server_certs_len = ctx->certslen; + } + + if (ctx->cacertslen > TLS_MAX_CERTIFICATES_SIZE) { + error_print(); + return -1; + } + memcpy(conn->ca_certs, ctx->cacerts, ctx->cacertslen); + conn->ca_certs_len = ctx->cacertslen; + + conn->sign_key = ctx->signkey; + conn->kenc_key = ctx->kenckey; + + return 1; +} + +void tls_cleanup(TLS_CONNECT *conn) +{ + gmssl_secure_clear(conn, sizeof(TLS_CONNECT)); +} + +int tls_set_socket(TLS_CONNECT *conn, tls_socket_t sock) +{ +#if 0 + int opts; + + // FIXME: do we still need this? when using select? + if ((opts = fcntl(sock, F_GETFL)) < 0) { + error_print(); + perror("tls_set_socket"); + return -1; + } + opts &= ~O_NONBLOCK; + if (fcntl(sock, F_SETFL, opts) < 0) { + error_print(); + return -1; + } +#endif + conn->sock = sock; + return 1; +} + +int tls_do_handshake(TLS_CONNECT *conn) +{ + switch (conn->protocol) { + case TLS_protocol_tlcp: + if (conn->is_client) return tlcp_do_connect(conn); + else return tlcp_do_accept(conn); + case TLS_protocol_tls12: + if (conn->is_client) return tls12_do_connect(conn); + else return tls12_do_accept(conn); + case TLS_protocol_tls13: + if (conn->is_client) return tls13_do_connect(conn); + else return tls13_do_accept(conn); + } + error_print(); + return -1; +} + +int tls_get_verify_result(TLS_CONNECT *conn, int *result) +{ + *result = conn->verify_result; + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/tls12.c b/Core/GmSSL-3.1.1/src/tls12.c new file mode 100644 index 0000000..f9bf6f9 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/tls12.c @@ -0,0 +1,1078 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static const int tls12_ciphers[] = { + TLS_cipher_ecdhe_sm4_cbc_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 tls12_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent) +{ + // 目前只支持TLCP的ECC公钥加密套件,因此不论用哪个套件解析都是一样的 + // 如果未来支持ECDHE套件,可以将函数改为宏,直接传入 (conn->cipher_suite << 8) + format |= tls12_ciphers[0] << 8; + return tls_record_print(fp, record, recordlen, format, indent); +} + + +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; +} + +// 这里返回的应该是一个SM2_POINT吗? +int tls_record_get_handshake_server_key_exchange_ecdhe(const uint8_t *record, + int *curve, SM2_POINT *point, const uint8_t **sig, size_t *siglen) +{ + int type; + const uint8_t *p; + size_t len; + uint8_t curve_type; + uint16_t named_curve; + 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; + } + if (tls_uint8_from_bytes(&curve_type, &p, &len) != 1 + || tls_uint16_from_bytes(&named_curve, &p, &len) != 1 + || tls_uint8array_from_bytes(&octets, &octetslen, &p, &len) != 1 + || tls_uint16_from_bytes(&sig_alg, &p, &len) != 1 + || tls_uint16array_from_bytes(sig, siglen, &p, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (curve_type != TLS_curve_type_named_curve) { + error_print(); + return -1; + } + if (named_curve != TLS_curve_sm2p256v1) { + error_print(); + return -1; + } + *curve = named_curve; + if (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; +} + +/* + Client Server + + ClientHello --------> + ServerHello + Certificate + ServerKeyExchange + CertificateRequest* + <-------- ServerHelloDone + Certificate* + ClientKeyExchange + CertificateVerify* + [ChangeCipherSpec] + Finished --------> + [ChangeCipherSpec] + <-------- Finished + Application Data <-------> Application Data + + +*/ + +int tls12_do_connect(TLS_CONNECT *conn) +{ + int ret = -1; + uint8_t *record = conn->record; + uint8_t finished_record[TLS_FINISHED_RECORD_BUF_SIZE]; + size_t recordlen, finished_record_len; + + uint8_t client_random[32]; + uint8_t server_random[32]; + int protocol; + int cipher_suite; + const uint8_t *random; + const uint8_t *session_id; + size_t session_id_len; + + uint8_t client_exts[TLS_MAX_EXTENSIONS_SIZE]; + size_t client_exts_len = 0; + const uint8_t *server_exts; + size_t server_exts_len; + + // 扩展的协商结果,-1 表示服务器不支持该扩展(未给出响应) + int ec_point_format = -1; + int supported_group = -1; + int signature_algor = -1; + + + SM2_KEY server_sign_key; + SM2_SIGN_CTX sign_ctx; + const uint8_t *sig; + size_t siglen; + uint8_t pre_master_secret[48]; + SM3_CTX sm3_ctx; + SM3_CTX tmp_sm3_ctx; + uint8_t sm3_hash[32]; + const uint8_t *verify_data; + size_t verify_data_len; + uint8_t local_verify_data[12]; + int handshake_type; + + const uint8_t *cp; + uint8_t *p; + size_t len; + + int depth = 5; + int alert = 0; + int verify_result; + + + // 初始化记录缓冲 + tls_record_set_protocol(record, TLS_protocol_tls1); // ClientHello的记录层协议版本是TLSv1.0 + tls_record_set_protocol(finished_record, conn->protocol); + + // 准备Finished Context(和ClientVerify) + sm3_init(&sm3_ctx); + if (conn->client_certs_len) + sm2_sign_init(&sign_ctx, &conn->sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH); + + + // send ClientHello + tls_random_generate(client_random); + int ec_point_formats[] = { TLS_point_uncompressed }; + size_t ec_point_formats_cnt = 1; + int supported_groups[] = { TLS_curve_sm2p256v1 }; + size_t supported_groups_cnt = 1; + int signature_algors[] = { TLS_sig_sm2sig_sm3 }; + size_t signature_algors_cnt = 1; + + + p = client_exts; + client_exts_len = 0; + + tls_ec_point_formats_ext_to_bytes(ec_point_formats, ec_point_formats_cnt, &p, &client_exts_len); + tls_supported_groups_ext_to_bytes(supported_groups, supported_groups_cnt, &p, &client_exts_len); + tls_signature_algorithms_ext_to_bytes(signature_algors, signature_algors_cnt, &p, &client_exts_len); + + if (tls_record_set_handshake_client_hello(record, &recordlen, + conn->protocol, client_random, NULL, 0, + tls12_ciphers, tls12_ciphers_count, + client_exts, client_exts_len) != 1) { + error_print(); + goto end; + } + tls_trace("send ClientHello\n"); + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (conn->client_certs_len) + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // recv ServerHello + tls_trace("recv ServerHello\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + if (tls_record_get_handshake_server_hello(record, + &protocol, &random, &session_id, &session_id_len, &cipher_suite, + &server_exts, &server_exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (protocol != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + // tls12_ciphers 应该改为conn的内部变量 + if (tls_cipher_suite_in_list(cipher_suite, tls12_ciphers, tls12_ciphers_count) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + if (!server_exts) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls_process_server_hello_exts(server_exts, server_exts_len, &ec_point_format, &supported_group, &signature_algor) != 1 + || ec_point_format < 0 + || supported_group < 0 + || signature_algor < 0) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + memcpy(server_random, random, 32); + memcpy(conn->session_id, session_id, session_id_len); + conn->cipher_suite = cipher_suite; + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (conn->client_certs_len) + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // recv ServerCertificate + tls_trace("recv ServerCertificate\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + + if (tls_record_get_handshake_certificate(record, + conn->server_certs, &conn->server_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (conn->client_certs_len) + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // verify ServerCertificate + if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server, + conn->ca_certs, conn->ca_certs_len, depth, &verify_result) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + + // recv ServerKeyExchange + tls_trace("recv ServerKeyExchange\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + + int curve; + SM2_POINT server_ecdhe_public; + if (tls_record_get_handshake_server_key_exchange_ecdhe(record, &curve, &server_ecdhe_public, &sig, &siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (curve != TLS_curve_sm2p256v1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (conn->client_certs_len) + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // verify ServerKeyExchange + if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cp, &len) != 1 + || x509_cert_get_subject_public_key(cp, len, &server_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + if (tls_verify_server_ecdh_params(&server_sign_key, // 这应该是签名公钥 + client_random, server_random, curve, &server_ecdhe_public, sig, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + + // recv CertificateRequest or ServerHelloDone + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol + || tls_record_get_handshake(record, &handshake_type, &cp, &len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (handshake_type == TLS_handshake_certificate_request) { + const uint8_t *cert_types; + size_t cert_types_len; + const uint8_t *ca_names; + size_t ca_names_len; + + // recv CertificateRequest + tls_trace("recv CertificateRequest\n"); + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate_request(record, + &cert_types, &cert_types_len, &ca_names, &ca_names_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if(!conn->client_certs_len) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_cert_types_accepted(cert_types, cert_types_len, conn->client_certs, conn->client_certs_len) != 1 + || tls_authorities_issued_certificate(ca_names, ca_names_len, conn->client_certs, conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unsupported_certificate); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // recv ServerHelloDone + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + } else { + // 这个得处理一下 + conn->client_certs_len = 0; + gmssl_secure_clear(&conn->sign_key, sizeof(SM2_KEY)); + } + tls_trace("recv ServerHelloDone\n"); + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_server_hello_done(record) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (conn->client_certs_len) + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // send ClientCertificate + if (conn->client_certs_len) { + tls_trace("send ClientCertificate\n"); + if (tls_record_set_handshake_certificate(record, &recordlen, conn->client_certs, conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + } + + // generate MASTER_SECRET + tls_trace("generate secrets\n"); + SM2_KEY client_ecdh; + sm2_key_generate(&client_ecdh); + sm2_do_ecdh(&client_ecdh, &server_ecdhe_public, &server_ecdhe_public); + memcpy(pre_master_secret, &server_ecdhe_public, 32); // 这个做法很不优雅 + // ECDHE和ECC的PMS结构是不一样的吗? + + if (tls_prf(pre_master_secret, 32, "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(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + 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, 48, + client_random, server_random, + conn->master_secret, + conn->key_block, 96, + 0, 4); + */ + + // send ClientKeyExchange + tls_trace("send ClientKeyExchange\n"); + if (tls_record_set_handshake_client_key_exchange_ecdhe(record, &recordlen, &client_ecdh.public_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (conn->client_certs_len) + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // send CertificateVerify + if (conn->client_certs_len) { + tls_trace("send CertificateVerify\n"); + uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE]; + if (sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1 + || tls_record_set_handshake_certificate_verify(record, &recordlen, sigbuf, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + } + + // send [ChangeCipherSpec] + tls_trace("send [ChangeCipherSpec]\n"); + if (tls_record_set_change_cipher_spec(record, &recordlen) !=1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + // send Client Finished + tls_trace("send 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(local_verify_data), local_verify_data) != 1 + || tls_record_set_handshake_finished(finished_record, &finished_record_len, + local_verify_data, sizeof(local_verify_data)) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, finished_record, finished_record_len, 0, 0); + sm3_update(&sm3_ctx, finished_record + 5, finished_record_len - 5); + + // encrypt Client Finished + tls_trace("encrypt Finished\n"); + if (tls_record_encrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key, + conn->client_seq_num, finished_record, finished_record_len, record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + tls_seq_num_incr(conn->client_seq_num); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + // [ChangeCipherSpec] + tls_trace("recv [ChangeCipherSpec]\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_change_cipher_spec(record) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + + // Finished + tls_trace("recv Finished\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (recordlen > sizeof(finished_record)) { + error_print(); // 解密可能导致 finished_record 溢出 + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls12_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + tls_trace("decrypt Finished\n"); + if (tls_record_decrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key, + conn->server_seq_num, record, recordlen, finished_record, &finished_record_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls12_record_trace(stderr, finished_record, finished_record_len, 0, 0); + tls_seq_num_incr(conn->server_seq_num); + if (tls_record_get_handshake_finished(finished_record, &verify_data, &verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (verify_data_len != sizeof(local_verify_data)) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + 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(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + fprintf(stderr, "Connection established!\n"); + + + conn->protocol = conn->protocol; + conn->cipher_suite = cipher_suite; + + ret = 1; + +end: + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret)); + return ret; +} + +int tls12_do_accept(TLS_CONNECT *conn) +{ + int ret = -1; + + int client_verify = 0; + + uint8_t *record = conn->record; + uint8_t finished_record[TLS_FINISHED_RECORD_BUF_SIZE]; // 解密可能导致前面的record被覆盖 + size_t recordlen, finished_record_len; + + // 这个ciphers不是应该在CTX中设置的吗 + const int server_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3 }; // 未来应该支持GCM/CBC两个套件 + + // ClientHello, ServerHello + uint8_t client_random[32]; + uint8_t server_random[32]; + int protocol; + const uint8_t *random; + const uint8_t *session_id; // TLCP服务器忽略客户端SessionID,也不主动设置SessionID + size_t session_id_len; + const uint8_t *client_ciphers; + size_t client_ciphers_len; + const uint8_t *client_exts; + size_t client_exts_len; + uint8_t server_exts[TLS_MAX_EXTENSIONS_SIZE]; + size_t server_exts_len; + int curve = TLS_curve_sm2p256v1; // 这个是否应该在conn中设置? + + // ServerKeyExchange + SM2_KEY server_ecdhe_key; + SM2_SIGN_CTX sign_ctx; + uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + // ClientCertificate, CertificateVerify + TLS_CLIENT_VERIFY_CTX client_verify_ctx; + SM2_KEY client_sign_key; + const uint8_t *sig; + const int verify_depth = 5; + int verify_result; + + // ClientKeyExchange + SM2_POINT client_ecdhe_point; + uint8_t pre_master_secret[SM2_MAX_PLAINTEXT_SIZE]; // sm2_decrypt 保证输出不会溢出 + + // Finished + SM3_CTX sm3_ctx; + SM3_CTX tmp_sm3_ctx; + uint8_t sm3_hash[32]; + uint8_t local_verify_data[12]; + const uint8_t *verify_data; + size_t verify_data_len; + + const uint8_t *cp; + size_t len; + + + // 服务器端如果设置了CA + if (conn->ca_certs_len) + client_verify = 1; + + // 初始化Finished和客户端验证环境 + sm3_init(&sm3_ctx); + if (client_verify) + tls_client_verify_init(&client_verify_ctx); + + + // recv ClientHello + tls_trace("recv ClientHello\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_protocol(record) != conn->protocol + && tls_record_protocol(record) != TLS_protocol_tls1) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + if (tls_record_get_handshake_client_hello(record, + &protocol, &random, &session_id, &session_id_len, + &client_ciphers, &client_ciphers_len, + &client_exts, &client_exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (protocol != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + memcpy(client_random, random, 32); + if (tls_cipher_suites_select(client_ciphers, client_ciphers_len, + server_ciphers, sizeof(server_ciphers)/sizeof(server_ciphers[0]), + &conn->cipher_suite) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_insufficient_security); + goto end; + } + if (client_exts) { + server_exts_len = 0; + curve = TLS_curve_sm2p256v1; + + tls_process_client_hello_exts(client_exts, client_exts_len, server_exts, &server_exts_len, sizeof(server_exts)); + + + + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + + + // send ServerHello + tls_trace("send ServerHello\n"); + tls_random_generate(server_random); + tls_record_set_protocol(record, conn->protocol); + if (tls_record_set_handshake_server_hello(record, &recordlen, + conn->protocol, server_random, NULL, 0, + conn->cipher_suite, server_exts, server_exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + + // send ServerCertificate + tls_trace("send ServerCertificate\n"); + if (tls_record_set_handshake_certificate(record, &recordlen, + conn->server_certs, conn->server_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + + // send ServerKeyExchange + tls_trace("send ServerKeyExchange\n"); + sm2_key_generate(&server_ecdhe_key); + if (tls_sign_server_ecdh_params(&conn->sign_key, + client_random, server_random, TLS_curve_sm2p256v1, &server_ecdhe_key.public_key, + sigbuf, &siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + return -1; + } + if (tls_record_set_handshake_server_key_exchange_ecdhe(record, &recordlen, + curve, &server_ecdhe_key.public_key, sigbuf, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + + // send CertificateRequest + if (client_verify) { + const uint8_t cert_types[] = { TLS_cert_type_ecdsa_sign }; + uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE] = {0}; // TODO: 根据客户端验证CA证书列计算缓冲大小,或直接输出到record缓冲 + size_t ca_names_len = 0; + + tls_trace("send CertificateRequest\n"); + if (tls_authorities_from_certs(ca_names, &ca_names_len, sizeof(ca_names), + conn->ca_certs, conn->ca_certs_len) != 1) { + error_print(); + goto end; + } + if (tls_record_set_handshake_certificate_request(record, &recordlen, + cert_types, sizeof(cert_types), + ca_names, ca_names_len) != 1) { + error_print(); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + } + + // send ServerHelloDone + tls_trace("send ServerHelloDone\n"); + tls_record_set_handshake_server_hello_done(record, &recordlen); + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + + // recv ClientCertificate + if (conn->ca_certs_len) { + tls_trace("recv ClientCertificate\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { // protocol检查应该在trace之后 + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate(record, conn->client_certs, &conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (x509_certs_verify(conn->client_certs, conn->client_certs_len, X509_cert_chain_client, + conn->ca_certs, conn->ca_certs_len, verify_depth, &verify_result) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + } + + // recv ClientKeyExchange + tls_trace("recv ClientKeyExchange\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); // 应该给tls12一个独立的trace + if (tls_record_get_handshake_client_key_exchange_ecdhe(record, &client_ecdhe_point) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + + // recv CertificateVerify + if (client_verify) { + tls_trace("recv CertificateVerify\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + tls_send_alert(conn, TLS_alert_unexpected_message); + error_print(); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate_verify(record, &sig, &siglen) != 1) { + tls_send_alert(conn, TLS_alert_unexpected_message); + error_print(); + goto end; + } + if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len, 0, &cp, &len) != 1 + || x509_cert_get_subject_public_key(cp, len, &client_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + if (tls_client_verify_finish(&client_verify_ctx, sig, siglen, &client_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + } + + // generate secrets + tls_trace("generate secrets\n"); + sm2_do_ecdh(&server_ecdhe_key, &client_ecdhe_point, &client_ecdhe_point); + memcpy(pre_master_secret, (uint8_t *)&client_ecdhe_point, 32); // 这里应该修改一下表示方式,比如get_xy() + 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, 4); + */ + + // recv [ChangeCipherSpec] + tls_trace("recv [ChangeCipherSpec]\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_change_cipher_spec(record) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + + // recv ClientFinished + tls_trace("recv Finished\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1 + || tls_record_protocol(record) != conn->protocol) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (recordlen > sizeof(finished_record)) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls12_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + + // decrypt ClientFinished + tls_trace("decrypt Finished\n"); + if (tls_record_decrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key, + conn->client_seq_num, record, recordlen, finished_record, &finished_record_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls12_record_trace(stderr, finished_record, finished_record_len, 0, 0); + tls_seq_num_incr(conn->client_seq_num); + if (tls_record_get_handshake_finished(finished_record, &verify_data, &verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + if (verify_data_len != sizeof(local_verify_data)) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + + // verify ClientFinished + memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(SM3_CTX)); + sm3_update(&sm3_ctx, finished_record + 5, finished_record_len - 5); + sm3_finish(&tmp_sm3_ctx, sm3_hash); + if (tls_prf(conn->master_secret, 48, "client finished", sm3_hash, 32, NULL, 0, + sizeof(local_verify_data), local_verify_data) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { + error_puts("client_finished.verify_data verification failure"); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + + // send [ChangeCipherSpec] + tls_trace("send [ChangeCipherSpec]\n"); + if (tls_record_set_change_cipher_spec(record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + // send ServerFinished + tls_trace("send Finished\n"); + 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 + || tls_record_set_handshake_finished(finished_record, &finished_record_len, + local_verify_data, sizeof(local_verify_data)) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls12_record_trace(stderr, finished_record, finished_record_len, 0, 0); + if (tls_record_encrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key, + conn->server_seq_num, finished_record, finished_record_len, record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls_trace("encrypt Finished\n"); + tls12_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + tls_seq_num_incr(conn->server_seq_num); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + + conn->protocol = conn->protocol; + + fprintf(stderr, "Connection Established!\n\n"); + ret = 1; + +end: + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret)); + if (client_verify) tls_client_verify_cleanup(&client_verify_ctx); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/tls13.c b/Core/GmSSL-3.1.1/src/tls13.c new file mode 100644 index 0000000..4f8d386 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/tls13.c @@ -0,0 +1,2371 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const int tls13_ciphers[] = { TLS_cipher_sm4_gcm_sm3 }; +static size_t tls13_ciphers_count = sizeof(tls13_ciphers)/sizeof(int); + +/* +int tls13_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent) +{ + // 目前只支持TLCP的ECC公钥加密套件,因此不论用哪个套件解析都是一样的 + // 如果未来支持ECDHE套件,可以将函数改为宏,直接传入 (conn->cipher_suite << 8) + format |= tls13_ciphers[0] << 8; + return tls_record_print(fp, record, recordlen, format, indent); +} +*/ + +static int tls13_client_hello_exts[] = { + TLS_extension_supported_versions, + TLS_extension_padding, +}; + + +/* +struct { + opaque content[TLSPlaintext.length]; + ContentType type; + uint8 zeros[length_of_padding]; +} TLSInnerPlaintext; + +struct { + ContentType opaque_type = application_data; // 23 + ProtocolVersion legacy_record_version = 0x0303; // TLS v1.2 + uint16 length; + opaque encrypted_record[TLSCiphertext.length]; +} TLSCiphertext; +*/ +int tls13_gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12], + const uint8_t seq_num[8], int record_type, + const uint8_t *in, size_t inlen, size_t padding_len, // TLSInnerPlaintext.content + uint8_t *out, size_t *outlen) // TLSCiphertext.encrypted_record +{ + uint8_t nonce[12]; + uint8_t aad[5]; + uint8_t *gmac; + uint8_t *mbuf = NULL; // FIXME: update gcm_encrypt API + size_t mlen, clen; + + if (!(mbuf = malloc(inlen + 256))) { + error_print(); + return -1; + } + + // nonce = (zeros|seq_num) xor (iv) + nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0; + memcpy(nonce + 4, seq_num, 8); + gmssl_memxor(nonce, nonce, iv, 12); + + // TLSInnerPlaintext + memcpy(mbuf, in, inlen); + mbuf[inlen] = record_type; + memset(mbuf + inlen + 1, 0, padding_len); + mlen = inlen + 1 + padding_len; + clen = mlen + GHASH_SIZE; + + // aad = TLSCiphertext header + aad[0] = TLS_record_application_data; + aad[1] = 0x03; //TLS_protocol_tls12_major; + aad[2] = 0x03; //TLS_protocol_tls12_minor; + aad[3] = (uint8_t)(clen >> 8); + aad[4] = (uint8_t)(clen); + + gmac = out + mlen; + if (gcm_encrypt(key, nonce, sizeof(nonce), aad, sizeof(aad), mbuf, mlen, out, 16, gmac) != 1) { + error_print(); + free(mbuf); + return -1; + } + *outlen = clen; + free(mbuf); + + return 1; +} + +int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12], + const uint8_t seq_num[8], const uint8_t *in, size_t inlen, + int *record_type, uint8_t *out, size_t *outlen) +{ + uint8_t nonce[12]; + uint8_t aad[5]; + size_t mlen; + const uint8_t *gmac; + + // nonce = (zeros|seq_num) xor (iv) + nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0; + memcpy(nonce + 4, seq_num, 8); + gmssl_memxor(nonce, nonce, iv, 12); + + // aad = TLSCiphertext header + aad[0] = TLS_record_application_data; + aad[1] = 0x03; //TLS_protocol_tls12_major; + aad[2] = 0x03; //TLS_protocol_tls12_minor; + aad[3] = (uint8_t)(inlen >> 8); + aad[4] = (uint8_t)(inlen); + + if (inlen < GHASH_SIZE) { + error_print(); + return -1; + } + mlen = inlen - GHASH_SIZE; + gmac = in + mlen; + + if (gcm_decrypt(key, nonce, 12, aad, 5, in, mlen, gmac, GHASH_SIZE, out) != 1) { + error_print(); + return -1; + } + // remove padding, get record_type + *record_type = 0; + while (mlen--) { + if (out[mlen] != 0) { + *record_type = out[mlen]; + break; + } + } + *outlen = mlen; + if (!tls_record_type_name(*record_type)) { + error_print(); + return -1; + } + return 1; +} + +// 这个函数是不对的,在我们的一些情况下,加密的时候并不会组成完整的数据 +int tls13_record_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12], + const uint8_t seq_num[8], const uint8_t *record, size_t recordlen, size_t padding_len, + uint8_t *enced_record, size_t *enced_recordlen) +{ + // 被加密的是握手消息或者是应用层数据 + + if (tls13_gcm_encrypt(key, iv, + seq_num, record[0], record + 5, recordlen - 5, padding_len, + enced_record + 5, enced_recordlen) != 1) { + error_print(); + return -1; + } + + enced_record[0] = TLS_record_application_data; // 显然这个不太对啊 + enced_record[1] = 0x03; //TLS_protocol_tls12_major; + enced_record[2] = 0x03; //TLS_protocol_tls12_minor; + enced_record[3] = (uint8_t)((*enced_recordlen) >> 8); + enced_record[4] = (uint8_t)(*enced_recordlen); + + (*enced_recordlen) += 5; + return 1; +} + +int tls13_record_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12], + const uint8_t seq_num[8], const uint8_t *enced_record, size_t enced_recordlen, + uint8_t *record, size_t *recordlen) +{ + int record_type; + + if (tls13_gcm_decrypt(key, iv, + seq_num, enced_record + 5, enced_recordlen - 5, + &record_type, record + 5, recordlen) != 1) { + error_print(); + return -1; + } + record[0] = record_type; + record[1] = 0x03; //TLS_protocol_tls12_major; + record[2] = 0x03; //TLS_protocol_tls12_minor; + record[3] = (uint8_t)((*recordlen) >> 8); + record[4] = (uint8_t)(*recordlen); + + (*recordlen) += 5; + return 1; +} + +int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *sentlen) +{ + const BLOCK_CIPHER_KEY *key; + const uint8_t *iv; + uint8_t *seq_num; + uint8_t *record = conn->record; + size_t recordlen; + size_t padding_len = 0; //FIXME: 在conn中设置是否加随机填充,及设置该值 + + tls_trace("send {ApplicationData}\n"); + + if (conn->is_client) { + key = &conn->client_write_key; + iv = conn->client_write_iv; + seq_num = conn->client_seq_num; + } else { + key = &conn->server_write_key; + iv = conn->server_write_iv; + seq_num = conn->server_seq_num; + } + + if (tls13_gcm_encrypt(key, iv, + seq_num, TLS_record_application_data, data, datalen, padding_len, + record + 5, &recordlen) != 1) { + error_print(); + return -1; + } + + record[0] = TLS_record_application_data; + record[1] = TLS_protocol_tls12 >> 8; + record[2] = TLS_protocol_tls12 & 0xff; + record[3] = (uint8_t)(recordlen >> 8); + record[4] = (uint8_t)(recordlen); + recordlen += 5; + + tls_record_send(record, recordlen, conn->sock); + tls_record_trace(stderr, record, tls_record_length(record), 0, 0); + + tls_seq_num_incr(seq_num); + + *sentlen = datalen; + + return 1; +} + +/* +int tls13_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen) +{ + int record_type; + uint8_t *record = conn->record; + size_t recordlen; + const BLOCK_CIPHER_KEY *key; + const uint8_t *iv; + uint8_t *seq_num; + + + tls_trace("recv {ApplicationData}\n"); + + if (conn->is_client) { + key = &conn->server_write_key; + iv = conn->server_write_iv; + seq_num = conn->server_seq_num; + } else { + key = &conn->client_write_key; + iv = conn->client_write_iv; + seq_num = conn->client_seq_num; + } + + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { + error_print(); + return -1; + } + if (record[0] != TLS_record_application_data) { + error_print(); + return -1; + } + + if (tls13_gcm_decrypt(key, iv, + seq_num, record + 5, recordlen - 5, + &record_type, data, datalen) != 1) { + error_print(); + return -1; + } + + tls_record_trace(stderr, record, tls_record_length(record), 0, 0); + tls_seq_num_incr(seq_num); + + if (record_type != TLS_record_application_data) { + error_print(); + return -1; + } + return 1; +} +*/ + +int tls13_do_recv(TLS_CONNECT *conn) +{ + int ret; + const BLOCK_CIPHER_KEY *key; + const uint8_t *iv; + uint8_t *seq_num; + uint8_t *record = conn->record; + size_t recordlen; + int record_type; + + if (conn->is_client) { + key = &conn->server_write_key; + iv = conn->server_write_iv; + seq_num = conn->server_seq_num; + } else { + key = &conn->client_write_key; + iv = conn->client_write_iv; + seq_num = conn->client_seq_num; + } + + tls_trace("recv ApplicationData\n"); + if ((ret = tls_record_recv(record, &recordlen, conn->sock)) != 1) { + if (ret < 0) error_print(); + return ret; + } + tls_record_trace(stderr, record, recordlen, 0, 0); + // TODO: 是否需要检查record_type? record[0] != TLS_record_application_data + + if (tls13_gcm_decrypt(key, iv, + seq_num, record + 5, recordlen - 5, + &record_type, conn->databuf, &conn->datalen) != 1) { + error_print(); + return -1; + } + conn->data = conn->databuf; + tls_seq_num_incr(seq_num); + + tls_record_set_data(record, conn->data, conn->datalen); + tls_trace("decrypt ApplicationData\n"); + tls_record_trace(stderr, record, tls_record_length(record), 0, 0); + + + if (record_type != TLS_record_application_data) { + error_print(); + return -1; + } + return 1; +} + +int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen) +{ + if (!conn || !out || !outlen || !recvlen) { + error_print(); + return -1; + } + if (conn->datalen == 0) { + int ret; + if ((ret = tls13_do_recv(conn)) != 1) { + if (ret) error_print(); + return ret; + } + } + *recvlen = outlen <= conn->datalen ? outlen : conn->datalen; + memcpy(out, conn->data, *recvlen); + conn->data += *recvlen; + conn->datalen -= *recvlen; + return 1; +} + + + +/* +HKDF-Expand-Label(Secret, Label, Context, Length) = + HKDF-Expand(Secret, HkdfLabel, Length); + + HkdfLabel = struct { + uint16 length = Length; + opaque label<7..255> = "tls13 " + Label; + opaque context<0..255> = Context; } + +Derive-Secret(Secret, Label, Messages) = + HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.length) + +*/ + +int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32]) +{ + size_t dgstlen; + + if (hkdf_extract(digest, salt, 32, in, 32, out, &dgstlen) != 1 + || dgstlen != 32) { + error_print(); + return -1; + } + return 1; +} + +int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32], + const char *label, const uint8_t *context, size_t context_len, + size_t outlen, uint8_t *out) +{ + uint8_t label_len; + uint8_t hkdf_label[2 + 256 + 256]; + uint8_t *p = hkdf_label; + size_t hkdf_label_len = 0; + + label_len = (uint8_t)(strlen("tls13 ") + strlen(label)); //FIXME: check length < 255 + tls_uint16_to_bytes((uint16_t)outlen, &p, &hkdf_label_len); + tls_uint8_to_bytes(label_len, &p, &hkdf_label_len); + tls_array_to_bytes((uint8_t *)"tls13 ", strlen("tls13 "), &p, &hkdf_label_len); + tls_array_to_bytes((uint8_t *)label, strlen(label), &p, &hkdf_label_len); + tls_uint8array_to_bytes(context, context_len, &p, &hkdf_label_len); + + hkdf_expand(digest, secret, 32, hkdf_label, hkdf_label_len, outlen, out); + + return 1; +} + +int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32]) +{ + DIGEST_CTX ctx = *dgst_ctx; + uint8_t dgst[64]; + size_t dgstlen; + + if (digest_finish(&ctx, dgst, &dgstlen) != 1 + || tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, dgst, 32, dgstlen, out) != 1) { + error_print(); + return -1; + } + return 1; +} + +static const uint8_t TLS13_client_context_str_and_zero[] = "TLS 1.3, client CertificateVerify"; +static const uint8_t TLS13_server_context_str_and_zero[] = "TLS 1.3, server CertificateVerify"; +static size_t TLS13_client_context_str_and_zero_size = sizeof(TLS13_client_context_str_and_zero); +static size_t TLS13_server_context_str_and_zero_size = sizeof(TLS13_server_context_str_and_zero); + +int tls13_sign_certificate_verify(int tls_mode, + const SM2_KEY *key, const char *signer_id, size_t signer_id_len, + const DIGEST_CTX *tbs_dgst_ctx, + uint8_t *sig, size_t *siglen) +{ + SM2_SIGN_CTX sign_ctx; + uint8_t prefix[64]; + const uint8_t *context_str_and_zero; + size_t context_str_and_zero_len; + DIGEST_CTX dgst_ctx; + uint8_t dgst[64]; + size_t dgstlen; + + memset(prefix, 0x20, 64); + + switch (tls_mode) { + case TLS_client_mode: + context_str_and_zero = TLS13_client_context_str_and_zero; + context_str_and_zero_len = TLS13_client_context_str_and_zero_size; + break; + case TLS_server_mode: + context_str_and_zero = TLS13_server_context_str_and_zero; + context_str_and_zero_len = TLS13_server_context_str_and_zero_size; + break; + default: + error_print(); + return -1; + } + + dgst_ctx = *tbs_dgst_ctx; + digest_finish(&dgst_ctx, dgst, &dgstlen); + + sm2_sign_init(&sign_ctx, key, signer_id, signer_id_len); + sm2_sign_update(&sign_ctx, prefix, 64); + sm2_sign_update(&sign_ctx, context_str_and_zero, context_str_and_zero_len); + sm2_sign_update(&sign_ctx, dgst, dgstlen); + sm2_sign_finish(&sign_ctx, sig, siglen); + + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + return 1; +} + +int tls13_verify_certificate_verify(int tls_mode, + const SM2_KEY *public_key, const char *signer_id, size_t signer_id_len, + const DIGEST_CTX *tbs_dgst_ctx, const uint8_t *sig, size_t siglen) +{ + int ret; + SM2_SIGN_CTX verify_ctx; + uint8_t prefix[64]; + const uint8_t *context_str_and_zero; + size_t context_str_and_zero_len; + DIGEST_CTX dgst_ctx; + uint8_t dgst[64]; + size_t dgstlen; + + memset(prefix, 0x20, 64); + + switch (tls_mode) { + case TLS_client_mode: + context_str_and_zero = TLS13_client_context_str_and_zero; + context_str_and_zero_len = TLS13_client_context_str_and_zero_size; + break; + case TLS_server_mode: + context_str_and_zero = TLS13_server_context_str_and_zero; + context_str_and_zero_len = TLS13_server_context_str_and_zero_size; + break; + default: + error_print(); + return -1; + } + + dgst_ctx = *tbs_dgst_ctx; + digest_finish(&dgst_ctx, dgst, &dgstlen); + + sm2_verify_init(&verify_ctx, public_key, signer_id, signer_id_len); + sm2_verify_update(&verify_ctx, prefix, 64); + sm2_verify_update(&verify_ctx, context_str_and_zero, context_str_and_zero_len); + sm2_verify_update(&verify_ctx, dgst, dgstlen); + + if ((ret = sm2_verify_finish(&verify_ctx, sig, siglen)) < 0) { + error_print(); + return -1; + } + if (ret != 1) { + error_print(); + } + return ret; +} + +/* + verify_data in Finished + + finished_key = + HKDF-Expand-Label(BaseKey, "finished", "", Hash.length) + Structure of this message: + struct { + opaque verify_data[Hash.length]; + } Finished; + The verify_data value is computed as follows: + verify_data = + HMAC(finished_key, + Transcript-Hash(Handshake Context, + Certificate*, CertificateVerify*)) +*/ + +int tls13_compute_verify_data(const uint8_t *handshake_traffic_secret, + const DIGEST_CTX *dgst_ctx, uint8_t *verify_data, size_t *verify_data_len) +{ + DIGEST_CTX temp_dgst_ctx; + uint8_t dgst[64]; + size_t dgstlen; + uint8_t finished_key[64]; + size_t finished_key_len; + + temp_dgst_ctx = *dgst_ctx; + digest_finish(&temp_dgst_ctx, dgst, &dgstlen); + finished_key_len = dgstlen; + + tls13_hkdf_expand_label(dgst_ctx->digest, handshake_traffic_secret, + "finished", NULL, 0, finished_key_len, finished_key); + + hmac(dgst_ctx->digest, finished_key, finished_key_len, dgst, dgstlen, verify_data, verify_data_len); + return 1; +} + +/* +Handshakes + +*/ + +int tls13_client_hello_exts_set(uint8_t *exts, size_t *extslen, size_t maxlen, + const SM2_POINT *client_ecdhe_public) +{ + int protocols[] = { TLS_protocol_tls13 }; + int supported_groups[] = { TLS_curve_sm2p256v1 }; + int sig_algs[] = { TLS_sig_sm2sig_sm3 }; + size_t protocols_cnt = sizeof(protocols)/sizeof(int); + size_t supported_groups_cnt = sizeof(supported_groups)/sizeof(int); + size_t sig_algs_cnt = sizeof(sig_algs)/sizeof(int); + + + if (!exts || !extslen || !client_ecdhe_public) { + error_print(); + return -1; + } + + *extslen = 0; + if (tls13_supported_versions_ext_to_bytes(TLS_client_mode, protocols, protocols_cnt, NULL, extslen) != 1 + || tls_supported_groups_ext_to_bytes(supported_groups, supported_groups_cnt, NULL, extslen) != 1 + || tls_signature_algorithms_ext_to_bytes(sig_algs, sig_algs_cnt, NULL, extslen) != 1 + || tls13_client_key_share_ext_to_bytes(client_ecdhe_public, NULL, extslen) != 1) { + error_print(); + return -1; + } + if (*extslen > maxlen) { + error_print(); + return -1; + } + *extslen = 0; + tls13_supported_versions_ext_to_bytes(TLS_client_mode, protocols, protocols_cnt, &exts, extslen); + tls_supported_groups_ext_to_bytes(supported_groups, supported_groups_cnt, &exts, extslen); + tls_signature_algorithms_ext_to_bytes(sig_algs, sig_algs_cnt, &exts, extslen); + tls13_client_key_share_ext_to_bytes(client_ecdhe_public, &exts, extslen); + return 1; +} + +int tls13_process_client_hello_exts(const uint8_t *exts, size_t extslen, + const SM2_KEY *server_ecdhe_key, SM2_POINT *client_ecdhe_public, + uint8_t *server_exts, size_t *server_exts_len, size_t server_exts_maxlen) +{ + size_t len = 0; + *server_exts_len = 0; + + while (extslen) { + uint16_t ext_type; + const uint8_t *ext_data; + size_t ext_datalen; + + 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; + } + + switch (ext_type) { + /* + // tls13_process_client_hello_exts 的接口需要处理,部分输出要输出到server_exts中 + case TLS_extension_supported_groups: // 这个应该放在EE里面 + if (tls_process_client_supported_groups(ext_data, ext_datalen, NULL, &len) != 1 + || len > server_exts_maxlen) { + error_print(); + return -1; + } + tls_process_client_supported_groups(ext_data, ext_datalen, &server_exts, server_exts_len); + break; + case TLS_extension_signature_algorithms: // client单方面通知就可以了,服务器不需要响应 + if (tls_process_client_signature_algorithms(ext_data, ext_datalen, NULL, &len) != 1 + || len > server_exts_maxlen) { + error_print(); + return -1; + } + tls_process_client_signature_algorithms(ext_data, ext_datalen, &server_exts, server_exts_len); + break; + */ + case TLS_extension_supported_versions: + if (tls13_process_client_supported_versions(ext_data, ext_datalen, NULL, &len) != 1 + || len > server_exts_maxlen) { + error_print(); + return -1; + } + tls13_process_client_supported_versions(ext_data, ext_datalen, &server_exts, server_exts_len); + break; + case TLS_extension_key_share: + if (tls13_process_client_key_share(ext_data, ext_datalen, server_ecdhe_key, client_ecdhe_public, &server_exts, server_exts_len) != 1 + || len > server_exts_maxlen) { + error_print(); + return -1; + } + break; + + default: + ; // server ignore unkonwn extensions + } + } + + return 1; +} + +int tls_client_key_shares_from_bytes(SM2_POINT *sm2_point, const uint8_t **in, size_t *inlen) +{ + const uint8_t *key_shares; + size_t key_shares_len; + + tls_uint16array_from_bytes(&key_shares, &key_shares_len, in, inlen); + + while (key_shares_len) { + uint16_t group; + const uint8_t *key_exch; + size_t key_exch_len; + + tls_uint16_from_bytes(&group, &key_shares, &key_shares_len); + tls_uint16array_from_bytes(&key_exch, &key_exch_len, &key_shares, &key_shares_len); + + if (key_exch_len != 65) { + error_print(); + return -1; + } + + switch (group) { + case TLS_curve_sm2p256v1: + sm2_point_from_octets(sm2_point, key_exch, key_exch_len); + break; + default: + error_print(); + return -1; + } + } + + return 1; +} + +// 这个函数不是太正确,应该也是一个process +int tls13_server_hello_extensions_get(const uint8_t *exts, size_t extslen, SM2_POINT *sm2_point) +{ + uint16_t version; + while (extslen) { + uint16_t ext_type; + const uint8_t *ext_data; + size_t ext_datalen; + + tls_uint16_from_bytes(&ext_type, &exts, &extslen); + tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen); + + switch (ext_type) { + case TLS_extension_supported_versions: + if (tls_uint16_from_bytes(&version, &ext_data, &ext_datalen) != 1 + || ext_datalen > 0) { + error_print(); + return -1; + } + if (version != TLS_protocol_tls13) { + error_print(); + return -1; + } + break; + case TLS_extension_key_share: + if (tls13_process_server_key_share(ext_data, ext_datalen, sm2_point) != 1) { + error_print(); + return -1; + } + break; + //default: + // FIXME: 还有几个扩展没有处理! + //error_print(); + //return -1; + } + } + return 1; +} + + +/* +struct { + Extension extensions<0..2^16-1>; +} EncryptedExtensions; +*/ +static int tls13_encrypted_exts[] = { + TLS_extension_server_name, + TLS_extension_max_fragment_length, + TLS_extension_supported_groups, + TLS_extension_use_srtp, + TLS_extension_heartbeat, + TLS_extension_application_layer_protocol_negotiation, + TLS_extension_client_certificate_type, + TLS_extension_server_certificate_type, + TLS_extension_early_data, +}; + +int tls13_encrypted_extensions_print(FILE *fp, int fmt, int ind, const uint8_t *data, size_t datalen) +{ + const uint8_t *exts; + size_t extslen; + + format_print(fp, fmt, ind, "EncryptedExtensions\n"); + ind += 4; + + if (tls_uint16array_from_bytes(&exts, &extslen, &data, &datalen) != 1) { + error_print(); + return -1; + } + if (exts) { + tls13_extensions_print(fp, fmt, ind, TLS_handshake_encrypted_extensions, exts, extslen); + } + if (tls_length_is_zero(datalen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls13_record_set_handshake_encrypted_extensions(uint8_t *record, size_t *recordlen) +{ + int type = TLS_handshake_encrypted_extensions; + uint8_t *p = record + 5 + 4; + size_t len = 0; + uint8_t exts[128]; + size_t extslen = 0; + uint8_t *pexts = exts; + const int supported_groups[] = { TLS_curve_sm2p256v1 }; + + tls_supported_groups_ext_to_bytes(supported_groups, sizeof(supported_groups)/sizeof(int), &pexts, &extslen); + + tls_uint16array_to_bytes(exts, extslen, &p, &len); + tls_record_set_handshake(record, recordlen, type, NULL, len); + + return 1; +} + +int tls13_record_get_handshake_encrypted_extensions(const uint8_t *record) +{ + int type; + const uint8_t *p; + size_t len; + const uint8_t *exts_data; + size_t exts_datalen; + + if (tls_record_get_handshake(record, &type, &p, &len) != 1) { + error_print(); + return -1; + } + if (tls_uint16array_from_bytes(&exts_data, &exts_datalen, &p, &len) != 1) { + error_print(); + return -1; + } + // 当前实现不需要在EncryptedExtensions提供扩展 + if (exts_datalen) { + // FIXME: 实际上supported_groups是放在这里的,应该加以处理 + //error_print(); + //return -1; + } + return 1; +} + + +/* + ClientHello.Extensions.signature_algorithms 列出客户端支持的签名+哈希算法 + ServerHello.Extensions.supported_groups 决定了服务器的公钥类型, + 因此也决定了服务器的签名算法 + ServerHello.cipher_suite决定了哈希函数 +*/ + +/* +struct { + SignatureScheme algorithm; + opaque signature<0..2^16-1>; +} CertificateVerify; + +注意:TLS 1.2中只有RAW signature, 也就是没有经过uint16array封装的,这其实不太符合TLS的设计逻辑 +*/ +int tls13_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen, + int sign_algor, const uint8_t *sig, size_t siglen) +{ + int type = TLS_handshake_certificate_verify; + uint8_t *p = record + 5 + 4; + size_t len = 0; + + tls_uint16_to_bytes((uint16_t)sign_algor, &p, &len); + tls_uint16array_to_bytes(sig, siglen, &p, &len); + + if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls13_record_get_handshake_certificate_verify(const uint8_t *record, + int *sign_algor, const uint8_t **sig, size_t *siglen) +{ + int type; + const uint8_t *p; + size_t len ; + uint16_t alg; + + if (tls_record_get_handshake(record, &type, &p, &len) != 1 + || type != TLS_handshake_certificate_verify) { + error_print(); + return -1; + } + + tls_uint16_from_bytes(&alg, &p, &len); + tls_uint16array_from_bytes(sig, siglen, &p, &len); + *sign_algor = alg; + + return 1; +} + + +/* +struct { + opaque certificate_request_context<0..2^8-1>; + Extension extensions<2..2^16-1>; +} CertificateRequest; + +certificate_request_context 用于 Post-handshake Authentication,否则应该长度为0 + +*/ +static int tls13_certificate_request_exts[] = { + TLS_extension_signature_algorithms, // 必须包含 + TLS_extension_status_request, + TLS_extension_signed_certificate_timestamp, + TLS_extension_certificate_authorities, + TLS_extension_oid_filters, + TLS_extension_signature_algorithms_cert, +}; + + + + +/* +struct { + opaque certificate_request_context<0..2^8-1>; + Extension extensions<2..2^16-1>; +} CertificateRequest; + +extensiosns: + Extension signature_algorithms MUST be specified +*/ +int tls13_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen, + const uint8_t *request_context, size_t request_context_len, + const uint8_t *exts, size_t extslen) +{ + int type = TLS_handshake_certificate_request; + uint8_t *data; + size_t datalen = 0; + + if (!record || !recordlen) { + error_print(); + return -1; + } + data = tls_handshake_data(tls_record_data(record)); + tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen); + tls_uint16array_to_bytes(exts, extslen, &data, &datalen); + tls_record_set_handshake(record, recordlen, type, NULL, datalen); + return 1; +} + +int tls13_record_set_handshake_certificate_request_default(uint8_t *record, size_t *recordlen) +{ + int sig_algs[] = { TLS_sig_sm2sig_sm3 }; + uint8_t exts[256]; + uint8_t *p = exts; + size_t extslen = 0; + + tls_signature_algorithms_ext_to_bytes(sig_algs, sizeof(sig_algs)/sizeof(int), &p, &extslen); + tls13_record_set_handshake_certificate_request(record, recordlen, NULL, 0, exts, extslen); + return 1; +} + +int tls13_record_get_handshake_certificate_request(const uint8_t *record, + const uint8_t **requst_context, size_t *request_context_len, + const uint8_t **exts, size_t *exts_len) +{ + int type; + const uint8_t *p; + size_t len; + + if (tls_record_get_handshake(record, &type, &p, &len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_certificate_request) { + error_print(); + return -1; + } + if (tls_uint8array_from_bytes(requst_context, request_context_len, &p, &len) != 1 + || tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +static const int tls13_handshake_certificate_exts[] = { + TLS_extension_status_request, + TLS_extension_signed_certificate_timestamp, +}; +/* +enum { X509(0), RawPublicKey(2), (255) } CertificateType; + +struct { + select (certificate_type) { + case RawPublicKey: opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; -- TLS 1.3可以只传公钥不传证书 + case X509: opaque cert_data<1..2^24-1>; + }; + Extension extensions<0..2^16-1>; +} CertificateEntry; + +struct { + opaque certificate_request_context<0..2^8-1>; -- 用于客户端证书,服务器证书该域长度为0 + CertificateEntry certificate_list<0..2^24-1>; +} Certificate; + +TLS 1.3 Certificate: + + * TLS 1.3 支持发送公钥,可以去掉嵌入式环境的证书传输开销 + * TLS 1.3 的证书链中增加了 certificate_request_context + 用于客户端发送证书时标识context,服务器端的证书中该域的长度为0 + * 证书链中每个证书都有一个独立的扩展域,TLS 1.2 中的证书相关扩展移至此处 + +Extensions in client Certificate MUST from ClientHello +Extensions in server Certificate MUST from CertificateRequest +Entensions apply to entire chain SHOULD be in the first CertificateEntry + +目前CertificateEntry中的扩展主要用于服务器证书的验证 +客户端在ClientHello中可以包含status_request 和 signed_certificate_timestamp +让服务器提供 OCSP 的状态证明和时间戳信息 +服务器则在证书消息的每个证书否面附带这两个扩展,提供相关信息 + +在 RFC 8446 (TLS 1.3) 中还没有涉及客户端证书的具体扩展 +但是客户端在提供客户端证书时,应该响应服务器CertificateRequest消息中的扩展 + +目前GmSSLv3还不支持这两个证书扩展的生成,但是提供解析和显示 + +Valid extensions for server certificates: + TLS_extension_status_request (5) + TLS_extension_signed_certificate_timestamp (18) +*/ + +int tls13_certificate_print(FILE *fp, int fmt, int ind, const uint8_t *cert, size_t certlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "Certificate\n"); + ind += 4; + + if (tls_uint8array_from_bytes(&p, &len, &cert, &certlen) != 1) { + error_print(); + return -1; + } + format_bytes(fp, fmt, ind, "certificate_request_context", p, len); + + format_print(fp, fmt, ind, "certificate_list\n"); + ind += 4; + if (tls_uint24array_from_bytes(&p, &len, &cert, &certlen) != 1) { + error_print(); + return -1; + } + while (len) { + const uint8_t *cert_data; + size_t cert_data_len; + const uint8_t *exts; + size_t extslen; + + if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &p, &len) != 1 + || tls_uint16array_from_bytes(&exts, &extslen, &p, &len) != 1) { + error_print(); + return -1; + } + if (!cert_data) { + error_print(); + return -1; + } + + format_print(fp, fmt, ind, "CertificateEntry\n"); + x509_cert_print(fp, fmt, ind + 4, "Certificate", cert_data, cert_data_len); + x509_cert_to_pem(cert_data, cert_data_len, fp); + tls13_extensions_print(fp, fmt, ind + 4, TLS_handshake_certificate, exts, extslen); + } + return 1; +} + +int tls13_certificate_request_print(FILE *fp, int fmt, int ind, const uint8_t *certreq, size_t certreqlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "CertificateRequest\n"); + ind += 4; + + if (tls_uint8array_from_bytes(&p, &len, &certreq, &certreqlen) != 1) { + error_print(); + return -1; + } + format_bytes(fp, fmt, ind, "certificate_request_context", p, len); + + if (tls_uint16array_from_bytes(&p, &len, &certreq, &certreqlen) != 1) { + error_print(); + return -1; + } + format_bytes(fp, fmt, ind, "extensions", p, len); + + if (tls_length_is_zero(certreqlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls13_certificate_verify_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen) +{ + uint16_t sig_alg; + const uint8_t *sig; + size_t siglen; + + format_print(fp, fmt, ind, "CertificateVerify\n"); + ind += 4; + + if (tls_uint16_from_bytes(&sig_alg, &d, &dlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "algorithm: %s (0x%04x)\n", tls_signature_scheme_name(sig_alg), sig_alg); + if (tls_uint16array_from_bytes(&sig, &siglen, &d, &dlen) != 1) { + error_print(); + return -1; + } + format_bytes(fp, fmt, ind, "signature", sig, siglen); + if (tls_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls13_certificate_list_to_bytes(const uint8_t *certs, size_t certslen, + uint8_t **out, size_t *outlen) +{ + uint8_t *p = NULL; + size_t cert_list_len = 0; + + if (out && *out) { + p = (*out) + tls_uint24_size(); + } + while (certslen) { + const uint8_t *cert; + size_t certlen; + const uint8_t *entry_exts = NULL; + size_t entry_exts_len = 0; + + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + tls_uint24array_to_bytes(cert, certlen, &p, &cert_list_len); + tls_uint16array_to_bytes(entry_exts, entry_exts_len, &p, &cert_list_len); + + } + tls_uint24array_to_bytes(NULL, cert_list_len, out, outlen); + return 1; +} + +int tls13_process_certificate_list(const uint8_t *cert_list, size_t cert_list_len, + uint8_t *certs, size_t *certs_len) +{ + *certs_len = 0; + + while (cert_list_len) { + const uint8_t *cert_data; + size_t cert_data_len; + const uint8_t *exts; + size_t exts_len; + const uint8_t *cert; + size_t cert_len; + + if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &cert_list, &cert_list_len) != 1 + || tls_uint16array_from_bytes(&exts, &exts_len, &cert_list, &cert_list_len) != 1) { + error_print(); + return -1; + } + if (x509_cert_from_der(&cert, &cert_len, &cert_data, &cert_data_len) != 1 + || asn1_length_is_zero(cert_data_len) != 1 + || x509_cert_to_der(cert, cert_len, &certs, certs_len) != 1) { + error_print(); + return -1; + } + + while (exts_len) { + int ext_type; + const uint8_t *ext_data; + size_t ext_data_len; + + if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_data_len, &exts, &exts_len) != 1) { + error_print(); + return -1; + } + switch (ext_type) { + case TLS_extension_status_request: + case TLS_extension_signed_certificate_timestamp: + error_print(); + return -1; + default: + error_print(); + return -1; + } + } + } + return 1; +} + +int tls13_record_set_handshake_certificate(uint8_t *record, size_t *recordlen, + const uint8_t *request_context, size_t request_context_len, + const uint8_t *certs, size_t certslen) +{ + int type = TLS_handshake_certificate; + uint8_t *data; + size_t datalen; + + if (!record || !recordlen || !certs || !certslen) { + error_print(); + return -1; + } + + datalen = 0; + tls_uint8array_to_bytes(request_context, request_context_len, NULL, &datalen); + tls13_certificate_list_to_bytes(certs, certslen, NULL, &datalen); + if (datalen > TLS_MAX_HANDSHAKE_DATA_SIZE) { + error_print(); + return -1; + } + + data = tls_handshake_data(tls_record_data(record)); + datalen = 0; + tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen); + tls13_certificate_list_to_bytes(certs, certslen, &data, &datalen); + tls_record_set_handshake(record, recordlen, type, NULL, datalen); + + return 1; +} + +int tls13_record_get_handshake_certificate(const uint8_t *record, + const uint8_t **cert_request_context, size_t *cert_request_context_len, + const uint8_t **cert_list, size_t *cert_list_len) +{ + int type; + const uint8_t *p; + size_t len; + + if (tls_record_get_handshake(record, &type, &p, &len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_certificate) { + error_print(); + return -1; + } + if (tls_uint8array_from_bytes(cert_request_context, cert_request_context_len, &p, &len) != 1 + || tls_uint24array_from_bytes(cert_list, cert_list_len, &p, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (*cert_list == NULL) { + error_print(); + return -1; + } + return 1; +} + + + +/* +finished_key = HKDF-Expand-Label(BaseKey, "finished", "", Hash.length) + +struct { + opaque verify_data[Hash.length]; +} Finished; + +verify_data = HMAC(finished_key, Hash(Handshake Context, Certificate*, CertificateVerify*)) +Hash = SM3, SHA256 or SHA384 +*/ + + +int tls13_record_set_handshake_finished(uint8_t *record, size_t *recordlen, + const uint8_t *verify_data, size_t verify_data_len) +{ + int type = TLS_handshake_finished; + if (!record || !recordlen || !verify_data) { + error_print(); + return -1; + } + tls_record_set_handshake(record, recordlen, type, verify_data, verify_data_len); + return 1; +} + +int tls13_record_get_handshake_finished(const uint8_t *record, + const uint8_t **verify_data, size_t *verify_data_len) +{ + int type; + + if (tls_record_get_handshake(record, &type, verify_data, verify_data_len) != 1) { + error_print(); + return -1; + } + if (type != TLS_handshake_finished) { + error_print(); + return -1; + } + if (*verify_data_len != SM3_DIGEST_SIZE + && *verify_data_len != SHA384_DIGEST_SIZE) { + error_print(); + return -1; + } + return 1; +} + + +int tls13_padding_len_rand(size_t *padding_len) +{ + uint8_t val; + rand_bytes(&val, 1); + *padding_len = val % 128; + return 1; +} + + + +int tls13_cipher_suite_get(int cipher_suite, const DIGEST **digest, const BLOCK_CIPHER **cipher) +{ + switch (cipher_suite) { + case TLS_cipher_sm4_gcm_sm3: + *digest = DIGEST_sm3(); + *cipher = BLOCK_CIPHER_sm4(); + break; + case TLS_cipher_aes_128_gcm_sha256: + *digest = DIGEST_sha256(); + *cipher = BLOCK_CIPHER_aes128(); + break; + default: + error_print(); + return -1; + } + return 1; +} + + + +/* + Client Server + +Key ^ ClientHello +Exch | + key_share* + | + signature_algorithms* + | + psk_key_exchange_modes* + v + pre_shared_key* --------> + ServerHello ^ Key + + key_share* | Exch + + pre_shared_key* v + + + | ecdhe => handshake_secret | + | handshake_secret => master_secret | + | handshake_secret, client_hello, server_hello | + | => client_handshake_traffic_secret | + | => server_handshake_traffic_secret | + + + {EncryptedExtensions} ^ Server + {CertificateRequest*} v Params + {Certificate} ^ + {CertificateVerify} | Auth + {Finished} v + + + master_secret, ClientHello .. server Finished + => server_application_traffic_secret_0 + + <-------- [Application Data*] + + ^ {Certificate*} +Auth | {CertificateVerify*} + v {Finished} --------> + + + + master_secret, ClientHello .. server Finished + => client_application_traffic_secret_0 + + [Application Data] <-------> [Application Data] + + +TLS 1.3的区别: + + * 首先在最开始的握手阶段就协商好了密钥,因此握手之后传输的就是加密消息了 + * 因此在第二阶段,双方不再发送ServerKeyExchange和ClientKeyExchange + * 服务器先发送CertificateRequest,再发送Certificate + * 没有ChangeCipherSpec了 + * 在握手阶段就需要加密,并且Certificate也在其中,因此需要格外的大的密文数据缓冲 + + 0 + | + v +[1] PSK -> HKDF-Extract = Early Secret + | +[2] +-----> Derive-Secret(., "ext binder" | "res binder", "") + | = binder_key + | +[3] +-----> Derive-Secret(., "c e traffic", ClientHello) + | = client_early_traffic_secret + | +[4] +-----> Derive-Secret(., "e exp master", ClientHello) + | = early_exporter_master_secret + v +[5] Derive-Secret(., "derived", "") + | + v +[6] (EC)DHE -> HKDF-Extract = Handshake Secret + | +[7] +-----> Derive-Secret(., "c hs traffic", + | ClientHello...ServerHello) + | = client_handshake_traffic_secret + | +[8] +-----> Derive-Secret(., "s hs traffic", + | ClientHello...ServerHello) + | = server_handshake_traffic_secret + v +[9] Derive-Secret(., "derived", "") + | + v +[10] 0 -> HKDF-Extract = Master Secret + | +[11] +-----> Derive-Secret(., "c ap traffic", + | ClientHello...server Finished) + | = client_application_traffic_secret_0 + | +[12] +-----> Derive-Secret(., "s ap traffic", + | ClientHello...server Finished) + | = server_application_traffic_secret_0 + | +[13] +-----> Derive-Secret(., "exp master", + | ClientHello...server Finished) + | = exporter_master_secret + | +[14] +-----> Derive-Secret(., "res master", + ClientHello...client Finished) + = resumption_master_secret + +*/ + + + +int tls13_do_connect(TLS_CONNECT *conn) +{ + int ret = -1; + uint8_t *record = conn->record; + uint8_t *enced_record = conn->enced_record; + size_t recordlen; + + size_t enced_recordlen; + + + int type; + const uint8_t *data; + size_t datalen; + + int protocol; + uint8_t client_random[32]; + uint8_t server_random[32]; + int cipher_suite; + const uint8_t *random; + const uint8_t *session_id; + size_t session_id_len; + + int protocols[] = { TLS_protocol_tls13 }; + int supported_groups[] = { TLS_curve_sm2p256v1 }; + int sign_algors[] = { TLS_sig_sm2sig_sm3 }; + + uint8_t client_exts[TLS_MAX_EXTENSIONS_SIZE]; + size_t client_exts_len; + const uint8_t *server_exts; + size_t server_exts_len; + + uint8_t sig[TLS_MAX_SIGNATURE_SIZE]; + size_t siglen = sizeof(sig); + uint8_t verify_data[32]; + size_t verify_data_len; + + int server_sign_algor; + const uint8_t *server_sig; + size_t server_siglen; + const uint8_t *server_verify_data; + size_t server_verify_data_len; + + SM2_KEY client_ecdhe; + SM2_POINT server_ecdhe_public; + SM2_KEY server_sign_key; + + const DIGEST *digest = DIGEST_sm3(); + DIGEST_CTX dgst_ctx; // secret generation过程中需要ClientHello等数据输入的 + DIGEST_CTX null_dgst_ctx; // secret generation过程中不需要握手数据的 + const BLOCK_CIPHER *cipher = NULL; + size_t padding_len; + + uint8_t zeros[32] = {0}; + uint8_t psk[32] = {0}; + uint8_t early_secret[32]; + uint8_t handshake_secret[32]; + uint8_t master_secret[32]; + uint8_t client_handshake_traffic_secret[32]; + uint8_t server_handshake_traffic_secret[32]; + uint8_t client_application_traffic_secret[32]; + uint8_t server_application_traffic_secret[32]; + uint8_t client_write_key[16]; + uint8_t server_write_key[16]; + + + const uint8_t *request_context; + size_t request_context_len; + const uint8_t *cert_request_exts; + size_t cert_request_extslen; + const uint8_t *cert_list; + size_t cert_list_len; + const uint8_t *cert; + size_t certlen; + + + conn->is_client = 1; + tls_record_set_protocol(enced_record, TLS_protocol_tls12); + + digest_init(&dgst_ctx, digest); + null_dgst_ctx = dgst_ctx; + + + // send ClientHello + tls_trace("send ClientHello\n"); + tls_record_set_protocol(record, TLS_protocol_tls1); + rand_bytes(client_random, 32); // TLS 1.3 Random 不再包含 UNIX Time + sm2_key_generate(&client_ecdhe); + tls13_client_hello_exts_set(client_exts, &client_exts_len, sizeof(client_exts), &(client_ecdhe.public_key)); + tls_record_set_handshake_client_hello(record, &recordlen, + TLS_protocol_tls12, client_random, NULL, 0, + tls13_ciphers, sizeof(tls13_ciphers)/sizeof(tls13_ciphers[0]), + client_exts, client_exts_len); + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + // 此时尚未确定digest算法,因此无法digest_update + + + // recv ServerHello + tls_trace("recv ServerHello\n"); + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls13_record_trace(stderr, enced_record, enced_recordlen, 0, 0); + if (tls_record_get_handshake_server_hello(enced_record, + &protocol, &random, &session_id, &session_id_len, + &cipher_suite, &server_exts, &server_exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (protocol != TLS_protocol_tls12) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + memcpy(server_random, random, 32); + memcpy(conn->session_id, session_id, session_id_len); + conn->session_id_len = session_id_len; + if (tls_cipher_suite_in_list(cipher_suite, + tls13_ciphers, sizeof(tls13_ciphers)/sizeof(tls13_ciphers[0])) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + conn->cipher_suite = cipher_suite; + if (tls13_server_hello_extensions_get(server_exts, server_exts_len, &server_ecdhe_public) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + conn->protocol = TLS_protocol_tls13; + + tls13_cipher_suite_get(conn->cipher_suite, &digest, &cipher); + digest_update(&dgst_ctx, record + 5, recordlen - 5); + digest_update(&dgst_ctx, enced_record + 5, enced_recordlen - 5); + + + printf("generate handshake secrets\n"); + /* + generate handshake keys + uint8_t client_write_key[32] + uint8_t server_write_key[32] + uint8_t client_write_iv[12] + uint8_t server_write_iv[12] + */ + sm2_do_ecdh(&client_ecdhe, &server_ecdhe_public, &server_ecdhe_public); + /* [1] */ tls13_hkdf_extract(digest, zeros, psk, early_secret); + /* [5] */ tls13_derive_secret(early_secret, "derived", &null_dgst_ctx, handshake_secret); + /* [6] */ tls13_hkdf_extract(digest, handshake_secret, (uint8_t *)&server_ecdhe_public, handshake_secret); + /* [7] */ tls13_derive_secret(handshake_secret, "c hs traffic", &dgst_ctx, client_handshake_traffic_secret); + /* [8] */ tls13_derive_secret(handshake_secret, "s hs traffic", &dgst_ctx, server_handshake_traffic_secret); + /* [9] */ tls13_derive_secret(handshake_secret, "derived", &null_dgst_ctx, master_secret); + /* [10] */ tls13_hkdf_extract(digest, master_secret, zeros, master_secret); + //[sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length) + //[sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length) + //[sender] in {server, client} + tls13_hkdf_expand_label(digest, server_handshake_traffic_secret, "key", NULL, 0, 16, server_write_key); + tls13_hkdf_expand_label(digest, server_handshake_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv); + block_cipher_set_encrypt_key(&conn->server_write_key, cipher, server_write_key); + memset(conn->server_seq_num, 0, 8); + tls13_hkdf_expand_label(digest, client_handshake_traffic_secret, "key", NULL, 0, 16, client_write_key); + tls13_hkdf_expand_label(digest, client_handshake_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv); + block_cipher_set_encrypt_key(&conn->client_write_key, cipher, client_write_key); + memset(conn->client_seq_num, 0, 8); + /* + format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16); + format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16); + format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12); + format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12); + format_print(stderr, 0, 0, "\n"); + */ + + // recv {EncryptedExtensions} + printf("recv {EncryptedExtensions}\n"); + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, enced_record, enced_recordlen, + record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls13_record_get_handshake_encrypted_extensions(record) != 1) { + tls_send_alert(conn, TLS_alert_handshake_failure); + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + + // recv {CertififcateRequest*} or {Certificate} + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, enced_record, enced_recordlen, + record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + if (tls_record_get_handshake(record, &type, &data, &datalen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + if (type == TLS_handshake_certificate_request) { + tls_trace("recv {CertificateRequest*}\n"); + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls13_record_get_handshake_certificate_request(record, + &request_context, &request_context_len, + &cert_request_exts, &cert_request_extslen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + // 当前忽略 request_context 和 cert_request_exts + // request_context 应该为空,当前实现中不支持Post-Handshake Auth + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + + // recv {Certificate} + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_handshake_failure); + goto end; + } + if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, enced_record, enced_recordlen, + record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + } else { + conn->client_certs_len = 0; + // 清空客户端签名密钥 + } + + // recv {Certificate} + tls_trace("recv {Certificate}\n"); + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls13_record_get_handshake_certificate(record, + &request_context, &request_context_len, + &cert_list, &cert_list_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_process_certificate_list(cert_list, cert_list_len, conn->server_certs, &conn->server_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cert, &certlen) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &server_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + // verify ServerCertificate + int verify_result = 0; // TODO: maybe remove this arg from x509_certs_verify() + if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server, + conn->ca_certs, conn->ca_certs_len, X509_MAX_VERIFY_DEPTH, &verify_result) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + + // recv {CertificateVerify} + tls_trace("recv {CertificateVerify}\n"); + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, enced_record, enced_recordlen, + record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls13_record_get_handshake_certificate_verify(record, + &server_sign_algor, &server_sig, &server_siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (server_sign_algor != TLS_sig_sm2sig_sm3) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_verify_certificate_verify(TLS_server_mode, &server_sign_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH, &dgst_ctx, server_sig, server_siglen) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + + // use Transcript-Hash(Handshake Context, Certificate*, CertificateVerify*) + tls13_compute_verify_data(server_handshake_traffic_secret, + &dgst_ctx, verify_data, &verify_data_len); + + + // recv {Finished} + tls_trace("recv {Finished}\n"); + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, enced_record, enced_recordlen, + record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls13_record_get_handshake_finished(record, + &server_verify_data, &server_verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (server_verify_data_len != verify_data_len + || memcmp(server_verify_data, verify_data, verify_data_len) != 0) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + + // generate server_application_traffic_secret + /* [12] */ tls13_derive_secret(master_secret, "s ap traffic", &dgst_ctx, server_application_traffic_secret); + // generate client_application_traffic_secret + /* [11] */ tls13_derive_secret(master_secret, "c ap traffic", &dgst_ctx, client_application_traffic_secret); + + + if (conn->client_certs_len) { + int client_sign_algor; + uint8_t sig[TLS_MAX_SIGNATURE_SIZE]; + size_t siglen; + + // send client {Certificate*} + tls_trace("send {Certificate*}\n"); + if (tls13_record_set_handshake_certificate(record, &recordlen, + NULL, 0, // certificate_request_context + conn->client_certs, conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->client_write_key, conn->client_write_iv, + conn->client_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->client_seq_num); + + + // send {CertificateVerify*} + tls_trace("send {CertificateVerify*}\n"); + client_sign_algor = TLS_sig_sm2sig_sm3; // FIXME: 应该放在conn里面 + tls13_sign_certificate_verify(TLS_client_mode, &conn->sign_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH, &dgst_ctx, sig, &siglen); + if (tls13_record_set_handshake_certificate_verify(record, &recordlen, + client_sign_algor, sig, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->client_write_key, conn->client_write_iv, + conn->client_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->client_seq_num); + } + + // send Client {Finished} + tls_trace("send {Finished}\n"); + tls13_compute_verify_data(client_handshake_traffic_secret, &dgst_ctx, verify_data, &verify_data_len); + if (tls_record_set_handshake_finished(record, &recordlen, verify_data, verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->client_write_key, conn->client_write_iv, + conn->client_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->client_seq_num); + + + + // update server_write_key, server_write_iv, reset server_seq_num + tls13_hkdf_expand_label(digest, server_application_traffic_secret, "key", NULL, 0, 16, server_write_key); + block_cipher_set_encrypt_key(&conn->server_write_key, cipher, server_write_key); + tls13_hkdf_expand_label(digest, server_application_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv); + memset(conn->server_seq_num, 0, 8); + /* + format_print(stderr, 0, 0, "update server secrets\n"); + format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16); + format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12); + format_print(stderr, 0, 0, "\n"); + */ + + //update client_write_key, client_write_iv, reset client_seq_num + tls13_hkdf_expand_label(digest, client_application_traffic_secret, "key", NULL, 0, 16, client_write_key); + tls13_hkdf_expand_label(digest, client_application_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv); + block_cipher_set_encrypt_key(&conn->client_write_key, cipher, client_write_key); + memset(conn->client_seq_num, 0, 8); + + /* + format_print(stderr, 0, 0, "update client secrets\n"); + format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16); + format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12); + format_print(stderr, 0, 0, "\n"); + */ + fprintf(stderr, "Connection established\n"); + ret = 1; + +end: + gmssl_secure_clear(&client_ecdhe, sizeof(client_ecdhe)); + gmssl_secure_clear(&server_sign_key, sizeof(server_sign_key)); + gmssl_secure_clear(psk, sizeof(psk)); + gmssl_secure_clear(early_secret, sizeof(early_secret)); + gmssl_secure_clear(handshake_secret, sizeof(handshake_secret)); + gmssl_secure_clear(master_secret, sizeof(master_secret)); + gmssl_secure_clear(client_handshake_traffic_secret, sizeof(client_handshake_traffic_secret)); + gmssl_secure_clear(server_handshake_traffic_secret, sizeof(server_handshake_traffic_secret)); + gmssl_secure_clear(client_application_traffic_secret, sizeof(client_application_traffic_secret)); + gmssl_secure_clear(server_application_traffic_secret, sizeof(server_application_traffic_secret)); + gmssl_secure_clear(client_write_key, sizeof(client_write_key)); + gmssl_secure_clear(server_write_key, sizeof(server_write_key)); + return ret; +} + +int tls13_do_accept(TLS_CONNECT *conn) +{ + int ret = -1; + uint8_t *record = conn->record; + size_t recordlen; + uint8_t enced_record[25600]; + size_t enced_recordlen = sizeof(enced_record); + + int server_ciphers[] = { TLS_cipher_sm4_gcm_sm3 }; + + + int protocol; + const uint8_t *random; + const uint8_t *session_id; + size_t session_id_len; + const uint8_t *client_exts; + size_t client_exts_len; + + uint8_t client_random[32]; + uint8_t server_random[32]; + const uint8_t *client_ciphers; + size_t client_ciphers_len; + uint8_t server_exts[TLS_MAX_EXTENSIONS_SIZE]; + size_t server_exts_len; + + SM2_KEY server_ecdhe; + SM2_POINT client_ecdhe_public; + SM2_KEY client_sign_key; + const BLOCK_CIPHER *cipher; + const DIGEST *digest; + DIGEST_CTX dgst_ctx; + DIGEST_CTX null_dgst_ctx; + size_t padding_len; + + + uint8_t sig[TLS_MAX_SIGNATURE_SIZE]; + size_t siglen = sizeof(sig); + + uint8_t verify_data[32]; + size_t verify_data_len; + + const uint8_t *client_verify_data; + size_t client_verify_data_len; + + uint8_t client_write_key[16]; + uint8_t server_write_key[16]; + + uint8_t zeros[32] = {0}; + uint8_t psk[32] = {0}; + uint8_t early_secret[32]; + uint8_t handshake_secret[32]; + uint8_t client_handshake_traffic_secret[32]; + uint8_t server_handshake_traffic_secret[32]; + uint8_t client_application_traffic_secret[32]; + uint8_t server_application_traffic_secret[32]; + uint8_t master_secret[32]; + + const uint8_t *request_context; + size_t request_context_len; + const uint8_t *cert_list; + size_t cert_list_len; + const uint8_t *cert; + size_t certlen; + + + int client_verify = 0; + if (conn->ca_certs_len) + client_verify = 1; + + + // 1. Recv ClientHello + tls_trace("recv ClientHello\n"); + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_client_hello(record, + &protocol, &random, + &session_id, &session_id_len, // 不支持SessionID,不做任何处理 + &client_ciphers, &client_ciphers_len, + &client_exts, &client_exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (protocol != TLS_protocol_tls12) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; + } + memcpy(client_random, random, 32); + if (tls_cipher_suites_select(client_ciphers, client_ciphers_len, + server_ciphers, sizeof(server_ciphers)/sizeof(int), + &conn->cipher_suite) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_insufficient_security); + goto end; + } + if (!client_exts) { + error_print(); + goto end; + } + tls13_cipher_suite_get(conn->cipher_suite, &digest, &cipher); // 这个函数是否应该放到tls_里面? + digest_init(&dgst_ctx, digest); + null_dgst_ctx = dgst_ctx; // 在密钥导出函数中可能输入的消息为空,因此需要一个空的dgst_ctx,这里不对了,应该在tls13_derive_secret里面直接支持NULL! + digest_update(&dgst_ctx, record + 5, recordlen - 5); + + + // 2. Send ServerHello + tls_trace("send ServerHello\n"); + rand_bytes(server_random, 32); + sm2_key_generate(&server_ecdhe); + if (tls13_process_client_hello_exts(client_exts, client_exts_len, + &server_ecdhe, &client_ecdhe_public, + server_exts, &server_exts_len, sizeof(server_exts)) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls_record_set_protocol(record, TLS_protocol_tls12); + if (tls_record_set_handshake_server_hello(record, &recordlen, + TLS_protocol_tls12, server_random, + NULL, 0, // openssl的兼容模式在ClientHello中发送SessionID并检查在ServerHello是否返回,用`-no_middlebox`可关闭兼容模式 + conn->cipher_suite, server_exts, server_exts_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_send(record, recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + + + sm2_do_ecdh(&server_ecdhe, &client_ecdhe_public, &client_ecdhe_public); + /* 1 */ tls13_hkdf_extract(digest, zeros, psk, early_secret); + /* 5 */ tls13_derive_secret(early_secret, "derived", &null_dgst_ctx, handshake_secret); + /* 6 */ tls13_hkdf_extract(digest, handshake_secret, (uint8_t *)&client_ecdhe_public, handshake_secret); + /* 7 */ tls13_derive_secret(handshake_secret, "c hs traffic", &dgst_ctx, client_handshake_traffic_secret); + /* 8 */ tls13_derive_secret(handshake_secret, "s hs traffic", &dgst_ctx, server_handshake_traffic_secret); + /* 9 */ tls13_derive_secret(handshake_secret, "derived", &null_dgst_ctx, master_secret); + /* 10 */ tls13_hkdf_extract(digest, master_secret, zeros, master_secret); + // generate server_write_key, server_write_iv, reset server_seq_num + tls13_hkdf_expand_label(digest, server_handshake_traffic_secret, "key", NULL, 0, 16, server_write_key); + block_cipher_set_encrypt_key(&conn->server_write_key, cipher, server_write_key); + tls13_hkdf_expand_label(digest, server_handshake_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv); + memset(conn->server_seq_num, 0, 8); + // generate client_write_key, client_write_iv, reset client_seq_num + tls13_hkdf_expand_label(digest, client_handshake_traffic_secret, "key", NULL, 0, 16, client_write_key); + block_cipher_set_encrypt_key(&conn->client_write_key, cipher, client_write_key); + tls13_hkdf_expand_label(digest, client_handshake_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv); + memset(conn->client_seq_num, 0, 8); + /* + format_print(stderr, 0, 0, "generate handshake secrets\n"); + format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16); + format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12); + format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16); + format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12); + format_print(stderr, 0, 0, "\n"); + */ + + // 3. Send {EncryptedExtensions} + tls_trace("send {EncryptedExtensions}\n"); + tls_record_set_protocol(record, TLS_protocol_tls12); + tls13_record_set_handshake_encrypted_extensions(record, &recordlen); + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + // FIXME: tls13_record_encrypt需要支持握手消息 + // tls_record_data(enced_record)[0] = TLS_handshake_encrypted_extensions; + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + + // send {CertificateRequest*} + if (client_verify) { + tls_trace("send {CertificateRequest*}\n"); + + // TODO: 设置certificate_request中的extensions! + if (tls13_record_set_handshake_certificate_request_default(record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + } + + // send Server {Certificate} + tls_trace("send {Certificate}\n"); + if (tls13_record_set_handshake_certificate(record, &recordlen, NULL, 0, conn->server_certs, conn->server_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + + // send Server {CertificateVerify} + tls_trace("send {CertificateVerify}\n"); + tls13_sign_certificate_verify(TLS_server_mode, &conn->sign_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH, &dgst_ctx, sig, &siglen); + if (tls13_record_set_handshake_certificate_verify(record, &recordlen, + TLS_sig_sm2sig_sm3, sig, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + + // Send Server {Finished} + tls_trace("send {Finished}\n"); + + // compute server verify_data before digest_update() + tls13_compute_verify_data(server_handshake_traffic_secret, + &dgst_ctx, verify_data, &verify_data_len); + if (tls13_record_set_handshake_finished(record, &recordlen, verify_data, verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + tls13_padding_len_rand(&padding_len); + if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv, + conn->server_seq_num, record, recordlen, padding_len, + enced_record, &enced_recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_record_send(enced_record, enced_recordlen, conn->sock) != 1) { + error_print(); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->server_seq_num); + + // generate server_application_traffic_secret + /* 12 */ tls13_derive_secret(master_secret, "s ap traffic", &dgst_ctx, server_application_traffic_secret); + // Generate client_application_traffic_secret + /* 11 */ tls13_derive_secret(master_secret, "c ap traffic", &dgst_ctx, client_application_traffic_secret); + // 因为后面还要解密握手消息,因此client application key, iv 等到握手结束之后再更新 + + // Recv Client {Certificate*} + if (client_verify) { + tls_trace("recv {Certificate*}\n"); + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_record_decrypt(&conn->client_write_key, conn->client_write_iv, + conn->client_seq_num, enced_record, enced_recordlen, + record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + + if (tls13_record_get_handshake_certificate(record, + &request_context, &request_context_len, + &cert_list, &cert_list_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_process_certificate_list(cert_list, cert_list_len, conn->client_certs, &conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len, 0, &cert, &certlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (x509_cert_get_subject_public_key(cert, certlen, &client_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->client_seq_num); + + // verify client Certificate + int verify_result; + if (x509_certs_verify(conn->client_certs, conn->client_certs_len, X509_cert_chain_client, + conn->ca_certs, conn->ca_certs_len, X509_MAX_VERIFY_DEPTH, &verify_result) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + } + + // Recv client {CertificateVerify*} + if (client_verify) { + int client_sign_algor; + const uint8_t *client_sig; + size_t client_siglen; + + tls_trace("recv Client {CertificateVerify*}\n"); + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_record_decrypt(&conn->client_write_key, conn->client_write_iv, + conn->client_seq_num, enced_record, enced_recordlen, record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + + if (tls13_record_get_handshake_certificate_verify(record, &client_sign_algor, &client_sig, &client_siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_verify_certificate_verify(TLS_client_mode, &client_sign_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH, &dgst_ctx, client_sig, client_siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->client_seq_num); + } + + // 12. Recv Client {Finished} + + tls_trace("recv {Finished}\n"); + if (tls_record_recv(enced_record, &enced_recordlen, conn->sock) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_record_decrypt(&conn->client_write_key, conn->client_write_iv, + conn->client_seq_num, enced_record, enced_recordlen, + record, &recordlen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tls13_record_trace(stderr, record, recordlen, 0, 0); + if (tls13_record_get_handshake_finished(record, &client_verify_data, &client_verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (tls13_compute_verify_data(client_handshake_traffic_secret, &dgst_ctx, verify_data, &verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (client_verify_data_len != verify_data_len + || memcmp(client_verify_data, verify_data, verify_data_len) != 0) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + digest_update(&dgst_ctx, record + 5, recordlen - 5); + tls_seq_num_incr(conn->client_seq_num); + + + // 注意:OpenSSL兼容模式在此处会收发ChangeCipherSpec报文 + + + // update server_write_key, server_write_iv, reset server_seq_num + tls13_hkdf_expand_label(digest, server_application_traffic_secret, "key", NULL, 0, 16, server_write_key); + tls13_hkdf_expand_label(digest, server_application_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv); + block_cipher_set_encrypt_key(&conn->server_write_key, cipher, server_write_key); + memset(conn->server_seq_num, 0, 8); + /* + format_print(stderr, 0, 0, "update server secrets\n"); + format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16); + format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12); + format_print(stderr, 0, 0, "\n"); + */ + + // update client_write_key, client_write_iv + // reset client_seq_num + tls13_hkdf_expand_label(digest, client_application_traffic_secret, "key", NULL, 0, 16, client_write_key); + tls13_hkdf_expand_label(digest, client_application_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv); + block_cipher_set_encrypt_key(&conn->client_write_key, cipher, client_write_key); + memset(conn->client_seq_num, 0, 8); + /* + format_print(stderr, 0, 0, "update client secrets\n"); + format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16); + format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12); + format_print(stderr, 0, 0, "\n"); + */ + + fprintf(stderr, "Connection Established!\n\n"); + ret = 1; +end: + gmssl_secure_clear(&server_ecdhe, sizeof(server_ecdhe)); + gmssl_secure_clear(&client_sign_key, sizeof(client_sign_key)); + gmssl_secure_clear(psk, sizeof(psk)); + gmssl_secure_clear(early_secret, sizeof(early_secret)); + gmssl_secure_clear(handshake_secret, sizeof(handshake_secret)); + gmssl_secure_clear(master_secret, sizeof(master_secret)); + gmssl_secure_clear(client_handshake_traffic_secret, sizeof(client_handshake_traffic_secret)); + gmssl_secure_clear(server_handshake_traffic_secret, sizeof(server_handshake_traffic_secret)); + gmssl_secure_clear(client_application_traffic_secret, sizeof(client_application_traffic_secret)); + gmssl_secure_clear(server_application_traffic_secret, sizeof(server_application_traffic_secret)); + gmssl_secure_clear(client_write_key, sizeof(client_write_key)); + gmssl_secure_clear(server_write_key, sizeof(server_write_key)); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/tls_ext.c b/Core/GmSSL-3.1.1/src/tls_ext.c new file mode 100644 index 0000000..cfb08c1 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/tls_ext.c @@ -0,0 +1,966 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* +ec_point_formats + + struct { + ECPointFormat ec_point_format_list<1..2^8-1> + } ECPointFormatList; +*/ +int tls_ec_point_formats_ext_to_bytes(const int *formats, size_t formats_cnt, + uint8_t **out, size_t *outlen) +{ + uint16_t ext_type = TLS_extension_ec_point_formats; + size_t ext_datalen; + size_t ec_point_format_list_len; + size_t i; + + if (!formats || !formats_cnt || !outlen) { + error_print(); + return -1; + } + ec_point_format_list_len = tls_uint8_size() * formats_cnt; + if (ec_point_format_list_len < 1 || ec_point_format_list_len > 255) { + error_print(); + return -1; + } + ext_datalen = tls_uint8_size() + ec_point_format_list_len; + + tls_uint16_to_bytes(ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); + tls_uint8_to_bytes((uint8_t)ec_point_format_list_len, out, outlen); + for (i = 0; i < formats_cnt; i++) { + if (!tls_ec_point_format_name(formats[i])) { + error_print(); + return -1; + } + tls_uint8_to_bytes((uint8_t)formats[i], out, outlen); + } + return 1; +} + +int tls_process_client_ec_point_formats(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen) +{ + int shared_formats[] = { TLS_point_uncompressed }; + size_t shared_formats_cnt = 0; + const uint8_t *p; + size_t len; + + if (tls_uint8array_from_bytes(&p, &len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + while (len) { + uint8_t format; + if (tls_uint8_from_bytes(&format, &p, &len) != 1) { + error_print(); + return -1; + } + if (!tls_ec_point_format_name(format)) { + error_print(); + return -1; + } + if (format == shared_formats[0]) { + shared_formats_cnt = 1; + } + } + if (!shared_formats_cnt) { + error_print(); + return -1; + } + if (tls_ec_point_formats_ext_to_bytes(shared_formats, shared_formats_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_process_server_ec_point_formats(const uint8_t *ext_data, size_t ext_datalen) +{ + const uint8_t *p; + size_t len; + uint8_t format; + + if (tls_uint8array_from_bytes(&p, &len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + if (tls_uint8_from_bytes(&format, &p, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (format != TLS_point_uncompressed) { + error_print(); + return -1; + } + return 1; +} + +#define TLS_MAX_SUPPORTED_GROUPS_COUNT 64 + + +/* +supported_groups + + struct { + NamedGroup named_group_list<2..2^16-1>; + } NamedGroupList; +*/ +int tls_supported_groups_ext_to_bytes(const int *groups, size_t groups_cnt, + uint8_t **out, size_t *outlen) +{ + uint16_t ext_type = TLS_extension_supported_groups; + size_t ext_datalen; + size_t named_group_list_len; + size_t i; + + if (!groups || !groups_cnt) { + error_print(); + return -1; + } + if (!outlen) { + error_print(); + return -1; + } + + if (groups_cnt > ((1<<16) - 1)/2) { + error_print(); + return -1; + } + named_group_list_len = tls_uint16_size() * groups_cnt; + ext_datalen = tls_uint16_size() + named_group_list_len; + + tls_uint16_to_bytes(ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); + tls_uint16_to_bytes((uint16_t)named_group_list_len, out, outlen); + for (i = 0; i < groups_cnt; i++) { + if (!tls_named_curve_name(groups[i])) { + error_print(); + return -1; + } + tls_uint16_to_bytes((uint16_t)groups[i], out, outlen); + } + return 1; +} + +int tls_process_client_supported_groups(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen) +{ + int shared_groups[] = { TLS_curve_sm2p256v1 }; + size_t shared_groups_cnt = 0; + const uint8_t *p; + size_t len; + + if (tls_uint16array_from_bytes(&p, &len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + while (len) { + uint16_t group; + if (tls_uint16_from_bytes(&group, &p, &len) != 1) { + error_print(); + return -1; + } + if (!tls_named_curve_name(group)) { + error_print(); + return -1; + } + if (group == shared_groups[0]) { + shared_groups_cnt = 1; + } + } + if (!shared_groups_cnt) { + error_print(); + return -1; + } + if (tls_supported_groups_ext_to_bytes(shared_groups, shared_groups_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_process_server_supported_groups(const uint8_t *ext_data, size_t ext_datalen) +{ + const uint8_t *p; + size_t len; + uint16_t group; + + if (tls_uint16array_from_bytes(&p, &len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + if (tls_uint16_from_bytes(&group, &p, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (group != TLS_curve_sm2p256v1) { + error_print(); + return -1; + } + return 1; +} + + + +#define TLS_MAX_SIGNATURE_ALGORS_COUNT 64 + +/* +signature_algorithms +signature_algorithms_cert + + struct { + SignatureScheme supported_signature_algorithms<2..2^16-2>; + } SignatureSchemeList; +*/ +int tls_signature_algorithms_ext_to_bytes_ex(int ext_type, const int *algs, size_t algs_cnt, + uint8_t **out, size_t *outlen) +{ + size_t ext_datalen; + size_t supported_signature_algorithms_len; + size_t i; + + if (!algs || !algs_cnt || !outlen) { + error_print(); + return -1; + } + if (algs_cnt > ((1<<16) - 2)/2) { + error_print(); + return -1; + } + supported_signature_algorithms_len = tls_uint16_size() * algs_cnt; + ext_datalen = tls_uint16_size() + supported_signature_algorithms_len; + + tls_uint16_to_bytes((uint16_t)ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); + tls_uint16_to_bytes((uint16_t)supported_signature_algorithms_len, out, outlen); + for (i = 0; i < algs_cnt; i++) { + if (!tls_signature_scheme_name(algs[i])) { + error_print(); + return -1; + } + tls_uint16_to_bytes((uint16_t)algs[i], out, outlen); + } + return 1; +} + +int tls_signature_algorithms_ext_to_bytes(const int *algs, size_t algs_cnt, + uint8_t **out, size_t *outlen) +{ + int ext_type = TLS_extension_signature_algorithms; + if (tls_signature_algorithms_ext_to_bytes_ex(ext_type, algs, algs_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls13_signature_algorithms_cert_ext_to_bytes(const int *algs, size_t algs_cnt, + uint8_t **out, size_t *outlen) +{ + int ext_type = TLS_extension_signature_algorithms_cert; + if (tls_signature_algorithms_ext_to_bytes_ex(ext_type, algs, algs_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_process_client_signature_algorithms(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen) +{ + int shared_algs[1] = { TLS_sig_sm2sig_sm3 }; + size_t shared_algs_cnt = 0; + const uint8_t *p; + size_t len; + + if (!ext_data || !ext_datalen || !outlen) { + error_print(); + return -1; + } + if (tls_uint16array_from_bytes(&p, &len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + while (len) { + uint16_t alg; + if (tls_uint16_from_bytes(&alg, &p, &len) != 1) { + error_print(); + return -1; + } + /* + // GmSSL不识别所有的算法! + if (!tls_signature_scheme_name(alg)) { + error_print(); + return -1; + } + */ + if (alg == shared_algs[0]) { + shared_algs_cnt = 1; + break; + } + } + if (!shared_algs_cnt) { + error_print(); + return -1; + } + if (tls_signature_algorithms_ext_to_bytes(shared_algs, shared_algs_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls_process_server_signature_algors(const uint8_t *ext_data, size_t ext_datalen) +{ + const uint8_t *p; + size_t len; + uint16_t alg; + + if (tls_uint16array_from_bytes(&p, &len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + if (tls_uint16_from_bytes(&alg, &p, &len) != 1 + || tls_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (alg != TLS_sig_sm2sig_sm3) { + error_print(); + return -1; + } + return 1; +} + +/* +supported_versions + + struct { + select (Handshake.msg_type) { + case client_hello: + ProtocolVersion versions<2..254>; + case server_hello: -- and HelloRetryRequest + ProtocolVersion selected_version; + }; + } SupportedVersions; +*/ + +int tls13_supported_versions_ext_print(FILE *fp, int fmt, int ind, + int handshake_type, const uint8_t *data, size_t datalen) +{ + const uint8_t *versions; + size_t versions_len; + uint16_t version; + + switch (handshake_type) { + case TLS_handshake_client_hello: + format_print(fp, fmt, ind, "versions\n"); + ind += 4; + + if (tls_uint8array_from_bytes(&versions, &versions_len, &data, &datalen) != 1) { + error_print(); + return -1; + } + if (versions_len < 2 || versions_len > 254) { + error_print(); + return -1; + } + while (versions_len) { + if (tls_uint16_from_bytes(&version, &versions, &versions_len) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "%s (0x%04x)\n", tls_protocol_name(version), version); + } + break; + + case TLS_handshake_server_hello: + case TLS_handshake_hello_retry_request: + if (tls_uint16_from_bytes(&version, &data, &datalen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "selected_version: %s (0x%04x)\n", tls_protocol_name(version), version); + break; + + default: + error_print(); + return -1; + } + + if (datalen) { + error_print(); + return -1; + } + return 1; +} + +int tls13_supported_versions_ext_to_bytes(int handshake_type, const int *protos, size_t protos_cnt, + uint8_t **out, size_t *outlen) +{ + uint16_t ext_type = TLS_extension_supported_versions; + size_t ext_datalen; + size_t i; + + if (!protos || !protos_cnt || !outlen) { + error_print(); + return -1; + } + switch (handshake_type) { + case TLS_handshake_client_hello: + { + size_t versions_len; + if (protos_cnt > 254/2) { + error_print(); + return -1; + } + versions_len = tls_uint16_size() * protos_cnt; + ext_datalen = tls_uint8_size() + versions_len; + tls_uint16_to_bytes(ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); + tls_uint8_to_bytes((uint8_t)versions_len, out, outlen); + for (i = 0; i < protos_cnt; i++) { + if (!tls_protocol_name(protos[i])) { + error_print(); + return -1; + } + tls_uint16_to_bytes((uint16_t)protos[i], out, outlen); + } + break; + } + case TLS_handshake_server_hello: + case TLS_handshake_hello_retry_request: + { + uint16_t selected_version; + if (protos_cnt > 1) { + error_print(); + return -1; + } + selected_version = protos[0]; + ext_datalen = tls_uint16_size(); + tls_uint16_to_bytes(ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); + tls_uint16_to_bytes(selected_version, out, outlen); + break; + } + default: + error_print(); + return -1; + } + return 1; +} + +int tls13_process_client_supported_versions(const uint8_t *ext_data, size_t ext_datalen, + uint8_t **out, size_t *outlen) +{ + const uint8_t *versions; + size_t versions_len; + int selected_version = -1; + + if (tls_uint8array_from_bytes(&versions, &versions_len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + if (versions_len < 2 || versions_len > 254) { + error_print(); + return -1; + } + while (versions_len) { + uint16_t proto; + if (tls_uint16_from_bytes(&proto, &versions, &versions_len) != 1) { + error_print(); + return -1; + } + if (!tls_protocol_name(proto)) { + error_print(); + return -1; + } + if (proto == TLS_protocol_tls13) { + selected_version = proto; + } + } + if (selected_version < 0) { + error_print(); + return -1; + } + if (tls13_supported_versions_ext_to_bytes(TLS_handshake_server_hello, &selected_version, 1, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls13_process_server_supported_versions(const uint8_t *ext_data, size_t ext_datalen) +{ + uint16_t selected_version; + + if (tls_uint16_from_bytes(&selected_version, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + if (selected_version != TLS_protocol_tls13) { + error_print(); + return -1; + } + return 1; +} + +/* +key_share + +实际上这个 key_share 也存在相同的问题 + + + struct { + NamedGroup group; + opaque key_exchange<1..2^16-1>; + } KeyShareEntry; + + struct { + KeyShareEntry client_shares<0..2^16-1>; + } KeyShareClientHello; + + struct { + KeyShareEntry server_share; + } KeyShareServerHello; +*/ + +int tls13_key_share_ext_print(FILE *fp, int fmt, int ind, int handshake_type, const uint8_t *data, size_t datalen) +{ + const uint8_t *client_shares; + size_t client_shares_len; + uint16_t group; + const uint8_t *key_exchange; + size_t key_exchange_len; + + switch (handshake_type) { + case TLS_handshake_client_hello: + format_print(fp, fmt, ind, "client_shares\n"); + ind += 4; + if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &data, &datalen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "KeyShareEntry\n"); + ind += 4; + while (client_shares_len) { + if (tls_uint16_from_bytes(&group, &client_shares, &client_shares_len) != 1) goto err; + format_print(fp, fmt, ind, "group: %s (0x%04x)\n", tls_named_curve_name(group), group); + if (tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &client_shares, &client_shares_len) != 1) goto err; + format_bytes(fp, fmt, ind, "key_exchange", key_exchange, key_exchange_len); + } + break; + case TLS_handshake_server_hello: + format_print(fp, fmt, ind, "server_share\n"); + ind += 4; + if (tls_uint16_from_bytes(&group, &data, &datalen) != 1) goto err; + format_print(fp, fmt, ind, "group: %s (0x%04x)\n", tls_named_curve_name(group), group); + if (tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &data, &datalen) != 1) goto err; + format_bytes(fp, fmt, ind, "key_exchange", key_exchange, key_exchange_len); + break; + default: + error_print(); + return -1; + } + if (tls_length_is_zero(datalen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int tls13_key_share_entry_to_bytes(const SM2_POINT *point, uint8_t **out, size_t *outlen) +{ + uint16_t group = TLS_curve_sm2p256v1; + uint8_t key_exchange[65]; + + if (!point || !outlen) { + error_print(); + return -1; + } + sm2_point_to_uncompressed_octets(point, key_exchange); + tls_uint16_to_bytes(group, out, outlen); + tls_uint16array_to_bytes(key_exchange, 65, out, outlen); + return 1; +} + +int tls13_server_key_share_ext_to_bytes(const SM2_POINT *point, uint8_t **out, size_t *outlen) +{ + uint16_t ext_type = TLS_extension_key_share; + size_t ext_datalen = 0; + + if (!point || !outlen) { + error_print(); + return -1; + } + tls13_key_share_entry_to_bytes(point, NULL, &ext_datalen); + tls_uint16_to_bytes(ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); + tls13_key_share_entry_to_bytes(point, out, outlen); + return 1; +} + +int tls13_process_server_key_share(const uint8_t *ext_data, size_t ext_datalen, SM2_POINT *point) +{ + uint16_t group; + const uint8_t *key_exchange; + size_t key_exchange_len; + + if (!point) { + error_print(); + return -1; + } + if (tls_uint16_from_bytes(&group, &ext_data, &ext_datalen) != 1 + || tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + if (group != TLS_curve_sm2p256v1) { + error_print(); + return -1; + } + if (key_exchange_len != 65) { + error_print(); + return -1; + } + if (sm2_point_from_octets(point, key_exchange, key_exchange_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int tls13_client_key_share_ext_to_bytes(const SM2_POINT *point, uint8_t **out, size_t *outlen) +{ + uint16_t ext_type = TLS_extension_key_share; + size_t ext_datalen; + size_t client_shares_len = 0; + + if (!point || !outlen) { + error_print(); + return -1; + } + tls13_key_share_entry_to_bytes(point, NULL, &client_shares_len); + ext_datalen = tls_uint16_size() + client_shares_len; + + tls_uint16_to_bytes(ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); // FIXME: do we need to check length < UINT16_MAX? + tls_uint16_to_bytes((uint16_t)client_shares_len, out, outlen); + tls13_key_share_entry_to_bytes(point, out, outlen); + return 1; +} + +int tls13_process_client_key_share(const uint8_t *ext_data, size_t ext_datalen, + const SM2_KEY *server_ecdhe_key, SM2_POINT *client_ecdhe_public, + uint8_t **out, size_t *outlen) +{ + const uint8_t *client_shares; + size_t client_shares_len; + uint16_t group; + const uint8_t *key_exchange; + size_t key_exchange_len; + + if (!server_ecdhe_key || !client_ecdhe_public || !outlen) { + error_print(); + return -1; + } + if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &ext_data, &ext_datalen) != 1 + || tls_length_is_zero(ext_datalen) != 1) { + error_print(); + return -1; + } + while (client_shares_len) { + if (tls_uint16_from_bytes(&group, &client_shares, &client_shares_len) != 1 + || tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &client_shares, &client_shares_len) != 1) { + error_print(); + return -1; + } + if (!tls_named_curve_name(group)) { + error_print(); + return -1; + } + if (!key_exchange) { + error_print(); + return -1; + } + if (group == TLS_curve_sm2p256v1) { + if (key_exchange_len != 65) { + error_print(); + return -1; + } + if (sm2_point_from_octets(client_ecdhe_public, key_exchange, key_exchange_len) != 1) { + error_print(); + return -1; + } + if (tls13_server_key_share_ext_to_bytes(&server_ecdhe_key->public_key, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; + } + } + error_print(); + return -1; +} + +/* +certificate_authorities + + opaque DistinguishedName<1..2^16-1>; + + struct { + DistinguishedName authorities<3..2^16-1>; + } CertificateAuthoritiesExtension; +*/ + +int tls13_certificate_authorities_ext_to_bytes(const uint8_t *ca_names, size_t ca_names_len, + uint8_t **out, size_t *outlen) +{ + int ext_type = TLS_extension_certificate_authorities; + size_t ext_datalen; + size_t authorities_len; + const uint8_t *name; + size_t namelen; + const uint8_t *p; + size_t len; + + p = ca_names; + len = ca_names_len; + authorities_len = 0; + while (len) { + if (x509_name_from_der(&name, &namelen, &p, &len) != 1) { + error_print(); + return -1; + } + tls_uint16array_to_bytes(name, namelen, NULL, &authorities_len); + } + if (authorities_len < 3 || authorities_len > (1 << 16) - 1) { + error_print(); + return -1; + } + ext_datalen = tls_uint16_size() + authorities_len; + + tls_uint16_to_bytes(ext_type, out, outlen); + tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen); + tls_uint16_to_bytes((uint16_t)authorities_len, out, outlen); + while (ca_names_len) { + x509_name_from_der(&name, &namelen, &ca_names, &ca_names_len); + tls_uint16array_to_bytes(name, namelen, out, outlen); + } + return 1; +} + + +int tls_ext_from_bytes(int *type, const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) +{ + uint16_t ext_type; + if (tls_uint16_from_bytes(&ext_type, in, inlen) != 1 + || tls_uint16array_from_bytes(data, datalen, in, inlen) != 1) { + error_print(); + return -1; + } + *type = ext_type; + if (!tls_extension_name(ext_type)) { + error_print(); + return -1; + } + return 1; +} + +int tls_process_client_hello_exts(const uint8_t *exts, size_t extslen, uint8_t *out, size_t *outlen, size_t maxlen) +{ + int type; + const uint8_t *data; + size_t datalen; + + while (extslen) { + if (tls_ext_from_bytes(&type, &data, &datalen, &exts, &extslen) != 1) { + error_print(); + return -1; + } + + switch (type) { + case TLS_extension_ec_point_formats: + if (tls_process_client_ec_point_formats(data, datalen, &out, outlen) != 1) { + error_print(); + return -1; + } + break; + case TLS_extension_signature_algorithms: + if (tls_process_client_signature_algorithms(data, datalen, &out, outlen) != 1) { + error_print(); + return -1; + } + break; + case TLS_extension_supported_groups: + if (tls_process_client_supported_groups(data, datalen, &out, outlen) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + } + return 1; +} + +int tls_process_server_hello_exts(const uint8_t *exts, size_t extslen, + int *ec_point_format, int *supported_group, int *signature_algor) +{ + int type; + const uint8_t *data; + size_t datalen; + + *ec_point_format = -1; + *supported_group = -1; + *signature_algor = -1; + + while (extslen) { + if (tls_ext_from_bytes(&type, &data, &datalen, &exts, &extslen) != 1) { + error_print(); + return -1; + } + + switch (type) { + case TLS_extension_ec_point_formats: + if (tls_process_server_ec_point_formats(data, datalen) != 1) { + error_print(); + return -1; + } + *ec_point_format = TLS_point_uncompressed; + break; + case TLS_extension_signature_algorithms: + if (tls_process_server_signature_algors(data, datalen) != 1) { + error_print(); + return -1; + } + *supported_group = TLS_curve_sm2p256v1; + break; + case TLS_extension_supported_groups: + if (tls_process_server_supported_groups(data, datalen) != 1) { + error_print(); + return -1; + } + *signature_algor = TLS_sig_sm2sig_sm3; + break; + default: + error_print(); + return -1; + } + } + return 1; +} + + + +static int tls13_server_hello_exts[] = { + TLS_extension_key_share, + TLS_extension_pre_shared_key, + TLS_extension_supported_versions, +}; + +/* +struct { + Extension extensions<0..2^16-1>; +} EncryptedExtensions; +*/ +static int tls13_encrypted_extensions_exts[] = { + TLS_extension_server_name, + TLS_extension_max_fragment_length, + TLS_extension_supported_groups, // 必须放在EE中,不能放在SH中 + TLS_extension_use_srtp, + TLS_extension_heartbeat, + TLS_extension_application_layer_protocol_negotiation, + TLS_extension_client_certificate_type, + TLS_extension_server_certificate_type, + TLS_extension_early_data, +}; + +static int tls13_certificate_exts[] = { + TLS_extension_status_request, + TLS_extension_signed_certificate_timestamp, +}; + +static int tls13_certificate_request_exts[] = { + TLS_extension_status_request, + TLS_extension_signature_algorithms, + TLS_extension_signed_certificate_timestamp, + TLS_extension_certificate_authorities, + TLS_extension_oid_filters, + TLS_extension_signature_algorithms_cert, +}; + +static int tls13_hello_retry_request_exts[] = { + TLS_extension_key_share, + TLS_extension_cookie, + TLS_extension_supported_versions, +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/GmSSL-3.1.1/src/tls_trace.c b/Core/GmSSL-3.1.1/src/tls_trace.c new file mode 100644 index 0000000..c0012cc --- /dev/null +++ b/Core/GmSSL-3.1.1/src/tls_trace.c @@ -0,0 +1,1184 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +//#include +#include +#include +#include +#include + + +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_protocol_name(int protocol) +{ + switch(protocol) { + case TLS_protocol_tlcp: return "TLCP"; + case TLS_protocol_ssl2: return "SSL2.0"; + case TLS_protocol_ssl3: return "SSL3.0"; + case TLS_protocol_tls1: return "TLS1.0"; + case TLS_protocol_tls11: return "TLS1.1"; + case TLS_protocol_tls12: return "TLS1.2"; + case TLS_protocol_tls13: return "TLS1.3"; + case TLS_protocol_dtls1: return "DTLS1.0"; + case TLS_protocol_dtls12: return "DTLS1.2"; + } + return NULL; +} + +const char *tls_cipher_suite_name(int cipher) +{ + switch (cipher) { + case TLS_cipher_null_with_null_null: return "TLS_NULL_WITH_NULL_NULL"; + case TLS_cipher_sm4_gcm_sm3: return "TLS_SM4_GCM_SM3"; + case TLS_cipher_sm4_ccm_sm3: return "TLS_SM4_CCM_SM3"; + case TLS_cipher_ecdhe_sm4_cbc_sm3: return "TLS_ECDHE_SM4_CBC_SM3"; + case TLS_cipher_ecdhe_sm4_gcm_sm3: return "TLS_ECDHE_SM4_GCM_SM3"; + case TLS_cipher_ecc_sm4_cbc_sm3: return "TLS_ECC_SM4_CBC_SM3"; + case TLS_cipher_ecc_sm4_gcm_sm3: return "TLS_ECC_SM4_GCM_SM3"; + case TLS_cipher_ibsdh_sm4_cbc_sm3: return "TLS_IBSDH_SM4_CBC_SM3"; + case TLS_cipher_ibsdh_sm4_gcm_sm3: return "TLS_IBSDH_SM4_GCM_SM3"; + case TLS_cipher_ibc_sm4_cbc_sm3: return "TLS_IBC_SM4_CBC_SM3"; + case TLS_cipher_ibc_sm4_gcm_sm3: return "TLS_IBC_SM4_GCM_SM3"; + case TLS_cipher_rsa_sm4_cbc_sm3: return "TLS_RSA_SM4_CBC_SM3"; + case TLS_cipher_rsa_sm4_gcm_sm3: return "TLS_RSA_SM4_GCM_SM3"; + case TLS_cipher_rsa_sm4_cbc_sha256: return "TLS_RSA_SM4_CBC_SHA256"; + case TLS_cipher_rsa_sm4_gcm_sha256: return "TLS_RSA_SM4_GCM_SHA256"; + case TLS_cipher_aes_128_gcm_sha256: return "TLS_AES_128_GCM_SHA256"; + case TLS_cipher_aes_256_gcm_sha384: return "TLS_AES_256_GCM_SHA384"; + case TLS_cipher_chacha20_poly1305_sha256: return "TLS_CHACHA20_POLY1305_SHA256"; + case TLS_cipher_aes_128_ccm_sha256: return "TLS_AES_128_CCM_SHA256"; + case TLS_cipher_aes_128_ccm_8_sha256: return "TLS_AES_128_CCM_8_SHA256"; + 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_hello_verify_request: return "HelloVerifyRequest"; + case TLS_handshake_new_session_ticket: return "NewSessionTicket"; + case TLS_handshake_end_of_early_data: return "EndOfEarlyData"; + case TLS_handshake_hello_retry_request: return "HelloRetryRequest"; + case TLS_handshake_encrypted_extensions: return "EncryptedExtensions"; + 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 "CertificateVerify"; + case TLS_handshake_client_key_exchange: return "ClientKeyExchange"; + case TLS_handshake_finished: return "Finished"; + case TLS_handshake_certificate_url: return "CertificateUrl"; + case TLS_handshake_certificate_status: return "CertificateStatus"; + case TLS_handshake_supplemental_data: return "SupplementalData"; + case TLS_handshake_key_update: return "KeyUpdate"; + case TLS_handshake_compressed_certificate: return "CompressedCertificate"; + case TLS_handshake_ekt_key: return "EktKey"; + case TLS_handshake_message_hash: return "MessageHash"; + } + 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_msg("unknown alert level %d\n", 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_extension: return "unsupported_extension"; + 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_msg("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; +} + + +// FIXME: 是否应该将函数名改为 tls_curve_name() 这样和 TLS_curve_xxx 保持一致 +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) +{ + 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 protocol = ((int)pre_master_secret[0] << 8) | pre_master_secret[1]; + format_print(fp, format, indent, "PreMasterSecret\n"); + indent += 4; + format_print(fp, format, indent, "protocol : %s\n", tls_protocol_name(protocol)); + format_bytes(fp, format, indent, "pre_master_secret", pre_master_secret, 48); + return 1; +} + +// supported_versions 的格式还受到 handshake_type 影响 +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_versions: + if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1 + || tls_length_is_zero(datalen) != 1 + || len % 2) { + error_print(); + return -1; + } + while (len) { + uint16_t proto; + tls_uint16_from_bytes(&proto, &p, &len); + format_print(fp, format, indent, "%s (0x%04x)\n", + tls_protocol_name(proto), proto); + } + break; + 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 (%d)\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; + case TLS_extension_key_share: + if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1 + || datalen) { + error_print(); + return -1; + } + while (len) { + uint16_t group; + const uint8_t *key_exch; + size_t key_exch_len; + + if (tls_uint16_from_bytes(&group, &p, &len) != 1 + || tls_uint16array_from_bytes(&key_exch, &key_exch_len, &p, &len) != 1) { + error_print(); + return -1; + } + format_print(fp, format, indent, "group: %s (%d)\n", tls_named_curve_name(group), group); + format_bytes(fp, format, indent, "key_exchange", key_exch, key_exch_len); + } + break; + + default: + format_bytes(fp, format, indent, "raw_data", data, datalen); + } + return 1; +} + +int tls13_extension_print(FILE *fp, int fmt, int ind, + int handshake_type, int ext_type, const uint8_t *ext_data, size_t ext_datalen) +{ + switch (ext_type) { + case TLS_extension_supported_groups: + case TLS_extension_ec_point_formats: + case TLS_extension_signature_algorithms: + return tls_extension_print(fp, ext_type, ext_data, ext_datalen, fmt, ind); + } + + format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type); + ind += 4; + + switch (ext_type) { + case TLS_extension_supported_versions: + tls13_supported_versions_ext_print(fp, fmt, ind, handshake_type, ext_data, ext_datalen); + break; + case TLS_extension_key_share: + tls13_key_share_ext_print(fp, fmt, ind, handshake_type, ext_data, ext_datalen); + break; + default: + format_bytes(fp, fmt, ind, "raw_data", ext_data, ext_datalen); + } + return 1; +} + +int tls13_extensions_print(FILE *fp, int fmt, int ind, + int handshake_type, const uint8_t *exts, size_t extslen) +{ + uint16_t ext_type; + const uint8_t *ext_data; + size_t ext_datalen; + + if (!exts) { + format_print(fp, fmt, ind, "Extensions: (null)\n"); + return 1; + } + + format_print(fp, fmt, ind, "Extensions\n"); + ind += 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 (tls13_extension_print(fp, fmt, ind, handshake_type, ext_type, ext_data, ext_datalen) != 1) { + error_print(); + return -1; + } + } + 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_hello_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) +{ + format_print(fp, format, indent, "HelloRequest\n"); + indent += 4; + if (data || datalen > 0) { + 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 protocol; + 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(&protocol, &data, &datalen) != 1) goto end; + format_print(fp, format, indent, "Version: %s (%d.%d)\n", + tls_protocol_name(protocol), protocol >> 8, protocol & 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); + tls13_extensions_print(fp, format, indent, TLS_handshake_client_hello, exts, exts_len); + } + 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 protocol; + 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, exts_len; + + format_print(fp, format, indent, "ServerHello\n"); indent += 4; + if (tls_uint16_from_bytes(&protocol, &data, &datalen) != 1) goto bad; + format_print(fp, format, indent, "Version: %s (%d.%d)\n", + tls_protocol_name(protocol), protocol >> 8, protocol & 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 + //tls_extensions_print(fp, exts, exts_len, format, indent); + tls13_extensions_print(fp, format, indent, TLS_handshake_server_hello, exts, exts_len); + } + return 1; +bad: + error_print(); + return -1; +} + +int tls_certificate_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) +{ + const uint8_t *certs; + size_t certslen; + const uint8_t *der; + size_t derlen; + + if (tls_uint24array_from_bytes(&certs, &certslen, &data, &datalen) != 1) { + error_print(); + return -1; + } + while (certslen > 0) { + if (tls_uint24array_from_bytes(&der, &derlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + (void)x509_cert_print(fp, format, indent, "Certificate", der, derlen); + (void)x509_cert_to_pem(der, derlen, fp); + } + + if (datalen) { + error_print(); + return -1; + } + 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 (%d)\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 (0x%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 TLS_cipher_ecc_sm4_cbc_sm3: + case TLS_cipher_ecc_sm4_gcm_sm3: + if (tlcp_server_key_exchange_pke_print(fp, data, datalen, format, indent) != 1) { + error_print(); + return -1; + } + break; + case TLS_cipher_ecdhe_sm4_cbc_sm3: + case TLS_cipher_ecdhe_sm4_gcm_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_subjects_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *a; + size_t alen; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + const uint8_t *name; + size_t namelen; + + if (tls_uint16array_from_bytes(&a, &alen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (asn1_sequence_from_der(&name, &namelen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + x509_name_print(fp, fmt, ind, "DistinguishedName", name, namelen); + } + 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; + + 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--) { + int cert_type = *cert_types++; + format_print(fp, format, indent + 4, "%s (%d)\n", tls_cert_type_name(cert_type), cert_type); + } + if (tls_uint16array_from_bytes(&ca_names, &ca_names_len, &data, &datalen) != 1) goto bad; + tls_certificate_subjects_print(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 TLS_cipher_ecc_sm4_cbc_sm3: + case TLS_cipher_ecc_sm4_gcm_sm3: + if (tls_client_key_exchange_pke_print(fp, data, datalen, format, indent) != 1) { + error_print(); + return -1; + } + break; + case TLS_cipher_ecdhe_sm4_cbc_sm3: + case TLS_cipher_ecdhe_sm4_gcm_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 tls13_handshake_print(FILE *fp, int fmt, int ind, const uint8_t *handshake, size_t handshake_len) +{ + const uint8_t *p = handshake; + size_t len = handshake_len; + uint8_t type; + const uint8_t *data; + size_t datalen; + + if (tls_uint8_from_bytes(&type, &handshake, &handshake_len) != 1 + || tls_uint24array_from_bytes(&data, &datalen, &handshake, &handshake_len) != 1 + || tls_length_is_zero(handshake_len) != 1) { + error_print(); + return -1; + } + + switch (type) { + case TLS_handshake_certificate: + case TLS_handshake_certificate_request: + case TLS_handshake_certificate_verify: + format_print(fp, fmt, ind, "Handshake\n"); + ind += 4; + format_print(fp, fmt, ind, "Type: %s (%d)\n", tls_handshake_type_name(type), type); + format_print(fp, fmt, ind, "Length: %zu\n", datalen); + break; + } + switch (type) { + case TLS_handshake_certificate: + return tls13_certificate_print(fp, fmt, ind, data, datalen); + case TLS_handshake_certificate_request: + return tls13_certificate_request_print(fp, fmt, ind, data, datalen); + case TLS_handshake_certificate_verify: + return tls13_certificate_verify_print(fp, fmt, ind, data, datalen); + } + + return tls_handshake_print(fp, p, len, fmt, ind); +} + +// 这个是有问题的,因为TLS 1.3的证书和TLS 1.2是不一样的 +int tls_handshake_print(FILE *fp, const uint8_t *handshake, size_t handshakelen, int format, int indent) +{ + const uint8_t *cp = handshake; + uint8_t type; + const uint8_t *data; + uint24_t datalen; + + format_print(fp, format, indent, "Handshake\n"); + indent += 4; + + if (tls_uint8_from_bytes(&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(&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_hello_request: + if (tls_hello_request_print(fp, data, datalen, format, indent) != 1) + { error_print(); return -1; } break; + 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_encrypted_extensions: + tls13_encrypted_extensions_print(fp, format, indent, data, datalen); + 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 tls13_record_print(FILE *fp, int format, int indent, const uint8_t *record, size_t recordlen) +{ + const uint8_t *data; + size_t datalen; + int protocol; + + format |= TLS_cipher_sm4_gcm_sm3 << 8; + + if (!fp || !record || recordlen < 5) { + error_print(); + return -1; + } + protocol = tls_record_protocol(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_protocol_name(protocol), protocol >> 8, protocol & 0xff); + format_print(fp, format, indent, "Length: %d\n", tls_record_data_length(record)); + + data = tls_record_data(record); + datalen = tls_record_data_length(record); + + if (recordlen < tls_record_length(record)) { + error_print(); + return -1; + } + + // 最高字节设置后强制打印记录原始数据 + if (format >> 24) { + format_bytes(fp, format, indent, "Data", data, datalen); + fprintf(fp, "\n"); + return 1; + } + + switch (record[0]) { + case TLS_record_handshake: + tls13_handshake_print(fp, format, indent, data, datalen); + 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; + } + + recordlen -= tls_record_length(record); + if (recordlen) { + format_print(fp, 0, 0, "DataLeftInRecord: %zu\n", recordlen); + } + + fprintf(fp, "\n"); + return 1; + +} + + +// 仅从record数据是不能判断这个record是TLS 1.2还是TLS 1.3 +// 不同协议上,同名的握手消息,其格式也是不一样的。这真是太恶心了!!!! + +// 当消息为ClientKeyExchange,ServerKeyExchange,需要密码套件中的密钥交换算法信息 +// 当消息为加密的Finished,记录类型为Handshake,但是记录负载数据中没有Handshake头 +// 注意:这里的recordlen 是冗余的,要容忍recordlen的错误 +// +// supported_versions 的格式由handshake_type 是否为ClientHello, ServerHello 决定 +// record中是包含这个信息的,但是在exts中没有这个信息 +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 protocol; + + if (!fp || !record || recordlen < 5) { + error_print(); + return -1; + } + protocol = tls_record_protocol(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_protocol_name(protocol), protocol >> 8, protocol & 0xff); + format_print(fp, format, indent, "Length: %d\n", tls_record_data_length(record)); + + data = tls_record_data(record); + datalen = tls_record_data_length(record); + + if (recordlen < tls_record_length(record)) { + error_print(); + return -1; + } + + // 最高字节设置后强制打印记录原始数据 + if (format >> 24) { + format_bytes(fp, format, indent, "Data", data, datalen); + fprintf(fp, "\n"); + return 1; + } + + 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; + } + + recordlen -= tls_record_length(record); + if (recordlen) { + format_print(fp, 0, 0, "DataLeftInRecord: %zu\n", recordlen); + } + + 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) +{ + // 应该检查一下key_block_len的值,判断是否支持,或者算法选择, 或者要求输入一个cipher_suite参数 + 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; +} diff --git a/Core/GmSSL-3.1.1/src/version.c b/Core/GmSSL-3.1.1/src/version.c new file mode 100644 index 0000000..ad92691 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/version.c @@ -0,0 +1,22 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include + +int gmssl_version_num(void) +{ + return GMSSL_VERSION_NUM; +} + +const char *gmssl_version_str(void) +{ + return GMSSL_VERSION_STR; +} diff --git a/Core/GmSSL-3.1.1/src/x509_alg.c b/Core/GmSSL-3.1.1/src/x509_alg.c new file mode 100644 index 0000000..67223d6 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/x509_alg.c @@ -0,0 +1,695 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static uint32_t oid_sm3[] = { 1,2,156,10197,1,401 }; +static uint32_t oid_md5[] = { 1,2,840,113549,2,5 }; +static uint32_t oid_sha1[] = { 1,3,14,3,2,26 }; +static uint32_t oid_sha256[] = { 2,16,840,1,101,3,4,2,1 }; +static uint32_t oid_sha384[] = { 2,16,840,1,101,3,4,2,2 }; +static uint32_t oid_sha512[] = { 2,16,840,1,101,3,4,2,3 }; +static uint32_t oid_sha224[] = { 2,16,840,1,101,3,4,2,4 }; + +static const ASN1_OID_INFO x509_digest_algors[] = { + { OID_sm3, "sm3", oid_sm3, sizeof(oid_sm3)/sizeof(int) }, + { OID_md5, "md5", oid_md5, sizeof(oid_md5)/sizeof(int) }, + { OID_sha1, "sha1", oid_sha1, sizeof(oid_sha1)/sizeof(int) }, + { OID_sha224, "sha224", oid_sha224, sizeof(oid_sha224)/sizeof(int) }, + { OID_sha256, "sha256", oid_sha256, sizeof(oid_sha256)/sizeof(int) }, + { OID_sha384, "sha384", oid_sha384, sizeof(oid_sha384)/sizeof(int) }, + { OID_sha512, "sha512", oid_sha512, sizeof(oid_sha512)/sizeof(int) }, +}; + +static const int x509_digest_algors_count = + sizeof(x509_digest_algors)/sizeof(x509_digest_algors[0]); + +const char *x509_digest_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_digest_algors, x509_digest_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_digest_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_digest_algors, x509_digest_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +/* +from RFC 5754 Using SHA2 Algorithms with Cryptographic Message Syntax + + 2. Message Digest Algorithms + + The AlgorithmIdentifier parameters field is OPTIONAL. + Implementations MUST accept SHA2 AlgorithmIdentifiers with absent + parameters. Implementations MUST accept SHA2 AlgorithmIdentifiers + with NULL parameters. Implementations MUST generate SHA2 + AlgorithmIdentifiers with absent parameters. + +from RFC 5758 Internet X.509 Public Key Infrastructure: + Additional Algorithms and Identifiers for DSA and ECDSA + + 2. Hash Functions + + id-sha224 + id-sha256 + id-sha384 + id-sha512 + + When one of these OIDs appears in an AlgorithmIdentifier, all + implementations MUST accept both NULL and absent parameters as legal + and equivalent encodings. + +*/ +int x509_digest_algor_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_digest_algors, x509_digest_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_digest_algor_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = 0; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if ((ret = asn1_oid_info_from_der(&info, x509_digest_algors, x509_digest_algors_count, &p, &len)) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return ret; + } + *oid = info->oid; + return 1; +} + +int x509_digest_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_digest_algors, x509_digest_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static uint32_t oid_sm4_cbc[] = { 1,2,156,10197,1,104,2 }; +static uint32_t oid_aes128_cbc[] = { 2,16,840,1,101,3,4,1,2 }; +static uint32_t oid_aes192_cbc[] = { 2,16,840,1,101,3,4,1,22 }; +static uint32_t oid_aes256_cbc[] = { 2,16,840,1,101,3,4,1,42 }; + +static const ASN1_OID_INFO x509_enc_algors[] = { + { OID_sm4_cbc, "sm4-cbc", oid_sm4_cbc, sizeof(oid_sm4_cbc)/sizeof(int) }, + { OID_aes128_cbc, "aes128-cbc", oid_aes128_cbc, sizeof(oid_aes128_cbc)/sizeof(int) }, + { OID_aes192_cbc, "aes192-cbc", oid_aes192_cbc, sizeof(oid_aes192_cbc)/sizeof(int) }, + { OID_aes256_cbc, "aes256-cbc", oid_aes256_cbc, sizeof(oid_aes256_cbc)/sizeof(int) }, +}; + +static const int x509_enc_algors_count = + sizeof(x509_enc_algors)/sizeof(x509_enc_algors[0]); + +const char *x509_encryption_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_enc_algors, x509_enc_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_encryption_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_enc_algors, x509_enc_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_encryption_algor_to_der(int oid, const uint8_t *iv, size_t ivlen, + uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + + if (!(info = asn1_oid_info_from_oid(x509_enc_algors, x509_enc_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, 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(info->nodes, info->nodes_cnt, 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 *oid, const uint8_t **iv, size_t *ivlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = OID_undef; + *iv = NULL; + *ivlen = 0; + + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_oid_info_from_der(&info, x509_enc_algors, x509_enc_algors_count, &p, &len) != 1 + || asn1_octet_string_from_der(iv, ivlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (!(*iv) || *ivlen != 16) { + error_print(); + return -1; + } + *oid = info->oid; + return 1; +} + +int x509_encryption_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + const uint8_t *iv; + size_t ivlen; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_enc_algors, x509_enc_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if (asn1_octet_string_from_der(&iv, &ivlen, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "iv: ", iv, ivlen); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static uint32_t oid_sm2sign_with_sm3[] = { 1,2,156,10197,1,501 }; +static uint32_t oid_rsasign_with_sm3[] = { 1,2,156,10197,1,504 }; +static uint32_t oid_ecdsa_with_sha1[] = { 1,2,840,10045,4,1 }; +static uint32_t oid_ecdsa_with_sha224[] = { 1,2,840,10045,4,3,1 }; +static uint32_t oid_ecdsa_with_sha256[] = { 1,2,840,10045,4,3,2 }; +static uint32_t oid_ecdsa_with_sha384[] = { 1,2,840,10045,4,3,3 }; +static uint32_t oid_ecdsa_with_sha512[] = { 1,2,840,10045,4,3,4 }; +static uint32_t oid_rsasign_with_md5[] = { 1,2,840,113549,1,1,4 }; +static uint32_t oid_rsasign_with_sha1[] = { 1,2,840,113549,1,1,5 }; +static uint32_t oid_rsasign_with_sha224[] = { 1,2,840,113549,1,1,14 }; +static uint32_t oid_rsasign_with_sha256[] = { 1,2,840,113549,1,1,11 }; +static uint32_t oid_rsasign_with_sha384[] = { 1,2,840,113549,1,1,12 }; +static uint32_t oid_rsasign_with_sha512[] = { 1,2,840,113549,1,1,13 }; + + +/* +from RFC 3447 Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography + Specifications Version 2.1 + + Appendix C. ASN.1 module + + -- When rsaEncryption is used in an AlgorithmIdentifier the + -- parameters MUST be present and MUST be NULL. + + -- When the following OIDs are used in an AlgorithmIdentifier the + -- parameters MUST be present and MUST be NULL. + -- + md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } + md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } + sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } + sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } + sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } + sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } + +from RFC 3279 Algorithms and Identifiers for the + Internet X.509 Public Key Infrastructure + Certificate and Certificate Revocation List (CRL) Profile + + 2.2.3 ECDSA Signature Algorithm + + When the ecdsa-with-SHA1 algorithm identifier appears as the + algorithm field in an AlgorithmIdentifier, the encoding MUST omit the + parameters field. That is, the AlgorithmIdentifier SHALL be a + SEQUENCE of one component: the OBJECT IDENTIFIER ecdsa-with-SHA1. + + +from RFC 5754 Using SHA2 Algorithms with Cryptographic Message Syntax + + 3.3. ECDSA + + When any of these four object identifiers appears within an + ^ ecdsa-with-SHA224/SHA256/SHA384/SHA512 + AlgorithmIdentifier, the parameters field MUST be absent. That is, + the AlgorithmIdentifier SHALL be a SEQUENCE of one component: the OID + ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or ecdsa- + with-SHA512. + + +from RFC 5758 Internet X.509 Public Key Infrastructure: + Additional Algorithms and Identifiers for DSA and ECDSA + + 3.1. DSA Signature Algorithm + + When the id-dsa-with-sha224 or id-dsa-with-sha256 algorithm + identifier appears in the algorithm field as an AlgorithmIdentifier, + the encoding SHALL omit the parameters field. That is, the + AlgorithmIdentifier SHALL be a SEQUENCE of one component, the OID id- + dsa-with-sha224 or id-dsa-with-sha256. + + 3.2. ECDSA Signature Algorithm + + When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or + ecdsa-with-SHA512 algorithm identifier appears in the algorithm field + as an AlgorithmIdentifier, the encoding MUST omit the parameters + field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one + component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- + SHA384, or ecdsa-with-SHA512. + +*/ + +#ifdef SM2_ALGOR_ID_ENCODE_NULL // from CMakeLists.txt +#define SM2_SIGN_ALGOR_FLAGS 1 +#else +#define SM2_SIGN_ALGOR_FLAGS 0 +#endif + +static const ASN1_OID_INFO x509_sign_algors[] = { + { OID_sm2sign_with_sm3, "sm2sign-with-sm3", oid_sm2sign_with_sm3, sizeof(oid_sm2sign_with_sm3)/sizeof(int), SM2_SIGN_ALGOR_FLAGS }, + { OID_rsasign_with_sm3, "rsasign-with-sm3", oid_rsasign_with_sm3, sizeof(oid_rsasign_with_sm3)/sizeof(int), 1 }, + { OID_ecdsa_with_sha1, "ecdsa-with-sha1", oid_ecdsa_with_sha1, sizeof(oid_ecdsa_with_sha1)/sizeof(int), 0 }, + { OID_ecdsa_with_sha224, "ecdsa-with-sha224", oid_ecdsa_with_sha224, sizeof(oid_ecdsa_with_sha224)/sizeof(int), 0 } , + { OID_ecdsa_with_sha256, "ecdsa-with-sha256", oid_ecdsa_with_sha256, sizeof(oid_ecdsa_with_sha256)/sizeof(int), 0 }, + { OID_ecdsa_with_sha384, "ecdsa-with-sha384", oid_ecdsa_with_sha384, sizeof(oid_ecdsa_with_sha384)/sizeof(int), 0 }, + { OID_ecdsa_with_sha512, "ecdsa-with-sha512", oid_ecdsa_with_sha512, sizeof(oid_ecdsa_with_sha512)/sizeof(int), 0 }, + { OID_rsasign_with_md5, "md5WithRSAEncryption", oid_rsasign_with_md5, sizeof(oid_rsasign_with_md5)/sizeof(int), 0 }, + { OID_rsasign_with_sha1, "sha1WithRSAEncryption", oid_rsasign_with_sha1, sizeof(oid_rsasign_with_sha1)/sizeof(int), 0 }, + { OID_rsasign_with_sha224, "sha224WithRSAEncryption", oid_rsasign_with_sha224, sizeof(oid_rsasign_with_sha224)/sizeof(int), 1 }, + { OID_rsasign_with_sha256, "sha256WithRSAEncryption", oid_rsasign_with_sha256, sizeof(oid_rsasign_with_sha256)/sizeof(int), 1 }, + { OID_rsasign_with_sha384, "sha384WithRSAEncryption", oid_rsasign_with_sha384, sizeof(oid_rsasign_with_sha384)/sizeof(int), 1 }, + { OID_rsasign_with_sha512, "sha512WithRSAEncryption", oid_rsasign_with_sha512, sizeof(oid_rsasign_with_sha512)/sizeof(int), 1 }, +}; + +static const int x509_sign_algors_count = + sizeof(x509_sign_algors)/sizeof(x509_sign_algors[0]); + +const char *x509_signature_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_sign_algors, x509_sign_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_signature_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_sign_algors, x509_sign_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_signature_algor_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_sign_algors, x509_sign_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || (info->flags && asn1_null_to_der(NULL, &len) != 1) + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1 + || (info->flags && 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 *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = OID_undef; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_oid_info_from_der(&info, x509_sign_algors, x509_sign_algors_count, &p, &len) != 1) { + error_print(); + return -1; + } + if (len) { + if (info->flags == 0) { + //warning_print(); + } + if (asn1_null_from_der(&p, &len) < 0) { + error_print(); + return -1; + } + if (len) { + error_print(); + return -1; + } + } + *oid = info->oid; + return 1; +} + +int x509_signature_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + int null_param; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_sign_algors, x509_sign_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if ((null_param = asn1_null_from_der(&d, &dlen)) < 0) goto err; + if (null_param) format_print(fp, fmt, ind, "parameters: %s\n", asn1_tag_name(ASN1_TAG_NULL)); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +/* +sm2encrypt: no parameters + +rsaes_oaep: from rfc 3560 +RSAES-OAEP-params ::= SEQUENCE { + hashFunc [0] AlgorithmIdentifier DEFAULT sha1Identifier, + maskGenFunc [1] AlgorithmIdentifier DEFAULT mgf1SHA1Identifier, + pSourceFunc [2] AlgorithmIdentifier DEFAULT +*/ + +static uint32_t oid_sm2encrypt[] = { 1,2,156,10197,1,301,2 }; +static uint32_t oid_rsa_encryption[] = { 1,2,840,113549,1,1,1 }; +static uint32_t oid_rsaes_oaep[] = { 1,2,840,113549,1,1,7 }; + +static const ASN1_OID_INFO x509_pke_algors[] = { + { OID_sm2encrypt, "sm2encrypt", oid_sm2encrypt, sizeof(oid_sm2encrypt)/sizeof(int) }, + { OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int) }, + { OID_rsaes_oaep, "rsaesOAEP", oid_rsaes_oaep, sizeof(oid_rsaes_oaep)/sizeof(int) }, +}; + +static const int x509_pke_algors_count = + sizeof(x509_pke_algors)/sizeof(x509_pke_algors[0]); + +const char *x509_public_key_encryption_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_pke_algors, x509_pke_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_public_key_encryption_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_pke_algors, x509_pke_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_public_key_encryption_algor_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + + if (oid != OID_sm2encrypt) { + error_print(); + return -1; + } + if (!(info = asn1_oid_info_from_oid(x509_pke_algors, x509_pke_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_public_key_encryption_algor_from_der(int *oid, const uint8_t **params, size_t *params_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = OID_undef; + *params = NULL; + *params_len = 0; + + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_oid_info_from_der(&info, x509_pke_algors, x509_pke_algors_count, &p, &len) != 1) { + error_print(); + return -1; + } + *oid = info->oid; + if (asn1_length_is_zero(len) != 1) { + if (info->oid == OID_sm2encrypt) { + error_print(); + return -1; + } + *params = p; + *params_len = len; + } + return 1; +} + +int x509_public_key_encryption_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_pke_algors, x509_pke_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if (asn1_length_is_zero(dlen) != 1) { + if (info->oid == OID_sm2encrypt) goto err; + format_bytes(fp, fmt, ind, "parameters: ", d, dlen); + } + return 1; +err: + error_print(); + return -1; +} + + + + + +static uint32_t oid_ec_public_key[] = { oid_x9_62,2,1 }; +//static uint32_t oid_rsa_encryption[] = { 1,2,840,113549,1,1,1 }; + +static const ASN1_OID_INFO x509_public_key_algors[] = { + { OID_ec_public_key, "ecPublicKey", oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), 0, "X9.62 ecPublicKey" }, + { OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), 0, "RSAEncryption" }, +}; + +static const int x509_public_key_algors_count = + sizeof(x509_public_key_algors)/sizeof(x509_public_key_algors[0]); + +const char *x509_public_key_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_public_key_algors, x509_public_key_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_public_key_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_public_key_algors, x509_public_key_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_public_key_algor_to_der(int oid, int curve_or_null, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + switch (oid) { + case OID_ec_public_key: + if (asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), NULL, &len) != 1 + || ec_named_curve_to_der(curve_or_null, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), out, outlen) != 1 + || ec_named_curve_to_der(curve_or_null, out, outlen) != 1) { + error_print(); + return -1; + } + break; + case OID_rsa_encryption: + if (asn1_object_identifier_to_der(oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), NULL, &len) != 1 + || asn1_null_to_der(NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), out, outlen) != 1 + || asn1_null_to_der(out, outlen) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_public_key_algor_from_der(int *oid , int *curve_or_null, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const ASN1_OID_INFO *info; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + + if (asn1_oid_info_from_der(&info, x509_public_key_algors, x509_public_key_algors_count, &d, &dlen) != 1) { + error_print(); + return -1; + } + *oid = info->oid; + + switch (*oid) { + case OID_ec_public_key: + if (ec_named_curve_from_der(curve_or_null, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + break; + case OID_rsa_encryption: + if ((*curve_or_null = asn1_null_from_der(&d, &dlen)) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + int val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_public_key_algors, x509_public_key_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + + switch (info->oid) { + case OID_ec_public_key: + if (ec_named_curve_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "namedCurve: %s\n", ec_named_curve_name(val)); + break; + case OID_rsa_encryption: + if ((val = asn1_null_from_der(&d, &dlen)) < 0) goto err; + else if (val) format_print(fp, fmt, ind, "parameters: %s\n", asn1_null_name()); + break; + default: + error_print(); + return -1; + } + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/src/x509_cer.c b/Core/GmSSL-3.1.1/src/x509_cer.c new file mode 100644 index 0000000..218ace8 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/x509_cer.c @@ -0,0 +1,2009 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +const char *x509_version_name(int version) +{ + switch (version) { + case X509_version_v1: return "v1"; + case X509_version_v2: return "v2"; + case X509_version_v3: return "v3"; + } + return NULL; +} + +int x509_explicit_version_to_der(int index, int version, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (version == -1) { + return 0; + } + if (!x509_version_name(version)) { + error_print(); + return -1; + } + if (asn1_int_to_der(version, NULL, &len) != 1 + || asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_version_from_der(int index, int *version, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_explicit_from_der(index, &d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *version = -1; + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (!x509_version_name(*version)) { + error_print(); + return -1; + } + return 1; +} + +int x509_time_to_der(time_t tv, uint8_t **out, size_t *outlen) +{ + if (tv == -1) { + return 0; + } + + if (tv < -1 || tv > X509_MAX_GENERALIZED_TIME) { + error_print(); + return -1; + } + if (tv <= X509_MAX_UTC_TIME) { + if (asn1_utc_time_to_der(tv, out, outlen) != 1) { + error_print(); + return -1; + } + } else { + if (asn1_generalized_time_to_der(tv, out, outlen) !=1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_time_from_der(time_t *tv, const uint8_t **in, size_t *inlen) +{ + int ret; + int tag; + + if ((ret = asn1_tag_from_der_readonly(&tag, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *tv = -1; + return ret; + } + switch (tag) { + case ASN1_TAG_UTCTime: + if (asn1_utc_time_from_der(tv, in, inlen) != 1) { + error_print(); + return -1; + } + break; + case ASN1_TAG_GeneralizedTime: + if (asn1_generalized_time_from_der(tv, in, inlen) != 1) { + error_print(); + return -1; + } + break; + default: + return 0; + } + return 1; +} + +int x509_validity_add_days(time_t *not_after, time_t not_before, int days) +{ + if (days < X509_VALIDITY_MIN_DAYS + || days > X509_VALIDITY_MAX_DAYS) { + error_print(); + return -1; + } + *not_after = not_before + (time_t)days * 24 * 60 * 60; + return 1; +} + +int x509_validity_to_der(time_t not_before, time_t not_after, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_time_to_der(not_before, NULL, &len) != 1 + || x509_time_to_der(not_after, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_time_to_der(not_before, out, outlen) != 1 + || x509_time_to_der(not_after, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_validity_from_der(time_t *not_before, time_t *not_after, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *not_before = *not_after = -1; + return ret; + } + if (x509_time_from_der(not_before, &d, &dlen) != 1 + || x509_time_from_der(not_after, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (*not_before >= *not_after) { + error_print(); + return -1; + } + return 1; +} + +int x509_validity_check(time_t not_before, time_t not_after, time_t now, int max_secs) +{ + if (!(not_before <= not_after)) { + error_print(); + return -1; + } + if (!(not_after - not_before <= (unsigned int)max_secs)) { + error_print(); + return -1; + } + if (!(not_before <= now && now <= not_after)) { + error_print(); + return -1; + } + return 1; +} + +int x509_validity_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + time_t tv; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_time_from_der(&tv, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "notBefore: %s", ctime(&tv)); + if (x509_time_from_der(&tv, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "notAfter: %s", ctime(&tv)); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static uint32_t oid_at_name[] = { oid_at,41 }; +static uint32_t oid_at_surname[] = { oid_at,4 }; +static uint32_t oid_at_given_name[] = { oid_at,42 }; +static uint32_t oid_at_initials[] = { oid_at,43 }; +static uint32_t oid_at_generation_qualifier[] = { oid_at,44 }; +static uint32_t oid_at_common_name[] = { oid_at,3 }; +static uint32_t oid_at_locality_name[] = { oid_at,7 }; +static uint32_t oid_at_state_or_province_name[] = { oid_at,8 }; +static uint32_t oid_at_organization_name[] = { oid_at,10 }; +static uint32_t oid_at_organizational_unit_name[] = { oid_at,11 }; +static uint32_t oid_at_title[] = { oid_at,12 }; +static uint32_t oid_at_dn_qualifier[] = { oid_at,46 }; +static uint32_t oid_at_country_name[] = { oid_at,6 }; +static uint32_t oid_at_serial_number[] = { oid_at,5 }; +static uint32_t oid_at_pseudonym[] = { oid_at,65 }; +static uint32_t oid_domain_component[] = { 0,9,2342,19200300,100,1,25 }; +static uint32_t oid_email_address[] = { 1,2,840,113549,1,9,1 }; + +#define OID_AT_CNT (sizeof(oid_at_name)/sizeof(int)) + +static const ASN1_OID_INFO x509_name_types[] = { + { OID_at_name, "name", oid_at_name, OID_AT_CNT }, + { OID_at_surname, "surname", oid_at_surname, OID_AT_CNT }, + { OID_at_given_name, "givenName", oid_at_given_name, OID_AT_CNT }, + { OID_at_initials, "initials", oid_at_initials, OID_AT_CNT }, + { OID_at_generation_qualifier, "generationQualifier", oid_at_generation_qualifier, OID_AT_CNT }, + { OID_at_common_name, "commonName", oid_at_common_name, OID_AT_CNT }, + { OID_at_locality_name, "localityName", oid_at_locality_name, OID_AT_CNT }, + { OID_at_state_or_province_name, "stateOrProvinceName", oid_at_state_or_province_name, OID_AT_CNT }, + { OID_at_organization_name, "organizationName", oid_at_organization_name, OID_AT_CNT }, + { OID_at_organizational_unit_name, "organizationalUnitName", oid_at_organizational_unit_name, OID_AT_CNT }, + { OID_at_title, "title", oid_at_title, OID_AT_CNT }, + { OID_at_dn_qualifier, "dnQualifier", oid_at_dn_qualifier, OID_AT_CNT }, + { OID_at_country_name, "countryName", oid_at_country_name, OID_AT_CNT }, + { OID_at_serial_number, "serialNumber", oid_at_serial_number, OID_AT_CNT }, + { OID_at_pseudonym, "pseudonym", oid_at_pseudonym, OID_AT_CNT }, + { OID_domain_component, "domainComponent", oid_domain_component, sizeof(oid_domain_component)/sizeof(int) }, + { OID_email_address, "emailAddress", oid_email_address, sizeof(oid_email_address)/sizeof(int) }, +}; + +static const int x509_name_types_count + = sizeof(x509_name_types)/sizeof(x509_name_types[0]); + +const char *x509_name_type_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_name_types, x509_name_types_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_name_type_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_name_types, x509_name_types_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_name_type_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_name_types, x509_name_types_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_name_type_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + + if ((ret = asn1_oid_info_from_der(&info, x509_name_types, x509_name_types_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + +int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen) +{ + if (dlen == 0) { + return 0; + } + if (!d) { + error_print(); + return -1; + } + + switch (tag) { + case ASN1_TAG_TeletexString: + case ASN1_TAG_PrintableString: + case ASN1_TAG_UniversalString: + case ASN1_TAG_UTF8String: + if (strnlen((char *)d, dlen) != dlen) { + error_print(); + return -1; + } + break; + case ASN1_TAG_BMPString: + if (dlen % 2) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen) +{ + int ret; + + if ((ret = x509_directory_name_check(tag, d, dlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (dlen < minlen || dlen > maxlen) { + error_print(); + return -1; + } + return 1; +} + +int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + if (dlen == 0) { + return 0; + } + if (x509_directory_name_check(tag, d, dlen) != 1) { + error_print(); + return -1; + } + if (asn1_type_to_der(tag, d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_tag_from_der_readonly(tag, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + switch (*tag) { + case ASN1_TAG_TeletexString: + case ASN1_TAG_PrintableString: + case ASN1_TAG_UniversalString: + case ASN1_TAG_UTF8String: + case ASN1_TAG_BMPString: + break; + default: + return 0; + } + if (asn1_any_type_from_der(tag, d, dlen, in, inlen) != 1) { + error_print(); + return -1; + } + if (x509_directory_name_check(*tag, *d, *dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen) +{ + return asn1_string_print(fp, fmt, ind, label, tag, d, dlen); +} + +int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + size_t len = 0; + + if ((ret = x509_directory_name_to_der(tag, d, dlen, NULL, &len)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || x509_directory_name_to_der(tag, d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_directory_name_from_der(tag, d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +static const struct { + int oid; + int is_printable_string_only; + int minlen; + int maxlen; +} x509_name_types_info[] = { + { OID_at_country_name, 1, 2, 2 }, + { OID_at_state_or_province_name, 0, 1, X509_ub_state_name }, + { OID_at_locality_name, 0, 1, X509_ub_locality_name }, + { OID_at_organization_name, 0, 1, X509_ub_organization_name }, + { OID_at_organizational_unit_name, 0, 1, X509_ub_organizational_unit_name }, + { OID_at_common_name, 0, 1, X509_ub_common_name }, + { OID_at_serial_number, 1, 1, X509_ub_serial_number }, + { OID_at_dn_qualifier, 1, 1, 64 }, // max length unspecified in RFC 5280 + { OID_at_title, 0, 1, X509_ub_title }, + { OID_at_surname, 0, 1, X509_ub_name }, + { OID_at_given_name, 0, 1, X509_ub_name }, + { OID_at_initials, 0, 1, X509_ub_name }, + { OID_at_generation_qualifier, 0, 1, X509_ub_name }, + { OID_at_pseudonym, 0, 1, X509_ub_pseudonym }, +}; + +static const int x509_name_types_info_count + = sizeof(x509_name_types_info)/sizeof(x509_name_types_info[0]); + +int x509_attr_type_and_value_check(int oid, int tag, const uint8_t *val, size_t vlen) +{ + int i; + for (i = 0; i < x509_name_types_info_count; i++) { + if (oid == x509_name_types_info[i].oid) { + if (x509_name_types_info[i].is_printable_string_only + && tag != ASN1_TAG_PrintableString) { + error_print(); + return -1; + } + if (x509_directory_name_check_ex(tag, val, vlen, + x509_name_types_info[i].minlen, x509_name_types_info[i].maxlen) != 1) { + error_print(); + return -1; + } + return 1; + } + } + error_print(); + return -1; +} + +int x509_attr_type_and_value_to_der(int oid, int tag, const uint8_t *val, size_t vlen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (vlen == 0) { + return 0; + } + if (x509_attr_type_and_value_check(oid, tag, val, vlen) != 1 + || x509_name_type_to_der(oid, NULL, &len) != 1 + || x509_directory_name_to_der(tag, val, vlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_name_type_to_der(oid, out, outlen) != 1 + || x509_directory_name_to_der(tag, val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_attr_type_and_value_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *tag = -1; + *val = NULL; + *vlen = 0; + } + return ret; + } + if (x509_name_type_from_der(oid, &d, &dlen) != 1 + || x509_directory_name_from_der(tag, val, vlen, &d, &dlen) != 1 + || x509_attr_type_and_value_check(*oid, *tag, *val, *vlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_attr_type_and_value_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid, tag; + const uint8_t *val; + size_t vlen; + + if (fmt & ASN1_FMT_FULL) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_name_type_from_der(&oid, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "type", x509_name_type_name(oid), NULL, 0); + if (oid == OID_email_address) { + if (asn1_ia5_string_from_der((const char **)&val, &vlen, &d, &dlen) != 1) goto err; + format_string(fp, fmt, ind, "value", val, vlen); + } else { + if (x509_directory_name_from_der(&tag, &val, &vlen, &d, &dlen) != 1) goto err; + x509_directory_name_print(fp, fmt, ind, "value", tag, val, vlen); + } + } else { + if (x509_name_type_from_der(&oid, &d, &dlen) != 1) { error_print(); goto err; } + if (oid == OID_email_address) { + if (asn1_ia5_string_from_der((const char **)&val, &vlen, &d, &dlen) != 1) goto err; + format_string(fp, fmt, ind, "emailAddress", val, vlen); + } else { + if (x509_directory_name_from_der(&tag, &val, &vlen, &d, &dlen) != 1) goto err; + x509_directory_name_print(fp, fmt, ind, x509_name_type_name(oid), tag, val, vlen); + } + } + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_rdn_check(const uint8_t *d, size_t dlen) +{ + int oid; + int tag; + const uint8_t *val; + size_t vlen; + + if (dlen == 0) { + return 0; + } + while (dlen) { + if (x509_attr_type_and_value_from_der(&oid, &tag, &val, &vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (vlen == 0) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_rdn_to_der(int oid, int tag, const uint8_t *val, size_t vlen, + const uint8_t *more, size_t morelen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (vlen == 0 && morelen == 0) { + return 0; + } + if (x509_rdn_check(more, morelen) < 0) { + error_print(); + return -1; + } + if (x509_attr_type_and_value_to_der(oid, tag, val, vlen, NULL, &len) < 0 + || asn1_data_to_der(more, morelen, NULL, &len) < 0 + || asn1_set_header_to_der(len, out, outlen) != 1 + || x509_attr_type_and_value_to_der(oid, tag, val, vlen, out, outlen) < 0 + || asn1_data_to_der(more, morelen, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_rdn_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, + const uint8_t **more, size_t *morelen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_set_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *oid = *tag = -1; + *val = *more = NULL; + *vlen = *morelen = 0; + } + return ret; + } + if (x509_attr_type_and_value_from_der(oid, tag, val, vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_rdn_check(d, dlen) < 0) { + error_print(); + return -1; + } + *more = dlen ? d : NULL; + *morelen = dlen; + return 1; +} + +int x509_rdn_get_value_by_type(const uint8_t *d, size_t dlen, int type, int *tag, const uint8_t **val, size_t *vlen) +{ + int oid; + + while (dlen) { + if (x509_attr_type_and_value_from_der(&oid, tag, val, vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (oid == type) { + return 1; + } + } + + *tag = -1; + *val = NULL; + *vlen = 0; + return 0; +} + +int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (fmt & ASN1_FMT_FULL) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_attr_type_and_value_print(fp, fmt, ind, "AttributeTypeAndValue", p, len); + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_attr_type_and_value_print(fp, fmt, ind + 4, "AttributeTypeAndValue", p, len); + } + return 1; +} + +int x509_name_check(const uint8_t *d, size_t dlen) +{ + const uint8_t *rdn; + size_t rdnlen; + + if (dlen == 0) { + return 0; + } + while (dlen) { + if (asn1_set_from_der(&rdn, &rdnlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_rdn_check(rdn, rdnlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_name_add_rdn(uint8_t *d, size_t *dlen, size_t maxlen, + int oid, int tag, const uint8_t *val, size_t vlen, + const uint8_t *more, size_t morelen) +{ + int ret; + uint8_t *p; + size_t len; + + if (!d || !dlen) { + error_print(); + return -1; + } + p = d + (*dlen); + if (x509_rdn_to_der(oid, tag, val, vlen, more, morelen, NULL, dlen) < 0 + || asn1_length_le(*dlen, maxlen) != 1 + || (ret = x509_rdn_to_der(oid, tag, val, vlen, more, morelen, &p, &len)) < 0) { + error_print(); + return -1; + } + return ret; +} + +int x509_name_add_country_name(uint8_t *d, size_t *dlen, size_t maxlen, const char val[2]) +{ + int ret; + ret = x509_name_add_rdn(d, dlen, maxlen, + OID_at_country_name, ASN1_TAG_PrintableString, (uint8_t *)val, val ? 2 : 0, NULL, 0); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_add_state_or_province_name(uint8_t *d, size_t *dlen, size_t maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + int ret; + ret = x509_name_add_rdn(d, dlen, maxlen, OID_at_state_or_province_name, tag, val, vlen, NULL, 0); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_add_locality_name(uint8_t *d, size_t *dlen, size_t maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + int ret; + ret = x509_name_add_rdn(d, dlen, maxlen, OID_at_locality_name, tag, val, vlen, NULL, 0); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_add_organization_name(uint8_t *d, size_t *dlen, size_t maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + int ret; + ret = x509_name_add_rdn(d, dlen, maxlen, OID_at_organization_name, tag, val, vlen, NULL, 0); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_add_organizational_unit_name(uint8_t *d, size_t *dlen, size_t maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + int ret; + ret = x509_name_add_rdn(d, dlen, maxlen, OID_at_organizational_unit_name, tag, val, vlen, NULL, 0); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_add_common_name(uint8_t *d, size_t *dlen, size_t maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + int ret; + ret = x509_name_add_rdn(d, dlen, maxlen, OID_at_common_name, tag, val, vlen, NULL, 0); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_add_domain_component(uint8_t *d, size_t *dlen, size_t maxlen, + const char *val, size_t vlen) +{ + int ret; + return x509_name_add_rdn(d, dlen, maxlen, OID_domain_component, ASN1_TAG_IA5String, (uint8_t *)val, vlen, NULL, 0); + if (ret < 0) error_print(); + return ret; +} + +static size_t optstrlen(const char *s) { return s ? strlen(s) : 0; } + +static int x509_name_tag(const char *str) +{ + if (str) { + if (asn1_string_is_printable_string(str, strlen(str)) == 1) + return ASN1_TAG_PrintableString; + else return ASN1_TAG_UTF8String; + } + return 0; +} + +int x509_name_set(uint8_t *d, size_t *dlen, size_t maxlen, + const char country[2], const char *state, const char *locality, + const char *org, const char *org_unit, const char *common_name) +{ + if (country && strlen(country) != 2) { + error_print(); + return -1; + } + *dlen = 0; + if (x509_name_add_country_name(d, dlen, maxlen, country) < 0 + || x509_name_add_state_or_province_name(d, dlen, maxlen, x509_name_tag(state), (uint8_t *)state, optstrlen(state)) < 0 + || x509_name_add_locality_name(d, dlen, maxlen, x509_name_tag(locality), (uint8_t *)locality, optstrlen(locality)) < 0 + || x509_name_add_organization_name(d, dlen, maxlen, x509_name_tag(org), (uint8_t *)org, optstrlen(org)) < 0 + || x509_name_add_organizational_unit_name(d, dlen, maxlen, x509_name_tag(org_unit), (uint8_t *)org_unit, optstrlen(org_unit)) < 0 + || x509_name_add_common_name(d, dlen, maxlen, x509_name_tag(common_name), (uint8_t *)common_name, optstrlen(common_name)) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen) +{ + int ret; + const uint8_t *rdn; + size_t rdnlen; + + while (dlen) { + if (asn1_set_from_der(&rdn, &rdnlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if ((ret = x509_rdn_get_value_by_type(rdn, rdnlen, oid, tag, val, vlen)) < 0) { + error_print(); + return -1; + } + if (ret) { + return 1; + } + } + return 0; +} + +int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen) +{ + int ret; + ret = x509_name_get_value_by_type(d, dlen, OID_at_common_name, tag, val, vlen); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_equ(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) +{ + if (alen != blen || memcmp(a, b, blen) != 0) { + return 0; + } + return 1; +} + +int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_rdn_print(fp, fmt, ind, "RelativeDistinguishedName", p, len); + } + return 1; +} + +int x509_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_name_print(fp, fmt, ind, "Name", p, len); + } + return 1; +} + +int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p = d; + size_t len = dlen; + int alg; + int params; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_public_key_algor_from_der(&alg, ¶ms, &p, &len) != 1) goto err; + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_algor_print(fp, fmt, ind, "algorithm", p, len); + format_print(fp, fmt, ind, "subjectPublicKey\n"); + ind += 4; + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + switch (alg) { + case OID_ec_public_key: + format_bytes(fp, fmt, ind, "ECPoint", p, len); + break; + case OID_rsa_encryption: + rsa_public_key_print(fp, fmt, ind, "RSAPublicKey", p, len); + break; + default: + format_bytes(fp, fmt, ind, "raw_data", p, len); + } + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_explicit_exts_to_der(int index, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (dlen == 0) { + return 0; + } + if (asn1_sequence_to_der(d, dlen, NULL, &len) != 1 + || asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || asn1_sequence_to_der(d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_exts_from_der(int index, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *d = NULL; + *dlen = 0; + } + return ret; + } + if (asn1_sequence_from_der(d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_tbs_cert_to_der( + int version, + const uint8_t *serial, size_t serial_len, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t not_before, time_t not_after, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *issuer_unique_id, size_t issuer_unique_id_len, + const uint8_t *subject_unique_id, size_t subject_unique_id_len, + const uint8_t *exts, size_t exts_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_explicit_version_to_der(0, version, NULL, &len) < 0 + || asn1_integer_to_der(serial, serial_len, NULL, &len) != 1 + || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 + || asn1_sequence_to_der(issuer, issuer_len, NULL, &len) != 1 + || x509_validity_to_der(not_before, not_after, NULL, &len) != 1 + || asn1_sequence_to_der(subject, subject_len, NULL, &len) != 1 + || x509_public_key_info_to_der(subject_public_key, NULL, &len) != 1 + || asn1_implicit_bit_octets_to_der(1, issuer_unique_id, issuer_unique_id_len, NULL, &len) < 0 + || asn1_implicit_bit_octets_to_der(2, subject_unique_id, subject_unique_id_len, NULL, &len) < 0 + || x509_explicit_exts_to_der(3, exts, exts_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_explicit_version_to_der(0, version, out, outlen) < 0 + || asn1_integer_to_der(serial, serial_len, out, outlen) != 1 + || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 + || asn1_sequence_to_der(issuer, issuer_len, out, outlen) != 1 + || x509_validity_to_der(not_before, not_after, out, outlen) != 1 + || asn1_sequence_to_der(subject, subject_len, out, outlen) != 1 + || x509_public_key_info_to_der(subject_public_key, out, outlen) != 1 + || asn1_implicit_bit_octets_to_der(1, issuer_unique_id, issuer_unique_id_len, out, outlen) < 0 + || asn1_implicit_bit_octets_to_der(2, subject_unique_id, subject_unique_id_len, out, outlen) < 0 + || x509_explicit_exts_to_der(3, exts, exts_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_tbs_cert_from_der( + int *version, + const uint8_t **serial, size_t *serial_len, + int *signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *not_before, time_t *not_after, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **issuer_unique_id, size_t *issuer_unique_id_len, + const uint8_t **subject_unique_id, size_t *subject_unique_id_len, + const uint8_t **exts, size_t *exts_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_explicit_version_from_der(0, version, &d, &dlen) < 0 + || asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 + || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 + || asn1_sequence_from_der(issuer, issuer_len, &d, &dlen) != 1 + || x509_validity_from_der(not_before, not_after, &d, &dlen) != 1 + || asn1_sequence_from_der(subject, subject_len, &d, &dlen) != 1 + || x509_public_key_info_from_der(subject_public_key, &d, &dlen) != 1 + || asn1_implicit_bit_octets_from_der(1, issuer_unique_id, issuer_unique_id_len, &d, &dlen) < 0 + || asn1_implicit_bit_octets_from_der(2, subject_unique_id, subject_unique_id_len, &d, &dlen) < 0 + || x509_explicit_exts_from_der(3, exts, exts_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_tbs_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = x509_explicit_version_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "version: %s (%d)\n", x509_version_name(val), val); + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "serialNumber", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "signature", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "issuer", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_validity_print(fp, fmt, ind, "validity", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "subject", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_info_print(fp, fmt, ind, "subjectPulbicKeyInfo", p, len); + if ((ret = asn1_implicit_bit_octets_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "issuerUniqueID", p, len); + if ((ret = asn1_implicit_bit_octets_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "subjectUniqueID", p, len); + if ((ret = x509_explicit_exts_from_der(3, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_exts_print(fp, fmt, ind, "extensions", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_cert_sign_to_der( + int version, + const uint8_t *serial, size_t serial_len, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t not_before, time_t not_after, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *issuer_unique_id, size_t issuer_unique_id_len, + const uint8_t *subject_unique_id, size_t subject_unique_id_len, + const uint8_t *exts, size_t exts_len, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + uint8_t *tbs; + int sig_alg = OID_sm2sign_with_sm3; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen = SM2_signature_typical_size; + + if (x509_tbs_cert_to_der( + version, + serial, serial_len, + signature_algor, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + subject_public_key, + issuer_unique_id, issuer_unique_id_len, + subject_unique_id, subject_unique_id_len, + exts, exts_len, + NULL, &len) != 1 + || x509_signature_algor_to_der(sig_alg, NULL, &len) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + if (out && *out) { + tbs = *out; + } + + if (x509_tbs_cert_to_der( + version, + serial, serial_len, + signature_algor, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + subject_public_key, + issuer_unique_id, issuer_unique_id_len, + subject_unique_id, subject_unique_id_len, + exts, exts_len, + out, outlen) != 1) { + error_print(); + return -1; + } + + if (out && *out) { + SM2_SIGN_CTX sign_ctx; + if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 + || sm2_sign_update(&sign_ctx, tbs, *out - tbs) != 1 + || sm2_sign_finish_fixlen(&sign_ctx, siglen, sig) != 1) { + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + error_print(); + return -1; + } + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + } + + if (x509_signature_algor_to_der(sig_alg, out, outlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_signed_from_der(const uint8_t **tbs, size_t *tbslen, + int *sig_alg, const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *tbs = *sig = NULL; + *tbslen = *siglen = 0; + *sig_alg = -1; + } + return ret; + } + if (asn1_any_from_der(tbs, tbslen, &d, &dlen) != 1 + || x509_signature_algor_from_der(sig_alg, &d, &dlen) != 1 + || asn1_bit_octets_from_der(sig, siglen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_signed_verify(const uint8_t *a, size_t alen, + const SM2_KEY *pub_key, const char *signer_id, size_t signer_id_len) +{ + const uint8_t *tbs; + size_t tbslen; + int sig_alg; + const uint8_t *sig; + size_t siglen; + SM2_SIGN_CTX verify_ctx; + + if (x509_signed_from_der(&tbs, &tbslen, &sig_alg, &sig, &siglen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + if (sig_alg != OID_sm2sign_with_sm3) { + error_print(); + return -1; + } + if (sm2_verify_init(&verify_ctx, pub_key, signer_id, signer_id_len) != 1 + || sm2_verify_update(&verify_ctx, tbs, tbslen) != 1 + || sm2_verify_finish(&verify_ctx, sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_signed_verify_by_ca_cert(const uint8_t *a, size_t alen, + const uint8_t *cacert, size_t cacertlen, + const char *signer_id, size_t signer_id_len) +{ + int ret; + SM2_KEY public_key; + + if (x509_cert_get_subject_public_key(cacert, cacertlen, &public_key) != 1 + || (ret = x509_signed_verify(a, alen, &public_key, signer_id, signer_id_len)) < 0) { + error_print(); + return -1; + } + if (!ret) error_print(); + return ret; +} + +int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen, + const uint8_t *cacert, size_t cacertlen, + const char *signer_id, size_t signer_id_len) +{ + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *subject; + size_t subject_len; + + if (x509_cert_get_issuer(a, alen, &issuer, &issuer_len) != 1 + || x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1 + || x509_name_equ(issuer, issuer_len, subject, subject_len) != 1) { + error_print(); + return -1; + } + if (x509_signed_verify_by_ca_cert(a, alen, cacert, cacertlen, signer_id, signer_id_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen) +{ + int ret; + if (x509_cert_get_subject(a, alen, NULL, NULL) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_any_to_der(a, alen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_cert_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = asn1_any_from_der(a, alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_cert_get_subject(*a, *alen, NULL, NULL) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_to_pem(const uint8_t *a, size_t alen, FILE *fp) +{ + if (x509_cert_get_subject(a, alen, NULL, NULL) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, "CERTIFICATE", a, alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp) +{ + int ret; + if ((ret = pem_read(fp, "CERTIFICATE", a, alen, maxlen)) != 1) { + if (ret < 0) error_print(); + else *alen = 0; + return ret; + } + if (x509_cert_get_subject(a, *alen, NULL, NULL) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_from_pem_by_subject(uint8_t *a, size_t *alen, size_t maxlen, const uint8_t *name, size_t namelen, FILE *fp) +{ + int ret; + const uint8_t *d; + size_t dlen; + + for (;;) { + if ((ret = x509_cert_from_pem(a, alen, maxlen, fp)) != 1) { + if (ret < 0) error_print(); + else *alen = 0; + return ret; + } + if (x509_cert_get_subject(a, *alen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_name_equ(d, dlen, name, namelen) == 1) { + return 1; + } + } + *alen = 0; + return 0; +} + +static int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_tbs_cert_print(fp, fmt, ind, "tbsCertificate", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "signatureValue", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + const uint8_t *d; + size_t dlen; + + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1) { + error_print(); + return -1; + } + x509_certificate_print(fp, fmt, ind, label, d, dlen); + if (asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_get_details(const uint8_t *a, size_t alen, + int *version, + const uint8_t **serial_number, size_t *serial_number_len, + int *inner_signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *not_before, time_t *not_after, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **issuer_unique_id, size_t *issuer_unique_id_len, + const uint8_t **subject_unique_id, size_t *subject_unique_id_len, + const uint8_t **extensions, size_t *extensions_len, + int *signature_algor, + const uint8_t **signature, size_t *signature_len) +{ + const uint8_t *tbs_a; + size_t tbs_alen; + int sig_alg; + const uint8_t *sig; + size_t sig_len; + + struct { + int version; + const uint8_t *serial; size_t serial_len; + int sig_alg; + const uint8_t *issuer; size_t issuer_len; + time_t not_before; time_t not_after; + const uint8_t *subject; size_t subject_len; + SM2_KEY subject_public_key; + const uint8_t *issuer_unique_id; size_t issuer_unique_id_len; + const uint8_t *subject_unique_id; size_t subject_unique_id_len; + const uint8_t *exts; size_t exts_len; + } tbs; + + if (x509_signed_from_der(&tbs_a, &tbs_alen, &sig_alg, &sig, &sig_len, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + if (x509_tbs_cert_from_der( + &tbs.version, + &tbs.serial, &tbs.serial_len, + &tbs.sig_alg, + &tbs.issuer, &tbs.issuer_len, + &tbs.not_before, &tbs.not_after, + &tbs.subject, &tbs.subject_len, + &tbs.subject_public_key, + &tbs.issuer_unique_id, &tbs.issuer_unique_id_len, + &tbs.subject_unique_id, &tbs.subject_unique_id_len, + &tbs.exts, &tbs.exts_len, &tbs_a, &tbs_alen) != 1) { + error_print(); + return -1; + } + + if (version) *version = tbs.version; + if (serial_number) *serial_number = tbs.serial; + if (serial_number_len) *serial_number_len = tbs.serial_len; + if (inner_signature_algor) *inner_signature_algor = tbs.sig_alg; + if (issuer) *issuer = tbs.issuer; + if (issuer_len) *issuer_len = tbs.issuer_len; + if (not_before) *not_before = tbs.not_before; + if (not_after) *not_after = tbs.not_after; + if (subject) *subject = tbs.subject; + if (subject_len) *subject_len = tbs.subject_len; + if (subject_public_key) *subject_public_key = tbs.subject_public_key; + if (issuer_unique_id) *issuer_unique_id = tbs.issuer_unique_id; + if (issuer_unique_id_len) *issuer_unique_id_len = tbs.issuer_unique_id_len; + if (subject_unique_id) *subject_unique_id = tbs.subject_unique_id; + if (subject_unique_id_len) *subject_unique_id_len = tbs.subject_unique_id_len; + if (extensions) *extensions = tbs.exts; + if (extensions_len) *extensions_len = tbs.exts_len; + if (signature_algor) *signature_algor = sig_alg; + if (signature) *signature = sig; + if (signature_len) *signature_len = sig_len; + return 1; +} + +int x509_cert_get_issuer_and_serial_number(const uint8_t *a, size_t alen, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len) +{ + return x509_cert_get_details(a, alen, + NULL, // version + serial_number, serial_number_len, // serial + NULL, // signature_algor + issuer, issuer_len, // issuer + NULL, NULL, // validity + NULL, NULL, // subject + NULL, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + NULL, NULL, // extensions + NULL, // signature_algor + NULL, NULL); // signature +} + +int x509_cert_get_subject_public_key(const uint8_t *a, size_t alen, SM2_KEY *public_key) +{ + return x509_cert_get_details(a, alen, + NULL, // version + NULL, NULL, // serial + NULL, // signature_algor + NULL, NULL, // issuer + NULL, NULL, // validity + NULL, NULL, // subject + public_key, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + NULL, NULL, // extensions + NULL, // signature_algor + NULL, NULL); // signature +} + +int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen) +{ + return x509_cert_get_details(a, alen, + NULL, // version + NULL, NULL, // serial + NULL, // signature_algor + NULL, NULL, // issuer + NULL, NULL, // validity + d, dlen, // subject + NULL, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + NULL, NULL, // extensions + NULL, // signature_algor + NULL, NULL); // signature +} + +int x509_cert_get_issuer(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen) +{ + return x509_cert_get_details(a, alen, + NULL, // version + NULL, NULL, // serial + NULL, // signature_algor + d, dlen, // issuer + NULL, NULL, // validity + NULL, NULL, // subject + NULL, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + NULL, NULL, // extensions + NULL, // signature_algor + NULL, NULL); // signature +} + +int x509_cert_get_exts(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen) +{ + if (x509_cert_get_details(a, alen, + NULL, // version + NULL, NULL, // serial + NULL, // signature_algor + NULL, NULL, // issuer + NULL, NULL, // validity + NULL, NULL, // subject + NULL, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + d, dlen, // extensions + NULL, // signature_algor + NULL, NULL // signature + ) != 1) { + error_print(); + return -1; + } + if (!d || !dlen) { + return 0; + } + return 1; +} + +int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp) +{ + const uint8_t *a; + size_t alen; + + while (dlen) { + if (asn1_any_from_der(&a, &alen, &d, &dlen) != 1 + || x509_cert_to_pem(a, alen, fp) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp) +{ + int ret; + size_t len; + + *dlen = 0; + + for (;;) { + if ((ret = x509_cert_from_pem(d, &len, maxlen, fp)) < 0) { + error_print(); + return -1; + } else if (ret == 0) { + break; + } + + d += len; + *dlen += len; + maxlen -= len; + } + + if (*dlen == 0) { + return 0; + } + return 1; +} + +int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt) +{ + int ret; + ret = asn1_types_get_count(d, dlen, ASN1_TAG_SEQUENCE, cnt); + if (ret < 0) error_print(); + return ret; +} + +int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen) +{ + int i = 0; + + if (index < 0) { + error_print(); + return -1; + } + while (dlen) { + if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (i++ == index) { + return 1; + } + } + *cert = NULL; + *certlen = 0; + return 0; +} + +int x509_certs_get_last(const uint8_t *d, size_t dlen, const uint8_t **cert, size_t *certlen) +{ + if (dlen == 0) { + return 0; + } + while (dlen) { + if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, + const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen) +{ + const uint8_t *subj; + size_t subj_len; + + while (dlen) { + if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_cert_get_subject(*cert, *certlen, &subj, &subj_len) != 1) { + error_print(); + return -1; + } + if (x509_name_equ(subj, subj_len, subject, subject_len) == 1) { + return 1; + } + } + *cert = NULL; + *certlen = 0; + return 0; +} + +int x509_certs_get_cert_by_issuer_and_serial_number(const uint8_t *d, size_t dlen, + const uint8_t *issuer, size_t issuer_len, const uint8_t *serial, size_t serial_len, + const uint8_t **cert, size_t *cert_len) +{ + const uint8_t *cur_issuer; + size_t cur_issuer_len; + const uint8_t *cur_serial; + size_t cur_serial_len; + + while (dlen) { + if (x509_cert_from_der(cert, cert_len, &d, &dlen) != 1 + || x509_cert_get_issuer_and_serial_number(*cert, *cert_len, + &cur_issuer, &cur_issuer_len, &cur_serial, &cur_serial_len) != 1) { + error_print(); + return -1; + } + if (x509_name_equ(cur_issuer, cur_issuer_len, issuer, issuer_len) == 1 + && cur_serial_len == serial_len && memcmp(cur_serial, serial, serial_len) == 0) { + return 1; + } + } + *cert = NULL; + *cert_len = 0; + return 0; +} + +int x509_cert_check(const uint8_t *cert, size_t certlen, int cert_type, + int *path_len_constraint) +{ + int version; + const uint8_t *serial; + size_t serial_len; + int tbs_sig_algor; + const uint8_t *issuer; + size_t issuer_len; + time_t not_before; + time_t not_after; + time_t now; + const uint8_t *subject; + size_t subject_len; + const uint8_t *exts; + size_t extslen; + int sig_algor; + + + if (x509_cert_get_details(cert, certlen, + &version, // version + &serial, &serial_len, // serial + &tbs_sig_algor, // signature_algor + &issuer, &issuer_len, // issuer + ¬_before, ¬_after, // validity + &subject, &subject_len, // subject + NULL, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + &exts, &extslen, // extensions + &sig_algor, // signature_algor + NULL, NULL // signature + ) != 1) { + error_print(); + return -1; + } + + if (version != X509_version_v3) { + error_print(); + return -1; + } + if (!serial || !serial_len) { + error_print(); + return -1; + } + if (serial_len < 4) { + error_print(); // not enough randomness + } + + time(&now); + if (x509_validity_check(not_before, not_after, now, X509_VALIDITY_MAX_SECONDS) != 1) { + error_print(); + return -1; + } + + // check issuer and subject not empty + if (x509_name_check(issuer, issuer_len) != 1) { + error_print(); + return -1; + } + if (x509_name_check(subject, subject_len) != 1) { + error_print(); + return -1; + } + + if (x509_exts_check(exts, extslen, cert_type, path_len_constraint) != 1) { + error_print(); + return -1; + } + if (tbs_sig_algor != sig_algor) { + error_print(); + return -1; + } + + return 1; +} + +int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result) +{ + int entity_cert_type; + const uint8_t *cert; + size_t certlen; + const uint8_t *cacert; + size_t cacertlen; + const uint8_t *name; + size_t namelen; + + int path_len = 0; + int path_len_constraint; + + switch (certs_type) { + case X509_cert_chain_server: + entity_cert_type = X509_cert_server_auth; + break; + case X509_cert_chain_client: + entity_cert_type = X509_cert_client_auth; + break; + default: + error_print(); + return -1; + } + + // entity cert + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + if (x509_cert_check(cert, certlen, entity_cert_type, &path_len_constraint) != 1) { + error_print(); + x509_cert_print(stderr, 0, 10, "Invalid Entity Certificate", cert, certlen); + return -1; + } + + while (certslen) { + + if (x509_cert_from_der(&cacert, &cacertlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + error_print(); + x509_cert_print(stderr, 0, 10, "Invalid CA Certificate", cacert, cacertlen); + return -1; + } + + if (path_len == 0) { + if (path_len_constraint != 0) { + error_print(); + return -1; + } + } + if ((path_len_constraint >= 0 && path_len > path_len_constraint) + || path_len > depth) { + error_print(); + return -1; + } + + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + + cert = cacert; + certlen = cacertlen; + path_len++; + } + + if (x509_cert_get_issuer(cert, certlen, &name, &namelen) != 1) { + error_print(); + return -1; + } + if (x509_certs_get_cert_by_subject(rootcerts, rootcertslen, name, namelen, + &cacert, &cacertlen) != 1) { + error_print(); + return -1; + } + + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + error_print(); + return -1; + } + if ((path_len_constraint >= 0 && path_len > path_len_constraint) + || path_len > depth) { + error_print(); + return -1; + } + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + + return 1; +} + +int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result) +{ + int sign_cert_type; + int kenc_cert_type; + const uint8_t *cert; + size_t certlen; + const uint8_t *kenc_cert; + size_t kenc_certlen; + const uint8_t *cacert; + size_t cacertlen; + const uint8_t *name; + size_t namelen; + + int path_len = 0; + int path_len_constraint; + + switch (certs_type) { + case X509_cert_chain_server: + sign_cert_type = X509_cert_server_auth; + kenc_cert_type = X509_cert_server_key_encipher; + break; + case X509_cert_chain_client: + sign_cert_type = X509_cert_server_auth; + kenc_cert_type = X509_cert_server_key_encipher; + break; + default: + error_print(); + return -1; + } + + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + if (x509_cert_check(cert, certlen, sign_cert_type, &path_len_constraint) != 1) { + error_print(); + return -1; + } + + // entity key encipherment cert + if (x509_cert_from_der(&kenc_cert, &kenc_certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + if (x509_cert_check(kenc_cert, kenc_certlen, kenc_cert_type, &path_len_constraint) != 1) { + error_print(); + return -1; + } + + while (certslen) { + + if (x509_cert_from_der(&cacert, &cacertlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + error_print(); + return -1; + } + + if (path_len == 0) { + if (path_len_constraint != 0) { + error_print(); + return -1; + } + + // verify entity key encipherment cert + if (x509_cert_verify_by_ca_cert(kenc_cert, kenc_certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + } + if ((path_len_constraint >= 0 && path_len > path_len_constraint) + || path_len > depth) { + error_print(); + return -1; + } + + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + + cert = cacert; + certlen = cacertlen; + path_len++; + } + + + if (x509_cert_get_issuer(cert, certlen, &name, &namelen) != 1) { + error_print(); + return -1; + } + if (x509_certs_get_cert_by_subject(rootcerts, rootcertslen, name, namelen, &cacert, &cacertlen) != 1) { + error_print(); + return -1; + } + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + error_print(); + return -1; + } + if ((path_len_constraint >= 0 && path_len > path_len_constraint) + || path_len > depth) { + error_print(); + return -1; + } + + // when no mid CA certs + if (path_len == 0) { + if (x509_cert_verify_by_ca_cert(kenc_cert, kenc_certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + } + + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_certificate_print(fp, fmt, ind, "Certficate", p, len); + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/x509_crl.c b/Core/GmSSL-3.1.1/src/x509_crl.c new file mode 100644 index 0000000..776dca8 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/x509_crl.c @@ -0,0 +1,1697 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *x509_crl_reason_names[] = { + "unspecified", + "keyCompromise", + "cACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "notAssigned", + "removeFromCRL", + "privilegeWithdrawn", + "aACompromise", +}; + +static const size_t x509_crl_reason_names_count = + sizeof(x509_crl_reason_names)/sizeof(x509_crl_reason_names[0]); + +const char *x509_crl_reason_name(int reason) +{ + if (reason < 0 || reason >= x509_crl_reason_names_count) { + error_print(); + return NULL; + } + return x509_crl_reason_names[reason]; +} + +int x509_crl_reason_from_name(int *reason, const char *name) +{ + int i; + for (i = 0; i < x509_crl_reason_names_count; i++) { + if (strcmp(name, x509_crl_reason_names[i]) == 0) { + *reason = i; + return 1; + } + } + error_print(); + return -1; +} + +int x509_crl_reason_to_der(int reason, uint8_t **out, size_t *outlen) +{ + if (reason == -1) { + return 0; + } + if (!x509_crl_reason_name(reason)) { + error_print(); + return -1; + } + if (asn1_enumerated_to_der(reason, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_reason_from_der(int *reason, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = asn1_enumerated_from_der(reason, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_crl_reason_name(*reason) == NULL) { + error_print(); + return -1; + } + return 1; +} + +/* +int x509_implicit_crl_reason_from_der(int index, int *reason, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = asn1_implicit_enumerated_from_der(index, reason, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (!x509_crl_reason_name(*reason)) { + error_print(); + return -1; + } + return 1; +} +*/ + +static uint32_t oid_ce_crl_reasons[] = { oid_ce,21 }; +static uint32_t oid_ce_invalidity_date[] = { oid_ce,24 }; +static uint32_t oid_ce_certificate_issuer[] = { oid_ce,29 }; + +static const ASN1_OID_INFO x509_crl_entry_exts[] = { + { OID_ce_crl_reasons, "CRLReasons", oid_ce_crl_reasons, oid_cnt(oid_ce_crl_reasons) }, + { OID_ce_invalidity_date, "InvalidityDate", oid_ce_invalidity_date, oid_cnt(oid_ce_invalidity_date) }, + { OID_ce_certificate_issuer, "CertificateIssuer", oid_ce_certificate_issuer, oid_cnt(oid_ce_certificate_issuer) }, +}; + +static const int x509_crl_entry_exts_count = + sizeof(x509_crl_entry_exts)/sizeof(x509_crl_entry_exts[0]); + +const char *x509_crl_entry_ext_id_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_crl_entry_exts, x509_crl_entry_exts_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_crl_entry_ext_id_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_crl_entry_exts, x509_crl_entry_exts_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_crl_entry_ext_id_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_crl_entry_exts, x509_crl_entry_exts_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + + if ((ret = asn1_oid_info_from_der(&info, x509_crl_entry_exts, x509_crl_entry_exts_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + +int x509_crl_entry_ext_critical_check(int oid, int critical) +{ + switch (oid) { + case OID_ce_crl_reasons: + case OID_ce_invalidity_date: + if (critical == X509_critical) { + error_print(); + return -1; + } + break; + case OID_ce_certificate_issuer: + if (critical != X509_critical) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (vlen == 0) { + return 0; + } + if (x509_crl_entry_ext_id_to_der(oid, NULL, &len) != 1 + || asn1_boolean_to_der(critical, NULL, &len) < 0 + || asn1_octet_string_to_der(val, vlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_crl_entry_ext_id_to_der(oid, out, outlen) != 1 + || asn1_boolean_to_der(critical, out, outlen) < 0 + || asn1_octet_string_to_der(val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_ext_from_der(int *oid, int *critical, const uint8_t **val, size_t *vlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_crl_entry_ext_id_from_der(oid, &d, &dlen) != 1 + || asn1_boolean_from_der(critical, &d, &dlen) < 0 + || asn1_octet_string_from_der(val, vlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_reason_ext_to_der(int critical, int reason, uint8_t **out, size_t *outlen) +{ + int oid = OID_ce_crl_reasons; + uint8_t val[3]; + uint8_t *p = val; + size_t vlen = 0; + + if (reason == -1) { + return 0; + } + if (x509_crl_reason_to_der(reason, &p, &vlen) != 1 + || asn1_length_le(vlen, sizeof(val)) != 1 + || x509_crl_entry_ext_to_der(oid, critical, val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_invalidity_date_ext_to_der(int critical, time_t date, uint8_t **out, size_t *outlen) +{ + int oid = OID_ce_invalidity_date; + uint8_t val[ASN1_GENERALIZED_TIME_MAX_SIZE]; + uint8_t *p = val; + size_t vlen = 0; + + if (date == -1) { + return 0; + } + if (asn1_generalized_time_to_der(date, &p, &vlen) != 1 + || asn1_length_le(vlen, sizeof(val)) != 1 + || x509_crl_entry_ext_to_der(oid, critical, val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_issuer_ext_to_der(int critical, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int oid = OID_ce_certificate_issuer; + uint8_t val[256]; + uint8_t *p = val; + size_t vlen = 0; + + if (dlen == 0) { + return 0; + } + if (asn1_sequence_to_der(d, dlen, NULL, &vlen) != 1 + || asn1_length_le(vlen, sizeof(val)) != 1) { + error_print(); + return -1; + } + vlen = 0; + if (asn1_sequence_to_der(d, dlen, &p, &vlen) != 1 + || x509_crl_entry_ext_to_der(oid, critical, val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_ext_from_der_ex(int *oid, int *critical, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *val; + size_t vlen; + + if ((ret = x509_crl_entry_ext_from_der(oid, critical, &val, &vlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *reason = -1; + *invalid_date = -1; + *cert_issuer = NULL; + *cert_issuer_len = 0; + } + return ret; + } + switch (*oid) { + case OID_ce_crl_reasons: + if (*reason != -1) { + error_print(); + return -1; + } + if (x509_crl_reason_from_der(reason, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_invalidity_date: + if (*invalid_date != -1) { + error_print(); + return -1; + } + if (asn1_generalized_time_from_der(invalid_date, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_certificate_issuer: + if (*cert_issuer != NULL) { + error_print(); + return -1; + } + if (asn1_sequence_from_der(cert_issuer, cert_issuer_len, &val, &vlen) != 1) { + error_print(); + return -1; + } + if (!cert_issuer) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, oid, critical; + const uint8_t *v; + size_t vlen; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_crl_entry_ext_id_from_der(&oid, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "extnID: %s\n", x509_crl_entry_ext_id_name(oid)); + if ((ret = asn1_boolean_from_der(&critical, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "critical: %s\n", asn1_boolean_name(critical)); + if (asn1_octet_string_from_der(&v, &vlen, &d, &dlen) != 1) goto err; + + if (oid == OID_ce_crl_reasons) { + int reason; + if (x509_crl_reason_from_der(&reason, &v, &vlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "reasonCode: %s\n", x509_crl_reason_name(reason)); + + } else if (oid == OID_ce_invalidity_date) { + time_t invalidity_date; + if (asn1_generalized_time_from_der(&invalidity_date, &v, &vlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "invalidityDate: %s", ctime(&invalidity_date)); + + } else if (oid == OID_ce_certificate_issuer) { + const uint8_t *gns; + size_t gnslen; + if (asn1_sequence_from_der(&gns, &gnslen, &v, &vlen) != 1) { + error_print(); + return -1; + } + x509_general_names_print(fp, fmt, ind, "certificateIssuer", gns, gnslen); + + } else { +err: + error_print(); + return -1; + } + + return 1; +} + +int x509_crl_entry_exts_to_der( + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (reason == -1 && invalid_date == -1 && cert_issuer_len == 0) { + return 0; + } + if (x509_crl_reason_ext_to_der(-1, reason, NULL, &len) < 0 + || x509_invalidity_date_ext_to_der(-1, invalid_date, NULL, &len) < 0 + || x509_cert_issuer_ext_to_der(X509_critical, cert_issuer, cert_issuer_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_crl_reason_ext_to_der(-1, reason, out, outlen) < 0 + || x509_invalidity_date_ext_to_der(-1, invalid_date, out, outlen) < 0 + || x509_cert_issuer_ext_to_der(X509_critical, cert_issuer, cert_issuer_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_exts_get(const uint8_t *d, size_t dlen, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len) +{ + int oid; + int critical; + *reason = -1; + *invalid_date = -1; + *cert_issuer = NULL; + *cert_issuer_len = 0; + + while (dlen) { + if (x509_crl_entry_ext_from_der_ex(&oid, &critical, reason, invalid_date, cert_issuer, cert_issuer_len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_entry_ext_critical_check(oid, critical) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_crl_entry_exts_from_der( + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret = 0; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (!d || !dlen) { + error_print(); + return -1; + } + if (x509_crl_entry_exts_get(d, dlen, reason, invalid_date, cert_issuer, cert_issuer_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_exts_check(const uint8_t *d, size_t dlen) +{ + int oid; + int critical; + int reason = -1; + time_t invalid_date = -1; + const uint8_t *cert_issuer = NULL; + size_t cert_issuer_len = 0; + + while (dlen) { + if (x509_crl_entry_ext_from_der_ex(&oid, &critical, + &reason, &invalid_date, &cert_issuer, &cert_issuer_len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_entry_ext_critical_check(oid, critical) != 1) { + error_print(); + return -1; + } + if (cert_issuer) { + error_print(); + //return -1; // currently cert_issuer can not be processed + } + } + return 1; +} + +int x509_crl_entry_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_crl_entry_ext_print(fp, fmt, ind, "Extension", p, len); + } + return 1; +} + +int x509_revoked_cert_to_der( + const uint8_t *serial, size_t serial_len, time_t revoke_date, + const uint8_t *crl_entry_exts, size_t crl_entry_exts_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (serial_len == 0 && revoke_date == -1 && crl_entry_exts_len == 0) { + return 0; + } + if (asn1_integer_to_der(serial, serial_len, NULL, &len) != 1 + || asn1_generalized_time_to_der(revoke_date, NULL, &len) != 1 + || asn1_sequence_to_der(crl_entry_exts, crl_entry_exts_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(serial, serial_len, out, outlen) != 1 + || asn1_generalized_time_to_der(revoke_date, out, outlen) != 1 + || asn1_sequence_to_der(crl_entry_exts, crl_entry_exts_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_revoked_cert_to_der_ex( + const uint8_t *serial, size_t serial_len, time_t revoke_date, + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (serial_len ==0 && revoke_date == -1 + && reason == -1 && invalid_date == -1 && cert_issuer_len == 0) { + return 0; + } + if (asn1_integer_to_der(serial, serial_len, NULL, &len) != 1 + || asn1_generalized_time_to_der(revoke_date, NULL, &len) != 1 + || x509_crl_entry_exts_to_der(reason, invalid_date, cert_issuer, cert_issuer_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(serial, serial_len, out, outlen) != 1 + || asn1_generalized_time_to_der(revoke_date, out, outlen) != 1 + || x509_crl_entry_exts_to_der(reason, invalid_date, cert_issuer, cert_issuer_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_revoked_cert_from_der( + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 + || x509_time_from_der(revoke_date, &d, &dlen) != 1 + || asn1_sequence_from_der(crl_entry_exts, crl_entry_exts_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_revoked_cert_from_der_ex( + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *crl_entry_exts; + size_t crl_entry_exts_len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 + || x509_time_from_der(revoke_date, &d, &dlen) != 1 + || asn1_sequence_from_der(&crl_entry_exts, &crl_entry_exts_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_entry_exts_get(crl_entry_exts, crl_entry_exts_len, + reason, invalid_date, cert_issuer, cert_issuer_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_revoked_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + time_t tv; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "userCertificate", p, len); + if (x509_time_from_der(&tv, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "revocationDate: %s", ctime(&tv)); + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_crl_entry_exts_print(fp, fmt, ind, "crlEntryExtensions", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_cert_revoke_to_der(const uint8_t *cert, size_t certlen, + time_t revoke_date, int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen) +{ + const uint8_t *serial; + size_t serial_len; + + if (x509_cert_get_issuer_and_serial_number(cert, certlen, NULL, 0, &serial, &serial_len) != 1 + || x509_revoked_cert_to_der_ex(serial, serial_len, revoke_date, + reason, invalid_date, cert_issuer, cert_issuer_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_revoked_certs_find_revoked_cert_by_serial_number(const uint8_t *d, size_t dlen, + const uint8_t *serial, size_t serial_len, + time_t *revoke_date, const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len) +{ + const uint8_t *sn; + size_t sn_len; + + while (dlen) { + if (x509_revoked_cert_from_der(&sn, &sn_len, revoke_date, + crl_entry_exts, crl_entry_exts_len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (sn_len == serial_len && memcmp(sn, serial, serial_len) == 0) { + return 1; + } + } + *revoke_date = -1; + *crl_entry_exts = NULL; + *crl_entry_exts_len = 0; + return 0; +} + +int x509_revoked_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_revoked_cert_print(fp, fmt, ind, "RevokedCertificate", p, len); + } + return 1; +} + + +// CRL Extensions +static uint32_t oid_ce_authority_key_identifier[] = { oid_ce,35 }; +static uint32_t oid_ce_issuer_alt_name[] = { oid_ce,18 }; +static uint32_t oid_ce_crl_number[] = { oid_ce,20 }; +static uint32_t oid_ce_delta_crl_indicator[] = { oid_ce,27 }; +static uint32_t oid_ce_issuing_distribution_point[] = { oid_ce,28 }; +static uint32_t oid_ce_freshest_crl[] = { oid_ce,46 }; +static uint32_t oid_pe_authority_info_access[] = { oid_pe,1 }; + +static const ASN1_OID_INFO x509_crl_exts[] = { + { OID_ce_authority_key_identifier, "AuthorityKeyIdentifier", oid_ce_authority_key_identifier, oid_cnt(oid_ce_authority_key_identifier) }, + { OID_ce_issuer_alt_name, "IssuerAltName", oid_ce_issuer_alt_name, oid_cnt(oid_ce_issuer_alt_name) }, + { OID_ce_crl_number, "CRLNumber", oid_ce_crl_number, oid_cnt(oid_ce_crl_number) }, + { OID_ce_delta_crl_indicator, "DeltaCRLIndicator", oid_ce_delta_crl_indicator, oid_cnt(oid_ce_delta_crl_indicator) }, + { OID_ce_issuing_distribution_point, "IssuingDistributionPoint", oid_ce_issuing_distribution_point, oid_cnt(oid_ce_issuing_distribution_point) }, + { OID_ce_freshest_crl, "FreshestCRL", oid_ce_freshest_crl, oid_cnt(oid_ce_freshest_crl) }, + { OID_pe_authority_info_access, "AuthorityInfoAccess", oid_pe_authority_info_access, oid_cnt(oid_pe_authority_info_access) }, +}; + +static const int x509_crl_exts_count = + sizeof(x509_crl_exts)/sizeof(x509_crl_exts[0]); + +const char *x509_crl_ext_id_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid))) { + return NULL; + } + return info->name; +} + +int x509_crl_ext_id_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_crl_exts, x509_crl_exts_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_crl_ext_id_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid)) + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_ext_id_from_der_ex(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + + *oid = 0; + if ((ret = asn1_oid_info_from_der_ex(&info, nodes, nodes_cnt, x509_crl_exts, x509_crl_exts_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (info) { + *oid = info->oid; + } + return ret; +} + +int x509_crl_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + uint32_t nodes[32]; + size_t nodes_cnt; + + if ((ret = x509_crl_ext_id_from_der_ex(oid, nodes, &nodes_cnt, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*oid == OID_undef) { + error_print(); + return -1; + } + return 1; +} + +int x509_issuing_distribution_point_to_der( + const char *dist_point_uri, size_t dist_point_uri_len, + int only_contains_user_certs, + int only_contains_ca_certs, + int only_some_reasons, + int indirect_crl, + int only_contains_attr_certs, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (dist_point_uri_len == 0 + && only_contains_user_certs == -1 + && only_contains_ca_certs == -1 + && only_some_reasons == -1 + && indirect_crl == -1 + && only_contains_attr_certs == -1) { + return 0; + } + if (x509_uri_as_explicit_distribution_point_name_to_der(0, dist_point_uri, dist_point_uri_len, NULL, &len) < 0 + || asn1_implicit_boolean_to_der(1, only_contains_user_certs, NULL, &len) < 0 + || asn1_implicit_boolean_to_der(2, only_contains_ca_certs, NULL, &len) < 0 + || asn1_implicit_bits_to_der(3, only_some_reasons, NULL, &len) < 0 // TODO: 特化的类型 + || asn1_implicit_boolean_to_der(4, indirect_crl, NULL, &len) < 0 + || asn1_implicit_boolean_to_der(5, only_contains_attr_certs, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_uri_as_explicit_distribution_point_name_to_der(0, dist_point_uri, dist_point_uri_len, out, outlen) < 0 + || asn1_implicit_boolean_to_der(1, only_contains_user_certs, out, outlen) < 0 + || asn1_implicit_boolean_to_der(2, only_contains_ca_certs, out, outlen) < 0 + || asn1_implicit_bits_to_der(3, only_some_reasons, out, outlen) < 0 // TODO: 特化的类型 + || asn1_implicit_boolean_to_der(4, indirect_crl, out, outlen) < 0 + || asn1_implicit_boolean_to_der(5, only_contains_attr_certs, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_issuing_distribution_point_from_der( + int *dist_point_choice, const uint8_t **dist_point, size_t *dist_point_len, + int *only_contains_user_certs, + int *only_contains_ca_certs, + int *only_some_reasons, + int *indirect_crl, + int *only_contains_attr_certs, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *a; + size_t alen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_explicit_from_der(0, &a, &alen, &d, &dlen) < 0 + || asn1_implicit_boolean_from_der(1, only_contains_user_certs, &d, &dlen) < 0 + || asn1_implicit_boolean_from_der(2, only_contains_ca_certs, &d, &dlen) < 0 + || asn1_implicit_bits_from_der(3, only_some_reasons, &d, &dlen) < 0 + || asn1_implicit_boolean_from_der(4, indirect_crl, &d, &dlen) < 0 + || asn1_implicit_boolean_from_der(5, only_contains_attr_certs, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (x509_distribution_point_name_from_der(dist_point_choice, dist_point, dist_point_len, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_issuing_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_explicit_from_der(0, &p, &len, &d, &dlen)) < 0) goto end; + if (ret) x509_distribution_point_name_print(fp, fmt, ind, "distributionPoint", p, len); + if ((ret = asn1_implicit_boolean_from_der(1, &val, &d, &dlen)) < 0) goto end; + if (!ret) val = 0; + format_print(fp, fmt, ind, "onlyContainsUserCerts: %s\n", asn1_boolean_name(val)); + if ((ret = asn1_implicit_boolean_from_der(2, &val, &d, &dlen)) < 0) goto end; + if (!ret) val = 0; + format_print(fp, fmt, ind, "onlyContainsCACerts: %s\n", asn1_boolean_name(val)); + if ((ret = asn1_implicit_bits_from_der(3, &val, &d, &dlen)) < 0) goto end; + if (ret) x509_revoke_reason_flags_print(fp, fmt, ind, "onlySomeReasons", val); + if ((ret = asn1_implicit_boolean_from_der(4, &val, &d, &dlen)) < 0) goto end; + if (!ret) val = 0; + format_print(fp, fmt, ind, "indirectCRL: %s\n", asn1_boolean_name(val)); + if ((ret = asn1_implicit_boolean_from_der(5, &val, &d, &dlen)) < 0) goto end; + if (!ret) val = 0; + format_print(fp, fmt, ind, "onlyContainsAttributeCerts: %s\n", asn1_boolean_name(val)); + if (asn1_length_is_zero(dlen) != 1) goto end; + return 1; +end: + error_print(); + return -1; +} + +int x509_crl_ext_critical_check(int oid, int critical) +{ + switch (oid) { + // MUST be critical + case OID_ce_delta_crl_indicator: + case OID_ce_issuing_distribution_point: + if (critical != X509_critical) { + error_print(); + return -1; + } + break; + // critical or non-critical + case OID_ce_authority_key_identifier: + break; + // SHOULD be non-critical + case OID_ce_issuer_alt_name: + if (critical == X509_critical) { + error_print(); + return 0; + } + break; + // MUST be non-critical + case OID_ce_crl_number: + case OID_ce_freshest_crl: + case OID_pe_authority_info_access: + default: + if (critical == X509_critical) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_crl_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (vlen == 0) { + return 0; + } + if (x509_crl_ext_id_to_der(oid, NULL, &len) != 1 + || asn1_boolean_to_der(critical, NULL, &len) < 0 + || asn1_octet_string_to_der(val, vlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_crl_ext_id_to_der(oid, out, outlen) != 1 + || asn1_boolean_to_der(critical, out, outlen) < 0 + || asn1_octet_string_to_der(val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_ext_from_der_ex(int *oid, uint32_t *nodes, size_t *nodes_cnt, + int *critical, const uint8_t **val, size_t *vlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_crl_ext_id_from_der_ex(oid, nodes, nodes_cnt, &d, &dlen) != 1 + || asn1_boolean_from_der(critical, &d, &dlen) < 0 + || asn1_octet_string_from_der(val, vlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, oid, critical; + const char *name; + const uint8_t *v; + size_t vlen; + const uint8_t *p; + size_t len; + uint32_t nodes[32]; + size_t nodes_cnt; + int num; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_crl_ext_id_from_der_ex(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "extnID", x509_crl_ext_id_name(oid), nodes, nodes_cnt); + if ((ret = asn1_boolean_from_der(&critical, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "critical: %s\n", asn1_boolean_name(critical)); + if (asn1_octet_string_from_der(&v, &vlen, &d, &dlen) != 1) goto err; + + switch (oid) { + case OID_ce_authority_key_identifier: + case OID_ce_issuer_alt_name: + case OID_ce_issuing_distribution_point: + case OID_ce_freshest_crl: + case OID_pe_authority_info_access: + if (asn1_sequence_from_der(&p, &len, &v, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_crl_number: + case OID_ce_delta_crl_indicator: + if (asn1_int_from_der(&num, &v, &vlen) != 1) { + error_print(); + return -1; + } + break; + default: + if (asn1_any_from_der(&p, &len, &v, &vlen) != 1) { + error_print(); + return -1; + } + } + + name = x509_crl_ext_id_name(oid); + + switch (oid) { + case OID_ce_authority_key_identifier: x509_authority_key_identifier_print(fp, fmt, ind, name, p, len); break; + case OID_ce_issuer_alt_name: x509_general_names_print(fp, fmt, ind, name, p, len); break; + case OID_ce_crl_number: format_print(fp, fmt, ind, "%s: %d\n", name, num); break; + case OID_ce_delta_crl_indicator: format_print(fp, fmt, ind, "%s: %d\n", name, num); break; + case OID_ce_issuing_distribution_point: x509_issuing_distribution_point_print(fp, fmt, ind, name, p, len); break; + case OID_ce_freshest_crl: x509_crl_distribution_points_print(fp, fmt, ind, name, p, len); break; + case OID_pe_authority_info_access: x509_authority_info_access_print(fp, fmt, ind, name, p, len); break; + default: format_bytes(fp, fmt, ind, "value", p, len); + } + if (asn1_length_is_zero(vlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_crl_exts_add_authority_key_identifier( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len) +{ + int ret; + if ((ret = x509_exts_add_authority_key_identifier(exts, extslen, maxlen, critical, + keyid, keyid_len, issuer, issuer_len, serial, serial_len)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_crl_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + const SM2_KEY *public_key) +{ + int ret; + if ((ret = x509_exts_add_default_authority_key_identifier(exts, extslen, maxlen, public_key)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_crl_exts_add_issuer_alt_name( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *d, size_t dlen) +{ + int ret; + if ((ret = x509_exts_add_issuer_alt_name(exts, extslen, maxlen, critical, d, dlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_crl_exts_add_crl_number_ex( + uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, int num) +{ + size_t curlen = *extslen; + uint8_t val[32]; + uint8_t *p = val; + size_t vlen = 0; + + if (num < 0) { + return 0; + } + + exts += *extslen; + if (asn1_int_to_der(num, &p, &vlen) != 1 + || x509_crl_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_crl_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_crl_number( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int num) +{ + int oid = OID_ce_crl_number; + int ret; + + if ((ret = x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_crl_exts_add_delta_crl_indicator( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + int num) +{ + int oid = OID_ce_delta_crl_indicator; + int ret; + + if ((ret = x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_crl_exts_add_issuing_distribution_point( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const char *dist_point_uri, size_t dist_point_uri_len, + int only_contains_user_certs, + int only_contains_ca_certs, + int only_some_reasons, + int indirect_crl, + int only_contains_attr_certs) +{ + int oid = OID_ce_issuing_distribution_point; + int ret; + size_t curlen = *extslen; + uint8_t val[512]; + size_t vlen = 0; + uint8_t *p = val; + size_t len = 0; + + if ((ret = x509_issuing_distribution_point_to_der( + dist_point_uri, dist_point_uri_len, + only_contains_user_certs, + only_contains_ca_certs, + only_some_reasons, + indirect_crl, + only_contains_attr_certs, NULL, &len)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (len > sizeof(val)) { + error_print(); + return -1; + } + if (x509_issuing_distribution_point_to_der( + dist_point_uri, dist_point_uri_len, + only_contains_user_certs, + only_contains_ca_certs, + only_some_reasons, + indirect_crl, + only_contains_attr_certs, &p, &vlen) != 1) { + error_print(); + return -1; + } + exts += *extslen; + if (x509_crl_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_crl_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_freshest_crl( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen) +{ + int oid = OID_ce_freshest_crl; + int ret; + if ((ret = x509_exts_add_crl_distribution_points_ex(exts, extslen, maxlen, + oid, critical, http_uri, http_urilen, ldap_uri, ldap_urilen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_crl_exts_add_authority_info_acess( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *ca_issuers_uri, size_t ca_issuers_urilen, const char *ocsp_uri, size_t ocsp_urilen) +{ + int ret; + if ((ret = x509_exts_add_authority_info_access(exts, extslen, maxlen, critical, + ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_crl_exts_check(const uint8_t *d, size_t dlen) +{ + int oid; + uint32_t nodes[32]; + size_t nodes_cnt; + int critical; + const uint8_t *val; + size_t vlen; + + while (dlen) { + if (x509_crl_ext_from_der_ex(&oid, nodes, &nodes_cnt, &critical, &val, &vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_ext_critical_check(oid, critical) != 1) { + error_print(); + return -1; + } + if (critical == X509_critical) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_crl_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_crl_ext_print(fp, fmt, ind, "Extension", p, len); + } + return 1; +} + +int x509_tbs_crl_to_der( + int version, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t this_update, time_t next_update, + const uint8_t *revoked_certs, size_t revoked_certs_len, + const uint8_t *exts, size_t exts_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_int_to_der(version, NULL, &len) < 0 + || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 + || x509_name_to_der(issuer, issuer_len, NULL, &len) != 1 + || x509_time_to_der(this_update, NULL, &len) != 1 + || x509_time_to_der(next_update, NULL, &len) < 0 + || asn1_sequence_to_der(revoked_certs, revoked_certs_len, NULL, &len) < 0 + || x509_explicit_exts_to_der(0, exts, exts_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) < 0 + || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 + || x509_name_to_der(issuer, issuer_len, out, outlen) != 1 + || x509_time_to_der(this_update, out, outlen) != 1 + || x509_time_to_der(next_update, out, outlen) < 0 + || asn1_sequence_to_der(revoked_certs, revoked_certs_len, out, outlen) < 0 + || x509_explicit_exts_to_der(0, exts, exts_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_tbs_crl_from_der( + int *version, + int *signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, + time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + const uint8_t **exts, size_t *exts_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) < 0 + || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 + || x509_name_from_der(issuer, issuer_len, &d, &dlen) != 1 + || x509_time_from_der(this_update, &d, &dlen) != 1 + || x509_time_from_der(next_update, &d, &dlen) < 0 + || asn1_sequence_from_der(revoked_certs, revoked_certs_len, &d, &dlen) < 0 + || x509_explicit_exts_from_der(0, exts, exts_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (*version >= 0 && *version != X509_version_v2) { + error_print(); + return -1; + } + if (*revoked_certs && *version != X509_version_v2) { + error_print(); + return -1; + } + if (*exts && *version != X509_version_v2) { + error_print(); + return -1; + } + + return 1; +} + +int x509_tbs_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + time_t tv; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "version: %s (%d)\n", x509_version_name(val), val); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "signature", p, len); + if (x509_name_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "issuer", p, len); + if (x509_time_from_der(&tv, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "thisUpdate: %s", ctime(&tv)); + if ((ret = x509_time_from_der(&tv, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "nextUpdate: %s", ctime(&tv)); + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_revoked_certs_print(fp, fmt, ind, "revokedCertificates", p, len); + if ((ret = x509_explicit_exts_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) { + x509_crl_exts_print(fp, fmt, ind, "crlExtensions", p, len); + } + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +static int x509_cert_list_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_tbs_crl_print(fp, fmt, ind, "tbsCertList", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "signatureValue", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_crl_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen) +{ + if (x509_crl_get_issuer(a, alen, NULL, NULL) != 1) { + error_print(); + return -1; + } + if (asn1_any_to_der(a, alen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = asn1_any_from_der(a, alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_crl_get_issuer(*a, *alen, NULL, NULL) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + const uint8_t *d; + size_t dlen; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + x509_cert_list_print(fp, fmt, ind, label, d, dlen); + return 1; +} + +int x509_crl_sign_to_der( + int version, int sig_alg, + const uint8_t *issuer, size_t issuer_len, + time_t this_update, time_t next_update, + const uint8_t *revoked_certs, size_t revoked_certs_len, + const uint8_t *crl_exts, size_t crl_exts_len, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + uint8_t *tbs; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen = SM2_signature_typical_size; + + if (sig_alg != OID_sm2sign_with_sm3) { + error_print(); + return -1; + } + + if (x509_tbs_crl_to_der(version, sig_alg, issuer, issuer_len, + this_update, next_update, revoked_certs, revoked_certs_len, + crl_exts, crl_exts_len, NULL, &len) != 1 + || x509_signature_algor_to_der(sig_alg, NULL, &len) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + if (out && *out) { + tbs = *out; + } + if (x509_tbs_crl_to_der(version, sig_alg, issuer, issuer_len, + this_update, next_update, revoked_certs, revoked_certs_len, + crl_exts, crl_exts_len, out, outlen) != 1) { + error_print(); + return -1; + } + if (out && *out) { + SM2_SIGN_CTX sign_ctx; + if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 + || sm2_sign_update(&sign_ctx, tbs, *out - tbs) != 1 + || sm2_sign_finish_fixlen(&sign_ctx, siglen, sig) != 1) { + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + error_print(); + return -1; + } + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + } + if (x509_signature_algor_to_der(sig_alg, out, outlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_from_der_ex( + int *version, + int *inner_sig_alg, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + const uint8_t **exts, size_t *exts_len, + int *sig_alg, const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *tbs; + size_t tbs_len; + + if ((ret = x509_signed_from_der(&tbs, &tbs_len, sig_alg, sig, siglen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_tbs_crl_from_der(version, inner_sig_alg, issuer, issuer_len, + this_update, next_update, revoked_certs, revoked_certs_len, + exts, exts_len, &tbs, &tbs_len) != 1 + || asn1_length_is_zero(tbs_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_verify_by_ca_cert(const uint8_t *a, size_t alen, + const uint8_t *cert, size_t certlen, const char *signer_id, size_t signer_id_len) +{ + const uint8_t *crl_issuer; + size_t crl_issuer_len; + const uint8_t *ca_subject; + size_t ca_subject_len; + + if (x509_crl_get_issuer(a, alen, &crl_issuer, &crl_issuer_len) != 1 + || x509_cert_get_subject(cert, certlen, &ca_subject, &ca_subject_len) != 1) { + error_print(); + return -1; + } + if (x509_name_equ(crl_issuer, crl_issuer_len, ca_subject, ca_subject_len) != 1) { + error_print(); + return -1; + } + if (x509_signed_verify_by_ca_cert(a, alen, cert, certlen, signer_id, signer_id_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_get_details(const uint8_t *a, size_t alen, + int *version, int *inner_sig_alg, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + const uint8_t **exts, size_t *exts_len, + int *sig_alg, const uint8_t **sig, size_t *siglen) +{ + const uint8_t *crl_tbs; + size_t crl_tbslen; + int crl_sig_alg; + const uint8_t *crl_sig; + size_t crl_siglen; + + struct { + int version; + int sig_alg; + const uint8_t *issuer; size_t issuer_len; + time_t this_update; time_t next_update; + const uint8_t *revoked_certs; size_t revoked_certs_len; + const uint8_t *exts; size_t exts_len; + } tbs; + + if (x509_signed_from_der(&crl_tbs, &crl_tbslen, &crl_sig_alg, &crl_sig, &crl_siglen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + if (x509_tbs_crl_from_der( + &tbs.version, &tbs.sig_alg, + &tbs.issuer, &tbs.issuer_len, + &tbs.this_update, &tbs.next_update, + &tbs.revoked_certs, &tbs.revoked_certs_len, + &tbs.exts, &tbs.exts_len, &crl_tbs, &crl_tbslen) != 1 + || asn1_length_is_zero(crl_tbslen) != 1) { + error_print(); + return -1; + } + + if (version) *version = tbs.version; + if (inner_sig_alg) *inner_sig_alg = tbs.sig_alg; + if (issuer) *issuer = tbs.issuer; + if (issuer_len) *issuer_len = tbs.issuer_len; + if (this_update) *this_update = tbs.this_update; + if (next_update) *next_update = tbs.next_update; + if (revoked_certs) *revoked_certs = tbs.revoked_certs; + if (revoked_certs_len) *revoked_certs_len = tbs.revoked_certs_len; + if (exts) *exts = tbs.exts; + if (exts_len) *exts_len = tbs.exts_len; + if (sig_alg) *sig_alg = crl_sig_alg; + if (sig) *sig = crl_sig; + if (siglen) *siglen = crl_siglen; + return 1; +} + +int x509_crl_check(const uint8_t *a, size_t alen, time_t now) +{ + int version; + int inner_sig_alg; + const uint8_t *issuer; + size_t issuer_len; + time_t this_update; + time_t next_update; + const uint8_t *exts; + size_t exts_len; + int sig_alg; + + if (x509_crl_get_details(a, alen, &version, &inner_sig_alg, + &issuer, &issuer_len, &this_update, &next_update, + NULL, NULL, &exts, &exts_len, &sig_alg, NULL, NULL) != 1) { + error_print(); + return -1; + } + if (inner_sig_alg != sig_alg) { + error_print(); + return -1; + } + if (version != X509_version_v1 && version != X509_version_v2) { + error_print(); + return -1; + } + // this_update <= now < next_update + if (now < this_update) { + error_print(); + return -1; + } + if (next_update >= 0) { + if (now >= next_update) { + error_print(); + return -1; + } + } + if (x509_crl_exts_check(exts, exts_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_get_issuer(const uint8_t *crl, size_t crl_len, + const uint8_t **issuer, size_t *issuer_len) +{ + if (x509_crl_get_details(crl, crl_len, + NULL, // version + NULL, // sig_alg + issuer, issuer_len, // issuer, issuer_len + NULL, NULL, // this_udpate, next_update + NULL, NULL, // revoked_certs, revoked_certs_len + NULL, NULL, // exts, exts_len, + NULL, NULL, NULL // sig_alg, sig, siglen + ) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_get_revoked_certs(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen) +{ + if (x509_crl_get_details(a, alen, + NULL, // version + NULL, // sig_alg + NULL, NULL, // issuer, issuer_len + NULL, NULL, // this_udpate, next_update + d, dlen, // revoked_certs, revoked_certs_len + NULL, NULL, // exts, exts_len + NULL, NULL, NULL // sig_alg, sig, siglen + ) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_find_revoked_cert_by_serial_number(const uint8_t *a, size_t alen, + const uint8_t *serial, size_t serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if (x509_crl_get_revoked_certs(a, alen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if ((ret = x509_revoked_certs_find_revoked_cert_by_serial_number(d, dlen, serial, serial_len, + revoke_date, crl_entry_exts, crl_entry_exts_len)) < 0) { + error_print(); + return -1; + } + return ret; +} + +int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_cert_list_print(fp, fmt, ind, "CertificateRevocationList", p, len); + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/x509_ext.c b/Core/GmSSL-3.1.1/src/x509_ext.c new file mode 100644 index 0000000..e27d1f5 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/x509_ext.c @@ -0,0 +1,3252 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static uint32_t oid_ce_subject_directory_attributes[] = { oid_ce,9 }; +static uint32_t oid_ce_subject_key_identifier[] = { oid_ce,14 }; +static uint32_t oid_ce_key_usage[] = { oid_ce,15 }; +static uint32_t oid_ce_subject_alt_name[] = { oid_ce,17 }; +static uint32_t oid_ce_issuer_alt_name[] = { oid_ce,18 }; +static uint32_t oid_ce_basic_constraints[] = { oid_ce,19 }; +static uint32_t oid_ce_name_constraints[] = { oid_ce,30 }; +static uint32_t oid_ce_crl_distribution_points[] = { oid_ce,31 }; +static uint32_t oid_ce_certificate_policies[] = { oid_ce,32 }; +static uint32_t oid_ce_policy_mappings[] = { oid_ce,33 }; +static uint32_t oid_ce_authority_key_identifier[] = { oid_ce,35 }; +static uint32_t oid_ce_policy_constraints[] = { oid_ce,36 }; +static uint32_t oid_ce_ext_key_usage[] = { oid_ce,37 }; +static uint32_t oid_ce_freshest_crl[] = { oid_ce,46 }; +static uint32_t oid_ce_inhibit_any_policy[] = { oid_ce,54 }; +static uint32_t oid_ce_crl_reasons[] = { oid_ce,21 }; // crl_entry_ext +static uint32_t oid_ce_invalidity_date[] = { oid_ce,24 }; // crl_entry_ext +static uint32_t oid_ce_certificate_issuer[] = { oid_ce,29 }; // crl_entry_ext +#define OID_CE_CNT sizeof(oid_ce_subject_directory_attributes)/sizeof(int) +static uint32_t oid_netscape_cert_type[] = { 2,16,840,1,113730,1,1 }; +static uint32_t oid_netscape_cert_comment[] = { 2,16,840,1,113730,1,13 }; +static uint32_t oid_pe_authority_info_access[] = { 1,3,6,1,5,5,7,1,1 }; +static uint32_t oid_ct_precertificate_scts[] = { 1,3,6,1,4,1,11129,2,4,2 }; + +static const ASN1_OID_INFO x509_ext_ids[] = { + { OID_ce_authority_key_identifier, "AuthorityKeyIdentifier", oid_ce_authority_key_identifier, OID_CE_CNT }, + { OID_ce_subject_key_identifier, "SubjectKeyIdentifier", oid_ce_subject_key_identifier, OID_CE_CNT }, + { OID_ce_key_usage, "KeyUsage", oid_ce_key_usage, OID_CE_CNT }, + { OID_ce_certificate_policies, "CertificatePolicies", oid_ce_certificate_policies, OID_CE_CNT }, + { OID_ce_policy_mappings, "PolicyMappings", oid_ce_policy_mappings, OID_CE_CNT }, + { OID_ce_subject_alt_name, "SubjectAltName", oid_ce_subject_alt_name, OID_CE_CNT }, + { OID_ce_issuer_alt_name, "IssuerAltName", oid_ce_issuer_alt_name, OID_CE_CNT }, + { OID_ce_subject_directory_attributes, "SubjectDirectoryAttributes", oid_ce_subject_directory_attributes, OID_CE_CNT }, + { OID_ce_basic_constraints, "BasicConstraints", oid_ce_basic_constraints, OID_CE_CNT }, + { OID_ce_name_constraints, "NameConstraints", oid_ce_name_constraints, OID_CE_CNT }, + { OID_ce_policy_constraints, "PolicyConstraints", oid_ce_policy_constraints, OID_CE_CNT }, + { OID_ce_ext_key_usage, "ExtKeyUsage", oid_ce_ext_key_usage, OID_CE_CNT }, + { OID_ce_crl_distribution_points, "CRLDistributionPoints", oid_ce_crl_distribution_points, OID_CE_CNT }, + { OID_ce_inhibit_any_policy, "InhibitAnyPolicy", oid_ce_inhibit_any_policy, OID_CE_CNT }, + { OID_ce_freshest_crl, "FreshestCRL", oid_ce_freshest_crl, OID_CE_CNT }, + { OID_ce_crl_reasons, "CRLReasons", oid_ce_crl_reasons, OID_CE_CNT }, + { OID_ce_invalidity_date, "InvalidityDate", oid_ce_invalidity_date, OID_CE_CNT }, + { OID_ce_certificate_issuer, "CertificateIssuer", oid_ce_certificate_issuer, OID_CE_CNT }, + { OID_netscape_cert_type, "NetscapeCertType", oid_netscape_cert_type, sizeof(oid_netscape_cert_type)/sizeof(int) }, + { OID_netscape_cert_comment, "NetscapeCertComment", oid_netscape_cert_comment, sizeof(oid_netscape_cert_comment)/sizeof(int) }, + { OID_pe_authority_info_access, "AuthorityInformationAccess", oid_pe_authority_info_access, sizeof(oid_pe_authority_info_access)/sizeof(int) }, + { OID_ct_precertificate_scts, "CT-PrecertificateSCTs", oid_ct_precertificate_scts, sizeof(oid_ct_precertificate_scts)/sizeof(int) }, +}; + +static const int x509_ext_ids_count = + sizeof(x509_ext_ids)/sizeof(x509_ext_ids[0]); + +const char *x509_ext_id_name(int oid) +{ + const ASN1_OID_INFO *info; + if (oid == 0) { + return NULL; + } + if (!(info = asn1_oid_info_from_oid(x509_ext_ids, x509_ext_ids_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_ext_id_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_ext_ids, x509_ext_ids_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_ext_id_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_ext_ids, x509_ext_ids_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +// 如果要支持未知的ext_id,应该提供一个callback +int x509_ext_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + + if ((ret = asn1_oid_info_from_der_ex(&info, nodes, nodes_cnt, x509_ext_ids, x509_ext_ids_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info ? info->oid : 0; + return 1; +} + +int x509_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (vlen == 0) { + return 0; + } + if (x509_ext_id_to_der(oid, NULL, &len) != 1 + || asn1_boolean_to_der(critical, NULL, &len) < 0 + || asn1_octet_string_to_der(val, vlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_ext_id_to_der(oid, out, outlen) != 1 + || asn1_boolean_to_der(critical, out, outlen) < 0 + || asn1_octet_string_to_der(val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_ext_to_der_ex(int oid, int critical, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + size_t vlen = 0; + size_t len = 0; + + if (dlen == 0) { + return 0; + } + if (asn1_sequence_to_der(d, dlen, NULL, &vlen) != 1) { + error_print(); + return -1; + } + if (x509_ext_id_to_der(oid, NULL, &len) != 1 + || asn1_boolean_to_der(critical, NULL, &len) < 0 + || asn1_tag_to_der(ASN1_TAG_OCTET_STRING, NULL, &len) != 1 + || asn1_length_to_der(vlen, NULL, &len) != 1 + || asn1_sequence_to_der(d, dlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_ext_id_to_der(oid, out, outlen) != 1 + || asn1_boolean_to_der(critical, out, outlen) < 0 + || asn1_tag_to_der(ASN1_TAG_OCTET_STRING, out, outlen) != 1 + || asn1_length_to_der(vlen, out, outlen) != 1 + || asn1_sequence_to_der(d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_ext_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, + int *critical, const uint8_t **val, size_t *vlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_ext_id_from_der(oid, nodes, nodes_cnt, &d, &dlen) != 1 + || asn1_boolean_from_der(critical, &d, &dlen) < 0 + || asn1_octet_string_from_der(val, vlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, oid, critical; + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *val; + size_t vlen; + + const uint8_t *p; + size_t len; + int ival; + const char *name; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if (x509_ext_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "extnID", x509_ext_id_name(oid), nodes, nodes_cnt); + if ((ret = asn1_boolean_from_der(&critical, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "critical: %s\n", asn1_boolean_name(critical)); + if (asn1_octet_string_from_der(&val, &vlen, &d, &dlen) != 1) goto err; + + switch (oid) { + case OID_ce_subject_key_identifier: + if (asn1_octet_string_from_der(&p, &len, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_key_usage: + case OID_netscape_cert_type: + if (asn1_bits_from_der(&ival, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_inhibit_any_policy: + if (asn1_int_from_der(&ival, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_netscape_cert_comment: + if (asn1_ia5_string_from_der((const char **)&p, &len, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ct_precertificate_scts: + case OID_undef: + p = val; + len = vlen; + vlen = 0; + break; + default: + if (asn1_sequence_from_der(&p, &len, &val, &vlen) != 1) { + error_print(); + return -1; + } + } + if (asn1_length_is_zero(vlen) != 1) { + error_print(); + return -1; + } + + name = x509_ext_id_name(oid); + + switch (oid) { + case OID_ce_authority_key_identifier: return x509_authority_key_identifier_print(fp, fmt, ind, name, p, len); + case OID_ce_subject_key_identifier: return format_bytes(fp, fmt, ind, name, p, len); + case OID_ce_key_usage: return x509_key_usage_print(fp, fmt, ind, name, ival); + case OID_ce_certificate_policies: return x509_certificate_policies_print(fp, fmt, ind, name, p, len); + case OID_ce_policy_mappings: return x509_policy_mappings_print(fp, fmt, ind, name, p, len); + case OID_ce_subject_alt_name: return x509_general_names_print(fp, fmt, ind, name, p, len); + case OID_ce_issuer_alt_name: return x509_general_names_print(fp, fmt, ind, name, p, len); + case OID_ce_subject_directory_attributes: return x509_attributes_print(fp, fmt, ind, name, p, len); + case OID_ce_basic_constraints: return x509_basic_constraints_print(fp, fmt, ind, name, p, len); + case OID_ce_name_constraints: return x509_name_constraints_print(fp, fmt, ind, name, p, len); + case OID_ce_policy_constraints: return x509_policy_constraints_print(fp, fmt, ind, name, p, len); + case OID_ce_ext_key_usage: return x509_ext_key_usage_print(fp, fmt, ind, name, p, len); + case OID_ce_crl_distribution_points: return x509_crl_distribution_points_print(fp, fmt, ind, name, p, len); + case OID_ce_inhibit_any_policy: format_print(fp, fmt, ind, "%s: %d\n", name, ival); + case OID_ce_freshest_crl: return x509_freshest_crl_print(fp, fmt, ind, name, p, len); + case OID_netscape_cert_type: return x509_netscape_cert_type_print(fp, fmt, ind, name, ival); + case OID_netscape_cert_comment: return format_string(fp, fmt, ind, name, p, len); + case OID_pe_authority_info_access: return x509_authority_info_access_print(fp, fmt, ind, name, p, len); + default: format_bytes(fp, fmt, ind, "extnValue", p, len); + } + return 1; +err: + error_print(); + return -1; +} + +int x509_exts_add_sequence(uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, const uint8_t *d, size_t dlen) +{ + size_t curlen = *extslen; + + if (dlen == 0) { + return 0; + } + exts += *extslen; + if (x509_ext_to_der_ex(oid, critical, d, dlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der_ex(oid, critical, d, dlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len) +{ + int oid = OID_ce_authority_key_identifier; + size_t curlen = *extslen; + uint8_t val[512]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; + + if (keyid_len == 0 && issuer_len == 0 && serial_len == 0) { + return 0; + } + exts += *extslen; + if (x509_authority_key_identifier_to_der( + keyid, keyid_len, + issuer, issuer_len, + serial, serial_len, + NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_authority_key_identifier_to_der( + keyid, keyid_len, + issuer, issuer_len, + serial, serial_len, + &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + const SM2_KEY *public_key) +{ + uint8_t buf[65]; + uint8_t id[32]; + int critical = -1; + + if (!public_key) { + return 0; + } + sm2_point_to_uncompressed_octets(&public_key->public_key, buf); + sm3_digest(buf, sizeof(buf), id); + + if (x509_exts_add_authority_key_identifier(exts, extslen, maxlen, critical, + id, sizeof(id), NULL, 0, NULL, 0) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_subject_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_subject_key_identifier; + size_t curlen = *extslen; + uint8_t val[32 + X509_SUBJECT_KEY_IDENTIFIER_MAX_LEN]; + uint8_t *p = val; + size_t vlen = 0; + + if (dlen == 0) { + return 0; + } + if (dlen < X509_SUBJECT_KEY_IDENTIFIER_MIN_LEN + || dlen > X509_SUBJECT_KEY_IDENTIFIER_MAX_LEN) { + error_print(); + return -1; + } + + exts += *extslen; + if (asn1_octet_string_to_der(d, dlen, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_subject_key_identifier_ex(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const SM2_KEY *subject_key) +{ + uint8_t buf[65]; + uint8_t id[32]; + + if (!subject_key) { + return 0; + } + sm2_point_to_uncompressed_octets(&subject_key->public_key, buf); + sm3_digest(buf, sizeof(buf), id); + + if (x509_exts_add_subject_key_identifier(exts, extslen, maxlen, critical, id, 32) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int bits) +{ + int oid = OID_ce_key_usage; + size_t curlen = *extslen; + uint8_t val[16]; + uint8_t *p = val; + size_t vlen = 0; + + if (bits == -1) { + return 0; + } + if (!bits) { + if (x509_key_usage_check(bits, -1) != 1) { + error_print(); + return -1; + } + } + + exts += *extslen; + if (asn1_bits_to_der(bits, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_certificate_policies(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_certificate_policies; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_exts_add_policy_mappings(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_policy_mappings; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_exts_add_subject_alt_name(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_subject_alt_name; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_exts_add_issuer_alt_name(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_issuer_alt_name; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_exts_add_subject_directory_attributes(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_subject_directory_attributes; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_exts_add_name_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *permitted_subtrees, size_t permitted_subtrees_len, + const uint8_t *excluded_subtrees, size_t excluded_subtrees_len) +{ + int oid = OID_ce_name_constraints; + size_t curlen = *extslen; + uint8_t val[512]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; + + if (permitted_subtrees_len == 0 && excluded_subtrees_len == 0) { + return 0; + } + exts += *extslen; + if (x509_name_constraints_to_der( + permitted_subtrees, permitted_subtrees_len, + excluded_subtrees, excluded_subtrees_len, + NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_name_constraints_to_der( + permitted_subtrees, permitted_subtrees_len, + excluded_subtrees, excluded_subtrees_len, + &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_policy_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int require_explicit_policy, int inhibit_policy_mapping) +{ + int oid = OID_ce_policy_constraints; + size_t curlen = *extslen; + uint8_t val[32]; + uint8_t *p = val; + size_t vlen = 0; + + if (require_explicit_policy == -1 && inhibit_policy_mapping == -1) { + return 0; + } + exts += *extslen; + if (x509_policy_constraints_to_der( + require_explicit_policy, + inhibit_policy_mapping, + &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_basic_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int ca, int path_len_constraint) +{ + int oid = OID_ce_basic_constraints; + size_t curlen = *extslen; + uint8_t val[32]; + uint8_t *p = val; + size_t vlen = 0; + + if (ca == -1 && path_len_constraint == -1) { + return 0; + } + exts += *extslen; + if (x509_basic_constraints_to_der(ca, path_len_constraint, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const int *key_purposes, size_t key_purposes_cnt) +{ + int oid = OID_ce_ext_key_usage; + size_t curlen = *extslen; + uint8_t val[256]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; + + if (key_purposes_cnt == 0) { + return 0; + } + exts += *extslen; + if (x509_ext_key_usage_to_der(key_purposes, key_purposes_cnt, NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_ext_key_usage_to_der(key_purposes, key_purposes_cnt, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_crl_distribution_points_ex(uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, const char *uri, size_t urilen, const char *ldap_uri, size_t ldap_urilen) +{ + size_t curlen = *extslen; + uint8_t val[256]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; + + if (urilen == 0 && ldap_urilen == 0) { + return 0; + } + if (x509_uri_as_distribution_points_to_der(uri, urilen, -1, NULL, 0, NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_uri_as_distribution_points_to_der(uri, urilen, -1, NULL, 0, &p, &vlen) != 1) { + error_print(); + return -1; + } + exts += *extslen; + if (x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen) +{ + int oid = OID_ce_crl_distribution_points; + if (x509_exts_add_crl_distribution_points_ex(exts, extslen, maxlen, + oid, critical, http_uri, http_urilen, ldap_uri, ldap_urilen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int skip_certs) +{ + int oid = OID_ce_inhibit_any_policy; + size_t curlen = *extslen; + uint8_t val[16]; + uint8_t *p = val; + size_t vlen = 0; + + if (skip_certs == -1) { + return 0; + } + exts += *extslen; + if (x509_inhibit_any_policy_to_der(skip_certs, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_freshest_crl(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_freshest_crl; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_exts_get_ext_by_oid(const uint8_t *d, size_t dlen, int oid, + int *critical, const uint8_t **val, size_t *vlen) +{ + int ext_id; + uint32_t nodes[32]; + size_t nodes_cnt; + + while (dlen) { + if (x509_ext_from_der(&ext_id, nodes, &nodes_cnt, critical, val, vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (ext_id == oid) { + return 1; + } + } + *critical = -1; + *val = NULL; + *vlen = 0; + return 0; +} + +int x509_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_ext_print(fp, fmt, ind, "Extension", p, len); + } + return 1; +} + +// GeneralName + +int x509_other_name_to_der( + const uint32_t *type_nodes, size_t type_nodes_cnt, + const uint8_t *value_a, size_t value_alen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (type_nodes_cnt == 0 && value_alen == 0) { + return 0; + } + if (asn1_object_identifier_to_der(type_nodes, type_nodes_cnt, NULL, &len) != 1 + || asn1_explicit_to_der(0, value_a, value_alen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(type_nodes, type_nodes_cnt, out, outlen) != 1 + || asn1_explicit_to_der(0, value_a, value_alen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_other_name_from_der( + uint32_t *type_nodes, size_t *type_nodes_cnt, + const uint8_t **value, size_t *value_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_object_identifier_from_der(type_nodes, type_nodes_cnt, &p, &len) != 1 + || asn1_explicit_from_der(0, value, value_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_other_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "type-id", NULL, nodes, nodes_cnt); + if (asn1_explicit_from_der(0, &p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "value", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_edi_party_name_to_der( + int assigner_choice, const uint8_t *assigner, size_t assigner_len, + int party_name_choice, const uint8_t *party_name, size_t party_name_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (assigner_len == 0 && party_name_len == 0) { + return 0; + } + if (x509_explicit_directory_name_to_der(0, assigner_choice, assigner, assigner_len, NULL, &len) < 0 + || x509_explicit_directory_name_to_der(1, party_name_choice, party_name, party_name_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_explicit_directory_name_to_der(0, assigner_choice, assigner, assigner_len, out, outlen) < 0 + || x509_explicit_directory_name_to_der(1, party_name_choice, party_name, party_name_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_edi_party_name_from_der( + int *assigner_choice, const uint8_t **assigner, size_t *assigner_len, + int *party_name_choice, const uint8_t **party_name, size_t *party_name_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_explicit_directory_name_from_der(0, assigner_choice, assigner, assigner_len, &p, &len) < 0 + || x509_explicit_directory_name_from_der(1, party_name_choice, party_name, party_name_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_edi_party_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + int tag; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = x509_explicit_directory_name_from_der(0, &tag, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_directory_name_print(fp, fmt, ind, "nameAssigner", tag, p, len); + if (x509_explicit_directory_name_from_der(1, &tag, &p, &len, &d, &dlen) != 1) goto err; + x509_directory_name_print(fp, fmt, ind, "partyName", tag, p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + + if (dlen == 0) { + return 0; + } + switch (choice) { + case X509_gn_other_name: + case X509_gn_rfc822_name: + case X509_gn_dns_name: + case X509_gn_x400_address: + case X509_gn_directory_name: + case X509_gn_edi_party_name: + case X509_gn_uniform_resource_identifier: + case X509_gn_ip_address: + case X509_gn_registered_id: + if ((ret = asn1_implicit_to_der(choice, d, dlen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + int tag; + if ((ret = asn1_any_type_from_der(&tag, d, dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + switch (tag) { + case ASN1_TAG_EXPLICIT(0): *choice = 0; break; + case ASN1_TAG_IMPLICIT(1): *choice = 1; break; + case ASN1_TAG_IMPLICIT(2): *choice = 2; break; + case ASN1_TAG_EXPLICIT(3): *choice = 3; break; + case ASN1_TAG_EXPLICIT(4): *choice = 4; break; + case ASN1_TAG_EXPLICIT(5): *choice = 5; break; + case ASN1_TAG_IMPLICIT(6): *choice = 6; break; + case ASN1_TAG_IMPLICIT(7): *choice = 7; break; + case ASN1_TAG_IMPLICIT(8): *choice = 8; break; + default: + fprintf(stderr, "%s %d: tag = %x\n", __FILE__, __LINE__, tag); + error_print(); + return -1; + } + return 1; +} + +int x509_general_name_print(FILE *fp, int fmt, int ind, const char *label, int choice, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + switch (choice) { + case 0: + case 3: + case 4: + case 5: + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + d = p; + dlen = len; + } + switch (choice) { + case 0: return x509_other_name_print(fp, fmt, ind, "otherName", d, dlen); + case 1: return asn1_string_print(fp, fmt, ind, "rfc822Name", ASN1_TAG_IA5String, d, dlen); + case 2: return asn1_string_print(fp, fmt, ind, "DNSName", ASN1_TAG_IA5String, d, dlen); + case 3: return format_bytes(fp, fmt, ind, "x400Address", d, dlen); + case 4: return x509_name_print(fp, fmt, ind, "directoryName", d, dlen); + case 5: return x509_edi_party_name_print(fp, fmt, ind, "ediPartyName", d, dlen); + case 6: return asn1_string_print(fp, fmt, ind, "URI", ASN1_TAG_IA5String, d, dlen); + case 7: return format_bytes(fp, fmt, ind, "IPAddress", d, dlen); + case 8: + { + uint32_t nodes[32]; + size_t nodes_cnt; + if (asn1_object_identifier_from_octets(nodes, &nodes_cnt, d, dlen) != 1) { + error_print(); + return -1; + } + return asn1_object_identifier_print(fp, fmt, ind, "registeredID", NULL, nodes, nodes_cnt); + } + default: + error_print(); + return -1; + } + return 1; +} + +int x509_general_names_add_general_name(uint8_t *gns, size_t *gnslen, size_t maxlen, + int choice, const uint8_t *d, size_t dlen) +{ + size_t len = 0; + uint8_t *p = gns + *gnslen; + + switch (choice) { + case X509_gn_rfc822_name: + case X509_gn_dns_name: + case X509_gn_uniform_resource_identifier: + if (asn1_string_is_ia5_string((char *)d, dlen) != 1) { + error_print(); + return -1; + } + break; + } + if (x509_general_name_to_der(choice, d, dlen, NULL, &len) != 1 + || asn1_length_le(*gnslen + len, maxlen) != 1 + || x509_general_name_to_der(choice, d, dlen, &p, gnslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_general_names_add_other_name(uint8_t *gns, size_t *gnslen, size_t maxlen, + const uint32_t *nodes, size_t nodes_cnt, + const uint8_t *value, size_t value_len) +{ + int choice = X509_gn_other_name; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + if (x509_other_name_to_der(nodes, nodes_cnt, value, value_len, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || x509_general_names_add_general_name(gns, gnslen, maxlen, choice, d, dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_general_names_add_edi_party_name(uint8_t *gns, size_t *gnslen, size_t maxlen, + int assigner_tag, const uint8_t *assigner, size_t assigner_len, + int party_name_tag, const uint8_t *party_name, size_t party_name_len) +{ + int choice = X509_gn_edi_party_name; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + if (x509_edi_party_name_to_der( + assigner_tag, assigner, assigner_len, + party_name_tag, party_name, party_name_len, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || x509_general_names_add_general_name(gns, gnslen, maxlen, choice, d, dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t maxlen, + const uint32_t *nodes, size_t nodes_cnt) +{ + int choice = X509_gn_registered_id; + uint8_t d[64]; + size_t dlen; + + if (asn1_object_identifier_to_octets(nodes, nodes_cnt, d, &dlen) != 1 + || x509_general_names_add_general_name(gns, gnslen, maxlen, choice, d, dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_general_names_get_next(const uint8_t *gns, size_t gns_len, const uint8_t **ptr, int choice, const uint8_t **d, size_t *dlen) +{ + if (!gns || !gns_len) { + error_print(); + return -1; + } + if (!ptr || !d || !dlen) { + error_print(); + return -1; + } + + if (*ptr > gns + gns_len) { + error_print(); + return -1; + } + gns_len -= (*ptr - gns); + + while (gns_len) { + int tag; + if (x509_general_name_from_der(&tag, d, dlen, ptr, &gns_len) != 1) { + error_print(); + return -1; + } + if (tag == choice) { + return 1; + } + } + + *d = NULL; + *dlen = 0; + return 0; +} + +int x509_general_names_get_first(const uint8_t *gns, size_t gns_len, const uint8_t **ptr, int choice, const uint8_t **d, size_t *dlen) +{ + int ret; + const uint8_t *p; + p = gns; + + if ((ret = x509_general_names_get_next(gns, gns_len, &p, choice, d, dlen)) < 0) { + error_print(); + return - 1; + } + + if (ptr) { + *ptr = p; + } + + return ret; +} + +int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen, + uint8_t **out, size_t *outlen) +{ + int choice = X509_gn_uniform_resource_identifier; + size_t len = 0; + + if (!urilen) { + return 0; + } + if (x509_general_name_to_der(choice, (uint8_t *)uri, urilen, NULL, &len) != 1 + || asn1_sequence_header_to_der_ex(tag, len, out, outlen) != 1 + || x509_general_name_to_der(choice, (uint8_t *)uri, urilen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_uri_as_general_names_from_der_ex(int tag, const uint8_t **uri, size_t *urilen, + const uint8_t **in, size_t *inlen) +{ + int choice = X509_gn_uniform_resource_identifier; + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_type_from_der(tag, &d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *uri = NULL; + *urilen = 0; + } + return ret; + } + if (x509_general_names_get_first(d, dlen, NULL, choice, uri, urilen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_general_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int choice; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (x509_general_name_from_der(&choice, &p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_general_name_print(fp, fmt, ind, "GeneralName", choice, p, len); + } + return 1; +} + +int x509_authority_key_identifier_to_der( + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (keyid_len == 0 && issuer_len == 0 && serial_len == 0) { + return 0; + } + if (asn1_implicit_octet_string_to_der(0, keyid, keyid_len, NULL, &len) < 0 + || asn1_implicit_sequence_to_der(1, issuer, issuer_len, NULL, &len) < 0 + || asn1_implicit_integer_to_der(2, serial, serial_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_implicit_octet_string_to_der(0, keyid, keyid_len, out, outlen) < 0 + || asn1_implicit_sequence_to_der(1, issuer, issuer_len, out, outlen) < 0 + || asn1_implicit_integer_to_der(2, serial, serial_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_authority_key_identifier_from_der( + const uint8_t **keyid, size_t *keyid_len, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial, size_t *serial_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_implicit_octet_string_from_der(0, keyid, keyid_len, &d, &dlen) < 0 + || asn1_implicit_sequence_from_der(1, issuer, issuer_len, &d, &dlen) < 0 + || asn1_implicit_integer_from_der(2, serial, serial_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_authority_key_identifier_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_implicit_octet_string_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "keyIdentifier", p, len); + if ((ret = asn1_implicit_sequence_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_names_print(fp, fmt, ind, "authorityCertIssuer", p, len); + if ((ret = asn1_implicit_integer_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "authorityCertSerialNumber", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +static const char *x509_key_usages[] = { + "digitalSignature", + "nonRepudiation", + "keyEncipherment", + "dataEncipherment", + "keyAgreement", + "keyCertSign", + "cRLSign", + "encipherOnly", + "decipherOnly", +}; + +static size_t x509_key_usages_count = + sizeof(x509_key_usages)/sizeof(x509_key_usages[0]); + +const char *x509_key_usage_name(int flag) +{ + int i; + for (i = 0; i < x509_key_usages_count; i++) { + if (flag & 1) { + if (flag >> 1) { + error_print(); + return NULL; + } + return x509_key_usages[i]; + } + flag >>= 1; + } + error_print(); + return NULL; +} + +int x509_key_usage_from_name(int *flag, const char *name) +{ + int i; + for (i = 0; i < x509_key_usages_count; i++) { + if (strcmp(name, x509_key_usages[i]) == 0) { + *flag = 1 << i; + return 1; + } + } + *flag = 0; + error_print(); + return -1; +} + +int x509_key_usage_check(int bits, int cert_type) +{ + if (bits == -1) { + return 0; + } + if (!bits) { + error_print(); + return -1; + } + + switch (cert_type) { + case -1: + break; + case X509_cert_server_auth: + case X509_cert_client_auth: + if (!(bits & X509_KU_DIGITAL_SIGNATURE) + //&& !(bits & X509_KU_NON_REPUDIATION) // un-comment for compatibility + ) { + error_print(); + return -1; + } + if ((bits & X509_KU_KEY_CERT_SIGN) + || (bits & X509_KU_CRL_SIGN)) { + error_print(); + return -1; + } + break; + + case X509_cert_server_key_encipher: + case X509_cert_client_key_encipher: + if (!(bits & X509_KU_KEY_ENCIPHERMENT) + //&& !(bits & X509_KU_KEY_AGREEMENT) // un-comment for compatibility + ) { + error_print(); + return -1; + } + if ((bits & X509_KU_KEY_CERT_SIGN) + || (bits & X509_KU_CRL_SIGN)) { + error_print(); + return -1; + } + break; + + case X509_cert_ca: + if (!(bits & X509_KU_KEY_CERT_SIGN)) { + error_print(); + return -1; + } + if ((bits & X509_KU_DIGITAL_SIGNATURE) + || (bits & X509_KU_NON_REPUDIATION)) { + error_print(); + //return -1; // comment to print warning + } + break; + case X509_cert_crl_sign: + if (!(bits & X509_KU_CRL_SIGN)) { + error_print(); + return -1; + } + if ((bits & X509_KU_DIGITAL_SIGNATURE) + || (bits & X509_KU_NON_REPUDIATION)) { + error_print(); + //return -1; // comment to print warning + } + break; + default: + error_print(); + return -1; + } + + return 1; +} + +int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, int bits) +{ + (void)asn1_bits_print(fp, fmt, ind, label, x509_key_usages, x509_key_usages_count, bits); + return 1; +} + +int x509_display_text_check(int tag, const uint8_t *d, size_t dlen) +{ + switch (tag) { + case ASN1_TAG_IA5String: + case ASN1_TAG_VisibleString: + case ASN1_TAG_UTF8String: + if (d && strnlen((char *)d, dlen) != dlen) { + error_print(); + return -1; + } + break; + case ASN1_TAG_BMPString: + if (d && dlen % 2) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + if (dlen < X509_DISPLAY_TEXT_MIN_LEN || dlen > X509_DISPLAY_TEXT_MAX_LEN) { + error_print(); + return -1; + } + return 1; +} + +int x509_display_text_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + if (x509_display_text_check(tag, d, dlen) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(tag, d, dlen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_display_text_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_tag_from_der_readonly(tag, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + switch (*tag) { + case ASN1_TAG_IA5String: + case ASN1_TAG_VisibleString: + case ASN1_TAG_UTF8String: + case ASN1_TAG_BMPString: + break; + default: + return 0; + } + + if ((ret = asn1_any_type_from_der(tag, d, dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_display_text_check(*tag, *d, *dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_display_text_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen) +{ + return asn1_string_print(fp, fmt, ind, label, tag, d, dlen); +} + +int x509_notice_reference_to_der( + int org_tag, const uint8_t *org, size_t org_len, + const int *notice_numbers, size_t notice_numbers_cnt, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (org_len == 0 && notice_numbers_cnt == 0) { + return 0; + } + if (x509_display_text_to_der(org_tag, org, org_len, NULL, &len) != 1 + || asn1_sequence_of_int_to_der(notice_numbers, notice_numbers_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_display_text_to_der(org_tag, org, org_len, out, outlen) != 1 + || asn1_sequence_of_int_to_der(notice_numbers, notice_numbers_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_notice_reference_from_der( + int *org_tag, const uint8_t **org, size_t *org_len, + int *notice_numbers, size_t *notice_numbers_cnt, size_t max_notice_numbers, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else error_print(); + return ret; + } + if (x509_display_text_from_der(org_tag, org, org_len, &d, &dlen) != 1 + || asn1_sequence_of_int_from_der(notice_numbers, notice_numbers_cnt, max_notice_numbers, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_notice_reference_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int tag; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_display_text_from_der(&tag, &p, &len, &d, &dlen) != 1) goto err; + x509_display_text_print(fp, fmt, ind, "organization", tag, p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + asn1_sequence_of_int_print(fp, fmt, ind, "noticeNumbers", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_user_notice_to_der( + int notice_ref_org_tag, const uint8_t *notice_ref_org, size_t notice_ref_org_len, + const int *notice_ref_notice_numbers, size_t notice_ref_notice_numbers_cnt, + int explicit_text_tag, const uint8_t *explicit_text, size_t explicit_text_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (notice_ref_org_len == 0 + && notice_ref_notice_numbers_cnt == 0 + && explicit_text_len == 0) { + return 0; + } + if (x509_notice_reference_to_der( + notice_ref_org_tag, notice_ref_org, notice_ref_org_len, + notice_ref_notice_numbers, notice_ref_notice_numbers_cnt, + NULL, &len) < 0 + || x509_display_text_to_der(explicit_text_tag, explicit_text, explicit_text_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_notice_reference_to_der( + notice_ref_org_tag, notice_ref_org, notice_ref_org_len, + notice_ref_notice_numbers, notice_ref_notice_numbers_cnt, + out, outlen) < 0 + || x509_display_text_to_der(explicit_text_tag, explicit_text, explicit_text_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_user_notice_from_der( + int *notice_ref_org_tag, const uint8_t **notice_ref_org, size_t *notice_ref_org_len, + int *notice_ref_notice_numbers, size_t *notice_ref_notice_numbers_cnt, size_t max_notice_ref_notice_numbers, + int *explicit_text_tag, const uint8_t **explicit_text, size_t *explicit_text_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_notice_reference_from_der(notice_ref_org_tag, notice_ref_org, notice_ref_org_len, + notice_ref_notice_numbers, notice_ref_notice_numbers_cnt, max_notice_ref_notice_numbers, &d, &dlen) < 0 + || x509_display_text_from_der(explicit_text_tag, explicit_text, explicit_text_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_user_notice_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + int tag; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_notice_reference_print(fp, fmt, ind, "noticeRef", p, len); + if ((ret = x509_display_text_from_der(&tag, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_display_text_print(fp, fmt, ind, "explicitText", tag, p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + + + +static uint32_t oid_qt_cps[] = { oid_qt,1 }; +static uint32_t oid_qt_unotice[] = {oid_qt,2 }; + +static const ASN1_OID_INFO x509_qt_ids[] = { + { OID_qt_cps, "CPS", oid_qt_cps, sizeof(oid_qt_cps)/sizeof(int) }, + { OID_qt_unotice, "userNotice", oid_qt_unotice, sizeof(oid_qt_unotice)/sizeof(int) } +}; + +static const int x509_qt_ids_count = + sizeof(x509_qt_ids)/sizeof(x509_qt_ids[0]); + +int x509_qualifier_id_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_qt_ids, x509_qt_ids_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +const char *x509_qualifier_id_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_qt_ids, x509_qt_ids_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_qualifier_id_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_qt_ids, x509_qt_ids_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_qualifier_id_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + if ((ret = asn1_oid_info_from_der(&info, x509_qt_ids, x509_qt_ids_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + + +int x509_policy_qualifier_info_to_der( + int oid, + const uint8_t *qualifier, size_t qualifier_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (qualifier_len == 0) { + return 0; + } + if (x509_qualifier_id_to_der(oid, NULL, &len) != 1 + || asn1_any_to_der(qualifier, qualifier_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_qualifier_id_to_der(oid, out, outlen) != 1 + || asn1_any_to_der(qualifier, qualifier_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_qualifier_info_from_der(int *oid, const uint8_t **qualifier, size_t *qualifier_len, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_qualifier_id_from_der(oid, &p, &len) != 1 + || asn1_any_from_der(qualifier, qualifier_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_qualifier_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + const uint8_t *p; + size_t len; + + if (x509_qualifier_id_from_der(&oid, &d, &dlen) != 1) goto err; + switch (oid) { + case OID_qt_cps: + if (asn1_ia5_string_from_der((const char **)&p, &len, &d, &dlen) != 1) goto err; + format_string(fp, fmt, ind, "cPSuri", p, len); + break; + case OID_qt_unotice: + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_user_notice_print(fp, fmt, ind, "userNotice", p, len); + break; + } + return 1; +err: + error_print(); + return -1; +} + +int x509_policy_qualifier_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_policy_qualifier_info_print(fp, fmt, ind, "PolicyQualifierInfo", p, len); + } + return 1; +} + + +int x509_cert_policy_id_from_name(const char *name) +{ + if (strcmp(name, "anyPolicy") == 0) { + return OID_any_policy; + } + return OID_undef; +} + +char *x509_cert_policy_id_name(int oid) +{ + switch (oid) { + case OID_any_policy: return "anyPolicy"; + } + return NULL; +} + +static uint32_t oid_any_policy[] = { oid_ce,32,0 }; + +int x509_cert_policy_id_to_der(int oid, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen) +{ + switch (oid) { + case OID_any_policy: + if (asn1_object_identifier_to_der(oid_any_policy, sizeof(oid_any_policy)/sizeof(int), out, outlen) != 1) { + error_print(); + return -1; + } + break; + case OID_undef: + if (asn1_object_identifier_to_der(nodes, nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_cert_policy_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = asn1_object_identifier_from_der(nodes, nodes_cnt, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + if (asn1_object_identifier_equ(nodes, *nodes_cnt, oid_any_policy, oid_cnt(oid_any_policy))) + *oid = OID_any_policy; + else *oid = 0; + return 1; +} + +int x509_policy_information_to_der( + int oid, const uint32_t *nodes, size_t nodes_cnt, + const uint8_t *qualifiers, size_t qualifiers_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_cert_policy_id_to_der(oid, nodes, nodes_cnt, NULL, &len) != 1 + || asn1_sequence_to_der(qualifiers, qualifiers_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_cert_policy_id_to_der(oid, nodes, nodes_cnt, out, outlen) != 1 + || asn1_sequence_to_der(qualifiers, qualifiers_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_information_from_der( + int *oid, uint32_t *nodes, size_t *nodes_cnt, + const uint8_t **qualifiers, size_t *qualifiers_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_cert_policy_id_from_der(oid, nodes, nodes_cnt, &d, &dlen) != 1 + || asn1_sequence_from_der(qualifiers, qualifiers_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_information_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, oid; + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_cert_policy_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "policyIdentifier", x509_cert_policy_id_name(oid), nodes, nodes_cnt); + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_policy_qualifier_infos_print(fp, fmt, ind, "policyQualifiers", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_certificate_policies_add_policy_information(uint8_t *d, size_t *dlen, size_t maxlen, + int policy_oid, const uint32_t *policy_nodes, size_t policy_nodes_cnt, + const uint8_t *qualifiers, size_t qualifiers_len) +{ + error_print(); + return -1; +} + +int x509_certificate_polices_check(const uint8_t *d, size_t dlen) +{ + error_print(); + return -1; +} + +int x509_certificate_policies_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_policy_information_print(fp, fmt, ind, label, p, len); + } + return 1; +} + +int x509_policy_mapping_to_der( + int issuer_policy_oid, const uint32_t *issuer_policy_nodes, size_t issuer_policy_nodes_cnt, + int subject_policy_oid, const uint32_t *subject_policy_nodes, size_t subject_policy_nodes_cnt, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (issuer_policy_oid == -1 && subject_policy_oid == -1) { + return 0; + } + if (x509_cert_policy_id_to_der(issuer_policy_oid, + issuer_policy_nodes, issuer_policy_nodes_cnt, NULL, &len) != 1 + || x509_cert_policy_id_to_der(subject_policy_oid, + subject_policy_nodes, subject_policy_nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_cert_policy_id_to_der(issuer_policy_oid, + issuer_policy_nodes, issuer_policy_nodes_cnt, out, outlen) != 1 + || x509_cert_policy_id_to_der(subject_policy_oid, + subject_policy_nodes, subject_policy_nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_mapping_from_der( + int *issuer_policy_oid, uint32_t *issuer_policy_nodes, size_t *issuer_policy_nodes_cnt, + int *subject_policy_oid, uint32_t *subject_policy_nodes, size_t *subject_policy_nodes_cnt, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_cert_policy_id_from_der(issuer_policy_oid, + issuer_policy_nodes, issuer_policy_nodes_cnt, &d, &dlen) != 1 + || x509_cert_policy_id_from_der(subject_policy_oid, + subject_policy_nodes, subject_policy_nodes_cnt, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_mapping_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + uint32_t nodes[32]; + size_t nodes_cnt; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_cert_policy_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "issuerDomainPolicy", x509_cert_policy_id_name(oid), nodes, nodes_cnt); + if (x509_cert_policy_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "subjectDomainPolicy", x509_cert_policy_id_name(oid), nodes, nodes_cnt); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_policy_mappings_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_policy_mapping_print(fp, fmt, ind, label, p, len); + } + return 1; +} + +int x509_attribute_to_der( + const uint32_t *nodes, size_t nodes_cnt, + const uint8_t *values, size_t values_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_object_identifier_to_der(nodes, nodes_cnt, NULL, &len) != 1 + || asn1_set_to_der(values, values_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(nodes, nodes_cnt, out, outlen) != 1 + || asn1_set_to_der(values, values_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_attribute_from_der( + int *oid, uint32_t *nodes, size_t *nodes_cnt, + const uint8_t **values, size_t *values_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + *oid = OID_undef; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_object_identifier_from_der(nodes, nodes_cnt, &p, &len) != 1 + || asn1_set_from_der(values, values_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_attribute_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "type", NULL, nodes, nodes_cnt); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "values", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_attributes_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if (!dlen) { + format_print(fp, fmt, ind, "(null)\n"); + } + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_attribute_print(fp, fmt, ind, "Attribute", p, len); + } + return 1; +} + +int x509_basic_constraints_to_der(int ca, int path_len_cons, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (ca == -1 && path_len_cons == -1) { + error_print(); + return -1; + } + if (asn1_boolean_to_der(ca, NULL, &len) < 0 + || asn1_int_to_der(path_len_cons, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_boolean_to_der(ca, out, outlen) < 0 + || asn1_int_to_der(path_len_cons, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *ca = *path_len_cons = -1; + return ret; + } + if (dlen == 0) { + error_print(); + return -1; + } + if (asn1_boolean_from_der(ca, &d, &dlen) < 0 + || asn1_int_from_der(path_len_cons, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_basic_constraints_check(int ca, int path_len_constraint, int cert_type) +{ + /* + entity_cert: + ca = -1 or 0 + path_len_constraint = -1 + first_ca_cert: + ca = 1 + path_len_constraint = 0 + middle_ca_cert: + ca = 1 + path_len_constraint = -1 or > 0 + root_ca_cert: + ca = 1 + path_len_constraint = -1 or > 0 (=0 might be ok?) + */ + switch (cert_type) { + case X509_cert_server_auth: + case X509_cert_client_auth: + case X509_cert_server_key_encipher: + case X509_cert_client_key_encipher: + if (ca > 0 || path_len_constraint != -1) { + error_print(); + return -1; + } + break; + // FIXME: add more cert types and check path_len_constraint + case X509_cert_ca: + case X509_cert_crl_sign: + case X509_cert_root_ca: + if (ca != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + // BasicConstraints might be an empty sequence in entity certificates + if (!d || !dlen) { + return 1; + } + + if ((ret = asn1_boolean_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "cA: %s\n", asn1_boolean_name(val)); + if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "pathLenConstraint: %d\n", val); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_general_subtree_to_der( + int base_choice, const uint8_t *base, size_t base_len, + int minimum, + int maximum, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_general_name_to_der(base_choice, base, base_len, NULL, &len) != 1 + || asn1_implicit_int_to_der(0, minimum, NULL, &len) < 0 + || asn1_implicit_int_to_der(1, maximum, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_general_name_to_der(base_choice, base, base_len, out, outlen) != 1 + || asn1_implicit_int_to_der(0, minimum, out, outlen) < 0 + || asn1_implicit_int_to_der(1, maximum, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_general_subtree_from_der( + int *base_choice, const uint8_t **base, size_t *base_len, + int *minimum, + int *maximum, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_general_name_from_der(base_choice, base, base_len, &d, &dlen) != 1 + || asn1_implicit_int_from_der(0, minimum, &d, &dlen) < 0 + || asn1_implicit_int_from_der(1, maximum, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (*minimum < 0) *minimum = 0; + return 1; +} + +int x509_general_subtree_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, choice, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_general_name_from_der(&choice, &p, &len, &d, &dlen) != 1) goto err; + x509_general_name_print(fp, fmt, ind, "base", choice, p, len); + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "minimum: %d\n", val); + if ((ret = asn1_implicit_int_from_der(1, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "maximum: %d\n", val); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_general_subtrees_add_general_subtree(uint8_t *d, size_t *dlen, size_t maxlen, + int base_choice, const uint8_t *base, size_t base_len, + int minimum, int maximum) +{ + error_print(); + return -1; +} + +int x509_general_subtrees_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_general_subtree_print(fp, fmt, ind, "GeneralSubtree", p, len); + } + return 1; +} + +int x509_name_constraints_to_der( + const uint8_t *permitted_subtrees, size_t permitted_subtrees_len, + const uint8_t *excluded_subtrees, size_t excluded_subtrees_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_implicit_sequence_to_der(0, permitted_subtrees, permitted_subtrees_len, NULL, &len) < 0 + || asn1_implicit_sequence_to_der(1, excluded_subtrees, excluded_subtrees_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_implicit_sequence_to_der(0, permitted_subtrees, permitted_subtrees_len, out, outlen) < 0 + || asn1_implicit_sequence_to_der(1, excluded_subtrees, excluded_subtrees_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_name_constraints_from_der( + const uint8_t **permitted_subtrees, size_t *permitted_subtrees_len, + const uint8_t **excluded_subtrees, size_t *excluded_subtrees_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + *permitted_subtrees = NULL; + *permitted_subtrees_len = 0; + *excluded_subtrees = NULL; + *excluded_subtrees_len = 0; + if (asn1_implicit_sequence_from_der(0, permitted_subtrees, permitted_subtrees_len, &d, &dlen) < 0 + || asn1_implicit_sequence_from_der(1, excluded_subtrees, excluded_subtrees_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_name_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_implicit_sequence_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_subtrees_print(fp, fmt, ind, "permittedSubtrees", p, len); + if ((ret = asn1_implicit_sequence_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_subtrees_print(fp, fmt, ind, "excludedSubtrees", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_policy_constraints_to_der( + int require_explicit_policy, + int inhibit_policy_mapping, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (require_explicit_policy == -1 && inhibit_policy_mapping == -1) { + error_print(); + return -1; + } + if (asn1_implicit_int_to_der(0, require_explicit_policy, NULL, &len) < 0 + || asn1_implicit_int_to_der(1, inhibit_policy_mapping, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_implicit_int_to_der(0, require_explicit_policy, out, outlen) < 0 + || asn1_implicit_int_to_der(1, inhibit_policy_mapping, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_constraints_from_der( + int *require_explicit_policy, + int *inhibit_policy_mapping, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *require_explicit_policy = *inhibit_policy_mapping = -1; + return ret; + } + if (dlen == 0) { + error_print(); + return -1; + } + if (asn1_implicit_int_from_der(0, require_explicit_policy, &d, &dlen) < 0 + || asn1_implicit_int_from_der(1, inhibit_policy_mapping, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_policy_constraints_check(const uint8_t *a, size_t alen) +{ + error_print(); + return -1; +} + +int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "requireExplicitPolicy: %d\n", val); + if ((ret = asn1_implicit_int_from_der(1, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "inhibitPolicyMapping: %d\n", val); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static uint32_t oid_any_extended_key_usage[] = { oid_ce,37,0 }; + +#define oid_kp oid_pkix,3 + +static uint32_t oid_kp_server_auth[] = { oid_kp,1 }; +static uint32_t oid_kp_client_auth[] = { oid_kp,2 }; +static uint32_t oid_kp_code_signing[] = { oid_kp,3 }; +static uint32_t oid_kp_email_protection[] = { oid_kp,4 }; +static uint32_t oid_kp_time_stamping[] = { oid_kp,8 }; +static uint32_t oid_kp_ocsp_signing[] = { oid_kp,9 }; +#define OID_KP_CNT sizeof(oid_kp_server_auth)/sizeof(int) + +static const ASN1_OID_INFO x509_key_purposes[] = { + { OID_any_extended_key_usage, "anyExtendedKeyUsage", oid_any_extended_key_usage, sizeof(oid_any_extended_key_usage)/sizeof(uint32_t), 0, "Any Extended Key Usage" }, + { OID_kp_server_auth, "serverAuth", oid_kp_server_auth, OID_KP_CNT, 0, "TLS WWW server authentication" }, + { OID_kp_client_auth, "clientAuth", oid_kp_client_auth, OID_KP_CNT, 0, "TLS WWW client authentication" }, + { OID_kp_code_signing, "codeSigning", oid_kp_code_signing, OID_KP_CNT, 0, "Signing of downloadable executable code" }, + { OID_kp_email_protection, "emailProtection", oid_kp_email_protection, OID_KP_CNT, 0, "Email protection" }, + { OID_kp_time_stamping, "timeStamping", oid_kp_time_stamping, OID_KP_CNT, 0, "Binding the hash of an object to a time" }, + { OID_kp_ocsp_signing, "OCSPSigning", oid_kp_ocsp_signing, OID_KP_CNT, 0, "Signing OCSP responses" }, +}; + +static const int x509_key_purposes_count = + sizeof(x509_key_purposes)/sizeof(x509_key_purposes[0]); + +int x509_key_purpose_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_key_purposes, x509_key_purposes_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +const char *x509_key_purpose_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_key_purposes, x509_key_purposes_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +const char *x509_key_purpose_text(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_key_purposes, x509_key_purposes_count, oid))) { + error_print(); + return NULL; + } + return info->description; +} + +int x509_key_purpose_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_key_purposes, x509_key_purposes_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_key_purpose_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + if ((ret = asn1_oid_info_from_der(&info, x509_key_purposes, x509_key_purposes_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + + +int x509_ext_key_usage_to_der(const int *oids, size_t oids_cnt, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + size_t i; + + if (oids_cnt > X509_MAX_KEY_PURPOSES) { + error_print(); + return -1; + } + for (i = 0; i < oids_cnt; i++) { + if (x509_key_purpose_to_der(oids[i], NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < oids_cnt; i++) { + if (x509_key_purpose_to_der(oids[i], out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + *oids_cnt = 0; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + while (len && (*oids_cnt < max_cnt)) { + if (x509_key_purpose_from_der(oids, &p, &len) != 1) { + error_print(); + return -1; + } + oids++; + (*oids_cnt)++; + } + if (len) { + error_print(); + return -1; + } + return 1; +} + +int x509_ext_key_usage_check(const int *oids, size_t oids_cnt, int cert_type) +{ + int ret = -1; + size_t i; + + for (i = 0; i < oids_cnt; i++) { + // anyExtendedKeyUsage might not acceptable for strict validation + if (oids[i] == OID_any_extended_key_usage) { + ret = 0; + } + + switch (cert_type) { + case X509_cert_server_auth: + case X509_cert_server_key_encipher: + if (oids[i] == OID_kp_server_auth) { + return 1; + } + break; + + case X509_cert_client_auth: + case X509_cert_client_key_encipher: + if (oids[i] == OID_kp_client_auth) { + return 1; + } + break; + + default: + error_print(); + return -1; + } + } + return ret; +} + +int x509_ext_key_usage_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (x509_key_purpose_from_der(&oid, &d, &dlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "%s\n", x509_key_purpose_name(oid)); + } + return 1; +} + +static const char *x509_revoke_reason_flags[] = { + "unused", + "keyCompromise", + "cACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "privilegeWithdrawn", + "aACompromise", +}; + +static size_t x509_revoke_reason_flags_count = + sizeof(x509_revoke_reason_flags)/sizeof(x509_revoke_reason_flags[0]); + +const char *x509_revoke_reason_flag_name(int flag) +{ + int i; + for (i = 0; i < x509_revoke_reason_flags_count; i++) { + if (flag & 1) { + if (flag >> 1) { + error_print(); + return NULL; + } + return x509_revoke_reason_flags[i]; + } + flag >>= 1; + } + return NULL; +} + +int x509_revoke_reason_flag_from_name(int *flag, const char *name) +{ + int i; + for (i = 0; i < x509_revoke_reason_flags_count; i++) { + if (strcmp(name, x509_revoke_reason_flags[i]) == 0) { + *flag = 1 << i; + return 1; + } + } + *flag = 0; + error_print(); + return -1; +} + +int x509_revoke_reason_flags_print(FILE *fp, int fmt, int ind, const char *label, int bits) +{ + return asn1_bits_print(fp, fmt, ind, label, x509_revoke_reason_flags, x509_revoke_reason_flags_count, bits); +} + +int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen, + uint8_t **out, size_t *outlen) +{ + int tag = ASN1_TAG_EXPLICIT(X509_full_name); + + if (urilen == 0) { + return 0; + } + if (x509_uri_as_general_names_to_der_ex(tag, uri, urilen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + int tag; + + if ((ret = asn1_any_type_from_der(&tag, d, dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + switch (tag) { + case ASN1_TAG_EXPLICIT(X509_full_name): + *choice = X509_full_name; + break; + case ASN1_TAG_EXPLICIT(X509_name_relative_to_crl_issuer): + *choice = X509_name_relative_to_crl_issuer; + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_uri_as_distribution_point_name_from_der(const char **uri, size_t *urilen, + const uint8_t **in, size_t *inlen) +{ + int ret; + int choice; + const uint8_t *d; + size_t dlen; + + if ((ret = x509_distribution_point_name_from_der(&choice, &d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (choice == X509_full_name) { + if (x509_general_names_get_first(d, dlen, NULL, X509_gn_uniform_resource_identifier, (const uint8_t **)uri, urilen) < 0) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + int tag; + const uint8_t *d; + size_t dlen; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_any_type_from_der(&tag, &d, &dlen, &a, &alen) != 1) { + error_print(); + return -1; + } + switch (tag) { + case ASN1_TAG_EXPLICIT(0): return x509_general_names_print(fp, fmt, ind, "fullName", d, dlen); + case ASN1_TAG_IMPLICIT(1): return x509_rdn_print(fp, fmt, ind, "nameRelativeToCRLIssuer", d, dlen); + default: + error_print(); + return -1; + } + return 1; +} + +int x509_uri_as_explicit_distribution_point_name_to_der(int index, + const char *uri, size_t urilen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (!urilen) { + return 0; + } + if (x509_uri_as_distribution_point_name_to_der(uri, urilen, NULL, &len) != 1 + || asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || x509_uri_as_distribution_point_name_to_der(uri, urilen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_uri_as_explicit_distribution_point_name_from_der(int index, + const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *a; + size_t alen; + + if ((ret = asn1_explicit_from_der(index, &a, &alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_uri_as_distribution_point_name_from_der(uri, urilen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen, + int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, NULL, &len) != 1 + || x509_revoke_reason_flags_to_der(reasons, NULL, &len) < 0 + || x509_general_names_to_der(crl_issuer, crl_issuer_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, out, outlen) != 1 + || x509_revoke_reason_flags_to_der(reasons, out, outlen) < 0 + || x509_general_names_to_der(crl_issuer, crl_issuer_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_uri_as_distribution_point_from_der(const char **uri, size_t *urilen, + int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_uri_as_explicit_distribution_point_name_from_der(0, uri, urilen, &d, &dlen) < 0 + || x509_revoke_reason_flags_from_der(reasons, &d, &dlen) < 0 + || x509_general_names_from_der(crl_issuer, crl_issuer_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + int bits; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_explicit_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_distribution_point_name_print(fp, fmt, ind, "distributionPoint", p, len); + + if ((ret = asn1_implicit_bits_from_der(1, &bits, &d, &dlen)) < 0) goto err; + if (ret) x509_revoke_reason_flags_print(fp, fmt, ind, "reasons", bits); + + if ((ret = asn1_implicit_sequence_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_names_print(fp, fmt, ind, "cRLIssuer", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_uri_as_distribution_points_to_der(const char *uri, size_t urilen, + int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_uri_as_distribution_point_to_der(uri, urilen, reasons, crl_issuer, crl_issuer_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_uri_as_distribution_point_to_der(uri, urilen, reasons, crl_issuer, crl_issuer_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_uri_as_distribution_points_from_der(const char **uri, size_t *urilen, + int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + while (dlen) { + if (x509_uri_as_distribution_point_from_der(uri, urilen, reasons, crl_issuer, crl_issuer_len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (*uri != NULL) { + return 1; + } + } + *uri = NULL; + *urilen = 0; + *reasons = -1; + *crl_issuer = NULL; + *crl_issuer_len = 0; + return 1; +} + +int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_distribution_point_print(fp, fmt, ind, "DistributionPoint", p, len); + } + return 1; +} + +static const char *netscape_cert_types[] = { + "SSL Client certificate", + "SSL Server certificate", + "S/MIME certificate", + "Object-signing certificate", + "Reserved for future use", + "SSL CA certificate", + "S/MIME CA certificate", + "Object-signing CA certificate", +}; + +int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label, int bits) +{ + return asn1_bits_print(fp, fmt, ind, label, netscape_cert_types, + sizeof(netscape_cert_types)/sizeof(netscape_cert_types[0]), bits); +} + +int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type, + int *path_len_constraint) +{ + int oid; + uint32_t nodes[32]; + size_t nodes_cnt; + int critical; + const uint8_t *val; + size_t vlen; + + int ca = -1; + int path_len = -1; + int key_usage; + int ext_key_usages[X509_MAX_KEY_PURPOSES]; + size_t ext_key_usages_cnt; + + *path_len_constraint = -1; + + while (extslen) { + if (x509_ext_from_der(&oid, nodes, &nodes_cnt, &critical, &val, &vlen, &exts, &extslen) != 1) { + error_print(); + return -1; + } + + switch (oid) { + case OID_ce_authority_key_identifier: + if (critical == X509_critical) { + error_print(); + return -1; + } + /* + if (x509_authority_key_identifier(val, vlen) != 1) { + error_print(); + return -1; + } + */ + break; + case OID_ce_subject_key_identifier: + if (critical == X509_critical) { + error_print(); + return -1; + } + const uint8_t *p; + size_t len; + if (asn1_octet_string_from_der(&p, &len, &val, &vlen) != 1 + || asn1_length_is_zero(vlen) != 1) { + error_print(); + return -1; + } + if (!p || !len) { + error_print(); + return -1; + } + break; + case OID_ce_key_usage: + if (critical != X509_critical) { + error_print(); + // conforming CAs SHOULD mark this extension as critical. + } + if (asn1_bits_from_der(&key_usage, &val, &vlen) != 1 + || x509_key_usage_check(key_usage, cert_type) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_certificate_policies: + break; + case OID_ce_policy_mappings: + if (critical != X509_critical) { + error_print(); + return -1; + } + break; + case OID_ce_subject_alt_name: + break; + case OID_ce_issuer_alt_name: + if (critical == X509_critical) { + error_print(); + return -1; + } + break; + case OID_ce_subject_directory_attributes: + if (critical == X509_critical) { + error_print(); + return -1; + } + break; + + case OID_ce_basic_constraints: + if (x509_basic_constraints_from_der(&ca, &path_len, &val, &vlen) != 1 + || x509_basic_constraints_check(ca, path_len, cert_type) != 1) { + error_print(); + return -1; + } + *path_len_constraint = path_len; + break; + + case OID_ce_ext_key_usage: + if (x509_ext_key_usage_from_der(ext_key_usages, &ext_key_usages_cnt, + sizeof(ext_key_usages)/sizeof(ext_key_usages[0]), &val, &vlen) != 1 + || x509_ext_key_usage_check(ext_key_usages, ext_key_usages_cnt, cert_type) != 1) { + error_print(); + return -1; + } + break; + + case OID_ce_name_constraints: + case OID_ce_policy_constraints: + case OID_ce_crl_distribution_points: + case OID_ce_inhibit_any_policy: + case OID_ce_freshest_crl: + + break; + default: + if (critical == X509_critical) { + error_print(); + return -1; + } + } + } + + return 1; +} + +// AuthorityInfoAccess Extension + +static uint32_t oid_ad_ocsp[] = { oid_ad,1 }; +static uint32_t oid_ad_ca_issuers[] = { oid_ad,2 }; + +#define cnt(oid) (sizeof(oid)/sizeof((oid)[0])) + +static const ASN1_OID_INFO access_methods[] = { + { OID_ad_ocsp, "OCSP", oid_ad_ocsp, oid_cnt(oid_ad_ocsp) }, + { OID_ad_ca_issuers, "CAIssuers", oid_ad_ca_issuers, oid_cnt(oid_ad_ca_issuers) }, +}; + +const char *x509_access_method_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(access_methods, cnt(access_methods), oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_access_method_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(access_methods, cnt(access_methods), name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_access_method_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(access_methods, cnt(access_methods), oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_access_method_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + uint32_t nodes[32]; + size_t nodes_cnt; + + if ((ret = asn1_oid_info_from_der_ex(&info, nodes, &nodes_cnt, access_methods, cnt(access_methods), in, inlen)) != 1) { + if (ret < 0) error_print(); + else *oid = -1; + return ret; + } + *oid = info->oid; + return 1; +} + +// currently AccessDescription not support values of SubjectInfoAccess extension +int x509_access_description_to_der(int oid, const char *uri, size_t urilen, uint8_t **out, size_t *outlen) +{ + const int uri_choice = X509_gn_uniform_resource_identifier; + size_t len = 0; + + if (oid != OID_ad_ocsp && oid != OID_ad_ca_issuers) { + error_print(); + return -1; + } + if (!uri || !urilen) { + error_print(); + return -1; + } + if (x509_access_method_to_der(oid, NULL, &len) != 1 + || x509_general_name_to_der(uri_choice, (const uint8_t *)uri, urilen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_access_method_to_der(oid, out, outlen) != 1 + || x509_general_name_to_der(uri_choice, (const uint8_t *)uri, urilen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_access_description_from_der(int *oid, const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int uri_choice; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else { + *oid = -1; + *uri = NULL; + *urilen = 0; + } + return ret; + } + if (x509_access_method_from_der(oid, &d, &dlen) != 1 + || x509_general_name_from_der(&uri_choice, (const uint8_t **)uri, urilen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (uri_choice != X509_gn_uniform_resource_identifier) { + error_print(); + return -1; + } + if (*uri == NULL || *urilen == 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_access_description_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + int choice; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_access_method_from_der(&oid, &d, &dlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "accessMethod: %s\n", x509_access_method_name(oid)); + + if (x509_general_name_from_der(&choice, &p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_general_name_print(fp, fmt, ind, "GeneralName", choice, p, len); + + if (dlen) { + error_print(); + return -1; + } + return 1; +} + +int x509_authority_info_access_to_der( + const char *ca_issuers_uri, size_t ca_issuers_urilen, + const char *ocsp_uri, size_t ocsp_urilen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (ca_issuers_uri && ca_issuers_urilen) { + if (x509_access_description_to_der(OID_ad_ca_issuers, ca_issuers_uri, ca_issuers_urilen, NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (ocsp_uri && ocsp_urilen) { + if (x509_access_description_to_der(OID_ad_ocsp, ocsp_uri, ocsp_urilen, NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (!len) { + error_print(); + return -1; + } + if (asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + if (ca_issuers_uri && ca_issuers_urilen) { + if (x509_access_description_to_der(OID_ad_ca_issuers, ca_issuers_uri, ca_issuers_urilen, out, outlen) != 1) { + error_print(); + return -1; + } + } + if (ocsp_uri && ocsp_urilen) { + if (x509_access_description_to_der(OID_ad_ocsp, ocsp_uri, ocsp_urilen, out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_authority_info_access_from_der( + const char **ca_issuers_uri, size_t *ca_issuers_urilen, + const char **ocsp_uri, size_t *ocsp_urilen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if (!ca_issuers_uri || !ca_issuers_urilen || !ocsp_uri || !ocsp_urilen || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + + *ca_issuers_uri = NULL; + *ca_issuers_urilen = 0; + *ocsp_uri = NULL; + *ocsp_urilen = 0; + + if ((ret = asn1_sequence_of_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + + while (dlen) { + int oid; + const char *uri; + size_t urilen; + + if (x509_access_description_from_der(&oid, &uri, &urilen, &d, &dlen) != 1) { + error_print(); + return -1; + } + switch (oid) { + case OID_ad_ca_issuers: + if (*ca_issuers_uri) { + error_print(); + return -1; + } + *ca_issuers_uri = uri; + *ca_issuers_urilen = urilen; + break; + case OID_ad_ocsp: + if (*ocsp_uri) { + error_print(); + return -1; + } + *ocsp_uri = uri; + *ocsp_urilen = urilen; + break; + default: + error_print(); + return -1; + } + } + return 1; +} + +int x509_authority_info_access_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_access_description_print(fp, fmt, ind, "AccessDescription", p, len); + } + return 1; +} + +int x509_exts_add_authority_info_access(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *ca_issuers_uri, size_t ca_issuers_urilen, const char *ocsp_uri, size_t ocsp_urilen) +{ + int oid = OID_pe_authority_info_access; + size_t curlen = *extslen; + uint8_t val[256]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; + + if (x509_authority_info_access_to_der(ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen, NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_authority_info_access_to_der(ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen, &p, &vlen) != 1) { + error_print(); + return -1; + } + exts += *extslen; + if (x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/x509_new.c b/Core/GmSSL-3.1.1/src/x509_new.c new file mode 100644 index 0000000..d3b669d --- /dev/null +++ b/Core/GmSSL-3.1.1/src/x509_new.c @@ -0,0 +1,284 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +int x509_cert_new_from_file(uint8_t **out, size_t *outlen, const char *file) +{ + int ret = -1; + FILE *fp = NULL; + size_t fsize; + uint8_t *buf = NULL; + size_t buflen; + + if (!(fp = fopen(file, "r")) + || file_size(fp, &fsize) != 1 + || (buflen = (fsize * 3)/4 + 1) < 0 + || (buf = malloc((fsize * 3)/4 + 1)) == NULL) { + error_print(); + goto end; + } + if (x509_cert_from_pem(buf, outlen, buflen, fp) != 1) { + error_print(); + goto end; + } + *out = buf; + buf = NULL; + ret = 1; +end: + if (fp) fclose(fp); + if (buf) free(buf); + return ret; +} + +int x509_certs_new_from_file(uint8_t **out, size_t *outlen, const char *file) +{ + int ret = -1; + FILE *fp = NULL; + size_t fsize; + uint8_t *buf = NULL; + size_t buflen; + + if (!(fp = fopen(file, "r")) + || file_size(fp, &fsize) != 1 + || (buflen = (fsize * 3)/4 + 1) < 0 + || (buf = malloc((fsize * 3)/4 + 1)) == NULL) { + error_print(); + goto end; + } + if (x509_certs_from_pem(buf, outlen, buflen, fp) != 1) { + error_print(); + goto end; + } + *out = buf; + buf = NULL; + ret = 1; +end: + if (fp) fclose(fp); + if (buf) free(buf); + return ret; +} + +int x509_req_new_from_pem(uint8_t **out, size_t *outlen, FILE *fp) +{ + uint8_t *req; + size_t reqlen; + size_t maxlen; + + if (!out || !outlen || !fp) { + error_print(); + return -1; + } + if (file_size(fp, &maxlen) != 1) { + error_print(); + return -1; + } + if (!(req = malloc(maxlen))) { + error_print(); + return -1; + } + if (x509_req_from_pem(req, &reqlen, maxlen, fp) != 1) { + free(req); + error_print(); + return -1; + } + *out = req; + *outlen = reqlen; + return 1; +} + +int x509_req_new_from_file(uint8_t **req, size_t *reqlen, const char *file) +{ + FILE *fp = NULL; + + if (!(fp = fopen(file, "rb"))) { + error_print(); + return -1; + } + if (x509_req_new_from_pem(req, reqlen, fp) != 1) { + error_print(); + fclose(fp); + return -1; + } + fclose(fp); + return 1; +} + +int x509_crl_new_from_uri(uint8_t **crl, size_t *crl_len, const char *uri, size_t urilen) +{ + int ret = -1; + char *uristr = NULL; + uint8_t *buf = NULL; + size_t buflen; + const uint8_t *p; + + if (!(uristr = malloc(urilen + 1))) { + error_print(); + return -1; + } + memcpy(uristr, uri, urilen); + uristr[urilen] = 0; + + if (http_get(uristr, NULL, &buflen, 0) < 0) { + error_print(); + goto end; + } + if (!buflen) { + error_print(); + goto end; + } + if (!(buf = malloc(buflen))) { + error_print(); + goto end; + } + if (http_get(uristr, buf, &buflen, buflen) != 1) { + error_print(); + goto end; + } + p = buf; + if (x509_crl_from_der((const uint8_t **)crl, crl_len, &p, &buflen) != 1) { + error_print(); + goto end; + } + buf = NULL; + ret = 1; +end: + if (uristr) free(uristr); + if (buf) free(buf); + return ret; +} + +int x509_crl_new_from_cert(uint8_t **crl, size_t *crl_len, const uint8_t *cert, size_t certlen) +{ + int ret; + const uint8_t *exts; + size_t extslen; + + int critical; + const uint8_t *val; + size_t vlen; + + const char *uri; + size_t urilen; + int reason; + const uint8_t *crl_issuer; + size_t crl_issuer_len; + + if ((ret = x509_cert_get_exts(cert, certlen, &exts, &extslen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if ((ret = x509_exts_get_ext_by_oid(exts, extslen, + OID_ce_crl_distribution_points, &critical, &val, &vlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_uri_as_distribution_points_from_der(&uri, &urilen, + &reason, &crl_issuer, &crl_issuer_len, &val, &vlen) != 1 + || asn1_length_is_zero(vlen) != 1) { + error_print(); + return -1; + } + if (!uri) { + *crl = NULL; + *crl_len = 0; + return 0; + } + if (x509_crl_new_from_uri(crl, crl_len, uri, urilen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_check_crl(const uint8_t *cert, size_t certlen, const uint8_t *cacert, size_t cacertlen, + const char *ca_signer_id, size_t ca_signer_id_len) +{ + int ret = -1; + uint8_t *crl = NULL; + size_t crl_len = 0; + const uint8_t *crl_issuer; + size_t crl_issuer_len; + + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + + time_t revoke_date; + const uint8_t *crl_entry_exts; + size_t crl_entry_exts_len; + + // download CRL and do basic validation + if (x509_crl_new_from_cert(&crl, &crl_len, cert, certlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_check(crl, crl_len, time(NULL)) != 1) { + error_print(); + goto end; + } + + if (x509_cert_get_issuer_and_serial_number(cert, certlen, &issuer, &issuer_len, &serial, &serial_len) != 1) { + error_print(); + goto end; + } + + // make sure CRL's issuer is the certificate issuer + if (x509_crl_get_issuer(crl, crl_len, &crl_issuer, &crl_issuer_len) != 1) { + error_print(); + goto end; + } + if (x509_name_equ(issuer, issuer_len, crl_issuer, crl_issuer_len) != 1) { + error_print(); + goto end; + } + + // verify CRL + if (x509_crl_verify_by_ca_cert(crl, crl_len, cacert, cacertlen, ca_signer_id, ca_signer_id_len) != 1) { + error_print(); + goto end; + } + + // check if the certificate in the CRL + if ((ret = x509_crl_find_revoked_cert_by_serial_number(crl, crl_len, serial, serial_len, + &revoke_date, &crl_entry_exts, &crl_entry_exts_len)) < 0) { + error_print(); + goto end; + } + if (ret == 1) { + ret = -1; + error_print(); + goto end; + } + ret = 1; + +end: + if (crl) free(crl); + return ret; +} diff --git a/Core/GmSSL-3.1.1/src/x509_req.c b/Core/GmSSL-3.1.1/src/x509_req.c new file mode 100644 index 0000000..d8d261b --- /dev/null +++ b/Core/GmSSL-3.1.1/src/x509_req.c @@ -0,0 +1,333 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int x509_request_info_to_der( + int version, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *attrs, size_t attrs_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (version != X509_version_v1) { + error_print(); + return -1; + } + if (asn1_int_to_der(version, NULL, &len) != 1 + || asn1_sequence_to_der(subject, subject_len, NULL, &len) != 1 + || x509_public_key_info_to_der(subject_public_key, NULL, &len) != 1 + || asn1_implicit_set_to_der(0, attrs, attrs_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || asn1_sequence_to_der(subject, subject_len, out, outlen) != 1 + || x509_public_key_info_to_der(subject_public_key, out, outlen) != 1 + || asn1_implicit_set_to_der(0, attrs, attrs_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_request_info_from_der( + int *version, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **attrs, size_t *attrs_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || asn1_sequence_from_der(subject, subject_len, &d, &dlen) != 1 + || x509_public_key_info_from_der(subject_public_key, &d, &dlen) != 1 + || asn1_implicit_set_from_der(0, attrs, attrs_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + /* + if (*version != X509_version_v1) { + error_print(); + return -1; + } + */ + return 1; +} + +int x509_request_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, ival; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&ival, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %s (%d)\n", x509_version_name(ival), ival); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "subject", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_info_print(fp, fmt, ind, "subjectPublicKeyInfo", p, len); + if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_attributes_print(fp, fmt, ind, "attributes", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +static int x509_request_from_der( + int *version, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **attrs, size_t *attrs_len, + int *signature_algor, + const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_request_info_from_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, &d, &dlen) != 1 + || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 + || asn1_bit_octets_from_der(sig, siglen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +static int x509_request_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_request_info_print(fp, fmt, ind, "certificationRequestInfo", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "signature: ", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_req_sign_to_der( + int version, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *attrs, size_t attrs_len, + int signature_algor, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + uint8_t *tbs; + int sig_alg = OID_sm2sign_with_sm3; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen = SM2_signature_typical_size; + + if (x509_request_info_to_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, NULL, &len) != 1 + || x509_signature_algor_to_der(sig_alg, NULL, &len) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + if (out && *out) { + tbs = *out; + } + if (x509_request_info_to_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, out, outlen) != 1) { + error_print(); + return -1; + } + if (out && *out) { + SM2_SIGN_CTX sign_ctx; + if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 + || sm2_sign_update(&sign_ctx, tbs, *out - tbs) != 1 + || sm2_sign_finish_fixlen(&sign_ctx, siglen, sig) != 1) { + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + error_print(); + return -1; + } + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + } + if (x509_signature_algor_to_der(sig_alg, out, outlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_req_verify(const uint8_t *a, size_t alen, const char *signer_id, size_t signer_id_len) +{ + SM2_KEY public_key; + + if (x509_req_get_details(a, alen, + NULL, NULL, NULL, &public_key, NULL, NULL, NULL, NULL, NULL) != 1) { + error_print(); + return -1; + } + if (x509_signed_verify(a, alen, &public_key, signer_id, signer_id_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_req_get_details(const uint8_t *a, size_t alen, + int *version, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **attributes, size_t *attributes_len, + int *signature_algor, + const uint8_t **signature, size_t *signature_len) +{ + int ver; + const uint8_t *subj; + size_t subj_len; + SM2_KEY pub_key; + const uint8_t *attrs; + size_t attrs_len; + int sig_alg; + const uint8_t *sig; + size_t siglen; + + if (x509_request_from_der(&ver, &subj, &subj_len, &pub_key, &attrs, &attrs_len, + &sig_alg, &sig, &siglen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + if (version) *version = ver; + if (subject) *subject = subj; + if (subject_len) *subject_len = subj_len; + if (subject_public_key) *subject_public_key = pub_key; + if (attributes) *attributes = attrs; + if (attributes_len) *attributes_len = attrs_len; + if (signature_algor) *signature_algor = sig_alg; + if (signature) *signature = sig; + if (signature_len) *signature_len = siglen; + return 1; +} + +int x509_req_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen) +{ + int ret; + if (x509_req_get_details(a, alen, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_any_to_der(a, alen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_req_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen) +{ + int ret; + if ((ret = asn1_any_from_der(a, alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_req_get_details(*a, *alen, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_req_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + const uint8_t *d; + size_t dlen; + + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + x509_request_print(fp, fmt, ind, label, d, dlen); + return 1; +} + +int x509_req_to_pem(const uint8_t *a, size_t alen, FILE *fp) +{ + if (x509_req_get_details(a, alen, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, "CERTIFICATE REQUEST", a, alen) <= 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_req_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp) +{ + if (pem_read(fp, "CERTIFICATE REQUEST", a, alen, maxlen) != 1) { + error_print(); + return -1; + } + if (x509_req_get_details(a, *alen, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != 1) { + error_print(); + return -1; + } + return 1; +} diff --git a/Core/GmSSL-3.1.1/src/zuc.c b/Core/GmSSL-3.1.1/src/zuc.c new file mode 100644 index 0000000..fafbb02 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/zuc.c @@ -0,0 +1,604 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +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 = (uint32_t)((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_init(ZUC_STATE *state, const uint8_t *user_key, const uint8_t *iv) +{ + ZUC_UINT31 *LFSR = state->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(); + + state->R1 = R1; + state->R2 = R2; +} + +uint32_t zuc_generate_keyword(ZUC_STATE *state) +{ + ZUC_UINT31 *LFSR = state->LFSR; + uint32_t R1 = state->R1; + uint32_t R2 = state->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(); + + state->R1 = R1; + state->R2 = R2; + + return Z; +} + +void zuc_generate_keystream(ZUC_STATE *state, size_t nwords, uint32_t *keystream) +{ + ZUC_UINT31 *LFSR = state->LFSR; + uint32_t R1 = state->R1; + uint32_t R2 = state->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(); + } + + state->R1 = R1; + state->R2 = R2; +} + +void zuc_encrypt(ZUC_STATE *state, const uint8_t *in, size_t inlen, uint8_t *out) +{ + ZUC_UINT31 *LFSR = state->LFSR; + uint32_t R1 = state->R1; + uint32_t R2 = state->R2; + uint32_t X0, X1, X2, X3; + uint32_t W1, W2, U, V; + uint32_t Z; + uint8_t block[4]; + size_t nwords = inlen / sizeof(uint32_t); + size_t i; + + for (i = 0; i < nwords; i ++) { + BitReconstruction4(X0, X1, X2, X3); + Z = X3 ^ F(X0, X1, X2); + LFSRWithWorkMode(); + PUTU32(block, Z); + gmssl_memxor(out, in, block, sizeof(block)); + in += sizeof(block); + out += sizeof(block); + } + if (inlen % 4) { + // TODO: use assert to make sure this branch should not be arrived + BitReconstruction4(X0, X1, X2, X3); + Z = X3 ^ F(X0, X1, X2); + LFSRWithWorkMode(); + PUTU32(block, Z); + gmssl_memxor(out, in, block, inlen % 4); + } + + state->R1 = R1; + state->R2 = R2; +} + +void zuc_mac_init(ZUC_MAC_CTX *ctx, const uint8_t key[16], const uint8_t iv[16]) +{ + memset(ctx, 0, sizeof(*ctx)); + zuc_init((ZUC_STATE *)ctx, key, iv); + ctx->K0 = zuc_generate_keyword((ZUC_STATE *)ctx); +} + +void zuc_mac_update(ZUC_MAC_CTX *ctx, const uint8_t *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 uint8_t *data, size_t nbits, uint8_t 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); + + memset(ctx, 0, sizeof(*ctx)); +} + + +typedef uint8_t 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_STATE *key, const uint8_t K[32], + const uint8_t 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_init(ZUC_STATE *key, const uint8_t K[32], + const uint8_t IV[23]) +{ + zuc256_set_mac_key(key, K, IV, 0); +} + +void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const uint8_t key[32], + const uint8_t 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_STATE *)ctx, key, iv, macbits); + zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->T); + zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->K0); + ctx->macbits = (macbits/32) * 32; +} + +void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const uint8_t *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_STATE *)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_STATE *)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 uint8_t *data, size_t nbits, uint8_t *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_STATE *)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; + } + + memset(ctx, 0, sizeof(*ctx)); +} diff --git a/Core/GmSSL-3.1.1/src/zuc_modes.c b/Core/GmSSL-3.1.1/src/zuc_modes.c new file mode 100644 index 0000000..75f89b7 --- /dev/null +++ b/Core/GmSSL-3.1.1/src/zuc_modes.c @@ -0,0 +1,141 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +static void zuc_set_eea_key(ZUC_STATE *key, const uint8_t user_key[16], + ZUC_UINT32 count, ZUC_UINT5 bearer, ZUC_BIT direction) +{ + uint8_t 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_init(key, user_key, iv); +} + +void zuc_eea_encrypt(const ZUC_UINT32 *in, ZUC_UINT32 *out, size_t nbits, + const uint8_t key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, + ZUC_BIT direction) +{ + ZUC_STATE 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))); + } +} + +static void zuc_set_eia_iv(uint8_t 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); +} + +ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits, + const uint8_t key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, + ZUC_BIT direction) +{ + ZUC_MAC_CTX ctx; + uint8_t iv[16]; + uint8_t mac[4]; + zuc_set_eia_iv(iv, count, bearer, direction); + zuc_mac_init(&ctx, key, iv); + zuc_mac_finish(&ctx, (uint8_t *)data, nbits, mac); + return GETU32(mac); +} + +#define ZUC_BLOCK_SIZE 4 + +int zuc_encrypt_init(ZUC_CTX *ctx, const uint8_t key[ZUC_KEY_SIZE], const uint8_t iv[ZUC_IV_SIZE]) +{ + if (!ctx || !key || !iv) { + error_print(); + return -1; + } + zuc_init(&ctx->zuc_state, key, iv); + memset(ctx->block, 0, ZUC_BLOCK_SIZE); + ctx->block_nbytes = 0; + return 1; +} + +int zuc_encrypt_update(ZUC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t left; + size_t nblocks; + size_t len; + + if (ctx->block_nbytes >= ZUC_BLOCK_SIZE) { + error_print(); + return -1; + } + *outlen = 0; + if (ctx->block_nbytes) { + left = ZUC_BLOCK_SIZE - ctx->block_nbytes; + if (inlen < left) { + memcpy(ctx->block + ctx->block_nbytes, in, inlen); + ctx->block_nbytes += inlen; + return 1; + } + memcpy(ctx->block + ctx->block_nbytes, in, left); + zuc_encrypt(&ctx->zuc_state, ctx->block, ZUC_BLOCK_SIZE, out); + in += left; + inlen -= left; + out += ZUC_BLOCK_SIZE; + *outlen += ZUC_BLOCK_SIZE; + } + if (inlen >= ZUC_BLOCK_SIZE) { + nblocks = inlen / ZUC_BLOCK_SIZE; + len = nblocks * ZUC_BLOCK_SIZE; + zuc_encrypt(&ctx->zuc_state, in, len, out); + in += len; + inlen -= len; + out += len; + *outlen += len; + } + if (inlen) { + memcpy(ctx->block, in, inlen); + } + ctx->block_nbytes = inlen; + return 1; +} + +int zuc_encrypt_finish(ZUC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (ctx->block_nbytes >= ZUC_BLOCK_SIZE) { + error_print(); + return -1; + } + zuc_encrypt(&ctx->zuc_state, ctx->block, ctx->block_nbytes, out); + *outlen = ctx->block_nbytes; + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/aeadtest.c b/Core/GmSSL-3.1.1/tests/aeadtest.c new file mode 100644 index 0000000..a7eb7a9 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/aeadtest.c @@ -0,0 +1,385 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_aead_sm4_cbc_sm3_hmac(void) +{ + SM4_CBC_SM3_HMAC_CTX aead_ctx; + uint8_t key[16 + 32]; + uint8_t iv[16]; + uint8_t aad[29]; + uint8_t plain[71]; + size_t plainlen = sizeof(plain); + uint8_t cipher[256]; + size_t cipherlen = 0; + uint8_t buf[256]; + size_t buflen = 0; + + size_t lens[] = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }; + uint8_t *in = plain; + uint8_t *out = cipher; + size_t inlen, outlen; + size_t i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(aad, sizeof(aad)); + rand_bytes(plain, plainlen); + + if (sm4_cbc_sm3_hmac_encrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + error_print(); + return -1; + } + for (i = 0; plainlen; i++) { + assert(i < sizeof(lens)/sizeof(lens[0])); + + inlen = plainlen < lens[i] ? plainlen : lens[i]; + if (sm4_cbc_sm3_hmac_encrypt_update(&aead_ctx, in, inlen, out, &outlen) != 1) { + error_print(); + return -1; + } + in += inlen; + plainlen -= inlen; + out += outlen; + cipherlen += outlen; + } + if (sm4_cbc_sm3_hmac_encrypt_finish(&aead_ctx, out, &outlen) != 1) { + error_print(); + return -1; + } + out += outlen; + cipherlen += outlen; + + format_bytes(stdout, 0, 4, "plaintext ", plain, sizeof(plain)); + format_bytes(stdout, 0, 4, "ciphertext", cipher, cipherlen); + + { + SM4_KEY sm4_key; + SM3_HMAC_CTX sm3_hmac_ctx; + uint8_t tmp[256]; + size_t tmplen; + + sm4_set_encrypt_key(&sm4_key, key); + if (sm4_cbc_padding_encrypt(&sm4_key, iv, plain, sizeof(plain), tmp, &tmplen) != 1) { + error_print(); + return -1; + } + + sm3_hmac_init(&sm3_hmac_ctx, key + 16, 32); + sm3_hmac_update(&sm3_hmac_ctx, aad, sizeof(aad)); + sm3_hmac_update(&sm3_hmac_ctx, tmp, tmplen); + sm3_hmac_finish(&sm3_hmac_ctx, tmp + tmplen); + tmplen += 32; + + format_bytes(stdout, 0, 4, "ciphertext", tmp, tmplen); + + if (cipherlen != tmplen + || memcmp(cipher, tmp, tmplen) != 0) { + error_print(); + return -1; + } + } + + in = cipher; + out = buf; + + if (sm4_cbc_sm3_hmac_decrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + error_print(); + return -1; + } + for (i = sizeof(lens)/sizeof(lens[0]) - 1; cipherlen; i--) { + inlen = cipherlen < lens[i] ? cipherlen : lens[i]; + + if (sm4_cbc_sm3_hmac_decrypt_update(&aead_ctx, in, inlen, out, &outlen) != 1) { + error_print(); + return -1; + } + in += inlen; + cipherlen -= inlen; + out += outlen; + buflen += outlen; + } + if (sm4_cbc_sm3_hmac_decrypt_finish(&aead_ctx, out, &outlen) != 1) { + error_print(); + return -1; + } + out += outlen; + buflen += outlen; + + format_bytes(stdout, 0, 4, "plaintext ", buf, buflen); + + if (buflen != sizeof(plain)) { + error_print(); + return -1; + } + if (memcmp(buf, plain, sizeof(plain)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_aead_sm4_ctr_sm3_hmac(void) +{ + SM4_CTR_SM3_HMAC_CTX aead_ctx; + uint8_t key[16 + 32]; + uint8_t iv[16]; + uint8_t aad[29]; + uint8_t plain[71]; + size_t plainlen = sizeof(plain); + uint8_t cipher[256]; + size_t cipherlen = 0; + uint8_t buf[256]; + size_t buflen = 0; + + size_t lens[] = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }; + uint8_t *in = plain; + uint8_t *out = cipher; + size_t inlen, outlen; + size_t i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(aad, sizeof(aad)); + rand_bytes(plain, plainlen); + + if (sm4_ctr_sm3_hmac_encrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + error_print(); + return -1; + } + for (i = 0; plainlen; i++) { + assert(i < sizeof(lens)/sizeof(lens[0])); + + inlen = plainlen < lens[i] ? plainlen : lens[i]; + if (sm4_ctr_sm3_hmac_encrypt_update(&aead_ctx, in, inlen, out, &outlen) != 1) { + error_print(); + return -1; + } + in += inlen; + plainlen -= inlen; + out += outlen; + cipherlen += outlen; + } + if (sm4_ctr_sm3_hmac_encrypt_finish(&aead_ctx, out, &outlen) != 1) { + error_print(); + return -1; + } + out += outlen; + cipherlen += outlen; + + format_bytes(stdout, 0, 4, "plaintext ", plain, sizeof(plain)); + format_bytes(stdout, 0, 4, "ciphertext", cipher, cipherlen); + + { + SM4_KEY sm4_key; + uint8_t ctr[16]; + SM3_HMAC_CTX sm3_hmac_ctx; + uint8_t tmp[256]; + size_t tmplen; + + sm4_set_encrypt_key(&sm4_key, key); + memcpy(ctr, iv, 16); + + sm4_ctr_encrypt(&sm4_key, ctr, plain, sizeof(plain), tmp); + tmplen = sizeof(plain); + + sm3_hmac_init(&sm3_hmac_ctx, key + 16, 32); + sm3_hmac_update(&sm3_hmac_ctx, aad, sizeof(aad)); + sm3_hmac_update(&sm3_hmac_ctx, tmp, tmplen); + sm3_hmac_finish(&sm3_hmac_ctx, tmp + tmplen); + tmplen += 32; + + format_bytes(stdout, 0, 4, "ciphertext", tmp, tmplen); + + if (cipherlen != tmplen + || memcmp(cipher, tmp, tmplen) != 0) { + error_print(); + return -1; + } + } + + + in = cipher; + out = buf; + + if (sm4_ctr_sm3_hmac_decrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + error_print(); + return -1; + } + for (i = sizeof(lens)/sizeof(lens[0]) - 1; cipherlen; i--) { + inlen = cipherlen < lens[i] ? cipherlen : lens[i]; + + if (sm4_ctr_sm3_hmac_decrypt_update(&aead_ctx, in, inlen, out, &outlen) != 1) { + error_print(); + return -1; + } + in += inlen; + cipherlen -= inlen; + out += outlen; + buflen += outlen; + + } + if (sm4_ctr_sm3_hmac_decrypt_finish(&aead_ctx, out, &outlen) != 1) { + error_print(); + return -1; + } + out += outlen; + buflen += outlen; + + format_bytes(stdout, 0, 4, "plaintext ", buf, buflen); + + if (buflen != sizeof(plain)) { + error_print(); + return -1; + } + if (memcmp(buf, plain, sizeof(plain)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_aead_sm4_gcm(void) +{ + SM4_GCM_CTX aead_ctx; + uint8_t key[16]; + uint8_t iv[16]; + uint8_t aad[29]; + uint8_t plain[71]; + size_t plainlen = sizeof(plain); + uint8_t cipher[256]; + size_t cipherlen = 0; + uint8_t buf[256]; + size_t buflen = 0; + + size_t lens[] = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }; + uint8_t *in = plain; + uint8_t *out = cipher; + size_t inlen, outlen; + size_t i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(aad, sizeof(aad)); + rand_bytes(plain, plainlen); + + if (sm4_gcm_encrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad), GHASH_SIZE) != 1) { + error_print(); + return -1; + } + for (i = 0; plainlen; i++) { + assert(i < sizeof(lens)/sizeof(lens[0])); + + inlen = plainlen < lens[i] ? plainlen : lens[i]; + if (sm4_gcm_encrypt_update(&aead_ctx, in, inlen, out, &outlen) != 1) { + error_print(); + return -1; + } + in += inlen; + plainlen -= inlen; + out += outlen; + cipherlen += outlen; + } + if (sm4_gcm_encrypt_finish(&aead_ctx, out, &outlen) != 1) { + error_print(); + return -1; + } + out += outlen; + cipherlen += outlen; + + format_bytes(stdout, 0, 4, "plaintext ", plain, sizeof(plain)); + format_bytes(stdout, 0, 4, "ciphertext", cipher, cipherlen); + + { + SM4_KEY sm4_key; + uint8_t tmp[256]; + size_t tmplen; + + sm4_set_encrypt_key(&sm4_key, key); + + if (sm4_gcm_encrypt(&sm4_key, iv, sizeof(iv), aad, sizeof(aad), plain, sizeof(plain), + tmp, GHASH_SIZE, tmp + sizeof(plain)) != 1) { + error_print(); + return -1; + } + tmplen = sizeof(plain) + GHASH_SIZE; + + format_bytes(stdout, 0, 4, "ciphertext", tmp, tmplen); + + if (cipherlen != tmplen + || memcmp(cipher, tmp, tmplen) != 0) { + error_print(); + return -1; + } + } + + in = cipher; + out = buf; + + if (sm4_gcm_decrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad), GHASH_SIZE) != 1) { + error_print(); + return -1; + } + for (i = sizeof(lens)/sizeof(lens[0]) - 1; cipherlen; i--) { + inlen = cipherlen < lens[i] ? cipherlen : lens[i]; + + if (sm4_gcm_decrypt_update(&aead_ctx, in, inlen, out, &outlen) != 1) { + error_print(); + return -1; + } + in += inlen; + cipherlen -= inlen; + out += outlen; + buflen += outlen; + + } + if (sm4_gcm_decrypt_finish(&aead_ctx, out, &outlen) != 1) { + error_print(); + return -1; + } + out += outlen; + buflen += outlen; + + format_bytes(stdout, 0, 4, "plaintext ", buf, buflen); + + if (buflen != sizeof(plain)) { + error_print(); + return -1; + } + if (memcmp(buf, plain, sizeof(plain)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_aead_sm4_cbc_sm3_hmac() != 1) { error_print(); return -1; } + if (test_aead_sm4_ctr_sm3_hmac() != 1) { error_print(); return -1; } + if (test_aead_sm4_gcm() != 1) { error_print(); return -1; } + printf("%s all tests passed!\n", __FILE__); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/aestest.c b/Core/GmSSL-3.1.1/tests/aestest.c new file mode 100644 index 0000000..0dbce1d --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/aestest.c @@ -0,0 +1,375 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +int test_aes(void) +{ + AES_KEY aes_key; + + /* 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"); + return -1; + } 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"); + return -1; + } 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"); + return -1; + } 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"); + return -1; + } 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"); + return -1; + } else { + printf("ok\n"); + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_aes_ctr(void) +{ + // NIST SP 800-38A F.5.1 + char *hex_key = "2b7e151628aed2a6abf7158809cf4f3c"; + char *hex_ctr = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + char *hex_msg = "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"; + char *hex_out = "874d6191b620e3261bef6864990db6ce" + "9806f66b7970fdff8617187bb9fffdff" + "5ae4df3edbd5d35e5b4f09020db03eab" + "1e031dda2fbe03d1792170a0f3009cee"; + + AES_KEY aes_key; + uint8_t key[32]; + uint8_t ctr[16]; + uint8_t msg[64]; + uint8_t out[64]; + uint8_t buf[64]; + size_t keylen, ctrlen, msglen, outlen, buflen; + + hex_to_bytes(hex_key, strlen(hex_key), key, &keylen); + hex_to_bytes(hex_ctr, strlen(hex_ctr), ctr, &ctrlen); + hex_to_bytes(hex_msg, strlen(hex_msg), msg, &msglen); + hex_to_bytes(hex_out, strlen(hex_out), out, &outlen); + + aes_set_encrypt_key(&aes_key, key, keylen); + aes_ctr_encrypt(&aes_key, ctr, msg, msglen, buf); + buflen = msglen; + + printf("aes ctr test 1 "); + if (memcmp(buf, out, outlen) != 0) { + printf("failed\n"); + format_bytes(stdout, 0, 0, "aes_ctr(msg) = ", buf, buflen); + format_bytes(stdout, 0, 0, " != ", out, outlen); + return -1; + } else { + printf("ok\n"); + } + + printf("aes ctr test 2 "); + hex_to_bytes(hex_ctr, strlen(hex_ctr), ctr, &ctrlen); + aes_ctr_decrypt(&aes_key, ctr, buf, buflen, buf); + if (memcmp(buf, msg, msglen) != 0) { + printf("failed\n"); + format_bytes(stdout, 0, 0, "msg = ", msg, msglen); + format_bytes(stdout, 0, 0, " = ", buf, buflen); + return -1; + } else { + printf("ok\n"); + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + +struct { + char *K; + char *P; + char *A; + char *IV; + char *C; + char *T; +} aes_gcm_tests[] = { + // test 1 + { + "00000000000000000000000000000000", + "", + "", + "000000000000000000000000", + "", + "58e2fccefa7e3061367f1d57a4e7455a", + }, + // test 2 + { + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "", + "000000000000000000000000", + "0388dace60b6a392f328c2b971b2fe78", + "ab6e47d42cec13bdf53a67b21257bddf", + }, + // test 3 + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b391aafd255", + "", + "cafebabefacedbaddecaf888", + "42831ec2217774244b7221b784d0d49c" + "e3aa212f2c02a4e035c17e2329aca12e" + "21d514b25466931c7d8f6a5aac84aa05" + "1ba30b396a0aac973d58e091473f5985", + "4d5c2af327cd64a62cf35abd2ba6fab4", + }, + // test 4 + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "cafebabefacedbaddecaf888", + "42831ec2217774244b7221b784d0d49c" + "e3aa212f2c02a4e035c17e2329aca12e" + "21d514b25466931c7d8f6a5aac84aa05" + "1ba30b396a0aac973d58e091", + "5bc94fbc3221a5db94fae95ae7121a47", + }, + // test 5 + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "cafebabefacedbad", + "61353b4c2806934a777ff51fa22a4755" + "699b2a714fcdc6f83766e5f97b6c7423" + "73806900e49f24b22b097544d4896b42" + "4989b5e1ebac0f07c23f4598", + "3612d2e79e3b0785561be14aaca2fccb", + }, + // test 6 + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a" + "86a7a9531534f7da2e4c303d8a318a72" + "1c3c0c95956809532fcf0e2449a6b525" + "b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "9313225df88406e555909c5aff5269aa" + "6a7a9538534f7da1e4c303d2a318a728" + "c3c0c95156809539fcf0e2429a6b5254" + "16aedbf5a0de6a57a637b39b", + "8ce24998625615b603a033aca13fb894" + "be9112a5c3a211a8ba262a3cca7e2ca7" + "01e4a9a4fba43c90ccdcb281d48c7c6f" + "d62875d2aca417034c34aee5", + "619cc5aefffe0bfa462af43c1699d050", + }, + // test 7 + { + "00000000000000000000000000000000" + "0000000000000000", + "", + "", + "000000000000000000000000", + "", + "cd33b28ac773f74ba00ed1f312572435", + }, +}; + +int test_aes_gcm(void) +{ + int err = 0; + uint8_t K[32]; + uint8_t P[64]; + uint8_t A[32]; + uint8_t IV[64]; + uint8_t C[64]; + uint8_t T[16]; + size_t Klen, Plen, Alen, IVlen, Clen, Tlen; + + AES_KEY aes_key; + uint8_t out[64]; + uint8_t tag[16]; + uint8_t buf[64]; + int i; + + for (i = 0; i < sizeof(aes_gcm_tests)/sizeof(aes_gcm_tests[0]); i++) { + hex_to_bytes(aes_gcm_tests[i].K, strlen(aes_gcm_tests[i].K), K, &Klen); + hex_to_bytes(aes_gcm_tests[i].P, strlen(aes_gcm_tests[i].P), P, &Plen); + hex_to_bytes(aes_gcm_tests[i].A, strlen(aes_gcm_tests[i].A), A, &Alen); + hex_to_bytes(aes_gcm_tests[i].IV, strlen(aes_gcm_tests[i].IV), IV, &IVlen); + hex_to_bytes(aes_gcm_tests[i].C, strlen(aes_gcm_tests[i].C), C, &Clen); + hex_to_bytes(aes_gcm_tests[i].T, strlen(aes_gcm_tests[i].T), T, &Tlen); + + aes_set_encrypt_key(&aes_key, K, Klen); + aes_gcm_encrypt(&aes_key, IV, IVlen, A, Alen, P, Plen, out, Tlen, tag); + + printf("aes gcm test %d ", i + 1); + if (aes_gcm_decrypt(&aes_key, IV, IVlen, A, Alen, out, Plen, tag, Tlen, buf) != 1 + || memcmp(buf, P, Plen) != 0) { + printf("failed\n"); + format_print(stdout, 0, 2, "K = %s\n", aes_gcm_tests[i].K); + format_print(stdout, 0, 2, "P = %s\n", aes_gcm_tests[i].P); + format_print(stdout, 0, 2, "A = %s\n", aes_gcm_tests[i].A); + format_print(stdout, 0, 2, "IV = %s\n", aes_gcm_tests[i].IV); + format_print(stdout, 0, 2, "C = %s\n", aes_gcm_tests[i].C); + format_bytes(stdout, 0, 2, " = ", out, Plen); + format_print(stdout, 0, 2, "T = %s\n", aes_gcm_tests[i].T); + format_bytes(stdout, 0, 2, " = ", tag, Tlen); + return -1; + } else { + printf("ok\n"); + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_aes() != 1) goto err; + if (test_aes_ctr() != 1) goto err; + if (test_aes_gcm() != 1) goto err; + printf("%s all tests passed!\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/asn1test.c b/Core/GmSSL-3.1.1/tests/asn1test.c new file mode 100644 index 0000000..4bbcff2 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/asn1test.c @@ -0,0 +1,829 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static void print_buf(const uint8_t *a, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + printf("%02x ", a[i]); + } + printf("\n"); +} + +static void print_integer(const uint8_t *a, size_t alen) +{ + size_t i; + printf("integer = "); + for (i = 0; i < alen; i++) { + printf("%02x", a[i]); + } + printf("\n"); +} + +static void print_bits(const uint8_t *bits, size_t nbits) +{ + size_t i; + printf("bits (%zu) = ", nbits); + for (i = 0; i < (nbits + 7)/8; i++) { + printf("%02x", bits[i]); + } + printf("\n"); +} + +static void print_octets(const uint8_t *o, size_t olen) +{ + size_t i; + printf("octets (%zu) = ", olen); + for (i = 0; i < olen; i++) { + printf("%02x", o[i]); + } + printf("\n"); +} + +static int test_asn1_tag(void) +{ + int i; + format_print(stderr, 0, 0, "Tags:\n"); + for (i = 1; i <= 13; i++) { + format_print(stderr, 0, 4, "%s (0x%02x)\n", asn1_tag_name(i), i); + } + for (i = 18; i <= 30; i++) { + format_print(stderr, 0, 4, "%s (0x%02x)\n", asn1_tag_name(i), i); + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_length(void) +{ + size_t tests[] = { + 0, + 5, + 127, + 128, + 256, + 344, + 65537, + 1<<23, + INT_MAX, // INT_MAX = 2^31 - 1 + //(size_t)1<<31, // default int value of (1<<31) is -2^31, 2^31 is larger than the INT_MAX limit + }; + size_t length; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "Length:\n"); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_length_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + int ret; + ret = asn1_length_from_der(&length, &cp, &len); + if (ret != 1 && ret != -2) { + error_print(); + return -1; + } + if (length != tests[i]) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%zd\n", length); + } + if (len != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_boolean(void) +{ + int tests[] = {0, 1}; + int val; + uint8_t buf[128] = {0}; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_BOOLEAN)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_boolean_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_boolean_from_der(&val, &cp, &len) != 1 + || asn1_check(val == tests[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", val ? "true" : "false"); + } + if (len != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_int(void) +{ + int tests[] = { + 0, + 1, + 127, + 128, + 65535, + 65537, + 1<<23, + 1<<30, + }; + int val; + uint8_t buf[256] = {0}; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_INTEGER)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_int_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + // 测试 -1 表示默认不编码 + if (asn1_int_to_der(-1, &p, &len) != 0) { + error_print(); + return -1; + } + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_int_from_der(&val, &cp, &len) != 1 + || asn1_check(val == tests[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%d\n", val); + } + if (len != 0) { + error_print(); + return -1; + } + + // 测试返回0时是否对val值做初始化 + if (asn1_int_from_der(&val, &cp, &len) != 0) { + error_print(); + return -1; + } + if (val != -1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_bits(void) +{ + int tests[] = { + 0x01, + 0x02, + 0x03, + 0x7f, + 0xfe, + 0xff, + 0xffff, + 0xfffff, + }; + uint8_t der[] = { + 0x03,0x02,0x07,0x80, + 0x03,0x02,0x06,0x40, + 0x03,0x02,0x06,0xC0, + 0x03,0x02,0x01,0xFE, + 0x03,0x02,0x00,0x7F, + 0x03,0x02,0x00,0xFF, + 0x03,0x03,0x00,0xFF,0xFF, + 0x03,0x04,0x04,0xFF,0xFF,0xF0, + }; + int bits; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_BIT_STRING)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_bits_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + if (sizeof(der) != len + || memcmp(der, buf, len) != 0) { + error_print(); + return -1; + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_bits_from_der(&bits, &cp, &len) != 1 + || asn1_check(bits == tests[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%x\n", bits); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_null(void) +{ + uint8_t buf[256] = {0}; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "NULL\n"); + for (i = 0; i < 3; i++) { + if (asn1_null_to_der(&p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < 3; i++) { + if (asn1_null_from_der(&cp, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", asn1_tag_name(ASN1_TAG_NULL)); + } + if (asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_object_identifier(void) +{ + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_OBJECT_IDENTIFIER)); + + // test 1 + { + char *name = "sm2"; + uint32_t oid[] = { 1,2,156,10197,1,301 }; + uint8_t der[] = { 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D }; + uint32_t nodes[32]; + size_t nodes_cnt; + uint8_t buf[128]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + format_print(stderr, 0 ,4, "%s ", name); + if (asn1_object_identifier_to_der(oid, sizeof(oid)/sizeof(int), &p, &len) != 1 + || asn1_check(len == sizeof(der)) != 1 + || asn1_check(memcmp(buf, der, sizeof(der)) == 0) != 1 + || asn1_object_identifier_from_der(nodes, &nodes_cnt, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1 + || asn1_object_identifier_equ(nodes, nodes_cnt, oid, sizeof(oid)/sizeof(int)) != 1) { + fprintf(stderr, "failed\n"); + error_print(); + return -1; + } else { + printf("ok\n"); + } + } + + // test 2 + { + char *name = "x9.62-ecPublicKey"; + uint32_t oid[] = { 1,2,840,10045,2,1 }; + uint8_t der[] = { 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01 }; + uint8_t buf[128]; + uint32_t nodes[32]; + size_t nodes_cnt; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + format_print(stderr, 0 ,4, "%s ", name); + if (asn1_object_identifier_to_der(oid, sizeof(oid)/sizeof(int), &p, &len) != 1 + || asn1_check(len == sizeof(der)) != 1 + || asn1_check(memcmp(buf, der, sizeof(der)) == 0) != 1 + || asn1_object_identifier_from_der(nodes, &nodes_cnt, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1 + || asn1_object_identifier_equ(nodes, nodes_cnt, oid, sizeof(oid)/sizeof(int)) != 1) { + fprintf(stderr, "failed\n"); + error_print(); + return -1; + } else { + printf("ok\n"); + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_printable_string(void) +{ + char *tests[] = { + "hello", + "world", + "Just do it", // string "Just do it!" include invalid '!' + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_PrintableString)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_printable_string_to_der(tests[i], strlen(tests[i]), &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + const char *d; + size_t dlen; + if (asn1_printable_string_from_der(&d, &dlen, &cp, &len) != 1 + || strlen(tests[i]) != dlen + || memcmp(tests[i], d, dlen) != 0) { + error_print(); + return -1; + } + format_string(stderr, 0, 4, "", (uint8_t *)d, dlen); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_printable_string_check(void) +{ + char *printable_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?"; + if (asn1_string_is_printable_string(printable_str, strlen(printable_str)) != 1) { + error_print(); + return -1; + } + + if (asn1_string_is_printable_string("a*b", 3) == 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_printable_string_case_ignore_match(void) +{ + if (asn1_printable_string_case_ignore_match("HELLO", 5, "WORLD", 5) == 1) { + error_print(); + return -1; + } + + if (asn1_printable_string_case_ignore_match("HELLO", 5, "HELLO", 5) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match("HELLO", 5, "hello", 5) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" HELLO", 7, "hello", 5) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" HELLO", 7, "hello ", 8) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" A2b ", 5, " a2B ", 7) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" ", 5, " ", 7) != 1) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_utf8_string(void) +{ + char *tests[] = { + "hello", + "world", + "Just do it!", + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_UTF8String)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_utf8_string_to_der(tests[i], strlen(tests[i]), &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + const char *d; + size_t dlen; + if (asn1_utf8_string_from_der(&d, &dlen, &cp, &len) != 1 + || strlen(tests[i]) != dlen + || memcmp(tests[i], d, dlen) != 0) { + error_print(); + return -1; + } + format_string(stderr, 0, 4, "", (uint8_t *)d, dlen); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_ia5_string(void) +{ + char *tests[] = { + "hello", + "world", + "Just do it!", + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_IA5String)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_ia5_string_to_der(tests[i], strlen(tests[i]), &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + const char *d; + size_t dlen; + if (asn1_ia5_string_from_der(&d, &dlen, &cp, &len) != 1 + || strlen(tests[i]) != dlen + || memcmp(tests[i], d, dlen) != 0) { + error_print(); + return -1; + } + format_string(stderr, 0, 4, "", (uint8_t *)d, dlen); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_time(void) +{ + time_t tval = 0; + printf("%s", ctime(&tval)); + time(&tval); + printf("%s", ctime(&tval)); + + printf("%08x%08x\n", (uint32_t)(tval >> 32), (uint32_t)tval); + + return 1; +} + +static int test_asn1_time(void) +{ + time_t tests[] = { + 0, + 31*86400, + (31+28)*86400, + }; + char *utc_time[] = { + "700101000000Z", + "700201000000Z", + "700301000000Z", + }; + char *gen_time[] = { + "19700101000000Z", + "19700201000000Z", + "19700301000000Z", + }; + time_t cur = time(NULL); + time_t ts; + char str[16] = {0}; + int i; + + if (asn1_time_to_str(0, cur, str) != 1 + || asn1_time_from_str(0, &ts, str) != 1 + || ts != cur) { + error_print(); + return -1; + } + + if (asn1_time_to_str(1, cur, str) != 1 + || asn1_time_from_str(1, &ts, str) != 1 + || ts != cur) { + error_print(); + return -1; + } + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + memset(str, 0, sizeof(str)); + if (asn1_time_to_str(1, tests[i], str) != 1 + || strcmp(str, utc_time[i]) != 0) { + error_print(); + return -1; + } + + memset(str, 0, sizeof(str)); + if (asn1_time_to_str(0, tests[i], str) != 1 + || strcmp(str, gen_time[i]) != 0) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_time_limits(void) +{ + char *tests[] = { + "20491231235959Z", + "20500101000000Z", + "99991231235959Z", + }; + size_t i; + + time_t tv[sizeof(tests)/sizeof(tests[0])]; + char str[16] = {0}; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_time_from_str(0, &tv[i], tests[i]) != 1) { + error_print(); + return -1; + } + fprintf(stderr, " %s: %lld\n", tests[i], (long long)tv[i]); + } + if (tv[0] + 1 != tv[1]) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_utc_time(void) +{ + time_t tests[] = { + 0, + 0, + 1<<30, + }; + time_t tv; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + time(&tests[1]); + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_UTCTime)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_utc_time_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_utc_time_from_der(&tv, &cp, &len) != 1 + || asn1_check(tv == tests[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s", ctime(&tv)); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_generalized_time(void) +{ + time_t tests[] = { + 0, + 1<<30, + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + size_t i; + + time(&tests[0]); + + format_print(stderr, 0, 0, "%s\n", asn1_tag_name(ASN1_TAG_GeneralizedTime)); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (asn1_generalized_time_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + time_t tv; + if (asn1_generalized_time_from_der(&tv, &cp, &len) != 1 + || asn1_check(tv == tests[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s", ctime(&tv)); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_from_der_null_args(void) +{ + uint8_t buf[100]; + const uint8_t *cp = NULL; + size_t len = 100; + + int val; + const char *str; + size_t dlen; + time_t t; + uint32_t nodes[32]; + size_t nodes_cnt; + + fprintf(stderr, "%s: *inlen = 0\n", __FUNCTION__); + cp = buf; + len = 0; + if (asn1_boolean_from_der(&val, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_int_from_der(&val, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_bits_from_der(&val, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_null_from_der(&cp, &len) != 0) { error_print(); return -1; } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_utf8_string_from_der(&str, &dlen, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_printable_string_from_der(&str, &dlen, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_ia5_string_from_der(&str, &dlen, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_utc_time_from_der(&t, &cp, &len) != 0) { error_print(); return -1; } + if (asn1_generalized_time_from_der(&t, &cp, &len) != 0) { error_print(); return -1; } + fprintf(stderr, "%s: result = NULL\n", __FUNCTION__); + + cp = NULL; + len = 100; + if (asn1_boolean_from_der(NULL, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_int_from_der(NULL, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_bits_from_der(NULL, &cp, &len) != -1) { error_print(); return -1; } + //if (asn1_null_from_der(&cp, &len) != -1) { error_print(); return -1; } + if (asn1_object_identifier_from_der(NULL, &nodes_cnt, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_utf8_string_from_der(NULL, &dlen, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_printable_string_from_der(NULL, &dlen, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_ia5_string_from_der(NULL, &dlen, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_utc_time_from_der(NULL, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_generalized_time_from_der(NULL, &cp, &len) != -1) { error_print(); return -1; } + + fprintf(stderr, "%s: *inlen = 0\n", __FUNCTION__); + cp = buf; + len = 0; + if (asn1_boolean_from_der(&val, &cp, &len) != 0) { error_print(); return -1; } + fprintf(stderr, "%s: in = NULL\n", __FUNCTION__); + len = 100; + if (asn1_boolean_from_der(&val, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_int_from_der(&val, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_bits_from_der(&val, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_null_from_der(NULL, &len) != -1) { error_print(); return -1; } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_utf8_string_from_der(&str, &dlen, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_printable_string_from_der(&str, &dlen, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_ia5_string_from_der(&str, &dlen, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_utc_time_from_der(&t, NULL, &len) != -1) { error_print(); return -1; } + if (asn1_generalized_time_from_der(&t, NULL, &len) != -1) { error_print(); return -1; } + + fprintf(stderr, "%s: inlen = NULL\n", __FUNCTION__); + cp = buf; + if (asn1_boolean_from_der(&val, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_int_from_der(&val, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_bits_from_der(&val, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_null_from_der(&cp, NULL) != -1) { error_print(); return -1; } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_utf8_string_from_der(&str, &dlen, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_printable_string_from_der(&str, &dlen, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_ia5_string_from_der(&str, &dlen, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_utc_time_from_der(&t, &cp, NULL) != -1) { error_print(); return -1; } + if (asn1_generalized_time_from_der(&t, &cp, NULL) != -1) { error_print(); return -1; } + + fprintf(stderr, "%s: *in = NULL\n", __FUNCTION__); + cp = NULL; + len = 100; + if (asn1_boolean_from_der(&val, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_int_from_der(&val, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_bits_from_der(&val, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_null_from_der(&cp, &len) != -1) { error_print(); return -1; } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_utf8_string_from_der(&str, &dlen, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_printable_string_from_der(&str, &dlen, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_ia5_string_from_der(&str, &dlen, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_utc_time_from_der(&t, &cp, &len) != -1) { error_print(); return -1; } + if (asn1_generalized_time_from_der(&t, &cp, &len) != -1) { error_print(); return -1; } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_asn1_tag() != 1) goto err; + if (test_asn1_length() != 1) goto err; + if (test_asn1_boolean() != 1) goto err; + if (test_asn1_int() != 1) goto err; + if (test_asn1_bits() != 1) goto err; + if (test_asn1_null() != 1) goto err; + if (test_asn1_object_identifier() != 1) goto err; + if (test_asn1_printable_string() != 1) goto err; + if (test_asn1_printable_string_case_ignore_match() != 1) goto err; + if (test_asn1_utf8_string() != 1) goto err; + if (test_asn1_ia5_string() != 1) goto err; + if (test_asn1_time() != 1) goto err; + if (test_asn1_time_limits() != 1) goto err; + if (test_asn1_utc_time() != 1) goto err; + if (test_asn1_generalized_time() != 1) goto err; + if (test_asn1_from_der_null_args() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/base64test.c b/Core/GmSSL-3.1.1/tests/base64test.c new file mode 100644 index 0000000..ef2ae23 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/base64test.c @@ -0,0 +1,72 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include + + +static int test_base64(void) +{ + uint8_t bin1[50]; + uint8_t bin2[100]; + uint8_t bin3[200]; + uint8_t buf1[8000] = {0}; + uint8_t buf2[8000] = {0}; + + BASE64_CTX ctx; + uint8_t *p; + int len; + + memset(bin1, 0x01, sizeof(bin1)); + memset(bin2, 0xA5, sizeof(bin2)); + memset(bin3, 0xff, sizeof(bin3)); + + + p = buf1; + base64_encode_init(&ctx); + base64_encode_update(&ctx, bin1, sizeof(bin1), p, &len); p += len; + base64_encode_update(&ctx, bin2, sizeof(bin2), p, &len); p += len; + base64_encode_update(&ctx, bin3, sizeof(bin3), p, &len); p += len; + base64_encode_finish(&ctx, p, &len); p += len; + len = (int)(p - buf1); + + p = buf2; + base64_decode_init(&ctx); + base64_decode_update(&ctx, buf1, len, p, &len); p += len; + base64_decode_finish(&ctx, p, &len); p += len; + len = (int)(p - buf2); + + printf("base64 test "); + if (len != sizeof(bin1) + sizeof(bin2) + sizeof(bin3) + || memcmp(buf2, bin1, sizeof(bin1)) != 0 + || memcmp(buf2 + sizeof(bin1), bin2, sizeof(bin2)) != 0 + || memcmp(buf2 + sizeof(bin1) + sizeof(bin2), bin3, sizeof(bin3)) != 0) { + printf("failed\n"); + return -1; + } else { + printf("ok\n"); + } + + return 1; +} + +int main(void) +{ + if (test_base64() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/block_ciphertest.c b/Core/GmSSL-3.1.1/tests/block_ciphertest.c new file mode 100644 index 0000000..83426df --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/block_ciphertest.c @@ -0,0 +1,19 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include + +int main(void) +{ + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/chacha20test.c b/Core/GmSSL-3.1.1/tests/chacha20test.c new file mode 100644 index 0000000..e88eebb --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/chacha20test.c @@ -0,0 +1,58 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include + + +int main(void) +{ + int err = 0; + const unsigned char key[] = { + 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, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }; + const unsigned char nonce[] = { + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x00, + }; + uint32_t counter = 1; + const unsigned char testdata[] = { + 0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15, + 0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20, 0x71, 0xc4, + 0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03, + 0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e, + 0xd2, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09, + 0x14, 0xc2, 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2, + 0xb5, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9, + 0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e, + }; + unsigned char buf[64]; + + CHACHA20_STATE state; + chacha20_init(&state, key, nonce, counter); + chacha20_generate_keystream(&state, 1, buf); + + printf("chacha20 test "); + if (memcmp(buf, testdata, sizeof(testdata)) != 0) { + printf("failed\n"); + err++; + } else { + printf("ok\n"); + } + + return err; +} + diff --git a/Core/GmSSL-3.1.1/tests/cmstest.c b/Core/GmSSL-3.1.1/tests/cmstest.c new file mode 100644 index 0000000..4561e24 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/cmstest.c @@ -0,0 +1,1002 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_cms_content_type(void) +{ + int tests[] = { + OID_cms_data, + OID_cms_signed_data, + OID_cms_enveloped_data, + OID_cms_signed_and_enveloped_data, + OID_cms_encrypted_data, + OID_cms_key_agreement_info, + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (cms_content_type_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + int oid; + if (cms_content_type_from_der(&oid, &cp, &len) != 1 + || asn1_check(oid == tests[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", cms_content_type_name(oid)); + } + (void)asn1_length_is_zero(len); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_content_info(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + uint8_t data[20] = { 0x01,0x02 }; + int oid; + const uint8_t *d; + size_t dlen; + + if (cms_content_info_to_der(OID_cms_data, data, sizeof(data), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_content_info_print(stderr, 0, 0, "ContentInfo", d, dlen); + + p = buf; + cp = buf; + len = 0; + +// 当类型为OID_cms_data, 数据是OCTET STRING,需要再解析一次 + + if (cms_content_info_to_der(OID_cms_data, data, sizeof(data), &p, &len) != 1 + || cms_content_info_from_der(&oid, &d, &dlen, &cp, &len) != 1 + || asn1_check(oid == OID_cms_data) != 1 +// || asn1_check(dlen == sizeof(data)) != 1 +// || asn1_check(memcmp(data, d, dlen) == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_enced_content_info(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + uint8_t iv[16] = {0}; + uint8_t enced[32] = { 0x01,0x02 }; + const uint8_t *d; + size_t dlen; + + int oid; + int cipher; + const uint8_t *piv; + size_t ivlen; + const uint8_t *shared_info1; + size_t shared_info1_len; + const uint8_t *shared_info2; + size_t shared_info2_len; + + if (cms_enced_content_info_to_der(OID_cms_data, + OID_sm4_cbc, iv, sizeof(iv), enced, sizeof(enced), + NULL, 0, NULL, 0, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_enced_content_info_print(stderr, 0, 0, "EncryptedContentInfo", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (cms_enced_content_info_to_der(OID_cms_data, + OID_sm4_cbc, iv, sizeof(iv), enced, sizeof(enced), + NULL, 0, NULL, 0, &p, &len) != 1 + || cms_enced_content_info_from_der(&oid, + &cipher, &piv, &ivlen, &d, &dlen, + &shared_info1, &shared_info1_len, + &shared_info2, &shared_info2_len, &cp, &len) != 1 + || asn1_check(oid == OID_cms_data) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == sizeof(iv)) != 1 + || asn1_check(dlen == sizeof(enced)) != 1 + || asn1_check(shared_info1 == NULL) != 1 + || asn1_check(shared_info1_len == 0) != 1 + || asn1_check(shared_info2 == NULL) != 1 + || asn1_check(shared_info2_len == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_enced_content_info_encrypt(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + uint8_t key[16] = {0}; + uint8_t iv[16] = {1}; + uint8_t data[20] = {2}; + + const uint8_t *d; + size_t dlen; + + int oid; + int cipher; + uint8_t data2[256]; + const uint8_t *shared_info1; + size_t shared_info1_len; + const uint8_t *shared_info2; + size_t shared_info2_len; + + if (cms_enced_content_info_encrypt_to_der( + OID_sm4_cbc, + key, sizeof(key), + iv, sizeof(iv), + OID_cms_data, data, sizeof(data), + NULL, 0, + NULL, 0, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_enced_content_info_print(stderr, 0, 0, "EncryptedContentInfo", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (cms_enced_content_info_encrypt_to_der( + OID_sm4_cbc, + key, sizeof(key), + iv, sizeof(iv), + OID_cms_data, data, sizeof(data), + NULL, 0, + NULL, 0, + &p, &len) != 1 + // 显然这个解密函数是有问题的,在from_der的时候不知道密文的长度,因此无法知道需要的输出缓冲长度 + || cms_enced_content_info_decrypt_from_der( + &cipher, + key, sizeof(key), + &oid, data2, &dlen, + &shared_info1, &shared_info1_len, + &shared_info2, &shared_info2_len, + &cp, &len) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(oid = OID_cms_data) != 1 + || asn1_check(dlen == sizeof(data)) != 1 + || asn1_check(memcmp(data, data2, dlen) == 0) != 1 + || asn1_check(shared_info1 == NULL) != 1 + || asn1_check(shared_info2 == NULL) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_issuer_and_serial_number(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + uint8_t issuer[256]; + size_t issuer_len; + uint8_t serial[20] = {1}; + + const uint8_t *d; + size_t dlen; + const uint8_t *pissuer; + const uint8_t *pserial; + size_t serial_len; + + if (x509_name_set(issuer, &issuer_len, sizeof(issuer), + "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1 + || cms_issuer_and_serial_number_to_der( + issuer, issuer_len, serial, sizeof(serial), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_issuer_and_serial_number_print(stderr, 0, 0, "IssuerAndSerialNumber", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_name_set(issuer, &issuer_len, sizeof(issuer), + "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1 + || cms_issuer_and_serial_number_to_der( + issuer, issuer_len, serial, sizeof(serial), &p, &len) != 1 + || cms_issuer_and_serial_number_from_der( + &pissuer, &issuer_len, &pserial, &serial_len, &cp, &len) != 1 + || asn1_check(memcmp(pissuer, issuer, issuer_len) == 0) != 1 + || asn1_check(serial_len == sizeof(serial)) != 1 + || asn1_check(memcmp(serial, pserial, serial_len) == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_signer_info(void) +{ + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + uint8_t issuer_buf[256]; + size_t issuer_len; + uint8_t serial_buf[20]; + uint8_t sig_buf[256]; + size_t siglen = sizeof(sig_buf); + + int version; + const uint8_t *issuer; + const uint8_t *serial; + size_t serial_len; + int digest_alg; + const uint8_t *auth_attrs; + size_t auth_attrs_len; + int sig_alg; + const uint8_t *sig; + const uint8_t *unauth_attrs; + size_t unauth_attrs_len; + + + if (x509_name_set(issuer_buf, &issuer_len, sizeof(issuer_buf), + "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1) { + error_print(); + return -1; + } + + if (cms_signer_info_to_der( + CMS_version_v1, + issuer_buf, issuer_len, + serial_buf, sizeof(serial_buf), + OID_sm3, + NULL, 0, + OID_sm2sign_with_sm3, + sig_buf, siglen, + NULL, 0, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_signer_info_print(stderr, 0, 0, "SignerInfo", d, dlen); + + cp = p = buf; len = 0; + if (cms_signer_info_to_der( + CMS_version_v1, + issuer_buf, issuer_len, + serial_buf, sizeof(serial_buf), + OID_sm3, + NULL, 0, + OID_sm2sign_with_sm3, + sig_buf, siglen, + NULL, 0, + &p, &len) != 1 + || cms_signer_info_from_der( + &version, + &issuer, &issuer_len, + &serial, &serial_len, + &digest_alg, + &auth_attrs, &auth_attrs_len, + &sig_alg, + &sig, &siglen, + &unauth_attrs, &unauth_attrs_len, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_signer_info_sign(void) +{ + uint8_t buf[1024]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + SM2_KEY sm2_key; + uint8_t serial_buf[20]; + uint8_t name[256]; + size_t namelen; + time_t not_before, not_after; + uint8_t certs[1024]; + size_t certslen = 0; + uint8_t *pcerts = certs; + + SM3_CTX sm3_ctx; + + const uint8_t *cert; + size_t certlen; + const uint8_t *serial; + const uint8_t *issuer; + const uint8_t *auth_attrs; + const uint8_t *unauth_attrs; + size_t serial_len, issuer_len, auth_attrs_len, unauth_attrs_len; + + if (sm2_key_generate(&sm2_key) != 1 + || rand_bytes(serial_buf, sizeof(serial_buf)) != 1 + || x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "Alice") != 1 + || time(¬_before) == -1 + || x509_validity_add_days(¬_after, not_before, 365) != 1 + || x509_cert_sign_to_der( + X509_version_v3, serial_buf, sizeof(serial_buf), + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, NULL, 0, NULL, 0, NULL, 0, + &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &pcerts, &certslen) != 1) { + error_print(); + return -1; + } + + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, (uint8_t *)"hello", 5); + + cp = p = buf; len = 0; + if (cms_signer_info_sign_to_der( + &sm3_ctx, &sm2_key, + name, namelen, serial_buf, sizeof(serial_buf), + NULL, 0, NULL, 0, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_signer_info_print(stderr, 0, 0, "SignerInfo", d, dlen); + + cp = p = buf; len = 0; + if (cms_signer_info_sign_to_der( + &sm3_ctx, &sm2_key, + name, namelen, serial_buf, sizeof(serial_buf), + NULL, 0, NULL, 0, + &p, &len) != 1 + || cms_signer_info_verify_from_der( + &sm3_ctx, certs, certslen, + &cert, &certlen, + &issuer, &issuer_len, + &serial, &serial_len, + &auth_attrs, &auth_attrs_len, + &unauth_attrs, &unauth_attrs_len, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_signer_infos(void) +{ + uint8_t buf[1280]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + uint8_t signer_infos[1024]; + size_t signer_infos_len = 0; + + SM3_CTX sm3_ctx; + SM2_KEY sm2_key; + + uint8_t issuer_buf[256]; + size_t issuer_len; + uint8_t serial_buf[20]; + + sm2_key_generate(&sm2_key); + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, (uint8_t *)"hello", 5); + x509_name_set(issuer_buf, &issuer_len, sizeof(issuer_buf), "CN", "Beijing", "Haidian", "PKU", "CS", "CA"); + + + if (cms_signer_infos_add_signer_info( + signer_infos, &signer_infos_len, sizeof(signer_infos), + &sm3_ctx, &sm2_key, + issuer_buf, issuer_len, + serial_buf, sizeof(serial_buf), + NULL, 0, + NULL, 0) != 1 + || cms_signer_infos_add_signer_info( + signer_infos, &signer_infos_len, sizeof(signer_infos), + &sm3_ctx, &sm2_key, + issuer_buf, issuer_len, + serial_buf, sizeof(serial_buf), + NULL, 0, + NULL, 0) != 1 + || cms_signer_infos_add_signer_info( + signer_infos, &signer_infos_len, sizeof(signer_infos), + &sm3_ctx, &sm2_key, + issuer_buf, issuer_len, + serial_buf, sizeof(serial_buf), + NULL, 0, + NULL, 0) != 1 + || cms_signer_infos_to_der(signer_infos, signer_infos_len, &p, &len) != 1 + || cms_signer_infos_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1){ + error_print(); + return -1; + } + cms_signer_infos_print(stderr, 0, 0, "SET OF SignerInfo", d, dlen); + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_digest_algors(void) +{ + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int oids[] = { + OID_sm3, + OID_md5, + OID_sha1, + OID_sha256, + OID_sha512, + }; + + int algs[16]; + size_t algs_cnt; + + if (cms_digest_algors_to_der(oids, sizeof(oids)/sizeof(oids[0]), &p, &len) != 1 + || asn1_set_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_digest_algors_print(stderr, 0, 0, "digestAlgorithms", d, dlen); + + if (cms_digest_algors_to_der(oids, sizeof(oids)/sizeof(oids[0]), &p, &len) != 1 + || cms_digest_algors_from_der(algs, &algs_cnt, sizeof(algs)/sizeof(algs[0]), &cp, &len) != 1 + || asn1_check(algs_cnt == sizeof(oids)/sizeof(oids[0])) != 1 + || asn1_check(memcmp(algs, oids, sizeof(oids)) == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_signed_data(void) +{ + SM2_KEY sm2_key; + uint8_t cert[4096]; + size_t certlen = 0; + CMS_CERTS_AND_KEY signers[1]; + uint8_t data[48] = {0}; + uint8_t buf[4096]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + sm2_key_generate(&sm2_key); + + { + uint8_t serial[20]; + size_t serial_len = sizeof(serial); + uint8_t name[256]; + size_t namelen = 0; + time_t not_before, not_after; + size_t subject_len = 0; + uint8_t *p = cert; + const uint8_t *cp = cert; + + rand_bytes(serial, sizeof(serial)); + x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "CA"); + time(¬_before); + x509_validity_add_days(¬_after, not_before, 365); + + if (x509_cert_sign_to_der( + X509_version_v3, + serial, sizeof(serial), + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, + NULL, 0, + NULL, 0, + NULL, 0, + &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &p, &certlen) != 1) { + error_print(); + return -1; + } + } + + signers[0].certs = cert; + signers[0].certs_len = certlen; + signers[0].sign_key = &sm2_key; + + if (cms_signed_data_sign_to_der( + signers, sizeof(signers)/sizeof(signers[0]), + OID_cms_data, data, sizeof(data), + NULL, 0, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_signed_data_print(stderr, 0, 0, "SignedData", d, dlen); + + cp = p = buf; len = 0; + { + int content_type; + const uint8_t *content; + size_t content_len; + const uint8_t *certs; + size_t certslen; + const uint8_t *crls; + size_t crlslen; + const uint8_t *signer_infos; + size_t signer_infos_len; + + if (cms_signed_data_sign_to_der( + signers, sizeof(signers)/sizeof(signers[0]), + OID_cms_data, data, sizeof(data), + NULL, 0, + &p, &len) != 1 + || cms_signed_data_verify_from_der( + NULL, 0, + NULL, 0, + &content_type, &content, &content_len, + &certs, &certslen, + &crls, &crlslen, + &signer_infos, &signer_infos_len, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_recipient_info(void) +{ + SM2_KEY sm2_key; + uint8_t name[256]; + size_t namelen; + uint8_t serial_buf[20]; + uint8_t in[16]; + + uint8_t buf[1024]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int version; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + int pke_algor; + const uint8_t *params; + size_t params_len; + const uint8_t *enced_key; + size_t enced_key_len; + + uint8_t out[sizeof(in)]; + size_t outlen; + + sm2_key_generate(&sm2_key); + x509_name_set(name, &namelen, sizeof(name), "US", "CA", NULL, "BB", "AA", "CC"); + rand_bytes(serial_buf, sizeof(serial_buf)); + rand_bytes(in, sizeof(in)); + + if (cms_recipient_info_encrypt_to_der(&sm2_key, + name, namelen, + serial_buf, sizeof(serial_buf), + in, sizeof(in), + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_recipient_info_print(stderr, 0, 0, "RecipientInfo", d, dlen); + + + cp = p = buf; len = 0; + if (cms_recipient_info_encrypt_to_der(&sm2_key, + name, namelen, + serial_buf, sizeof(serial_buf), + in, sizeof(in), + &p, &len) != 1 + || cms_recipient_info_from_der( + &version, + &issuer, &issuer_len, + &serial, &serial_len, + &pke_algor, ¶ms, ¶ms_len, + &enced_key, &enced_key_len, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + + cp = p = buf; len = 0; + if (cms_recipient_info_encrypt_to_der( + &sm2_key, + name, namelen, + serial_buf, sizeof(serial_buf), + in, sizeof(in), + &p, &len) != 1 + || cms_recipient_info_decrypt_from_der( + &sm2_key, + name, namelen, + serial_buf, sizeof(serial_buf), + out, &outlen, sizeof(out), + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (sizeof(in) != outlen + || memcmp(in, out, outlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_cms_enveloped_data(void) +{ + SM2_KEY sm2_key1; + uint8_t name1[256]; + size_t name1_len; + uint8_t serial1[20]; + + SM2_KEY sm2_key2; + uint8_t name2[256]; + size_t name2_len; + uint8_t serial2[20]; + + time_t not_before, not_after; + + uint8_t certs[2048]; + size_t certslen; + + uint8_t key[16]; + uint8_t iv[16]; + + uint8_t in[80]; + uint8_t out[256]; + size_t outlen; + + uint8_t buf[4096]; + uint8_t *p; + const uint8_t *cp; + size_t len; + const uint8_t *d; + size_t dlen; + + // prepare keys and certs + + if (time(¬_before) == -1 + || x509_validity_add_days(¬_after, not_before, 365) != 1) { + error_print(); + return -1; + } + + p = certs; + certslen = 0; + + if (sm2_key_generate(&sm2_key1) != 1 + || rand_bytes(serial1, sizeof(serial1)) != 1 + || x509_name_set(name1, &name1_len, sizeof(name1), "CN", "Beijing", "Haidian", "PKU", "CS", "Alice") != 1 + || x509_cert_sign_to_der( + X509_version_v3, + serial1, sizeof(serial1), + OID_sm2sign_with_sm3, + name1, name1_len, + not_before, not_after, + name1, name1_len, + &sm2_key1, NULL, 0, NULL, 0, NULL, 0, + &sm2_key1, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &p, &certslen) != 1) { + error_print(); + return -1; + } + + if (sm2_key_generate(&sm2_key2) != 1 + || rand_bytes(serial2, sizeof(serial2)) != 1 + || x509_name_set(name2, &name2_len, sizeof(name2), "CN", "Beijing", "Haidian", "PKU", "CS", "Bob") != 1 + || x509_cert_sign_to_der( + X509_version_v3, + serial2, sizeof(serial2), + OID_sm2sign_with_sm3, + name2, name2_len, + not_before, not_after, + name2, name2_len, + &sm2_key2, NULL, 0, NULL, 0, NULL, 0, + &sm2_key2, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &p, &certslen) != 1) { + error_print(); + return -1; + } + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(in, sizeof(in)); + + // test + + cp = p = buf; len = 0; + if (cms_enveloped_data_encrypt_to_der( + certs, certslen, + OID_sm4_cbc, key, sizeof(key), iv, sizeof(iv), + OID_cms_data, in, sizeof(in), + NULL, 0, NULL, 0, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_enveloped_data_print(stderr, 0, 0, "EnvelopedData", d, dlen); + + + int content_type; + + + cp = p = buf; len = 0; + if (cms_enveloped_data_encrypt_to_der( + certs, certslen, + OID_sm4_cbc, key, sizeof(key), iv, sizeof(iv), + OID_cms_data, in, sizeof(in), + NULL, 0, NULL, 0, + &p, &len) != 1) { + error_print(); + return -1; + } + + const uint8_t *rcpt_infos; + const uint8_t *shared_info1; + const uint8_t *shared_info2; + size_t rcpt_infos_len, shared_info1_len, shared_info2_len; + + if (cms_enveloped_data_decrypt_from_der( + &sm2_key1, + name1, name1_len, + serial1, sizeof(serial1), + &content_type, out, &outlen, + &rcpt_infos, &rcpt_infos_len, + &shared_info1, &shared_info1_len, + &shared_info2, &shared_info2_len, + &cp, &len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_signed_and_enveloped_data(void) +{ +/* + SM2_KEY sign_key; + SM2_KEY decr_key; + + + + uint8_t sign_serial[20]; + uint8_t sign_name[256]; + size_t sign_name_len; +*/ + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_cms_key_agreement_info(void) +{ + SM2_KEY sm2_key; + uint8_t name[256]; + size_t namelen; + uint8_t serial[20]; + time_t not_before, not_after; + uint8_t cert[2048]; + size_t certlen = 0; + + uint8_t buf[4096]; + uint8_t *p; + const uint8_t *cp; + size_t len; + const uint8_t *d; + size_t dlen; + + int version; + SM2_KEY public_key; + const uint8_t *pcert; + size_t pcertlen; + const uint8_t *id; + size_t idlen; + + p = cert; + if (sm2_key_generate(&sm2_key) != 1 + || rand_bytes(serial, sizeof(serial)) != 1 + || x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "Alice") != 1 + || time(¬_before) == - 1 + || x509_validity_add_days(¬_after, not_before, 365) != 1 + || x509_cert_sign_to_der( + X509_version_v3, + serial, sizeof(serial), + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, NULL, 0, NULL, 0, NULL, 0, + &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &p, &certlen) != 1) { + error_print(); + return -1; + } + + cp = p = buf; len = 0; + if (cms_key_agreement_info_to_der( + CMS_version_v1, + &sm2_key, + cert, certlen, + (uint8_t *)SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + cms_key_agreement_info_print(stderr, 0, 0, "KeyAgreementInfo", d, dlen); + + + cp = p = buf; len = 0; + if (cms_key_agreement_info_to_der( + CMS_version_v1, + &sm2_key, + cert, certlen, + (uint8_t *)SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &p, &len) != 1 + || cms_key_agreement_info_from_der( + &version, + &public_key, + &pcert, &pcertlen, + &id, &idlen, + &cp, &len) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (sm2_public_key_equ(&sm2_key, &public_key) != 1) { + error_print(); + return -1; + } + if (pcertlen != certlen + || memcmp(pcert, cert, certlen) != 0 + || idlen != SM2_DEFAULT_ID_LENGTH + || memcmp(SM2_DEFAULT_ID, id, idlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(int argc, char **argv) +{ + if (test_cms_content_type() != 1) goto err; + if (test_cms_content_info() != 1) goto err; + if (test_cms_enced_content_info() != 1) goto err; + if (test_cms_enced_content_info_encrypt() != 1) goto err; + if (test_cms_issuer_and_serial_number() != 1) goto err; + if (test_cms_signer_info() != 1) goto err; + if (test_cms_signer_info_sign() != 1) goto err; + if (test_cms_signer_infos() != 1) goto err; + if (test_cms_digest_algors() != 1) goto err; + if (test_cms_signed_data() != 1) goto err; + if (test_cms_recipient_info() != 1) goto err; + if (test_cms_enveloped_data() != 1) goto err; + if (test_cms_key_agreement_info() != 1) goto err; + + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/destest.c b/Core/GmSSL-3.1.1/tests/destest.c new file mode 100644 index 0000000..35d08dd --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/destest.c @@ -0,0 +1,23 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include + + +int main(void) +{ + int err = 0; + return err; +} + diff --git a/Core/GmSSL-3.1.1/tests/digesttest.c b/Core/GmSSL-3.1.1/tests/digesttest.c new file mode 100644 index 0000000..34f01d2 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/digesttest.c @@ -0,0 +1,49 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include + +const char *digests[] = { +#ifdef ENABLE_BROKEN_CRYPTO + "md5", + "sha1", +#endif + "sm3", + "sha224", + "sha256", + "sha384", + "sha512", + "sha512-224", + "sha512-256", +}; + +int main(void) +{ + uint8_t dgst[64]; + size_t dgstlen; + size_t i, j; + + for (i = 0; i < sizeof(digests)/sizeof(digests[0]); i++) { + const DIGEST *algor = digest_from_name(digests[i]); + digest(algor, (uint8_t *)"abc", 3, dgst, &dgstlen); + + printf("%s (%zu) ", digests[i], dgstlen); + for (j = 0; j < dgstlen; j++) { + printf("%02x", dgst[j]); + } + printf("\n"); + } + + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/ectest.c b/Core/GmSSL-3.1.1/tests/ectest.c new file mode 100644 index 0000000..7b15f4b --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/ectest.c @@ -0,0 +1,121 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static int test_ec_named_curve(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + char *curves[] = { + "sm2p256v1", + "prime192v1", + "prime256v1", + "secp256k1", + "secp384r1", + "secp521r1", + }; + int oid; + int i; + + for (i = 0; i < sizeof(curves)/sizeof(curves[0]); i++) { + if ((oid = ec_named_curve_from_name(curves[i])) == OID_undef) { + error_print(); + return -1; + } + if (ec_named_curve_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + } + + for (i = 0; i < sizeof(curves)/sizeof(curves[0]); i++) { + if (ec_named_curve_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + if (oid != ec_named_curve_from_name(curves[i])) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", ec_named_curve_name(oid)); + } + (void)asn1_length_is_zero(len); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_ec_point_print(void) +{ + SM2_KEY sm2_key; + uint8_t buf[256]; + uint8_t *p = buf; + size_t len = 0; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + if (sm2_point_to_der(&(sm2_key.public_key), &p, &len) != 1) { + error_print(); + return -1; + } + ec_point_print(stderr, 0, 4, "ECPoint", buf, len); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_ec_private_key_print(void) +{ + SM2_KEY sm2_key; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + if (sm2_private_key_to_der(&sm2_key, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + ec_private_key_print(stderr, 0, 4, "ECPrivateKey", d, dlen); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_ec_named_curve() != 1) goto err; + if (test_ec_point_print() != 1) goto err; + if (test_ec_private_key_print() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/gcmtest.c b/Core/GmSSL-3.1.1/tests/gcmtest.c new file mode 100644 index 0000000..d15e1b5 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/gcmtest.c @@ -0,0 +1,193 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +struct { + char *H; + char *A; + char *C; + char *T; +} ghash_tests[] = { + // test 1 + { + "66e94bd4ef8a2c3b884cfa59ca342b2e", + "", + "", + "00000000000000000000000000000000", + }, + // test 2 + { + "66e94bd4ef8a2c3b884cfa59ca342b2e", + "", + "0388dace60b6a392f328c2b971b2fe78", + "f38cbb1ad69223dcc3457ae5b6b0f885", + + }, + // test 3 + { + "b83b533708bf535d0aa6e52980d53b78", + "", + "42831ec2217774244b7221b784d0d49c" + "e3aa212f2c02a4e035c17e2329aca12e" + "21d514b25466931c7d8f6a5aac84aa05" + "1ba30b396a0aac973d58e091473f5985", + "7f1b32b81b820d02614f8895ac1d4eac", + }, + // test 4 + { + "b83b533708bf535d0aa6e52980d53b78", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "42831ec2217774244b7221b784d0d49c" + "e3aa212f2c02a4e035c17e2329aca12e" + "21d514b25466931c7d8f6a5aac84aa05" + "1ba30b396a0aac973d58e091", + "698e57f70e6ecc7fd9463b7260a9ae5f", + }, + // test 5 + { + "b83b533708bf535d0aa6e52980d53b78", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "61353b4c2806934a777ff51fa22a4755" + "699b2a714fcdc6f83766e5f97b6c7423" + "73806900e49f24b22b097544d4896b42" + "4989b5e1ebac0f07c23f4598", + "df586bb4c249b92cb6922877e444d37b", + }, + // test 6 + { + "b83b533708bf535d0aa6e52980d53b78", + "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", + "8ce24998625615b603a033aca13fb894" + "be9112a5c3a211a8ba262a3cca7e2ca7" + "01e4a9a4fba43c90ccdcb281d48c7c6f" + "d62875d2aca417034c34aee5", + "1c5afe9760d3932f3c9a878aac3dc3de", + }, +}; + +int test_ghash(void) +{ + uint8_t H[16]; + uint8_t A[32]; + uint8_t C[64]; + uint8_t T[16]; + uint8_t out[16]; + size_t Hlen, Alen, Clen, Tlen; + int i; + + for (i = 0; i < sizeof(ghash_tests)/sizeof(ghash_tests[0]); i++) { + hex_to_bytes(ghash_tests[i].H, strlen(ghash_tests[i].H), H, &Hlen); + hex_to_bytes(ghash_tests[i].A, strlen(ghash_tests[i].A), A, &Alen); + hex_to_bytes(ghash_tests[i].C, strlen(ghash_tests[i].C), C, &Clen); + hex_to_bytes(ghash_tests[i].T, strlen(ghash_tests[i].T), T, &Tlen); + ghash(H, A, Alen, C, Clen, out); + + if (memcmp(out, T, Tlen) != 0) { + format_print(stderr, 0, 0, "test %d failed\n", i + 1); + format_print(stderr, 0, 2, "H = %s\n", ghash_tests[i].H); + format_print(stderr, 0, 2, "A = %s\n", ghash_tests[i].A); + format_print(stderr, 0, 2, "C = %s\n", ghash_tests[i].C); + format_bytes(stderr, 0, 2, "GHASH(H,A,C) = ", out, 16); + format_print(stderr, 0, 2, " = %s\n\n", ghash_tests[i].T); + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_gcm(void) +{ + BLOCK_CIPHER_KEY block_key; + uint8_t key[16]; + uint8_t iv[12]; + uint8_t aad[64]; + uint8_t in[100]; + uint8_t out[sizeof(in)]; + uint8_t buf[sizeof(in)]; + uint8_t tag[16]; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(aad, sizeof(aad)); + rand_bytes(in, sizeof(in)); + + memset(out, 0, sizeof(out)); + memset(buf, 0, sizeof(buf)); + memset(tag, 0, sizeof(tag)); + + if (block_cipher_set_encrypt_key(&block_key, BLOCK_CIPHER_aes128(), key) != 1) { + error_print(); + return -1; + } + if (gcm_encrypt(&block_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, sizeof(tag), tag) != 1) { + error_print(); + return -1; + } + if (gcm_decrypt(&block_key, iv, sizeof(iv), aad, sizeof(aad), out, sizeof(out), tag, sizeof(tag), buf) != 1) { + error_print(); + return -1; + } + if (memcmp(buf, in, sizeof(in)) != 0) { + error_print(); + return -1; + } + + memset(out, 0, sizeof(out)); + memset(buf, 0, sizeof(buf)); + memset(tag, 0, sizeof(tag)); + + if (block_cipher_set_encrypt_key(&block_key, BLOCK_CIPHER_sm4(), key) != 1) { + error_print(); + return -1; + } + if (gcm_encrypt(&block_key, iv, sizeof(iv), aad, sizeof(aad), in, sizeof(in), out, sizeof(tag), tag) != 1) { + error_print(); + return -1; + } + if (gcm_decrypt(&block_key, iv, sizeof(iv), aad, sizeof(aad), out, sizeof(out), tag, sizeof(tag), buf) != 1) { + error_print(); + return -1; + } + if (memcmp(buf, in, sizeof(in)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + + + + +int main(int argc, char **argv) +{ + if (test_ghash() != 1) goto err; + if (test_gcm() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/gf128test.c b/Core/GmSSL-3.1.1/tests/gf128test.c new file mode 100644 index 0000000..ad64956 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/gf128test.c @@ -0,0 +1,108 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +int test_gf128_from_hex(void) +{ + char *tests[] = { + "00000000000000000000000000000000", + "00000000000000000000000000000001", + "10000000000000000000000000000000", + "de300f9301a499a965f8bf677e99e80d", + "14b267838ec9ef1bb7b5ce8c19e34bc6", + }; + gf128_t a; + int i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + a = gf128_from_hex(tests[i]); + if (gf128_equ_hex(a, tests[i]) != 1) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_gf128_mul2(void) +{ + char *tests[] = { + "00000000000000000000000000000001", + "de300f9301a499a965f8bf677e99e80d", + }; + char *results[] = { + "e1000000000000000000000000000000", + "8e1807c980d24cd4b2fc5fb3bf4cf406", + }; + gf128_t a; + int i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + a = gf128_from_hex(tests[i]); + a = gf128_mul2(a); + if (gf128_equ_hex(a, results[i]) != 1) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int test_gf128_mul(void) +{ + char *hex_a = "de300f9301a499a965f8bf677e99e80d"; + char *hex_b = "14b267838ec9ef1bb7b5ce8c19e34bc6"; + char *hex_add_a_b = "ca8268108f6d76b2d24d71eb677aa3cb"; + char *hex_mul_a_b = "7d87dda57a20b0c51d9743071ab14010"; + gf128_t a, b, r; + + a = gf128_from_hex(hex_a); + b = gf128_from_hex(hex_b); + + r = gf128_add(a, b); + if (gf128_equ_hex(r, hex_add_a_b) != 1) { + error_print(); + return -1; + } + + r = gf128_mul(a, b); + if (gf128_equ_hex(r, hex_mul_a_b) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_gf128_from_hex() != 1) goto err; + if (test_gf128_mul2() != 1) goto err; + if (test_gf128_mul() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; + +} diff --git a/Core/GmSSL-3.1.1/tests/hash_drbgtest.c b/Core/GmSSL-3.1.1/tests/hash_drbgtest.c new file mode 100644 index 0000000..da4e6be --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/hash_drbgtest.c @@ -0,0 +1,94 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define EntropyInput "212956390783381dbfc6362dd0da9a09" +#define Nonce "5280987fc5e27a49" +#define PersonalizationString "" +#define AdditionalInput "" +#define V0 "02b84eba8121ca090b6b66d3371609eaf76405a5c2807d80035c1a13dfed5aa18e536af599a7b3c68b2c56240ed11997f4048910d84604" +#define C0 "a677e4921587563eebe55d1b25e59c3f3d200bc61aaee665e7a6858c2857c45dba4bce8182252962ae86de491046a5e3450eec44938a0a" + +#define AdditionalInput1 "" +#define EntropyInputPR1 "2edb396eeb8960f77943c2a59075a786" +#define V1 "f9afadfbbf2c3d1004f9baca38be247342e5fbb83281915d5de18beb963712a344e89bb0e6b925a7bbc32eadb8b441efc1fa0c649df42a" +#define C1 "1d41cbbd634909e4761c232fcfd6a6c2edf0a7f4d3d3c164f74a88955f355efce2d86c1e9fa897b7005ef9d4d3a51bf4fc0b805ab896c9" + +#define PR1 "2edb396eeb8960f77943c2a59075a786" +#define PR2 "30b565b63a5012676940d3ef17d9e996" + + +int main(void) +{ +// currently we only has SHA-1 test suites +#ifdef ENABLE_BROKEN_CRYPTO + HASH_DRBG drbg; + + uint8_t entropy[sizeof(EntropyInput)/2]; + uint8_t nonce[sizeof(Nonce)/2]; + uint8_t personalstr[1 + sizeof(PersonalizationString)/2]; + uint8_t v[sizeof(V0)/2]; + uint8_t c[sizeof(C0)/2]; + uint8_t entropy_pr1[sizeof(EntropyInputPR1)/2]; + uint8_t pr1[sizeof(PR1)/2]; + uint8_t pr2[sizeof(PR2)/2]; + size_t entropy_len, nonce_len, personalstr_len, vlen, clen; + size_t entropy_pr1len; + size_t pr1_len, pr2_len; + unsigned char out[640/8]; + int i; + + hex_to_bytes(EntropyInput, strlen(EntropyInput), entropy, &entropy_len); + hex_to_bytes(Nonce, strlen(Nonce), nonce, &nonce_len); + hex_to_bytes(PersonalizationString, strlen(PersonalizationString), personalstr, &personalstr_len); + hex_to_bytes(V0, strlen(V0), v, &vlen); + hex_to_bytes(C0, strlen(C0), c, &clen); + hex_to_bytes(EntropyInputPR1, strlen(EntropyInputPR1), entropy_pr1, &entropy_pr1len); + hex_to_bytes(PR1, strlen(PR1), pr1, &pr1_len); + hex_to_bytes(PR2, strlen(PR2), pr2, &pr2_len); + + hash_drbg_init(&drbg, DIGEST_sha1(), + entropy, entropy_len, + nonce, nonce_len, + personalstr, personalstr_len); + + printf("sha1_drbg test 1 "); + if (drbg.seedlen != vlen + || memcmp(drbg.V, v, vlen) != 0 + || memcmp(drbg.C, c, clen) != 0 + || drbg.reseed_counter != 1) { + printf("failed\n"); + return 1; + } else { + printf("ok\n"); + } + + hash_drbg_reseed(&drbg, pr1, pr1_len, NULL, 0); + hash_drbg_generate(&drbg, NULL, 0, 640/8, out); + + hash_drbg_reseed(&drbg, pr2, pr2_len, NULL, 0); + hash_drbg_generate(&drbg, NULL, 0, 640/8, out); + + for (i = 0; i < sizeof(out); i++) { + printf("%02x", out[i]); + } + printf("\n"); +#endif + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/hextest.c b/Core/GmSSL-3.1.1/tests/hextest.c new file mode 100644 index 0000000..38157ca --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/hextest.c @@ -0,0 +1,19 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include + +int main(void) +{ + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/hkdftest.c b/Core/GmSSL-3.1.1/tests/hkdftest.c new file mode 100644 index 0000000..9754e65 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/hkdftest.c @@ -0,0 +1,218 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + +static struct { + char *algor; + char *ikm; + char *salt; + char *info; + int L; + char *prk; + char *okm; +} hkdf_tests[] = { + { + // test 1 + "sha256", + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + 42, + "077709362c2e32df0ddc3f0dc47bba63" + "90b6c73bb50f9c3122ec844ad7c2b3e5", + "3cb25f25faacd57a90434f64d0362f2a" + "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + "34007208d5b887185865", + }, + { + // test 2 + "sha256", + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + 82, + "06a6b88c5853361a06104c9ceb35b45c" + "ef760014904671014a193f40c15fc244", + "b11e398dc80327a1c8e7f78c596a4934" + "4f012eda2d4efad8a050cc4c19afa97c" + "59045a99cac7827271cb41c65e590e09" + "da3275600c2f09b8367793a9aca3db71" + "cc30c58179ec3e87c14c01d5c1f3434f" + "1d87", + }, + { + // test 3 + "sha256", + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + 42, + "19ef24a32c717b167f33a91d6f648bdf" + "96596776afdb6377ac434c1c293ccb04", + "8da4e775a563c18f715f802a063c5a31" + "b8a11f5c5ee1879ec3454e5f3c738d2d" + "9d201395faa4b61a96c8", + }, +#ifdef ENABLE_BROKEN_CRYPTO + { + // test 4 + "sha1", + "0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + 42, + "9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243", + "085a01ea1b10f36933068b56efa5ad81" + "a4f14b822f5b091568a9cdd4f155fda2" + "c22e422478d305f3f896", + }, + { + // test 5 + "sha1", + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + 82, + "8adae09a2a307059478d309b26c4115a224cfaf6", + "0bd770a74d1160f7c9f12cd5912a06eb" + "ff6adcae899d92191fe4305673ba2ffe" + "8fa3f1a4e5ad79f3f334b3b202b2173c" + "486ea37ce3d397ed034c7f9dfeb15c5e" + "927336d0441f4c4300e2cff0d0900b52" + "d3b4", + }, + { + // test 6 + "sha1", + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + 42, + "da8c8a73c7fa77288ec6f5e7c297786aa0d32d01", + "0ac1af7002b3d761d1e55298da9d0506" + "b9ae52057220a306e07b6b87e8df21d0" + "ea00033de03984d34918" + }, + { + // test 7 + "sha1", + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + "", + "", + 42, + "2adccada18779e7c2077ad2eb19d3f3e731385dd", + "2c91117204d745f3500d636a62f64f0a" + "b3bae548aa53d423b0d1f27ebba6f5e5" + "673a081d70cce7acfc48", + }, +#endif +}; + +int test_hkdf(void) +{ + int i; + const DIGEST *digest; + uint8_t ikm[512]; + uint8_t salt[512]; + uint8_t info[512]; + uint8_t prk[512]; + uint8_t okm[512]; + size_t ikmlen, saltlen, infolen, prklen, okmlen; + size_t L; + uint8_t buf[512]; + size_t buflen; + size_t len; + + for (i = 0; i < sizeof(hkdf_tests)/sizeof(hkdf_tests[0]); i++) { + + digest = digest_from_name(hkdf_tests[i].algor); + hex_to_bytes(hkdf_tests[i].ikm, strlen(hkdf_tests[i].ikm), ikm, &len); + hex_to_bytes(hkdf_tests[i].salt, strlen(hkdf_tests[i].salt), salt, &len); + hex_to_bytes(hkdf_tests[i].info, strlen(hkdf_tests[i].info), info, &len); + hex_to_bytes(hkdf_tests[i].prk, strlen(hkdf_tests[i].prk), prk, &len); + hex_to_bytes(hkdf_tests[i].okm, strlen(hkdf_tests[i].okm), okm, &len); + ikmlen = strlen(hkdf_tests[i].ikm)/2; + saltlen = strlen(hkdf_tests[i].salt)/2; + infolen = strlen(hkdf_tests[i].info)/2; + prklen = strlen(hkdf_tests[i].prk)/2; + okmlen = strlen(hkdf_tests[i].okm)/2; + L = hkdf_tests[i].L; + + printf("test %d\n", i + 1); + format_print(stdout, 0, 0, "Hash = %s\n", digest_name(digest)); + format_bytes(stdout, 0, 0, "IKM = ", ikm, ikmlen); + format_bytes(stdout, 0, 0, "salt = ", salt, saltlen); + format_bytes(stdout, 0, 0, "info = ", info, infolen); + format_print(stdout, 0, 0, "L = %zu\n", L); + + if (hkdf_extract(digest, salt, saltlen, ikm, ikmlen, buf, &buflen) != 1) { + error_print(); + return -1; + } + format_bytes(stdout, 0, 0, "PRK = ", buf, buflen); + format_bytes(stdout, 0, 0, " = ", prk, prklen); + if (buflen != prklen || memcmp(buf, prk, prklen) != 0) { + error_print(); + return -1; + } + + if (hkdf_expand(digest, prk, prklen, info, infolen, L, buf) != 1) { + error_print(); + return -1; + } + format_bytes(stdout, 0, 0, "OKM = ", buf, L); + format_bytes(stdout, 0, 0, " = ", okm, okmlen); + if (L != okmlen || memcmp(buf, okm, okmlen) != 0) { + error_print(); + return -1; + } + + printf("\n"); + + } + return 0; +} + +int main(void) +{ + int err = 0; + err += test_hkdf(); + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/hmactest.c b/Core/GmSSL-3.1.1/tests/hmactest.c new file mode 100644 index 0000000..5b7c289 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/hmactest.c @@ -0,0 +1,125 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +// FIXME: md5, sha1, sm3 test vectors + + +struct { + char *key; + char *data; + char *hmac_sha224; + char *hmac_sha256; + char *hmac_sha384; + char *hmac_sha512; +} hmac_tests[] = { + + // rfc 4231 test vectors + { + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" + "0b0b0b0b", + "4869205468657265", + "896fb1128abbdf196832107cd49df33f" + "47b4b1169912ba4f53684b22", + "b0344c61d8db38535ca8afceaf0bf12b" + "881dc200c9833da726e9376c2e32cff7", + "afd03944d84895626b0825f4ab46907f" + "15f9dadbe4101ec682aa034c7cebc59c" + "faea9ea9076ede7f4af152e8b2fa9cb6", + "87aa7cdea5ef619d4ff0b4241a1d6cb0" + "2379f4e2ce4ec2787ad0b30545e17cde" + "daa833b7d6b8a702038b274eaea3f4e4" + "be9d914eeb61f1702e696c203a126854", + }, + { + "4a656665", + "7768617420646f2079612077616e7420" + "666f72206e6f7468696e673f", + "a30e01098bc6dbbf45690f3a7e9e6d0f" + "8bbea2a39e6148008fd05e44", + "5bdcc146bf60754e6a042426089575c7" + "5a003f089d2739839dec58b964ec3843", + "af45d2e376484031617f78d2b58a6b1b" + "9c7ef464f5a01b47e42ec3736322445e" + "8e2240ca5e69e2c78b3239ecfab21649", + "164b7a7bfcf819e2e395fbe73b56e0a3" + "87bd64222e831fd610270cd7ea250554" + "9758bf75c05a994a6d034f65f8f0e6fd" + "caeab1a34d4a6b4b636e070a38bce737", + }, + { + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaa", + "dddddddddddddddddddddddddddddddd" + "dddddddddddddddddddddddddddddddd" + "dddddddddddddddddddddddddddddddd" + "dddd", + "7fb3cb3588c6c1f6ffa9694d7d6ad264" + "9365b0c1f65d69d1ec8333ea", + "773ea91e36800e46854db8ebd09181a7" + "2959098b3ef8c122d9635514ced565fe", + "88062608d3e6ad8a0aa2ace014c8a86f" + "0aa635d947ac9febe83ef4e55966144b" + "2a5ab39dc13814b94e3ab6e101a34f27", + "fa73b0089d56a284efb0f0756c890be9" + "b1b5dbdd8ee81a3655f83e33b2279d39" + "bf3e848279a722c806b485a47e67c807" + "b946a337bee8942674278859e13292fb", + }, +}; + +int test_hmac(const DIGEST *digest, const char *key_hex, const char *data_hex, const char *hmac_hex) +{ + HMAC_CTX ctx; + uint8_t *key = (uint8_t *)malloc(strlen(key_hex)/2); + uint8_t *data = (uint8_t *)malloc(strlen(data_hex)/2); + uint8_t *hmac = (uint8_t *)malloc(strlen(hmac_hex) / 2); + size_t keylen, datalen, hmaclen; + uint8_t buf[64]; + size_t buflen; + + hex_to_bytes(key_hex, strlen(key_hex), key, &keylen); + hex_to_bytes(data_hex, strlen(data_hex), data, &datalen); + hex_to_bytes(hmac_hex, strlen(hmac_hex), hmac, &hmaclen); + + hmac_init(&ctx, digest, key, keylen); + hmac_update(&ctx, data, datalen); + hmac_finish(&ctx, buf, &buflen); + + if (buflen != hmaclen || memcmp(buf, hmac, hmaclen) != 0) { + printf("failed\n"); + return 0; + } + printf("ok\n"); + + if (key) free(key); + if (data) free(data); + if (hmac) free(hmac); + return 1; +} + +int main(void) +{ + int i; + for (i = 0; i < sizeof(hmac_tests)/sizeof(hmac_tests[0]); i++) { + test_hmac(DIGEST_sha224(), hmac_tests[i].key, hmac_tests[i].data, hmac_tests[i].hmac_sha224); + test_hmac(DIGEST_sha256(), hmac_tests[i].key, hmac_tests[i].data, hmac_tests[i].hmac_sha256); + test_hmac(DIGEST_sha384(), hmac_tests[i].key, hmac_tests[i].data, hmac_tests[i].hmac_sha384); + test_hmac(DIGEST_sha512(), hmac_tests[i].key, hmac_tests[i].data, hmac_tests[i].hmac_sha512); + }; + + return 0; +}; diff --git a/Core/GmSSL-3.1.1/tests/http_crltest.c b/Core/GmSSL-3.1.1/tests/http_crltest.c new file mode 100644 index 0000000..3c156ec --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/http_crltest.c @@ -0,0 +1,57 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_x509_crl_new_from_uri(void) +{ + char *tests[] = { + "http://crl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl", // from bing.com entity-cert + "http://crl3.digicert.com/Omniroot2025.crl", // from bing.com mid-CA cert + "http://crl.globalsign.com/gsrsaovsslca2018.crl", // from baidu.com entity cert + "http://crl.globalsign.com/root-r3.crl", // from baidu.com mid-CA cert + "http://crl.globalsign.com/gs/gsorganizationvalsha2g2.crl", // from taobao.com entity cert + }; + size_t i; + + uint8_t *crl = NULL; + size_t crl_len; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_crl_new_from_uri(&crl, &crl_len, tests[i], strlen(tests[i])) != 1) { + error_print(); + fprintf(stderr, "test %zu: %s\n", i, tests[i]); + return -1; + } + x509_crl_print(stderr, 0, 0, "CRL", crl, crl_len); + fprintf(stderr, "\n\n"); + free(crl); + crl = NULL; + } + return 1; +} + +int main(void) +{ + if (test_x509_crl_new_from_uri() != 1) { error_print(); return -1; } + + printf("%s all tests passed\n", __FILE__); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/httptest.c b/Core/GmSSL-3.1.1/tests/httptest.c new file mode 100644 index 0000000..7c7641c --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/httptest.c @@ -0,0 +1,110 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static int test_http_parse_uri(void) +{ + char *tests[] = { + "http://www.example.com:8080/ca/ca2023.crl", + "http://www.example.com:80/ca/ca2023.crl", + "http://www.example.com/ca/ca2023.crl", + "http://www.example.com/ca2023.crl", + "http://www.example.com:8080/", + "http://www.example.com:8080", + "http://www.example.com/", + "http://www.example.com", + }; + size_t i; + + char host[128]; + int port; + char path[256]; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (http_parse_uri(tests[i], host, &port, path) != 1) { + fprintf(stderr, "error: tests[%zu]: %s\n", i, tests[i]); + error_print(); + return -1; + } + printf("%s: host = %s, port = %d, path = %s\n", tests[i], host, port, path); + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_http_parse_uri_bad(void) +{ + char *tests[] = { + "ldap://www.example.com:8080/ca/ca2023.crl", + "http://www.example.com::8080/ca/ca2023.crl", + "http://www.example.com:8080:/ca/ca2023.crl", + "http://www.example.com:-100/ca/ca2023.crl", + "http://www.example.com:/ca/ca2023.crl", + "http:///ca2023.crl", + "http:///", + "http://", + }; + size_t i; + + char host[128]; + int port; + char path[256]; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (http_parse_uri(tests[i], host, &port, path) != -1) { + fprintf(stderr, "error: tests[%zu]: %s\n", i, tests[i]); + printf("%s: host = %s, port = %d, path = %s\n", tests[i], host, port, path); + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_http_get_crl(void) +{ + char *tests[] = { + "http://crl.pki.goog/gsr1/gsr1.crl", + }; + uint8_t buf[65536]; + size_t contentlen; + size_t i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (http_get(tests[i], buf, &contentlen, sizeof(buf)) != 1) { + fprintf(stderr, "%s() tests[%zu] <%s> failure\n", __FUNCTION__, i, tests[i]); + error_print(); + return -1; + } + x509_crl_print(stderr, 0, 0, "CRL", buf, contentlen); + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_http_parse_uri() != 1) { error_print(); return -1; } + if (test_http_parse_uri_bad() != 1) { error_print(); return -1; } + if (test_http_get_crl() != 1) { error_print(); return -1; } + printf("%s all tests passed\n", __FILE__); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/md5test.c b/Core/GmSSL-3.1.1/tests/md5test.c new file mode 100644 index 0000000..3e72dfe --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/md5test.c @@ -0,0 +1,68 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +static char *teststr[] = { + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890", +}; + +static char *dgsthex[] = { + "d41d8cd98f00b204e9800998ecf8427e", + "0cc175b9c0f1b6a831c399e269772661", + "900150983cd24fb0d6963f7d28e17f72", + "f96b697d7cb7938d525a2f31aaf161d0", + "c3fcd3d76192e4007dfb496cca67e13b", + "d174ab98d277d9f5a5611c2c9f419d9f", + "57edf4a22be3c955ac49da2e2107b67a", +}; + +int main(int argc, char **argv) +{ + int err = 0; + uint8_t dgst[16]; + uint8_t dgstbuf[16]; + size_t dgstbuflen; + size_t i; + + for (i = 0; i < sizeof(teststr)/sizeof(teststr[0]); i++) { + hex_to_bytes(dgsthex[i], strlen(dgsthex[i]), dgstbuf, &dgstbuflen); + md5_digest((uint8_t *)teststr[i], strlen(teststr[i]), dgst); + + if (memcmp(dgstbuf, dgst, sizeof(dgst)) != 0) { + int n; + printf("error calculating MD5 on %s\n", teststr[i]); + printf(" digest(corret) = "); + for (n = 0; n < sizeof(dgst); n++) { + printf("%02X", dgst[n]); + } + printf("\n"); + printf(" digest(error) = %s\n", dgsthex[i]); + err++; + } else { + printf("md5 test %zu ok\n", i+1); + } + } + + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/pbkdf2test.c b/Core/GmSSL-3.1.1/tests/pbkdf2test.c new file mode 100644 index 0000000..15a1eba --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/pbkdf2test.c @@ -0,0 +1,138 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +struct { + char *pass; + char *salt; + int iter; + int dklen; + char *dk; +} pbkdf2_hmac_sha1_tests[] = { + + // rfc 6070 test vectors for pbkdf2-hmac-sha1 + { + "password", + "salt", + 1, + 20, + "0c60c80f961f0e71f3a9b524af6012062fe037a6", + }, + { + "password", + "salt", + 2, + 20, + "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", + }, + { + "password", + "salt", + 4096, + 20, + "4b007901b765489abead49d926f721d065a429c1", + }, + /* + { + "password", + "salt", + 16777216, // very slow + 20, + "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984", + }, + */ + { + "passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + 25, + "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038", + }, +}; + +/* +void test(void) +{ + HMAC_CTX ctx; + uint8_t iter[4] = {0, 0, 0, 1}; + uint8_t mac[20]; + size_t len; + int i; + + hmac_init(&ctx, DIGEST_sha1(), (uint8_t *)"password", 8); + hmac_update(&ctx, (uint8_t *)"salt", 4); + hmac_update(&ctx, iter, 4); + hmac_finish(&ctx, mac, &len); + + for (i = 1; i < 4096; i++) { + uint8_t buf[20]; + memset(&ctx, 0, sizeof(HMAC_CTX)); + hmac_init(&ctx, DIGEST_sha1(), (uint8_t *)"password", 8); + hmac_update(&ctx, mac, len); + hmac_finish(&ctx, buf, &len); + int j; + for (j = 0; j < len; j++) { + mac[j] ^= buf[j]; + } + } + + + for (i = 0; i < len; i++) { + printf("%02x", mac[i]); + } + printf("\n"); +} +*/ + +static int test_pbkdf2_genkey(void) +{ +// FIXME: currently we only has SHA-1 tests, replace with SHA-256 +#ifdef ENABLE_BROKEN_CRYPTO + int i; + uint8_t key[64]; + uint8_t buf[64]; + size_t len; + + for (i = 0; i < sizeof(pbkdf2_hmac_sha1_tests)/sizeof(pbkdf2_hmac_sha1_tests[0]); i++) { + hex_to_bytes(pbkdf2_hmac_sha1_tests[i].dk, strlen(pbkdf2_hmac_sha1_tests[i].dk), buf, &len); + + if (pbkdf2_genkey(DIGEST_sha1(), + pbkdf2_hmac_sha1_tests[i].pass, strlen(pbkdf2_hmac_sha1_tests[i].pass), + (uint8_t *)pbkdf2_hmac_sha1_tests[i].salt, strlen(pbkdf2_hmac_sha1_tests[i].salt), + pbkdf2_hmac_sha1_tests[i].iter, pbkdf2_hmac_sha1_tests[i].dklen, key) != 1) { + error_print(); + return -1; + } + if (memcmp(key, buf, pbkdf2_hmac_sha1_tests[i].dklen) != 0) { + fprintf(stderr, "test_pbkdf2_genkey test %d failed\n", i); + return -1; + } else { + fprintf(stderr, "test_pbkdf2_genkey test %d ok\n", i); + } + } +#endif + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +int main(int argc, char **argv) +{ + int err = 0; + err += test_pbkdf2_genkey(); + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/pemtest.c b/Core/GmSSL-3.1.1/tests/pemtest.c new file mode 100644 index 0000000..3c00b4d --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/pemtest.c @@ -0,0 +1,245 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *pem_unix_style = + "-----BEGIN CERTIFICATE-----\n" + "MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG\n" + "EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw\n" + "MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO\n" + "UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" + "MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT\n" + "V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti\n" + "W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ\n" + "MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b\n" + "53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI\n" + "pDoiVhsLwg==\n" + "-----END CERTIFICATE-----\n"; + +static const char *pem_windows_style = + "-----BEGIN CERTIFICATE-----\r\n" + "MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG\r\n" + "EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw\r\n" + "MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO\r\n" + "UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\r\n" + "MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT\r\n" + "V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti\r\n" + "W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ\r\n" + "MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b\r\n" + "53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI\r\n" + "pDoiVhsLwg==\r\n" + "-----END CERTIFICATE-----\r\n"; + +#define TEST_PEM_BASE64_DECODE 1 + +static const char *pem_bin_hex = + "308201B330820157A003020102020869E2FEC0170AC67B300C06082A811CCF550183750500302E310B30090603550406" + "1302434E310E300C060355040A0C054E52434143310F300D06035504030C06524F4F544341301E170D31323037313430" + "33313135395A170D3432303730373033313135395A302E310B300906035504061302434E310E300C060355040A0C054E" + "52434143310F300D06035504030C06524F4F5443413059301306072A8648CE3D020106082A811CCF5501822D03420004" + "30F09C6BAA6681C721B137F652705E2FDAEDA789F0FA2B64D4ACEB99B9EAA34E655309309562BEE0E22BB45740AA7453" + "57B43DBF586D92FE364EC22EB73775DBA35D305B301F0603551D230418301680144C32B197D9331BC4A605C1C6E58B62" + "5BF0977658300C0603551D13040530030101FF300B0603551D0F040403020106301D0603551D0E041604144C32B197D9" + "331BC4A605C1C6E58B625BF0977658300C06082A811CCF550183750500034800304502201B56D22DE397A77A01F07EDB" + "E775BE08A38F9763E49E6584ABF94C86D9F6E479022100DA1C3816C5616D9C2AC18C7D7AFD6DC4CE7EFF53F563A39C48" + "A43A22561B0BC2"; + + +static int test_pem_unix_style(void) +{ + FILE *fp; + const char *text = pem_unix_style; + size_t textlen = strlen(text); + const char *file = "test_unix_style.pem"; + uint8_t buf[1024]; + size_t len; + + if (!(fp = fopen(file, "wb"))) { + error_print(); + return -1; + } + fwrite(text, 1, textlen, fp); + fclose(fp); + + if (!(fp = fopen(file, "rb"))) { + error_print(); + return -1; + } + if (pem_read(fp, "CERTIFICATE", buf, &len, sizeof(buf)) != 1) { + error_print(); + return -1; + } + fclose(fp); + + if (TEST_PEM_BASE64_DECODE) { + uint8_t bin[1024]; + size_t binlen; + hex_to_bytes(pem_bin_hex, strlen(pem_bin_hex), bin, &binlen); + if (len != binlen) { + error_print(); + return -1; + } + if (memcmp(buf, bin, binlen) != 0) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_pem_unix_style_without_last_newline(void) +{ + FILE *fp; + const char *text = pem_unix_style; + size_t textlen = strlen(text) - 1; // without last '\n' + const char *file = "test_unix_style_without_last_newline.pem"; + uint8_t buf[1024]; + size_t len; + + if (!(fp = fopen(file, "wb"))) { + error_print(); + return -1; + } + fwrite(text, 1, textlen, fp); + fclose(fp); + + if (!(fp = fopen(file, "rb"))) { + error_print(); + return -1; + } + if (pem_read(fp, "CERTIFICATE", buf, &len, sizeof(buf)) != 1) { + error_print(); + return -1; + } + fclose(fp); + + if (TEST_PEM_BASE64_DECODE) { + uint8_t bin[1024]; + size_t binlen; + hex_to_bytes(pem_bin_hex, strlen(pem_bin_hex), bin, &binlen); + if (len != binlen) { + error_print(); + return -1; + } + if (memcmp(buf, bin, binlen) != 0) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_pem_windows_style(void) +{ + FILE *fp; + const char *text = pem_windows_style; + size_t textlen = strlen(text); + const char *file = "test_windows_style.pem"; + uint8_t buf[1024]; + size_t len; + + if (!(fp = fopen(file, "wb"))) { + error_print(); + return -1; + } + fwrite(text, 1, textlen, fp); + fclose(fp); + + if (!(fp = fopen(file, "rb"))) { + error_print(); + return -1; + } + if (pem_read(fp, "CERTIFICATE", buf, &len, sizeof(buf)) != 1) { + error_print(); + return -1; + } + fclose(fp); + + if (TEST_PEM_BASE64_DECODE) { + uint8_t bin[1024]; + size_t binlen; + hex_to_bytes(pem_bin_hex, strlen(pem_bin_hex), bin, &binlen); + if (len != binlen) { + error_print(); + return -1; + } + if (memcmp(buf, bin, binlen) != 0) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_pem_windows_style_without_last_newline(void) +{ + FILE *fp; + const char *text = pem_windows_style; + size_t textlen = strlen(text) - 2; // without last '\r\n' + const char *file = "test_windows_style_without_last_newline.pem"; + uint8_t buf[1024]; + size_t len; + + if (!(fp = fopen(file, "wb"))) { + error_print(); + return -1; + } + fwrite(text, 1, textlen, fp); + fclose(fp); + + if (!(fp = fopen(file, "rb"))) { + error_print(); + return -1; + } + if (pem_read(fp, "CERTIFICATE", buf, &len, sizeof(buf)) != 1) { + error_print(); + return -1; + } + fclose(fp); + + if (TEST_PEM_BASE64_DECODE) { + uint8_t bin[1024]; + size_t binlen; + hex_to_bytes(pem_bin_hex, strlen(pem_bin_hex), bin, &binlen); + if (len != binlen) { + error_print(); + return -1; + } + if (memcmp(buf, bin, binlen) != 0) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_pem_unix_style() != 1) { error_print(); return 1; } + if (test_pem_unix_style_without_last_newline() != 1) { error_print(); return 1; } + if (test_pem_windows_style() != 1) { error_print(); return 1; } + if (test_pem_windows_style_without_last_newline() != 1) { error_print(); return 1; } + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/pkcs8test.c b/Core/GmSSL-3.1.1/tests/pkcs8test.c new file mode 100644 index 0000000..dd02647 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/pkcs8test.c @@ -0,0 +1,417 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_pbkdf2_params(void) +{ + uint8_t salt[8] = {0}; + size_t saltlen; + int iter = 65536; + int keylen = 16; + int prf = OID_hmac_sm3; + + uint8_t buf[128]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + const uint8_t *d; + size_t dlen; + const uint8_t *psalt; + + if (pbkdf2_params_to_der(salt, sizeof(salt), iter, keylen, prf, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pbkdf2_params_print(stderr, 0, 0, "PBKDF2-params", d, dlen); + + p = buf; + cp = buf; + len = 0; + keylen = -1; + prf = -1; + if (pbkdf2_params_to_der(salt, sizeof(salt), iter, keylen, prf, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pbkdf2_params_print(stderr, 0, 0, "PBKDF2-params", d, dlen); + + p = buf; + cp = buf; + len = 0; + keylen = -1; + prf = -1; + if (pbkdf2_params_to_der(salt, sizeof(salt), iter, keylen, prf, &p, &len) != 1 + || pbkdf2_params_from_der(&psalt, &saltlen, &iter, &keylen, &prf, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 0, "PBKDF2-params\n"); + format_bytes(stderr, 0, 4, "salt", psalt, saltlen); + format_print(stderr, 0, 4, "iterationCount: %d\n", iter); + format_print(stderr, 0, 4, "keyLength: %d\n", keylen); + format_print(stderr, 0, 4, "prf: %d\n", prf); + + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_pbkdf2_algor(void) +{ + uint8_t salt[8] = {0}; + size_t saltlen; + int iter = 65536; + int keylen = 16; + int prf = OID_hmac_sm3; + + uint8_t buf[128]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + const uint8_t *d; + size_t dlen; + const uint8_t *psalt; + + if (pbkdf2_algor_to_der(salt, sizeof(salt), iter, keylen, prf, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pbkdf2_algor_print(stderr, 0, 0, "PBKDF2", d, dlen); + + p = buf; + cp = buf; + len = 0; + if (pbkdf2_algor_to_der(salt, sizeof(salt), iter, keylen, prf, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 0, "PBKDF2\n"); + format_bytes(stderr, 0, 4, "salt", psalt, saltlen); + format_print(stderr, 0, 4, "iterationCount: %d\n", iter); + format_print(stderr, 0, 4, "keyLength: %d\n", keylen); + format_print(stderr, 0, 4, "prf: %d\n", prf); + + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_pbes2_enc_algor(void) +{ + int cipher = OID_sm4_cbc; + uint8_t iv[16] = {1}; + + uint8_t buf[128]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + const uint8_t *d; + size_t dlen; + const uint8_t *piv; + size_t ivlen; + + if (pbes2_enc_algor_to_der(cipher, iv, sizeof(iv), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pbes2_enc_algor_print(stderr, 0, 0, "PBES2-Enc", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (pbes2_enc_algor_to_der(cipher, iv, sizeof(iv), &p, &len) != 1 + || pbes2_enc_algor_from_der(&cipher, &piv, &ivlen, &cp, &len) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == sizeof(iv)) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_pbes2_params(void) +{ + uint8_t salt[8] = {0}; + size_t saltlen; + int iter = 65536; + int keylen = -1; + int prf = OID_hmac_sm3; + int cipher = OID_sm4_cbc; + uint8_t iv[16]; + + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + const uint8_t *d; + size_t dlen; + const uint8_t *psalt; + const uint8_t *piv; + size_t ivlen; + + if (pbes2_params_to_der(salt, sizeof(salt), iter, keylen, prf, cipher, iv, sizeof(iv), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pbes2_params_print(stderr, 0, 0, "PBES2-params", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (pbes2_params_to_der(salt, sizeof(salt), iter, keylen, prf, cipher, iv, sizeof(iv), &p, &len) != 1 + || pbes2_params_from_der(&psalt, &saltlen, &iter, &keylen, &prf, &cipher, &piv, &ivlen, &cp, &len) != 1 + || asn1_check(saltlen == sizeof(salt)) != 1 + || asn1_check(iter == 65536) != 1 + || asn1_check(keylen == -1) != 1 + || asn1_check(prf == OID_hmac_sm3) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == sizeof(iv)) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_pbes2_algor(void) +{ + uint8_t salt[8] = {0}; + size_t saltlen; + int iter = 65536; + int keylen = -1; + int prf = OID_hmac_sm3; + int cipher = OID_sm4_cbc; + uint8_t iv[16]; + + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + const uint8_t *d; + size_t dlen; + const uint8_t *psalt; + const uint8_t *piv; + size_t ivlen; + + if (pbes2_algor_to_der(salt, sizeof(salt), iter, keylen, prf, cipher, iv, sizeof(iv), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pbes2_algor_print(stderr, 0, 0, "PBES2", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (pbes2_algor_to_der(salt, sizeof(salt), iter, keylen, prf, cipher, iv, sizeof(iv), &p, &len) != 1 + || pbes2_algor_from_der(&psalt, &saltlen, &iter, &keylen, &prf, &cipher, &piv, &ivlen, &cp, &len) != 1 + || asn1_check(saltlen == sizeof(salt)) != 1 + || asn1_check(iter == 65536) != 1 + || asn1_check(keylen == -1) != 1 + || asn1_check(prf == OID_hmac_sm3) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == sizeof(iv)) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_pkcs8_enced_private_key_info(void) +{ + uint8_t salt[8] = { 1,0 }; + int iter = 65536; + int keylen = -1; + int prf = OID_hmac_sm3; + int cipher = OID_sm4_cbc; + uint8_t iv[16] = { 2,0 }; + uint8_t enced[128] = { 3,0 }; + + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + const uint8_t *d; + size_t dlen; + const uint8_t *psalt; + size_t saltlen; + const uint8_t *piv; + size_t ivlen; + const uint8_t *penced; + size_t encedlen; + + if (pkcs8_enced_private_key_info_to_der( + salt, sizeof(salt), iter, keylen, prf, + cipher, iv, sizeof(iv), + enced, sizeof(enced), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pkcs8_enced_private_key_info_print(stderr, 0, 0, "EncryptedPrivateKeyInfo", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (pkcs8_enced_private_key_info_to_der( + salt, sizeof(salt), iter, keylen, prf, + cipher, iv, sizeof(iv), + enced, sizeof(enced), &p, &len) != 1 + || pkcs8_enced_private_key_info_from_der( + &psalt, &saltlen, &iter, &keylen, &prf, + &cipher, &piv, &ivlen, + &penced, &encedlen, &cp, &len) != 1 + || asn1_check(saltlen == sizeof(salt)) != 1 + || asn1_check(keylen == -1) != 1 + || asn1_check(prf == OID_hmac_sm3) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == sizeof(iv)) != 1 + || asn1_check(encedlen == sizeof(enced)) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_pkcs8(void) +{ + int err = 0; + SM2_KEY sm2_key; + SM2_KEY sm2_buf; + const uint8_t *attrs; + size_t attrslen; + uint8_t buf[1024]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + sm2_key_generate(&sm2_key); + memcpy(&sm2_buf, &sm2_key, sizeof(sm2_key)); + sm2_key_print(stderr, 0, 0, "SM2_KEY", &sm2_key); + + if (sm2_private_key_info_encrypt_to_der(&sm2_key, "password", &p, &len) != 1) { + error_print(); + return -1; + } + { + const uint8_t *a = buf; + size_t alen = len; + const uint8_t *d; + size_t dlen; + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + pkcs8_enced_private_key_info_print(stderr, 0, 0, "test_pkcs8: 392", d, dlen); + fprintf(stderr, "\n"); + } + + memset(&sm2_key, 0, sizeof(sm2_key)); + if (sm2_private_key_info_decrypt_from_der(&sm2_key, &attrs, &attrslen, "password", &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + fprintf(stderr, "\n"); + sm2_key_print(stderr, 0, 0, "SM2_KEY", &sm2_key); + + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_pkcs8_pem(void) +{ + int err = 0; + char *file = "test_pkcs8_pem.pem"; + char *pass = "password"; + SM2_KEY sm2_key; + SM2_KEY sm2_buf; + FILE *fp; + + sm2_key_generate(&sm2_key); + memcpy(&sm2_buf, &sm2_key, sizeof(sm2_key)); + sm2_key_print(stderr, 0, 0, "SM2_KEY", &sm2_key); + + if (!(fp = fopen(file, "w")) + || sm2_private_key_info_encrypt_to_pem(&sm2_key, pass, fp) != 1) { + error_print(); + return -1; + } + fclose(fp); + + memset(&sm2_key, 0, sizeof(sm2_key)); + if (!(fp = fopen(file, "r")) + || sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, fp) != 1) { + error_print(); + return -1; + } + sm2_key_print(stderr, 0, 0, "SM2_KEY", &sm2_key); + + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +int main(void) +{ + int err = 0; + /* + err += test_pbkdf2_params(); + err += test_pbkdf2_algor(); + err += test_pbes2_enc_algor(); + err += test_pbes2_params(); + err += test_pbes2_algor(); + err += test_pkcs8_enced_private_key_info(); + */ + err += test_pkcs8(); +// err += test_pkcs8_pem(); + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/rc4test.c b/Core/GmSSL-3.1.1/tests/rc4test.c new file mode 100644 index 0000000..7ea6ed1 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/rc4test.c @@ -0,0 +1,389 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include + + +/* tests from RFC 6229 Test Vectors for the Stream Cipher RC4 */ + +unsigned char key1[] = { + 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, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, +}; + +unsigned char key2[] = { + 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21, + 0xc1, 0x09, 0x16, 0x39, 0x08, 0xeb, 0xe5, 0x1d, + 0xeb, 0xb4, 0x62, 0x27, 0xc6, 0xcc, 0x8b, 0x37, + 0x64, 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a, +}; + +int keybits[] = { + 40, + 56, + 64, + 80, + 128, + 192, + 256, +}; + +int testindex[] = { + 0, + 16, + 240, + 256, + 496, + 512, + 752, + 768, + 1008, + 1024, + 1520, + 1536, + 2032, + 2048, + 3056, + 3072, + 4080, + 4096, +}; + +unsigned char testdata1[][16 * 18] = { + { + 0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27, 0xcc, 0xc3, 0x52, 0x4a, 0x0a, 0x11, 0x18, 0xa8, + 0x69, 0x82, 0x94, 0x4f, 0x18, 0xfc, 0x82, 0xd5, 0x89, 0xc4, 0x03, 0xa4, 0x7a, 0x0d, 0x09, 0x19, + 0x28, 0xcb, 0x11, 0x32, 0xc9, 0x6c, 0xe2, 0x86, 0x42, 0x1d, 0xca, 0xad, 0xb8, 0xb6, 0x9e, 0xae, + 0x1c, 0xfc, 0xf6, 0x2b, 0x03, 0xed, 0xdb, 0x64, 0x1d, 0x77, 0xdf, 0xcf, 0x7f, 0x8d, 0x8c, 0x93, + 0x42, 0xb7, 0xd0, 0xcd, 0xd9, 0x18, 0xa8, 0xa3, 0x3d, 0xd5, 0x17, 0x81, 0xc8, 0x1f, 0x40, 0x41, + 0x64, 0x59, 0x84, 0x44, 0x32, 0xa7, 0xda, 0x92, 0x3c, 0xfb, 0x3e, 0xb4, 0x98, 0x06, 0x61, 0xf6, + 0xec, 0x10, 0x32, 0x7b, 0xde, 0x2b, 0xee, 0xfd, 0x18, 0xf9, 0x27, 0x76, 0x80, 0x45, 0x7e, 0x22, + 0xeb, 0x62, 0x63, 0x8d, 0x4f, 0x0b, 0xa1, 0xfe, 0x9f, 0xca, 0x20, 0xe0, 0x5b, 0xf8, 0xff, 0x2b, + 0x45, 0x12, 0x90, 0x48, 0xe6, 0xa0, 0xed, 0x0b, 0x56, 0xb4, 0x90, 0x33, 0x8f, 0x07, 0x8d, 0xa5, + 0x30, 0xab, 0xbc, 0xc7, 0xc2, 0x0b, 0x01, 0x60, 0x9f, 0x23, 0xee, 0x2d, 0x5f, 0x6b, 0xb7, 0xdf, + 0x32, 0x94, 0xf7, 0x44, 0xd8, 0xf9, 0x79, 0x05, 0x07, 0xe7, 0x0f, 0x62, 0xe5, 0xbb, 0xce, 0xea, + 0xd8, 0x72, 0x9d, 0xb4, 0x18, 0x82, 0x25, 0x9b, 0xee, 0x4f, 0x82, 0x53, 0x25, 0xf5, 0xa1, 0x30, + 0x1e, 0xb1, 0x4a, 0x0c, 0x13, 0xb3, 0xbf, 0x47, 0xfa, 0x2a, 0x0b, 0xa9, 0x3a, 0xd4, 0x5b, 0x8b, + 0xcc, 0x58, 0x2f, 0x8b, 0xa9, 0xf2, 0x65, 0xe2, 0xb1, 0xbe, 0x91, 0x12, 0xe9, 0x75, 0xd2, 0xd7, + 0xf2, 0xe3, 0x0f, 0x9b, 0xd1, 0x02, 0xec, 0xbf, 0x75, 0xaa, 0xad, 0xe9, 0xbc, 0x35, 0xc4, 0x3c, + 0xec, 0x0e, 0x11, 0xc4, 0x79, 0xdc, 0x32, 0x9d, 0xc8, 0xda, 0x79, 0x68, 0xfe, 0x96, 0x56, 0x81, + 0x06, 0x83, 0x26, 0xa2, 0x11, 0x84, 0x16, 0xd2, 0x1f, 0x9d, 0x04, 0xb2, 0xcd, 0x1c, 0xa0, 0x50, + 0xff, 0x25, 0xb5, 0x89, 0x95, 0x99, 0x67, 0x07, 0xe5, 0x1f, 0xbd, 0xf0, 0x8b, 0x34, 0xd8, 0x75, + }, + { + 0x29, 0x3f, 0x02, 0xd4, 0x7f, 0x37, 0xc9, 0xb6, 0x33, 0xf2, 0xaf, 0x52, 0x85, 0xfe, 0xb4, 0x6b, + 0xe6, 0x20, 0xf1, 0x39, 0x0d, 0x19, 0xbd, 0x84, 0xe2, 0xe0, 0xfd, 0x75, 0x20, 0x31, 0xaf, 0xc1, + 0x91, 0x4f, 0x02, 0x53, 0x1c, 0x92, 0x18, 0x81, 0x0d, 0xf6, 0x0f, 0x67, 0xe3, 0x38, 0x15, 0x4c, + 0xd0, 0xfd, 0xb5, 0x83, 0x07, 0x3c, 0xe8, 0x5a, 0xb8, 0x39, 0x17, 0x74, 0x0e, 0xc0, 0x11, 0xd5, + 0x75, 0xf8, 0x14, 0x11, 0xe8, 0x71, 0xcf, 0xfa, 0x70, 0xb9, 0x0c, 0x74, 0xc5, 0x92, 0xe4, 0x54, + 0x0b, 0xb8, 0x72, 0x02, 0x93, 0x8d, 0xad, 0x60, 0x9e, 0x87, 0xa5, 0xa1, 0xb0, 0x79, 0xe5, 0xe4, + 0xc2, 0x91, 0x12, 0x46, 0xb6, 0x12, 0xe7, 0xe7, 0xb9, 0x03, 0xdf, 0xed, 0xa1, 0xda, 0xd8, 0x66, + 0x32, 0x82, 0x8f, 0x91, 0x50, 0x2b, 0x62, 0x91, 0x36, 0x8d, 0xe8, 0x08, 0x1d, 0xe3, 0x6f, 0xc2, + 0xf3, 0xb9, 0xa7, 0xe3, 0xb2, 0x97, 0xbf, 0x9a, 0xd8, 0x04, 0x51, 0x2f, 0x90, 0x63, 0xef, 0xf1, + 0x8e, 0xcb, 0x67, 0xa9, 0xba, 0x1f, 0x55, 0xa5, 0xa0, 0x67, 0xe2, 0xb0, 0x26, 0xa3, 0x67, 0x6f, + 0xd2, 0xaa, 0x90, 0x2b, 0xd4, 0x2d, 0x0d, 0x7c, 0xfd, 0x34, 0x0c, 0xd4, 0x58, 0x10, 0x52, 0x9f, + 0x78, 0xb2, 0x72, 0xc9, 0x6e, 0x42, 0xea, 0xb4, 0xc6, 0x0b, 0xd9, 0x14, 0xe3, 0x9d, 0x06, 0xe3, + 0xf4, 0x33, 0x2f, 0xd3, 0x1a, 0x07, 0x93, 0x96, 0xee, 0x3c, 0xee, 0x3f, 0x2a, 0x4f, 0xf0, 0x49, + 0x05, 0x45, 0x97, 0x81, 0xd4, 0x1f, 0xda, 0x7f, 0x30, 0xc1, 0xbe, 0x7e, 0x12, 0x46, 0xc6, 0x23, + 0xad, 0xfd, 0x38, 0x68, 0xb8, 0xe5, 0x14, 0x85, 0xd5, 0xe6, 0x10, 0x01, 0x7e, 0x3d, 0xd6, 0x09, + 0xad, 0x26, 0x58, 0x1c, 0x0c, 0x5b, 0xe4, 0x5f, 0x4c, 0xea, 0x01, 0xdb, 0x2f, 0x38, 0x05, 0xd5, + 0xf3, 0x17, 0x2c, 0xef, 0xfc, 0x3b, 0x3d, 0x99, 0x7c, 0x85, 0xcc, 0xd5, 0xaf, 0x1a, 0x95, 0x0c, + 0xe7, 0x4b, 0x0b, 0x97, 0x31, 0x22, 0x7f, 0xd3, 0x7c, 0x0e, 0xc0, 0x8a, 0x47, 0xdd, 0xd8, 0xb8, + }, + { + 0x97, 0xab, 0x8a, 0x1b, 0xf0, 0xaf, 0xb9, 0x61, 0x32, 0xf2, 0xf6, 0x72, 0x58, 0xda, 0x15, 0xa8, + 0x82, 0x63, 0xef, 0xdb, 0x45, 0xc4, 0xa1, 0x86, 0x84, 0xef, 0x87, 0xe6, 0xb1, 0x9e, 0x5b, 0x09, + 0x96, 0x36, 0xeb, 0xc9, 0x84, 0x19, 0x26, 0xf4, 0xf7, 0xd1, 0xf3, 0x62, 0xbd, 0xdf, 0x6e, 0x18, + 0xd0, 0xa9, 0x90, 0xff, 0x2c, 0x05, 0xfe, 0xf5, 0xb9, 0x03, 0x73, 0xc9, 0xff, 0x4b, 0x87, 0x0a, + 0x73, 0x23, 0x9f, 0x1d, 0xb7, 0xf4, 0x1d, 0x80, 0xb6, 0x43, 0xc0, 0xc5, 0x25, 0x18, 0xec, 0x63, + 0x16, 0x3b, 0x31, 0x99, 0x23, 0xa6, 0xbd, 0xb4, 0x52, 0x7c, 0x62, 0x61, 0x26, 0x70, 0x3c, 0x0f, + 0x49, 0xd6, 0xc8, 0xaf, 0x0f, 0x97, 0x14, 0x4a, 0x87, 0xdf, 0x21, 0xd9, 0x14, 0x72, 0xf9, 0x66, + 0x44, 0x17, 0x3a, 0x10, 0x3b, 0x66, 0x16, 0xc5, 0xd5, 0xad, 0x1c, 0xee, 0x40, 0xc8, 0x63, 0xd0, + 0x27, 0x3c, 0x9c, 0x4b, 0x27, 0xf3, 0x22, 0xe4, 0xe7, 0x16, 0xef, 0x53, 0xa4, 0x7d, 0xe7, 0xa4, + 0xc6, 0xd0, 0xe7, 0xb2, 0x26, 0x25, 0x9f, 0xa9, 0x02, 0x34, 0x90, 0xb2, 0x61, 0x67, 0xad, 0x1d, + 0x1f, 0xe8, 0x98, 0x67, 0x13, 0xf0, 0x7c, 0x3d, 0x9a, 0xe1, 0xc1, 0x63, 0xff, 0x8c, 0xf9, 0xd3, + 0x83, 0x69, 0xe1, 0xa9, 0x65, 0x61, 0x0b, 0xe8, 0x87, 0xfb, 0xd0, 0xc7, 0x91, 0x62, 0xaa, 0xfb, + 0x0a, 0x01, 0x27, 0xab, 0xb4, 0x44, 0x84, 0xb9, 0xfb, 0xef, 0x5a, 0xbc, 0xae, 0x1b, 0x57, 0x9f, + 0xc2, 0xcd, 0xad, 0xc6, 0x40, 0x2e, 0x8e, 0xe8, 0x66, 0xe1, 0xf3, 0x7b, 0xdb, 0x47, 0xe4, 0x2c, + 0x26, 0xb5, 0x1e, 0xa3, 0x7d, 0xf8, 0xe1, 0xd6, 0xf7, 0x6f, 0xc3, 0xb6, 0x6a, 0x74, 0x29, 0xb3, + 0xbc, 0x76, 0x83, 0x20, 0x5d, 0x4f, 0x44, 0x3d, 0xc1, 0xf2, 0x9d, 0xda, 0x33, 0x15, 0xc8, 0x7b, + 0xd5, 0xfa, 0x5a, 0x34, 0x69, 0xd2, 0x9a, 0xaa, 0xf8, 0x3d, 0x23, 0x58, 0x9d, 0xb8, 0xc8, 0x5b, + 0x3f, 0xb4, 0x6e, 0x2c, 0x8f, 0x0f, 0x06, 0x8e, 0xdc, 0xe8, 0xcd, 0xcd, 0x7d, 0xfc, 0x58, 0x62, + }, + { + 0xed, 0xe3, 0xb0, 0x46, 0x43, 0xe5, 0x86, 0xcc, 0x90, 0x7d, 0xc2, 0x18, 0x51, 0x70, 0x99, 0x02, + 0x03, 0x51, 0x6b, 0xa7, 0x8f, 0x41, 0x3b, 0xeb, 0x22, 0x3a, 0xa5, 0xd4, 0xd2, 0xdf, 0x67, 0x11, + 0x3c, 0xfd, 0x6c, 0xb5, 0x8e, 0xe0, 0xfd, 0xde, 0x64, 0x01, 0x76, 0xad, 0x00, 0x00, 0x04, 0x4d, + 0x48, 0x53, 0x2b, 0x21, 0xfb, 0x60, 0x79, 0xc9, 0x11, 0x4c, 0x0f, 0xfd, 0x9c, 0x04, 0xa1, 0xad, + 0x3e, 0x8c, 0xea, 0x98, 0x01, 0x71, 0x09, 0x97, 0x90, 0x84, 0xb1, 0xef, 0x92, 0xf9, 0x9d, 0x86, + 0xe2, 0x0f, 0xb4, 0x9b, 0xdb, 0x33, 0x7e, 0xe4, 0x8b, 0x8d, 0x8d, 0xc0, 0xf4, 0xaf, 0xef, 0xfe, + 0x5c, 0x25, 0x21, 0xea, 0xcd, 0x79, 0x66, 0xf1, 0x5e, 0x05, 0x65, 0x44, 0xbe, 0xa0, 0xd3, 0x15, + 0xe0, 0x67, 0xa7, 0x03, 0x19, 0x31, 0xa2, 0x46, 0xa6, 0xc3, 0x87, 0x5d, 0x2f, 0x67, 0x8a, 0xcb, + 0xa6, 0x4f, 0x70, 0xaf, 0x88, 0xae, 0x56, 0xb6, 0xf8, 0x75, 0x81, 0xc0, 0xe2, 0x3e, 0x6b, 0x08, + 0xf4, 0x49, 0x03, 0x1d, 0xe3, 0x12, 0x81, 0x4e, 0xc6, 0xf3, 0x19, 0x29, 0x1f, 0x4a, 0x05, 0x16, + 0xbd, 0xae, 0x85, 0x92, 0x4b, 0x3c, 0xb1, 0xd0, 0xa2, 0xe3, 0x3a, 0x30, 0xc6, 0xd7, 0x95, 0x99, + 0x8a, 0x0f, 0xed, 0xdb, 0xac, 0x86, 0x5a, 0x09, 0xbc, 0xd1, 0x27, 0xfb, 0x56, 0x2e, 0xd6, 0x0a, + 0xb5, 0x5a, 0x0a, 0x5b, 0x51, 0xa1, 0x2a, 0x8b, 0xe3, 0x48, 0x99, 0xc3, 0xe0, 0x47, 0x51, 0x1a, + 0xd9, 0xa0, 0x9c, 0xea, 0x3c, 0xe7, 0x5f, 0xe3, 0x96, 0x98, 0x07, 0x03, 0x17, 0xa7, 0x13, 0x39, + 0x55, 0x22, 0x25, 0xed, 0x11, 0x77, 0xf4, 0x45, 0x84, 0xac, 0x8c, 0xfa, 0x6c, 0x4e, 0xb5, 0xfc, + 0x7e, 0x82, 0xcb, 0xab, 0xfc, 0x95, 0x38, 0x1b, 0x08, 0x09, 0x98, 0x44, 0x21, 0x29, 0xc2, 0xf8, + 0x1f, 0x13, 0x5e, 0xd1, 0x4c, 0xe6, 0x0a, 0x91, 0x36, 0x9d, 0x23, 0x22, 0xbe, 0xf2, 0x5e, 0x3c, + 0x08, 0xb6, 0xbe, 0x45, 0x12, 0x4a, 0x43, 0xe2, 0xeb, 0x77, 0x95, 0x3f, 0x84, 0xdc, 0x85, 0x53, + }, + { + 0x9a, 0xc7, 0xcc, 0x9a, 0x60, 0x9d, 0x1e, 0xf7, 0xb2, 0x93, 0x28, 0x99, 0xcd, 0xe4, 0x1b, 0x97, + 0x52, 0x48, 0xc4, 0x95, 0x90, 0x14, 0x12, 0x6a, 0x6e, 0x8a, 0x84, 0xf1, 0x1d, 0x1a, 0x9e, 0x1c, + 0x06, 0x59, 0x02, 0xe4, 0xb6, 0x20, 0xf6, 0xcc, 0x36, 0xc8, 0x58, 0x9f, 0x66, 0x43, 0x2f, 0x2b, + 0xd3, 0x9d, 0x56, 0x6b, 0xc6, 0xbc, 0xe3, 0x01, 0x07, 0x68, 0x15, 0x15, 0x49, 0xf3, 0x87, 0x3f, + 0xb6, 0xd1, 0xe6, 0xc4, 0xa5, 0xe4, 0x77, 0x1c, 0xad, 0x79, 0x53, 0x8d, 0xf2, 0x95, 0xfb, 0x11, + 0xc6, 0x8c, 0x1d, 0x5c, 0x55, 0x9a, 0x97, 0x41, 0x23, 0xdf, 0x1d, 0xbc, 0x52, 0xa4, 0x3b, 0x89, + 0xc5, 0xec, 0xf8, 0x8d, 0xe8, 0x97, 0xfd, 0x57, 0xfe, 0xd3, 0x01, 0x70, 0x1b, 0x82, 0xa2, 0x59, + 0xec, 0xcb, 0xe1, 0x3d, 0xe1, 0xfc, 0xc9, 0x1c, 0x11, 0xa0, 0xb2, 0x6c, 0x0b, 0xc8, 0xfa, 0x4d, + 0xe7, 0xa7, 0x25, 0x74, 0xf8, 0x78, 0x2a, 0xe2, 0x6a, 0xab, 0xcf, 0x9e, 0xbc, 0xd6, 0x60, 0x65, + 0xbd, 0xf0, 0x32, 0x4e, 0x60, 0x83, 0xdc, 0xc6, 0xd3, 0xce, 0xdd, 0x3c, 0xa8, 0xc5, 0x3c, 0x16, + 0xb4, 0x01, 0x10, 0xc4, 0x19, 0x0b, 0x56, 0x22, 0xa9, 0x61, 0x16, 0xb0, 0x01, 0x7e, 0xd2, 0x97, + 0xff, 0xa0, 0xb5, 0x14, 0x64, 0x7e, 0xc0, 0x4f, 0x63, 0x06, 0xb8, 0x92, 0xae, 0x66, 0x11, 0x81, + 0xd0, 0x3d, 0x1b, 0xc0, 0x3c, 0xd3, 0x3d, 0x70, 0xdf, 0xf9, 0xfa, 0x5d, 0x71, 0x96, 0x3e, 0xbd, + 0x8a, 0x44, 0x12, 0x64, 0x11, 0xea, 0xa7, 0x8b, 0xd5, 0x1e, 0x8d, 0x87, 0xa8, 0x87, 0x9b, 0xf5, + 0xfa, 0xbe, 0xb7, 0x60, 0x28, 0xad, 0xe2, 0xd0, 0xe4, 0x87, 0x22, 0xe4, 0x6c, 0x46, 0x15, 0xa3, + 0xc0, 0x5d, 0x88, 0xab, 0xd5, 0x03, 0x57, 0xf9, 0x35, 0xa6, 0x3c, 0x59, 0xee, 0x53, 0x76, 0x23, + 0xff, 0x38, 0x26, 0x5c, 0x16, 0x42, 0xc1, 0xab, 0xe8, 0xd3, 0xc2, 0xfe, 0x5e, 0x57, 0x2b, 0xf8, + 0xa3, 0x6a, 0x4c, 0x30, 0x1a, 0xe8, 0xac, 0x13, 0x61, 0x0c, 0xcb, 0xc1, 0x22, 0x56, 0xca, 0xcc, + }, + { + 0x05, 0x95, 0xe5, 0x7f, 0xe5, 0xf0, 0xbb, 0x3c, 0x70, 0x6e, 0xda, 0xc8, 0xa4, 0xb2, 0xdb, 0x11, + 0xdf, 0xde, 0x31, 0x34, 0x4a, 0x1a, 0xf7, 0x69, 0xc7, 0x4f, 0x07, 0x0a, 0xee, 0x9e, 0x23, 0x26, + 0xb0, 0x6b, 0x9b, 0x1e, 0x19, 0x5d, 0x13, 0xd8, 0xf4, 0xa7, 0x99, 0x5c, 0x45, 0x53, 0xac, 0x05, + 0x6b, 0xd2, 0x37, 0x8e, 0xc3, 0x41, 0xc9, 0xa4, 0x2f, 0x37, 0xba, 0x79, 0xf8, 0x8a, 0x32, 0xff, + 0xe7, 0x0b, 0xce, 0x1d, 0xf7, 0x64, 0x5a, 0xdb, 0x5d, 0x2c, 0x41, 0x30, 0x21, 0x5c, 0x35, 0x22, + 0x9a, 0x57, 0x30, 0xc7, 0xfc, 0xb4, 0xc9, 0xaf, 0x51, 0xff, 0xda, 0x89, 0xc7, 0xf1, 0xad, 0x22, + 0x04, 0x85, 0x05, 0x5f, 0xd4, 0xf6, 0xf0, 0xd9, 0x63, 0xef, 0x5a, 0xb9, 0xa5, 0x47, 0x69, 0x82, + 0x59, 0x1f, 0xc6, 0x6b, 0xcd, 0xa1, 0x0e, 0x45, 0x2b, 0x03, 0xd4, 0x55, 0x1f, 0x6b, 0x62, 0xac, + 0x27, 0x53, 0xcc, 0x83, 0x98, 0x8a, 0xfa, 0x3e, 0x16, 0x88, 0xa1, 0xd3, 0xb4, 0x2c, 0x9a, 0x02, + 0x93, 0x61, 0x0d, 0x52, 0x3d, 0x1d, 0x3f, 0x00, 0x62, 0xb3, 0xc2, 0xa3, 0xbb, 0xc7, 0xc7, 0xf0, + 0x96, 0xc2, 0x48, 0x61, 0x0a, 0xad, 0xed, 0xfe, 0xaf, 0x89, 0x78, 0xc0, 0x3d, 0xe8, 0x20, 0x5a, + 0x0e, 0x31, 0x7b, 0x3d, 0x1c, 0x73, 0xb9, 0xe9, 0xa4, 0x68, 0x8f, 0x29, 0x6d, 0x13, 0x3a, 0x19, + 0xbd, 0xf0, 0xe6, 0xc3, 0xcc, 0xa5, 0xb5, 0xb9, 0xd5, 0x33, 0xb6, 0x9c, 0x56, 0xad, 0xa1, 0x20, + 0x88, 0xa2, 0x18, 0xb6, 0xe2, 0xec, 0xe1, 0xe6, 0x24, 0x6d, 0x44, 0xc7, 0x59, 0xd1, 0x9b, 0x10, + 0x68, 0x66, 0x39, 0x7e, 0x95, 0xc1, 0x40, 0x53, 0x4f, 0x94, 0x26, 0x34, 0x21, 0x00, 0x6e, 0x40, + 0x32, 0xcb, 0x0a, 0x1e, 0x95, 0x42, 0xc6, 0xb3, 0xb8, 0xb3, 0x98, 0xab, 0xc3, 0xb0, 0xf1, 0xd5, + 0x29, 0xa0, 0xb8, 0xae, 0xd5, 0x4a, 0x13, 0x23, 0x24, 0xc6, 0x2e, 0x42, 0x3f, 0x54, 0xb4, 0xc8, + 0x3c, 0xb0, 0xf3, 0xb5, 0x02, 0x0a, 0x98, 0xb8, 0x2a, 0xf9, 0xfe, 0x15, 0x44, 0x84, 0xa1, 0x68, + }, + { + 0xea, 0xa6, 0xbd, 0x25, 0x88, 0x0b, 0xf9, 0x3d, 0x3f, 0x5d, 0x1e, 0x4c, 0xa2, 0x61, 0x1d, 0x91, + 0xcf, 0xa4, 0x5c, 0x9f, 0x7e, 0x71, 0x4b, 0x54, 0xbd, 0xfa, 0x80, 0x02, 0x7c, 0xb1, 0x43, 0x80, + 0x11, 0x4a, 0xe3, 0x44, 0xde, 0xd7, 0x1b, 0x35, 0xf2, 0xe6, 0x0f, 0xeb, 0xad, 0x72, 0x7f, 0xd8, + 0x02, 0xe1, 0xe7, 0x05, 0x6b, 0x0f, 0x62, 0x39, 0x00, 0x49, 0x64, 0x22, 0x94, 0x3e, 0x97, 0xb6, + 0x91, 0xcb, 0x93, 0xc7, 0x87, 0x96, 0x4e, 0x10, 0xd9, 0x52, 0x7d, 0x99, 0x9c, 0x6f, 0x93, 0x6b, + 0x49, 0xb1, 0x8b, 0x42, 0xf8, 0xe8, 0x36, 0x7c, 0xbe, 0xb5, 0xef, 0x10, 0x4b, 0xa1, 0xc7, 0xcd, + 0x87, 0x08, 0x4b, 0x3b, 0xa7, 0x00, 0xba, 0xde, 0x95, 0x56, 0x10, 0x67, 0x27, 0x45, 0xb3, 0x74, + 0xe7, 0xa7, 0xb9, 0xe9, 0xec, 0x54, 0x0d, 0x5f, 0xf4, 0x3b, 0xdb, 0x12, 0x79, 0x2d, 0x1b, 0x35, + 0xc7, 0x99, 0xb5, 0x96, 0x73, 0x8f, 0x6b, 0x01, 0x8c, 0x76, 0xc7, 0x4b, 0x17, 0x59, 0xbd, 0x90, + 0x7f, 0xec, 0x5b, 0xfd, 0x9f, 0x9b, 0x89, 0xce, 0x65, 0x48, 0x30, 0x90, 0x92, 0xd7, 0xe9, 0x58, + 0x40, 0xf2, 0x50, 0xb2, 0x6d, 0x1f, 0x09, 0x6a, 0x4a, 0xfd, 0x4c, 0x34, 0x0a, 0x58, 0x88, 0x15, + 0x3e, 0x34, 0x13, 0x5c, 0x79, 0xdb, 0x01, 0x02, 0x00, 0x76, 0x76, 0x51, 0xcf, 0x26, 0x30, 0x73, + 0xf6, 0x56, 0xab, 0xcc, 0xf8, 0x8d, 0xd8, 0x27, 0x02, 0x7b, 0x2c, 0xe9, 0x17, 0xd4, 0x64, 0xec, + 0x18, 0xb6, 0x25, 0x03, 0xbf, 0xbc, 0x07, 0x7f, 0xba, 0xbb, 0x98, 0xf2, 0x0d, 0x98, 0xab, 0x34, + 0x8a, 0xed, 0x95, 0xee, 0x5b, 0x0d, 0xcb, 0xfb, 0xef, 0x4e, 0xb2, 0x1d, 0x3a, 0x3f, 0x52, 0xf9, + 0x62, 0x5a, 0x1a, 0xb0, 0x0e, 0xe3, 0x9a, 0x53, 0x27, 0x34, 0x6b, 0xdd, 0xb0, 0x1a, 0x9c, 0x18, + 0xa1, 0x3a, 0x7c, 0x79, 0xc7, 0xe1, 0x19, 0xb5, 0xab, 0x02, 0x96, 0xab, 0x28, 0xc3, 0x00, 0xb9, + 0xf3, 0xe4, 0xc0, 0xa2, 0xe0, 0x2d, 0x1d, 0x01, 0xf7, 0xf0, 0xa7, 0x46, 0x18, 0xaf, 0x2b, 0x48, + }, +}; + +unsigned char testdata2[][16 * 18] = { + { + 0x80, 0xad, 0x97, 0xbd, 0xc9, 0x73, 0xdf, 0x8a, 0x2e, 0x87, 0x9e, 0x92, 0xa4, 0x97, 0xef, 0xda, + 0x20, 0xf0, 0x60, 0xc2, 0xf2, 0xe5, 0x12, 0x65, 0x01, 0xd3, 0xd4, 0xfe, 0xa1, 0x0d, 0x5f, 0xc0, + 0xfa, 0xa1, 0x48, 0xe9, 0x90, 0x46, 0x18, 0x1f, 0xec, 0x6b, 0x20, 0x85, 0xf3, 0xb2, 0x0e, 0xd9, + 0xf0, 0xda, 0xf5, 0xba, 0xb3, 0xd5, 0x96, 0x83, 0x98, 0x57, 0x84, 0x6f, 0x73, 0xfb, 0xfe, 0x5a, + 0x1c, 0x7e, 0x2f, 0xc4, 0x63, 0x92, 0x32, 0xfe, 0x29, 0x75, 0x84, 0xb2, 0x96, 0x99, 0x6b, 0xc8, + 0x3d, 0xb9, 0xb2, 0x49, 0x40, 0x6c, 0xc8, 0xed, 0xff, 0xac, 0x55, 0xcc, 0xd3, 0x22, 0xba, 0x12, + 0xe4, 0xf9, 0xf7, 0xe0, 0x06, 0x61, 0x54, 0xbb, 0xd1, 0x25, 0xb7, 0x45, 0x56, 0x9b, 0xc8, 0x97, + 0x75, 0xd5, 0xef, 0x26, 0x2b, 0x44, 0xc4, 0x1a, 0x9c, 0xf6, 0x3a, 0xe1, 0x45, 0x68, 0xe1, 0xb9, + 0x6d, 0xa4, 0x53, 0xdb, 0xf8, 0x1e, 0x82, 0x33, 0x4a, 0x3d, 0x88, 0x66, 0xcb, 0x50, 0xa1, 0xe3, + 0x78, 0x28, 0xd0, 0x74, 0x11, 0x9c, 0xab, 0x5c, 0x22, 0xb2, 0x94, 0xd7, 0xa9, 0xbf, 0xa0, 0xbb, + 0xad, 0xb8, 0x9c, 0xea, 0x9a, 0x15, 0xfb, 0xe6, 0x17, 0x29, 0x5b, 0xd0, 0x4b, 0x8c, 0xa0, 0x5c, + 0x62, 0x51, 0xd8, 0x7f, 0xd4, 0xaa, 0xae, 0x9a, 0x7e, 0x4a, 0xd5, 0xc2, 0x17, 0xd3, 0xf3, 0x00, + 0xe7, 0x11, 0x9b, 0xd6, 0xdd, 0x9b, 0x22, 0xaf, 0xe8, 0xf8, 0x95, 0x85, 0x43, 0x28, 0x81, 0xe2, + 0x78, 0x5b, 0x60, 0xfd, 0x7e, 0xc4, 0xe9, 0xfc, 0xb6, 0x54, 0x5f, 0x35, 0x0d, 0x66, 0x0f, 0xab, + 0xaf, 0xec, 0xc0, 0x37, 0xfd, 0xb7, 0xb0, 0x83, 0x8e, 0xb3, 0xd7, 0x0b, 0xcd, 0x26, 0x83, 0x82, + 0xdb, 0xc1, 0xa7, 0xb4, 0x9d, 0x57, 0x35, 0x8c, 0xc9, 0xfa, 0x6d, 0x61, 0xd7, 0x3b, 0x7c, 0xf0, + 0x63, 0x49, 0xd1, 0x26, 0xa3, 0x7a, 0xfc, 0xba, 0x89, 0x79, 0x4f, 0x98, 0x04, 0x91, 0x4f, 0xdc, + 0xbf, 0x42, 0xc3, 0x01, 0x8c, 0x2f, 0x7c, 0x66, 0xbf, 0xde, 0x52, 0x49, 0x75, 0x76, 0x81, 0x15, + }, + { + 0xbc, 0x92, 0x22, 0xdb, 0xd3, 0x27, 0x4d, 0x8f, 0xc6, 0x6d, 0x14, 0xcc, 0xbd, 0xa6, 0x69, 0x0b, + 0x7a, 0xe6, 0x27, 0x41, 0x0c, 0x9a, 0x2b, 0xe6, 0x93, 0xdf, 0x5b, 0xb7, 0x48, 0x5a, 0x63, 0xe3, + 0x3f, 0x09, 0x31, 0xaa, 0x03, 0xde, 0xfb, 0x30, 0x0f, 0x06, 0x01, 0x03, 0x82, 0x6f, 0x2a, 0x64, + 0xbe, 0xaa, 0x9e, 0xc8, 0xd5, 0x9b, 0xb6, 0x81, 0x29, 0xf3, 0x02, 0x7c, 0x96, 0x36, 0x11, 0x81, + 0x74, 0xe0, 0x4d, 0xb4, 0x6d, 0x28, 0x64, 0x8d, 0x7d, 0xee, 0x8a, 0x00, 0x64, 0xb0, 0x6c, 0xfe, + 0x9b, 0x5e, 0x81, 0xc6, 0x2f, 0xe0, 0x23, 0xc5, 0x5b, 0xe4, 0x2f, 0x87, 0xbb, 0xf9, 0x32, 0xb8, + 0xce, 0x17, 0x8f, 0xc1, 0x82, 0x6e, 0xfe, 0xcb, 0xc1, 0x82, 0xf5, 0x79, 0x99, 0xa4, 0x61, 0x40, + 0x8b, 0xdf, 0x55, 0xcd, 0x55, 0x06, 0x1c, 0x06, 0xdb, 0xa6, 0xbe, 0x11, 0xde, 0x4a, 0x57, 0x8a, + 0x62, 0x6f, 0x5f, 0x4d, 0xce, 0x65, 0x25, 0x01, 0xf3, 0x08, 0x7d, 0x39, 0xc9, 0x2c, 0xc3, 0x49, + 0x42, 0xda, 0xac, 0x6a, 0x8f, 0x9a, 0xb9, 0xa7, 0xfd, 0x13, 0x7c, 0x60, 0x37, 0x82, 0x56, 0x82, + 0xcc, 0x03, 0xfd, 0xb7, 0x91, 0x92, 0xa2, 0x07, 0x31, 0x2f, 0x53, 0xf5, 0xd4, 0xdc, 0x33, 0xd9, + 0xf7, 0x0f, 0x14, 0x12, 0x2a, 0x1c, 0x98, 0xa3, 0x15, 0x5d, 0x28, 0xb8, 0xa0, 0xa8, 0xa4, 0x1d, + 0x2a, 0x3a, 0x30, 0x7a, 0xb2, 0x70, 0x8a, 0x9c, 0x00, 0xfe, 0x0b, 0x42, 0xf9, 0xc2, 0xd6, 0xa1, + 0x86, 0x26, 0x17, 0x62, 0x7d, 0x22, 0x61, 0xea, 0xb0, 0xb1, 0x24, 0x65, 0x97, 0xca, 0x0a, 0xe9, + 0x55, 0xf8, 0x77, 0xce, 0x4f, 0x2e, 0x1d, 0xdb, 0xbf, 0x8e, 0x13, 0xe2, 0xcd, 0xe0, 0xfd, 0xc8, + 0x1b, 0x15, 0x56, 0xcb, 0x93, 0x5f, 0x17, 0x33, 0x37, 0x70, 0x5f, 0xbb, 0x5d, 0x50, 0x1f, 0xc1, + 0xec, 0xd0, 0xe9, 0x66, 0x02, 0xbe, 0x7f, 0x8d, 0x50, 0x92, 0x81, 0x6c, 0xcc, 0xf2, 0xc2, 0xe9, + 0x02, 0x78, 0x81, 0xfa, 0xb4, 0x99, 0x3a, 0x1c, 0x26, 0x20, 0x24, 0xa9, 0x4f, 0xff, 0x3f, 0x61, + }, + { + 0xbb, 0xf6, 0x09, 0xde, 0x94, 0x13, 0x17, 0x2d, 0x07, 0x66, 0x0c, 0xb6, 0x80, 0x71, 0x69, 0x26, + 0x46, 0x10, 0x1a, 0x6d, 0xab, 0x43, 0x11, 0x5d, 0x6c, 0x52, 0x2b, 0x4f, 0xe9, 0x36, 0x04, 0xa9, + 0xcb, 0xe1, 0xff, 0xf2, 0x1c, 0x96, 0xf3, 0xee, 0xf6, 0x1e, 0x8f, 0xe0, 0x54, 0x2c, 0xbd, 0xf0, + 0x34, 0x79, 0x38, 0xbf, 0xfa, 0x40, 0x09, 0xc5, 0x12, 0xcf, 0xb4, 0x03, 0x4b, 0x0d, 0xd1, 0xa7, + 0x78, 0x67, 0xa7, 0x86, 0xd0, 0x0a, 0x71, 0x47, 0x90, 0x4d, 0x76, 0xdd, 0xf1, 0xe5, 0x20, 0xe3, + 0x8d, 0x3e, 0x9e, 0x1c, 0xae, 0xfc, 0xcc, 0xb3, 0xfb, 0xf8, 0xd1, 0x8f, 0x64, 0x12, 0x0b, 0x32, + 0x94, 0x23, 0x37, 0xf8, 0xfd, 0x76, 0xf0, 0xfa, 0xe8, 0xc5, 0x2d, 0x79, 0x54, 0x81, 0x06, 0x72, + 0xb8, 0x54, 0x8c, 0x10, 0xf5, 0x16, 0x67, 0xf6, 0xe6, 0x0e, 0x18, 0x2f, 0xa1, 0x9b, 0x30, 0xf7, + 0x02, 0x11, 0xc7, 0xc6, 0x19, 0x0c, 0x9e, 0xfd, 0x12, 0x37, 0xc3, 0x4c, 0x8f, 0x2e, 0x06, 0xc4, + 0xbd, 0xa6, 0x4f, 0x65, 0x27, 0x6d, 0x2a, 0xac, 0xb8, 0xf9, 0x02, 0x12, 0x20, 0x3a, 0x80, 0x8e, + 0xbd, 0x38, 0x20, 0xf7, 0x32, 0xff, 0xb5, 0x3e, 0xc1, 0x93, 0xe7, 0x9d, 0x33, 0xe2, 0x7c, 0x73, + 0xd0, 0x16, 0x86, 0x16, 0x86, 0x19, 0x07, 0xd4, 0x82, 0xe3, 0x6c, 0xda, 0xc8, 0xcf, 0x57, 0x49, + 0x97, 0xb0, 0xf0, 0xf2, 0x24, 0xb2, 0xd2, 0x31, 0x71, 0x14, 0x80, 0x8f, 0xb0, 0x3a, 0xf7, 0xa0, + 0xe5, 0x96, 0x16, 0xe4, 0x69, 0x78, 0x79, 0x39, 0xa0, 0x63, 0xce, 0xea, 0x9a, 0xf9, 0x56, 0xd1, + 0xc4, 0x7e, 0x0d, 0xc1, 0x66, 0x09, 0x19, 0xc1, 0x11, 0x01, 0x20, 0x8f, 0x9e, 0x69, 0xaa, 0x1f, + 0x5a, 0xe4, 0xf1, 0x28, 0x96, 0xb8, 0x37, 0x9a, 0x2a, 0xad, 0x89, 0xb5, 0xb5, 0x53, 0xd6, 0xb0, + 0x6b, 0x6b, 0x09, 0x8d, 0x0c, 0x29, 0x3b, 0xc2, 0x99, 0x3d, 0x80, 0xbf, 0x05, 0x18, 0xb6, 0xd9, + 0x81, 0x70, 0xcc, 0x3c, 0xcd, 0x92, 0xa6, 0x98, 0x62, 0x1b, 0x93, 0x9d, 0xd3, 0x8f, 0xe7, 0xb9, + }, + { + 0xab, 0x65, 0xc2, 0x6e, 0xdd, 0xb2, 0x87, 0x60, 0x0d, 0xb2, 0xfd, 0xa1, 0x0d, 0x1e, 0x60, 0x5c, + 0xbb, 0x75, 0x90, 0x10, 0xc2, 0x96, 0x58, 0xf2, 0xc7, 0x2d, 0x93, 0xa2, 0xd1, 0x6d, 0x29, 0x30, + 0xb9, 0x01, 0xe8, 0x03, 0x6e, 0xd1, 0xc3, 0x83, 0xcd, 0x3c, 0x4c, 0x4d, 0xd0, 0xa6, 0xab, 0x05, + 0x3d, 0x25, 0xce, 0x49, 0x22, 0x92, 0x4c, 0x55, 0xf0, 0x64, 0x94, 0x33, 0x53, 0xd7, 0x8a, 0x6c, + 0x12, 0xc1, 0xaa, 0x44, 0xbb, 0xf8, 0x7e, 0x75, 0xe6, 0x11, 0xf6, 0x9b, 0x2c, 0x38, 0xf4, 0x9b, + 0x28, 0xf2, 0xb3, 0x43, 0x4b, 0x65, 0xc0, 0x98, 0x77, 0x47, 0x00, 0x44, 0xc6, 0xea, 0x17, 0x0d, + 0xbd, 0x9e, 0xf8, 0x22, 0xde, 0x52, 0x88, 0x19, 0x61, 0x34, 0xcf, 0x8a, 0xf7, 0x83, 0x93, 0x04, + 0x67, 0x55, 0x9c, 0x23, 0xf0, 0x52, 0x15, 0x84, 0x70, 0xa2, 0x96, 0xf7, 0x25, 0x73, 0x5a, 0x32, + 0x8b, 0xab, 0x26, 0xfb, 0xc2, 0xc1, 0x2b, 0x0f, 0x13, 0xe2, 0xab, 0x18, 0x5e, 0xab, 0xf2, 0x41, + 0x31, 0x18, 0x5a, 0x6d, 0x69, 0x6f, 0x0c, 0xfa, 0x9b, 0x42, 0x80, 0x8b, 0x38, 0xe1, 0x32, 0xa2, + 0x56, 0x4d, 0x3d, 0xae, 0x18, 0x3c, 0x52, 0x34, 0xc8, 0xaf, 0x1e, 0x51, 0x06, 0x1c, 0x44, 0xb5, + 0x3c, 0x07, 0x78, 0xa7, 0xb5, 0xf7, 0x2d, 0x3c, 0x23, 0xa3, 0x13, 0x5c, 0x7d, 0x67, 0xb9, 0xf4, + 0xf3, 0x43, 0x69, 0x89, 0x0f, 0xcf, 0x16, 0xfb, 0x51, 0x7d, 0xca, 0xae, 0x44, 0x63, 0xb2, 0xdd, + 0x02, 0xf3, 0x1c, 0x81, 0xe8, 0x20, 0x07, 0x31, 0xb8, 0x99, 0xb0, 0x28, 0xe7, 0x91, 0xbf, 0xa7, + 0x72, 0xda, 0x64, 0x62, 0x83, 0x22, 0x8c, 0x14, 0x30, 0x08, 0x53, 0x70, 0x17, 0x95, 0x61, 0x6f, + 0x4e, 0x0a, 0x8c, 0x6f, 0x79, 0x34, 0xa7, 0x88, 0xe2, 0x26, 0x5e, 0x81, 0xd6, 0xd0, 0xc8, 0xf4, + 0x43, 0x8d, 0xd5, 0xea, 0xfe, 0xa0, 0x11, 0x1b, 0x6f, 0x36, 0xb4, 0xb9, 0x38, 0xda, 0x2a, 0x68, + 0x5f, 0x6b, 0xfc, 0x73, 0x81, 0x58, 0x74, 0xd9, 0x71, 0x00, 0xf0, 0x86, 0x97, 0x93, 0x57, 0xd8, + }, + { + 0x72, 0x0c, 0x94, 0xb6, 0x3e, 0xdf, 0x44, 0xe1, 0x31, 0xd9, 0x50, 0xca, 0x21, 0x1a, 0x5a, 0x30, + 0xc3, 0x66, 0xfd, 0xea, 0xcf, 0x9c, 0xa8, 0x04, 0x36, 0xbe, 0x7c, 0x35, 0x84, 0x24, 0xd2, 0x0b, + 0xb3, 0x39, 0x4a, 0x40, 0xaa, 0xbf, 0x75, 0xcb, 0xa4, 0x22, 0x82, 0xef, 0x25, 0xa0, 0x05, 0x9f, + 0x48, 0x47, 0xd8, 0x1d, 0xa4, 0x94, 0x2d, 0xbc, 0x24, 0x9d, 0xef, 0xc4, 0x8c, 0x92, 0x2b, 0x9f, + 0x08, 0x12, 0x8c, 0x46, 0x9f, 0x27, 0x53, 0x42, 0xad, 0xda, 0x20, 0x2b, 0x2b, 0x58, 0xda, 0x95, + 0x97, 0x0d, 0xac, 0xef, 0x40, 0xad, 0x98, 0x72, 0x3b, 0xac, 0x5d, 0x69, 0x55, 0xb8, 0x17, 0x61, + 0x3c, 0xb8, 0x99, 0x93, 0xb0, 0x7b, 0x0c, 0xed, 0x93, 0xde, 0x13, 0xd2, 0xa1, 0x10, 0x13, 0xac, + 0xef, 0x2d, 0x67, 0x6f, 0x15, 0x45, 0xc2, 0xc1, 0x3d, 0xc6, 0x80, 0xa0, 0x2f, 0x4a, 0xdb, 0xfe, + 0xb6, 0x05, 0x95, 0x51, 0x4f, 0x24, 0xbc, 0x9f, 0xe5, 0x22, 0xa6, 0xca, 0xd7, 0x39, 0x36, 0x44, + 0xb5, 0x15, 0xa8, 0xc5, 0x01, 0x17, 0x54, 0xf5, 0x90, 0x03, 0x05, 0x8b, 0xdb, 0x81, 0x51, 0x4e, + 0x3c, 0x70, 0x04, 0x7e, 0x8c, 0xbc, 0x03, 0x8e, 0x3b, 0x98, 0x20, 0xdb, 0x60, 0x1d, 0xa4, 0x95, + 0x11, 0x75, 0xda, 0x6e, 0xe7, 0x56, 0xde, 0x46, 0xa5, 0x3e, 0x2b, 0x07, 0x56, 0x60, 0xb7, 0x70, + 0x00, 0xa5, 0x42, 0xbb, 0xa0, 0x21, 0x11, 0xcc, 0x2c, 0x65, 0xb3, 0x8e, 0xbd, 0xba, 0x58, 0x7e, + 0x58, 0x65, 0xfd, 0xbb, 0x5b, 0x48, 0x06, 0x41, 0x04, 0xe8, 0x30, 0xb3, 0x80, 0xf2, 0xae, 0xde, + 0x34, 0xb2, 0x1a, 0xd2, 0xad, 0x44, 0xe9, 0x99, 0xdb, 0x2d, 0x7f, 0x08, 0x63, 0xf0, 0xd9, 0xb6, + 0x84, 0xa9, 0x21, 0x8f, 0xc3, 0x6e, 0x8a, 0x5f, 0x2c, 0xcf, 0xbe, 0xae, 0x53, 0xa2, 0x7d, 0x25, + 0xa2, 0x22, 0x1a, 0x11, 0xb8, 0x33, 0xcc, 0xb4, 0x98, 0xa5, 0x95, 0x40, 0xf0, 0x54, 0x5f, 0x4a, + 0x5b, 0xbe, 0xb4, 0x78, 0x7d, 0x59, 0xe5, 0x37, 0x3f, 0xdb, 0xea, 0x6c, 0x6f, 0x75, 0xc2, 0x9b, + }, + { + 0x54, 0xb6, 0x4e, 0x6b, 0x5a, 0x20, 0xb5, 0xe2, 0xec, 0x84, 0x59, 0x3d, 0xc7, 0x98, 0x9d, 0xa7, + 0xc1, 0x35, 0xee, 0xe2, 0x37, 0xa8, 0x54, 0x65, 0xff, 0x97, 0xdc, 0x03, 0x92, 0x4f, 0x45, 0xce, + 0xcf, 0xcc, 0x92, 0x2f, 0xb4, 0xa1, 0x4a, 0xb4, 0x5d, 0x61, 0x75, 0xaa, 0xbb, 0xf2, 0xd2, 0x01, + 0x83, 0x7b, 0x87, 0xe2, 0xa4, 0x46, 0xad, 0x0e, 0xf7, 0x98, 0xac, 0xd0, 0x2b, 0x94, 0x12, 0x4f, + 0x17, 0xa6, 0xdb, 0xd6, 0x64, 0x92, 0x6a, 0x06, 0x36, 0xb3, 0xf4, 0xc3, 0x7a, 0x4f, 0x46, 0x94, + 0x4a, 0x5f, 0x9f, 0x26, 0xae, 0xee, 0xd4, 0xd4, 0xa2, 0x5f, 0x63, 0x2d, 0x30, 0x52, 0x33, 0xd9, + 0x80, 0xa3, 0xd0, 0x1e, 0xf0, 0x0c, 0x8e, 0x9a, 0x42, 0x09, 0xc1, 0x7f, 0x4e, 0xeb, 0x35, 0x8c, + 0xd1, 0x5e, 0x7d, 0x5f, 0xfa, 0xaa, 0xbc, 0x02, 0x07, 0xbf, 0x20, 0x0a, 0x11, 0x77, 0x93, 0xa2, + 0x34, 0x96, 0x82, 0xbf, 0x58, 0x8e, 0xaa, 0x52, 0xd0, 0xaa, 0x15, 0x60, 0x34, 0x6a, 0xea, 0xfa, + 0xf5, 0x85, 0x4c, 0xdb, 0x76, 0xc8, 0x89, 0xe3, 0xad, 0x63, 0x35, 0x4e, 0x5f, 0x72, 0x75, 0xe3, + 0x53, 0x2c, 0x7c, 0xec, 0xcb, 0x39, 0xdf, 0x32, 0x36, 0x31, 0x84, 0x05, 0xa4, 0xb1, 0x27, 0x9c, + 0xba, 0xef, 0xe6, 0xd9, 0xce, 0xb6, 0x51, 0x84, 0x22, 0x60, 0xe0, 0xd1, 0xe0, 0x5e, 0x3b, 0x90, + 0xe8, 0x2d, 0x8c, 0x6d, 0xb5, 0x4e, 0x3c, 0x63, 0x3f, 0x58, 0x1c, 0x95, 0x2b, 0xa0, 0x42, 0x07, + 0x4b, 0x16, 0xe5, 0x0a, 0xbd, 0x38, 0x1b, 0xd7, 0x09, 0x00, 0xa9, 0xcd, 0x9a, 0x62, 0xcb, 0x23, + 0x36, 0x82, 0xee, 0x33, 0xbd, 0x14, 0x8b, 0xd9, 0xf5, 0x86, 0x56, 0xcd, 0x8f, 0x30, 0xd9, 0xfb, + 0x1e, 0x5a, 0x0b, 0x84, 0x75, 0x04, 0x5d, 0x9b, 0x20, 0xb2, 0x62, 0x86, 0x24, 0xed, 0xfd, 0x9e, + 0x63, 0xed, 0xd6, 0x84, 0xfb, 0x82, 0x62, 0x82, 0xfe, 0x52, 0x8f, 0x9c, 0x0e, 0x92, 0x37, 0xbc, + 0xe4, 0xdd, 0x2e, 0x98, 0xd6, 0x96, 0x0f, 0xae, 0x0b, 0x43, 0x54, 0x54, 0x56, 0x74, 0x33, 0x91, + }, + { + 0xdd, 0x5b, 0xcb, 0x00, 0x18, 0xe9, 0x22, 0xd4, 0x94, 0x75, 0x9d, 0x7c, 0x39, 0x5d, 0x02, 0xd3, + 0xc8, 0x44, 0x6f, 0x8f, 0x77, 0xab, 0xf7, 0x37, 0x68, 0x53, 0x53, 0xeb, 0x89, 0xa1, 0xc9, 0xeb, + 0xaf, 0x3e, 0x30, 0xf9, 0xc0, 0x95, 0x04, 0x59, 0x38, 0x15, 0x15, 0x75, 0xc3, 0xfb, 0x90, 0x98, + 0xf8, 0xcb, 0x62, 0x74, 0xdb, 0x99, 0xb8, 0x0b, 0x1d, 0x20, 0x12, 0xa9, 0x8e, 0xd4, 0x8f, 0x0e, + 0x25, 0xc3, 0x00, 0x5a, 0x1c, 0xb8, 0x5d, 0xe0, 0x76, 0x25, 0x98, 0x39, 0xab, 0x71, 0x98, 0xab, + 0x9d, 0xcb, 0xc1, 0x83, 0xe8, 0xcb, 0x99, 0x4b, 0x72, 0x7b, 0x75, 0xbe, 0x31, 0x80, 0x76, 0x9c, + 0xa1, 0xd3, 0x07, 0x8d, 0xfa, 0x91, 0x69, 0x50, 0x3e, 0xd9, 0xd4, 0x49, 0x1d, 0xee, 0x4e, 0xb2, + 0x85, 0x14, 0xa5, 0x49, 0x58, 0x58, 0x09, 0x6f, 0x59, 0x6e, 0x4b, 0xcd, 0x66, 0xb1, 0x06, 0x65, + 0x5f, 0x40, 0xd5, 0x9e, 0xc1, 0xb0, 0x3b, 0x33, 0x73, 0x8e, 0xfa, 0x60, 0xb2, 0x25, 0x5d, 0x31, + 0x34, 0x77, 0xc7, 0xf7, 0x64, 0xa4, 0x1b, 0xac, 0xef, 0xf9, 0x0b, 0xf1, 0x4f, 0x92, 0xb7, 0xcc, + 0xac, 0x4e, 0x95, 0x36, 0x8d, 0x99, 0xb9, 0xeb, 0x78, 0xb8, 0xda, 0x8f, 0x81, 0xff, 0xa7, 0x95, + 0x8c, 0x3c, 0x13, 0xf8, 0xc2, 0x38, 0x8b, 0xb7, 0x3f, 0x38, 0x57, 0x6e, 0x65, 0xb7, 0xc4, 0x46, + 0x13, 0xc4, 0xb9, 0xc1, 0xdf, 0xb6, 0x65, 0x79, 0xed, 0xdd, 0x8a, 0x28, 0x0b, 0x9f, 0x73, 0x16, + 0xdd, 0xd2, 0x78, 0x20, 0x55, 0x01, 0x26, 0x69, 0x8e, 0xfa, 0xad, 0xc6, 0x4b, 0x64, 0xf6, 0x6e, + 0xf0, 0x8f, 0x2e, 0x66, 0xd2, 0x8e, 0xd1, 0x43, 0xf3, 0xa2, 0x37, 0xcf, 0x9d, 0xe7, 0x35, 0x59, + 0x9e, 0xa3, 0x6c, 0x52, 0x55, 0x31, 0xb8, 0x80, 0xba, 0x12, 0x43, 0x34, 0xf5, 0x7b, 0x0b, 0x70, + 0xd5, 0xa3, 0x9e, 0x3d, 0xfc, 0xc5, 0x02, 0x80, 0xba, 0xc4, 0xa6, 0xb5, 0xaa, 0x0d, 0xca, 0x7d, + 0x37, 0x0b, 0x1c, 0x1f, 0xe6, 0x55, 0x91, 0x6d, 0x97, 0xfd, 0x0d, 0x47, 0xca, 0x1d, 0x72, 0xb8, + }, +}; + +int main(void) +{ + int err = 0; + RC4_STATE state; + unsigned char buf[4096 + 16]; + size_t i, j; + + for (i = 0; i < sizeof(keybits)/sizeof(keybits[0]); i++) { + int e = 0; + rc4_init(&state, key1, keybits[i]/8); + rc4_generate_keystream(&state, sizeof(buf), buf); + for (j = 0; j < sizeof(testindex)/sizeof(testindex[0]); j++) { + if (memcmp(buf + testindex[j], &testdata1[i][j * 16], 16) != 0) { + e++; + } + } + fprintf(stderr, "rc4 test 1.%zu %s\n", i+1, e ? "failed" : "ok"); + if (e) { + err++; + } + } + + for (i = 0; i < sizeof(keybits)/sizeof(keybits[0]); i++) { + int e = 0; + rc4_init(&state, key2 + sizeof(key2) - keybits[i]/8, keybits[i]/8); + rc4_generate_keystream(&state, sizeof(buf), buf); + for (j = 0; j < sizeof(testindex)/sizeof(testindex[0]); j++) { + if (memcmp(buf + testindex[j], &testdata2[i][j * 16], 16) != 0) { + e++; + } + } + fprintf(stderr, "rc4 test 2.%zu %s\n", i+1, e ? "failed" : "ok"); + if (e) { + err++; + } + } + + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/sha1test.c b/Core/GmSSL-3.1.1/tests/sha1test.c new file mode 100644 index 0000000..9043a08 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sha1test.c @@ -0,0 +1,72 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static char *teststr[] = { + "abc", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "a", + "0123456701234567012345670123456701234567012345670123456701234567", +}; + +static size_t testcnt[] = { + 1, + 1, + 1000000, + 10, +}; + +static char *dgsthex[] = { + "A9993E364706816ABA3E25717850C26C9CD0D89D", + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1", + "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F", + "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452", +}; + +int main(void) +{ + int err = 0; + SHA1_CTX ctx; + uint8_t dgst[20]; + uint8_t dgstbuf[20]; + size_t dgstlen; + size_t i, j; + + for (i = 0; i < sizeof(teststr)/sizeof(teststr[0]); i++) { + hex_to_bytes(dgsthex[i], strlen(dgsthex[i]), dgstbuf, &dgstlen); + + sha1_init(&ctx); + for (j = 0; j < testcnt[i]; j++) { + sha1_update(&ctx, (uint8_t *)teststr[i], strlen(teststr[i])); + } + sha1_finish(&ctx, dgst); + + if (memcmp(dgstbuf, dgst, sizeof(dgst)) != 0) { + printf("sha1 test %zu failed\n", i+1); + printf("%s\n", dgsthex[i]); + for (j = 0; j < sizeof(dgst); j++) { + printf("%02X", dgst[j]); + } + printf("\n"); + err++; + } else { + printf("sha1 test %zu ok\n", i+1); + } + } + + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/sha224test.c b/Core/GmSSL-3.1.1/tests/sha224test.c new file mode 100644 index 0000000..98a4523 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sha224test.c @@ -0,0 +1,94 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +#define TEST1 "abc" +#define TEST2 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +#define TEST3 "a" +#define TEST4 "0123456701234567012345670123456701234567012345670123456701234567" +#define TEST5 "\x07" +#define TEST6 "\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29\x9d\x6f\x9d\x93\xdf\x62" +#define TEST7 \ + "\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52\x06\x22\xd1\xac\x97\xd5" \ + "\xcd\xbe\x8c\xb3\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba\x09\xab" \ + "\xc8\x53\x3c\x52\x50\x88\x7a\x43\xbe\xbb\xac\x90\x6c\x2e\x18\x37" \ + "\xf2\x6b\x36\xa5\x9a\xe3\xbe\x78\x14\xd5\x06\x89\x6b\x71\x8b\x2a" \ + "\x38\x3e\xcd\xac\x16\xb9\x61\x25\x55\x3f\x41\x6f\xf3\x2c\x66\x74" \ + "\xc7\x45\x99\xa9\x00\x53\x86\xd9\xce\x11\x12\x24\x5f\x48\xee\x47" \ + "\x0d\x39\x6c\x1e\xd6\x3b\x92\x67\x0c\xa5\x6e\xc8\x4d\xee\xa8\x14" \ + "\xb6\x13\x5e\xca\x54\x39\x2b\xde\xdb\x94\x89\xbc\x9b\x87\x5a\x8b" \ + "\xaf\x0d\xc1\xae\x78\x57\x36\x91\x4a\xb7\xda\xa2\x64\xbc\x07\x9d" \ + "\x26\x9f\x2c\x0d\x7e\xdd\xd8\x10\xa4\x26\x14\x5a\x07\x76\xf6\x7c" \ + "\x87\x82\x73" + + +#define DGST1 "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7" +#define DGST2 "75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525" +#define DGST3 "20794655980C91D8BBB4C1EA97618A4BF03F42581948B2EE4EE7AD67" +#define DGST4 "567F69F168CD7844E65259CE658FE7AADFA25216E68ECA0EB7AB8262" +#define DGST5 "00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450BEE2AA8C2A" +#define DGST6 "DF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC388E56191DB1" +#define DGST7 "0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E9F20D5C3A4" + +struct { + char *data; + size_t length; + size_t count; + char *dgsthex; +} tests[7] = { + {TEST1, sizeof(TEST1) - 1, 1, DGST1}, + {TEST2, sizeof(TEST2) - 1, 1, DGST2}, + {TEST3, sizeof(TEST3) - 1, 1000000, DGST3}, + {TEST4, sizeof(TEST4) - 1, 10, DGST4}, + {TEST5, sizeof(TEST5) - 1, 1, DGST5}, + {TEST6, sizeof(TEST6) - 1, 1, DGST6}, + {TEST7, sizeof(TEST7) - 1, 1, DGST7}, +}; + +int main(int argc, char **argv) +{ + int err = 0; + SHA224_CTX ctx; + uint8_t dgst[SHA224_DIGEST_SIZE]; + uint8_t dgstbuf[SHA224_DIGEST_SIZE]; + size_t dgstlen; + size_t i, j; + + for (i = 0; i < 7; i++) { + hex_to_bytes(tests[i].dgsthex, strlen(tests[i].dgsthex), dgstbuf, &dgstlen); + + sha224_init(&ctx); + for (j = 0; j < tests[i].count; j++) { + sha224_update(&ctx, (uint8_t *)tests[i].data, tests[i].length); + } + sha224_finish(&ctx, dgst); + + if (memcmp(dgstbuf, dgst, sizeof(dgst)) != 0) { + printf("sha224 test %zu failed\n", i+1); + printf("%s\n", tests[i].dgsthex); + for (j = 0; j < sizeof(dgst); j++) { + printf("%02X", dgst[j]); + } + printf("\n"); + err++; + } else { + printf("sha224 test %zu ok\n", i+1); + } + } + + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/sha256test.c b/Core/GmSSL-3.1.1/tests/sha256test.c new file mode 100644 index 0000000..cba9d39 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sha256test.c @@ -0,0 +1,93 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +#define TEST1 "abc" +#define TEST2 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +#define TEST3 "a" +#define TEST4 "0123456701234567012345670123456701234567012345670123456701234567" +#define TEST5 "\x19" +#define TEST6 "\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52" +#define TEST7 "\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \ + "\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \ + "\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \ + "\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \ + "\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \ + "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65\x92\xec\xed\xaa\x66\xca" \ + "\x82\xa2\x9d\x0c\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4\xc0\xa4" \ + "\x3f\x8d\x79\xa3\x0a\x16\x5c\xba\xbe\x45\x2b\x77\x4b\x9c\x71\x09" \ + "\xa9\x7d\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc\x10\x6a\xad\x5a" \ + "\x9f\xdd\x30\x82\x57\x69\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" \ + "\x3d\x54\xd6" + +#define DGST1 "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD" +#define DGST2 "248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1" +#define DGST3 "CDC76E5C9914FB9281A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0" +#define DGST4 "594847328451BDFA85056225462CC1D867D877FB388DF0CE35F25AB5562BFBB5" +#define DGST5 "68AA2E2EE5DFF96E3355E6C7EE373E3D6A4E17F75F9518D843709C0C9BC3E3D4" +#define DGST6 "175EE69B02BA9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" +#define DGST7 "97DBCA7DF46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" + +struct { + char *data; + size_t length; + size_t count; + char *dgsthex; +} tests[7] = { + {TEST1, sizeof(TEST1) - 1, 1, DGST1}, + {TEST2, sizeof(TEST2) - 1, 1, DGST2}, + {TEST3, sizeof(TEST3) - 1, 1000000, DGST3}, + {TEST4, sizeof(TEST4) - 1, 10, DGST4}, + {TEST5, sizeof(TEST5) - 1, 1, DGST5}, + {TEST6, sizeof(TEST6) - 1, 1, DGST6}, + {TEST7, sizeof(TEST7) - 1, 1, DGST7}, +}; + +int main(int argc, char **argv) +{ + int err = 0; + SHA256_CTX ctx; + uint8_t dgst[SHA256_DIGEST_SIZE]; + uint8_t dgstbuf[SHA256_DIGEST_SIZE]; + size_t dgstlen; + size_t i, j; + + for (i = 0; i < 7; i++) { + hex_to_bytes(tests[i].dgsthex, strlen(tests[i].dgsthex), dgstbuf, &dgstlen); + + sha256_init(&ctx); + for (j = 0; j < tests[i].count; j++) { + sha256_update(&ctx, (uint8_t *)tests[i].data, tests[i].length); + } + sha256_finish(&ctx, dgst); + + if (memcmp(dgstbuf, dgst, sizeof(dgst)) != 0) { + printf("sha256 test %zu failed\n", i+1); + printf("%s\n", tests[i].dgsthex); + for (j = 0; j < sizeof(dgst); j++) { + printf("%02X", dgst[j]); + } + printf("\n"); + err++; + } else { + printf("sha256 test %zu ok\n", i+1); + } + } + + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/sha384test.c b/Core/GmSSL-3.1.1/tests/sha384test.c new file mode 100644 index 0000000..c2eec21 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sha384test.c @@ -0,0 +1,99 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +#define TEST1 "abc" +#define TEST2 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" \ + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" +#define TEST3 "a" +#define TEST4 "0123456701234567012345670123456701234567012345670123456701234567" +#define TEST5 "\xb9" +#define TEST6 "\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1\x0a\x7f\x4e\x08\x59\x17\x39" +#define TEST7 "\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb\x69\x12\xec\x10\xff\xcf" \ + "\x74\x79\x03\x49\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21\xdb\x0f" \ + "\x3e\x7d\xc8\x7f\x82\x32\x64\xbb\xe4\x0d\x18\x11\xc9\xea\x20\x61" \ + "\xe1\xc8\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02\xfc\x3f\x50\x42" \ + "\xe6\xbf\x58\xcb\xa8\xa2\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71" \ + "\x15\x07\x05\x3c\xf4\xe5\x33\x9d\x52\x86\x5f\x25\xcc\x22\xb5\xe8" \ + "\x77\x84\xa1\x2f\xc9\x61\xd6\x6c\xb6\xe8\x95\x73\x19\x9a\x2c\xe6" \ + "\x56\x5c\xbd\xf1\x3d\xca\x40\x38\x32\xcf\xcb\x0e\x8b\x72\x11\xe8" \ + "\x3a\xf3\x2a\x11\xac\x17\x92\x9f\xf1\xc0\x73\xa5\x1c\xc0\x27\xaa" \ + "\xed\xef\xf8\x5a\xad\x7c\x2b\x7c\x5a\x80\x3e\x24\x04\xd9\x6d\x2a" \ + "\x77\x35\x7b\xda\x1a\x6d\xae\xed\x17\x15\x1c\xb9\xbc\x51\x25\xa4" \ + "\x22\xe9\x41\xde\x0c\xa0\xfc\x50\x11\xc2\x3e\xcf\xfe\xfd\xd0\x96" \ + "\x76\x71\x1c\xf3\xdb\x0a\x34\x40\x72\x0e\x16\x15\xc1\xf2\x2f\xbc" \ + "\x3c\x72\x1d\xe5\x21\xe1\xb9\x9b\xa1\xbd\x55\x77\x40\x86\x42\x14" \ + "\x7e\xd0\x96" + +#define DGST1 "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7" +#define DGST2 "09330C33F71147E83D192FC782CD1B4753111B173B3B05D22FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039" +#define DGST3 "9D0E1809716474CB086E834E310A4A1CED149E9C00F248527972CEC5704C2A5B07B8B3DC38ECC4EBAE97DDD87F3D8985" +#define DGST4 "2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A70BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A0D79FB4596" +#define DGST5 "BC8089A19007C0B14195F4ECC74094FEC64F01F90929282C2FB392881578208AD466828B1C6C283D2722CF0AD1AB6938" +#define DGST6 "C9A68443A005812256B8EC76B00516F0DBB74FAB26D665913F194B6FFB0E91EA9967566B58109CBC675CC208E4C823F7" +#define DGST7 "4F440DB1E6EDD2899FA335F09515AA025EE177A79F4B4AAF38E42B5C4DE660F5DE8FB2A5B2FBD2A3CBFFD20CFF1288C0" + + +struct { + char *data; + size_t length; + size_t count; + char *dgsthex; +} tests[7] = { + {TEST1, sizeof(TEST1) - 1, 1, DGST1}, + {TEST2, sizeof(TEST2) - 1, 1, DGST2}, + {TEST3, sizeof(TEST3) - 1, 1000000, DGST3}, + {TEST4, sizeof(TEST4) - 1, 10, DGST4}, + {TEST5, sizeof(TEST5) - 1, 1, DGST5}, + {TEST6, sizeof(TEST6) - 1, 1, DGST6}, + {TEST7, sizeof(TEST7) - 1, 1, DGST7}, +}; + +int main(void) +{ + int err = 0; + SHA384_CTX ctx; + uint8_t dgst[SHA384_DIGEST_SIZE]; + uint8_t dgstbuf[SHA384_DIGEST_SIZE]; + size_t dgstlen; + size_t i, j; + + for (i = 0; i < 7; i++) { + hex_to_bytes(tests[i].dgsthex, strlen(tests[i].dgsthex), dgstbuf, &dgstlen); + + sha384_init(&ctx); + for (j = 0; j < tests[i].count; j++) { + sha384_update(&ctx, (uint8_t *)tests[i].data, tests[i].length); + } + sha384_finish(&ctx, dgst); + + if (memcmp(dgstbuf, dgst, sizeof(dgst)) != 0) { + printf("sha384 test %zu failed\n", i+1); + printf("%s\n", tests[i].dgsthex); + for (j = 0; j < sizeof(dgst); j++) { + printf("%02x", dgst[j]); + } + printf("\n"); + err++; + } else { + printf("sha384 test %zu ok\n", i+1); + } + } + + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/sha512test.c b/Core/GmSSL-3.1.1/tests/sha512test.c new file mode 100644 index 0000000..3d08c82 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sha512test.c @@ -0,0 +1,100 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include + + +#define TEST1 "abc" +#define TEST2 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" \ + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" +#define TEST3 "a" +#define TEST4 "0123456701234567012345670123456701234567012345670123456701234567" +#define TEST5 "\xD0" +#define TEST6 "\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0" +#define TEST7 \ + "\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \ + "\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \ + "\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \ + "\x93\x60\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d\x03\xe5\x6f\xf2" \ + "\xf8\x68\x00\x2b\xc3\xe4\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" \ + "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69\x4f\xcb\xba\xf8\x8d\x95" \ + "\x19\xe4\xeb\x50\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc\x44\x65" \ + "\xc8\x82\x1a\xac\xd2\xfe\x15\xab\x49\x81\x16\x4b\xbb\x6d\xc3\x2f" \ + "\x96\x90\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b\x76\x32\x99\x41" \ + "\x9c\xc4\x12\x8b\xe9\xa0\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" \ + "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13\x2e\x9a\x0d\xc6\xd3\xb1" \ + "\xf8\xb2\x46\xf1\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20\x98\xe8" \ + "\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f\x47\x07\xfe\x1e\xa1\xa1\x79\x1b" \ + "\xa2\xf3\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9\x49\xad\x47\xd7" \ + "\xfb\x40\xd2" + +#define DGST1 "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F" +#define DGST2 "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA17299AEADB6889018501D289E4900F7E4331B99DEC4B5433AC7D329EEB6DD26545E96E55B874BE909" +#define DGST3 "E718483D0CE769644E2E42C7BC15B4638E1F98B13B2044285632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B" +#define DGST4 "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB510813A39CD5A84C4ACAA64D3F3FB7BAE9" +#define DGST5 "9992202938E882E73E20F6B69E68A0A7149090423D93C81BAB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4AD6E74CECE9631BFA8A549B4AB3FBBA15" +#define DGST6 "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBDD1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F6773988213EB1B16F517AD0DE4B2F0C95C90F8" +#define DGST7 "C665BEFB36DA189D78822D10528CBF3B12B3EEF726039909C1A16A270D48719377966B957A878E720584779A62825C18DA26415E49A7176A894E7510FD1451F5" + + +struct { + char *data; + size_t length; + size_t count; + char *dgsthex; +} tests[7] = { + {TEST1, sizeof(TEST1) - 1, 1, DGST1}, + {TEST2, sizeof(TEST2) - 1, 1, DGST2}, + {TEST3, sizeof(TEST3) - 1, 1000000, DGST3}, + {TEST4, sizeof(TEST4) - 1, 10, DGST4}, + {TEST5, sizeof(TEST5) - 1, 1, DGST5}, + {TEST6, sizeof(TEST6) - 1, 1, DGST6}, + {TEST7, sizeof(TEST7) - 1, 1, DGST7}, +}; + +int main(void) +{ + int err = 0; + SHA512_CTX ctx; + uint8_t dgst[SHA512_DIGEST_SIZE]; + uint8_t dgstbuf[SHA512_DIGEST_SIZE]; + size_t dgstlen; + size_t i, j; + + for (i = 0; i < 7; i++) { + hex_to_bytes(tests[i].dgsthex, strlen(tests[i].dgsthex), dgstbuf, &dgstlen); + + sha512_init(&ctx); + for (j = 0; j < tests[i].count; j++) { + sha512_update(&ctx, (uint8_t *)tests[i].data, tests[i].length); + } + sha512_finish(&ctx, dgst); + + if (memcmp(dgstbuf, dgst, sizeof(dgst)) != 0) { + printf("sha512 test %zu failed\n", i+1); + printf("%s\n", tests[i].dgsthex); + for (j = 0; j < sizeof(dgst); j++) { + printf("%02x", dgst[j]); + } + printf("\n"); + err++; + } else { + printf("sha512 test %zu ok\n", i+1); + } + } + + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_blindtest.c b/Core/GmSSL-3.1.1/tests/sm2_blindtest.c new file mode 100644 index 0000000..7fdce98 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_blindtest.c @@ -0,0 +1,100 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + + +static int test_sm2_blind_sign(void) +{ + int r = -1; + + // signer + SM2_KEY key; + SM2_Fn k; + uint8_t commit[65]; + size_t commitlen; + + // caller + SM2_KEY public_key; + SM2_BLIND_SIGN_CTX sign_ctx; + uint8_t msg[128] = {0}; + uint8_t blinded_sig_s[32]; + uint8_t blinded_sig_r[32]; + uint8_t sig[128]; + size_t siglen; + + // verifier + SM2_SIGN_CTX verify_ctx; + + + // signer + if (sm2_key_generate(&key) != 1 + || sm2_key_set_public_key(&public_key, &key.public_key) != 1) { + error_print(); + goto end; + } + if (sm2_blind_sign_commit(k, commit, &commitlen) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 0, "signer: commitment", commit, commitlen); + + // caller + if (sm2_blind_sign_init(&sign_ctx, &public_key, + SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1 + || sm2_blind_sign_update(&sign_ctx, msg, 32) != 1 + || sm2_blind_sign_update(&sign_ctx, msg + 32, 32) != 1 + || sm2_blind_sign_update(&sign_ctx, msg + 64, 64) != 1 + || sm2_blind_sign_finish(&sign_ctx, commit, commitlen, blinded_sig_r) != 1) { + error_print(); + goto end; + } + format_bytes(stderr, 0, 0, "caller: blinded_sig_r", blinded_sig_r, sizeof(blinded_sig_r)); + + // signer + if (sm2_blind_sign(&key, k, blinded_sig_r, blinded_sig_s) != 1) { + error_print(); + goto end; + } + format_bytes(stderr, 0, 0, "signer: blinded_sig_s", blinded_sig_s, sizeof(blinded_sig_s)); + + // caller + if (sm2_blind_sign_unblind(&sign_ctx, blinded_sig_s, sig, &siglen) != 1) { + error_print(); + goto end; + } + format_bytes(stderr, 0, 0, "caller: unblinded_sig", sig, siglen); + + // verifier + if (sm2_verify_init(&verify_ctx, &public_key, + SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1 + || sm2_verify_update(&verify_ctx, msg, sizeof(msg)) != 1 + || (r = sm2_verify_finish(&verify_ctx, sig, siglen)) < 0) { + error_print(); + goto end; + } + format_print(stderr, 0, 0, "verifier: %s\n", r == 1 ? "success" : "failure"); + +end: + gmssl_secure_clear(&key, sizeof(key)); + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + return r; +} + +int main(void) +{ + if (test_sm2_blind_sign() != 1) { error_print(); return -1; } + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_committest.c b/Core/GmSSL-3.1.1/tests/sm2_committest.c new file mode 100644 index 0000000..80d474e --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_committest.c @@ -0,0 +1,59 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + + +static int test_sm2_commit(void) +{ + uint8_t x[32]; + uint8_t xvec[8][32]; + uint8_t r[32]; + uint8_t commit[65]; + size_t commitlen; + int ret; + + rand_bytes(x, sizeof(x)); + format_bytes(stderr, 0, 0, "secret", x, sizeof(x)); + + sm2_commit_generate(x, r, commit, &commitlen); + format_bytes(stderr, 0, 0, "random", r, sizeof(r)); + format_bytes(stderr, 0, 0, "commitment", commit, commitlen); + + ret = sm2_commit_open(x, r, commit, commitlen); + printf("open commitment: %s\n", ret == 1 ? "success" : "failure"); + + + sm2_commit_vector_generate(&x, 1, r, commit, &commitlen); + format_bytes(stderr, 0, 0, "random", r, sizeof(r)); + format_bytes(stderr, 0, 0, "commitment", commit, commitlen); + + ret = sm2_commit_vector_open(&x, 1, r, commit, commitlen); + printf("open commitment: %s\n", ret == 1 ? "success" : "failure"); + + + rand_bytes(xvec[0], sizeof(xvec)); + sm2_commit_vector_generate(xvec, 8, r, commit, &commitlen); + ret = sm2_commit_vector_open(xvec, 8, r, commit, commitlen); + printf("open commitment: %s\n", ret == 1 ? "success" : "failure"); + + return 1; +} + +int main(void) +{ + if (test_sm2_commit() != 1) { error_print(); return -1; } + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_elgamaltest.c b/Core/GmSSL-3.1.1/tests/sm2_elgamaltest.c new file mode 100644 index 0000000..57cd7b8 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_elgamaltest.c @@ -0,0 +1,22 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + + +int main(void) +{ + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_key_sharetest.c b/Core/GmSSL-3.1.1/tests/sm2_key_sharetest.c new file mode 100644 index 0000000..ac969fd --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_key_sharetest.c @@ -0,0 +1,96 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_sm2_key_share_args(size_t k, size_t n) +{ + SM2_KEY key; + SM2_KEY key_; + SM2_KEY_SHARE shares[SM2_KEY_MAX_SHARES]; + + if (sm2_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (sm2_key_split(&key, k, n, shares) != 1) { + error_print(); + return -1; + } + + // recover from 0 .. k + if (sm2_key_recover(&key_, shares, k) != 1) { + error_print(); + return -1; + } + if (memcmp(&key_, &key, sizeof(SM2_KEY)) != 0) { + error_print(); + return -1; + } + + // recover from n-k .. n + memset(&key_, 0, sizeof(key_)); + if (sm2_key_recover(&key_, shares + n - k, k) != 1) { + error_print(); + return -1; + } + if (memcmp(&key_, &key, sizeof(SM2_KEY)) != 0) { + error_print(); + return -1; + } + return 1; +} + +static int test_sm2_key_share(void) +{ + if (test_sm2_key_share_args(1, 1) != 1) { error_print(); return -1; } + if (test_sm2_key_share_args(1, 3) != 1) { error_print(); return -1; } + if (test_sm2_key_share_args(2, 3) != 1) { error_print(); return -1; } + if (test_sm2_key_share_args(3, 5) != 1) { error_print(); return -1; } + if (test_sm2_key_share_args(4, 5) != 1) { error_print(); return -1; } + if (test_sm2_key_share_args(5, 5) != 1) { error_print(); return -1; } + if (test_sm2_key_share_args(11, 12) != 1) { error_print(); return -1; } + if (test_sm2_key_share_args(12, 12) != 1) { error_print(); return -1; } + return 1; +} + +static int test_sm2_key_share_file(void) +{ + SM2_KEY key; + SM2_KEY_SHARE shares[SM2_KEY_MAX_SHARES]; + + if (sm2_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (sm2_key_split(&key, 2, 3, shares) != 1) { + error_print(); + return -1; + } + if (sm2_key_share_encrypt_to_file(&shares[0], "123456", "sm2key") != 1 + || sm2_key_share_encrypt_to_file(&shares[1], "123456", "sm2key") != 1 + || sm2_key_share_encrypt_to_file(&shares[2], "123456", "sm2key") != 1) { + error_print(); + return -1; + } + return 1; +} + +int main(void) +{ + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_recovertest.c b/Core/GmSSL-3.1.1/tests/sm2_recovertest.c new file mode 100644 index 0000000..66fe82e --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_recovertest.c @@ -0,0 +1,44 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + + +static int test_sm2_signature_to_public_key_points(void) +{ + SM2_KEY key; + uint8_t dgst[32] = {1,2,3,4}; + SM2_SIGNATURE sig; + SM2_POINT points[4]; + size_t points_cnt, i; + + sm2_key_generate(&key); + sm2_do_sign(&key, dgst, &sig); + sm2_signature_to_public_key_points(&sig, dgst, points, &points_cnt); + + for (i = 0; i < points_cnt; i++) { + int vr; + sm2_point_print(stderr, 0, 0, "point", &points[i]); + vr = sm2_do_verify((SM2_KEY *)&points[1], dgst, &sig); + printf("verify = %d\n", vr); + } + return 1; +} + +int main(void) +{ + if (test_sm2_signature_to_public_key_points() != 1) { error_print(); return -1; } + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_ringtest.c b/Core/GmSSL-3.1.1/tests/sm2_ringtest.c new file mode 100644 index 0000000..5a1776c --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_ringtest.c @@ -0,0 +1,174 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + + +static int test_sm2_ring_do_sign(void) +{ + SM2_KEY sign_key; + SM2_POINT public_keys[5]; + size_t public_keys_count = sizeof(public_keys)/sizeof(public_keys[0]); + size_t sign_index, i; + uint8_t dgst[32]; + uint8_t r[32]; + uint8_t s[sizeof(public_keys)/sizeof(public_keys[0])][32]; + + for (sign_index = 0; sign_index < 5; sign_index++) { + + for (i = 0; i < public_keys_count; i++) { + SM2_KEY key; + sm2_key_generate(&key); + memcpy(&public_keys[i], &(key.public_key), sizeof(SM2_POINT)); + + if (i == sign_index) { + memcpy(&sign_key, &key, sizeof(SM2_KEY)); + } + } + if (sm2_ring_do_sign(&sign_key, public_keys, public_keys_count, dgst, r, s) != 1) { + error_print(); + return -1; + } + if (sm2_ring_do_verify(public_keys, public_keys_count, dgst, r, s) != 1) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_ring_sign(void) +{ + SM2_KEY sign_key; + SM2_POINT public_keys[5]; + size_t public_keys_count = sizeof(public_keys)/sizeof(public_keys[0]); + size_t sign_index = 2, i; + uint8_t dgst[32]; + uint8_t sig[9 + (2 + 33) * (1 + sizeof(public_keys)/sizeof(public_keys[0]))]; + size_t siglen = 0; + + for (i = 0; i < public_keys_count; i++) { + SM2_KEY key; + sm2_key_generate(&key); + memcpy(&public_keys[i], &(key.public_key), sizeof(SM2_POINT)); + + if (i == sign_index) { + memcpy(&sign_key, &key, sizeof(SM2_KEY)); + } + } + if (sm2_ring_sign(&sign_key, public_keys, public_keys_count, dgst, sig, &siglen) != 1) { + error_print(); + return -1; + } + if (sm2_ring_verify(public_keys, 5, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_ring_sign_crosscheck(void) +{ + SM2_KEY sign_key; + SM2_POINT public_key; + uint8_t dgst[32]; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen = 0; + + sm2_key_generate(&sign_key); + public_key = sign_key.public_key; + + if (sm2_ring_sign(&sign_key, &public_key, 1, dgst, sig, &siglen) != 1) { + error_print(); + return -1; + } + if (sm2_ring_verify(&public_key, 1, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_ring_sign_update(void) +{ + SM2_KEY keys[5]; + SM2_RING_SIGN_CTX sign_ctx; + SM2_RING_SIGN_CTX verify_ctx; + size_t public_keys_count = sizeof(keys)/sizeof(keys[0]); + char *id = "Alice"; + uint8_t msg[128] = {0}; + uint8_t sig[9 + (2 + 33) * (1 + sizeof(keys)/sizeof(keys[0]))]; + size_t siglen = 0; + size_t i; + + for (i = 0; i < public_keys_count; i++) { + sm2_key_generate(&keys[i]); + } + + if (sm2_ring_sign_init(&sign_ctx, &keys[0], id, strlen(id)) != 1) { + error_print(); + return -1; + } + for (i = 1; i < public_keys_count; i++) { + if (sm2_ring_sign_add_signer(&sign_ctx, &keys[i]) != 1) { + error_print(); + return -1; + } + } + if (sm2_ring_sign_update(&sign_ctx, msg, 32) != 1 + || sm2_ring_sign_update(&sign_ctx, msg + 32, 32) != 1 + || sm2_ring_sign_update(&sign_ctx, msg + 64, 64) != 1 + || sm2_ring_sign_finish(&sign_ctx, sig, &siglen) != 1) { + error_print(); + return -1; + } + + if (sm2_ring_verify_init(&verify_ctx, id, strlen(id)) != 1) { + error_print(); + return -1; + } + for (i = 0; i < public_keys_count; i++) { + if (sm2_ring_verify_add_signer(&verify_ctx, &keys[i]) != 1) { + error_print(); + return -1; + } + } + if (sm2_ring_verify_update(&verify_ctx, msg, sizeof(msg)) != 1) { + error_print(); + return -1; + } + if (sm2_ring_verify_finish(&verify_ctx, sig, siglen) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_sm2_ring_do_sign() != 1) { error_print(); return -1; } + if (test_sm2_ring_sign() != 1) { error_print(); return -1; } + if (test_sm2_ring_sign_crosscheck() != 1) { error_print(); return -1; } + if (test_sm2_ring_sign_update() != 1) { error_print(); return -1; } + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_uint128test.c b/Core/GmSSL-3.1.1/tests/sm2_uint128test.c new file mode 100644 index 0000000..e8d5b61 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_uint128test.c @@ -0,0 +1,158 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +int test_sm2_points_mul_g(void) +{ + const char *k_hex[] = { + "D49733EF7322BCA402FF2C55A76226D036293578228F05BB0A084E7FD679DA6A", + "EE459A3CEA02B64116CA83738284A8673141F2C0800791A5774B3B3326BCBAE9", + "112C903A44D865817C34050F32A7B7C5562FF21D5FB86F3EBC82E017E63AA650", + }; + const char *P_hex[] = { + "DA0A26E5A2FD1A8338E6465CD73EACD360EFD0C0278DD3239174077FD1646D0D" + "7B5454054D4E799DE8AF8D2BB4E35D34B4C4A286BE6E631691E11A8D878EF0AA", + "FBEEA44629CCCE80894CCDD66594B391E62A476AD2F401CBF1B64728C6195402" + "45E6ACF90653E584C6F71A6A130B311B9582977751AE413697398C85D35C4DD4", + "7D40E2CDA2528106C41D90B654E8BEB52E66BAF2D1F49574992FE707F0BE6223" + "E4C5F597E924662F2A85C6065F05A2E554D856C8135C34A4BC82870D555F9084", + }; + uint8_t k[32]; + uint8_t P[64]; + uint8_t x[64]; + uint8_t *y = x + 32; + size_t len, i; + + for (i = 0; i < sizeof(k_hex)/sizeof(k_hex[0]); i++) { + hex_to_bytes(k_hex[i], strlen(k_hex[i]), k, &len); + hex_to_bytes(P_hex[i], strlen(P_hex[i]), P, &len); + + sm2_points_mul(x, y, k, 0, NULL, NULL); + + if (memcmp(x, P, 64) != 0) { + error_print(); + return -1; + } + } + + printf("%s ok\n", __FUNCTION__); + return 1; +} + +int test_sm2_points_mul(void) +{ + const char *k_hex[] = { + "84890E2149BF27124A123441ED574373C5506293AA087B319A44A8481CFF4201", + "C80DD28E6093883E8BB637CA8C73CDD43D562D4235E201A83FB5FEF6CE7B0E00", + "1BFC60372080CDCB4B11A798FE91D15FBB9ACD1B696850DFC84DA4B54B849D92", + "06104FD237BCA808B3D6039A0A859C7AD46E4FF8358F0E909A65CB0F5E63D07E", + }; + const char *P_hex[] = { + "E658713DDCDB7C89431C2F19CE1187CA323620197534AFCFD322EE39CD18CDB8" + "D1FCD5160877086EF85F5C7CF2F850D0D3D57BA4B2547CB719EE5EDD3A2ACD54", + "01E9266592CF24B124A8CE2ACA03941A32FA05EADB7EB165207148F0468A32D0" + "AD576F985A6365EF43654C6F82B151153928C59D0A04BDB8865CBC3370093E7C", + "F77F4A004CA3ACFC1476D6BE6E74B3724D116CB43913B81CD18C9F67FB684FDD" + "A64D24AA17DAAFC359D368CA4FB5023552C1C9158C8C63359B8617C12031A723", + "A56B91BA232C11099C2545F637E0949E943631032592BE3AD063426A54B6D4B9" + "7E706E500A0D0BCE94A6574889544A8425791C5C1D5E80EBA73B1A4D2FBA85DF", + }; + const char *Q_hex[] = { + "D9C7FE8529EC92CD4C371BF031DFBC939DB3A4571C0FBE3BFFAF53016B57A767" + "995BDFC720CD7504839275029A423172725B2EFD57448A45533727167578257C", + "9ED9C5F08B7853ABB486B9C62D6E8D76A014A7BBA1967710CF419FBA8D038F15" + "EB503473E3C401974BD2CD61BFC9B3F84E32B4137F116FBFEC551D604DD654CC", + "6FDEEC7B9405F75E1F6BD81524AD982A8752AD0093CA356535AFDDD37068D960" + "1D010E962355349956CC8F0408C5FA945A4F29FC4D7083F9325F392528C40693", + "2520E6EFB29A073E71B63ABBD93FA2899ABA1940DC942BF628861BD6697B3F6F" + "BEB40823F2365975B10AA0848E127C72D32F0924323B276413FA267717E0716B", + }; + uint8_t k[32]; + uint8_t P[64]; + uint8_t Q[64]; + uint8_t R[64]; + size_t len, i; + + + for (i = 0; i < sizeof(k_hex)/sizeof(k_hex[0]); i++) { + hex_to_bytes(k_hex[i], strlen(k_hex[i]), k, &len); + hex_to_bytes(P_hex[i], strlen(P_hex[i]), P, &len); + hex_to_bytes(Q_hex[i], strlen(Q_hex[i]), Q, &len); + + sm2_points_mul(R, R + 32, NULL, 1, (SM2_POINT *)P, &k); + + if (memcmp(R, Q, 64) != 0) { + error_print(); + return -1; + } + } + + printf("%s ok\n", __FUNCTION__); + return 1; +} + +int test_sm2_points_mul_mult(void) +{ + const char *s_hex = + "75B6973113B59FBF4EF91D3986B8EA3548B8DA538611154A4F91049645F36C74"; + const char *k_hex[] = { + "0E7A0ABB57773AA55F4B829767654D451AB6E7AECF05FFA8DFF41134D5700D40", + "27F4E552EE458A90FB5A46BC9106799AAF9F51D873E188D148C61154539A272A", + "2C6C45FFBD27C2F9AFFCEB023F45E16B6A9415BF34A4D94599B6C35B03EAC1F7", + }; + const char *P_hex[] = { + "E8346D7CCF6C071C3C8343A305F5AD9EDCE59EF75F64774732F2CED8F3B7143A" + "D0CF09FDFD9C69775BE47FBA558D3AD904D61D5DB6CC8D9C6F7CA484DFF0182B", + "E6679FBC4C0E460B1FAB57EA3CD653601BA68223062E6C53B65DF3DE4A566862" + "124EE9725C6A3FB427B05130B68FD963FB4762DC6EDCC0319B807DB290B3032D", + "FA6654F72E8DEDD9ED00EA74C81F0CAB37C6D28000E02A2648E7BEB7F22FC118" + "97F08B2357503E7BBCE7275C336FF1F713DD9B5BE66BFEEC18A6C837E59FD4E6", + }; + const char *Q_hex = + "F5F2749B9D36AE0175DC63F3F97D9747B813F63D1475978E8792DD1AB7F13050" + "1B6951A69477F39550F5550FF783905F3B7305186F38D3A63A8ECCD6E28E1603"; + + uint8_t s[32]; + uint8_t k[3][32]; + SM2_POINT P[3]; + uint8_t Q[64]; + uint8_t R[64]; + size_t len, i; + + hex_to_bytes(s_hex, strlen(s_hex), s, &len); + for (i = 0; i < sizeof(k_hex)/sizeof(k_hex[0]); i++) { + hex_to_bytes(k_hex[i], strlen(k_hex[i]), k[i], &len); + hex_to_bytes(P_hex[i], strlen(P_hex[i]), (uint8_t *)&P[i], &len); + } + hex_to_bytes(Q_hex, strlen(Q_hex), Q, &len); + + sm2_points_mul(R, R + 32, s, sizeof(k_hex)/sizeof(k_hex[0]), P, k); + if (memcmp(R, Q, 64) != 0) { + error_print(); + return -1; + } + + printf("%s ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_sm2_points_mul() != 1) { error_print(); return -1; } + if (test_sm2_points_mul_mult() != 1) { error_print(); return -1; } + printf("%s all tests passed\n", __FILE__); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm2_z256test.c b/Core/GmSSL-3.1.1/tests/sm2_z256test.c new file mode 100644 index 0000000..75a48c1 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2_z256test.c @@ -0,0 +1,557 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + + +static int sm2_z256_equ_hex(const uint64_t a[4], const char *hex) +{ + uint64_t b[4]; + sm2_z256_from_hex(b, hex); + return (sm2_z256_cmp(a, b) == 0); +} + + +int sm2_z256_mont_equ_hex(const uint64_t a[4], const char *hex) +{ + uint64_t a_[4]; + uint64_t b[4]; + + sm2_z256_from_mont(a_, a); + sm2_z256_from_hex(b, hex); + return (sm2_z256_cmp(a_, b) == 0); +} + +static int test_sm2_z256_add(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_add_x_y = "eefbe4cf140ff8b5b956d329d5a2eae8608c933cb89053217439786e54866567"; + char *hex_2y = "786e6d45e9ecef38b37b9dc6d6d242a7a1530ef98c548e8005be65ca4273e140"; + + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[4]; + uint64_t c; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + c = sm2_z256_add(r, x, y); + if (c != 0 || sm2_z256_equ_hex(r, hex_add_x_y) != 1) { + error_print(); + return -1; + } + + c = sm2_z256_add(r, y, y); + if (c != 1 || sm2_z256_equ_hex(r, hex_2y) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_sub(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_sub_x_y = "768d77892a23097d05db3562fed0a840bf3984432c3bc4a16e7b12a412128427"; + char *hex_sub_y_x = "89728876d5dcf682fa24ca9d012f57bf40c67bbcd3c43b5e9184ed5beded7bd9"; + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[4]; + uint64_t c; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + c = sm2_z256_sub(r, x, y); + if (c != 1 || sm2_z256_equ_hex(r, hex_sub_x_y) != 1) { + error_print(); + return -1; + } + + c = sm2_z256_sub(r, y, x); + if (c != 0 || sm2_z256_equ_hex(r, hex_sub_y_x) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_mul(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_mul_x_y = + "255362ffa019467e48add0ebbe29d15e82fab48f15592867dbdab16dde8d0673" + "dd4057dd755d04ff86dad43f0ecaf69ddccd043ba61f523ebe51b0ee64928c60"; + + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[8]; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + sm2_z256_mul(r, x, y); + + if (sm2_z256_equ_hex(r + 4, hex_mul_x_y) != 1 + || sm2_z256_equ_hex(r, hex_mul_x_y + 64) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_cmp(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + + uint64_t x[4]; + uint64_t y[4]; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + if (sm2_z256_cmp(x, y) != -1 + || sm2_z256_cmp(x, x) != 0 + || sm2_z256_cmp(y, y) != 0 + || sm2_z256_cmp(y, x) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_modp_add(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_modp_add_x_y = "eefbe4cf140ff8b5b956d329d5a2eae8608c933cb89053217439786e54866567"; + char *hex_neg_x = "cd3b51d2e0e67ee6a066fbb995c6366b701cf43f0d99f41f8ea5ba76ccb38b38"; + char *hex_p_sub_1 = "fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffe"; + char *hex_2 = "0000000000000000000000000000000000000000000000000000000000000002"; + char *hex_1 = "0000000000000000000000000000000000000000000000000000000000000001"; + char *hex_0 = "0000000000000000000000000000000000000000000000000000000000000000"; + char *hex_modp_2y = "786e6d46e9ecef38b37b9dc6d6d242a7a1530efa8c548e7f05be65ca4273e141"; + + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[4]; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + // x + y < p + sm2_z256_modp_add(r, x, y); + if (sm2_z256_equ_hex(r, hex_modp_add_x_y) != 1) { + error_print(); + return -1; + } + + // x + y > 2^256 + sm2_z256_modp_add(r, y, y); + if (sm2_z256_equ_hex(r, hex_modp_2y) != 1) { + error_print(); + return -1; + } + + // x + y = p + sm2_z256_from_hex(r, hex_neg_x); + sm2_z256_modp_add(r, r, x); + if (sm2_z256_equ_hex(r, hex_0) != 1) { + error_print(); + return -1; + } + + // p < x + y < 2^256 + sm2_z256_from_hex(x, hex_p_sub_1); + sm2_z256_from_hex(y, hex_2); + sm2_z256_modp_add(r, x, y); + if (sm2_z256_equ_hex(r, hex_1) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_modp_sub(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_modp_sub_x_y = "768d77882a23097d05db3562fed0a840bf3984422c3bc4a26e7b12a412128426"; + char *hex_modp_sub_y_x = "89728876d5dcf682fa24ca9d012f57bf40c67bbcd3c43b5e9184ed5beded7bd9"; + char *hex_0 = "0000000000000000000000000000000000000000000000000000000000000000"; + + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[4]; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + sm2_z256_modp_sub(r, x, y); + if (sm2_z256_equ_hex(r, hex_modp_sub_x_y) != 1) { + error_print(); + return -1; + } + + sm2_z256_modp_sub(r, y, x); + if (sm2_z256_equ_hex(r, hex_modp_sub_y_x) != 1) { + error_print(); + return -1; + } + + sm2_z256_modp_sub(r, x, x); + if (sm2_z256_equ_hex(r, hex_0) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_modp_div_by_2(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_modp_x_div_2 = "996257158f8cc08cafcc8223351ce4ca47f185df793305f138ad22c499a63a63"; + char *hex_modp_y_div_2 = "5e1b9b517a7b3bce2cdee771b5b490a9e854c3be631523a0016f9972909cf850"; + + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[4]; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + sm2_z256_modp_div_by_2(r, x); + if (sm2_z256_equ_hex(r, hex_modp_x_div_2) != 1) { + error_print(); + return -1; + } + + sm2_z256_modp_div_by_2(r, y); + if (sm2_z256_equ_hex(r, hex_modp_y_div_2) != 1) { + error_print(); + return -1; + } + + printf("%s ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_modp_mul(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_modp_mul_x_y = "edd7e745bdc4630ccfa1da1057033a525346dbf202f082f3c431349991ace76a"; + char *hex_0 = "0000000000000000000000000000000000000000000000000000000000000000"; + + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[4]; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + sm2_z256_to_mont(x, x); + sm2_z256_to_mont(y, y); + sm2_z256_mont_mul(r, x, y); + sm2_z256_from_mont(r, r); + + if (sm2_z256_equ_hex(r, hex_modp_mul_x_y) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_modp_inv(void) +{ + char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + char *hex_modp_inv_x = "053b878fb82e213c17e554b9a574b7bd31775222704b7fd9c7d6f8441026cd80"; + char *hex_modp_inv_y = "7adc850505c462b280f710414ab54e922551dbc97eefbc04e99cb743624c729f"; + char *hex_0 = "0000000000000000000000000000000000000000000000000000000000000000"; + char *hex_1 = "0000000000000000000000000000000000000000000000000000000000000001"; + + uint64_t x[4]; + uint64_t y[4]; + uint64_t r[4]; + + sm2_z256_from_hex(x, hex_x); + sm2_z256_from_hex(y, hex_y); + + sm2_z256_to_mont(x, x); + sm2_z256_mont_inv(r, x); + sm2_z256_from_mont(r ,r); + if (sm2_z256_equ_hex(r, hex_modp_inv_x) != 1) { + error_print(); + return -1; + } + + sm2_z256_to_mont(y, y); + sm2_z256_mont_inv(r, y); + sm2_z256_from_mont(r ,r); + if (sm2_z256_equ_hex(r, hex_modp_inv_y) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + + +static const uint64_t SM2_Z256_MONT_X[4] = { + 0x61328990f418029e, 0x3e7981eddca6c050, 0xd6a1ed99ac24c3c3, 0x91167a5ee1c13b05, +}; + +static const uint64_t SM2_Z256_MONT_Y[4] = { + 0xc1354e593c2d0ddd, 0xc1f5e5788d3295fa, 0x8d4cfb066e2a48f8, 0x63cd65d481d735bd, +}; + +static int test_sm2_z256_point_get_affine(void) +{ + const char *hex_x = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7"; + const char *hex_y = "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; + SM2_Z256_POINT P; + uint64_t x[4]; + uint64_t y[4]; + + sm2_z256_copy(P.X, SM2_Z256_MONT_X); + sm2_z256_copy(P.Y, SM2_Z256_MONT_Y); + sm2_z256_copy(P.Z, SM2_Z256_MONT_ONE); + + sm2_z256_point_get_affine(&P, x, y); + + if (sm2_z256_equ_hex(x, hex_x) != 1 || sm2_z256_equ_hex(y, hex_y) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_point_dbl(void) +{ + char *hex_x_2G = "56cefd60d7c87c000d58ef57fa73ba4d9c0dfa08c08a7331495c2e1da3f2bd52"; + char *hex_y_2G = "31b7e7e6cc8189f668535ce0f8eaf1bd6de84c182f6c8e716f780d3a970a23c3"; + SM2_Z256_POINT P; + uint64_t x[4]; + uint64_t y[4]; + + sm2_z256_copy(P.X, SM2_Z256_MONT_X); + sm2_z256_copy(P.Y, SM2_Z256_MONT_Y); + sm2_z256_copy(P.Z, SM2_Z256_MONT_ONE); + + sm2_z256_point_dbl(&P, &P); + sm2_z256_point_get_affine(&P, x, y); + + if (sm2_z256_equ_hex(x, hex_x_2G) != 1 || sm2_z256_equ_hex(y, hex_y_2G) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; + +} + +static int test_sm2_z256_point_add_affine(void) +{ + char *hex_x_3G = "a97f7cd4b3c993b4be2daa8cdb41e24ca13f6bd945302244e26918f1d0509ebf"; + char *hex_y_3G = "530b5dd88c688ef5ccc5cec08a72150f7c400ee5cd045292aaacdd037458f6e6"; + SM2_Z256_POINT P; + SM2_Z256_POINT Q; + uint64_t x[4]; + uint64_t y[4]; + + sm2_z256_copy(P.X, SM2_Z256_MONT_X); + sm2_z256_copy(P.Y, SM2_Z256_MONT_Y); + sm2_z256_copy(P.Z, SM2_Z256_MONT_ONE); + + sm2_z256_point_dbl(&Q, &P); + sm2_z256_point_add_affine(&Q, &Q, (SM2_Z256_POINT_AFFINE *)&P); + sm2_z256_point_get_affine(&Q, x, y); + + if (sm2_z256_equ_hex(x, hex_x_3G) != 1 || sm2_z256_equ_hex(y, hex_y_3G) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_point_add(void) +{ + char *hex_x_5G = "c749061668652e26040e008fdd5eb77a344a417b7fce19dba575da57cc372a9e"; + char *hex_y_5G = "f2df5db2d144e9454504c622b51cf38f5006206eb579ff7da6976eff5fbe6480"; + SM2_Z256_POINT G; + SM2_Z256_POINT P; + SM2_Z256_POINT Q; + SM2_Z256_POINT R; + uint64_t x[4]; + uint64_t y[4]; + + sm2_z256_copy(G.X, SM2_Z256_MONT_X); + sm2_z256_copy(G.Y, SM2_Z256_MONT_Y); + sm2_z256_copy(G.Z, SM2_Z256_MONT_ONE); + + // P = 2*G + sm2_z256_point_dbl(&P, &G); + + // Q = 3*G + sm2_z256_point_add_affine(&Q, &P, (SM2_Z256_POINT_AFFINE *)&G); + + // R = P + Q + sm2_z256_point_add(&R, &P, &Q); + + sm2_z256_point_get_affine(&R, x, y); + + if (sm2_z256_equ_hex(x, hex_x_5G) != 1 || sm2_z256_equ_hex(y, hex_y_5G) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_get_booth(void) +{ + char *hex_a = "7a648a77d0cbe0b9ee841433be0c132aa98f6757da70a18c74999774fa587762"; + + // window_size = 7, len(booth) = (256 + 6)/7 = 7 + int booth_a[37] = { + -30, -17, -30, -45, -48, -17, -26, -51, -11, 25, 6, 5, 39, -5, -42, 52, + 15, -45, 43, 25, -63, -62, -16, 26, 20, 8, 58, -49, 12, -4, 51, -24, -8, + 21, 18, -45, 8 + }; + uint64_t a[4]; + int i = 0; + + sm2_z256_from_hex(a, hex_a); + + for (i = 0; i < 37; i++) { + if (sm2_z256_get_booth(a, 7, i) != booth_a[i]) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_z256_point_mul_generator(void) +{ + char *hex_b = "28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93"; + char *hex_x = "528470bc74a6ebc663c06fc4cfa1b630d1e9d4a80c0a127b47f73c324c46c0ba"; + char *hex_y = "832cf9c5a15b997e60962b4cf6e2c9cee488faaec98d20599d323d4cabfc1bf4"; + + uint64_t b[4]; + SM2_Z256_POINT P; + uint64_t x[4]; + uint64_t y[4]; + + sm2_z256_from_hex(b, hex_b); + sm2_z256_point_mul_generator(&P, b); + sm2_z256_point_get_affine(&P, x, y); + + if (sm2_z256_equ_hex(x, hex_x) != 1 || sm2_z256_equ_hex(y, hex_y) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + +static int test_sm2_z256_point_mul(void) +{ + char *hex_b = "28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93"; + char *hex_x = "528470bc74a6ebc663c06fc4cfa1b630d1e9d4a80c0a127b47f73c324c46c0ba"; + char *hex_y = "832cf9c5a15b997e60962b4cf6e2c9cee488faaec98d20599d323d4cabfc1bf4"; + + uint64_t b[4]; + SM2_Z256_POINT G; + SM2_Z256_POINT P; + uint64_t x[4]; + uint64_t y[4]; + + sm2_z256_from_hex(b, hex_b); + + sm2_z256_copy(G.X, SM2_Z256_MONT_X); + sm2_z256_copy(G.Y, SM2_Z256_MONT_Y); + sm2_z256_copy(G.Z, SM2_Z256_MONT_ONE); + + sm2_z256_point_mul(&P, &G, b); + sm2_z256_point_get_affine(&P, x, y); + + if (sm2_z256_equ_hex(x, hex_x) != 1 || sm2_z256_equ_hex(y, hex_y) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_sm2_z256_add() != 1) { error_print(); return -1; } + if (test_sm2_z256_sub() != 1) { error_print(); return -1; } + if (test_sm2_z256_mul() != 1) { error_print(); return -1; } + if (test_sm2_z256_cmp() != 1) { error_print(); return -1; } + if (test_sm2_z256_modp_add() != 1) { error_print(); return -1; } + if (test_sm2_z256_modp_sub() != 1) { error_print(); return -1; } + if (test_sm2_z256_modp_mul() != 1) { error_print(); return -1; } + if (test_sm2_z256_modp_inv() != 1) { error_print(); return -1; } + if (test_sm2_z256_modp_div_by_2() != 1) { error_print(); return -1; } + if (test_sm2_z256_get_booth() != 1) { error_print(); return -1; } + if (test_sm2_z256_point_get_affine() != 1) { error_print(); return -1; } + if (test_sm2_z256_point_dbl() != 1) { error_print(); return -1; } + if (test_sm2_z256_point_add_affine() != 1) { error_print(); return -1; } + if (test_sm2_z256_point_add() != 1) { error_print(); return -1; } + if (test_sm2_z256_point_mul_generator() != 1) { error_print(); return -1; } + if (test_sm2_z256_point_mul() != 1) { error_print(); return -1; } + + printf("%s all tests passed\n", __FILE__); + return 0; +} + diff --git a/Core/GmSSL-3.1.1/tests/sm2test.c b/Core/GmSSL-3.1.1/tests/sm2test.c new file mode 100644 index 0000000..468a609 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm2test.c @@ -0,0 +1,886 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + +#define sm2_print_bn(label,a) sm2_bn_print(stderr,0,0,label,a) // 这个不应该放在这里,应该放在测试文件中 + + +#define hex_fp_add_x_y "eefbe4cf140ff8b5b956d329d5a2eae8608c933cb89053217439786e54866567" +#define hex_fp_sub_x_y "768d77882a23097d05db3562fed0a840bf3984422c3bc4a26e7b12a412128426" +#define hex_fp_sub_y_x "89728876d5dcf682fa24ca9d012f57bf40c67bbcd3c43b5e9184ed5beded7bd9" +#define hex_fp_neg_x "cd3b51d2e0e67ee6a066fbb995c6366b701cf43f0d99f41f8ea5ba76ccb38b38" +#define hex_fp_mul_x_y "edd7e745bdc4630ccfa1da1057033a525346dbf202f082f3c431349991ace76a" +#define hex_fp_squ_x "f4e2cca0bcfd67fba8531eebff519e4cb3d47f9fe8c5eff5151f4c497ec99fbf" +#define hex_fp_exp_x_y "8cafd11b1a0d2072b82911ba87e0d376103a1be5986fce91d8d297b758f68146" +#define hex_fp_inv_x "053b878fb82e213c17e554b9a574b7bd31775222704b7fd9c7d6f8441026cd80" + +#define hex_fn_add_x_y "eefbe4cf140ff8b5b956d329d5a2eae8608c933cb89053217439786e54866567" +#define hex_fn_sub_x_y "768d77882a23097d05db3562fed0a840313d63ae4e01c9ccc23706ad4be7c54a" +#define hex_fn_sub_y_x "89728876d5dcf682fa24ca9d012f57bf40c67bbcd3c43b5e9184ed5beded7bd9" +#define hex_fn_neg_x "cd3b51d2e0e67ee6a066fbb995c6366ae220d3ab2f5ff949e261ae800688cc5c" +#define hex_fn_mul_x_y "cf7296d5cbf0b64bb5e9a11b294962e9c779b41c038e9c8d815234a0df9d6623" +#define hex_fn_sqr_x "82d3d1b296d3a3803888b7ffc78f23eca824e7ec8d7ddaf231ffb0d256a19da2" +#define hex_fn_exp_x_y "0cf4df7e76d7d49ff23b94853a98aba1e36e9ca0358acbf23a3bbda406f46df3" +#define hex_fn_inv_x "96340ec8b80f44e9b345a706bdb5c9e3ab8a6474a5cb4e0d4645dbaecf1cf03d" +#define hex_v "d3da0ef661be97360e1b32f834e6ca5673b1984b22bb420133da05e56ccd59fb" +#define hex_fn_mul_x_v "0375c61e1ed13e460f4b5d462dc5b2c846f36c7b481cd4bed8f7dd55908a6afd" + +#define hex_t "2fbadf57b52dc19e8470bf201cb182e0a4f7fa5e28d356b15da173132b94b325" + + +int test_sm2_bn(void) +{ + const SM2_JACOBIAN_POINT _G = { + { + 0x334c74c7, 0x715a4589, 0xf2660be1, 0x8fe30bbf, + 0x6a39c994, 0x5f990446, 0x1f198119, 0x32c4ae2c, + }, + { + 0x2139f0a0, 0x02df32e5, 0xc62a4740, 0xd0a9877c, + 0x6b692153, 0x59bdcee3, 0xf4f6779c, 0xbc3736a2, + }, + { + 1, 0, 0, 0, 0, 0, 0, 0, + }, + }; + const SM2_JACOBIAN_POINT *G = &_G; + SM2_BN r; + SM2_BN x; + SM2_BN y; + int ok, i = 1; + + char hex[65]; + + SM2_BN v = { + 0x6ccd59fb, 0x33da05e5, 0x22bb4201, 0x73b1984b, + 0x34e6ca56, 0x0e1b32f8, 0x61be9736, 0xd3da0ef6, + }; + + SM2_BN t; + + sm2_bn_copy(x, G->X); + sm2_bn_copy(y, G->Y); + + sm2_bn_from_hex(r, hex_v); + ok = (sm2_bn_cmp(r, v) == 0); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + // fp tests + sm2_fp_add(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fp_add_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fp_sub(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fp_sub_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fp_mul(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fp_mul_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fp_exp(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fp_exp_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fp_inv(r, x); + ok = sm2_bn_equ_hex(r, hex_fp_inv_x); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fp_neg(r, x); + ok = sm2_bn_equ_hex(r, hex_fp_neg_x); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + // fn tests + sm2_fn_add(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fn_add_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_sub(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fn_sub_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_sub(r, y, x); + ok = sm2_bn_equ_hex(r, hex_fn_sub_y_x); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_neg(r, x); + ok = sm2_bn_equ_hex(r, hex_fn_neg_x); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_mul(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fn_mul_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_mul(r, x, v); + ok = sm2_bn_equ_hex(r, hex_fn_mul_x_v); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_sqr(r, x); + ok = sm2_bn_equ_hex(r, hex_fn_sqr_x); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_exp(r, x, y); + ok = sm2_bn_equ_hex(r, hex_fn_exp_x_y); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_fn_inv(r, x); + ok = sm2_bn_equ_hex(r, hex_fn_inv_x); + printf("sm2 bn test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + SM2_BN tv = { + 0x2b94b325, 0x5da17313, 0x28d356b1, 0xa4f7fa5e, + 0x1cb182e0, 0x8470bf20, 0xb52dc19e, 0x2fbadf57, + }; + sm2_bn_from_hex(t, hex_t); + ok = (sm2_bn_cmp(t, tv) == 0); + if (!ok) return -1; + + sm2_bn_to_hex(t, hex); + + return 1; +} + + +#define hex_G \ + "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7" \ + "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0" +#define hex_2G \ + "56cefd60d7c87c000d58ef57fa73ba4d9c0dfa08c08a7331495c2e1da3f2bd52" \ + "31b7e7e6cc8189f668535ce0f8eaf1bd6de84c182f6c8e716f780d3a970a23c3" +#define hex_3G \ + "a97f7cd4b3c993b4be2daa8cdb41e24ca13f6bd945302244e26918f1d0509ebf" \ + "530b5dd88c688ef5ccc5cec08a72150f7c400ee5cd045292aaacdd037458f6e6" +#define hex_negG \ + "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7" \ + "43c8c95c0b098863a642311c9496deac2f56788239d5b8c0fd20cd1adec60f5f" +#define hex_10G \ + "d3f94862519621c121666061f65c3e32b2d0d065cd219e3284a04814db522756" \ + "4b9030cf676f6a742ebd57d146dca428f6b743f64d1482d147d46fb2bab82a14" +#define hex_bG \ + "528470bc74a6ebc663c06fc4cfa1b630d1e9d4a80c0a127b47f73c324c46c0ba" \ + "832cf9c5a15b997e60962b4cf6e2c9cee488faaec98d20599d323d4cabfc1bf4" + +#define hex_P \ + "504cfe2fae749d645e99fbb5b25995cc6fed70196007b039bdc44706bdabc0d9" \ + "b80a8018eda5f55ddc4b870d7784b7b84e53af02f575ab53ed8a99a3bbe2abc2" +#define hex_2P \ + "a53d20e89312b5243f66aec12ef6471f5911941d86302d5d8337cb70937d65ae" \ + "96953c46815e4259363256ddd6c77fcc33787aeafc6a57beec5833f476dd69e0" + +#define hex_tP \ + "02deff2c5b3656ca3f7c7ca9d710ca1d69860c75a9c7ec284b96b8adc50b2936" \ + "b74bcba937e9267fce4ccc069a6681f5b04dcedd9e2794c6a25ddc7856df7145" + + +int test_sm2_jacobian_point(void) +{ + const SM2_JACOBIAN_POINT _G = { + { + 0x334c74c7, 0x715a4589, 0xf2660be1, 0x8fe30bbf, + 0x6a39c994, 0x5f990446, 0x1f198119, 0x32c4ae2c, + }, + { + 0x2139f0a0, 0x02df32e5, 0xc62a4740, 0xd0a9877c, + 0x6b692153, 0x59bdcee3, 0xf4f6779c, 0xbc3736a2, + }, + { + 1, 0, 0, 0, 0, 0, 0, 0, + }, + }; + const SM2_BN _B = { + 0x4d940e93, 0xddbcbd41, 0x15ab8f92, 0xf39789f5, + 0xcf6509a7, 0x4d5a9e4b, 0x9d9f5e34, 0x28e9fa9e, + }; + const SM2_JACOBIAN_POINT *G = &_G; + SM2_JACOBIAN_POINT _P, *P = &_P; + SM2_BN k; + int i = 1, ok; + + uint8_t buf[64]; + + printf("sm2_jacobian_point_test\n"); + + ok = sm2_jacobian_point_equ_hex(G, hex_G); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + ok = sm2_jacobian_point_is_on_curve(G); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_jacobian_point_dbl(P, G); + ok = sm2_jacobian_point_equ_hex(P, hex_2G); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_jacobian_point_add(P, P, G); + ok = sm2_jacobian_point_equ_hex(P, hex_3G); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_jacobian_point_sub(P, P, G); + ok = sm2_jacobian_point_equ_hex(P, hex_2G); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_jacobian_point_neg(P, G); + ok = sm2_jacobian_point_equ_hex(P, hex_negG); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_bn_set_word(k, 10); + sm2_jacobian_point_mul(P, k, G); + ok = sm2_jacobian_point_equ_hex(P, hex_10G); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_jacobian_point_mul_generator(P, _B); + ok = sm2_jacobian_point_equ_hex(P, hex_bG); + printf("sm2 point test %d %s\n", i++, ok ? "ok" : "failed"); + if (!ok) return -1; + + sm2_jacobian_point_to_bytes(P, buf); + sm2_jacobian_point_from_hex(P, hex_P); + + return 1; +} + +#define hex_d "5aebdfd947543b713bc0df2c65baaecc5dadd2cab39c6971402daf92c263fad2" +#define hex_e "c0881c19beec741b9af27cc26493dcc33b05d481bfeab2f3ce9cc056e6ff8400" +#define hex_k "981325ee1ab171e9d2cffb317181a02957b18a34bca610a6d2f8afcdeb53f6b8" +#define hex_x1 "17d2dfe83f23cce8499bca983950d59f0fd56c4c671dd63c04b27e4e94cfd767" +#define hex_r "d85afc01fe104103e48e475a9de4b2624adb40ce2708892fd34f3ea57bcf5b67" +#define hex_rd "a70ba64f9c30e05095f39fe26675114e3f157b2c35191bf6ff06246452f82eb3" +#define hex_di "3ecfdb51c24b0eecb2d4238d1da8c013b8b575cef14ef43e2ddb7bce740ce9cf" +#define hex_krd "f1077f9d7e8091993cdc5b4f0b0c8eda8a9fee73a952f9db27ae7f72d2310928" +#define hex_s "006bac5b8057ca829534dfde72a0d7883444a3b9bfe9bcdfb383fb90ed7d9486" + + +static int test_sm2_point(void) +{ + SM2_POINT P, Q; + uint8_t k[32] = {0}; + uint8_t buf[65] = {0}; + int i; + + for (i = 1; i < 8; i++) { + k[31] = (uint8_t)i; + + if (sm2_point_mul_generator(&P, k) != 1 + || sm2_point_is_on_curve(&P) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 0, "k = %d, ", i); + sm2_point_print(stderr, 0, 0, "k * G", &P); + + memset(buf, 0, sizeof(buf)); + sm2_point_to_compressed_octets(&P, buf); + format_bytes(stderr, 0, 4, "compressedPoint", buf, 33); + memset(&Q, 0, sizeof(Q)); + if (sm2_point_from_x(&Q, buf + 1, buf[0]) != 1 + || memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) { + + sm2_point_print(stderr, 0, 4, "P", &P); + sm2_point_print(stderr, 0, 4, "Q", &Q); + + error_print(); + return -1; + } + + memset(buf, 0, sizeof(buf)); + sm2_point_to_uncompressed_octets(&P, buf); + format_bytes(stderr, 0, 4, "compressedPoint", buf, 65); + memset(&Q, 0, sizeof(Q)); + if (sm2_point_from_octets(&Q, buf, 65) != 1 + || memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_point_der(void) +{ + SM2_POINT P, Q; + uint8_t k[32] = {0}; + uint8_t buf[512]; + int i; + + for (i = 1; i < 8; i++) { + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + k[31] = i; + memset(&P, 0, sizeof(P)); + memset(&Q, 0, sizeof(Q)); + + if (sm2_point_mul_generator(&P, k) != 1 + || sm2_point_to_der(&P, &p, &len) != 1 + || format_bytes(stderr, 0, 4, "ECPoint", buf, len) != 1 + || sm2_point_from_der(&Q, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) { + error_print(); + sm2_point_print(stderr, 0, 4, "P", &P); + sm2_point_print(stderr, 0, 4, "Q", &Q); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_point_octets(void) +{ + SM2_POINT P, Q; + uint8_t k[32] = {0}; + uint8_t buf[33]; + int i; + + for (i = 1; i < 8; i++) { + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + k[31] = i; + memset(&P, 0, sizeof(P)); + memset(&Q, 0, sizeof(Q)); + + if (sm2_point_mul_generator(&P, k) != 1) { + error_print(); + return -1; + } + sm2_point_to_compressed_octets(&P, buf); + format_bytes(stderr, 0, 4, "compressedPoint", buf, sizeof(buf)); + if (sm2_point_from_octets(&Q, buf, sizeof(buf)) != 1) { + error_print(); + return -1; + } + if (memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) { + error_print(); + sm2_point_print(stderr, 0, 4, "P", &P); + sm2_point_print(stderr, 0, 4, "Q", &Q); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_point_from_x(void) +{ + SM2_POINT P, Q; + uint8_t k[32] = {0}; + uint8_t buf[33]; + int i; + + for (i = 1; i < 8; i++) { + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + k[31] = i; + memset(&P, 0, sizeof(P)); + memset(&Q, 0, sizeof(Q)); + + if (sm2_point_mul_generator(&P, k) != 1) { + error_print(); + return -1; + } + sm2_point_to_compressed_octets(&P, buf); + if (sm2_point_from_x(&Q, buf + 1, buf[0]) != 1) { + error_print(); + return -1; + } + if (memcmp(&P, &Q, sizeof(SM2_POINT)) != 0) { + error_print(); + sm2_point_print(stderr, 0, 4, "P", &P); + sm2_point_print(stderr, 0, 4, "Q", &Q); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_signature(void) +{ + SM2_SIGNATURE sig; + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + // MinLen + memset(&sig, 0x00, sizeof(sig)); + cp = p = buf; len = 0; + if (sm2_signature_to_der(&sig, &p, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "SM2_MIN_SIGNATURE_SIZE: %zu\n", len); + format_bytes(stderr, 0, 4, "", buf, len); + sm2_signature_print(stderr, 0, 4, "signature", buf, len); + if (len != SM2_MIN_SIGNATURE_SIZE) { + error_print(); + return -1; + } + if (sm2_signature_from_der(&sig, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + + // MaxLen + memset(&sig, 0x80, sizeof(sig)); + cp = p = buf; len = 0; + if (sm2_signature_to_der(&sig, &p, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "SM2_MAX_SIGNATURE_SIZE: %zu\n", len); + format_bytes(stderr, 0, 4, "", buf, len); + sm2_signature_print(stderr, 0, 4, "signature", buf, len); + if (len != SM2_MAX_SIGNATURE_SIZE) { + error_print(); + return -1; + } + if (sm2_signature_from_der(&sig, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_sign(void) +{ + int ret; + SM2_KEY sm2_key; + SM2_SIGN_CTX sign_ctx; + uint8_t msg[] = "Hello World!"; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE] = {0}; + size_t siglen; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key); + + if (sm2_sign_init(&sign_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 + || sm2_sign_update(&sign_ctx, msg, sizeof(msg)) != 1 + || sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "signature", sig, siglen); + sm2_signature_print(stderr, 0, 4, "signature", sig, siglen); + + if (sm2_verify_init(&sign_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 + || sm2_verify_update(&sign_ctx, msg, sizeof(msg)) != 1 + || (ret = sm2_verify_finish(&sign_ctx, sig, siglen)) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "verification: %s\n", ret ? "success" : "failed"); + + + // FIXME: 还应该增加验证不通过的测试 + // 还应该增加底层的参数 + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +// 由于当前Ciphertext中椭圆曲线点数据不正确,因此无法通过测试 +static int test_sm2_ciphertext(void) +{ + SM2_CIPHERTEXT C; + uint8_t buf[1024]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + memset(&C, 0, sizeof(SM2_CIPHERTEXT)); + + cp = p = buf; len = 0; + if (sm2_ciphertext_to_der(&C, &p, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "SM2_NULL_CIPHERTEXT_SIZE: %zu\n", len); + format_bytes(stderr, 0, 4, "", buf, len); + + + if (sm2_ciphertext_from_der(&C, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + + // {0, 0, Hash, MinLen} + C.ciphertext_size = SM2_MIN_PLAINTEXT_SIZE; + cp = p = buf; len = 0; + if (sm2_ciphertext_to_der(&C, &p, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "SM2_MIN_PLAINTEXT_SIZE: %zu\n", SM2_MIN_PLAINTEXT_SIZE); + format_print(stderr, 0, 4, "SM2_MIN_CIPHERTEXT_SIZE: %zu\n", len); + format_bytes(stderr, 0, 4, "", buf, len); + if (len != SM2_MIN_CIPHERTEXT_SIZE) { + error_print(); + return -1; + } + if (sm2_ciphertext_from_der(&C, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + // { 33, 33, Hash, NULL } + memset(&C, 0x80, sizeof(SM2_POINT)); + cp = p = buf; len = 0; + if (sm2_ciphertext_to_der(&C, &p, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "ciphertext len: %zu\n", len); + format_bytes(stderr, 0, 4, "", buf, len); + if (sm2_ciphertext_from_der(&C, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + // { 33, 33, Hash, MaxLen } + C.ciphertext_size = SM2_MAX_PLAINTEXT_SIZE;//SM2_MAX_PLAINTEXT_SIZE; + cp = p = buf; len = 0; + if (sm2_ciphertext_to_der(&C, &p, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "SM2_MAX_PLAINTEXT_SIZE: %zu\n", SM2_MAX_PLAINTEXT_SIZE); + format_print(stderr, 0, 4, "SM2_MAX_CIPHERTEXT_SIZE: %zu\n", len); + format_bytes(stderr, 0, 4, "", buf, len); + if (len != SM2_MAX_CIPHERTEXT_SIZE) { + error_print(); + return -1; + } + if (sm2_ciphertext_from_der(&C, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + +static int test_sm2_do_encrypt(void) +{ + SM2_KEY sm2_key; + uint8_t plaintext[] = "Hello World!"; + SM2_CIPHERTEXT ciphertext; + + uint8_t plainbuf[SM2_MAX_PLAINTEXT_SIZE] = {0}; + size_t plainlen = 0; + int r = 0; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + + if (sm2_do_encrypt(&sm2_key, plaintext, sizeof(plaintext), &ciphertext) != 1 + || sm2_do_decrypt(&sm2_key, &ciphertext, plainbuf, &plainlen) != 1) { + error_print(); + return -1; + } + + if (plainlen != sizeof(plaintext) + || memcmp(plainbuf, plaintext, sizeof(plaintext)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + +static int test_sm2_encrypt(void) +{ + SM2_KEY sm2_key; + uint8_t msg[SM2_MAX_PLAINTEXT_SIZE]; + uint8_t cbuf[SM2_MAX_CIPHERTEXT_SIZE+100]; + uint8_t mbuf[SM2_MAX_CIPHERTEXT_SIZE]; + size_t lens[] = { +// 0, + 1, + 16, + SM2_MAX_PLAINTEXT_SIZE, + }; + size_t clen, mlen; + int i; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + + for (i = 0; i < sizeof(msg); i++) { + msg[i] = (uint8_t)i; + } + + for (i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { + format_print(stderr, 0, 0, "test %d\n", i + 1); + format_bytes(stderr, 0, 4, "plaintext", msg, lens[i]); + if (sm2_encrypt(&sm2_key, msg, lens[i], cbuf, &clen) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "ciphertext", cbuf, clen); + sm2_ciphertext_print(stderr, 0, 4, "Ciphertext", cbuf, clen); + format_print(stderr, 0, 0, "\n"); + + if (sm2_decrypt(&sm2_key, cbuf, clen, mbuf, &mlen) != 1) { + error_print(); + return -1; + } + if (mlen != lens[i] + || memcmp(mbuf, msg, lens[i]) != 0) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + + +static int test_sm2_private_key(void) +{ + SM2_KEY sm2_key; + SM2_KEY tmp_key; + uint8_t buf[SM2_PRIVATE_KEY_BUF_SIZE]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key); + + if (sm2_private_key_to_der(&sm2_key, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "ECPrivateKey", buf, len); + format_print(stderr, 0, 4, "#define SM2_PRIVATE_KEY_DEFAULT_SIZE %zu\n", len); + if (sm2_private_key_from_der(&tmp_key, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + if (memcmp(&tmp_key, &sm2_key, sizeof(SM2_KEY)) != 0) { + + sm2_key_print(stderr, 0, 0, "sm2_key", &sm2_key); + sm2_key_print(stderr, 0, 0, "tmp_key", &tmp_key); + + + error_print(); + return -1; + } + + cp = p = buf; len = 0; + memset(&tmp_key, 0, sizeof(tmp_key)); + if (sm2_private_key_to_der(&sm2_key, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + sm2_private_key_print(stderr, 0, 4, "ECPrivateKey", d, dlen); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_private_key_info(void) +{ + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + SM2_KEY sm2_key; + SM2_KEY tmp_key; + const uint8_t *attrs; + size_t attrs_len; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key); + + if (sm2_private_key_info_to_der(&sm2_key, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "PrivateKeyInfo", buf, len); + format_print(stderr, 0, 4, "sizeof(PrivateKeyInfo): %zu\n", len); + if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + sm2_private_key_info_print(stderr, 0, 4, "PrivateKeyInfo", d, dlen); + + cp = p = buf; len = 0; + if (sm2_private_key_info_to_der(&sm2_key, &p, &len) != 1) { + error_print(); + return -1; + } + if (sm2_private_key_info_from_der(&tmp_key, &attrs, &attrs_len, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1 + || memcmp(&tmp_key, &sm2_key, sizeof(SM2_KEY)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm2_enced_private_key_info(void) +{ + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + SM2_KEY sm2_key; + SM2_KEY tmp_key; + const uint8_t *attrs; + size_t attrs_len; + const char *pass = "Password"; + + if (sm2_key_generate(&sm2_key) != 1) { + error_print(); + return -1; + } + sm2_key_print(stderr, 0, 4, "SM2_KEY", &sm2_key); + + if (sm2_private_key_info_encrypt_to_der(&sm2_key, pass, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "EncryptedPrivateKeyInfo", buf, len); + format_print(stderr, 0, 4, "sizeof(EncryptedPrivateKeyInfo): %zu\n", len); + if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + pkcs8_enced_private_key_info_print(stderr, 0, 4, "EncryptedPrivateKeyInfo", d, dlen); + + + cp = p = buf; len = 0; + if (sm2_private_key_info_encrypt_to_der(&sm2_key, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (sm2_private_key_info_decrypt_from_der(&tmp_key, &attrs, &attrs_len, pass, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1 + || memcmp(&tmp_key, &sm2_key, sizeof(SM2_KEY)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + +int main(void) +{ + if (test_sm2_bn() != 1) goto err; + if (test_sm2_jacobian_point() != 1) goto err; + if (test_sm2_point() != 1) goto err; + if (test_sm2_point_octets() != 1) goto err; + if (test_sm2_point_from_x() != 1) goto err; + if (test_sm2_point_der() != 1) goto err; + if (test_sm2_private_key() != 1) goto err; + if (test_sm2_private_key_info() != 1) goto err; + if (test_sm2_enced_private_key_info() != 1) goto err; + if (test_sm2_signature() != 1) goto err; + if (test_sm2_sign() != 1) goto err; + //if (test_sm2_ciphertext() != 1) goto err; // 需要正确的Ciphertext数据 + if (test_sm2_do_encrypt() != 1) goto err; + if (test_sm2_encrypt() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/sm3_rngtest.c b/Core/GmSSL-3.1.1/tests/sm3_rngtest.c new file mode 100644 index 0000000..4beb0d9 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm3_rngtest.c @@ -0,0 +1,23 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +int main(void) +{ + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/sm3test.c b/Core/GmSSL-3.1.1/tests/sm3test.c new file mode 100644 index 0000000..66dad8c --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm3test.c @@ -0,0 +1,183 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static int test_sm3(void) +{ + const char *testhex[] = { + /* 0 "abc" */ + "616263", + /* 1 "abcd" 16 times */ + "6162636461626364616263646162636461626364616263646162636461626364" + "6162636461626364616263646162636461626364616263646162636461626364", + /* 2 p.57 ZA */ + "0090" + "414C494345313233405941484F4F2E434F4D" + "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498" + "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A" + "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D" + "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2" + "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A" + "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857", + /* 3 p.59 ZA */ + "0090" + "414C494345313233405941484F4F2E434F4D" + "000000000000000000000000000000000000000000000000000000000000000000" + "00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B" + "00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD" + "013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E" + "0165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B2" + "01686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612", + /* 4 p.72 ZA */ + "0090" + "414C494345313233405941484F4F2E434F4D" + "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498" + "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A" + "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D" + "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2" + "3099093BF3C137D8FCBBCDF4A2AE50F3B0F216C3122D79425FE03A45DBFE1655" + "3DF79E8DAC1CF0ECBAA2F2B49D51A4B387F2EFAF482339086A27A8E05BAED98B", + /* 5 p.72 ZB */ + "0088" + "42494C4C343536405941484F4F2E434F4D" + "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498" + "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A" + "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D" + "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2" + "245493D446C38D8CC0F118374690E7DF633A8A4BFB3329B5ECE604B2B4F37F43" + "53C0869F4B9E17773DE68FEC45E14904E0DEA45BF6CECF9918C85EA047C60A4C", + /* 6 p.75 ZA */ + "0090" + "414C494345313233405941484F4F2E434F4D" + "000000000000000000000000000000000000000000000000000000000000000000" + "00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B" + "00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD" + "013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E" + "008E3BDB2E11F9193388F1F901CCC857BF49CFC065FB38B9069CAAE6D5AFC3592F" + "004555122AAC0075F42E0A8BBD2C0665C789120DF19D77B4E3EE4712F598040415", + /* 7 p.76 ZB */ + "0088" + "42494C4C343536405941484F4F2E434F4D" + "000000000000000000000000000000000000000000000000000000000000000000" + "00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B" + "00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD" + "013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E" + "0034297DD83AB14D5B393B6712F32B2F2E938D4690B095424B89DA880C52D4A7D9" + "0199BBF11AC95A0EA34BBD00CA50B93EC24ACB68335D20BA5DCFE3B33BDBD2B62D", + /* 8 TopsecCA cert ZA */ + "0080" + "31323334353637383132333435363738" + "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC" + "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93" + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7" + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" + "D69C2F1EEC3BFB6B95B30C28085C77B125D77A9C39525D8190768F37D6B205B5" + "89DCD316BBE7D89A9DC21917F17799E698531F5E6E3E10BD31370B259C3F81C3", + /* 9 */ + "4D38D2958CA7FD2CFAE3AF04486959CF92C8EF48E8B83A05C112E739D5F181D0" + "3082020CA003020102020900" + "AF28725D98D33143300C06082A811CCF" + "550183750500307D310B300906035504" + "060C02636E310B300906035504080C02" + "626A310B300906035504070C02626A31" + "0F300D060355040A0C06746F70736563" + "310F300D060355040B0C06746F707365" + "633111300F06035504030C08546F7073" + "65634341311F301D06092A864886F70D" + "0109010C10626A40746F707365632E63" + "6F6D2E636E301E170D31323036323430" + "37353433395A170D3332303632303037" + "353433395A307D310B30090603550406" + "0C02636E310B300906035504080C0262" + "6A310B300906035504070C02626A310F" + "300D060355040A0C06746F7073656331" + "0F300D060355040B0C06746F70736563" + "3111300F06035504030C08546F707365" + "634341311F301D06092A864886F70D01" + "09010C10626A40746F707365632E636F" + "6D2E636E3059301306072A8648CE3D02" + "0106082A811CCF5501822D03420004D6" + "9C2F1EEC3BFB6B95B30C28085C77B125" + "D77A9C39525D8190768F37D6B205B589" + "DCD316BBE7D89A9DC21917F17799E698" + "531F5E6E3E10BD31370B259C3F81C3A3" + "733071300F0603551D130101FF040530" + "030101FF301D0603551D0E041604148E" + "5D90347858BAAAD870D8BDFBA6A85E7B" + "563B64301F0603551D23041830168014" + "8E5D90347858BAAAD870D8BDFBA6A85E" + "7B563B64300B0603551D0F0404030201" + "06301106096086480186F84201010404" + "03020057", + }; + + const char *dgsthex[] = { + "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0", + "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732", + "F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A", + "26352AF82EC19F207BBC6F9474E11E90CE0F7DDACE03B27F801817E897A81FD5", + "E4D1D0C3CA4C7F11BC8FF8CB3F4C02A78F108FA098E51A668487240F75E20F31", + "6B4B6D0E276691BD4A11BF72F4FB501AE309FDACB72FA6CC336E6656119ABD67", + "329c2f6030cc7e0ca3af6c97b76243ca250338ad3d3dc3a8b322d1cfdf98c2b7", + /*"ECF0080215977B2E5D6D61B98A99442F03E8803DC39E349F8DCA5621A9ACDF2B",*/ + "557BAD30E183559AEEC3B2256E1C7C11F870D22B165D015ACF9465B09B87B527", + "4D38D2958CA7FD2CFAE3AF04486959CF92C8EF48E8B83A05C112E739D5F181D0", + "C3B02E500A8B60B77DEDCF6F4C11BEF8D56E5CDE708C72065654FD7B2167915A", + }; + + int err = 0; + uint8_t testbuf[sizeof(testhex)/2 + 1000]; + uint8_t dgstbuf[32]; + size_t testbuflen, dgstbuflen; + uint8_t dgst[32]; + size_t i; + + for (i = 0; i < sizeof(testhex)/sizeof(testhex[0]); i++) { + hex_to_bytes(testhex[i], strlen(testhex[i]), testbuf, &testbuflen); + hex_to_bytes(dgsthex[i], strlen(dgsthex[i]), dgstbuf, &dgstbuflen); + + sm3_digest(testbuf, testbuflen, dgst); + + if (memcmp(dgstbuf, dgst, sizeof(dgst)) != 0) { + int n; + fprintf(stderr, "sm3 test %zu failed\n", i+1); + fprintf(stderr, "error calculating SM3 on %s\n", testhex[i]); + fprintf(stderr, " digest(corret) = "); + for (n = 0; n < sizeof(dgst); n++) { + fprintf(stderr, "%02X", dgst[n]); + } + fprintf(stderr, "\n"); + fprintf(stderr, " digest(error) = %s\n", dgsthex[i]); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + +int main(void) +{ + if (test_sm3() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/sm4_aesni_avxtest.c b/Core/GmSSL-3.1.1/tests/sm4_aesni_avxtest.c new file mode 100644 index 0000000..a4256cc --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm4_aesni_avxtest.c @@ -0,0 +1,98 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +extern void sm4_aesni_avx_encrypt(const uint32_t rk[32], const uint8_t in[16 * 4], uint8_t out[16 * 4]); + +static int test_sm4_aesni_avx(void) +{ + const uint32_t rk[32] = { + 0xf12186f9, 0x41662b61, 0x5a6ab19a, 0x7ba92077, + 0x367360f4, 0x776a0c61, 0xb6bb89b3, 0x24763151, + 0xa520307c, 0xb7584dbd, 0xc30753ed, 0x7ee55b57, + 0x6988608c, 0x30d895b7, 0x44ba14af, 0x104495a1, + 0xd120b428, 0x73b55fa3, 0xcc874966, 0x92244439, + 0xe89e641f, 0x98ca015a, 0xc7159060, 0x99e1fd2e, + 0xb79bd80c, 0x1d2115b0, 0x0e228aeb, 0xf1780c81, + 0x428d3654, 0x62293496, 0x01cf72e5, 0x9124a012, + }; + const uint8_t plaintext[16 * 4] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + const uint8_t ciphertext[16 * 4] = { + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, + }; + const uint8_t ciphertext1m[16 * 4] = { + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, + 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66, + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, + 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66, + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, + 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66, + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, + 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66, + }; + + uint8_t buf[16 * 4]; + int i; + + // test encrypt once + sm4_aesni_avx_encrypt(rk, plaintext, buf); + + if (memcmp(buf, ciphertext, sizeof(ciphertext)) != 0) { + fprintf(stderr, "%s %d: %s error\n", __FILE__, __LINE__, __FUNCTION__); + return -1; + } + + // test encrypt 1000000 times + memcpy(buf, plaintext, sizeof(plaintext)); + for (i = 0; i < 1000000; i++) { + sm4_aesni_avx_encrypt(rk, buf, buf); + } + if (memcmp(buf, ciphertext1m, sizeof(ciphertext1m)) != 0) { + fprintf(stderr, "%s %d: %s 1 million times error\n", __FILE__, __LINE__, __FUNCTION__); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_sm4_aesni_avx() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/sm4_cbc_mactest.c b/Core/GmSSL-3.1.1/tests/sm4_cbc_mactest.c new file mode 100644 index 0000000..a898cc1 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm4_cbc_mactest.c @@ -0,0 +1,87 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_sm4_cbc_mac(void) +{ + SM4_KEY sm4_key; + SM4_CBC_MAC_CTX ctx; + uint8_t key[16]; + uint8_t iv[16] = {0}; + uint8_t m[128]; + uint8_t c[128]; + uint8_t mac1[16]; + uint8_t mac2[16]; + uint8_t *p; + size_t len, left; + + rand_bytes(key, sizeof(key)); + rand_bytes(m, sizeof(m)); + sm4_set_encrypt_key(&sm4_key, key); + + // test 1 + sm4_cbc_encrypt(&sm4_key, iv, m, sizeof(m)/16, c); + memcpy(mac1, c + sizeof(m) - 16, 16); + + sm4_cbc_mac_init(&ctx, key); + p = m; + len = 0; + left = sizeof(m); + while (left) { + len = left < len ? left : len; + sm4_cbc_mac_update(&ctx, p, len); + p += len; + left -= len; + len++; + } + sm4_cbc_mac_finish(&ctx, mac2); + if (memcmp(mac1, mac2, 16)) { + error_print(); + return -1; + } + + // test 2 + m[sizeof(m) - 1] = 0; + sm4_cbc_encrypt(&sm4_key, iv, m, sizeof(m)/16, c); + memcpy(mac1, c + sizeof(m) - 16, 16); + + sm4_cbc_mac_init(&ctx, key); + p = m; + len = 0; + left = sizeof(m) - 1; + while (left) { + len = left < len ? left : len; + sm4_cbc_mac_update(&ctx, p, len); + p += len; + left -= len; + len++; + } + sm4_cbc_mac_finish(&ctx, mac2); + if (memcmp(mac1, mac2, 16)) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_sm4_cbc_mac() != 1) { error_print(); return -1; } + return 0; +} diff --git a/Core/GmSSL-3.1.1/tests/sm4_rngtest.c b/Core/GmSSL-3.1.1/tests/sm4_rngtest.c new file mode 100644 index 0000000..8e912d5 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm4_rngtest.c @@ -0,0 +1,23 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +int main(void) +{ + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/sm4test.c b/Core/GmSSL-3.1.1/tests/sm4test.c new file mode 100644 index 0000000..16edb93 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm4test.c @@ -0,0 +1,710 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static int test_sm4(void) +{ + const uint8_t user_key[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + const uint32_t rk[32] = { + 0xf12186f9, 0x41662b61, 0x5a6ab19a, 0x7ba92077, + 0x367360f4, 0x776a0c61, 0xb6bb89b3, 0x24763151, + 0xa520307c, 0xb7584dbd, 0xc30753ed, 0x7ee55b57, + 0x6988608c, 0x30d895b7, 0x44ba14af, 0x104495a1, + 0xd120b428, 0x73b55fa3, 0xcc874966, 0x92244439, + 0xe89e641f, 0x98ca015a, 0xc7159060, 0x99e1fd2e, + 0xb79bd80c, 0x1d2115b0, 0x0e228aeb, 0xf1780c81, + 0x428d3654, 0x62293496, 0x01cf72e5, 0x9124a012, + }; + const uint8_t plaintext[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + const uint8_t ciphertext[16] = { + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, + }; + const uint8_t ciphertext1m[16] = { + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, + 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66, + }; + + SM4_KEY key; + unsigned char buf[16]; + int i; + + /* test key scheduling */ + sm4_set_encrypt_key(&key, user_key); + + if (memcmp(key.rk, rk, sizeof(rk)) != 0) { + fprintf(stderr, "sm4 key scheduling not passed!\n"); + return -1; + } + + /* test encrypt once */ + sm4_encrypt(&key, plaintext, buf); + if (memcmp(buf, ciphertext, sizeof(ciphertext)) != 0) { + fprintf(stderr, "sm4 encrypt not pass!\n"); + return -1; + } + + /* test encrypt 1000000 times */ + memcpy(buf, plaintext, sizeof(plaintext)); + for (i = 0; i < 1000000; i++) { + sm4_encrypt(&key, buf, buf); + } + if (memcmp(buf, ciphertext1m, sizeof(ciphertext1m)) != 0) { + fprintf(stderr, "sm4 encrypt 1000000 times not pass!\n"); + return -1; + } + + /* test decrypt */ + memset(&key, 0, sizeof(key)); + memset(buf, 0, sizeof(buf)); + sm4_set_decrypt_key(&key, user_key); + sm4_decrypt(&key, ciphertext, buf); + if (memcmp(buf, plaintext, sizeof(plaintext)) != 0) { + fprintf(stderr, "sm4 decrypt not pass!\n"); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_cbc(void) +{ + SM4_KEY sm4_key; + uint8_t key[16] = {0}; + uint8_t iv[16] = {0}; + uint8_t buf1[32] = {0}; + uint8_t buf2[32] = {0}; + uint8_t buf3[32] = {0}; + + sm4_set_encrypt_key(&sm4_key, key); + sm4_cbc_encrypt(&sm4_key, iv, buf1, 2, buf2); + sm4_set_decrypt_key(&sm4_key, key); + sm4_cbc_decrypt(&sm4_key, iv, buf2, 2, buf3); + + if (memcmp(buf1, buf3, sizeof(buf3)) != 0) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_cbc_padding(void) +{ + SM4_KEY enc_key; + SM4_KEY dec_key; + uint8_t key[16] = {0}; + uint8_t iv[16] = {0}; + uint8_t buf1[64]; + uint8_t buf2[128]; + uint8_t buf3[128]; + size_t len1, len2, len3; + + sm4_set_encrypt_key(&enc_key, key); + sm4_set_decrypt_key(&dec_key, key); + + len1 = 0; + sm4_cbc_padding_encrypt(&enc_key, iv, buf1, len1, buf2, &len2); + sm4_cbc_padding_decrypt(&dec_key, iv, buf2, len2, buf3, &len3); + if (len1 != len3 || memcmp(buf1, buf3, len3) != 0) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return -1; + } + + len1 = 7; + sm4_cbc_padding_encrypt(&enc_key, iv, buf1, len1, buf2, &len2); + sm4_cbc_padding_decrypt(&dec_key, iv, buf2, len2, buf3, &len3); + if (len1 != len3 || memcmp(buf1, buf3, len3) != 0) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return -1; + } + + len1 = 16; + sm4_cbc_padding_encrypt(&enc_key, iv, buf1, len1, buf2, &len2); + sm4_cbc_padding_decrypt(&dec_key, iv, buf2, len2, buf3, &len3); + if (len1 != len3 || memcmp(buf1, buf3, len3) != 0) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return -1; + } + + len1 = 33; + sm4_cbc_padding_encrypt(&enc_key, iv, buf1, len1, buf2, &len2); + sm4_cbc_padding_decrypt(&dec_key, iv, buf2, len2, buf3, &len3); + if (len1 != len3 || memcmp(buf1, buf3, len3) != 0) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return -1; + } + + len1 = sizeof(buf1); + sm4_cbc_padding_encrypt(&enc_key, iv, buf1, len1, buf2, &len2); + sm4_cbc_padding_decrypt(&dec_key, iv, buf2, len2, buf3, &len3); + if (len1 != len3 || memcmp(buf1, buf3, len3) != 0) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_ctr(void) +{ + SM4_KEY sm4_key; + uint8_t key[16] = {0}; + uint8_t ctr[16]; + uint8_t buf1[30] = {0}; + uint8_t buf2[30] = {0}; + uint8_t buf3[30] = {0}; + + sm4_set_encrypt_key(&sm4_key, key); + memset(ctr, 0, sizeof(ctr)); + sm4_ctr_encrypt(&sm4_key, ctr, buf1, sizeof(buf1), buf2); + + memset(ctr, 0, sizeof(ctr)); + sm4_ctr_decrypt(&sm4_key, ctr, buf2, sizeof(buf2), buf3); + + if (memcmp(buf1, buf3, sizeof(buf3)) != 0) { + fprintf(stderr, "%s %d: error\n", __FILE__, __LINE__); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_ctr_with_carray(void) +{ + const char *hex_key = "0123456789ABCDEFFEDCBA9876543210"; + const char *hex_ctr = "0000000000000000000000000000FFFF"; + const char *hex_in = "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB" + "CCCCCCCCCCCCCCCCDDDDDDDDDDDD"; + const char *hex_out = "7EA678F9F0CBE2000917C63D4E77B4C8" + "6E4E8532B0046E4AC1E97DA8B831"; + + SM4_KEY sm4_key; + uint8_t key[16] = {0}; + uint8_t ctr[16]; + uint8_t buf1[30] = {0}; + uint8_t buf2[30] = {0}; + uint8_t buf3[30] = {0}; + + size_t keylen, ctrlen, inlen, outlen; + + hex_to_bytes(hex_key, strlen(hex_key), key, &keylen); + hex_to_bytes(hex_ctr, strlen(hex_ctr), ctr, &ctrlen); + hex_to_bytes(hex_in, strlen(hex_in), buf1, &inlen); + hex_to_bytes(hex_out, strlen(hex_out), buf3, &outlen); + + sm4_set_encrypt_key(&sm4_key, key); + + sm4_ctr_encrypt(&sm4_key, ctr, buf1, sizeof(buf1), buf2); + + if (memcmp(buf2, buf3, sizeof(buf3)) != 0) { + error_print(); + return -1; + } + + hex_to_bytes(hex_ctr, strlen(hex_ctr), ctr, &ctrlen); + sm4_ctr_decrypt(&sm4_key, ctr, buf3, sizeof(buf3), buf2); + + if (memcmp(buf2, buf1, sizeof(buf1)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_gcm(void) +{ + // gcm test vectors from rfc 8998 A.1 + const char *hex_key = "0123456789ABCDEFFEDCBA9876543210"; + const char *hex_iv = "00001234567800000000ABCD"; + const char *hex_aad = "FEEDFACEDEADBEEFFEEDFACEDEADBEEF" + "ABADDAD2"; + const char *hex_in = "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB" + "CCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDD" + "EEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFF" + "EEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAA"; + const char *hex_out = "17F399F08C67D5EE19D0DC9969C4BB7D" + "5FD46FD3756489069157B282BB200735" + "D82710CA5C22F0CCFA7CBF93D496AC15" + "A56834CBCF98C397B4024A2691233B8D"; + const char *hex_tag = "83DE3541E4C2B58177E065A9BF7B62EC"; + + SM4_KEY sm4_key; + uint8_t key[16]; + uint8_t iv[12]; + uint8_t aad[20]; + uint8_t in[64]; + uint8_t out[64]; + uint8_t tag[16]; + size_t keylen, ivlen, aadlen, inlen, outlen, taglen; + + uint8_t buf[64]; + uint8_t mac[16]; + + hex_to_bytes(hex_key, strlen(hex_key), key, &keylen); + hex_to_bytes(hex_iv, strlen(hex_iv), iv, &ivlen); + hex_to_bytes(hex_aad, strlen(hex_aad), aad, &aadlen); + hex_to_bytes(hex_in, strlen(hex_in), in, &inlen); + hex_to_bytes(hex_out, strlen(hex_out), out, &outlen); + hex_to_bytes(hex_tag, strlen(hex_tag), tag, &taglen); + + memset(buf, 0, sizeof(buf)); + memset(mac, 0, sizeof(mac)); + + sm4_set_encrypt_key(&sm4_key, key); + + // test gcm encrypt + sm4_gcm_encrypt(&sm4_key, iv, ivlen, aad, aadlen, in, inlen, buf, taglen, mac); + if (memcmp(buf, out, outlen) != 0) { + error_print(); + return -1; + } + if (memcmp(mac, tag, taglen) != 0) { + error_print(); + return -1; + } + + // test gcm decrypt + memset(buf, 0, sizeof(buf)); + sm4_gcm_decrypt(&sm4_key, iv, ivlen, aad, aadlen, out, outlen, tag, taglen, buf); + if (memcmp(buf, in, inlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_gcm_gbt36624_1(void) +{ + // gcm test vectors from GB/T 36624-2018 C.5 + const char *hex_key = "00000000000000000000000000000000"; + const char *hex_iv = "000000000000000000000000"; + const char *hex_aad = ""; + const char *hex_in = ""; + const char *hex_out = ""; + const char *hex_tag = "232F0CFE308B49EA6FC88229B5DC858D"; + + SM4_KEY sm4_key; + uint8_t key[16]; + uint8_t iv[12]; + uint8_t aad[20]; + uint8_t in[64]; + uint8_t out[64]; + uint8_t tag[16]; + size_t keylen, ivlen, aadlen, inlen, outlen, taglen; + + uint8_t buf[64]; + uint8_t mac[16]; + + hex_to_bytes(hex_key, strlen(hex_key), key, &keylen); + hex_to_bytes(hex_iv, strlen(hex_iv), iv, &ivlen); + hex_to_bytes(hex_aad, strlen(hex_aad), aad, &aadlen); + hex_to_bytes(hex_in, strlen(hex_in), in, &inlen); + hex_to_bytes(hex_out, strlen(hex_out), out, &outlen); + hex_to_bytes(hex_tag, strlen(hex_tag), tag, &taglen); + + memset(buf, 0, sizeof(buf)); + memset(mac, 0, sizeof(mac)); + + sm4_set_encrypt_key(&sm4_key, key); + + // test gcm encrypt + sm4_gcm_encrypt(&sm4_key, iv, ivlen, aad, aadlen, in, inlen, buf, taglen, mac); + if (memcmp(buf, out, outlen) != 0) { + error_print(); + return -1; + } + if (memcmp(mac, tag, taglen) != 0) { + error_print(); + return -1; + } + + // test gcm decrypt + memset(buf, 0, sizeof(buf)); + sm4_gcm_decrypt(&sm4_key, iv, ivlen, aad, aadlen, out, outlen, tag, taglen, buf); + if (memcmp(buf, in, inlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_gcm_gbt36624_2(void) +{ + // gcm test vectors from GB/T 36624-2018 C.5 + const char *hex_key = "00000000000000000000000000000000"; + const char *hex_iv = "000000000000000000000000"; + const char *hex_aad = ""; + const char *hex_in = "00000000000000000000000000000000"; + const char *hex_out = "7DE2AA7F1110188218063BE1BFEB6D89"; + const char *hex_tag = "B851B5F39493752BE508F1BB4482C557"; + + SM4_KEY sm4_key; + uint8_t key[16]; + uint8_t iv[12]; + uint8_t aad[20]; + uint8_t in[64]; + uint8_t out[64]; + uint8_t tag[16]; + size_t keylen, ivlen, aadlen, inlen, outlen, taglen; + + uint8_t buf[64]; + uint8_t mac[16]; + + hex_to_bytes(hex_key, strlen(hex_key), key, &keylen); + hex_to_bytes(hex_iv, strlen(hex_iv), iv, &ivlen); + hex_to_bytes(hex_aad, strlen(hex_aad), aad, &aadlen); + hex_to_bytes(hex_in, strlen(hex_in), in, &inlen); + hex_to_bytes(hex_out, strlen(hex_out), out, &outlen); + hex_to_bytes(hex_tag, strlen(hex_tag), tag, &taglen); + + memset(buf, 0, sizeof(buf)); + memset(mac, 0, sizeof(mac)); + + sm4_set_encrypt_key(&sm4_key, key); + + // test gcm encrypt + sm4_gcm_encrypt(&sm4_key, iv, ivlen, aad, aadlen, in, inlen, buf, taglen, mac); + if (memcmp(buf, out, outlen) != 0) { + error_print(); + return -1; + } + if (memcmp(mac, tag, taglen) != 0) { + error_print(); + return -1; + } + + // test gcm decrypt + memset(buf, 0, sizeof(buf)); + sm4_gcm_decrypt(&sm4_key, iv, ivlen, aad, aadlen, out, outlen, tag, taglen, buf); + if (memcmp(buf, in, inlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_cbc_update(void) +{ + SM4_KEY sm4_key; + SM4_CBC_CTX enc_ctx; + SM4_CBC_CTX dec_ctx; + + uint8_t key[16]; + uint8_t iv[16]; + uint8_t mbuf[16 * 10]; + uint8_t cbuf[16 * 11]; + uint8_t pbuf[16 * 11]; + size_t mlen = 0; + size_t clen = 0; + size_t plen = 0; + + uint8_t *in; + uint8_t *out; + size_t len; + size_t lens[] = { 1,5,17,80 }; + int i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + + + + // first test + + mlen = 16; + rand_bytes(mbuf, mlen); + + if (sm4_cbc_encrypt_init(&enc_ctx, key, iv) != 1 + || sm4_cbc_encrypt_update(&enc_ctx, mbuf, mlen, cbuf, &clen) != 1 + || sm4_cbc_encrypt_finish(&enc_ctx, cbuf + clen, &len) != 1) { + error_print(); + return -1; + } + clen += len; + + // check ciphertext + sm4_set_encrypt_key(&sm4_key, key); + sm4_cbc_padding_encrypt(&sm4_key, iv, mbuf, mlen, pbuf, &plen); + if (clen != plen || memcmp(cbuf, pbuf, plen) != 0) { + error_print(); + return -1; + } + + // check decrypt + if (sm4_cbc_decrypt_init(&dec_ctx, key, iv) != 1 + || sm4_cbc_decrypt_update(&dec_ctx, cbuf, clen, pbuf, &plen) != 1 + || sm4_cbc_decrypt_finish(&dec_ctx, pbuf + plen, &len) != 1) { + error_print(); + return -1; + } + plen += len; + if (plen != mlen || memcmp(pbuf, mbuf, mlen) != 0) { + error_print(); + return -1; + } + + + // second test + + rand_bytes(mbuf, sizeof(mbuf)); + + if (sm4_cbc_encrypt_init(&enc_ctx, key, iv) != 1) { + error_print(); + return -1; + } + in = mbuf; + out = cbuf; + mlen = 0; + clen = 0; + for (i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { + if (sm4_cbc_encrypt_update(&enc_ctx, in, lens[i], out, &len) != 1) { + error_print(); + return -1; + } + in += lens[i]; + mlen += lens[i]; + out += len; + clen += len; + + } + if (sm4_cbc_encrypt_finish(&enc_ctx, out, &len) != 1) { + error_print(); + return -1; + } + clen += len; + + // check ciphertest + sm4_cbc_padding_encrypt(&sm4_key, iv, mbuf, mlen, pbuf, &plen); + if (plen != clen || memcmp(pbuf, cbuf, clen) != 0) { + error_print(); + return -1; + } + + // check decrypt + if (sm4_cbc_decrypt_init(&dec_ctx, key, iv) != 1) { + error_print(); + return -1; + } + plen = 0; + in = cbuf; + out = pbuf; + for (i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { + if (sm4_cbc_decrypt_update(&dec_ctx, in, lens[i], out, &len) != 1) { + error_print(); + return -1; + } + in += lens[i]; + clen -= lens[i]; + out += len; + plen += len; + } + if (sm4_cbc_decrypt_update(&dec_ctx, in, clen, out, &len) != 1) { + error_print(); + return -1; + } + out += len; + plen += len; + if (sm4_cbc_decrypt_finish(&dec_ctx, out, &len) != 1) { + error_print(); + return -1; + } + plen += len; + + if (plen != mlen || memcmp(pbuf, mbuf, mlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sm4_ctr_update(void) +{ + SM4_KEY sm4_key; + SM4_CTR_CTX enc_ctx; + SM4_CTR_CTX dec_ctx; + + uint8_t key[16]; + uint8_t iv[16]; + uint8_t ctr[16]; + uint8_t mbuf[16 * 10]; + uint8_t cbuf[16 * 11]; + uint8_t pbuf[16 * 11]; + size_t mlen = 0; + size_t clen = 0; + size_t plen = 0; + + uint8_t *in; + uint8_t *out; + size_t len; + size_t lens[] = { 1,5,17,80 }; + int i; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + + // first test + + mlen = 16; + rand_bytes(mbuf, mlen); + memcpy(ctr, iv, sizeof(iv)); + if (sm4_ctr_encrypt_init(&enc_ctx, key, ctr) != 1 + || sm4_ctr_encrypt_update(&enc_ctx, mbuf, mlen, cbuf, &clen) != 1 + || sm4_ctr_encrypt_finish(&enc_ctx, cbuf + clen, &len) != 1) { + error_print(); + return -1; + } + clen += len; + + // check ciphertext + sm4_set_encrypt_key(&sm4_key, key); + sm4_ctr_encrypt(&sm4_key, ctr, mbuf, mlen, pbuf); // 注意:sm4_ctr_encrypt() 会修改ctr的值 + memcpy(ctr, iv, sizeof(iv)); + if (memcmp(cbuf, pbuf, clen) != 0) { + error_print(); + return -1; + } + + // check decrypt + if (sm4_ctr_decrypt_init(&dec_ctx, key, ctr) != 1 + || sm4_ctr_decrypt_update(&dec_ctx, cbuf, clen, pbuf, &plen) != 1 + || sm4_ctr_decrypt_finish(&dec_ctx, pbuf + plen, &len) != 1) { + error_print(); + return -1; + } + plen += len; + + if (plen != mlen || memcmp(pbuf, mbuf, mlen) != 0) { + error_print(); + return -1; + } + + + // second test + + rand_bytes(mbuf, sizeof(mbuf)); + + if (sm4_ctr_encrypt_init(&enc_ctx, key, ctr) != 1) { + error_print(); + return -1; + } + in = mbuf; + out = cbuf; + mlen = 0; + clen = 0; + for (i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { + if (sm4_ctr_encrypt_update(&enc_ctx, in, lens[i], out, &len) != 1) { + error_print(); + return -1; + } + in += lens[i]; + mlen += lens[i]; + out += len; + clen += len; + + } + if (sm4_ctr_encrypt_finish(&enc_ctx, out, &len) != 1) { + error_print(); + return -1; + } + clen += len; + + // check ciphertest + sm4_ctr_encrypt(&sm4_key, ctr, mbuf, mlen, pbuf); + memcpy(ctr, iv, sizeof(iv)); + if (memcmp(pbuf, cbuf, mlen) != 0) { + error_print(); + return -1; + } + + // check decrypt + if (sm4_ctr_decrypt_init(&dec_ctx, key, ctr) != 1) { + error_print(); + return -1; + } + plen = 0; + in = cbuf; + out = pbuf; + for (i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { + if (sm4_ctr_decrypt_update(&dec_ctx, in, lens[i], out, &len) != 1) { + error_print(); + return -1; + } + in += lens[i]; + clen -= lens[i]; + out += len; + plen += len; + } + if (sm4_ctr_decrypt_update(&dec_ctx, in, clen, out, &len) != 1) { + error_print(); + return -1; + } + out += len; + plen += len; + if (sm4_ctr_decrypt_finish(&dec_ctx, out, &len) != 1) { + error_print(); + return -1; + } + plen += len; + + if (plen != mlen || memcmp(pbuf, mbuf, mlen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_sm4() != 1) goto err; + if (test_sm4_cbc() != 1) goto err; + if (test_sm4_cbc_padding() != 1) goto err; + if (test_sm4_ctr() != 1) goto err; + if (test_sm4_gcm() != 1) goto err; + if (test_sm4_gcm_gbt36624_1() != 1) goto err; + if (test_sm4_gcm_gbt36624_2() != 1) goto err; + if (test_sm4_cbc_update() != 1) goto err; + if (test_sm4_ctr_update() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/sm9test.c b/Core/GmSSL-3.1.1/tests/sm9test.c new file mode 100644 index 0000000..f74f7e6 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/sm9test.c @@ -0,0 +1,704 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static int sm9_bn_equ_hex(const sm9_bn_t a, const char *hex) +{ + sm9_bn_t b; + sm9_bn_from_hex(b, hex); + return (sm9_bn_cmp(a, b) == 0); +} + + +#define hex_iv "123456789abcdef00fedcba987654321123456789abcdef00fedcba987654321" +#define hex_fp_add "114efe24536598809df494ff7657484edff1812d51c3955b7d869149aa123d31" +#define hex_fp_sub "43cee97c9abed9be3efe7ffffc9d30abe1d643b9b27ea351460aabb2239d3fd4" +#define hex_fp_nsub "7271168367e4cd3397052b4ff8f19699401c4f9167fc4b8a9f64ef75bfb405a9" +#define hex_fp_dbl "551de7a0ee24723edcf314ff72f478fac1c7c4e7044238acc3913cfbcdaf7d05" +#define hex_fp_tri "248cdb7163e4d7e5606ac9d731a751d591b25db4f925dd9532a20de5c2de98c9" +#define hex_fp_div2 "9df779e83d83d9c517bf85bbd4e833b289e7dfb214ecc1501cf8039cdde8d35f" +#define hex_fp_neg "30910c2f8a3f9a597c884b28414d2725301567320b1c5b1790ef2f160ad0e43c" +#define hex_fp_mul "9e4d19bb5d94a47352e6f53f4116b2a71b16a1113dc789b26528ee19f46b72e0" +#define hex_fp_sqr "46dc2a5b8853234b341d9c57f9c4ca5709e95bbfef25356812e884e4f38cd0d6" +#define hex_fp_pow "5679a8f0a46ada5b9d48008cde0b8b7a233f882c08afe8f08a36a20ac845bb1a" +#define hex_fp_inv "7d404b0027a93e3fa8f8bc7ee367a96814c42a3b69feb1845093406948a34753" + +int test_sm9_fp() { + const SM9_TWIST_POINT _P2 = { + {{0xAF82D65B, 0xF9B7213B, 0xD19C17AB, 0xEE265948, 0xD34EC120, 0xD2AAB97F, 0x92130B08, 0x37227552}, + {0xD8806141, 0x54806C11, 0x0F5E93C4, 0xF1DD2C19, 0xB441A01F, 0x597B6027, 0x78640C98, 0x85AEF3D0}}, + {{0xC999A7C7, 0x6215BBA5, 0xA71A0811, 0x47EFBA98, 0x3D278FF2, 0x5F317015, 0x19BE3DA6, 0xA7CF28D5}, + {0x84EBEB96, 0x856DC76B, 0xA347C8BD, 0x0736A96F, 0x2CBEE6ED, 0x66BA0D26, 0x2E845C12, 0x17509B09}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, + }; + const SM9_TWIST_POINT *P2 = &_P2; + const SM9_TWIST_POINT _Ppubs = { + {{0x96EA5E32, 0x8F14D656, 0x386A92DD, 0x414D2177, 0x24A3B573, 0x6CE843ED, 0x152D1F78, 0x29DBA116}, + {0x1B94C408, 0x0AB1B679, 0x5E392CFB, 0x1CE0711C, 0x41B56501, 0xE48AFF4B, 0x3084F733, 0x9F64080B}}, + {{0xB4E3216D, 0x0E75C05F, 0x5CDFF073, 0x1006E85F, 0xB7A46F74, 0x1A7CE027, 0xDDA532DA, 0x41E00A53}, + {0xD0EF1C25, 0xE89E1408, 0x1A77F335, 0xAD3E2FDB, 0x47E3A0CB, 0xB57329F4, 0xABEA0112, 0x69850938}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, + }; + const SM9_TWIST_POINT *Ppubs = &_Ppubs; + sm9_fp_t x; + sm9_fp_t y; + sm9_fp_t r; + int j = 1; + + sm9_bn_copy(x, P2->X[1]); + sm9_bn_copy(y, Ppubs->Y[0]); + + sm9_fp_t iv = {0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678, 0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678}; + sm9_bn_from_hex(r, hex_iv); if (sm9_bn_cmp(r, iv) != 0) goto err; ++j; + + sm9_fp_add(r, x, y); if (!sm9_bn_equ_hex(r, hex_fp_add)) goto err; ++j; + sm9_fp_sub(r, x, y); if (!sm9_bn_equ_hex(r, hex_fp_sub)) goto err; ++j; + sm9_fp_sub(r, y, x); if (!sm9_bn_equ_hex(r, hex_fp_nsub)) goto err; ++j; + sm9_fp_dbl(r, x); if (!sm9_bn_equ_hex(r, hex_fp_dbl)) goto err; ++j; + sm9_fp_tri(r, x); if (!sm9_bn_equ_hex(r, hex_fp_tri)) goto err; ++j; + sm9_fp_div2(r, x); if (!sm9_bn_equ_hex(r, hex_fp_div2)) goto err; ++j; + sm9_fp_neg(r, x); if (!sm9_bn_equ_hex(r, hex_fp_neg)) goto err; ++j; + sm9_fp_mul(r, x, y); if (!sm9_bn_equ_hex(r, hex_fp_mul)) goto err; ++j; + sm9_fp_sqr(r, x); if (!sm9_bn_equ_hex(r, hex_fp_sqr)) goto err; ++j; + sm9_fp_pow(r, x, y); if (!sm9_bn_equ_hex(r, hex_fp_pow)) goto err; ++j; + sm9_fp_inv(r, x); if (!sm9_bn_equ_hex(r, hex_fp_inv)) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s() test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_x "483f336f119053cba8c0e738cabc2bfdbf047caf7e1aaa92526fa48041ceea2b" +#define hex_y "3220b45276e3692a387faa7bf3cd46e390608f2f4298cce467bf2b7fda091edb" +#define hex_fn_add "7a5fe7c18873bcf5e14091b4be8972e14f650bdec0b37776ba2ed0001bd80906" +#define hex_fn_sub "161e7f1c9aaceaa170413cbcd6eee51a2ea3ed803b81ddadeab0790067c5cb50" +#define hex_fn_nsub "a02180e367f6bc5065c26e931e9fe22a1b4ea5cadd68ae40fabe689c6ed903d5" +#define hex_fn_mul "25c528484b65755b1ff57b47b77f2b32e20467be1dde566ede4264b2e092d223" +#define hex_fn_pow "445cb9b76f27e9d03a2c30fbabb59b0ea6d7b06259b0c8a1b30f21b9b274a055" +#define hex_fn_inv "3e3e849c2144c3596d9c79cb1f8ee7c60828787e298b06cc341a9a165191bc5e" + +int test_sm9_fn() { + sm9_fn_t x; + sm9_fn_t y; + sm9_fn_t r; + int j = 1; + + sm9_bn_from_hex(x, hex_x); + sm9_bn_from_hex(y, hex_y); + + sm9_fn_t iv = {0, 0, 0, 0, 0, 0, 0, 0}; if (!sm9_fn_is_zero(iv)) goto err; ++j; + sm9_fn_add(r, x, y); if (!sm9_bn_equ_hex(r, hex_fn_add)) goto err; ++j; + sm9_fn_sub(r, x, y); if (!sm9_bn_equ_hex(r, hex_fn_sub)) goto err; ++j; + sm9_fn_sub(r, y, x); if (!sm9_bn_equ_hex(r, hex_fn_nsub)) goto err; ++j; + sm9_fn_mul(r, x, y); if (!sm9_bn_equ_hex(r, hex_fn_mul)) goto err; ++j; + sm9_fn_pow(r, x, y); if (!sm9_bn_equ_hex(r, hex_fn_pow)) goto err; ++j; + sm9_fn_inv(r, x); if (!sm9_bn_equ_hex(r, hex_fn_inv)) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_iv2 "123456789abcdef00fedcba987654321123456789abcdef00fedcba987654321-a39654024e243d806e492768664a2b72d632457dd14f49a9f1fdd299c9bb073c" +#define hex_fp2_add "0074a3145c65ac547541612178e584a902248740e70606dcaaafe2bcbd2f6a21-1b6ac9eb2c47b62cf61608b26c3c7e20674a48c4c509ac130bbaf6d47d32c07c" +#define hex_fp2_dbl "2ea136125d08b824cd741a4c597dcdda0e6d52df468f917b0adb8ed709d7d72c-995e51aa30d8d45ae85f34da84c0589f6dece1e633b92146debbdc23afe20a11" +#define hex_fp2_tri "45f1d11b8b8d1437342e2772863cb4c715a3fc4ee9d75a38904956428ec3c2c2-8aed7a7f47f36b0f718cf99fcc59214c93ea0933c0583a7c5b61fca1962a6c5b" +#define hex_fp2_sub "2e2c92fe00a30bd05832b92ae09849310c48cb9e5f898a9e602bac1a4ca86d0b-7df387bf04911e2df2492c281883da7f06a299216eaf7533d300e54f32af4995" +#define hex_fp2_neg "9eef64f6d41f4adf6f499e29c8cfe0581abbe9db7733261e6001d3bc5e6559e7-0e70d72ae8e5694b76d23b3ab8673752da02d8b27360e6ca8359df8219b79db6" +#define hex_fp2_mul "192eb5c3350a03e4baf23dd035b8804af8d5189c710adda53edd9cc0633f2d67-27fe3a559abcc3e1b1fc3f1eb35b4bd5e465f0ef2bcb9997b36e3548637456b6" +#define hex_fp2_mul_u "27fe3a559abcc3e1b1fc3f1eb35b4bd5e465f0ef2bcb9997b36e3548637456b6-83e29479988f9f28601f2faf8a1dc6af304862123865339167b461a71cd2eaaf" +#define hex_fp2_mul_fp "546e5945201b73c6ae44053114761efe351d5884c737301cfc7d2376d349a616-3c2f6327ef1c5aa1d06e8cebc4100f0758c04476f40e8a0facb0a0bf09a9dd42" +#define hex_fp2_sqr "8896d4306fb19d0e4a0e09899240e35cafed70bebb3ad56cf7b07964fefdfb93-16bd622a907d7a92e475ed336e8ebca2cc1e38dd2ae69aaf2a96208eba0ee06e" +#define hex_fp2_sqr_u "16bd622a907d7a92e475ed336e8ebca2cc1e38dd2ae69aaf2a96208eba0ee06e-5b52579f25e413c717eb438cc69bc7d0e40a4518be8032dddb7e4385c8a693d4" +#define hex_fp2_inv "93ceda7dddd537eb9307a06313598e650a568d931d16ab98ca0a7483c3b502e2-6face8b958e2bdc0771fd9d700f2703f881ef0d13509f16937f0a0c344647175" +#define hex_fp2_div "ad68ff7c507f2d4e1cc6cd973c6b821906b9f5937a04fdedc84af1f75f97d00b-8a84a35da11d401c8dca50a572ce7a8c99e7117c45d251f57a2418613dab16bb" +#define hex_fp2_div2 "0ba84d8497422e09335d0693165f7376839b54b7d1a3e45ec2b6e3b5c275f5cb-af07946a8e30f24c1a9a8db2995b2b9bb4f126f1e0ca7b76a3c2ab66d67576a2" + +int test_sm9_fp2() { + const SM9_TWIST_POINT _P2 = { + {{0xAF82D65B, 0xF9B7213B, 0xD19C17AB, 0xEE265948, 0xD34EC120, 0xD2AAB97F, 0x92130B08, 0x37227552}, + {0xD8806141, 0x54806C11, 0x0F5E93C4, 0xF1DD2C19, 0xB441A01F, 0x597B6027, 0x78640C98, 0x85AEF3D0}}, + {{0xC999A7C7, 0x6215BBA5, 0xA71A0811, 0x47EFBA98, 0x3D278FF2, 0x5F317015, 0x19BE3DA6, 0xA7CF28D5}, + {0x84EBEB96, 0x856DC76B, 0xA347C8BD, 0x0736A96F, 0x2CBEE6ED, 0x66BA0D26, 0x2E845C12, 0x17509B09}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, + }; + const SM9_TWIST_POINT *P2 = &_P2; + const SM9_TWIST_POINT _Ppubs = { + {{0x96EA5E32, 0x8F14D656, 0x386A92DD, 0x414D2177, 0x24A3B573, 0x6CE843ED, 0x152D1F78, 0x29DBA116}, + {0x1B94C408, 0x0AB1B679, 0x5E392CFB, 0x1CE0711C, 0x41B56501, 0xE48AFF4B, 0x3084F733, 0x9F64080B}}, + {{0xB4E3216D, 0x0E75C05F, 0x5CDFF073, 0x1006E85F, 0xB7A46F74, 0x1A7CE027, 0xDDA532DA, 0x41E00A53}, + {0xD0EF1C25, 0xE89E1408, 0x1A77F335, 0xAD3E2FDB, 0x47E3A0CB, 0xB57329F4, 0xABEA0112, 0x69850938}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, + }; + const SM9_TWIST_POINT *Ppubs = &_Ppubs; + sm9_fp2_t x; + sm9_fp2_t y; + sm9_fp2_t r; + sm9_fp2_t s; + sm9_fp_t k; + int j = 1; + + sm9_fp2_copy(x, P2->Y); + sm9_fp2_copy(y, Ppubs->X); + sm9_bn_from_hex(k, hex_iv); + + sm9_fp2_t iv2 = {{0xc9bb073c, 0xf1fdd299, 0xd14f49a9, 0xd632457d, 0x664a2b72, 0x6e492768, 0x4e243d80, 0xa3965402}, + {0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678, 0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678}}; + sm9_fp2_from_hex(r, hex_iv2); if (!sm9_fp2_equ(r, iv2)) goto err; ++j; + + sm9_fp2_add(r, x, y); sm9_fp2_from_hex(s, hex_fp2_add); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_dbl(r, x); sm9_fp2_from_hex(s, hex_fp2_dbl); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_tri(r, x); sm9_fp2_from_hex(s, hex_fp2_tri); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_sub(r, x, y); sm9_fp2_from_hex(s, hex_fp2_sub); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_neg(r, x); sm9_fp2_from_hex(s, hex_fp2_neg); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_mul(r, x, y); sm9_fp2_from_hex(s, hex_fp2_mul); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_mul_u(r, x, y); sm9_fp2_from_hex(s, hex_fp2_mul_u); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_mul_fp(r, x, k); sm9_fp2_from_hex(s, hex_fp2_mul_fp); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_sqr(r, x); sm9_fp2_from_hex(s, hex_fp2_sqr); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_sqr_u(r, x); sm9_fp2_from_hex(s, hex_fp2_sqr_u); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_inv(r, x); sm9_fp2_from_hex(s, hex_fp2_inv); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_div(r, x, y); sm9_fp2_from_hex(s, hex_fp2_div); if (!sm9_fp2_equ(r, s)) goto err; ++j; + sm9_fp2_div2(r, x); sm9_fp2_from_hex(s, hex_fp2_div2); if (!sm9_fp2_equ(r, s)) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_iv4 \ + "123456789abcdef00fedcba987654321123456789abcdef00fedcba987654321\n" \ + "a39654024e243d806e492768664a2b72d632457dd14f49a9f1fdd299c9bb073c\n" \ + "123456789abcdef00fedcba987654321123456789abcdef00fedcba987654321\n" \ + "a39654024e243d806e492768664a2b72d632457dd14f49a9f1fdd299c9bb073c" +#define hex_fp4_mul \ + "11d8f3dc2c4a7cd3ff4d557d86871210cff65187190711430b2d898affd61cda\n" \ + "960ee85c0aaacd6cc805053293a4955245ba973c9972b6767d0c68450a905ee7\n" \ + "ac9891b21d82827f6ccc2cd8524179b833239019c0b66cad89d7d8735ee03782\n" \ + "8f456b1cee442d189d01fc42fff7fd8481173dae8dc547d85c01a843005a063e" +#define hex_fp4_mul_fp \ + "413b76fe8748ab9130dc2907a55c15da925b496395c2cd82d6311863a4d9cfa8\n" \ + "5cc754d5318f3ed489db7e53f94f3878a527053693983f4d4a61b30f6ea74984\n" \ + "6769891769934201aa8d6de63cc012ec2b722d7b0ad9c9039246a3eea6f3d479\n" \ + "408d33e58a4d3bfaf1d84a7ddad4e4026ca41f2aaa179611d9894584baed89d0" +#define hex_fp4_mul_fp2 \ + "242956015bdff53db568b970d64a7de56a0506309e1309b283317134dd52d53e\n" \ + "5333c472d44677df131eeb1180badb3e1e9f88ba58190d16a92d95f939efb2c3\n" \ + "0ccdaa76a6876ff69de6792161b614ca720bfcee2d5521533fbb28179ec0e31e\n" \ + "2a2d6b832e919c313920f2e13e822795e2ceda8c0d8f4abe78220e4e00aeb6fd" +#define hex_fp4_mul_v \ + "ac9891b21d82827f6ccc2cd8524179b833239019c0b66cad89d7d8735ee03782\n" \ + "8f456b1cee442d189d01fc42fff7fd8481173dae8dc547d85c01a843005a063e\n" \ + "960ee85c0aaacd6cc805053293a4955245ba973c9972b6767d0c68450a905ee7\n" \ + "928e1847aa0ead49d7690054e880a3238205f03ce86ccc55cf148811e3a50bc9" +#define hex_fp4_sqr \ + "8d3bc7848d4ad61017a7cb4efc280103bfe558e240c46c5765f1a4e2ec2e8c54\n" \ + "2f0f2ef9dd3979c7018b67837ba6e73938ba88ae66a101aaa0cf27ee449835ec\n" \ + "93838cbf9e5be34562c5bc031e27357d206f783837a6a921cbf4829292b69441\n" \ + "3681ecc58b68ffc15af31c5b1f1e10e1f3c60bdabb329c0dc7ffb2cc3925f005" +#define hex_fp4_sqr_v \ + "93838cbf9e5be34562c5bc031e27357d206f783837a6a921cbf4829292b69441\n" \ + "3681ecc58b68ffc15af31c5b1f1e10e1f3c60bdabb329c0dc7ffb2cc3925f005\n" \ + "2f0f2ef9dd3979c7018b67837ba6e73938ba88ae66a101aaa0cf27ee449835ec\n" \ + "520870f6eab1a1c37cb7c001f2cd8c82c41a74d1b36d0508fefbec89ee457252" +#define hex_fp4_inv \ + "1ec69309f84c5ad450750826fc804b72fb89fb48474222ba05be08bb1765f1d6\n" \ + "3f16de331f77f510a3ec06e79319e3be5b3777471f79cd53404652b485133e99\n" \ + "1cbf7f3bb04e2389184eade12de2752711cbff452363d2dfaf2bfef40618cebc\n" \ + "3a70e829b83dc311970bc8d3e3e652f88a1ecd49b4672aa18c1c613c9a97d86f" + +int test_sm9_fp4() { + const SM9_TWIST_POINT _Ppubs = { + {{0x96EA5E32, 0x8F14D656, 0x386A92DD, 0x414D2177, 0x24A3B573, 0x6CE843ED, 0x152D1F78, 0x29DBA116}, + {0x1B94C408, 0x0AB1B679, 0x5E392CFB, 0x1CE0711C, 0x41B56501, 0xE48AFF4B, 0x3084F733, 0x9F64080B}}, + {{0xB4E3216D, 0x0E75C05F, 0x5CDFF073, 0x1006E85F, 0xB7A46F74, 0x1A7CE027, 0xDDA532DA, 0x41E00A53}, + {0xD0EF1C25, 0xE89E1408, 0x1A77F335, 0xAD3E2FDB, 0x47E3A0CB, 0xB57329F4, 0xABEA0112, 0x69850938}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, + }; + const SM9_TWIST_POINT *Ppubs = &_Ppubs; + sm9_fp4_t x; + sm9_fp4_t y; + sm9_fp4_t r; + sm9_fp4_t s; + sm9_fp2_t q; + sm9_fp_t k; + int j = 1; + + sm9_fp2_from_hex(x[0], hex_fp2_mul_fp); + sm9_fp2_from_hex(x[1], hex_fp2_sqr); + sm9_fp2_from_hex(y[0], hex_fp2_add); + sm9_fp2_from_hex(y[1], hex_fp2_tri); + sm9_bn_from_hex(k, hex_iv); + sm9_fp2_copy(q, Ppubs->X); + + sm9_fp4_t iv4 = {{{0xc9bb073c, 0xf1fdd299, 0xd14f49a9, 0xd632457d, 0x664a2b72, 0x6e492768, 0x4e243d80, 0xa3965402}, + {0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678, 0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678}}, + {{0xc9bb073c, 0xf1fdd299, 0xd14f49a9, 0xd632457d, 0x664a2b72, 0x6e492768, 0x4e243d80, 0xa3965402}, + {0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678, 0x87654321, 0x0fedcba9, 0x9abcdef0, 0x12345678}}}; + sm9_fp4_from_hex(r, hex_iv4); if (!sm9_fp4_equ(r, iv4)) goto err; ++j; + + sm9_fp4_mul(r, x, y); sm9_fp4_from_hex(s, hex_fp4_mul); if (!sm9_fp4_equ(r, s)) goto err; ++j; + sm9_fp4_mul_fp(r, x, k); sm9_fp4_from_hex(s, hex_fp4_mul_fp); if (!sm9_fp4_equ(r, s)) goto err; ++j; + sm9_fp4_mul_fp2(r, x, q); sm9_fp4_from_hex(s, hex_fp4_mul_fp2); if (!sm9_fp4_equ(r, s)) goto err; ++j; + sm9_fp4_mul_v(r, x, y); sm9_fp4_from_hex(s, hex_fp4_mul_v); if (!sm9_fp4_equ(r, s)) goto err; ++j; + sm9_fp4_sqr(r, x); sm9_fp4_from_hex(s, hex_fp4_sqr); if (!sm9_fp4_equ(r, s)) goto err; ++j; + sm9_fp4_sqr_v(r, x); sm9_fp4_from_hex(s, hex_fp4_sqr_v); if (!sm9_fp4_equ(r, s)) goto err; ++j; + sm9_fp4_inv(r, x); sm9_fp4_from_hex(s, hex_fp4_inv); if (!sm9_fp4_equ(r, s)) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_fp12_mul \ + "058d43459faee14ba2b6a69ff2d8c3ad933a1253e1764dedf5419b144a2ab82b\n" \ + "20ef84805ba02ef92a48fb2ae8086e566a644ab0639249f175268f18d8091ad4\n" \ + "83cc3be54a699ae24d8f920c87baa395befb424a6dcad1dcdfc2a006765ef8d5\n" \ + "1d705169165d9c2386c3bc673df3fa84975afa955a7be27f1b362000a96b8c2c\n" \ + "22b910d826f02961ff0fed439beb1e91f45193f87c2cdd9562da539290846ace\n" \ + "2c618991ae82d35063cfed629ff7d930b8070ba07d0652ba092f046e133e3491\n" \ + "137bc78a9aa182330bd71fb8859314422dd36f5e3c1f6fd36d6c9685fc39419f\n" \ + "8d83e7380abe10a2f3677864c2dbbcdad7ae5434e92043a2da3b71f3f9cedd8c\n" \ + "850c0562ac08996c05d22ea466cf4b1fa7a7064d4653b5fa725d623254bf7125\n" \ + "6dc41016b3ab9b44a4841aa8037e3b4d331cc7c8313abee0c5111a9be5915e90\n" \ + "6d1a15e5b765c4b139bf5c6c4a87214c269b26fb709ff5de885c053f405cf626\n" \ + "8d4d853489a4a5d809fa77e35627a5351651b926f001e1ee46e95808f9001d24" +#define hex_fp12_sqr \ + "3592cba3482fb39756b2ed1d3d756685caa005bd5e8288bc92841d29276aa321\n" \ + "8e3a49919e6de83b1ab1a5bb9eb993c3bbd68e8d305aed5c0b88cef0ef41c47f\n" \ + "3d3d9cc8e07619efd21745f6938a26f7cb0a83ad4aa3a9d066e18ad99833e3ac\n" \ + "25195ec7af551c42d7d37a0b120607d4adba6b9377299688b92a8393f3b8c20f\n" \ + "76f676d5d2cb8d1a2cc237fc78c8d544bef1cd560e654236f502aed0d8c9148c\n" \ + "6cde174a5e9d117175a4a163f041b65f868dffa05b5f3474f729b87f92493f2c\n" \ + "667a86d73e8f88a81306f7f0cd28789a55bf7e9cbe155fc6abb300ad027d8801\n" \ + "a49a66d48ec2ef72a9929413a40e316a8aee1d6236a1db8c56496524f1c23f11\n" \ + "1684bc9679aaba4afe35ec8c0852e438f41e15ab37620d9661018f90fe7415f1\n" \ + "8d37fb8b7edf942885b3009cf7e295bea89444d34091fc57380c778395b7c4e4\n" \ + "278b9d9ea61b6b2758e758ed9a64034576b520e65a9d276a0c82f079501a226e\n" \ + "01a333fa4177601de7cd8ed49ea4906f30e23988dcb7cde173da48499fce3ee5" +#define hex_fp12_inv \ + "47ae900b90945e31afde7fe09f0b69640c468a1648ee52070584a5d13af22bb9\n" \ + "8f273655182c3a9f184dc30421161ecdd50655c36a9266c7df1016e410f34102\n" \ + "a26e789013203804b5f8f1c5a51dd3fb50176d41108b235d6e66712721060252\n" \ + "090aaed5cb83068a0376c6eaca210007744d00c8b4ce53279a67cc069cc519e7\n" \ + "80ab89aa446df59ffe2f29cdb917b760d740ceb634c731b93bf1661aa5868b54\n" \ + "1e13ab51b3198619cc0016599562ed4d266d1481d0d273d3f97cffe5f8e0dd21\n" \ + "5aeb8ed89aafc971a857b8d02f3e3c37ef15ba0e3220e3a7c13c9da8af0c393b\n" \ + "518c338b1430e3129c2555650e5d5634d89513f694ba3a5f2aeb444c540f125a\n" \ + "aba8c5682695f3feee64772d0e49b432c96470e7d663098e9c271a91d4fc991a\n" \ + "0ed800dabe29af5fb41a41cc49fd4084deb02442e8e66f88186607f46395e533\n" \ + "a31b642cd5453c7bb16c82bc67bd3b66fa4db58b8e9aa45f9b579860f18d402c\n" \ + "798b84002e95753e3b07027a8d68b0a7ab2ac40328fc7ca3ea40780b3428dbc1" +#define hex_fp12_pow \ + "43291d68970ec9c00ed4616b8fa4b2b332c15a6e4ed833a4b1d68db20a06896c\n" \ + "48f861508cb878a1f1f806a486f3aa6889571bd5fb1010d73933550d219afd14\n" \ + "34b20766a4cc466efe1ee0d48206d683890494aec331d5b345e9a9adb5c5845a\n" \ + "0e3edea737b3db1083b776eb48e7bfaa4256a8d37d7ab13a370d7682daaf794d\n" \ + "9808adfd960da7837736fca5acb13a84d56962a21af424e48c0aa52c77dfd157\n" \ + "a8aa94ea4f3026eed8fa99ab9a793468db12bb7256c50570e72e375f981861a1\n" \ + "3fd308b4cdcec640fa4f17aac455b2f3daed3fb86a850b47c301c3941dbd6c4c\n" \ + "11b99f09fa20368e840c3d76e706939e4a3e8367165bb802de43acc83ae622d5\n" \ + "a5e97a50168650cae7b02b4c2511eeb194cd5ea5ff02a0284abd5961b46d47e4\n" \ + "b52a91d96353ef501bdbe6424ea26414faeeb930b9e618c2882a85d1fdeea3d0\n" \ + "6c78632b7dbbbdbf347a3f5fd6935a9f9b425125b7ac106e3586a7fbee3f2f20\n" \ + "6b35df1d1153684f1363fce020088a797802e18959df4f006bc5d7f4a632e9f9" + +int test_sm9_fp12() { + sm9_fp12_t x; + sm9_fp12_t y; + sm9_fp12_t r; + sm9_fp12_t s; + sm9_bn_t k; + int j = 1; + + sm9_fp4_from_hex(x[0], hex_fp4_mul); + sm9_fp4_from_hex(x[1], hex_fp4_mul_fp); + sm9_fp4_from_hex(x[2], hex_fp4_mul_fp2); + sm9_fp4_from_hex(y[0], hex_fp4_mul_v); + sm9_fp4_from_hex(y[1], hex_fp4_sqr); + sm9_fp4_from_hex(y[2], hex_fp4_inv); + sm9_bn_from_hex(k, hex_iv); + + sm9_fp12_mul(r, x, y); sm9_fp12_from_hex(s, hex_fp12_mul); if (!sm9_fp12_equ(r, s)) goto err; ++j; + sm9_fp12_sqr(r, x); sm9_fp12_from_hex(s, hex_fp12_sqr); if (!sm9_fp12_equ(r, s)) goto err; ++j; + sm9_fp12_inv(r, x); sm9_fp12_from_hex(s, hex_fp12_inv); if (!sm9_fp12_equ(r, s)) goto err; ++j; + sm9_fp12_pow(r, x, k); sm9_fp12_from_hex(s, hex_fp12_pow); if (!sm9_fp12_equ(r, s)) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_point1 "917be49d159184fba140f4dfc5d653464e94f718fe195b226b3f715829e6e768-288578d9505d462867a50acee40ee143b896e72505be10e8ce4c6b0c945b642b" +#define hex_point2 "593417680f252445fd0522383e23c77a54b11fe222de4a886eabc26e16bffa3c-38e8fc9a8b60f5ba0c6c411f721c117044435a833757d8fee65828511b8b245d" +#define hex_point_dbl "268def7968f1e8c51635e277425403df88355fb2ecf16f7920f112eb2a7e50c9-5c596b534bbaa85c1d3aecf436e61ff1bfd9f70856f0309c2a63d8248205d84e" +#define hex_point_add "056610cb69f8d5659ea94e4a67bbf3b93fb0bd449672d7ca2525ec3b68c894d1-88f3f99ce78ed3ffe6ca1cface5242570cb5d053f16a8e0baae10414babd86a7" +#define hex_point_neg "917be49d159184fba140f4dfc5d653464e94f718fe195b226b3f715829e6e768-8dba8726b24660c96e5ea081117fe601695bac2614bcddf31723301b4ef5e152" +#define hex_point_sub "29e4a54cad98da9939b95f677784bff3b1dd9334c83d93e351e0f8f7c4ce2dc5-4473eba3b8ff990b8456c41ec0727b76cb2b0f960495b144949f70bf95643b82" +#define hex_point_mul "997fcff625adbae62566f684f9e89181713f972c5a9cd9ce6764636761ba87d1-8142a28d1bd109501452a649e2d68f012e265460e0c7d3da743fb036eb23b03b" +#define hex_point_mul_g "7cf689748f3714490d7a19eae0e7bfad0e0182498b7bcd8a6998dfd00f59be51-4e2e98d190e9d775e0caa943196bfb066d9c30818b2d768fb5299e7135830a6f" + +int test_sm9_point() { + SM9_POINT p; + SM9_POINT q; + SM9_POINT r; + SM9_POINT s; + sm9_bn_t k; + int j = 1; + uint8_t buf[65]; + + sm9_bn_from_hex(k, hex_iv); + + sm9_point_from_hex(&p, hex_point1); if (!sm9_point_is_on_curve(&p)) goto err; ++j; + sm9_point_from_hex(&q, hex_point2); if (!sm9_point_is_on_curve(&q)) goto err; ++j; + sm9_point_dbl(&r, &p); sm9_point_from_hex(&s, hex_point_dbl); if (!sm9_point_equ(&r, &s)) goto err; ++j; + sm9_point_add(&r, &p, &q); sm9_point_from_hex(&s, hex_point_add); if (!sm9_point_equ(&r, &s)) goto err; ++j; + sm9_point_neg(&r, &p); sm9_point_from_hex(&s, hex_point_neg); if (!sm9_point_equ(&r, &s)) goto err; ++j; + sm9_point_sub(&r, &p, &q); sm9_point_from_hex(&s, hex_point_sub); if (!sm9_point_equ(&r, &s)) goto err; ++j; + sm9_point_mul(&r, k, &p); sm9_point_from_hex(&s, hex_point_mul); if (!sm9_point_equ(&r, &s)) goto err; ++j; + sm9_point_mul_generator(&r, k); sm9_point_from_hex(&s, hex_point_mul_g); if (!sm9_point_equ(&r, &s)) goto err; ++j; + + sm9_point_to_uncompressed_octets(&p, buf); + sm9_point_from_uncompressed_octets(&q, buf); + if (!sm9_point_equ(&p, &q)) { + error_print(); + return -1; + } + + + + + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_tpoint1 \ + "83f6a65d85d51ec72eacf19bc38384e0369eb22a134a725a0191faa6e4f192ef\n" \ + "9a79bfd491ef1cb32d9b57f7d0590ccff6b1cfe63dd15c0823d692fafbe96dbc\n" \ + "9ed11c499291db0454d738555af0ce8a1df960056ee7425a6bf296eae60a5037\n" \ + "849d4434eb7113fc9fb3809b51d54064fa2f20503423d256bc044905b1eba3fb" +#define hex_tpoint2 \ + "a36232a9713f69157b7cdceef54aa0237b3ba0642a80dbb597af8935aea2c130\n" \ + "624b19114e49f00281e2aee1f1b9d4f0a081a135868f8bbdb7b7a7b7da5fd6bc\n" \ + "77966917ec1c5a294dd836c34691ab5e891f8c9f017443902c0a73ec54d449d8\n" \ + "1be45454b6fa085a53744b22fd398238e400c3e031c8796e59e1bd6222048af0" +#define hex_tpoint_neg \ + "83f6a65d85d51ec72eacf19bc38384e0369eb22a134a725a0191faa6e4f192ef\n" \ + "9a79bfd491ef1cb32d9b57f7d0590ccff6b1cfe63dd15c0823d692fafbe96dbc\n" \ + "176ee3b67011cbed812c72fa9a9df8bb03f93345ab93ac81797d043cfd46f546\n" \ + "31a2bbcb173292f536502ab4a3b986e027c372fae6571c85296b52223165a182" +#define hex_tpoint_dbl \ + "73cbced58a8e76ef5235b480050a74e906e4d27185bd85d7ebdcd43ad24475fd\n" \ + "58400f0eb23000d814f5b5d0706749a72909795b7b04f26d6d58b2cf478ad9c9\n" \ + "19b460e09ac9ddbb380d6441e078a47bfcaa7d4c3d60b3a6c0d05f896472dc3c\n" \ + "1d69f785f47d6f25cb901b131612c37edc5e89ee9ba2dac8c401ced40e340a39" +#define hex_tpoint_add \ + "5f443752a19e368f404b89abae20a386d2b534c424b93ededdbfd04d4c569e6b\n" \ + "a411bbd84ee92a6ee53e5ca9cb81bacc192c6ba406f6fdcb2b04d0ab9c42ae44\n" \ + "6a3dadfcaac134e8353dd3abf37d487b206ca28dfab1e0a9376649df748f1605\n" \ + "4fa25e5e6100a023d4923df385dd236749c6a7f8e68db55e0bd1e2263fc04d28" +#define hex_tpoint_sub \ + "3cbbf5fcc6c11a3579036e617bbf0b2861c53979f01e37f59fc4a10d991ccde7\n" \ + "1e9c3c99524c7867c9dbc4f52fdc938cf5aa4a980d3905cc91a5b91331235290\n" \ + "44027c5d814bab73ad93d14b564303aab153ad7355bcfbf8a8bed7cb577e7fd8\n" \ + "47a4037d1d6f6d2014aa04292fa91cf07b1f4331a85d4b66a6e048226ddfc43e" +#define hex_tpoint_mul \ + "5d704de3261290dbba39dbd14e6bc416025240fd1ed65ec982efed685ae41e8b\n" \ + "705c9ca4b5ef465c4e5db80ca4880627a6d9d6bcefd4756496baba9d5eaa3304\n" \ + "4e96eb3543aabf1e9a65cae24177b9d13b0f7fae9472145ba7ae2b14bb447aef\n" \ + "5d7ba50d7eac49a00b18fee2069afd3cc9719993fa78271e66b7a3efed46ac8b" +#define hex_tpoint_mulg \ + "920ef6fb3a2acff52aa0c004c18feca149dfd33d98086f8f402ea9e0de303c49\n" \ + "1f97dd359f2b065d63e0987f5bea2f3dc865c2cc112d7d161b46b83451716fd8\n" \ + "614881d4d05fef3173a4990465876c5200f58c5015e13354b23ae401c20c4aef\n" \ + "18a22e02b7d395a49f0646a79438e79cd37c32f163fe8923c13d56bab668e8a7" + +int test_sm9_twist_point() { + SM9_TWIST_POINT p; + SM9_TWIST_POINT q; + SM9_TWIST_POINT r; + SM9_TWIST_POINT s; + sm9_bn_t k; + int j = 1; + + sm9_bn_from_hex(k, hex_iv); + + sm9_twist_point_from_hex(&p, hex_tpoint1); if (!sm9_twist_point_is_on_curve(&p)) goto err; ++j; + sm9_twist_point_from_hex(&q, hex_tpoint2); if (!sm9_twist_point_is_on_curve(&q)) goto err; ++j; + sm9_twist_point_neg(&r, &p); sm9_twist_point_from_hex(&s, hex_tpoint_neg); if (!sm9_twist_point_equ(&r, &s)) goto err; ++j; + sm9_twist_point_dbl(&r, &p); sm9_twist_point_from_hex(&s, hex_tpoint_dbl); if (!sm9_twist_point_equ(&r, &s)) goto err; ++j; + sm9_twist_point_add(&r, &p, &q); sm9_twist_point_from_hex(&s, hex_tpoint_add); if (!sm9_twist_point_equ(&r, &s)) goto err; ++j; + sm9_twist_point_add_full(&r, &p, &q); if (!sm9_twist_point_equ(&r, &s)) goto err; ++j; + sm9_twist_point_sub(&r, &p, &q); sm9_twist_point_from_hex(&s, hex_tpoint_sub); if (!sm9_twist_point_equ(&r, &s)) goto err; ++j; + sm9_twist_point_mul(&r, k, &p); sm9_twist_point_from_hex(&s, hex_tpoint_mul); if (!sm9_twist_point_equ(&r, &s)) goto err; ++j; + sm9_twist_point_mul_generator(&r, k); sm9_twist_point_from_hex(&s, hex_tpoint_mulg); if (!sm9_twist_point_equ(&r, &s)) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_pairing1 \ + "4e378fb5561cd0668f906b731ac58fee25738edf09cadc7a29c0abc0177aea6d\n" \ + "28b3404a61908f5d6198815c99af1990c8af38655930058c28c21bb539ce0000\n" \ + "38bffe40a22d529a0c66124b2c308dac9229912656f62b4facfced408e02380f\n" \ + "a01f2c8bee81769609462c69c96aa923fd863e209d3ce26dd889b55e2e3873db\n" \ + "67e0e0c2eed7a6993dce28fe9aa2ef56834307860839677f96685f2b44d0911f\n" \ + "5a1ae172102efd95df7338dbc577c66d8d6c15e0a0158c7507228efb078f42a6\n" \ + "1604a3fcfa9783e667ce9fcb1062c2a5c6685c316dda62de0548baa6ba30038b\n" \ + "93634f44fa13af76169f3cc8fbea880adaff8475d5fd28a75deb83c44362b439\n" \ + "b3129a75d31d17194675a1bc56947920898fbf390a5bf5d931ce6cbb3340f66d\n" \ + "4c744e69c4a2e1c8ed72f796d151a17ce2325b943260fc460b9f73cb57c9014b\n" \ + "84b87422330d7936eaba1109fa5a7a7181ee16f2438b0aeb2f38fd5f7554e57a\n" \ + "aab9f06a4eeba4323a7833db202e4e35639d93fa3305af73f0f071d7d284fcfb" + +#define hex_RA \ + "7CBA5B19069EE66AA79D490413D11846B9BA76DD22567F809CF23B6D964BB265\n" \ + "A9760C99CB6F706343FED05637085864958D6C90902ABA7D405FBEDF7B781599" +#define hex_deB \ + "74CCC3AC9C383C60AF083972B96D05C75F12C8907D128A17ADAFBAB8C5A4ACF7\n" \ + "01092FF4DE89362670C21711B6DBE52DCD5F8E40C6654B3DECE573C2AB3D29B2\n" \ + "44B0294AA04290E1524FF3E3DA8CFD432BB64DE3A8040B5B88D1B5FC86A4EBC1\n" \ + "8CFC48FB4FF37F1E27727464F3C34E2153861AD08E972D1625FC1A7BD18D5539" + +#define hex_pairing2 \ + "28542FB6954C84BE6A5F2988A31CB6817BA0781966FA83D9673A9577D3C0C134\n" \ + "5E27C19FC02ED9AE37F5BB7BE9C03C2B87DE027539CCF03E6B7D36DE4AB45CD1\n" \ + "A1ABFCD30C57DB0F1A838E3A8F2BF823479C978BD137230506EA6249C891049E\n" \ + "3497477913AB89F5E2960F382B1B5C8EE09DE0FA498BA95C4409D630D343DA40\n" \ + "4FEC93472DA33A4DB6599095C0CF895E3A7B993EE5E4EBE3B9AB7D7D5FF2A3D1\n" \ + "647BA154C3E8E185DFC33657C1F128D480F3F7E3F16801208029E19434C733BB\n" \ + "73F21693C66FC23724DB26380C526223C705DAF6BA18B763A68623C86A632B05\n" \ + "0F63A071A6D62EA45B59A1942DFF5335D1A232C9C5664FAD5D6AF54C11418B0D\n" \ + "8C8E9D8D905780D50E779067F2C4B1C8F83A8B59D735BB52AF35F56730BDE5AC\n" \ + "861CCD9978617267CE4AD9789F77739E62F2E57B48C2FF26D2E90A79A1D86B93\n" \ + "9B1CA08F64712E33AEDA3F44BD6CB633E0F722211E344D73EC9BBEBC92142765\n" \ + "6BA584CE742A2A3AB41C15D3EF94EDEB8EF74A2BDCDAAECC09ABA567981F6437" + + +#define hex_Ppube \ + "9174542668E8F14AB273C0945C3690C66E5DD09678B86F734C4350567ED06283\n" \ + "54E598C6BF749A3DACC9FFFEDD9DB6866C50457CFC7AA2A4AD65C3168FF74210" +#define rB "00018B98C44BEF9F8537FB7D071B2C928B3BC65BD3D69E1EEE213564905634FE" +#define hex_pairing3 \ + "1052D6E9D13E381909DFF7B2B41E13C987D0A9068423B769480DACCE6A06F492\n" \ + "5FFEB92AD870F97DC0893114DA22A44DBC9E7A8B6CA31A0CF0467265A1FB48C7\n" \ + "2C5C3B37E4F2FF83DB33D98C0317BCBBBBF4AC6DF6B89ECA58268B280045E612\n" \ + "6CED9E2D7C9CD3D5AD630DEFAB0B831506218037EE0F861CF9B43C78434AEC38\n" \ + "0AE7BF3E1AEC0CB67A03440906C7DFB3BCD4B6EEEBB7E371F0094AD4A816088D\n" \ + "98DBC791D0671CACA12236CDF8F39E15AEB96FAEB39606D5B04AC581746A663D\n" \ + "00DD2B7416BAA91172E89D5309D834F78C1E31B4483BB97185931BAD7BE1B9B5\n" \ + "7EBAC0349F8544469E60C32F6075FB0468A68147FF013537DF792FFCE024F857\n" \ + "10CC2B561A62B62DA36AEFD60850714F49170FD94A0010C6D4B651B64F3A3A5E\n" \ + "58C9687BEDDCD9E4FEDAB16B884D1FE6DFA117B2AB821F74E0BF7ACDA2269859\n" \ + "2A430968F16086061904CE201847934B11CA0F9E9528F5A9D0CE8F015C9AEA79\n" \ + "934FDDA6D3AB48C8571CE2354B79742AA498CB8CDDE6BD1FA5946345A1A652F6" + + +int test_sm9_pairing() +{ + const SM9_POINT _P1 = { + {0x7c66dddd, 0xe8c4e481, 0x09dc3280, 0xe1e40869, 0x487d01d6, 0xf5ed0704, 0x62bf718f, 0x93de051d}, + {0x0a3ea616, 0x0c464cd7, 0xfa602435, 0x1c1c00cb, 0x5c395bbc, 0x63106512, 0x4f21e607, 0x21fe8dda}, + {1,0,0,0,0,0,0,0} + }; + const SM9_POINT *P1 = &_P1; + + const SM9_TWIST_POINT _P2 = { + {{0xAF82D65B, 0xF9B7213B, 0xD19C17AB, 0xEE265948, 0xD34EC120, 0xD2AAB97F, 0x92130B08, 0x37227552}, + {0xD8806141, 0x54806C11, 0x0F5E93C4, 0xF1DD2C19, 0xB441A01F, 0x597B6027, 0x78640C98, 0x85AEF3D0}}, + {{0xC999A7C7, 0x6215BBA5, 0xA71A0811, 0x47EFBA98, 0x3D278FF2, 0x5F317015, 0x19BE3DA6, 0xA7CF28D5}, + {0x84EBEB96, 0x856DC76B, 0xA347C8BD, 0x0736A96F, 0x2CBEE6ED, 0x66BA0D26, 0x2E845C12, 0x17509B09}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, + }; + const SM9_TWIST_POINT *P2 = &_P2; + + const SM9_TWIST_POINT _Ppubs = { + {{0x96EA5E32, 0x8F14D656, 0x386A92DD, 0x414D2177, 0x24A3B573, 0x6CE843ED, 0x152D1F78, 0x29DBA116}, + {0x1B94C408, 0x0AB1B679, 0x5E392CFB, 0x1CE0711C, 0x41B56501, 0xE48AFF4B, 0x3084F733, 0x9F64080B}}, + {{0xB4E3216D, 0x0E75C05F, 0x5CDFF073, 0x1006E85F, 0xB7A46F74, 0x1A7CE027, 0xDDA532DA, 0x41E00A53}, + {0xD0EF1C25, 0xE89E1408, 0x1A77F335, 0xAD3E2FDB, 0x47E3A0CB, 0xB57329F4, 0xABEA0112, 0x69850938}}, + {{1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}}, + }; + const SM9_TWIST_POINT *Ppubs = &_Ppubs; + + SM9_TWIST_POINT p; + SM9_POINT q; + sm9_fp12_t r; + sm9_fp12_t s; + sm9_bn_t k; + int j = 1; + + sm9_pairing(r, Ppubs, P1); sm9_fp12_from_hex(s, hex_pairing1); if (!sm9_fp12_equ(r, s)) goto err; ++j; + + sm9_twist_point_from_hex(&p, hex_deB); sm9_point_from_hex(&q, hex_RA); + sm9_pairing(r, &p, &q); sm9_fp12_from_hex(s, hex_pairing2); if (!sm9_fp12_equ(r, s)) goto err; ++j; + + sm9_bn_from_hex(k, rB); sm9_point_from_hex(&q, hex_Ppube); + sm9_pairing(r, P2, &q); sm9_fp12_pow(r, r, k); sm9_fp12_from_hex(s, hex_pairing3); if (!sm9_fp12_equ(r, s)) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_ks "000130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4" +#define hex_ds "A5702F05CF1315305E2D6EB64B0DEB923DB1A0BCF0CAFF90523AC8754AA69820-78559A844411F9825C109F5EE3F52D720DD01785392A727BB1556952B2B013D3" + +int test_sm9_sign() { + SM9_SIGN_CTX ctx; + SM9_SIGN_KEY key; + SM9_SIGN_MASTER_KEY mpk; + SM9_POINT ds; + uint8_t sig[1000] = {0}; + size_t siglen = 0; + int j = 1; + + uint8_t data[20] = {0x43, 0x68, 0x69, 0x6E, 0x65, 0x73, 0x65, 0x20, 0x49, 0x42, 0x53, 0x20, 0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64}; + uint8_t IDA[5] = {0x41, 0x6C, 0x69, 0x63, 0x65}; + + sm9_bn_from_hex(mpk.ks, hex_ks); sm9_twist_point_mul_generator(&(mpk.Ppubs), mpk.ks); + if (sm9_sign_master_key_extract_key(&mpk, (char *)IDA, sizeof(IDA), &key) < 0) goto err; ++j; + sm9_point_from_hex(&ds, hex_ds); if (!sm9_point_equ(&(key.ds), &ds)) goto err; ++j; + + sm9_sign_init(&ctx); + sm9_sign_update(&ctx, data, sizeof(data)); + if (sm9_sign_finish(&ctx, &key, sig, &siglen) < 0) goto err; ++j; + + sm9_verify_init(&ctx); + sm9_verify_update(&ctx, data, sizeof(data)); + if (sm9_verify_finish(&ctx, sig, siglen, &mpk, (char *)IDA, sizeof(IDA)) != 1) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +#define hex_ke "0001EDEE3778F441F8DEA3D9FA0ACC4E07EE36C93F9A08618AF4AD85CEDE1C22" + +#define hex_de \ + "94736ACD2C8C8796CC4785E938301A139A059D3537B6414140B2D31EECF41683\n" \ + "115BAE85F5D8BC6C3DBD9E5342979ACCCF3C2F4F28420B1CB4F8C0B59A19B158\n" \ + "7AA5E47570DA7600CD760A0CF7BEAF71C447F3844753FE74FA7BA92CA7D3B55F\n" \ + "27538A62E7F7BFB51DCE08704796D94C9D56734F119EA44732B50E31CDEB75C1" + +int test_sm9_ciphertext() +{ + const SM9_POINT _P1 = { + {0x7c66dddd, 0xe8c4e481, 0x09dc3280, 0xe1e40869, 0x487d01d6, 0xf5ed0704, 0x62bf718f, 0x93de051d}, + {0x0a3ea616, 0x0c464cd7, 0xfa602435, 0x1c1c00cb, 0x5c395bbc, 0x63106512, 0x4f21e607, 0x21fe8dda}, + {1,0,0,0,0,0,0,0} + }; + const SM9_POINT *P1 = &_P1; + + SM9_POINT C1; + uint8_t c2[SM9_MAX_PLAINTEXT_SIZE]; + uint8_t c3[SM3_HMAC_SIZE]; + uint8_t buf[1024]; + uint8_t *p = buf; + size_t len = 0; + + sm9_point_copy(&C1, P1); + if (sm9_ciphertext_to_der(&C1, c2, sizeof(c2), c3, &p, &len) != 1) { + error_print(); + return -1; + } + //printf("SM9_MAX_CIPHERTEXT_SIZE %zu\n", len); + return 1; +} + + +int test_sm9_encrypt() { + SM9_ENC_MASTER_KEY msk; + SM9_ENC_KEY key; + SM9_TWIST_POINT de; + uint8_t out[1000] = {0}; + size_t outlen = 0; + int j = 1; + + uint8_t data[20] = {0x43, 0x68, 0x69, 0x6E, 0x65, 0x73, 0x65, 0x20, 0x49, 0x42, 0x53, 0x20, 0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64}; + uint8_t dec[20] = {0}; + size_t declen = 20; + uint8_t IDB[3] = {0x42, 0x6F, 0x62}; + + sm9_bn_from_hex(msk.ke, hex_ke); + sm9_point_mul_generator(&(msk.Ppube), msk.ke); + + if (sm9_enc_master_key_extract_key(&msk, (char *)IDB, sizeof(IDB), &key) < 0) goto err; ++j; + + + sm9_twist_point_from_hex(&de, hex_de); if (!sm9_twist_point_equ(&(key.de), &de)) goto err; ++j; + + if (sm9_encrypt(&msk, (char *)IDB, sizeof(IDB), data, sizeof(data), out, &outlen) < 0) goto err; ++j; + if (sm9_decrypt(&key, (char *)IDB, sizeof(IDB), out, outlen, dec, &declen) < 0) goto err; ++j; + if (memcmp(data, dec, sizeof(data)) != 0) goto err; ++j; + + printf("%s() ok\n", __FUNCTION__); + return 1; +err: + printf("%s test %d failed\n", __FUNCTION__, j); + error_print(); + return -1; +} + +int main(void) { + if (test_sm9_fp() != 1) goto err; + if (test_sm9_fn() != 1) goto err; + if (test_sm9_fp2() != 1) goto err; + if (test_sm9_fp4() != 1) goto err; + if (test_sm9_fp12() != 1) goto err; + if (test_sm9_point() != 1) goto err; + if (test_sm9_twist_point() != 1) goto err; + if (test_sm9_pairing() != 1) goto err; + if (test_sm9_sign() != 1) goto err; + if (test_sm9_ciphertext() != 1) goto err; + if (test_sm9_encrypt() != 1) goto err; + + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/tls13test.c b/Core/GmSSL-3.1.1/tests/tls13test.c new file mode 100644 index 0000000..82b4f39 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/tls13test.c @@ -0,0 +1,81 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_tls13_gcm(void) +{ + + BLOCK_CIPHER_KEY block_key; + uint8_t key[16]; + uint8_t iv[12]; + uint8_t seq_num[8] = {0,0,0,0,0,0,0,1}; + int record_type = TLS_record_handshake; + uint8_t in[40]; + size_t padding_len = 8; + uint8_t out[256]; + size_t outlen; + uint8_t buf[256]; + size_t buflen; + + rand_bytes(key, sizeof(key)); + rand_bytes(iv, sizeof(iv)); + rand_bytes(in, sizeof(in)); + + memset(out, 1, sizeof(out)); + outlen = 0; + memset(buf, 1, sizeof(buf)); + buflen = 0; + + if (block_cipher_set_encrypt_key(&block_key, BLOCK_CIPHER_sm4(), key) != 1) { + error_print(); + return -1; + } + + if (tls13_gcm_encrypt(&block_key, iv, seq_num, record_type, in, sizeof(in), padding_len, out, &outlen) != 1) { + error_print(); + return -1; + } + if (tls13_gcm_decrypt(&block_key, iv, seq_num, out, outlen, &record_type, buf, &buflen) != 1) { + error_print(); + return -1; + } + + if (buflen != sizeof(in)) { + error_print(); + return -1; + } + if (memcmp(in, buf, buflen) != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_tls13_gcm() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/tlstest.c b/Core/GmSSL-3.1.1/tests/tlstest.c new file mode 100644 index 0000000..a374ae5 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/tlstest.c @@ -0,0 +1,345 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_tls_encode(void) +{ + uint8_t a1 = 200; + uint16_t a2 = 30000; + uint24_t a3 = 4000000; + uint32_t a4 = 4000000000; + uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8}; + + uint8_t r1; + uint16_t r2; + uint24_t r3; + uint32_t r4; + const uint8_t *pdata; + size_t datalen; + + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + tls_uint8_to_bytes(a1, &p, &len); + tls_uint16_to_bytes(a2, &p, &len); + tls_uint24_to_bytes(a3, &p, &len); + tls_uint32_to_bytes(a4, &p, &len); + tls_uint8array_to_bytes(data, 5, &p, &len); + tls_uint16array_to_bytes(data, 6, &p, &len); + tls_uint24array_to_bytes(data, 7, &p, &len); + + if (tls_uint8_from_bytes(&r1, &cp, &len) != 1 || r1 != a1 + || tls_uint16_from_bytes(&r2, &cp, &len) != 1 || r2 != a2 + || tls_uint24_from_bytes(&r3, &cp, &len) != 1 || r3 != a3 + || tls_uint32_from_bytes(&r4, &cp, &len) != 1 || r4 != a4 + || tls_uint8array_from_bytes(&pdata, &datalen, &cp, &len) != 1 || datalen != 5 || memcmp(pdata, data, 5) != 0 + || tls_uint16array_from_bytes(&pdata, &datalen, &cp, &len) != 1 || datalen != 6 || memcmp(pdata, data, 6) != 0 + || tls_uint24array_from_bytes(&pdata, &datalen, &cp, &len) != 1 || datalen != 7 || memcmp(pdata, data, 7) != 0 + || len > 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_cbc(void) +{ + uint8_t key[32] = {0}; + SM3_HMAC_CTX hmac_ctx; + SM4_KEY sm4_key; + uint8_t seq_num[8] = { 0,0,0,0,0,0,0,1 }; + uint8_t header[5]; + uint8_t in[] = "hello world"; + uint8_t out[256]; + uint8_t buf[256] = {0}; + size_t len; + size_t buflen; + + header[0] = TLS_record_handshake; + header[1] = TLS_protocol_tls12 >> 8; + header[2] = TLS_protocol_tls12 & 0xff; + header[3] = sizeof(in) >> 8; + header[4] = sizeof(in) & 0xff; + + sm3_hmac_init(&hmac_ctx, key, 32); + sm4_set_encrypt_key(&sm4_key, key); + tls_cbc_encrypt(&hmac_ctx, &sm4_key, seq_num, header, in, sizeof(in), out, &len); + + sm3_hmac_init(&hmac_ctx, key, 32); + sm4_set_decrypt_key(&sm4_key, key); + + tls_cbc_decrypt(&hmac_ctx, &sm4_key, seq_num, header, out, len, buf, &buflen); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_random(void) +{ + uint8_t random[32]; + tls_random_generate(random); + tls_random_print(stdout, random, 0, 0); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_client_hello(void) +{ + uint8_t record[512]; + size_t recordlen = 0; + + int version = TLS_protocol_tlcp; + uint8_t random[32]; + int cipher_suites[] = { + TLS_cipher_ecc_sm4_cbc_sm3, + TLS_cipher_ecc_sm4_gcm_sm3, + TLS_cipher_ecdhe_sm4_cbc_sm3, + TLS_cipher_ecdhe_sm4_gcm_sm3, + TLS_cipher_ibsdh_sm4_cbc_sm3, + TLS_cipher_ibsdh_sm4_gcm_sm3, + TLS_cipher_ibc_sm4_cbc_sm3, + TLS_cipher_ibc_sm4_gcm_sm3, + TLS_cipher_rsa_sm4_cbc_sm3, + TLS_cipher_rsa_sm4_gcm_sm3, + TLS_cipher_rsa_sm4_cbc_sha256, + TLS_cipher_rsa_sm4_gcm_sha256, + }; + int comp_meths[] = {0}; + + tls_record_set_protocol(record, TLS_protocol_tlcp); + if (tls_record_set_handshake_client_hello(record, &recordlen, + version, + random, + NULL, 0, + cipher_suites, sizeof(cipher_suites)/sizeof(cipher_suites[0]), + NULL, 0) != 1) { + error_print(); + return -1; + } + tls_client_hello_print(stdout, record + 5 + 4, recordlen - 5 -4, 0, 4); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_server_hello(void) +{ + uint8_t record[512]; + size_t recordlen = 0; + + uint8_t random[32]; + uint16_t cipher_suite = TLS_cipher_ecdhe_sm4_cbc_sm3; + + + tls_record_set_protocol(record, TLS_protocol_tlcp); + if (tls_record_set_handshake_server_hello(record, &recordlen, + TLS_protocol_tlcp, + random, + NULL, 0, + cipher_suite, + NULL, 0) != 1) { + error_print(); + return -1; + } + tls_server_hello_print(stdout, record + 5 + 4, recordlen - 5 -4, 0, 0); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_certificate(void) +{ + size_t recordlen = 0; + FILE *fp = NULL; + + // 测试函数不要有外部的依赖 + // TODO: 输出一些握手过程的record字节数组和handshake字节数组,作为后续测试的测试数据 + + /* + if (!(fp = fopen("cacert.pem", "r"))) { + error_print(); + return -1; + } + if (tls_record_set_handshake_certificate_from_pem(record, &recordlen, fp) != 1) { + error_print(); + return -1; + } + tls_certificate_print(stdout, record + 9, recordlen - 9, 0, 0); + */ + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_server_key_exchange(void) +{ + uint8_t record[1024]; + size_t recordlen = 0; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE] = {0xAA, 0xBB}; + const uint8_t *psig; + size_t siglen; + + tls_record_set_protocol(record, TLS_protocol_tlcp); + if (tlcp_record_set_handshake_server_key_exchange_pke(record, &recordlen, sig, sizeof(sig)) != 1) { + error_print(); + return -1; + } + if (tlcp_record_get_handshake_server_key_exchange_pke(record, &psig, &siglen) != 1) { + error_print(); + return -1; + } + format_bytes(stdout, 0, 0, "server_key_exchange siganture", psig, siglen); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_certificate_verify(void) +{ + uint8_t record[1024]; + size_t recordlen = 0; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + const uint8_t *psig; + size_t siglen; + + tls_record_set_protocol(record, TLS_protocol_tls12); + if (tls_record_set_handshake_certificate_verify(record, &recordlen, sig, sizeof(sig)) != 1) { + error_print(); + return -1; + } + if (tls_record_get_handshake_certificate_verify(record, &psig, &siglen) != 1) { + error_print(); + return -1; + } + tls_certificate_verify_print(stdout, psig, siglen, 0, 0); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_finished(void) +{ + uint8_t record[1024]; + size_t recordlen = 0; + uint8_t verify_data[12]; + const uint8_t *verify_data_ptr; + size_t verify_data_len; + + if (tls_record_set_handshake_finished(record, &recordlen, verify_data, sizeof(verify_data)) != 1) { + error_print(); + return -1; + } + if (tls_record_get_handshake_finished(record, &verify_data_ptr, &verify_data_len) != 1) { + error_print(); + return -1; + } + tls_finished_print(stdout, verify_data_ptr, verify_data_len, 0, 0); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_alert(void) +{ + uint8_t record[1024]; + size_t recordlen = 0; + int level; + int reason; + + if (tls_record_set_alert(record, &recordlen, TLS_alert_level_fatal, TLS_alert_close_notify) != 1) { + error_print(); + return -1; + } + if (tls_record_get_alert(record, &level, &reason) != 1) { + error_print(); + return -1; + } + tls_alert_print(stdout, record + 5, recordlen - 5, 0, 0); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_change_cipher_spec(void) +{ + uint8_t record[1024]; + size_t recordlen = 0; + + if (tls_record_set_change_cipher_spec(record, &recordlen) != 1) { + error_print(); + return -1; + } + if (tls_record_get_change_cipher_spec(record) != 1) { + error_print(); + return -1; + } + tls_change_cipher_spec_print(stdout, record + 5, recordlen - 5, 0, 0); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_tls_application_data(void) +{ + uint8_t record[1024]; + size_t recordlen = 0; + uint8_t data[88]; + const uint8_t *p; + size_t len; + + if (tls_record_set_application_data(record, &recordlen, data, sizeof(data)) != 1) { + error_print(); + return -1; + } + if (tls_record_get_application_data(record, &p, &len) != 1) { + error_print(); + return -1; + } + tls_application_data_print(stdout, p, len, 0, 0); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_tls_encode() != 1) goto err; + if (test_tls_cbc() != 1) goto err; + if (test_tls_random() != 1) goto err; + if (test_tls_client_hello() != 1) goto err; + if (test_tls_server_hello() != 1) goto err; + if (test_tls_certificate() != 1) goto err; + if (test_tls_server_key_exchange() != 1) goto err; + if (test_tls_certificate_verify() != 1) goto err; + //if (test_tls_finished() != 1) goto err; //FIXME + if (test_tls_alert() != 1) goto err; + if (test_tls_change_cipher_spec() != 1) goto err; + if (test_tls_application_data() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return -1; +} diff --git a/Core/GmSSL-3.1.1/tests/x509_algtest.c b/Core/GmSSL-3.1.1/tests/x509_algtest.c new file mode 100644 index 0000000..be71cad --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/x509_algtest.c @@ -0,0 +1,198 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_x509_digest_algor(void) +{ + char *names[] = { + "sm3", + "md5", + "sha1", + "sha224", + "sha256", + "sha384", + "sha512", + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int oid; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_digest_algor_from_name(names[i]); + if (x509_digest_algor_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_digest_algor_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + if (oid != x509_digest_algor_from_name(names[i])) { + error_print(); + return 1; + } + format_print(stderr, 0, 4, "%s\n", x509_digest_algor_name(oid)); + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_encryption_algor(void) +{ + char *names[] = { + "sm4-cbc", + "aes128-cbc", + "aes192-cbc", + "aes256-cbc", + }; + uint8_t iv[16] = {0}; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int oid; + const uint8_t *params; + size_t paramslen; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_encryption_algor_from_name(names[i]); + if (x509_encryption_algor_to_der(oid, iv, sizeof(iv), &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_encryption_algor_from_der(&oid, ¶ms, ¶mslen, &cp, &len) != 1 + || asn1_check(params != NULL) != 1 + || asn1_check(paramslen == sizeof(iv)) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_encryption_algor_name(oid)); + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_signature_algor(void) +{ + char *names[] = { + "sm2sign-with-sm3", + "rsasign-with-sm3", + "ecdsa-with-sha1", + "ecdsa-with-sha224", + "ecdsa-with-sha256", + "ecdsa-with-sha384", + "ecdsa-with-sha512", + "sha1WithRSAEncryption", + "sha224WithRSAEncryption", + "sha256WithRSAEncryption", + "sha384WithRSAEncryption", + "sha512WithRSAEncryption", + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int oid; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_signature_algor_from_name(names[i]); + if (x509_signature_algor_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_signature_algor_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_signature_algor_name(oid)); + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_public_key_encryption_algor(void) +{ + char *names[] = { + "sm2encrypt", + // "rsaesOAEP", + // "rsaEncryption", + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int oid; + const uint8_t *params; + size_t paramslen; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_public_key_encryption_algor_from_name(names[i]); + if (x509_public_key_encryption_algor_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_public_key_encryption_algor_from_der(&oid, ¶ms, ¶mslen, &cp, &len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_public_key_encryption_algor_name(oid)); + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_x509_digest_algor() != 1) goto err; + if (test_x509_encryption_algor() != 1) goto err; + if (test_x509_signature_algor() != 1) goto err; + if (test_x509_public_key_encryption_algor() != 1) goto err; + printf("%s all tests passed!\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/x509_crltest.c b/Core/GmSSL-3.1.1/tests/x509_crltest.c new file mode 100644 index 0000000..217b2fb --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/x509_crltest.c @@ -0,0 +1,462 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_x509_crl_reason(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int reason; + int i; + + for (i = 0; i < 11; i++) { + if (x509_crl_reason_to_der(i, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < 11; i++) { + if (x509_crl_reason_from_der(&reason, &cp, &len) != 1 + || asn1_check(reason == i) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s (%d)\n", x509_crl_reason_name(reason), reason); + } + (void)asn1_length_is_zero(len); + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_crl_entry_ext(void) +{ + int exts[] = { + OID_ce_crl_reasons, + OID_ce_invalidity_date, + OID_ce_certificate_issuer, + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int oid; + int i; + + for (i = 0; i < sizeof(exts)/sizeof(exts[0]); i++) { + if (x509_crl_entry_ext_id_to_der(exts[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(exts)/sizeof(exts[0]); i++) { + if (x509_crl_entry_ext_id_from_der(&oid, &cp, &len) != 1 + || asn1_check(oid == exts[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_crl_entry_ext_id_name(oid)); + } + (void)asn1_length_is_zero(len); + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_vector_gen_uri_as_general_names(void) +{ + const char *uri = "http://www.example.com/path"; + uint8_t buf[256]; + uint8_t *p; + const uint8_t *cp; + size_t len; + const uint8_t *d; + size_t dlen; + size_t i; + + cp = p = buf; len = 0; + if (x509_uri_as_general_names_to_der(uri, strlen(uri), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + printf("// generated by %s()\n", __FUNCTION__); + printf("const uint8_t cert_issuer[] = {\n\t"); + for (i = 0; i < dlen; i++) { + printf("0x%02x,", d[i]); + if ((i + 1) % 8 == 0) printf("\n\t"); + } + printf("\n};\n"); + return 1; +} + + +static int test_x509_crl_entry_exts(void) +{ + // generated by test_vector_gen_uri_as_general_names() + const uint8_t cert_issuer[] = { + 0x86,0x1b,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x77,0x77,0x77,0x2e,0x65,0x78,0x61, + 0x6d,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d, + 0x2f,0x70,0x61,0x74,0x68, + }; + struct { + int reason; + time_t invalid_date; + const uint8_t *cert_issuer; + size_t cert_issuer_len; + } tests[] = { + { X509_cr_key_compromise, -1, NULL, 0 }, + { -1, time(NULL), NULL, 0 }, + { -1, -1, cert_issuer, sizeof(cert_issuer) }, + { X509_cr_key_compromise, time(NULL), NULL, 0 }, + { X509_cr_key_compromise, time(NULL), cert_issuer, sizeof(cert_issuer) }, + }; + + uint8_t buf[1024]; + uint8_t *p; + const uint8_t *cp; + size_t len; + size_t i; + + int reason; + time_t invalid_date; + const uint8_t *issuer; + size_t issuer_len; + + cp = p = buf; len = 0; + if (x509_crl_entry_exts_to_der(-1, -1, NULL, 0, &p, &len) != 0) { + error_print(); + return -1; + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_crl_entry_exts_to_der( + tests[i].reason, + tests[i].invalid_date, + tests[i].cert_issuer, + tests[i].cert_issuer_len, &p, &len) != 1) { + error_print(); + return -1; + } + //printf("%s %d: test %zu passed\n", __FILE__, __LINE__, i); + if (len > sizeof(buf)) { + error_print(); + return -1; + } + } + + { + size_t left = len; + const uint8_t *d; + size_t dlen; + cp = buf; + while (left) { + if (asn1_sequence_from_der(&d, &dlen, &cp, &left) != 1) { + error_print(); + return -1; + } + x509_crl_entry_exts_print(stderr, 0, 0, "CRLEntryExtensions", d, dlen); + + if (x509_crl_entry_exts_check(d, dlen) != 1) { + error_print(); + return -1; + } + } + } + + cp = p = buf; + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_crl_entry_exts_from_der(&reason, &invalid_date, &issuer, &issuer_len, &cp, &len) != 1) { + error_print(); + return -1; + } + if (reason != tests[i].reason) { + error_print(); + return -1; + } + if (invalid_date != tests[i].invalid_date) { + error_print(); + return -1; + } + if (issuer_len != tests[i].cert_issuer_len || memcmp(issuer, tests[i].cert_issuer, issuer_len) != 0) { + error_print(); + return -1; + } + //printf("%s %d: test %zu passed\n", __FILE__, __LINE__, i); + } + if (len != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_revoked_cert(void) +{ + uint8_t serial_buf[16] = { 0x01,0x02,0x00 }; + time_t revoke_date = time(NULL); + int reason = X509_cr_key_compromise; + time_t invalid_date = revoke_date; + // generated by test_vector_gen_uri_as_general_names() + const uint8_t cert_issuer_buf[] = { + 0x86,0x1b,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x77,0x77,0x77,0x2e,0x65,0x78,0x61, + 0x6d,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d, + 0x2f,0x70,0x61,0x74,0x68, + }; + const uint8_t *serial; + size_t serial_len; + const uint8_t *cert_issuer; + size_t cert_issuer_len; + + uint8_t buf[512]; + uint8_t *p; + const uint8_t *cp; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + cp = p = buf; len = 0; + if (x509_revoked_cert_to_der_ex(serial_buf, sizeof(serial_buf), revoke_date, + reason, invalid_date, cert_issuer_buf, sizeof(cert_issuer_buf), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_revoked_cert_print(stderr, 0, 0, "RevokedCertificate", d, dlen); + + cp = p = buf; len = 0; + if (x509_revoked_cert_to_der_ex(serial_buf, sizeof(serial_buf), revoke_date, + reason, invalid_date, cert_issuer_buf, sizeof(cert_issuer_buf), &p, &len) != 1 + || x509_revoked_cert_from_der_ex(&serial, &serial_len, &revoke_date, + &reason, &invalid_date, &cert_issuer, &cert_issuer_len, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_crl_ext_id(void) +{ + int crl_ext_oids[] = { + OID_ce_authority_key_identifier, + OID_ce_issuer_alt_name, + OID_ce_crl_number, + OID_ce_delta_crl_indicator, + OID_ce_issuing_distribution_point, + OID_ce_freshest_crl, + OID_pe_authority_info_access, + }; + int oid; + + uint8_t buf[512]; + uint8_t *p; + const uint8_t *cp; + size_t len; + size_t i; + + cp = p = buf; len = 0; + for (i = 0; i < sizeof(crl_ext_oids)/sizeof(crl_ext_oids[0]); i++) { + if (x509_crl_ext_id_to_der(crl_ext_oids[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 0, "", buf, len); + } + for (i = 0; i < sizeof(crl_ext_oids)/sizeof(crl_ext_oids[0]); i++) { + if (x509_crl_ext_id_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + printf(" %s\n", x509_crl_ext_id_name(oid)); + } + if (len) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_issuing_distribution_point(void) +{ + char *dist_point_uri = "http://www.example.com/crl.crl"; + int reason_flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE; + + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + if (x509_issuing_distribution_point_to_der( + dist_point_uri, strlen(dist_point_uri), + ASN1_TRUE, + ASN1_TRUE, + reason_flags, + ASN1_TRUE, + ASN1_TRUE, &p, &len) != 1) { + error_print(); + return -1; + } + if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_issuing_distribution_point_print(stderr, 0, 0, "IssuingDistributionPoint", d, dlen); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_issuing_distribution_point_from_der(void) +{ + char *uri = "http://www.example.com/crl.crl"; + int flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE; + + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + int dist_point_choice; + const uint8_t *dist_point; + size_t dist_point_len; + int only_contains_user_certs; + int only_contains_ca_certs; + int only_some_reasons; + int indirect_crl; + int only_contains_attr_certs; + + if (x509_issuing_distribution_point_to_der( + uri, strlen(uri), + ASN1_TRUE, + ASN1_FALSE, + flags, + -1, + ASN1_FALSE, &p, &len) != 1) { + error_print(); + return -1; + } + if (x509_issuing_distribution_point_from_der( + &dist_point_choice, &dist_point, &dist_point_len, + &only_contains_user_certs, + &only_contains_ca_certs, + &only_some_reasons, + &indirect_crl, + &only_contains_attr_certs, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_crl_exts(void) +{ + uint8_t exts[1024]; + size_t extslen = 0; + uint8_t key_id[32]; + uint8_t issuer[128]; + size_t issuer_len = 0; + uint8_t serial[20]; + char *http_uri = "http://www.example.com/crl.crl"; + char *ldap_uri = "ldap://www.example.com/ldap"; + char *ca_issuers_uri = "http://www.example.com/ca.crt"; + char *ocsp_uri = "http://www.example.com/ocsp"; + char *dist_point_uri = "http://www.example.com/crl.crl"; + int reason_flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE; + + if (rand_bytes(key_id, sizeof(key_id)) != 1 + || x509_general_names_add_uniform_resource_identifier(issuer, &issuer_len, sizeof(issuer), "http://www.example.com") != 1 + || rand_bytes(serial, sizeof(serial)) != 1) { + error_print(); + return -1; + } + + if (x509_crl_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts), + -1, key_id, sizeof(key_id), issuer, issuer_len, serial, sizeof(serial)) != 1 + || x509_crl_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts), + X509_non_critical, issuer, issuer_len) != 1 + || x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts), + X509_non_critical, 112) != 1 + || x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts), + X509_critical, 113) != 1 + || x509_crl_exts_add_issuing_distribution_point(exts, &extslen, sizeof(exts), + X509_critical, dist_point_uri, strlen(dist_point_uri), + ASN1_FALSE, ASN1_FALSE, reason_flags, ASN1_FALSE, ASN1_FALSE) != 1 + || x509_crl_exts_add_freshest_crl(exts, &extslen, sizeof(exts), + X509_non_critical, http_uri, strlen(http_uri), ldap_uri, strlen(ldap_uri)) != 1 + || x509_crl_exts_add_authority_info_acess(exts, &extslen, sizeof(exts), + X509_non_critical, ca_issuers_uri, strlen(ca_issuers_uri), ocsp_uri, strlen(ocsp_uri)) != 1 + ) { + error_print(); + return -1; + } + + x509_crl_exts_print(stderr, 0, 0, "CRLExtensions", exts, extslen); + + return 1; +} + +static int test_x509_cert_revoke(void) +{ + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +/* + http://mscrl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl + http://crl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl + http://crl3.digicert.com/Omniroot2025.crl +*/ + +int main(void) +{ + if (test_x509_crl_reason() != 1) goto err; + if (test_x509_crl_entry_ext() != 1) goto err; + if (test_x509_crl_entry_exts() != 1) goto err; + if (test_x509_revoked_cert() != 1) goto err; + if (test_vector_gen_uri_as_general_names() != 1) goto err; + if (test_x509_crl_ext_id() != 1) goto err; + if (test_x509_issuing_distribution_point() != 1) goto err; + if (test_x509_issuing_distribution_point_from_der() != 1) goto err; + if (test_x509_crl_exts() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/x509_exttest.c b/Core/GmSSL-3.1.1/tests/x509_exttest.c new file mode 100644 index 0000000..1b2ca6c --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/x509_exttest.c @@ -0,0 +1,885 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define cnt(nodes) (sizeof(nodes)/sizeof(int)) + +static int test_x509_other_name(void) +{ + const uint32_t oid[] = { 1,3,5 }; + const uint8_t value[] = { 0x30,0x01,0x00 }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *val; + size_t vlen; + + if (x509_other_name_to_der(oid, sizeof(oid)/sizeof(int), value, sizeof(value), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_other_name_print(stderr, 0, 0, "OtherName", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_other_name_to_der(oid, sizeof(oid)/sizeof(int), value, sizeof(value), &p, &len) != 1 + || x509_other_name_from_der(nodes, &nodes_cnt, &val, &vlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + asn1_object_identifier_print(stderr, 0, 4, "type-id", NULL, nodes, nodes_cnt); + format_bytes(stderr, 0, 4, "value", val, vlen); + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_edi_party_name(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int assigner_tag; + const uint8_t *assigner; + size_t assigner_len; + int party_name_tag; + const uint8_t *party_name; + size_t party_name_len; + + if (x509_edi_party_name_to_der( + ASN1_TAG_PrintableString, (uint8_t *)"Hello", 5, + ASN1_TAG_PrintableString, (uint8_t *)"World", 5, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_edi_party_name_print(stderr, 0, 0, "EDIPartyName", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_edi_party_name_to_der( + ASN1_TAG_PrintableString, (uint8_t *)"Hello", 5, + ASN1_TAG_PrintableString, (uint8_t *)"World", 5, + &p, &len) != 1 + || x509_edi_party_name_from_der( + &assigner_tag, &assigner, &assigner_len, + &party_name_tag, &party_name, &party_name_len, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_directory_name_print(stderr, 0, 4, "nameAssigner", assigner_tag, assigner, assigner_len); + x509_directory_name_print(stderr, 0, 4, "partyName", party_name_tag, party_name, party_name_len); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_general_name(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + uint8_t gns[512]; + size_t gnslen; + uint32_t other_id[] = { 1,3,5,7 }; + uint8_t value[] = { ASN1_TAG_OCTET_STRING, 0x02, 0x05, 0x05 }; + uint8_t x400[] = { ASN1_TAG_SEQUENCE, 0x00 }; + uint8_t name[512]; + size_t namelen; + uint32_t reg_id[] = { 2,4,6,8 }; + + if (x509_name_set(name, &namelen, sizeof(name), + "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1) { + error_print(); + return -1; + } + gnslen = 0; + if (0 + || x509_general_names_add_other_name(gns, &gnslen, sizeof(gns), other_id, cnt(other_id), value, sizeof(value)) != 1 + || x509_general_names_add_rfc822_name(gns, &gnslen, sizeof(gns), "guan@pku.edu.cn") != 1 + || x509_general_names_add_dns_name(gns, &gnslen, sizeof(gns), "www.pku.edu.cn") != 1 + || x509_general_names_add_x400_address(gns, &gnslen, sizeof(gns), x400, sizeof(x400)) != 1 + || x509_general_names_add_directory_name(gns, &gnslen, sizeof(gns), name, namelen) != 1 + || x509_general_names_add_edi_party_name(gns, &gnslen, sizeof(gns), + ASN1_TAG_PrintableString, (uint8_t *)"Assigner", strlen("Assigner"), + ASN1_TAG_PrintableString, (uint8_t *)"PartyName", strlen("PartyName")) != 1 + || x509_general_names_add_uniform_resource_identifier(gns, &gnslen, sizeof(gns), "http://localhost") != 1 + || x509_general_names_add_ip_address(gns, &gnslen, sizeof(gns), "127.0.0.1") != 1 + || x509_general_names_add_registered_id(gns, &gnslen, sizeof(gns), reg_id, cnt(reg_id)) != 1 + || x509_general_names_to_der(gns, gnslen, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_general_names_print(stderr, 0, 0, "GeneralNames", d, dlen); + { + size_t i; + printf("uint8_t general_names[%zu] = {", dlen); + for (i = 0; i < dlen; i++) { + if (i % 16 == 0) { + printf("\n\t"); + } + printf("0x%02x,", d[i]); + } + printf("\n};\n"); + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +uint8_t general_names[202] = { + 0x80,0x0b,0x06,0x03,0x2b,0x05,0x07,0xa0,0x04,0x04,0x02,0x05,0x05,0x81,0x0f,0x67, + 0x75,0x61,0x6e,0x40,0x70,0x6b,0x75,0x2e,0x65,0x64,0x75,0x2e,0x63,0x6e,0x82,0x0e, + 0x77,0x77,0x77,0x2e,0x70,0x6b,0x75,0x2e,0x65,0x64,0x75,0x2e,0x63,0x6e,0x83,0x02, + 0x30,0x00,0x84,0x59,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43, + 0x4e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x42,0x65,0x69,0x6a, + 0x69,0x6e,0x67,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x48,0x61, + 0x69,0x64,0x69,0x61,0x6e,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x0a,0x13,0x03, + 0x50,0x4b,0x55,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x0b,0x13,0x02,0x43,0x53, + 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x13,0x02,0x43,0x41,0x85,0x19,0xa0, + 0x0a,0x13,0x08,0x41,0x73,0x73,0x69,0x67,0x6e,0x65,0x72,0xa1,0x0b,0x13,0x09,0x50, + 0x61,0x72,0x74,0x79,0x4e,0x61,0x6d,0x65,0x86,0x10,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x6c,0x6f,0x63,0x61,0x6c,0x68,0x6f,0x73,0x74,0x87,0x09,0x31,0x32,0x37,0x2e, + 0x30,0x2e,0x30,0x2e,0x31,0x88,0x03,0x54,0x06,0x08, +}; + +static int test_x509_authority_key_identifier(void) +{ + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + uint8_t keyid[32]; + uint8_t serial[20]; + + const uint8_t *keyidp; + size_t keyidlen; + const uint8_t *issuerp; + size_t issuerlen; + const uint8_t *serialp; + size_t seriallen; + + sm3_digest((uint8_t *)"abc", 3, keyid); + rand_bytes(serial, sizeof(serial)); + + if (x509_authority_key_identifier_to_der( + keyid, sizeof(keyid), + general_names, sizeof(general_names), + serial, sizeof(serial), + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_authority_key_identifier_print(stderr, 0, 0, "AuthorityKeyIdentifier", d, dlen); + + p = buf; + cp = buf; + len = 0; + if (x509_authority_key_identifier_to_der( + keyid, sizeof(keyid), + general_names, sizeof(general_names), + serial, sizeof(serial), + &p, &len) != 1 + || x509_authority_key_identifier_from_der( + &keyidp, &keyidlen, + &issuerp, &issuerlen, + &serialp, &seriallen, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_key_usage(void) +{ + int tests[] = { + 0, + 1, + 2, + X509_KU_NON_REPUDIATION|X509_KU_CRL_SIGN, + 7, + 8, + X509_KU_DIGITAL_SIGNATURE|X509_KU_NON_REPUDIATION|X509_KU_DECIPHER_ONLY, + 0x1ff, + // 0x3ff, // this should return error + }; + + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int usage; + int i; + + for (i = 0; i <= 8; i++) { + format_print(stderr, 0, 4, "%d %s\n", i, x509_key_usage_name(1 << i)); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_key_usage_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_key_usage_from_der(&usage, &cp, &len) != 1 + || asn1_check(usage == tests[i]) != 1) { + error_print(); + return -1; + } + x509_key_usage_print(stderr, 0, 4, "KeyUsage", usage); + } + (void)asn1_length_is_zero(len); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_notice_reference(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int notice_nums[] = { 1,2,3,4,5 }; + + int org_tag; + const uint8_t *org; + size_t orglen; + int nums[32]; + size_t nums_cnt; + + if (x509_notice_reference_to_der( + ASN1_TAG_IA5String, (uint8_t *)"Hello", 5, + notice_nums, sizeof(notice_nums)/sizeof(notice_nums[0]), + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_notice_reference_print(stderr, 0, 0, "NoticeReference", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_notice_reference_to_der( + ASN1_TAG_IA5String, (uint8_t *)"Hello", 5, + notice_nums, sizeof(notice_nums)/sizeof(notice_nums[0]), + &p, &len) != 1 + || x509_notice_reference_from_der( + &org_tag, &org, &orglen, + nums, &nums_cnt, sizeof(nums)/sizeof(nums[0]), + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_user_notice(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int notice_nums[] = { 1,2,3,4,5 }; + + int org_tag; + const uint8_t *org; + size_t orglen; + int nums[32]; + size_t nums_cnt; + int text_tag; + const uint8_t *text; + size_t textlen; + + if (x509_user_notice_to_der( + ASN1_TAG_IA5String, (uint8_t *)"Hello", 5, + notice_nums, sizeof(notice_nums)/sizeof(notice_nums[0]), + ASN1_TAG_IA5String, (uint8_t *)"World", 5, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_user_notice_print(stderr, 0, 0, "UserNotice", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_user_notice_to_der( + ASN1_TAG_IA5String, (uint8_t *)"Hello", 5, + notice_nums, sizeof(notice_nums)/sizeof(notice_nums[0]), + ASN1_TAG_IA5String, (uint8_t *)"World", 5, + &p, &len) != 1 + || x509_user_notice_from_der( + &org_tag, &org, &orglen, + nums, &nums_cnt, sizeof(nums)/sizeof(nums[0]), + &text_tag, &text, &textlen, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_policy_qualifier_info(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + + if (x509_policy_qualifier_info_to_der( + OID_qt_cps, + (uint8_t *)"Qualifier", strlen("Qualifier"), + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_policy_qualifier_info_print(stderr, 0, 0, "PolicyQualifierInfo", d, dlen); + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_policy_mapping(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int issuer_policy_oid; + uint32_t issuer_policy_nodes[32]; + size_t issuer_policy_nodes_cnt; + int subject_policy_oid; + uint32_t subject_policy_nodes[32]; + size_t subject_policy_nodes_cnt; + + if (x509_policy_mapping_to_der( + OID_any_policy, NULL, 0, + OID_any_policy, NULL, 0, + &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_policy_mapping_print(stderr, 0, 0, "PolicyMapping", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_policy_mapping_to_der( + OID_any_policy, NULL, 0, + OID_any_policy, NULL, 0, + &p, &len) != 1 + || x509_policy_mapping_from_der( + &issuer_policy_oid, issuer_policy_nodes, &issuer_policy_nodes_cnt, + &subject_policy_oid, subject_policy_nodes, &subject_policy_nodes_cnt, + &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +// 这里的一些OID应该在RFC中有,但是我们不实现 +static int test_x509_attribute(void) +{ + // TODO + return 1; +} + +static int test_x509_basic_constraints(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int ca; + int path; + + if (x509_basic_constraints_to_der(1, 4, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_basic_constraints_print(stderr, 0, 0, "BasicConstraints", d, dlen); + + cp = p = buf; len = 0; + if (x509_basic_constraints_to_der(-1, 4, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_basic_constraints_print(stderr, 0, 0, "BasicConstraints", d, dlen); + + + cp = p = buf; len = 0; + if (x509_basic_constraints_to_der(-1, -1, &p, &len) != -1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 0 // empty sequence is not allowed + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_basic_constraints_print(stderr, 0, 0, "BasicConstraints", d, dlen); + + cp = p = buf; len = 0; + if (x509_basic_constraints_to_der(1, 4, &p, &len) != 1 + || x509_basic_constraints_from_der(&ca, &path, &cp, &len) != 1 + || asn1_check(ca == 1) != 1 + || asn1_check(path == 4) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + cp = p = buf; len = 0; + if (x509_basic_constraints_to_der(-1, 4, &p, &len) != 1 + || x509_basic_constraints_from_der(&ca, &path, &cp, &len) != 1 + || asn1_check(ca == -1) != 1 + || asn1_check(path == 4) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + cp = p = buf; len = 0; + if (x509_basic_constraints_to_der(-1, -1, &p, &len) != -1 // should return error + || x509_basic_constraints_from_der(&ca, &path, &cp, &len) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_general_subtree(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + uint8_t *dns = (uint8_t *)"www.pku.edu.cn"; + size_t dnslen = strlen((char *)dns); + + int choice; + const uint8_t *dns_name; + size_t dns_name_len; + int min_dis; + int max_dis; + + if (x509_general_subtree_to_der(X509_gn_dns_name, dns, dnslen, 1, 5, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_general_subtree_print(stderr, 0, 0, "GeneralSubtree", d, dlen); + + cp = p = buf; len = 0; + min_dis = max_dis = 99; + if (x509_general_subtree_to_der(X509_gn_dns_name, dns, dnslen, -1, 5, &p, &len) != 1 + || x509_general_subtree_from_der(&choice, &dns_name, &dns_name_len, &min_dis, &max_dis, &cp, &len) != 1 + || asn1_check(choice == X509_gn_dns_name) != 1 + || asn1_check(dns_name_len == dnslen && memcmp(dns_name, dns, dnslen) == 0) != 1 + || asn1_check(min_dis == 0) != 1 + || asn1_check(max_dis == 5) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + cp = p = buf; len = 0; + min_dis = max_dis = 99; + if (x509_general_subtree_to_der(X509_gn_dns_name, dns, dnslen, 1, -1, &p, &len) != 1 + || x509_general_subtree_from_der(&choice, &dns_name, &dns_name_len, &min_dis, &max_dis, &cp, &len) != 1 + || asn1_check(choice == X509_gn_dns_name) != 1 + || asn1_check(dns_name_len == dnslen && memcmp(dns_name, dns, dnslen) == 0) != 1 + || asn1_check(min_dis == 1) != 1 + || asn1_check(max_dis == -1) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_policy_constraints(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int val1; + int val2; + + if (x509_policy_constraints_to_der(2, 5, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_policy_constraints_print(stderr, 0, 0, "PolicyConstraints", d, dlen); + + cp = p = buf; len = 0; + if (x509_policy_constraints_to_der(2, -1, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_policy_constraints_print(stderr, 0, 0, "PolicyConstraints", d, dlen); + + cp = p = buf; len = 0; + if (x509_policy_constraints_to_der(-1, 5, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_policy_constraints_print(stderr, 0, 0, "PolicyConstraints", d, dlen); + + cp = p = buf; len = 0; + val1 = val2 = 99; + if (x509_policy_constraints_to_der(2, 5, &p, &len) != 1 + || x509_policy_constraints_from_der(&val1, &val2, &cp, &len) != 1 + || asn1_check(val1 == 2) != 1 + || asn1_check(val2 == 5) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + cp = p = buf; len = 0; + val1 = val2 = 99; + if (x509_policy_constraints_to_der(-1, -1, &p, &len) != -1 + || x509_policy_constraints_from_der(&val1, &val2, &cp, &len) != 0 // empty sequence is not allowed + || asn1_check(val1 == -1) != 1 + || asn1_check(val2 == -1) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_ext_key_usage(void) +{ + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int kp[] = { + OID_kp_server_auth, + OID_kp_client_auth, + OID_kp_code_signing, + OID_kp_email_protection, + OID_kp_time_stamping, + OID_kp_ocsp_signing, + }; + int oids[16] = {0}; + size_t oids_cnt; + + if (x509_ext_key_usage_to_der(kp, sizeof(kp)/sizeof(int), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_ext_key_usage_print(stderr, 0, 0, "ExtKeyUsageSyntax", d, dlen); + + if (x509_ext_key_usage_to_der(kp, sizeof(kp)/sizeof(int), &p, &len) != 1 + || x509_ext_key_usage_from_der(oids, &oids_cnt, sizeof(oids)/sizeof(oids[0]), &cp, &len) != 1 + || asn1_check(oids_cnt == sizeof(kp)/sizeof(int)) != 1 + || asn1_check(memcmp(oids, kp, sizeof(kp)) == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_revoke_reasons(void) +{ + int tests[] = { + 0, + 1, + 2, + X509_RF_SUPERSEDED|X509_RF_PRIVILEGE_WITHDRAWN|X509_RF_AA_COMPROMISE, + 0x1ff, + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int bits; + int i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_revoke_reason_flags_to_der(tests[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_revoke_reason_flags_from_der(&bits, &cp, &len) != 1 + || asn1_check(bits == tests[i]) != 1) { + error_print(); + return -1; + } + x509_revoke_reason_flags_print(stderr, 0, 4, "ReasonFlags", bits); + } + (void)asn1_length_is_zero(len); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_exts(void) +{ + uint8_t buf[1024]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + uint8_t exts[512]; + size_t extslen = 0; + uint8_t keyid[32] = {1}; + uint8_t serial[20] = {2}; + + if (0 + || x509_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts), 1, + keyid, sizeof(keyid), + general_names, sizeof(general_names), + serial, sizeof(serial)) != 1 + || x509_exts_add_subject_key_identifier(exts, &extslen, sizeof(exts), 0, + keyid, sizeof(keyid)) != 1 + || x509_exts_add_key_usage(exts, &extslen, sizeof(exts), 0, + X509_KU_NON_REPUDIATION|X509_KU_CRL_SIGN) != 1 + || x509_exts_to_der(exts, extslen, &p, &len) != 1 + || x509_exts_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_exts_print(stderr, 0, 0, "Extensions", d, dlen); + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_cert_with_exts(void) +{ + uint8_t cert[1024]; + size_t certlen = 0; + uint8_t *p = cert; + uint8_t serial[20]; + uint8_t name[256]; + size_t namelen; + time_t not_before, not_after; + SM2_KEY sm2_key; + uint8_t uniq_id[32]; + uint8_t exts[512]; + size_t extslen = 0; + uint8_t keyid[32] = {1}; + + + rand_bytes(serial, sizeof(serial)); + x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "CA"); + time(¬_before); + x509_validity_add_days(¬_after, not_before, 365); + sm2_key_generate(&sm2_key); + sm3_digest((uint8_t *)&(sm2_key.public_key), sizeof(SM2_POINT), uniq_id); + + if (x509_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts), 1, + keyid, sizeof(keyid), + general_names, sizeof(general_names), + serial, sizeof(serial)) != 1 + || x509_exts_add_subject_key_identifier(exts, &extslen, sizeof(exts), 0, + keyid, sizeof(keyid)) != 1 + || x509_exts_add_key_usage(exts, &extslen, sizeof(exts), 0, + X509_KU_NON_REPUDIATION|X509_KU_CRL_SIGN) != 1) { + error_print(); + return -1; + } + + if (x509_cert_sign_to_der( + X509_version_v3, + serial, sizeof(serial), + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, + uniq_id, sizeof(uniq_id), + uniq_id, sizeof(uniq_id), + exts, extslen, + &sm2_key, + SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID), + &p, &certlen) != 1) { + error_print(); + return -1; + } + if (certlen > sizeof(cert)) { + error_print(); + return -1; + } + + x509_cert_print(stderr, 0, 0, "Certificate", cert, certlen); + + + return 1; +} + +static int test_x509_distribution_point_name(void) +{ + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + + x509_general_name_to_der(X509_gn_uniform_resource_identifier, (uint8_t *)"http://", 7, &p, &len); + +// x509_uri_as_general_names_to_der_ex(0x80, "http://", 7, &p, &len); + + format_bytes(stderr, 0, 0, "GeneralNames", buf, len); + + return 1; +} + + + +int main(int argc, char **argv) +{ + if (test_x509_other_name() != 1) goto err; + if (test_x509_edi_party_name() != 1) goto err; + if (test_x509_general_name() != 1) goto err; + if (test_x509_authority_key_identifier() != 1) goto err; + if (test_x509_key_usage() != 1) goto err; + if (test_x509_notice_reference() != 1) goto err; + if (test_x509_user_notice() != 1) goto err; + if (test_x509_policy_qualifier_info() != 1) goto err; + if (test_x509_policy_mapping() != 1) goto err; + if (test_x509_basic_constraints() != 1) goto err; + if (test_x509_general_subtree() != 1) goto err; + if (test_x509_policy_constraints() != 1) goto err; + if (test_x509_ext_key_usage() != 1) goto err; + if (test_x509_revoke_reasons() != 1) goto err; + if (test_x509_exts() != 1) goto err; + if (test_x509_cert_with_exts() != 1) goto err; + if (test_x509_distribution_point_name() != 1) goto err; + + printf("%s all tests passed!\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/x509_oidtest.c b/Core/GmSSL-3.1.1/tests/x509_oidtest.c new file mode 100644 index 0000000..8504140 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/x509_oidtest.c @@ -0,0 +1,287 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_x509_name_type() +{ + char *names[] = { + "name", + "surname", + "givenName", + "initials", + "generationQualifier", + "commonName", + "localityName", + "stateOrProvinceName", + "organizationName", + "organizationalUnitName", + "title", + "dnQualifier", + "countryName", + "serialNumber", + "pseudonym", + "domainComponent", + }; + int oid; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_name_type_from_name(names[i]); + if (asn1_check(oid != OID_undef) != 1 + || x509_name_type_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_name_type_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + if (oid != x509_name_type_from_name(names[i])) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_name_type_name(oid)); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_ext_id() +{ + char *names[] = { + "AuthorityKeyIdentifier", + "SubjectKeyIdentifier", + "KeyUsage", + "CertificatePolicies", + "PolicyMappings", + "SubjectAltName", + "IssuerAltName", + "SubjectDirectoryAttributes", + "BasicConstraints", + "NameConstraints", + "PolicyConstraints", + "ExtKeyUsage", + "CRLDistributionPoints", + "InhibitAnyPolicy", + "FreshestCRL", + }; + int oid; + uint32_t nodes[32]; + size_t nodes_cnt; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_ext_id_from_name(names[i]); + if (asn1_check(oid != OID_undef) != 1 + || x509_ext_id_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + + format_print(stderr, 0, 0, "ExtnID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_ext_id_from_der(&oid, nodes, &nodes_cnt, &cp, &len) != 1) { + error_print(); + return -1; + } + if (oid != x509_ext_id_from_name(names[i])) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_ext_id_name(oid)); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_qualifier_id(void) +{ + char *names[] = { + "CPS", + "userNotice", + }; + int oid; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_qualifier_id_from_name(names[i]); + if (asn1_check(oid != OID_undef) != 1 + || x509_qualifier_id_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_qualifier_id_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + if (asn1_check(oid == x509_qualifier_id_from_name(names[i])) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_qualifier_id_name(oid)); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_cert_policy_id(void) +{ + char *names[] = { + "anyPolicy", + }; + int oid; + uint32_t nodes[32]; + size_t nodes_cnt; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_cert_policy_id_from_name(names[i]); + if (asn1_check(oid != OID_undef) != 1 + || x509_cert_policy_id_to_der(oid, NULL, 0, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_cert_policy_id_from_der(&oid, nodes, &nodes_cnt, &cp, &len) != 1) { + error_print(); + return -1; + } + if (oid != x509_cert_policy_id_from_name(names[i])) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_cert_policy_id_name(oid)); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_key_purpose(void) +{ + char *names[] = { + "serverAuth", + "clientAuth", + "codeSigning", + "emailProtection", + "timeStamping", + "OCSPSigning", + }; + int oid; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int i; + + format_print(stderr, 0, 0, "DER\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + oid = x509_key_purpose_from_name(names[i]); + if (asn1_check(oid != OID_undef) != 1 + || x509_key_purpose_to_der(oid, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + + format_print(stderr, 0, 0, "OID\n"); + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) { + if (x509_key_purpose_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + if (oid != x509_key_purpose_from_name(names[i])) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_key_purpose_name(oid)); + } + if (len != 0) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_x509_name_type() != 1) goto err; + if (test_x509_ext_id() != 1) goto err; + if (test_x509_qualifier_id() != 1) goto err; + if (test_x509_cert_policy_id() != 1) goto err; + if (test_x509_key_purpose() != 1) goto err; + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/x509_reqtest.c b/Core/GmSSL-3.1.1/tests/x509_reqtest.c new file mode 100644 index 0000000..8dd0470 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/x509_reqtest.c @@ -0,0 +1,218 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_x509_request_info(void) +{ + uint8_t subject[256]; + size_t subject_len; + SM2_KEY sm2_key; + + uint8_t attrs_buf[512]; + size_t attrs_len = 0; + + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int version; + const uint8_t *subj; + size_t subj_len; + SM2_KEY pub_key; + const uint8_t *attrs; + + if (sm2_key_generate(&sm2_key) != 1 + || x509_name_set(subject, &subject_len, sizeof(subject), "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1 + || x509_request_info_to_der(X509_version_v1, subject, subject_len, &sm2_key, attrs_buf, attrs_len, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_request_info_print(stderr, 0, 0, "CertificationRequestInfo", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_request_info_to_der(X509_version_v1, subject, subject_len, &sm2_key, attrs_buf, attrs_len, &p, &len) != 1 + || x509_request_info_from_der(&version, &subj, &subj_len, &pub_key, &attrs, &attrs_len, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 0, "CertificationRequestInfo\n"); + format_print(stderr, 0, 4, "version: %d\n", version); + x509_name_print(stderr, 0, 4, "subject", subj, subj_len); + sm2_public_key_print(stderr, 0, 4, "publicKey", &pub_key); + format_bytes(stderr, 0, 4, "attributes", attrs, attrs_len); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_request(void) +{ +/* + uint8_t subject[256]; + size_t subject_len; + SM2_KEY sm2_key; + uint8_t signature[128] = { 0x01, 0x02 }; + + uint8_t buf[512]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + int version; + const uint8_t *subj; + size_t subj_len; + SM2_KEY pub_key; + const uint8_t *attrs; + size_t attrs_len; + int sig_alg; + const uint8_t *sig; + size_t siglen; + + if (sm2_key_generate(&sm2_key) != 1 + || x509_name_set(subject, &subject_len, sizeof(subject), "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1 + || x509_request_to_der(X509_version_v1, subject, subject_len, &sm2_key, NULL, 0, + OID_sm2sign_with_sm3, signature, sizeof(signature), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_request_print(stderr, 0, 0, "CertificationRequest", d, dlen); + + p = buf; + cp = buf; + len = 0; + + if (x509_request_to_der(X509_version_v1, subject, subject_len, &sm2_key, NULL, 0, + OID_sm2sign_with_sm3, signature, sizeof(signature), &p, &len) != 1 + || x509_request_from_der(&version, &subj, &subj_len, &pub_key, &attrs, &attrs_len, + &sig_alg, &sig, &siglen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 0, "CertificationRequest\n"); + format_print(stderr, 0, 4, "version: %d\n", version); + x509_name_print(stderr, 0, 4, "subject", subj, subj_len); + sm2_public_key_print(stderr, 0, 4, "publicKey", &pub_key); + format_bytes(stderr, 0, 4, "attributes", attrs, attrs_len); + format_print(stderr, 0, 4, "signatureAlgor: %s\n", x509_signature_algor_name(sig_alg)); + format_bytes(stderr, 0, 4, "signature", sig, siglen); + +*/ + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_req(void) +{ + uint8_t subject[256]; + size_t subject_len; + SM2_KEY sm2_key; + uint8_t attrs[256]; + size_t attrs_len = 0; + + uint8_t req[512]; + uint8_t *p = req; + size_t reqlen = 0; + + if (sm2_key_generate(&sm2_key) != 1 + || x509_name_set(subject, &subject_len, sizeof(subject), "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1 + || x509_req_sign_to_der( + X509_version_v1, subject, subject_len, &sm2_key, attrs, attrs_len, + OID_sm2sign_with_sm3, &sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID), + &p, &reqlen) != 1) { + error_print(); + return -1; + } + x509_req_print(stderr, 0, 0, "CertificationRequest", req, reqlen); + + + + FILE *fp; + + if ((fp = fopen("req.pem", "w")) == NULL) { + error_print(); + return -1; + } + if (x509_req_to_pem(req, reqlen, fp) != 1) { + error_print(); + return -1; + } + fclose(fp); + x509_req_to_pem(req, reqlen, stderr); + + + memset(req, 0, sizeof(req)); + + if ((fp = fopen("req.pem", "r")) == NULL) { + error_print(); + return -1; + } + if (x509_req_from_pem(req, &reqlen, sizeof(req), fp) != 1) { + error_print(); + return -1; + } + if (x509_req_verify(req, reqlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 0, "x509_req_verify() success\n"); + + + + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + + + + + + + + + +int main(void) +{ + if (test_x509_request_info() != 1) goto err; + if (test_x509_request() != 1) goto err; + if (test_x509_req() != 1) goto err; + printf("%s all tests passed!\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} + diff --git a/Core/GmSSL-3.1.1/tests/x509_strtest.c b/Core/GmSSL-3.1.1/tests/x509_strtest.c new file mode 100644 index 0000000..898ad4e --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/x509_strtest.c @@ -0,0 +1,79 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_x509_directory_name(void) +{ + uint8_t str[] = { 'a', 'b', 'c', 0 }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int tag; + const uint8_t *d; + size_t dlen; + + if (x509_directory_name_check_ex(ASN1_TAG_UTF8String, str, 3, 1, 10) != 1 // str,4 will fail + || x509_directory_name_to_der(ASN1_TAG_UTF8String, str, 3, &p, &len) != 1 + || x509_directory_name_from_der(&tag, &d, &dlen, &cp, &len) != 1 + || asn1_check(tag == ASN1_TAG_UTF8String) != 1 + || asn1_check(dlen == 3) != 1 + || asn1_check(memcmp(str, d, dlen) == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_display_text(void) +{ + uint8_t str[] = { 'a', 'b', 'c', 0 }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int tag; + const uint8_t *d; + size_t dlen; + + if (x509_display_text_check(ASN1_TAG_UTF8String, str, 3) != 1 // str,4 will fail + || x509_display_text_to_der(ASN1_TAG_UTF8String, str, 3, &p, &len) != 1 + || x509_display_text_from_der(&tag, &d, &dlen, &cp, &len) != 1 + || asn1_check(tag == ASN1_TAG_UTF8String) != 1 + || asn1_check(dlen == 3) != 1 + || asn1_check(memcmp(str, d, dlen) == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_x509_directory_name() != 1) goto err; + if (test_x509_display_text() != 1) goto err; + printf("%s all tests passed!\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tests/x509test.c b/Core/GmSSL-3.1.1/tests/x509test.c new file mode 100644 index 0000000..ddc2977 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/x509test.c @@ -0,0 +1,398 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_x509_version(void) +{ + + int tests[] = { + X509_version_v1, + X509_version_v2, + X509_version_v3, + -1, + }; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + int i; + + format_print(stderr, 0, 0, "Version\n"); + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_explicit_version_to_der(i, tests[i], &p, &len) < 0) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + int ver; + if (x509_explicit_version_from_der(i, &ver, &cp, &len) < 0 + || asn1_check(ver == tests[i]) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s\n", x509_version_name(ver)); + } + (void)asn1_length_is_zero(len); + printf("%s() ok\n", __FUNCTION__); + return 0; +} + + +static int test_x509_validity(void) +{ + time_t not_before, not_before_; + time_t not_after, not_after_; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + time(¬_before); + + format_print(stderr, 0, 0, "Validity\n"); + if (x509_validity_add_days(¬_after, not_before, 365) != 1 + || x509_validity_to_der(not_before, not_after, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + if (x509_validity_from_der(¬_before_, ¬_after_, &cp, &len) != 1 + || asn1_check(not_before == not_before_) != 1 + || asn1_check(not_after == not_after_) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return 1; + } + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_x509_attr_type_and_value(void) +{ + int oid; + int tag; + const uint8_t *d; + size_t dlen; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + format_print(stderr, 0, 0, "AttributeTypeAndValue\n"); + if (x509_attr_type_and_value_to_der(OID_at_locality_name, ASN1_TAG_PrintableString, (uint8_t *)"Haidian", strlen("Haidian"), &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + if (x509_attr_type_and_value_from_der(&oid, &tag, &d, &dlen, &cp, &len) != 1 + || asn1_check(oid == OID_at_locality_name) != 1 + || asn1_check(tag == ASN1_TAG_PrintableString) != 1 + || asn1_check(dlen == strlen("Haidian")) != 1 + || asn1_check(memcmp("Haidian", d, dlen) == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s : %s ", x509_name_type_name(oid), asn1_tag_name(tag)); + format_string(stderr, 0, 0, "", d, dlen); + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_x509_rdn(void) +{ + int oid; + int tag; + const uint8_t *d; + size_t dlen; + const uint8_t *more; + size_t morelen; + uint8_t buf[256]; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + + format_print(stderr, 0, 0, "RDN\n"); + if (x509_rdn_to_der(OID_at_locality_name, ASN1_TAG_PrintableString, + (uint8_t *)"Haidian", strlen("Haidian"), NULL, 0, &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "", buf, len); + if (x509_rdn_from_der(&oid, &tag, &d, &dlen, &more, &morelen, &cp, &len) != 1 + || asn1_check(oid == OID_at_locality_name) != 1 + || asn1_check(tag == ASN1_TAG_PrintableString) != 1 + || asn1_check(dlen == strlen("Haidian")) != 1 + || asn1_check(memcmp("Haidian", d, dlen) == 0) != 1 + || asn1_check(more == NULL) != 1 + || asn1_check(morelen == 0) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + format_print(stderr, 0, 4, "%s : %s ", x509_name_type_name(oid), asn1_tag_name(tag)); + format_string(stderr, 0, 0, "", d, dlen); + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int test_x509_name(void) +{ + int err = 0; + uint8_t name[512]; + size_t namelen = 0; + uint8_t buf[1024]; + const uint8_t *cp = buf; + uint8_t *p = buf; + size_t len = 0; + + if (x509_name_add_country_name(name, &namelen, sizeof(name), "CN") != 1 + || format_bytes(stderr, 0, 4, "", name, namelen) > 2 + || x509_name_add_locality_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"Haidian", strlen("Haidian")) != 1 + || format_bytes(stderr, 0, 4, "", name, namelen) > 2 + || x509_name_add_state_or_province_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"Beijing", strlen("Beijing")) != 1 + || format_bytes(stderr, 0, 4, "", name, namelen) > 2 + || x509_name_add_organization_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"PKU", strlen("PKU")) != 1 + || format_bytes(stderr, 0, 4, "", name, namelen) > 2 + || x509_name_add_organizational_unit_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"CS", strlen("CS")) != 1 + || format_bytes(stderr, 0, 4, "", name, namelen) > 2 + || x509_name_add_common_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"CA", strlen("CA")) != 1 + || format_bytes(stderr, 0, 4, "", name, namelen) > 2 + ) { + error_print(); + return 1; + } + format_bytes(stdout, 0, 0, "der ", name, namelen); + x509_name_print(stdout, 0, 0, "Name", name, namelen); + return 0; +} + +static int test_x509_public_key_info(void) +{ + int err = 0; + SM2_KEY sm2_key; + SM2_KEY pub_key; + uint8_t buf[256]; + const uint8_t *cp = buf; + uint8_t *p = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + + if (sm2_key_generate(&sm2_key) != 1 + || x509_public_key_info_to_der(&sm2_key, &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return 1; + } + x509_public_key_info_print(stdout, 0, 0, "PublicKeyInfo", d, dlen); + if (sm2_key_generate(&sm2_key) != 1 + || x509_public_key_info_to_der(&sm2_key, &p, &len) != 1 + || x509_public_key_info_from_der(&pub_key, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return 1; + } + sm2_public_key_print(stdout, 0, 8, "ECPublicKey", &pub_key); + + printf("%s() ok\n", __FUNCTION__); + return 0; +} + +static int set_x509_name(uint8_t *name, size_t *namelen, size_t maxlen) +{ + *namelen = 0; + if (x509_name_add_country_name(name, namelen, maxlen, "CN") != 1 + || x509_name_add_locality_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"Haidian", strlen("Haidian")) != 1 + || x509_name_add_state_or_province_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"Beijing", strlen("Beijing")) != 1 + || x509_name_add_organization_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"PKU", strlen("PKU")) != 1 + || x509_name_add_organizational_unit_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"CS", strlen("CS")) != 1 + || x509_name_add_common_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"CA", strlen("CA")) != 1) { + error_print(); + return -1; + } + return 1; +} + +static int test_x509_tbs_cert(void) +{ + uint8_t serial[20] = { 0x01, 0x00 }; + uint8_t issuer[256]; + size_t issuer_len = 0; + time_t not_before, not_after; + uint8_t subject[256]; + size_t subject_len = 0; + SM2_KEY sm2_key; + uint8_t buf[1024] = {0}; + uint8_t *p = buf; + const uint8_t *cp = buf; + size_t len = 0; + const uint8_t *d; + size_t dlen; + + set_x509_name(issuer, &issuer_len, sizeof(issuer)); + time(¬_before); + x509_validity_add_days(¬_after, not_before, 365); + set_x509_name(subject, &subject_len, sizeof(subject)); + sm2_key_generate(&sm2_key); + + if (x509_tbs_cert_to_der( + X509_version_v3, + serial, sizeof(serial), + OID_sm2sign_with_sm3, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + &sm2_key, + NULL, 0, + NULL, 0, + NULL, 0, + &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 0, "tbs_cert", buf, len); + if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + x509_tbs_cert_print(stderr, 0, 4, "TBSCertificate", d, dlen); + + return 0; +} + +static int test_x509_cert_get(const uint8_t *cert, size_t certlen) +{ + const uint8_t *serial; + size_t serial_len; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *subject; + size_t subject_len; + SM2_KEY public_key; + + if (x509_cert_get_issuer_and_serial_number(cert, certlen, &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "SerialNumber", serial, serial_len); + x509_name_print(stderr, 0, 4, "Issuer", issuer, issuer_len); + x509_name_print(stderr, 0, 4, "Subject", subject, subject_len); + sm2_public_key_print(stderr, 0, 4, "SubjectPublicKey", &public_key); + return 0; +} + +static int test_x509_cert(void) +{ + uint8_t serial[20] = { 0x01, 0x00 }; + uint8_t issuer[256]; + size_t issuer_len = 0; + time_t not_before, not_after; + uint8_t subject[256]; + size_t subject_len = 0; + SM2_KEY sm2_key; + uint8_t cert[1024] = {0}; + uint8_t *p = cert; + const uint8_t *cp = cert; + size_t certlen = 0; + + set_x509_name(issuer, &issuer_len, sizeof(issuer)); + time(¬_before); + x509_validity_add_days(¬_after, not_before, 365); + set_x509_name(subject, &subject_len, sizeof(subject)); + sm2_key_generate(&sm2_key); + + if (x509_cert_sign_to_der( + X509_version_v3, + serial, sizeof(serial), + OID_sm2sign_with_sm3, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + &sm2_key, + NULL, 0, + NULL, 0, + NULL, 0, + &sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID), + &p, &certlen) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 4, "cert", cert, certlen); + x509_cert_print(stderr, 0, 4, "Certificate", cert, certlen); + + /* + // TODO: use the same cert to verify? + if (x509_cert_verify(cert, certlen, &sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) { + error_print(); + return -1; + } + printf("x509_cert_verify() success\n"); + */ + + test_x509_cert_get(cert, certlen); + + + FILE *fp; + + if (!(fp = fopen("cert.pem", "w"))) { + error_print(); + return -1; + } + + x509_cert_to_pem(cert, certlen, fp); + x509_cert_to_pem(cert, certlen, stderr); + fclose(fp); + + + if (!(fp = fopen("cert.pem", "r"))) { + error_print(); + return -1; + } + + memset(cert, 0, sizeof(cert)); + if (x509_cert_from_pem(cert, &certlen, sizeof(cert), fp) != 1) { + error_print(); + return -1; + } + x509_cert_print(stderr, 0, 4, "Certificate", cert, certlen); + + return 0; +} + +int main(void) +{ + int err = 0; + err += test_x509_version(); + err += test_x509_validity(); + err += test_x509_attr_type_and_value(); + err += test_x509_rdn(); + err += test_x509_name(); + err += test_x509_public_key_info(); + err += test_x509_tbs_cert(); + err += test_x509_cert(); + return err; +} diff --git a/Core/GmSSL-3.1.1/tests/zuctest.c b/Core/GmSSL-3.1.1/tests/zuctest.c new file mode 100644 index 0000000..7791905 --- /dev/null +++ b/Core/GmSSL-3.1.1/tests/zuctest.c @@ -0,0 +1,483 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +static void bswap_buf(uint32_t *buf, size_t nwords) +{ + size_t i; + for (i = 0; i < nwords; i++) { + uint32_t a = buf[i]; + buf[i] = (a >> 24) | ((a >> 8) & 0xff00) | + ((a << 8) & 0xff0000) | (a << 24); + } +} + +int zuc_test(void) +{ + unsigned char key[][16] = { + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + {0x3d,0x4c,0x4b,0xe9,0x6a,0x82,0xfd,0xae,0xb5,0x8f,0x64,0x1d,0xb1,0x7b,0x45,0x5b}, + }; + unsigned char iv[][16] = { + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + {0x84,0x31,0x9a,0xa8,0xde,0x69,0x15,0xca,0x1f,0x6b,0xda,0x6b,0xfb,0xd8,0xc7,0x66}, + }; + uint32_t ciphertext[][2] = { + {0x27bede74, 0x018082da}, + {0x0657cfa0, 0x7096398b}, + {0x14f1c272, 0x3279c419}, + }; + int i; + + for (i = 0; i < 3; i++) { + ZUC_STATE zuc = {{0}}; + uint32_t buf[3] = {0}; + zuc_init(&zuc, key[i], iv[i]); + zuc_generate_keystream(&zuc, 2, buf); + if (buf[0] != ciphertext[i][0] || buf[1] != ciphertext[i][1]) { + fprintf(stderr, "error generating ZUC key stream on test vector %d\n", i); + error_print(); + return -1; + } else { + fprintf(stderr, "zuc test %d ok\n", i); + } + } + + return 1; +} + +/* test vector from GM/T 0001.2-2012 */ +static int zuc_eea_test(void) +{ + unsigned char key[][16] = { + {0x17, 0x3d, 0x14, 0xba, 0x50, 0x03, 0x73, 0x1d, + 0x7a, 0x60, 0x04, 0x94, 0x70, 0xf0, 0x0a, 0x29}, + {0xe5, 0xbd, 0x3e, 0xa0, 0xeb, 0x55, 0xad, 0xe8, + 0x66, 0xc6, 0xac, 0x58, 0xbd, 0x54, 0x30, 0x2a}, + {0xe1, 0x3f, 0xed, 0x21, 0xb4, 0x6e, 0x4e, 0x7e, + 0xc3, 0x12, 0x53, 0xb2, 0xbb, 0x17, 0xb3, 0xe0}, + }; + ZUC_UINT32 count[] = {0x66035492, 0x56823, 0x2738cdaa}; + ZUC_UINT5 bearer[] = {0x0f, 0x18, 0x1a}; + ZUC_BIT direction[] = {0, 1, 0}; + ZUC_UINT32 ibs0[] = { + 0x6cf65340, 0x735552ab, 0x0c9752fa, 0x6f9025fe, + 0x0bd675d9, 0x005875b2, 0x00000000, + }; + ZUC_UINT32 ibs1[] = { + 0x14a8ef69, 0x3d678507, 0xbbe7270a, 0x7f67ff50, + 0x06c3525b, 0x9807e467, 0xc4e56000, 0xba338f5d, + 0x42955903, 0x67518222, 0x46c80d3b, 0x38f07f4b, + 0xe2d8ff58, 0x05f51322, 0x29bde93b, 0xbbdcaf38, + 0x2bf1ee97, 0x2fbf9977, 0xbada8945, 0x847a2a6c, + 0x9ad34a66, 0x7554e04d, 0x1f7fa2c3, 0x3241bd8f, + 0x01ba220d, + }; + ZUC_UINT32 ibs2[] = { + 0x8d74e20d, 0x54894e06, 0xd3cb13cb, 0x3933065e, + 0x8674be62, 0xadb1c72b, 0x3a646965, 0xab63cb7b, + 0x7854dfdc, 0x27e84929, 0xf49c64b8, 0x72a490b1, + 0x3f957b64, 0x827e71f4, 0x1fbd4269, 0xa42c97f8, + 0x24537027, 0xf86e9f4a, 0xd82d1df4, 0x51690fdd, + 0x98b6d03f, 0x3a0ebe3a, 0x312d6b84, 0x0ba5a182, + 0x0b2a2c97, 0x09c090d2, 0x45ed267c, 0xf845ae41, + 0xfa975d33, 0x33ac3009, 0xfd40eba9, 0xeb5b8857, + 0x14b768b6, 0x97138baf, 0x21380eca, 0x49f644d4, + 0x8689e421, 0x5760b906, 0x739f0d2b, 0x3f091133, + 0xca15d981, 0xcbe401ba, 0xf72d05ac, 0xe05cccb2, + 0xd297f4ef, 0x6a5f58d9, 0x1246cfa7, 0x7215b892, + 0xab441d52, 0x78452795, 0xccb7f5d7, 0x9057a1c4, + 0xf77f80d4, 0x6db2033c, 0xb79bedf8, 0xe60551ce, + 0x10c667f6, 0x2a97abaf, 0xabbcd677, 0x2018df96, + 0xa282ea73, 0x7ce2cb33, 0x1211f60d, 0x5354ce78, + 0xf9918d9c, 0x206ca042, 0xc9b62387, 0xdd709604, + 0xa50af16d, 0x8d35a890, 0x6be484cf, 0x2e74a928, + 0x99403643, 0x53249b27, 0xb4c9ae29, 0xeddfc7da, + 0x6418791a, 0x4e7baa06, 0x60fa6451, 0x1f2d685c, + 0xc3a5ff70, 0xe0d2b742, 0x92e3b8a0, 0xcd6b04b1, + 0xc790b8ea, 0xd2703708, 0x540dea2f, 0xc09c3da7, + 0x70f65449, 0xc84d817a, 0x4f551055, 0xe19ab850, + 0x18a0028b, 0x71a144d9, 0x6791e9a3, 0x57793350, + 0x4eee0060, 0x340c69d2, 0x74e1bf9d, 0x805dcbcc, + 0x1a6faa97, 0x6800b6ff, 0x2b671dc4, 0x63652fa8, + 0xa33ee509, 0x74c1c21b, 0xe01eabb2, 0x16743026, + 0x9d72ee51, 0x1c9dde30, 0x797c9a25, 0xd86ce74f, + 0x5b961be5, 0xfdfb6807, 0x814039e7, 0x137636bd, + 0x1d7fa9e0, 0x9efd2007, 0x505906a5, 0xac45dfde, + 0xed7757bb, 0xee745749, 0xc2963335, 0x0bee0ea6, + 0xf409df45, 0x80160000, + }; + ZUC_UINT32 obs0[] = { + 0xa6c85fc6, 0x6afb8533, 0xaafc2518, 0xdfe78494, + 0x0ee1e4b0, 0x30238cc8, 0x00000000, + }; + ZUC_UINT32 obs1[] = { + 0x131d43e0, 0xdea1be5c, 0x5a1bfd97, 0x1d852cbf, + 0x712d7b4f, 0x57961fea, 0x3208afa8, 0xbca433f4, + 0x56ad09c7, 0x417e58bc, 0x69cf8866, 0xd1353f74, + 0x865e8078, 0x1d202dfb, 0x3ecff7fc, 0xbc3b190f, + 0xe82a204e, 0xd0e350fc, 0x0f6f2613, 0xb2f2bca6, + 0xdf5a473a, 0x57a4a00d, 0x985ebad8, 0x80d6f238, + 0x64a07b01, + }; + ZUC_UINT32 obs2[] = { + 0x94eaa4aa, 0x30a57137, 0xddf09b97, 0xb25618a2, + 0x0a13e2f1, 0x0fa5bf81, 0x61a879cc, 0x2ae797a6, + 0xb4cf2d9d, 0xf31debb9, 0x905ccfec, 0x97de605d, + 0x21c61ab8, 0x531b7f3c, 0x9da5f039, 0x31f8a064, + 0x2de48211, 0xf5f52ffe, 0xa10f392a, 0x04766998, + 0x5da454a2, 0x8f080961, 0xa6c2b62d, 0xaa17f33c, + 0xd60a4971, 0xf48d2d90, 0x9394a55f, 0x48117ace, + 0x43d708e6, 0xb77d3dc4, 0x6d8bc017, 0xd4d1abb7, + 0x7b7428c0, 0x42b06f2f, 0x99d8d07c, 0x9879d996, + 0x00127a31, 0x985f1099, 0xbbd7d6c1, 0x519ede8f, + 0x5eeb4a61, 0x0b349ac0, 0x1ea23506, 0x91756bd1, + 0x05c974a5, 0x3eddb35d, 0x1d4100b0, 0x12e522ab, + 0x41f4c5f2, 0xfde76b59, 0xcb8b96d8, 0x85cfe408, + 0x0d1328a0, 0xd636cc0e, 0xdc05800b, 0x76acca8f, + 0xef672084, 0xd1f52a8b, 0xbd8e0993, 0x320992c7, + 0xffbae17c, 0x408441e0, 0xee883fc8, 0xa8b05e22, + 0xf5ff7f8d, 0x1b48c74c, 0x468c467a, 0x028f09fd, + 0x7ce91109, 0xa570a2d5, 0xc4d5f4fa, 0x18c5dd3e, + 0x4562afe2, 0x4ef77190, 0x1f59af64, 0x5898acef, + 0x088abae0, 0x7e92d52e, 0xb2de5504, 0x5bb1b7c4, + 0x164ef2d7, 0xa6cac15e, 0xeb926d7e, 0xa2f08b66, + 0xe1f759f3, 0xaee44614, 0x725aa3c7, 0x482b3084, + 0x4c143ff8, 0x7b53f1e5, 0x83c50125, 0x7dddd096, + 0xb81268da, 0xa303f172, 0x34c23335, 0x41f0bb8e, + 0x190648c5, 0x807c866d, 0x71932286, 0x09adb948, + 0x686f7de2, 0x94a802cc, 0x38f7fe52, 0x08f5ea31, + 0x96d0167b, 0x9bdd02f0, 0xd2a5221c, 0xa508f893, + 0xaf5c4b4b, 0xb9f4f520, 0xfd84289b, 0x3dbe7e61, + 0x497a7e2a, 0x584037ea, 0x637b6981, 0x127174af, + 0x57b471df, 0x4b2768fd, 0x79c1540f, 0xb3edf2ea, + 0x22cb69be, 0xc0cf8d93, 0x3d9c6fdd, 0x645e8505, + 0x91cca3d6, 0x2c0cc000, + }; + ZUC_UINT32 *ibs[] = {ibs0, ibs1, ibs2}; + ZUC_UINT32 *obs[] = {obs0, obs1, obs2}; + size_t bits[] = {0xc1, 0x320, 0xfb3}; + ZUC_UINT32 buf[sizeof(obs2)/4]; + size_t i; + + for (i = 0; i < sizeof(key)/sizeof(key[i]); i++) { + zuc_eea_encrypt(ibs[i], buf, bits[i], key[i], count[i], bearer[i], direction[i]); + if (memcmp(buf, obs[i], ZUC_EEA_ENCRYPT_NBYTES(bits[i])) != 0) { + printf("zuc eea test %zu failed\n", i); + error_print(); + return -1; + } else { + printf("zuc eea test %zu ok\n", i); + } + } + + return 1; +} + +/* test vector from GM/T 0001.3-2012 */ +static int zuc_eia_test(void) +{ + unsigned char key[][16] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb, + 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a}, + {0x6b, 0x8b, 0x08, 0xee, 0x79, 0xe0, 0xb5, 0x98, + 0x2d, 0x6d, 0x12, 0x8e, 0xa9, 0xf2, 0x20, 0xcb}, + }; + ZUC_UINT32 count[] = {0, 0xa94059daU, 0x561eb2ddU}; + ZUC_UINT5 bearer[] = {0, 0x0a, 0x1c}; + ZUC_BIT direction[] = {0, 1, 0}; + ZUC_UINT32 mesg0[] = {0}; + ZUC_UINT32 mesg1[] = { + 0x983b41d4, 0x7d780c9e, 0x1ad11d7e, 0xb70391b1, + 0xde0b35da, 0x2dc62f83, 0xe7b78d63, 0x06ca0ea0, + 0x7e941b7b, 0xe91348f9, 0xfcb170e2, 0x217fecd9, + 0x7f9f68ad, 0xb16e5d7d, 0x21e569d2, 0x80ed775c, + 0xebde3f40, 0x93c53881, 0x00000000, + }; + ZUC_UINT32 mesg2[] = { + 0x5bad7247, 0x10ba1c56, 0xd5a315f8, 0xd40f6e09, + 0x3780be8e, 0x8de07b69, 0x92432018, 0xe08ed96a, + 0x5734af8b, 0xad8a575d, 0x3a1f162f, 0x85045cc7, + 0x70925571, 0xd9f5b94e, 0x454a77c1, 0x6e72936b, + 0xf016ae15, 0x7499f054, 0x3b5d52ca, 0xa6dbeab6, + 0x97d2bb73, 0xe41b8075, 0xdce79b4b, 0x86044f66, + 0x1d4485a5, 0x43dd7860, 0x6e0419e8, 0x059859d3, + 0xcb2b67ce, 0x0977603f, 0x81ff839e, 0x33185954, + 0x4cfbc8d0, 0x0fef1a4c, 0x8510fb54, 0x7d6b06c6, + 0x11ef44f1, 0xbce107cf, 0xa45a06aa, 0xb360152b, + 0x28dc1ebe, 0x6f7fe09b, 0x0516f9a5, 0xb02a1bd8, + 0x4bb0181e, 0x2e89e19b, 0xd8125930, 0xd178682f, + 0x3862dc51, 0xb636f04e, 0x720c47c3, 0xce51ad70, + 0xd94b9b22, 0x55fbae90, 0x6549f499, 0xf8c6d399, + 0x47ed5e5d, 0xf8e2def1, 0x13253e7b, 0x08d0a76b, + 0x6bfc68c8, 0x12f375c7, 0x9b8fe5fd, 0x85976aa6, + 0xd46b4a23, 0x39d8ae51, 0x47f680fb, 0xe70f978b, + 0x38effd7b, 0x2f7866a2, 0x2554e193, 0xa94e98a6, + 0x8b74bd25, 0xbb2b3f5f, 0xb0a5fd59, 0x887f9ab6, + 0x8159b717, 0x8d5b7b67, 0x7cb546bf, 0x41eadca2, + 0x16fc1085, 0x0128f8bd, 0xef5c8d89, 0xf96afa4f, + 0xa8b54885, 0x565ed838, 0xa950fee5, 0xf1c3b0a4, + 0xf6fb71e5, 0x4dfd169e, 0x82cecc72, 0x66c850e6, + 0x7c5ef0ba, 0x960f5214, 0x060e71eb, 0x172a75fc, + 0x1486835c, 0xbea65344, 0x65b055c9, 0x6a72e410, + 0x52241823, 0x25d83041, 0x4b40214d, 0xaa8091d2, + 0xe0fb010a, 0xe15c6de9, 0x0850973b, 0xdf1e423b, + 0xe148a237, 0xb87a0c9f, 0x34d4b476, 0x05b803d7, + 0x43a86a90, 0x399a4af3, 0x96d3a120, 0x0a62f3d9, + 0x507962e8, 0xe5bee6d3, 0xda2bb3f7, 0x237664ac, + 0x7a292823, 0x900bc635, 0x03b29e80, 0xd63f6067, + 0xbf8e1716, 0xac25beba, 0x350deb62, 0xa99fe031, + 0x85eb4f69, 0x937ecd38, 0x7941fda5, 0x44ba67db, + 0x09117749, 0x38b01827, 0xbcc69c92, 0xb3f772a9, + 0xd2859ef0, 0x03398b1f, 0x6bbad7b5, 0x74f7989a, + 0x1d10b2df, 0x798e0dbf, 0x30d65874, 0x64d24878, + 0xcd00c0ea, 0xee8a1a0c, 0xc753a279, 0x79e11b41, + 0xdb1de3d5, 0x038afaf4, 0x9f5c682c, 0x3748d8a3, + 0xa9ec54e6, 0xa371275f, 0x1683510f, 0x8e4f9093, + 0x8f9ab6e1, 0x34c2cfdf, 0x4841cba8, 0x8e0cff2b, + 0x0bcc8e6a, 0xdcb71109, 0xb5198fec, 0xf1bb7e5c, + 0x531aca50, 0xa56a8a3b, 0x6de59862, 0xd41fa113, + 0xd9cd9578, 0x08f08571, 0xd9a4bb79, 0x2af271f6, + 0xcc6dbb8d, 0xc7ec36e3, 0x6be1ed30, 0x8164c31c, + 0x7c0afc54, 0x1c000000, + }; + ZUC_UINT32 *mesg[] = {mesg0, mesg1, mesg2}; + size_t bits[] = {1, 0x241, 0x1626}; + ZUC_UINT32 mac[] = {0xc8a9595eU, 0xfae8ff0bU, 0x0ca12792U}; + size_t i; + + bswap_buf(mesg0, sizeof(mesg0)/sizeof(mesg0[0])); + bswap_buf(mesg1, sizeof(mesg1)/sizeof(mesg1[0])); + bswap_buf(mesg2, sizeof(mesg2)/sizeof(mesg2[0])); + + for (i = 0; i < sizeof(key)/sizeof(key[0]); i++) { + ZUC_UINT32 T; + T = zuc_eia_generate_mac(mesg[i], bits[i], key[i], + count[i], bearer[i], direction[i]); + if (T != mac[i]) { + printf("zuc eia test %zu failed\n", i); + error_print(); + return -1; + } else { + printf("zuc eia test %zu ok\n", i); + } + } + + return 1; +} + +/* from ZUC256 draft */ +int zuc256_test(void) +{ + unsigned char key[][32] = { + {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}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} + }; + unsigned char iv[][23] = { + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + }; + uint32_t ciphertext[][20] = { + {0x58d03ad6,0x2e032ce2,0xdafc683a,0x39bdcb03,0x52a2bc67, + 0xf1b7de74,0x163ce3a1,0x01ef5558,0x9639d75b,0x95fa681b, + 0x7f090df7,0x56391ccc,0x903b7612,0x744d544c,0x17bc3fad, + 0x8b163b08,0x21787c0b,0x97775bb8,0x4943c6bb,0xe8ad8afd}, + {0x3356cbae,0xd1a1c18b,0x6baa4ffe,0x343f777c,0x9e15128f, + 0x251ab65b,0x949f7b26,0xef7157f2,0x96dd2fa9,0xdf95e3ee, + 0x7a5be02e,0xc32ba585,0x505af316,0xc2f9ded2,0x7cdbd935, + 0xe441ce11,0x15fd0a80,0xbb7aef67,0x68989416,0xb8fac8c2} + }; + int i; + + for (i = 0; i < sizeof(key)/sizeof(key[0]); i++) { + ZUC_STATE zuc_key; + uint32_t buf[20] = {0}; + + zuc256_init(&zuc_key, key[i], iv[i]); + zuc_generate_keystream(&zuc_key, 20, buf); + + if (memcmp(buf, ciphertext[i], 20) != 0) { + printf("zuc256 test %d failed\n", i); + error_print(); + return -1; + } else { + printf("zuc256 test %d ok\n", i); + } + } + + return 1; +} + +int zuc256_mac_test(void) +{ + unsigned char key[][32] = { + {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}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} + }; + unsigned char iv[][23] = { + {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}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff}, + }; + unsigned char msg[][50] = { + /* 400 zero bits */ + {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}, + /* 4000 bits */ + {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, + /* 400 zero bits */ + {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}, + /* 4000 bits */ + {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, + }; + unsigned int msg_num[] = { + 1, + 10, + 1, + 10 + }; + unsigned int tag32[][1] = { + {0x9b972a74}, + {0x8754f5cf}, + {0x1f3079b4}, + {0x5c7c8b88}, + }; + unsigned int tag64[][2] = { + {0x673e5499,0x0034d38c}, + {0x130dc225,0xe72240cc}, + {0x8c71394d,0x39957725}, + {0xea1dee54,0x4bb6223b}, + }; + unsigned int tag128[][4] = { + {0xd85e54bb,0xcb960096,0x7084c952,0xa1654b26}, + {0xdf1e8307,0xb31cc62b,0xeca1ac6f,0x8190c22f}, + {0xa35bb274,0xb567c48b,0x28319f11,0x1af34fbd}, + {0x3a83b554,0xbe408ca5,0x494124ed,0x9d473205}, + }; + unsigned int i, j; + + bswap_buf((uint32_t *)tag32, sizeof(tag32)/4); + bswap_buf((uint32_t *)tag64, sizeof(tag64)/4); + bswap_buf((uint32_t *)tag128, sizeof(tag128)/4); + + for (i = 0; i < 4; i++) { + ZUC256_MAC_CTX ctx; + unsigned char mac[16]; + + zuc256_mac_init(&ctx, key[i], iv[i], 32); + for (j = 0; j < msg_num[i]; j++) { + zuc256_mac_update(&ctx, msg[i], 50); + } + zuc256_mac_finish(&ctx, NULL, 0, mac); + if (memcmp(mac, tag32[i], 4) != 0) { + printf("zuc256 mac test %d 32-bit failed\n", i); + error_print(); + return -1; + } else { + printf("zuc256 mac test %d 32-bit ok\n", i); + } + + zuc256_mac_init(&ctx, key[i], iv[i], 64); + for (j = 0; j < msg_num[i]; j++) { + zuc256_mac_update(&ctx, msg[i], 50); + } + zuc256_mac_finish(&ctx, NULL, 0, mac); + if (memcmp(mac, tag64[i], 8) != 0) { + printf("zuc256 mac test %d 64-bit failed\n", i); + error_print(); + return -1; + } else { + printf("zuc256 mac test %d 64-bit ok\n", i); + } + + zuc256_mac_init(&ctx, key[i], iv[i], 128); + for (j = 0; j < msg_num[i]; j++) { + zuc256_mac_update(&ctx, msg[i], 50); + } + zuc256_mac_finish(&ctx, NULL, 0, mac); + if (memcmp(mac, tag128[i], 16) != 0) { + printf("zuc256 mac test %d 128-bit failed\n", i); + error_print(); + return -1; + } else { + printf("zuc256 mac test %d 128-bit ok\n", i); + } + } + + return 1; +} + +int main(void) +{ + if (zuc_test() != 1) { error_print(); return -1; } + if (zuc_eea_test() != 1) { error_print(); return -1; } + if (zuc_eia_test() != 1) { error_print(); return -1; } + if (zuc256_test() != 1) { error_print(); return -1; } + if (zuc256_mac_test() != 1) { error_print(); return -1; } + return 0; +} diff --git a/Core/GmSSL-3.1.1/tools/certgen.c b/Core/GmSSL-3.1.1/tools/certgen.c new file mode 100644 index 0000000..6c8301f --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/certgen.c @@ -0,0 +1,553 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = + "[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str" + " -serial_len num" + " -days num" + " -key pem -pass pass" + " [-sm2_id str | -sm2_id_hex hex]" + " [-gen_authority_key_id]" + " [-gen_subject_key_id]" + " [-key_usage str]*" + " [-subject_dns_name str]*" + " [-issuer_dns_name str]*" + " [-ca -path_len_constraint num]" + " [-ext_key_usage str]*" + " [-crl_http_uri uri] [-crl_ldap_uri uri]" + " [-inhibit_any_policy num]" + " [-ca_issuers_uri uri] [-ocsp_uri uri uri]" + " [-out pem]"; + +static char *usage = +"Options\n" +"\n" +" -serial_len num Serial number length in bytes\n" +" -days num Validity peroid in days\n" +" -key file Private key file in PEM format\n" +" -pass pass Password for decrypting private key file\n" +" -sm2_id str Signer's ID in SM2 signature algorithm\n" +" -sm2_id_hex hex Signer's ID in hex format\n" +" When `-sm2_id` or `-sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" +" -out file Output certificate file in PEM format\n" +"\n" +" Subject and Issuer options\n" +"\n" +" -C str Country\n" +" -ST str State or province name\n" +" -L str Locality\n" +" -O str Organization\n" +" -OU str Organizational unit\n" +" -CN str Common name\n" +"\n" +" Extension options\n" +"\n" +" -gen_authority_key_id Generate AuthorityKeyIdentifier extension use SM3\n" +" -gen_subject_key_id Generate SubjectKeyIdentifier extension use SM3\n" +" -key_usage str Add KeyUsage extension\n" +" this option can be called multi-times\n" +" avaiable values:\n" +" * digitalSignature\n" +" * nonRepudiation\n" +" * keyEncipherment\n" +" * dataEncipherment\n" +" * keyAgreement\n" +" * keyCertSign\n" +" * cRLSign\n" +" * encipherOnly\n" +" * decipherOnly\n" +" -subject_dns_name str Add DNS name to SubjectAltName extension\n" +" this option can be called multi-times\n" +" -issuer_dns_name str Add DNS name to IssuerAltName extension\n" +" this option can be called multi-times\n" +" -ca Set cA of BasicConstaints extension\n" +" -path_len_constraint num Set pathLenConstraint of BasicConstaints extension\n" +" -ext_key_usage str Set ExtKeyUsage extension\n" +" this option can be called multi-times\n" +" avaiable values:\n" +" * anyExtendedKeyUsage\n" +" * serverAuth\n" +" * clientAuth\n" +" * codeSigning\n" +" * emailProtection\n" +" * timeStamping\n" +" * OCSPSigning\n" +" -crl_http_uri uri Set HTTP URI of CRL of CRLDistributionPoints extension\n" +" -crl_ldap_uri uri Set LDAP URI of CRL of CRLDistributionPoints extension\n" +" -inhibit_any_policy num Set skipCerts number of InhibitAnyPolicy extension\n" +" -ca_issuers_uri uri Set URI of the CA certificate in DER-encoding o FreshestCRL extension\n" +" -ocsp_uri uri Set OCSP URI of FreshestCRL extension\n" +"\n" +"Examples\n" +"\n" +" gmssl sm2keygen -pass P@ssw0rd -out rootcakey.pem\n" +"\n" +" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \\\n" +" -key rootcakey.pem -pass P@ssw0rd \\\n" +" -ca -path_len_constraint 6 \\\n" +" -key_usage keyCertSign -key_usage cRLSign \\\n" +" -crl_http_uri http://pku.edu.cn/ca.crl \\\n" +" -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn \\\n" +" -out rootcacert.pem\n" +"\n"; + + +static int ext_key_usage_set(int *usages, const char *usage_name) +{ + int flag; + if (x509_key_usage_from_name(&flag, usage_name) != 1) { + error_print(); + return -1; + } + *usages |= flag; + return 1; +} + +int certgen_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + // SerialNumber + uint8_t serial[20]; + int serial_len = 12; + + // Issuer, Subject + uint8_t name[256]; + size_t namelen; + char *country = NULL; + char *state = NULL; + char *locality = NULL; + char *org = NULL; + char *org_unit = NULL; + char *common_name = NULL; + + // Validity + int days = 0; + time_t not_before; + time_t not_after; + + // Private Key + FILE *keyfp = NULL; + char *pass = NULL; + SM2_KEY sm2_key; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + uint8_t *cert = NULL; + size_t certlen = 0; + FILE *outfp = stdout; + char *outfile = NULL; + uint8_t *p; + + // Extensions + uint8_t exts[4096]; + size_t extslen = 0; + + // AuthorityKeyIdentifier + int gen_authority_key_id = 0; + + // SubjectKeyIdentifier + int gen_subject_key_id = 0; + + // KeyUsage + int key_usage = 0; + + // SubjectAltName + uint8_t subject_alt_name[2048]; + size_t subject_alt_name_len = 0; + + // IssuerAltName + uint8_t issuer_alt_name[512]; + size_t issuer_alt_name_len = 0; + + // BasicConstraints + int ca = -1; + int path_len_constraint = -1; + + // ExtKeyUsageSyntax + int ext_key_usages[12]; + size_t ext_key_usages_cnt = 0; + + // CRLDistributionPoints + char *crl_http_uri = NULL; + char *crl_ldap_uri = NULL; + + // InhibitAnyPolicy + int inhibit_any_policy = -1; + + // FreshestCRL + char *ca_issuers_uri = NULL; + char *ocsp_uri = NULL; + + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: gmssl %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n\n", prog, options); + printf("%s\n", usage); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-serial_len")) { + if (--argc < 1) goto bad; + serial_len = atoi(*(++argv)); + if (serial_len <= 0 || serial_len > sizeof(serial)) { + fprintf(stderr, "%s: invalid `-serial_len` value, need a number less than %zu\n", prog, sizeof(serial)); + goto end; + } + } else if (!strcmp(*argv, "-CN")) { + if (--argc < 1) goto bad; + common_name = *(++argv); + } else if (!strcmp(*argv, "-O")) { + if (--argc < 1) goto bad; + org = *(++argv); + } else if (!strcmp(*argv, "-OU")) { + if (--argc < 1) goto bad; + org_unit = *(++argv); + } else if (!strcmp(*argv, "-C")) { + if (--argc < 1) goto bad; + country = *(++argv); + if (strlen(country) != 2) { + fprintf(stderr, "%s: invalid '-C' value, need 2-char country name such as 'CN', 'US'\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-ST")) { + if (--argc < 1) goto bad; + state = *(++argv); + } else if (!strcmp(*argv, "-L")) { + if (--argc < 1) goto bad; + locality = *(++argv); + } else if (!strcmp(*argv, "-days")) { + if (--argc < 1) goto bad; + days = atoi(*(++argv)); + if (days <= 0) { + fprintf(stderr, "%s: invalid `-days` value, need a positive number\n", prog); + goto end; + } + + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (!(keyfp = fopen(str, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(signer_id) - 1) { + fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog); + goto end; + } + strncpy(signer_id, str, sizeof(signer_id)); + signer_id_len = strlen(str); + } else if (!strcmp(*argv, "-sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(signer_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog); + goto end; + } + + } else if (!strcmp(*argv, "-gen_authority_key_id")) { + gen_authority_key_id = 1; + } else if (!strcmp(*argv, "-gen_subject_key_id")) { + gen_subject_key_id = 1; + } else if (!strcmp(*argv, "-key_usage")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (ext_key_usage_set(&key_usage, str) != 1) { + fprintf(stderr, "%s: invalid `-key_usage` value '%s'\n", prog, str); + goto end; + } + } else if (!strcmp(*argv, "-subject_dns_name")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_general_names_add_dns_name( + subject_alt_name, &subject_alt_name_len, sizeof(subject_alt_name), str) != 1) { + fprintf(stderr, "%s: inner error on processing `-subject_dns_name`\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-issuer_dns_name")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_general_names_add_dns_name( + issuer_alt_name, &issuer_alt_name_len, sizeof(issuer_alt_name), str) != 1) { + fprintf(stderr, "%s: inner error on processing `-issuer_dns_name`\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-ca")) { + ca = 1; + } else if (!strcmp(*argv, "-path_len_constraint")) { + if (--argc < 1) goto bad; + path_len_constraint = atoi(*(++argv)); + if (path_len_constraint < 0) { + fprintf(stderr, "%s: invalid `-path_len_constraint` value\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-ext_key_usage")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_key_purpose_from_name(str) <= 0) { + fprintf(stderr, "%s: invalid `-ext_key_usage` value '%s'\n", prog, str); + goto end; + } + if (ext_key_usages_cnt >= sizeof(ext_key_usages)/sizeof(ext_key_usages[0])) { + fprintf(stderr, "%s: too much `-ext_key_usage` options\n", prog); + goto end; + } + ext_key_usages[ext_key_usages_cnt++] = x509_key_purpose_from_name(str); + } else if (!strcmp(*argv, "-crl_http_uri")) { + if (--argc < 1) goto bad; + crl_http_uri = *(++argv); + } else if (!strcmp(*argv, "-crl_ldap_uri")) { + if (--argc < 1) goto bad; + crl_ldap_uri = *(++argv); + } else if (!strcmp(*argv, "-inhibit_any_policy")) { + if (--argc < 1) goto bad; + inhibit_any_policy = atoi(*(++argv)); + if (inhibit_any_policy < 0) { + fprintf(stderr, "%s: invalid `-inhibit_any_policy` value\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-ca_issuers_uri")) { + if (--argc < 1) goto bad; + ca_issuers_uri = *(++argv); + } else if (!strcmp(*argv, "-ocsp_uri")) { + if (--argc < 1) goto bad; + ocsp_uri = *(++argv); + + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!common_name) { + fprintf(stderr, "%s: option `-CN` required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!days) { + fprintf(stderr, "%s: option `-days` required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!keyfp) { + fprintf(stderr, "%s: option `-key` required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: option `-pass` required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load private key failed\n", prog); + goto end; + } + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + + // Serial + if (rand_bytes(serial, sizeof(serial)) != 1) { + fprintf(stderr, "%s: RNG error\n", prog); + goto end; + } + + // Issuer, Subject + if (x509_name_set(name, &namelen, sizeof(name), country, state, locality, org, org_unit, common_name) != 1) { + fprintf(stderr, "%s: set Issuer/Subject Name error\n", prog); + goto end; + } + + // Validity + time(¬_before); + if (x509_validity_add_days(¬_after, not_before, days) != 1) { + fprintf(stderr, "%s: set Validity failure\n", prog); + goto end; + } + + // Extensions + if (gen_authority_key_id) { + if (x509_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sm2_key) != 1) { + fprintf(stderr, "%s: set AuthorityKeyIdentifier extension failure\n", prog); + goto end; + } + } + if (gen_subject_key_id) { + if (x509_exts_add_subject_key_identifier_ex(exts, &extslen, sizeof(exts), -1, &sm2_key) != 1) { + fprintf(stderr, "%s: set SubjectKeyIdentifier extension failure\n", prog); + goto end; + } + } + if (key_usage) { + if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), X509_critical, key_usage) != 1) { + fprintf(stderr, "%s: set KeyUsage extension failure\n", prog); + goto end; + } + } + // no CertificatePolicies + // no PolicyMappings + if (subject_alt_name_len) { + if (x509_exts_add_subject_alt_name(exts, &extslen, sizeof(exts), + -1, subject_alt_name, subject_alt_name_len) != 1) { + fprintf(stderr, "%s: set SubjectAltName extension failure\n", prog); + goto end; + } + } + if (issuer_alt_name_len) { + if (x509_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts), + -1, issuer_alt_name, issuer_alt_name_len) != 1) { + fprintf(stderr, "%s: set IssuerAltName extension failure\n", prog); + goto end; + } + } + // no SubjectDirectoryAttributes + if (ca >= 0 || path_len_constraint >= 0) { + if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts), + X509_critical, ca, path_len_constraint) != 1) { + fprintf(stderr, "%s: set BasicConstraints extension failure\n", prog); + goto end; + } + } + // no NameConstraints + // no PolicyConstraints + if (ext_key_usages_cnt) { + if (x509_exts_add_ext_key_usage(exts, &extslen, sizeof(exts), + -1, ext_key_usages, ext_key_usages_cnt) != 1) { + fprintf(stderr, "%s: set ExtKeyUsage extension failure\n", prog); + goto end; + } + } + if (crl_http_uri || crl_ldap_uri) { + if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts), + -1, + crl_http_uri, crl_http_uri ? strlen(crl_http_uri) : 0, + crl_ldap_uri, crl_ldap_uri ? strlen(crl_ldap_uri) : 0) != 1) { + fprintf(stderr, "%s: set CRLDistributionPoints extension failure\n", prog); + return -1; + } + } + if (inhibit_any_policy >= 0) { + if (x509_exts_add_inhibit_any_policy(exts, &extslen, sizeof(exts), + X509_critical, inhibit_any_policy) != 1) { + fprintf(stderr, "%s: set InhibitAnyPolicy extension failure\n", prog); + goto end; + } + } + if (ca_issuers_uri || ocsp_uri) { + if (x509_exts_add_authority_info_access(exts, &extslen, sizeof(exts), 0, + ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0, + ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) { + fprintf(stderr, "%s: set AuthorityInfoAccess extension failure\n", prog); + goto end; + } + } + + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + NULL, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + if (!(cert = malloc(certlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + p = cert; + certlen = 0; + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + name, namelen, + not_before, not_after, + name, namelen, + &sm2_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + &p, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + if (x509_cert_to_pem(cert, certlen, outfp) != 1) { + fprintf(stderr, "%s: output certificate failed\n", prog); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY)); + if (cert) free(cert); + if (keyfp) fclose(keyfp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/certparse.c b/Core/GmSSL-3.1.1/tools/certparse.c new file mode 100644 index 0000000..5bd1c86 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/certparse.c @@ -0,0 +1,97 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-in pem] [-out file]"; + +static char *usage = +"Options\n" +"\n" +" [-in pem]|stdin Input certificates in PEM format.\n" +" This command supports continuous multiple certificates\n" +" Do not include blank line or comments between PEM data\n" +" [-out file]stdout Output file\n" +"\n" +"Examples\n" +"\n" +" gmssl certparse -in certs.pem\n" +"\n"; + +int certparse_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + uint8_t cert[18192]; + size_t certlen; + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n\n", prog, options); + printf("%s\n", usage); + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + for (;;) { + int rv; + if ((rv = x509_cert_from_pem(cert, &certlen, sizeof(cert), infp)) != 1) { + if (rv < 0) fprintf(stderr, "%s: read certificate failure\n", prog); + else ret = 0; + goto end; + } + x509_cert_print(outfp, 0, 0, "Certificate", cert, certlen); + if (x509_cert_to_pem(cert, certlen, outfp) != 1) { + fprintf(stderr, "%s: output certficate failure\n", prog); + goto end; + } + } + +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/certrevoke.c b/Core/GmSSL-3.1.1/tools/certrevoke.c new file mode 100644 index 0000000..8d11102 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/certrevoke.c @@ -0,0 +1,155 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = + " -in pem" + " [-reason str]" + " [-invalid_date time]" + " -out der"; // on windows, send 0x0a through pipe will be connverted to 0x0d0a + // so stdout and pipe is not supported + +static char *usage = +"Options\n" +"\n" +" -in pem Certificate in PEM format to be revoked\n" +" -reason str Revocation reason code, avaiable codes:\n" +" * unspecified\n" +" * keyCompromise\n" +" * cACompromise\n" +" * affiliationChanged\n" +" * superseded\n" +" * cessationOfOperation\n" +" * certificateHold\n" +" * notAssigned\n" +" * removeFromCRL\n" +" * privilegeWithdrawn\n" +" * aACompromise\n" +" -invalid_date time The date on which it is known or suspected the certificate became invalid\n" +" Time in `YYYYMMDDHHMMSSZ` format such as 20221231000000Z\n" +" The last 'Z' means it is Zulu (GMT) time\n" +" -out der Output X.509 RevokedCertificate in DER-encoding\n" +" This file stores multiple RevokedCertificates, used as input by `crlsign`\n" +"\n" +"Examples\n" +"\n" +" gmssl certrevoke -in cert1.pem -reason keyCompromise -invalid_date 20221230000000Z -out revoked_certs.der\n" +" gmssl certrevoke -in cert1.pem -reason keyCompromise -invalid_date 20221230000000Z >> revoked_certs.der\n" +"\n"; + + +int certrevoke_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + uint8_t *cert = NULL; + size_t certlen; + int reason = -1; + time_t invalid_date = -1; + char *outfile = NULL; + FILE *outfp = NULL; + uint8_t *outbuf = NULL; + uint8_t *out; + size_t outlen = 0; + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n\n", prog, options); + printf("%s", usage); + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_cert_new_from_file(&cert, &certlen, str) != 1) { + fprintf(stderr, "%s: open cert file '%s' failure\n", prog, str); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "ab"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-reason")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_crl_reason_from_name(&reason, str) != 1) { + fprintf(stderr, "%s: invalid reason '%s'\n", prog, str); + goto end; + } + } else if (!strcmp(*argv, "-invalid_date")) { + if (--argc < 1) goto bad; + str =*(++argv); + if (asn1_time_from_str(0, &invalid_date, str) != 1) { + fprintf(stderr, "%s: invalid time '%s', should in 'YYYYMMDDHHMMSSZ' format\n", prog, str); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!cert) { + fprintf(stderr, "%s: option `-in` missing\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!outfile) { + fprintf(stderr, "%s: option `-out` missing\n", prog); + goto end; + } + + if (x509_cert_revoke_to_der(cert, certlen, time(NULL), reason, invalid_date, NULL, 0, NULL, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (!(outbuf = malloc(outlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + out = outbuf; + outlen = 0; + if (x509_cert_revoke_to_der(cert, certlen, time(NULL), reason, invalid_date, NULL, 0, &out, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure\n", prog); + goto end; + } + ret = 0; + +end: + if (cert) free(cert); + if (outfile && outfp) fclose(outfp); + if (outbuf) free(outbuf); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/certverify.c b/Core/GmSSL-3.1.1/tools/certverify.c new file mode 100644 index 0000000..d184648 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/certverify.c @@ -0,0 +1,312 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *usage = + " -in pem [-double_certs]" + " [-check_crl]" + " -cacert pem" + " [-sm2_id str | -sm2_id_hex hex]" + "\n"; + +static const char *options = +"Options\n" +"\n" +" -in pem Input certificate chain file in PEM format\n" +" -double_certs The first two certificates are SM2 signing and encryption entity certificate\n" +" -check_crl If the entity certificate has CRLDistributionPoints extension, Download and check againt the CRL\n" +" -cacert pem CA certificate\n" +" -sm2_id str Signer's ID in SM2 signature algorithm\n" +" -sm2_id_hex hex Signer's ID in hex format\n" +" When `-sm2_id` or `-sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" +"\n"; + + +int certverify_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + char *infile = NULL; + char *cacertfile = NULL; + FILE *infp = stdin; + FILE *cacertfp = NULL; + uint8_t cert[1024]; + size_t certlen; + uint8_t cacert[1024]; + size_t cacertlen; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + const uint8_t *serial; + size_t serial_len; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *subject; + size_t subject_len; + + const uint8_t *enc_serial; + size_t enc_serial_len; + const uint8_t *enc_issuer; + size_t enc_issuer_len; + const uint8_t *enc_subject; + size_t enc_subject_len; + + int double_certs = 0; + uint8_t enc_cert[1024]; + size_t enc_cert_len; + int rv; + + int check_crl = 0; + int crl_ret; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, usage); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, usage); + printf("%s\n", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-double_certs")) { + double_certs = 1; + } else if (!strcmp(*argv, "-check_crl")) { + check_crl = 1; + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + if (!(cacertfp = fopen(cacertfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, cacertfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(signer_id) - 1) { + fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog); + goto end; + } + strncpy(signer_id, str, sizeof(signer_id)); + signer_id_len = strlen(str); + } else if (!strcmp(*argv, "-sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(signer_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + + if (!infile) { + fprintf(stderr, "%s: '-in' option required\n", prog); + goto end; + } + if (!cacertfile) { + fprintf(stderr, "%s: '-cacert' option required\n", prog); + goto end; + } + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + + // read first to be verified certificate + if (x509_cert_from_pem(cert, &certlen, sizeof(cert), infp) != 1 + || x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { + fprintf(stderr, "%s: read certificate failure\n", prog); + goto end; + } + format_print(stdout, 0, 0, "Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", serial, serial_len); + x509_name_print(stdout, 0, 4, "subject", subject, subject_len); + + // read encryption cert in double certs + if (double_certs) { + if (x509_cert_from_pem(enc_cert, &enc_cert_len, sizeof(enc_cert), infp) != 1 + || x509_cert_get_issuer_and_serial_number(enc_cert, enc_cert_len, + &enc_issuer, &enc_issuer_len, &enc_serial, &enc_serial_len) != 1 + || x509_cert_get_subject(enc_cert, enc_cert_len, &enc_subject, &enc_subject_len) != 1) { + fprintf(stderr, "%s: read encryption certficate failure\n", prog); + goto end; + } + if (x509_name_equ(enc_subject, enc_subject_len, subject, subject_len) != 1 + || x509_name_equ(enc_issuer, enc_issuer_len, issuer, issuer_len) != 1) { + fprintf(stderr, "%s: double certificates not compatible\n", prog); + goto end; + } + } + + for (;;) { + if ((rv = x509_cert_from_pem(cacert, &cacertlen, sizeof(cacert), infp)) != 1) { + if (rv < 0) goto end; + goto final; + } + + if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) != 1) { + fprintf(stderr, "%s: Verification failure\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Verification success\n"); + + if (check_crl) { + if ((crl_ret = x509_cert_check_crl(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: Certificate has been revoked\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); + } + + if (double_certs) { + if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: Verification failure\n", prog); + goto end; + } + format_print(stdout, 0, 0, "Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", enc_serial, enc_serial_len); + x509_name_print(stdout, 0, 4, "subject", enc_subject, enc_subject_len); + format_print(stdout, 0, 4, "Verification success\n"); + if (check_crl) { + if ((crl_ret = x509_cert_check_crl(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: Certificate has been revoked\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); + } + double_certs = 0; + + } + + // NOTE: make sure the buffer (issuer, issuer_len) not crashed + memcpy(cert, cacert, cacertlen); + certlen = cacertlen; + if (x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { + error_print(); + goto end; + } + format_print(stdout, 0, 0, "Signed by Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", serial, serial_len); + x509_name_print(stdout, 0, 4, "Certificate", subject, subject_len); + + check_crl = 0; // only check the entity CRL + + } + +final: + if (x509_cert_from_pem_by_subject(cacert, &cacertlen, sizeof(cacert), issuer, issuer_len, cacertfp) != 1) { + fprintf(stderr, "%s: load CA certificate failure\n", prog); + goto end; + } + if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Verification success\n"); + + if (check_crl) { + if ((crl_ret = x509_cert_check_crl(cert, certlen, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: certificate has been revoked\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); + } + + if (double_certs) { + if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + format_print(stdout, 0, 0, "Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", enc_serial, enc_serial_len); + x509_name_print(stdout, 0, 4, "subject", enc_subject, enc_subject_len); + format_print(stdout, 0, 4, "Verification success\n"); + + if (check_crl) { + if ((crl_ret = x509_cert_check_crl(enc_cert, enc_cert_len, cacert, cacertlen, + signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: certificate has been revoked\n", prog); + goto end; + } + format_print(stdout, 0, 4, "Revocation status: %s\n", + crl_ret ? "Not revoked by CRL" : "No CRL URI found in certificate"); + } + } + + if (x509_cert_get_issuer_and_serial_number(cacert, cacertlen, NULL, NULL, &serial, &serial_len) != 1 + || x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1) { + fprintf(stderr, "%s: parse certificate error\n", prog); + goto end; + } + format_print(stdout, 0, 0, "Signed by Certificate\n"); + format_bytes(stdout, 0, 4, "serialNumber", serial, serial_len); + x509_name_print(stdout, 0, 4, "subject", subject, subject_len); + + printf("\n"); + + ret = 0; +end: + if (infile && infp) fclose(infp); + if (cacertfp) fclose(cacertfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/cmsdecrypt.c b/Core/GmSSL-3.1.1/tools/cmsdecrypt.c new file mode 100644 index 0000000..d3460f2 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/cmsdecrypt.c @@ -0,0 +1,180 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + + +static const char *options = "-key file -pass str -cert file -in file [-out file]"; + +int cmsdecrypt_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyfile = NULL; + char *pass = NULL; + char *certfile = NULL; + char *infile = NULL; + char *outfile = NULL; + FILE *keyfp = NULL; + FILE *certfp = NULL; + FILE *infp = NULL; + FILE *outfp = stdout; + uint8_t cert[1024]; + size_t certlen; + size_t inlen; + uint8_t *cms = NULL; + size_t cmslen, cms_maxlen; + SM2_KEY key; + int content_type; + uint8_t *content = NULL; + size_t content_len; + const uint8_t *rcpt_infos; + size_t rcpt_infos_len; + const uint8_t *shared_info1; + const uint8_t *shared_info2; + size_t shared_info1_len, shared_info2_len; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + if (!(certfp = fopen(certfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!keyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + goto end; + } + if (!certfile) { + fprintf(stderr, "%s: '-cert' option required\n", prog); + goto end; + } + if (!infile) { + fprintf(stderr, "%s: '-in' option required\n", prog); + goto end; + } + + if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { + fprintf(stderr, "%s: private key decryption failure\n", prog); + goto end; + } + if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1) { + fprintf(stderr, "%s: load certificate failure\n", prog); + goto end; + } + + if (file_size(infp, &inlen) != 1) { + fprintf(stderr, "%s: get input length failed\n", prog); + goto end; + } + cms_maxlen = (inlen * 3)/4 + 1; + if (!(cms = malloc(cms_maxlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (cms_from_pem(cms, &cmslen, cms_maxlen, infp) != 1) { + fprintf(stderr, "%s: read CMS failure\n", prog); + goto end; + } + + if (!(content = malloc(cmslen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + + if (cms_deenvelop(cms, cmslen, + &key, cert, certlen, + &content_type, content, &content_len, + &rcpt_infos, &rcpt_infos_len, + &shared_info1, &shared_info1_len, + &shared_info2, &shared_info2_len) != 1) { + fprintf(stderr, "%s: decryption failure\n", prog); + goto end; + } + if (content_type != OID_cms_data) { + fprintf(stderr, "%s: invalid CMS content type: %s\n", prog, cms_content_type_name(content_type)); + goto end; + } + + if (fwrite(content, 1, content_len, outfp) != content_len) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + if (keyfile && keyfp) fclose(keyfp); + if (cms) free(cms); + if (content) free(content); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/cmsencrypt.c b/Core/GmSSL-3.1.1/tools/cmsencrypt.c new file mode 100644 index 0000000..efdd0de --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/cmsencrypt.c @@ -0,0 +1,235 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + +签名的时候要提供签名者的证书,并且提供签名私钥 +但是验证的时候假定CMS中已经包含签名者的证书了,但是我们要提供CA证书库 + +加密的时候要指定接收者的证书,并且可以有多个接收者 +解密的时候只提供一个解密私钥,但是最好配合解密者的证书,从这个证书中找到解密者的名字 + +如果即加密又签名,那么输出的是SignedAndEnveloped + +CMS有PEM吗? + +cms -encrypt -rcpt a.pem -rcpt b.pem -rcpt c.pem -in file -sign -signcert a.pem -signcert b.pem + -rcptcert -rcpt_cert -sign_cert b.pem -signkey + +首先接收者可以有多个证书 + +这里面有个问题,因为我们要输出一个加密的对象,因此我们必须把输入的内容读取进来。 + + +EnvelopedData 是一个封装的SEQUENCE中,因此必须读取所有的内容。 +如果是一个文件,就需要读取所有的文件内容,如果是一个stream ,也需要读取完整的内容到一个足够大的buffer中,如何设置这个buffer的大小呢 + + + +对于输入文件,如果输入有文件名的话,可以直接通过stat获取文件长度 +但是如果对于stream的话,实际上我们是没有办法获得输入长度的,那么就直接准备一个buffer好了。 +不要给自己找麻烦了,直接只支持文件输入吧 +encrypt + +*/ + +static const char *options = "-encrypt (-rcptcert pem)* -in file -out file"; + + +static int get_files_size(int argc, char **argv, const char *option, size_t *len) +{ + char *prog = argv[0]; + char *file = NULL; + FILE *fp = NULL; + + argc--; + argv++; + + *len = 0; + while (argc > 1) { + if (!strcmp(*argv, option)) { + size_t fsize; + + if (--argc < 1) { + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + return -1; + } + file = *(++argv); + + if (!(fp = fopen(file, "rb"))) { + fprintf(stderr, "%s: open '%s' failed : %s\n", prog, file, strerror(errno)); + return -1; + } + if (file_size(fp, &fsize) != 1) { + fprintf(stderr, "%s: access '%s' failed : %s\n", prog, file, strerror(errno)); + fclose(fp); + return -1; + } + *len += fsize; + fclose(fp); + } + argc--; + argv++; + } + + return 1; +} + +int cmsencrypt_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int op = 0; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + uint8_t *rcpt_certs = NULL; + size_t rcpt_certs_len; + uint8_t key[16]; + uint8_t iv[16]; + uint8_t *inbuf = NULL; + size_t inlen; + uint8_t *cms = NULL; + size_t cmslen; + uint8_t *cert; + + if (argc < 2) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + // 预先统计证书缓冲大小和输入大小 + if (get_files_size(argc, argv, "-rcptcert", &rcpt_certs_len) != 1) { + goto end; + } + if (rcpt_certs_len <= 0) { + fprintf(stderr, "%s: invalid cert length\n", prog); + goto end; + } + rcpt_certs_len = (rcpt_certs_len * 3)/4; + if (!(rcpt_certs = malloc(rcpt_certs_len))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + cert = rcpt_certs; + + if (get_files_size(argc, argv, "-in", &inlen) != 1) { + goto end; + } + if (inlen <= 0) { + fprintf(stderr, "%s: invalid input length\n", prog); + goto end; + } + if (!(inbuf = malloc(inlen))) { + fprintf(stderr, "%s: %s\n", prog, strerror(errno)); + goto end; + } + + argc--; + argv++; + + while (argc > 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-rcptcert")) { + char *certfile; + FILE *certfp; + size_t certlen; + if (--argc < 1) goto bad; + certfile = *(++argv); + if (!(certfp = fopen(certfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno)); + goto end; + } + if (x509_cert_from_pem(cert, &certlen, rcpt_certs_len, certfp) != 1) { + fprintf(stderr, "%s: error\n", prog); + fclose(certfp); + goto end; + } + cert += certlen; + fclose(certfp); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + if ((inlen = fread(inbuf, 1, inlen, infp)) <= 0) { + fprintf(stderr, "%s: read data error: %s\n", prog, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + rcpt_certs_len = cert - rcpt_certs; + + if (rand_bytes(key, sizeof(key)) != 1 + || rand_bytes(iv, sizeof(iv)) != 1 + || cms_envelop(NULL, &cmslen, rcpt_certs, rcpt_certs_len, + OID_sm4_cbc, key, sizeof(key), iv, sizeof(iv), + OID_cms_data, inbuf, inlen, NULL, 0, NULL, 0) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (!(cms = malloc(cmslen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (cms_envelop(cms, &cmslen, rcpt_certs, rcpt_certs_len, + OID_sm4_cbc, key, sizeof(key), iv, sizeof(iv), + OID_cms_data, inbuf, inlen, NULL, 0, NULL, 0) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (cms_to_pem(cms, cmslen, outfp) != 1) { + fprintf(stderr, "%s: output CMS failure\n", prog); + goto end; + } + + ret = 0; + +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + if (rcpt_certs) free(rcpt_certs); + if (inbuf) free(inbuf); + if (cms) free(cms); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/cmsparse.c b/Core/GmSSL-3.1.1/tools/cmsparse.c new file mode 100644 index 0000000..204f524 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/cmsparse.c @@ -0,0 +1,88 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "-in file"; + +int cmsparse_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + FILE *infp = stdin; + size_t inlen; + uint8_t *cms = NULL; + size_t cms_maxlen, cmslen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + while (argc > 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!infile) { + fprintf(stderr, "%s: option '-in' required'\n", prog); + goto end; + } + + if (file_size(infp, &inlen) != 1) { // FIXME: infp == stdin? + fprintf(stderr, "%s: access '%s' failed : %s\n", prog, infile, strerror(errno)); + goto end; + } + cms_maxlen = (inlen * 3)/4 + 1; + if (!(cms = malloc(cms_maxlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (cms_from_pem(cms, &cmslen, cms_maxlen, infp) != 1) { + fprintf(stderr, "%s: parse CMS error\n", prog); + goto end; + } + cms_print(stdout, 0, 0, "CMS", cms, cmslen); + ret = 0; +end: + if (infp) fclose(infp); + if (cms) free(cms); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/cmssign.c b/Core/GmSSL-3.1.1/tools/cmssign.c new file mode 100644 index 0000000..f6d1c14 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/cmssign.c @@ -0,0 +1,193 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* +302 typedef struct { +303 uint8_t *certs; +304 size_t certs_len; +305 SM2_KEY *sign_key; +306 } CMS_CERTS_AND_KEY; + + + +输出长度主要由输入长度和 + +*/ + +static const char *options = "-key file -pass str -cert file -in file [-out file]"; + +int cmssign_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyfile = NULL; + char *pass = NULL; + char *certfile = NULL; + char *infile = NULL; + char *outfile = NULL; + FILE *keyfp = NULL; + FILE *certfp = NULL; + FILE *infp = NULL; + FILE *outfp = stdout; + SM2_KEY key; + uint8_t cert[1024]; + size_t certlen; + uint8_t *in = NULL; + size_t inlen; + uint8_t *cms = NULL; + size_t cmslen, cms_maxlen; + CMS_CERTS_AND_KEY cert_and_key; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + if (!(certfp = fopen(certfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!keyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + goto end; + } + if (!certfile) { + fprintf(stderr, "%s: '-cert' option required\n", prog); + goto end; + } + if (!infile) { + fprintf(stderr, "%s: '-in' option required\n", prog); + goto end; + } + + if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { + fprintf(stderr, "%s: private key decryption failure\n", prog); + goto end; + } + if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1) { + fprintf(stderr, "%s: load certificate failure\n", prog); + goto end; + } + { + SM2_KEY public_key; + if (x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) { + fprintf(stderr, "%s: parse certficate failure\n", prog); + goto end; + } + if (sm2_public_key_equ(&key, &public_key) != 1) { + fprintf(stderr, "%s: key and cert are not match!\n", prog); + goto end; + } + } + + cert_and_key.certs = cert; + cert_and_key.certs_len = certlen; + cert_and_key.sign_key = &key; + + if (file_size(infp, &inlen) != 1) { + fprintf(stderr, "%s: get input length failed\n", prog); + goto end; + } + if (!(in = malloc(inlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (fread(in, 1, inlen, infp) != inlen) { + fprintf(stderr, "%s: read file error : %s\n", prog, strerror(errno)); + goto end; + } + + cms_maxlen = (inlen * 4)/3 + 4096; // 主要由SignerInfos,其中的DN长度决定 + if (!(cms = malloc(cms_maxlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + + if (cms_sign(cms, &cmslen, &cert_and_key, 1, OID_cms_data, in, inlen, NULL, 0) != 1) { + fprintf(stderr, "%s: sign failure\n", prog); + goto end; + } + + if (cms_to_pem(cms, cmslen, outfp) != 1) { + fprintf(stderr, "%s: output failure\n", prog); + goto end; + } + + ret = 0; + +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + if (keyfile && keyfp) fclose(keyfp); + if (cms) free(cms); + if (in) free(in); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/cmsverify.c b/Core/GmSSL-3.1.1/tools/cmsverify.c new file mode 100644 index 0000000..7112511 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/cmsverify.c @@ -0,0 +1,141 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + + +static const char *options = "-in file [-out file]"; + +int cmsverify_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = NULL; + FILE *outfp = NULL; + size_t inlen; + uint8_t *cms = NULL; + size_t cmslen, cms_maxlen; + int content_type; + const uint8_t *content; + size_t content_len; + const uint8_t *certs; + size_t certslen; + const uint8_t *crls; + size_t crlslen; + const uint8_t *signer_infos; + size_t signer_infos_len; + int rv; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!infile) { + fprintf(stderr, "%s: '-in' option required\n", prog); + goto end; + } + if (file_size(infp, &inlen) != 1) { + fprintf(stderr, "%s: get input length failed\n", prog); + goto end; + } + cms_maxlen = (inlen * 3)/4 + 1; + if (!(cms = malloc(cms_maxlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (cms_from_pem(cms, &cmslen, cms_maxlen, infp) != 1) { + fprintf(stderr, "%s: read CMS failure\n", prog); + goto end; + } + + if ((rv = cms_verify(cms, cmslen, NULL, 0, NULL, 0, + &content_type, &content, &content_len, + &certs, &certslen, &crls, &crlslen, + &signer_infos, &signer_infos_len)) < 0) { + fprintf(stderr, "%s: verify error\n", prog); + goto end; + } + printf("verify %s\n", rv ? "success" : "failure"); + ret = rv ? 0 : 1; + + if (outfile) { + const uint8_t *p; + size_t len; + + if (content_type == OID_cms_data) { + if (asn1_octet_string_from_der(&p, &len, &content, &content_len) != 1 + || asn1_length_is_zero(content_len) != 1) { + fprintf(stderr, "%s: invalid CMS\n", prog); + goto end; + } + if (len != fwrite(p, 1, len, outfp)) { + fprintf(stderr, "%s: output error : %s\n", prog, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: error\n", prog); + goto end; + } + + } + + + +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + if (cms) free(cms); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/copyright.sh b/Core/GmSSL-3.1.1/tools/copyright.sh new file mode 100755 index 0000000..3a94ab4 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/copyright.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +YEAR=$(date "+%Y") +COPYRIGHT="" +COPYRIGHT+="/*"$'\n' +COPYRIGHT+=" * Copyright 2014-$YEAR The GmSSL Project. All Rights Reserved."$'\n' +COPYRIGHT+=" *"$'\n' +COPYRIGHT+=" * Licensed under the Apache License, Version 2.0 (the "License"); you may"$'\n' +COPYRIGHT+=" * not use this file except in compliance with the License."$'\n' +COPYRIGHT+=" *"$'\n' +COPYRIGHT+=" * http://www.apache.org/licenses/LICENSE-2.0"$'\n' +COPYRIGHT+=" */" +COPYRIGHT_FILE=copyright.txt +echo "$COPYRIGHT" >$COPYRIGHT_FILE +TEMP_FILE=tempfile.temp +touch $TEMP_FILE +copyright_start_string="/*" +copyright_end_string="*/" + +function modify_copyright() { + file_path=$1 + copyright_start_line=$(grep -n "/\*" $file_path | head -1 | cut -d ':' -f 1) + copyright_end_line=$(grep -n "\*/" $file_path | head -1 | cut -d ':' -f 1) + echo $file_path $copyright_start_line $copyright_end_line + if [[ $copyright_start_line && $copyright_end_line ]]; then + sed -i $copyright_start_line,$copyright_end_line'd' $file_path + fi + + cat $COPYRIGHT_FILE >$TEMP_FILE + cat $file_path >>$TEMP_FILE + mv $TEMP_FILE $file_path + +} + +function getDir() { + for filename in $1/*; do + if [[ -d $filename ]]; then + getDir $filename + else + if [[ "${filename##*.}" == 'h' || "${filename##*.}" == 'c' ]]; then + modify_copyright $filename + #sed -i "1i\/*$filename*/" $filename + fi + fi + done +} + +getDir .. + +rm -f $COPYRIGHT_FILE diff --git a/Core/GmSSL-3.1.1/tools/crlgen.c b/Core/GmSSL-3.1.1/tools/crlgen.c new file mode 100644 index 0000000..376de61 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/crlgen.c @@ -0,0 +1,326 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *usage = + " -in revoked_certs" + " -cacert pem -key pem -pass pass [-sm2_id str | -sm2_id_hex hex]" + " [-next_update time] " + " [-gen_authority_key_id]" + " [-crl_num num]" + " [-delta_crl_indicator num]" + " [-ca_issuers_uri uri]" + " [-ocsp_uri uri]" + " [-out der]\n"; + +static const char *options = +"Options\n" +"\n" +" -in revoked_certs To be revoked certificate list\n" +" This input file format is DER-encoding of SEQUENCE OF RevokedCertificate\n" +" revoked_certs.der can be generated by `gmssl certrevoke`\n" +" -cacert pem The issuer certificate\n" +" -key pem The issuer private key\n" +" -pass pass Password for decrypting private key file\n" +" -sm2_id str Authority's ID in SM2 signature algorithm\n" +" -sm2_id_hex hex Authority's ID in hex format\n" +" When `-sm2_id` or `-sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" +" -next_update time Optional CRL attribute\n" +" -out der | stdout Output CRL in DER-encoding\n" +"\n" +"Examples\n" +"\n" +" gmssl crlgen -in revoked_certs.der -cacert cacert.pem -key cakey.pem -pass P@ssw0rd -gen_authority_key_id -crl_num 1\n" +" gmssl crlgen -in revoked_certs.der -cacert cacert.pem -key cakey.pem -pass P@ssw0rd -gen_authority_key_id -crl_num 2\n" +"\n"; + +int crlgen_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + uint8_t *revoked_certs = NULL; + size_t revoked_certs_len = 0; + + char *outfile = NULL; + FILE *outfp = stdout; + uint8_t *outbuf = NULL; + uint8_t *out; + size_t outlen = 0; + + uint8_t *cacert = NULL; + size_t cacert_len = 0; + FILE *keyfp = NULL; + char *pass = NULL; + SM2_KEY sign_key; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + const uint8_t *issuer; + size_t issuer_len; + time_t this_update = time(NULL); + time_t next_update = -1; + + uint8_t exts[512]; + size_t extslen = 0; + int gen_authority_key_id = 0; + int crl_num = -1; + int delta_crl_indicator = -1; + char *http_uri = NULL; + char *ldap_uri = NULL; + char *ca_issuers_uri = NULL; + char *ocsp_uri = NULL; + + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n\n", prog, usage); + printf("%s\n", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (file_read_all(str, &revoked_certs, &revoked_certs_len) != 1) { + fprintf(stderr, "%s: read input file '%s' failed\n", prog, str); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_cert_new_from_file(&cacert, &cacert_len, str) != 1) { + fprintf(stderr, "%s: open certificate '%s' failure\n", prog, str); + goto end; + } + + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (!(keyfp = fopen(str, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(signer_id) - 1) { + fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog); + goto end; + } + strncpy(signer_id, str, sizeof(signer_id)); + signer_id_len = strlen(str); + } else if (!strcmp(*argv, "-sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(signer_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog); + goto end; + } + + } else if (!strcmp(*argv, "-next_update")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (asn1_time_from_str(0, &next_update, str) != 1) { + fprintf(stderr, "%s: invalid time '%s' for `-next_update`\n", prog, str); + goto bad; + } + } else if (!strcmp(*argv, "-gen_authority_key_id")) { + gen_authority_key_id = 1; + } else if (!strcmp(*argv, "-crl_num")) { + if (--argc < 1) goto bad; + crl_num = atoi(*(++argv)); + } else if (!strcmp(*argv, "-delta_crl_indicator")) { + if (--argc < 1) goto bad; + delta_crl_indicator = atoi(*(++argv)); + } else if (!strcmp(*argv, "-http_uri")) { + if (--argc < 1) goto bad; + http_uri = *(++argv); + } else if (!strcmp(*argv, "-ldap_uri")) { + if (--argc < 1) goto bad; + ldap_uri = *(++argv); + } else if (!strcmp(*argv, "-ca_issuers_uri")) { + ca_issuers_uri = *(++argv); + } else if (!strcmp(*argv, "-ocsp_uri")) { + if (--argc < 1) goto bad; + ocsp_uri = *(++argv); + } else { + fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!revoked_certs) { + fprintf(stderr, "%s: `-in` option required\n", prog); + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + goto end; + } else { + const uint8_t *d = revoked_certs; + size_t dlen = revoked_certs_len; + const uint8_t *serial; + size_t serial_len; + time_t revoke_date; + const uint8_t *exts; + size_t exts_len; + + while (dlen) { + if (x509_revoked_cert_from_der(&serial, &serial_len, &revoke_date, &exts, &exts_len, &d, &dlen) != 1) { + fprintf(stderr, "%s: invalid input\n", prog); + goto end; + } + format_bytes(stderr, 0, 4, "Revoked Certificate SN", serial, serial_len); + } + } + + if (!cacert) { + fprintf(stderr, "%s: `-cacert` option required\n", prog); + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + goto end; + } + + if (!keyfp) { + fprintf(stderr, "%s: `-key` option required\n", prog); + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + goto end; + } + if (!pass) { + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + fprintf(stderr, "%s: `-pass` option required\n", prog); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&sign_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load private key failure\n", prog); + goto end; + } + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + + if (x509_cert_get_subject(cacert, cacert_len, &issuer, &issuer_len) != 1) { + fprintf(stderr, "%s: parse CA certificate failure\n", prog); + goto end; + } + + // Extensions + if (gen_authority_key_id) { + if (x509_crl_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sign_key) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + } + if (x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts), -1, crl_num) < 0) { + fprintf(stderr, "%s: add CRLNumber error\n", prog); + goto end; + } + if (x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts), X509_critical, delta_crl_indicator) < 0) { + fprintf(stderr, "%s: add DeltaCRLIndicator error\n", prog); + goto end; + } + if (ca_issuers_uri || ocsp_uri) { + if (x509_crl_exts_add_authority_info_acess(exts, &extslen, sizeof(exts), -1, + ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0, + ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) { + fprintf(stderr, "%s: add AuthorityInfoAccess error\n", prog); + goto end; + } + } + if (http_uri || ldap_uri) { + if (x509_crl_exts_add_freshest_crl(exts, &extslen, sizeof(exts), -1, + http_uri, http_uri ? strlen(http_uri) : 0, + ldap_uri, ldap_uri ? strlen(ldap_uri) : 0) != 1) { + fprintf(stderr, "%s: add FreshestCRL error\n", prog); + goto end; + } + } + + if (x509_crl_sign_to_der( + X509_version_v2, + OID_sm2sign_with_sm3, + issuer, issuer_len, + this_update, next_update, + revoked_certs, revoked_certs_len, + extslen ? exts : NULL, extslen, + &sign_key, signer_id, signer_id_len, + NULL, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (!(outbuf = malloc(outlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + out = outbuf; + outlen = 0; + if (x509_crl_sign_to_der( + X509_version_v2, + OID_sm2sign_with_sm3, + issuer, issuer_len, + this_update, next_update, + revoked_certs, revoked_certs_len, + extslen ? exts : NULL, extslen, + &sign_key, signer_id, signer_id_len, + &out, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure\n", prog); + return -1; + } + ret = 0; + +end: + if (revoked_certs) free(revoked_certs); + if (keyfp) fclose(keyfp); + if (cacert) free(cacert); + if (outfile && outfp) fclose(outfp); + if (outbuf) free(outbuf); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/crlget.c b/Core/GmSSL-3.1.1/tools/crlget.c new file mode 100644 index 0000000..3b70363 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/crlget.c @@ -0,0 +1,156 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static const char *usage = "-cert pem [-out file]\n"; + +static const char *options = +"Options\n" +"\n" +" -cert pem Input certificates in PEM format.\n" +" -out der | stdout Output CRL file in DER-encoding\n" +"\n" +"Examples\n" +"\n" +" gmssl crlget -cert cert.pem -out crl.der\n" +"\n"; + +int crlget_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + uint8_t *cert = NULL; + size_t certlen = 0; + char *outfile = NULL; + FILE *outfp = stdout; + uint8_t *crl = NULL; + size_t crl_len = 0; + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n\n", prog, usage); + printf("%s\n", options); + goto end; + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_cert_new_from_file(&cert, &certlen, str) != 1) { + fprintf(stderr, "%s: load ca certificate '%s' failure\n", prog, str); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!cert) { + fprintf(stderr, "%s: `-cert` option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, usage); + goto end; + } + + /* + const uint8_t *exts; + size_t extslen; + if (x509_cert_get_exts(cert, certlen, &exts, &extslen) != 1) { + error_print(); + goto end; + } + if (!exts) { + goto end; + } + + int critical; + const uint8_t *val; + size_t vlen; + + if ((ret = x509_exts_get_ext_by_oid(exts, extslen, OID_ce_crl_distribution_points, &critical, &val, &vlen)) < 0) { + error_print(); + goto end; + } + + + char *uristr; + const char *uri; + size_t urilen; + int reason; + const uint8_t *crl_issuer; + size_t crl_issuer_len; + + if (x509_uri_as_distribution_points_from_der(&uri, &urilen, &reason, &crl_issuer, &crl_issuer_len, &val, &vlen) != 1) { + error_print(); + goto end; + } + if (!(uristr = strndup(uri, urilen))) { + error_print(); + goto end; + } + + + if (http_get(uristr, NULL, &crl_len, 0) < 0) { + error_print(); + goto end; + } + if (!(crl = malloc(crl_len))) { + error_print(); + goto end; + } + if (http_get(uristr, crl, &crl_len, crl_len) != 1) { + error_print(); + goto end; + } + */ + + + if (x509_crl_new_from_cert(&crl, &crl_len, cert, certlen) != 1) { + error_print(); + goto end; + } + + fwrite(crl, crl_len, 1, outfp); + + + ret = 0; +end: + if (cert) free(cert); + if (outfile && outfp) fclose(outfp); + return ret; +} + diff --git a/Core/GmSSL-3.1.1/tools/crlparse.c b/Core/GmSSL-3.1.1/tools/crlparse.c new file mode 100644 index 0000000..f591d14 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/crlparse.c @@ -0,0 +1,104 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "-in file [-out file]"; + +int crlparse_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + uint8_t *in = NULL; + size_t inlen; + const uint8_t *pin; + const uint8_t *crl = NULL; + size_t crllen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!infile) { + fprintf(stderr, "%s: '-in' option required\n", prog); + goto end; + } + if (file_size(infp, &inlen) != 1) { + fprintf(stderr, "%s: get input length failed\n", prog); + goto end; + } + if (!(in = malloc(inlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (fread(in, 1, inlen, infp) != inlen) { + fprintf(stderr, "%s: read file error : %s\n", prog, strerror(errno)); + goto end; + } + pin = in; + if (x509_crl_from_der(&crl, &crllen, &pin, &inlen) != 1 + || asn1_length_is_zero(inlen) != 1) { + fprintf(stderr, "%s: read CRL failure\n", prog); + goto end; + } + x509_crl_print(outfp, 0, 0, "CRL", crl, crllen); + ret = 0; + +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + if (in) free(in); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/crlverify.c b/Core/GmSSL-3.1.1/tools/crlverify.c new file mode 100644 index 0000000..56b3fa8 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/crlverify.c @@ -0,0 +1,137 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *usage = " -in der -cacert pem [-req_sm2_id str | -req_sm2_id_hex hex]\n"; +static const char *options = +"Options\n" +"\n" +" -in pem Input CSR file in PEM format\n" +" -cacert pem Issuer CA certificate\n" +" -sm2_id str Authority's ID in SM2 signature algorithm\n" +" -sm2_id_hex hex Authority's ID in hex format\n" +" When `-sm2_id` or `-sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" +"\n" +"Examples\n" +"\n" +" gmssl certverify -in crl.der -cacert cacert.pem\n" +"\n"; + +int crlverify_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + uint8_t *crl = NULL; + size_t crl_len; + uint8_t *cacert = NULL; + size_t cacertlen; + char signer_id[SM2_MAX_ID_LENGTH + 1] = SM2_DEFAULT_ID; + size_t signer_id_len = strlen(SM2_DEFAULT_ID); + int rv; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (file_read_all(str, &crl, &crl_len) != 1) { + fprintf(stderr, "%s: read '%s' failure : %s\n", prog, str, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_cert_new_from_file(&cacert, &cacertlen, str) != 1) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(signer_id) - 1) { + fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog); + goto end; + } + strncpy(signer_id, str, sizeof(signer_id)); + signer_id_len = strlen(str); + } else if (!strcmp(*argv, "-sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(signer_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!crl) { + fprintf(stderr, "%s: `-in` option required\n", prog); + goto end; + } + if (!cacert) { + fprintf(stderr, "%s: `-cacert` option required\n", prog); + goto end; + } + + if (x509_crl_check(crl, crl_len, time(NULL)) != 1) { + fprintf(stderr, "%s: invalid CRL data or format\n", prog); + goto end; + } + if ((rv = x509_crl_verify_by_ca_cert(crl, crl_len, cacert, cacertlen, signer_id, signer_id_len)) < 0) { + fprintf(stderr, "%s: verification inner error\n", prog); + goto end; + } + + printf("Verification %s\n", rv ? "success" : "failure"); + if (rv == 1) ret = 0; + +end: + if (crl) free(crl); + if (cacert) free(cacert); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/gmssl.c b/Core/GmSSL-3.1.1/tools/gmssl.c new file mode 100644 index 0000000..ef2bd6d --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/gmssl.c @@ -0,0 +1,227 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include + + +extern int version_main(int argc, char **argv); +extern int rand_main(int argc, char **argv); +extern int certgen_main(int argc, char **argv); +extern int certparse_main(int argc, char **argv); +extern int certverify_main(int argc, char **argv); +extern int certrevoke_main(int argc, char **argv); +extern int crlget_main(int argc, char **argv); +extern int crlgen_main(int argc, char **argv); +extern int crlparse_main(int argc, char **argv); +extern int crlverify_main(int argc, char **argv); +extern int pbkdf2_main(int argc, char **argv); +extern int reqgen_main(int argc, char **argv); +extern int reqparse_main(int argc, char **argv); +extern int reqsign_main(int argc, char **argv); +extern int sm2keygen_main(int argc, char **argv); +extern int sm2sign_main(int argc, char **argv); +extern int sm2verify_main(int argc, char **argv); +extern int sm2encrypt_main(int argc, char **argv); +extern int sm2decrypt_main(int argc, char **argv); +extern int sm3_main(int argc, char **argv); +extern int sm3hmac_main(int argc, char **argv); +extern int sm4_main(int argc, char **argv); +extern int zuc_main(int argc, char **argv); +extern int sm9setup_main(int argc, char **argv); +extern int sm9keygen_main(int argc, char **argv); +extern int sm9sign_main(int argc, char **argv); +extern int sm9verify_main(int argc, char **argv); +extern int sm9encrypt_main(int argc, char **argv); +extern int sm9decrypt_main(int argc, char **argv); +extern int cmsparse_main(int argc, char **argv); +extern int cmsencrypt_main(int argc, char **argv); +extern int cmsdecrypt_main(int argc, char **argv); +extern int cmssign_main(int argc, char **argv); +extern int cmsverify_main(int argc, char **argv); +extern int tlcp_client_main(int argc, char **argv); +extern int tlcp_server_main(int argc, char **argv); +extern int tls12_client_main(int argc, char **argv); +extern int tls12_server_main(int argc, char **argv); +extern int tls13_client_main(int argc, char **argv); +extern int tls13_server_main(int argc, char **argv); +extern int sdfutil_main(int argc, char **argv); +extern int skfutil_main(int argc, char **argv); + + +static const char *options = + "command [options]\n" + "command -help\n" + "\n" + "Commands:\n" + " help Print this help message\n" + " version Print version\n" + " rand Generate random bytes\n" + " sm2keygen Generate SM2 keypair\n" + " sm2sign Generate SM2 signature\n" + " sm2verify Verify SM2 signature\n" + " sm2encrypt Encrypt with SM2 public key\n" + " sm2decrypt Decrypt with SM2 private key\n" + " sm3 Generate SM3 hash\n" + " sm3hmac Generate SM3 HMAC tag\n" + " sm4 Encrypt or decrypt with SM4\n" + " zuc Encrypt or decrypt with ZUC\n" + " sm9setup Generate SM9 master secret\n" + " sm9keygen Generate SM9 private key\n" + " sm9sign Generate SM9 signature\n" + " sm9verify Verify SM9 signature\n" + " sm9encrypt SM9 public key encryption\n" + " sm9decrypt SM9 decryption\n" + " pbkdf2 Generate key from password\n" + " reqgen Generate certificate signing request (CSR)\n" + " reqsign Generate certificate from CSR\n" + " reqparse Parse and print a CSR\n" + " crlget Download the CRL of given certificate\n" + " crlgen Sign a CRL with CA certificate and private key\n" + " crlverify Verify a CRL with issuer's certificate\n" + " crlparse Parse and print CRL\n" + " certgen Generate a self-signed certificate\n" + " certparse Parse and print certificates\n" + " certverify Verify certificate chain\n" + " certrevoke Revoke certificate and output RevokedCertificate record\n" + " cmsparse Parse CMS (cryptographic message syntax) file\n" + " cmsencrypt Generate CMS EnvelopedData\n" + " cmsdecrypt Decrypt CMS EnvelopedData\n" + " cmssign Generate CMS SignedData\n" + " cmsverify Verify CMS SignedData\n" + " sdfutil SDF crypto device utility\n" + " skfutil SKF crypto device utility\n" + " tlcp_client TLCP client\n" + " tlcp_server TLCP server\n" + " tls12_client TLS 1.2 client\n" + " tls12_server TLS 1.2 server\n" + " tls13_client TLS 1.3 client\n" + " tls13_server TLS 1.3 server\n" + "\n" + "run `gmssl -help` to print help of the given command\n" + "\n"; + + +int main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + + argc--; + argv++; + + if (argc < 1) { + printf("Usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "help")) { + printf("usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "version")) { + return version_main(argc, argv); + } else if (!strcmp(*argv, "rand")) { + return rand_main(argc, argv); + } else if (!strcmp(*argv, "certgen")) { + return certgen_main(argc, argv); + } else if (!strcmp(*argv, "certparse")) { + return certparse_main(argc, argv); + } else if (!strcmp(*argv, "certverify")) { + return certverify_main(argc, argv); + } else if (!strcmp(*argv, "certrevoke")) { + return certrevoke_main(argc, argv); + } else if (!strcmp(*argv, "crlget")) { + return crlget_main(argc, argv); + } else if (!strcmp(*argv, "crlgen")) { + return crlgen_main(argc, argv); + } else if (!strcmp(*argv, "crlparse")) { + return crlparse_main(argc, argv); + } else if (!strcmp(*argv, "crlverify")) { + return crlverify_main(argc, argv); + } else if (!strcmp(*argv, "reqgen")) { + return reqgen_main(argc, argv); + } else if (!strcmp(*argv, "reqparse")) { + return reqparse_main(argc, argv); + } else if (!strcmp(*argv, "reqsign")) { + return reqsign_main(argc, argv); + } else if (!strcmp(*argv, "pbkdf2")) { + return pbkdf2_main(argc, argv); + } else if (!strcmp(*argv, "sm2keygen")) { + return sm2keygen_main(argc, argv); + } else if (!strcmp(*argv, "sm2sign")) { + return sm2sign_main(argc, argv); + } else if (!strcmp(*argv, "sm2verify")) { + return sm2verify_main(argc, argv); + } else if (!strcmp(*argv, "sm2encrypt")) { + return sm2encrypt_main(argc, argv); + } else if (!strcmp(*argv, "sm2decrypt")) { + return sm2decrypt_main(argc, argv); + } else if (!strcmp(*argv, "sm3")) { + return sm3_main(argc, argv); + } else if (!strcmp(*argv, "sm3hmac")) { + return sm3hmac_main(argc, argv); + } else if (!strcmp(*argv, "sm4")) { + return sm4_main(argc, argv); + } else if (!strcmp(*argv, "zuc")) { + return zuc_main(argc, argv); + } else if (!strcmp(*argv, "sm9setup")) { + return sm9setup_main(argc, argv); + } else if (!strcmp(*argv, "sm9keygen")) { + return sm9keygen_main(argc, argv); + } else if (!strcmp(*argv, "sm9sign")) { + return sm9sign_main(argc, argv); + } else if (!strcmp(*argv, "sm9verify")) { + return sm9verify_main(argc, argv); + } else if (!strcmp(*argv, "sm9encrypt")) { + return sm9encrypt_main(argc, argv); + } else if (!strcmp(*argv, "sm9decrypt")) { + return sm9decrypt_main(argc, argv); + } else if (!strcmp(*argv, "cmsparse")) { + return cmsparse_main(argc, argv); + } else if (!strcmp(*argv, "cmsencrypt")) { + return cmsencrypt_main(argc, argv); + } else if (!strcmp(*argv, "cmsdecrypt")) { + return cmsdecrypt_main(argc, argv); + } else if (!strcmp(*argv, "cmssign")) { + return cmssign_main(argc, argv); + } else if (!strcmp(*argv, "cmsverify")) { + return cmsverify_main(argc, argv); + } else if (!strcmp(*argv, "tlcp_client")) { + return tlcp_client_main(argc, argv); + } else if (!strcmp(*argv, "tlcp_server")) { + return tlcp_server_main(argc, argv); + } else if (!strcmp(*argv, "tls12_client")) { + return tls12_client_main(argc, argv); + } else if (!strcmp(*argv, "tls12_server")) { + return tls12_server_main(argc, argv); + } else if (!strcmp(*argv, "tls13_client")) { + return tls13_client_main(argc, argv); + } else if (!strcmp(*argv, "tls13_server")) { + return tls13_server_main(argc, argv); +#ifndef WIN32 + } else if (!strcmp(*argv, "sdfutil")) { + return sdfutil_main(argc, argv); + } else if (!strcmp(*argv, "skfutil")) { + return skfutil_main(argc, argv); +#endif + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + argc--; + argv++; + } + + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/pbkdf2.c b/Core/GmSSL-3.1.1/tools/pbkdf2.c new file mode 100644 index 0000000..9f59ab3 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/pbkdf2.c @@ -0,0 +1,142 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "-pass str -salt hex -iter num -outlen num [-bin|-hex] [-out file]"; + +int pbkdf2_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *pass = NULL; + char *salthex = NULL; + uint8_t salt[PBKDF2_MAX_SALT_SIZE]; + size_t saltlen; + int iter = 0; + int outlen = 0; + int bin = 0; + char *outfile = NULL; + uint8_t outbuf[64]; + FILE *outfp = stdout; + int i; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-salt")) { + if (--argc < 1) goto bad; + salthex = *(++argv); + if (strlen(salthex) > sizeof(salt) * 2) { + fprintf(stderr, "%s: invalid salt length\n", prog); + goto end; + } + if (hex_to_bytes(salthex, strlen(salthex), salt, &saltlen) != 1) { + fprintf(stderr, "%s: invalid HEX digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iter")) { + if (--argc < 1) goto bad; + iter = atoi(*(++argv)); + if (iter < PBKDF2_MIN_ITER || iter > INT_MAX) { + fprintf(stderr, "%s: invalid '-iter' value\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-outlen")) { + if (--argc < 1) goto bad; + outlen = atoi(*(++argv)); + if (outlen < 1 || outlen > sizeof(outbuf)) { + fprintf(stderr, "%s: invalid outlen\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-hex")) { + bin = 0; + } else if (!strcmp(*argv, "-bin")) { + bin = 1; + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!pass) { + fprintf(stderr, "%s: option '-pass' required\n", prog); + goto end; + } + if (!salthex) { + fprintf(stderr, "%s: option '-salt' required\n", prog); + goto end; + } + if (!iter) { + fprintf(stderr, "%s: option '-iter' required\n", prog); + goto end; + } + if (!outlen) { + fprintf(stderr, "%s: option '-outlen' required\n", prog); + goto end; + } + + if (pbkdf2_hmac_sm3_genkey(pass, strlen(pass), salt, saltlen, iter, outlen, outbuf) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + + if (bin) { + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } else { + for (i = 0; i < outlen; i++) { + fprintf(outfp, "%02x", outbuf[i]); + } + fprintf(outfp, "\n"); + } + ret = 0; + +end: + gmssl_secure_clear(outbuf, sizeof(outbuf)); + gmssl_secure_clear(salt, sizeof(salt)); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/rand.c b/Core/GmSSL-3.1.1/tools/rand.c new file mode 100644 index 0000000..b71610b --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/rand.c @@ -0,0 +1,133 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-hex] [-rdrand|-rdseed] -outlen num [-out file]"; + +int rand_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int hex = 0; + int rdrand = 0; + int rdseed = 0; + int outlen = 0; + char *outfile = NULL; + FILE *outfp = stdout; + uint8_t buf[2048]; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-hex")) { + hex = 1; + } else if (!strcmp(*argv, "-rdrand")) { + rdrand = 1; + } else if (!strcmp(*argv, "-rdseed")) { + rdseed = 1; + } else if (!strcmp(*argv, "-outlen")) { + if (--argc < 1) goto bad; + outlen = atoi(*(++argv)); + if (outlen < 1 || outlen > INT_MAX) { + fprintf(stderr, "%s: invalid outlen\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!outlen) { + fprintf(stderr, "%s: option -outlen missing\n", prog); + goto end; + } + + while (outlen > 0) { + size_t len = outlen < sizeof(buf) ? outlen : sizeof(buf); + + if (rdrand) { +#ifdef INTEL_RDRAND + if (rdrand_bytes(buf, len) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } +#else + fprintf(stderr, "%s: `-rdrand` is not supported on your platform\n", prog); +#endif + } else if (rdseed) { +#ifdef INTEL_RDSEED + if (rdseed_bytes(buf, len) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } +#else + fprintf(stderr, "%s: `-rdseed` is not supported on your platform\n", prog); +#endif + } else { + if (rand_bytes(buf, len) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + } + + if (hex) { + int i; + for (i = 0; i < len; i++) { + fprintf(outfp, "%02X", buf[i]); + } + } else { + if (fwrite(buf, 1, len, outfp) != len) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + outlen -= (int)len; + } + if (hex) { + fprintf(outfp, "\n"); + } + ret = 0; +end: + gmssl_secure_clear(buf, sizeof(buf)); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/reqgen.c b/Core/GmSSL-3.1.1/tools/reqgen.c new file mode 100644 index 0000000..2aeffa6 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/reqgen.c @@ -0,0 +1,227 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static const char *options = + "[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str" + " -key pem -pass pass" + " [-sm2_id str | -sm2_id_hex hex]" + " [-out pem]"; + +static char *usage = +"Options\n" +"\n" +" -key file Private key file in PEM format\n" +" -pass pass Password for decrypting private key file\n" +" -sm2_id str Signer's ID in SM2 signature algorithm\n" +" -sm2_id_hex hex Signer's ID in hex format\n" +" When `-sm2_id` or `-sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" +" -out file Output Certificate Request (CSR) file in PEM format\n" +"\n" +" Subject options\n" +"\n" +" -C str Country\n" +" -ST str State or province name\n" +" -L str Locality\n" +" -O str Organization\n" +" -OU str Organizational unit\n" +" -CN str Common name\n" +"\n" +"Examples\n" +"\n" +" gmssl sm2keygen -pass P@ssw0rd -out key.pem\n" +" gmssl reqgen -CN www.gmssl.org -key key.pem -pass P@ssw0rd -out req.pem\n" +"\n"; + + +int reqgen_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + // Subject + uint8_t name[256]; + size_t namelen = 0; + char *country = NULL; + char *state = NULL; + char *locality = NULL; + char *org = NULL; + char *org_unit = NULL; + char *common_name = NULL; + + // Attributs + uint8_t attrs[512]; + size_t attrs_len = 0; + + // Private Key + FILE *keyfp = NULL; + char *pass = NULL; + SM2_KEY sm2_key; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + // Output + char *outfile = NULL; + FILE *outfp = stdout; + uint8_t req[1024]; + uint8_t *p = req; + size_t reqlen = 0; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n\n", prog, options); + printf("%s\n", usage); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-C")) { + if (--argc < 1) goto bad; + country = *(++argv); + } else if (!strcmp(*argv, "-ST")) { + if (--argc < 1) goto bad; + state = *(++argv); + } else if (!strcmp(*argv, "-L")) { + if (--argc < 1) goto bad; + locality = *(++argv); + } else if (!strcmp(*argv, "-O")) { + if (--argc < 1) goto bad; + org = *(++argv); + } else if (!strcmp(*argv, "-OU")) { + if (--argc < 1) goto bad; + org_unit = *(++argv); + } else if (!strcmp(*argv, "-CN")) { + if (--argc < 1) goto bad; + common_name = *(++argv); + + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (!(keyfp = fopen(str, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(signer_id) - 1) { + fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog); + goto end; + } + strncpy(signer_id, str, sizeof(signer_id)); + signer_id_len = strlen(str); + } else if (!strcmp(*argv, "-sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(signer_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog); + goto end; + } + + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!common_name) { + fprintf(stderr, "%s: `-CN` option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!keyfp) { + fprintf(stderr, "%s: `-key` option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: `-pass` option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load private key failed\n", prog); + goto end; + } + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + + if (x509_name_set(name, &namelen, sizeof(name), country, state, locality, org, org_unit, common_name) != 1) { + fprintf(stderr, "%s: set Subject Name error\n", prog); + goto end; + } + + if (x509_req_sign_to_der( + X509_version_v1, + name, namelen, + &sm2_key, + attrs, attrs_len, + OID_sm2sign_with_sm3, + &sm2_key, signer_id, signer_id_len, + &p, &reqlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (x509_req_to_pem(req, reqlen, outfp) != 1) { + fprintf(stderr, "%s: output CSR failed\n", prog); + goto end; + } + ret = 0; +end: + gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY)); + if (keyfp) fclose(keyfp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/reqparse.c b/Core/GmSSL-3.1.1/tools/reqparse.c new file mode 100644 index 0000000..3a9e1c6 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/reqparse.c @@ -0,0 +1,79 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-in file] [-out file]"; + +int reqparse_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + uint8_t req[1024]; + size_t reqlen; + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + goto end; + } else if(!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (x509_req_from_pem(req, &reqlen, sizeof(req), infp) != 1) { + fprintf(stderr, "%s: read CSR failure\n", prog); + goto end; + } + x509_req_print(outfp, 0, 0, "CertificationRequest", req, reqlen); + if (x509_req_to_pem(req, reqlen, outfp) != 1) { + fprintf(stderr, "%s: output CSR failure\n", prog); + goto end; + } + ret = 0; +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/reqsign.c b/Core/GmSSL-3.1.1/tools/reqsign.c new file mode 100644 index 0000000..31f74b7 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/reqsign.c @@ -0,0 +1,613 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = + " [-in pem]" + " [-req_sm2_id str | -req_sm2_id_hex hex]" + " [-serial_len num]" + " -days num" + " -cacert pem -key file -pass pass" + " [-sm2_id str | -sm2_id_hex hex]" + " [-gen_authority_key_id]" + " [-gen_subject_key_id]" + " [-key_usage str]*" + " [-subject_dns_name str]*" + " [-issuer_dns_name str]*" + " [-ca -path_len_constraint num]" + " [-ext_key_usage str]*" + " [-crl_http_uri uri] [-crl_ldap_uri uri]" + " [-inhibit_any_policy num]" + " [-ca_issuers_uri uri] [-ocsp_uri uri uri]" + " [-out pem]"; + +static char *usage = +"Options\n" +"\n" +" -in pem | stdin Input CSR file in PEM format\n" +" -req_sm2_id str CSR Owner's ID in SM2 signature algorithm\n" +" -req_sm2_id_hex hex CSR Owner's ID in hex format\n" +" When `-req_sm2_id` or `-req_sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-req_sm2_id` nor `-req_sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" +" -serial_len num Serial number length in bytes\n" +" -days num Validity peroid in days\n" +" -cacert pem Issuer CA certificate\n" +" -key pem Issuer private key file in PEM format\n" +" -sm2_id str Authority's ID in SM2 signature algorithm\n" +" -sm2_id_hex hex Authority's ID in hex format\n" +" When `-sm2_id` or `-sm2_id_hex` is specified,\n" +" must use the same ID in other commands explicitly.\n" +" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" +" the default string '1234567812345678' is used\n" +" -pass pass Password for decrypting private key file\n" +" -out pem Output certificate file in PEM format\n" +"\n" +" Extension options\n" +"\n" +" -gen_authority_key_id Generate AuthorityKeyIdentifier extension use SM3\n" +" -gen_subject_key_id Generate SubjectKeyIdentifier extension use SM3\n" +" -key_usage str Add KeyUsage extension\n" +" this option can be called multi-times\n" +" avaiable values:\n" +" digitalSignature\n" +" nonRepudiation\n" +" keyEncipherment\n" +" dataEncipherment\n" +" keyAgreement\n" +" keyCertSign\n" +" cRLSign\n" +" encipherOnly\n" +" decipherOnly\n" +" -subject_dns_name str Add DNS name to SubjectAltName extension\n" +" this option can be called multi-times\n" +" -issuer_dns_name str Add DNS name to IssuerAltName extension\n" +" this option can be called multi-times\n" +" -ca Set cA of BasicConstaints extension\n" +" -path_len_constraint num Set pathLenConstaint of BasicConstaints extension\n" +" -ext_key_usage str Set ExtKeyUsage extension\n" +" this option can be called multi-times\n" +" avaiable values:\n" +" anyExtendedKeyUsage\n" +" serverAuth\n" +" clientAuth\n" +" codeSigning\n" +" emailProtection\n" +" timeStamping\n" +" OCSPSigning\n" +" -crl_http_uri uri Set HTTP URI of CRL of CRLDistributionPoints extension\n" +" -crl_ldap_uri uri Set LDAP URI of CRL of CRLDistributionPoints extension\n" +" -inhibit_any_policy num Set skipCerts number of InhibitAnyPolicy extension\n" +" -ca_issuers_uri uri Set URI of the CA certificate in DER-encoding o FreshestCRL extension\n" +" -ocsp_uri uri Set OCSP URI of FreshestCRL extension\n" +"\n" +"Examples\n" +"\n" +" # Generate self-signed root CA certificate\n" +"\n" +" gmssl sm2keygen -pass P@ssw0rd -out rootcakey.pem\n" +" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \\\n" +" -key rootcakey.pem -pass P@ssw0rd \\\n" +" -ca -path_len_constraint 6 \\\n" +" -key_usage keyCertSign -key_usage cRLSign \\\n" +" -crl_http_uri http://pku.edu.cn/ca.crl \\\n" +" -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn \\\n" +" -out rootcacert.pem\n" +"\n" +" # Generate sub-CA certificate request\n" +"\n" +" gmssl sm2keygen -pass P@ssw0rd -out cakey.pem\n" +" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN CA -key cakey.pem -pass P@ssw0rd -out careq.pem\n" +"\n" +" # Sign certificate request to generate sub-CA certificate\n" +"\n" +" gmssl reqsign -in careq.pem -serial_len 12 -days 365 \\\n" +" -cacert rootcacert.pem -key rootcakey.pem -pass P@ssw0rd \\\n" +" -ca -path_len_constraint 0 \\\n" +" -key_usage keyCertSign -key_usage cRLSign \\\n" +" -crl_http_uri http://pku.edu.cn/ca.crl \\\n" +" -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn \\\n" +" -out cacert.pem\n" +"\n"; + +static int ext_key_usage_set(int *usages, const char *usage_name) +{ + int flag = 0; + if (x509_key_usage_from_name(&flag, usage_name) != 1) { + return -1; + } + *usages |= flag; + return 1; +} + +int reqsign_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *str; + + // Input Req/CSR + char *infile = NULL; + FILE *infp = stdin; + uint8_t req[512]; + size_t reqlen; + char req_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t req_id_len = 0; + + // SerialNumber + uint8_t serial[20]; + int serial_len = 12; + + // Validity + int days = 0; + time_t not_before; + time_t not_after; + + // Subject from Req + const uint8_t *subject; + size_t subject_len; + SM2_KEY subject_public_key; + + // CA certficate and Private Key + uint8_t *cacert = NULL; + size_t cacertlen; + FILE *keyfp = NULL; + char *pass = NULL; + SM2_KEY sm2_key; + char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; + size_t signer_id_len = 0; + + // Issuer from CA certificate + const uint8_t *issuer; + size_t issuer_len; + SM2_KEY issuer_public_key; + + // Output + char *outfile = NULL; + FILE *outfp = stdout; + uint8_t *cert = NULL; + size_t certlen = 0; + uint8_t *p; + + // Extensions + uint8_t exts[4096]; + size_t extslen = 0; + + // AuthorityKeyIdentifier + int gen_authority_key_id = 0; + + // SubjectKeyIdentifier + int gen_subject_key_id = 0; + + // KeyUsage + int key_usage = 0; + + // SubjectAltName + uint8_t subject_alt_name[2048]; + size_t subject_alt_name_len = 0; + + // IssuerAltName + uint8_t issuer_alt_name[512]; + size_t issuer_alt_name_len = 0; + + // BasicConstraints + int ca = -1; + int path_len_constraint = -1; + + // ExtKeyUsageSyntax + int ext_key_usages[12]; + size_t ext_key_usages_cnt = 0; + + // CRLDistributionPoints + char *crl_http_uri = NULL; + char *crl_ldap_uri = NULL; + + // InhibitAnyPolicy + int inhibit_any_policy = -1; + + // FreshestCRL + char *ca_issuers_uri = NULL; + char *ocsp_uri = NULL; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc >= 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n\n", prog, options); + printf("%s\n", usage); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-req_sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(req_id) - 1) { + fprintf(stderr, "%s: invalid `-req_sm2_id` length\n", prog); + goto end; + } + strncpy(req_id, str, sizeof(req_id)); + req_id_len = strlen(str); + } else if (!strcmp(*argv, "-req_sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(req_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-req_sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)req_id, &req_id_len) != 1) { + fprintf(stderr, "%s: invalid `-req_sm2_id_hex` value\n", prog); + goto end; + } + + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + + } else if (!strcmp(*argv, "-serial_len")) { + if (--argc < 1) goto bad; + serial_len = atoi(*(++argv)); + if (serial_len <= 0 || serial_len > sizeof(serial)) { + fprintf(stderr, "%s: invalid `-serial_len` value, need a number less than %zu\n", prog, sizeof(serial)); + goto end; + } + } else if (!strcmp(*argv, "-days")) { + if (--argc < 1) goto bad; + days = atoi(*(++argv)); + if (days <= 0) { + fprintf(stderr, "%s: invalid `-days` value, need a positive number\n", prog); + goto end; + } + + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_cert_new_from_file(&cacert, &cacertlen, str) != 1) { + fprintf(stderr, "%s: load ca certificate '%s' failure\n", prog, str); + goto end; + } + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (!(keyfp = fopen(str, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-sm2_id")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > sizeof(signer_id) - 1) { + fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog); + goto end; + } + strncpy(signer_id, str, sizeof(signer_id)); + signer_id_len = strlen(str); + } else if (!strcmp(*argv, "-sm2_id_hex")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (strlen(str) > (sizeof(signer_id) - 1) * 2) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog); + goto end; + } + if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) { + fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog); + goto end; + } + + // following copy from certgen.c + } else if (!strcmp(*argv, "-gen_authority_key_id")) { + gen_authority_key_id = 1; + } else if (!strcmp(*argv, "-gen_subject_key_id")) { + gen_subject_key_id = 1; + } else if (!strcmp(*argv, "-key_usage")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (ext_key_usage_set(&key_usage, str) != 1) { + fprintf(stderr, "%s: invalid `-key_usage` value '%s'\n", prog, str); + goto end; + } + } else if (!strcmp(*argv, "-subject_dns_name")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_general_names_add_dns_name( + subject_alt_name, &subject_alt_name_len, sizeof(subject_alt_name), str) != 1) { + fprintf(stderr, "%s: inner error on processing `-subject_dns_name`\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-issuer_dns_name")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_general_names_add_dns_name( + issuer_alt_name, &issuer_alt_name_len, sizeof(issuer_alt_name), str) != 1) { + fprintf(stderr, "%s: inner error on processing `-issuer_dns_name`\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-ca")) { + ca = 1; + } else if (!strcmp(*argv, "-path_len_constraint")) { + if (--argc < 1) goto bad; + path_len_constraint = atoi(*(++argv)); + if (path_len_constraint < 0) { + fprintf(stderr, "%s: invalid `-path_len_constraint` value\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-ext_key_usage")) { + if (--argc < 1) goto bad; + str = *(++argv); + if (x509_key_purpose_from_name(str) <= 0) { + fprintf(stderr, "%s: invalid `-ext_key_usage` value '%s'\n", prog, str); + goto end; + } + if (ext_key_usages_cnt >= sizeof(ext_key_usages)/sizeof(ext_key_usages[0])) { + fprintf(stderr, "%s: too much `-ext_key_usage` options\n", prog); + goto end; + } + ext_key_usages[ext_key_usages_cnt++] = x509_key_purpose_from_name(str); + } else if (!strcmp(*argv, "-crl_http_uri")) { + if (--argc < 1) goto bad; + crl_http_uri = *(++argv); + } else if (!strcmp(*argv, "-crl_ldap_uri")) { + if (--argc < 1) goto bad; + crl_ldap_uri = *(++argv); + } else if (!strcmp(*argv, "-inhibit_any_policy")) { + if (--argc < 1) goto bad; + inhibit_any_policy = atoi(*(++argv)); + if (inhibit_any_policy < 0) { + fprintf(stderr, "%s: invalid `-inhibit_any_policy` value\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-ca_issuers_uri")) { + if (--argc < 1) goto bad; + ca_issuers_uri = *(++argv); + } else if (!strcmp(*argv, "-ocsp_uri")) { + if (--argc < 1) goto bad; + ocsp_uri = *(++argv); + + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!days) { + fprintf(stderr, "%s: '-days' option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!cacert) { + fprintf(stderr, "%s: '-cacert' option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!keyfp) { + fprintf(stderr, "%s: '-key' option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + printf("usage: gmssl %s %s\n\n", prog, options); + goto end; + } + + if (x509_req_from_pem(req, &reqlen, sizeof(req), infp) != 1) { + fprintf(stderr, "%s: parse CSR failure\n", prog); + goto end; + } + if (!req_id_len) { + strcpy(req_id, SM2_DEFAULT_ID); + req_id_len = strlen(SM2_DEFAULT_ID); + } + if (x509_req_verify(req, reqlen, req_id, req_id_len) != 1) { + fprintf(stderr, "%s: signature verification failure\n", prog); + goto end; + } + if (x509_req_get_details(req, reqlen, + NULL, &subject, &subject_len, &subject_public_key, + NULL, NULL, NULL, NULL, NULL) != 1) { + fprintf(stderr, "%s: parse CSR failure\n", prog); + goto end; + } + + if (x509_cert_get_subject(cacert, cacertlen, &issuer, &issuer_len) != 1 + || x509_cert_get_subject_public_key(cacert, cacertlen, &issuer_public_key) != 1) { + fprintf(stderr, "%s: parse CA certificate failure\n", prog); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load private key failure\n", prog); + goto end; + } + if (sm2_public_key_equ(&sm2_key, &issuer_public_key) != 1) { + fprintf(stderr, "%s: private key and CA certificate not match\n", prog); + goto end; + } + if (!signer_id_len) { + strcpy(signer_id, SM2_DEFAULT_ID); + signer_id_len = strlen(SM2_DEFAULT_ID); + } + + if (rand_bytes(serial, serial_len) != 1) { + fprintf(stderr, "%s: random number generator error\n", prog); + goto end; + } + + time(¬_before); + if (x509_validity_add_days(¬_after, not_before, days) != 1) { + fprintf(stderr, "%s: set Validity failure\n", prog); + goto end; + } + + // following code copy from certgen.c + // Extensions + if (gen_authority_key_id) { + if (x509_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sm2_key) != 1) { + fprintf(stderr, "%s: set AuthorityKeyIdentifier extension failure\n", prog); + goto end; + } + } + if (gen_subject_key_id) { + if (x509_exts_add_subject_key_identifier_ex(exts, &extslen, sizeof(exts), -1, &sm2_key) != 1) { + fprintf(stderr, "%s: set SubjectKeyIdentifier extension failure\n", prog); + goto end; + } + } + if (key_usage) { + if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), X509_critical, key_usage) != 1) { + fprintf(stderr, "%s: set KeyUsage extension failure\n", prog); + goto end; + } + } + // no CertificatePolicies + // no PolicyMappings + if (subject_alt_name_len) { + if (x509_exts_add_subject_alt_name(exts, &extslen, sizeof(exts), + -1, subject_alt_name, subject_alt_name_len) != 1) { + fprintf(stderr, "%s: set SubjectAltName extension failure\n", prog); + goto end; + } + } + if (issuer_alt_name_len) { + if (x509_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts), + -1, issuer_alt_name, issuer_alt_name_len) != 1) { + fprintf(stderr, "%s: set IssuerAltName extension failure\n", prog); + goto end; + } + } + // no SubjectDirectoryAttributes + if (ca >= 0 || path_len_constraint >= 0) { + if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts), + X509_critical, ca, path_len_constraint) != 1) { + fprintf(stderr, "%s: set BasicConstraints extension failure\n", prog); + goto end; + } + } + // no NameConstraints + // no PolicyConstraints + if (ext_key_usages_cnt) { + if (x509_exts_add_ext_key_usage(exts, &extslen, sizeof(exts), + -1, ext_key_usages, ext_key_usages_cnt) != 1) { + fprintf(stderr, "%s: set ExtKeyUsage extension failure\n", prog); + goto end; + } + } + if (crl_http_uri || crl_ldap_uri) { + if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts), + -1, + crl_http_uri, crl_http_uri ? strlen(crl_http_uri) : 0, + crl_ldap_uri, crl_ldap_uri ? strlen(crl_ldap_uri) : 0) != 1) { + fprintf(stderr, "%s: set CRLDistributionPoints extension failure\n", prog); + return -1; + } + } + if (inhibit_any_policy >= 0) { + if (x509_exts_add_inhibit_any_policy(exts, &extslen, sizeof(exts), + X509_critical, inhibit_any_policy) != 1) { + fprintf(stderr, "%s: set InhibitAnyPolicy extension failure\n", prog); + goto end; + } + } + if (ca_issuers_uri || ocsp_uri) { + if (x509_exts_add_authority_info_access(exts, &extslen, sizeof(exts), 0, + ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0, + ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) { + fprintf(stderr, "%s: set AuthorityInfoAccess extension failure\n", prog); + goto end; + } + } + + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + &subject_public_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + NULL, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + if (!(cert = malloc(certlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + p = cert; + certlen = 0; + if (x509_cert_sign_to_der( + X509_version_v3, + serial, serial_len, + OID_sm2sign_with_sm3, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + &subject_public_key, + NULL, 0, + NULL, 0, + exts, extslen, + &sm2_key, signer_id, signer_id_len, + &p, &certlen) != 1) { + fprintf(stderr, "%s: certificate generation failure\n", prog); + goto end; + } + + if (x509_cert_to_pem(cert, certlen, outfp) != 1) { + fprintf(stderr, "%s: output certificate failed\n", prog); + goto end; + } + ret = 0; +end: + gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY)); + if (cert) free(cert); + if (keyfp) fclose(keyfp); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sdfutil.c b/Core/GmSSL-3.1.1/tools/sdfutil.c new file mode 100644 index 0000000..117b265 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sdfutil.c @@ -0,0 +1,215 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define OP_NONE 0 +#define OP_DEVINFO 1 +#define OP_EXPORTPUBKEY 2 +#define OP_SIGN 3 +#define OP_RAND 4 + + +static void print_usage(FILE *fp, const char *prog) +{ + fprintf(fp, "usage:\n"); + fprintf(fp, " %s -lib so_path -devinfo\n", prog); + fprintf(fp, " %s -lib so_path -exportpubkey -key index [-out file]\n", prog); + fprintf(fp, " %s -lib so_path -sign [-in file] [-out file]\n", prog); + fprintf(fp, " %s -lib so_path -rand num [-out file]\n", prog); +} + +int sdfutil_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *lib = NULL; + int op = 0; + int keyindex = -1; + char *pass = NULL; + char *id = SM2_DEFAULT_ID; + int num = 0; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + unsigned char buf[4096]; + size_t len; + SDF_DEVICE dev; + SDF_KEY key; + int dev_opened = 0; + int key_opened = 0; + + memset(&dev, 0, sizeof(dev)); + memset(&key, 0, sizeof(key)); + + argc--; + argv++; + + if (argc < 1) { + print_usage(stderr, prog); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + print_usage(stdout, prog); + goto end; + } else if (!strcmp(*argv, "-lib")) { + if (--argc < 1) goto bad; + lib = *(++argv); + } else if (!strcmp(*argv, "-devinfo")) { + op = OP_DEVINFO; + } else if (!strcmp(*argv, "-exportpubkey")) { + op = OP_EXPORTPUBKEY; + } else if (!strcmp(*argv, "-sign")) { + op = OP_SIGN; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyindex = atoi(*(++argv)); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-rand")) { + if (--argc < 1) goto bad; + len = atoi(*(++argv)); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!lib) { + fprintf(stderr, "%s: option '-lib' required\n", prog); + goto end; + } + if (sdf_load_library(lib, NULL) != 1) { + fprintf(stderr, "%s: load library failure\n", prog); + goto end; + } + + if (sdf_open_device(&dev) != 1) { + fprintf(stderr, "%s: open device failure\n", prog); + goto end; + } + dev_opened = 1; + + switch (op) { + case OP_DEVINFO: + sdf_print_device_info(stdout, 0, 0, "SDF", &dev); + break; + + case OP_EXPORTPUBKEY: + if (keyindex < 0) { + fprintf(stderr, "%s: invalid key index\n", prog); + goto end; + } + if (sdf_load_sign_key(&dev, &key, keyindex, pass) != 1) { + fprintf(stderr, "%s: load sign key failed\n", prog); + goto end; + } + key_opened = 1; + if (sm2_public_key_info_to_pem(&(key.public_key), outfp) != 1) { + fprintf(stderr, "%s: output public key to PEM failed\n", prog); + goto end; + } + break; + + case OP_SIGN: + { + SM3_CTX sm3_ctx; + uint8_t dgst[32]; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + if (sdf_load_sign_key(&dev, &key, keyindex, pass) != 1) { + fprintf(stderr, "%s: load sign key failed\n", prog); + goto end; + } + key_opened = 1; + + sm3_init(&sm3_ctx); + sm2_compute_z(dgst, &(key.public_key.public_key), id, strlen(id)); + sm3_update(&sm3_ctx, dgst, sizeof(dgst)); + + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + sm3_update(&sm3_ctx, buf, len); + } + sm3_finish(&sm3_ctx, dgst); + + if ((ret = sdf_sign(&key, dgst, sig, &siglen)) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(sig, 1, siglen, outfp) != siglen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + break; + + case OP_RAND: + if (sdf_rand_bytes(&dev, buf, len) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(buf, 1, len, outfp) != len) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + break; + + default: + fprintf(stderr, "%s: this should not happen\n", prog); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(buf, sizeof(buf)); + if (key_opened) sdf_release_key(&key); + if (dev_opened) sdf_close_device(&dev); + if (lib) sdf_unload_library(); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/skfutil.c b/Core/GmSSL-3.1.1/tools/skfutil.c new file mode 100644 index 0000000..a17079b --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/skfutil.c @@ -0,0 +1,256 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define OP_NONE 0 +#define OP_DEVINFO 1 +#define OP_EXPORTPUBKEY 2 +#define OP_SIGN 3 +#define OP_RAND 4 + + + +static void print_usage(FILE *fp, const char *prog) +{ + fprintf(fp, "usage:\n"); + fprintf(fp, " %s -lib so_path -dev str -devinfo\n", prog); + fprintf(fp, " %s -lib so_path -dev str -app str [-pass str] -container str -exportpubkey [-out file]\n", prog); + fprintf(fp, " %s -lib so_path -dev str -app str [-pass str] -container str -sign [-in file] [-out file]\n", prog); + fprintf(fp, " %s -lib so_path -dev str -rand num [-out file]\n", prog); +} + +int skfutil_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *lib = NULL; + int op = 0; + char *devname = NULL; + char *authkeystr = NULL; + char *appname = NULL; + char *container_name = NULL; + char *pass = NULL; + char *id = SM2_DEFAULT_ID; + int num = 0; + char *infile = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + unsigned char buf[4096]; + size_t len; + + uint8_t authkey[16]; + size_t authkeylen; + SKF_DEVICE dev; + SKF_KEY key; + int dev_opened = 0; + int key_opened = 0; + + memset(&dev, 0, sizeof(dev)); + memset(&key, 0, sizeof(key)); + + argc--; + argv++; + + if (argc < 1) { + print_usage(stderr, prog); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + print_usage(stdout, prog); + goto end; + } else if (!strcmp(*argv, "-lib")) { + if (--argc < 1) goto bad; + lib = *(++argv); + } else if (!strcmp(*argv, "-lib")) { + if (--argc < 1) goto bad; + devname = *(++argv); + } else if (!strcmp(*argv, "-devinfo")) { + op = OP_DEVINFO; + } else if (!strcmp(*argv, "-dev")) { + if (--argc < 1) goto bad; + devname = *(++argv); + } else if (!strcmp(*argv, "-authkey")) { + if (--argc < 1) goto bad; + authkeystr = *(++argv); + if (strlen(authkeystr) != 32) { + fprintf(stderr, "%s: invalid authkey length\n", prog); + goto end; + } + hex_to_bytes(authkeystr, strlen(authkeystr), authkey, &authkeylen); + } else if (!strcmp(*argv, "-exportpubkey")) { + op = OP_EXPORTPUBKEY; + } else if (!strcmp(*argv, "-sign")) { + op = OP_SIGN; + } else if (!strcmp(*argv, "-app")) { + if (--argc < 1) goto bad; + appname = *(++argv); + } else if (!strcmp(*argv, "-container")) { + if (--argc < 1) goto bad; + container_name = *(++argv); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-rand")) { + if (--argc < 1) goto bad; + len = atoi(*(++argv)); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!lib) { + fprintf(stderr, "%s: option '-lib' required\n", prog); + goto end; + } + if (skf_load_library(lib, NULL) != 1) { + fprintf(stderr, "%s: load library failure\n", prog); + goto end; + } + + if (!op) { + fprintf(stderr, "%s: option of (-devinfo|-exportpubkey|-sign|-rand) required\n", prog); + goto end; + } + + if (!devname) { + fprintf(stderr, "%s: option '-dev' required\n", prog); + goto end; + } + if (op == OP_DEVINFO) { + skf_print_device_info(stdout, 0, 0, devname); + ret = 0; + goto end; + } + + if (skf_open_device(&dev, devname, authkey) != 1) { + fprintf(stderr, "%s: open device failure\n", prog); + goto end; + } + dev_opened = 1; + + if (op == OP_RAND) { + if (skf_rand_bytes(&dev, buf, len) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(buf, 1, len, outfp) != len) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + ret = 0; + goto end; + } + + if (!appname) { + fprintf(stderr, "%s: option '-app' required\n", prog); + goto end; + } + if (!container_name) { + fprintf(stderr, "%s: option '-container' required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: option '-pass' required\n", prog); + goto end; + } + + if (op == OP_EXPORTPUBKEY) { + if (skf_load_sign_key(&dev, appname, pass, container_name, &key) != 1) { + fprintf(stderr, "%s: load sign key failed\n", prog); + goto end; + } + if (sm2_public_key_info_to_pem(&(key.public_key), outfp) != 1) { + fprintf(stderr, "%s: output public key PEM failure\n", prog); + goto end; + } + ret = 0; + goto end; + } + + if (op == OP_SIGN) { + SM3_CTX sm3_ctx; + uint8_t dgst[32]; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + if (skf_load_sign_key(&dev, appname, pass, container_name, &key) != 1) { + fprintf(stderr, "%s: load sign key failed\n", prog); + goto end; + } + key_opened = 1; + + sm3_init(&sm3_ctx); + sm2_compute_z(dgst, &(key.public_key.public_key), id, strlen(id)); + sm3_update(&sm3_ctx, dgst, sizeof(dgst)); + + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + sm3_update(&sm3_ctx, buf, len); + } + sm3_finish(&sm3_ctx, dgst); + + if ((ret = skf_sign(&key, dgst, sig, &siglen)) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + ret = 0; + goto end; + + } else { + fprintf(stderr, "%s: this should not happen\n", prog); + goto end; + } + +end: + gmssl_secure_clear(buf, sizeof(buf)); + if (key_opened) skf_release_key(&key); + if (dev_opened) skf_close_device(&dev); + if (lib) skf_unload_library(); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm2decrypt.c b/Core/GmSSL-3.1.1/tools/sm2decrypt.c new file mode 100644 index 0000000..2e25707 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm2decrypt.c @@ -0,0 +1,119 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "-key pem -pass str [-in file] [-out file]"; + +int sm2decrypt_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyfile = NULL; + char *pass = NULL; + char *infile = NULL; + char *outfile = NULL; + FILE *keyfp = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + SM2_KEY key; + uint8_t inbuf[SM2_MAX_CIPHERTEXT_SIZE]; + uint8_t outbuf[SM2_MAX_CIPHERTEXT_SIZE]; + size_t inlen, outlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!keyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + goto end; + } + + if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { + fprintf(stderr, "%s: private key decryption failure\n", prog); + goto end; + } + + if ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) <= 0) { + fprintf(stderr, "%s: read input failed : %s\n", prog, strerror(errno)); + goto end; + } + if (sm2_decrypt(&key, inbuf, inlen, outbuf, &outlen) != 1) { + fprintf(stderr, "%s: decryption failure\n", prog); + goto end; + } + if (outlen != fwrite(outbuf, 1, outlen, outfp)) { + fprintf(stderr, "%s: output plaintext failed : %s\n", prog, strerror(errno)); + goto end; + } + ret = 0; +end: + gmssl_secure_clear(&key, sizeof(key)); + if (keyfp) fclose(keyfp); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm2encrypt.c b/Core/GmSSL-3.1.1/tools/sm2encrypt.c new file mode 100644 index 0000000..3e75802 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm2encrypt.c @@ -0,0 +1,144 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "(-pubkey pem | -cert pem) [-in file] [-out file]"; + +int sm2encrypt_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *pubkeyfile = NULL; + char *certfile = NULL; + char *infile = NULL; + char *outfile = NULL; + FILE *pubkeyfp = NULL; + FILE *certfp = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + uint8_t cert[1024]; + size_t certlen; + SM2_KEY key; + uint8_t inbuf[SM2_MAX_PLAINTEXT_SIZE + 1]; + uint8_t outbuf[SM2_MAX_CIPHERTEXT_SIZE]; + size_t inlen, outlen = sizeof(outbuf); + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-pubkey")) { + if (certfile) { + fprintf(stderr, "%s: options '-pubkey' '-cert' conflict\n", prog); + goto end; + } + if (--argc < 1) goto bad; + pubkeyfile = *(++argv); + if (!(pubkeyfp = fopen(pubkeyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, pubkeyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-cert")) { + if (pubkeyfile) { + fprintf(stderr, "%s: options '-pubkey' '-cert' conflict\n", prog); + goto end; + } + if (--argc < 1) goto bad; + certfile = *(++argv); + if (!(certfp = fopen(certfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + + if (pubkeyfile) { + if (sm2_public_key_info_from_pem(&key, pubkeyfp) != 1) { + fprintf(stderr, "%s: parse public key failed\n", prog); + goto end; + } + } else if (certfile) { + if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &key) != 1) { + fprintf(stderr, "%s: parse certificate failed\n", prog); + goto end; + } + } else { + fprintf(stderr, "%s: '-pubkey' or '-cert' option required\n", prog); + goto end; + } + + if ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) <= 0) { + fprintf(stderr, "%s: read input error : %s\n", prog, strerror(errno)); + goto end; + } + if (inlen > SM2_MAX_PLAINTEXT_SIZE) { + fprintf(stderr, "%s: input long than SM2_MAX_PLAINTEXT_SIZE (%d)\n", prog, SM2_MAX_PLAINTEXT_SIZE); + goto end; + } + + if (sm2_encrypt(&key, inbuf, inlen, outbuf, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + + if (outlen != fwrite(outbuf, 1, outlen, outfp)) { + fprintf(stderr, "%s: output error : %s\n", prog, strerror(errno)); + goto end; + } + ret = 0; + +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + if (pubkeyfp) fclose(pubkeyfp); + if (certfp) fclose(certfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm2keygen.c b/Core/GmSSL-3.1.1/tools/sm2keygen.c new file mode 100644 index 0000000..c4f7f65 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm2keygen.c @@ -0,0 +1,100 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *usage = "-pass str [-out pem] [-pubout pem]\n"; + +static const char *options = +"Options\n" +" -pass pass Password to encrypt the private key\n" +" -out pem Output password-encrypted PKCS #8 private key in PEM format\n" +" -pubout pem Output public key in PEM format\n" +"\n"; + +int sm2keygen_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *pass = NULL; + char *outfile = NULL; + char *puboutfile = NULL; + FILE *outfp = stdout; + FILE *puboutfp = stdout; + SM2_KEY key; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, usage); + printf("%s\n", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pubout")) { + if (--argc < 1) goto bad; + puboutfile = *(++argv); + if (!(puboutfp = fopen(puboutfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!pass) { + fprintf(stderr, "%s: `-pass` option required\n", prog); + goto end; + } + + if (sm2_key_generate(&key) != 1 + || sm2_private_key_info_encrypt_to_pem(&key, pass, outfp) != 1 + || sm2_public_key_info_to_pem(&key, puboutfp) != 1) { + fprintf(stderr, "%s: inner failure\n", prog); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(&key, sizeof(key)); + if (outfile && outfp) fclose(outfp); + if (puboutfile && puboutfp) fclose(puboutfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm2sign.c b/Core/GmSSL-3.1.1/tools/sm2sign.c new file mode 100644 index 0000000..5dc1641 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm2sign.c @@ -0,0 +1,131 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "-key pem -pass str [-id str] [-in file] [-out file]"; + +int sm2sign_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyfile = NULL; + char *pass = NULL; + char *id = SM2_DEFAULT_ID; + char *infile = NULL; + char *outfile = NULL; + FILE *keyfp = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + SM2_KEY key; + SM2_SIGN_CTX sign_ctx; + uint8_t buf[4096]; + size_t len; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!keyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { + fprintf(stderr, "%s: private key decryption failure\n", prog); + goto end; + } + + if (sm2_sign_init(&sign_ctx, &key, id, strlen(id)) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (sm2_sign_update(&sign_ctx, buf, len) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + } + if (sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(sig, 1, siglen, outfp) != siglen) { + fprintf(stderr, "%s: output signature failed : %s\n", prog, strerror(errno)); + goto end; + } + ret = 0; +end: + gmssl_secure_clear(&key, sizeof(key)); + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + if (keyfp) fclose(keyfp); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm2verify.c b/Core/GmSSL-3.1.1/tools/sm2verify.c new file mode 100644 index 0000000..0e4e91b --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm2verify.c @@ -0,0 +1,161 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "(-pubkey pem | -cert pem) [-id str] [-in file] -sig file"; + +int sm2verify_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *id = SM2_DEFAULT_ID; + char *pubkeyfile = NULL; + char *certfile = NULL; + char *infile = NULL; + char *sigfile = NULL; + FILE *pubkeyfp = NULL; + FILE *certfp = NULL; + FILE *infp = stdin; + FILE *sigfp = NULL; + SM2_KEY key; + SM2_SIGN_CTX verify_ctx; + uint8_t cert[1024]; + size_t certlen; + uint8_t buf[4096]; + size_t len; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + int vr; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-pubkey")) { + if (certfile) { + fprintf(stderr, "%s: options '-pubkey' '-cert' conflict\n", prog); + goto end; + } + if (--argc < 1) goto bad; + pubkeyfile = *(++argv); + if (!(pubkeyfp = fopen(pubkeyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, pubkeyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-cert")) { + if (pubkeyfile) { + fprintf(stderr, "%s: options '-pubkey' '-cert' conflict\n", prog); + goto end; + } + if (--argc < 1) goto bad; + certfile = *(++argv); + if (!(certfp = fopen(certfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-sig")) { + if (--argc < 1) goto bad; + sigfile = *(++argv); + if (!(sigfp = fopen(sigfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, sigfile, strerror(errno)); + goto end; + } + + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!sigfile) { + fprintf(stderr, "%s: '-sig' option required\n", prog); + goto end; + } + if ((siglen = fread(sig, 1, sizeof(sig), sigfp)) <= 0) { + fprintf(stderr, "%s: read signature error : %s\n", prog, strerror(errno)); + goto end; + } + + if (pubkeyfile) { + if (sm2_public_key_info_from_pem(&key, pubkeyfp) != 1) { + fprintf(stderr, "%s: parse public key failed\n", prog); + goto end; + } + } else if (certfile) { + if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &key) != 1) { + fprintf(stderr, "%s: parse certificate failed\n", prog); + goto end; + } + } else { + fprintf(stderr, "%s: '-pubkey' or '-cert' option required\n", prog); + goto end; + } + + + if (sm2_verify_init(&verify_ctx, &key, id, strlen(id)) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (sm2_verify_update(&verify_ctx, buf, len) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + } + if ((vr = sm2_verify_finish(&verify_ctx, sig, siglen)) < 0) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + + fprintf(stdout, "verify : %s\n", vr == 1 ? "success" : "failure"); + if (vr == 1) { + ret = 0; + } + +end: + if (infile && infp) fclose(infp); + if (pubkeyfp) fclose(pubkeyfp); + if (certfp) fclose(certfp); + if (sigfp) fclose(sigfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm3.c b/Core/GmSSL-3.1.1/tools/sm3.c new file mode 100644 index 0000000..a68d095 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm3.c @@ -0,0 +1,138 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-hex|-bin] [-pubkey pem [-id str]] [-in file] [-out file]"; + +int sm3_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int bin = 0; + char *pubkeyfile = NULL; + char *infile = NULL; + char *outfile = NULL; + char *id = NULL; + FILE *pubkeyfp = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + SM3_CTX sm3_ctx; + uint8_t dgst[32]; + uint8_t buf[4096]; + size_t len; + int i; + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + printf("usage: echo -n \"abc\" | %s\n", prog); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-hex")) { + if (bin) { + error_print(); + goto end; + } + bin = 0; + } else if (!strcmp(*argv, "-bin")) { + bin = 1; + } else if (!strcmp(*argv, "-pubkey")) { + if (--argc < 1) goto bad; + pubkeyfile = *(++argv); + if (!(pubkeyfp = fopen(pubkeyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, pubkeyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + sm3_init(&sm3_ctx); + + if (pubkeyfile) { + SM2_KEY sm2_key; + uint8_t z[32]; + + if (sm2_public_key_info_from_pem(&sm2_key, pubkeyfp) != 1) { + fprintf(stderr, "%s: parse public key failed\n", prog); + goto end; + } + if (!id) { + id = SM2_DEFAULT_ID; + } + + sm2_compute_z(z, (SM2_POINT *)&sm2_key, id, strlen(id)); + sm3_update(&sm3_ctx, z, sizeof(z)); + } else { + if (id) { + fprintf(stderr, "%s: option '-id' must be with '-pubkey'\n", prog); + goto end; + } + } + + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + sm3_update(&sm3_ctx, buf, len); + } + sm3_finish(&sm3_ctx, dgst); + + if (bin) { + if (fwrite(dgst, 1, sizeof(dgst), outfp) != sizeof(dgst)) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } else { + for (i = 0; i < sizeof(dgst); i++) { + fprintf(outfp, "%02x", dgst[i]); + } + fprintf(outfp, "\n"); + } + ret = 0; +end: + if (pubkeyfp) fclose(pubkeyfp); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm3hmac.c b/Core/GmSSL-3.1.1/tools/sm3hmac.c new file mode 100644 index 0000000..5d1f4c3 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm3hmac.c @@ -0,0 +1,123 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "-key hex [-in file] [-bin|-hex] [-out file]"; + +int sm3hmac_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyhex = NULL; + int bin = 0; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[SM3_DIGEST_SIZE]; + size_t keylen; + FILE *infp = stdin; + FILE *outfp = stdout; + uint8_t buf[4096]; + size_t len; + SM3_HMAC_CTX ctx; + uint8_t mac[SM3_HMAC_SIZE]; + size_t i; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) > sizeof(key) * 2) { + fprintf(stderr, "%s: key should be less than 64 digits (32 bytes)\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "%s: invalid HEX digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-hex")) { + bin = 0; + } else if (!strcmp(*argv, "-bin")) { + bin = 1; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!keyhex) { + fprintf(stderr, "%s: option '-key' required\n", prog); + goto end; + } + + sm3_hmac_init(&ctx, key, keylen); + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + sm3_hmac_update(&ctx, buf, len); + } + sm3_hmac_finish(&ctx, mac); + + if (bin) { + if (fwrite(mac, 1, sizeof(mac), outfp) != sizeof(mac)) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } else { + for (i = 0; i < sizeof(mac); i++) { + fprintf(outfp, "%02x", mac[i]); + } + fprintf(outfp, "\n"); + } + ret = 0; +end: + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(&ctx, sizeof(ctx)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm4.c b/Core/GmSSL-3.1.1/tools/sm4.c new file mode 100755 index 0000000..96fce3b --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm4.c @@ -0,0 +1,392 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SM4_MODE_CBC 1 +#define SM4_MODE_CTR 2 +#define SM4_MODE_GCM 3 +#define SM4_MODE_CBC_SM3_HMAC 4 +#define SM4_MODE_CTR_SM3_HMAC 5 + + +static const char *usage = "(-cbc|-ctr|-gcm|-cbc_sm3_hmac|-ctr_sm3_hmac) {-encrypt|-decrypt} -key hex -iv hex [-aad str| -aad_hex hex] [-in file] [-out file]"; + +static const char *options = +"Options\n" +"\n" +" Modes\n" +"\n" +" -cbc CBC mode with padding, need 16-byte key and 16-byte iv\n" +" -ctr CTR mode, need 16-byte key and 16-byte iv\n" +" -gcm GCM mode, need 16-byte key and any iv length\n" +" -cbc_sm3_hmac CBC mode with padding and HMAC-SM3 (encrypt-then-mac), need 48-byte key and 16-byte iv\n" +" -ctr_sm3_hmac CTR mode with HMAC-SM3 (entrypt-then-mac), need 48-byte key and 16-byte iv\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format\n" +" -iv hex IV in HEX format\n" +" -aad str Authenticated-only message\n" +" -aad_hex hex Authenticated-only data in HEX format\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +" gmssl sm4 -gcm -decrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in ciphertext.bin\n" +"\n" +" echo \"hello\" | gmssl sm4 -cbc_sm3_hmac -encrypt \\\n" +" -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \\\n" +" -iv 11223344556677881122334455667788 -out ciphertext.bin\n" +" gmssl sm4 -cbc_sm3_hmac -decrypt \\\n" +" -key 112233445566778811223344556677881122334455667788112233445566778811223344556677881122334455667788 \\\n" +" -iv 11223344556677881122334455667788 -in ciphertext.bin\n" +"\n"; + +int sm4_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyhex = NULL; + char *ivhex = NULL; + uint8_t *aad = NULL; + uint8_t *aad_buf = NULL; + size_t aadlen = 0; + + char *infile = NULL; + char *outfile = NULL; + uint8_t key[48]; + uint8_t iv[SM4_GCM_MAX_IV_SIZE]; + size_t keylen = sizeof(key); + size_t ivlen = sizeof(iv); + FILE *infp = stdin; + FILE *outfp = stdout; + int mode = 0; + int enc = -1; + int rv; + union { + SM4_CBC_CTX cbc; + SM4_CTR_CTX ctr; + SM4_CBC_SM3_HMAC_CTX cbc_sm3_hmac; + SM4_CTR_SM3_HMAC_CTX ctr_sm3_hmac; + SM4_GCM_CTX gcm; + } sm4_ctx; + uint8_t inbuf[4096]; + size_t inlen; + uint8_t outbuf[4196]; + size_t outlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, usage); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, usage); + printf("%s\n", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) > sizeof(key) * 2) { + fprintf(stderr, "%s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "%s: invalid key hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) > sizeof(iv) * 2) { + fprintf(stderr, "%s: IV length too long\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "%s: invalid IV hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-encrypt")) { + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + enc = 0; + } else if (!strcmp(*argv, "-cbc")) { + if (mode) goto bad; + mode = SM4_MODE_CBC; + } else if (!strcmp(*argv, "-ctr")) { + if (mode) goto bad; + mode = SM4_MODE_CTR; + } else if (!strcmp(*argv, "-cbc_sm3_hmac")) { + if (mode) goto bad; + mode = SM4_MODE_CBC_SM3_HMAC; + } else if (!strcmp(*argv, "-ctr_sm3_hmac")) { + if (mode) goto bad; + mode = SM4_MODE_CTR_SM3_HMAC; + } else if (!strcmp(*argv, "-gcm")) { + if (mode) goto bad; + mode = SM4_MODE_GCM; + } else if (!strcmp(*argv, "-aad")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "%s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + aadlen = strlen((char *)aad); + } else if (!strcmp(*argv, "-aad_hex")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "%s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + if (!(aad_buf = malloc(strlen((char *)aad)/2 + 1))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (hex_to_bytes((char *)aad, strlen((char *)aad), aad_buf, &aadlen) != 1) { + fprintf(stderr, "%s: `-aad_hex` invalid HEX format argument\n", prog); + goto end; + } + aad = aad_buf; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!mode) { + fprintf(stderr, "%s: mode not assigned, `-cbc`, `-ctr`, `-gcm`, `-cbc_sm3_hmac` or `-ctr_sm3_hmac` required\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "%s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "%s: option `-iv` missing\n", prog); + goto end; + } + + switch (mode) { + case SM4_MODE_CTR: + case SM4_MODE_CBC: + case SM4_MODE_GCM: + if (keylen != 16) { + fprintf(stderr, "%s: invalid key length, should be 32 hex digits\n", prog); + goto end; + } + break; + case SM4_MODE_CBC_SM3_HMAC: + case SM4_MODE_CTR_SM3_HMAC: + if (keylen != 48) { + fprintf(stderr, "%s: invalid key length, should be 96 hex digits\n", prog); + goto end; + } + break; + } + + switch (mode) { + case SM4_MODE_CTR: + case SM4_MODE_CBC: + case SM4_MODE_CBC_SM3_HMAC: + case SM4_MODE_CTR_SM3_HMAC: + if (ivlen != 16) { + fprintf(stderr, "%s: invalid IV length, should be 32 hex digits\n", prog); + goto end; + } + break; + } + + switch (mode) { + case SM4_MODE_CBC: + case SM4_MODE_CTR: + if (aad) { + fprintf(stderr, "%s: specified mode does not support `-aad` nor `-aad_hex`\n", prog); + goto end; + } + break; + } + + if (mode == SM4_MODE_CTR) { + if (sm4_ctr_encrypt_init(&sm4_ctx.ctr, key, iv) != 1) { + error_print(); + goto end; + } + while ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) > 0) { + if (sm4_ctr_encrypt_update(&sm4_ctx.ctr, inbuf, inlen, outbuf, &outlen) != 1) { + error_print(); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + if (sm4_ctr_encrypt_finish(&sm4_ctx.ctr, outbuf, &outlen) != 1) { + error_print(); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + goto end; + } + + if (enc < 0) { + fprintf(stderr, "%s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + + if (enc) { + switch (mode) { + case SM4_MODE_CBC: rv = sm4_cbc_encrypt_init(&sm4_ctx.cbc, key, iv); break; + case SM4_MODE_GCM: rv = sm4_gcm_encrypt_init(&sm4_ctx.gcm, key, keylen, iv, ivlen, aad, aadlen, GHASH_SIZE); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_encrypt_init(&sm4_ctx.cbc_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_encrypt_init(&sm4_ctx.ctr_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; + } + if (rv != 1) { + error_print(); + goto end; + } + + while ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) > 0) { + switch (mode) { + case SM4_MODE_CBC: rv = sm4_cbc_encrypt_update(&sm4_ctx.cbc, inbuf, inlen, outbuf, &outlen); break; + case SM4_MODE_GCM: rv = sm4_gcm_encrypt_update(&sm4_ctx.gcm, inbuf, inlen, outbuf, &outlen); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_encrypt_update(&sm4_ctx.cbc_sm3_hmac, inbuf, inlen, outbuf, &outlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_encrypt_update(&sm4_ctx.ctr_sm3_hmac, inbuf, inlen, outbuf, &outlen); break; + } + if (rv != 1) { + error_print(); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + switch (mode) { + case SM4_MODE_CBC: rv = sm4_cbc_encrypt_finish(&sm4_ctx.cbc, outbuf, &outlen); break; + case SM4_MODE_GCM: rv = sm4_gcm_encrypt_finish(&sm4_ctx.gcm, outbuf, &outlen); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_encrypt_finish(&sm4_ctx.cbc_sm3_hmac, outbuf, &outlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_encrypt_finish(&sm4_ctx.ctr_sm3_hmac, outbuf, &outlen); break; + } + if (rv != 1) { + error_print(); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + } else { + switch (mode) { + case SM4_MODE_CBC: rv = sm4_cbc_decrypt_init(&sm4_ctx.cbc, key, iv); break; + case SM4_MODE_GCM: rv = sm4_gcm_decrypt_init(&sm4_ctx.gcm, key, keylen, iv, ivlen, aad, aadlen, GHASH_SIZE); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_decrypt_init(&sm4_ctx.cbc_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_decrypt_init(&sm4_ctx.ctr_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; + } + if (rv != 1) { + error_print(); + goto end; + } + + while ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) > 0) { + switch (mode) { + case SM4_MODE_CBC: rv = sm4_cbc_decrypt_update(&sm4_ctx.cbc, inbuf, inlen, outbuf, &outlen); break; + case SM4_MODE_GCM: rv = sm4_gcm_decrypt_update(&sm4_ctx.gcm, inbuf, inlen, outbuf, &outlen); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_decrypt_update(&sm4_ctx.cbc_sm3_hmac, inbuf, inlen, outbuf, &outlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_decrypt_update(&sm4_ctx.ctr_sm3_hmac, inbuf, inlen, outbuf, &outlen); break; + } + if (rv != 1) { + error_print(); + goto end; + } + + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + switch (mode) { + case SM4_MODE_CBC: rv = sm4_cbc_decrypt_finish(&sm4_ctx.cbc, outbuf, &outlen); break; + case SM4_MODE_GCM: rv = sm4_gcm_decrypt_finish(&sm4_ctx.gcm, outbuf, &outlen); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_decrypt_finish(&sm4_ctx.cbc_sm3_hmac, outbuf, &outlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_decrypt_finish(&sm4_ctx.ctr_sm3_hmac, outbuf, &outlen); break; + } + if (rv != 1) { + error_print(); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + ret = 0; + +end: + gmssl_secure_clear(&sm4_ctx, sizeof(sm4_ctx)); + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(iv, sizeof(iv)); + gmssl_secure_clear(inbuf, sizeof(inbuf)); + gmssl_secure_clear(outbuf, sizeof(outbuf)); + if (aad_buf) { + gmssl_secure_clear(aad_buf, aadlen); + free(aad_buf); + } + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm9decrypt.c b/Core/GmSSL-3.1.1/tools/sm9decrypt.c new file mode 100644 index 0000000..4851ef7 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm9decrypt.c @@ -0,0 +1,117 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-in file] -key file -pass str -id str [-out file]"; + +int sm9decrypt_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *keyfile = NULL; + char *pass = NULL; + char *id = NULL; + char *outfile = NULL; + FILE *keyfp = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + SM9_ENC_KEY key; + uint8_t inbuf[SM9_MAX_CIPHERTEXT_SIZE]; + uint8_t outbuf[SM9_MAX_CIPHERTEXT_SIZE]; + size_t inlen, outlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stdout, "usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + if (!(keyfp = fopen(keyfile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + error_print(); + goto end; + } + } else { +bad: + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; + } + + argc--; + argv++; + } + + if (!keyfile || !pass || !id) { + error_print(); + goto end; + } + + if (sm9_enc_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { + error_print(); + goto end; + } + if ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) <= 0) { + error_print(); + goto end; + } + if (sm9_decrypt(&key, id, strlen(id), inbuf, inlen, outbuf, &outlen) != 1) { + error_print(); + goto end; + } + if (outlen != fwrite(outbuf, 1, outlen, outfp)) { + error_print(); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(&key, sizeof(key)); + gmssl_secure_clear(outbuf, sizeof(outbuf)); + if (keyfp) fclose(keyfp); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm9encrypt.c b/Core/GmSSL-3.1.1/tools/sm9encrypt.c new file mode 100644 index 0000000..d7824a6 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm9encrypt.c @@ -0,0 +1,109 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +static const char *options = "-pubmaster file -id str [-in file] [-out file]"; + + +int sm9encrypt_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *mpkfile = NULL; + char *id = NULL; + char *infile = NULL; + char *outfile = NULL; + FILE *mpkfp = NULL; + FILE *infp = stdin; + FILE *outfp = stdout; + SM9_ENC_MASTER_KEY mpk; + uint8_t inbuf[SM9_MAX_PLAINTEXT_SIZE]; + uint8_t outbuf[SM9_MAX_CIPHERTEXT_SIZE]; + size_t inlen, outlen = sizeof(outbuf); + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stdout, "usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-pubmaster")) { + if (--argc < 1) goto bad; + mpkfile = *(++argv); + if (!(mpkfp = fopen(mpkfile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + error_print(); + goto end; + } + } else { +bad: + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; + } + + argc--; + argv++; + } + + if (!mpkfp || !id) { + error_print(); + goto end; + } + if (sm9_enc_master_public_key_from_pem(&mpk, mpkfp) != 1) { + error_print(); + return -1; + } + if ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) <= 0) { + error_print(); + goto end; + } + if (sm9_encrypt(&mpk, id, strlen(id), inbuf, inlen, outbuf, &outlen) != 1) { + error_print(); + goto end; + } + if (outlen != fwrite(outbuf, 1, outlen, outfp)) { + error_print(); + goto end; + } + ret = 0; +end: + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + if (mpkfp) fclose(mpkfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm9keygen.c b/Core/GmSSL-3.1.1/tools/sm9keygen.c new file mode 100644 index 0000000..b077c80 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm9keygen.c @@ -0,0 +1,131 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + +static const char *options = "-alg (sm9sign|sm9encrypt) -in master_key.pem -inpass str -id str [-out pem] -outpass str"; + +int sm9keygen_main(int argc, char **argv) +{ + int ret = -1; + char *prog = argv[0]; + char *alg = NULL; + char *infile = NULL; + char *inpass = NULL; + char *id = NULL; + char *outfile = NULL; + char *outpass = NULL; + int oid = 0; + FILE *infp = stdin; + FILE *outfp = stdout; + SM9_SIGN_MASTER_KEY sign_msk; + SM9_ENC_MASTER_KEY enc_msk; + SM9_SIGN_KEY sign_key; + SM9_ENC_KEY enc_key; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stdout, "usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-alg")) { + if (--argc < 1) goto bad; + alg = *(++argv); + if ((oid = sm9_oid_from_name(alg)) < 1) { + fprintf(stdout, "%s: invalid alg '%s', should be sm9sign or sm9encrypt\n", prog, alg); + goto end; + } + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-inpass")) { + if (--argc < 1) goto bad; + inpass = *(++argv); + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-outpass")) { + if (--argc < 1) goto bad; + outpass = *(++argv); + } else { +bad: + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; + } + + + argc--; + argv++; + } + + if (!id) { + fprintf(stderr, "%s: option '-id' is required\n", prog); + goto end; + } + if (!inpass || !outpass) { + error_print(); + goto end; + } + + switch (oid) { + case OID_sm9sign: + if (sm9_sign_master_key_info_decrypt_from_pem(&sign_msk, inpass, infp) != 1 + || sm9_sign_master_key_extract_key(&sign_msk, id, strlen(id), &sign_key) != 1 + || sm9_sign_key_info_encrypt_to_pem(&sign_key, outpass, outfp) != 1) { + error_print(); + goto end; + } + break; + case OID_sm9encrypt: + if (sm9_enc_master_key_info_decrypt_from_pem(&enc_msk, inpass, infp) != 1 + || sm9_enc_master_key_extract_key(&enc_msk, id, strlen(id), &enc_key) != 1 + || sm9_enc_key_info_encrypt_to_pem(&enc_key, outpass, outfp) != 1) { + error_print(); + goto end; + } + break; + default: + error_print(); + goto end; + } + ret = 0; +end: + gmssl_secure_clear(&sign_msk, sizeof(sign_msk)); + gmssl_secure_clear(&enc_msk, sizeof(enc_msk)); + gmssl_secure_clear(&sign_key, sizeof(sign_key)); + gmssl_secure_clear(&enc_key, sizeof(enc_key)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return 1; +} diff --git a/Core/GmSSL-3.1.1/tools/sm9setup.c b/Core/GmSSL-3.1.1/tools/sm9setup.c new file mode 100644 index 0000000..4dc07fe --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm9setup.c @@ -0,0 +1,139 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + +static const char *options = "-alg (sm9sign|sm9encrypt) [-pass password] [-out pem] [-pubout pem]"; + +int sm9setup_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *alg = NULL; + char *pass = NULL; + char *outfile = NULL; + char *puboutfile = NULL; + int oid; + FILE *outfp = stdout; + FILE *puboutfp = stdout; + SM9_SIGN_MASTER_KEY sign_msk; + SM9_ENC_MASTER_KEY enc_msk; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stdout, "usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-alg")) { + if (--argc < 1) goto bad; + alg = *(++argv); + if ((oid = sm9_oid_from_name(alg)) < 1) { + fprintf(stdout, "%s: invalid alg '%s', should be sm9sign or sm9encrypt\n", prog, alg); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-pubout")) { + if (--argc < 1) goto bad; + puboutfile = *(++argv); + if (!(puboutfp = fopen(puboutfile, "wb"))) { + error_print(); + goto end; + } + } else { +bad: + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; + } + + argc--; + argv++; + } + + if (!alg) { + error_print(); + return -1; + } + if (!pass) { + error_print(); + return -1; + } + + switch (oid) { + case OID_sm9sign: + if (sm9_sign_master_key_generate(&sign_msk) != 1 + || sm9_sign_master_key_info_encrypt_to_pem(&sign_msk, pass, outfp) != 1 + || sm9_sign_master_public_key_to_pem(&sign_msk, puboutfp) != 1) { + error_print(); + goto end; + } + break; + case OID_sm9encrypt: + if (sm9_enc_master_key_generate(&enc_msk) != 1 + || sm9_enc_master_key_info_encrypt_to_pem(&enc_msk, pass, outfp) != 1 + || sm9_enc_master_public_key_to_pem(&enc_msk, puboutfp) != 1) { + error_print(); + goto end; + } + break; + default: + error_print(); + goto end; + } + ret = 0; + +end: + gmssl_secure_clear(&sign_msk, sizeof(sign_msk)); + gmssl_secure_clear(&enc_msk, sizeof(enc_msk)); + if (outfile && outfp) fclose(outfp); + if (puboutfile && puboutfp) fclose(puboutfp); + return 1; +} + + + + + + + + + + + + + + + + + + + + diff --git a/Core/GmSSL-3.1.1/tools/sm9sign.c b/Core/GmSSL-3.1.1/tools/sm9sign.c new file mode 100644 index 0000000..4e3bbba --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm9sign.c @@ -0,0 +1,127 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-in file] -key file -pass str [-out file]"; + + +int sm9sign_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *keyfile = NULL; + char *pass = NULL; + char *outfile = NULL; + FILE *infp = stdin; + FILE *keyfp = NULL; + FILE *outfp = stdout; + SM9_SIGN_KEY key; + SM9_SIGN_CTX ctx; + uint8_t buf[4096]; + size_t len; + uint8_t sig[SM9_SIGNATURE_SIZE]; + size_t siglen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stdout, "usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + if (!(keyfp = fopen(keyfile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + error_print(); + goto end; + } + } else { +bad: + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; + } + + argc--; + argv++; + } + + if (!keyfile || !pass) { + error_print(); + goto end; + } + + if (sm9_sign_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { + error_print(); + return -1; + } + + if (sm9_sign_init(&ctx) != 1) { + error_print(); + goto end; + } + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (sm9_sign_update(&ctx, buf, len) != 1) { + error_print(); + goto end; + } + } + if (sm9_sign_finish(&ctx, &key, sig, &siglen) != 1) { + error_print(); + goto end; + } + + if (siglen != fwrite(sig, 1, siglen, outfp)) { + error_print(); + goto end; + } + + + + ret = 0; + +end: + gmssl_secure_clear(&key, sizeof(key)); + gmssl_secure_clear(&ctx, sizeof(ctx)); + gmssl_secure_clear(buf, sizeof(buf)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/sm9verify.c b/Core/GmSSL-3.1.1/tools/sm9verify.c new file mode 100644 index 0000000..dc92813 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/sm9verify.c @@ -0,0 +1,128 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + + +static const char *options = "[-in file] -pubmaster file -id str -sig file"; + +int sm9verify_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *mpkfile = NULL; + char *id = NULL; + char *sigfile = NULL; + FILE *infp = stdin; + FILE *mpkfp = NULL; + FILE *sigfp = NULL; + SM9_SIGN_MASTER_KEY mpk; + SM9_SIGN_CTX ctx; + uint8_t buf[4096]; + size_t len; + uint8_t sig[SM9_SIGNATURE_SIZE]; + size_t siglen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stdout, "usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-pubmaster")) { + if (--argc < 1) goto bad; + mpkfile = *(++argv); + if (!(mpkfp = fopen(mpkfile, "rb"))) { + error_print(); + goto end; + } + } else if (!strcmp(*argv, "-id")) { + if (--argc < 1) goto bad; + id = *(++argv); + } else if (!strcmp(*argv, "-sig")) { + if (--argc < 1) goto bad; + sigfile = *(++argv); + if (!(sigfp = fopen(sigfile, "rb"))) { + error_print(); + goto end; + } + } else { +bad: + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; + } + + argc--; + argv++; + } + + if (!mpkfile || !id || !sigfile) { + error_print(); + goto end; + } + + if (sm9_sign_master_public_key_from_pem(&mpk, mpkfp) != 1) { + error_print(); + goto end; + } + + if ((siglen = fread(sig, 1, sizeof(sig), sigfp)) <= 0) { + error_print(); + goto end; + } + + if (sm9_verify_init(&ctx) != 1) { + error_print(); + goto end; + } + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (sm9_verify_update(&ctx, buf, len) != 1) { + error_print(); + goto end; + } + } + if ((ret = sm9_verify_finish(&ctx, sig, siglen, &mpk, id, strlen(id))) != 1) { + error_print(); + goto end; + } + printf("%s %s\n", prog, ret ? "success" : "failure"); + +end: + if (infile && infp) fclose(infp); + if (mpkfile && mpkfp) fclose(mpkfp); + if (sigfile && sigfp) fclose(sigfp); + return ret; +} + + + + + + + + diff --git a/Core/GmSSL-3.1.1/tools/tlcp_client.c b/Core/GmSSL-3.1.1/tools/tlcp_client.c new file mode 100644 index 0000000..a4aecc2 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/tlcp_client.c @@ -0,0 +1,225 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +static int client_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3, }; + +static const char *http_get = + "GET / HTTP/1.1\r\n" + "Hostname: aaa\r\n" + "\r\n\r\n"; + +static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str]"; + +int tlcp_client_main(int argc, char *argv[]) +{ + int ret = -1; + char *prog = argv[0]; + char *host = NULL; + int port = 443; + char *cacertfile = NULL; + char *certfile = NULL; + char *keyfile = NULL; + char *pass = NULL; + struct hostent *hp; + struct sockaddr_in server; + tls_socket_t sock; + int sock_inited = 0; + TLS_CTX ctx; + TLS_CONNECT conn; + char buf[1024] = {0}; + size_t len = sizeof(buf); + char send_buf[1024] = {0}; + + argc--; + argv++; + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + while (argc >= 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-host")) { + if (--argc < 1) goto bad; + host = *(++argv); + } else if (!strcmp(*argv, "-port")) { + if (--argc < 1) goto bad; + port = atoi(*(++argv)); + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else { + fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv); + return 0; + } + argc--; + argv++; + } + + if (!host) { + fprintf(stderr, "%s: '-in' option required\n", prog); + return -1; + } + + if (tls_socket_lib_init() != 1) { + error_print(); + return -1; + } + + if (!(hp = gethostbyname(host))) { + //herror("tlcp_client: '-host' invalid"); + goto end; + } + + memset(&ctx, 0, sizeof(ctx)); + memset(&conn, 0, sizeof(conn)); + + server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]); + server.sin_family = AF_INET; + server.sin_port = htons(port); + + + if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) { + fprintf(stderr, "%s: open socket error\n", prog); + goto end; + } + sock_inited = 1; + + if (tls_socket_connect(sock, &server) != 1) { + fprintf(stderr, "%s: socket connect error\n", prog); + goto end; + } + + if (tls_ctx_init(&ctx, TLS_protocol_tlcp, TLS_client_mode) != 1 + || tls_ctx_set_cipher_suites(&ctx, client_ciphers, sizeof(client_ciphers)/sizeof(client_ciphers[0])) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + if (cacertfile) { + if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + } + if (certfile) { + if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + } + + if (tls_init(&conn, &ctx) != 1 + || tls_set_socket(&conn, sock) != 1 + || tls_do_handshake(&conn) != 1) { + fprintf(stderr, "%s: error\n", prog); + goto end; + } + + for (;;) { + fd_set fds; + size_t sentlen; + + if (!fgets(send_buf, sizeof(send_buf), stdin)) { + if (feof(stdin)) { + tls_shutdown(&conn); + goto end; + } else { + continue; + } + } + if (tls_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + + FD_ZERO(&fds); + FD_SET(conn.sock, &fds); +#ifdef WIN32 +#else + FD_SET(fileno(stdin), &fds); //FD_SET(STDIN_FILENO, &fds); // NOT allowed in winsock2 !!! +#endif + + if (select((int)(conn.sock + 1), // WinSock2 select() ignore this arg + &fds, NULL, NULL, NULL) < 0) { + fprintf(stderr, "%s: select failed\n", prog); +#ifdef WIN32 + fprintf(stderr, "WSAGetLastError = %u\n", WSAGetLastError()); +#endif + goto end; + } + + if (FD_ISSET(conn.sock, &fds)) { + for (;;) { + memset(buf, 0, sizeof(buf)); + if (tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) { + goto end; + } + fwrite(buf, 1, len, stdout); + fflush(stdout); + + // 应该调整tls_recv 逻辑、API或者其他方式 + if (conn.datalen == 0) { + break; + } + } + + } +#ifdef WIN32 +#else + if (FD_ISSET(fileno(stdin), &fds)) { + fprintf(stderr, "recv from stdin\n"); + + memset(send_buf, 0, sizeof(send_buf)); + + if (!fgets(send_buf, sizeof(send_buf), stdin)) { + if (feof(stdin)) { + tls_shutdown(&conn); + goto end; + } else { + continue; + } + } + if (tls_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + } +#endif + + fprintf(stderr, "end of this round\n"); + } + +end: + if (sock_inited) tls_socket_close(sock); + tls_ctx_cleanup(&ctx); + tls_cleanup(&conn); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tools/tlcp_server.c b/Core/GmSSL-3.1.1/tools/tlcp_server.c new file mode 100644 index 0000000..e0abfff --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/tlcp_server.c @@ -0,0 +1,198 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-port num] -cert file -key file [-pass str] -ex_key file [-ex_pass str] [-cacert file]"; + +int tlcp_server_main(int argc , char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int port = 443; + char *certfile = NULL; + char *signkeyfile = NULL; + char *signpass = NULL; + char *enckeyfile = NULL; + char *encpass = NULL; + char *cacertfile = NULL; + + int server_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3, }; + + TLS_CTX ctx; + TLS_CONNECT conn; + char buf[1600] = {0}; + size_t len = sizeof(buf); + tls_socket_t sock; + tls_socket_t conn_sock; + struct sockaddr_in server_addr; + struct sockaddr_in client_addr; + tls_socklen_t client_addrlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-port")) { + if (--argc < 1) goto bad; + port = atoi(*(++argv)); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + signkeyfile = *(++argv); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + signpass = *(++argv); + } else if (!strcmp(*argv, "-ex_key")) { + if (--argc < 1) goto bad; + enckeyfile = *(++argv); + } else if (!strcmp(*argv, "-ex_pass")) { + if (--argc < 1) goto bad; + encpass = *(++argv); + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + } else { + fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv); + return 1; + } + argc--; + argv++; + } + if (!certfile) { + fprintf(stderr, "%s: '-cert' option required\n", prog); + return 1; + } + if (!signkeyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + return 1; + } + if (!signpass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + return 1; + } + if (!enckeyfile) { + fprintf(stderr, "%s: '-ex_key' option required\n", prog); + return 1; + } + if (!encpass) { + fprintf(stderr, "%s: '-ex_pass' option required\n", prog); + return 1; + } + + memset(&ctx, 0, sizeof(ctx)); + memset(&conn, 0, sizeof(conn)); + + if (tls_ctx_init(&ctx, TLS_protocol_tlcp, TLS_server_mode) != 1 + || tls_ctx_set_cipher_suites(&ctx, server_ciphers, sizeof(server_ciphers)/sizeof(int)) != 1 + || tls_ctx_set_tlcp_server_certificate_and_keys(&ctx, certfile, signkeyfile, signpass, enckeyfile, encpass) != 1) { + error_print(); + return -1; + } + if (cacertfile) { + if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) { + error_print(); + return -1; + } + } + + + if (tls_socket_lib_init() != 1) { + error_print(); + return -1; + } + + if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) { + 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 (tls_socket_bind(sock, &server_addr) != 1) { + fprintf(stderr, "%s: socket bind error\n", prog); + goto end; + } + + puts("start listen ...\n"); + tls_socket_listen(sock, 1); + + +restart: + + client_addrlen = sizeof(client_addr); + + if (tls_socket_accept(sock, &client_addr, &conn_sock) != 1) { + fprintf(stderr, "%s: socket accept error\n", prog); + goto end; + } + puts("socket connected\n"); + + if (tls_init(&conn, &ctx) != 1 + || tls_set_socket(&conn, conn_sock) != 1) { + error_print(); + return -1; + } + + if (tls_do_handshake(&conn) != 1) { + error_print(); // 为什么这个会触发呢? + return -1; + } + + for (;;) { + + int rv; + size_t sentlen; + + do { + len = sizeof(buf); + if ((rv = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) { + if (rv < 0) fprintf(stderr, "%s: recv failure\n", prog); + else fprintf(stderr, "%s: Disconnected by remote\n", prog); + + //tls_socket_close(conn.sock); // FIXME: + tls_cleanup(&conn); + goto restart; + } + } while (!len); + + if (tls_send(&conn, (uint8_t *)buf, len, &sentlen) != 1) { + fprintf(stderr, "%s: send failure, close connection\n", prog); + tls_socket_close(conn.sock); + goto end; + } + } + + +end: + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/tls12_client.c b/Core/GmSSL-3.1.1/tools/tls12_client.c new file mode 100644 index 0000000..b97f48d --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/tls12_client.c @@ -0,0 +1,217 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +// TLSv1.2客户单和TLCP客户端可能没有什么区别 + +static int client_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3 }; + +static const char *http_get = + "GET / HTTP/1.1\r\n" + "Hostname: aaa\r\n" + "\r\n\r\n"; + +static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str]"; + +int tls12_client_main(int argc, char *argv[]) +{ + int ret = -1; + char *prog = argv[0]; + char *host = NULL; + int port = 443; + char *cacertfile = NULL; + char *certfile = NULL; + char *keyfile = NULL; + char *pass = NULL; + struct hostent *hp; + struct sockaddr_in server; + tls_socket_t sock; + TLS_CTX ctx; + TLS_CONNECT conn; + char buf[1024] = {0}; + size_t len = sizeof(buf); + char send_buf[1024] = {0}; + + argc--; + argv++; + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + while (argc >= 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-host")) { + if (--argc < 1) goto bad; + host = *(++argv); + } else if (!strcmp(*argv, "-port")) { + if (--argc < 1) goto bad; + port = atoi(*(++argv)); + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else { + fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv); + return 0; + } + argc--; + argv++; + } + + if (!host) { + fprintf(stderr, "%s: '-in' option required\n", prog); + return -1; + } + + if (tls_socket_lib_init() != 1) { + error_print(); + return -1; + } + + if (!(hp = gethostbyname(host))) { + //herror("tls12_client: '-host' invalid"); // herror() not in winsock2, use WSAGetLastError() instead + goto end; + } + + memset(&ctx, 0, sizeof(ctx)); + memset(&conn, 0, sizeof(conn)); + + server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]); + server.sin_family = AF_INET; + server.sin_port = htons(port); + + + if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) { + fprintf(stderr, "%s: create socket error\n", prog); + goto end; + } + if (tls_socket_connect(sock, &server) != 1) { + fprintf(stderr, "%s: socket connect error\n", prog); + goto end; + } + + if (tls_ctx_init(&ctx, TLS_protocol_tls12, TLS_client_mode) != 1 + || tls_ctx_set_cipher_suites(&ctx, client_ciphers, sizeof(client_ciphers)/sizeof(client_ciphers[0])) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + if (cacertfile) { + if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + } + if (certfile) { + if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + } + + if (tls_init(&conn, &ctx) != 1 + || tls_set_socket(&conn, sock) != 1 + || tls_do_handshake(&conn) != 1) { + fprintf(stderr, "%s: error\n", prog); + goto end; + } + + for (;;) { + fd_set fds; + size_t sentlen; + + if (!fgets(send_buf, sizeof(send_buf), stdin)) { + if (feof(stdin)) { + tls_shutdown(&conn); + goto end; + } else { + continue; + } + } + if (tls_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + + FD_ZERO(&fds); + FD_SET(conn.sock, &fds); +#ifdef WIN32 +#else + FD_SET(fileno(stdin), &fds); +#endif + + if (select((int)(conn.sock + 1), &fds, NULL, NULL, NULL) < 0) { + fprintf(stderr, "%s: select failed\n", prog); + goto end; + } + + if (FD_ISSET(conn.sock, &fds)) { + for (;;) { + memset(buf, 0, sizeof(buf)); + if (tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) { + goto end; + } + fwrite(buf, 1, len, stdout); + fflush(stdout); + + // 应该调整tls_recv 逻辑、API或者其他方式 + if (conn.datalen == 0) { + break; + } + } + + } +#ifdef WIN32 +#else + if (FD_ISSET(fileno(stdin), &fds)) { + memset(send_buf, 0, sizeof(send_buf)); + + if (!fgets(send_buf, sizeof(send_buf), stdin)) { + if (feof(stdin)) { + tls_shutdown(&conn); + goto end; + } else { + continue; + } + } + if (tls_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + } +#endif + } + + +end: + tls_socket_close(sock); + tls_ctx_cleanup(&ctx); + tls_cleanup(&conn); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tools/tls12_server.c b/Core/GmSSL-3.1.1/tools/tls12_server.c new file mode 100644 index 0000000..55aa45a --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/tls12_server.c @@ -0,0 +1,183 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-port num] -cert file -key file -pass str [-cacert file]"; + +int tls12_server_main(int argc , char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int port = 443; + char *certfile = NULL; + char *keyfile = NULL; + char *pass = NULL; + char *cacertfile = NULL; + + int server_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3, }; + + TLS_CTX ctx; + TLS_CONNECT conn; + char buf[1600] = {0}; + size_t len = sizeof(buf); + tls_socket_t sock; + tls_socket_t conn_sock; + struct sockaddr_in server_addr; + struct sockaddr_in client_addr; + tls_socklen_t client_addrlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-port")) { + if (--argc < 1) goto bad; + port = atoi(*(++argv)); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + } else { + fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv); + return 1; + } + argc--; + argv++; + } + if (!certfile) { + fprintf(stderr, "%s: '-cert' option required\n", prog); + return 1; + } + if (!keyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + return 1; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + return 1; + } + + memset(&ctx, 0, sizeof(ctx)); + memset(&conn, 0, sizeof(conn)); + + if (tls_socket_lib_init() != 1) { + error_print(); + return -1; + } + + if (tls_ctx_init(&ctx, TLS_protocol_tls12, TLS_server_mode) != 1 + || tls_ctx_set_cipher_suites(&ctx, server_ciphers, sizeof(server_ciphers)/sizeof(int)) != 1 + || tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) { + error_print(); + return -1; + } + if (cacertfile) { + if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) { + error_print(); + return -1; + } + } + + // Socket + + if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) { + fprintf(stderr, "%s: create socket error\n", prog); + goto end; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port); + + if (tls_socket_bind(sock, &server_addr) != 1) { + fprintf(stderr, "%s: socket bind error\n", prog); + goto end; + } + + puts("start listen ...\n"); + tls_socket_listen(sock, 1); + +restart: + + //client_addrlen = sizeof(client_addr); + + if (tls_socket_accept(sock, &client_addr, &conn_sock) != 1) { + fprintf(stderr, "%s: socket accept error\n", prog); + goto end; + } + puts("socket connected\n"); + + if (tls_init(&conn, &ctx) != 1 + || tls_set_socket(&conn, conn_sock) != 1) { + error_print(); + return -1; + } + + if (tls_do_handshake(&conn) != 1) { + error_print(); // 为什么这个会触发呢? + return -1; + } + + for (;;) { + + int rv; + size_t sentlen; + + do { + len = sizeof(buf); + if ((rv = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) { + if (rv < 0) fprintf(stderr, "%s: recv failure\n", prog); + else fprintf(stderr, "%s: Disconnected by remote\n", prog); + + //tls_socket_close(conn.sock); // FIXME: + tls_cleanup(&conn); + goto restart; + } + } while (!len); + + if (tls_send(&conn, (uint8_t *)buf, len, &sentlen) != 1) { + fprintf(stderr, "%s: send failure, close connection\n", prog); + tls_socket_close(conn.sock); + goto end; + } + } + + +end: + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/tls13_client.c b/Core/GmSSL-3.1.1/tools/tls13_client.c new file mode 100644 index 0000000..156782d --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/tls13_client.c @@ -0,0 +1,215 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include + + +// TLSv1.2客户单和TLCP客户端可能没有什么区别 + +static int client_ciphers[] = { TLS_cipher_sm4_gcm_sm3 }; + +static const char *http_get = + "GET / HTTP/1.1\r\n" + "Hostname: aaa\r\n" + "\r\n\r\n"; + +static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str]"; + +int tls13_client_main(int argc, char *argv[]) +{ + int ret = -1; + char *prog = argv[0]; + char *host = NULL; + int port = 443; + char *cacertfile = NULL; + char *certfile = NULL; + char *keyfile = NULL; + char *pass = NULL; + struct hostent *hp; + struct sockaddr_in server; + tls_socket_t sock; + TLS_CTX ctx; + TLS_CONNECT conn; + char buf[1024] = {0}; + size_t len = sizeof(buf); + char send_buf[1024] = {0}; + + argc--; + argv++; + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + while (argc >= 1) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-host")) { + if (--argc < 1) goto bad; + host = *(++argv); + } else if (!strcmp(*argv, "-port")) { + if (--argc < 1) goto bad; + port = atoi(*(++argv)); + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else { + fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv); + return 0; + } + argc--; + argv++; + } + + if (!host) { + fprintf(stderr, "%s: '-in' option required\n", prog); + return -1; + } + + if (tls_socket_lib_init() != 1) { + error_print(); + return -1; + } + if (!(hp = gethostbyname(host))) { + //herror("tls13_client: '-host' invalid"); + goto end; + } + + memset(&ctx, 0, sizeof(ctx)); + memset(&conn, 0, sizeof(conn)); + + server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]); + server.sin_family = AF_INET; + server.sin_port = htons(port); + + if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) { + fprintf(stderr, "%s: socket create error\n", prog); + goto end; + } + if (tls_socket_connect(sock, &server) != 1) { + fprintf(stderr, "%s: socket connect error\n", prog); + goto end; + } + + if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_client_mode) != 1 + || tls_ctx_set_cipher_suites(&ctx, client_ciphers, sizeof(client_ciphers)/sizeof(client_ciphers[0])) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + if (cacertfile) { + if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + } + if (certfile) { + if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) { + fprintf(stderr, "%s: context init error\n", prog); + goto end; + } + } + if (tls_init(&conn, &ctx) != 1 + || tls_set_socket(&conn, sock) != 1 + || tls_do_handshake(&conn) != 1) { + fprintf(stderr, "%s: error\n", prog); + goto end; + } + + for (;;) { + fd_set fds; + size_t sentlen; + + if (!fgets(send_buf, sizeof(send_buf), stdin)) { + if (feof(stdin)) { + tls_shutdown(&conn); + goto end; + } else { + continue; + } + } + if (tls13_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + + + FD_ZERO(&fds); + FD_SET(conn.sock, &fds); +#ifdef WIN32 +#else + FD_SET(fileno(stdin), &fds); +#endif + + if (select((int)(conn.sock + 1), // In WinSock2, select() ignore the this arg + &fds, NULL, NULL, NULL) < 0) { + fprintf(stderr, "%s: select failed\n", prog); + goto end; + } + + if (FD_ISSET(conn.sock, &fds)) { + for (;;) { + memset(buf, 0, sizeof(buf)); + if (tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) { + goto end; + } + fwrite(buf, 1, len, stdout); + fflush(stdout); + + // 应该调整tls_recv 逻辑、API或者其他方式 + if (conn.datalen == 0) { + break; + } + } + + } +#ifdef WIN32 +#else + if (FD_ISSET(fileno(stdin), &fds)) { + memset(send_buf, 0, sizeof(send_buf)); + + if (!fgets(send_buf, sizeof(send_buf), stdin)) { + if (feof(stdin)) { + tls_shutdown(&conn); + goto end; + } else { + continue; + } + } + if (tls13_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) { + fprintf(stderr, "%s: send error\n", prog); + goto end; + } + } +#endif + } + +end: + tls_socket_close(sock); + tls_ctx_cleanup(&ctx); + tls_cleanup(&conn); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tools/tls13_server.c b/Core/GmSSL-3.1.1/tools/tls13_server.c new file mode 100644 index 0000000..a86ac5c --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/tls13_server.c @@ -0,0 +1,177 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-port num] -cert file -key file -pass str [-cacert file]"; + +int tls13_server_main(int argc , char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int port = 443; + char *certfile = NULL; + char *keyfile = NULL; + char *pass = NULL; + char *cacertfile = NULL; + int server_ciphers[] = { TLS_cipher_sm4_gcm_sm3, }; + TLS_CTX ctx; + TLS_CONNECT conn; + char buf[1600] = {0}; + size_t len = sizeof(buf); + tls_socket_t sock; + tls_socket_t conn_sock; + struct sockaddr_in server_addr; + struct sockaddr_in client_addr; + tls_socklen_t client_addrlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "-port")) { + if (--argc < 1) goto bad; + port = atoi(*(++argv)); + } else if (!strcmp(*argv, "-cert")) { + if (--argc < 1) goto bad; + certfile = *(++argv); + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + } else { + fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv); + return 1; + } + argc--; + argv++; + } + if (!certfile) { + fprintf(stderr, "%s: '-cert' option required\n", prog); + return 1; + } + if (!keyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + return 1; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + return 1; + } + if (tls_socket_lib_init() != 1) { + error_print(); + return -1; + } + + memset(&ctx, 0, sizeof(ctx)); + memset(&conn, 0, sizeof(conn)); + + if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_server_mode) != 1 + || tls_ctx_set_cipher_suites(&ctx, server_ciphers, sizeof(server_ciphers)/sizeof(int)) != 1 + || tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) { + error_print(); + return -1; + } + if (cacertfile) { + if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) { + error_print(); + return -1; + } + } + + + if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) { + fprintf(stderr, "%s: socket create error\n", prog); + goto end; + } + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port); + if (tls_socket_bind(sock, &server_addr) != 1) { + fprintf(stderr, "%s: socket bind error\n", prog); + goto end; + } + puts("start listen ...\n"); + tls_socket_listen(sock, 1); + + + +restart: + + //client_addrlen = sizeof(client_addr); + if (tls_socket_accept(sock, &client_addr, &conn_sock) != 1) { + fprintf(stderr, "%s: socket accept error\n", prog); + goto end; + } + puts("socket connected\n"); + + if (tls_init(&conn, &ctx) != 1 + || tls_set_socket(&conn, conn_sock) != 1) { + error_print(); + return -1; + } + + if (tls_do_handshake(&conn) != 1) { + error_print(); // 为什么这个会触发呢? + return -1; + } + + for (;;) { + + int rv; + size_t sentlen; + + do { + len = sizeof(buf); + if ((rv = tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) { + if (rv < 0) fprintf(stderr, "%s: recv failure\n", prog); + else fprintf(stderr, "%s: Disconnected by remote\n", prog); + + //close(conn.sock); + tls_cleanup(&conn); + goto restart; + } + } while (!len); + + if (tls13_send(&conn, (uint8_t *)buf, len, &sentlen) != 1) { + fprintf(stderr, "%s: send failure, close connection\n", prog); + tls_socket_close(conn.sock); + goto end; + } + } + + +end: + return ret; +} diff --git a/Core/GmSSL-3.1.1/tools/version.c b/Core/GmSSL-3.1.1/tools/version.c new file mode 100644 index 0000000..3ebe6c4 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/version.c @@ -0,0 +1,21 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include + + +int version_main(int argc, char **argv) +{ + printf("%s\n", gmssl_version_str()); + return 0; +} diff --git a/Core/GmSSL-3.1.1/tools/zuc.c b/Core/GmSSL-3.1.1/tools/zuc.c new file mode 100644 index 0000000..797fea9 --- /dev/null +++ b/Core/GmSSL-3.1.1/tools/zuc.c @@ -0,0 +1,144 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = "-key hex -iv hex [-in file] [-out file]"; + +int zuc_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyhex = NULL; + char *ivhex = NULL; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + uint8_t iv[16]; + size_t keylen = sizeof(key); + size_t ivlen = sizeof(iv); + FILE *infp = stdin; + FILE *outfp = stdout; + ZUC_CTX zuc_ctx; + uint8_t inbuf[4096]; + size_t inlen; + uint8_t outbuf[4196]; + size_t outlen; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "%s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "%s: invalid HEX digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) != sizeof(iv) * 2) { + fprintf(stderr, "%s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "%s: invalid HEX digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!keyhex) { + fprintf(stderr, "%s: option '-key' missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "%s: option '-iv' missing\n", prog); + goto end; + } + + if (zuc_encrypt_init(&zuc_ctx, key, iv) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + while ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) > 0) { + if (zuc_encrypt_update(&zuc_ctx, inbuf, inlen, outbuf, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + if (zuc_encrypt_finish(&zuc_ctx, outbuf, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + ret = 0; +end: + gmssl_secure_clear(&zuc_ctx, sizeof(zuc_ctx)); + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(iv, sizeof(iv)); + gmssl_secure_clear(inbuf, sizeof(inbuf)); + gmssl_secure_clear(outbuf, sizeof(outbuf)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/LICENSE b/Core/LICENSE similarity index 100% rename from LICENSE rename to Core/LICENSE diff --git a/DEVELOP.md b/DEVELOP.md deleted file mode 100644 index 4f8874a..0000000 --- a/DEVELOP.md +++ /dev/null @@ -1,12 +0,0 @@ -# GmSSL-Python Develop - -## Publish to PiPy - -See https://packaging.python.org/distributing/ - -1. Update version in `gmssl.py` -2. Update version in `pyproject.toml` -3. Build package, run `python3 -m build` -4. Publish package to PiPy, run `python3 -m twine upload dist/*` - - diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..0be95a1 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include README.md +include *.py +recursive-include easy_gmssl/ * \ No newline at end of file diff --git a/README.md b/README.md index bff227f..3298bb8 100644 --- a/README.md +++ b/README.md @@ -1,917 +1,208 @@ -# GmSSL-Python +# EasyGmssl-Python -## 简介 +## 一、概述 -`gmssl-python`是GmSSL密码库 https://github.com/guanzhi/GmSSL 的Python语言封装,以`ctypes`方式实现,通过Python类和函数提供了如下密码接口: +EasyGmSSL FORK 自**北京大学 GUNAZHI 老师团队的开源国密算法库**: [GmSSL](https://github.com/guanzhi/GmSSL),EasyGmSSL旨在为开发者提供一套接口更加友好的国密算法应用开发工具。它涵盖了SM2、SM3、SM4等国密算法的核心功能,并针对实际使用场景中的痛点进行了针对性改进。 -* 密码随机数生成器 -* SM2加密和签名,SM2密钥生成、私钥口令加密保护、密钥PEM文件导入导出 -* SM2数字证书的导入、解析和验证 -* SM3哈希函数、HMAC-SM3消息认证码、基于SM3的PBKDF2密钥导出函数 -* SM4分组加密,以及SM4的CBC、CTR、GCM三种加密模式 -* SM9加密和签名,以及SM9密钥生成、密钥口令加密保护、密钥PEM文件导入导出 -* ZUC序列密码加密 +此 SDK 的 git 地址为:https://github.com/bowenerchen/GmSSL-Python -目前`gmssl-python`功能可以覆盖除SSL/TLS/TLCP之外的国密算法主要应用开发场景。 +## 二、特色功能 -## 安装 +1. **便捷安装** + - 在通过pip安装本SDK时,具备自动编译底层C库的能力,并且会智能地安装编译好的二进制文件,避免对系统路径造成污染,确保了安装过程的简洁性与独立性,让您无需繁琐的手动配置即可快速上手。 + +2. **SM2增强功能** + - **密钥加解密模式多样化** + 新增了多种SM2密钥加解密模式选择,包括C1C3C2、C1C3C2_ASN1、C1C2C3、C1C2C3_ASN1。这些模式为不同应用需求提供了更灵活的加密策略,无论是在对加密效率有要求,还是对加密数据格式兼容性有考量的场景下,都能找到合适的解决方案。 + + - **签名验签模式扩展** + 在SM2签名验签时,增加了RS_ASN1、RS两种模式选择,适应不同的签名规范和验证场景,使签名验签操作更加贴合实际业务需求。 + + - **密钥读取便捷化** + 允许用户轻松读取SM2公钥、私钥的十六进制明文,方便在调试、密钥管理等环节快速获取关键信息,提升开发效率。 + +3. **基础算法优化** + + 对于SM4和SM3以及随机数生成部分,虽然核心算法基于底层库,但在接口层着重增加了参数说明。这使得即使是初次接触国密算法的开发者,也能迅速理解每个参数的含义与用途,降低了开发门槛,加速项目开发进程。 -由于`gmssl-python`以`ctypes`方式实现,因此所有密码功能都是通过调用本地安装的GmSSL动态库 (如`/usr/local/lib/libgmssl.so`)实现的,在安装和调用`gmssl-python`之前必须首先在系统上安装GmSSL,然后通过Python的包管理工具`pip`从Python代码仓库安装,或者从`gmssl-python`项目的代码仓库https://github.com/GmSSL/GmSSL-Python 下载最新的源代码,从本地安装。 +## 三、安装指南 -### 安装GmSSL - -首先在https://github.com/guanzhi/GmSSL 项目上下载最新的GmSSL代码[GmSSL-master.zip](https://github.com/guanzhi/GmSSL/archive/refs/heads/master.zip),编译并安装。GmSSL代码是C语言编写的,需要安装GCC、CMake来编译,在Ubuntu/Debian系统上可以执行 - -```bash -sudo install build-essentials cmake -``` - -安装依赖的编译工具,然后解压GmSSL源代码,进入源码目录`GmSSL-master`并执行如下指令: - -```bash -$ mkdir build -$ cd build -$ cmake .. -$ make -$ make test -$ sudo make install -``` - -安装完成后可以执行`gmssl`命令行工具检查是否安装完毕。 - -```bash -$ gmssl help -``` - -由于`gmssl-python`需要`libgmssl`动态库,因此GmSSL安装时不要改变配置,仅以静态库安装时`gmssl-python`是不可用的。安装后执行`gmssl`命令可能提示找不到动态库,在Ubuntu系统下可以执行`sudo ldconfig`来发现新安装的动态库,在CentOS系统上需要在`/etc/ld.so.conf`配置文件中将`libgmssl`动态库的目录`/usr/local/lib`加入到配置文件中。 - -### 从Python代码仓库安装`gmssl-python` - -`gmssl-python` 会定期发布到Python代码仓库中,可以通过`pip`工具安装 - -```bash -$ pip install gmssl-python -$ pip show gmssl-python -``` - -通过`pip show`命令可以查看当前安装的`gmssl-python`的版本信息。 - -### 下载源码本地安装 - -从代码仓库中安装的`gmssl-python`通常不是最新版本,可以下载最新的GmSSL-Python代码 [GmSSL-Python-main.zip](https://github.com/GmSSL/GmSSL-Python/archive/refs/heads/main.zip),本地安装。 - -解压缩并进入源代码目录`GmSSL-Python-main`。由于最新代码可能还处于开发过程中,在安装前必须进行测试确保全部功能正确,`gmssl-python`中提供了测试,执行如下命令 - -运行测试 - -```bash -$ python -m unittest -v -................ ----------------------------------------------------------------------- -Ran 16 tests in 1.407s - -OK -``` - -上面的输出表明测试通过。 - -然后可以通过`pip`命令安装当前目录下的代码 - -```bash -$ pip install . -$ pip show gmssl-python -``` - -### 验证安装成功 - -注意`gmssl-python`包中只包含一个`gmssl`模块(而不是`gmssl_python`模块)。 - -可以在Python交互环境中做简单的测试 - -```python ->>> import gmssl ->>> gmssl.GMSSL_PYTHON_VERSION ->>> gmssl.GMSSL_LIBRARY_VERSION -``` - -分别查看当前`gmssl-python`的版本和`libgmssl`的版本。 - -编写一个简单的测试程序`sm3.py` - -```python -from gmssl import * - -sm3 = Sm3() -sm3.update(b'abc') -dgst = sm3.digest() -print("sm3('abc') : " + dgst.hex()) -``` - -执行这个程序 +只需在命令行中执行以下pip命令即可完成安装: ```bash -$ python demo.py -sm3('abc') : 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0 -``` - -可以看到运行成功。通过`gmssl`命令行验证输出是正确的 - -``` -echo -n abc | gmssl sm3 -``` - -可以看到输出相同的SM3哈希值 - - - - - -## 开发手册 - -### 随机数生成器 - -函数`rand_bytes`实现随机数生成功能。 - -```python -rand_bytes(size : int) -> bytes -``` - -输入参数`size` 是输出字节数组长度,返回值为`size`长度的随机字节数组。 - -通过`rand_bytes`方法生成的是具备密码安全性的随机数,可以用于密钥、IV或者其他随机数生成器的随机种子。 - -```python ->>> import gmssl ->>> key = gmssl.rand_bytes(16) ->>> print(key.hex()) -``` - -`rand_bytes`是通过调用操作系统的密码随机数生成器(如`/dev/urandom`)实现的。由于底层操作系统的限制,在一次调用`rand_bytes`时不要指定明显超过密钥长度的输出长度,例如参数`size`的值不要超过128,否则可能导致阻塞,或者产生错误和异常。如果应用需要大量的随机数据,不应使用`rand_bytes`,而是应该考虑其他伪随机数生成算法。 - -需要注意的是,`rand_bytes`的安全性依赖于底层的操作系统随机数生成器的安全性。在服务器、笔记本等主流硬件和Windows、Linux、Mac主流服务器、桌面操作系统环境上,当计算机已经启动并且经过一段时间的用户交互和网络通信后,`rand_bytes`可以输出高质量的随机数。但是在缺乏用户交互和网络通信的嵌入式设备中,`rand_bytes`返回的随机数可能存在随机性不足的问题,在这些特殊的环境中,开发者需要提前或在运行时检测`rand_bytes`是否能够提供具有充分的随机性。 - -### SM3哈希 - -SM3密码杂凑函数可以将任意长度的输入数据计算为固定32字节长度的哈希值。 - -模块`gmssl`中包含如下SM3的常量 - -* `SM3_DIGEST_SIZE` 即SM3哈希值的字节长度 - -类`Sm3`实现了SM3功能,类`Sm3`的对象是由构造函数生成的 - -``` -gmssl.Sm3() -``` - -对象sm3的方法: - -* `sm3.update(data : bytes)` 要哈希的消息是通过`update`方法输入的,输入`data`的数据类型是`bytes`类型,如果输入的数据是字符串,需要通过字符串的`encode`方法转换成`bytes`,否则无法生成正确的哈希值。 -* `sm3.digest() -> bytes` 在通过`update`输入完所有消息后,就可以通过`digest`方法获得输出的哈希值,输出的结果类型为`bytes`类型,长度为`SM3_DIGEST_SIZE`。 -* `sm3.reset()` 在SM3对象完成一个消息的哈希后,可以通过`reset`方法重置对象状态,效果等同于构造函数,重置后可以通过`update`、`digest`计算新一个消息的哈希值。`reset`方法使得应用可以只创建一个`Sm3`的对象,计算任意数量的哈希值。 - -下面的例子展示了如何通过类`Sm3`计算字符串的SM3哈希值。 - -```Python ->>> from gmssl import * ->>> sm3 = Sm3() ->>> sm3.update(b'abc') ->>> sm3.digest().hex() -``` - -注意这里提供的消息字符串是`bytes`格式的。这个例子的源代码在`examples/sm3.py`文件中,编译并运行这个例子。 - -```bash -$ python examples/sm3.py -``` - -打印出的`66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0`就是字符串`abc`的哈希值。字符串`abc`的哈希值也是SM3标准文本中给出的第一个测试数据,通过对比标准文本可以确定这个哈希值是正确的。 - -也可以通过`gmssl`命令行来验证`Sm3`类的计算是正确的。 - -```bash -$ echo -n abc | gmssl sm3 -66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0 -``` - -可以看到输出的结果是一样。 - -注意,如果将字符串`abc`写入到文本文件中,文本编辑器通常会在文本结尾处增加格外的结束符,如`0x0a`字符,那么计算出的哈希值将不是上面的结果,比如可能是`12d4e804e1fcfdc181ed383aa07ba76cc69d8aedcbb7742d6e28ff4fb7776c34`。如果命令`echo`不使用`-n`的参数,也会出现同样的错误。这是很多开发者在初次进行哈希函数开发时容易遇到的错误,哈希函数的安全性质保证,即使输入的消息只差一个比特,那么输出的哈希值也完全不同。 - -如果需要哈希的数据来自于网络或者文件,那么应用可能需要多次读取才能获得全部的数据。在通过`Sm3`计算哈希值时,应用不需要通过保存一个缓冲区来保存全部的数据,而是可以通过多次调用`update`方法,将数据输入给`Sm3`对象,在数据全都输入完之后,最后调用`digest`方法得到全部数据的SM3哈希值。下面的代码片段展示了这一用法。 - -```python ->>> from gmssl import * ->>> sm3 = Sm3() ->>> sm3.update(b"Hello ") ->>> sm3.update(b"world!") ->>> dgst = sm3.digest() -``` - -这个例子中两次调用了`update`方法,效果等同于 - -```python -sm3.update(b"Hello world!"); -``` - -注意,SM3算法也支持生成空数据的哈希值,因此下面的代码片段也是合法的。 - -```java ->>> from gmssl import * ->>> sm3 = Sm3() ->>> dgst = sm3.digest() -``` - -GmSSL-Python其他类的`update`方法通常也都提供了这种形式的接口。在输入完所有的数据之后,通过调用`digest`方法就可以获得所有输入数据的SM3哈希值了。`digest`方法输出的是长度为`SM3_DIGEST_SIZE`字节(即32字节)的二进制哈希值。 - -如果应用要计算多组数据的不同SM3哈希值,可以通过`reset`方法重置`Sm3`对象的状态,然后可以再次调用`update`和`digest`方法计算新一组数据的哈希值。这样只需要一个`Sm3`对象就可以完成多组哈希值的计算。 - -```python ->>> from gmssl import * ->>> sm3 = Sm3() ->>> sm3.update(b"abc") ->>> dgst1 = sm3.digest() ->>> ->>> sm3.reset() ->>> sm3.update(b"Hello ") ->>> sm3.update(b"world!") ->>> dgst2 = sm3.digest() -``` - -GmSSL-Python的部分其他类也提供了`reset`方法。 - -### HMAC-SM3消息认证码 - -HMAC-SM3是基于SM3密码杂凑算法的消息认证码(MAC)算法,消息认证码算法可以看作带密钥的哈希函数,主要用于保护消息不受篡改。通信双方需要事先协商出一个密钥,比如32字节的随机字节序列,数据的发送方用这个密钥对消息计算MAC值,并且把MAC值附在消息后面。消息的接收方在收到消息后,用相同的密钥计算消息的MAC值,并且和发送消息附带的MAC值做对比,如果一致说明消息没有被篡改,如果不一致,说明消息被篡改了。 - -模块`gmssl`中包含如下Sm3Hmac的常量: - -* `SM3_HMAC_MIN_KEY_SIZE` -* `SM3_HMAC_MAX_KEY_SIZE` -* `SM3_HMAC_SIZE` HMAC-SM3密钥长度,与SM3哈希值的长度相等 - -`Sm3Hmac`类实现了基于SM3的HMAC消息认证码算法,类`Sm3Hmac`的对象是由构造函数生成的。 - -``` -gmssl.Sm3Hmac(key) -``` - -对象Sm3Hmac的方法: - -* `Sm3Hmac.update(data : bytes)` -* `Sm3Hmac.generate_mac() -> bytes` -* `Sm3Hmac.reset()` - -HMAC-SM3算法可以看作是带密钥的SM3算法,因此在生成`Sm3Hmac`对象时需要传入一个密钥`key`作为输入参数。虽然HMAC-SM3在算法和实现上对密钥长度没有限制,但是出于安全性、效率等方面的考虑,HMAC-SM3算法的密钥长度建议采用32字节(等同于SM3哈希值的长度),不应少于16字节,采用比32字节更长的密钥长度会增加计算开销而不会增加安全性。 - -下面的例子显示了如何用HMAC-SM3生成消息`abc`的MAC值。 - -```python ->>> from gmssl import * ->>> key = rand_bytes(SM3_HMAC_MIN_KEY_SIZE) ->>> sm3_hmac = Sm3Hmac(key) ->>> sm3_hmac.update(b'abc') ->>> sm3_hmac.generate_mac().hex() -``` - -`Sm3Hmac`也通过`update`方法来提供输入消息,应用可以多次调用`update`。 - -应用在通过`update`完成数据输入后,调用`generate_mac`可以获得消息认证码。 - -### 基于口令的密钥导出函数PBKDF2 - -常用软件如Word、PDF、WinRAR等支持基于口令的文件加密,字符串形式的口令相对于随机的密钥字节序列对用户来说更容易记忆和输入,对用户更加友好。但是由于口令中存在的信息熵远低于随机的二进制密钥,直接将口令字符串作为密钥,甚至无法抵御来自个人计算机的暴力破解攻击。一种典型的错误用法是直接用哈希函数计算口令的哈希值,将看起来随机的哈希值作为密钥使用。但是由于口令的空间相对较小,攻击者仍然可以尝试所有可能口令的哈希值,对于暴力破解来说,破解口令的哈希值和原始口令,在攻击难度上没有太大差别。 - -安全和规范的做法是采用一个基于口令的密钥导出函数(Password-Based Key Derivation Function, PBKDF)从口令中导出密钥。通过PBKDF导出密钥并不会降低攻击者在暴力破解时尝试的口令数量,但是可以防止攻击者通过查预计算表的方式来加速破解,并且可以大大增加攻击者尝试每一个可能口令的计算时间。PBKDF2是安全的并且使用广泛的PBKDF算法标准之一,算法采用哈希函数作为将口令映射为密钥的主要部件,通过加入随机并且公开的盐值(Salt)来抵御预计算,通过增加多轮的循环计算来增加在线破解的难度,并且支持可变的导出密钥长度。 - -模块`gmssl`中包含如下Sm3Pbkdf2的常量 - -* `SM3_PBKDF2_MIN_ITER` -* `SM3_PBKDF2_MAX_ITER` -* `SM3_PBKDF2_MAX_SALT_SIZE` -* `SM3_PBKDF2_DEFAULT_SALT_SIZE` -* `SM3_PBKDF2_MAX_KEY_SIZE` - -函数`Sm3Pbkdf2`实现了基于SM3的PBKDF2算法。 - -```python -sm3_pbkdf2(passwd, salt, iterator, keylen) -``` - -其中: - -- `passwd`用于导出密钥的用户口令。 -- `salt`是用于抵御与计算的盐值。这个值需要用随机生成(比如通过`Random`类),并且具有一定的长度。Salt值不需要保密,因此在口令加密数据时,可以直接将这个值附在密文前,传输给接收方。Salt值越长,抵御预计算攻击的效果就更好。例如当Salt为8字节(64比特)长的随机值时,攻击者预计算表就要扩大$2^{64}$倍。`Sm3Pbkdf2`提供一个推荐的Salt值长度`SM3_PBKDF2_DEFAULT_SALT_SIZE`常量,并且在实现上不支持超过`SM3_PBKDF2_MAX_KEY_SIZE`长度的Salt值。 -- `iterator`参数用于表示在导出密钥时调用SM3算法的循环次数,`iterator`值越大,暴力破解的难度越大,但是同时用户在调用这个函数时的开销也增大了。一般来说`iterator`值的应该选择在用户可接收延迟情况下的最大值,比如当`iterator = 10000`时,用户延迟为100毫秒,但是对于用户来说延迟感受不明显,但是对于暴力攻击者来说`iterator = 10000`意味着攻击的开销增加了大约1万倍。`Sm3Pbkdf2`通过`SM3_PBKDF2_MIN_ITER`和`SM3_PBKDF2_MAX_ITER`两个常量给出了`iterator`值的范围,用户可以根据当前计算机的性能及用户对延迟的可感知度,在这个范围内选择合适的值。 -- `keylen`参数表示希望导出的密钥长度,这个长度不可超过常量`SM3_PBKDF2_MAX_KEY_SIZE`。 - -下面的例子展示了如何从口令字符串导出一个密钥。 - -```python ->>> from gmssl import * ->>> passwd = "Password" ->>> salt = rand_bytes(SM3_PBKDF2_DEFAULT_SALT_SIZE) ->>> iterator = SM3_PBKDF2_MIN_ITER ->>> keylen = 32 ->>> sm3_pbkdf2(passwd, salt, iterator, keylen).hex() -``` - -### SM4分组密码 - -SM4算法是分组密码算法,其密钥长度为128比特(16字节),分组长度为128比特(16字节)。SM4算法每次只能加密或者解密一个固定16字节长度的分组,不支持加解密任意长度的消息。分组密码通常作为更高层密码方案的一个组成部分,不适合普通上层应用调用。如果应用需要保护数据和消息,那么应该优先选择采用SM4-GCM模式,或者为了兼容已有的系统,也可以使用SM4-CBC或SM4-CTR模式。 - -模块`gmssl`中包含如下SM4的常量 - -* `SM4_KEY_SIZE` -* `SM4_BLOCK_SIZE` - -`SM4`类实现了基本的SM4分组密码算法,类`SM4`的对象是由构造函数生成的。 - -``` -gmssl.Sm4(key, encrypt) -``` - -对象SM4的方法: - -* `Sm4.encrypt(block : int) -> bytes` - -`Sm4`对象在创建时需要提供`SM4_KEY_SIZE`字节长度的密钥,以及一个布尔值`DO_ENCRYPT`表示是用于加密还是解密。方法`encrypt`根据创建时的选择进行加密或解密,每次调用`encrypt`只处理一个分组,即读入`SM4_BLOCK_SIZE`长度的输入。 - -下面的例子展示SM4分组加密 - -```python ->>> from gmssl import * ->>> key = rand_bytes(SM4_KEY_SIZE) ->>> plaintext = rand_bytes(SM4_BLOCK_SIZE) ->>> sm4_enc = Sm4(key, DO_ENCRYPT) ->>> ciphertext = sm4_enc.encrypt(plaintext) ->>> sm4_dec = Sm4(key, DO_DECRYPT) ->>> decrypted = sm4_dec.encrypt(ciphertext) -``` - -多次调用`Sm4`的分组加密解密功能可以实现ECB模式,由于ECB模式在消息加密应用场景中并不安全,因此GmSSL中没有提供ECB模式。如果应用需要开发SM4的其他加密模式,也可以基于`Sm4`类来开发这些模式。 - -### SM4-CBC加密模式 - -CBC模式是应用最广泛的分组密码加密模式之一,虽然目前不建议在新的应用中继续使用CBC默认,为了保证兼容性,应用仍然可能需要使用CBC模式。 - -模块`gmssl`中包含如下Sm4Cbc的常量: - -* `SM4_CBC_IV_SIZE` - -`Sm4Cbc`类实现了基本的SM4-CBC分组密码算法,类`Sm4Cbc`的对象是由构造函数生成的。 - -``` -gmssl.Sm4Cbc(key, iv, encrypt) -``` - -对象Sm4Cbc的方法: - -* `Sm4Cbc.update(data : bytes)` -* `Sm4Cbc.finish() -> bytes` - -`Sm4Cbc`类实现了SM4的带填充CBC模式,可以实现对任意长度数据的加密。由于需要对明文进行填充,因此`Sm4Cbc`输出的密文长度总是长于明文长度,并且密文的长度是整数个分组长度。 - -通过`Sm4Cbc`加密时,`key`和`iv`都必须为16字节长度。由于CBC模式中加密和解密的计算过程不同,因此必须通过布尔值`DO_ENCRYPT`指定是加密还是解密。 - -由于`Sm4Cbc`在加解密时维护了内部的缓冲区,因此`update`的输出长度可能不等于输入长度,应该保证输出缓冲区的长度至少比输入长度长一个`SM4_CBC_IV_SIZE`长度。 - -下面的例子显示了采用SM4-CBC加密和解密的过程。 - -```python ->>> from gmssl import * ->>> key = rand_bytes(SM4_KEY_SIZE) ->>> iv = rand_bytes(SM4_CBC_IV_SIZE) ->>> plaintext = b'abc' ->>> sm4_enc = Sm4Cbc(key, iv, DO_ENCRYPT) ->>> ciphertext = sm4_enc.update(plaintext) ->>> ciphertext += sm4_enc.finish() ->>> sm4_dec = Sm4Cbc(key, iv, DO_DECRYPT) ->>> decrypted = sm4_dec.update(ciphertext) ->>> decrypted += sm4_dec.finish() -``` - -### SM4-CTR加密模式 - -CTR加密模式可以加密任意长度的消息,和CBC模式不同,并不需要采用填充方案,因此SM4-CTR加密输出的密文长度和输入的明文等长。对于存储或传输带宽有限的应用场景,SM4-CTR相对SM4-CBC模式,密文不会增加额外长度。 - -模块`gmssl`中包含如下Sm4Ctr的常量: - -* `SM4_CTR_IV_SIZE` - -`Sm4Ctr`类实现了基本的SM4-CBC分组密码算法,类`Sm4Ctr`的对象是由构造函数生成的。 - -``` -gmssl.Sm4Ctr(key, iv) -``` - -对象Sm4Cbc的方法: - -* `Sm4Ctr.update(data : bytes)` -* `Sm4Ctr.finish() -> bytes` - -SM4-CTR在加密和解密时计算过程一样,因此在初始化时不需要指定加密或解密,因此没有`Sm4Cbc`中的`DO_ENCRYPT`参数。其他过程和SM4-CBC是一样的。 - -由于`Sm4Ctr`在加解密时维护了内部的缓冲区,因此`update`的输出长度可能不等于输入长度,应该保证输出缓冲区的长度至少比输入长度长一个`SM4_BLOCK_SIZE`长度。 - -注意 ,SM4-CBC和SM4-CTR模式都不能保证消息的完整性,在使用这两个模式时,应用还需要生成一个独立的HMAC-SM3密钥,并且生成密文的MAC值。 - -### SM4-GCM认证加密模式 - -SM4的GCM模式是一种认证加密模式,和CBC、CTR等加密模式的主要区别在于,GCM模式的加密过程默认在密文最后添加完整性标签,也就是MAC标签,因此应用在采用SM4-GCM模式时,没有必要再计算并添加SM3-HMAC了。在有的应用场景中,比如对消息报文进行加密,对于消息头部的一段数据(报头字段)只需要做完整性保护,不需要加密,SM4-GCM支持这种场景。在`Sm4Gcm`类的`init`方法中,除了`key`、`iv`参数,还可以提供`aad`字节数字用于提供不需要加密的消息头部数据。 - -模块`gmssl`中包含如下Sm4Gcm的常量: - -* `SM4_GCM_MIN_IV_SIZE` -* `SM4_GCM_MAX_IV_SIZE` -* `SM4_GCM_DEFAULT_IV_SIZE` -* `SM4_GCM_DEFAULT_TAG_SIZE` -* `SM4_GCM_MAX_TAG_SIZE ` - -`Sm4Gcm`类实现了基本的SM4-CBC分组密码算法,类`Sm4Gcm`的对象是由构造函数生成的。 - -``` -gmssl.Sm4Gcm(key, iv, aad, taglen = SM4_GCM_DEFAULT_TAG_SIZE, encrypt = True) -``` - -对象Sm4Gcm的方法: - -* `Sm4Gcm.update(data : bytes)` -* `Sm4Gcm.finish() -> bytes` - -GCM模式和CBC、CTR、HMAC不同之处还在于可选的IV长度和MAC长度,其中IV的长度必须在`SM4_GCM_MIN_IV_SIZE`和`SM4_GCM_MAX_IV_SIZE`之间,长度为`SM4_GCM_DEFAULT_IV_SIZE`有最佳的计算效率。MAC的长度也是可选的,通过`init`方法中的`taglen`设定,其长度不应低于8字节,不应长于`SM4_GCM_DEFAULT_TAG_SIZE = 16`字节。 - -下面例子展示SM4-GCM加密和解密的过程。 - -```python ->>> from gmssl import * ->>> key = rand_bytes(SM4_KEY_SIZE) ->>> iv = rand_bytes(SM4_GCM_DEFAULT_IV_SIZE) ->>> aad = b'Additional auth-data' ->>> plaintext = b'abc' ->>> taglen = SM4_GCM_DEFAULT_TAG_SIZE ->>> sm4_enc = Sm4Gcm(key, iv, aad, taglen, DO_ENCRYPT) ->>> ciphertext = sm4_enc.update(plaintext) ->>> ciphertext += sm4_enc.finish() ->>> sm4_dec = Sm4Gcm(key, iv, aad, taglen, DO_DECRYPT) ->>> decrypted = sm4_dec.update(ciphertext) ->>> decrypted += sm4_dec.finish() -``` - -通过上面的例子可以看出,SM4-GCM加密模式中可以通过指定了一个不需要加密的字段`aad`,注意`aad`是不会在`update`中输出的。由于GCM模式输出个外的完整性标签,因此`update`和`finish`输出的总密文长度会比总的输入明文长度多`taglen`个字节。 - -### Zuc序列密码 - -祖冲之密码算法(ZU Cipher, ZUC)是一种序列密码,密钥和IV长度均为16字节。作为序列密码ZUC可以加密可变长度的输入数据,并且输出的密文数据长度和输入数据等长,因此适合不允许密文膨胀的应用场景。在国密算法体系中,ZUC算法的设计晚于SM4,在32位通用处理器上通常比SM4-CBC明显要快。 - -在安全性方面,不建议在一组密钥和IV的情况下用ZUC算法加密大量的数据(比如GB级或TB级),避免序列密码超长输出时安全性降低。另外ZUC算法本身并不支持数据的完整性保护,因此在采用ZUC算法加密应用数据时,应考虑配合HMAC-SM3提供完整性保护。ZUC的标准中还包括针对移动通信底层数据报文加密的128-EEA3方案和用于消息完整性保护的128-EIA3算法,目前GmSSL-Python中不支持这两个算法。 - -模块`gmssl`中包含如下Sm4Gcm的常量: - -* `ZUC_KEY_SIZE` -* `ZUC_IV_SIZE` - -`Zuc`类实现了基本的Zuc序列密码算法,类`Zuc`的对象是由构造函数生成的。 - -``` -gmssl.Zuc(key, iv) -``` - -对象Sm4Cbc的方法: - -* `Zuc.update(data : bytes)` -* `Zuc.finish() -> bytes` - -`Zuc`类的接口说明如下: - -- 序列密码通过生成密钥序列和输入数据进行异或操作的方式来加密或解密,因此序列密码的加密和解密的过程一致,因此创建`Zuc`对象时不需要格外的参数表明加密还是解密。 -- 由于CTR模式实际上是以分组密码实现了序列密码的能力,因此可以发现`Zuc`和`Sm4Cbc`的接口是完全一致的。 -- ZUC算法内部实现是以32比特字(4字节)为单位进行处理,因此`Zuc`实现加解密过程中也有内部的状态缓冲区,因此`update`的输出长度可能和输入长度不一致,调用方应该保证输出缓冲区长度比输入长度长`BLOCK_SIZE`个字节。注意,`BLOCK_SIZE`的实际值在未来也有可能会变化。 - -下面的例子展示了`Zuc`的加密和解密过程。 - -```python ->>> from gmssl import * ->>> iv = rand_bytes(ZUC_IV_SIZE) ->>> plaintext = b'abc' ->>> zuc_enc = Zuc(key, iv) ->>> ciphertext = zuc_enc.update(plaintext) ->>> ciphertext += zuc_enc.finish() ->>> zuc_dec = Zuc(key, iv) ->>> decrypted = zuc_dec.update(ciphertext) ->>> decrypted += zuc_dec.finish() -``` - -### SM2 - -SM2是国密标准中的椭圆曲线公钥密码,包含数字签名算法和公钥加密算法。SM2相关的功能由类`Sm2Key`和`Sm2Signature`实现,其中`Sm2Key`实现了SM2密钥对的生成、基础的加密和签名方案,`Sm2Signature`类实现了对任意长度消息签名的签名方案。 - -模块`gmssl`中包含如下Sm2Key的常量: - -* `SM2_DEFAULT_ID` -* `SM2_MAX_SIGNATURE_SIZE` -* `SM2_MIN_PLAINTEXT_SIZE` -* `SM2_MAX_PLAINTEXT_SIZE ` -* `SM2_MIN_CIPHERTEXT_SIZE` -* `SM2_MAX_CIPHERTEXT_SIZE` - -`Sm2Key`类实现了基本的SM4-CBC分组密码算法,类`Sm2Key`的对象是由构造函数生成的。 - -``` -gmssl.Sm2Key() -``` - -对象Sm2Key的方法: - -* `Sm2Key.generate_key()` -* `Sm2Key.compute_z()` -* `Sm2Key.export_encrypted_private_key_info_pem()` -* `Sm2Key.import_encrypted_private_key_info_pem()` -* `Sm2Key.export_public_key_info_pem()` -* `Sm2Key.import_public_key_info_pem()` -* `Sm2Key.sign()` -* `Sm2Key.verify()` -* `Sm2Key.encrypt()` -* `Sm2Key.decrypt()` - -需要注意的是,通过构造函数生成的新`Sm2Key`对象是一个空白的对象,可以通过`generate_key`方法生成一个新的密钥对,或者通过导入函数从外部导入密钥。`Sm2Key`一共提供了2个不同的导入方法: - -- `import_encrypted_private_key_info_pem` 从加密的PEM文件中导入SM2私钥,因此调用时需要提供PEM文件的路径和解密的口令(Password)。 -- `import_public_key_info_pem`从PEM文件中导入SM2公钥,只需要提供文件的路径,不需要提供口令。 - -上面2个导入函数也都有对应的导出函数。从PEM文件中导入导出公钥私钥和`gmssl`命令行工具的默认密钥格式一致,并且在处理私钥时安全性更高。因此建议在默认情况下,在导入导出私钥时默认采用加密的PEM文件格式。 - -下面的代码片段展示了`Sm2Key`密钥对和导出为加密的PEM私钥文件: - -```python ->>> sm2 = Sm2Key() ->>> sm2.generate_key() ->>> ->>> sm2.export_encrypted_private_key_info_pem('sm2.pem', 'password') ->>> private_key = Sm2Key() ->>> private_key.import_encrypted_private_key_info_pem('sm2.pem', 'password') -``` - -用文本编辑器打开`sm2.pem`文件可以看到如下内容 - -``` ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIBBjBhBgkqhkiG9w0BBQ0wVDA0BgkqhkiG9w0BBQwwJwQQaADudE4Ycenuoth4 -ZqcewgIDAQAAAgEQMAsGCSqBHM9VAYMRAjAcBggqgRzPVQFoAgQQ9aUmOaXn0mZD -7xhBdd+FlQSBoKc0GG7US2SsmQIrppPNQeyDFpG8xthNI6G4R/YbSPJCvSMJ/9y3 -LQ/jrdUumuKevgg9miAcjbKndm7HC07lMYUk1ZXlaEG/1awER4RJsRvZ64GlBQOV -D7jbu93mSs9t3SDt4TniDua5WyXo5Y8S6DjkkUD5epHRzYZ4uFFC/8pTeehK7X+S -p2b6CndfB6H4LrvCGuRnjX4l5Q5AgfWDmWU= ------END ENCRYPTED PRIVATE KEY----- -``` - -下面的代码片段展示了`Sm2Key`导出为PEM公钥文件,这是一个标准的PKCS #8 EncryptPrivateKeyInfo类型并且PEM编码的私钥文件格式,`openssl pkeyutil`命令行工具也默认采用这个格式的私钥,但是由于GmSSL在私钥文件中采用SM4-CBC、HMAC-SM3组合加密了SM2的私钥,因此对于默认使用3DES的`openssl`等工具可能无法解密这个私钥(即使这个工具包含SM2算法的实现)。 - -```python ->>> sm2.export_public_key_info_pem('sm2pub.pem') ->>> public_key = Sm2Key() ->>> public_key.import_public_key_info_pem('sm2pub.pem') -``` - -用文本编辑器打开`sm2pub.pem`文件可以看到如下内容 - -``` ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5djp+Gw/Wdg9JwVwYDiQn1AocezI -C2qT54fqJBNWevCNru8ENwj4t/52Yf50LF5+fMlcoWPbfm/TcCgYPb49jw== ------END PUBLIC KEY----- -``` - -由于公钥文件是不加密的,因此这个公钥可以被支持SM2的第三方工具、库打开和访问。 - -`Sm2Key`类除了`generate_key`方法之外,提供了`compute_z`、`sign`、`verify`、`encrypt`、`decrypt`这几个密码计算相关的方法。 - -其中`compute_z`是由公钥和用户的字符串ID值计算出一个称为“Z值”的哈希值,用于对消息的签名。由于`Sm2Signature`类中提供了SM2消息签名的完整功能,因此这个`compute_z`方法只是用于实验验证。 - -```python ->>> z = public_key.compute_z(SM2_DEFAULT_ID) -``` - -类`Sm2Key`的`sign`和`verify`方法实现了SM2签名的底层功能,这两个方法不支持对数据或消息的签名,只能实现对SM3哈希值的签名和验证,并没有实现SM2签名的完整功能。应用需要保证调用时提供的`dgst`参数的字节序列长度为32。只有密码协议的底层开发者才需要调用`compute_z`、`sign`、`verify`这几个底层方法。 - -```python ->>> dgst = sm3.digest() ->>> sig = private_key.sign(dgst) ->>> ret = public_key.verify(dgst, sig) -``` - -类`Sm2Key`的`encrypt`和`decrypt`方法实现了SM2加密和解密功能。注意,虽然SM2标准中没有限制加密消息的长度,但是公钥加密应该主要用于加密较短的对称密钥、主密钥等密钥数据,因此GmSSL库中限制了SM2加密消息的最大长度。应用在调用`encrypt`时,需要保证输入的明文长度不超过`SM2_MAX_PLAINTEXT_SIZE `的限制。如果需要加密引用层的消息,应该首先生成对称密钥,用SM4-GCM加密消息,再用SM2加密对称密钥。 - -```python ->>> ciphertext = public_key.encrypt(plaintext) ->>> decrypted = private_key.decrypt(ciphertext) -``` - -类`Sm2Signatue`提供了对任意长消息的签名、验签功能。 - -模块`gmssl`中包含如下Sm2Signatue的常量: - -* `DO_ENCRYPT = True` -* `DO_DECRYPT = False` -* `DO_SIGN = True` -* `DO_VERIFY = False` - -`Sm2Signatue`类实现了基本的SM4-CBC分组密码算法,类`Sm2Signatue`的对象是由构造函数生成的。 - -``` -gmssl.Sm2Signatue(sm2_key, signer_id = SM2_DEFAULT_ID, sign = DO_SIGN) -``` - -对象Sm2Signatue的方法: - -* `Sm2Signatue.update()` -* `Sm2Signatue.sign()` -* `Sm2Signatue.verify()` - -在生成`Sm2Signature`对象时,不仅需要提供`Sm2Key`,还需要提供签名方的字符串ID,以满足SM2签名的标准。如果提供的`Sm2Key`来自于导入的公钥,那么这个`Sm2Signature`对象只能进行签名验证操作,即在构造时`DO_SIGN = False`,并且只能调用`verify`方法,不能调用`sign`方法。 - -```python -signer = Sm2Signature(private_key, SM2_DEFAULT_ID, DO_SIGN) -signer.update(b'abc') -sig2 = signer.sign() - -verifier = Sm2Signature(public_key, SM2_DEFAULT_ID, DO_VERIFY) -verifier.update(b'abc') -ret = verifier.verify(sig2) -``` - -不管是`Sm2Key`的`sign`还是`Sm2Signature`的`sign`方法输出的都是DER编码的签名值。这个签名值的第一个字节总是`0x30`,并且长度是可变的,常见的长度包括70字节、71字节、72字节,也可能短于70字节。一些SM2的实现不能输出DER编码的签名,只能输出固定64字节长度的签名值。可以通过签名值的长度以及首字节的值来判断SM2签名值的格式。 - -### SM2数字证书 - -类`Sm2Certificate`实现了SM2证书的导入、导出、解析和验证等功能。这里的“SM2证书”含义和“RSA证书”类似,是指证书中的公钥字段是SM2公钥,证书中签名字段是SM2签名,证书格式就是标准的X.509v3证书。由于GmSSL库目前只支持SM2签名算法,不支持ECDSA、RSA、DSA等签名算法,因此`Sm2Certificate`类无法支持其他公钥类型的证书。注意,有一种不常见的情况,一个证书可以公钥是SM2公钥而数字签名是RSA签名,这种证书可能是采用RSA公钥的CA中心对SM2证书请求签发而产生的,由于目前GmSSL不支持SM2之外的签名算法,因此`Sm2Certificate`不支持此类证书。 - -类`Sm2Certificate`只支持SM2证书的解析和验证等功能,不支持SM2证书的签发和生成,如果应用需要实现证书申请(即生成CSR文件)或者自建CA签发证书功能,那么可以通过GmSSL库或者`gmssl`命令行工具实现,GmSSL-Python目前不考虑支持证书签发、生成的相关功能。 - -模块`gmssl`中包含如下Sm2Certificate的常量: - -* `ZUC_KEY_SIZE` -* `ZUC_IV_SIZE` - -Sm2Certificate的方法: - -* `Sm2Certificate.import_pem()` -* `Sm2Certificate.get_raw()` -* `Sm2Certificate.export_pem()` -* `Sm2Certificate.get_serial_number()` -* `Sm2Certificate.get_issuer()` -* `Sm2Certificate.get_subject()` -* `Sm2Certificate.get_subject_public_key()` -* `Sm2Certificate.get_validity()` -* `Sm2Certificate.verify_by_ca_certificate()` - -新生成的`Sm2Certificate`对象中的证书数据为空,必须通过导入证书数据才能实现真正的初始化。证书有很多种不同格式的编码,如二进制DER编码的`crt`文件或者文本PEM编码的`cer`文件或者`pem`文件,有的证书也会把二进制的证书数据编码为一串连续的十六进制字符串,也有的CA会把多个证书构成的证书链封装在一个PKCS#7格式的密码消息中,而这个密码消息可能是二进制的,也可能是PEM编码的。 - -在这些格式中最常用的格式是本文的PEM格式,这也是`Sm2Certificate`类默认支持的证书格式。下面这个例子中就是一个证书的PEM文件内容,可以看到内容是由文本构成的,并且总是以`-----BEGIN CERTIFICATE-----`一行作为开头,以`-----END CERTIFICATE-----`一行作为结尾。PEM格式的好处是很容易用文本编辑器打开来,容易作为文本被复制、传输,一个文本文件中可以依次写入多个证书,从而在一个文件中包含多个证书或证书链。因此PEM格式也是CA签发生成证书使用的最主流的格式。由于PEM文件中头尾之间的文本就是证书二进制DER数据的BASE64编码,因此PEM文件也很容易和二进制证书进行手动或自动的互相转换。 - -``` ------BEGIN CERTIFICATE----- -MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG -EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw -MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO -UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE -MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT -V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti -W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ -MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b -53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI -pDoiVhsLwg== ------END CERTIFICATE----- -``` - -通过`gmssl certparse`命令可以打印这个证书的内容 - -```python -$ gmssl certparse -in ROOTCA.pemCertificate - tbsCertificate - version: v3 (2) - serialNumber: 69E2FEC0170AC67B - signature - algorithm: sm2sign-with-sm3 - parameters: NULL - issuer - countryName: CN - organizationName: NRCAC - commonName: ROOTCA - validity - notBefore: Sat Jul 14 11:11:59 2012 - notAfter: Mon Jul 7 11:11:59 2042 - subject - countryName: CN - organizationName: NRCAC - commonName: ROOTCA - subjectPulbicKeyInfo - algorithm - algorithm: ecPublicKey - namedCurve: sm2p256v1 - subjectPublicKey - ECPoint: 0430F09C6BAA6681C721B137F652705E2FDAEDA789F0FA2B64D4ACEB99B9EAA34E655309309562BEE0E22BB45740AA745357B43DBF586D92FE364EC22EB73775DB - extensions - Extension - extnID: AuthorityKeyIdentifier (2.5.29.35) - AuthorityKeyIdentifier - keyIdentifier: 4C32B197D9331BC4A605C1C6E58B625BF0977658 - Extension - extnID: BasicConstraints (2.5.29.19) - BasicConstraints - cA: true - Extension - extnID: KeyUsage (2.5.29.15) - KeyUsage: keyCertSign,cRLSign - Extension - extnID: SubjectKeyIdentifier (2.5.29.14) - SubjectKeyIdentifier: 4C32B197D9331BC4A605C1C6E58B625BF0977658 - signatureAlgorithm - algorithm: sm2sign-with-sm3 - parameters: NULL - signatureValue: 304502201B56D22DE397A77A01F07EDBE775BE08A38F9763E49E6584ABF94C86D9F6E479022100DA1C3816C5616D9C2AC18C7D7AFD6DC4CE7EFF53F563A39C48A43A22561B0BC2 -``` - -可以看到一个证书的主要内容是包含证书持有者信息的tbsCertificate字段,以及权威机构对tbsCertificate字段的签名算法signatureAlgorithm和签名值signatureValue。因为这个证书是SM2证书,因此其中的签名算法是`sm2sign-with-sm3`,签名值是`0x30`开头的DER编码的可变长度签名值。 - -证书中持有者信息包含如下字段: - -- 证书格式的版本号 version,目前版本号应该是第3版,即`v3`。 -- 证书的序列号 serialNumber,早期证书中的序列号是一个递增的整数,但是近年来的证书必须是随机值。、 -- 证书的签名算法 signature,这个字段的值必须和最后的signatureAlgorithm保持一致。 -- 证书签发机构的名字 issuer,通常是一个CA中心,issuer的内容是由多个Key-Value格式的多个字段组合而成,其中的Key包括国家countryName、省stateOrProvinceName、城市localityName、组织organizationName、组织内单位organizationUnitName、常用名commonName等,其中commonName应该是CA机构的名字。 -- 证书的有效期 validity,有效期是由起始时间notBefore和终止时间notAfter两个时间构成的,如果当前时间早于notBefore,说明证书还没有启用,如果当前时间晚于notAfter,说明证书已经过期作废。 -- 证书持有者(证书主体)的名字 subject,这个字段的数据类型和issuer是一样的,一般对于网站服务器证书来说,subject的commonName应该是服务器的域名。 -- 证书持有者的公钥信息subjectPulbicKeyInfo,对于SM2证书来说,公钥算法必须是ecPublicKey并且曲线必须是sm2p256v1,公钥的值是一个编码的椭圆曲线点,这个值总是以`0x04`开头,后跟总共64字节的点的X、Y坐标。 -- 证书中通常还有多个扩展,其中有的扩展是关键的(critical)扩展,有些则不重要,只是提供了参考信息,这里介绍两个比较重要的扩展: - - BasicConstraints (2.5.29.19) 扩展,这个扩展标明证书是权威机构的CA证书(比如北京市CA中心)还是普通用户的证书(比如某个网站的证书),如果一个证书中没有包含这个扩展,或者扩展中的`cA: true`字段不存在,那么这个证书不能作为CA证书使用。 - - KeyUsage (2.5.29.15) 扩展,这个扩展表明证书持有者公钥的用途,类似于驾驶证中的A照、B照、C照等划分大客车、大货车、小客车准驾车型,密钥用途表明证书是否可以签名、加密、签发证书等用途。如果一个数字签名附带的证书中有KeyUsage扩展并且扩展包含的密钥用途只有加密,没有签名,那么这个证书对于这个签名来说就是无效的。 - -`Sm2Certificate`类只支持第3版证书的解析,因此没有提供`getVersion`方法获取证书的版本号。GmSSL支持常用扩展的解析和验证,如果某个证书中有GmSSL不支持的非关键扩展,那么GmSSL会忽略这个扩展,如果存在GmSSL不识别或无法验证的关键性扩展,那么GmSSL在解析证书的时候会返回失败,因此如果`Sm2Certificate`类`import_pem`成功,说明证书的格式、内容是可以识别的并且是正确的。 - -拿他其他人提供的证书还必须验证该证书是否有效,首先需要检查证书的有效期。目前很多CA中心的策略是颁发有效期尽可能短的证书(比如3个月有效期),因此拿到的证书很有可能已经过期了。可以通过`get_validity()`方法获得有效期时间,判断当前时间点是否在有效期范围内。如果要验证过去某个时间点证书支持者的操作是否合法,那么应该检查那个时间点是否在证书的有效期范围内。 - -对证书最重要的验证之一是这个证书是否是由权威机构签发的。证书用户需要先通过`get_issuer`方法获得签发机构的名字,确认这个签发机构是否可信。例如,如果一个北京市政府机构的证书中的签发机构是一个商业性CA中心,那么这个证书的有效性就是存疑的。在确认CA中心名字(即整个issuer字段)无误之后,还需要通过Issuer字段从可信的渠道获得这个CA中心的证书,然后调用`verify_by_ca_certificate`方法,用获得的CA证书验证当前证书中的签名是否正确。在典型的应用中,开发者和软件发行方应该将所有可信的CA中心的证书硬编码到软件中,或者内置到软件或系统的证书库中,避免应用的用户需要手动添加、导入CA证书。 - -所有的私钥都有泄露的可能,安全性不佳的自建CA有被攻击者渗透的可能,商业性的小CA甚至有被收购、收买的可能,因此有效期范围内的证书也存在被作废的可能。检查证书是否作废主要是通过证书作废列表CRL文件检查,或者通过证书状态在线检查协议OCSP来在线查询。目前`Sm2Certificate`类没有支持证书作为查询的功能,开发者暂时可以通过`GmSSL`库或者`gmssl`命令行工具进行CRL的检查。 - -在完成所有证书检查之后,应用可以完全信任从证书中读取的持有者身份信息(subject)和支持有的公钥了,这两个信息分别通过`get_subject()`和`get_subject_public_key`方法获得。 - -### SM9基于身份的密码 - -SM9算法属于基于身份的密码。基于身份的密码是一种“高级”的公钥密码方案,在具备常规公钥密码加密、签名等密码功能的同时,基于身份的密码体系不需要CA中心和数字证书体系。SM9方案的基本原理是,可以由用户的唯一身份ID(如对方的电子邮件地址、域名或ID号等),从系统的全局主密钥中导出对应的私钥或公钥,导出密钥的正确性是由算法保证的,因此在进行加密、验签的时候,只需要获得解密方或签名方的ID即可,不再需要对方的数字证书了。因此如果应用面对的是一个内部的封闭环境,所有参与用户都是系统内用户,那么采用SM9方案而不是SM2证书和CA的方案,可以简化系统的开发、设计和使用,并降低后续CA体系的维护成本。 - -对应数字证书体系中的CA中心,SM9体系中也存在一个权威中心,用于生成全局的主密钥(MasterKey),并且为系统中的每个用户生成、分配用户的私钥。和SM2密钥对一样,SM9的主密钥也包含私钥和公钥,其中主公钥(PublicMasterKey)是可以导出并公开给系统中全体用户的。而SM9中用户的密钥对比较特殊,其中的公钥并不能从私钥中导出,SM9用户密钥需要包含用户的ID起到公钥的作用,在加密和验证签名等密码计算中,真正的用户公钥是在计算中,在运行时通过用户ID从主公钥中导出的。因此从应用的角度看,SM9中用户的公钥就是一个字符串形式的ID。 - -SM9算法体系中包括SM9加密、SM9签名和SM9密钥交换协议,GmSSL-Java中实现了SM9加密和SM9签名,没有实现SM9密钥交换。其中SM9加密功能包含`Sm9EncMasterKey`类和`Sm9EncKey`类,分别实现了SM9加密主密钥和SM9加密用户密钥,SM9签名功能包含`Sm9SignMasterKey`类、`Sm9SignKey`类和`Sm9Signature`类,分别实现了SM9签名主密钥、SM9签名用户密钥和SM9签名功能。 - -和SM2算法中相同的密钥对既可以用于加密又可以用于签名不同,SM9中加密、签名的主密钥、用户密钥的组成是完全不同的,因此GmSSL中分别实现为不同的类。SM9签名由于需要特殊的哈希过程,因此SM9用户签名私钥不提供直接签哈希值的底层签名功能实现,只能通过`Sm9Signature`实现对消息的签名、验证。 - -模块`gmssl`中包含如下Sm9EncMasterKey的常量: - -* `SM9_MAX_ID_SIZE` -* `SM9_MAX_PLAINTEXT_SIZE` -* `SM9_MAX_CIPHERTEXT_SIZE` - -SM9加密主密钥由类`Sm9EncMasterKey`实现。 - -``` -gmssl.Sm9EncMasterKey() -``` - -对象Sm9EncMasterKey的接口包括: - -* `Sm9EncMasterKey.generate_master_key()` 主密钥的生成 -* `Sm9EncMasterKey.extract_key()`用户私钥的生成 -* `Sm9EncMasterKey.import_encrypted_master_key_info_pem()` 主密钥的导入,注意`Sm2Key`的对应接口类似,这里主密钥都是以口令加密的方式导出到文件上的 -* `Sm9EncMasterKey.export_encrypted_master_key_info_pem()`主密钥的导出 -* `Sm9EncMasterKey.export_public_master_key_pem()`主公钥(主密钥的公钥部分)的导入 -* `Sm9EncMasterKey.import_public_master_key_pem()`主公钥(主密钥的公钥部分)的导出 -* `Sm9EncMasterKey.encrypt()`数据加密 - -这个类的用户包括两个不同角色,权威中心和用户。其中权威中心调用主密钥的生成、主密钥的导入导出、主公钥导出和用户私钥生成这几个接口,而用户调用主公钥导入和加密这两个接口。 - -类`Sm9EncKey`对象是由`Sm9SEncMasterKey`的`extract_key`方法生成的。 - -``` -gmssl.Sm9EncKey() -``` - -对象Sm9EncKey的方法: - -* `Sm9EncKey.get_id()` -* `Sm9EncKey.import_encrypted_private_key_info_pem()` -* `Sm9EncKey.export_encrypted_private_key_info_pem()` -* `Sm9EncKey.decrypt()` - -类`Sm9EncKey`提供了解密、导入导出等接口,由于在SM9中用户密钥总是包含私钥的,因此导出的是经过口令加密的密钥。 - -下面的例子中给出了SM9加密方案的主密钥生成、用户密钥导出、加密、解密的整个过程。 - -```python -master_key = Sm9EncMasterKey() -master_key.generate_master_key() -print("SM9 master key generated") - -master_key.export_encrypted_master_key_info_pem('enc_msk.pem', 'password') -master_key.export_public_master_key_pem('enc_mpk.pem') -print("Export master key and public master key") - -# Encrypt -master_pub = Sm9EncMasterKey() -master_pub.import_public_master_key_pem('enc_mpk.pem') - -plaintext = rand_bytes(SM4_KEY_SIZE + SM3_HMAC_MIN_KEY_SIZE) - -receiver_id = 'Alice' - -ciphertext = master_pub.encrypt(plaintext, receiver_id) - -# Decrypt -master = Sm9EncMasterKey() -master.import_encrypted_master_key_info_pem('enc_msk.pem', 'password') - -receiver_key = master.extract_key(receiver_id) - -decrypted = receiver_key.decrypt(ciphertext) -``` - -SM9签名功能由`Sm9SignMasterKey`、`Sm9SignKey`和`Sm9Signature`几个类实现,前两者在接口上和SM9加密非常类似,只是这两个类不直接提供签名、验签的功能。 - -```python -gmssl.Sm9SignMasterKey() -gmssl.Sm9SignKey(owner_id) -``` - -对象Sm9SignMasterKey的方法: - -* `Sm9SignMasterKey.generate_master_key()` -* `Sm9SignMasterKey.extract_key()` -* `Sm9SignMasterKey.import_encrypted_master_key_info_pem()` -* `Sm9SignMasterKey.export_encrypted_master_key_info_pem()` -* `Sm9SignMasterKey.export_public_master_key_pem()` -* `Sm9SignMasterKey.import_public_master_key_pem()` - -对象Sm9SignKey的方法: - -- `Sm9SignKey.get_id()` -- `Sm9SignKey.import_encrypted_private_key_info_pem()` -- `Sm9SignKey.export_encrypted_private_key_info_pem()` - -类`Sm9Signature`实现对数据的SM9签名和验证功能。SM9签名时需要提供`Sm9SignKey`类型的签名方私钥(其中包含签名者的ID),在验证签名时需要提供`Sm9SignMasterKey`格式的系统主公钥和签名方的ID。`Sm9Signature`和`Sm2Signature`提供类似的`update`、`sign`、`verify`接口,只是在验证的时候需要提供的不是公钥,而是系统的主公钥和签名方的ID。 - -```python -gmssl.Sm9Signature(sign = DO_SIGN) -``` - -模块`gmssl`中包含如下Sm9Signature的常量: - -- `SM9_SIGNATURE_SIZE` - -对象Sm9Signature的方法: - -- `Sm9Signature.reset()` -- `Sm9Signature.update()` -- `Sm9Signature.sign()` -- `Sm9Signature.verify()` - -下面的例子展示了SM9签名的主密钥生成、用户私钥生成、签名、验证的过程。 - -```python -master_key = Sm9SignMasterKey() -master_key.generate_master_key() -print("SM9 master key generated") - -master_key.export_encrypted_master_key_info_pem('sign_msk.pem', 'password') -master_key.export_public_master_key_pem('sign_mpk.pem') -print("Export master key and public master key") - - -master = Sm9SignMasterKey() -master.import_encrypted_master_key_info_pem('sign_msk.pem', 'password') - -signer_id = 'Alice' -key = master.extract_key(signer_id) - -message = "Message to be signed" - -sign = Sm9Signature(DO_SIGN) -sign.update(message.encode('utf-8')) -sig = sign.sign(key) - - -master_pub = Sm9SignMasterKey() -master_pub.import_public_master_key_pem('sign_mpk.pem') - -verify = Sm9Signature(DO_VERIFY) -verify.update(message.encode('utf-8')) -ret = verify.verify(sig, master_pub, signer_id) -``` - - - - - - - - +pip install easy_gmssl +``` + +安装过程中,系统会自动处理底层C库的编译与安装事宜,待编译安装完成后即可开启国密算法开发之旅。 + +## 四、使用示例 + +1. **SM2密钥加解密** + - 输出多种模式下的密文: + ```python + from __future__ import annotations + + from easy_gmssl import EasySm2EncryptionKey, SM2CipherFormat, SM2CipherMode + + enc = EasySm2EncryptionKey() + plain = 'hello,world' + # 遍历当前支持的所有 SM2 加解密算法模式 + # 当前支持的模式包括: + # C1C3C2_ASN1、C1C3C2、C1C2C3_ASN1、C1C2C3 + for mode in SM2CipherMode: + print(mode, '密文 in Hex:', enc.Encrypt('hello,world'.encode('utf-8'), mode, SM2CipherFormat.HexStr)) + ``` + +2. **SM2公钥、私钥读取** + ```python + from __future__ import annotations + + from easy_gmssl import EasySm2Key + + test = EasySm2Key() + print('公钥数据 In Hex:', test.get_sm2_public_key_in_hex()) + print('私钥数据 In Hex:', test.get_sm2_private_key_in_hex()) + ``` + +3. **SM2签名验签** + + - 以RS_ASN1模式为例: + ```python + from __future__ import annotations + + import random + + from easy_gmssl import EasySM2SignKey, EasySM2VerifyKey, SignatureMode + + signer_id = 'test_signer' + print('signer_id hex:', signer_id.encode('utf-8').hex()) + # 初始化用于签名验签的 SM2 密钥,此时不需要关心签名值的模式 + test = EasySM2SignKey(signer_id = signer_id, pem_private_key_file = './test_keys/tmp_test_sm2_private.pem', + password = '123456') + plain = bytes([random.randint(0, 255) for _ in range(0, 64)]) + print('plain hex:', plain.hex()) + print('private key hex:', test.get_sm2_private_key_in_hex()) + print('public key hex:', test.get_sm2_public_key_in_hex()) + + # 计算签名 + test.UpdateData(plain) + # 指定签名值模式为 RS 模式,可选 RS、RS_ASN1 + sign_value = test.GetSignValue(signature_mode = SignatureMode.RS) + print('signature hex:', sign_value.hex()) + + # 初始化用于验证签名的 SM2 密钥 + verify_test = EasySM2VerifyKey(signer_id = signer_id, pem_public_key_file = './test_keys/tmp_test_sm2_public.pem') + # 验证签名 + verify_test.UpdateData(plain) + # 验证签名时同样指定签名值格式为 RS 模式 + ret = verify_test.VerifySignature(sign_value, signature_mode = SignatureMode.RS) + ``` + +4. **SM4对称加解密示例** + + ```python + from __future__ import annotations + + from easy_gmssl import EasySm4CBC + from easy_gmssl.gmssl import SM4_BLOCK_SIZE, SM4_CBC_IV_SIZE + + key = 'x' * SM4_BLOCK_SIZE + iv = 'y' * SM4_CBC_IV_SIZE + + test_cbc_enc = EasySm4CBC(key.encode('utf-8'), iv.encode('utf-8'), True) + plain1 = 'hello,world' + plain2 = '1234567890' + cipher1 = test_cbc_enc.Update(plain1.encode('utf-8')) + cipher2 = test_cbc_enc.Update(plain2.encode('utf-8')) + ciphers = cipher1 + cipher2 + test_cbc_enc.Finish() + + test_dec = EasySm4CBC(key.encode('utf-8'), iv.encode('utf-8'), False) + decrypted_plain1 = test_dec.Update(ciphers) + decrypted_plain = decrypted_plain1 + test_dec.Finish() + + print('解密成功:', decrypted_plain == (plain1 + plain2).encode('utf-8')) + ``` + +5. **SM3 HASH 与 HMAC 示例** + + ```python + from __future__ import annotations + + import random + + from easy_gmssl import EasySM3Digest, EasySM3Hmac + from easy_gmssl.gmssl import SM3_HMAC_MAX_KEY_SIZE + + test = EasySM3Digest() + + plain1 = 'hello,world'.encode('utf-8') + plain2 = '1234567890'.encode('utf-8') + plain3 = (plain1 + plain2) + print('plain hex:', plain3.hex()) + test.UpdateData(plain3) + hash_value_2, hash_len, length2 = test.GetHash() + print('hash value:', hash_value_2.hex()) + print('hash value length in bytes:', hash_len) + + + plain = 'hello,world'.encode('utf-8') + print('plain hex:', plain.hex()) + key = bytes([random.randint(0, 255) for _ in range(0, SM3_HMAC_MAX_KEY_SIZE)]) + print('key hex:', key.hex()) + test = EasySM3Hmac(key) + test.UpdateData(plain) + hmac_hex, hmac_len, plain_len = test.GetHmac() + print('hmac value:', hmac_hex.hex(), 'hmac len:', hmac_len, 'plain len:', plain_len) + ``` + +6. **随机数生成示例** + + ```python + from __future__ import annotations + from easy_gmssl import EasyRandomData, RandomMode + test = EasyRandomData() + ret = test.GetRandomData(20) + print(ret.hex()) + test = EasyRandomData(mode = RandomMode.RandomStr) + ret = test.GetRandomData(64) + print(ret) + ``` + + + +7. **ZUC 加解密示例** + + ```python + from __future__ import annotations + + from easy_gmssl import EasyRandomData, EasyZuc + from easy_gmssl.gmssl import ZUC_IV_SIZE, ZUC_KEY_SIZE + + # 生成密钥与 IV + key = EasyRandomData().GetRandomData(ZUC_KEY_SIZE) + iv = EasyRandomData().GetRandomData(ZUC_IV_SIZE) + # 加密操作 + test = EasyZuc(key, iv) + plain1 = 'hello,world'.encode('utf-8') + cipher1 = test.Update(plain1) + plain2 = '1234567890'.encode('utf-8') + cipher2 = test.Update(plain2) + cipher3 = test.Finish() + + # 解密操作 + test2 = EasyZuc(key, iv) + ret1 = test2.Update(cipher1) + ret2 = test2.Update(cipher2) + ret3 = test2.Update(cipher3) + ret4 = test2.Finish() + assert ret1 + ret2 + ret3 + ret4 == plain1 + plain2 + print('解密成功:', ret1 + ret2 + ret3 + ret4 == plain1 + plain2) + ``` + + + +## 五、注意事项 + +1. 在使用SM2密钥加解密、签名验签等功能时,请务必根据实际需求谨慎选择合适的模式,不同模式在数据格式、兼容性等方面存在差异。 +2. 对于读取的公钥、私钥十六进制明文,要妥善保管,防止泄露,因为这是加密体系的核心机密信息。 +3. 虽然SDK尽力优化了接口,但国密算法涉及密码学专业知识,在开发高安全性应用时,建议开发者深入了解相关算法原理,确保应用的安全性。 diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..6c3752b --- /dev/null +++ b/__init__.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-23 20:28:26 + +from __future__ import annotations + +__all__ = [ + 'RandomMode', + 'EasyRandomData', + 'SM2PubKeyASN1Sequence', + 'SM2PubKeyRawData', + 'SM2CipherMode', + 'SM2CipherFormat', + 'SM2CipherLength', + 'SM2_C1C3C2_ASN1_Ciphertext', + 'SM2_C1C2C3_ASN1_Ciphertext', + 'EasySm2Key', + 'EasySm2EncryptionKey', + 'SM2_RS_ASN1_Signature', + 'SignatureMode', + 'EasySM2SignKey', + 'EasySM2VerifyKey', + 'EasySM3Digest', + 'EasySM3Hmac', + 'EncryptionMode', + 'EasySm4CBC', + 'EasySm4GCM', + 'EasyZuc', + + ] + +from .easy_random_data import EasyRandomData, RandomMode +from .easy_sm2_key import EasySm2EncryptionKey, EasySm2Key, SM2_C1C2C3_ASN1_Ciphertext, SM2_C1C3C2_ASN1_Ciphertext, \ + SM2CipherFormat, \ + SM2CipherLength, \ + SM2CipherMode, \ + SM2PubKeyASN1Sequence, SM2PubKeyRawData +from .easy_sm2_sign_key import EasySM2SignKey, EasySM2VerifyKey, SignatureMode, SM2_RS_ASN1_Signature +from .easy_sm3_key import EasySM3Digest, EasySM3Hmac +from .easy_sm4_key import EasySm4CBC, EasySm4GCM, EncryptionMode +from .easy_zuc import EasyZuc diff --git a/demo_easy_gmssl/random_data.py b/demo_easy_gmssl/random_data.py new file mode 100644 index 0000000..4ca6604 --- /dev/null +++ b/demo_easy_gmssl/random_data.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 10:54:41 + +from __future__ import annotations + +from easy_gmssl import EasyRandomData, RandomMode + +# 生成随机字节流 +test = EasyRandomData() +ret = test.GetRandomData(20) +print(ret.hex()) +# 生成随机字符串 +test = EasyRandomData(mode = RandomMode.RandomStr) +ret = test.GetRandomData(64) +print(ret) diff --git a/demo_easy_gmssl/sm2_cipher_mode.py b/demo_easy_gmssl/sm2_cipher_mode.py new file mode 100644 index 0000000..782f8ac --- /dev/null +++ b/demo_easy_gmssl/sm2_cipher_mode.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 10:47:27 + +from __future__ import annotations + +from easy_gmssl import EasySm2EncryptionKey, SM2CipherFormat, SM2CipherMode + +enc = EasySm2EncryptionKey() +plain = 'hello,world' +# 遍历当前支持的所有 SM2 加解密算法模式 +# 当前支持的模式包括: +# C1C3C2_ASN1、C1C3C2、C1C2C3_ASN1、C1C2C3 +for mode in SM2CipherMode: + print(mode, '密文 in Hex:', enc.Encrypt('hello,world'.encode('utf-8'), mode, SM2CipherFormat.HexStr)) diff --git a/demo_easy_gmssl/sm2_encryption_decryption.py b/demo_easy_gmssl/sm2_encryption_decryption.py new file mode 100644 index 0000000..8448193 --- /dev/null +++ b/demo_easy_gmssl/sm2_encryption_decryption.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 09:48:59 + +from __future__ import annotations + +from easy_gmssl import EasySm2Key + +test = EasySm2Key() +print('公钥数据 In Hex:', test.get_sm2_public_key_in_hex()) +print('私钥数据 In Hex:', test.get_sm2_private_key_in_hex()) diff --git a/demo_easy_gmssl/sm2_sign.py b/demo_easy_gmssl/sm2_sign.py new file mode 100644 index 0000000..284c233 --- /dev/null +++ b/demo_easy_gmssl/sm2_sign.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 10:48:31 + +from __future__ import annotations + +import random + +from easy_gmssl import EasySM2SignKey, EasySM2VerifyKey, SignatureMode + +signer_id = 'test_signer' +print('signer_id hex:', signer_id.encode('utf-8').hex()) +# 初始化用于签名验签的 SM2 密钥,此时不需要关心签名值的模式 +test = EasySM2SignKey(signer_id = signer_id, pem_private_key_file = '../test_keys/tmp_test_sm2_private.pem', + password = '123456') +plain = bytes([random.randint(0, 255) for _ in range(0, 64)]) +print('plain hex:', plain.hex()) +print('private key hex:', test.get_sm2_private_key_in_hex()) +print('public key hex:', test.get_sm2_public_key_in_hex()) + +# 计算签名 +test.UpdateData(plain) +# 指定签名值模式为 RS 模式,可选 RS、RS_ASN1 +sign_value = test.GetSignValue(signature_mode = SignatureMode.RS) +print('signature hex:', sign_value.hex()) + +# 初始化用于验证签名的 SM2 密钥 +verify_test = EasySM2VerifyKey(signer_id = signer_id, pem_public_key_file = '../test_keys/tmp_test_sm2_public.pem') +# 验证签名 +verify_test.UpdateData(plain) +# 验证签名时同样指定签名值格式为 RS 模式 +ret = verify_test.VerifySignature(sign_value, signature_mode = SignatureMode.RS) diff --git a/demo_easy_gmssl/sm3_hash_hmac.py b/demo_easy_gmssl/sm3_hash_hmac.py new file mode 100644 index 0000000..0d7fcb8 --- /dev/null +++ b/demo_easy_gmssl/sm3_hash_hmac.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 10:52:54 + +from __future__ import annotations + +import random + +from easy_gmssl import EasySM3Digest, EasySM3Hmac +from easy_gmssl.gmssl import SM3_HMAC_MAX_KEY_SIZE + +test = EasySM3Digest() +# 计算哈希 +plain1 = 'hello,world'.encode('utf-8') +plain2 = '1234567890'.encode('utf-8') +plain3 = (plain1 + plain2) +print('plain hex:', plain3.hex()) +test.UpdateData(plain3) +hash_value_2, hash_len, length2 = test.GetHash() +print('hash value:', hash_value_2.hex()) +print('hash value length in bytes:', hash_len) + +# 计算HMAC +plain = 'hello,world'.encode('utf-8') +print('plain hex:', plain.hex()) +key = bytes([random.randint(0, 255) for _ in range(0, SM3_HMAC_MAX_KEY_SIZE)]) +print('key hex:', key.hex()) +test = EasySM3Hmac(key) +test.UpdateData(plain) +hmac_hex, hmac_len, plain_len = test.GetHmac() +print('hmac value:', hmac_hex.hex(), 'hmac len:', hmac_len, 'plain len:', plain_len) diff --git a/demo_easy_gmssl/sm4_cbc.py b/demo_easy_gmssl/sm4_cbc.py new file mode 100644 index 0000000..0c2e8a7 --- /dev/null +++ b/demo_easy_gmssl/sm4_cbc.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 10:49:46 + +from __future__ import annotations + +from easy_gmssl import EasySm4CBC +from easy_gmssl.gmssl import SM4_BLOCK_SIZE, SM4_CBC_IV_SIZE + +key = 'x' * SM4_BLOCK_SIZE +iv = 'y' * SM4_CBC_IV_SIZE +# 加密操作 +test_cbc_enc = EasySm4CBC(key.encode('utf-8'), iv.encode('utf-8'), True) +plain1 = 'hello,world' +plain2 = '1234567890' +cipher1 = test_cbc_enc.Update(plain1.encode('utf-8')) +cipher2 = test_cbc_enc.Update(plain2.encode('utf-8')) +ciphers = cipher1 + cipher2 + test_cbc_enc.Finish() + +# 解密操作 +test_dec = EasySm4CBC(key.encode('utf-8'), iv.encode('utf-8'), False) +decrypted_plain1 = test_dec.Update(ciphers) +decrypted_plain = decrypted_plain1 + test_dec.Finish() + +print('解密成功:', decrypted_plain == (plain1 + plain2).encode('utf-8')) diff --git a/demo_easy_gmssl/sm4_gcm.py b/demo_easy_gmssl/sm4_gcm.py new file mode 100644 index 0000000..b7a86fa --- /dev/null +++ b/demo_easy_gmssl/sm4_gcm.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 10:51:29 + +from __future__ import annotations + +from easy_gmssl import EasySm4GCM +from easy_gmssl.gmssl import SM4_BLOCK_SIZE, SM4_CBC_IV_SIZE, SM4_GCM_DEFAULT_TAG_SIZE + +key = 'x' * SM4_BLOCK_SIZE +iv = 'y' * SM4_CBC_IV_SIZE +# 定义拓展验证数据,加解密时此数据需要保持一致 +aad = 'a' * (SM4_BLOCK_SIZE + SM4_CBC_IV_SIZE) +# 定义tag长度,最小 8 个字节 +tag_len = int(SM4_GCM_DEFAULT_TAG_SIZE / 2) +test_gcm_enc = EasySm4GCM(key.encode('utf-8'), iv.encode('utf-8'), aad, tag_len, True) +plain1 = 'hello,world' +plain2 = '1234567890' +# 进行加密操作 +cipher1 = test_gcm_enc.Update(plain1.encode('utf-8')) +cipher2 = test_gcm_enc.Update(plain2.encode('utf-8')) +ciphers = cipher1 + cipher2 + test_gcm_enc.Finish() +# GCM模式下的密文长度与明文长度等长 +# 返回的密文中包含了 tag 长度 +print('ciphers len:', len(ciphers), 'tag_len=', tag_len, 'plain len:', len(plain1 + plain2)) + +# 进行解密操作,此时aad和tag_len需要与加密时保持一致 +test_dec = EasySm4GCM(key.encode('utf-8'), iv.encode('utf-8'), aad, tag_len, False) +decrypted_plain1 = test_dec.Update(ciphers) +decrypted_plain = decrypted_plain1 + test_dec.Finish() + +print('解密成功:', decrypted_plain == (plain1 + plain2).encode('utf-8')) diff --git a/demo_easy_gmssl/zuc.py b/demo_easy_gmssl/zuc.py new file mode 100644 index 0000000..c05028b --- /dev/null +++ b/demo_easy_gmssl/zuc.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-24 10:55:13 + +from __future__ import annotations + +from easy_gmssl import EasyRandomData, EasyZuc +from easy_gmssl.gmssl import ZUC_IV_SIZE, ZUC_KEY_SIZE + +# 生成密钥与 IV +key = EasyRandomData().GetRandomData(ZUC_KEY_SIZE) +iv = EasyRandomData().GetRandomData(ZUC_IV_SIZE) +# 加密操作 +test = EasyZuc(key, iv) +plain1 = 'hello,world'.encode('utf-8') +cipher1 = test.Update(plain1) +plain2 = '1234567890'.encode('utf-8') +cipher2 = test.Update(plain2) +cipher3 = test.Finish() + +# 解密操作 +test2 = EasyZuc(key, iv) +ret1 = test2.Update(cipher1) +ret2 = test2.Update(cipher2) +ret3 = test2.Update(cipher3) +ret4 = test2.Finish() +assert ret1 + ret2 + ret3 + ret4 == plain1 + plain2 +print('解密成功:', ret1 + ret2 + ret3 + ret4 == plain1 + plain2) diff --git a/easy_random_data.py b/easy_random_data.py new file mode 100644 index 0000000..2b24192 --- /dev/null +++ b/easy_random_data.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-23 17:00:50 + +from __future__ import annotations + +import random +import string +from enum import Enum +from typing import Union + +from .gmssl import rand_bytes + + +class RandomMode(Enum): + RandomBytes = 'RandomBytes' + RandomStr = 'RandomStr' + + +class EasyRandomData(object): + _all_random_characters_ = list(string.ascii_letters + string.digits + "'\"{}[]\\!@#$%^&*()_+|:") + + def __init__(self, mode: RandomMode = RandomMode.RandomBytes): + self._mode = mode + + def GetRandomData(self, length: int = 16) -> Union[bytes | str]: + r = rand_bytes(length) + if length < 1: + raise ValueError('invalid random length, required greater than 0') + if self._mode == RandomMode.RandomBytes: + return r + elif self._mode == RandomMode.RandomStr: + random.shuffle(self._all_random_characters_) + result = "" + for i in r: + result += self._all_random_characters_[int(i) % len(self._all_random_characters_)] + return result diff --git a/easy_random_data_test.py b/easy_random_data_test.py new file mode 100644 index 0000000..f367257 --- /dev/null +++ b/easy_random_data_test.py @@ -0,0 +1,30 @@ +import string +import unittest + +from .easy_random_data import EasyRandomData, RandomMode + + +class MyTestCase(unittest.TestCase): + def test_random_data(self): + test = EasyRandomData() + ret = test.GetRandomData(20) + print(ret.hex()) + self.assertTrue(len(ret) == 20) + + test = EasyRandomData(mode = RandomMode.RandomStr) + ret = test.GetRandomData(64) + print(ret) + for i in ret: + self.assertTrue(i in list(string.ascii_letters + string.digits + string.printable + "'\"{}[]\\!@#$%^&*()_+|:")) + + try: + test.GetRandomData(0) + except Exception as e: + print(e) + self.assertTrue(True) + else: + self.assertTrue(False) + + +if __name__ == '__main__': + unittest.main() diff --git a/easy_sm2_key.py b/easy_sm2_key.py new file mode 100644 index 0000000..508f412 --- /dev/null +++ b/easy_sm2_key.py @@ -0,0 +1,558 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-21 14:31:17 + +from __future__ import annotations + +import base64 +import binascii +import ctypes +from enum import Enum +from typing import Dict, List, Literal, Tuple + +from pyasn1.codec.der import decoder, encoder +from pyasn1.type import namedtype, univ + +from .gmssl import NativeError, SM2_MAX_CIPHERTEXT_SIZE, SM2_MAX_PLAINTEXT_SIZE, Sm2Key + + +class SM2PubKeyASN1Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('oid-tags', + univ.Sequence( + componentType = namedtype.NamedTypes( + namedtype.NamedType('oid-1', univ.ObjectIdentifier()), + namedtype.NamedType('oid-2', univ.ObjectIdentifier()) + ) + )), + namedtype.NamedType('sm2_public_key', univ.BitString()) + ) + + +class SM2PubKeyRawData(object): + def __init__(self, oids: List[str], hex_data: str): + self.__oids = oids + self.__hex_data = hex_data + + @property + def oids(self) -> List[str]: + return self.__oids + + @property + def hex_data(self) -> str: + return self.__hex_data + + +class SM2CipherMode(Enum): + C1C3C2_ASN1 = 'C1C3C2_ASN1' + C1C3C2 = 'C1C3C2' + C1C2C3_ASN1 = 'C1C2C3_ASN1' + C1C2C3 = 'C1C2C3' + + +class SM2CipherFormat(Enum): + Base64Str = 'Base64' + HexStr = 'Hex' + + +class SM2CipherLength(Enum): + """ + SM2密文主要由C1、C2、C3三部分构成, + 其中C1是随机数计算出的椭圆曲线、C2是密文数据、C3是SM3杂凑值, + C1固定为64字节,C2的长度与明文相同,C3的长度固定为32字节, + """ + C1LenInBytes = 64 + C1XLenInBytes = 32 + C1YLenInBytes = 32 + C3LenInBytes = 32 + + +def __easy_parse_sm2_pub_key__(base64_content: str) -> SM2PubKeyRawData: + try: + raw_bytes = base64.b64decode(base64_content) + ret_obj, _ = decoder.decode(raw_bytes, asn1Spec = SM2PubKeyASN1Sequence()) + except Exception: + raise ValueError('invalid sm2 public key bytes') + else: + oid1 = ret_obj['oid-tags']['oid-1'].prettyPrint() + oid2 = ret_obj['oid-tags']['oid-2'].prettyPrint() + sm2_pub = ret_obj['sm2_public_key'] + bit_string = sm2_pub.asOctets() + hex_string = binascii.hexlify(bit_string).decode('utf-8') + return SM2PubKeyRawData([oid1, oid2], hex_string) + + +def __check_private_key_password__(pri_key_password: str): + if len(pri_key_password) <= 0: + raise ValueError('empty password for sm2 private key') + if len(pri_key_password) > 32: + raise ValueError('sm2 private key password too long') + + +def __easy_read_sm2_pub_pem_file_lines__(pem_file: str) -> str: + """ + 返回 base64 编码的公钥内容 + """ + MAX_FILE_SIZE = 2048 + file_size = 0 + lines = [] + try: + with open(pem_file, 'r') as pem_file: + for line in pem_file: + file_size += len(line) + if file_size > MAX_FILE_SIZE: + raise ValueError("PEM File Too Large") + lines.append(line.strip()) + except FileNotFoundError: + raise FileNotFoundError("invalid file:{}".format(pem_file)) + else: + content = '' + for i in lines: + i = i.strip() + if len(i) > 0: + content += i.strip() + content = content.replace('-----BEGIN PUBLIC KEY-----', '') + content = content.replace('-----END PUBLIC KEY-----', '') + if len(content) <= 0: + raise ValueError("invalid pem content") + return content + + +# 定义SM2 C1C3C2_ASN1 Ciphertext结构 +class SM2_C1C3C2_ASN1_Ciphertext(univ.Sequence): + """ + c1x 和 c1y 分别代表 C1 点的 x 和 y 坐标 + 这个 C1 点是加密过程中随机生成的,用于与接收方的公钥进行交互以确保加密的安全性 + C1 的坐标(c1x, c1y)与公钥的坐标(x, y)是不会相同的 + 在实际应用中,随机数 k 是每次加密时新生成的随机数,以确保加密的安全性 + """ + componentType = namedtype.NamedTypes( + namedtype.NamedType('c1x', univ.Integer()), + namedtype.NamedType('c1y', univ.Integer()), + namedtype.NamedType('c3', univ.OctetString()), + namedtype.NamedType('c2', univ.OctetString()) + ) + + +# 定义SM2 C1C2C3_ASN1 Ciphertext结构 +class SM2_C1C2C3_ASN1_Ciphertext(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('c1x', univ.Integer()), + namedtype.NamedType('c1y', univ.Integer()), + namedtype.NamedType('c2', univ.OctetString()), + namedtype.NamedType('c3', univ.OctetString()) + ) + + +def __check_raw_cipher_length__(raw_cipher: bytes): + min_length = SM2CipherLength.C1LenInBytes.value + SM2CipherLength.C3LenInBytes.value + if len(raw_cipher) < min_length: + raise ValueError('invalid cipher length, required at least:{} bytes'.format(min_length)) + return + + +def __parse_sm2_asn1_cipher_bytes__(raw_cipher: bytes, + cipher_mode: Literal[ + SM2CipherMode.C1C3C2_ASN1, SM2CipherMode.C1C2C3_ASN1] = SM2CipherMode.C1C3C2_ASN1) -> \ + Tuple[ + bytes, bytes, bytes, bytes]: + """ + 解析 C1C3C2_ASN1 或 C1C2C3_ASN1 格式的密文数据,返回 C1X、C1Y、C3、C2 字节序列 + """ + if cipher_mode not in [SM2CipherMode.C1C3C2_ASN1, SM2CipherMode.C1C2C3_ASN1]: + raise ValueError('invalid sm2 cipher mode:{}'.format(cipher_mode)) + asn1SpecObj = SM2_C1C3C2_ASN1_Ciphertext() + if cipher_mode == SM2CipherMode.C1C2C3_ASN1: + asn1SpecObj = SM2_C1C2C3_ASN1_Ciphertext() + try: + __check_raw_cipher_length__(raw_cipher) + decoded, _ = decoder.decode(raw_cipher, asn1Spec = asn1SpecObj) + except Exception: + raise ValueError('invalid ASN1 cipher data') + else: + # print(decoded) + c1x = int(decoded['c1x']) # 大整数 + c1y = int(decoded['c1y']) # 大整数 + c2 = bytes(decoded['c2']) # 字节流 + c3 = bytes(decoded['c3']) # 字节流 + # 大端字节序 + c1x_bytes = c1x.to_bytes(length = 32, byteorder = 'big') + c1y_bytes = c1y.to_bytes(length = 32, byteorder = 'big') + return c1x_bytes, c1y_bytes, c3, c2 + + +def __encode_sm2_cipher_to_asn1_sequence__(cipher_c1c3c2: Tuple[bytes, bytes, bytes, bytes], + cipher_mode: Literal[ + SM2CipherMode.C1C3C2_ASN1, SM2CipherMode.C1C2C3_ASN1] = SM2CipherMode.C1C3C2_ASN1) -> bytes: + if cipher_mode not in [SM2CipherMode.C1C3C2_ASN1, SM2CipherMode.C1C2C3_ASN1]: + raise ValueError('invalid sm2 cipher mode:{}'.format(cipher_mode)) + try: + c1x = cipher_c1c3c2[0] + c1x_int = int.from_bytes(c1x, byteorder = 'big') + c1y = cipher_c1c3c2[1] + c1y_int = int.from_bytes(c1y, byteorder = 'big') + c3 = cipher_c1c3c2[2] + c2 = cipher_c1c3c2[3] + except Exception as e: + raise ValueError('invalid sm2 cipher data:{}'.format(e)) + else: + ciphertext = SM2_C1C3C2_ASN1_Ciphertext() + if cipher_mode == SM2CipherMode.C1C2C3_ASN1: + ciphertext = SM2_C1C2C3_ASN1_Ciphertext() + ciphertext.setComponentByName('c1x', c1x_int) + ciphertext.setComponentByName('c1y', c1y_int) + ciphertext.setComponentByName('c3', c3) + ciphertext.setComponentByName('c2', c2) + encoded_ciphertext = encoder.encode(ciphertext) + return encoded_ciphertext + + +def __parse_sm2_c1c3c2_cipher_bytes__(raw_cipher: bytes) -> Tuple[bytes, bytes, bytes, bytes]: + """ + 解析 C1C3C2 格式的密文数据,返回 C1X、C1Y、C3、C2 字节序列 + """ + try: + __check_raw_cipher_length__(raw_cipher) + c1x_bytes = raw_cipher[:SM2CipherLength.C1XLenInBytes.value] + c1y_bytes = raw_cipher[ + SM2CipherLength.C1XLenInBytes.value: SM2CipherLength.C1XLenInBytes.value + SM2CipherLength.C1YLenInBytes.value] + c3_bytes = raw_cipher[SM2CipherLength.C1XLenInBytes.value + SM2CipherLength.C1YLenInBytes.value: + SM2CipherLength.C1XLenInBytes.value + SM2CipherLength.C1YLenInBytes.value + SM2CipherLength.C3LenInBytes.value] + c2_bytes = raw_cipher[ + SM2CipherLength.C1XLenInBytes.value + SM2CipherLength.C1YLenInBytes.value + SM2CipherLength.C3LenInBytes.value:] + except Exception as e: + raise ValueError('invalid sm2 cipher data:{}'.format(e)) + else: + return c1x_bytes, c1y_bytes, c3_bytes, c2_bytes + + +def __parse_sm2_c1c2c3_bytes__(raw_cipher: bytes) -> Tuple[bytes, bytes, bytes, bytes]: + """ + 解析 C1C2C3 格式的密文数据,返回 C1X、C1Y、C3、C2 字节序列 + """ + try: + __check_raw_cipher_length__(raw_cipher) + c1x_bytes = raw_cipher[:SM2CipherLength.C1XLenInBytes.value] + c1y_bytes = raw_cipher[ + SM2CipherLength.C1XLenInBytes.value: SM2CipherLength.C1XLenInBytes.value + SM2CipherLength.C1YLenInBytes.value] + c3_bytes = raw_cipher[len(raw_cipher) - SM2CipherLength.C3LenInBytes.value:] + c2_bytes = raw_cipher[SM2CipherLength.C1XLenInBytes.value + SM2CipherLength.C1YLenInBytes.value:len( + raw_cipher) - SM2CipherLength.C3LenInBytes.value] + except Exception as e: + raise ValueError('invalid sm2 cipher data:{}'.format(e)) + else: + return c1x_bytes, c1y_bytes, c3_bytes, c2_bytes + + +def __encode_cipher__(target_mode: SM2CipherMode, cipher_c1c3c2: Tuple[bytes, bytes, bytes, bytes]) -> bytes: + """ + 将 C1X C1Y C3 C2 密文字节序列编码成指定的 SM2 密文格式 + 如果是 ASN1 格式,则需要单独做二进制编码 + 如果是非 ASN1 格式,则只需要按照指定的顺序将 C1、C3、C2进行拼接 + """ + try: + c1x = cipher_c1c3c2[0] + c1y = cipher_c1c3c2[1] + c3 = cipher_c1c3c2[2] + c2 = cipher_c1c3c2[3] + except Exception as e: + raise ValueError('invalid cipher data:{}'.format(e)) + else: + ret = bytearray() + if target_mode == SM2CipherMode.C1C2C3: + ret.extend(c1x) + ret.extend(c1y) + ret.extend(c2) + ret.extend(c3) + return bytes(ret) + elif target_mode == SM2CipherMode.C1C3C2: + ret.extend(c1x) + ret.extend(c1y) + ret.extend(c3) + ret.extend(c2) + return bytes(ret) + else: + try: + if target_mode in [SM2CipherMode.C1C3C2_ASN1, SM2CipherMode.C1C2C3_ASN1]: + return __encode_sm2_cipher_to_asn1_sequence__(cipher_c1c3c2 = cipher_c1c3c2, + cipher_mode = target_mode) + else: + raise TypeError('invalid cipher mode:{}'.format(target_mode)) + except Exception as e: + raise ValueError('encode cipher to asn1 mode:{} error:{}'.format(target_mode, e)) + + +def __parse_and_repack_cipher__(cipher_mode: SM2CipherMode, + cipher_format: SM2CipherFormat, + c1c3c2_asn1_cipher: bytes) -> str: + if not isinstance(cipher_mode, SM2CipherMode): + raise TypeError('invalid cipher mode: {}'.format(cipher_mode)) + if not isinstance(cipher_format, SM2CipherFormat): + raise TypeError('invalid cipher format: {}'.format(cipher_format)) + encoded_cipher_bytes = c1c3c2_asn1_cipher + if cipher_mode != SM2CipherMode.C1C3C2_ASN1: + # 首先按照C1C3C2_ASN1格式解析原始的数据,获取到 C1X、C1Y、C3、C2这四部分数据 + cipher_c1_c3_c2 = __parse_sm2_asn1_cipher_bytes__(raw_cipher = c1c3c2_asn1_cipher, + cipher_mode = SM2CipherMode.C1C3C2_ASN1) + encoded_cipher_bytes = __encode_cipher__(target_mode = cipher_mode, cipher_c1c3c2 = cipher_c1_c3_c2) + + if cipher_format == SM2CipherFormat.Base64Str: + return base64.b64encode(encoded_cipher_bytes).decode('utf-8') + else: + return encoded_cipher_bytes.hex() + + +def __parse_raw_cipher_and_repack_to_c1c3c2_asn1__(cipher_mode: Literal[ + SM2CipherMode.C1C3C2_ASN1, + SM2CipherMode.C1C3C2, + SM2CipherMode.C1C2C3_ASN1, + SM2CipherMode.C1C2C3], + raw_cipher_bytes: bytes) -> bytes: + """ + 将不同模式下的密文数据统一转换为 C1C3C2_ASN1 模式的密文 + """ + try: + __check_raw_cipher_length__(raw_cipher_bytes) + c1_c3_c2_bytes = bytes() + if cipher_mode == SM2CipherMode.C1C3C2_ASN1: + return raw_cipher_bytes + elif cipher_mode == SM2CipherMode.C1C2C3_ASN1: + c1_c3_c2_bytes = __parse_sm2_asn1_cipher_bytes__(raw_cipher = raw_cipher_bytes, cipher_mode = cipher_mode) + elif cipher_mode == SM2CipherMode.C1C2C3: + c1_c3_c2_bytes = __parse_sm2_c1c2c3_bytes__(raw_cipher = raw_cipher_bytes) + elif cipher_mode == SM2CipherMode.C1C3C2: + c1_c3_c2_bytes = __parse_sm2_c1c3c2_cipher_bytes__(raw_cipher = raw_cipher_bytes) + except Exception as e: + raise ValueError('invalid cipher data:{}, cipher mode = {}'.format(e, cipher_mode)) + else: + return __encode_cipher__(target_mode = SM2CipherMode.C1C3C2_ASN1, cipher_c1c3c2 = c1_c3_c2_bytes) + + +class EasySm2Key(object): + """ + EasySM2Key 对象非线程安全,不可并发执行写操作 + """ + + def __init__(self): + self._point_x = '' + self._point_y = '' + self._private_key_hex = '' + self._sm2_raw_key = Sm2Key() + self.reset_key() + self.new_key() + + def reset_key(self): + """ + 清理 key 数据 + 清理后可以使用 new_key() 生成新的 SM2密钥对数据 + """ + self.__clear_raw_key_data__() + + def __clear_raw_key_data__(self): + # 清空数据 + ctypes.memset(ctypes.byref(self._sm2_raw_key.public_key.x), 0, 32) + ctypes.memset(ctypes.byref(self._sm2_raw_key.public_key.y), 0, 32) + ctypes.memset(ctypes.byref(self._sm2_raw_key.private_key), 0, 32) + self._point_x = '' + self._point_y = '' + self._private_key_hex = '' + self._sm2_raw_key._has_public_key = False + self._sm2_raw_key._has_private_key = False + + def __set_point_x_y_in_hex__(self): + if self._sm2_raw_key.has_public_key(): + self._point_x = bytes(self._sm2_raw_key.public_key.x).hex() + self._point_y = bytes(self._sm2_raw_key.public_key.y).hex() + + def __set_private_key_in_hex__(self): + if self._sm2_raw_key.has_private_key(): + self._private_key_hex = bytes(self._sm2_raw_key.private_key).hex() + + def new_key(self) -> EasySm2Key: + """ + 用于在使用 reset_key() 后重新生成新的 SM2 密钥对 + """ + self.__clear_raw_key_data__() + self._sm2_raw_key.generate_key() + self.__set_point_x_y_in_hex__() + self.__set_private_key_in_hex__() + return self + + def export_to_pem_file(self, file_name_prefix: str, pri_key_password: str): + """ + 输入:文件名前缀、私钥密码 + 假设文件名前缀为 test, 则生成的文件名为: test_sm2_public.pem、test_sm2_private.pem + 私钥密码不能为空,最长允许 32 个字节 + """ + if len(file_name_prefix) <= 0: + raise ValueError('empty sm2 file name prefix') + pub_key_file_name = f'{file_name_prefix}_sm2_public.pem' + pri_key_file_name = f'{file_name_prefix}_sm2_private.pem' + try: + __check_private_key_password__(pri_key_password) + self._sm2_raw_key.export_public_key_info_pem(pub_key_file_name) + self._sm2_raw_key.export_encrypted_private_key_info_pem(pri_key_file_name, pri_key_password) + except Exception as e: + raise e + + def load_sm2_pub_key(self, pub_key_file: str) -> SM2PubKeyRawData: + """ + 从 PEM 文件中加载 SM2 公钥 + """ + try: + base64_content_data = __easy_read_sm2_pub_pem_file_lines__(pub_key_file) + sm2_pub_raw_data = __easy_parse_sm2_pub_key__(base64_content_data) + except Exception: + raise ValueError('invalid sm2 public key file') + else: + self.__clear_raw_key_data__() + self._sm2_raw_key.import_public_key_info_pem(pub_key_file) + self.__set_point_x_y_in_hex__() + assert sm2_pub_raw_data.hex_data == self.__get_pub_key_by_point__() + return sm2_pub_raw_data + + def load_sm2_private_key(self, pri_key_file: str, password: str): + """ + 从 PEM 文件中加载 SM2 私钥,加载的私钥必须要输入解密密码 + 加载密钥时会重置公钥和私钥数据 + """ + try: + __check_private_key_password__(password) + self._sm2_raw_key.import_encrypted_private_key_info_pem(pri_key_file, password) + except NativeError as e: + raise ValueError('invalid sm2 private key file or password, {}'.format(e)) + except Exception: + raise TypeError('sm2 pem private key imported failed') + else: + self.__set_point_x_y_in_hex__() + self.__set_private_key_in_hex__() + + def __get_pub_key_by_point__(self, uncompressed: bool = True) -> str: + """ + 在 SM2 公钥十六进制表示中,前导字节04表示该公钥是非压缩形式。 + SM2 公钥是椭圆曲线上的一个点,由横坐标X和纵坐标Y两个分量组成。 + 非压缩形式的公钥直接存储了完整的X和Y坐标值,其格式为04||X||Y ,其中X和Y均为 32 字节 + + 如果公钥是压缩形式,公钥的表示以字节 02 或者 03 开头 + """ + if self._sm2_raw_key.has_public_key(): + if uncompressed: + return '04' + self._point_x + self._point_y + else: + raise TypeError('SM2 Public Key in compressed form are not supported') + return '' + + def get_sm2_public_key_in_hex(self) -> str: + """ + 返回公钥的十六进制字符串 + 如果没有公钥, 则返回的字符串为空 + """ + if self._sm2_raw_key.has_public_key(): + return self.__get_pub_key_by_point__() + return '' + + def get_sm2_private_key_in_hex(self) -> str: + """ + 返回私钥的十六进制字符串 + 如果没有私钥,则返回的字符串为空 + """ + if self._sm2_raw_key.has_public_key(): + return self._private_key_hex + return '' + + def get_point_in_hex(self) -> Dict[str, str]: + """ + 返回 [X, Y] 坐标的十六进制字符串 + 如果没有公钥,则返回的坐标值为空 + """ + if self._sm2_raw_key.has_public_key(): + return {'X': self._point_x, 'Y': self._point_y} + return {'X': '', 'Y': ''} + + +class EasySm2EncryptionKey(EasySm2Key): + def __init__(self): + super().__init__() + + def Encrypt(self, plain_data: bytes, + cipher_mode: Literal[ + SM2CipherMode.C1C3C2_ASN1, + SM2CipherMode.C1C3C2, + SM2CipherMode.C1C2C3_ASN1, + SM2CipherMode.C1C2C3] = SM2CipherMode.C1C3C2_ASN1, + cipher_format: Literal[ + SM2CipherFormat.Base64Str, + SM2CipherFormat.HexStr] = SM2CipherFormat.Base64Str) -> str: + if not isinstance(cipher_mode, SM2CipherMode): + raise TypeError('invalid cipher mode: {}'.format(cipher_mode)) + if not isinstance(cipher_format, SM2CipherFormat): + raise TypeError('invalid cipher format: {}'.format(cipher_format)) + if self._sm2_raw_key.has_public_key(): + if len(plain_data) <= SM2_MAX_PLAINTEXT_SIZE: + c1c3c2_asn1_cipher_bytes: bytes = self._sm2_raw_key.encrypt(plain_data) + return __parse_and_repack_cipher__(cipher_mode, cipher_format, c1c3c2_asn1_cipher_bytes) + else: + raise ValueError('the maximum limit for the plaintext is {} bytes'.format(SM2_MAX_PLAINTEXT_SIZE)) + else: + raise ValueError('empty sm2 public key') + + def Decrypt(self, cipher_data: bytes, + cipher_mode: Literal[ + SM2CipherMode.C1C3C2_ASN1, + SM2CipherMode.C1C3C2, + SM2CipherMode.C1C2C3_ASN1, + SM2CipherMode.C1C2C3] = SM2CipherMode.C1C3C2_ASN1) -> bytes: + """ + cipher_data: 密文数据 + cipher_mode: 密文模式 + 返回明文的字节序列 + """ + if not isinstance(cipher_mode, SM2CipherMode): + raise TypeError('invalid cipher mode: {}'.format(cipher_mode)) + if not self._sm2_raw_key.has_private_key(): + raise TypeError('no private key included, can not decrypt') + if len(cipher_data) > SM2_MAX_CIPHERTEXT_SIZE: + raise ValueError('cipher data too long, the maximum limit for the cipher is {} bytes'.format(SM2_MAX_CIPHERTEXT_SIZE)) + try: + to_be_decrypted_cipher = __parse_raw_cipher_and_repack_to_c1c3c2_asn1__(cipher_mode = cipher_mode, + raw_cipher_bytes = cipher_data) + ret = bytes(self._sm2_raw_key.decrypt(to_be_decrypted_cipher)) + except Exception as e: + raise ValueError('decrypt error:{}, cipher mode = {}'.format(e, cipher_mode)) + else: + return ret + + +if __name__ == '__main__': + enc = EasySm2EncryptionKey() + enc.load_sm2_private_key('./test_keys/tmp_test_sm2_private.pem', '123456') + plain = 'hello,world' + print('明文:', plain.encode('utf-8').hex()) + print('随机生成的公钥数据:', enc.get_sm2_public_key_in_hex()) + print('随机生成的私钥数据:', enc.get_sm2_private_key_in_hex()) + print('公钥 XY 坐标:', enc.get_point_in_hex()) + print('-' * 32) + for mode in SM2CipherMode: + print(mode, '密文 in Hex:', enc.Encrypt('hello,world'.encode('utf-8'), mode, SM2CipherFormat.HexStr)) + + print('-' * 32) + + # c1c3c2_asn1_cipher_hex = "307302202DDE3E3B518AE79A0DA24792AACCAF277C70D2BF094A721402F988ABF34D8A2B022045FF327DDDECEDB4A239BF262539A435AC4B5A2CD40496921A15C44DE4FD8ED60420EDDF4218FE658B672FC09E3F86676702EC380AAA4A9495C26BDAB191826FB547040BC6CF28A8BF426DF50F5E4F" + # c1c2c3_asn1_cipher_hex = "3074022100AEC56299468A3F0915D07607D25CE80091953530962F60CB953269AA17D1CC370220775B350FFF2F5E6593DDF289D74EF180D272EE27F7EFC7BF7E77FF760B26A376040B603717A97A68C54DD12D33042034049DB7F277C2E78E9984E01BB5B1F8718CA1CB4ADFB5DB567604A65E877C4E" + # c1c3c2_cipher_hex = "D3E1C15A8DE95D7213C916DAD6E416764910DC219F9E2E59283D55C6F124DEA845948F16201DA56B4072D7A63E81DB50993133338B6571C2D4FC4A6DA25C17D956508371AB83490E140E6445CC2A2224CB576D2711B698D67BCA38004119C91AD6F505BAC893ACBAE5B8B7" + # c1c2c3_cipher_hex = "F7F93B18B51DEE2384EF6EF4E45F5802FD980C0B00131CBE8006E89BA66D8E1241855F38293970306C974D4DD929A3D059BB9082DD7AA68420630B24A61E92754A4307FB47B3FEB7CB15E7D1F94CF4F99F8378548ED73D0EDD86418D823ACDB58F1802B7C8BB03F99112F7" + # + # tmp_ciphers = { + # SM2CipherMode.C1C3C2_ASN1: c1c3c2_asn1_cipher_hex, + # SM2CipherMode.C1C2C3_ASN1: c1c2c3_asn1_cipher_hex, + # SM2CipherMode.C1C2C3: c1c2c3_cipher_hex, + # SM2CipherMode.C1C3C2: c1c3c2_cipher_hex, + # } + # + # for mode, cipher in tmp_ciphers.items(): + # try: + # plain_hex = enc.decrypt(bytes.fromhex(cipher), mode).hex() + # except Exception as e: + # print('decrypt failed, mode={}'.format(mode)) + # else: + # print('mode={}, decrypt success:{}, 明文 in Hex:{}'.format(mode, plain_hex == plain.encode('utf-8').hex(), plain_hex)) diff --git a/easy_sm2_key_test.py b/easy_sm2_key_test.py new file mode 100644 index 0000000..a8694d9 --- /dev/null +++ b/easy_sm2_key_test.py @@ -0,0 +1,162 @@ +import base64 +import random +import unittest + +from .easy_sm2_key import EasySm2EncryptionKey, EasySm2Key, SM2CipherFormat, SM2CipherMode +from .gmssl import SM2_MAX_CIPHERTEXT_SIZE, SM2_MAX_PLAINTEXT_SIZE + + +class SM2KeyCase(unittest.TestCase): + def test_new_sm2_key(self): + test1 = EasySm2Key() + self.assertTrue(test1.get_sm2_public_key_in_hex() != '') + self.assertTrue(test1.get_sm2_private_key_in_hex() != '') + self.assertTrue('X' in test1.get_point_in_hex().keys()) + self.assertTrue(test1.get_point_in_hex()['X'] != '') + self.assertTrue('Y' in test1.get_point_in_hex().keys()) + self.assertTrue(test1.get_point_in_hex()['Y'] != '') + + test1_pub_key = test1.get_sm2_public_key_in_hex() + test1_pri_key = test1.get_sm2_private_key_in_hex() + + # 重新生成密钥 + test1.reset_key() + test1.new_key() + self.assertTrue(test1.get_sm2_public_key_in_hex() != '') + self.assertTrue(test1.get_sm2_private_key_in_hex() != '') + self.assertTrue(test1.get_sm2_public_key_in_hex() != test1_pub_key) + self.assertTrue(test1.get_sm2_private_key_in_hex() != test1_pri_key) + + def test_key_export(self): + test = EasySm2Key() + self.assertTrue(test.get_sm2_public_key_in_hex() != '') + self.assertTrue(test.get_sm2_private_key_in_hex() != '') + pub_key = test.get_sm2_public_key_in_hex() + pri_key = test.get_sm2_private_key_in_hex() + + # 先导出密钥对 + test.export_to_pem_file('./test_keys/tmp_test', '123456') + + # 重新导入公钥,此时私钥数据为空 + test.load_sm2_pub_key('./test_keys/tmp_test_sm2_public.pem') + self.assertTrue(test.get_sm2_public_key_in_hex() == pub_key) + self.assertTrue(test.get_sm2_private_key_in_hex() == '') + + # 重新导入私钥,此时公钥、私钥数据均不为空 + test.load_sm2_private_key('./test_keys/tmp_test_sm2_private.pem', '123456') + self.assertTrue(test.get_sm2_public_key_in_hex() == pub_key) + self.assertTrue(test.get_sm2_private_key_in_hex() == pri_key) + + test.load_sm2_pub_key('./test_keys/kms_sm2.pem') + self.assertFalse(test.get_sm2_public_key_in_hex() == pub_key) + + def test_key_import(self): + test = EasySm2Key() + self.assertTrue(test.get_sm2_public_key_in_hex() != '') + self.assertTrue(test.get_sm2_private_key_in_hex() != '') + + try: + test.load_sm2_pub_key('./test_keys/invalid_pub_key.pem') + except Exception as e: + print(e) + self.assertTrue(True) + else: + self.assertTrue(False) + + try: + # 密码为空 + print('密码为空') + test.load_sm2_private_key('./test_keys/tmp_test_sm2_private.pem', '') + except Exception as e: + print(e) + self.assertTrue(True) + else: + self.assertTrue(False) + + try: + # 密码错误 + print('密码错误') + test.load_sm2_private_key('./test_keys/tmp_test_sm2_private.pem', '1' * 32) + except Exception as e: + print(e) + self.assertTrue(True) + else: + self.assertTrue(False) + + try: + # 密码过长 + print('密码过长') + test.load_sm2_private_key('./test_keys/tmp_test_sm2_private.pem', '1' * 33) + except Exception as e: + print(e) + self.assertTrue(True) + else: + self.assertTrue(False) + + def test_valid_encrypt_decrypt(self): + test = EasySm2EncryptionKey() + plain_valid = bytes([random.randint(1, 255) for _ in range(0, SM2_MAX_PLAINTEXT_SIZE)]) + for mode in SM2CipherMode: + cipher = test.Encrypt(plain_data = plain_valid, cipher_mode = mode, cipher_format = SM2CipherFormat.Base64Str) + decrypted_plain = test.Decrypt(cipher_data = base64.b64decode(cipher), cipher_mode = mode) + self.assertTrue(decrypted_plain == plain_valid) + + def test_encrypt_too_long_plain(self): + test = EasySm2EncryptionKey() + plain_valid = bytes([random.randint(1, 255) for _ in range(0, SM2_MAX_PLAINTEXT_SIZE + 1)]) + try: + test.Encrypt(plain_data = plain_valid) + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + def test_decrypt_too_long_cipher(self): + test = EasySm2EncryptionKey() + cipher_invalid = bytes([random.randint(1, 255) for _ in range(0, SM2_MAX_CIPHERTEXT_SIZE + 1)]) + try: + test.Decrypt(cipher_data = cipher_invalid) + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + def test_invalid_cipher_mode(self): + test = EasySm2EncryptionKey() + plain_valid = bytes([random.randint(1, 255) for _ in range(0, SM2_MAX_PLAINTEXT_SIZE)]) + try: + test.Encrypt(plain_data = plain_valid, cipher_mode = 'abc') + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + def test_invalid_cipher_format(self): + test = EasySm2EncryptionKey() + plain_valid = bytes([random.randint(1, 255) for _ in range(0, SM2_MAX_PLAINTEXT_SIZE)]) + try: + test.Encrypt(plain_data = plain_valid, cipher_format = 'abc') + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + def test_has_no_private_key(self): + test = EasySm2EncryptionKey() + test.load_sm2_pub_key('./test_keys/tmp_test_sm2_public.pem') + cipher_invalid = bytes([random.randint(1, 255) for _ in range(0, SM2_MAX_CIPHERTEXT_SIZE)]) + try: + test.Decrypt(cipher_data = cipher_invalid) + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + +if __name__ == '__main__': + unittest.main() diff --git a/easy_sm2_sign_key.py b/easy_sm2_sign_key.py new file mode 100644 index 0000000..042613a --- /dev/null +++ b/easy_sm2_sign_key.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-23 15:18:18 + +from __future__ import annotations + +from enum import Enum +from typing import Tuple + +from pyasn1.codec.der import decoder, encoder +from pyasn1.type import namedtype, univ + +from .gmssl import SM2_DEFAULT_ID, SM2_MAX_SIGNATURE_SIZE, Sm2Signature +from .easy_sm2_key import EasySm2Key + + +# 定义 SM2 签名 ASN.1 结构 +class SM2_RS_ASN1_Signature(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('r', univ.Integer()), + namedtype.NamedType('s', univ.Integer()) + ) + + +class SignatureMode(Enum): + RS_ASN1 = 'RS_ASN1' + RS = 'RAW_RS' + + +def __parse_sm2_rs_asn1_signature__(signature: bytes) -> Tuple[bytes, bytes]: + if len(signature) > SM2_MAX_SIGNATURE_SIZE: + raise ValueError('invalid sm2 signature, maximum limit size:{}'.format(SM2_MAX_SIGNATURE_SIZE)) + try: + decoded, _ = decoder.decode(signature, asn1Spec = SM2_RS_ASN1_Signature()) + r_int = int(decoded['r']) + r_bytes = r_int.to_bytes(length = 32, byteorder = 'big') + s_int = int(decoded['s']) + s_bytes = s_int.to_bytes(length = 32, byteorder = 'big') + except Exception as e: + raise ValueError('invalid RS_ASN1 signature:{}'.format(e)) + else: + return r_bytes, s_bytes + + +def __encode_rs_to_asn1_sequence__(rs_bytes: Tuple[bytes, bytes]) -> bytes: + try: + r_bytes = rs_bytes[0] + s_bytes = rs_bytes[1] + r_int = int.from_bytes(r_bytes, byteorder = 'big') + s_int = int.from_bytes(s_bytes, byteorder = 'big') + except Exception as e: + raise ValueError('invalid rs bytes:{}'.format(e)) + else: + signature = SM2_RS_ASN1_Signature() + signature.setComponentByName('r', r_int) + signature.setComponentByName('s', s_int) + encoded_signature = encoder.encode(signature) + return encoded_signature + + +class EasySM2SignKey(EasySm2Key): + def __init__(self, signer_id: str = SM2_DEFAULT_ID, pem_private_key_file: str = '', password = ''): + super().__init__() + try: + self.load_sm2_private_key(pri_key_file = pem_private_key_file, password = password) + except Exception: + raise ValueError('load sm2 private key in pem format failed:{}, password:{}'.format(pem_private_key_file, password)) + else: + self._raw_sign_key = Sm2Signature(sm2_key = self._sm2_raw_key, signer_id = signer_id, sign = True) + + def UpdateData(self, data: bytes): + if not self._sm2_raw_key.has_private_key(): + raise ValueError('empty sm2 private key, cannot do sign') + self._raw_sign_key.update(data) + + def GetSignValue(self, signature_mode: SignatureMode = SignatureMode.RS_ASN1) -> bytes: + if not self._sm2_raw_key.has_private_key(): + raise ValueError('empty sm2 private key, cannot do sign') + if not isinstance(signature_mode, SignatureMode): + raise ValueError('invalid signature mode:{}'.format(signature_mode)) + ret = self._raw_sign_key.sign() + if signature_mode == SignatureMode.RS: + rs_bytes = __parse_sm2_rs_asn1_signature__(ret) + assert len(rs_bytes) == 2 + assert len(rs_bytes[0]) == 32 + assert len(rs_bytes[1]) == 32 + return rs_bytes[0] + rs_bytes[1] + return bytes(ret) + + +class EasySM2VerifyKey(EasySm2Key): + def __init__(self, signer_id: str = SM2_DEFAULT_ID, pem_public_key_file: str = ''): + super().__init__() + try: + self.load_sm2_pub_key(pem_public_key_file) + except Exception: + raise ValueError('invalid sm2 public key in pem format:{}'.format(pem_public_key_file)) + else: + self._raw_sign_key = Sm2Signature(sm2_key = self._sm2_raw_key, signer_id = signer_id, sign = False) + + def UpdateData(self, data: bytes): + if not self._sm2_raw_key.has_public_key(): + raise ValueError('empty sm2 public key, cannot do verify') + self._raw_sign_key.update(data) + + def VerifySignature(self, signature_data: bytes, signature_mode: SignatureMode = SignatureMode.RS_ASN1) -> bool: + if not self._sm2_raw_key.has_public_key(): + raise ValueError('empty sm2 public key, cannot do signature verify') + if not isinstance(signature_mode, SignatureMode): + raise ValueError('invalid signature mode:{}'.format(signature_mode)) + if signature_mode == SignatureMode.RS_ASN1: + if len(signature_data) > SM2_MAX_SIGNATURE_SIZE: + raise ValueError( + 'invalid RS_ASN1 signature size, maximum size limited to:{}, current size:{}'.format(SM2_MAX_SIGNATURE_SIZE, + len(signature_data))) + if signature_mode == SignatureMode.RS: + if len(signature_data) != 64: + raise ValueError('invalid RS mode signature, current length is:{}'.format(len(signature_data))) + signature_data = __encode_rs_to_asn1_sequence__((signature_data[:32], signature_data[32:])) + return self._raw_sign_key.verify(signature_data) diff --git a/easy_sm2_sign_test.py b/easy_sm2_sign_test.py new file mode 100644 index 0000000..7e162f7 --- /dev/null +++ b/easy_sm2_sign_test.py @@ -0,0 +1,112 @@ +import random +import unittest + +from gmssl import SM2_MAX_SIGNATURE_SIZE +from .easy_sm2_sign_key import EasySM2SignKey, EasySM2VerifyKey, SignatureMode + + +class MyTestCase(unittest.TestCase): + def test_sign_data(self): + signer_id = 'test_signer' + print('signer_id hex:', signer_id.encode('utf-8').hex()) + + test = EasySM2SignKey(signer_id = signer_id, pem_private_key_file = './easy_gmssl/test_keys/tmp_test_sm2_private.pem', + password = '123456') + plain = bytes([random.randint(0, 255) for _ in range(0, 64)]) + print('plain hex:', plain.hex()) + print('private key hex:', test.get_sm2_private_key_in_hex()) + print('public key hex:', test.get_sm2_public_key_in_hex()) + test.UpdateData(plain) + sign_value = test.GetSignValue() + print('signature hex:', sign_value.hex()) + self.assertTrue(len(sign_value) <= SM2_MAX_SIGNATURE_SIZE) + self.assertTrue(len(sign_value) >= 64) # RS_ASN1 模式下的签名不小于 64 字节 + + verify_test = EasySM2VerifyKey(signer_id = signer_id, + pem_public_key_file = './easy_gmssl/test_keys/tmp_test_sm2_public.pem') + print('verify public key:', verify_test.get_sm2_public_key_in_hex()) + verify_test.UpdateData(plain) + ret = verify_test.VerifySignature(sign_value) + self.assertTrue(ret is True) + + def test_rs_sign_mode(self): + signer_id = 'test_signer' + print('signer_id hex:', signer_id.encode('utf-8').hex()) + test = EasySM2SignKey(signer_id = signer_id, pem_private_key_file = './easy_gmssl/test_keys/tmp_test_sm2_private.pem', + password = '123456') + plain = bytes([random.randint(0, 255) for _ in range(0, 64)]) + print('plain hex:', plain.hex()) + print('private key hex:', test.get_sm2_private_key_in_hex()) + print('public key hex:', test.get_sm2_public_key_in_hex()) + test.UpdateData(plain) + + sign_value = test.GetSignValue(signature_mode = SignatureMode.RS) + print('signature hex:', sign_value.hex()) + self.assertTrue(len(sign_value) <= SM2_MAX_SIGNATURE_SIZE) + self.assertTrue(len(sign_value) == 64) + + verify_test = EasySM2VerifyKey(signer_id = signer_id, + pem_public_key_file = './easy_gmssl/test_keys/tmp_test_sm2_public.pem') + print('verify public key:', verify_test.get_sm2_public_key_in_hex()) + verify_test.UpdateData(plain) + ret = verify_test.VerifySignature(sign_value, signature_mode = SignatureMode.RS) + self.assertTrue(ret is True) + + def test_invalid_sign_mode(self): + signer_id = 'test_signer' + test = EasySM2SignKey(signer_id = signer_id, pem_private_key_file = './easy_gmssl/test_keys/tmp_test_sm2_private.pem', + password = '123456') + plain = bytes([random.randint(0, 255) for _ in range(0, 64)]) + try: + test.UpdateData(plain) + test.GetSignValue(signature_mode = 'abc') + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + def test_invalid_signature_size(self): + signer_id = 'test_signer' + plain = bytes([random.randint(0, 255) for _ in range(0, 64)]) + verify_test = EasySM2VerifyKey(signer_id = signer_id, + pem_public_key_file = './easy_gmssl/test_keys/tmp_test_sm2_public.pem') + print('verify public key:', verify_test.get_sm2_public_key_in_hex()) + verify_test.UpdateData(plain) + + # RS_ASN1 模式下的签名长度最长为 72 字节 + test_sign_value = bytes([random.randint(0, 255) for _ in range(0, SM2_MAX_SIGNATURE_SIZE + 1)]) + try: + ret = verify_test.VerifySignature(test_sign_value) + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + # RS 模式下的签名固定为 64 字节 + test_sign_value = bytes([random.randint(0, 255) for _ in range(0, 64 + 1)]) + try: + ret = verify_test.VerifySignature(test_sign_value, signature_mode = SignatureMode.RS) + except Exception as e: + self.assertTrue(True) + print(e) + else: + self.assertTrue(False) + + # def test_origin_sign_verify(self): + # sm2_key = gmssl.Sm2Key() + # sm2_key.generate_key() + # sign_key = Sm2Signature(sm2_key) + # plain = 'hello,world'.encode('utf-8') + # sign_key.update(plain) + # signature = sign_key.sign() + # + # verify_key = Sm2Signature(sm2_key, sign = False) + # verify_key.update(plain) + # ret = verify_key.verify(signature) + # self.assertTrue(ret is True) + + +if __name__ == '__main__': + unittest.main() diff --git a/easy_sm3_key.py b/easy_sm3_key.py new file mode 100644 index 0000000..db6ee2d --- /dev/null +++ b/easy_sm3_key.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-23 14:10:41 + +from __future__ import annotations + +from typing import Tuple + +from .gmssl import Sm3, SM3_DIGEST_SIZE, SM3_HMAC_MAX_KEY_SIZE, SM3_HMAC_MIN_KEY_SIZE, SM3_HMAC_SIZE, Sm3Hmac + + +class EasySM3Digest(object): + """ + EasySM3Digest 对象非线程安全,同一个对象不可并发执行写操作 + """ + + def __init__(self): + self._raw_sm3_key = Sm3() + self._data_length: int = 0 + + def UpdateData(self, data: bytes): + self._raw_sm3_key.update(data) + self._data_length += len(data) + + def Reset(self): + self._raw_sm3_key.reset() + self._data_length = 0 + + def GetHash(self) -> Tuple[bytes, int, int]: + """ + 返回:哈希十六进制串、哈希值长度、明文数据长度 + """ + hash_bytes = self._raw_sm3_key.digest() + assert len(hash_bytes) == SM3_DIGEST_SIZE + return hash_bytes, len(hash_bytes), self._data_length + + +class EasySM3Hmac(object): + def __init__(self, key: bytes): + if len(key) > SM3_HMAC_MAX_KEY_SIZE: + raise ValueError('invalid key, maximum key size limit to:{} bytes'.format(SM3_HMAC_MAX_KEY_SIZE)) + if len(key) < SM3_HMAC_MIN_KEY_SIZE: + raise ValueError('invalid key, minimum key size required at least:{} bytes'.format(SM3_HMAC_MIN_KEY_SIZE)) + self._raw_sm3_hmac = Sm3Hmac(key) + self._key: bytes = key + self._plain_length: int = 0 + + def UpdateData(self, data: bytes): + self._raw_sm3_hmac.update(data) + self._plain_length += len(data) + + def Reset(self): + self._raw_sm3_hmac.reset(self._key) + self._plain_length = 0 + + def GetHmac(self) -> Tuple[bytes, int, int]: + """ + 返回:HMAC十六进制字符串、HMAC值长度、明文数据长度 + """ + hmac_bytes = self._raw_sm3_hmac.generate_mac() + assert len(hmac_bytes) == SM3_HMAC_SIZE + return hmac_bytes, len(hmac_bytes), self._plain_length diff --git a/easy_sm3_key_test.py b/easy_sm3_key_test.py new file mode 100644 index 0000000..1ba2805 --- /dev/null +++ b/easy_sm3_key_test.py @@ -0,0 +1,77 @@ +import random +import unittest + +from .easy_sm3_key import EasySM3Digest, EasySM3Hmac + +from .gmssl import SM3_DIGEST_SIZE, SM3_HMAC_MAX_KEY_SIZE, SM3_HMAC_MIN_KEY_SIZE, SM3_HMAC_SIZE + + +class MyTestCase(unittest.TestCase): + def test_sm3_hash(self): + test = EasySM3Digest() + plain1 = 'hello,world'.encode('utf-8') + plain2 = '1234567890'.encode('utf-8') + test.UpdateData(plain1) + test.UpdateData(plain2) + hash_value, _, length = test.GetHash() + print(hash_value.hex(), length) + self.assertTrue(length == len(plain1) + len(plain2)) + self.assertTrue(len(hash_value) == SM3_DIGEST_SIZE) + + test.Reset() + plain3 = (plain1 + plain2) + print('plain hex:', plain3.hex()) + test.UpdateData(plain3) + hash_value_2, hash_len, length2 = test.GetHash() + print('hash value:', hash_value_2.hex()) + print('hash value length in bytes:', hash_len) + self.assertTrue(length2 == len(plain1) + len(plain2)) + self.assertTrue(hash_len == SM3_DIGEST_SIZE) + self.assertTrue(len(hash_value_2) == SM3_DIGEST_SIZE) + self.assertTrue(hash_value_2 == hash_value) + + def test_sm3_hmac_key(self): + lt_min_key_size = bytes([random.randint(0, 255) for _ in range(0, SM3_HMAC_MIN_KEY_SIZE - 1)]) + print('lt_min_key_size', len(lt_min_key_size)) + gt_max_key_size = bytes([random.randint(0, 255) for _ in range(0, SM3_HMAC_MAX_KEY_SIZE + 1)]) + print('gt_max_key_size', len(gt_max_key_size)) + eq_min_key_size = bytes([random.randint(0, 255) for _ in range(0, SM3_HMAC_MIN_KEY_SIZE)]) + print('eq_min_key_size', len(eq_min_key_size)) + eq_max_key_size = bytes([random.randint(0, 255) for _ in range(0, SM3_HMAC_MAX_KEY_SIZE)]) + print('eq_max_key_size', len(eq_max_key_size)) + + try: + EasySM3Hmac(lt_min_key_size) + except Exception as e: + self.assertTrue(True) + print(e) + + try: + EasySM3Hmac(gt_max_key_size) + except Exception as e: + self.assertTrue(True) + print(e) + + try: + EasySM3Hmac(eq_min_key_size) + EasySM3Hmac(eq_max_key_size) + except Exception: + self.assertTrue(False) + else: + self.assertTrue(True) + + def test_sm3_hmac_value(self): + plain = 'hello,world'.encode('utf-8') + print('plain hex:', plain.hex()) + key = bytes([random.randint(0, 255) for _ in range(0, SM3_HMAC_MAX_KEY_SIZE)]) + print('key hex:', key.hex()) + test = EasySM3Hmac(key) + test.UpdateData(plain) + hmac_hex, hmac_len, plain_len = test.GetHmac() + print('hmac value:', hmac_hex.hex(), 'hmac len:', hmac_len, 'plain len:', plain_len) + self.assertTrue(hmac_len == SM3_HMAC_SIZE) + self.assertTrue(len(plain) == plain_len) + + +if __name__ == '__main__': + unittest.main() diff --git a/easy_sm4_key.py b/easy_sm4_key.py new file mode 100644 index 0000000..e6791c9 --- /dev/null +++ b/easy_sm4_key.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-23 17:23:36 + +from __future__ import annotations + +from enum import Enum + +from .gmssl import SM4_BLOCK_SIZE, SM4_CBC_IV_SIZE, SM4_GCM_DEFAULT_TAG_SIZE, Sm4Cbc, Sm4Gcm + + +class EncryptionMode(Enum): + CBCMode = 'CBC' + GCMMode = 'GCM' + CTRMode = 'CTR' + + +class EasySm4CBC(object): + def __init__(self, key: bytes, iv: bytes, do_encrypt: bool = True): + """ + key 和 iv 的长度必须为 16 字节 + """ + if len(key) != SM4_BLOCK_SIZE: + raise ValueError('invalid key length:{}, required:{}'.format(len(key), SM4_BLOCK_SIZE)) + if len(iv) != SM4_CBC_IV_SIZE: + raise ValueError('invalid iv length:{}, required:{}'.format(len(key), SM4_CBC_IV_SIZE)) + self._sm4_cbc_ = Sm4Cbc(key, iv, do_encrypt) + self._do_encryption = do_encrypt + if self._do_encryption: + self._action_ = 'sm4 cbc encryption' + else: + self._action_ = 'sm4 cbc decryption' + + def Update(self, data: bytes) -> bytes: + """ + 返回的 bytes 数据需要累加 + """ + try: + ret = self._sm4_cbc_.update(data) + except Exception as e: + raise ValueError('{} failed:{}'.format(self._action_, e)) + else: + return bytes(ret) + + def Finish(self) -> bytes: + """ + 返回的 bytes 数据需要累加作为最终的密文或者明文 + """ + try: + ret = self._sm4_cbc_.finish() + except Exception as e: + raise ValueError('{} failed:{}'.format(self._action_, e)) + return bytes(ret) + + +class EasySm4GCM(object): + def __init__(self, key: bytes, iv: bytes, aad: bytes = b'', tag_len: int = SM4_GCM_DEFAULT_TAG_SIZE, do_encrypt: bool = True): + """ + key 和 iv 的长度必须为 16 字节 + tag_len 值最小为 8,最长为 16 + """ + if len(key) != SM4_BLOCK_SIZE: + raise ValueError('invalid key length:{}, required:{}'.format(len(key), SM4_BLOCK_SIZE)) + if len(iv) != SM4_CBC_IV_SIZE: + raise ValueError('invalid iv length:{}, required:{}'.format(len(key), SM4_CBC_IV_SIZE)) + if tag_len < SM4_GCM_DEFAULT_TAG_SIZE / 2 or tag_len > SM4_GCM_DEFAULT_TAG_SIZE: + raise ValueError( + 'invalid tag_len:{}, required:[{},{}]'.format( + tag_len, int(SM4_GCM_DEFAULT_TAG_SIZE / 2), SM4_GCM_DEFAULT_TAG_SIZE)) + self._sm4_gcm_ = Sm4Gcm(key, iv, aad, tag_len, do_encrypt) + self._do_encryption = do_encrypt + if self._do_encryption: + self._action_ = 'sm4 gcm encryption' + else: + self._action_ = 'sm4 gcm decryption' + + def Update(self, data: bytes) -> bytes: + """ + 返回的 bytes 数据需要累加 + """ + try: + ret = self._sm4_gcm_.update(data) + except Exception as e: + raise ValueError('{} failed:{}'.format(self._action_, e)) + else: + return bytes(ret) + + def Finish(self) -> bytes: + """ + 返回的 bytes 数据需要累加作为最终的密文或者明文 + """ + try: + ret = self._sm4_gcm_.finish() + except Exception as e: + raise ValueError('{} failed:{}'.format(self._action_, e)) + return bytes(ret) diff --git a/easy_sm4_test.py b/easy_sm4_test.py new file mode 100644 index 0000000..59961ff --- /dev/null +++ b/easy_sm4_test.py @@ -0,0 +1,86 @@ +import unittest + +from .easy_sm4_key import EasySm4CBC, EasySm4GCM +from .gmssl import SM4_BLOCK_SIZE, SM4_CBC_IV_SIZE, SM4_GCM_DEFAULT_TAG_SIZE, Sm4Cbc + + +class MyTestCase(unittest.TestCase): + def test_sm4_cbc(self): + key = 'x' * SM4_BLOCK_SIZE + iv = 'y' * SM4_CBC_IV_SIZE + test_enc = Sm4Cbc(key.encode('utf-8'), iv.encode('utf-8'), True) + plain1 = 'hello,world' + plain2 = '1234567890' + cipher1 = test_enc.update(plain1.encode('utf-8')) + cipher2 = test_enc.update(plain2.encode('utf-8')) + ciphers = cipher1 + cipher2 + test_enc.finish() + self.assertTrue(len(ciphers) % SM4_BLOCK_SIZE == 0) + + test_dec = Sm4Cbc(key.encode('utf-8'), iv.encode('utf-8'), False) + decrypted_plain1 = test_dec.update(ciphers) + decrypted_plain = decrypted_plain1 + test_dec.finish() + self.assertEqual(decrypted_plain, (plain1 + plain2).encode('utf-8')) + + def test_sm4_cbc_invalid_key_len(self): + key = 'x' * (SM4_BLOCK_SIZE - 1) + iv = 'y' * SM4_CBC_IV_SIZE + try: + test_enc = Sm4Cbc(key.encode('utf-8'), iv.encode('utf-8'), True) + except Exception as e: + print(e) + self.assertTrue(True) + else: + self.assertTrue(False) + + def test_sm4_cbc_invalid_iv_len(self): + key = 'x' * SM4_BLOCK_SIZE + iv = 'y' * (SM4_CBC_IV_SIZE - 1) + try: + test_enc = Sm4Cbc(key.encode('utf-8'), iv.encode('utf-8'), True) + except Exception as e: + print(e) + self.assertTrue(True) + else: + self.assertTrue(False) + + def test_easy_sm4_cbc(self): + key = 'x' * SM4_BLOCK_SIZE + iv = 'y' * SM4_CBC_IV_SIZE + test_cbc_enc = EasySm4CBC(key.encode('utf-8'), iv.encode('utf-8'), True) + plain1 = 'hello,world' + plain2 = '1234567890' + cipher1 = test_cbc_enc.Update(plain1.encode('utf-8')) + cipher2 = test_cbc_enc.Update(plain2.encode('utf-8')) + ciphers = cipher1 + cipher2 + test_cbc_enc.Finish() + self.assertTrue(len(ciphers) % SM4_BLOCK_SIZE == 0) + print('ciphers len:', len(ciphers)) + + test_dec = EasySm4CBC(key.encode('utf-8'), iv.encode('utf-8'), False) + decrypted_plain1 = test_dec.Update(ciphers) + decrypted_plain = decrypted_plain1 + test_dec.Finish() + self.assertEqual(decrypted_plain, (plain1 + plain2).encode('utf-8')) + + def test_easy_sm4_gcm(self): + key = 'x' * SM4_BLOCK_SIZE + iv = 'y' * SM4_CBC_IV_SIZE + aad = 'a' * (SM4_BLOCK_SIZE + SM4_CBC_IV_SIZE) + tag_len = int(SM4_GCM_DEFAULT_TAG_SIZE / 2) + test_gcm_enc = EasySm4GCM(key.encode('utf-8'), iv.encode('utf-8'), aad, tag_len, True) + plain1 = 'hello,world' + plain2 = '1234567890' + cipher1 = test_gcm_enc.Update(plain1.encode('utf-8')) + cipher2 = test_gcm_enc.Update(plain2.encode('utf-8')) + ciphers = cipher1 + cipher2 + test_gcm_enc.Finish() + # GCM模式下的密文长度与明文长度等长 + # 返回的密文中包含了 tag 长度 + self.assertTrue((len(ciphers) - tag_len) == len(plain1 + plain2)) + print('ciphers len:', len(ciphers), 'tag_len=', tag_len, 'plain len:', len(plain1 + plain2)) + + test_dec = EasySm4GCM(key.encode('utf-8'), iv.encode('utf-8'), aad, tag_len, False) + decrypted_plain1 = test_dec.Update(ciphers) + decrypted_plain = decrypted_plain1 + test_dec.Finish() + self.assertEqual(decrypted_plain, (plain1 + plain2).encode('utf-8')) + + +if __name__ == '__main__': + unittest.main() diff --git a/easy_zuc.py b/easy_zuc.py new file mode 100644 index 0000000..6639b1f --- /dev/null +++ b/easy_zuc.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# @Time: 2024-12-23 18:59:33 + +from __future__ import annotations + +from .gmssl import Zuc, ZUC_IV_SIZE, ZUC_KEY_SIZE + + +class EasyZuc(object): + def __init__(self, key: bytes, iv: bytes): + """ + 祖冲之密码算法(ZU Cipher, ZUC)是一种序列密码,密钥和IV长度均为16字节。 + 作为序列密码ZUC可以加密可变长度的输入数据,并且输出的密文数据长度和输入数据等长 + 因此适合不允许密文膨胀的应用场景 + """ + if len(key) != ZUC_KEY_SIZE: + raise ValueError('invalid key size:{}, required:{}'.format(len(key), ZUC_KEY_SIZE)) + if len(iv) != ZUC_IV_SIZE: + raise ValueError('invalid iv size:{}, required:{}'.format(len(iv), ZUC_IV_SIZE)) + self._zuc_ = Zuc(key, iv) + + def Update(self, data: bytes): + try: + ret = bytes(self._zuc_.update(data)) + except Exception as e: + raise ValueError('zuc process error:{}'.format(e)) + else: + return bytes(ret) + + def Finish(self): + try: + ret = bytes(self._zuc_.finish()) + except Exception as e: + raise ValueError('zuc process error:{}'.format(e)) + else: + return bytes(ret) diff --git a/easy_zuc_test.py b/easy_zuc_test.py new file mode 100644 index 0000000..bc3ca52 --- /dev/null +++ b/easy_zuc_test.py @@ -0,0 +1,32 @@ +import unittest + +from .easy_zuc import EasyZuc + +from .easy_random_data import EasyRandomData +from .gmssl import ZUC_IV_SIZE, ZUC_KEY_SIZE + + +class MyTestCase(unittest.TestCase): + def test_zuc(self): + key = EasyRandomData().GetRandomData(ZUC_KEY_SIZE) + iv = EasyRandomData().GetRandomData(ZUC_IV_SIZE) + test = EasyZuc(key, iv) + plain1 = 'hello,world'.encode('utf-8') + cipher1 = test.Update(plain1) + plain2 = '1234567890'.encode('utf-8') + cipher2 = test.Update(plain2) + cipher3 = test.Finish() + + self.assertTrue(len(cipher1 + cipher2 + cipher3) == len(plain1 + plain2)) + + test2 = EasyZuc(key, iv) + ret1 = test2.Update(cipher1) + ret2 = test2.Update(cipher2) + ret3 = test2.Update(cipher3) + ret4 = test2.Finish() + + self.assertTrue(ret1 + ret2 + ret3 + ret4 == plain1 + plain2) + + +if __name__ == '__main__': + unittest.main() diff --git a/examples/sm2_cert.py b/examples/sm2_cert.py deleted file mode 100644 index 1352e6e..0000000 --- a/examples/sm2_cert.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -cert_txt = '''\ ------BEGIN CERTIFICATE----- -MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG -EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw -MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO -UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE -MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT -V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti -W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ -MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b -53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI -pDoiVhsLwg== ------END CERTIFICATE-----''' -with open('ROOTCA.pem', 'w') as file: - file.write(cert_txt) - file.close() - -cert = Sm2Certificate() -cert.import_pem('ROOTCA.pem') - -print("Certificate") - -serial = cert.get_serial_number() -print("Serial :", serial.hex()) - -validity = cert.get_validity() -print("Validity.notBefore :", validity.not_before) -print("Validity.notAfter :", validity.not_after) - -issuer = cert.get_issuer() -print("Issuer :") -for key in issuer: - if key == 'raw_data': - print(" ", key, ":", issuer[key].hex()) - else: - print(" ", key, ":", issuer[key]) - - -subject = cert.get_subject() -print("Subject :") -for key in subject: - if key == 'raw_data': - print(" ", key, ":", subject[key].hex()) - else: - print(" ", key, ":", subject[key]) - -public_key = cert.get_subject_public_key() -public_key.export_public_key_info_pem('subject_public_key.pem') - -file = open('subject_public_key.pem',mode='r') -fulltext = file.read() -file.close() -print("Subject Public Key:") -print(fulltext) - - diff --git a/examples/sm2_enc.py b/examples/sm2_enc.py deleted file mode 100644 index b4f7ff1..0000000 --- a/examples/sm2_enc.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -# run sm2_key.py first - - -print("SM2_MIN_PLAINTEXT_SIZE =", SM2_MIN_PLAINTEXT_SIZE) -print("SM2_MAX_PLAINTEXT_SIZE =", SM2_MAX_PLAINTEXT_SIZE) -print("SM2_MIN_CIPHERTEXT_SIZE =", SM2_MIN_CIPHERTEXT_SIZE) -print("SM2_MAX_CIPHERTEXT_SIZE =", SM2_MAX_CIPHERTEXT_SIZE) -print("") - -# Sender - -public_key = Sm2Key() -public_key.import_public_key_info_pem('sm2pub.pem') - -plaintext = rand_bytes(SM4_KEY_SIZE + SM3_HMAC_MIN_KEY_SIZE) -ciphertext = public_key.encrypt(plaintext) - - -# Receiver - -private_key = Sm2Key() -private_key.import_encrypted_private_key_info_pem('sm2.pem', 'password') - -decrypted = private_key.decrypt(ciphertext) - -print("plaintext :", plaintext.hex()) -print("ciphertext :", ciphertext.hex()) -print("decrypted :", decrypted.hex()) - diff --git a/examples/sm2_key.py b/examples/sm2_key.py deleted file mode 100644 index 625182e..0000000 --- a/examples/sm2_key.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -sm2 = Sm2Key() -sm2.generate_key() - -sm2.export_encrypted_private_key_info_pem('sm2.pem', 'password') -print('export private key to encrypted file sm2.pem') - -sm2.export_public_key_info_pem('sm2pub.pem') -print('export public key to file sm2pub.pem') - -private_key = Sm2Key() -private_key.import_encrypted_private_key_info_pem('sm2.pem', 'password') -print("private key has private key :", private_key.has_private_key()) -print("private key has public key :", private_key.has_public_key()) - -public_key = Sm2Key() -public_key.import_public_key_info_pem('sm2pub.pem') -print("public key has private key :", public_key.has_private_key()) -print("public key has public key :", public_key.has_public_key()) - diff --git a/examples/sm2_sign.py b/examples/sm2_sign.py deleted file mode 100644 index 9e3a12b..0000000 --- a/examples/sm2_sign.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -# run sm2_key.py first - - -print("SM2_DEFAULT_ID =", SM2_DEFAULT_ID) -print("SM2_MAX_SIGNATURE_SIZE =", SM2_MAX_SIGNATURE_SIZE) -print("") - -# Signer - -private_key = Sm2Key() -private_key.import_encrypted_private_key_info_pem('sm2.pem', 'password') - -z = private_key.compute_z(SM2_DEFAULT_ID) - -sm3 = Sm3() -sm3.update(z) -sm3.update(b'abc') -dgst = sm3.digest() - -sig = private_key.sign(dgst) -print("signature1 :", sig.hex()) - -signer = Sm2Signature(private_key, SM2_DEFAULT_ID, DO_SIGN) -signer.update(b'abc') -sig2 = signer.sign() -print("signature2 :", sig2.hex()) - -# Verifier - -public_key = Sm2Key() -public_key.import_public_key_info_pem('sm2pub.pem') - -z = public_key.compute_z(SM2_DEFAULT_ID) - -sm3 = Sm3() -sm3.update(z) -sm3.update(b'abc') -dgst = sm3.digest() - -ret = public_key.verify(dgst, sig) -print("Verify signature1 success :", ret) - -ret = public_key.verify(dgst, sig2) -print("Verify signature2 success :", ret) - -verifier = Sm2Signature(public_key, SM2_DEFAULT_ID, DO_VERIFY) -verifier.update(b'abc') -ret = verifier.verify(sig) -print("Verify signature1 success :", ret) - -verifier = Sm2Signature(public_key, SM2_DEFAULT_ID, DO_VERIFY) -verifier.update(b'abc') -ret = verifier.verify(sig2) -print("Verify signature2 success :", ret) - - diff --git a/examples/sm3.py b/examples/sm3.py deleted file mode 100644 index d16c104..0000000 --- a/examples/sm3.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -print("SM3_DIGEST_SIZE =", SM3_DIGEST_SIZE) - -sm3 = Sm3() -sm3.update(b'abc') -dgst = sm3.digest() -print("sm3('abc') : " + dgst.hex()) - -sm3.reset() -for i in range(16): - sm3.update(b'abcd') -dgst = sm3.digest() -print("sm3('abcd'*16) : " + dgst.hex()) - diff --git a/examples/sm3_hmac.py b/examples/sm3_hmac.py deleted file mode 100644 index 9315bab..0000000 --- a/examples/sm3_hmac.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -print("SM3_HMAC_MIN_KEY_SIZE =", SM3_HMAC_MIN_KEY_SIZE) -print("SM3_HMAC_MAX_KEY_SIZE =", SM3_HMAC_MAX_KEY_SIZE) -print("SM3_HMAC_SIZE =", SM3_HMAC_SIZE) - -key = rand_bytes(SM3_HMAC_MIN_KEY_SIZE) - -sm3_hmac = Sm3Hmac(key) -sm3_hmac.update(b'abc') -mac = sm3_hmac.generate_mac() -print("key = " + key.hex()) -print("sm3_hmac('abc') : " + mac.hex()) - -sm3_hmac.reset(key) -for i in range(16): - sm3_hmac.update(b'abcd') -mac = sm3_hmac.generate_mac() -print("sm3_hmac('abcd'*16) : " + mac.hex()) - diff --git a/examples/sm3_pbkdf2.py b/examples/sm3_pbkdf2.py deleted file mode 100644 index 40aabb3..0000000 --- a/examples/sm3_pbkdf2.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - - -from gmssl import * - - -print("SM3_PBKDF2_MIN_ITER =", SM3_PBKDF2_MIN_ITER) -print("SM3_PBKDF2_MAX_ITER =", SM3_PBKDF2_MAX_ITER) -print("SM3_PBKDF2_MAX_SALT_SIZE =", SM3_PBKDF2_MAX_SALT_SIZE) -print("SM3_PBKDF2_DEFAULT_SALT_SIZE =", SM3_PBKDF2_DEFAULT_SALT_SIZE) -print("SM3_PBKDF2_MAX_KEY_SIZE =", SM3_PBKDF2_MAX_KEY_SIZE) -print("") - -passwd = "Password" -salt = rand_bytes(SM3_PBKDF2_DEFAULT_SALT_SIZE) -iterator = SM3_PBKDF2_MIN_ITER -keylen = 32 - -key = sm3_pbkdf2(passwd, salt, iterator, keylen) -print("Password :", passwd) -print("Salt :", salt.hex()) -print("Iterator :", iterator) -print("Keylen :", keylen) -print("sm2_pbkdf2(Password, Salt, Iter, Keylen) :", key.hex()) - diff --git a/examples/sm4.py b/examples/sm4.py deleted file mode 100644 index 08458c3..0000000 --- a/examples/sm4.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -print("SM4_KEY_SIZE =", SM4_KEY_SIZE) -print("SM4_BLOCK_SIZE =", SM4_BLOCK_SIZE) -print("") - -key = rand_bytes(SM4_KEY_SIZE) -plaintext = rand_bytes(SM4_BLOCK_SIZE) - -sm4_enc = Sm4(key, DO_ENCRYPT) -ciphertext = sm4_enc.encrypt(plaintext) - -sm4_dec = Sm4(key, DO_DECRYPT) -decrypted = sm4_dec.encrypt(ciphertext) - -print("key =", key.hex()) -print("plaintext =", plaintext.hex()) -print("ciphertext = ", ciphertext.hex()) -print("decrypted =", decrypted.hex()) - diff --git a/examples/sm4_cbc.py b/examples/sm4_cbc.py deleted file mode 100644 index 60ec98e..0000000 --- a/examples/sm4_cbc.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -print("SM4_KEY_SIZE =", SM4_KEY_SIZE) -print("SM4_CBC_IV_SIZE =", SM4_CBC_IV_SIZE) -print("") - -key = rand_bytes(SM4_KEY_SIZE) -iv = rand_bytes(SM4_CBC_IV_SIZE) -plaintext = b'abc' - -sm4_enc = Sm4Cbc(key, iv, DO_ENCRYPT) -ciphertext = sm4_enc.update(plaintext) -ciphertext += sm4_enc.finish() - -sm4_dec = Sm4Cbc(key, iv, DO_DECRYPT) -decrypted = sm4_dec.update(ciphertext) -decrypted += sm4_dec.finish() - -print("key =", key.hex()) -print("iv =", iv.hex()) -print("plaintext =", plaintext.hex()) -print("ciphertext = ", ciphertext.hex()) -print("decrypted =", decrypted.hex()) - diff --git a/examples/sm4_ctr.py b/examples/sm4_ctr.py deleted file mode 100644 index 06fc8a2..0000000 --- a/examples/sm4_ctr.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -print("SM4_KEY_SIZE =", SM4_KEY_SIZE) -print("SM4_CTR_IV_SIZE =", SM4_CTR_IV_SIZE) -print("") - -key = rand_bytes(SM4_KEY_SIZE) -iv = rand_bytes(SM4_CTR_IV_SIZE) -plaintext = b'abc' - -sm4_enc = Sm4Ctr(key, iv) -ciphertext = sm4_enc.update(plaintext) -ciphertext += sm4_enc.finish() - -sm4_dec = Sm4Ctr(key, iv) -decrypted = sm4_dec.update(ciphertext) -decrypted += sm4_dec.finish() - -print("key =", key.hex()) -print("iv =", iv.hex()) -print("plaintext =", plaintext.hex()) -print("ciphertext = ", ciphertext.hex()) -print("decrypted =", decrypted.hex()) - diff --git a/examples/sm4_gcm.py b/examples/sm4_gcm.py deleted file mode 100644 index 30a1213..0000000 --- a/examples/sm4_gcm.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - - -print("SM4_GCM_MIN_IV_SIZE =", SM4_GCM_MIN_IV_SIZE) -print("SM4_GCM_MAX_IV_SIZE =", SM4_GCM_MAX_IV_SIZE) -print("SM4_GCM_DEFAULT_IV_SIZE =", SM4_GCM_DEFAULT_IV_SIZE) -print("SM4_GCM_DEFAULT_TAG_SIZE =", SM4_GCM_DEFAULT_TAG_SIZE) -print("SM4_GCM_MAX_TAG_SIZE =", SM4_GCM_MAX_TAG_SIZE) -print("") - - -key = rand_bytes(SM4_KEY_SIZE) -iv = rand_bytes(SM4_GCM_DEFAULT_IV_SIZE) -aad = b'Additional auth-data' -plaintext = b'abc' -taglen = SM4_GCM_DEFAULT_TAG_SIZE - -sm4_enc = Sm4Gcm(key, iv, aad, taglen, DO_ENCRYPT) -ciphertext = sm4_enc.update(plaintext) -ciphertext += sm4_enc.finish() - -sm4_dec = Sm4Gcm(key, iv, aad, taglen, DO_DECRYPT) -decrypted = sm4_dec.update(ciphertext) -decrypted += sm4_dec.finish() - -print("key =", key.hex()) -print("iv =", iv.hex()) -print("aad =", aad.hex()) -print("taglen =", taglen) -print("plaintext =", plaintext.hex()) -print("ciphertext = ", ciphertext.hex()) -print("decrypted =", decrypted.hex()) - diff --git a/examples/sm9_enc.py b/examples/sm9_enc.py deleted file mode 100644 index 7e16526..0000000 --- a/examples/sm9_enc.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - - -print("SM9_MAX_ID_SIZE =", SM9_MAX_ID_SIZE) -print("SM9_MAX_PLAINTEXT_SIZE =", SM9_MAX_PLAINTEXT_SIZE) -print("SM9_MAX_CIPHERTEXT_SIZE =", SM9_MAX_CIPHERTEXT_SIZE) -print("") - -master_key = Sm9EncMasterKey() -master_key.generate_master_key() -print("SM9 master key generated") - -master_key.export_encrypted_master_key_info_pem('enc_msk.pem', 'password') -master_key.export_public_master_key_pem('enc_mpk.pem') -print("Export master key and public master key") - -# Encrypt -master_pub = Sm9EncMasterKey() -master_pub.import_public_master_key_pem('enc_mpk.pem') - -plaintext = rand_bytes(SM4_KEY_SIZE + SM3_HMAC_MIN_KEY_SIZE) - -receiver_id = 'Alice' - -ciphertext = master_pub.encrypt(plaintext, receiver_id) - -# Decrypt -master = Sm9EncMasterKey() -master.import_encrypted_master_key_info_pem('enc_msk.pem', 'password') - -receiver_key = master.extract_key(receiver_id) - -decrypted = receiver_key.decrypt(ciphertext) - -print("receiver :", receiver_id) -print("plaintext :", plaintext.hex()) -print("ciphertext:", ciphertext.hex()) -print("decrypted :", decrypted.hex()) - diff --git a/examples/sm9_sign.py b/examples/sm9_sign.py deleted file mode 100644 index 8728ce7..0000000 --- a/examples/sm9_sign.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - - -print("SM9_MAX_ID_SIZE =", SM9_MAX_ID_SIZE) -print("SM9_SIGNATURE_SIZE =", SM9_SIGNATURE_SIZE) -print("") - - -master_key = Sm9SignMasterKey() -master_key.generate_master_key() -print("SM9 master key generated") - -master_key.export_encrypted_master_key_info_pem('sign_msk.pem', 'password') -master_key.export_public_master_key_pem('sign_mpk.pem') -print("Export master key and public master key") - - -master = Sm9SignMasterKey() -master.import_encrypted_master_key_info_pem('sign_msk.pem', 'password') - -signer_id = 'Alice' -key = master.extract_key(signer_id) - -message = "Message to be signed" - -sign = Sm9Signature(DO_SIGN) -sign.update(message.encode('utf-8')) -sig = sign.sign(key) - - -master_pub = Sm9SignMasterKey() -master_pub.import_public_master_key_pem('sign_mpk.pem') - -verify = Sm9Signature(DO_VERIFY) -verify.update(message.encode('utf-8')) -ret = verify.verify(sig, master_pub, signer_id) - -print("signer :", signer_id) -print("message :", message) -print("signature :", sig.hex()) -print("verify success :", ret) - diff --git a/examples/zuc.py b/examples/zuc.py deleted file mode 100644 index 5d062fe..0000000 --- a/examples/zuc.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - -from gmssl import * - -print("ZUC_KEY_SIZE =", ZUC_KEY_SIZE) -print("ZUC_IV_SIZE =", ZUC_IV_SIZE) -print("") - -key = rand_bytes(ZUC_KEY_SIZE) -iv = rand_bytes(ZUC_IV_SIZE) -plaintext = b'abc' - -zuc_enc = Zuc(key, iv) -ciphertext = zuc_enc.update(plaintext) -ciphertext += zuc_enc.finish() - -zuc_dec = Zuc(key, iv) -decrypted = zuc_dec.update(ciphertext) -decrypted += zuc_dec.finish() - -print("key =", key.hex()) -print("iv =", iv.hex()) -print("plaintext =", plaintext.hex()) -print("ciphertext = ", ciphertext.hex()) -print("decrypted =", decrypted.hex()) - diff --git a/gmssl.py b/gmssl.py index d9a786d..c4c7ccf 100755 --- a/gmssl.py +++ b/gmssl.py @@ -5,313 +5,327 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# GmSSL-Python - Python binding of the GmSSL library with `ctypes` +# easy_gmssl - Python binding of the GmSSL library with `ctypes` -from ctypes import * -from ctypes.util import find_library import datetime +import os import sys +from ctypes import * +from ctypes.util import find_library + +try: + home_directory = os.path.expanduser('~') + if not home_directory.endswith('/'): + home_directory += '/' + ext_dir = home_directory + ".gmssl_3.1.1_install/" + gmssl = cdll.LoadLibrary(ext_dir + "lib/libgmssl.so.3.1") +except Exception: + try: + gmssl = cdll.LoadLibrary(find_library("gmssl")) + except Exception: + raise ValueError('Install GmSSL dynamic library from https://github.com/guanzhi/GmSSL') + finally: + pass +finally: + pass -if find_library('gmssl') == None: - raise ValueError('Install GmSSL dynamic library from https://github.com/guanzhi/GmSSL') -gmssl = cdll.LoadLibrary(find_library("gmssl")) if gmssl.gmssl_version_num() < 30101: - raise ValueError('GmSSL version < 3.1.1') + raise ValueError('GmSSL version < 3.1.1') if sys.platform == 'win32': - libc = cdll.LoadLibrary(find_library('msvcrt')) + libc = cdll.LoadLibrary(find_library('msvcrt')) else: - libc = cdll.LoadLibrary(find_library('c')) + libc = cdll.LoadLibrary(find_library('c')) class NativeError(Exception): - ''' - GmSSL libraray inner error - ''' + ''' + GmSSL libraray inner error + ''' + class StateError(Exception): - ''' - Crypto state error - ''' + ''' + Crypto state error + ''' + + +GMSSL_PYTHON_VERSION = "binding-for-cmd-v1" -GMSSL_PYTHON_VERSION = "2.2.2" def gmssl_library_version_num(): - return gmssl.gmssl_version_num() + return gmssl.gmssl_version_num() + def gmssl_library_version_str(): - gmssl.gmssl_version_str.restype = c_char_p - return gmssl.gmssl_version_str().decode('ascii') + gmssl.gmssl_version_str.restype = c_char_p + return gmssl.gmssl_version_str().decode('ascii') + GMSSL_LIBRARY_VERSION = gmssl_library_version_str() def rand_bytes(size): - buf = create_string_buffer(size) - gmssl.rand_bytes(buf, c_size_t(size)) - return buf.raw - + buf = create_string_buffer(size) + gmssl.rand_bytes(buf, c_size_t(size)) + return buf.raw SM3_DIGEST_SIZE = 32 _SM3_STATE_WORDS = 8 _SM3_BLOCK_SIZE = 64 -class Sm3(Structure): - _fields_ = [ - ("dgst", c_uint32 * _SM3_STATE_WORDS), - ("nblocks", c_uint64), - ("block", c_uint8 * _SM3_BLOCK_SIZE), - ("num", c_size_t) - ] +class Sm3(Structure): + _fields_ = [ + ("dgst", c_uint32 * _SM3_STATE_WORDS), + ("nblocks", c_uint64), + ("block", c_uint8 * _SM3_BLOCK_SIZE), + ("num", c_size_t) + ] - def __init__(self): - gmssl.sm3_init(byref(self)) + def __init__(self): + gmssl.sm3_init(byref(self)) - def reset(self): - gmssl.sm3_init(byref(self)) + def reset(self): + gmssl.sm3_init(byref(self)) - def update(self, data): - gmssl.sm3_update(byref(self), data, c_size_t(len(data))) + def update(self, data): + gmssl.sm3_update(byref(self), data, c_size_t(len(data))) - def digest(self): - dgst = create_string_buffer(SM3_DIGEST_SIZE) - gmssl.sm3_finish(byref(self), dgst) - return dgst.raw + def digest(self): + dgst = create_string_buffer(SM3_DIGEST_SIZE) + gmssl.sm3_finish(byref(self), dgst) + return dgst.raw SM3_HMAC_MIN_KEY_SIZE = 16 SM3_HMAC_MAX_KEY_SIZE = 64 SM3_HMAC_SIZE = SM3_DIGEST_SIZE -class Sm3Hmac(Structure): - _fields_ = [ - ("sm3_ctx", Sm3), - ("key", c_uint8 * _SM3_BLOCK_SIZE) - ] +class Sm3Hmac(Structure): + _fields_ = [ + ("sm3_ctx", Sm3), + ("key", c_uint8 * _SM3_BLOCK_SIZE) + ] - def __init__(self, key): - if len(key) < SM3_HMAC_MIN_KEY_SIZE or len(key) > SM3_HMAC_MAX_KEY_SIZE: - raise ValueError('Invalid SM3 HMAC key length') - gmssl.sm3_hmac_init(byref(self), key, c_size_t(len(key))) + def __init__(self, key): + if len(key) < SM3_HMAC_MIN_KEY_SIZE or len(key) > SM3_HMAC_MAX_KEY_SIZE: + raise ValueError('Invalid SM3 HMAC key length') + gmssl.sm3_hmac_init(byref(self), key, c_size_t(len(key))) - def reset(self, key): - if len(key) < SM3_HMAC_MIN_KEY_SIZE or len(key) > SM3_HMAC_MAX_KEY_SIZE: - raise ValueError('Invalid SM3 HMAC key length') - gmssl.sm3_hmac_init(byref(self), key, c_size_t(len(key))) + def reset(self, key): + if len(key) < SM3_HMAC_MIN_KEY_SIZE or len(key) > SM3_HMAC_MAX_KEY_SIZE: + raise ValueError('Invalid SM3 HMAC key length') + gmssl.sm3_hmac_init(byref(self), key, c_size_t(len(key))) - def update(self, data): - gmssl.sm3_hmac_update(byref(self), data, c_size_t(len(data))) + def update(self, data): + gmssl.sm3_hmac_update(byref(self), data, c_size_t(len(data))) - def generate_mac(self): - hmac = create_string_buffer(SM3_HMAC_SIZE) - gmssl.sm3_hmac_finish(byref(self), hmac) - return hmac.raw + def generate_mac(self): + hmac = create_string_buffer(SM3_HMAC_SIZE) + gmssl.sm3_hmac_finish(byref(self), hmac) + return hmac.raw +SM3_PBKDF2_MIN_ITER = 10000 # from +SM3_PBKDF2_MAX_ITER = 16777216 # 2^24 +SM3_PBKDF2_MAX_SALT_SIZE = 64 # from +SM3_PBKDF2_DEFAULT_SALT_SIZE = 8 # from +SM3_PBKDF2_MAX_KEY_SIZE = 256 # from gmssljni.c:sm3_pbkdf2():sizeof(keybuf) -SM3_PBKDF2_MIN_ITER = 10000 # from -SM3_PBKDF2_MAX_ITER = 16777216 # 2^24 -SM3_PBKDF2_MAX_SALT_SIZE = 64 # from -SM3_PBKDF2_DEFAULT_SALT_SIZE = 8 # from -SM3_PBKDF2_MAX_KEY_SIZE = 256 # from gmssljni.c:sm3_pbkdf2():sizeof(keybuf) def sm3_pbkdf2(passwd, salt, iterator, keylen): + if len(salt) > SM3_PBKDF2_MAX_SALT_SIZE: + raise ValueError('Invalid salt length') - if len(salt) > SM3_PBKDF2_MAX_SALT_SIZE: - raise ValueError('Invalid salt length') + if iterator < SM3_PBKDF2_MIN_ITER or iterator > SM3_PBKDF2_MAX_ITER: + raise ValueError('Invalid iterator value') - if iterator < SM3_PBKDF2_MIN_ITER or iterator > SM3_PBKDF2_MAX_ITER: - raise ValueError('Invalid iterator value') + if keylen > SM3_PBKDF2_MAX_KEY_SIZE: + raise ValueError('Invalid key length') - if keylen > SM3_PBKDF2_MAX_KEY_SIZE: - raise ValueError('Invalid key length') + passwd = passwd.encode('utf-8') + key = create_string_buffer(keylen) - passwd = passwd.encode('utf-8') - key = create_string_buffer(keylen) - - if gmssl.pbkdf2_hmac_sm3_genkey(c_char_p(passwd), c_size_t(len(passwd)), - salt, c_size_t(len(salt)), c_size_t(iterator), c_size_t(keylen), key) != 1: - raise NativeError('libgmssl inner error') - - return key.raw + if gmssl.pbkdf2_hmac_sm3_genkey(c_char_p(passwd), c_size_t(len(passwd)), + salt, c_size_t(len(salt)), c_size_t(iterator), c_size_t(keylen), key) != 1: + raise NativeError('libgmssl inner error') + return key.raw SM4_KEY_SIZE = 16 SM4_BLOCK_SIZE = 16 _SM4_NUM_ROUNDS = 32 -class Sm4(Structure): - - _fields_ = [ - ("rk", c_uint32 * _SM4_NUM_ROUNDS) - ] - def __init__(self, key, encrypt): - if len(key) != SM4_KEY_SIZE: - raise ValueError('Invalid key length') - if encrypt: - gmssl.sm4_set_encrypt_key(byref(self), key) - else: - gmssl.sm4_set_decrypt_key(byref(self), key) - - def encrypt(self, block): - if len(block) != SM4_BLOCK_SIZE: - raise ValueError('Invalid block size') - outbuf = create_string_buffer(SM4_BLOCK_SIZE) - gmssl.sm4_encrypt(byref(self), block, outbuf) - return outbuf.raw +class Sm4(Structure): + _fields_ = [ + ("rk", c_uint32 * _SM4_NUM_ROUNDS) + ] + + def __init__(self, key, encrypt): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if encrypt: + gmssl.sm4_set_encrypt_key(byref(self), key) + else: + gmssl.sm4_set_decrypt_key(byref(self), key) + + def encrypt(self, block): + if len(block) != SM4_BLOCK_SIZE: + raise ValueError('Invalid block size') + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + gmssl.sm4_encrypt(byref(self), block, outbuf) + return outbuf.raw SM4_CBC_IV_SIZE = SM4_BLOCK_SIZE class Sm4Cbc(Structure): - - _fields_ = [ - ("sm4_key", Sm4), - ("iv", c_uint8 * SM4_BLOCK_SIZE), - ("block", c_uint8 * SM4_BLOCK_SIZE), - ("block_nbytes", c_size_t) - ] - - def __init__(self, key, iv, encrypt): - if len(key) != SM4_KEY_SIZE: - raise ValueError('Invalid key length') - if len(iv) != SM4_BLOCK_SIZE: - raise ValueError('Invalid IV size') - if encrypt == DO_ENCRYPT: - if gmssl.sm4_cbc_encrypt_init(byref(self), key, iv) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm4_cbc_decrypt_init(byref(self), key, iv) != 1: - raise NativeError('libgmssl inner error') - self._encrypt = encrypt - - def update(self, data): - outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) - outlen = c_size_t() - if self._encrypt == DO_ENCRYPT: - if gmssl.sm4_cbc_encrypt_update(byref(self), data, c_size_t(len(data)), - outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm4_cbc_decrypt_update(byref(self), data, c_size_t(len(data)), - outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[0:outlen.value] - - def finish(self): - outbuf = create_string_buffer(SM4_BLOCK_SIZE) - outlen = c_size_t() - if self._encrypt == True: - if gmssl.sm4_cbc_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm4_cbc_decrypt_finish(byref(self), outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[:outlen.value] - + _fields_ = [ + ("sm4_key", Sm4), + ("iv", c_uint8 * SM4_BLOCK_SIZE), + ("block", c_uint8 * SM4_BLOCK_SIZE), + ("block_nbytes", c_size_t) + ] + + def __init__(self, key, iv, encrypt): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) != SM4_BLOCK_SIZE: + raise ValueError('Invalid IV size') + if encrypt == DO_ENCRYPT: + if gmssl.sm4_cbc_encrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_cbc_decrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + self._encrypt = encrypt + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if self._encrypt == DO_ENCRYPT: + if gmssl.sm4_cbc_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_cbc_decrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + outlen = c_size_t() + if self._encrypt == True: + if gmssl.sm4_cbc_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_cbc_decrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] SM4_CTR_IV_SIZE = 16 class Sm4Ctr(Structure): - - _fields_ = [ - ("sm4_key", Sm4), - ("ctr", c_uint8 * SM4_BLOCK_SIZE), - ("block", c_uint8 * SM4_BLOCK_SIZE), - ("block_nbytes", c_size_t) - ] - - def __init__(self, key, iv): - if len(key) != SM4_KEY_SIZE: - raise ValueError('Invalid key length') - if len(iv) != SM4_BLOCK_SIZE: - raise ValueError('Invalid IV size') - if gmssl.sm4_ctr_encrypt_init(byref(self), key, iv) != 1: - raise NativeError('libgmssl inner error') - - def update(self, data): - outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) - outlen = c_size_t() - if gmssl.sm4_ctr_encrypt_update(byref(self), data, c_size_t(len(data)), - outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[0:outlen.value] - - def finish(self): - outbuf = create_string_buffer(SM4_BLOCK_SIZE) - outlen = c_size_t() - if gmssl.sm4_ctr_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[:outlen.value] + _fields_ = [ + ("sm4_key", Sm4), + ("ctr", c_uint8 * SM4_BLOCK_SIZE), + ("block", c_uint8 * SM4_BLOCK_SIZE), + ("block_nbytes", c_size_t) + ] + + def __init__(self, key, iv): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) != SM4_BLOCK_SIZE: + raise ValueError('Invalid IV size') + if gmssl.sm4_ctr_encrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.sm4_ctr_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.sm4_ctr_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] ZUC_KEY_SIZE = 16 ZUC_IV_SIZE = 16 + class ZucState(Structure): - _fields_ = [ - ("LFSR", c_uint32 * 16), - ("R1", c_uint32), - ("R2", c_uint32) - ] + _fields_ = [ + ("LFSR", c_uint32 * 16), + ("R1", c_uint32), + ("R2", c_uint32) + ] -class Zuc(Structure): - _fields_ = [ - ("zuc_state", ZucState), - ("block", c_uint8 * 4), - ("block_nbytes", c_size_t) - ] - - def __init__(self, key, iv): - if len(key) != ZUC_KEY_SIZE: - raise ValueError('Invalid key length') - if len(iv) != ZUC_IV_SIZE: - raise ValueError('Invalid IV size') - if gmssl.zuc_encrypt_init(byref(self), key, iv) != 1: - raise NativeError('libgmssl inner error') - - def update(self, data): - outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) - outlen = c_size_t() - if gmssl.zuc_encrypt_update(byref(self), data, c_size_t(len(data)), - outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[0:outlen.value] - - def finish(self): - outbuf = create_string_buffer(SM4_BLOCK_SIZE) - outlen = c_size_t() - if gmssl.zuc_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[:outlen.value] +class Zuc(Structure): + _fields_ = [ + ("zuc_state", ZucState), + ("block", c_uint8 * 4), + ("block_nbytes", c_size_t) + ] + + def __init__(self, key, iv): + if len(key) != ZUC_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) != ZUC_IV_SIZE: + raise ValueError('Invalid IV size') + if gmssl.zuc_encrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.zuc_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.zuc_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] class gf128_t(Structure): - _fields_ = [ - ("hi", c_uint64), - ("lo", c_uint64) - ] + _fields_ = [ + ("hi", c_uint64), + ("lo", c_uint64) + ] class Ghash(Structure): - _fields_ = [ - ("H", gf128_t), - ("X", gf128_t), - ("aadlen", c_size_t), - ("clen", c_size_t), - ("block", c_uint8 * 16), - ("num", c_size_t) - ] + _fields_ = [ + ("H", gf128_t), + ("X", gf128_t), + ("aadlen", c_size_t), + ("clen", c_size_t), + ("block", c_uint8 * 16), + ("num", c_size_t) + ] SM4_GCM_MIN_IV_SIZE = 1 @@ -320,59 +334,59 @@ class Ghash(Structure): SM4_GCM_DEFAULT_TAG_SIZE = 16 SM4_GCM_MAX_TAG_SIZE = 16 -class Sm4Gcm(Structure): - _fields_ = [ - ("sm4_ctr_ctx", Sm4Ctr), - ("mac_ctx", Ghash), - ("Y", c_uint8 * 16), - ("taglen", c_size_t), - ("mac", c_uint8 * 16), - ("maclen", c_size_t) - ] - - def __init__(self, key, iv, aad, taglen = SM4_GCM_DEFAULT_TAG_SIZE, encrypt = True): - if len(key) != SM4_KEY_SIZE: - raise ValueError('Invalid key length') - if len(iv) < SM4_GCM_MIN_IV_SIZE or len(iv) > SM4_GCM_MAX_IV_SIZE: - raise ValueError('Invalid IV size') - if taglen < 1 or taglen > SM4_GCM_MAX_TAG_SIZE: - raise ValueError('Invalid Tag length') - if encrypt == DO_ENCRYPT: - if gmssl.sm4_gcm_encrypt_init(byref(self), key, c_size_t(len(key)), - iv, c_size_t(len(iv)), aad, c_size_t(len(aad)), - c_size_t(taglen)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm4_gcm_decrypt_init(byref(self), key, c_size_t(len(key)), - iv, c_size_t(len(iv)), aad, c_size_t(len(aad)), - c_size_t(taglen)) != 1: - raise NativeError('libgmssl inner error') - self._encrypt = encrypt - - def update(self, data): - outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) - outlen = c_size_t() - if self._encrypt == DO_ENCRYPT: - if gmssl.sm4_gcm_encrypt_update(byref(self), data, c_size_t(len(data)), - outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm4_gcm_decrypt_update(byref(self), data, c_size_t(len(data)), - outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[0:outlen.value] - - def finish(self): - outbuf = create_string_buffer(SM4_BLOCK_SIZE + SM4_GCM_MAX_TAG_SIZE) - outlen = c_size_t() - if self._encrypt == DO_ENCRYPT: - if gmssl.sm4_gcm_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm4_gcm_decrypt_finish(byref(self), outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[:outlen.value] +class Sm4Gcm(Structure): + _fields_ = [ + ("sm4_ctr_ctx", Sm4Ctr), + ("mac_ctx", Ghash), + ("Y", c_uint8 * 16), + ("taglen", c_size_t), + ("mac", c_uint8 * 16), + ("maclen", c_size_t) + ] + + def __init__(self, key, iv, aad, taglen = SM4_GCM_DEFAULT_TAG_SIZE, encrypt = True): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) < SM4_GCM_MIN_IV_SIZE or len(iv) > SM4_GCM_MAX_IV_SIZE: + raise ValueError('Invalid IV size') + if taglen < 1 or taglen > SM4_GCM_MAX_TAG_SIZE: + raise ValueError('Invalid Tag length') + if encrypt == DO_ENCRYPT: + if gmssl.sm4_gcm_encrypt_init(byref(self), key, c_size_t(len(key)), + iv, c_size_t(len(iv)), aad, c_size_t(len(aad)), + c_size_t(taglen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_gcm_decrypt_init(byref(self), key, c_size_t(len(key)), + iv, c_size_t(len(iv)), aad, c_size_t(len(aad)), + c_size_t(taglen)) != 1: + raise NativeError('libgmssl inner error') + self._encrypt = encrypt + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if self._encrypt == DO_ENCRYPT: + if gmssl.sm4_gcm_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_gcm_decrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE + SM4_GCM_MAX_TAG_SIZE) + outlen = c_size_t() + if self._encrypt == DO_ENCRYPT: + if gmssl.sm4_gcm_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_gcm_decrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] SM2_DEFAULT_ID = '1234567812345678' @@ -386,122 +400,125 @@ def finish(self): class Sm2Point(Structure): - _fields_ = [ - ("x", c_uint8 * 32), - ("y", c_uint8 * 32) - ] + _fields_ = [ + ("x", c_uint8 * 32), + ("y", c_uint8 * 32) + ] class Sm2Key(Structure): - - _fields_ = [ - ("public_key", Sm2Point), - ("private_key", c_uint8 * 32) - ] - - def __init__(self): - self._has_public_key = False - self._has_private_key = False - - def generate_key(self): - if gmssl.sm2_key_generate(byref(self)) != 1: - raise NativeError('libgmssl inner error') - self._has_public_key = True - self._has_private_key = True - - def has_private_key(self): - return self._has_private_key - - def has_public_key(self): - return self._has_public_key - - def compute_z(self, signer_id = SM2_DEFAULT_ID): - if self._has_public_key == False: - raise TypeError('has no public key') - signer_id = signer_id.encode('utf-8') - z = create_string_buffer(SM3_DIGEST_SIZE) - gmssl.sm2_compute_z(z, byref(self), c_char_p(signer_id), c_size_t(len(signer_id))) - return z.raw - - def export_encrypted_private_key_info_pem(self, path, passwd): - if self._has_private_key == False: - raise TypeError('has no private key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - passwd = passwd.encode('utf-8') - if gmssl.sm2_private_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - - def import_encrypted_private_key_info_pem(self, path, passwd): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - passwd = passwd.encode('utf-8') - if gmssl.sm2_private_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_public_key = True - self._has_private_key = True - - def export_public_key_info_pem(self, path): - if self._has_public_key == False: - raise TypeError('has no public key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - if gmssl.sm2_public_key_info_to_pem(byref(self), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - - def import_public_key_info_pem(self, path): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - if gmssl.sm2_public_key_info_from_pem(byref(self), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_public_key = True - self._has_private_key = False - - def sign(self, dgst): - if self._has_private_key == False: - raise TypeError('has no private key') - if len(dgst) != SM3_DIGEST_SIZE: - raise ValueError('Invalid SM3 digest size') - sig = create_string_buffer(SM2_MAX_SIGNATURE_SIZE) - siglen = c_size_t() - if gmssl.sm2_sign(byref(self), dgst, sig, byref(siglen)) != 1: - raise NativeError('libgmssl inner error') - return sig[:siglen.value] - - def verify(self, dgst, signature): - if self._has_public_key == False: - raise TypeError('has no public key') - if len(dgst) != SM3_DIGEST_SIZE: - raise ValueError('Invalid SM3 digest size') - if gmssl.sm2_verify(byref(self), dgst, signature, c_size_t(len(signature))) != 1: - return False - return True - - def encrypt(self, data): - if self._has_public_key == False: - raise TypeError('has no public key') - if len(data) > SM2_MAX_PLAINTEXT_SIZE: - raise NativeError('libgmssl inner error') - outbuf = create_string_buffer(SM2_MAX_CIPHERTEXT_SIZE) - outlen = c_size_t() - if gmssl.sm2_encrypt(byref(self), data, c_size_t(len(data)), - outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[:outlen.value] - - def decrypt(self, ciphertext): - if self._has_private_key == False: - raise TypeError('has no private key') - outbuf = create_string_buffer(SM2_MAX_PLAINTEXT_SIZE) - outlen = c_size_t() - if gmssl.sm2_decrypt(byref(self), ciphertext, c_size_t(len(ciphertext)) - , outbuf, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return outbuf[:outlen.value] + _fields_ = [ + ("public_key", Sm2Point), + ("private_key", c_uint8 * 32) + ] + + def __init__(self): + self._has_public_key = False + self._has_private_key = False + + def generate_key(self): + if gmssl.sm2_key_generate(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._has_public_key = True + self._has_private_key = True + + def has_private_key(self): + return self._has_private_key + + def has_public_key(self): + return self._has_public_key + + def compute_z(self, signer_id = SM2_DEFAULT_ID): + if self._has_public_key == False: + raise TypeError('has no public key') + signer_id = signer_id.encode('utf-8') + z = create_string_buffer(SM3_DIGEST_SIZE) + gmssl.sm2_compute_z(z, byref(self), c_char_p(signer_id), c_size_t(len(signer_id))) + return z.raw + + def export_encrypted_private_key_info_pem(self, path, passwd): + if self._has_private_key == False: + raise TypeError('has no private key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm2_private_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_encrypted_private_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm2_private_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = True + + def export_public_key_info_pem(self, path): + if self._has_public_key == False: + raise TypeError('has no public key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.sm2_public_key_info_to_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_public_key_info_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + if gmssl.sm2_public_key_info_from_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = False + + def sign(self, dgst): + if self._has_private_key == False: + raise TypeError('has no private key') + if len(dgst) != SM3_DIGEST_SIZE: + raise ValueError('Invalid SM3 digest size') + sig = create_string_buffer(SM2_MAX_SIGNATURE_SIZE) + siglen = c_size_t() + if gmssl.sm2_sign(byref(self), dgst, sig, byref(siglen)) != 1: + raise NativeError('libgmssl inner error') + return sig[:siglen.value] + + def verify(self, dgst, signature): + if self._has_public_key == False: + raise TypeError('has no public key') + if len(dgst) != SM3_DIGEST_SIZE: + raise ValueError('Invalid SM3 digest size') + if gmssl.sm2_verify(byref(self), dgst, signature, c_size_t(len(signature))) != 1: + return False + return True + + def encrypt(self, data): + if self._has_public_key == False: + raise TypeError('has no public key') + if len(data) > SM2_MAX_PLAINTEXT_SIZE: + raise NativeError('libgmssl inner error') + outbuf = create_string_buffer(SM2_MAX_CIPHERTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm2_encrypt(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + def decrypt(self, ciphertext): + if self._has_private_key == False: + raise TypeError('has no private key') + outbuf = create_string_buffer(SM2_MAX_PLAINTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm2_decrypt(byref(self), ciphertext, c_size_t(len(ciphertext)) + , outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + @property + def fields_(self): + return self._fields_ DO_ENCRYPT = True @@ -509,380 +526,381 @@ def decrypt(self, ciphertext): DO_SIGN = True DO_VERIFY = False -class Sm2Signature(Structure): - _fields_ = [ - ("sm3_ctx", Sm3), - ("key", Sm2Key) - ] - - def __init__(self, sm2_key, signer_id = SM2_DEFAULT_ID, sign = DO_SIGN): - signer_id = signer_id.encode('utf-8') - if sign == DO_SIGN: - if sm2_key.has_private_key() != True: - raise NativeError('libgmssl inner error') - if gmssl.sm2_sign_init(byref(self), byref(sm2_key), - c_char_p(signer_id), c_size_t(len(signer_id))) != 1: - raise NativeError('libgmssl inner error') - else: - if sm2_key.has_public_key() != True: - raise NativeError('libgmssl inner error') - if gmssl.sm2_verify_init(byref(self), byref(sm2_key), - c_char_p(signer_id), c_size_t(len(signer_id))) != 1: - raise NativeError('libgmssl inner error') - self._sign = sign - - def update(self, data): - if self._sign == DO_SIGN: - if gmssl.sm2_sign_update(byref(self), data, c_size_t(len(data))) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm2_verify_update(byref(self), data, c_size_t(len(data))) != 1: - raise NativeError('libgmssl inner error') - - def sign(self): - if self._sign != DO_SIGN: - raise StateError('not sign state') - sig = create_string_buffer(SM2_MAX_SIGNATURE_SIZE) - siglen = c_size_t() - if gmssl.sm2_sign_finish(byref(self), sig, byref(siglen)) != 1: - raise NativeError('libgmssl inner error') - return sig[:siglen.value] - - def verify(self, signature): - if self._sign != DO_VERIFY: - raise StateError('not verify state') - if gmssl.sm2_verify_finish(byref(self), signature, c_size_t(len(signature))) != 1: - return False - return True +class Sm2Signature(Structure): + _fields_ = [ + ("sm3_ctx", Sm3), + ("key", Sm2Key) + ] + + def __init__(self, sm2_key, signer_id = SM2_DEFAULT_ID, sign = DO_SIGN): + signer_id = signer_id.encode('utf-8') + if sign == DO_SIGN: + if sm2_key.has_private_key() != True: + raise NativeError('libgmssl inner error') + if gmssl.sm2_sign_init(byref(self), byref(sm2_key), + c_char_p(signer_id), c_size_t(len(signer_id))) != 1: + raise NativeError('libgmssl inner error') + else: + if sm2_key.has_public_key() != True: + raise NativeError('libgmssl inner error') + if gmssl.sm2_verify_init(byref(self), byref(sm2_key), + c_char_p(signer_id), c_size_t(len(signer_id))) != 1: + raise NativeError('libgmssl inner error') + self._sign = sign + + def update(self, data): + if self._sign == DO_SIGN: + if gmssl.sm2_sign_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm2_verify_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + + def sign(self): + if self._sign != DO_SIGN: + raise StateError('not sign state') + sig = create_string_buffer(SM2_MAX_SIGNATURE_SIZE) + siglen = c_size_t() + if gmssl.sm2_sign_finish(byref(self), sig, byref(siglen)) != 1: + raise NativeError('libgmssl inner error') + return sig[:siglen.value] + + def verify(self, signature): + if self._sign != DO_VERIFY: + raise StateError('not verify state') + if gmssl.sm2_verify_finish(byref(self), signature, c_size_t(len(signature))) != 1: + return False + return True class sm9_bn_t(Structure): - _fields_ = [ - ("d", c_uint64 * 8) - ] + _fields_ = [ + ("d", c_uint64 * 8) + ] + class sm9_fp2_t(Structure): - _fields_ = [ - ("d", sm9_bn_t * 2) - ] + _fields_ = [ + ("d", sm9_bn_t * 2) + ] + class Sm9Point(Structure): - _fields_ = [ - ("X", sm9_bn_t), - ("Y", sm9_bn_t), - ("Z", sm9_bn_t) - ] + _fields_ = [ + ("X", sm9_bn_t), + ("Y", sm9_bn_t), + ("Z", sm9_bn_t) + ] + class Sm9TwistPoint(Structure): - _fields_ = [ - ("X", sm9_fp2_t), - ("Y", sm9_fp2_t), - ("Z", sm9_fp2_t) - ] + _fields_ = [ + ("X", sm9_fp2_t), + ("Y", sm9_fp2_t), + ("Z", sm9_fp2_t) + ] -SM9_MAX_ID_SIZE = 63 +SM9_MAX_ID_SIZE = 63 SM9_MAX_PLAINTEXT_SIZE = 255 SM9_MAX_CIPHERTEXT_SIZE = 367 + class Sm9EncKey(Structure): - _fields_ = [ - ("Ppube", Sm9Point), - ("de", Sm9TwistPoint) - ] - - def __init__(self, owner_id): - self._id = owner_id.encode('utf-8') - self._has_private_key = False - - def get_id(self): - return self._id; - - def has_private_key(self): - return self._has_private_key - - def import_encrypted_private_key_info_pem(self, path, passwd): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_enc_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_private_key = True - - def export_encrypted_private_key_info_pem(self, path, passwd): - if self._has_private_key != True: - raise TypeError('has no private key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_enc_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - - def decrypt(self, ciphertext): - if self._has_private_key != True: - raise TypeError('has no private key') - plaintext = create_string_buffer(SM9_MAX_PLAINTEXT_SIZE) - outlen = c_size_t() - if gmssl.sm9_decrypt(byref(self), c_char_p(self._id), c_size_t(len(self._id)), - ciphertext, c_size_t(len(ciphertext)), plaintext, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return plaintext[0:outlen.value] + _fields_ = [ + ("Ppube", Sm9Point), + ("de", Sm9TwistPoint) + ] + + def __init__(self, owner_id): + self._id = owner_id.encode('utf-8') + self._has_private_key = False + + def get_id(self): + return self._id; + + def has_private_key(self): + return self._has_private_key + + def import_encrypted_private_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_private_key = True + + def export_encrypted_private_key_info_pem(self, path, passwd): + if self._has_private_key != True: + raise TypeError('has no private key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def decrypt(self, ciphertext): + if self._has_private_key != True: + raise TypeError('has no private key') + plaintext = create_string_buffer(SM9_MAX_PLAINTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm9_decrypt(byref(self), c_char_p(self._id), c_size_t(len(self._id)), + ciphertext, c_size_t(len(ciphertext)), plaintext, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return plaintext[0:outlen.value] class Sm9EncMasterKey(Structure): - _fields_ = [ - ("Ppube", Sm9Point), - ("ke", sm9_bn_t) - ] - - def __init__(self): - self._has_public_key = False - self._has_private_key = False - - def generate_master_key(self): - if gmssl.sm9_enc_master_key_generate(byref(self)) != 1: - raise NativeError('libgmssl inner error') - self._has_public_key = True - self._has_private_key = True - - def extract_key(self, identity): - if self._has_private_key != True: - raise TypeError('has no master key') - key = Sm9EncKey(identity) - identity = identity.encode('utf-8') - if gmssl.sm9_enc_master_key_extract_key(byref(self), - c_char_p(identity), c_size_t(len(identity)), byref(key)) != 1: - raise NativeError('libgmssl inner error') - key._has_public_key = True - key._has_private_key = True - return key - - def import_encrypted_master_key_info_pem(self, path, passwd): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_enc_master_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_public_key = True - self._has_private_key = True - - def export_encrypted_master_key_info_pem(self, path, passwd): - if self._has_private_key != True: - raise TypeError('has no master key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_enc_master_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - - def export_public_master_key_pem(self, path): - if self._has_public_key != True: - raise TypeError('has no public master key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - if gmssl.sm9_enc_master_public_key_to_pem(byref(self), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - - def import_public_master_key_pem(self, path): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - if gmssl.sm9_enc_master_public_key_from_pem(byref(self), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_public_key = True - self._has_private_key = False - - def encrypt(self, plaintext, to): - if self._has_public_key != True: - raise TypeError('has no public master key') - to = to.encode('utf-8') - ciphertext = create_string_buffer(SM9_MAX_CIPHERTEXT_SIZE) - outlen = c_size_t() - if gmssl.sm9_encrypt(byref(self), c_char_p(to), c_size_t(len(to)), - plaintext, c_size_t(len(plaintext)), ciphertext, byref(outlen)) != 1: - raise NativeError('libgmssl inner error') - return ciphertext[0:outlen.value] + _fields_ = [ + ("Ppube", Sm9Point), + ("ke", sm9_bn_t) + ] + + def __init__(self): + self._has_public_key = False + self._has_private_key = False + + def generate_master_key(self): + if gmssl.sm9_enc_master_key_generate(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._has_public_key = True + self._has_private_key = True + + def extract_key(self, identity): + if self._has_private_key != True: + raise TypeError('has no master key') + key = Sm9EncKey(identity) + identity = identity.encode('utf-8') + if gmssl.sm9_enc_master_key_extract_key(byref(self), + c_char_p(identity), c_size_t(len(identity)), byref(key)) != 1: + raise NativeError('libgmssl inner error') + key._has_public_key = True + key._has_private_key = True + return key + + def import_encrypted_master_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_master_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = True + + def export_encrypted_master_key_info_pem(self, path, passwd): + if self._has_private_key != True: + raise TypeError('has no master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_master_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def export_public_master_key_pem(self, path): + if self._has_public_key != True: + raise TypeError('has no public master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.sm9_enc_master_public_key_to_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_public_master_key_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + if gmssl.sm9_enc_master_public_key_from_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = False + + def encrypt(self, plaintext, to): + if self._has_public_key != True: + raise TypeError('has no public master key') + to = to.encode('utf-8') + ciphertext = create_string_buffer(SM9_MAX_CIPHERTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm9_encrypt(byref(self), c_char_p(to), c_size_t(len(to)), + plaintext, c_size_t(len(plaintext)), ciphertext, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return ciphertext[0:outlen.value] class Sm9SignKey(Structure): - _fields_ = [ - ("Ppubs", Sm9TwistPoint), - ("ds", Sm9Point) - ] - - def __init__(self, owner_id): - self._id = owner_id.encode('utf-8') - self._has_private_key = False - - def get_id(self): - return self._id; - - def has_private_key(self): - return self._has_private_key - - def import_encrypted_private_key_info_pem(self, path, passwd): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_sign_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_private_key = True - - def export_encrypted_private_key_info_pem(self, path, passwd): - if self._has_private_key == False: - raise TypeError('has no master key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_sign_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) + _fields_ = [ + ("Ppubs", Sm9TwistPoint), + ("ds", Sm9Point) + ] + + def __init__(self, owner_id): + self._id = owner_id.encode('utf-8') + self._has_private_key = False + + def get_id(self): + return self._id; + + def has_private_key(self): + return self._has_private_key + + def import_encrypted_private_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_private_key = True + + def export_encrypted_private_key_info_pem(self, path, passwd): + if self._has_private_key == False: + raise TypeError('has no master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) class Sm9SignMasterKey(Structure): - _fields_ = [ - ("Ppubs", Sm9TwistPoint), - ("ks", sm9_bn_t) - ] - - def __init__(self): - self._has_public_key = False - self._has_private_key = False - - def generate_master_key(self): - if gmssl.sm9_sign_master_key_generate(byref(self)) != 1: - raise NativeError('libgmssl inner error') - self._has_public_key = True - self._has_private_key = True - - def extract_key(self, identity): - if self._has_private_key != True: - raise TypeError('has no master key') - key = Sm9SignKey(identity) - identity = identity.encode('utf-8') - if gmssl.sm9_sign_master_key_extract_key(byref(self), - c_char_p(identity), c_size_t(len(identity)), byref(key)) != 1: - raise NativeError('libgmssl inner error') - key._has_public_key = True - key._has_private_key = True - return key - - def import_encrypted_master_key_info_pem(self, path, passwd): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_sign_master_key_info_decrypt_from_pem(byref(self), - c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_public_key = True - self._has_private_key = True - - def export_encrypted_master_key_info_pem(self, path, passwd): - if self._has_private_key != True: - raise TypeError('has no master key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - passwd = passwd.encode('utf-8') - if gmssl.sm9_sign_master_key_info_encrypt_to_pem(byref(self), - c_char_p(passwd), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - - def export_public_master_key_pem(self, path): - if self._has_public_key != True: - raise TypeError('has no public master key') - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - if gmssl.sm9_sign_master_public_key_to_pem(byref(self), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - - def import_public_master_key_pem(self, path): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'rb') - if gmssl.sm9_sign_master_public_key_from_pem(byref(self), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - libc.fclose(c_void_p(fp)) - self._has_public_key = True - self._has_private_key = False + _fields_ = [ + ("Ppubs", Sm9TwistPoint), + ("ks", sm9_bn_t) + ] + + def __init__(self): + self._has_public_key = False + self._has_private_key = False + + def generate_master_key(self): + if gmssl.sm9_sign_master_key_generate(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._has_public_key = True + self._has_private_key = True + + def extract_key(self, identity): + if self._has_private_key != True: + raise TypeError('has no master key') + key = Sm9SignKey(identity) + identity = identity.encode('utf-8') + if gmssl.sm9_sign_master_key_extract_key(byref(self), + c_char_p(identity), c_size_t(len(identity)), byref(key)) != 1: + raise NativeError('libgmssl inner error') + key._has_public_key = True + key._has_private_key = True + return key + + def import_encrypted_master_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_master_key_info_decrypt_from_pem(byref(self), + c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = True + + def export_encrypted_master_key_info_pem(self, path, passwd): + if self._has_private_key != True: + raise TypeError('has no master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_master_key_info_encrypt_to_pem(byref(self), + c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def export_public_master_key_pem(self, path): + if self._has_public_key != True: + raise TypeError('has no public master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.sm9_sign_master_public_key_to_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_public_master_key_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + if gmssl.sm9_sign_master_public_key_from_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = False SM9_SIGNATURE_SIZE = 104 -class Sm9Signature(Structure): - - _fields_ = [ - ("sm3", Sm3) - ] - - def __init__(self, sign = DO_SIGN): - if sign == DO_SIGN: - if gmssl.sm9_sign_init(byref(self)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm9_verify_init(byref(self)) != 1: - raise NativeError('libgmssl inner error') - self._sign = sign - self._inited = True - - - def reset(self): - if self._inited != True: - raise StateError('not initialized') - - if self._sign == DO_SIGN: - if gmssl.sm9_sign_init(byref(self)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm9_verify_init(byref(self)) != 1: - raise NativeError('libgmssl inner error') - - def update(self, data): - - if self._inited != True: - raise StateError('not initialized') - - if self._sign == DO_SIGN: - if gmssl.sm9_sign_update(byref(self), data, c_size_t(len(data))) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.sm9_verify_update(byref(self), data, c_size_t(len(data))) != 1: - raise NativeError('libgmssl inner error') - - - def sign(self, sign_key): - if self._inited != True: - raise StateError('not initialized') - if self._sign != DO_SIGN: - raise StateError('not sign state') - - sig = create_string_buffer(SM9_SIGNATURE_SIZE) - siglen = c_size_t() - if gmssl.sm9_sign_finish(byref(self), byref(sign_key), sig, byref(siglen)) != 1: - raise NativeError('libgmssl inner error') - return sig[:siglen.value] - - def verify(self, signature, public_master_key, signer_id): - if self._inited != True: - raise StateError('not initialized') - if self._sign != DO_VERIFY: - raise StateError('not verify state') - - signer_id = signer_id.encode('utf-8') - - if gmssl.sm9_verify_finish(byref(self), signature, c_size_t(len(signature)), - byref(public_master_key), c_char_p(signer_id), c_size_t(len(signer_id))) != 1: - return False - return True +class Sm9Signature(Structure): + _fields_ = [ + ("sm3", Sm3) + ] + + def __init__(self, sign = DO_SIGN): + if sign == DO_SIGN: + if gmssl.sm9_sign_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm9_verify_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._sign = sign + self._inited = True + + def reset(self): + if self._inited != True: + raise StateError('not initialized') + + if self._sign == DO_SIGN: + if gmssl.sm9_sign_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm9_verify_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + + def update(self, data): + + if self._inited != True: + raise StateError('not initialized') + + if self._sign == DO_SIGN: + if gmssl.sm9_sign_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm9_verify_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + + def sign(self, sign_key): + if self._inited != True: + raise StateError('not initialized') + if self._sign != DO_SIGN: + raise StateError('not sign state') + + sig = create_string_buffer(SM9_SIGNATURE_SIZE) + siglen = c_size_t() + if gmssl.sm9_sign_finish(byref(self), byref(sign_key), sig, byref(siglen)) != 1: + raise NativeError('libgmssl inner error') + return sig[:siglen.value] + + def verify(self, signature, public_master_key, signer_id): + if self._inited != True: + raise StateError('not initialized') + if self._sign != DO_VERIFY: + raise StateError('not verify state') + + signer_id = signer_id.encode('utf-8') + + if gmssl.sm9_verify_finish(byref(self), signature, c_size_t(len(signature)), + byref(public_master_key), c_char_p(signer_id), c_size_t(len(signer_id))) != 1: + return False + return True _ASN1_TAG_IA5String = 22 @@ -890,152 +908,151 @@ def verify(self, signature, public_master_key, signer_id): _ASN1_TAG_SET = 0x31 - def gmssl_parse_attr_type_and_value(name, d, dlen): - oid = c_int() - tag = c_int() - val = c_void_p() - vlen = c_size_t() + oid = c_int() + tag = c_int() + val = c_void_p() + vlen = c_size_t() + + if gmssl.x509_name_type_from_der(byref(oid), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + gmssl.x509_name_type_name.restype = c_char_p + oid_name = gmssl.x509_name_type_name(oid).decode('ascii') - if gmssl.x509_name_type_from_der(byref(oid), byref(d), byref(dlen)) != 1: - raise NativeError('libgmssl inner error') - gmssl.x509_name_type_name.restype = c_char_p - oid_name = gmssl.x509_name_type_name(oid).decode('ascii') + if oid_name == 'emailAddress': + if gmssl.asn1_ia5_string_from_der_ex(_ASN1_TAG_IA5String, byref(val), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.x509_directory_name_from_der(byref(tag), byref(val), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') - if oid_name == 'emailAddress': - if gmssl.asn1_ia5_string_from_der_ex(_ASN1_TAG_IA5String, byref(val), byref(vlen), byref(d), byref(dlen)) != 1: - raise NativeError('libgmssl inner error') - else: - if gmssl.x509_directory_name_from_der(byref(tag), byref(val), byref(vlen), byref(d), byref(dlen)) != 1: - raise NativeError('libgmssl inner error') + if dlen.value != 0: + raise ValueError('invalid der encoding') - if dlen.value != 0: - raise ValueError('invalid der encoding') + value = create_string_buffer(vlen.value) + libc.memcpy(value, val, vlen) - value = create_string_buffer(vlen.value) - libc.memcpy(value, val, vlen) + name[oid_name] = value.raw.decode('utf-8') + return True - name[oid_name] = value.raw.decode('utf-8') - return True def gmssl_parse_rdn(name, d, dlen): - v = c_void_p() - vlen = c_size_t() + v = c_void_p() + vlen = c_size_t() - while dlen.value > 0: - if gmssl.asn1_type_from_der(_ASN1_TAG_SEQUENCE, byref(v), byref(vlen), byref(d), byref(dlen)) != 1: - raise NativeError('libgmssl inner error') + while dlen.value > 0: + if gmssl.asn1_type_from_der(_ASN1_TAG_SEQUENCE, byref(v), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') - if gmssl_parse_attr_type_and_value(name, v, vlen) != 1: - raise NativeError('libgmssl inner error') + if gmssl_parse_attr_type_and_value(name, v, vlen) != 1: + raise NativeError('libgmssl inner error') + + return True - return True # https://stacktuts.com/how-to-correctly-pass-pointer-to-pointer-into-dll-in-python-and-ctypes# def gmssl_parse_name(name, d, dlen): - v = c_void_p() - vlen = c_size_t() + v = c_void_p() + vlen = c_size_t() - while dlen.value > 0: - if gmssl.asn1_nonempty_type_from_der(c_int(_ASN1_TAG_SET), byref(v), byref(vlen), byref(d), byref(dlen)) != 1: - raise NativeError('libgmssl inner error') - gmssl_parse_rdn(name, v, vlen) - return True + while dlen.value > 0: + if gmssl.asn1_nonempty_type_from_der(c_int(_ASN1_TAG_SET), byref(v), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + gmssl_parse_rdn(name, v, vlen) + return True class Validity: - def __init__(self, not_before, not_after): - self.not_before = datetime.datetime.fromtimestamp(not_before) - self.not_after = datetime.datetime.fromtimestamp(not_after) + def __init__(self, not_before, not_after): + self.not_before = datetime.datetime.fromtimestamp(not_before) + self.not_after = datetime.datetime.fromtimestamp(not_after) class Sm2Certificate: - def import_pem(self, path): - - cert = c_void_p() - certlen = c_size_t() - if gmssl.x509_cert_new_from_file(byref(cert), byref(certlen), path.encode('utf-8')) != 1: - raise NativeError('libgmssl inner error') - - self._cert = create_string_buffer(certlen.value) - libc.memcpy(self._cert, cert, certlen) - libc.free(cert) - - def get_raw(self): - return self._cert; - - def export_pem(self, path): - libc.fopen.restype = c_void_p - fp = libc.fopen(path.encode('utf-8'), 'wb') - if gmssl.x509_cert_to_pem(self._cert, c_size_t(len(self._cert)), c_void_p(fp)) != 1: - raise NativeError('libgmssl inner error') - - def get_serial_number(self): - - serial_ptr = c_void_p() - serial_len = c_size_t() - - if gmssl.x509_cert_get_issuer_and_serial_number(self._cert, c_size_t(len(self._cert)), - None, None, byref(serial_ptr), byref(serial_len)) != 1: - raise NativeError('libgmssl inner error') - - serial = create_string_buffer(serial_len.value) - libc.memcpy(serial, serial_ptr, serial_len) - return serial.raw - - def get_issuer(self): - issuer_ptr = c_void_p() - issuer_len = c_size_t() - if gmssl.x509_cert_get_issuer(self._cert, c_size_t(len(self._cert)), - byref(issuer_ptr), byref(issuer_len)) != 1: - raise NativeError('libgmssl inner error') - issuer_raw = create_string_buffer(issuer_len.value) - libc.memcpy(issuer_raw, issuer_ptr, issuer_len) - - issuer = { "raw_data" : issuer_raw.raw } - gmssl_parse_name(issuer, issuer_ptr, issuer_len) - return issuer - - def get_subject(self): - subject_ptr = c_void_p() - subject_len = c_size_t() - if gmssl.x509_cert_get_subject(self._cert, c_size_t(len(self._cert)), - byref(subject_ptr), byref(subject_len)) != 1: - raise NativeError('libgmssl inner error') - subject_raw = create_string_buffer(subject_len.value) - libc.memcpy(subject_raw, subject_ptr, subject_len) - - subject = { "raw_data" : subject_raw.raw } - gmssl_parse_name(subject, subject_ptr, subject_len) - return subject - - def get_subject_public_key(self): - public_key = Sm2Key() - gmssl.x509_cert_get_subject_public_key(self._cert, c_size_t(len(self._cert)), byref(public_key)) - public_key._has_private_key = False - public_key._has_public_key = True - return public_key - - def get_validity(self): - not_before = c_ulong() - not_after = c_ulong() - if gmssl.x509_cert_get_details(self._cert, c_size_t(len(self._cert)), - None, None, None, None, None, None, - byref(not_before), byref(not_after), - None, None, None, None, None, None, None, None, None, None, None, None) != 1: - raise NativeError('libgmssl inner error') - return Validity(not_before.value, not_after.value) - - def verify_by_ca_certificate(self, cacert, sm2_id): - - cacert_raw = cacert.get_raw() - sm2_id = sm2_id.encode('utf-8') - - if gmssl.x509_cert_verify_by_ca_cert(self._cert, c_size_t(len(self._cert)), - cacert_raw, c_size_t(len(cacert_raw)), c_char_p(sm2_id), c_size_t(len(sm2_id))) != 1: - return False - return True - - + def import_pem(self, path): + + cert = c_void_p() + certlen = c_size_t() + if gmssl.x509_cert_new_from_file(byref(cert), byref(certlen), path.encode('utf-8')) != 1: + raise NativeError('libgmssl inner error') + + self._cert = create_string_buffer(certlen.value) + libc.memcpy(self._cert, cert, certlen) + libc.free(cert) + + def get_raw(self): + return self._cert; + + def export_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.x509_cert_to_pem(self._cert, c_size_t(len(self._cert)), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + + def get_serial_number(self): + + serial_ptr = c_void_p() + serial_len = c_size_t() + + if gmssl.x509_cert_get_issuer_and_serial_number(self._cert, c_size_t(len(self._cert)), + None, None, byref(serial_ptr), byref(serial_len)) != 1: + raise NativeError('libgmssl inner error') + + serial = create_string_buffer(serial_len.value) + libc.memcpy(serial, serial_ptr, serial_len) + return serial.raw + + def get_issuer(self): + issuer_ptr = c_void_p() + issuer_len = c_size_t() + if gmssl.x509_cert_get_issuer(self._cert, c_size_t(len(self._cert)), + byref(issuer_ptr), byref(issuer_len)) != 1: + raise NativeError('libgmssl inner error') + issuer_raw = create_string_buffer(issuer_len.value) + libc.memcpy(issuer_raw, issuer_ptr, issuer_len) + + issuer = {"raw_data": issuer_raw.raw} + gmssl_parse_name(issuer, issuer_ptr, issuer_len) + return issuer + + def get_subject(self): + subject_ptr = c_void_p() + subject_len = c_size_t() + if gmssl.x509_cert_get_subject(self._cert, c_size_t(len(self._cert)), + byref(subject_ptr), byref(subject_len)) != 1: + raise NativeError('libgmssl inner error') + subject_raw = create_string_buffer(subject_len.value) + libc.memcpy(subject_raw, subject_ptr, subject_len) + + subject = {"raw_data": subject_raw.raw} + gmssl_parse_name(subject, subject_ptr, subject_len) + return subject + + def get_subject_public_key(self): + public_key = Sm2Key() + gmssl.x509_cert_get_subject_public_key(self._cert, c_size_t(len(self._cert)), byref(public_key)) + public_key._has_private_key = False + public_key._has_public_key = True + return public_key + + def get_validity(self): + not_before = c_ulong() + not_after = c_ulong() + if gmssl.x509_cert_get_details(self._cert, c_size_t(len(self._cert)), + None, None, None, None, None, None, + byref(not_before), byref(not_after), + None, None, None, None, None, None, None, None, None, None, None, None) != 1: + raise NativeError('libgmssl inner error') + return Validity(not_before.value, not_after.value) + + def verify_by_ca_certificate(self, cacert, sm2_id): + + cacert_raw = cacert.get_raw() + sm2_id = sm2_id.encode('utf-8') + + if gmssl.x509_cert_verify_by_ca_cert(self._cert, c_size_t(len(self._cert)), + cacert_raw, c_size_t(len(cacert_raw)), c_char_p(sm2_id), c_size_t(len(sm2_id))) != 1: + return False + return True diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index cd544f6..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,23 +0,0 @@ -[build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" - - -[project] -name = "gmssl_python" -version = "2.2.2" -authors = [ - { name="Zhi Guan", email="guan@pku.edu.cn" }, -] -description = "Python binding of the GmSSL library with ctypes" -readme = "README.md" -requires-python = ">=3.7" -classifiers = [ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", -] - -[project.urls] -"Homepage" = "https://gmssl.github.io/GmSSL-Python/" -"Bug Tracker" = "https://github.com/GmSSL/GmSSL-Python/issues" diff --git a/run_unittest.sh b/run_unittest.sh new file mode 100755 index 0000000..9354da2 --- /dev/null +++ b/run_unittest.sh @@ -0,0 +1,7 @@ +#! /bin/bash + +python3 -m unittest easy_gmssl/easy_random_data_test.py +python3 -m unittest easy_gmssl/easy_sm2_key.py +python3 -m unittest easy_gmssl/easy_sm2_sign_test.py +python3 -m unittest easy_gmssl/easy_sm3_key_test.py +python3 -m unittest easy_gmssl/easy_sm4_test.py diff --git a/test.py b/test.py deleted file mode 100644 index ce80cf2..0000000 --- a/test.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2023 The GmSSL Project. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# -# http://www.apache.org/licenses/LICENSE-2.0 - - -import unittest -from gmssl import * - -class TestGmSSL(unittest.TestCase): - - def test_version(self): - self.assertTrue(gmssl_library_version_num() > 0) - self.assertTrue(len(GMSSL_LIBRARY_VERSION) > 0) - self.assertTrue(len(GMSSL_PYTHON_VERSION) > 0) - - def test_rand(self): - keylen = 20 - key = rand_bytes(keylen) - self.assertEqual(len(key), keylen) - - def test_sm3(self): - dgst_hex = '66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0' - sm3 = Sm3() - sm3.update(b'abc') - dgst = sm3.digest() - self.assertEqual(dgst, bytes.fromhex(dgst_hex)) - - def test_sm3_hmac(self): - key = b'1234567812345678' - mac_hex = '0a69401a75c5d471f5166465eec89e6a65198ae885c1fdc061556254d91c1080' - sm3_hmac = Sm3Hmac(key) - sm3_hmac.update(b'abc') - mac = sm3_hmac.generate_mac() - self.assertEqual(mac, bytes.fromhex(mac_hex)) - - def test_sm3_pbkdf2(self): - passwd = 'password' - salt = b'12345678' - iterator = 10000 - keylen = 32 - keyhex = 'ac5b4a93a130252181434970fa9d8e6f1083badecafc4409aaf0097c813e9fc6' - key = sm3_pbkdf2(passwd, salt, iterator, keylen) - self.assertEqual(key, bytes.fromhex(keyhex)) - - def test_sm4(self): - key = b'1234567812345678' - plaintext = b'block of message' - ciphertext_hex = 'dd99d30fd7baf5af2930335d2554ddb7' - sm4 = Sm4(key, DO_ENCRYPT) - ciphertext = sm4.encrypt(plaintext) - self.assertEqual(ciphertext, bytes.fromhex(ciphertext_hex)) - sm4 = Sm4(key, DO_DECRYPT) - decrypted = sm4.encrypt(ciphertext) - self.assertEqual(decrypted, plaintext) - - def test_sm4_cbc(self): - key = b'1234567812345678' - iv = b'1234567812345678' - plaintext = b'abc' - ciphertext_hex = '532b22f9a096e7e5b8d84a620f0f7078' - sm4_cbc = Sm4Cbc(key, iv, DO_ENCRYPT) - ciphertext = sm4_cbc.update(plaintext) - ciphertext += sm4_cbc.finish() - self.assertEqual(ciphertext, bytes.fromhex(ciphertext_hex)) - sm4_cbc = Sm4Cbc(key, iv, DO_DECRYPT) - decrypted = sm4_cbc.update(ciphertext) - decrypted += sm4_cbc.finish() - self.assertEqual(decrypted, plaintext) - - def test_sm4_ctr(self): - key = b'1234567812345678' - iv = b'1234567812345678' - plaintext = b'abc' - ciphertext_hex = '890106' - sm4_ctr = Sm4Ctr(key, iv) - ciphertext = sm4_ctr.update(plaintext) - ciphertext += sm4_ctr.finish() - self.assertEqual(ciphertext, bytes.fromhex(ciphertext_hex)) - sm4_ctr = Sm4Ctr(key, iv) - decrypted = sm4_ctr.update(ciphertext) - decrypted += sm4_ctr.finish() - self.assertEqual(decrypted, plaintext) - - def test_sm4_gcm(self): - key = b'1234567812345678' - iv = b'0123456789ab' - aad = b'Additional Authenticated Data' - taglen = 16 - plaintext = b'abc' - ciphertext_hex = '7d8bd8fdc7ea3b04c15fb61863f2292c15eeaa' - sm4_gcm = Sm4Gcm(key, iv, aad, taglen, DO_ENCRYPT) - ciphertext = sm4_gcm.update(plaintext) - ciphertext += sm4_gcm.finish() - self.assertEqual(ciphertext, bytes.fromhex(ciphertext_hex)) - sm4_gcm = Sm4Gcm(key, iv, aad, taglen, DO_DECRYPT) - decrypted = sm4_gcm.update(ciphertext) - decrypted += sm4_gcm.finish() - self.assertEqual(decrypted, plaintext) - - def test_zuc(self): - key = b'1234567812345678' - iv = b'1234567812345678' - plaintext = b'abc' - ciphertext_hex = '3d144b' - zuc = Zuc(key, iv) - ciphertext = zuc.update(plaintext) - ciphertext += zuc.finish() - self.assertEqual(ciphertext, bytes.fromhex(ciphertext_hex)) - zuc = Zuc(key, iv) - decrypted = zuc.update(ciphertext) - decrypted += zuc.finish() - self.assertEqual(decrypted, plaintext) - - def test_sm2_key(self): - dgst = bytes.fromhex('66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0') - plaintext = b'abc' - sm2 = Sm2Key() - sm2.generate_key() - sm2.export_encrypted_private_key_info_pem('sm2.pem', 'password') - sm2.export_public_key_info_pem('sm2pub.pem') - sm2pri = Sm2Key() - sm2pri.import_encrypted_private_key_info_pem('sm2.pem', 'password') - sm2pub = Sm2Key() - sm2pub.import_public_key_info_pem("sm2pub.pem"); - sig = sm2pri.sign(dgst) - verify_ret = sm2pub.verify(dgst, sig) - self.assertTrue(verify_ret) - ciphertext = sm2pub.encrypt(plaintext) - decrypted = sm2pri.decrypt(ciphertext) - self.assertEqual(decrypted, plaintext) - - def test_sm2_id(self): - pem_txt = '''\ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE+XVF76aof3ZtBVUwXobDQwQn+Sb2 -ethykPiYkXDLFdLnTrqr0b9QuA63DPdyrxJS3LZZwp9qzaMSyStai8+nrQ== ------END PUBLIC KEY-----''' - with open('pub.pem', 'w') as file: - file.write(pem_txt) - file.close() - z_hex = '4e469c92c425960603a315491bb2181c2f25939172775e223e1759b413cfc8ba' - sm2pub = Sm2Key() - sm2pub.import_public_key_info_pem('pub.pem') - z = sm2pub.compute_z(SM2_DEFAULT_ID) - self.assertEqual(z, bytes.fromhex(z_hex)) - - def test_sm2_sig(self): - sm2 = Sm2Key() - sm2.generate_key() - sign = Sm2Signature(sm2, SM2_DEFAULT_ID, DO_SIGN) - sign.update(b'abc') - sig = sign.sign() - verify = Sm2Signature(sm2, SM2_DEFAULT_ID, DO_VERIFY) - verify.update(b'abc') - verify_ret = verify.verify(sig) - self.assertTrue(verify_ret) - - def test_sm9_enc(self): - master_key = Sm9EncMasterKey() - master_key.generate_master_key() - master_key.export_encrypted_master_key_info_pem('enc_msk.pem', 'password') - master_key.export_public_master_key_pem('enc_mpk.pem') - master_pub = Sm9EncMasterKey() - master_pub.import_public_master_key_pem('enc_mpk.pem') - ciphertext = master_pub.encrypt(b'plaintext', 'Alice') - master = Sm9EncMasterKey() - master.import_encrypted_master_key_info_pem('enc_msk.pem', 'password') - key = master.extract_key('Alice') - plaintext = key.decrypt(ciphertext) - self.assertEqual(plaintext, b'plaintext') - - def test_sm9_sign(self): - master_key = Sm9SignMasterKey() - master_key.generate_master_key() - master_key.export_encrypted_master_key_info_pem('sign_msk.pem', 'password') - master_key.export_public_master_key_pem('sign_mpk.pem') - master = Sm9SignMasterKey() - master.import_encrypted_master_key_info_pem('sign_msk.pem', 'password') - key = master.extract_key('Alice') - sign = Sm9Signature(DO_SIGN) - sign.update(b'message') - sig = sign.sign(key) - master_pub = Sm9SignMasterKey() - master_pub.import_public_master_key_pem('sign_mpk.pem') - verify = Sm9Signature(DO_VERIFY) - verify.update(b'message') - ret = verify.verify(sig, master_pub, 'Alice') - self.assertTrue(ret) - - def test_sm2_cert(self): - cert_txt = '''\ ------BEGIN CERTIFICATE----- -MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG -EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw -MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO -UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE -MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT -V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti -W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ -MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b -53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI -pDoiVhsLwg== ------END CERTIFICATE-----''' - with open('ROOTCA.pem', 'w') as file: - file.write(cert_txt) - file.close() - - cert = Sm2Certificate() - cert.import_pem('ROOTCA.pem') - serial = cert.get_serial_number() - self.assertTrue(len(serial) > 0) - validity = cert.get_validity() - self.assertTrue(validity.not_before < validity.not_after) - issuer = cert.get_issuer() - self.assertTrue(len(issuer) > 1) - subject = cert.get_subject() - self.assertTrue(len(subject) > 1) - public_key = cert.get_subject_public_key() - public_key.export_public_key_info_pem('public_key.pem') - public_key.import_public_key_info_pem('public_key.pem') - ret = cert.verify_by_ca_certificate(cert, SM2_DEFAULT_ID) - self.assertTrue(ret) - - -if __name__ == '__main__': - unittest.main() -