diff --git a/CMakeLists.txt b/CMakeLists.txt index 0411a57..9af904b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ include_directories(include) set(libsrc src/error.c src/mem.c + src/meth.c src/pool.c src/version.c ) @@ -36,6 +37,7 @@ OPTION(WITH_ASCON "Build with ASCON module" OFF) OPTION(WITH_ASN1 "Build with asn1 module" OFF) OPTION(WITH_DEBUG "Enable debug" OFF) OPTION(WITH_ERRSTR "Build with error string" OFF) +OPTION(WITH_EXAMPLE "Build example program" OFF) OPTION(WITH_HMAC "Build with HMAC module" OFF) OPTION(WITH_LOG "Build with log module" OFF) OPTION(WITH_OSCORE "Build with OSCORE module" OFF) @@ -48,6 +50,7 @@ if(WITH_ALL) set(WITH_ASN1 ON) set(WITH_DEBUG ON) set(WITH_ERRSTR ON) + set(WITH_EXAMPLE ON) set(WITH_HMAC ON) set(WITH_LOG ON) set(WITH_OSCORE ON) @@ -148,15 +151,25 @@ endif() if(WITH_HMAC) list(APPEND libsrc src/hmac.c) + if(WITH_SM3) + add_executable(test_hmac_sm3 test/test_hmac_sm3.c) + target_include_directories(test_hmac_sm3 PUBLIC test) + target_link_libraries(test_hmac_sm3 LINK_PUBLIC tongsuo-mini) + add_test(NAME test_hmac_sm3 + COMMAND python3 -m pytest test_hmac_sm3.py + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test + ) + endif(WITH_SM3) + if(WITH_ASCON) - add_executable(test_ascon_hmac test/test_ascon_hmac.c) - target_include_directories(test_ascon_hmac PUBLIC test) - target_link_libraries(test_ascon_hmac LINK_PUBLIC tongsuo-mini) - add_test(NAME test_ascon_hmac - COMMAND python3 -m pytest test_ascon_hmac.py + add_executable(test_hmac_ascon test/test_hmac_ascon.c) + target_include_directories(test_hmac_ascon PUBLIC test) + target_link_libraries(test_hmac_ascon LINK_PUBLIC tongsuo-mini) + add_test(NAME test_hmac_ascon + COMMAND python3 -m pytest test_hmac_ascon.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test ) - endif() + endif(WITH_ASCON) endif() add_library(tongsuo-mini-obj OBJECT ${libsrc}) @@ -174,6 +187,80 @@ if(WITH_PERF) target_link_libraries(minisuo-perf LINK_PUBLIC tongsuo-mini) endif() +if(WITH_EXAMPLE) + if(WITH_SM3) + add_executable(sm3_demo examples/sm3_demo.c) + target_link_libraries(sm3_demo LINK_PUBLIC tongsuo-mini) + set_property(TARGET sm3_demo + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + + add_executable(sm3_oneshot examples/sm3_oneshot.c) + target_link_libraries(sm3_oneshot LINK_PUBLIC tongsuo-mini) + set_property(TARGET sm3_oneshot + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + endif(WITH_SM3) + + if(WITH_SM4) + add_executable(sm4_cbc_enc examples/sm4_cbc_enc.c) + target_link_libraries(sm4_cbc_enc LINK_PUBLIC tongsuo-mini) + set_property(TARGET sm4_cbc_enc + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + + add_executable(sm4_oneshot examples/sm4_oneshot.c) + target_link_libraries(sm4_oneshot LINK_PUBLIC tongsuo-mini) + set_property(TARGET sm4_oneshot + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + endif(WITH_SM4) + + if(WITH_ASCON) + add_executable(ascon_aead_enc examples/ascon_aead_enc.c) + target_link_libraries(ascon_aead_enc LINK_PUBLIC tongsuo-mini) + set_property(TARGET ascon_aead_enc + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + + add_executable(ascon_aead_oneshot examples/ascon_aead_oneshot.c) + target_link_libraries(ascon_aead_oneshot LINK_PUBLIC tongsuo-mini) + set_property(TARGET ascon_aead_oneshot + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + + add_executable(ascon_hash examples/ascon_hash.c) + target_link_libraries(ascon_hash LINK_PUBLIC tongsuo-mini) + set_property(TARGET ascon_hash + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + + add_executable(ascon_hash_oneshot examples/ascon_hash_oneshot.c) + target_link_libraries(ascon_hash_oneshot LINK_PUBLIC tongsuo-mini) + set_property(TARGET ascon_hash_oneshot + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + endif(WITH_ASCON) + + if(WITH_HMAC) + if(WITH_ASCON) + add_executable(hmac_ascon examples/hmac_ascon.c) + target_link_libraries(hmac_ascon LINK_PUBLIC tongsuo-mini) + set_property(TARGET hmac_ascon + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + endif(WITH_ASCON) + + if(WITH_SM3) + add_executable(hmac_sm3 examples/hmac_sm3.c) + target_link_libraries(hmac_sm3 LINK_PUBLIC tongsuo-mini) + set_property(TARGET hmac_sm3 + PROPERTY RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/examples) + endif(WITH_SM3) + endif(WITH_HMAC) +endif() + enable_testing() add_test(NAME test_minisuo COMMAND python3 -m pytest test_minisuo.py @@ -189,6 +276,7 @@ message(STATUS "WITH_ASCON.................${WITH_ASCON}") message(STATUS "WITH_ASN1..................${WITH_ASN1}") message(STATUS "WITH_DEBUG.................${WITH_DEBUG}") message(STATUS "WITH_ERRSTR................${WITH_ERRSTR}") +message(STATUS "WITH_EXAMPLE...............${WITH_EXAMPLE}") message(STATUS "WITH_HMAC..................${WITH_HMAC}") message(STATUS "WITH_LOG...................${WITH_LOG}") message(STATUS "WITH_OSCORE................${WITH_OSCORE}") diff --git a/app/minisuo.c b/app/minisuo.c index 508420b..2d377c2 100644 --- a/app/minisuo.c +++ b/app/minisuo.c @@ -200,7 +200,7 @@ static int sm3_handler(int argc, char **argv) return 1; } /* calculate SM3 hash, take argv[3] as the input */ - if (tsm_sm3_oneshot(argv[3], strlen(argv[3]), md) != TSM_OK) { + if (tsm_sm3_oneshot((const unsigned char *)argv[3], strlen(argv[3]), md) != TSM_OK) { fprintf(stderr, "calculation error\n"); return 1; } @@ -461,16 +461,17 @@ static int ascon_hash_handler(int argc, char **argv) return 1; } if (strcasecmp(argv[3], "HASH") == 0) { - scheme = TSM_ASCON_HASH; + scheme = TSM_HASH_ASCON_HASH; } else if (strcasecmp(argv[3], "HASHA") == 0) { - scheme = TSM_ASCON_HASHA; + scheme = TSM_HASH_ASCON_HASHA; } else { fprintf(stderr, "wrong ASCON hash scheme\n"); return 1; } /* calculate ASCON hash, take argv[5] as the input */ - if (tsm_ascon_hash_oneshot(scheme, (const unsigned char *)argv[5], strlen(argv[5]), - md, &md_len) != TSM_OK) { + if (tsm_ascon_hash_oneshot(scheme, (const unsigned char *)argv[5], strlen(argv[5]), md, + &md_len) + != TSM_OK) { fprintf(stderr, "calculation error\n"); return 1; } diff --git a/examples/ascon_aead_enc.c b/examples/ascon_aead_enc.c index 73fb97e..642dfaf 100644 --- a/examples/ascon_aead_enc.c +++ b/examples/ascon_aead_enc.c @@ -18,17 +18,24 @@ int main(void) int ret = 1; void *ctx = NULL; const char *plaintext = "hello world"; + const char *ad = "0123456789abcdef"; unsigned char *key = tsm_hex2buf("0123456789abcdef0123456789abcdef"); unsigned char *iv = tsm_hex2buf("0123456789abcdef0123456789abcdef"); unsigned char out[1024]; + unsigned char tag[TSM_ASCON_AEAD_TAG_LEN]; size_t outl, tmplen; + if (key == NULL || iv == NULL) { + goto err; + } + ctx = tsm_ascon_aead_ctx_new(); if (ctx == NULL) { goto err; } if (tsm_ascon_aead_init(ctx, TSM_ASCON_AEAD_128, key, iv, TSM_CIPH_FLAG_ENCRYPT) != TSM_OK + || tsm_ascon_aead_update(ctx, (const unsigned char *)ad, strlen(ad), NULL, NULL) != TSM_OK || tsm_ascon_aead_update(ctx, (const unsigned char *)plaintext, strlen(plaintext), @@ -41,12 +48,20 @@ int main(void) outl += tmplen; + if (tsm_ascon_aead_get_tag(ctx, tag) != TSM_OK) { + goto err; + } + printf("ASCON_AEAD_Encrypt(%s)=", plaintext); for (size_t i = 0; i < outl; i++) { printf("%02x", out[i]); } + for (size_t i = 0; i < TSM_ASCON_AEAD_TAG_LEN; i++) { + printf("%02x", tag[i]); + } + printf("\n"); ret = 0; @@ -56,6 +71,3 @@ int main(void) tsm_free(iv); return ret; } -/* cc ascon_aead_enc.c -I/opt/tongsuo-mini/include -L/opt/tongsuo-mini/lib -ltongsuo-mini \ --Wl,-rpath /opt/tongsuo-mini/lib -o ascon_aead_enc - */ diff --git a/examples/ascon_aead_oneshot.c b/examples/ascon_aead_oneshot.c new file mode 100644 index 0000000..4a5d0cd --- /dev/null +++ b/examples/ascon_aead_oneshot.c @@ -0,0 +1,57 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int ret = 1; + const char *plaintext = "hello world"; + const char *ad = "0123456789abcdef"; + unsigned char *key = tsm_hex2buf("0123456789abcdef0123456789abcdef"); + unsigned char *iv = tsm_hex2buf("0123456789abcdef0123456789abcdef"); + unsigned char out[1024]; + size_t outl; + + if (key == NULL || iv == NULL) { + goto err; + } + + if (tsm_ascon_aead_oneshot(TSM_ASCON_AEAD_128, + key, + iv, + (const unsigned char *)ad, + strlen(ad), + (const unsigned char *)plaintext, + strlen(plaintext), + out, + &outl, + TSM_CIPH_FLAG_ENCRYPT) + != TSM_OK) { + goto err; + } + + printf("ASCON_AEAD_Encrypt(%s)=", plaintext); + + for (size_t i = 0; i < outl; i++) { + printf("%02x", out[i]); + } + + printf("\n"); + + ret = 0; +err: + tsm_free(key); + tsm_free(iv); + return ret; +} diff --git a/examples/ascon_hash.c b/examples/ascon_hash.c index 0e7c95f..0183263 100644 --- a/examples/ascon_hash.c +++ b/examples/ascon_hash.c @@ -24,7 +24,7 @@ int main(void) return 1; } - if (tsm_ascon_hash_init(ctx, TSM_ASCON_HASH) != TSM_OK + if (tsm_ascon_hash_init(ctx) != TSM_OK || tsm_ascon_hash_update(ctx, (const unsigned char *)data, strlen(data)) != TSM_OK || tsm_ascon_hash_final(ctx, md, &outl) != TSM_OK) { tsm_ascon_hash_ctx_free(ctx); @@ -43,6 +43,3 @@ int main(void) return 0; } -/* cc ascon_hash.c -I/opt/tongsuo-mini/include -L/opt/tongsuo-mini/lib -ltongsuo-mini -Wl,-rpath \ -/opt/tongsuo-mini/lib -o ascon_hash - */ diff --git a/examples/ascon_hash_oneshot.c b/examples/ascon_hash_oneshot.c new file mode 100644 index 0000000..5b2dd86 --- /dev/null +++ b/examples/ascon_hash_oneshot.c @@ -0,0 +1,35 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ +#include +#include +#include +#include + +int main(void) +{ + const char *data = "hello world"; + unsigned char md[TSM_ASCON_HASH_LEN]; + size_t outl; + + if (tsm_ascon_hash_oneshot(TSM_HASH_ASCON_HASH, (const unsigned char *)data, strlen(data), md, + &outl) + != TSM_OK) { + return 1; + } + + printf("ASCON_HASH(%s)=", data); + + for (size_t i = 0; i < outl; i++) { + printf("%02x", md[i]); + } + + printf("\n"); + + return 0; +} diff --git a/examples/hmac_ascon.c b/examples/hmac_ascon.c new file mode 100644 index 0000000..bec0f23 --- /dev/null +++ b/examples/hmac_ascon.c @@ -0,0 +1,54 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ +#include +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int ret = 1; + void *ctx = NULL; + const char *data = "hello world"; + unsigned char *key = + tsm_hex2buf("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + unsigned char hmac[TSM_ASCON_HMAC_LEN]; + size_t outl; + + if (key == NULL) + goto err; + + ctx = tsm_hmac_ctx_new(); + if (ctx == NULL) { + goto err; + } + + if (tsm_hmac_init(ctx, key, 32, TSM_HASH_ASCON_HASH) != TSM_OK + || tsm_hmac_update(ctx, (const unsigned char *)data, strlen(data)) != TSM_OK + || tsm_hmac_final(ctx, hmac, &outl) != TSM_OK) { + goto err; + } + + printf("HMAC_ASCON(%s)=", data); + + for (size_t i = 0; i < outl; i++) { + printf("%02x", hmac[i]); + } + + printf("\n"); + + ret = 0; +err: + tsm_free(key); + tsm_hmac_ctx_free(ctx); + return ret; +} diff --git a/examples/hmac_sm3.c b/examples/hmac_sm3.c new file mode 100644 index 0000000..bec0f23 --- /dev/null +++ b/examples/hmac_sm3.c @@ -0,0 +1,54 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ +#include +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int ret = 1; + void *ctx = NULL; + const char *data = "hello world"; + unsigned char *key = + tsm_hex2buf("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + unsigned char hmac[TSM_ASCON_HMAC_LEN]; + size_t outl; + + if (key == NULL) + goto err; + + ctx = tsm_hmac_ctx_new(); + if (ctx == NULL) { + goto err; + } + + if (tsm_hmac_init(ctx, key, 32, TSM_HASH_ASCON_HASH) != TSM_OK + || tsm_hmac_update(ctx, (const unsigned char *)data, strlen(data)) != TSM_OK + || tsm_hmac_final(ctx, hmac, &outl) != TSM_OK) { + goto err; + } + + printf("HMAC_ASCON(%s)=", data); + + for (size_t i = 0; i < outl; i++) { + printf("%02x", hmac[i]); + } + + printf("\n"); + + ret = 0; +err: + tsm_free(key); + tsm_hmac_ctx_free(ctx); + return ret; +} diff --git a/examples/sm3_demo.c b/examples/sm3_demo.c index 951939f..bc44ffa 100644 --- a/examples/sm3_demo.c +++ b/examples/sm3_demo.c @@ -14,7 +14,8 @@ int main(void) { void *ctx = NULL; - const char *data = "hello world"; + const char *data1 = "hello "; + const char *data2 = "world"; unsigned char md[TSM_SM3_DIGEST_LEN]; ctx = tsm_sm3_ctx_new(); @@ -22,15 +23,17 @@ int main(void) return 1; } - if (tsm_sm3_init(ctx) != TSM_OK || tsm_sm3_update(ctx, data, strlen(data)) != TSM_OK - || tsm_sm3_final(ctx, md) != TSM_OK) { + if (tsm_sm3_init(ctx) != TSM_OK + || tsm_sm3_update(ctx, (const unsigned char *)data1, strlen(data1)) != TSM_OK + || tsm_sm3_update(ctx, (const unsigned char *)data2, strlen(data2)) != TSM_OK + || tsm_sm3_final(ctx, md, NULL) != TSM_OK) { tsm_sm3_ctx_free(ctx); return 1; } tsm_sm3_ctx_free(ctx); - printf("SM3(%s)=", data); + printf("SM3(%s%s)=", data1, data2); for (int i = 0; i < TSM_SM3_DIGEST_LEN; i++) { printf("%02x", md[i]); @@ -40,6 +43,3 @@ int main(void) return 0; } -/* cc sm3_demo.c -I/opt/tongsuo-mini/include -L/opt/tongsuo-mini/lib -ltongsuo-mini -Wl,-rpath \ -/opt/tongsuo-mini/lib -o sm3_demo - */ diff --git a/examples/sm3_oneshot.c b/examples/sm3_oneshot.c new file mode 100644 index 0000000..5d74f72 --- /dev/null +++ b/examples/sm3_oneshot.c @@ -0,0 +1,32 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ +#include +#include +#include +#include + +int main(void) +{ + const char *data = "hello world"; + unsigned char md[TSM_SM3_DIGEST_LEN]; + + if (tsm_sm3_oneshot((const unsigned char *)data, strlen(data), md) != TSM_OK) { + return 1; + } + + printf("SM3(%s)=", data); + + for (int i = 0; i < TSM_SM3_DIGEST_LEN; i++) { + printf("%02x", md[i]); + } + + printf("\n"); + + return 0; +} diff --git a/examples/sm4_cbc_enc.c b/examples/sm4_cbc_enc.c index a3ea8f4..fcca9e4 100644 --- a/examples/sm4_cbc_enc.c +++ b/examples/sm4_cbc_enc.c @@ -58,7 +58,3 @@ int main(void) tsm_free(iv); return ret; } - -/* cc sm4_cbc_enc.c -I/opt/tongsuo-mini/include -L/opt/tongsuo-mini/lib -ltongsuo-mini -Wl,-rpath \ -/opt/tongsuo-mini/lib -o sm4_cbc_enc - */ diff --git a/examples/sm4_oneshot.c b/examples/sm4_oneshot.c new file mode 100644 index 0000000..ac0c7bc --- /dev/null +++ b/examples/sm4_oneshot.c @@ -0,0 +1,53 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ +#include +#include +#include +#include +#include + +int main(void) +{ + int ret = 1; + const char *plaintext = "hello world"; + unsigned char *key = tsm_hex2buf("0123456789abcdef0123456789abcdef"); + unsigned char *iv = tsm_hex2buf("0123456789abcdef0123456789abcdef"); + unsigned char ciphertext[1024]; + size_t outl; + + if (key == NULL || iv == NULL) { + goto err; + } + + if (tsm_sm4_oneshot(TSM_CIPH_MODE_CBC, + key, + iv, + (const unsigned char *)plaintext, + strlen(plaintext), + ciphertext, + &outl, + TSM_CIPH_FLAG_ENCRYPT) + != TSM_OK) { + goto err; + } + + printf("SM4_CBC_Encrypt(%s)=", plaintext); + + for (size_t i = 0; i < outl; i++) { + printf("%02x", ciphertext[i]); + } + + printf("\n"); + + ret = 0; +err: + tsm_free(key); + tsm_free(iv); + return ret; +} diff --git a/include/internal/ascon.h b/include/internal/ascon.h index 1f6143d..21b2fce 100644 --- a/include/internal/ascon.h +++ b/include/internal/ascon.h @@ -42,7 +42,7 @@ typedef struct tsm_ascon_aead_ctx_st { typedef struct tsm_ascon_hash_ctx_st { ascon_state_t s; - uint8_t mode; + uint8_t alg; uint8_t buf_len; unsigned char buf[8]; /* saved partial block */ } TSM_ASCON_HASH_CTX; diff --git a/include/internal/meth.h b/include/internal/meth.h index 88d8514..3abac29 100644 --- a/include/internal/meth.h +++ b/include/internal/meth.h @@ -15,13 +15,15 @@ typedef struct { const char *name; - uint8_t type; + uint8_t alg; uint8_t hashsize; + uint8_t blocksize; void *(*newctx)(void); void (*freectx)(void *ctx); - int (*init)(void *ctx, int type); + int (*init)(void *ctx); int (*update)(void *ctx, const unsigned char *data, size_t len); int (*final)(void *ctx, unsigned char *out, size_t *outl); } TSM_HASH_METH; +void *tsm_get_hash_meth(int alg); #endif diff --git a/include/tongsuo/ascon.h b/include/tongsuo/ascon.h index abcbb9c..f93c759 100644 --- a/include/tongsuo/ascon.h +++ b/include/tongsuo/ascon.h @@ -24,9 +24,6 @@ extern "C" { # define TSM_ASCON_AEAD_KEY_LEN 16 # define TSM_ASCON_AEAD_IV_LEN 16 -# define TSM_ASCON_HASH 0x1 -# define TSM_ASCON_HASHA 0x2 - # define TSM_ASCON_HASH_LEN 32 # define TSM_ASCON_HMAC_LEN TSM_ASCON_HASH_LEN @@ -52,16 +49,19 @@ int tsm_ascon_aead_update(void *ctx, const unsigned char *in, size_t inl, unsign * function is called the encryption operation is finished and no further calls to * tsm_ascon_aead_update() should be made. Returns TSM_OK for success and others for failure. */ int tsm_ascon_aead_final(void *ctx, unsigned char *out, size_t *outl); -/* Set tag before ascon AEAD decryption. */ +/* Set tag before ascon AEAD decryption. Returns TSM_OK on success, error code on failure. */ int tsm_ascon_aead_set_tag(void *ctx, const unsigned char *tag); -/* Get tag after ascon AEAD encryption. */ +/* Get tag after ascon AEAD encryption. Returns TSM_OK on success, error code on failure. */ int tsm_ascon_aead_get_tag(void *ctx, unsigned char *tag); /* Encrypts or decrypts data at in with length inl, and retrives the result at out. The number of * bytes of result written will be written to the integer at outl. The length of key and iv * should be 16 bytes. type should be TSM_ASCON_AEAD_128 or TSM_ASCON_AEAD_128A. flags may be * TSM_CIPH_FLAG_ENCRYPT or TSM_CIPH_FLAG_DECRYPT. If you want to encrypt data without padding, - * flags should be TSM_CIPH_FLAG_ENCRYPT | TSM_CIPH_FLAG_NO_PAD. Returns TSM_OK for success and - * others for failure. */ + * flags should be TSM_CIPH_FLAG_ENCRYPT | TSM_CIPH_FLAG_NO_PAD. + * When encryption, the tag is appended to the ciphertext, so the length of out should be inl + + * TSM_ASCON_AEAD_TAG_LEN. When decryption, the tag should be located at the end of plaintext with + * the length TSM_ASCON_AEAD_TAG_LEN. + * Returns TSM_OK on success, error code on failure. */ int tsm_ascon_aead_oneshot(int type, const unsigned char *key, const unsigned char *iv, const unsigned char *ad, size_t adl, const unsigned char *in, size_t inl, unsigned char *out, size_t *outl, int flags); @@ -69,27 +69,28 @@ int tsm_ascon_aead_oneshot(int type, const unsigned char *key, const unsigned ch void *tsm_ascon_hash_ctx_new(void); /* Destroy ctx of ascon hash. */ void tsm_ascon_hash_ctx_free(void *ctx); -/* Initialize ctx with type. type should be TSM_ASCON_HASH or TSM_ASCON_HASHA. Returns TSM_OK for - * success and others for failure. */ -int tsm_ascon_hash_init(void *ctx, int type); +/* Initialize ascon hash ctx. Returns TSM_OK on success, error code on failure. */ +int tsm_ascon_hash_init(void *ctx); +/* Identical to tsm_ascon_hash_init(), but used by ascon hasha only. */ +int tsm_ascon_hasha_init(void *ctx); /* Hashes inl bytes of data at in into the hash context ctx. This function can be called serveral * times on the same ctx to hash more data. Returns TSM_OK for success and others for failure. */ int tsm_ascon_hash_update(void *ctx, const unsigned char *in, size_t inl); +/* Identical to tsm_ascon_hash_update(), but used by ascon hasha only. */ +int tsm_ascon_hasha_update(void *ctx, const unsigned char *in, size_t inl); /* Retrieves the hash value from ctx and place it in out. The number of bytes of data written will * be written to the integer at outl. If successful, the length of digest should be * TSM_ASCON_HASH_LEN. After calling tsm_ascon_hash_final() no additional calls to * tsm_ascon_hash_update() can be made. Returns TSM_OK for success and others for failure. */ int tsm_ascon_hash_final(void *ctx, unsigned char *out, size_t *outl); -/* Hashes inl bytes of data at in, and retrieves the hash value at out. type should be - * TSM_ASCON_HASH or TSM_ASCON_HASHA. The number of bytes of data written will be written to the - * integer at outl. If successful, the length of digest should be TSM_ASCON_HASH_LEN. Returns TSM_OK - * for success and others for failure. */ -int tsm_ascon_hash_oneshot(int type, const unsigned char *in, size_t inl, unsigned char *out, +/* Identical to tsm_ascon_hasha_final(), but used by ascon hasha only. */ +int tsm_ascon_hasha_final(void *ctx, unsigned char *out, size_t *outl); +/* Hashes inl bytes of data at in, and retrieves the hash value at out. hash should be either + * TSM_HASH_ASCON_HASH or TSM_HASH_ASCON_HASHA. The number of bytes of data written will be written + * to the integer at outl. If successful, the length of digest should be TSM_ASCON_HASH_LEN. Returns + * TSM_OK on success, error code on failure. */ +int tsm_ascon_hash_oneshot(int hash, const unsigned char *in, size_t inl, unsigned char *out, size_t *outl); -/* Return the method of ascon hash, including create ctx, destroy ctx, etc, maybe used by - * tsm_hmac_oneshot(). type should be TSM_ASCON_HASH or TSM_ASCON_HASHA. */ -void *tsm_ascon_hash_meth(int type); - # ifdef __cplusplus } # endif diff --git a/include/tongsuo/hmac.h b/include/tongsuo/hmac.h index a9a863a..342ecf3 100644 --- a/include/tongsuo/hmac.h +++ b/include/tongsuo/hmac.h @@ -21,10 +21,10 @@ extern "C" { void *tsm_hmac_ctx_new(void); /* Frees up the context ctx of HMAC. */ void tsm_hmac_ctx_free(void *ctx); -/* Initialize the HMAC context with the given key and key length. The meth sets the used hash - * methods. For example, if you want to use ascon hash, the meth can be obtained by calling - * tsm_ascon_hash_meth(). Returns TSM_OK for success and others for failure. */ -int tsm_hmac_init(void *ctx, const unsigned char *key, size_t keylen, void *meth); +/* Initialize the HMAC context with the given key and key length. The hash_alg sets the used hash + * algorith. + * Returns TSM_OK on success, error code on failure. */ +int tsm_hmac_init(void *ctx, const unsigned char *key, size_t keylen, int hash_alg); /* Updates the HMAC context with the given data in and data length inlen. Returns TSM_OK for success * and others for failure. */ int tsm_hmac_update(void *ctx, const unsigned char *in, size_t inlen); @@ -32,10 +32,10 @@ int tsm_hmac_update(void *ctx, const unsigned char *in, size_t inlen); * outlen. Returns TSM_OK for success and others for failure. */ int tsm_hmac_final(void *ctx, unsigned char *out, size_t *outlen); /* Computes the HMAC of the given data in and data length inlen with the given key and key length - * keylen. The result is written to out. The length of the result is written to outl. The meth sets - * the used hash methods. For example, if you want to use ascon hash, the meth can be obtained by - * calling tsm_ascon_hash_meth(). Returns TSM_OK for success and others for failure. */ -int tsm_hmac_oneshot(void *meth, const unsigned char *key, size_t keylen, const unsigned char *in, + * keylen. The result is written to out. The length of the result is written to outl. The hash_alg + * sets the used hash algorithm, maybe TSM_HASH_SM3, TSM_HASH_ASCON_HASH or others. Returns + * TSM_OK for success and others for failure. */ +int tsm_hmac_oneshot(int hash_alg, const unsigned char *key, size_t keylen, const unsigned char *in, size_t inlen, unsigned char *out, size_t *outl); # ifdef __cplusplus diff --git a/include/tongsuo/minisuo.h b/include/tongsuo/minisuo.h index d6bac6a..c4f94d1 100644 --- a/include/tongsuo/minisuo.h +++ b/include/tongsuo/minisuo.h @@ -48,8 +48,15 @@ extern "C" { # define TSM_MAX_IV_LENGTH 16 # define TSM_MAX_BLOCK_LENGTH 32 -/* Return 0 (i.e. TSM_OK) means success, others mean failure whether it is > 0 or < 0. - * Try to return specific error code if possible. */ +/* Supported hash algorithms. */ +enum { + TSM_HASH_SM3 = 1, + TSM_HASH_ASCON_HASH, + TSM_HASH_ASCON_HASHA, +}; + +/* All error codes are defined here. + * Most of APIs return TSM_OK on success, specific error code on failure. */ enum { TSM_FAILED = -1, TSM_OK = 0, @@ -72,7 +79,7 @@ enum { TSM_ERR_INVALID_ASCON_SCHEME, TSM_ERR_AEAD_VERIFY_FAILED, TSM_ERR_INVALID_HASH_SIZE, - TSM_ERR_INVALID_ALGORITHM, + TSM_ERR_INVALID_HASH_ALGORITHM, TSM_ERR_NOT_FOUND, TSM_ERR_INVALID_SEQ, TSM_ERR_REPLAYED_SEQ, diff --git a/include/tongsuo/oscore_cose.h b/include/tongsuo/oscore_cose.h index 7cd35d0..24c02e1 100644 --- a/include/tongsuo/oscore_cose.h +++ b/include/tongsuo/oscore_cose.h @@ -113,16 +113,6 @@ typedef enum { COSE_ALGORITHM_HMAC_ASCON_HMACA = 100, } cose_alg_t; -/* cose HMAC specific algorithms */ -typedef enum { - COSE_HMAC_ALG_HMAC256_64 = 4, /* truncated to 64 bits */ - COSE_HMAC_ALG_HMAC256_256 = 5, - COSE_HMAC_ALG_HMAC384_384 = 6, - COSE_HMAC_ALG_HMAC512_512 = 7, - COSE_HMAC_ALG_HMAC_ASCON_HMAC = 100, - COSE_HMAC_ALG_HMAC_ASCON_HMACA = 101, -} cose_hmac_alg_t; - /* cose HKDF specific algorithms */ typedef enum { COSE_HKDF_ALG_HKDF_ASCON_HASHA = -101, @@ -140,7 +130,7 @@ cose_alg_t tsm_cose_get_alg_id(const char *name); * buffer is returned. */ const char *tsm_cose_get_hkdf_alg_name(cose_hkdf_alg_t id, char *buffer, size_t buflen); /* Retrives HMAC algorithm from HKDF. Returns TSM_OK means success, others mean failure. */ -int tsm_cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg); +int tsm_cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, int *hmac_alg); /* Returns tag length belonging to cose algorithm. */ size_t tsm_cose_tag_len(cose_alg_t cose_alg); /* Returns hash length belonging to cose algorithm. */ diff --git a/include/tongsuo/sm3.h b/include/tongsuo/sm3.h index a339b75..89c8d0e 100644 --- a/include/tongsuo/sm3.h +++ b/include/tongsuo/sm3.h @@ -24,20 +24,21 @@ extern "C" { void *tsm_sm3_ctx_new(void); /* Frees up the context of sm3. */ void tsm_sm3_ctx_free(void *ctx); -/* Initialize the sm3 context. Returns TSM_OK on success, error code on error. */ +/* Initialize the sm3 context. Returns TSM_OK on success, error code on failure. */ int tsm_sm3_init(void *ctx); /* Updates the sm3 context with the given data in and data length len. Returns TSM_OK on success, - * error code on error. */ -int tsm_sm3_update(void *ctx, const void *data, size_t len); + * error code on failure. */ +int tsm_sm3_update(void *ctx, const unsigned char *data, size_t len); /* Finalizes the sm3 context and writes the result to md. The buffer md must hold TSM_SM3_DIGEST_LEN - * bytes. Returns TSM_OK on success, error code on error. */ -int tsm_sm3_final(void *ctx, unsigned char *md); + * bytes. The length of md is written to mdlen if mdlen is not NULL. Returns TSM_OK on success, + * error code on failure. */ +int tsm_sm3_final(void *ctx, unsigned char *md, size_t *mdlen); /* Perform SM3 transformation with the given data data and data length num. */ -void tsm_sm3_transform(void *ctx, const void *data, size_t num); +void tsm_sm3_transform(void *ctx, const unsigned char *data, size_t num); /* Computes the SM3 hash of the given data data and data length len. The result is written to md. - * The buffer md must hold TSM_SM3_DIGEST_LEN bytes. Returns TSM_OK on success, error code on error. - */ -int tsm_sm3_oneshot(const void *data, size_t len, unsigned char *md); + * The buffer md must hold TSM_SM3_DIGEST_LEN bytes. Returns TSM_OK on success, error code on + * failure. */ +int tsm_sm3_oneshot(const unsigned char *data, size_t len, unsigned char *md); # ifdef __cplusplus } diff --git a/perf/perf.c b/perf/perf.c index 00206ea..eec80de 100644 --- a/perf/perf.c +++ b/perf/perf.c @@ -117,7 +117,8 @@ int main(void) /* ASCON hash */ start = get_time(); - if (tsm_ascon_hash_oneshot(TSM_ASCON_HASH, rnd_data, inlen, ascon_md, &mdlen) != TSM_OK) { + if (tsm_ascon_hash_oneshot(TSM_HASH_ASCON_HASH, rnd_data, inlen, ascon_md, &mdlen) + != TSM_OK) { goto err; } end = get_time(); diff --git a/src/ascon.c b/src/ascon.c index b8a0ddd..3c1bfb7 100644 --- a/src/ascon.c +++ b/src/ascon.c @@ -556,7 +556,7 @@ int tsm_ascon_aead_oneshot(int type, const unsigned char *key, const unsigned ch if ((ret = tsm_ascon_aead_init(ctx, type, key, iv, flags)) != TSM_OK) goto err; - /* Expect tag after ciphertext */ + /* Expect tag after plaintext */ if (flags & TSM_CIPH_FLAG_DECRYPT) { if ((ret = tsm_ascon_aead_set_tag(ctx, in + inl - TSM_ASCON_AEAD_TAG_LEN)) != TSM_OK) goto err; @@ -594,20 +594,20 @@ int tsm_ascon_aead_oneshot(int type, const unsigned char *key, const unsigned ch return ret; } -int tsm_ascon_hash_init(void *c, int type) +static int ascon_hash_init(void *c, int alg) { TSM_ASCON_HASH_CTX *ctx = (TSM_ASCON_HASH_CTX *)c; tsm_memzero(ctx, sizeof(*ctx)); - ctx->mode = type; + ctx->alg = alg; - if (ctx->mode == TSM_ASCON_HASH) { + if (ctx->alg == TSM_HASH_ASCON_HASH) { ctx->s.x[0] = ASCON_HASH_IV; - } else if (ctx->mode == TSM_ASCON_HASHA) { + } else if (ctx->alg == TSM_HASH_ASCON_HASHA) { ctx->s.x[0] = ASCON_HASHA_IV; } else { - return eLOG(TSM_ERR_INVALID_ASCON_SCHEME); + return eLOG(TSM_ERR_INVALID_HASH_ALGORITHM); } P12(&ctx->s); @@ -616,7 +616,17 @@ int tsm_ascon_hash_init(void *c, int type) return 0; } -int tsm_ascon_hash_update(void *ctx, const unsigned char *in, size_t inl) +int tsm_ascon_hash_init(void *c) +{ + return ascon_hash_init(c, TSM_HASH_ASCON_HASH); +} + +int tsm_ascon_hasha_init(void *c) +{ + return ascon_hash_init(c, TSM_HASH_ASCON_HASHA); +} + +static int ascon_hash_update(void *ctx, const unsigned char *in, size_t inl) { TSM_ASCON_HASH_CTX *c = ctx; @@ -636,7 +646,7 @@ int tsm_ascon_hash_update(void *ctx, const unsigned char *in, size_t inl) c->s.x[0] ^= LOADBYTES(c->buf, 8); printstate("absorb text", &c->s); - if (c->mode == TSM_ASCON_HASH) + if (c->alg == TSM_HASH_ASCON_HASH) P12(&c->s); else P8(&c->s); @@ -651,7 +661,7 @@ int tsm_ascon_hash_update(void *ctx, const unsigned char *in, size_t inl) c->s.x[0] ^= LOADBYTES(in, 8); printstate("absorb text", &c->s); - if (c->mode == TSM_ASCON_HASH) + if (c->alg == TSM_HASH_ASCON_HASH) P12(&c->s); else P8(&c->s); @@ -666,7 +676,17 @@ int tsm_ascon_hash_update(void *ctx, const unsigned char *in, size_t inl) return TSM_OK; } -int tsm_ascon_hash_final(void *ctx, unsigned char *out, size_t *outl) +int tsm_ascon_hash_update(void *ctx, const unsigned char *in, size_t inl) +{ + return ascon_hash_update(ctx, in, inl); +} + +int tsm_ascon_hasha_update(void *ctx, const unsigned char *in, size_t inl) +{ + return ascon_hash_update(ctx, in, inl); +} + +int ascon_hash_final(void *ctx, unsigned char *out, size_t *outl) { TSM_ASCON_HASH_CTX *c = ctx; int len; @@ -687,7 +707,7 @@ int tsm_ascon_hash_final(void *ctx, unsigned char *out, size_t *outl) STOREBYTES(out, c->s.x[0], 8); printstate("squeeze output", &c->s); - if (c->mode == TSM_ASCON_HASH) + if (c->alg == TSM_HASH_ASCON_HASH) P12(&c->s); else P8(&c->s); @@ -704,7 +724,17 @@ int tsm_ascon_hash_final(void *ctx, unsigned char *out, size_t *outl) return TSM_OK; } -int tsm_ascon_hash_oneshot(int type, const unsigned char *in, size_t inl, unsigned char *out, +int tsm_ascon_hash_final(void *ctx, unsigned char *out, size_t *outl) +{ + return ascon_hash_final(ctx, out, outl); +} + +int tsm_ascon_hasha_final(void *ctx, unsigned char *out, size_t *outl) +{ + return ascon_hash_final(ctx, out, outl); +} + +int tsm_ascon_hash_oneshot(int hash, const unsigned char *in, size_t inl, unsigned char *out, size_t *outl) { int ret; @@ -712,9 +742,9 @@ int tsm_ascon_hash_oneshot(int type, const unsigned char *in, size_t inl, unsign if (ctx == NULL) return eLOG(TSM_ERR_MALLOC_FAILED); - if ((ret = tsm_ascon_hash_init(ctx, type)) != TSM_OK - || (ret = tsm_ascon_hash_update(ctx, in, inl)) != TSM_OK - || (ret = tsm_ascon_hash_final(ctx, out, outl)) != TSM_OK) { + if ((ret = ascon_hash_init(ctx, hash)) != TSM_OK + || (ret = ascon_hash_update(ctx, in, inl)) != TSM_OK + || (ret = ascon_hash_final(ctx, out, outl)) != TSM_OK) { tsm_ascon_hash_ctx_free(ctx); return ret; } @@ -742,35 +772,3 @@ void tsm_ascon_hash_ctx_free(void *ctx) tsm_free(c); } } - -static TSM_HASH_METH tsm_ascon_hash = { - .name = "ascon_hash", - .type = TSM_ASCON_HASH, - .hashsize = TSM_ASCON_HASH_LEN, - .newctx = tsm_ascon_hash_ctx_new, - .freectx = tsm_ascon_hash_ctx_free, - .init = tsm_ascon_hash_init, - .update = tsm_ascon_hash_update, - .final = tsm_ascon_hash_final, -}; - -static TSM_HASH_METH tsm_ascon_hasha = { - .name = "ascon_hasha", - .type = TSM_ASCON_HASHA, - .hashsize = TSM_ASCON_HASH_LEN, - .newctx = tsm_ascon_hash_ctx_new, - .freectx = tsm_ascon_hash_ctx_free, - .init = tsm_ascon_hash_init, - .update = tsm_ascon_hash_update, - .final = tsm_ascon_hash_final, -}; - -void *tsm_ascon_hash_meth(int type) -{ - if (type == TSM_ASCON_HASH) - return &tsm_ascon_hash; - else if (type == TSM_ASCON_HASHA) - return &tsm_ascon_hasha; - else - return NULL; -} diff --git a/src/error.c b/src/error.c index 831d0d9..43b62e6 100644 --- a/src/error.c +++ b/src/error.c @@ -32,7 +32,7 @@ static const char *errstr[] = { [TSM_ERR_INVALID_ASCON_SCHEME] = "Invalid Ascon scheme", [TSM_ERR_AEAD_VERIFY_FAILED] = "AEAD verify failed", [TSM_ERR_INVALID_HASH_SIZE] = "Invalid hash size", - [TSM_ERR_INVALID_ALGORITHM] = "Invalid algorithm", + [TSM_ERR_INVALID_HASH_ALGORITHM] = "Invalid hash algorithm", [TSM_ERR_NOT_FOUND] = "Not found", [TSM_ERR_INVALID_SEQ] = "Invalid sequence num", [TSM_ERR_REPLAYED_SEQ] = "Replayed sequence num", diff --git a/src/hmac.c b/src/hmac.c index 7ff518f..2cfaec8 100644 --- a/src/hmac.c +++ b/src/hmac.c @@ -16,24 +16,17 @@ #define HMAC_IPAD 0x36 #define HMAC_OPAD 0x5C -#define HMAC_BLOCK_SIZE 64 + +/* The current largest case is for SHA3-224 */ +#define HMAC_MAX_MD_CBLOCK_SIZE 144 typedef struct { void *algctx; TSM_HASH_METH *meth; - const unsigned char *key; + unsigned char *key; size_t keylen; } TSM_HMAC_CTX; -static void hmac_xor_pad(unsigned char *out, const unsigned char *in, size_t size, - unsigned char pad) -{ - while (size > 0) { - *out++ = *in++ ^ pad; - --size; - } -} - void *tsm_hmac_ctx_new(void) { return tsm_calloc(sizeof(TSM_HMAC_CTX)); @@ -44,64 +37,68 @@ void tsm_hmac_ctx_free(void *ctx) if (ctx == NULL) return; - tsm_free(ctx); + TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; + if (c->algctx != NULL) { + c->meth->freectx(c->algctx); + c->algctx = NULL; + } + + tsm_free(c->key); + tsm_free(c); } -static int hmac_absorb_key(TSM_HMAC_CTX *ctx, const unsigned char *key, size_t keylen, - unsigned char pad) +int tsm_hmac_init(void *ctx, const unsigned char *key, size_t keylen, int hash_alg) { + TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; + void *meth = tsm_get_hash_meth(hash_alg); unsigned char *temp = NULL; + unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE]; size_t temp_len; - int ret = TSM_FAILED; - size_t posn, len; + int ret, i; - temp = tsm_alloc(ctx->meth->hashsize); + if (meth == NULL) + return eLOG(TSM_ERR_INVALID_HASH_ALGORITHM); + + c->meth = meth; + + if (c->algctx == NULL) { + c->algctx = c->meth->newctx(); + if (c->algctx == NULL) + return eLOG(TSM_ERR_MALLOC_FAILED); + } + + temp = tsm_alloc(c->meth->blocksize); if (temp == NULL) return eLOG(TSM_ERR_MALLOC_FAILED); - /* Break the key up into smaller chunks and XOR it with "pad". - * We do it this way to avoid having a large buffer on the - * stack of size HMAC_BLOCK_SIZE. */ - if (keylen <= HMAC_BLOCK_SIZE) { - posn = 0; - while (posn < keylen) { - len = keylen - posn; - if (len > ctx->meth->hashsize) - len = ctx->meth->hashsize; - hmac_xor_pad(temp, key + posn, len, pad); - if ((ret = ctx->meth->update(ctx->algctx, temp, len)) != TSM_OK) - goto err; - posn += len; - } - } else { - /* Hash long keys down first and then absorb */ - if ((ret = ctx->meth->update(ctx->algctx, key, keylen)) != TSM_OK - || (ret = ctx->meth->final(ctx->algctx, temp, &temp_len)) != TSM_OK) - goto err; - - if (temp_len != ctx->meth->hashsize) { + if (keylen > c->meth->blocksize) { + if (c->meth->blocksize < c->meth->hashsize) { ret = TSM_ERR_INVALID_HASH_SIZE; goto err; } - if ((ret = ctx->meth->init(ctx->algctx, ctx->meth->type)) != TSM_OK) - goto err; - hmac_xor_pad(temp, temp, temp_len, pad); - if ((ret = ctx->meth->update(ctx->algctx, temp, temp_len)) != TSM_OK) + if ((ret = c->meth->init(c->algctx)) != TSM_OK + || (ret = c->meth->update(c->algctx, key, keylen)) != TSM_OK + || (ret = c->meth->final(c->algctx, temp, &temp_len)) != TSM_OK) goto err; - posn = temp_len; + } else { + memcpy(temp, key, keylen); + temp_len = keylen; } - /* Pad the rest of the block with the padding value */ - memset(temp, pad, ctx->meth->hashsize); - while (posn < HMAC_BLOCK_SIZE) { - len = HMAC_BLOCK_SIZE - posn; - if (len > ctx->meth->hashsize) - len = ctx->meth->hashsize; - if ((ret = ctx->meth->update(ctx->algctx, temp, len)) != TSM_OK) - goto err; - posn += len; - } + c->key = temp; + c->keylen = temp_len; + temp = NULL; + + if (c->keylen < c->meth->blocksize) + memset(c->key + c->keylen, 0, c->meth->blocksize - c->keylen); + + for (i = 0; i < c->meth->blocksize; i++) + pad[i] = c->key[i] ^ HMAC_IPAD; + + if ((ret = c->meth->init(c->algctx)) != TSM_OK + || (ret = c->meth->update(c->algctx, pad, c->meth->blocksize)) != TSM_OK) + goto err; ret = TSM_OK; err: @@ -109,28 +106,6 @@ static int hmac_absorb_key(TSM_HMAC_CTX *ctx, const unsigned char *key, size_t k return ret; } -int tsm_hmac_init(void *ctx, const unsigned char *key, size_t keylen, void *meth) -{ - TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; - int ret; - - c->key = key; - c->keylen = keylen; - c->meth = meth; - - if (c->algctx == NULL) { - c->algctx = c->meth->newctx(); - if (c->algctx == NULL) - return eLOG(TSM_ERR_MALLOC_FAILED); - } - - if ((ret = c->meth->init(c->algctx, c->meth->type)) != TSM_OK - || (ret = hmac_absorb_key(c, key, keylen, HMAC_IPAD)) != TSM_OK) - return ret; - - return TSM_OK; -} - int tsm_hmac_update(void *ctx, const unsigned char *in, size_t inlen) { TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; @@ -146,28 +121,34 @@ int tsm_hmac_final(void *ctx, unsigned char *out, size_t *outl) { TSM_HMAC_CTX *c = (TSM_HMAC_CTX *)ctx; unsigned char *temp = NULL; + unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE]; size_t temp_len; - int ret; + int ret, i; temp = tsm_alloc(c->meth->hashsize); if (temp == NULL) return eLOG(TSM_ERR_MALLOC_FAILED); - if ((ret = c->meth->final(c->algctx, temp, &temp_len)) != TSM_OK - || temp_len != c->meth->hashsize - || (ret = c->meth->init(c->algctx, c->meth->type)) != TSM_OK - || (ret = hmac_absorb_key(c, c->key, c->keylen, HMAC_OPAD)) != TSM_OK + if ((ret = c->meth->final(c->algctx, temp, &temp_len)) != TSM_OK) + goto err; + + for (i = 0; i < c->meth->blocksize; i++) + pad[i] = c->key[i] ^ HMAC_OPAD; + + if ((ret = c->meth->init(c->algctx) != TSM_OK) + || (ret = c->meth->update(c->algctx, pad, c->meth->blocksize)) != TSM_OK || (ret = c->meth->update(c->algctx, temp, temp_len)) != TSM_OK || (ret = c->meth->final(c->algctx, out, outl)) != TSM_OK) { - tsm_free(temp); - return ret; + goto err; } + ret = TSM_OK; +err: tsm_free(temp); - return TSM_OK; + return ret; } -int tsm_hmac_oneshot(void *meth, const unsigned char *key, size_t keylen, const unsigned char *in, +int tsm_hmac_oneshot(int hash_alg, const unsigned char *key, size_t keylen, const unsigned char *in, size_t inlen, unsigned char *out, size_t *outl) { TSM_HMAC_CTX *ctx; @@ -177,7 +158,7 @@ int tsm_hmac_oneshot(void *meth, const unsigned char *key, size_t keylen, const if (ctx == NULL) return eLOG(TSM_ERR_MALLOC_FAILED); - if ((ret = tsm_hmac_init(ctx, key, keylen, meth)) != TSM_OK + if ((ret = tsm_hmac_init(ctx, key, keylen, hash_alg)) != TSM_OK || (ret = tsm_hmac_update(ctx, in, inlen)) != TSM_OK || (ret = tsm_hmac_final(ctx, out, outl)) != TSM_OK) { tsm_hmac_ctx_free(ctx); diff --git a/src/meth.c b/src/meth.c new file mode 100644 index 0000000..b1fe762 --- /dev/null +++ b/src/meth.c @@ -0,0 +1,76 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ + +#include +#include +#include +#include "internal/sm3.h" +#include "internal/meth.h" + +#ifdef TSM_HAVE_ASCON +static TSM_HASH_METH tsm_ascon_hash_meth = { + .name = "ascon_hash", + .alg = TSM_HASH_ASCON_HASH, + .hashsize = TSM_ASCON_HASH_LEN, + /* The ASCON-HASH block absorption rate of 8 bytes is too short so we use the HMAC-SHA-256 + block size of 64 instead. */ + .blocksize = 64, + .newctx = tsm_ascon_hash_ctx_new, + .freectx = tsm_ascon_hash_ctx_free, + .init = tsm_ascon_hash_init, + .update = tsm_ascon_hash_update, + .final = tsm_ascon_hash_final, +}; + +static TSM_HASH_METH tsm_ascon_hasha_meth = { + .name = "ascon_hasha", + .alg = TSM_HASH_ASCON_HASHA, + .hashsize = TSM_ASCON_HASH_LEN, + /* The ASCON-HASHA block absorption rate of 8 bytes is too short so we use the HMAC-SHA-256 + block size of 64 instead.*/ + .blocksize = 64, + .newctx = tsm_ascon_hash_ctx_new, + .freectx = tsm_ascon_hash_ctx_free, + .init = tsm_ascon_hasha_init, + .update = tsm_ascon_hasha_update, + .final = tsm_ascon_hasha_final, +}; +#endif + +#ifdef TSM_HAVE_SM3 +static TSM_HASH_METH tsm_sm3_meth = { + .name = "sm3", + .alg = TSM_HASH_SM3, + .hashsize = TSM_SM3_DIGEST_LEN, + .blocksize = TSM_SM3_CBLOCK, + .newctx = tsm_sm3_ctx_new, + .freectx = tsm_sm3_ctx_free, + .init = tsm_sm3_init, + .update = tsm_sm3_update, + .final = tsm_sm3_final, +}; +#endif + +void *tsm_get_hash_meth(int alg) +{ +#ifdef TSM_HAVE_SM3 + if (alg == TSM_HASH_SM3) + return &tsm_sm3_meth; +#endif + +#ifdef TSM_HAVE_ASCON + if (alg == TSM_HASH_ASCON_HASH) + return &tsm_ascon_hash_meth; + + if (alg == TSM_HASH_ASCON_HASHA) + return &tsm_ascon_hasha_meth; +#endif + + return NULL; +} diff --git a/src/oscore_cose.c b/src/oscore_cose.c index b96981d..28d018f 100644 --- a/src/oscore_cose.c +++ b/src/oscore_cose.c @@ -8,7 +8,9 @@ */ #include "internal/log.h" +#include #include +#include #include #include #include @@ -105,13 +107,17 @@ const char *tsm_cose_get_hkdf_alg_name(cose_hkdf_alg_t id, char *buffer, size_t */ static struct hkdf_hmac_algs { cose_hkdf_alg_t hkdf_alg; - cose_hmac_alg_t hmac_alg; -} hkdf_hmacs[] = {{COSE_HKDF_ALG_HKDF_SHA_256, COSE_HMAC_ALG_HMAC256_256}, - {COSE_HKDF_ALG_HKDF_SHA_512, COSE_HMAC_ALG_HMAC512_512}, - {COSE_HKDF_ALG_HKDF_ASCON_HASH, TSM_ASCON_AEAD_128}, - {COSE_HKDF_ALG_HKDF_ASCON_HASHA, TSM_ASCON_AEAD_128A}}; + int hmac_alg; +} hkdf_hmacs[] = { + /* + {COSE_HKDF_ALG_HKDF_SHA_256, COSE_HMAC_ALG_HMAC256_256}, + {COSE_HKDF_ALG_HKDF_SHA_512, COSE_HMAC_ALG_HMAC512_512}, + */ + {COSE_HKDF_ALG_HKDF_ASCON_HASH, TSM_HASH_ASCON_HASH}, + {COSE_HKDF_ALG_HKDF_ASCON_HASHA, TSM_HASH_ASCON_HASHA}, +}; -int tsm_cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg) +int tsm_cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, int *hmac_alg) { size_t idx; diff --git a/src/oscore_crypto.c b/src/oscore_crypto.c index 2f495dc..4bce0cd 100644 --- a/src/oscore_crypto.c +++ b/src/oscore_crypto.c @@ -16,21 +16,21 @@ #include #include -static int oscore_hmac_hash(cose_hmac_alg_t hmac_alg, TSM_STR *key, TSM_STR *data, TSM_STR **hmac) +static int oscore_hmac_hash(int hmac_alg, TSM_STR *key, TSM_STR *data, TSM_STR **hmac) { int ret; unsigned char *out = NULL; size_t outl; - TSM_HASH_METH *meth = tsm_ascon_hash_meth(hmac_alg); + TSM_HASH_METH *meth = tsm_get_hash_meth(hmac_alg); if (meth == NULL) - return eLOG(TSM_ERR_INVALID_ALGORITHM); + return eLOG(TSM_ERR_INVALID_HASH_ALGORITHM); out = tsm_alloc(meth->hashsize); if (out == NULL) return eLOG(TSM_ERR_MALLOC_FAILED); - if ((ret = tsm_hmac_oneshot(meth, key->s, key->length, data->s, data->length, out, &outl)) + if ((ret = tsm_hmac_oneshot(hmac_alg, key->s, key->length, data->s, data->length, out, &outl)) != TSM_OK) { tsm_free(out); LOGE("oscore_hmac_hash: Failed hmac\n"); @@ -46,7 +46,7 @@ static int oscore_hmac_hash(cose_hmac_alg_t hmac_alg, TSM_STR *key, TSM_STR *dat static int oscore_hkdf_extract(cose_hkdf_alg_t hkdf_alg, TSM_STR *salt, TSM_STR *ikm, TSM_STR **hkdf_extract) { - cose_hmac_alg_t hmac_alg; + int hmac_alg; int ret; assert(ikm); @@ -80,7 +80,7 @@ static int oscore_hkdf_expand(cose_hkdf_alg_t hkdf_alg, size_t i; TSM_STR data; TSM_STR *hkdf = NULL; - cose_hmac_alg_t hmac_alg; + int hmac_alg; if ((ret = tsm_cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg)) != TSM_OK) goto fail; diff --git a/src/sm3.c b/src/sm3.c index af8ccc8..43a44b3 100644 --- a/src/sm3.c +++ b/src/sm3.c @@ -71,7 +71,7 @@ void *tsm_sm3_ctx_new(void) { TSM_SM3_CTX *c = NULL; - c = tsm_calloc(sizeof(*c)); + c = tsm_alloc(sizeof(*c)); if (c == NULL) { LOGERR(TSM_ERR_MALLOC_FAILED); return NULL; @@ -95,6 +95,8 @@ int tsm_sm3_init(void *ctx) { TSM_SM3_CTX *c = ctx; + tsm_memzero(c, sizeof(*c)); + c->A = SM3_A; c->B = SM3_B; c->C = SM3_C; @@ -107,7 +109,7 @@ int tsm_sm3_init(void *ctx) return TSM_OK; } -void tsm_sm3_transform(void *c, const void *p, size_t num) +void tsm_sm3_transform(void *c, const unsigned char *p, size_t num) { TSM_SM3_CTX *ctx = c; const unsigned char *data = p; @@ -276,10 +278,9 @@ void tsm_sm3_transform(void *c, const void *p, size_t num) } } -int tsm_sm3_update(void *ctx, const void *data_, size_t len) +int tsm_sm3_update(void *ctx, const unsigned char *data, size_t len) { TSM_SM3_CTX *c = ctx; - const unsigned char *data = data_; unsigned char *p; unsigned int l; size_t n; @@ -329,14 +330,14 @@ int tsm_sm3_update(void *ctx, const void *data_, size_t len) return TSM_OK; } -int tsm_sm3_final(void *ctx, unsigned char *md) +int tsm_sm3_final(void *ctx, unsigned char *md, size_t *mdlen) { TSM_SM3_CTX *c = ctx; unsigned char *p = (unsigned char *)c->data; size_t n = c->num; unsigned long ll; - p[n] = 0x80; /* there is always room for one */ + p[n] = 0x80; n++; if (n > (TSM_SM3_CBLOCK - 8)) { @@ -371,10 +372,13 @@ int tsm_sm3_final(void *ctx, unsigned char *md) ll=c->H; (void)HOST_l2c(ll, md); + if (mdlen) + *mdlen = TSM_SM3_DIGEST_LEN; + return TSM_OK; } -int tsm_sm3_oneshot(const void *data, size_t len, unsigned char *md) +int tsm_sm3_oneshot(const unsigned char *data, size_t len, unsigned char *md) { int ret; TSM_SM3_CTX *ctx = NULL; @@ -384,7 +388,7 @@ int tsm_sm3_oneshot(const void *data, size_t len, unsigned char *md) return eLOG(TSM_ERR_MALLOC_FAILED); if ((ret = tsm_sm3_init(ctx)) != TSM_OK || (ret = tsm_sm3_update(ctx, data, len)) != TSM_OK - || (ret = tsm_sm3_final(ctx, md)) != TSM_OK) { + || (ret = tsm_sm3_final(ctx, md, NULL)) != TSM_OK) { tsm_sm3_ctx_free(ctx); return ret; } diff --git a/test/test_ascon_hash.c b/test/test_ascon_hash.c index 10ee95d..8d2941d 100644 --- a/test/test_ascon_hash.c +++ b/test/test_ascon_hash.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include "test.h" @@ -25,9 +26,9 @@ int test_ascon_hash(void) size_t outlen; if (strcmp(schemestr, "hash") == 0) - scheme = TSM_ASCON_HASH; + scheme = TSM_HASH_ASCON_HASH; else - scheme = TSM_ASCON_HASHA; + scheme = TSM_HASH_ASCON_HASHA; ASSERT_OK( tsm_ascon_hash_oneshot(scheme, msg, msg == NULL ? 0 : strlen(hex_msg) / 2, buf, &outlen)); diff --git a/test/test_ascon_hmac.c b/test/test_hmac_ascon.c similarity index 83% rename from test/test_ascon_hmac.c rename to test/test_hmac_ascon.c index 663681a..aa6162f 100644 --- a/test/test_ascon_hmac.c +++ b/test/test_hmac_ascon.c @@ -13,7 +13,7 @@ #include "test.h" #include -int test_ascon_hmac(int type, const char *hex_key, const char *hex_msg, const char *hex_tag) +int test_ascon_hmac(int hash, const char *hex_key, const char *hex_msg, const char *hex_tag) { unsigned char *key = tsm_hex2buf(hex_key); unsigned char *msg = tsm_hex2buf(hex_msg); @@ -21,8 +21,8 @@ int test_ascon_hmac(int type, const char *hex_key, const char *hex_msg, const ch unsigned char buf[TSM_ASCON_HMAC_LEN]; size_t outlen; - ASSERT_OK(tsm_hmac_oneshot(tsm_ascon_hash_meth(type), key, strlen(hex_key) / 2, msg, - msg == NULL ? 0 : strlen(hex_msg) / 2, buf, &outlen)); + ASSERT_OK(tsm_hmac_oneshot(hash, key, strlen(hex_key) / 2, msg, + msg == NULL ? 0 : strlen(hex_msg) / 2, buf, &outlen)); ASSERT(outlen == TSM_ASCON_HMAC_LEN); ASSERT(memcmp(buf, tag, outlen) == 0); @@ -40,7 +40,7 @@ int test_ascon_hmac(int type, const char *hex_key, const char *hex_msg, const ch int main(int argc, char **argv) { int i; - int type; + int hash; const char *hex_key = NULL; const char *hex_msg = NULL; const char *hex_tag = NULL; @@ -68,13 +68,13 @@ int main(int argc, char **argv) } if (strcmp(algo, "ascon-hmac") == 0) - type = TSM_ASCON_HASH; + hash = TSM_HASH_ASCON_HASH; else if (strcmp(algo, "ascon-hmaca") == 0) - type = TSM_ASCON_HASHA; + hash = TSM_HASH_ASCON_HASHA; else return 1; - TEST_EX(test_ascon_hmac, type, hex_key, hex_msg, hex_tag); + TEST_EX(test_ascon_hmac, hash, hex_key, hex_msg, hex_tag); return 0; } diff --git a/test/test_ascon_hmac.py b/test/test_hmac_ascon.py similarity index 87% rename from test/test_ascon_hmac.py rename to test/test_hmac_ascon.py index 2c2dfe1..8ba0b3a 100644 --- a/test/test_ascon_hmac.py +++ b/test/test_hmac_ascon.py @@ -10,8 +10,8 @@ @pytest.mark.parametrize( "algo, kat_file", [ - ("ascon-hmac", "test_ascon_data/ascon_hmac.txt"), - ("ascon-hmaca", "test_ascon_data/ascon_hmaca.txt"), + ("ascon-hmac", "test_hmac_data/ascon_hmac.txt"), + ("ascon-hmaca", "test_hmac_data/ascon_hmaca.txt"), ], ) def test_ascon_hmac(algo, kat_file, subtests): @@ -35,4 +35,4 @@ def test_ascon_hmac(algo, kat_file, subtests): algo, tb["Key"], tb["Msg"], tb["Tag"] ) ) - tb.clear() + tb.clear() diff --git a/test/test_ascon_data/ascon_hmac.txt b/test/test_hmac_data/ascon_hmac.txt similarity index 100% rename from test/test_ascon_data/ascon_hmac.txt rename to test/test_hmac_data/ascon_hmac.txt diff --git a/test/test_ascon_data/ascon_hmaca.txt b/test/test_hmac_data/ascon_hmaca.txt similarity index 100% rename from test/test_ascon_data/ascon_hmaca.txt rename to test/test_hmac_data/ascon_hmaca.txt diff --git a/test/test_hmac_data/hmac_sm3.txt b/test/test_hmac_data/hmac_sm3.txt new file mode 100644 index 0000000..020a498 --- /dev/null +++ b/test/test_hmac_data/hmac_sm3.txt @@ -0,0 +1,21 @@ +#HMAC-SM3 from GM/T 0042-2015 Appendix D.3 + +Count = 1 +Input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +Key = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 +Output = ca05e144ed05d1857840d1f318a4a8669e559fc8391f414485bfdf7bb408963a + +Count = 2 +Input = cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd +Key = 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425 +Output = 220bf579ded555393f0159f66c99877822a3ecf610d1552154b41d44b94db3ae + +Count = 3 +Input = "Hi There" +Key = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Output = c0ba18c68b90c88bc07de794bfc7d2c8d19ec31ed8773bc2b390c9604e0be11e + +Count = 4 +Input = "what do ya want for nothing?" +Key = "Jefe" +Output = 2e87f1d16862e6d964b50a5200bf2b10b764faa9680a296a2405f24bec39f882 diff --git a/test/test_hmac_sm3.c b/test/test_hmac_sm3.c new file mode 100644 index 0000000..bb30f12 --- /dev/null +++ b/test/test_hmac_sm3.c @@ -0,0 +1,69 @@ +/* + * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + */ + +#include +#include +#include +#include "test.h" +#include + +int test_hmac_sm3(const char *hex_key, const char *hex_msg, const char *hex_tag) +{ + unsigned char *key = tsm_hex2buf(hex_key); + unsigned char *msg = tsm_hex2buf(hex_msg); + unsigned char *tag = tsm_hex2buf(hex_tag); + unsigned char buf[TSM_SM3_DIGEST_LEN]; + size_t outlen; + + ASSERT_OK(tsm_hmac_oneshot(TSM_HASH_SM3, key, strlen(hex_key) / 2, msg, + msg == NULL ? 0 : strlen(hex_msg) / 2, buf, &outlen)); + + ASSERT(outlen == TSM_SM3_DIGEST_LEN); + ASSERT(memcmp(buf, tag, outlen) == 0); + + if (key) + tsm_free(key); + if (msg) + tsm_free(msg); + if (tag) + tsm_free(tag); + + return 0; +} + +int main(int argc, char **argv) +{ + int i; + const char *hex_key = NULL; + const char *hex_msg = NULL; + const char *hex_tag = NULL; + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (i + 1 >= argc) + break; + + if (argv[i + 1][0] == '-') + continue; + + if (strcmp(argv[i], "-key") == 0) + hex_key = argv[++i]; + else if (strcmp(argv[i], "-msg") == 0) + hex_msg = argv[++i]; + else if (strcmp(argv[i], "-tag") == 0) + hex_tag = argv[++i]; + else + return 1; + } + } + + TEST_EX(test_hmac_sm3, hex_key, hex_msg, hex_tag); + + return 0; +} diff --git a/test/test_hmac_sm3.py b/test/test_hmac_sm3.py new file mode 100644 index 0000000..ac6ba3d --- /dev/null +++ b/test/test_hmac_sm3.py @@ -0,0 +1,47 @@ +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE + +import tf +import pytest +import binascii + + +@pytest.mark.parametrize( + "kat_file", + [ + "test_hmac_data/hmac_sm3.txt", + ], +) +def test_hmac_sm3(kat_file, subtests): + with open(kat_file) as f: + tb = {} + + for line in f: + if line.startswith("#"): + continue + line = line.strip() + if not line: + continue + + name, value = line.partition("=")[::2] + tb[name.strip()] = value.strip() + + if "Count" in tb and "Input" in tb and "Key" in tb and "Output" in tb: + if tb["Input"][0] == '"': + tb["Input"] = binascii.hexlify( + tb["Input"].strip('"').encode() + ).decode() + + if tb["Key"][0] == '"': + tb["Key"] = binascii.hexlify(tb["Key"].strip('"').encode()).decode() + + with subtests.test(i=tb["Count"]): + tf.ok( + "test_hmac_sm3 -key {} -msg {} -tag {}".format( + tb["Key"], tb["Input"], tb["Output"] + ) + ) + + tb.clear() diff --git a/test/test_sm3.c b/test/test_sm3.c index d71dd2a..1b13993 100644 --- a/test/test_sm3.c +++ b/test/test_sm3.c @@ -10,67 +10,48 @@ #include #include "test.h" #include -#include "tongsuo/sm3.h" +#include +#include -/* the test is ported from tongsuo */ -int test_sm3_hash(void) +int test_sm3_hash(const char *hex_input, const char *hex_output) { - static const unsigned char input1[] = { - 0x61, 0x62, 0x63 - }; + unsigned char *input = tsm_hex2buf(hex_input); + unsigned char *output = tsm_hex2buf(hex_output); + unsigned char md[TSM_SM3_DIGEST_LEN]; - /* - * This test vector comes from Example 1 (A.1) of GM/T 0004-2012 - */ - static const unsigned char expected1[TSM_SM3_DIGEST_LEN] = { - 0x66, 0xc7, 0xf0, 0xf4, 0x62, 0xee, 0xed, 0xd9, - 0xd1, 0xf2, 0xd4, 0x6b, 0xdc, 0x10, 0xe4, 0xe2, - 0x41, 0x67, 0xc4, 0x87, 0x5c, 0xf2, 0xf7, 0xa2, - 0x29, 0x7d, 0xa0, 0x2b, 0x8f, 0x4b, 0xa8, 0xe0 - }; + ASSERT_OK(tsm_sm3_oneshot(input, strlen(hex_input) / 2, md)); + ASSERT(memcmp(md, output, TSM_SM3_DIGEST_LEN) == 0); - static const unsigned char input2[] = { - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, - 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64 - }; - - /* - * This test vector comes from Example 2 (A.2) from GM/T 0004-2012 - */ - static const unsigned char expected2[TSM_SM3_DIGEST_LEN] = { - 0xde, 0xbe, 0x9f, 0xf9, 0x22, 0x75, 0xb8, 0xa1, - 0x38, 0x60, 0x48, 0x89, 0xc1, 0x8e, 0x5a, 0x4d, - 0x6f, 0xdb, 0x70, 0xe5, 0x38, 0x7e, 0x57, 0x65, - 0x29, 0x3d, 0xcb, 0xa3, 0x9c, 0x0c, 0x57, 0x32 - }; - - unsigned char md1[TSM_SM3_DIGEST_LEN], md2[TSM_SM3_DIGEST_LEN]; - int ret = 0; - - if (tsm_sm3_oneshot(input1, sizeof(input1), md1) != TSM_OK) - return TSM_FAILED; - - if (tsm_sm3_oneshot(input2, sizeof(input2), md2) != TSM_OK) - return TSM_FAILED; - - ret = memcmp(md1, expected1, TSM_SM3_DIGEST_LEN); - ASSERT_OK(ret); - - ret = memcmp(md2, expected2, TSM_SM3_DIGEST_LEN); - ASSERT_OK(ret); + tsm_free(input); + tsm_free(output); return TSM_OK; } -int main(void) +int main(int argc, char **argv) { - TEST(test_sm3_hash); - - return TSM_OK; + int i; + const char *input = NULL; + const char *output = NULL; + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (i + 1 >= argc) + break; + + if (argv[i + 1][0] == '-') + continue; + + if (strcmp(argv[i], "-input") == 0) + input = argv[++i]; + else if (strcmp(argv[i], "-output") == 0) + output = argv[++i]; + else + return 1; + } + } + + TEST_EX(test_sm3_hash, input, output); + + return 0; } diff --git a/test/test_sm3.py b/test/test_sm3.py index c2bc315..82b67fb 100644 --- a/test/test_sm3.py +++ b/test/test_sm3.py @@ -4,7 +4,35 @@ # https://github.com/Tongsuo-Project/tongsuo-mini/blob/main/LICENSE import tf +import pytest -def test_sm3_api(): - tf.ok("test_sm3") +@pytest.mark.parametrize( + "kat_file", + [ + "test_sm3_data/sm3.txt", + ], +) +def test_sm3(kat_file, subtests): + with open(kat_file) as f: + tb = {} + + for line in f: + if line.startswith("#"): + continue + line = line.strip() + if not line: + continue + + name, value = line.partition("=")[::2] + tb[name.strip()] = value.strip() + + if "Count" in tb and "Input" in tb and "Output" in tb: + with subtests.test(i=tb["Count"]): + tf.ok( + "test_sm3 -input {} -output {}".format( + tb["Input"], tb["Output"] + ) + ) + + tb.clear() diff --git a/test/test_sm3_data/sm3.txt b/test/test_sm3_data/sm3.txt new file mode 100644 index 0000000..d04fbc6 --- /dev/null +++ b/test/test_sm3_data/sm3.txt @@ -0,0 +1,31 @@ +Count = 1 +Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857 +Output = F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A + +Count = 2 +Input = 616263 +Output = 66C7F0F462EEEDD9D1F2D46BDC10E4E24167C4875CF2F7A2297DA02B8F4BA8E0 + +Count = 3 +Input = 61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364 +Output = DEBE9FF92275B8A138604889C18E5A4D6FDB70E5387E5765293dCbA39C0C5732 + +Count = 4 +Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857 +Output = F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A + +Count = 5 +Input = 0090414C494345313233405941484F4F2E434F4D00000000000000000000000000000000000000000000000000000000000000000000E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E0165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B201686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612 +Output = 26352AF82EC19F207BBC6F9474E11E90CE0F7DDACE03B27F801817E897A81FD5 + +Count = 6 +Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A23099093BF3C137D8FCBBCDF4A2AE50F3B0F216C3122D79425FE03A45DBFE16553DF79E8DAC1CF0ECBAA2F2B49D51A4B387F2EFAF482339086A27A8E05BAED98B +Output = E4D1D0C3CA4C7F11BC8FF8CB3F4C02A78F108FA098E51A668487240F75E20F31 + +Count = 7 +Input = 008842494C4C343536405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2245493D446C38D8CC0F118374690E7DF633A8A4BFB3329B5ECE604B2B4F37F4353C0869F4B9E17773DE68FEC45E14904E0DEA45BF6CECF9918C85EA047C60A4C +Output = 6B4B6D0E276691BD4A11BF72F4FB501AE309FDACB72FA6CC336E6656119ABD67 + +Count = 8 +Input = 4D38D2958CA7FD2CFAE3AF04486959CF92C8EF48E8B83A05C112E739D5F181D03082020CA003020102020900AF28725D98D33143300C06082A811CCF550183750500307D310B300906035504060C02636E310B300906035504080C02626A310B300906035504070C02626A310F300D060355040A0C06746F70736563310F300D060355040B0C06746F707365633111300F06035504030C08546F707365634341311F301D06092A864886F70D0109010C10626A40746F707365632E636F6D2E636E301E170D3132303632343037353433395A170D3332303632303037353433395A307D310B300906035504060C02636E310B300906035504080C02626A310B300906035504070C02626A310F300D060355040A0C06746F70736563310F300D060355040B0C06746F707365633111300F06035504030C08546F707365634341311F301D06092A864886F70D0109010C10626A40746F707365632E636F6D2E636E3059301306072A8648CE3D020106082A811CCF5501822D03420004D69C2F1EEC3BFB6B95B30C28085C77B125D77A9C39525D8190768F37D6B205B589DCD316BBE7D89A9DC21917F17799E698531F5E6E3E10BD31370B259C3F81C3A3733071300F0603551D130101FF040530030101FF301D0603551D0E041604148E5D90347858BAAAD870D8BDFBA6A85E7B563B64301F0603551D230418301680148E5D90347858BAAAD870D8BDFBA6A85E7B563B64300B0603551D0F040403020106301106096086480186F8420101040403020057 +Output = C3B02E500A8B60B77DEDCF6F4C11BEF8D56E5CDE708C72065654FD7B2167915A \ No newline at end of file