// // PQCgenKAT_sign.c // // Created by Bassham, Lawrence E (Fed) on 8/29/17. // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. // #include #include #include #include #include "rng.h" #include "api.h" #define STR1(x) #x #define STR(x) STR1(x) #define MAX_MARKER_LEN 50 #define KAT_SUCCESS 0 #define KAT_FILE_OPEN_ERROR -1 #define KAT_DATA_ERROR -3 #define KAT_CRYPTO_FAILURE -4 int FindMarker(FILE *infile, const char *marker); int ReadHex(FILE *infile, unsigned char *A, int Length, char *str); void fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L); char AlgName[] = "My Alg Name"; int main() { char fn_req[42], fn_rsp[42], fn_seedbuf[32], fn_seedbuf2[42]; FILE *fp_req, *fp_rsp, *fp_seedbuf, *fp_seedbuf2; unsigned char seed[48], seedbuf[CRYPTO_SEEDBYTES], seedbuf2[SPX_N]; unsigned char msg[3300]; unsigned char entropy_input[48]; unsigned char *m, *sm, *m1; unsigned long long mlen, smlen, mlen1; int count; int done; unsigned char pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES]; int ret_val; // Create the REQUEST file sprintf(fn_req, "PQCsignKAT_%s-%s.req", STR(PARAMS), STR(THASH)); if ( (fp_req = fopen(fn_req, "w")) == NULL ) { printf("Couldn't open <%s> for write\n", fn_req); return KAT_FILE_OPEN_ERROR; } sprintf(fn_rsp, "PQCsignKAT_%s-%s.rsp", STR(PARAMS), STR(THASH)); if ( (fp_rsp = fopen(fn_rsp, "w")) == NULL ) { printf("Couldn't open <%s> for write\n", fn_rsp); return KAT_FILE_OPEN_ERROR; } sprintf(fn_seedbuf, "SeedBufferKeygen_%i", CRYPTO_SEEDBYTES); if ( (fp_seedbuf = fopen(fn_seedbuf, "w")) == NULL ) { printf("Couldn't open <%s> for write\n", fn_seedbuf); return KAT_FILE_OPEN_ERROR; } sprintf(fn_seedbuf2, "SeedBufferSign_%i", SPX_N); if ( (fp_seedbuf2 = fopen(fn_seedbuf2, "w")) == NULL ) { printf("Couldn't open <%s> for write\n", fn_seedbuf2); return KAT_FILE_OPEN_ERROR; } for (int i=0; i<48; i++) entropy_input[i] = (unsigned char)i; randombytes_init(entropy_input, NULL); for (int i=0; i<100; i++) { fprintf(fp_req, "count = %d\n", i); randombytes(seed, 48); fprintBstr(fp_req, "seed = ", seed, 48); mlen = (unsigned long long int)(33*(i+1)); fprintf(fp_req, "mlen = %llu\n", mlen); randombytes(msg, mlen); fprintBstr(fp_req, "msg = ", msg, mlen); fprintf(fp_req, "pk =\n"); fprintf(fp_req, "sk =\n"); fprintf(fp_req, "smlen =\n"); fprintf(fp_req, "sm =\n\n"); } fclose(fp_req); //Create the RESPONSE file based on what's in the REQUEST file if ( (fp_req = fopen(fn_req, "r")) == NULL ) { printf("Couldn't open <%s> for read\n", fn_req); return KAT_FILE_OPEN_ERROR; } fprintf(fp_rsp, "# %s\n\n", CRYPTO_ALGNAME); done = 0; do { if ( FindMarker(fp_req, "count = ") ) ret_val = fscanf(fp_req, "%d", &count); else { done = 1; break; } fprintf(fp_rsp, "count = %d\n", count); if ( !ReadHex(fp_req, seed, 48, "seed = ") ) { printf("ERROR: unable to read 'seed' from <%s>\n", fn_req); return KAT_DATA_ERROR; } fprintBstr(fp_rsp, "seed = ", seed, 48); randombytes_init(seed, NULL); // Write intermediate seedbuffers to file randombytes(seedbuf, CRYPTO_SEEDBYTES); fprintBstr(fp_seedbuf, "", seedbuf, CRYPTO_SEEDBYTES); randombytes(seedbuf2, SPX_N); fprintBstr(fp_seedbuf2, "", seedbuf2, SPX_N); // Reset rng to initial seed state randombytes_init(seed, NULL); if ( FindMarker(fp_req, "mlen = ") ) ret_val = fscanf(fp_req, "%llu", &mlen); else { printf("ERROR: unable to read 'mlen' from <%s>\n", fn_req); return KAT_DATA_ERROR; } fprintf(fp_rsp, "mlen = %llu\n", mlen); m = (unsigned char *)calloc(mlen, sizeof(unsigned char)); m1 = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char)); sm = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char)); if ( !ReadHex(fp_req, m, (int)mlen, "msg = ") ) { printf("ERROR: unable to read 'msg' from <%s>\n", fn_req); return KAT_DATA_ERROR; } fprintBstr(fp_rsp, "msg = ", m, mlen); // Generate the public/private keypair if ( (ret_val = crypto_sign_keypair(pk, sk)) != 0) { printf("crypto_sign_keypair returned <%d>\n", ret_val); return KAT_CRYPTO_FAILURE; } fprintBstr(fp_rsp, "pk = ", pk, CRYPTO_PUBLICKEYBYTES); fprintBstr(fp_rsp, "sk = ", sk, CRYPTO_SECRETKEYBYTES); if ( (ret_val = crypto_sign(sm, &smlen, m, mlen, sk)) != 0) { printf("crypto_sign returned <%d>\n", ret_val); return KAT_CRYPTO_FAILURE; } fprintf(fp_rsp, "smlen = %llu\n", smlen); fprintBstr(fp_rsp, "sm = ", sm, smlen); fprintf(fp_rsp, "\n"); if ( (ret_val = crypto_sign_open(m1, &mlen1, sm, smlen, pk)) != 0) { printf("crypto_sign_open returned <%d>\n", ret_val); return KAT_CRYPTO_FAILURE; } if ( mlen != mlen1 ) { printf("crypto_sign_open returned bad 'mlen': Got <%llu>, expected <%llu>\n", mlen1, mlen); return KAT_CRYPTO_FAILURE; } if ( memcmp(m, m1, mlen) ) { printf("crypto_sign_open returned bad 'm' value\n"); return KAT_CRYPTO_FAILURE; } free(m); free(m1); free(sm); } while ( !done ); fclose(fp_req); fclose(fp_rsp); return KAT_SUCCESS; } // // ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.) // int FindMarker(FILE *infile, const char *marker) { char line[MAX_MARKER_LEN]; size_t i, len; int curr_line; len = strlen(marker); if ( len > MAX_MARKER_LEN-1 ) len = MAX_MARKER_LEN-1; for ( i=0; i= '0') && (ch <= '9') ) ich = (unsigned char)(ch - '0'); else if ( (ch >= 'A') && (ch <= 'F') ) ich = (unsigned char)(ch - 'A' + 10); else if ( (ch >= 'a') && (ch <= 'f') ) ich = (unsigned char)(ch - 'a' + 10); else // shouldn't ever get here ich = 0; for ( i=0; i> 4); A[Length-1] = (A[Length-1] << 4) | ich; } else return 0; return 1; } void fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L) { unsigned long long i; fprintf(fp, "%s", S); for ( i=0; i