From fb857d83ed2d34d180d12b40f44ac19ef045dbe9 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Wed, 20 May 2026 13:43:15 +0200 Subject: [PATCH] Auto-generate table of hashes. Fixes: 6c885c7732ea ("SM3 hash function") Signed-off-by: Steffen Jaeckel --- demos/latex-tables.c | 236 ++++++++++++++++++++++++++++++++++++------- doc/crypt.tex | 101 +++++++++++------- src/hashes/sm3.c | 2 +- 3 files changed, 263 insertions(+), 76 deletions(-) diff --git a/demos/latex-tables.c b/demos/latex-tables.c index af7a8df1..ef3297d7 100644 --- a/demos/latex-tables.c +++ b/demos/latex-tables.c @@ -63,16 +63,38 @@ static const char *s_map_mode(enum cipher_mode mode) exit(1); } - -static void LTC_NORETURN die(int status) +static int print_pem_ciphers(void) { - FILE* o = status == EXIT_SUCCESS ? stdout : stderr; - fprintf(o, - "Usage: latex-tables [<-h>]\n\n" - "Generate LaTeX tables from some library internal data.\n\n" - "\t-h\tThe help you're looking at.\n" - ); - exit(status); + unsigned long n; + printf("\nPEM ciphers:\n\n"); + for (n = 0; n < pem_dek_infos_num; ++n) { + char nbuf[32] = {0}; + size_t nlen = strlen(pem_dek_infos[n].name); + memcpy(nbuf, pem_dek_infos[n].name, nlen); + nbuf[nlen-1] = '}'; + printf("\\hline \\texttt{%-18s & %-15s & %-25ld & %-6s \\\\\n", + nbuf, s_map_cipher(pem_dek_infos[n].algo), + pem_dek_infos[n].keylen * 8, + s_map_mode(pem_dek_infos[n].mode)); + } + return 0; +} + +static int print_ssh_ciphers(void) +{ + unsigned long n; + printf("\nSSH ciphers:\n\n"); + for (n = 0; n < ssh_ciphers_num; ++n) { + char nbuf[32] = {0}; + size_t nlen = strlen(ssh_ciphers[n].name); + memcpy(nbuf, ssh_ciphers[n].name, nlen); + nbuf[nlen] = '}'; + printf("\\hline \\texttt{%-30s & %-16s & %-24ld & %-6s \\\\\n", + nbuf, s_map_cipher(ssh_ciphers[n].algo), + ssh_ciphers[n].keylen * 8, + s_map_mode(ssh_ciphers[n].mode)); + } + return 0; } static int s_to_lower(const char *in, char *out, unsigned long *outlen) @@ -88,35 +110,9 @@ static int s_to_lower(const char *in, char *out, unsigned long *outlen) return CRYPT_OK; } -int main(int argc, char **argv) +static int print_ecc_curves(void) { unsigned long n; - if (argc > 1 && strstr(argv[1], "-h")) - die(0); - printf("PEM ciphers:\n\n"); - for (n = 0; n < pem_dek_infos_num; ++n) { - char nbuf[32] = {0}; - size_t nlen = strlen(pem_dek_infos[n].name); - memcpy(nbuf, pem_dek_infos[n].name, nlen); - nbuf[nlen-1] = '}'; - printf("\\hline \\texttt{%-18s & %-15s & %-25ld & %-6s \\\\\n", - nbuf, s_map_cipher(pem_dek_infos[n].algo), - pem_dek_infos[n].keylen * 8, - s_map_mode(pem_dek_infos[n].mode)); - } - - printf("\nSSH ciphers:\n\n"); - for (n = 0; n < ssh_ciphers_num; ++n) { - char nbuf[32] = {0}; - size_t nlen = strlen(ssh_ciphers[n].name); - memcpy(nbuf, ssh_ciphers[n].name, nlen); - nbuf[nlen] = '}'; - printf("\\hline \\texttt{%-30s & %-16s & %-24ld & %-6s \\\\\n", - nbuf, s_map_cipher(ssh_ciphers[n].algo), - ssh_ciphers[n].keylen * 8, - s_map_mode(ssh_ciphers[n].mode)); - } - printf("\nECC curves:\n\n"); for (n = 0; ltc_ecc_curves[n].OID != NULL; ++n) { const char * const *names; @@ -160,6 +156,174 @@ int main(int argc, char **argv) lower[lowerl + 2] = '\0'; printf("\\hline \\texttt%-17s & %-36s & %-21s \\\\\n", lower, buf, ltc_ecc_curves[n].OID); } + return 0; +} + +static int s_to_upper(const char *in, char *out, unsigned long *outlen) +{ + unsigned long n; + for (n = 0; n < *outlen && in[n]; ++n) { + out[n] = toupper(in[n]); + } + if (n == *outlen) + return CRYPT_BUFFER_OVERFLOW; + out[n] = '\0'; + *outlen = n; + return CRYPT_OK; +} + +static int s_to_desc(const char *in, char *out, unsigned long outlen, int has_desc) +{ + unsigned long n, m; + if (outlen < 6) goto err_exit; + XMEMCPY(out, "\\code{", 6); + m = 6; + for (n = 0; m < outlen - 1 && in[n]; ++n, ++m) { + if (in[n] == '-' || in[n] == '_') { + out[m++] = '\\'; + out[m] = '_'; + } else + out[m] = tolower(in[n]); + } + if (outlen <= m) goto err_exit; + if (!has_desc) { + XMEMCPY(&out[m], "\\_desc", 6); + m += 6; + } + out[m++] = '}'; + out[m] = '\0'; + return CRYPT_OK; +err_exit: + fprintf(stderr, "Error: Can't print descriptor %s\n", in); + exit(1); +} + +struct desc { + void *orig; + char desc[64]; +}; + +static int hash_sorter(const void *a, const void *b) +{ + const struct ltc_hash_descriptor *A, *B; + A = ((const struct desc*)a)->orig; + B = ((const struct desc*)b)->orig; + if (A->hashsize < B->hashsize) return 1; + if (A->hashsize > B->hashsize) return -1; + if (A->ID < B->ID) return -1; + if (A->ID > B->ID) return 1; + return 0; +} + +static void print_hash_line(const char *name, const struct ltc_hash_descriptor *p) +{ + char nbuf[32]; + unsigned long nlen = sizeof(nbuf); + s_to_upper(p->name, nbuf, &nlen); + printf("\\hline %-17s & %-32s & %lu & %2d \\\\\n", nbuf, name, p->hashsize, p->ID); +} + +static int print_hash_descriptors(void) +{ + const struct { + const char *name; + const struct ltc_hash_descriptor * desc; + } special_hash_descriptors[] = { +#define HASH_DESC(name) { #name, &name } + HASH_DESC(sha256_portable_desc), +#ifdef LTC_SHA256_X86 + HASH_DESC(sha256_x86_desc), +#endif + HASH_DESC(sha224_portable_desc), +#ifdef LTC_SHA224_X86 + HASH_DESC(sha224_x86_desc), +#endif + HASH_DESC(sha1_portable_desc), +#ifdef LTC_SHA1_X86 + HASH_DESC(sha1_x86_desc), +#endif + }; + struct desc descs[TAB_SIZE + 1] = {0}; + int ids[TAB_SIZE + 1] = {0}; + unsigned long n; + + printf("\nhash descriptors:\n\n"); + register_all_hashes(); + + for (n = 0; hash_descriptor[n].name != NULL && n < TAB_SIZE; ++n) { + if (hash_descriptor[n].ID > TAB_SIZE) { + printf("Hash descriptor '%s' has invalid ID %d\n", hash_descriptor[n].name, hash_descriptor[n].ID); + return EXIT_FAILURE; + } + if (ids[hash_descriptor[n].ID] != 0) { + printf("Hash descriptor '%s' has duplicate ID %d\n", hash_descriptor[n].name, hash_descriptor[n].ID); + return EXIT_FAILURE; + } + ids[hash_descriptor[n].ID] = 1; + descs[n].orig = &hash_descriptor[n]; + s_to_desc(hash_descriptor[n].name, descs[n].desc, sizeof(descs[n].desc), 0); + } + qsort(descs, n, sizeof(struct desc), &hash_sorter); + for (n = 0; hash_descriptor[n].name != NULL && n < TAB_SIZE; ++n) { + print_hash_line(descs[n].desc, descs[n].orig); + } + + printf("\nspecial hash descriptors:\n\n"); + for (n = 0; n < LTC_ARRAY_SIZE(special_hash_descriptors); ++n) { + char nbuf[64]; + unsigned long nlen = sizeof(nbuf); + s_to_desc(special_hash_descriptors[n].name, nbuf, nlen, 1); + print_hash_line(nbuf, special_hash_descriptors[n].desc); + } + return 0; +} + +static void LTC_NORETURN die(int status) +{ + FILE* o = status == EXIT_SUCCESS ? stdout : stderr; + fprintf(o, + "Usage: latex-tables [<-h|-l|type>]\n\n" + "Generate LaTeX tables from some library internal data.\n\n" + "\ttype\tThe type of table to print.\n" + "\t-l\tList all built-in types that can be printed.\n" + "\t-h\tThe help you're looking at.\n" + ); + exit(status); +} + +int main(int argc, char **argv) +{ + const struct { + const char *name; + int (*printer)(void); + } printers[] = { + #define PRINTER(name) { #name, print_ ## name } + PRINTER(hash_descriptors), + PRINTER(pem_ciphers), + PRINTER(ssh_ciphers), + PRINTER(ecc_curves), + #undef PRINTER + }; + int err; + unsigned long n; + if (argc > 1) { + if (strstr(argv[1], "-h")) + die(0); + if (strstr(argv[1], "-l")) { + for (n = 0; n < LTC_ARRAY_SIZE(printers); ++n) { + printf("%s\n", printers[n].name); + } + return 0; + } + } + printf("libtomcrypt latex tables\n"); + + for (n = 0; n < LTC_ARRAY_SIZE(printers); ++n) { + if (argc > 1 && strstr(printers[n].name, argv[1]) == NULL) + continue; + if ((err = printers[n].printer()) != 0) + return err; + } return 0; } diff --git a/doc/crypt.tex b/doc/crypt.tex index 9285fa1d..1c8263b1 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -3066,52 +3066,75 @@ int unregister_hash(const struct ltc_hash_descriptor *hash); \end{verbatim} The following hashes are provided as of this release within the LibTomCrypt library: -\index{Hash descriptor table} +\index{Hash descriptor tables} \begin{figure}[H] \begin{center} \begin{tabular}{|c|c|c|c|} - \hline \textbf{Name} & \textbf{Descriptor Name} & \textbf{Size of Message Digest (bytes)} & \textbf{Id} \\ - \hline WHIRLPOOL & whirlpool\_desc & 64 & 11 \\ - \hline Keccak512 & keccak\_512\_desc & 64 & 32 \\ - \hline SHA3-512 & sha3\_512\_desc & 64 & 20 \\ - \hline SHA-512 & sha512\_desc & 64 & 5 \\ - \hline BLAKE2B-512 & blake2b\_512\_desc & 64 & 28 \\ - \hline Keccak384 & keccak\_384\_desc & 48 & 31 \\ - \hline SHA3-384 & sha3\_384\_desc & 48 & 19 \\ - \hline SHA-384 & sha384\_desc & 48 & 4 \\ - \hline BLAKE2B-384 & blake2b\_384\_desc & 48 & 27 \\ - \hline RIPEMD-320 & rmd160\_desc & 40 & 14 \\ - \hline SHA-512/256 & sha512\_256\_desc & 32 & 16 \\ - \hline Keccak256 & keccak\_256\_desc & 32 & 30 \\ - \hline SHA3-256 & sha3\_256\_desc & 32 & 18 \\ - \hline SHA-256 & sha256\_desc & 32 & 0 \\ - \hline RIPEMD-256 & rmd160\_desc & 32 & 13 \\ - \hline BLAKE2S-256 & blake2s\_256\_desc & 32 & 24 \\ - \hline BLAKE2B-256 & blake2b\_256\_desc & 32 & 26 \\ - \hline SM3 & sm3\_desc & 32 & 34 \\ - \hline SHA-512/224 & sha512\_224\_desc & 28 & 15 \\ - \hline Keccak224 & keccak\_224\_desc & 28 & 29 \\ - \hline SHA3-224 & sha3\_224\_desc & 28 & 17 \\ - \hline SHA-224 & sha224\_desc & 28 & 10 \\ - \hline BLAKE2S-224 & blake2s\_224\_desc & 28 & 23 \\ - \hline TIGER-192 & tiger\_desc & 24 & 1 \\ - \hline TIGER2-192 & tiger2\_desc & 24 & 33 \\ - \hline SHA-1 & sha1\_desc & 20 & 2 \\ - \hline RIPEMD-160 & rmd160\_desc & 20 & 9 \\ - \hline BLAKE2S-160 & blake2s\_160\_desc & 20 & 22 \\ - \hline BLAKE2B-160 & blake2b\_160\_desc & 20 & 25 \\ - \hline RIPEMD-128 & rmd128\_desc & 16 & 8 \\ - \hline MD5 & md5\_desc & 16 & 3 \\ - \hline MD4 & md4\_desc & 16 & 6 \\ - \hline MD2 & md2\_desc & 16 & 7 \\ - \hline BLAKE2S-128 & blake2s\_128\_desc & 16 & 21 \\ - \hline +\hline \textbf{Name} & \textbf{Descriptor Name} & \textbf{Size of Message Digest (bytes)} & \textbf{Id} \\ + +\hline SHA512 & \code{sha512\_desc} & 64 & 5 \\ +\hline WHIRLPOOL & \code{whirlpool\_desc} & 64 & 11 \\ +\hline SHA3-512 & \code{sha3\_512\_desc} & 64 & 20 \\ +\hline BLAKE2B-512 & \code{blake2b\_512\_desc} & 64 & 28 \\ +\hline KECCAK512 & \code{keccak512\_desc} & 64 & 32 \\ +\hline SHAKE256 & \code{shake256\_desc} & 64 & 35 \\ +\hline SHA384 & \code{sha384\_desc} & 48 & 4 \\ +\hline SHA3-384 & \code{sha3\_384\_desc} & 48 & 19 \\ +\hline BLAKE2B-384 & \code{blake2b\_384\_desc} & 48 & 27 \\ +\hline KECCAK384 & \code{keccak384\_desc} & 48 & 31 \\ +\hline RMD320 & \code{rmd320\_desc} & 40 & 14 \\ +\hline SHA256 & \code{sha256\_desc} & 32 & 0 \\ +\hline RMD256 & \code{rmd256\_desc} & 32 & 13 \\ +\hline SHA512-256 & \code{sha512\_256\_desc} & 32 & 16 \\ +\hline SHA3-256 & \code{sha3\_256\_desc} & 32 & 18 \\ +\hline BLAKE2S-256 & \code{blake2s\_256\_desc} & 32 & 24 \\ +\hline BLAKE2B-256 & \code{blake2b\_256\_desc} & 32 & 26 \\ +\hline KECCAK256 & \code{keccak256\_desc} & 32 & 30 \\ +\hline SHAKE128 & \code{shake128\_desc} & 32 & 34 \\ +\hline SM3 & \code{sm3\_desc} & 32 & 36 \\ +\hline SHA224 & \code{sha224\_desc} & 28 & 10 \\ +\hline SHA512-224 & \code{sha512\_224\_desc} & 28 & 15 \\ +\hline SHA3-224 & \code{sha3\_224\_desc} & 28 & 17 \\ +\hline BLAKE2S-224 & \code{blake2s\_224\_desc} & 28 & 23 \\ +\hline KECCAK224 & \code{keccak224\_desc} & 28 & 29 \\ +\hline TIGER & \code{tiger\_desc} & 24 & 1 \\ +\hline TIGER2 & \code{tiger2\_desc} & 24 & 33 \\ +\hline SHA1 & \code{sha1\_desc} & 20 & 2 \\ +\hline RMD160 & \code{rmd160\_desc} & 20 & 9 \\ +\hline BLAKE2S-160 & \code{blake2s\_160\_desc} & 20 & 22 \\ +\hline BLAKE2B-160 & \code{blake2b\_160\_desc} & 20 & 25 \\ +\hline MD5 & \code{md5\_desc} & 16 & 3 \\ +\hline MD4 & \code{md4\_desc} & 16 & 6 \\ +\hline MD2 & \code{md2\_desc} & 16 & 7 \\ +\hline RMD128 & \code{rmd128\_desc} & 16 & 8 \\ +\hline BLAKE2S-128 & \code{blake2s\_128\_desc} & 16 & 21 \\ + +\hline \end{tabular} \end{center} -\caption{Built--In Software Hashes} +\caption{Built--In Hashes} \end{figure} -\vfil + +Additional to those standard descriptors, there exist the following target-specific hash descriptors: + +\begin{figure}[H] +\begin{center} +\begin{tabular}{|c|c|c|c|} +\hline \textbf{Name} & \textbf{Descriptor Name} & \textbf{Size of Message Digest (bytes)} & \textbf{Id} \\ +\hline SHA256 & \code{sha256\_portable\_desc} & 32 & 0 \\ +\hline SHA256 & \code{sha256\_x86\_desc} & 32 & 0 \\ +\hline SHA224 & \code{sha224\_portable\_desc} & 28 & 10 \\ +\hline SHA224 & \code{sha224\_x86\_desc} & 28 & 10 \\ +\hline SHA1 & \code{sha1\_portable\_desc} & 20 & 2 \\ +\hline SHA1 & \code{sha1\_x86\_desc} & 20 & 2 \\ +\hline +\end{tabular} +\end{center} +\caption{Target--specific hash descriptors} +\end{figure} + +Those descriptors don't necessarily exist in all builds and their usage may only make sense in some setups. \mysection{Cipher Hash Construction} \index{Cipher Hash Construction} diff --git a/src/hashes/sm3.c b/src/hashes/sm3.c index acc73aee..f72ae81d 100644 --- a/src/hashes/sm3.c +++ b/src/hashes/sm3.c @@ -16,7 +16,7 @@ const struct ltc_hash_descriptor sm3_desc = { "sm3", /* name of hash */ - 34, /* internal ID */ + 36, /* internal ID */ 32, /* Size of digest in octets */ 64, /* Input block size in octets */ {1,2,156,10197,1,401}, /* ASN.1 OID 1.2.156.10197.1.401 */