Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ASCON command line tool #43

Merged
merged 1 commit into from
Oct 13, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 270 additions & 0 deletions app/minisuo.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <tongsuo/minisuo.h>
#include <tongsuo/sm3.h>
#include <tongsuo/sm4.h>
#include <tongsuo/ascon.h>
#include "internal/mem.h"

typedef int (*algorithm_handler)(int argc, char **argv);
Expand Down Expand Up @@ -211,12 +212,281 @@ static int sm3_handler(int argc, char **argv)
}
#endif

#ifdef TSM_HAVE_ASCON
static int ascon_aead_handler(int argc, char **argv)
{
int ret = 1, i, scheme, flags = 0, tag_set = 0;
long len;
int outlen;
size_t nread;
unsigned char inbuf[1024];
unsigned char outbuf[1024 + TSM_MAX_BLOCK_LENGTH];
void *ctx = NULL;
FILE *in = NULL, *out = NULL;
char *infile = NULL, *outfile = NULL;
unsigned char key[16];
unsigned char nonce[TSM_MAX_IV_LENGTH];
unsigned char tag[TSM_ASCON_AEAD_TAG_LEN];
/* associated data of ASCON is of arbitrary length. */
char *ad = NULL;

if (argc < 3) {
fprintf(stderr, "not adequate options\n");
return 1;
}

for (i = 2; i < argc; i++) {
if (strcmp(argv[i], "-scheme") == 0) {
i += 1;
if (i >= argc) {
fprintf(stderr, "no scheme argument\n");
return 1;
}
if (strcasecmp(argv[i], "128") == 0) {
scheme = TSM_ASCON_AEAD_128;
} else if (strcasecmp(argv[i], "128a") == 0) {
scheme = TSM_ASCON_AEAD_128A;
} else {
fprintf(stderr, "wrong scheme\n");
return 1;
}
} else if (strcmp(argv[i], "-key") == 0) {
i += 1;
if (i >= argc) {
fprintf(stderr, "no key\n");
return 1;
}
if (strlen(argv[i]) != 32) {
fprintf(stderr, "wrong key length\n");
return 1;
}

len = 16;
if (tsm_hex2bin(argv[i], key, &len) != TSM_OK || len != 16) {
fprintf(stderr, "wrong key format\n");
return 1;
}
} else if (strcmp(argv[i], "-nonce") == 0) {
i += 1;
if (i >= argc) {
fprintf(stderr, "no nonce\n");
return 1;
}
if (strlen(argv[i]) > sizeof(nonce) * 2) {
fprintf(stderr, "wrong nonce length\n");
return 1;
}

len = sizeof(nonce);
if (tsm_hex2bin(argv[i], nonce, &len) != TSM_OK) {
fprintf(stderr, "wrong iv format\n");
return 1;
}
} else if (strcmp(argv[i], "-ad") == 0) {
InfoHunter marked this conversation as resolved.
Show resolved Hide resolved
i += 1;
if (i >= argc) {
fprintf(stderr, "no associated data\n");
return 1;
}
ad = argv[i];
} else if (strcmp(argv[i], "-in") == 0) {
i += 1;
if (i >= argc) {
fprintf(stderr, "no input\n");
return 1;
}

infile = argv[i];
} else if (strcmp(argv[i], "-out") == 0) {
i += 1;
if (i >= argc) {
fprintf(stderr, "no output\n");
return 1;
}

outfile = argv[i];
} else if (strcmp(argv[i], "-enc") == 0) {
flags |= TSM_CIPH_FLAG_ENCRYPT;
} else if (strcmp(argv[i], "-dec") == 0) {
flags |= TSM_CIPH_FLAG_DECRYPT;
} else if (strcmp(argv[i], "-tag") == 0) {
i += 1;
if (i >= argc) {
fprintf(stderr, "no tag file\n");
return 1;
}
if (strlen(argv[i]) != 32) {
fprintf(stderr, "wrong tag length\n");
return 1;
}
len = TSM_ASCON_AEAD_TAG_LEN;
if (tsm_hex2bin(argv[i], tag, &len) != TSM_OK || len != 16) {
fprintf(stderr, "wrong tag format\n");
return 1;
}
tag_set = 1;
} else {
fprintf(stderr, "unknown option %s\n", argv[i]);
return 1;
}
}

if (flags == 0) {
fprintf(stderr, "either enc or dec should be specified\n");
return 1;
}

if (infile == NULL) {
in = stdin;
} else {
in = fopen(infile, "rb");
if (in == NULL) {
fprintf(stderr, "cannot open input file %s\n", infile);
return 1;
}
}

if (outfile == NULL) {
out = stdout;
} else {
out = fopen(outfile, "wb");
if (out == NULL) {
fprintf(stderr, "cannot open output file %s\n", outfile);
return 1;
}
}

ctx = tsm_ascon_aead_init(scheme, key, nonce, flags);
if (ctx == NULL)
return 1;

if (flags & TSM_CIPH_FLAG_DECRYPT) {
if (tag_set == 0) {
fprintf(stderr, "No tag set\n");
goto end;
InfoHunter marked this conversation as resolved.
Show resolved Hide resolved
}
if (tsm_ascon_aead_set_tag(ctx, tag) != TSM_OK) {
goto end;
}
}

if (ad != NULL && strlen(ad) > 0) {
if (tsm_ascon_aead_update(ctx, (unsigned char*)ad, strlen(ad), NULL, NULL) != TSM_OK) {
goto end;
}
}

while (1) {
nread = fread(inbuf, 1, sizeof(inbuf), in);
if (nread != sizeof(inbuf) && ferror(in)) {
fprintf(stderr, "read error\n");
goto end;
}

if (tsm_ascon_aead_update(ctx, inbuf, nread, outbuf, &outlen) != TSM_OK) {
fprintf(stderr, "cipher update error\n");
goto end;
}

if (fwrite(outbuf, 1, outlen, out) != (size_t)outlen) {
fprintf(stderr, "write error\n");
goto end;
}

if (feof(in))
break;
}

if (tsm_ascon_aead_final(ctx, outbuf, &outlen) != TSM_OK) {
fprintf(stderr, "cipher final error\n");
goto end;
}

if (fwrite(outbuf, 1, outlen, out) != (size_t)outlen) {
fprintf(stderr, "write error\n");
goto end;
}

/* tag is printed directly to stderr */
if (flags & TSM_CIPH_FLAG_ENCRYPT) {
if (tsm_ascon_aead_get_tag(ctx, tag) != TSM_OK) {
goto end;
}
fprintf(stderr, "TAG IS:\n");
for (i = 0; i < TSM_ASCON_AEAD_TAG_LEN; i++) {
fprintf(stderr, "%02X", tag[i]);
}
fprintf(stderr, "\n");
}

ret = 0;
end:
if (in != NULL && in != stdin)
fclose(in);
if (out != NULL && out != stdout)
fclose(out);
if (ctx != NULL)
tsm_ascon_aead_clean(ctx);
return ret;
}

static int ascon_hash_handler(int argc, char **argv)
{
unsigned char md[TSM_ASCON_HASH_LEN];
int i, md_len = 0, scheme;

if (argc == 3) {
/* it must be: minisuo ascon-hash -h */
if (strcmp(argv[2], "-h") == 0) {
fprintf(stderr, "minisuo ascon-hash -scheme HASH|HASHA -in DATA\n");
return 0;
}
}
if (argc == 6) {
if (strcmp(argv[2], "-scheme") != 0) {
fprintf(stderr, "wrong usage\n");
return 1;
}
if (strcmp(argv[4], "-in") != 0) {
fprintf(stderr, "wrong usage\n");
return 1;
}
if (strcasecmp(argv[3], "HASH") == 0) {
scheme = TSM_ASCON_HASH;
} else if (strcasecmp(argv[3], "HASHA") == 0) {
scheme = TSM_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) {
fprintf(stderr, "calculation error\n");
return 1;
}
printf("ASCON Hash: ");
for (i = 0; i < TSM_ASCON_HASH_LEN; i++) {
printf("%02X", (unsigned int)md[i]);
}
printf("\n");
return 0;
}
fprintf(stderr, "wrong usage\n");
return 1;
}
#endif

static cmd_handler cmds[] = {
#ifdef TSM_HAVE_SM3
{"sm3", sm3_handler},
#endif
#ifdef TSM_HAVE_SM4
{"sm4", sm4_handler},
#endif
#ifdef TSM_HAVE_ASCON
{"ascon-aead", ascon_aead_handler},
{"ascon-hash", ascon_hash_handler},
#endif
{"\0", NULL}
};
Expand Down