Path: blob/main/crypto/libecc/src/tests/ec_utils.c
34907 views
/*1* Copyright (C) 2017 - This file is part of libecc project2*3* Authors:4* Ryad BENADJILA <[email protected]>5* Arnaud EBALARD <[email protected]>6* Jean-Pierre FLORI <[email protected]>7*8* Contributors:9* Nicolas VIVET <[email protected]>10* Karim KHALFALLAH <[email protected]>11*12* This software is licensed under a dual BSD and GPL v2 license.13* See LICENSE file at the root folder of the project.14*/1516#include <libecc/libsig.h>1718#ifdef WITH_STDLIB19#include <string.h>20#include <stdlib.h>21#include <stdio.h>22#include <errno.h>23#endif2425#define HDR_MAGIC 0x342156092627typedef enum {28IMAGE_TYPE_UNKNOWN = 0,29IMAGE_TYPE0 = 1,30IMAGE_TYPE1 = 2,31IMAGE_TYPE2 = 3,32IMAGE_TYPE3 = 4,33/* Info: You can add more image header types */34} image_type;3536/* Generic header to prepend data */37typedef struct {38u32 magic; /* header header */39u32 type; /* Type of the signed image */40u32 version; /* Version */41u32 len; /* length of data after header */42u32 siglen; /* length of sig (on header + data) */43} ATTRIBUTE_PACKED metadata_hdr;4445/* Max stack working buffer size */46#define MAX_BUF_LEN 81924748typedef enum {49RAWBIN,50DOTH,51} export_file_type;5253ATTRIBUTE_WARN_UNUSED_RET static int export_private_key(FILE * file, const char *name,54const ec_priv_key *priv_key,55export_file_type file_type)56{57u8 export_buf_size, priv_key_buf[EC_STRUCTURED_PRIV_KEY_MAX_EXPORT_SIZE];58size_t written;59int ret;60u32 i;6162MUST_HAVE(file != NULL, ret, err);6364ret = priv_key_check_initialized(priv_key);65if (ret) {66printf("Error checking private key\n");67ret = -1;68goto err;69}7071/* Serialize the private key to a buffer */72export_buf_size = EC_STRUCTURED_PRIV_KEY_EXPORT_SIZE(priv_key);73ret = ec_structured_priv_key_export_to_buf(priv_key, priv_key_buf,74export_buf_size);75if (ret) {76printf("Error exporting private key to buffer\n");77ret = -1;78goto err;79}8081/* Export the private key to the file */82switch (file_type) {83case DOTH:84MUST_HAVE(name != NULL, ret, err);85fprintf(file, "const char %s[] = { ", name);86for (i = 0; i < export_buf_size; i++) {87fprintf(file, "0x%02x", priv_key_buf[i]);88fprintf(file, ", ");89}90fprintf(file, "};\n");91ret = 0;92break;93case RAWBIN:94written = fwrite(priv_key_buf, 1, export_buf_size, file);95if(written != export_buf_size){96ret = -1;97goto err;98}99ret = 0;100break;101default:102ret = -1;103}104105err:106return ret;107}108109ATTRIBUTE_WARN_UNUSED_RET static int export_public_key(FILE * file, const char *name,110const ec_pub_key *pub_key,111export_file_type file_type)112{113u8 pub_key_buf[EC_STRUCTURED_PUB_KEY_MAX_EXPORT_SIZE];114u8 export_buf_size;115int ret;116u32 i;117size_t written;118119MUST_HAVE(file != NULL, ret, err);120ret = pub_key_check_initialized(pub_key);121if (ret) {122printf("Error checking public key\n");123ret = -1;124goto err;125}126127/* Serialize the public key to a buffer */128export_buf_size = EC_STRUCTURED_PUB_KEY_EXPORT_SIZE(pub_key);129ret = ec_structured_pub_key_export_to_buf(pub_key, pub_key_buf,130export_buf_size);131if (ret) {132printf("Error exporting public key to buffer\n");133ret = -1;134goto err;135}136137/* Export the public key to the file */138switch (file_type) {139case DOTH:140MUST_HAVE(name != NULL, ret, err);141fprintf(file, "const char %s[] = { ", name);142for (i = 0; i < export_buf_size; i++) {143fprintf(file, "0x%02x", pub_key_buf[i]);144if (i != export_buf_size) {145fprintf(file, ", ");146}147}148fprintf(file, "};\n");149ret = 0;150break;151case RAWBIN:152written = fwrite(pub_key_buf, 1, export_buf_size, file);153if(written != export_buf_size){154ret = -1;155goto err;156}157ret = 0;158break;159default:160ret = -1;161}162163err:164return ret;165}166167ATTRIBUTE_WARN_UNUSED_RET static int string_to_params(const char *ec_name, const char *ec_sig_name,168ec_alg_type * sig_type,169const ec_str_params ** ec_str_p,170const char *hash_name, hash_alg_type * hash_type)171{172const ec_str_params *curve_params;173const ec_sig_mapping *sm;174const hash_mapping *hm;175u32 curve_name_len;176int ret;177178if (sig_type != NULL) {179/* Get sig type from signature alg name */180ret = get_sig_by_name(ec_sig_name, &sm);181if ((ret) || (!sm)) {182ret = -1;183printf("Error: signature type %s is unknown!\n",184ec_sig_name);185goto err;186}187*sig_type = sm->type;188}189190if (ec_str_p != NULL) {191/* Get curve params from curve name */192ret = local_strlen((const char *)ec_name, &curve_name_len); EG(ret, err);193curve_name_len += 1;194if(curve_name_len > 255){195/* Sanity check */196ret = -1;197goto err;198}199ret = ec_get_curve_params_by_name((const u8 *)ec_name,200(u8)curve_name_len, &curve_params);201if ((ret) || (!curve_params)) {202ret = -1;203printf("Error: EC curve %s is unknown!\n", ec_name);204goto err;205}206*ec_str_p = curve_params;207}208209if (hash_type != NULL) {210/* Get hash type from hash alg name */211ret = get_hash_by_name(hash_name, &hm);212if ((ret) || (!hm)) {213ret = -1;214printf("Error: hash function %s is unknown!\n",215hash_name);216goto err;217}218*hash_type = hm->type;219}220221ret = 0;222223err:224return ret;225}226227ATTRIBUTE_WARN_UNUSED_RET static int generate_and_export_key_pair(const char *ec_name,228const char *ec_sig_name,229const char *fname_prefix)230{231const ec_str_params *ec_str_p;232char fname[MAX_BUF_LEN];233char kname[MAX_BUF_LEN];234const u16 fname_len = sizeof(fname);235const u16 kname_len = sizeof(kname);236u16 prefix_len;237u32 len;238ec_alg_type sig_type;239ec_params params;240ec_key_pair kp;241FILE *file = NULL;242int ret;243244MUST_HAVE(ec_name != NULL, ret, err);245MUST_HAVE(fname_prefix != NULL, ret, err);246MUST_HAVE(ec_sig_name != NULL, ret, err);247248/* Get parameters from pretty names */249ret = string_to_params(ec_name, ec_sig_name, &sig_type, &ec_str_p,250NULL, NULL);251if (ret) {252ret = -1;253printf("Error: error when importing params\n");254goto err;255}256257/* Import the parameters */258ret = import_params(¶ms, ec_str_p); EG(ret, err);259260/* Generate the key pair */261ret = ec_key_pair_gen(&kp, ¶ms, sig_type); EG(ret, err);262263/* Get the unique affine equivalent representation of the projective point for the public key.264* This avoids ambiguity when exporting the point, and is mostly here265* for compatibility with external libraries.266*/267ret = prj_pt_unique(&(kp.pub_key.y), &(kp.pub_key.y)); EG(ret, err);268269/*************************/270271/* Export the private key to the raw binary file */272ret = local_strnlen(fname_prefix, fname_len, &len); EG(ret, err);273MUST_HAVE(len <= 0xffff, ret, err);274prefix_len = (u16)len;275ret = local_memset(fname, 0, fname_len); EG(ret, err);276ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);277ret = local_strncat(fname, "_private_key.bin", (u32)(fname_len - prefix_len)); EG(ret, err);278file = fopen(fname, "wb");279if (file == NULL) {280ret = -1;281printf("Error: file %s cannot be opened\n", fname);282goto err;283}284285ret = export_private_key(file, NULL, &(kp.priv_key), RAWBIN);286if (ret) {287ret = -1;288printf("Error exporting the private key\n");289goto err;290}291ret = fclose(file); EG(ret, err);292file = NULL;293294/* Export the private key to the .h file */295ret = local_memset(fname, 0, fname_len); EG(ret, err);296ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);297ret = local_strncat(fname, "_private_key.h", (u32)(fname_len - prefix_len)); EG(ret, err);298file = fopen(fname, "w");299if (file == NULL) {300ret = -1;301printf("Error: file %s cannot be opened\n", fname);302goto err;303}304305snprintf(kname, kname_len, "%s_%s_private_key", ec_name, ec_sig_name);306ret = export_private_key(file, kname, &(kp.priv_key), DOTH);307if (ret) {308ret = -1;309printf("Error: error exporting the private key\n");310goto err;311}312ret = fclose(file); EG(ret, err);313file = NULL;314315/*************************/316317/* Export the public key to the raw binary file */318ret = local_memset(fname, 0, fname_len); EG(ret, err);319ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);320ret = local_strncat(fname, "_public_key.bin", (u32)(fname_len - prefix_len)); EG(ret, err);321file = fopen(fname, "wb");322if (file == NULL) {323ret = -1;324printf("Error: file %s cannot be opened\n", fname);325goto err;326}327ret = export_public_key(file, NULL, &(kp.pub_key), RAWBIN);328if (ret) {329ret = -1;330printf("Error exporting the public key\n");331goto err;332}333ret = fclose(file); EG(ret, err);334file = NULL;335336/* Export the public key to the .h file */337ret = local_memset(fname, 0, fname_len); EG(ret, err);338ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);339ret = local_strncat(fname, "_public_key.h", (u32)(fname_len - prefix_len)); EG(ret, err);340file = fopen(fname, "w");341if (file == NULL) {342ret = -1;343printf("Error: file %s cannot be opened\n", fname);344goto err;345}346347snprintf(kname, kname_len, "%s_%s_public_key", ec_name, ec_sig_name);348ret = export_public_key(file, kname, &(kp.pub_key), DOTH);349if (ret) {350ret = -1;351printf("Error exporting the public key\n");352goto err;353}354ret = fclose(file); EG(ret, err);355file = NULL;356357ret = 0;358359err:360if(file != NULL){361if(fclose(file)){362ret = -1;363}364}365return ret;366}367368369ATTRIBUTE_WARN_UNUSED_RET static int store_sig(const char *in_fname, const char *out_fname,370const u8 *sig, u32 siglen,371ec_alg_type sig_type, hash_alg_type hash_type,372const u8 curve_name[MAX_CURVE_NAME_LEN],373metadata_hdr * hdr)374{375FILE *in_file = NULL, *out_file = NULL;376u8 buf[MAX_BUF_LEN];377size_t read, written;378int ret;379380MUST_HAVE((in_fname != NULL), ret, err);381MUST_HAVE((out_fname != NULL), ret, err);382MUST_HAVE((sig != NULL), ret, err);383MUST_HAVE((curve_name != NULL), ret, err);384MUST_HAVE((hdr != NULL), ret, err);385#if (MAX_BUF_LEN <= 255)386/* No need to check this is sizeof(buf) exceeds 256.387* (avoids -Werror,-Wtautological-constant-out-of-range-compare)388*/389MUST_HAVE(EC_STRUCTURED_SIG_EXPORT_SIZE(siglen) <= sizeof(buf), ret, err);390#endif391/* Import the data from the input file */392in_file = fopen(in_fname, "rb");393if (in_file == NULL) {394ret = -1;395printf("Error: file %s cannot be opened\n", in_fname);396goto err;397}398out_file = fopen(out_fname, "wb");399if (out_file == NULL) {400ret = -1;401printf("Error: file %s cannot be opened\n", out_fname);402goto err;403}404if (hdr != NULL) {405/* Write the metadata header as a prepending information */406written = fwrite(hdr, 1, sizeof(metadata_hdr), out_file);407if (written != sizeof(metadata_hdr)) {408ret = -1;409goto err;410}411}412413while (1) {414read = fread(buf, 1, sizeof(buf), in_file);415written = fwrite(buf, 1, read, out_file);416if (written != read) {417ret = -1;418printf("Error: error when writing to %s\n",419out_fname);420goto err;421}422if (read != sizeof(buf)) {423if (feof(in_file)) {424/* EOF */425break;426} else {427ret = -1;428printf("Error: error when reading from %s\n",429in_fname);430goto err;431}432}433434}435436/* Compute the structured signature */437ret = ec_structured_sig_export_to_buf(sig, siglen, buf, sizeof(buf),438sig_type, hash_type, curve_name);439if (ret) {440ret = -1;441printf("Error: error when exporting signature to structured buffer\n");442goto err;443}444/* Store the signature buffer */445written =446fwrite(buf, 1, EC_STRUCTURED_SIG_EXPORT_SIZE(siglen),447out_file);448if (written != EC_STRUCTURED_SIG_EXPORT_SIZE(siglen)) {449ret = -1;450printf("Error: error when writing to %s\n", out_fname);451goto err;452}453454ret = 0;455456err:457if(in_file != NULL){458if(fclose(in_file)){459ret = -1;460}461}462if(out_file != NULL){463if(fclose(out_file)){464ret = -1;465}466}467return ret;468}469470/* Get the raw size of a file */471ATTRIBUTE_WARN_UNUSED_RET static int get_file_size(const char *in_fname, size_t *outsz)472{473FILE *in_file = NULL;474long size;475int ret;476477MUST_HAVE(outsz != NULL, ret, err);478MUST_HAVE(in_fname != NULL, ret, err);479480*outsz = 0;481482in_file = fopen(in_fname, "rb");483if (in_file == NULL) {484ret = -1;485printf("Error: file %s cannot be opened\n", in_fname);486goto err;487}488/* Compute the size of the file */489if (fseek(in_file, 0L, SEEK_END)) {490ret = -1;491printf("Error: file %s cannot be seeked\n", in_fname);492goto err;493}494size = ftell(in_file);495if (size < 0) {496ret = -1;497printf("Error: cannot compute file %s size\n", in_fname);498goto err;499}500/* Check overflow */501if ((u64)size > (u64)(0xffffffff)) {502ret = -1;503printf("Error: file %s size %ld overflow (>= 2^32)\n",504in_fname, size);505goto err;506}507508*outsz = (u32)size;509ret = 0;510511err:512if(in_file != NULL){513if(fclose(in_file)){514ret = -1;515}516}517return ret;518}519520/* Generate a proper handler from a given type and other information */521ATTRIBUTE_WARN_UNUSED_RET static int generate_metadata_hdr(metadata_hdr * hdr, const char *hdr_type,522const char *version, size_t len, u8 siglen)523{524unsigned long ver;525char *endptr; /* for strtoul() */526int ret, check;527528MUST_HAVE((hdr != NULL), ret, err);529MUST_HAVE((hdr_type != NULL), ret, err);530MUST_HAVE((version != NULL), ret, err);531532/* The magic value */533hdr->magic = HDR_MAGIC;534535/* The given version */536#ifdef WITH_STDLIB537errno = 0;538#endif539ver = strtoul(version, &endptr, 0);540#ifdef WITH_STDLIB541if(errno){542ret = -1;543printf("Error: error in strtoul\n");544goto err;545}546#endif547if (*endptr != '\0') {548ret = -1;549printf("Error: error getting provided version %s\n", version);550goto err;551}552if ((ver & 0xffffffff) != ver) {553ret = -1;554printf("Error: provided version %s is too long!\n", version);555goto err;556}557hdr->version = (u32)ver;558559/* The image type */560hdr->type = IMAGE_TYPE_UNKNOWN;561ret = are_str_equal(hdr_type, "IMAGE_TYPE0", &check); EG(ret, err);562if (check) {563hdr->type = IMAGE_TYPE0;564}565ret = are_str_equal(hdr_type, "IMAGE_TYPE1", &check); EG(ret, err);566if (check) {567hdr->type = IMAGE_TYPE1;568}569ret = are_str_equal(hdr_type, "IMAGE_TYPE2", &check); EG(ret, err);570if (check) {571hdr->type = IMAGE_TYPE2;572}573ret = are_str_equal(hdr_type, "IMAGE_TYPE3", &check); EG(ret, err);574if (check) {575hdr->type = IMAGE_TYPE3;576}577if (hdr->type == IMAGE_TYPE_UNKNOWN) {578ret = -1;579printf("Error: unknown header type %s\n", hdr_type);580goto err;581}582583/* The length without the signature */584if ((len & 0xffffffff) != len) {585ret = -1;586printf("Error: provided length value %lu is too long!\n", (unsigned long)len);587goto err;588}589hdr->len = (u32)len;590591/* The signature length */592hdr->siglen = siglen;593594ret = 0;595596err:597return ret;598}599600/* Warn the user that the provided ancillary data won't be used601* if the algorithm does not need them.602*/603ATTRIBUTE_WARN_UNUSED_RET static int check_ancillary_data(const char *adata, ec_alg_type sig_type, const char *sig_name, int *check)604{605int ret;606607MUST_HAVE(check != NULL, ret, err);608MUST_HAVE(adata != NULL, ret, err);609MUST_HAVE(sig_name != NULL, ret, err);610MUST_HAVE(sig_type != UNKNOWN_ALG, ret, err);611612(*check) = 0;613614#if defined(WITH_SIG_EDDSA25519)615if(sig_type == EDDSA25519CTX){616(*check) = 1;617}618#endif619#if defined(WITH_SIG_EDDSA448)620if(sig_type == EDDSA448){621(*check) = 1;622}623#endif624#if defined(WITH_SIG_SM2)625if(sig_type == SM2){626(*check) = 1;627}628#endif629if((*check) == 0){630printf("Warning: you have provided optional ancillary data "\631"with a signature algorithm %s that does not need it! "\632"This data is ignored.\n", sig_name);633}634635ret = 0;636637err:638return ret;639}640641/*642* Sign data from file and append signature643*/644ATTRIBUTE_WARN_UNUSED_RET static int sign_bin_file(const char *ec_name, const char *ec_sig_name,645const char *hash_algorithm, const char *in_fname,646const char *in_key_fname,647const char *out_fname, const char *hdr_type,648const char *version, const char *adata, u16 adata_len)649{650u8 sig[EC_MAX_SIGLEN];651u8 buf[MAX_BUF_LEN];652u8 siglen;653FILE *in_file = NULL;654ec_key_pair key_pair;655FILE *in_key_file = NULL;656FILE *out_file = NULL;657const ec_str_params *ec_str_p;658ec_params params;659int ret, check;660ec_alg_type sig_type;661hash_alg_type hash_type;662u8 priv_key_buf[EC_STRUCTURED_PRIV_KEY_MAX_EXPORT_SIZE];663u8 priv_key_buf_len;664size_t raw_data_len;665metadata_hdr hdr;666size_t read, to_read;667int eof;668u8 *allocated_buff = NULL;669struct ec_sign_context sig_ctx;670671MUST_HAVE(ec_name != NULL, ret, err);672MUST_HAVE(ec_sig_name != NULL, ret, err);673MUST_HAVE(hash_algorithm != NULL, ret, err);674MUST_HAVE(in_fname != NULL, ret, err);675MUST_HAVE(in_key_fname != NULL, ret, err);676MUST_HAVE(out_fname != NULL, ret, err);677678/************************************/679/* Get parameters from pretty names */680if (string_to_params681(ec_name, ec_sig_name, &sig_type, &ec_str_p, hash_algorithm,682&hash_type)) {683ret = -1;684goto err;685}686if(adata != NULL){687/* Check if ancillary data will be used */688ret = check_ancillary_data(adata, sig_type, ec_sig_name, &check); EG(ret, err);689}690/* Import the parameters */691ret = import_params(¶ms, ec_str_p); EG(ret, err);692693/************************************/694/* Import the private key from the file */695in_key_file = fopen(in_key_fname, "rb");696if (in_key_file == NULL) {697ret = -1;698printf("Error: file %s cannot be opened\n", in_key_fname);699goto err;700}701priv_key_buf_len = (u8)fread(priv_key_buf, 1, sizeof(priv_key_buf),702in_key_file);703ret = ec_structured_key_pair_import_from_priv_key_buf(&key_pair,704¶ms,705priv_key_buf,706priv_key_buf_len,707sig_type);708if (ret) {709ret = -1;710printf("Error: error when importing key pair from %s\n",711in_key_fname);712goto err;713}714715ret = get_file_size(in_fname, &raw_data_len);716if (ret) {717ret = -1;718printf("Error: cannot retrieve file %s size\n", in_fname);719goto err;720}721if(raw_data_len == 0){722ret = -1;723printf("Error: file %s seems to be empty!\n", in_fname);724goto err;725}726ret = ec_get_sig_len(¶ms, sig_type, hash_type, &siglen);727if (ret) {728ret = -1;729printf("Error getting effective signature length from %s\n",730(const char *)(ec_str_p->name->buf));731goto err;732}733734/* Structured export case, we forge a header */735if((hdr_type != NULL) && (version != NULL)){736/************************************/737/* Forge the header */738ret = generate_metadata_hdr(&hdr, hdr_type, version, raw_data_len,739EC_STRUCTURED_SIG_EXPORT_SIZE(siglen));740741if (ret) {742ret = -1;743printf("Error: error when generating metadata\n");744goto err;745}746}747748/* Check if we support streaming */749ret = is_sign_streaming_mode_supported(sig_type, &check); EG(ret, err);750if(check){751/**** We support streaming mode ****/752/*753* Initialize signature context and start signature computation754* with generated metadata header.755*/756ret = ec_sign_init(&sig_ctx, &key_pair, sig_type, hash_type, (const u8*)adata, adata_len);757if (ret) {758ret = -1;759printf("Error: error when signing\n");760goto err;761}762763/* Structured export case, we prepend the header in the signature */764if((hdr_type != NULL) && (version != NULL)){765ret = ec_sign_update(&sig_ctx, (const u8 *)&hdr, sizeof(metadata_hdr));766if (ret) {767ret = -1;768printf("Error: error when signing\n");769goto err;770}771}772773/*774* Read file content chunk by chunk up to file length, passing each775* chunk to signature update function776*/777in_file = fopen(in_fname, "rb");778if (in_file == NULL) {779ret = -1;780printf("Error: file %s cannot be opened\n", in_fname);781goto err;782}783784eof = 0;785clearerr(in_file);786while (raw_data_len && !eof) {787to_read =788(raw_data_len <789sizeof(buf)) ? raw_data_len : sizeof(buf);790memset(buf, 0, sizeof(buf));791read = fread(buf, 1, to_read, in_file);792if (read != to_read) {793/* Check if this was EOF */794ret = feof(in_file);795clearerr(in_file);796if (ret) {797eof = 1;798}799}800801if (read > raw_data_len) {802/* we read more than expected: leave! */803break;804}805806raw_data_len -= read;807808ret = ec_sign_update(&sig_ctx, buf, (u32)read);809if (ret) {810break;811}812}813814if (raw_data_len) {815ret = -1;816printf("Error: unable to read full file content\n");817goto err;818}819820/* We can now complete signature generation */821ret = ec_sign_finalize(&sig_ctx, sig, siglen);822if (ret) {823ret = -1;824printf("Error: error when signing\n");825goto err;826}827}828else{829/**** We do not support streaming mode ****/830/* Since we don't support streaming mode, we unfortunately have to831* use a dynamic allocation here.832*/833size_t offset = 0;834allocated_buff = (u8*)malloc(1);835if(allocated_buff == NULL){836ret = -1;837printf("Error: allocation error\n");838goto err;839}840if((hdr_type != NULL) && (version != NULL)){841allocated_buff = (u8*)realloc(allocated_buff, sizeof(hdr));842if(allocated_buff == NULL){843ret = -1;844printf("Error: allocation error\n");845goto err;846}847memcpy(allocated_buff, &hdr, sizeof(hdr));848offset += sizeof(hdr);849}850in_file = fopen(in_fname, "rb");851if (in_file == NULL) {852ret = -1;853printf("Error: file %s cannot be opened\n", in_fname);854goto err;855}856857eof = 0;858clearerr(in_file);859while (raw_data_len && !eof) {860to_read =861(raw_data_len <862sizeof(buf)) ? raw_data_len : sizeof(buf);863read = fread(buf, 1, to_read, in_file);864if (read != to_read) {865/* Check if this was EOF */866ret = feof(in_file);867clearerr(in_file);868if (ret) {869eof = 1;870}871}872873if (read > raw_data_len) {874/* we read more than expected: leave! */875break;876}877878raw_data_len -= read;879880allocated_buff = (u8*)realloc(allocated_buff, offset + read);881if(allocated_buff == NULL){882ret = -1;883printf("Error: allocation error\n");884goto err;885}886memcpy(allocated_buff + offset, buf, read);887offset += read;888}889890if (raw_data_len) {891ret = -1;892printf("Error: unable to read full file content\n");893goto err;894}895896/* Sign */897ret = ec_sign(sig, siglen, &key_pair, allocated_buff, (u32)offset, sig_type, hash_type, (const u8*)adata, adata_len);898if(ret){899ret = -1;900printf("Error: error when signing\n");901goto err;902}903}904905/* Structured export case, forge the full structured file906* with HEADER || raw_binary || signature907*/908if((hdr_type != NULL) && (version != NULL)){909/***********************************/910/* Store the header, the raw data of the file as well as the signature */911ret = store_sig(in_fname, out_fname, sig, siglen, sig_type,912hash_type, params.curve_name, &hdr);913if (ret) {914ret = -1;915printf("Error: error when storing signature to %s\n",916out_fname);917goto err;918}919}920else{921/* Store the raw binary signature in the output file */922size_t written;923924out_file = fopen(out_fname, "wb");925if (out_file == NULL) {926ret = -1;927printf("Error: file %s cannot be opened\n", out_fname);928goto err;929}930written = fwrite(sig, 1, siglen, out_file);931if (written != siglen) {932ret = -1;933printf("Error: error when writing to %s\n",934out_fname);935goto err;936}937}938939ret = 0;940941err:942if(in_file != NULL){943if(fclose(in_file)){944ret = -1;945}946}947if(in_key_file != NULL){948if(fclose(in_key_file)){949ret = -1;950}951}952if(out_file != NULL){953if(fclose(out_file)){954ret = -1;955}956}957if(allocated_buff != NULL){958free(allocated_buff);959}960return ret;961}962963/* Dump metadata header */964ATTRIBUTE_WARN_UNUSED_RET static int dump_hdr_info(const metadata_hdr * hdr)965{966int ret;967968if (hdr == NULL) {969printf("Metadata header pointer is NULL!\n");970ret = -1;971goto err;972}973974/* Dump the header */975printf("Metadata header info:\n");976printf(" magic = 0x%08" PRIx32 "\n", hdr->magic);977switch (hdr->type) {978case IMAGE_TYPE0:979printf(" type = IMAGE_TYPE0\n");980break;981case IMAGE_TYPE1:982printf(" type = IMAGE_TYPE1\n");983break;984case IMAGE_TYPE2:985printf(" type = IMAGE_TYPE2\n");986break;987case IMAGE_TYPE3:988printf(" type = IMAGE_TYPE3\n");989break;990default:991printf(" type %" PRIu32 " unknown!\n", hdr->type);992break;993}994printf(" version = 0x%08" PRIx32 "\n", hdr->version);995printf(" len = 0x%08" PRIx32 "\n", hdr->len);996printf(" siglen = 0x%08" PRIx32 "\n", hdr->siglen);997ret = 0;998999err:1000return ret;1001}10021003/*1004* Verify signature data from file with appended signature1005*/1006ATTRIBUTE_WARN_UNUSED_RET static int verify_bin_file(const char *ec_name, const char *ec_sig_name,1007const char *hash_algorithm,1008const char *in_fname,1009const char *in_key_fname, const char *in_sig_fname, const char *adata, u16 adata_len)1010{1011u8 st_sig[EC_STRUCTURED_SIG_EXPORT_SIZE(EC_MAX_SIGLEN)];1012u8 stored_curve_name[MAX_CURVE_NAME_LEN];1013u8 pub_key_buf[EC_STRUCTURED_PUB_KEY_MAX_EXPORT_SIZE];1014struct ec_verify_context verif_ctx;1015ec_alg_type stored_sig_type;1016hash_alg_type stored_hash_type;1017const ec_str_params *ec_str_p;1018ec_alg_type sig_type;1019hash_alg_type hash_type;1020u8 sig[EC_MAX_SIGLEN];1021u8 siglen, st_siglen;1022size_t read, to_read;1023u8 buf[MAX_BUF_LEN];1024u8 pub_key_buf_len;1025size_t raw_data_len;1026ec_pub_key pub_key;1027FILE *in_key_file = NULL;1028FILE *in_sig_file = NULL;1029ec_params params;1030metadata_hdr hdr;1031size_t exp_len;1032FILE *in_file = NULL;1033int ret, eof, check;1034u8 *allocated_buff = NULL;10351036MUST_HAVE(ec_name != NULL, ret, err);1037MUST_HAVE(ec_sig_name != NULL, ret, err);1038MUST_HAVE(hash_algorithm != NULL, ret, err);1039MUST_HAVE(in_fname != NULL, ret, err);1040MUST_HAVE(in_key_fname != NULL, ret, err);10411042/************************************/1043/* Get parameters from pretty names */1044ret = string_to_params(ec_name, ec_sig_name, &sig_type, &ec_str_p,1045hash_algorithm, &hash_type); EG(ret, err);1046if(adata != NULL){1047/* Check if ancillary data will be used */1048ret = check_ancillary_data(adata, sig_type, ec_sig_name, &check); EG(ret, err);1049}1050/* Import the parameters */1051ret = import_params(¶ms, ec_str_p); EG(ret, err);10521053ret = ec_get_sig_len(¶ms, sig_type, hash_type, &siglen);1054if (ret) {1055ret = -1;1056printf("Error getting effective signature length from %s\n",1057(const char *)(ec_str_p->name->buf));1058goto err;1059}10601061/************************************/1062/* Import the public key from the file */1063in_key_file = fopen(in_key_fname, "rb");1064if (in_key_file == NULL) {1065ret = -1;1066printf("Error: file %s cannot be opened\n", in_key_fname);1067goto err;1068}1069pub_key_buf_len =(u8)fread(pub_key_buf, 1, sizeof(pub_key_buf),1070in_key_file);1071ret = ec_structured_pub_key_import_from_buf(&pub_key, ¶ms,1072pub_key_buf,1073pub_key_buf_len, sig_type);1074if (ret) {1075ret = -1;1076printf("Error: error when importing public key from %s\n",1077in_key_fname);1078goto err;1079}10801081/* Let's first get file size */1082ret = get_file_size(in_fname, &raw_data_len);1083if (ret) {1084ret = -1;1085printf("Error: cannot retrieve file %s size\n", in_fname);1086goto err;1087}1088if(raw_data_len == 0){1089ret = -1;1090printf("Error: file %s seems to be empty!\n", in_fname);1091goto err;1092}10931094/* Open main file to verify ... */1095in_file = fopen(in_fname, "rb");1096if (in_file == NULL) {1097ret = -1;1098printf("Error: file %s cannot be opened\n", in_fname);1099goto err;1100}11011102/*1103* We are in 'structured' mode, read the header and get the information1104* from it1105*/1106if (in_sig_fname == NULL) {1107/* ... and first read metadata header */1108read = fread(&hdr, 1, sizeof(hdr), in_file);1109if (read != sizeof(hdr)) {1110ret = -1;1111printf("Error: unable to read metadata header "1112"from file\n");1113goto err;1114}11151116/* Sanity checks on the header we get */1117if (hdr.magic != HDR_MAGIC) {1118ret = -1;1119printf("Error: got magic 0x%08" PRIx32 " instead of 0x%08x "1120"from metadata header\n", hdr.magic, (unsigned int)HDR_MAGIC);1121goto err;1122}11231124st_siglen = EC_STRUCTURED_SIG_EXPORT_SIZE(siglen);1125MUST_HAVE(raw_data_len > (sizeof(hdr) + st_siglen), ret, err);1126exp_len = raw_data_len - sizeof(hdr) - st_siglen;1127if (hdr.len != exp_len) {1128ret = -1;1129printf("Error: got raw size of %" PRIu32 " instead of %lu from "1130"metadata header\n", hdr.len,1131(unsigned long)exp_len);1132goto err;1133}11341135if (hdr.siglen != st_siglen) {1136ret = -1;1137printf("Error: got siglen %" PRIu32 " instead of %d from "1138"metadata header\n", hdr.siglen, siglen);1139goto err;1140}11411142/* Dump the header */1143ret = dump_hdr_info(&hdr); EG(ret, err);11441145/*1146* We now need to seek in file to get structured signature.1147* Before doing that, let's first check size is large enough.1148*/1149if (raw_data_len < (sizeof(hdr) + st_siglen)) {1150ret = -1;1151goto err;1152}11531154ret = fseek(in_file, (long)(raw_data_len - st_siglen),1155SEEK_SET);1156if (ret) {1157ret = -1;1158printf("Error: file %s cannot be seeked\n", in_fname);1159goto err;1160}1161read = fread(st_sig, 1, st_siglen, in_file);1162if (read != st_siglen) {1163ret = -1;1164printf("Error: unable to read structure sig from "1165"file\n");1166goto err;1167}1168/* Import the signature from the structured signature buffer */1169ret = ec_structured_sig_import_from_buf(sig, siglen,1170st_sig, st_siglen,1171&stored_sig_type,1172&stored_hash_type,1173stored_curve_name);1174if (ret) {1175ret = -1;1176printf("Error: error when importing signature "1177"from %s\n", in_fname);1178goto err;1179}1180if (stored_sig_type != sig_type) {1181ret = -1;1182printf("Error: signature type imported from signature "1183"mismatches with %s\n", ec_sig_name);1184goto err;1185}1186if (stored_hash_type != hash_type) {1187ret = -1;1188printf("Error: hash algorithm type imported from "1189"signature mismatches with %s\n",1190hash_algorithm);1191goto err;1192}1193ret = are_str_equal((char *)stored_curve_name, (char *)params.curve_name, &check); EG(ret, err);1194if (!check) {1195ret = -1;1196printf("Error: curve type '%s' imported from signature "1197"mismatches with '%s'\n", stored_curve_name,1198params.curve_name);1199goto err;1200}12011202/*1203* Get back to the beginning of file, at the beginning of header1204*/1205if (fseek(in_file, 0, SEEK_SET)) {1206ret = -1;1207printf("Error: file %s cannot be seeked\n", in_fname);1208goto err;1209}1210exp_len += sizeof(hdr);1211} else {1212/* Get the signature size */1213ret = get_file_size(in_sig_fname, &to_read);1214if (ret) {1215ret = -1;1216printf("Error: cannot retrieve file %s size\n",1217in_sig_fname);1218goto err;1219}1220if((to_read > EC_MAX_SIGLEN) || (to_read > 255) || (to_read == 0)){1221/* This is not an expected size, get out */1222ret = -1;1223printf("Error: size %d of signature in %s is > max "1224"signature size %d or > 255",1225(int)to_read, in_sig_fname, EC_MAX_SIGLEN);1226goto err;1227}1228siglen = (u8)to_read;1229/* Read the raw signature from the signature file */1230in_sig_file = fopen(in_sig_fname, "rb");1231if (in_sig_file == NULL) {1232ret = -1;1233printf("Error: file %s cannot be opened\n",1234in_sig_fname);1235goto err;1236}1237read = fread(&sig, 1, siglen, in_sig_file);1238if (read != siglen) {1239ret = -1;1240printf("Error: unable to read signature from %s\n",1241in_sig_fname);1242goto err;1243}1244exp_len = raw_data_len;1245}12461247/* Check if we support streaming */1248ret = is_verify_streaming_mode_supported(sig_type, &check); EG(ret, err);1249if(check){1250/**** We support streaming mode ****/1251/*1252* ... and read file content chunk by chunk to compute signature1253*/1254ret = ec_verify_init(&verif_ctx, &pub_key, sig, siglen,1255sig_type, hash_type, (const u8*)adata, adata_len);1256if (ret) {1257ret = -1;1258printf("Error: error when verifying ...\n");1259goto err;1260}12611262eof = 0;1263clearerr(in_file);1264while (exp_len && !eof) {1265to_read = (exp_len < sizeof(buf)) ? exp_len : sizeof(buf);1266read = fread(buf, 1, to_read, in_file);1267if (read != to_read) {1268/* Check if this was EOF */1269ret = feof(in_file);1270clearerr(in_file);1271if (ret) {1272eof = 1;1273}1274}12751276if (read > exp_len) {1277/* we read more than expected: leave! */1278break;1279}12801281exp_len -= read;12821283ret = ec_verify_update(&verif_ctx, buf, (u32)read);1284if(ret){1285ret = -1;1286printf("Error: error when verifying ...\n");1287goto err;1288}1289}1290if (exp_len) {1291ret = -1;1292printf("Error: unable to read full file content\n");1293goto err;1294}1295ret = ec_verify_finalize(&verif_ctx);1296if (ret) {1297ret = -1;1298goto err;1299}1300}1301else{1302/**** We do not support streaming mode ****/1303/* Since we don't support streaming mode, we unfortunately have to1304* use a dynamic allocation here.1305*/1306size_t offset = 0;1307allocated_buff = (u8*)malloc(1);13081309eof = 0;1310clearerr(in_file);1311while (exp_len && !eof) {1312to_read = (exp_len < sizeof(buf)) ? exp_len : sizeof(buf);1313read = fread(buf, 1, to_read, in_file);1314if (read != to_read) {1315/* Check if this was EOF */1316ret = feof(in_file);1317clearerr(in_file);1318if (ret) {1319eof = 1;1320}1321}13221323if (read > exp_len) {1324/* we read more than expected: leave! */1325break;1326}13271328exp_len -= read;13291330allocated_buff = (u8*)realloc(allocated_buff, offset + read);1331if(allocated_buff == NULL){1332ret = -1;1333printf("Error: allocation error\n");1334goto err;1335}1336memcpy(allocated_buff + offset, buf, read);1337offset += read;1338}1339if (exp_len) {1340ret = -1;1341printf("Error: unable to read full file content\n");1342goto err;1343}13441345ret = ec_verify(sig, siglen, &pub_key, allocated_buff, (u32)offset, sig_type, hash_type, (const u8*)adata, adata_len);1346if (ret) {1347ret = -1;1348goto err;1349}13501351}13521353ret = 0;13541355err:1356if(in_file != NULL){1357if(fclose(in_file)){1358ret = -1;1359}1360}1361if(in_key_file != NULL){1362if(fclose(in_key_file)){1363ret = -1;1364}1365}1366if(in_sig_file != NULL){1367if(fclose(in_sig_file)){1368ret = -1;1369}1370}1371if(allocated_buff != NULL){1372free(allocated_buff);1373}1374return ret;1375}13761377/* Compute 'scalar * Point' on the provided curve and prints1378* the result.1379*/1380ATTRIBUTE_WARN_UNUSED_RET static int ec_scalar_mult(const char *ec_name,1381const char *scalar_file,1382const char *point_file,1383const char *outfile_name)1384{1385const ec_str_params *ec_str_p;1386ec_params curve_params;1387int ret;1388u8 buf[MAX_BUF_LEN];1389size_t buf_len;1390FILE *in_file = NULL;1391FILE *out_file = NULL;1392u16 coord_len;13931394/* Scalar (natural number) to import */1395nn d;1396/* Point to import */1397prj_pt Q;1398d.magic = Q.magic = WORD(0);13991400MUST_HAVE(ec_name != NULL, ret, err);1401MUST_HAVE(scalar_file != NULL, ret, err);1402MUST_HAVE(point_file != NULL, ret, err);1403MUST_HAVE(outfile_name != NULL, ret, err);14041405/* Get parameters from pretty names */1406ret = string_to_params(ec_name, NULL, NULL, &ec_str_p,1407NULL, NULL); EG(ret, err);14081409/* Import the parameters */1410ret = import_params(&curve_params, ec_str_p); EG(ret, err);14111412/* Import the scalar in the local buffer from the file */1413/* Let's first get file size */1414ret = get_file_size(scalar_file, &buf_len);1415if(buf_len == 0){1416ret = -1;1417printf("Error: file %s seems to be empty!\n", scalar_file);1418goto err;1419}1420if (ret) {1421ret = -1;1422printf("Error: cannot retrieve file %s size\n", scalar_file);1423goto err;1424}1425if(buf_len > sizeof(buf)){1426ret = -1;1427printf("Error: file %s content too large for our local buffers\n", scalar_file);1428goto err;1429}1430/* Open main file to verify ... */1431in_file = fopen(scalar_file, "rb");1432if (in_file == NULL) {1433ret = -1;1434printf("Error: file %s cannot be opened\n", scalar_file);1435goto err;1436}1437/* Read the content of the file */1438if(fread(buf, 1, buf_len, in_file) != buf_len){1439ret = -1;1440printf("Error: error when reading in %s\n", scalar_file);1441goto err;1442}1443/* Import the scalar */1444ret = nn_init_from_buf(&d, buf, (u16)buf_len); EG(ret, err);14451446/* Import the point in the local buffer from the file */1447/* Let's first get file size */1448ret = get_file_size(point_file, &buf_len);1449if (ret) {1450ret = -1;1451printf("Error: cannot retrieve file %s size\n", point_file);1452goto err;1453}1454if(buf_len > sizeof(buf)){1455ret = -1;1456printf("Error: file %s content too large for our local buffers\n", point_file);1457goto err;1458}1459ret = fclose(in_file); EG(ret, err);1460in_file = NULL;1461/* Open main file to verify ... */1462in_file = fopen(point_file, "rb");1463if (in_file == NULL) {1464ret = -1;1465printf("Error: file %s cannot be opened\n", point_file);1466goto err;1467}1468/* Read the content of the file */1469if(fread(buf, 1, buf_len, in_file) != buf_len){1470ret = -1;1471printf("Error: error when reading in %s\n", point_file);1472goto err;1473}1474/* Import the point */1475if(prj_pt_import_from_buf(&Q, buf, (u16)buf_len, &(curve_params.ec_curve))){1476ret = -1;1477printf("Error: error when importing the projective point from %s\n", point_file);1478goto err;1479}14801481#ifdef USE_SIG_BLINDING1482/* NB: we use a blind scalar multiplication here since we do not want our1483* private d to leak ...1484*/1485ret = prj_pt_mul_blind(&Q, &d, &Q); EG(ret, err);1486#else1487ret = prj_pt_mul(&Q, &d, &Q); EG(ret, err);1488#endif1489/* Get the unique representation of the point */1490ret = prj_pt_unique(&Q, &Q); EG(ret, err);14911492/* Export the projective point in the local buffer */1493coord_len = (u16)(3 * BYTECEIL((Q.crv)->a.ctx->p_bitlen));1494if(coord_len > sizeof(buf)){1495ret = -1;1496printf("Error: error when exporting the point\n");1497goto err;1498}1499if(prj_pt_export_to_buf(&Q, buf, coord_len)){1500ret = -1;1501printf("Error: error when exporting the point\n");1502goto err;1503}1504/* Now save the coordinates in the output file */1505out_file = fopen(outfile_name, "wb");1506if (out_file == NULL) {1507ret = -1;1508printf("Error: file %s cannot be opened\n", outfile_name);1509goto err;1510}15111512/* Write in the file */1513if(fwrite(buf, 1, coord_len, out_file) != coord_len){1514ret = -1;1515printf("Error: error when writing to %s\n", outfile_name);1516goto err;1517}15181519ret = 0;15201521err:1522/* Uninit local variables */1523nn_uninit(&d);1524prj_pt_uninit(&Q);15251526if(in_file != NULL){1527if(fclose(in_file)){1528ret = -1;1529}1530}1531if(out_file != NULL){1532if(fclose(out_file)){1533ret = -1;1534}1535}1536return ret;1537}153815391540static void print_curves(void)1541{1542u8 i;15431544/* Print all the available curves */1545for (i = 0; i < EC_CURVES_NUM; i++) {1546printf("%s ", (const char *)(ec_maps[i].params->name->buf));1547}15481549return;1550}15511552static void print_hash_algs(void)1553{1554int i;15551556/* Print all the available hash functions */1557for (i = 0; hash_maps[i].type != UNKNOWN_HASH_ALG; i++) {1558printf("%s ", hash_maps[i].name);1559}15601561return;1562}15631564static void print_sig_algs(void)1565{1566int i;15671568/* Print all the available signature schemes */1569for (i = 0; ec_sig_maps[i].type != UNKNOWN_ALG; i++) {1570printf("%s ", ec_sig_maps[i].name);1571}15721573return;1574}15751576static void print_help(const char *prog_name)1577{1578printf("%s expects at least one argument\n", prog_name ? prog_name : "NULL");1579printf("\targ1 = 'gen_keys', 'sign', 'verify', 'struct_sign', 'struct_verify' or 'scalar_mult'\n");1580}15811582#ifdef __cplusplus1583/* In case of a C++ compiler, preserve our "main"1584* linkage.1585*/1586extern "C" {1587int main(int argc, char *argv[]);1588}1589#endif15901591int main(int argc, char *argv[])1592{1593int ret, check, found;1594u32 len;1595const char *adata = NULL;1596u16 adata_len = 0;15971598if (argc < 2) {1599ret = -1;1600print_help(argv[0]);1601goto err;1602}16031604found = 0;1605ret = are_str_equal(argv[1], "gen_keys", &check); EG(ret, err);1606if (check) {1607found = 1;1608/* Generate keys ---------------------------------1609*1610* arg1 = curve name ("frp256v1", ...)1611* arg2 = algorithm type ("ECDSA", "ECKCDSA", ...)1612* arg3 = file name prefix1613*/1614if (argc != 5){1615ret = -1;1616printf("Bad args number for %s %s:\n", argv[0],1617argv[1]);1618printf("\targ1 = curve name: ");1619print_curves();1620printf("\n");16211622printf("\targ2 = signature algorithm type: ");1623print_sig_algs();1624printf("\n");16251626printf("\targ3 = file name prefix\n");1627printf("\n");16281629goto err;1630}1631if(generate_and_export_key_pair(argv[2], argv[3], argv[4])){1632ret = -1;1633printf("gen_key error ...\n");1634goto err;1635}1636}1637ret = are_str_equal(argv[1], "sign", &check); EG(ret, err);1638if (check) {1639found = 1;1640/* Sign something --------------------------------1641* Signature is structured, i.e. the output is a self contained1642* data image1643* arg1 = curve name ("frp256v1", ...)1644* arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)1645* arg3 = hash algorithm type ("SHA256", "SHA512", ...)1646* arg4 = input file to sign1647* arg5 = input file containing the private key1648* arg6 = output file containing the signature1649* arg7 (optional) = ancillary data to be used1650*/1651if ((argc != 8) && (argc != 9)) {1652ret = -1;1653printf("Bad args number for %s %s:\n", argv[0],1654argv[1]);1655printf("\targ1 = curve name: ");1656print_curves();1657printf("\n");16581659printf("\targ2 = signature algorithm type: ");1660print_sig_algs();1661printf("\n");16621663printf("\targ3 = hash algorithm type: ");1664print_hash_algs();1665printf("\n");16661667printf("\targ4 = input file to sign\n");1668printf("\targ5 = input file containing the private key (in raw binary format)\n");1669printf("\targ6 = output file containing the signature\n");1670printf("\t<arg7 (optional) = ancillary data to be used>\n");1671goto err;1672}1673if(argc == 9){1674adata = argv[8];1675ret = local_strlen(adata, &len); EG(ret, err);1676MUST_HAVE(len <= 0xffff, ret, err);1677adata_len = (u16)len;1678}1679if(sign_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6],1680argv[7], NULL, NULL, adata, adata_len)){1681ret = -1;1682printf("sign error ...\n");1683goto err;1684}1685}1686ret = are_str_equal(argv[1], "verify", &check); EG(ret, err);1687if (check) {1688found = 1;1689/* Verify something ------------------------------1690*1691* arg1 = curve name ("frp256v1", ...)1692* arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)1693* arg3 = hash algorithm type ("SHA256", "SHA512", ...)1694* arg = input file to verify1695* arg5 = input file with the public key1696* arg6 = input file containing the signature1697* arg7 (optional) = ancillary data to be used1698*/1699if ((argc != 8) && (argc != 9)) {1700ret = -1;1701printf("Bad args number for %s %s:\n", argv[0],1702argv[1]);1703printf("\targ1 = curve name: ");1704print_curves();1705printf("\n");17061707printf("\targ2 = signature algorithm type: ");1708print_sig_algs();1709printf("\n");17101711printf("\targ3 = hash algorithm type: ");1712print_hash_algs();1713printf("\n");17141715printf("\targ4 = input file to verify\n");1716printf("\targ5 = input file containing the public key (in raw binary format)\n");1717printf("\targ6 = input file containing the signature\n");1718printf("\t<arg7 (optional) = ancillary data to be used>\n");1719goto err;1720}1721if(argc == 9){1722adata = argv[8];1723ret = local_strlen(adata, &len); EG(ret, err);1724MUST_HAVE(len <= 0xffff, ret, err);1725adata_len = (u16)len;1726}1727if (verify_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], adata, adata_len)) {1728ret = -1;1729printf("Signature check of %s failed\n", argv[5]);1730goto err;1731} else {1732printf("Signature check of %s OK\n", argv[5]);1733}1734}1735ret = are_str_equal(argv[1], "struct_sign", &check); EG(ret, err);1736if (check) {1737found = 1;1738/* Sign something --------------------------------1739* Signature is structured, i.e. the output is a self contained1740* data image1741* arg1 = curve name ("frp256v1", ...)1742* arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)1743* arg3 = hash algorithm type ("SHA256", "SHA512", ...)1744* arg4 = input file to sign1745* arg5 = input file with the private key1746* arg6 = output file containing the appended signature1747* arg7 = metadata header type1748* arg8 = version of the metadata header1749* arg9 (optional) = ancillary data to be used1750*/1751if ((argc != 10) && (argc != 11)) {1752ret = -1;1753printf("Bad args number for %s %s:\n", argv[0],1754argv[1]);1755printf("\targ1 = curve name: ");1756print_curves();1757printf("\n");17581759printf("\targ2 = signature algorithm type: ");1760print_sig_algs();1761printf("\n");17621763printf("\targ3 = hash algorithm type: ");1764print_hash_algs();1765printf("\n");17661767printf("\targ4 = input file to sign\n");1768printf("\targ5 = input file containing the private key (in raw binary format)\n");1769printf("\targ6 = output file containing the appended signature\n");1770printf("\targ7 = metadata header type (IMAGE_TYPE0, IMAGE_TYPE1, ...)\n");1771printf("\targ8 = version of the metadata header\n");1772printf("\t<arg9 (optional) = ancillary data to be used>\n");1773goto err;1774}1775if(argc == 11){1776adata = argv[10];1777ret = local_strlen(adata, &len); EG(ret, err);1778MUST_HAVE(len <= 0xffff, ret, err);1779adata_len = (u16)len;1780}1781if(sign_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6],1782argv[7], argv[8], argv[9], adata, adata_len)){1783ret = -1;1784printf("struct_sign error ...\n");1785goto err;1786}1787}1788ret = are_str_equal(argv[1], "struct_verify", &check); EG(ret, err);1789if (check) {1790found = 1;1791/* Verify something ------------------------------1792*1793* arg1 = curve name ("frp256v1", ...)1794* arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)1795* arg3 = hash algorithm type ("SHA256", "SHA512", ...)1796* arg4 = input file to verify1797* arg5 = input file containing the public key (in raw binary format)1798* arg6 (optional) = ancillary data to be used1799*/1800if ((argc != 7) && (argc != 8)) {1801ret = -1;1802printf("Bad args number for %s %s:\n", argv[0],1803argv[1]);1804printf("\targ1 = curve name: ");1805print_curves();1806printf("\n");18071808printf("\targ2 = signature algorithm type: ");1809print_sig_algs();1810printf("\n");18111812printf("\targ3 = hash algorithm type: ");1813print_hash_algs();1814printf("\n");18151816printf("\targ4 = input file to verify\n");1817printf("\targ5 = input file containing the public key (in raw binary format)\n");1818printf("\t<arg6 (optional) = ancillary data to be used>\n");1819goto err;1820}1821if(argc == 8){1822adata = argv[7];1823ret = local_strlen(adata, &len); EG(ret, err);1824MUST_HAVE(len <= 0xffff, ret, err);1825adata_len = (u16)len;1826}1827if (verify_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6], NULL, adata, adata_len)) {1828ret = -1;1829printf("Signature check of %s failed\n", argv[5]);1830goto err;1831} else {1832printf("Signature check of %s OK\n", argv[5]);1833}1834}1835ret = are_str_equal(argv[1], "scalar_mult", &check); EG(ret, err);1836if (check) {1837found = 1;1838/* Point scalar multiplication --------------------1839*1840* arg1 = curve name ("frp256v1", ...)1841* arg2 = scalar1842* arg3 = point to multiply1843* arg4 = file name where to save the result1844*/1845if (argc != 6) {1846ret = -1;1847printf("Bad args number for %s %s:\n", argv[0],1848argv[1]);1849printf("\targ1 = curve name: ");1850print_curves();1851printf("\n");18521853printf("\targ2 = scalar bin file\n");1854printf("\targ3 = point to multiply bin file (projective coordinates)\n");1855printf("\targ4 = file name where to save the result\n");1856goto err;1857}1858if(ec_scalar_mult(argv[2], argv[3], argv[4], argv[5])){1859ret = -1;1860printf("Scalar multiplication failed\n");1861goto err;1862}1863}18641865if (found == 0) {1866/* Bad first argument, print help */1867ret = -1;1868printf("Bad first argument '%s'\n", argv[1]);1869print_help(argv[0]);1870goto err;1871}18721873ret = 0;18741875err:1876return ret;1877}187818791880