mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-08-06 11:53:39 +08:00
Update QUIC/SM9/ZUC
This commit is contained in:
@@ -221,7 +221,7 @@ set(src
|
|||||||
set(tools
|
set(tools
|
||||||
tools/gmssl.c
|
tools/gmssl.c
|
||||||
tools/version.c
|
tools/version.c
|
||||||
tools/sm4.c
|
# tools/sm4.c
|
||||||
tools/sm4_cbc.c
|
tools/sm4_cbc.c
|
||||||
tools/sm4_ctr.c
|
tools/sm4_ctr.c
|
||||||
tools/sm4_gcm.c
|
tools/sm4_gcm.c
|
||||||
@@ -233,6 +233,7 @@ set(tools
|
|||||||
tools/sm2verify.c
|
tools/sm2verify.c
|
||||||
tools/sm2encrypt.c
|
tools/sm2encrypt.c
|
||||||
tools/sm2decrypt.c
|
tools/sm2decrypt.c
|
||||||
|
tools/sm2exch.c
|
||||||
tools/rand.c
|
tools/rand.c
|
||||||
tools/certgen.c
|
tools/certgen.c
|
||||||
tools/certparse.c
|
tools/certparse.c
|
||||||
@@ -507,7 +508,8 @@ if (ENABLE_SM9)
|
|||||||
tools/sm9sign.c
|
tools/sm9sign.c
|
||||||
tools/sm9verify.c
|
tools/sm9verify.c
|
||||||
tools/sm9encrypt.c
|
tools/sm9encrypt.c
|
||||||
tools/sm9decrypt.c)
|
tools/sm9decrypt.c
|
||||||
|
tools/sm9exch.c)
|
||||||
list(APPEND tests sm9)
|
list(APPEND tests sm9)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -657,7 +659,11 @@ if (ENABLE_ZUC)
|
|||||||
message(STATUS "ENABLE_ZUC is ON")
|
message(STATUS "ENABLE_ZUC is ON")
|
||||||
add_definitions(-DENABLE_ZUC)
|
add_definitions(-DENABLE_ZUC)
|
||||||
list(APPEND src src/zuc.c src/zuc_modes.c)
|
list(APPEND src src/zuc.c src/zuc_modes.c)
|
||||||
list(APPEND tools tools/zuc.c)
|
list(APPEND tools
|
||||||
|
tools/zuc.c
|
||||||
|
tools/zuc256.c
|
||||||
|
tools/zuc_128_eea3.c
|
||||||
|
tools/zuc_128_eia3.c)
|
||||||
list(APPEND tests zuc)
|
list(APPEND tests zuc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -1010,7 +1016,7 @@ endif()
|
|||||||
#
|
#
|
||||||
set(CPACK_PACKAGE_NAME "GmSSL")
|
set(CPACK_PACKAGE_NAME "GmSSL")
|
||||||
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
||||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1168")
|
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1169")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
||||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|||||||
@@ -64,6 +64,216 @@ if(NOT "${TEST_STDOUT}" STREQUAL "${SECRET_MESSAGE}")
|
|||||||
message(FATAL_ERROR "stdout: ${TEST_STDOUT}")
|
message(FATAL_ERROR "stdout: ${TEST_STDOUT}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2keygen -pass P@ssw0rd -out sm2_peer.pem -pubout sm2_peer_pub.pem
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage init
|
||||||
|
-exch_keyout sm2exch_alice_ra.pem -exch_pass P@ssw0rd
|
||||||
|
-out sm2exch_ra.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage respond
|
||||||
|
-key sm2_peer.pem -pass P@ssw0rd -id Bob
|
||||||
|
-peer_pubkey sm2pub.pem -peer_id Alice -in sm2exch_ra.bin
|
||||||
|
-exch_keyout sm2exch_bob_rb.pem -exch_pass P@ssw0rd
|
||||||
|
-secret_state_out sm2exch_bob_secret_state.bin
|
||||||
|
-out sm2exch_rb_sb.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage confirm
|
||||||
|
-key sm2.pem -pass P@ssw0rd -id Alice
|
||||||
|
-peer_pubkey sm2_peer_pub.pem -peer_id Bob
|
||||||
|
-exch_key sm2exch_alice_ra.pem -exch_pass P@ssw0rd
|
||||||
|
-in sm2exch_rb_sb.bin
|
||||||
|
-keylen 48 -keyout sm2exch_alice_key.bin
|
||||||
|
-secret_state_out sm2exch_alice_secret_state.bin
|
||||||
|
-out sm2exch_sa.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage finish
|
||||||
|
-key sm2_peer.pem -pass P@ssw0rd -id Bob
|
||||||
|
-peer_pubkey sm2pub.pem -peer_id Alice
|
||||||
|
-exch_key sm2exch_bob_rb.pem -exch_pass P@ssw0rd
|
||||||
|
-secret_state sm2exch_bob_secret_state.bin
|
||||||
|
-in sm2exch_sa.bin
|
||||||
|
-keylen 48 -keyout sm2exch_bob_key.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E compare_files sm2exch_alice_key.bin sm2exch_bob_key.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "SM2 key exchange output mismatch")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E compare_files sm2exch_alice_secret_state.bin sm2exch_bob_secret_state.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "SM2 key exchange secret_state mismatch")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage init -bin
|
||||||
|
-exch_keyout sm2exch_bin_alice_ra.pem -exch_pass P@ssw0rd
|
||||||
|
-out sm2exch_bin_ra.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage respond -bin
|
||||||
|
-key sm2_peer.pem -pass P@ssw0rd -id Bob
|
||||||
|
-peer_pubkey sm2pub.pem -peer_id Alice -in sm2exch_bin_ra.bin
|
||||||
|
-exch_keyout sm2exch_bin_bob_rb.pem -exch_pass P@ssw0rd
|
||||||
|
-secret_state_out sm2exch_bin_bob_secret_state.bin
|
||||||
|
-out sm2exch_bin_rb_sb.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage confirm -bin
|
||||||
|
-key sm2.pem -pass P@ssw0rd -id Alice
|
||||||
|
-peer_pubkey sm2_peer_pub.pem -peer_id Bob
|
||||||
|
-exch_key sm2exch_bin_alice_ra.pem -exch_pass P@ssw0rd
|
||||||
|
-in sm2exch_bin_rb_sb.bin
|
||||||
|
-keylen 48 -keyout sm2exch_bin_alice_key.bin
|
||||||
|
-secret_state_out sm2exch_bin_alice_secret_state.bin
|
||||||
|
-out sm2exch_bin_sa.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage finish -bin
|
||||||
|
-key sm2_peer.pem -pass P@ssw0rd -id Bob
|
||||||
|
-peer_pubkey sm2pub.pem -peer_id Alice
|
||||||
|
-exch_key sm2exch_bin_bob_rb.pem -exch_pass P@ssw0rd
|
||||||
|
-secret_state sm2exch_bin_bob_secret_state.bin
|
||||||
|
-in sm2exch_bin_sa.bin
|
||||||
|
-keylen 48 -keyout sm2exch_bin_bob_key.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E compare_files sm2exch_bin_alice_key.bin sm2exch_bin_bob_key.bin
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "SM2 binary key exchange output mismatch")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage init
|
||||||
|
-exch_keyout sm2exch_stdio_alice_ra.pem -exch_pass P@ssw0rd
|
||||||
|
OUTPUT_FILE sm2exch_stdio_ra.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage respond
|
||||||
|
-key sm2_peer.pem -pass P@ssw0rd -id Bob
|
||||||
|
-peer_pubkey sm2pub.pem -peer_id Alice
|
||||||
|
-exch_keyout sm2exch_stdio_bob_rb.pem -exch_pass P@ssw0rd
|
||||||
|
-secret_state_out sm2exch_stdio_bob_secret_state.hex
|
||||||
|
INPUT_FILE sm2exch_stdio_ra.hex
|
||||||
|
OUTPUT_FILE sm2exch_stdio_rb_sb.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage confirm
|
||||||
|
-key sm2.pem -pass P@ssw0rd -id Alice
|
||||||
|
-peer_pubkey sm2_peer_pub.pem -peer_id Bob
|
||||||
|
-exch_key sm2exch_stdio_alice_ra.pem -exch_pass P@ssw0rd
|
||||||
|
-keylen 48 -keyout sm2exch_stdio_alice_key.hex
|
||||||
|
-secret_state_out sm2exch_stdio_alice_secret_state.hex
|
||||||
|
INPUT_FILE sm2exch_stdio_rb_sb.hex
|
||||||
|
OUTPUT_FILE sm2exch_stdio_sa.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bin/gmssl sm2exch -stage finish
|
||||||
|
-key sm2_peer.pem -pass P@ssw0rd -id Bob
|
||||||
|
-peer_pubkey sm2pub.pem -peer_id Alice
|
||||||
|
-exch_key sm2exch_stdio_bob_rb.pem -exch_pass P@ssw0rd
|
||||||
|
-secret_state sm2exch_stdio_bob_secret_state.hex
|
||||||
|
-keylen 48 -keyout sm2exch_stdio_bob_key.hex
|
||||||
|
INPUT_FILE sm2exch_stdio_sa.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "stderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E compare_files sm2exch_stdio_alice_key.hex sm2exch_stdio_bob_key.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
)
|
||||||
|
if(NOT ${TEST_RESULT} EQUAL 0)
|
||||||
|
message(FATAL_ERROR "SM2 stdio key exchange output mismatch")
|
||||||
|
endif()
|
||||||
|
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND bin/gmssl sm2sign -key sm2.pem -pass P@ssw0rd -id Alice -in message.txt -out sm2_id.sig
|
COMMAND bin/gmssl sm2sign -key sm2.pem -pass P@ssw0rd -id Alice -in message.txt -out sm2_id.sig
|
||||||
RESULT_VARIABLE TEST_RESULT
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/tool_helpers.cmake")
|
|||||||
|
|
||||||
set(SM4_KEY 0123456789abcdeffedcba9876543210)
|
set(SM4_KEY 0123456789abcdeffedcba9876543210)
|
||||||
set(SM4_IV 00000000000000000000000000000000)
|
set(SM4_IV 00000000000000000000000000000000)
|
||||||
set(SM4_HMAC_KEY 0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210)
|
|
||||||
set(SM4_XTS_KEY 0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff)
|
set(SM4_XTS_KEY 0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff)
|
||||||
set(SM4_FF1_KEY 2b7e151628aed2a6abf7158809cf4f3c)
|
set(SM4_FF1_KEY 2b7e151628aed2a6abf7158809cf4f3c)
|
||||||
set(SM4_TEXT "0123456789abcdef0123456789abcdef")
|
set(SM4_TEXT "0123456789abcdef0123456789abcdef")
|
||||||
@@ -23,23 +22,39 @@ gmssl_run(sm4_cbc -decrypt -key ${SM4_KEY} -iv ${SM4_IV}
|
|||||||
-in tool_sm4_cbc_kat.cipher -out tool_sm4_cbc_kat.decrypt)
|
-in tool_sm4_cbc_kat.cipher -out tool_sm4_cbc_kat.decrypt)
|
||||||
gmssl_files_equal(tool_sm4_cbc_kat.plain tool_sm4_cbc_kat.decrypt)
|
gmssl_files_equal(tool_sm4_cbc_kat.plain tool_sm4_cbc_kat.decrypt)
|
||||||
|
|
||||||
|
file(WRITE tool_sm4_unified_cbc_kat.plain "0123456789abcdef")
|
||||||
|
gmssl_run(sm4 -cbc -encrypt -key ${SM4_KEY} -iv ${SM4_IV}
|
||||||
|
-in tool_sm4_unified_cbc_kat.plain -out tool_sm4_unified_cbc_kat.cipher)
|
||||||
|
gmssl_expect_file_hex(tool_sm4_unified_cbc_kat.cipher
|
||||||
|
"e6887b77dbabb572ffa07fed7548b192ceaace11f2b90b94c2b7a4d9382e471e")
|
||||||
|
gmssl_run(sm4 -cbc -decrypt -key ${SM4_KEY} -iv ${SM4_IV}
|
||||||
|
-in tool_sm4_unified_cbc_kat.cipher -out tool_sm4_unified_cbc_kat.decrypt)
|
||||||
|
gmssl_files_equal(tool_sm4_unified_cbc_kat.plain tool_sm4_unified_cbc_kat.decrypt)
|
||||||
|
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_cbc sm4_cbc -key ${SM4_KEY} -iv ${SM4_IV})
|
gmssl_symmetric_roundtrip(tool_sm4_cbc sm4_cbc -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_ctr sm4_ctr -key ${SM4_KEY} -iv ${SM4_IV})
|
gmssl_symmetric_roundtrip(tool_sm4_ctr sm4_ctr -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_gcm sm4_gcm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
|
gmssl_symmetric_roundtrip(tool_sm4_gcm sm4_gcm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_cbc_sm3_hmac sm4_cbc_sm3_hmac -key ${SM4_HMAC_KEY} -iv ${SM4_IV} -aad_hex 001122)
|
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_ctr_sm3_hmac sm4_ctr_sm3_hmac -key ${SM4_HMAC_KEY} -iv ${SM4_IV} -aad_hex 001122)
|
gmssl_symmetric_roundtrip(tool_sm4_unified_cbc sm4 -cbc -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
|
gmssl_symmetric_roundtrip(tool_sm4_unified_ctr sm4 -ctr -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
|
gmssl_symmetric_roundtrip(tool_sm4_unified_gcm sm4 -gcm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
|
||||||
|
|
||||||
if(ENABLE_SM4_ECB)
|
if(ENABLE_SM4_ECB)
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_ecb sm4_ecb -key ${SM4_KEY})
|
gmssl_symmetric_roundtrip(tool_sm4_ecb sm4_ecb -key ${SM4_KEY})
|
||||||
|
gmssl_symmetric_roundtrip(tool_sm4_unified_ecb sm4 -ecb -key ${SM4_KEY})
|
||||||
endif()
|
endif()
|
||||||
if(ENABLE_SM4_CFB)
|
if(ENABLE_SM4_CFB)
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_cfb sm4_cfb -sbytes 16 -key ${SM4_KEY} -iv ${SM4_IV})
|
gmssl_symmetric_roundtrip(tool_sm4_cfb sm4_cfb -sbytes 16 -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
|
gmssl_symmetric_roundtrip(tool_sm4_unified_cfb sm4 -cfb -sbytes 16 -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
|
gmssl_symmetric_roundtrip(tool_sm4_unified_cfb8 sm4 -cfb -sbytes 1 -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
endif()
|
endif()
|
||||||
if(ENABLE_SM4_OFB)
|
if(ENABLE_SM4_OFB)
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_ofb sm4_ofb -key ${SM4_KEY} -iv ${SM4_IV})
|
gmssl_symmetric_roundtrip(tool_sm4_ofb sm4_ofb -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
|
gmssl_symmetric_roundtrip(tool_sm4_unified_ofb sm4 -ofb -key ${SM4_KEY} -iv ${SM4_IV})
|
||||||
endif()
|
endif()
|
||||||
if(ENABLE_SM4_CCM)
|
if(ENABLE_SM4_CCM)
|
||||||
gmssl_symmetric_roundtrip(tool_sm4_ccm sm4_ccm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
|
gmssl_symmetric_roundtrip(tool_sm4_ccm sm4_ccm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
|
||||||
|
gmssl_symmetric_roundtrip(tool_sm4_unified_ccm sm4 -ccm -key ${SM4_KEY} -iv 000000000000000000000000 -aad_hex 001122 -taglen 16)
|
||||||
endif()
|
endif()
|
||||||
if(ENABLE_SM4_XTS)
|
if(ENABLE_SM4_XTS)
|
||||||
file(WRITE tool_sm4_xts.plain "0123456789abcdef0123456789abcdef")
|
file(WRITE tool_sm4_xts.plain "0123456789abcdef0123456789abcdef")
|
||||||
@@ -48,6 +63,12 @@ if(ENABLE_SM4_XTS)
|
|||||||
gmssl_run(sm4_xts -decrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32
|
gmssl_run(sm4_xts -decrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32
|
||||||
-in tool_sm4_xts.cipher -out tool_sm4_xts.decrypt)
|
-in tool_sm4_xts.cipher -out tool_sm4_xts.decrypt)
|
||||||
gmssl_files_equal(tool_sm4_xts.plain tool_sm4_xts.decrypt)
|
gmssl_files_equal(tool_sm4_xts.plain tool_sm4_xts.decrypt)
|
||||||
|
file(WRITE tool_sm4_unified_xts.plain "0123456789abcdef0123456789abcdef")
|
||||||
|
gmssl_run(sm4 -xts -encrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32
|
||||||
|
-in tool_sm4_unified_xts.plain -out tool_sm4_unified_xts.cipher)
|
||||||
|
gmssl_run(sm4 -xts -decrypt -key ${SM4_XTS_KEY} -iv ${SM4_IV} -data_unit_size 32
|
||||||
|
-in tool_sm4_unified_xts.cipher -out tool_sm4_unified_xts.decrypt)
|
||||||
|
gmssl_files_equal(tool_sm4_unified_xts.plain tool_sm4_unified_xts.decrypt)
|
||||||
endif()
|
endif()
|
||||||
if(ENABLE_SM4_FF1)
|
if(ENABLE_SM4_FF1)
|
||||||
gmssl_expect_stdout("2326982895499381\n"
|
gmssl_expect_stdout("2326982895499381\n"
|
||||||
|
|||||||
@@ -24,8 +24,119 @@ gmssl_run(sm9keygen -alg sm9encrypt
|
|||||||
-in tool_sm9_enc_msk.pem -inpass ${SM9_PASS}
|
-in tool_sm9_enc_msk.pem -inpass ${SM9_PASS}
|
||||||
-id ${SM9_ID}
|
-id ${SM9_ID}
|
||||||
-out tool_sm9_enc_key.pem -outpass ${SM9_USER_PASS})
|
-out tool_sm9_enc_key.pem -outpass ${SM9_USER_PASS})
|
||||||
|
gmssl_run(sm9keygen -alg sm9keyagreement
|
||||||
|
-in tool_sm9_enc_msk.pem -inpass ${SM9_PASS}
|
||||||
|
-id Bob
|
||||||
|
-out tool_sm9_bob_exch_key.pem -outpass ${SM9_USER_PASS})
|
||||||
gmssl_run(sm9encrypt -pubmaster tool_sm9_enc_mpk.pem -id ${SM9_ID}
|
gmssl_run(sm9encrypt -pubmaster tool_sm9_enc_mpk.pem -id ${SM9_ID}
|
||||||
-in tool_sm9_message.txt -out tool_sm9_cipher.der)
|
-in tool_sm9_message.txt -out tool_sm9_cipher.der)
|
||||||
gmssl_run(sm9decrypt -key tool_sm9_enc_key.pem -pass ${SM9_USER_PASS} -id ${SM9_ID}
|
gmssl_run(sm9decrypt -key tool_sm9_enc_key.pem -pass ${SM9_USER_PASS} -id ${SM9_ID}
|
||||||
-in tool_sm9_cipher.der -out tool_sm9_plain.txt)
|
-in tool_sm9_cipher.der -out tool_sm9_plain.txt)
|
||||||
gmssl_expect_file_text(tool_sm9_plain.txt "${SM9_TEXT}")
|
gmssl_expect_file_text(tool_sm9_plain.txt "${SM9_TEXT}")
|
||||||
|
|
||||||
|
gmssl_run(sm9keygen -alg sm9keyagreement
|
||||||
|
-in tool_sm9_enc_msk.pem -inpass ${SM9_PASS}
|
||||||
|
-id ${SM9_ID}
|
||||||
|
-out tool_sm9_alice_exch_key.pem -outpass ${SM9_USER_PASS})
|
||||||
|
gmssl_run(sm9exch -stage init
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem -peer_id Bob
|
||||||
|
-exch_keyout tool_sm9_alice_ra.pem -out tool_sm9_ra.bin)
|
||||||
|
gmssl_run(sm9exch -stage respond
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_bob_exch_key.pem -pass ${SM9_USER_PASS} -id Bob
|
||||||
|
-peer_id ${SM9_ID} -in tool_sm9_ra.bin
|
||||||
|
-exch_keyout tool_sm9_bob_rb.pem -out tool_sm9_rb_sb.bin)
|
||||||
|
gmssl_run(sm9exch -stage confirm
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_alice_exch_key.pem -pass ${SM9_USER_PASS} -id ${SM9_ID}
|
||||||
|
-peer_id Bob -exch_key tool_sm9_alice_ra.pem
|
||||||
|
-in tool_sm9_rb_sb.bin
|
||||||
|
-keylen 48 -keyout tool_sm9_alice_shared_key.bin
|
||||||
|
-out tool_sm9_sa.bin)
|
||||||
|
gmssl_run(sm9exch -stage finish
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_bob_exch_key.pem -pass ${SM9_USER_PASS} -id Bob
|
||||||
|
-peer_id ${SM9_ID}
|
||||||
|
-exch_key tool_sm9_bob_rb.pem
|
||||||
|
-in tool_sm9_sa.bin
|
||||||
|
-keylen 48 -keyout tool_sm9_bob_shared_key.bin)
|
||||||
|
gmssl_files_equal(tool_sm9_alice_shared_key.bin tool_sm9_bob_shared_key.bin)
|
||||||
|
|
||||||
|
gmssl_run(sm9exch -stage init -bin
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem -peer_id Bob
|
||||||
|
-exch_keyout tool_sm9_bin_alice_ra.pem -out tool_sm9_bin_ra.bin)
|
||||||
|
gmssl_run(sm9exch -stage respond -bin
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_bob_exch_key.pem -pass ${SM9_USER_PASS} -id Bob
|
||||||
|
-peer_id ${SM9_ID} -in tool_sm9_bin_ra.bin
|
||||||
|
-exch_keyout tool_sm9_bin_bob_rb.pem -out tool_sm9_bin_rb_sb.bin)
|
||||||
|
gmssl_run(sm9exch -stage confirm -bin
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_alice_exch_key.pem -pass ${SM9_USER_PASS} -id ${SM9_ID}
|
||||||
|
-peer_id Bob -exch_key tool_sm9_bin_alice_ra.pem
|
||||||
|
-in tool_sm9_bin_rb_sb.bin
|
||||||
|
-keylen 48 -keyout tool_sm9_bin_alice_shared_key.bin
|
||||||
|
-out tool_sm9_bin_sa.bin)
|
||||||
|
gmssl_run(sm9exch -stage finish -bin
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_bob_exch_key.pem -pass ${SM9_USER_PASS} -id Bob
|
||||||
|
-peer_id ${SM9_ID}
|
||||||
|
-exch_key tool_sm9_bin_bob_rb.pem
|
||||||
|
-in tool_sm9_bin_sa.bin
|
||||||
|
-keylen 48 -keyout tool_sm9_bin_bob_shared_key.bin)
|
||||||
|
gmssl_files_equal(tool_sm9_bin_alice_shared_key.bin tool_sm9_bin_bob_shared_key.bin)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GMSSL_BIN} sm9exch -stage init
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem -peer_id Bob
|
||||||
|
-exch_keyout tool_sm9_stdio_alice_ra.pem
|
||||||
|
OUTPUT_FILE tool_sm9_stdio_ra.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT TEST_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "command failed: ${GMSSL_BIN} sm9exch -stage init\nstderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GMSSL_BIN} sm9exch -stage respond
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_bob_exch_key.pem -pass ${SM9_USER_PASS} -id Bob
|
||||||
|
-peer_id ${SM9_ID}
|
||||||
|
-exch_keyout tool_sm9_stdio_bob_rb.pem
|
||||||
|
INPUT_FILE tool_sm9_stdio_ra.hex
|
||||||
|
OUTPUT_FILE tool_sm9_stdio_rb_sb.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT TEST_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "command failed: ${GMSSL_BIN} sm9exch -stage respond\nstderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GMSSL_BIN} sm9exch -stage confirm
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_alice_exch_key.pem -pass ${SM9_USER_PASS} -id ${SM9_ID}
|
||||||
|
-peer_id Bob -exch_key tool_sm9_stdio_alice_ra.pem
|
||||||
|
-keylen 48 -keyout tool_sm9_stdio_alice_shared_key.hex
|
||||||
|
INPUT_FILE tool_sm9_stdio_rb_sb.hex
|
||||||
|
OUTPUT_FILE tool_sm9_stdio_sa.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT TEST_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "command failed: ${GMSSL_BIN} sm9exch -stage confirm\nstderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GMSSL_BIN} sm9exch -stage finish
|
||||||
|
-pubmaster tool_sm9_enc_mpk.pem
|
||||||
|
-key tool_sm9_bob_exch_key.pem -pass ${SM9_USER_PASS} -id Bob
|
||||||
|
-peer_id ${SM9_ID}
|
||||||
|
-exch_key tool_sm9_stdio_bob_rb.pem
|
||||||
|
-keylen 48 -keyout tool_sm9_stdio_bob_shared_key.hex
|
||||||
|
INPUT_FILE tool_sm9_stdio_sa.hex
|
||||||
|
RESULT_VARIABLE TEST_RESULT
|
||||||
|
ERROR_VARIABLE TEST_STDERR
|
||||||
|
)
|
||||||
|
if(NOT TEST_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "command failed: ${GMSSL_BIN} sm9exch -stage finish\nstderr: ${TEST_STDERR}")
|
||||||
|
endif()
|
||||||
|
gmssl_files_equal(tool_sm9_stdio_alice_shared_key.hex tool_sm9_stdio_bob_shared_key.hex)
|
||||||
|
|||||||
@@ -8,3 +8,25 @@ gmssl_run(zuc -key ${ZUC_KEY} -iv ${ZUC_IV} -in tool_zuc.plain -out tool_zuc.cip
|
|||||||
gmssl_expect_file_hex(tool_zuc.cipher "178fec4735b5b4edbfed84d4fc7cda00")
|
gmssl_expect_file_hex(tool_zuc.cipher "178fec4735b5b4edbfed84d4fc7cda00")
|
||||||
gmssl_run(zuc -key ${ZUC_KEY} -iv ${ZUC_IV} -in tool_zuc.cipher -out tool_zuc.decrypt)
|
gmssl_run(zuc -key ${ZUC_KEY} -iv ${ZUC_IV} -in tool_zuc.cipher -out tool_zuc.decrypt)
|
||||||
gmssl_files_equal(tool_zuc.plain tool_zuc.decrypt)
|
gmssl_files_equal(tool_zuc.plain tool_zuc.decrypt)
|
||||||
|
|
||||||
|
gmssl_run(zuc_128_eea3
|
||||||
|
-key 173d14ba5003731d7a60049470f00a29
|
||||||
|
-count 0x66035492 -bearer 15 -direction 0
|
||||||
|
-in_hex 6cf65340735552ab0c9752fa6f9025fe0bd675d9005875b2
|
||||||
|
-out tool_zuc_128_eea3.cipher)
|
||||||
|
gmssl_expect_file_hex(tool_zuc_128_eea3.cipher
|
||||||
|
"a6c85fc66afb8533aafc2518dfe784940ee1e4b030238cc8")
|
||||||
|
gmssl_expect_stdout("390a91b7\n" zuc_128_eia3
|
||||||
|
-key 00000000000000000000000000000000
|
||||||
|
-count 0 -bearer 0 -direction 0 -in_hex 00)
|
||||||
|
|
||||||
|
gmssl_run(zuc256
|
||||||
|
-key 0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
-iv 0000000000000000000000000000000000000000000000
|
||||||
|
-in tool_zuc.plain -out tool_zuc256.cipher)
|
||||||
|
gmssl_expect_file_hex(tool_zuc256.cipher "68e108e51a361ad5e2c509585ad9ae65")
|
||||||
|
gmssl_run(zuc256
|
||||||
|
-key 0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
-iv 0000000000000000000000000000000000000000000000
|
||||||
|
-in tool_zuc256.cipher -out tool_zuc256.decrypt)
|
||||||
|
gmssl_files_equal(tool_zuc.plain tool_zuc256.decrypt)
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gmssl/digest.h>
|
||||||
|
#include <gmssl/tls.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -31,6 +34,40 @@ extern "C" {
|
|||||||
#define QUIC_TRANSPORT_PARAM_MAX_SIZE 512
|
#define QUIC_TRANSPORT_PARAM_MAX_SIZE 512
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QUIC_packet_initial = 0,
|
||||||
|
QUIC_packet_0_rtt = 1,
|
||||||
|
QUIC_packet_handshake = 2,
|
||||||
|
QUIC_packet_retry = 3,
|
||||||
|
} QUIC_PACKET_TYPE;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QUIC_frame_padding = 0x00,
|
||||||
|
QUIC_frame_ping = 0x01,
|
||||||
|
QUIC_frame_ack = 0x02,
|
||||||
|
QUIC_frame_ack_ecn = 0x03,
|
||||||
|
QUIC_frame_reset_stream = 0x04,
|
||||||
|
QUIC_frame_stop_sending = 0x05,
|
||||||
|
QUIC_frame_crypto = 0x06,
|
||||||
|
QUIC_frame_new_token = 0x07,
|
||||||
|
QUIC_frame_stream_base = 0x08,
|
||||||
|
QUIC_frame_max_data = 0x10,
|
||||||
|
QUIC_frame_max_stream_data = 0x11,
|
||||||
|
QUIC_frame_max_streams_bidi = 0x12,
|
||||||
|
QUIC_frame_max_streams_uni = 0x13,
|
||||||
|
QUIC_frame_data_blocked = 0x14,
|
||||||
|
QUIC_frame_stream_data_blocked = 0x15,
|
||||||
|
QUIC_frame_streams_blocked_bidi = 0x16,
|
||||||
|
QUIC_frame_streams_blocked_uni = 0x17,
|
||||||
|
QUIC_frame_new_connection_id = 0x18,
|
||||||
|
QUIC_frame_retire_connection_id = 0x19,
|
||||||
|
QUIC_frame_path_challenge = 0x1a,
|
||||||
|
QUIC_frame_path_response = 0x1b,
|
||||||
|
QUIC_frame_connection_close = 0x1c,
|
||||||
|
QUIC_frame_connection_close_app = 0x1d,
|
||||||
|
QUIC_frame_handshake_done = 0x1e,
|
||||||
|
} QUIC_FRAME_TYPE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
QUIC_transport_param_original_destination_connection_id = 0x00,
|
QUIC_transport_param_original_destination_connection_id = 0x00,
|
||||||
QUIC_transport_param_max_idle_timeout = 0x01,
|
QUIC_transport_param_max_idle_timeout = 0x01,
|
||||||
@@ -70,6 +107,25 @@ typedef struct {
|
|||||||
uint8_t hp[QUIC_INITIAL_HP_KEY_SIZE]; // hp = header protection key
|
uint8_t hp[QUIC_INITIAL_HP_KEY_SIZE]; // hp = header protection key
|
||||||
} QUIC_INITIAL_KEYS;
|
} QUIC_INITIAL_KEYS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int cipher_suite;
|
||||||
|
uint8_t key[QUIC_INITIAL_KEY_SIZE];
|
||||||
|
uint8_t iv[QUIC_INITIAL_IV_SIZE];
|
||||||
|
uint8_t hp[QUIC_INITIAL_HP_KEY_SIZE]; /* hp is Header Protection. QUIC protects packet number bytes and selected header bits separately from payload AEAD. */
|
||||||
|
} QUIC_PACKET_KEYS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int type;
|
||||||
|
uint64_t packet_number;
|
||||||
|
size_t packet_len;
|
||||||
|
uint8_t dcid[20];
|
||||||
|
size_t dcid_len;
|
||||||
|
uint8_t scid[20];
|
||||||
|
size_t scid_len;
|
||||||
|
uint8_t plaintext[4096];
|
||||||
|
size_t plaintext_len;
|
||||||
|
} QUIC_DECRYPTED_PACKET;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
uint8_t data[QUIC_TRANSPORT_PARAM_MAX_SIZE];
|
uint8_t data[QUIC_TRANSPORT_PARAM_MAX_SIZE];
|
||||||
@@ -104,6 +160,30 @@ int quic_derive_initial_secrets(const uint8_t *dcid, size_t dcid_len, QUIC_INITI
|
|||||||
int quic_derive_initial_client_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys);
|
int quic_derive_initial_client_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys);
|
||||||
int quic_derive_initial_server_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys);
|
int quic_derive_initial_server_keys(const QUIC_INITIAL_SECRETS *secrets, QUIC_INITIAL_KEYS *keys);
|
||||||
int quic_derive_initial_keys(const uint8_t secret[QUIC_INITIAL_SECRET_SIZE], QUIC_INITIAL_KEYS *keys);
|
int quic_derive_initial_keys(const uint8_t secret[QUIC_INITIAL_SECRET_SIZE], QUIC_INITIAL_KEYS *keys);
|
||||||
|
int quic_packet_keys_derive(const DIGEST *digest, const uint8_t secret[32], int cipher_suite, QUIC_PACKET_KEYS *keys);
|
||||||
|
int quic_packet_keys_from_initial(const QUIC_INITIAL_KEYS *initial_keys, QUIC_PACKET_KEYS *keys);
|
||||||
|
|
||||||
|
int quic_packet_total_length(const uint8_t *packet, size_t packet_len, size_t *total_len);
|
||||||
|
int quic_long_packet_decrypt(const QUIC_PACKET_KEYS *keys, const uint8_t *packet, size_t packet_len, int expected_type, QUIC_DECRYPTED_PACKET *out);
|
||||||
|
int quic_long_packet_encrypt(const QUIC_PACKET_KEYS *keys, int type, const uint8_t *dcid, size_t dcid_len,
|
||||||
|
const uint8_t *scid, size_t scid_len, uint64_t packet_number, const uint8_t *frames, size_t frames_len,
|
||||||
|
uint8_t *packet, size_t *packet_len);
|
||||||
|
int quic_short_packet_decrypt(const QUIC_PACKET_KEYS *keys, const uint8_t *packet, size_t packet_len,
|
||||||
|
const uint8_t *dcid, size_t dcid_len, QUIC_DECRYPTED_PACKET *out);
|
||||||
|
int quic_short_packet_encrypt(const QUIC_PACKET_KEYS *keys, const uint8_t *dcid, size_t dcid_len,
|
||||||
|
uint64_t packet_number, const uint8_t *frames, size_t frames_len, uint8_t *packet, size_t *packet_len);
|
||||||
|
|
||||||
|
int quic_client_hello_to_bytes_ex(TLS_CONNECT *conn, const QUIC_TRANSPORT_PARAMS *params, uint8_t **out, size_t *outlen);
|
||||||
|
int quic_client_hello_to_bytes(TLS_CONNECT *conn, uint8_t **out, size_t *outlen);
|
||||||
|
int quic_server_hello_to_bytes(TLS_CONNECT *conn, uint8_t **out, size_t *outlen);
|
||||||
|
|
||||||
|
const char *quic_packet_type_name(int type);
|
||||||
|
const char *quic_frame_type_name(uint64_t type);
|
||||||
|
const char *quic_encryption_level_name(int level);
|
||||||
|
int quic_packet_print(FILE *fp, int fmt, int ind, const uint8_t *packet, size_t packetlen);
|
||||||
|
int quic_frames_print(FILE *fp, int fmt, int ind, int level, const uint8_t *frames, size_t frameslen);
|
||||||
|
int quic_frame_print(FILE *fp, int fmt, int ind, int level, const uint8_t **in, size_t *inlen);
|
||||||
|
int quic_crypto_data_print(FILE *fp, int fmt, int ind, int level, const uint8_t *data, size_t datalen);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
#define GMSSL_VERSION_NUM 30300
|
#define GMSSL_VERSION_NUM 30300
|
||||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1168"
|
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1169"
|
||||||
|
|
||||||
int gmssl_version_num(void);
|
int gmssl_version_num(void);
|
||||||
const char *gmssl_version_str(void);
|
const char *gmssl_version_str(void);
|
||||||
|
|||||||
1222
src/quic.c
1222
src/quic.c
File diff suppressed because it is too large
Load Diff
897
src/sm9_cms.c
Normal file
897
src/sm9_cms.c
Normal file
@@ -0,0 +1,897 @@
|
|||||||
|
/*
|
||||||
|
GM/T 0081-2020 ASN.1 definitions
|
||||||
|
|
||||||
|
IdentifierRevocationLists ::= SET OF IdentifierRevocationList
|
||||||
|
|
||||||
|
ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||||
|
|
||||||
|
DigestAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||||
|
|
||||||
|
DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||||
|
|
||||||
|
KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||||
|
|
||||||
|
Version ::= INTEGER(1)
|
||||||
|
|
||||||
|
ContentInfo ::= SEQUENCE {
|
||||||
|
contentType ContentType,
|
||||||
|
content [0] EXPLICIT contentType OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentType ::= OBJECT IDENTIFIER
|
||||||
|
|
||||||
|
Identifier ::= SEQUENCE {
|
||||||
|
version EXPLICIT VERSION DEFAULT v1,
|
||||||
|
ibcType OBJECT IDENTIFIER,
|
||||||
|
ibcTypeAlias [0] OCTET STRING OPTIONAL,
|
||||||
|
identityData OCTET STRING,
|
||||||
|
validStart UTCTIME,
|
||||||
|
validEnd [1] UTCTIME OPTIONAL,
|
||||||
|
extensions [2] Extensions OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
||||||
|
|
||||||
|
Extension ::= SEQUENCE {
|
||||||
|
extnID OBJECT IDENTIFIER,
|
||||||
|
critical BOOLEAN DEFAULT FALSE,
|
||||||
|
extnValue OCTET STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
DistricInfo ::= SEQUENCE {
|
||||||
|
district IA5String,
|
||||||
|
districtNo INTEGER,
|
||||||
|
}
|
||||||
|
|
||||||
|
Validity ::= SEQUENCE {
|
||||||
|
notBefore Time,
|
||||||
|
notAfter Time,
|
||||||
|
Time ::= CHOICE {
|
||||||
|
utcTime UTCTime,
|
||||||
|
generalTime GeneralizedTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IBCSysParamsPublishInfo ::= SEQUENCE {
|
||||||
|
ibcSysParams IBCSysParams,
|
||||||
|
signatureAlgorithm OBJECT IDENTIFIER,
|
||||||
|
signatureValue BIT STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
AlgorithmIdentifier ::= SEQUENCE {
|
||||||
|
Algorithm OBJECT IDENTIFIER,
|
||||||
|
Parameters ANY DEFINED BY algorithm OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
BeSignParamsPubInfo ::= SEQUENCE {
|
||||||
|
ibcSysParams IBCSysParams,
|
||||||
|
signatureAlgorithm OBJECT IDENTIFIER
|
||||||
|
}
|
||||||
|
|
||||||
|
IDAppAttr ::= SEQUENCE {
|
||||||
|
versoin Version DEFAULT v1,
|
||||||
|
serialNumber IdentifierSerialNumber,
|
||||||
|
subjectId Identifier,
|
||||||
|
sysParamsPublishInfo IBCSysParamsPublishInfo,
|
||||||
|
extensions [0] EXPLICIT Externsions OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
version ::= INTEGER { v1(0) }
|
||||||
|
|
||||||
|
IdentifierSerialNumber ::= INTEGER
|
||||||
|
|
||||||
|
Externsions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
||||||
|
|
||||||
|
Data ::= OCTET STRING
|
||||||
|
|
||||||
|
SignedData ::= SEQUENCE {
|
||||||
|
version Version,
|
||||||
|
digestAlgorithms DigestAlgorithmIdentifiers,
|
||||||
|
contentInfo ContentInfo,
|
||||||
|
ibcSysParamsPublishInfos [0] IMPLICIT IBCSysParamsPublishInfos OPTIONAL,
|
||||||
|
irls [1] IMPLICIT IdentifierRevocationLists OPTIONAL,
|
||||||
|
signerInfos SignerInfos
|
||||||
|
}
|
||||||
|
|
||||||
|
IBCSysParamsPublishInfos ::= SET OF IBCSysParamsPublishInfo
|
||||||
|
|
||||||
|
DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
|
||||||
|
|
||||||
|
SignerInfos ::= SET OF SignerInfo
|
||||||
|
|
||||||
|
SignerInfo ::= SEQUENCE {
|
||||||
|
version Version,
|
||||||
|
issuerIdentifier Identifier,
|
||||||
|
digestAlgorithm DigestAlgorithmIdentifier,
|
||||||
|
authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
|
||||||
|
digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
|
||||||
|
encryptedDigest SM9Signature,
|
||||||
|
unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvelopedData ::= SEQUENCE {
|
||||||
|
version Version,
|
||||||
|
recipientInfos RecipientInfos,
|
||||||
|
encryptedContentInfo EncryptedContentInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
RecipientInfos ::= SET OF RecipientInfo
|
||||||
|
|
||||||
|
EncryptedContentInfo ::= SEQUENCE {
|
||||||
|
contentType ContentType,
|
||||||
|
contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
|
||||||
|
sharedInfo [0] OCTET STRING OPTIONAL,
|
||||||
|
sharedInfo2 [1] OCTET STRING OPTIONAL,
|
||||||
|
encryptedContent [2] IMPLICIT EncryptedContent OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
EncryptedContent ::= OCTET STRING
|
||||||
|
|
||||||
|
RecipientInfo ::= SEQUENCE {
|
||||||
|
Version Version,
|
||||||
|
issuerIdentifier Identifier,
|
||||||
|
keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
|
||||||
|
encryptedKey SM9cipher
|
||||||
|
}
|
||||||
|
|
||||||
|
SignedAndEnvelopedData ::= SEQUENCE {
|
||||||
|
version Version,
|
||||||
|
recipientInfos RecipientInfos,
|
||||||
|
digestAlgorithms DigestAlgorithmIdentifiers,
|
||||||
|
encryptedContentInfo EncryptedContentInfo,
|
||||||
|
idAppAttrInfos [0] IMPLICIT IDAppAttrInfos OPTIONAL,
|
||||||
|
irls [1] IMPLICIT IdentifierRevocationLists OPTIONAL,
|
||||||
|
signerInfos SignerInfos
|
||||||
|
}
|
||||||
|
|
||||||
|
EncryptedData ::= SEQUENCE {
|
||||||
|
Version Version,
|
||||||
|
encryptedContentInfo EncryptedContentInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
//-- 这之后的类型都需要实现
|
||||||
|
KeyAgreementInfo ::= SEQUENCE {
|
||||||
|
version Version(1),
|
||||||
|
tempKey SM9MastEncryptPublicKey,
|
||||||
|
userIDA OCTET STRING
|
||||||
|
userIDB OCTET STRING
|
||||||
|
hid OCTET STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
IdentifierRevocationList ::= SEQUENCE {
|
||||||
|
tbsIdList TBSIdList,
|
||||||
|
signInfos SignerInfos
|
||||||
|
}
|
||||||
|
|
||||||
|
TBSIdList ::= SEQUENCE {
|
||||||
|
Version(1) Version,
|
||||||
|
signatureOID AlgorithmIdentifier,
|
||||||
|
issuerIdentifier Identifier,
|
||||||
|
thisUpdate GeneralizedTime,
|
||||||
|
nextUpdate [0] GeneralizedTime OPTIONAL,
|
||||||
|
revokedIds RevokedIds,
|
||||||
|
irlExtensions [1] EXPLICIT Extensions OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
Version ::= INTEGER(1)
|
||||||
|
|
||||||
|
RevokedIds ::= SEQUENCE OF RevokedId
|
||||||
|
|
||||||
|
RevokedId ::= SEQUENCE {
|
||||||
|
id OCTET STRING,
|
||||||
|
revocationDate GeneralizedTime,
|
||||||
|
IrlEntryExtensions [0] Extensions OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
IBCSysParams ::= SEQUENCE {
|
||||||
|
version INTEGER { v2(2) },
|
||||||
|
districtName IA5String,
|
||||||
|
districtSerial INTEGER,
|
||||||
|
validity ValidityPeriod,
|
||||||
|
ibcPublicParameters IBCPublicParameters,
|
||||||
|
ibcIdentityType OBJECT IDENTIFIER,
|
||||||
|
issuerID Identifier,
|
||||||
|
ibcParamExtensions IBCParamExtensions OPTIONAL
|
||||||
|
}
|
||||||
|
|
||||||
|
IBCPublicParameters ::= SEQUENCE (1..MAX) OF IBCPublicParameter
|
||||||
|
|
||||||
|
IBCPublicParameter ::= SEQUENCE {
|
||||||
|
ibcAlgorithm OBJECT IDENTIFIER,
|
||||||
|
publicParameterData OCTET STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
SM9PublicParameterData ::= SEQUENCE {
|
||||||
|
pkgID OCTET STRING,
|
||||||
|
encMastPublicKey SM9EncryptMasterPublicKey,
|
||||||
|
signMastPublicKey SM9SignMasterPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
IBCParamExtensions ::= SEQUENCE OF IBCParamExtension
|
||||||
|
|
||||||
|
IBCParamExtension ::= SEQUENCE {
|
||||||
|
ibcParamExtensionOID OBJECT IDENTIFIER,
|
||||||
|
ibcParamExtensionValue OCTET STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
IbcParamExt OBJECT IDENTIFIER ::= {
|
||||||
|
ibcs ibcs3(3) parameter-extensions(2)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gmssl/asn1.h>
|
||||||
|
#include <gmssl/sm9.h>
|
||||||
|
#include <gmssl/x509.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
|
||||||
|
int sm9_cms_algorithm_identifier_to_der(
|
||||||
|
const uint32_t *algorithm, size_t algorithm_cnt,
|
||||||
|
const uint8_t *parameters, size_t parameters_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (asn1_object_identifier_to_der(algorithm, algorithm_cnt, NULL, &len) != 1
|
||||||
|
|| asn1_any_to_der(parameters, parameters_len, NULL, &len) < 0
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_object_identifier_to_der(algorithm, algorithm_cnt, out, outlen) != 1
|
||||||
|
|| asn1_any_to_der(parameters, parameters_len, out, outlen) < 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_algorithm_identifier_from_der(
|
||||||
|
uint32_t *algorithm, size_t *algorithm_cnt,
|
||||||
|
const uint8_t **parameters, size_t *parameters_len,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const uint8_t *d;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
*parameters = NULL;
|
||||||
|
*parameters_len = 0;
|
||||||
|
|
||||||
|
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||||
|
if (ret < 0) error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (asn1_object_identifier_from_der(algorithm, algorithm_cnt, &d, &dlen) != 1
|
||||||
|
|| asn1_any_from_der(parameters, parameters_len, &d, &dlen) < 0
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_extensions_to_der(const uint8_t *extensions, size_t extensions_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
if (asn1_sequence_of_to_der(extensions, extensions_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_extensions_from_der(const uint8_t **extensions, size_t *extensions_len,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = asn1_sequence_of_from_der(extensions, extensions_len, in, inlen)) != 1) {
|
||||||
|
if (ret < 0) error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_explicit_extensions_to_der(int index,
|
||||||
|
const uint8_t *extensions, size_t extensions_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (!extensions) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (sm9_cms_extensions_to_der(extensions, extensions_len, NULL, &len) != 1
|
||||||
|
|| asn1_explicit_header_to_der(index, len, out, outlen) != 1
|
||||||
|
|| sm9_cms_extensions_to_der(extensions, extensions_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_explicit_extensions_from_der(int index,
|
||||||
|
const uint8_t **extensions, size_t *extensions_len,
|
||||||
|
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 {
|
||||||
|
*extensions = NULL;
|
||||||
|
*extensions_len = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (sm9_cms_extensions_from_der(extensions, extensions_len, &d, &dlen) != 1
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_implicit_extensions_to_der(int index,
|
||||||
|
const uint8_t *extensions, size_t extensions_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
if (!extensions) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (asn1_implicit_sequence_to_der(index, extensions, extensions_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_implicit_extensions_from_der(int index,
|
||||||
|
const uint8_t **extensions, size_t *extensions_len,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = asn1_implicit_sequence_from_der(index, extensions, extensions_len, in, inlen)) < 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_key_agreement_info_to_der(
|
||||||
|
int version,
|
||||||
|
const SM9_ENC_MASTER_KEY *temp_key,
|
||||||
|
const uint8_t *user_id_a, size_t user_id_a_len,
|
||||||
|
const uint8_t *user_id_b, size_t user_id_b_len,
|
||||||
|
const uint8_t *hid, size_t hid_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
|
||||||
|
|| sm9_enc_master_public_key_to_der(temp_key, NULL, &len) != 1
|
||||||
|
|| asn1_octet_string_to_der(user_id_a, user_id_a_len, NULL, &len) != 1
|
||||||
|
|| asn1_octet_string_to_der(user_id_b, user_id_b_len, NULL, &len) != 1
|
||||||
|
|| asn1_octet_string_to_der(hid, hid_len, NULL, &len) != 1
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_int_to_der(version, out, outlen) != 1
|
||||||
|
|| sm9_enc_master_public_key_to_der(temp_key, out, outlen) != 1
|
||||||
|
|| asn1_octet_string_to_der(user_id_a, user_id_a_len, out, outlen) != 1
|
||||||
|
|| asn1_octet_string_to_der(user_id_b, user_id_b_len, out, outlen) != 1
|
||||||
|
|| asn1_octet_string_to_der(hid, hid_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_key_agreement_info_from_der(
|
||||||
|
int *version,
|
||||||
|
SM9_ENC_MASTER_KEY *temp_key,
|
||||||
|
const uint8_t **user_id_a, size_t *user_id_a_len,
|
||||||
|
const uint8_t **user_id_b, size_t *user_id_b_len,
|
||||||
|
const uint8_t **hid, size_t *hid_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
|
||||||
|
|| sm9_enc_master_public_key_from_der(temp_key, &d, &dlen) != 1
|
||||||
|
|| asn1_octet_string_from_der(user_id_a, user_id_a_len, &d, &dlen) != 1
|
||||||
|
|| asn1_octet_string_from_der(user_id_b, user_id_b_len, &d, &dlen) != 1
|
||||||
|
|| asn1_octet_string_from_der(hid, hid_len, &d, &dlen) != 1
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (*version != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_revoked_id_to_der(
|
||||||
|
const uint8_t *id, size_t id_len,
|
||||||
|
time_t revocation_date,
|
||||||
|
const uint8_t *irl_entry_extensions, size_t irl_entry_extensions_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (asn1_octet_string_to_der(id, id_len, NULL, &len) != 1
|
||||||
|
|| asn1_generalized_time_to_der(revocation_date, NULL, &len) != 1
|
||||||
|
|| sm9_cms_implicit_extensions_to_der(0, irl_entry_extensions, irl_entry_extensions_len, NULL, &len) < 0
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_octet_string_to_der(id, id_len, out, outlen) != 1
|
||||||
|
|| asn1_generalized_time_to_der(revocation_date, out, outlen) != 1
|
||||||
|
|| sm9_cms_implicit_extensions_to_der(0, irl_entry_extensions, irl_entry_extensions_len, out, outlen) < 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_revoked_id_from_der(
|
||||||
|
const uint8_t **id, size_t *id_len,
|
||||||
|
time_t *revocation_date,
|
||||||
|
const uint8_t **irl_entry_extensions, size_t *irl_entry_extensions_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_octet_string_from_der(id, id_len, &d, &dlen) != 1
|
||||||
|
|| asn1_generalized_time_from_der(revocation_date, &d, &dlen) != 1
|
||||||
|
|| sm9_cms_implicit_extensions_from_der(0, irl_entry_extensions, irl_entry_extensions_len, &d, &dlen) < 0
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_revoked_ids_to_der(const uint8_t *revoked_ids, size_t revoked_ids_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
if (asn1_sequence_of_to_der(revoked_ids, revoked_ids_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_revoked_ids_from_der(const uint8_t **revoked_ids, size_t *revoked_ids_len,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = asn1_sequence_of_from_der(revoked_ids, revoked_ids_len, in, inlen)) != 1) {
|
||||||
|
if (ret < 0) error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_tbs_id_list_to_der(
|
||||||
|
int version,
|
||||||
|
const uint32_t *signature_oid, size_t signature_oid_cnt,
|
||||||
|
const uint8_t *signature_params, size_t signature_params_len,
|
||||||
|
const uint8_t *issuer_identifier, size_t issuer_identifier_len,
|
||||||
|
time_t this_update, time_t next_update,
|
||||||
|
const uint8_t *revoked_ids, size_t revoked_ids_len,
|
||||||
|
const uint8_t *irl_extensions, size_t irl_extensions_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
|
||||||
|
|| sm9_cms_algorithm_identifier_to_der(signature_oid, signature_oid_cnt,
|
||||||
|
signature_params, signature_params_len, NULL, &len) != 1
|
||||||
|
|| asn1_any_to_der(issuer_identifier, issuer_identifier_len, NULL, &len) != 1
|
||||||
|
|| asn1_generalized_time_to_der(this_update, NULL, &len) != 1
|
||||||
|
|| asn1_implicit_generalized_time_to_der(0, next_update, NULL, &len) < 0
|
||||||
|
|| sm9_cms_revoked_ids_to_der(revoked_ids, revoked_ids_len, NULL, &len) != 1
|
||||||
|
|| sm9_cms_explicit_extensions_to_der(1, irl_extensions, irl_extensions_len, NULL, &len) < 0
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_int_to_der(version, out, outlen) != 1
|
||||||
|
|| sm9_cms_algorithm_identifier_to_der(signature_oid, signature_oid_cnt,
|
||||||
|
signature_params, signature_params_len, out, outlen) != 1
|
||||||
|
|| asn1_any_to_der(issuer_identifier, issuer_identifier_len, out, outlen) != 1
|
||||||
|
|| asn1_generalized_time_to_der(this_update, out, outlen) != 1
|
||||||
|
|| asn1_implicit_generalized_time_to_der(0, next_update, out, outlen) < 0
|
||||||
|
|| sm9_cms_revoked_ids_to_der(revoked_ids, revoked_ids_len, out, outlen) != 1
|
||||||
|
|| sm9_cms_explicit_extensions_to_der(1, irl_extensions, irl_extensions_len, out, outlen) < 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_tbs_id_list_from_der(
|
||||||
|
int *version,
|
||||||
|
uint32_t *signature_oid, size_t *signature_oid_cnt,
|
||||||
|
const uint8_t **signature_params, size_t *signature_params_len,
|
||||||
|
const uint8_t **issuer_identifier, size_t *issuer_identifier_len,
|
||||||
|
time_t *this_update, time_t *next_update,
|
||||||
|
const uint8_t **revoked_ids, size_t *revoked_ids_len,
|
||||||
|
const uint8_t **irl_extensions, size_t *irl_extensions_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
|
||||||
|
|| sm9_cms_algorithm_identifier_from_der(signature_oid, signature_oid_cnt,
|
||||||
|
signature_params, signature_params_len, &d, &dlen) != 1
|
||||||
|
|| asn1_any_from_der(issuer_identifier, issuer_identifier_len, &d, &dlen) != 1
|
||||||
|
|| asn1_generalized_time_from_der(this_update, &d, &dlen) != 1
|
||||||
|
|| asn1_implicit_generalized_time_from_der(0, next_update, &d, &dlen) < 0
|
||||||
|
|| sm9_cms_revoked_ids_from_der(revoked_ids, revoked_ids_len, &d, &dlen) != 1
|
||||||
|
|| sm9_cms_explicit_extensions_from_der(1, irl_extensions, irl_extensions_len, &d, &dlen) < 0
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (*version != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_signer_infos_to_der(const uint8_t *signer_infos, size_t signer_infos_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
if (asn1_set_of_to_der(signer_infos, signer_infos_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_signer_infos_from_der(const uint8_t **signer_infos, size_t *signer_infos_len,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = asn1_set_of_from_der(signer_infos, signer_infos_len, in, inlen)) != 1) {
|
||||||
|
if (ret < 0) error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_identifier_revocation_list_to_der(
|
||||||
|
const uint8_t *tbs_id_list, size_t tbs_id_list_len,
|
||||||
|
const uint8_t *signer_infos, size_t signer_infos_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (asn1_any_to_der(tbs_id_list, tbs_id_list_len, NULL, &len) != 1
|
||||||
|
|| sm9_cms_signer_infos_to_der(signer_infos, signer_infos_len, NULL, &len) != 1
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_any_to_der(tbs_id_list, tbs_id_list_len, out, outlen) != 1
|
||||||
|
|| sm9_cms_signer_infos_to_der(signer_infos, signer_infos_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_identifier_revocation_list_from_der(
|
||||||
|
const uint8_t **tbs_id_list, size_t *tbs_id_list_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_any_from_der(tbs_id_list, tbs_id_list_len, &d, &dlen) != 1
|
||||||
|
|| sm9_cms_signer_infos_from_der(signer_infos, signer_infos_len, &d, &dlen) != 1
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_validity_period_to_der(time_t not_before, time_t not_after,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
return x509_validity_to_der(not_before, not_after, out, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_validity_period_from_der(time_t *not_before, time_t *not_after,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
return x509_validity_from_der(not_before, not_after, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_public_parameter_to_der(
|
||||||
|
const uint32_t *ibc_algorithm, size_t ibc_algorithm_cnt,
|
||||||
|
const uint8_t *public_parameter_data, size_t public_parameter_data_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (asn1_object_identifier_to_der(ibc_algorithm, ibc_algorithm_cnt, NULL, &len) != 1
|
||||||
|
|| asn1_octet_string_to_der(public_parameter_data, public_parameter_data_len, NULL, &len) != 1
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_object_identifier_to_der(ibc_algorithm, ibc_algorithm_cnt, out, outlen) != 1
|
||||||
|
|| asn1_octet_string_to_der(public_parameter_data, public_parameter_data_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_public_parameter_from_der(
|
||||||
|
uint32_t *ibc_algorithm, size_t *ibc_algorithm_cnt,
|
||||||
|
const uint8_t **public_parameter_data, size_t *public_parameter_data_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_object_identifier_from_der(ibc_algorithm, ibc_algorithm_cnt, &d, &dlen) != 1
|
||||||
|
|| asn1_octet_string_from_der(public_parameter_data, public_parameter_data_len, &d, &dlen) != 1
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_public_parameters_to_der(
|
||||||
|
const uint8_t *ibc_public_parameters, size_t ibc_public_parameters_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
if (asn1_sequence_of_to_der(ibc_public_parameters, ibc_public_parameters_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_public_parameters_from_der(
|
||||||
|
const uint8_t **ibc_public_parameters, size_t *ibc_public_parameters_len,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = asn1_sequence_of_from_der(ibc_public_parameters, ibc_public_parameters_len, in, inlen)) != 1) {
|
||||||
|
if (ret < 0) error_print();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_sm9_public_parameter_data_to_der(
|
||||||
|
const uint8_t *pkg_id, size_t pkg_id_len,
|
||||||
|
const SM9_ENC_MASTER_KEY *enc_mast_public_key,
|
||||||
|
const SM9_SIGN_MASTER_KEY *sign_mast_public_key,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (asn1_octet_string_to_der(pkg_id, pkg_id_len, NULL, &len) != 1
|
||||||
|
|| sm9_enc_master_public_key_to_der(enc_mast_public_key, NULL, &len) != 1
|
||||||
|
|| sm9_sign_master_public_key_to_der(sign_mast_public_key, NULL, &len) != 1
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_octet_string_to_der(pkg_id, pkg_id_len, out, outlen) != 1
|
||||||
|
|| sm9_enc_master_public_key_to_der(enc_mast_public_key, out, outlen) != 1
|
||||||
|
|| sm9_sign_master_public_key_to_der(sign_mast_public_key, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_sm9_public_parameter_data_from_der(
|
||||||
|
const uint8_t **pkg_id, size_t *pkg_id_len,
|
||||||
|
SM9_ENC_MASTER_KEY *enc_mast_public_key,
|
||||||
|
SM9_SIGN_MASTER_KEY *sign_mast_public_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 (asn1_octet_string_from_der(pkg_id, pkg_id_len, &d, &dlen) != 1
|
||||||
|
|| sm9_enc_master_public_key_from_der(enc_mast_public_key, &d, &dlen) != 1
|
||||||
|
|| sm9_sign_master_public_key_from_der(sign_mast_public_key, &d, &dlen) != 1
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_param_extension_to_der(
|
||||||
|
const uint32_t *ibc_param_extension_oid, size_t ibc_param_extension_oid_cnt,
|
||||||
|
const uint8_t *ibc_param_extension_value, size_t ibc_param_extension_value_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (asn1_object_identifier_to_der(ibc_param_extension_oid, ibc_param_extension_oid_cnt, NULL, &len) != 1
|
||||||
|
|| asn1_octet_string_to_der(ibc_param_extension_value, ibc_param_extension_value_len, NULL, &len) != 1
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_object_identifier_to_der(ibc_param_extension_oid, ibc_param_extension_oid_cnt, out, outlen) != 1
|
||||||
|
|| asn1_octet_string_to_der(ibc_param_extension_value, ibc_param_extension_value_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_param_extension_from_der(
|
||||||
|
uint32_t *ibc_param_extension_oid, size_t *ibc_param_extension_oid_cnt,
|
||||||
|
const uint8_t **ibc_param_extension_value, size_t *ibc_param_extension_value_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_object_identifier_from_der(ibc_param_extension_oid, ibc_param_extension_oid_cnt, &d, &dlen) != 1
|
||||||
|
|| asn1_octet_string_from_der(ibc_param_extension_value, ibc_param_extension_value_len, &d, &dlen) != 1
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_param_extensions_to_der(
|
||||||
|
const uint8_t *ibc_param_extensions, size_t ibc_param_extensions_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
if (!ibc_param_extensions) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (asn1_sequence_of_to_der(ibc_param_extensions, ibc_param_extensions_len, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_param_extensions_from_der(
|
||||||
|
const uint8_t **ibc_param_extensions, size_t *ibc_param_extensions_len,
|
||||||
|
const uint8_t **in, size_t *inlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = asn1_sequence_of_from_der(ibc_param_extensions, ibc_param_extensions_len, in, inlen)) < 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_sys_params_to_der(
|
||||||
|
int version,
|
||||||
|
const char *district_name, size_t district_name_len,
|
||||||
|
int district_serial,
|
||||||
|
time_t not_before, time_t not_after,
|
||||||
|
const uint8_t *ibc_public_parameters, size_t ibc_public_parameters_len,
|
||||||
|
const uint32_t *ibc_identity_type, size_t ibc_identity_type_cnt,
|
||||||
|
const uint8_t *issuer_id, size_t issuer_id_len,
|
||||||
|
const uint8_t *ibc_param_extensions, size_t ibc_param_extensions_len,
|
||||||
|
uint8_t **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (version != 2) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (asn1_int_to_der(version, NULL, &len) != 1
|
||||||
|
|| asn1_ia5_string_to_der(district_name, district_name_len, NULL, &len) != 1
|
||||||
|
|| asn1_int_to_der(district_serial, NULL, &len) != 1
|
||||||
|
|| sm9_cms_validity_period_to_der(not_before, not_after, NULL, &len) != 1
|
||||||
|
|| sm9_cms_ibc_public_parameters_to_der(ibc_public_parameters, ibc_public_parameters_len, NULL, &len) != 1
|
||||||
|
|| asn1_object_identifier_to_der(ibc_identity_type, ibc_identity_type_cnt, NULL, &len) != 1
|
||||||
|
|| asn1_any_to_der(issuer_id, issuer_id_len, NULL, &len) != 1
|
||||||
|
|| sm9_cms_ibc_param_extensions_to_der(ibc_param_extensions, ibc_param_extensions_len, NULL, &len) < 0
|
||||||
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|
|| asn1_int_to_der(version, out, outlen) != 1
|
||||||
|
|| asn1_ia5_string_to_der(district_name, district_name_len, out, outlen) != 1
|
||||||
|
|| asn1_int_to_der(district_serial, out, outlen) != 1
|
||||||
|
|| sm9_cms_validity_period_to_der(not_before, not_after, out, outlen) != 1
|
||||||
|
|| sm9_cms_ibc_public_parameters_to_der(ibc_public_parameters, ibc_public_parameters_len, out, outlen) != 1
|
||||||
|
|| asn1_object_identifier_to_der(ibc_identity_type, ibc_identity_type_cnt, out, outlen) != 1
|
||||||
|
|| asn1_any_to_der(issuer_id, issuer_id_len, out, outlen) != 1
|
||||||
|
|| sm9_cms_ibc_param_extensions_to_der(ibc_param_extensions, ibc_param_extensions_len, out, outlen) < 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9_cms_ibc_sys_params_from_der(
|
||||||
|
int *version,
|
||||||
|
const char **district_name, size_t *district_name_len,
|
||||||
|
int *district_serial,
|
||||||
|
time_t *not_before, time_t *not_after,
|
||||||
|
const uint8_t **ibc_public_parameters, size_t *ibc_public_parameters_len,
|
||||||
|
uint32_t *ibc_identity_type, size_t *ibc_identity_type_cnt,
|
||||||
|
const uint8_t **issuer_id, size_t *issuer_id_len,
|
||||||
|
const uint8_t **ibc_param_extensions, size_t *ibc_param_extensions_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_ia5_string_from_der(district_name, district_name_len, &d, &dlen) != 1
|
||||||
|
|| asn1_int_from_der(district_serial, &d, &dlen) != 1
|
||||||
|
|| sm9_cms_validity_period_from_der(not_before, not_after, &d, &dlen) != 1
|
||||||
|
|| sm9_cms_ibc_public_parameters_from_der(ibc_public_parameters, ibc_public_parameters_len, &d, &dlen) != 1
|
||||||
|
|| asn1_object_identifier_from_der(ibc_identity_type, ibc_identity_type_cnt, &d, &dlen) != 1
|
||||||
|
|| asn1_any_from_der(issuer_id, issuer_id_len, &d, &dlen) != 1
|
||||||
|
|| sm9_cms_ibc_param_extensions_from_der(ibc_param_extensions, ibc_param_extensions_len, &d, &dlen) < 0
|
||||||
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (*version != 2) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
301
tests/quictest.c
301
tests/quictest.c
@@ -182,11 +182,310 @@ static int quic_test_initial_keys(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int quic_test_aes_128_gcm_sha256_packet_protection(void)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SHA2
|
||||||
|
const uint8_t secret[32] = {
|
||||||
|
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 uint8_t dcid[] = { 0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08 };
|
||||||
|
const uint8_t scid[] = { 0x08, 0x75, 0x6d, 0x35, 0x14, 0xf0, 0x9a, 0x1b };
|
||||||
|
const uint8_t frames[] = { QUIC_frame_ping, QUIC_frame_padding, QUIC_frame_padding };
|
||||||
|
QUIC_PACKET_KEYS keys;
|
||||||
|
QUIC_DECRYPTED_PACKET decrypted;
|
||||||
|
uint8_t packet[256];
|
||||||
|
size_t packet_len = 0;
|
||||||
|
|
||||||
|
memset(&keys, 0, sizeof(keys));
|
||||||
|
memset(&decrypted, 0, sizeof(decrypted));
|
||||||
|
|
||||||
|
if (quic_packet_keys_derive(DIGEST_sha256(), secret, TLS_cipher_aes_128_gcm_sha256, &keys) != 1
|
||||||
|
|| quic_long_packet_encrypt(&keys, QUIC_packet_initial, dcid, sizeof(dcid), scid, sizeof(scid),
|
||||||
|
1, frames, sizeof(frames), packet, &packet_len) != 1
|
||||||
|
|| quic_long_packet_decrypt(&keys, packet, packet_len, QUIC_packet_initial, &decrypted) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (decrypted.packet_number != 1
|
||||||
|
|| decrypted.plaintext_len != sizeof(frames)
|
||||||
|
|| memcmp(decrypted.plaintext, frames, sizeof(frames)) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(packet, 0, sizeof(packet));
|
||||||
|
memset(&decrypted, 0, sizeof(decrypted));
|
||||||
|
if (quic_short_packet_encrypt(&keys, dcid, sizeof(dcid), 2, frames, sizeof(frames), packet, &packet_len) != 1
|
||||||
|
|| quic_short_packet_decrypt(&keys, packet, packet_len, dcid, sizeof(dcid), &decrypted) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (decrypted.packet_number != 2
|
||||||
|
|| decrypted.plaintext_len != sizeof(frames)
|
||||||
|
|| memcmp(decrypted.plaintext, frames, sizeof(frames)) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int quic_test_sm4_gcm_sm3_packet_protection(void)
|
||||||
|
{
|
||||||
|
const uint8_t secret[32] = {
|
||||||
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||||
|
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||||
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||||
|
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||||
|
};
|
||||||
|
const uint8_t dcid[] = { 0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08 };
|
||||||
|
const uint8_t scid[] = { 0x08, 0x75, 0x6d, 0x35, 0x14, 0xf0, 0x9a, 0x1b };
|
||||||
|
const uint8_t frames[] = { QUIC_frame_ping, QUIC_frame_padding, QUIC_frame_padding };
|
||||||
|
QUIC_PACKET_KEYS keys;
|
||||||
|
QUIC_DECRYPTED_PACKET decrypted;
|
||||||
|
uint8_t packet[256];
|
||||||
|
size_t packet_len = 0;
|
||||||
|
|
||||||
|
memset(&keys, 0, sizeof(keys));
|
||||||
|
memset(&decrypted, 0, sizeof(decrypted));
|
||||||
|
|
||||||
|
if (quic_packet_keys_derive(DIGEST_sm3(), secret, TLS_cipher_sm4_gcm_sm3, &keys) != 1
|
||||||
|
|| quic_long_packet_encrypt(&keys, QUIC_packet_handshake, dcid, sizeof(dcid), scid, sizeof(scid),
|
||||||
|
3, frames, sizeof(frames), packet, &packet_len) != 1
|
||||||
|
|| quic_long_packet_decrypt(&keys, packet, packet_len, QUIC_packet_handshake, &decrypted) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (decrypted.packet_number != 3
|
||||||
|
|| decrypted.plaintext_len != sizeof(frames)
|
||||||
|
|| memcmp(decrypted.plaintext, frames, sizeof(frames)) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(packet, 0, sizeof(packet));
|
||||||
|
memset(&decrypted, 0, sizeof(decrypted));
|
||||||
|
if (quic_short_packet_encrypt(&keys, dcid, sizeof(dcid), 4, frames, sizeof(frames), packet, &packet_len) != 1
|
||||||
|
|| quic_short_packet_decrypt(&keys, packet, packet_len, dcid, sizeof(dcid), &decrypted) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (decrypted.packet_number != 4
|
||||||
|
|| decrypted.plaintext_len != sizeof(frames)
|
||||||
|
|| memcmp(decrypted.plaintext, frames, sizeof(frames)) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int quic_test_sm4_ccm_sm3_packet_protection(void)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SM4_CCM
|
||||||
|
const uint8_t secret[32] = {
|
||||||
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||||
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||||
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||||
|
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||||
|
};
|
||||||
|
const uint8_t dcid[] = { 0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08 };
|
||||||
|
const uint8_t scid[] = { 0x08, 0x75, 0x6d, 0x35, 0x14, 0xf0, 0x9a, 0x1b };
|
||||||
|
const uint8_t frames[] = { QUIC_frame_ping, QUIC_frame_padding, QUIC_frame_padding };
|
||||||
|
QUIC_PACKET_KEYS keys;
|
||||||
|
QUIC_DECRYPTED_PACKET decrypted;
|
||||||
|
uint8_t packet[256];
|
||||||
|
size_t packet_len = 0;
|
||||||
|
|
||||||
|
memset(&keys, 0, sizeof(keys));
|
||||||
|
memset(&decrypted, 0, sizeof(decrypted));
|
||||||
|
|
||||||
|
if (quic_packet_keys_derive(DIGEST_sm3(), secret, TLS_cipher_sm4_ccm_sm3, &keys) != 1
|
||||||
|
|| quic_long_packet_encrypt(&keys, QUIC_packet_handshake, dcid, sizeof(dcid), scid, sizeof(scid),
|
||||||
|
5, frames, sizeof(frames), packet, &packet_len) != 1
|
||||||
|
|| quic_long_packet_decrypt(&keys, packet, packet_len, QUIC_packet_handshake, &decrypted) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (decrypted.packet_number != 5
|
||||||
|
|| decrypted.plaintext_len != sizeof(frames)
|
||||||
|
|| memcmp(decrypted.plaintext, frames, sizeof(frames)) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(packet, 0, sizeof(packet));
|
||||||
|
memset(&decrypted, 0, sizeof(decrypted));
|
||||||
|
if (quic_short_packet_encrypt(&keys, dcid, sizeof(dcid), 6, frames, sizeof(frames), packet, &packet_len) != 1
|
||||||
|
|| quic_short_packet_decrypt(&keys, packet, packet_len, dcid, sizeof(dcid), &decrypted) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (decrypted.packet_number != 6
|
||||||
|
|| decrypted.plaintext_len != sizeof(frames)
|
||||||
|
|| memcmp(decrypted.plaintext, frames, sizeof(frames)) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int quic_test_client_hello_to_bytes(void)
|
||||||
|
{
|
||||||
|
TLS_CTX ctx;
|
||||||
|
TLS_CONNECT conn;
|
||||||
|
int cipher_suites[] = { TLS_cipher_sm4_gcm_sm3 };
|
||||||
|
int supported_groups[] = { TLS_curve_sm2p256v1 };
|
||||||
|
int signature_algorithms[] = { TLS_sig_sm2sig_sm3 };
|
||||||
|
uint8_t buf[TLS_MAX_RECORD_SIZE];
|
||||||
|
uint8_t *p = buf;
|
||||||
|
size_t len = 0;
|
||||||
|
size_t handshake_len;
|
||||||
|
|
||||||
|
if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_client_mode) != 1
|
||||||
|
|| tls_ctx_set_cipher_suites(&ctx, cipher_suites, sizeof(cipher_suites)/sizeof(cipher_suites[0])) != 1
|
||||||
|
|| tls_ctx_set_supported_groups(&ctx, supported_groups, sizeof(supported_groups)/sizeof(supported_groups[0])) != 1
|
||||||
|
|| tls_ctx_set_signature_algorithms(&ctx, signature_algorithms, sizeof(signature_algorithms)/sizeof(signature_algorithms[0])) != 1
|
||||||
|
|| tls_init(&conn, &ctx) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quic_client_hello_to_bytes(&conn, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len < TLS_HANDSHAKE_HEADER_SIZE || p != buf + len) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (buf[0] != TLS_handshake_client_hello || buf[0] == TLS_record_handshake) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
handshake_len = ((size_t)buf[1] << 16) | ((size_t)buf[2] << 8) | buf[3];
|
||||||
|
if (handshake_len + TLS_HANDSHAKE_HEADER_SIZE != len) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (conn.plain_recordlen != len || memcmp(conn.plain_record, buf, len) != 0) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int quic_test_verbose_print(void)
|
||||||
|
{
|
||||||
|
TLS_CTX ctx;
|
||||||
|
TLS_CONNECT conn;
|
||||||
|
int cipher_suites[] = { TLS_cipher_sm4_gcm_sm3 };
|
||||||
|
int supported_groups[] = { TLS_curve_sm2p256v1 };
|
||||||
|
int signature_algorithms[] = { TLS_sig_sm2sig_sm3 };
|
||||||
|
uint8_t handshake[TLS_MAX_RECORD_SIZE];
|
||||||
|
uint8_t frames[TLS_MAX_RECORD_SIZE];
|
||||||
|
uint8_t packet[64];
|
||||||
|
uint8_t *p = handshake;
|
||||||
|
uint8_t *q = frames;
|
||||||
|
uint8_t *r = packet;
|
||||||
|
size_t handshake_len = 0;
|
||||||
|
size_t frames_len = 0;
|
||||||
|
size_t packet_len = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = tmpfile();
|
||||||
|
if (!fp) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_client_mode) != 1
|
||||||
|
|| tls_ctx_set_cipher_suites(&ctx, cipher_suites, sizeof(cipher_suites)/sizeof(cipher_suites[0])) != 1
|
||||||
|
|| tls_ctx_set_supported_groups(&ctx, supported_groups, sizeof(supported_groups)/sizeof(supported_groups[0])) != 1
|
||||||
|
|| tls_ctx_set_signature_algorithms(&ctx, signature_algorithms, sizeof(signature_algorithms)/sizeof(signature_algorithms[0])) != 1
|
||||||
|
|| tls_init(&conn, &ctx) != 1) {
|
||||||
|
error_print();
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quic_client_hello_to_bytes(&conn, &p, &handshake_len) != 1
|
||||||
|
|| quic_crypto_data_print(fp, 0, 0, QUIC_encryption_initial, handshake, handshake_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quic_varint_to_bytes(QUIC_frame_ping, &q, &frames_len) != 1
|
||||||
|
|| quic_varint_to_bytes(QUIC_frame_crypto, &q, &frames_len) != 1
|
||||||
|
|| quic_varint_to_bytes(0, &q, &frames_len) != 1
|
||||||
|
|| quic_varint_to_bytes(handshake_len, &q, &frames_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(q, handshake, handshake_len);
|
||||||
|
q += handshake_len;
|
||||||
|
frames_len += handshake_len;
|
||||||
|
if (quic_frames_print(fp, 0, 0, QUIC_encryption_initial, frames, frames_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*r++ = 0xc0;
|
||||||
|
*r++ = 0x00; *r++ = 0x00; *r++ = 0x00; *r++ = 0x01;
|
||||||
|
*r++ = 0x08;
|
||||||
|
memcpy(r, "12345678", 8); r += 8;
|
||||||
|
*r++ = 0x08;
|
||||||
|
memcpy(r, "87654321", 8); r += 8;
|
||||||
|
*r++ = 0x00;
|
||||||
|
*r++ = 0x01;
|
||||||
|
*r++ = 0x00;
|
||||||
|
packet_len = (size_t)(r - packet);
|
||||||
|
if (quic_packet_print(fp, 0, 0, packet, packet_len) != 1) {
|
||||||
|
error_print();
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_ctx_cleanup(&ctx);
|
||||||
|
fclose(fp);
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
if (quic_test_varint() != 1
|
if (quic_test_varint() != 1
|
||||||
|| quic_test_transport_params() != 1
|
|| quic_test_transport_params() != 1
|
||||||
|| quic_test_initial_keys() != 1) {
|
|| quic_test_initial_keys() != 1
|
||||||
|
|| quic_test_aes_128_gcm_sha256_packet_protection() != 1
|
||||||
|
|| quic_test_sm4_gcm_sm3_packet_protection() != 1
|
||||||
|
|| quic_test_sm4_ccm_sm3_packet_protection() != 1
|
||||||
|
|| quic_test_client_hello_to_bytes() != 1
|
||||||
|
|| quic_test_verbose_print() != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ extern int sm2sign_main(int argc, char **argv);
|
|||||||
extern int sm2verify_main(int argc, char **argv);
|
extern int sm2verify_main(int argc, char **argv);
|
||||||
extern int sm2encrypt_main(int argc, char **argv);
|
extern int sm2encrypt_main(int argc, char **argv);
|
||||||
extern int sm2decrypt_main(int argc, char **argv);
|
extern int sm2decrypt_main(int argc, char **argv);
|
||||||
|
extern int sm2exch_main(int argc, char **argv);
|
||||||
extern int sm3_main(int argc, char **argv);
|
extern int sm3_main(int argc, char **argv);
|
||||||
extern int sm3hmac_main(int argc, char **argv);
|
extern int sm3hmac_main(int argc, char **argv);
|
||||||
extern int sm3_pbkdf2_main(int argc, char **argv);
|
extern int sm3_pbkdf2_main(int argc, char **argv);
|
||||||
@@ -64,6 +65,9 @@ extern int sm4_cbc_mac_main(int argc, char **argv);
|
|||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_ZUC
|
#ifdef ENABLE_ZUC
|
||||||
extern int zuc_main(int argc, char **argv);
|
extern int zuc_main(int argc, char **argv);
|
||||||
|
extern int zuc256_main(int argc, char **argv);
|
||||||
|
extern int zuc_128_eea3_main(int argc, char **argv);
|
||||||
|
extern int zuc_128_eia3_main(int argc, char **argv);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_GHASH
|
#ifdef ENABLE_GHASH
|
||||||
extern int ghash_main(int argc, char **argv);
|
extern int ghash_main(int argc, char **argv);
|
||||||
@@ -75,6 +79,7 @@ extern int sm9sign_main(int argc, char **argv);
|
|||||||
extern int sm9verify_main(int argc, char **argv);
|
extern int sm9verify_main(int argc, char **argv);
|
||||||
extern int sm9encrypt_main(int argc, char **argv);
|
extern int sm9encrypt_main(int argc, char **argv);
|
||||||
extern int sm9decrypt_main(int argc, char **argv);
|
extern int sm9decrypt_main(int argc, char **argv);
|
||||||
|
extern int sm9exch_main(int argc, char **argv);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_CMS
|
#ifdef ENABLE_CMS
|
||||||
extern int cmsparse_main(int argc, char **argv);
|
extern int cmsparse_main(int argc, char **argv);
|
||||||
@@ -92,6 +97,10 @@ extern int tls13_client_main(int argc, char **argv);
|
|||||||
extern int tls13_server_main(int argc, char **argv);
|
extern int tls13_server_main(int argc, char **argv);
|
||||||
extern int sctverify_main(int argc, char **argv);
|
extern int sctverify_main(int argc, char **argv);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_QUIC
|
||||||
|
extern int quic_client_main(int argc, char **argv);
|
||||||
|
extern int quic_server_main(int argc, char **argv);
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_SECP256R1
|
#ifdef ENABLE_SECP256R1
|
||||||
extern int p256keygen_main(int argc, char **argv);
|
extern int p256keygen_main(int argc, char **argv);
|
||||||
#endif
|
#endif
|
||||||
@@ -147,9 +156,11 @@ static const char *options =
|
|||||||
" sm2verify Verify SM2 signature\n"
|
" sm2verify Verify SM2 signature\n"
|
||||||
" sm2encrypt Encrypt with SM2 public key\n"
|
" sm2encrypt Encrypt with SM2 public key\n"
|
||||||
" sm2decrypt Decrypt with SM2 private key\n"
|
" sm2decrypt Decrypt with SM2 private key\n"
|
||||||
|
" sm2exch SM2 key exchange\n"
|
||||||
" sm3 Generate SM3 hash\n"
|
" sm3 Generate SM3 hash\n"
|
||||||
" sm3hmac Generate SM3 HMAC tag\n"
|
" sm3hmac Generate SM3 HMAC tag\n"
|
||||||
" sm3_pbkdf2 Hash password into key using PBKDF2 algoritm\n"
|
" sm3_pbkdf2 Hash password into key using PBKDF2 algoritm\n"
|
||||||
|
" sm4 Encrypt or decrypt with SM4\n"
|
||||||
" sm4_gcm Encrypt or decrypt with SM4 GCM\n"
|
" sm4_gcm Encrypt or decrypt with SM4 GCM\n"
|
||||||
" sm4_cbc Encrypt or decrypt with SM4 CBC\n"
|
" sm4_cbc Encrypt or decrypt with SM4 CBC\n"
|
||||||
" sm4_ctr Encrypt or decrypt with SM4 CTR\n"
|
" sm4_ctr Encrypt or decrypt with SM4 CTR\n"
|
||||||
@@ -179,6 +190,9 @@ static const char *options =
|
|||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_ZUC
|
#ifdef ENABLE_ZUC
|
||||||
" zuc Encrypt or decrypt with ZUC\n"
|
" zuc Encrypt or decrypt with ZUC\n"
|
||||||
|
" zuc256 Encrypt or decrypt with ZUC-256\n"
|
||||||
|
" zuc_128_eea3 Encrypt or decrypt with ZUC 128-EEA3\n"
|
||||||
|
" zuc_128_eia3 Generate ZUC 128-EIA3 MAC\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_SM9
|
#ifdef ENABLE_SM9
|
||||||
" sm9setup Generate SM9 master secret\n"
|
" sm9setup Generate SM9 master secret\n"
|
||||||
@@ -187,6 +201,7 @@ static const char *options =
|
|||||||
" sm9verify Verify SM9 signature\n"
|
" sm9verify Verify SM9 signature\n"
|
||||||
" sm9encrypt SM9 public key encryption\n"
|
" sm9encrypt SM9 public key encryption\n"
|
||||||
" sm9decrypt SM9 decryption\n"
|
" sm9decrypt SM9 decryption\n"
|
||||||
|
" sm9exch SM9 key exchange\n"
|
||||||
#endif
|
#endif
|
||||||
" reqgen Generate certificate signing request (CSR)\n"
|
" reqgen Generate certificate signing request (CSR)\n"
|
||||||
" reqsign Generate certificate from CSR\n"
|
" reqsign Generate certificate from CSR\n"
|
||||||
@@ -259,6 +274,10 @@ static const char *options =
|
|||||||
" tls12_server TLS 1.2 server\n"
|
" tls12_server TLS 1.2 server\n"
|
||||||
" tls13_client TLS 1.3 client\n"
|
" tls13_client TLS 1.3 client\n"
|
||||||
" tls13_server TLS 1.3 server\n"
|
" tls13_server TLS 1.3 server\n"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_QUIC
|
||||||
|
" quic_client QUIC client\n"
|
||||||
|
" quic_server QUIC server\n"
|
||||||
#endif
|
#endif
|
||||||
"\n"
|
"\n"
|
||||||
"run `gmssl <command> -help` to print help of the given command\n"
|
"run `gmssl <command> -help` to print help of the given command\n"
|
||||||
@@ -326,6 +345,8 @@ int main(int argc, char **argv)
|
|||||||
return sm2encrypt_main(argc, argv);
|
return sm2encrypt_main(argc, argv);
|
||||||
} else if (!strcmp(*argv, "sm2decrypt")) {
|
} else if (!strcmp(*argv, "sm2decrypt")) {
|
||||||
return sm2decrypt_main(argc, argv);
|
return sm2decrypt_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "sm2exch")) {
|
||||||
|
return sm2exch_main(argc, argv);
|
||||||
} else if (!strcmp(*argv, "sm3")) {
|
} else if (!strcmp(*argv, "sm3")) {
|
||||||
return sm3_main(argc, argv);
|
return sm3_main(argc, argv);
|
||||||
} else if (!strcmp(*argv, "sm3hmac")) {
|
} else if (!strcmp(*argv, "sm3hmac")) {
|
||||||
@@ -373,6 +394,12 @@ int main(int argc, char **argv)
|
|||||||
#ifdef ENABLE_ZUC
|
#ifdef ENABLE_ZUC
|
||||||
} else if (!strcmp(*argv, "zuc")) {
|
} else if (!strcmp(*argv, "zuc")) {
|
||||||
return zuc_main(argc, argv);
|
return zuc_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "zuc256")) {
|
||||||
|
return zuc256_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "zuc_128_eea3")) {
|
||||||
|
return zuc_128_eea3_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "zuc_128_eia3")) {
|
||||||
|
return zuc_128_eia3_main(argc, argv);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_SM9
|
#ifdef ENABLE_SM9
|
||||||
} else if (!strcmp(*argv, "sm9setup")) {
|
} else if (!strcmp(*argv, "sm9setup")) {
|
||||||
@@ -387,6 +414,8 @@ int main(int argc, char **argv)
|
|||||||
return sm9encrypt_main(argc, argv);
|
return sm9encrypt_main(argc, argv);
|
||||||
} else if (!strcmp(*argv, "sm9decrypt")) {
|
} else if (!strcmp(*argv, "sm9decrypt")) {
|
||||||
return sm9decrypt_main(argc, argv);
|
return sm9decrypt_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "sm9exch")) {
|
||||||
|
return sm9exch_main(argc, argv);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_CMS
|
#ifdef ENABLE_CMS
|
||||||
} else if (!strcmp(*argv, "cmsparse")) {
|
} else if (!strcmp(*argv, "cmsparse")) {
|
||||||
@@ -416,6 +445,12 @@ int main(int argc, char **argv)
|
|||||||
} else if (!strcmp(*argv, "sctverify")) {
|
} else if (!strcmp(*argv, "sctverify")) {
|
||||||
return sctverify_main(argc, argv);
|
return sctverify_main(argc, argv);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_QUIC
|
||||||
|
} else if (!strcmp(*argv, "quic_client")) {
|
||||||
|
return quic_client_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "quic_server")) {
|
||||||
|
return quic_server_main(argc, argv);
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_SECP256R1
|
#ifdef ENABLE_SECP256R1
|
||||||
} else if (!strcmp(*argv, "p256keygen")) {
|
} else if (!strcmp(*argv, "p256keygen")) {
|
||||||
return p256keygen_main(argc, argv);
|
return p256keygen_main(argc, argv);
|
||||||
|
|||||||
1270
tools/quic_client.c
Normal file
1270
tools/quic_client.c
Normal file
File diff suppressed because it is too large
Load Diff
35
tools/quic_help.h
Normal file
35
tools/quic_help.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
"\n"
|
||||||
|
"Supported cipher suites:\n"
|
||||||
|
#if defined(ENABLE_AES) && defined(ENABLE_SHA2)
|
||||||
|
" TLS_AES_128_GCM_SHA256\n"
|
||||||
|
#ifdef ENABLE_AES_CCM
|
||||||
|
" TLS_AES_128_CCM_SHA256\n"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
" TLS_SM4_GCM_SM3\n"
|
||||||
|
#ifdef ENABLE_SM4_CCM
|
||||||
|
" TLS_SM4_CCM_SM3\n"
|
||||||
|
#endif
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl quic_server -port 4433 -cert p256_tls_server_certs.pem -key p256_tls_server_key.pem \\\n"
|
||||||
|
" -pass P@ssw0rd -cipher_suite TLS_AES_128_GCM_SHA256 -supported_group prime256v1 \\\n"
|
||||||
|
" -sig_alg ecdsa_secp256r1_sha256 -verbose\n"
|
||||||
|
" gmssl quic_client -host 127.0.0.1 -port 4433 -server_name localhost \\\n"
|
||||||
|
" -cipher_suite TLS_AES_128_GCM_SHA256 -supported_group prime256v1 \\\n"
|
||||||
|
" -sig_alg ecdsa_secp256r1_sha256 -get / -verbose\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl quic_server -port 4434 -cert sm2_tls_server_certs.pem -key sm2_tls_server_key.pem \\\n"
|
||||||
|
" -pass P@ssw0rd -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 \\\n"
|
||||||
|
" -sig_alg sm2sig_sm3 -verbose\n"
|
||||||
|
" gmssl quic_client -host 127.0.0.1 -port 4434 -server_name localhost \\\n"
|
||||||
|
" -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3 \\\n"
|
||||||
|
" -get / -verbose\n"
|
||||||
|
"\n"
|
||||||
|
" ngtcp2/examples/osslserver --groups=P-256 --ciphers=TLS_AES_128_GCM_SHA256 \\\n"
|
||||||
|
" -d htdocs 127.0.0.1 4435 p256-key.pem p256-cert.pem\n"
|
||||||
|
" gmssl quic_client -host 127.0.0.1 -port 4435 -server_name localhost \\\n"
|
||||||
|
" -cipher_suite TLS_AES_128_GCM_SHA256 -supported_group prime256v1 \\\n"
|
||||||
|
" -sig_alg ecdsa_secp256r1_sha256 -get / -verbose\n"
|
||||||
|
"\n"
|
||||||
1010
tools/quic_server.c
Normal file
1010
tools/quic_server.c
Normal file
File diff suppressed because it is too large
Load Diff
929
tools/sm2exch.c
Normal file
929
tools/sm2exch.c
Normal file
@@ -0,0 +1,929 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 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 <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <gmssl/mem.h>
|
||||||
|
#include <gmssl/hex.h>
|
||||||
|
#include <gmssl/pem.h>
|
||||||
|
#include <gmssl/sm2.h>
|
||||||
|
#include <gmssl/x509.h>
|
||||||
|
#include <gmssl/x509_ext.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SM2EXCH_RA_SIZE 65
|
||||||
|
#define SM2EXCH_RB_SIZE 65
|
||||||
|
#define SM2EXCH_CONFIRM_SIZE 32
|
||||||
|
#define SM2EXCH_RB_SB_SIZE (SM2EXCH_RB_SIZE + SM2EXCH_CONFIRM_SIZE)
|
||||||
|
#define SM2EXCH_SECRET_STATE_SIZE 65
|
||||||
|
#define SM2EXCH_MAX_SHARED_KEY_SIZE 1024
|
||||||
|
#define PEM_SM2_EXCH_PEER_RA "SM2 EXCHANGE PEER RA"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SM2EXCH_FMT_BIN = 0,
|
||||||
|
SM2EXCH_FMT_HEX = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *usage =
|
||||||
|
"-stage init|respond|confirm|finish [options]";
|
||||||
|
|
||||||
|
static const char *options =
|
||||||
|
"\n"
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -stage init|respond|confirm|finish\n"
|
||||||
|
" SM2 key exchange stage\n"
|
||||||
|
" -cert pem Optional local SM2 certificate for checking against -key\n"
|
||||||
|
" -pubkey pem Optional local SM2 public key for checking against -key\n"
|
||||||
|
" -key pem Local SM2 private key in PEM format\n"
|
||||||
|
" -pass str Password to open local private key\n"
|
||||||
|
" -peer_cert pem Peer SM2 key exchange/encryption certificate in PEM format\n"
|
||||||
|
" -peer_pubkey pem Peer SM2 public key in PEM format\n"
|
||||||
|
" -id str Local SM2 identity, '1234567812345678' by default\n"
|
||||||
|
" -id_hex hex Local SM2 identity in hex\n"
|
||||||
|
" -peer_id str Peer SM2 identity, '1234567812345678' by default\n"
|
||||||
|
" -peer_id_hex hex Peer SM2 identity in hex\n"
|
||||||
|
" -in file | stdin Input data for this stage\n"
|
||||||
|
" respond: RA, 65 bytes\n"
|
||||||
|
" confirm: RB || SB, 97 bytes\n"
|
||||||
|
" finish: SA, 32 bytes\n"
|
||||||
|
" -out file | stdout Output data to send to peer\n"
|
||||||
|
" init: RA, 65 bytes\n"
|
||||||
|
" respond: RB || SB, 97 bytes\n"
|
||||||
|
" confirm: SA, 32 bytes\n"
|
||||||
|
" -exch_keyout pem Output local ephemeral private key\n"
|
||||||
|
" -exch_key pem Input local ephemeral private key\n"
|
||||||
|
" -exch_pass str Password for local ephemeral private key\n"
|
||||||
|
" -secret_state_out file\n"
|
||||||
|
" Output 65-byte secret_state point\n"
|
||||||
|
" -secret_state file Input 65-byte secret_state point\n"
|
||||||
|
" -keylen num Shared key length in bytes, 32 by default\n"
|
||||||
|
" -keyout file Output shared key\n"
|
||||||
|
" -hex Encode input/output data in hex, default\n"
|
||||||
|
" -bin Encode input/output data in binary\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
"Public-key file workflow:\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2keygen -pass P@ssw0rd -out alice.pem -pubout alicepub.pem\n"
|
||||||
|
" gmssl sm2keygen -pass P@ssw0rd -out bob.pem -pubout bobpub.pem\n"
|
||||||
|
" gmssl sm2exch -stage init \\\n"
|
||||||
|
" -exch_keyout alice_ra.pem -exch_pass P@ssw0rd -out ra.hex\n"
|
||||||
|
" gmssl sm2exch -stage respond \\\n"
|
||||||
|
" -key bob.pem -pass P@ssw0rd -id Bob \\\n"
|
||||||
|
" -peer_pubkey alicepub.pem -peer_id Alice -in ra.hex \\\n"
|
||||||
|
" -exch_keyout bob_rb.pem -exch_pass P@ssw0rd \\\n"
|
||||||
|
" -secret_state_out bob_secret_state.hex -out rb_sb.hex\n"
|
||||||
|
" gmssl sm2exch -stage confirm \\\n"
|
||||||
|
" -key alice.pem -pass P@ssw0rd -id Alice \\\n"
|
||||||
|
" -peer_pubkey bobpub.pem -peer_id Bob \\\n"
|
||||||
|
" -exch_key alice_ra.pem -exch_pass P@ssw0rd -in rb_sb.hex \\\n"
|
||||||
|
" -keylen 48 -keyout alice_shared_key.hex -out sa.hex\n"
|
||||||
|
" gmssl sm2exch -stage finish \\\n"
|
||||||
|
" -key bob.pem -pass P@ssw0rd -id Bob \\\n"
|
||||||
|
" -peer_pubkey alicepub.pem -peer_id Alice \\\n"
|
||||||
|
" -exch_key bob_rb.pem -exch_pass P@ssw0rd \\\n"
|
||||||
|
" -secret_state bob_secret_state.hex -in sa.hex \\\n"
|
||||||
|
" -keylen 48 -keyout bob_shared_key.hex\n"
|
||||||
|
"\n"
|
||||||
|
"Certificate workflow:\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm2exch -stage respond \\\n"
|
||||||
|
" -key bob_enc_key.pem -pass P@ssw0rd -id Bob \\\n"
|
||||||
|
" -peer_cert alice_enc_cert.pem -peer_id Alice -in ra.hex \\\n"
|
||||||
|
" -exch_keyout bob_rb.pem -exch_pass P@ssw0rd \\\n"
|
||||||
|
" -secret_state_out bob_secret_state.hex -out rb_sb.hex\n"
|
||||||
|
" gmssl sm2exch -stage confirm \\\n"
|
||||||
|
" -key alice_enc_key.pem -pass P@ssw0rd -id Alice \\\n"
|
||||||
|
" -peer_cert bob_enc_cert.pem -peer_id Bob \\\n"
|
||||||
|
" -exch_key alice_ra.pem -exch_pass P@ssw0rd -in rb_sb.hex \\\n"
|
||||||
|
" -keyout alice_shared_key.hex -out sa.hex\n"
|
||||||
|
"\n"
|
||||||
|
"Notes\n"
|
||||||
|
"\n"
|
||||||
|
" -cert and -peer_cert read only the first certificate from the PEM file.\n"
|
||||||
|
" If KeyUsage is present, the certificate must allow keyEncipherment or keyAgreement.\n"
|
||||||
|
" RA, RB and secret_state are fixed 65-byte uncompressed SM2 points.\n"
|
||||||
|
" The respond output is RB || SB, fixed 97 bytes.\n"
|
||||||
|
" -hex and -bin affect RA, RB||SB, SA, secret_state and shared key files.\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
static int read_file(const char *file, uint8_t *buf, size_t *len, size_t maxlen)
|
||||||
|
{
|
||||||
|
FILE *fp = stdin;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (!buf || !len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (file && !(fp = fopen(file, "rb"))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
n = fread(buf, 1, maxlen + 1, fp);
|
||||||
|
if (ferror(fp)) {
|
||||||
|
if (file) fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (file) fclose(fp);
|
||||||
|
if (n > maxlen) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*len = n;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_file(const char *file, const uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
FILE *fp = stdout;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!buf || !len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (file && !(fp = fopen(file, "wb"))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fwrite(buf, 1, len, fp) == len) {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
if (file) fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_read_exact(const char *file, uint8_t *buf, size_t len);
|
||||||
|
|
||||||
|
static int sm2exch_write_data(const char *file, const uint8_t *buf, size_t len, int format)
|
||||||
|
{
|
||||||
|
uint8_t *hexbuf = NULL;
|
||||||
|
size_t i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (format == SM2EXCH_FMT_BIN) {
|
||||||
|
return write_file(file, buf, len);
|
||||||
|
}
|
||||||
|
if (!(hexbuf = malloc(len * 2))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
static const char *hex = "0123456789abcdef";
|
||||||
|
hexbuf[i * 2] = (uint8_t)hex[buf[i] >> 4];
|
||||||
|
hexbuf[i * 2 + 1] = (uint8_t)hex[buf[i] & 0x0f];
|
||||||
|
}
|
||||||
|
ret = write_file(file, hexbuf, len * 2);
|
||||||
|
gmssl_secure_clear(hexbuf, len * 2);
|
||||||
|
free(hexbuf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_read_data(const char *file, uint8_t *buf, size_t len, int format)
|
||||||
|
{
|
||||||
|
uint8_t *in = NULL;
|
||||||
|
uint8_t *hex = NULL;
|
||||||
|
size_t inlen;
|
||||||
|
size_t hexlen = 0;
|
||||||
|
size_t outlen;
|
||||||
|
size_t i;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (format == SM2EXCH_FMT_BIN) {
|
||||||
|
return sm2exch_read_exact(file, buf, len);
|
||||||
|
}
|
||||||
|
if (!(in = malloc(len * 2 + 64)) || !(hex = malloc(len * 2))) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (read_file(file, in, &inlen, len * 2 + 63) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
for (i = 0; i < inlen; i++) {
|
||||||
|
if (in[i] == ' ' || in[i] == '\t' || in[i] == '\r' || in[i] == '\n') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (hexlen >= len * 2) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
hex[hexlen++] = in[i];
|
||||||
|
}
|
||||||
|
if (hexlen != len * 2
|
||||||
|
|| hex_to_bytes((char *)hex, hexlen, buf, &outlen) != 1
|
||||||
|
|| outlen != len) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
if (in) {
|
||||||
|
gmssl_secure_clear(in, len * 2 + 64);
|
||||||
|
free(in);
|
||||||
|
}
|
||||||
|
if (hex) {
|
||||||
|
gmssl_secure_clear(hex, len * 2);
|
||||||
|
free(hex);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_read_point(const char *file, uint8_t point[65], int format)
|
||||||
|
{
|
||||||
|
if (sm2exch_read_data(file, point, 65, format) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (point[0] != 0x04) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_read_exact(const char *file, uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t inlen;
|
||||||
|
|
||||||
|
if (read_file(file, buf, &inlen, len) != 1 || inlen != len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_cert_check_key_usage(const uint8_t *cert, size_t certlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int critical;
|
||||||
|
const uint8_t *exts;
|
||||||
|
size_t extslen;
|
||||||
|
const uint8_t *val;
|
||||||
|
size_t vlen;
|
||||||
|
int bits;
|
||||||
|
|
||||||
|
if (!cert || !certlen) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((ret = x509_cert_get_exts(cert, certlen, &exts, &extslen)) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((ret = x509_exts_get_ext_by_oid(exts, extslen, OID_ce_key_usage,
|
||||||
|
&critical, &val, &vlen)) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (x509_key_usage_from_der(&bits, &val, &vlen) != 1
|
||||||
|
|| asn1_length_is_zero(vlen) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((bits & (X509_KU_KEY_ENCIPHERMENT | X509_KU_KEY_AGREEMENT)) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_load_public_key(SM2_KEY *pub_key, const char *pubkeyfile,
|
||||||
|
const char *certfile, const char *prog, const char *label)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
uint8_t cert[4096];
|
||||||
|
size_t certlen;
|
||||||
|
X509_KEY x509_key;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!pub_key || !prog || !label) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pubkeyfile && certfile) {
|
||||||
|
if (label[0]) {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-%s_pubkey' and '-%s_cert' conflict\n",
|
||||||
|
prog, label, label);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-pubkey' and '-cert' conflict\n", prog);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pubkeyfile) {
|
||||||
|
if (!(fp = fopen(pubkeyfile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, pubkeyfile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = sm2_public_key_info_from_pem(pub_key, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (ret != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: parse public key failed\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (certfile) {
|
||||||
|
if (!(fp = fopen(certfile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, certfile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = x509_cert_from_pem(cert, &certlen, sizeof(cert), fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (ret != 1
|
||||||
|
|| x509_cert_get_subject_public_key(cert, certlen, &x509_key) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: parse certificate failed\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (x509_key.algor != OID_ec_public_key || x509_key.algor_param != OID_sm2) {
|
||||||
|
fprintf(stderr, "gmssl %s: certificate public key is not SM2\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = sm2exch_cert_check_key_usage(cert, certlen);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "gmssl %s: certificate KeyUsage parse failure\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
fprintf(stderr, "gmssl %s: certificate KeyUsage does not allow key exchange/encryption\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*pub_key = x509_key.u.sm2_key;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (label[0]) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-%s_pubkey' or '-%s_cert' option required\n",
|
||||||
|
prog, label, label);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: '-pubkey' or '-cert' option required\n", prog);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_load_private_key(SM2_KEY *key, const char *keyfile,
|
||||||
|
const char *pass, const char *prog)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-key' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!pass) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-pass' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(fp = fopen(keyfile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, keyfile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = sm2_private_key_info_decrypt_from_pem(key, pass, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (ret != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: private key decryption failure\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_load_exch_key(SM2_KEY *key, uint8_t peer_ra[65],
|
||||||
|
const char *keyfile, const char *pass, const char *prog)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int ret;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-exch_key' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!pass) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-exch_pass' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(fp = fopen(keyfile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, keyfile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = sm2_private_key_info_decrypt_from_pem(key, pass, fp);
|
||||||
|
if (ret != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: ephemeral private key decryption failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (peer_ra) {
|
||||||
|
if (pem_read(fp, PEM_SM2_EXCH_PEER_RA, peer_ra, &len, 65) != 1
|
||||||
|
|| len != 65 || peer_ra[0] != 0x04) {
|
||||||
|
fprintf(stderr, "gmssl %s: peer RA not found in exchange key\n", prog);
|
||||||
|
ret = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_save_exch_key(const SM2_KEY *key, const char *keyfile,
|
||||||
|
const char *pass, const uint8_t peer_ra[65], const char *prog)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-exch_keyout' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!pass) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-exch_pass' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(fp = fopen(keyfile, "wb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, keyfile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = sm2_private_key_info_encrypt_to_pem(key, pass, fp);
|
||||||
|
if (ret == 1 && peer_ra) {
|
||||||
|
ret = pem_write(fp, PEM_SM2_EXCH_PEER_RA, peer_ra, 65);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
if (ret != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: output ephemeral private key failed\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_load_local_keys(SM2_KEY *key, const char *keyfile, const char *pass,
|
||||||
|
const char *pubkeyfile, const char *certfile, const char *prog)
|
||||||
|
{
|
||||||
|
SM2_KEY pub_key;
|
||||||
|
|
||||||
|
if (sm2exch_load_private_key(key, keyfile, pass, prog) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pubkeyfile || certfile) {
|
||||||
|
if (sm2exch_load_public_key(&pub_key, pubkeyfile, certfile, prog, "") != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm2_public_key_equ(key, &pub_key) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: private key does not match local public key/certificate\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_derive_key_from_secret_state(int is_initiator,
|
||||||
|
const SM2_KEY *key, const char *id, size_t idlen,
|
||||||
|
const SM2_KEY *peer_public_key, const char *peer_id, size_t peer_idlen,
|
||||||
|
const uint8_t secret_state[65], uint8_t *shared_key, size_t shared_key_len)
|
||||||
|
{
|
||||||
|
SM2_Z256_POINT point;
|
||||||
|
uint8_t za[32];
|
||||||
|
uint8_t zb[32];
|
||||||
|
uint8_t kdf_input[128];
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!key || !id || !peer_public_key || !peer_id
|
||||||
|
|| !secret_state || !shared_key || !shared_key_len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm2_z256_point_from_octets(&point, secret_state, 65) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (is_initiator) {
|
||||||
|
if (sm2_compute_z(za, &key->public_key, id, idlen) != 1
|
||||||
|
|| sm2_compute_z(zb, &peer_public_key->public_key, peer_id, peer_idlen) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sm2_compute_z(za, &peer_public_key->public_key, peer_id, peer_idlen) != 1
|
||||||
|
|| sm2_compute_z(zb, &key->public_key, id, idlen) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sm2_z256_point_to_bytes(&point, kdf_input);
|
||||||
|
memcpy(kdf_input + 64, za, sizeof(za));
|
||||||
|
memcpy(kdf_input + 96, zb, sizeof(zb));
|
||||||
|
if (sm2_kdf(kdf_input, sizeof(kdf_input), shared_key_len, shared_key) != 1
|
||||||
|
|| mem_is_zero(shared_key, shared_key_len)) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&point, sizeof(point));
|
||||||
|
gmssl_secure_clear(za, sizeof(za));
|
||||||
|
gmssl_secure_clear(zb, sizeof(zb));
|
||||||
|
gmssl_secure_clear(kdf_input, sizeof(kdf_input));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_stage_init(const char *exch_keyoutfile, const char *exch_pass,
|
||||||
|
const char *outfile, int format, const char *prog)
|
||||||
|
{
|
||||||
|
SM2_KEY exch_key;
|
||||||
|
uint8_t ra[65];
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (sm2_key_generate(&exch_key) != 1
|
||||||
|
|| sm2_z256_point_to_uncompressed_octets(&exch_key.public_key, ra) != 1
|
||||||
|
|| sm2exch_save_exch_key(&exch_key, exch_keyoutfile, exch_pass, NULL, prog) != 1
|
||||||
|
|| sm2exch_write_data(outfile, ra, sizeof(ra), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: init stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&exch_key, sizeof(exch_key));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_stage_respond(const char *keyfile, const char *pass,
|
||||||
|
const char *pubkeyfile, const char *certfile,
|
||||||
|
const char *peer_pubkeyfile, const char *peer_certfile,
|
||||||
|
const char *id, size_t idlen, const char *peer_id, size_t peer_idlen,
|
||||||
|
const char *infile, const char *exch_keyoutfile, const char *exch_pass,
|
||||||
|
const char *secret_stateoutfile, const char *outfile, size_t keylen,
|
||||||
|
int format, const char *prog)
|
||||||
|
{
|
||||||
|
SM2_KEY key;
|
||||||
|
SM2_KEY peer_public_key;
|
||||||
|
SM2_KEY exch_key;
|
||||||
|
uint8_t ra[65];
|
||||||
|
uint8_t rb[65];
|
||||||
|
uint8_t secret_state[65];
|
||||||
|
uint8_t shared_key[SM2EXCH_MAX_SHARED_KEY_SIZE];
|
||||||
|
uint8_t sb[32];
|
||||||
|
uint8_t rb_sb[97];
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!secret_stateoutfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-secret_state_out' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm2exch_load_local_keys(&key, keyfile, pass, pubkeyfile, certfile, prog) != 1
|
||||||
|
|| sm2exch_load_public_key(&peer_public_key, peer_pubkeyfile, peer_certfile, prog, "peer") != 1
|
||||||
|
|| sm2exch_read_point(infile, ra, format) != 1
|
||||||
|
|| sm2_key_generate(&exch_key) != 1
|
||||||
|
|| sm2_z256_point_to_uncompressed_octets(&exch_key.public_key, rb) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: respond stage input failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm2_key_exchange(0, &key, id, idlen, &peer_public_key, peer_id, peer_idlen,
|
||||||
|
&exch_key, ra, secret_state, keylen, shared_key) != 1
|
||||||
|
|| sm2_key_exchange_compute_confirm(0, &key, id, idlen,
|
||||||
|
&peer_public_key, peer_id, peer_idlen,
|
||||||
|
&exch_key, ra, secret_state, sb) != 1
|
||||||
|
|| sm2exch_save_exch_key(&exch_key, exch_keyoutfile, exch_pass, ra, prog) != 1
|
||||||
|
|| sm2exch_write_data(secret_stateoutfile, secret_state, sizeof(secret_state), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: respond stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
memcpy(rb_sb, rb, sizeof(rb));
|
||||||
|
memcpy(rb_sb + sizeof(rb), sb, sizeof(sb));
|
||||||
|
if (sm2exch_write_data(outfile, rb_sb, sizeof(rb_sb), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: output RB||SB failed : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&peer_public_key, sizeof(peer_public_key));
|
||||||
|
gmssl_secure_clear(&exch_key, sizeof(exch_key));
|
||||||
|
gmssl_secure_clear(secret_state, sizeof(secret_state));
|
||||||
|
gmssl_secure_clear(shared_key, sizeof(shared_key));
|
||||||
|
gmssl_secure_clear(sb, sizeof(sb));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_stage_confirm(const char *keyfile, const char *pass,
|
||||||
|
const char *pubkeyfile, const char *certfile,
|
||||||
|
const char *peer_pubkeyfile, const char *peer_certfile,
|
||||||
|
const char *id, size_t idlen, const char *peer_id, size_t peer_idlen,
|
||||||
|
const char *exch_keyfile, const char *exch_pass, const char *infile,
|
||||||
|
const char *secret_stateoutfile, const char *keyoutfile, const char *outfile,
|
||||||
|
size_t keylen, int format, const char *prog)
|
||||||
|
{
|
||||||
|
SM2_KEY key;
|
||||||
|
SM2_KEY peer_public_key;
|
||||||
|
SM2_KEY exch_key;
|
||||||
|
uint8_t rb_sb[97];
|
||||||
|
uint8_t secret_state[65];
|
||||||
|
uint8_t shared_key[SM2EXCH_MAX_SHARED_KEY_SIZE];
|
||||||
|
uint8_t sa[32];
|
||||||
|
int vr;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!keyoutfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-keyout' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm2exch_load_local_keys(&key, keyfile, pass, pubkeyfile, certfile, prog) != 1
|
||||||
|
|| sm2exch_load_public_key(&peer_public_key, peer_pubkeyfile, peer_certfile, prog, "peer") != 1
|
||||||
|
|| sm2exch_load_exch_key(&exch_key, NULL, exch_keyfile, exch_pass, prog) != 1
|
||||||
|
|| sm2exch_read_data(infile, rb_sb, sizeof(rb_sb), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: confirm stage input failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm2_key_exchange(1, &key, id, idlen, &peer_public_key, peer_id, peer_idlen,
|
||||||
|
&exch_key, rb_sb, secret_state, keylen, shared_key) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: key exchange failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if ((vr = sm2_key_exchange_verify_confirm(1, &key, id, idlen,
|
||||||
|
&peer_public_key, peer_id, peer_idlen, &exch_key,
|
||||||
|
rb_sb, secret_state, rb_sb + SM2EXCH_RB_SIZE)) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: SB verification %s\n", prog, vr < 0 ? "failure" : "failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm2_key_exchange_compute_confirm(1, &key, id, idlen,
|
||||||
|
&peer_public_key, peer_id, peer_idlen, &exch_key,
|
||||||
|
rb_sb, secret_state, sa) != 1
|
||||||
|
|| sm2exch_write_data(keyoutfile, shared_key, keylen, format) != 1
|
||||||
|
|| sm2exch_write_data(outfile, sa, sizeof(sa), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: confirm stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (secret_stateoutfile
|
||||||
|
&& sm2exch_write_data(secret_stateoutfile, secret_state, sizeof(secret_state), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: output secret_state failed : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&peer_public_key, sizeof(peer_public_key));
|
||||||
|
gmssl_secure_clear(&exch_key, sizeof(exch_key));
|
||||||
|
gmssl_secure_clear(secret_state, sizeof(secret_state));
|
||||||
|
gmssl_secure_clear(shared_key, sizeof(shared_key));
|
||||||
|
gmssl_secure_clear(sa, sizeof(sa));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm2exch_stage_finish(const char *keyfile, const char *pass,
|
||||||
|
const char *pubkeyfile, const char *certfile,
|
||||||
|
const char *peer_pubkeyfile, const char *peer_certfile,
|
||||||
|
const char *id, size_t idlen, const char *peer_id, size_t peer_idlen,
|
||||||
|
const char *exch_keyfile, const char *exch_pass, const char *secret_statefile,
|
||||||
|
const char *infile, const char *keyoutfile, size_t keylen, int format,
|
||||||
|
const char *prog)
|
||||||
|
{
|
||||||
|
SM2_KEY key;
|
||||||
|
SM2_KEY peer_public_key;
|
||||||
|
SM2_KEY exch_key;
|
||||||
|
uint8_t ra[65];
|
||||||
|
uint8_t secret_state[65];
|
||||||
|
uint8_t sa[32];
|
||||||
|
uint8_t shared_key[SM2EXCH_MAX_SHARED_KEY_SIZE];
|
||||||
|
int vr;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!secret_statefile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-secret_state' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!keyoutfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-keyout' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm2exch_load_local_keys(&key, keyfile, pass, pubkeyfile, certfile, prog) != 1
|
||||||
|
|| sm2exch_load_public_key(&peer_public_key, peer_pubkeyfile, peer_certfile, prog, "peer") != 1
|
||||||
|
|| sm2exch_load_exch_key(&exch_key, ra, exch_keyfile, exch_pass, prog) != 1
|
||||||
|
|| sm2exch_read_point(secret_statefile, secret_state, format) != 1
|
||||||
|
|| sm2exch_read_data(infile, sa, sizeof(sa), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: finish stage input failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if ((vr = sm2_key_exchange_verify_confirm(0, &key, id, idlen,
|
||||||
|
&peer_public_key, peer_id, peer_idlen, &exch_key,
|
||||||
|
ra, secret_state, sa)) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: SA verification %s\n", prog, vr < 0 ? "failure" : "failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm2exch_derive_key_from_secret_state(0, &key, id, idlen,
|
||||||
|
&peer_public_key, peer_id, peer_idlen,
|
||||||
|
secret_state, shared_key, keylen) != 1
|
||||||
|
|| sm2exch_write_data(keyoutfile, shared_key, keylen, format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: finish stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&peer_public_key, sizeof(peer_public_key));
|
||||||
|
gmssl_secure_clear(&exch_key, sizeof(exch_key));
|
||||||
|
gmssl_secure_clear(secret_state, sizeof(secret_state));
|
||||||
|
gmssl_secure_clear(shared_key, sizeof(shared_key));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm2exch_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *stage = NULL;
|
||||||
|
char *certfile = NULL;
|
||||||
|
char *pubkeyfile = NULL;
|
||||||
|
char *keyfile = NULL;
|
||||||
|
char *pass = NULL;
|
||||||
|
char *peer_certfile = NULL;
|
||||||
|
char *peer_pubkeyfile = NULL;
|
||||||
|
char *id = NULL;
|
||||||
|
char *peer_id = NULL;
|
||||||
|
char *id_hex = NULL;
|
||||||
|
char *peer_id_hex = NULL;
|
||||||
|
char id_buf[SM2_MAX_ID_LENGTH];
|
||||||
|
size_t id_len = 0;
|
||||||
|
char peer_id_buf[SM2_MAX_ID_LENGTH];
|
||||||
|
size_t peer_id_len = 0;
|
||||||
|
char *infile = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
char *exch_keyfile = NULL;
|
||||||
|
char *exch_keyoutfile = NULL;
|
||||||
|
char *exch_pass = NULL;
|
||||||
|
char *secret_statefile = NULL;
|
||||||
|
char *secret_stateoutfile = NULL;
|
||||||
|
char *keyoutfile = NULL;
|
||||||
|
size_t keylen = 32;
|
||||||
|
int format = SM2EXCH_FMT_HEX;
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (!strcmp(*argv, "-help")) {
|
||||||
|
printf("usage: gmssl %s %s\n", prog, usage);
|
||||||
|
printf("%s\n", options);
|
||||||
|
return 0;
|
||||||
|
} else if (!strcmp(*argv, "-stage")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
stage = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-cert")) {
|
||||||
|
if (pubkeyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-cert' and '-pubkey' conflict\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
certfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-pubkey")) {
|
||||||
|
if (certfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-cert' and '-pubkey' conflict\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
pubkeyfile = *(++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, "-peer_cert")) {
|
||||||
|
if (peer_pubkeyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-peer_cert' and '-peer_pubkey' conflict\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
peer_certfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-peer_pubkey")) {
|
||||||
|
if (peer_certfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-peer_cert' and '-peer_pubkey' conflict\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
peer_pubkeyfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-id")) {
|
||||||
|
if (id_hex) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-id' and '-id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
id = *(++argv);
|
||||||
|
id_len = strlen(id);
|
||||||
|
} else if (!strcmp(*argv, "-id_hex")) {
|
||||||
|
if (id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-id' and '-id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
id_hex = *(++argv);
|
||||||
|
if (strlen(id_hex) > sizeof(id_buf) * 2
|
||||||
|
|| hex_to_bytes(id_hex, strlen(id_hex), (uint8_t *)id_buf, &id_len) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-id_hex' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
id = id_buf;
|
||||||
|
} else if (!strcmp(*argv, "-peer_id")) {
|
||||||
|
if (peer_id_hex) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' and '-peer_id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
peer_id = *(++argv);
|
||||||
|
peer_id_len = strlen(peer_id);
|
||||||
|
} else if (!strcmp(*argv, "-peer_id_hex")) {
|
||||||
|
if (peer_id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' and '-peer_id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
peer_id_hex = *(++argv);
|
||||||
|
if (strlen(peer_id_hex) > sizeof(peer_id_buf) * 2
|
||||||
|
|| hex_to_bytes(peer_id_hex, strlen(peer_id_hex), (uint8_t *)peer_id_buf, &peer_id_len) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-peer_id_hex' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
peer_id = peer_id_buf;
|
||||||
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
infile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-exch_keyout")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
exch_keyoutfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-exch_key")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
exch_keyfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-exch_pass")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
exch_pass = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-secret_state_out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
secret_stateoutfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-secret_state")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
secret_statefile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-keylen")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keylen = (size_t)atoi(*(++argv));
|
||||||
|
if (keylen < 1 || keylen > SM2EXCH_MAX_SHARED_KEY_SIZE) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-keylen' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-keyout")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keyoutfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-hex")) {
|
||||||
|
format = SM2EXCH_FMT_HEX;
|
||||||
|
} else if (!strcmp(*argv, "-bin")) {
|
||||||
|
format = SM2EXCH_FMT_BIN;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stage) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-stage' option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!id) {
|
||||||
|
id = SM2_DEFAULT_ID;
|
||||||
|
id_len = SM2_DEFAULT_ID_LENGTH;
|
||||||
|
}
|
||||||
|
if (!peer_id) {
|
||||||
|
peer_id = SM2_DEFAULT_ID;
|
||||||
|
peer_id_len = SM2_DEFAULT_ID_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(stage, "init")) {
|
||||||
|
ret = sm2exch_stage_init(exch_keyoutfile, exch_pass, outfile, format, prog);
|
||||||
|
} else if (!strcmp(stage, "respond")) {
|
||||||
|
ret = sm2exch_stage_respond(keyfile, pass, pubkeyfile, certfile,
|
||||||
|
peer_pubkeyfile, peer_certfile, id, id_len, peer_id, peer_id_len,
|
||||||
|
infile, exch_keyoutfile, exch_pass, secret_stateoutfile,
|
||||||
|
outfile, keylen, format, prog);
|
||||||
|
} else if (!strcmp(stage, "confirm")) {
|
||||||
|
ret = sm2exch_stage_confirm(keyfile, pass, pubkeyfile, certfile,
|
||||||
|
peer_pubkeyfile, peer_certfile, id, id_len, peer_id, peer_id_len,
|
||||||
|
exch_keyfile, exch_pass, infile, secret_stateoutfile,
|
||||||
|
keyoutfile, outfile, keylen, format, prog);
|
||||||
|
} else if (!strcmp(stage, "finish")) {
|
||||||
|
ret = sm2exch_stage_finish(keyfile, pass, pubkeyfile, certfile,
|
||||||
|
peer_pubkeyfile, peer_certfile, id, id_len, peer_id, peer_id_len,
|
||||||
|
exch_keyfile, exch_pass, secret_statefile, infile,
|
||||||
|
keyoutfile, keylen, format, prog);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-stage' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return ret == 0 ? 0 : 1;
|
||||||
|
}
|
||||||
31
tools/sm4.c
31
tools/sm4.c
@@ -27,8 +27,6 @@ enum {
|
|||||||
SM4_MODE_XTS,
|
SM4_MODE_XTS,
|
||||||
SM4_MODE_CCM,
|
SM4_MODE_CCM,
|
||||||
SM4_MODE_GCM,
|
SM4_MODE_GCM,
|
||||||
SM4_MODE_CBC_SM3_HMAC,
|
|
||||||
SM4_MODE_CTR_SM3_HMAC,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog)
|
static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog)
|
||||||
@@ -188,8 +186,6 @@ static const char *options =
|
|||||||
" -ctr CTR mode, need 16-byte key and 16-byte iv\n"
|
" -ctr CTR mode, need 16-byte key and 16-byte iv\n"
|
||||||
" -ccm CCM mode, need 16-byte key and any iv length\n"
|
" -ccm CCM mode, need 16-byte key and any iv length\n"
|
||||||
" -gcm GCM mode, need 16-byte key and any iv length\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"
|
|
||||||
" -xts XTS mode\n"
|
" -xts XTS mode\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -encrypt Encrypt\n"
|
" -encrypt Encrypt\n"
|
||||||
@@ -205,13 +201,6 @@ static const char *options =
|
|||||||
"\n"
|
"\n"
|
||||||
" echo \"hello\" | gmssl sm4 -gcm -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\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"
|
" 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";
|
"\n";
|
||||||
|
|
||||||
int sm4_main(int argc, char **argv)
|
int sm4_main(int argc, char **argv)
|
||||||
@@ -322,12 +311,6 @@ int sm4_main(int argc, char **argv)
|
|||||||
} else if (!strcmp(*argv, "-ctr")) {
|
} else if (!strcmp(*argv, "-ctr")) {
|
||||||
if (mode) goto bad;
|
if (mode) goto bad;
|
||||||
mode = SM4_MODE_CTR;
|
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")) {
|
} else if (!strcmp(*argv, "-gcm")) {
|
||||||
if (mode) goto bad;
|
if (mode) goto bad;
|
||||||
mode = SM4_MODE_GCM;
|
mode = SM4_MODE_GCM;
|
||||||
@@ -449,9 +432,6 @@ bad:
|
|||||||
#ifdef ENABLE_SM4_XTS
|
#ifdef ENABLE_SM4_XTS
|
||||||
case SM4_MODE_XTS:
|
case SM4_MODE_XTS:
|
||||||
#endif
|
#endif
|
||||||
case SM4_MODE_CBC_SM3_HMAC:
|
|
||||||
case SM4_MODE_CTR_SM3_HMAC:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: mode is not supported\n", prog);
|
fprintf(stderr, "%s: mode is not supported\n", prog);
|
||||||
goto end;
|
goto end;
|
||||||
@@ -477,13 +457,6 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
break;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check iv length
|
// check iv length
|
||||||
@@ -498,8 +471,6 @@ bad:
|
|||||||
case SM4_MODE_CFB:
|
case SM4_MODE_CFB:
|
||||||
case SM4_MODE_OFB:
|
case SM4_MODE_OFB:
|
||||||
case SM4_MODE_CTR:
|
case SM4_MODE_CTR:
|
||||||
case SM4_MODE_CBC_SM3_HMAC:
|
|
||||||
case SM4_MODE_CTR_SM3_HMAC:
|
|
||||||
if (ivlen != 16) {
|
if (ivlen != 16) {
|
||||||
fprintf(stderr, "%s: invalid IV length, should be 32 hex digits\n", prog);
|
fprintf(stderr, "%s: invalid IV length, should be 32 hex digits\n", prog);
|
||||||
goto end;
|
goto end;
|
||||||
@@ -613,7 +584,6 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
#ifdef ENABLE_SM4_ECB
|
#ifdef ENABLE_SM4_ECB
|
||||||
case SM4_MODE_ECB: rv = sm4_ecb_encrypt_finish(&sm4_ctx.ecb, outbuf, &outlen); break;
|
case SM4_MODE_ECB: rv = sm4_ecb_encrypt_finish(&sm4_ctx.ecb, outbuf, &outlen); break;
|
||||||
@@ -688,7 +658,6 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
#ifdef ENABLE_SM4_ECB
|
#ifdef ENABLE_SM4_ECB
|
||||||
case SM4_MODE_ECB: rv = sm4_ecb_decrypt_finish(&sm4_ctx.ecb, outbuf, &outlen); break;
|
case SM4_MODE_ECB: rv = sm4_ecb_decrypt_finish(&sm4_ctx.ecb, outbuf, &outlen); break;
|
||||||
|
|||||||
771
tools/sm9exch.c
Normal file
771
tools/sm9exch.c
Normal file
@@ -0,0 +1,771 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 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 <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <gmssl/mem.h>
|
||||||
|
#include <gmssl/hex.h>
|
||||||
|
#include <gmssl/pem.h>
|
||||||
|
#include <gmssl/sm9.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SM9EXCH_R_SIZE 32
|
||||||
|
#define SM9EXCH_RA_SIZE 65
|
||||||
|
#define SM9EXCH_RB_SIZE 65
|
||||||
|
#define SM9EXCH_CONFIRM_SIZE 32
|
||||||
|
#define SM9EXCH_RB_SB_SIZE (SM9EXCH_RB_SIZE + SM9EXCH_CONFIRM_SIZE)
|
||||||
|
#define SM9EXCH_EXCH_KEY_SIZE (SM9EXCH_R_SIZE + SM9EXCH_RB_SIZE)
|
||||||
|
#define SM9EXCH_EXCH_KEY_WITH_PEER_R_SIZE (SM9EXCH_EXCH_KEY_SIZE + SM9EXCH_RA_SIZE)
|
||||||
|
#define SM9EXCH_MAX_SHARED_KEY_SIZE 1024
|
||||||
|
#define PEM_SM9_EXCH_KEY "SM9 EXCHANGE PRIVATE KEY"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SM9EXCH_FMT_BIN = 0,
|
||||||
|
SM9EXCH_FMT_HEX = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *usage =
|
||||||
|
"-stage init|respond|confirm|finish [options]";
|
||||||
|
|
||||||
|
static const char *options =
|
||||||
|
"\n"
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -stage init|respond|confirm|finish\n"
|
||||||
|
" SM9 key exchange stage\n"
|
||||||
|
" -pubmaster pem SM9 exchange master public key in PEM format\n"
|
||||||
|
" -key pem Local SM9 exchange private key in PEM format\n"
|
||||||
|
" -pass str Password to open local private key\n"
|
||||||
|
" -id str Local SM9 identity\n"
|
||||||
|
" -id_hex hex Local SM9 identity in hex\n"
|
||||||
|
" -peer_id str Peer SM9 identity\n"
|
||||||
|
" -peer_id_hex hex Peer SM9 identity in hex\n"
|
||||||
|
" -in file | stdin Input data for this stage\n"
|
||||||
|
" respond: RA, 65 bytes\n"
|
||||||
|
" confirm: RB || SB, 97 bytes\n"
|
||||||
|
" finish: SA, 32 bytes\n"
|
||||||
|
" -out file | stdout Output data to send to peer\n"
|
||||||
|
" init: RA, 65 bytes\n"
|
||||||
|
" respond: RB || SB, 97 bytes\n"
|
||||||
|
" confirm: SA, 32 bytes\n"
|
||||||
|
" -exch_keyout pem Output local ephemeral exchange state r||R in PEM format\n"
|
||||||
|
" -exch_key pem Input local ephemeral exchange state r||R in PEM format\n"
|
||||||
|
" -keylen num Shared key length in bytes, 32 by default\n"
|
||||||
|
" -keyout file Output shared key\n"
|
||||||
|
" -hex Encode input/output data in hex, default\n"
|
||||||
|
" -bin Encode input/output data in binary\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl sm9setup -alg sm9encrypt -pass P@ssw0rd \\\n"
|
||||||
|
" -out sm9_msk.pem -pubout sm9_mpk.pem\n"
|
||||||
|
" gmssl sm9keygen -alg sm9keyagreement -in sm9_msk.pem -inpass P@ssw0rd \\\n"
|
||||||
|
" -id Alice -out alice.pem -outpass 123456\n"
|
||||||
|
" gmssl sm9keygen -alg sm9keyagreement -in sm9_msk.pem -inpass P@ssw0rd \\\n"
|
||||||
|
" -id Bob -out bob.pem -outpass 123456\n"
|
||||||
|
" gmssl sm9exch -stage init \\\n"
|
||||||
|
" -pubmaster sm9_mpk.pem -peer_id Bob \\\n"
|
||||||
|
" -exch_keyout alice_ra.pem -out ra.hex\n"
|
||||||
|
" gmssl sm9exch -stage respond \\\n"
|
||||||
|
" -pubmaster sm9_mpk.pem -key bob.pem -pass 123456 -id Bob \\\n"
|
||||||
|
" -peer_id Alice -in ra.hex \\\n"
|
||||||
|
" -exch_keyout bob_rb.pem -out rb_sb.hex\n"
|
||||||
|
" gmssl sm9exch -stage confirm \\\n"
|
||||||
|
" -pubmaster sm9_mpk.pem -key alice.pem -pass 123456 -id Alice \\\n"
|
||||||
|
" -peer_id Bob -exch_key alice_ra.pem -in rb_sb.hex \\\n"
|
||||||
|
" -keylen 48 -keyout alice_shared_key.hex -out sa.hex\n"
|
||||||
|
" gmssl sm9exch -stage finish \\\n"
|
||||||
|
" -pubmaster sm9_mpk.pem -key bob.pem -pass 123456 -id Bob \\\n"
|
||||||
|
" -peer_id Alice -exch_key bob_rb.pem \\\n"
|
||||||
|
" -in sa.hex -keylen 48 -keyout bob_shared_key.hex\n"
|
||||||
|
"\n"
|
||||||
|
"Notes\n"
|
||||||
|
"\n"
|
||||||
|
" RA and RB are fixed 65-byte uncompressed SM9 curve points.\n"
|
||||||
|
" The respond output is RB || SB, fixed 97 bytes.\n"
|
||||||
|
" The ephemeral exchange state contains secret scalar r, public point R and optional peer point.\n"
|
||||||
|
" -hex and -bin affect RA, RB||SB, SA and shared key files.\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
static int read_file(const char *file, uint8_t *buf, size_t *len, size_t maxlen)
|
||||||
|
{
|
||||||
|
FILE *fp = stdin;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (!buf || !len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (file && !(fp = fopen(file, "rb"))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
n = fread(buf, 1, maxlen + 1, fp);
|
||||||
|
if (ferror(fp)) {
|
||||||
|
if (file) fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (file) fclose(fp);
|
||||||
|
if (n > maxlen) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*len = n;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_file(const char *file, const uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
FILE *fp = stdout;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!buf || !len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (file && !(fp = fopen(file, "wb"))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fwrite(buf, 1, len, fp) == len) {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
if (file) fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_read_exact(const char *file, uint8_t *buf, size_t len);
|
||||||
|
|
||||||
|
static int sm9exch_write_data(const char *file, const uint8_t *buf, size_t len, int format)
|
||||||
|
{
|
||||||
|
uint8_t *hexbuf = NULL;
|
||||||
|
size_t i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (format == SM9EXCH_FMT_BIN) {
|
||||||
|
return write_file(file, buf, len);
|
||||||
|
}
|
||||||
|
if (!(hexbuf = malloc(len * 2))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
static const char *hex = "0123456789abcdef";
|
||||||
|
hexbuf[i * 2] = (uint8_t)hex[buf[i] >> 4];
|
||||||
|
hexbuf[i * 2 + 1] = (uint8_t)hex[buf[i] & 0x0f];
|
||||||
|
}
|
||||||
|
ret = write_file(file, hexbuf, len * 2);
|
||||||
|
gmssl_secure_clear(hexbuf, len * 2);
|
||||||
|
free(hexbuf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_read_data(const char *file, uint8_t *buf, size_t len, int format)
|
||||||
|
{
|
||||||
|
uint8_t *in = NULL;
|
||||||
|
uint8_t *hex = NULL;
|
||||||
|
size_t inlen;
|
||||||
|
size_t hexlen = 0;
|
||||||
|
size_t outlen;
|
||||||
|
size_t i;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (format == SM9EXCH_FMT_BIN) {
|
||||||
|
return sm9exch_read_exact(file, buf, len);
|
||||||
|
}
|
||||||
|
if (!(in = malloc(len * 2 + 64)) || !(hex = malloc(len * 2))) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (read_file(file, in, &inlen, len * 2 + 63) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
for (i = 0; i < inlen; i++) {
|
||||||
|
if (in[i] == ' ' || in[i] == '\t' || in[i] == '\r' || in[i] == '\n') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (hexlen >= len * 2) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
hex[hexlen++] = in[i];
|
||||||
|
}
|
||||||
|
if (hexlen != len * 2
|
||||||
|
|| hex_to_bytes((char *)hex, hexlen, buf, &outlen) != 1
|
||||||
|
|| outlen != len) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
if (in) {
|
||||||
|
gmssl_secure_clear(in, len * 2 + 64);
|
||||||
|
free(in);
|
||||||
|
}
|
||||||
|
if (hex) {
|
||||||
|
gmssl_secure_clear(hex, len * 2);
|
||||||
|
free(hex);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_read_exact(const char *file, uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t inlen;
|
||||||
|
|
||||||
|
if (read_file(file, buf, &inlen, len) != 1 || inlen != len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_read_point_file(const char *file, SM9_Z256_POINT *point, int format)
|
||||||
|
{
|
||||||
|
uint8_t buf[65];
|
||||||
|
|
||||||
|
if (sm9exch_read_data(file, buf, sizeof(buf), format) != 1
|
||||||
|
|| sm9_z256_point_from_uncompressed_octets(point, buf) != 1
|
||||||
|
|| !sm9_z256_point_is_on_curve(point)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_load_master_public_key(SM9_EXCH_MASTER_KEY *mpk,
|
||||||
|
const char *mpkfile, const char *prog)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!mpkfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-pubmaster' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(fp = fopen(mpkfile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open master public key failed : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm9_enc_master_public_key_from_pem(mpk, fp) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: parse master public key failed\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
if (fp) fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_load_private_key(SM9_EXCH_KEY *key, const char *keyfile,
|
||||||
|
const char *pass, const SM9_EXCH_MASTER_KEY *mpk, const char *prog)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-key' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!pass) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-pass' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(fp = fopen(keyfile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open private key failed : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm9_enc_key_info_decrypt_from_pem(key, pass, fp) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: parse private key failed\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (mpk && sm9_z256_point_equ(&key->Ppube, &mpk->Ppube) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: private key does not match master public key\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
if (fp) fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_generate_R(const SM9_EXCH_MASTER_KEY *mpk,
|
||||||
|
const char *peer_id, size_t peer_idlen, sm9_z256_t r, SM9_Z256_POINT *R)
|
||||||
|
{
|
||||||
|
if (!mpk || !peer_id || !peer_idlen || !r || !R) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (peer_idlen > SM9_MAX_ID_SIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm9_z256_hash1(r, peer_id, peer_idlen, SM9_HID_EXCH);
|
||||||
|
sm9_z256_point_mul(R, r, sm9_z256_generator());
|
||||||
|
sm9_z256_point_add(R, R, &mpk->Ppube);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (sm9_z256_rand_range(r, sm9_z256_order()) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while (sm9_z256_is_zero(r));
|
||||||
|
|
||||||
|
sm9_z256_point_mul(R, r, R);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_save_exch_key(const sm9_z256_t r, const SM9_Z256_POINT *R,
|
||||||
|
const SM9_Z256_POINT *peer_R, const char *keyfile, const char *prog)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
uint8_t buf[SM9EXCH_EXCH_KEY_WITH_PEER_R_SIZE];
|
||||||
|
size_t len = SM9EXCH_EXCH_KEY_SIZE;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-exch_keyout' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm9_z256_to_bytes(r, buf);
|
||||||
|
if (sm9_z256_point_to_uncompressed_octets(R, buf + SM9EXCH_R_SIZE) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (peer_R) {
|
||||||
|
if (sm9_z256_point_to_uncompressed_octets(peer_R, buf + SM9EXCH_EXCH_KEY_SIZE) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
len = SM9EXCH_EXCH_KEY_WITH_PEER_R_SIZE;
|
||||||
|
}
|
||||||
|
if (!(fp = fopen(keyfile, "wb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open output exchange key failed : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (pem_write(fp, PEM_SM9_EXCH_KEY, buf, len) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: output exchange key failed\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(buf, sizeof(buf));
|
||||||
|
if (fp) fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_load_exch_key(sm9_z256_t r, SM9_Z256_POINT *R,
|
||||||
|
SM9_Z256_POINT *peer_R, const char *keyfile, const char *prog)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
uint8_t buf[SM9EXCH_EXCH_KEY_WITH_PEER_R_SIZE];
|
||||||
|
size_t len;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-exch_key' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(fp = fopen(keyfile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open exchange key failed : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (pem_read(fp, PEM_SM9_EXCH_KEY, buf, &len, sizeof(buf)) != 1
|
||||||
|
|| (len != SM9EXCH_EXCH_KEY_SIZE && len != SM9EXCH_EXCH_KEY_WITH_PEER_R_SIZE)) {
|
||||||
|
fprintf(stderr, "gmssl %s: parse exchange key failed\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
sm9_z256_from_bytes(r, buf);
|
||||||
|
if (sm9_z256_is_zero(r)
|
||||||
|
|| sm9_z256_point_from_uncompressed_octets(R, buf + SM9EXCH_R_SIZE) != 1
|
||||||
|
|| !sm9_z256_point_is_on_curve(R)) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid exchange key\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (peer_R) {
|
||||||
|
if (len != SM9EXCH_EXCH_KEY_WITH_PEER_R_SIZE
|
||||||
|
|| sm9_z256_point_from_uncompressed_octets(peer_R, buf + SM9EXCH_EXCH_KEY_SIZE) != 1
|
||||||
|
|| !sm9_z256_point_is_on_curve(peer_R)) {
|
||||||
|
fprintf(stderr, "gmssl %s: peer exchange point not found in exchange key\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(buf, sizeof(buf));
|
||||||
|
if (fp) fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_stage_init(const char *mpkfile, const char *peer_id,
|
||||||
|
size_t peer_idlen, const char *exch_keyoutfile, const char *outfile,
|
||||||
|
int format, const char *prog)
|
||||||
|
{
|
||||||
|
SM9_EXCH_MASTER_KEY mpk;
|
||||||
|
SM9_Z256_POINT R;
|
||||||
|
sm9_z256_t r;
|
||||||
|
uint8_t ra[65];
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!peer_id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm9exch_load_master_public_key(&mpk, mpkfile, prog) != 1
|
||||||
|
|| sm9exch_generate_R(&mpk, peer_id, peer_idlen, r, &R) != 1
|
||||||
|
|| sm9_z256_point_to_uncompressed_octets(&R, ra) != 1
|
||||||
|
|| sm9exch_save_exch_key(r, &R, NULL, exch_keyoutfile, prog) != 1
|
||||||
|
|| sm9exch_write_data(outfile, ra, sizeof(ra), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: init stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&mpk, sizeof(mpk));
|
||||||
|
gmssl_secure_clear(&R, sizeof(R));
|
||||||
|
gmssl_secure_clear(r, sizeof(r));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_stage_respond(const char *mpkfile, const char *keyfile,
|
||||||
|
const char *pass, const char *id, size_t idlen,
|
||||||
|
const char *peer_id, size_t peer_idlen, const char *infile,
|
||||||
|
const char *exch_keyoutfile, const char *outfile, size_t keylen,
|
||||||
|
int format, const char *prog)
|
||||||
|
{
|
||||||
|
SM9_EXCH_MASTER_KEY mpk;
|
||||||
|
SM9_EXCH_KEY key;
|
||||||
|
SM9_Z256_POINT ra;
|
||||||
|
SM9_Z256_POINT rb;
|
||||||
|
sm9_z256_t r;
|
||||||
|
uint8_t rb_octets[65];
|
||||||
|
uint8_t shared_key[SM9EXCH_MAX_SHARED_KEY_SIZE];
|
||||||
|
uint8_t sb[32];
|
||||||
|
uint8_t rb_sb[97];
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-id' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!peer_id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm9exch_load_master_public_key(&mpk, mpkfile, prog) != 1
|
||||||
|
|| sm9exch_load_private_key(&key, keyfile, pass, &mpk, prog) != 1
|
||||||
|
|| sm9exch_read_point_file(infile, &ra, format) != 1
|
||||||
|
|| sm9exch_generate_R(&mpk, peer_id, peer_idlen, r, &rb) != 1
|
||||||
|
|| sm9_z256_point_to_uncompressed_octets(&rb, rb_octets) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: respond stage input failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm9_key_exchange(0, &mpk, &key, id, idlen, peer_id, peer_idlen,
|
||||||
|
r, &rb, &ra, keylen, shared_key) != 1
|
||||||
|
|| sm9_key_exchange_compute_confirm(0, &mpk, &key, id, idlen,
|
||||||
|
peer_id, peer_idlen, r, &rb, &ra, sb) != 1
|
||||||
|
|| sm9exch_save_exch_key(r, &rb, &ra, exch_keyoutfile, prog) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: respond stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
memcpy(rb_sb, rb_octets, sizeof(rb_octets));
|
||||||
|
memcpy(rb_sb + sizeof(rb_octets), sb, sizeof(sb));
|
||||||
|
if (sm9exch_write_data(outfile, rb_sb, sizeof(rb_sb), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: output RB||SB failed : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&mpk, sizeof(mpk));
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&ra, sizeof(ra));
|
||||||
|
gmssl_secure_clear(&rb, sizeof(rb));
|
||||||
|
gmssl_secure_clear(r, sizeof(r));
|
||||||
|
gmssl_secure_clear(shared_key, sizeof(shared_key));
|
||||||
|
gmssl_secure_clear(sb, sizeof(sb));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_stage_confirm(const char *mpkfile, const char *keyfile,
|
||||||
|
const char *pass, const char *id, size_t idlen,
|
||||||
|
const char *peer_id, size_t peer_idlen, const char *exch_keyfile,
|
||||||
|
const char *infile, const char *keyoutfile, const char *outfile,
|
||||||
|
size_t keylen, int format, const char *prog)
|
||||||
|
{
|
||||||
|
SM9_EXCH_MASTER_KEY mpk;
|
||||||
|
SM9_EXCH_KEY key;
|
||||||
|
SM9_Z256_POINT ra;
|
||||||
|
SM9_Z256_POINT rb;
|
||||||
|
sm9_z256_t r;
|
||||||
|
uint8_t rb_sb[97];
|
||||||
|
uint8_t shared_key[SM9EXCH_MAX_SHARED_KEY_SIZE];
|
||||||
|
uint8_t sa[32];
|
||||||
|
int vr;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-id' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!peer_id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!keyoutfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-keyout' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm9exch_load_master_public_key(&mpk, mpkfile, prog) != 1
|
||||||
|
|| sm9exch_load_private_key(&key, keyfile, pass, &mpk, prog) != 1
|
||||||
|
|| sm9exch_load_exch_key(r, &ra, NULL, exch_keyfile, prog) != 1
|
||||||
|
|| sm9exch_read_data(infile, rb_sb, sizeof(rb_sb), format) != 1
|
||||||
|
|| sm9_z256_point_from_uncompressed_octets(&rb, rb_sb) != 1
|
||||||
|
|| !sm9_z256_point_is_on_curve(&rb)) {
|
||||||
|
fprintf(stderr, "gmssl %s: confirm stage input failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm9_key_exchange(1, &mpk, &key, id, idlen, peer_id, peer_idlen,
|
||||||
|
r, &ra, &rb, keylen, shared_key) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: key exchange failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if ((vr = sm9_key_exchange_verify_confirm(1, &mpk, &key, id, idlen,
|
||||||
|
peer_id, peer_idlen, r, &ra, &rb, rb_sb + SM9EXCH_RB_SIZE)) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: SB verification %s\n", prog, vr < 0 ? "failure" : "failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm9_key_exchange_compute_confirm(1, &mpk, &key, id, idlen,
|
||||||
|
peer_id, peer_idlen, r, &ra, &rb, sa) != 1
|
||||||
|
|| sm9exch_write_data(keyoutfile, shared_key, keylen, format) != 1
|
||||||
|
|| sm9exch_write_data(outfile, sa, sizeof(sa), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: confirm stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&mpk, sizeof(mpk));
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&ra, sizeof(ra));
|
||||||
|
gmssl_secure_clear(&rb, sizeof(rb));
|
||||||
|
gmssl_secure_clear(r, sizeof(r));
|
||||||
|
gmssl_secure_clear(shared_key, sizeof(shared_key));
|
||||||
|
gmssl_secure_clear(sa, sizeof(sa));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sm9exch_stage_finish(const char *mpkfile, const char *keyfile,
|
||||||
|
const char *pass, const char *id, size_t idlen,
|
||||||
|
const char *peer_id, size_t peer_idlen, const char *exch_keyfile,
|
||||||
|
const char *infile, const char *keyoutfile, size_t keylen, int format,
|
||||||
|
const char *prog)
|
||||||
|
{
|
||||||
|
SM9_EXCH_MASTER_KEY mpk;
|
||||||
|
SM9_EXCH_KEY key;
|
||||||
|
SM9_Z256_POINT ra;
|
||||||
|
SM9_Z256_POINT rb;
|
||||||
|
sm9_z256_t r;
|
||||||
|
uint8_t sa[32];
|
||||||
|
uint8_t shared_key[SM9EXCH_MAX_SHARED_KEY_SIZE];
|
||||||
|
int vr;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-id' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!peer_id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!keyoutfile) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-keyout' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm9exch_load_master_public_key(&mpk, mpkfile, prog) != 1
|
||||||
|
|| sm9exch_load_private_key(&key, keyfile, pass, &mpk, prog) != 1
|
||||||
|
|| sm9exch_load_exch_key(r, &rb, &ra, exch_keyfile, prog) != 1
|
||||||
|
|| sm9exch_read_data(infile, sa, sizeof(sa), format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: finish stage input failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if ((vr = sm9_key_exchange_verify_confirm(0, &mpk, &key, id, idlen,
|
||||||
|
peer_id, peer_idlen, r, &rb, &ra, sa)) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: SA verification %s\n", prog, vr < 0 ? "failure" : "failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm9_key_exchange(0, &mpk, &key, id, idlen, peer_id, peer_idlen,
|
||||||
|
r, &rb, &ra, keylen, shared_key) != 1
|
||||||
|
|| sm9exch_write_data(keyoutfile, shared_key, keylen, format) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: finish stage failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&mpk, sizeof(mpk));
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&ra, sizeof(ra));
|
||||||
|
gmssl_secure_clear(&rb, sizeof(rb));
|
||||||
|
gmssl_secure_clear(r, sizeof(r));
|
||||||
|
gmssl_secure_clear(shared_key, sizeof(shared_key));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sm9exch_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *stage = NULL;
|
||||||
|
char *mpkfile = NULL;
|
||||||
|
char *keyfile = NULL;
|
||||||
|
char *pass = NULL;
|
||||||
|
char *id = NULL;
|
||||||
|
char *peer_id = NULL;
|
||||||
|
char *id_hex = NULL;
|
||||||
|
char *peer_id_hex = NULL;
|
||||||
|
char id_buf[SM9_MAX_ID_SIZE];
|
||||||
|
size_t id_len = 0;
|
||||||
|
char peer_id_buf[SM9_MAX_ID_SIZE];
|
||||||
|
size_t peer_id_len = 0;
|
||||||
|
char *infile = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
char *exch_keyfile = NULL;
|
||||||
|
char *exch_keyoutfile = NULL;
|
||||||
|
char *keyoutfile = NULL;
|
||||||
|
size_t keylen = 32;
|
||||||
|
int format = SM9EXCH_FMT_HEX;
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (!strcmp(*argv, "-help")) {
|
||||||
|
printf("usage: gmssl %s %s\n", prog, usage);
|
||||||
|
printf("%s\n", options);
|
||||||
|
return 0;
|
||||||
|
} else if (!strcmp(*argv, "-stage")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
stage = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-pubmaster")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
mpkfile = *(++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, "-id")) {
|
||||||
|
if (id_hex) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-id' and '-id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
id = *(++argv);
|
||||||
|
id_len = strlen(id);
|
||||||
|
} else if (!strcmp(*argv, "-id_hex")) {
|
||||||
|
if (id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-id' and '-id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
id_hex = *(++argv);
|
||||||
|
if (strlen(id_hex) > sizeof(id_buf) * 2
|
||||||
|
|| hex_to_bytes(id_hex, strlen(id_hex), (uint8_t *)id_buf, &id_len) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-id_hex' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
id = id_buf;
|
||||||
|
} else if (!strcmp(*argv, "-peer_id")) {
|
||||||
|
if (peer_id_hex) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' and '-peer_id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
peer_id = *(++argv);
|
||||||
|
peer_id_len = strlen(peer_id);
|
||||||
|
} else if (!strcmp(*argv, "-peer_id_hex")) {
|
||||||
|
if (peer_id) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-peer_id' and '-peer_id_hex' should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
peer_id_hex = *(++argv);
|
||||||
|
if (strlen(peer_id_hex) > sizeof(peer_id_buf) * 2
|
||||||
|
|| hex_to_bytes(peer_id_hex, strlen(peer_id_hex), (uint8_t *)peer_id_buf, &peer_id_len) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-peer_id_hex' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
peer_id = peer_id_buf;
|
||||||
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
infile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-exch_keyout")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
exch_keyoutfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-exch_key")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
exch_keyfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-keylen")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keylen = (size_t)atoi(*(++argv));
|
||||||
|
if (keylen < 1 || keylen > SM9EXCH_MAX_SHARED_KEY_SIZE) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-keylen' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-keyout")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keyoutfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-hex")) {
|
||||||
|
format = SM9EXCH_FMT_HEX;
|
||||||
|
} else if (!strcmp(*argv, "-bin")) {
|
||||||
|
format = SM9EXCH_FMT_BIN;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stage) {
|
||||||
|
fprintf(stderr, "gmssl %s: '-stage' option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (id && id_len > SM9_MAX_ID_SIZE) {
|
||||||
|
fprintf(stderr, "gmssl %s: local identity too long\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (peer_id && peer_id_len > SM9_MAX_ID_SIZE) {
|
||||||
|
fprintf(stderr, "gmssl %s: peer identity too long\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(stage, "init")) {
|
||||||
|
ret = sm9exch_stage_init(mpkfile, peer_id, peer_id_len,
|
||||||
|
exch_keyoutfile, outfile, format, prog);
|
||||||
|
} else if (!strcmp(stage, "respond")) {
|
||||||
|
ret = sm9exch_stage_respond(mpkfile, keyfile, pass, id, id_len,
|
||||||
|
peer_id, peer_id_len, infile, exch_keyoutfile,
|
||||||
|
outfile, keylen, format, prog);
|
||||||
|
} else if (!strcmp(stage, "confirm")) {
|
||||||
|
ret = sm9exch_stage_confirm(mpkfile, keyfile, pass, id, id_len,
|
||||||
|
peer_id, peer_id_len, exch_keyfile, infile,
|
||||||
|
keyoutfile, outfile, keylen, format, prog);
|
||||||
|
} else if (!strcmp(stage, "finish")) {
|
||||||
|
ret = sm9exch_stage_finish(mpkfile, keyfile, pass, id, id_len,
|
||||||
|
peer_id, peer_id_len, exch_keyfile, infile,
|
||||||
|
keyoutfile, keylen, format, prog);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid '-stage' value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return ret == 0 ? 0 : 1;
|
||||||
|
}
|
||||||
@@ -17,12 +17,13 @@
|
|||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
|
||||||
static const char *usage = "-alg (sm9sign|sm9encrypt) -in master_key.pem -inpass str -id str [-out pem] -outpass str";
|
static const char *usage = "-alg (sm9sign|sm9encrypt|sm9keyagreement) -in master_key.pem -inpass str -id str [-out pem] -outpass str";
|
||||||
|
|
||||||
static const char *options =
|
static const char *options =
|
||||||
"Options\n"
|
"Options\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -alg sm9sign|sm9encrypt Generate maeter key for sm9sign or sm9encrypt\n"
|
" -alg sm9sign|sm9encrypt|sm9keyagreement\n"
|
||||||
|
" Generate user's private key for sm9sign, sm9encrypt or sm9keyagreement\n"
|
||||||
" -in pem SM9 master private key in PEM format\n"
|
" -in pem SM9 master private key in PEM format\n"
|
||||||
" -inpass pass Password to decrypt the master private key\n"
|
" -inpass pass Password to decrypt the master private key\n"
|
||||||
" -id str User's identity\n"
|
" -id str User's identity\n"
|
||||||
@@ -36,6 +37,7 @@ static const char *options =
|
|||||||
"\n"
|
"\n"
|
||||||
" $ gmssl sm9setup -alg sm9encrypt -pass P@ssw0rd -out sm9enc_msk.pem\n"
|
" $ gmssl sm9setup -alg sm9encrypt -pass P@ssw0rd -out sm9enc_msk.pem\n"
|
||||||
" $ gmssl sm9keygen -alg sm9encrypt -in sm9enc_msk.pem -inpass P@ssw0rd -id Alice -out sm9enc.pem -outpass 123456\n"
|
" $ gmssl sm9keygen -alg sm9encrypt -in sm9enc_msk.pem -inpass P@ssw0rd -id Alice -out sm9enc.pem -outpass 123456\n"
|
||||||
|
" $ gmssl sm9keygen -alg sm9keyagreement -in sm9enc_msk.pem -inpass P@ssw0rd -id Alice -out sm9exch.pem -outpass 123456\n"
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
int sm9keygen_main(int argc, char **argv)
|
int sm9keygen_main(int argc, char **argv)
|
||||||
@@ -60,19 +62,20 @@ int sm9keygen_main(int argc, char **argv)
|
|||||||
argv++;
|
argv++;
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
fprintf(stderr, "usage: %s %s\n", prog, options);
|
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (!strcmp(*argv, "-help")) {
|
if (!strcmp(*argv, "-help")) {
|
||||||
fprintf(stdout, "usage: %s %s\n", prog, options);
|
fprintf(stdout, "usage: gmssl %s %s\n", prog, usage);
|
||||||
|
fprintf(stdout, "%s\n", options);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (!strcmp(*argv, "-alg")) {
|
} else if (!strcmp(*argv, "-alg")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
alg = *(++argv);
|
alg = *(++argv);
|
||||||
if ((oid = sm9_oid_from_name(alg)) < 1) {
|
if ((oid = sm9_oid_from_name(alg)) < 1) {
|
||||||
fprintf(stdout, "%s: invalid alg '%s', should be sm9sign or sm9encrypt\n", prog, alg);
|
fprintf(stdout, "%s: invalid alg '%s', should be sm9sign, sm9encrypt or sm9keyagreement\n", prog, alg);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(*argv, "-in")) {
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
@@ -135,6 +138,14 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OID_sm9keyagreement:
|
||||||
|
if (sm9_enc_master_key_info_decrypt_from_pem(&enc_msk, inpass, infp) != 1
|
||||||
|
|| sm9_exch_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:
|
default:
|
||||||
error_print();
|
error_print();
|
||||||
goto end;
|
goto end;
|
||||||
|
|||||||
150
tools/zuc256.c
Normal file
150
tools/zuc256.c
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 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 <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gmssl/mem.h>
|
||||||
|
#include <gmssl/zuc.h>
|
||||||
|
#include <gmssl/hex.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char *usage = "-key hex -iv hex [-in file] [-out file]";
|
||||||
|
|
||||||
|
static const char *help =
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -key hex ZUC-256 key in HEX format, 32 bytes\n"
|
||||||
|
" -iv hex ZUC-256 IV in HEX format, 23 bytes\n"
|
||||||
|
" -in file | stdin Input data\n"
|
||||||
|
" -out file | stdout Output data\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl zuc256 -key 0000000000000000000000000000000000000000000000000000000000000000 \\\n"
|
||||||
|
" -iv 0000000000000000000000000000000000000000000000 -in plaintext.bin -out ciphertext.bin\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
int zuc256_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[ZUC256_KEY_SIZE];
|
||||||
|
uint8_t iv[ZUC256_IV_SIZE];
|
||||||
|
size_t keylen;
|
||||||
|
size_t ivlen;
|
||||||
|
FILE *infp = stdin;
|
||||||
|
FILE *outfp = stdout;
|
||||||
|
ZUC_STATE zuc_state;
|
||||||
|
uint8_t inbuf[4096];
|
||||||
|
uint8_t outbuf[4096];
|
||||||
|
size_t inlen;
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (!strcmp(*argv, "-help")) {
|
||||||
|
printf("usage: gmssl %s %s\n", prog, usage);
|
||||||
|
printf("%s\n", help);
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
} else if (!strcmp(*argv, "-key")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keyhex = *(++argv);
|
||||||
|
if (strlen(keyhex) != sizeof(key) * 2) {
|
||||||
|
fprintf(stderr, "gmssl %s: key should be 32 bytes\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %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, "gmssl %s: IV should be 23 bytes\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid IV 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, "gmssl %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, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyhex) {
|
||||||
|
fprintf(stderr, "gmssl %s: option '-key' required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!ivhex) {
|
||||||
|
fprintf(stderr, "gmssl %s: option '-iv' required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
zuc256_init(&zuc_state, key, iv);
|
||||||
|
while ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) > 0) {
|
||||||
|
zuc_encrypt(&zuc_state, inbuf, inlen, outbuf);
|
||||||
|
if (fwrite(outbuf, 1, inlen, outfp) != inlen) {
|
||||||
|
fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ferror(infp)) {
|
||||||
|
fprintf(stderr, "gmssl %s: read failure : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&zuc_state, sizeof(zuc_state));
|
||||||
|
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;
|
||||||
|
}
|
||||||
310
tools/zuc_128_eea3.c
Normal file
310
tools/zuc_128_eea3.c
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 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 <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gmssl/mem.h>
|
||||||
|
#include <gmssl/zuc.h>
|
||||||
|
#include <gmssl/hex.h>
|
||||||
|
#include <gmssl/endian.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char *usage =
|
||||||
|
"-key hex -count num -bearer num -direction num [-in file|-in_hex hex] [-out file]";
|
||||||
|
|
||||||
|
static const char *help =
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -key hex 128-EEA3 confidentiality key, 16 bytes\n"
|
||||||
|
" -count num COUNT parameter, 32-bit integer, decimal or 0x-prefixed hex\n"
|
||||||
|
" -bearer num BEARER parameter, 5-bit integer in [0, 31]\n"
|
||||||
|
" -direction num DIRECTION parameter, 0 or 1\n"
|
||||||
|
" -in_hex hex Input bytes in HEX format\n"
|
||||||
|
" -in file | stdin Input file path\n"
|
||||||
|
" `-in_hex` and `-in` should not be used together\n"
|
||||||
|
" If neither `-in_hex` nor `-in` specified, read from stdin\n"
|
||||||
|
" -out file | stdout Output ciphertext bytes. If not specified, output to stdout\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl zuc_128_eea3 -key 173d14ba5003731d7a60049470f00a29 \\\n"
|
||||||
|
" -count 0x66035492 -bearer 15 -direction 0 \\\n"
|
||||||
|
" -in_hex 6cf65340735552ab0c9752fa6f9025fe0bd675d9005875b2 -out ciphertext.bin\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
static int parse_uint64(const char *s, uint64_t max, uint64_t *out)
|
||||||
|
{
|
||||||
|
char *end = NULL;
|
||||||
|
unsigned long long v;
|
||||||
|
|
||||||
|
if (!s || !*s) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
v = strtoull(s, &end, 0);
|
||||||
|
if (errno || *end || v > max) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*out = (uint64_t)v;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog)
|
||||||
|
{
|
||||||
|
const size_t initial_size = 4096;
|
||||||
|
const size_t max_size = 512 * 1024 * 1024;
|
||||||
|
uint8_t *buf = NULL;
|
||||||
|
size_t bufsiz = initial_size;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (!(buf = (uint8_t *)malloc(bufsiz))) {
|
||||||
|
fprintf(stderr, "gmssl %s: malloc failure\n", prog);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (len == bufsiz) {
|
||||||
|
uint8_t *tmp;
|
||||||
|
|
||||||
|
if (bufsiz >= max_size) {
|
||||||
|
fprintf(stderr, "gmssl %s: input too long, should be less than %zu\n", prog, max_size);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bufsiz *= 2;
|
||||||
|
if (bufsiz > max_size) {
|
||||||
|
bufsiz = max_size;
|
||||||
|
}
|
||||||
|
if (!(tmp = (uint8_t *)realloc(buf, bufsiz))) {
|
||||||
|
fprintf(stderr, "gmssl %s: realloc failure\n", prog);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = fread(buf + len, 1, bufsiz - len, infp);
|
||||||
|
len += n;
|
||||||
|
|
||||||
|
if (feof(infp)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ferror(infp)) {
|
||||||
|
fprintf(stderr, "gmssl %s: read failure : %s\n", prog, strerror(errno));
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*outlen = len;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zuc_128_eea3_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *keyhex = NULL;
|
||||||
|
char *inhex = NULL;
|
||||||
|
char *infile = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
uint8_t key[ZUC_KEY_SIZE];
|
||||||
|
size_t keylen;
|
||||||
|
uint8_t *in = NULL;
|
||||||
|
size_t inlen = 0;
|
||||||
|
uint8_t *padded = NULL;
|
||||||
|
ZUC_UINT32 *inwords = NULL;
|
||||||
|
ZUC_UINT32 *outwords = NULL;
|
||||||
|
uint8_t *out = NULL;
|
||||||
|
size_t nbits;
|
||||||
|
size_t nbytes = 0;
|
||||||
|
size_t nwords = 0;
|
||||||
|
size_t i;
|
||||||
|
uint64_t v;
|
||||||
|
ZUC_UINT32 count = 0;
|
||||||
|
ZUC_UINT5 bearer = 0;
|
||||||
|
ZUC_BIT direction = 0;
|
||||||
|
int count_set = 0;
|
||||||
|
int bearer_set = 0;
|
||||||
|
int direction_set = 0;
|
||||||
|
FILE *infp = stdin;
|
||||||
|
FILE *outfp = stdout;
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (!strcmp(*argv, "-help")) {
|
||||||
|
printf("usage: gmssl %s %s\n", prog, usage);
|
||||||
|
printf("%s\n", help);
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
} else if (!strcmp(*argv, "-key")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keyhex = *(++argv);
|
||||||
|
if (strlen(keyhex) != sizeof(key) * 2) {
|
||||||
|
fprintf(stderr, "gmssl %s: key should be 16 bytes\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-count")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
if (parse_uint64(*(++argv), UINT32_MAX, &v) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid COUNT value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
count = (ZUC_UINT32)v;
|
||||||
|
count_set = 1;
|
||||||
|
} else if (!strcmp(*argv, "-bearer")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
if (parse_uint64(*(++argv), 31, &v) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid BEARER value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
bearer = (ZUC_UINT5)v;
|
||||||
|
bearer_set = 1;
|
||||||
|
} else if (!strcmp(*argv, "-direction")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
if (parse_uint64(*(++argv), 1, &v) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid DIRECTION value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
direction = (ZUC_BIT)v;
|
||||||
|
direction_set = 1;
|
||||||
|
} else if (!strcmp(*argv, "-in_hex")) {
|
||||||
|
if (infile) {
|
||||||
|
fprintf(stderr, "gmssl %s: `-in` and `-in_hex` should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
inhex = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
|
if (inhex) {
|
||||||
|
fprintf(stderr, "gmssl %s: `-in` and `-in_hex` should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
infile = *(++argv);
|
||||||
|
if (!(infp = fopen(infile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %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, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyhex) {
|
||||||
|
fprintf(stderr, "gmssl %s: option '-key' required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!count_set || !bearer_set || !direction_set) {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-count', '-bearer' and '-direction' are required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inhex) {
|
||||||
|
if (strlen(inhex) % 2) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid input hex length\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
nbytes = strlen(inhex) / 2;
|
||||||
|
if (!(in = (uint8_t *)malloc(nbytes ? nbytes : 1))) {
|
||||||
|
fprintf(stderr, "gmssl %s: malloc failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (hex_to_bytes(inhex, strlen(inhex), in, &inlen) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid input hex digits\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!(in = read_content(infp, &inlen, prog))) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
nbytes = inlen;
|
||||||
|
nbits = inlen * 8;
|
||||||
|
nwords = (nbits + 31) / 32;
|
||||||
|
|
||||||
|
if (!(padded = (uint8_t *)calloc(nwords ? nwords : 1, sizeof(uint32_t)))
|
||||||
|
|| !(inwords = (ZUC_UINT32 *)calloc(nwords ? nwords : 1, sizeof(uint32_t)))
|
||||||
|
|| !(outwords = (ZUC_UINT32 *)calloc(nwords ? nwords : 1, sizeof(uint32_t)))
|
||||||
|
|| !(out = (uint8_t *)calloc(nwords ? nwords : 1, sizeof(uint32_t)))) {
|
||||||
|
fprintf(stderr, "gmssl %s: malloc failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
memcpy(padded, in, inlen);
|
||||||
|
for (i = 0; i < nwords; i++) {
|
||||||
|
inwords[i] = GETU32(padded + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
zuc_eea_encrypt(inwords, outwords, nbits, key, count, bearer, direction);
|
||||||
|
for (i = 0; i < nwords; i++) {
|
||||||
|
PUTU32(out + i * 4, outwords[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbytes && fwrite(out, 1, nbytes, outfp) != nbytes) {
|
||||||
|
fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(key, sizeof(key));
|
||||||
|
if (in) {
|
||||||
|
gmssl_secure_clear(in, inlen);
|
||||||
|
free(in);
|
||||||
|
}
|
||||||
|
if (padded) {
|
||||||
|
gmssl_secure_clear(padded, (nwords ? nwords : 1) * sizeof(uint32_t));
|
||||||
|
free(padded);
|
||||||
|
}
|
||||||
|
if (inwords) {
|
||||||
|
gmssl_secure_clear(inwords, (nwords ? nwords : 1) * sizeof(uint32_t));
|
||||||
|
free(inwords);
|
||||||
|
}
|
||||||
|
if (outwords) {
|
||||||
|
gmssl_secure_clear(outwords, (nwords ? nwords : 1) * sizeof(uint32_t));
|
||||||
|
free(outwords);
|
||||||
|
}
|
||||||
|
if (out) {
|
||||||
|
gmssl_secure_clear(out, (nwords ? nwords : 1) * sizeof(uint32_t));
|
||||||
|
free(out);
|
||||||
|
}
|
||||||
|
if (infile && infp) fclose(infp);
|
||||||
|
if (outfile && outfp) fclose(outfp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
299
tools/zuc_128_eia3.c
Normal file
299
tools/zuc_128_eia3.c
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 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 <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gmssl/mem.h>
|
||||||
|
#include <gmssl/zuc.h>
|
||||||
|
#include <gmssl/hex.h>
|
||||||
|
#include <gmssl/endian.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char *usage =
|
||||||
|
"-key hex -count num -bearer num -direction num [-in file|-in_hex hex] [-hex|-bin] [-out file]";
|
||||||
|
|
||||||
|
static const char *help =
|
||||||
|
"Options\n"
|
||||||
|
"\n"
|
||||||
|
" -key hex 128-EIA3 integrity key, 16 bytes\n"
|
||||||
|
" -count num COUNT parameter, 32-bit integer, decimal or 0x-prefixed hex\n"
|
||||||
|
" -bearer num BEARER parameter, 5-bit integer in [0, 31]\n"
|
||||||
|
" -direction num DIRECTION parameter, 0 or 1\n"
|
||||||
|
" -in_hex hex Input message bytes in HEX format\n"
|
||||||
|
" -in file | stdin Input file path\n"
|
||||||
|
" `-in_hex` and `-in` should not be used together\n"
|
||||||
|
" If neither `-in_hex` nor `-in` specified, read from stdin\n"
|
||||||
|
" -hex Output MAC as hex string (by default)\n"
|
||||||
|
" -bin Output MAC as binary\n"
|
||||||
|
" `-hex` and `-bin` should not be used together\n"
|
||||||
|
" -out file | stdout Output file path. If not specified, output to stdout\n"
|
||||||
|
"\n"
|
||||||
|
"Examples\n"
|
||||||
|
"\n"
|
||||||
|
" gmssl zuc_128_eia3 -key 00000000000000000000000000000000 \\\n"
|
||||||
|
" -count 0 -bearer 0 -direction 0 -in_hex 00\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
static int parse_uint64(const char *s, uint64_t max, uint64_t *out)
|
||||||
|
{
|
||||||
|
char *end = NULL;
|
||||||
|
unsigned long long v;
|
||||||
|
|
||||||
|
if (!s || !*s) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
v = strtoull(s, &end, 0);
|
||||||
|
if (errno || *end || v > max) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*out = (uint64_t)v;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog)
|
||||||
|
{
|
||||||
|
const size_t initial_size = 4096;
|
||||||
|
const size_t max_size = 512 * 1024 * 1024;
|
||||||
|
uint8_t *buf = NULL;
|
||||||
|
size_t bufsiz = initial_size;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (!(buf = (uint8_t *)malloc(bufsiz))) {
|
||||||
|
fprintf(stderr, "gmssl %s: malloc failure\n", prog);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (len == bufsiz) {
|
||||||
|
uint8_t *tmp;
|
||||||
|
|
||||||
|
if (bufsiz >= max_size) {
|
||||||
|
fprintf(stderr, "gmssl %s: input too long, should be less than %zu\n", prog, max_size);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bufsiz *= 2;
|
||||||
|
if (bufsiz > max_size) {
|
||||||
|
bufsiz = max_size;
|
||||||
|
}
|
||||||
|
if (!(tmp = (uint8_t *)realloc(buf, bufsiz))) {
|
||||||
|
fprintf(stderr, "gmssl %s: realloc failure\n", prog);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = fread(buf + len, 1, bufsiz - len, infp);
|
||||||
|
len += n;
|
||||||
|
|
||||||
|
if (feof(infp)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ferror(infp)) {
|
||||||
|
fprintf(stderr, "gmssl %s: read failure : %s\n", prog, strerror(errno));
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*outlen = len;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zuc_128_eia3_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *keyhex = NULL;
|
||||||
|
char *inhex = NULL;
|
||||||
|
char *infile = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
int outformat = 0;
|
||||||
|
uint8_t key[ZUC_KEY_SIZE];
|
||||||
|
size_t keylen;
|
||||||
|
uint8_t *in = NULL;
|
||||||
|
size_t inlen = 0;
|
||||||
|
size_t nbits;
|
||||||
|
size_t nbytes = 0;
|
||||||
|
uint64_t v;
|
||||||
|
ZUC_UINT32 count = 0;
|
||||||
|
ZUC_UINT5 bearer = 0;
|
||||||
|
ZUC_BIT direction = 0;
|
||||||
|
ZUC_UINT32 macword;
|
||||||
|
uint8_t mac[ZUC_MAC_SIZE];
|
||||||
|
int count_set = 0;
|
||||||
|
int bearer_set = 0;
|
||||||
|
int direction_set = 0;
|
||||||
|
FILE *infp = stdin;
|
||||||
|
FILE *outfp = stdout;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (!strcmp(*argv, "-help")) {
|
||||||
|
printf("usage: gmssl %s %s\n", prog, usage);
|
||||||
|
printf("%s\n", help);
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
} else if (!strcmp(*argv, "-key")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keyhex = *(++argv);
|
||||||
|
if (strlen(keyhex) != sizeof(key) * 2) {
|
||||||
|
fprintf(stderr, "gmssl %s: key should be 16 bytes\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-count")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
if (parse_uint64(*(++argv), UINT32_MAX, &v) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid COUNT value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
count = (ZUC_UINT32)v;
|
||||||
|
count_set = 1;
|
||||||
|
} else if (!strcmp(*argv, "-bearer")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
if (parse_uint64(*(++argv), 31, &v) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid BEARER value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
bearer = (ZUC_UINT5)v;
|
||||||
|
bearer_set = 1;
|
||||||
|
} else if (!strcmp(*argv, "-direction")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
if (parse_uint64(*(++argv), 1, &v) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid DIRECTION value\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
direction = (ZUC_BIT)v;
|
||||||
|
direction_set = 1;
|
||||||
|
} else if (!strcmp(*argv, "-in_hex")) {
|
||||||
|
if (infile) {
|
||||||
|
fprintf(stderr, "gmssl %s: `-in` and `-in_hex` should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
inhex = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
|
if (inhex) {
|
||||||
|
fprintf(stderr, "gmssl %s: `-in` and `-in_hex` should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
infile = *(++argv);
|
||||||
|
if (!(infp = fopen(infile, "rb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, infile, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-hex")) {
|
||||||
|
if (outformat == 2) {
|
||||||
|
fprintf(stderr, "gmssl %s: `-hex` and `-bin` should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
outformat = 1;
|
||||||
|
} else if (!strcmp(*argv, "-bin")) {
|
||||||
|
if (outformat == 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: `-hex` and `-bin` should not be used together\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
outformat = 2;
|
||||||
|
} else if (!strcmp(*argv, "-out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outfile = *(++argv);
|
||||||
|
if (!(outfp = fopen(outfile, "wb"))) {
|
||||||
|
fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyhex) {
|
||||||
|
fprintf(stderr, "gmssl %s: option '-key' required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!count_set || !bearer_set || !direction_set) {
|
||||||
|
fprintf(stderr, "gmssl %s: options '-count', '-bearer' and '-direction' are required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inhex) {
|
||||||
|
if (strlen(inhex) % 2) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid input hex length\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
nbytes = strlen(inhex) / 2;
|
||||||
|
if (!(in = (uint8_t *)malloc(nbytes ? nbytes : 1))) {
|
||||||
|
fprintf(stderr, "gmssl %s: malloc failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (hex_to_bytes(inhex, strlen(inhex), in, &inlen) != 1) {
|
||||||
|
fprintf(stderr, "gmssl %s: invalid input hex digits\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!(in = read_content(infp, &inlen, prog))) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
nbytes = inlen;
|
||||||
|
nbits = inlen * 8;
|
||||||
|
|
||||||
|
macword = zuc_eia_generate_mac((ZUC_UINT32 *)in, nbits, key, count, bearer, direction);
|
||||||
|
PUTU32(mac, macword);
|
||||||
|
|
||||||
|
if (outformat == 2) {
|
||||||
|
if (fwrite(mac, 1, sizeof(mac), outfp) != sizeof(mac)) {
|
||||||
|
fprintf(stderr, "gmssl %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(mac, sizeof(mac));
|
||||||
|
if (in) {
|
||||||
|
gmssl_secure_clear(in, inlen);
|
||||||
|
free(in);
|
||||||
|
}
|
||||||
|
if (infile && infp) fclose(infp);
|
||||||
|
if (outfile && outfp) fclose(outfp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user