diff --git a/aws/cl_zcash/software/runtime/Readme.md b/aws/cl_zcash/software/runtime/Readme.md new file mode 100644 index 0000000..75d6d58 --- /dev/null +++ b/aws/cl_zcash/software/runtime/Readme.md @@ -0,0 +1,28 @@ +1. ecdsa_test.cpp: hardcoded several TV and feed to FPGA for test; + +- Compile the ecdsa_test.cpp + + make -f makefile_ecdsa + +- Usage: (before doing below, make sure you had already load the fpga image, check master help document) + + sudo ./ecdsa_test + + +----------------------------- + + +2. openssl_verify.cpp: utilize the openssl lib to generate the test vector dynamiclly and feedback to fpga for verify test. + +- Compile the openssl_verify.cpp + + make -f openssl_verify.cpp + +- Usage: (before doing below, make sure you had already load the fpga image, check the master help document) + + sudo ./openssl_verify [iteration_num] [verbose: t | f] + + + [iteration num] is used to define how much round test to be done, just give a number; + + [verbose] control if you want to output more information(t) or not(f) diff --git a/aws/cl_zcash/software/runtime/ecdsa_test.cpp b/aws/cl_zcash/software/runtime/ecdsa_test.cpp new file mode 100644 index 0000000..b39c7d8 --- /dev/null +++ b/aws/cl_zcash/software/runtime/ecdsa_test.cpp @@ -0,0 +1,201 @@ +// +// ZCash FPGA test. +// +// Copyright (C) 2019 Benjamin Devlin and Zcash Foundation +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#define _XOPEN_SOURCE 500 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "./zcash_fpga.hpp" +#include "./ossl.h" + +/* use the stdout logger for printing debug information */ + +//const struct logger *logger = &logger_stdout; +/* + * check if the corresponding AFI for hello_world is loaded + */ +//int check_afi_ready(int slot_id); //I think this is not necessary as it is already override.. + +void usage(char* program_name) { + printf("usage: %s [--slot ][]\n", program_name); +} + +int main(int argc, char **argv) { + + unsigned int slot_id = 0; + int rc; + uint32_t value = 0; + unsigned int timeout = 0; + unsigned int read_len = 0; + uint8_t reply[640]; + uint32_t failed = 0; + // Process command line args + { + int i; + int value_set = 0; + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--slot")) { + i++; + if (i >= argc) { + printf("error: missing slot-id\n"); + usage(argv[0]); + return 1; + } + sscanf(argv[i], "%d", &slot_id); + } else if (!value_set) { + sscanf(argv[i], "%x", &value); + value_set = 1; + } else { + printf("error: Invalid arg: %s", argv[i]); + usage(argv[0]); + return 1; + } + } + } + + zcash_fpga& zfpga = zcash_fpga::get_instance(); + + // Test the secp256k1 core + if ((zfpga.m_command_cap & zcash_fpga::ENB_VERIFY_SECP256K1_SIG) != 0) { + printf("INFO: Testing secp256k1 core...\n"); + const unsigned int index_int=0xa; + for (unsigned int tv_ind=0; tv_ind<5; tv_ind++) { + printf("******************************************************\n"); + + printf("INFO: TV index=%d\n", tv_ind+1); + zcash_fpga::verify_secp256k1_sig_t verify_secp256k1_sig; + memset(&verify_secp256k1_sig, 0, sizeof(zcash_fpga::verify_secp256k1_sig_t)); + verify_secp256k1_sig.hdr.cmd = zcash_fpga::VERIFY_SECP256K1_SIG; + verify_secp256k1_sig.hdr.len = sizeof(zcash_fpga::verify_secp256k1_sig_t); + verify_secp256k1_sig.index = index_int+tv_ind; + switch (tv_ind) + { case 0: + std::cout<<"Hardcoded TV1 selected\n"; + string_to_hex("4c7dbc46486ad9569442d69b558db99a2612c4f003e6631b593942f531e67fd4", (unsigned char *)verify_secp256k1_sig.hash); + string_to_hex("01375af664ef2b74079687956fd9042e4e547d57c4438f1fc439cbfcb4c9ba8b", (unsigned char *)verify_secp256k1_sig.r); + string_to_hex("de0f72e442f7b5e8e7d53274bf8f97f0674f4f63af582554dbecbb4aa9d5cbcb", (unsigned char *)verify_secp256k1_sig.s); + string_to_hex("808a2c66c5b90fa1477d7820fc57a8b7574cdcb8bd829bdfcf98aa9c41fde3b4", (unsigned char *)verify_secp256k1_sig.Qx); + string_to_hex("eed249ffde6e46d784cb53b4df8c9662313c1ce8012da56cb061f12e55a32249", (unsigned char *)verify_secp256k1_sig.Qy); + break; + case 1: + std::cout<<"Hardcoded TV2 selected\n"; + string_to_hex("aca448f8093e33286c7d284569feae5f65ae7fa2ea5ce9c46acaad408da61e1f", (unsigned char *)verify_secp256k1_sig.hash); + string_to_hex("0bce4a3be622e3f919f97b03b45e3f32ccdf3dd6bcce40657d8f9fc973ae7b29", (unsigned char *)verify_secp256k1_sig.r); + string_to_hex("6abcd5e40fcee8bca6b506228a2dcae67daa5d743e684c4d3fb1cb77e43b48fe", (unsigned char *)verify_secp256k1_sig.s); + string_to_hex("b661c143ffbbad5acfe16d427767cdc57fb2e4c019a4753ba68cd02c29e4a153", (unsigned char *)verify_secp256k1_sig.Qx); + string_to_hex("6e1fb00fdb9ddd39b55596bfb559bc395f220ae51e46dbe4e4df92d1a5599726", (unsigned char *)verify_secp256k1_sig.Qy); + break; + case 2: + std::cout<<"Hardcoded TV3 selected\n"; + string_to_hex("9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0", (unsigned char *)verify_secp256k1_sig.hash); + string_to_hex("ae235401e2112948be75194de0bad0002e8e76e6cdf9267ccb179643d908dc5e", (unsigned char *)verify_secp256k1_sig.r); + string_to_hex("1f37bd6b617d03db5413cad3dc74fd091d071c2377fb74f488c56077823a2d56", (unsigned char *)verify_secp256k1_sig.s); + string_to_hex("5db9b06cc4928dd46f675c7dde14de8c7c2a8fd8e6c132da77e4ffeb90ff51d0", (unsigned char *)verify_secp256k1_sig.Qx); + string_to_hex("54d0967454193d20bc5733d0779ce3f6824666a3a9a66273c7f21e5f26ca0bbf", (unsigned char *)verify_secp256k1_sig.Qy); + break; + case 3: + std::cout<<"Hardcoded TV4 selected\n"; + string_to_hex("9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0", (unsigned char *)verify_secp256k1_sig.hash); + string_to_hex("a0c388bad0d0de5b8cd74dde1b130ae24f727874e00b0a19c9a0ee336ea420cf", (unsigned char *)verify_secp256k1_sig.r); + string_to_hex("4d549363cea5e7cf2e5a80de97057e6709b8014c9037d12aac86b9ae4fbb02bb", (unsigned char *)verify_secp256k1_sig.s); + string_to_hex("87d4561f92925beb4afd97fb0f883bc1f7f573494087191af8bc67557b4ab0f9", (unsigned char *)verify_secp256k1_sig.Qx); + string_to_hex("0d933ed3e39c30e27dfde32f276ef50db3eef6cbea8e913f7488b3dff15fb3ee", (unsigned char *)verify_secp256k1_sig.Qy); + break; + case 4: + printf ("This test vector may knock off fpga, you may need do fpga-load-local-image again!!!\n"); + string_to_hex("000ab00000000000000000000000000000000000000000000000000000000000", (unsigned char *)verify_secp256k1_sig.hash); + string_to_hex("0000000000000000000000000000000000000000000000000000000000000000", (unsigned char *)verify_secp256k1_sig.r); + string_to_hex("0000000000000000000000000000000000000000000000000000000000000000", (unsigned char *)verify_secp256k1_sig.s); + string_to_hex("00bcd00000000000000000000000000000000000000000000000000000000000", (unsigned char *)verify_secp256k1_sig.Qx); + string_to_hex("0000000000000000000000000000000000000000000000000000000000000000", (unsigned char *)verify_secp256k1_sig.Qy); + break; + default: + printf ("This test vector may knock off fpga, you may need do fpga-load-local-image again!!!\n"); + + } + rc = zfpga.write_stream((uint8_t*)&verify_secp256k1_sig, sizeof(zcash_fpga::verify_secp256k1_sig_t)); + fail_on(rc, out, "ERROR: Unable to send verify_secp256k1_sig to FPGA!"); + + timeout = 0; + read_len = 0; + memset(reply, 0, 512); + while ((read_len = zfpga.read_stream(reply, 256)) == 0) { + usleep(1); + timeout++; + if (timeout > 1000) { + printf("[ERROR]: No reply received, timeout\n"); + failed = true; + break; + } + } + + zcash_fpga::verify_secp256k1_sig_rpl_t verify_secp256k1_sig_rpl; + verify_secp256k1_sig_rpl = *(zcash_fpga::verify_secp256k1_sig_rpl_t*)reply; + + printf("[INFO]: hdr.cmd = 0x%x\n", verify_secp256k1_sig_rpl.hdr.cmd); + printf("[INFO]: .bm = 0x%x\n", verify_secp256k1_sig_rpl.bm); + printf("[INFO]: .index = 0x%lx, \t expect 0x%x\n", verify_secp256k1_sig_rpl.index,index_int+tv_ind); + printf("[INFO]: .cycle_cnt= 0x%x\n", verify_secp256k1_sig_rpl.cycle_cnt); + + if (verify_secp256k1_sig_rpl.hdr.cmd != zcash_fpga::VERIFY_SECP256K1_SIG_RPL) { + printf("[ERROR]: Header type was wrong for test vector#%d!\n",tv_ind); + failed++; + continue; + } + if (verify_secp256k1_sig_rpl.bm != 0) { + printf("[ERROR]: Signature verification failed for test vector #%d!\n",tv_ind); + failed++; + continue; + } + + if (verify_secp256k1_sig_rpl.index != index_int+tv_ind) { + printf("[ERROR]: Index was wrong for test vector #%d!\n",tv_ind); + failed++; + continue; + } + }//end of tv_ind loop + } + printf("\n======================================================\n"); + printf("Final result\n"); + printf("Total 5 round test, failed [%d]\n", failed); + + out: + return 1; +} diff --git a/aws/cl_zcash/software/runtime/makefile_ecdsa b/aws/cl_zcash/software/runtime/makefile_ecdsa new file mode 100644 index 0000000..caf0c3d --- /dev/null +++ b/aws/cl_zcash/software/runtime/makefile_ecdsa @@ -0,0 +1,43 @@ +# Amazon FPGA Hardware Development Kit +# +# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Amazon Software License (the "License"). You may not use +# this file except in compliance with the License. A copy of the License is +# located at +# +# http://aws.amazon.com/asl/ +# +# or in the "license" file accompanying this file. This file is distributed on +# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or +# implied. See the License for the specific language governing permissions and +# limitations under the License. + +VPATH = src:include:$(HDK_DIR)/common/software/src:$(HDK_DIR)/common/software/include + +INCLUDES = -I$(SDK_DIR)/userspace/include +INCLUDES += -I $(HDK_DIR)/common/software/include +INCLUDES += -I ./include + +CC = g++ +CFLAGS = -DCONFIG_LOGLEVEL=4 -g -Wall $(INCLUDES) -lstdc++ -std=c++11 + +LDLIBS = -lfpga_mgmt -lrt -lpthread -lcrypto -lssl + +SRC = zcash_fpga.cpp ecdsa_test.cpp ${SDK_DIR}/userspace/utils/sh_dpi_tasks.c + +OBJ = $(SRC:.c=.o) +BIN = ecdsa_test + +all: $(BIN) check_env + +$(BIN): $(OBJ) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +clean: + rm -f *.o $(BIN) + +check_env: +ifndef SDK_DIR + $(error SDK_DIR is undefined. Try "source sdk_setup.sh" to set the software environment) +endif diff --git a/aws/cl_zcash/software/runtime/makefile_openssl b/aws/cl_zcash/software/runtime/makefile_openssl new file mode 100644 index 0000000..1d832c5 --- /dev/null +++ b/aws/cl_zcash/software/runtime/makefile_openssl @@ -0,0 +1,43 @@ +# Amazon FPGA Hardware Development Kit +# +# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Amazon Software License (the "License"). You may not use +# this file except in compliance with the License. A copy of the License is +# located at +# +# http://aws.amazon.com/asl/ +# +# or in the "license" file accompanying this file. This file is distributed on +# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or +# implied. See the License for the specific language governing permissions and +# limitations under the License. + +VPATH = src:include:$(HDK_DIR)/common/software/src:$(HDK_DIR)/common/software/include + +INCLUDES = -I$(SDK_DIR)/userspace/include +INCLUDES += -I $(HDK_DIR)/common/software/include +INCLUDES += -I ./include + +CC = g++ +CFLAGS = -DCONFIG_LOGLEVEL=4 -g -Wall $(INCLUDES) -lstdc++ -std=c++11 + +LDLIBS = -lfpga_mgmt -lrt -lpthread -lssl -lcrypto + +SRC = zcash_fpga.cpp openssl_verify.cpp ${SDK_DIR}/userspace/utils/sh_dpi_tasks.c + +OBJ = $(SRC:.c=.o) +BIN = openssl_verify + +all: $(BIN) check_env + +$(BIN): $(OBJ) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +clean: + rm -f *.o $(BIN) + +check_env: +ifndef SDK_DIR + $(error SDK_DIR is undefined. Try "source sdk_setup.sh" to set the software environment) +endif diff --git a/aws/cl_zcash/software/runtime/openssl_verify.cpp b/aws/cl_zcash/software/runtime/openssl_verify.cpp new file mode 100644 index 0000000..912d046 --- /dev/null +++ b/aws/cl_zcash/software/runtime/openssl_verify.cpp @@ -0,0 +1,182 @@ +// +// ZCash FPGA test. +// +// Copyright (C) 2019 Benjamin Devlin and Zcash Foundation +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#define _XOPEN_SOURCE 500 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "./zcash_fpga.hpp" +#include "./ossl.h" + +#include +#include +#include + +#define MAX_TEST_ITER 10000 + + +int main(int argc, char *argv[]) { + + //unsigned int slot_id = 0; + int rc; + //uint32_t value = 0; + unsigned int timeout = 0; + unsigned int read_len = 0; + uint8_t reply[640]; + uint32_t failed = 0; + bool verb=false; + //uint32_t iter=100; + // Process command line args + if (argc != 3) { + std::cout << "Usage: " << argv[0] << " \n"; + printf ("TV number: any number between 1 and %d\n",MAX_TEST_ITER); + printf ("Verbose: t=ture f=false, control debug infor output (signature etc..) \n"); + + return 1; + } + char* argv1_ptr; + uint32_t iter = strtoul(argv[1], &argv1_ptr, 10); + if (*argv1_ptr != '\0') { + return 1; + } + if (iter < 1 || iter > MAX_TEST_ITER) { + printf ("[ERROR]: Incorrect num of TV input, should be between [%d-%d]\n",1,MAX_TEST_ITER); + return 1; + } + + if ((strcmp(argv[2], "t")!= 0) && (strcmp(argv[2], "f")!= 0) ) { + std::cout < 1000) { + printf("ERROR: No reply received, timeout\n"); + failed = true; + break; + } + } + + zcash_fpga::verify_secp256k1_sig_rpl_t verify_secp256k1_sig_rpl; + verify_secp256k1_sig_rpl = *(zcash_fpga::verify_secp256k1_sig_rpl_t*)reply; + /* + printf("[INFO]: hdr.cmd = 0x%x\n", verify_secp256k1_sig_rpl.hdr.cmd); + printf("[INFO]: .bm = 0x%x\n", verify_secp256k1_sig_rpl.bm); + printf("[INFO]: .index = 0x%lx, \t expect 0x%x\n", verify_secp256k1_sig_rpl.index,index_int+tv_ind); + printf("[INFO]: .cycle_cnt= 0x%x\n", verify_secp256k1_sig_rpl.cycle_cnt); + */ + if (verify_secp256k1_sig_rpl.hdr.cmd != zcash_fpga::VERIFY_SECP256K1_SIG_RPL) { + printf("[ERROR]: Header type was wrong for test vector#%d!\n",tv_ind); + failed++; + continue; + } + if (verify_secp256k1_sig_rpl.bm != 0) { + printf("[ERROR]: Signature verification failed for test vector #%d!\n",tv_ind); + printf("[INFO]: hdr.cmd = 0x%x\n", verify_secp256k1_sig_rpl.hdr.cmd); + printf("[INFO]: .bm = 0x%x\n", verify_secp256k1_sig_rpl.bm); + printf("[INFO]: .index = 0x%lx, \t expect 0x%x\n", verify_secp256k1_sig_rpl.index,index_int+tv_ind); + printf("[INFO]: .cycle_cnt= 0x%x\n", verify_secp256k1_sig_rpl.cycle_cnt); + failed++; + continue; + } + + if (verify_secp256k1_sig_rpl.index != index_int+tv_ind) { + printf("[ERROR]: Index was wrong for test vector #%d!\n",tv_ind); + failed++; + continue; + } + }//end of tv_ind loop + } + + printf("\n======================================================\n"); +printf("Final result\n"); +printf("Total [%d] round test, failed [%d]\n", iter, failed); + out: + return 1; +} diff --git a/aws/cl_zcash/software/runtime/ossl.h b/aws/cl_zcash/software/runtime/ossl.h new file mode 100644 index 0000000..be3853c --- /dev/null +++ b/aws/cl_zcash/software/runtime/ossl.h @@ -0,0 +1,174 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +//#include "ossl.hpp" + +#define NID 714 //using NID_secp256k1:714 + +#define SIG_SIZE 64 +#define PUB_KEY_SIZE 64 +#define DIG_SIZE 32 +#define PRIV_KEY_SIZE 32 + +typedef struct __attribute__((__packed__)) { + uint64_t s[4]; + uint64_t r[4]; + uint64_t hash[4]; + uint64_t Qx[4]; + uint64_t Qy[4]; +} Signature_t; + + +bool string_to_hex(const std::string &inStr, unsigned char *outStr) { + size_t len = inStr.length(); + for (ssize_t i = len-2; i >= 0; i -= 2) { + sscanf(inStr.c_str() + i, "%2hhx", outStr); + ++outStr; + } + return true; +} + + +std::vector Hash256(const std::string &str) { + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, str.c_str(), str.size()); + std::vector md(SHA256_DIGEST_LENGTH); + SHA256_Final(md.data(), &ctx); + return md; +} + +void char_array_display (const char* char_ptr, int size, const char* msg) { + for(int i = 0; i < size; i++) + std::cout << std::setw(1) << std::setfill('0') << static_cast(tolower(*(char_ptr+i))); + //printf("%c",static_cast(tolower(*(char_ptr+i))); + std::cout << " //" << msg << std::endl; +} + + +Signature_t sig_ossl (bool verb) { //verb=true, print more info. + Signature_t sig_ret; + memset(&sig_ret, 0, sizeof(Signature_t)); + //std::string mesg_string = "aaa"; + std::string mesg_string = "I am a fish"; + std::vector Digest (DIG_SIZE, 0); + Digest=Hash256(mesg_string); + + //fill sig_ret.hash. + unsigned char* p_hash = (unsigned char *)sig_ret.hash; + int i=0; + for (std::vector::iterator iter = Digest.begin(); iter != Digest.end(); ++iter) + { *(p_hash+i) =*iter; i++; } + + //EC_KEY OBJ create + EC_KEY *ec_key = EC_KEY_new(); + if (ec_key == NULL) perror("Error for creating ECC key object "); + EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID); //NID_secp256k1:714 + EC_KEY_set_group(ec_key, ec_group); + if (!EC_KEY_generate_key(ec_key)) perror("Error for creating ECC key pair"); + + //get private key and pub key (Qx, Qy) + const EC_POINT *pub = EC_KEY_get0_public_key (ec_key); + const BIGNUM *PRIV = EC_KEY_get0_private_key(ec_key); + BIGNUM *QX = BN_new(); + BIGNUM *QY = BN_new(); + //Gets the affine coordinates of an EC_POINT. + if (!(EC_POINT_get_affine_coordinates(ec_group, pub, QX, QY, NULL))) + perror("Error for creating ECC pub key"); +/* if (verb) { + printf("Pub key gen OK:\n"); + std::cout << "QX : "; + BN_print_fp(stdout, QX); + putc('\n', stdout); + std::cout << "QY : "; + BN_print_fp(stdout, QY); + putc('\n', stdout); + std::cout << "Priv key: "; + BN_print_fp(stdout, PRIV); + printf("--------------------------------------------------\n"); + + } +*/ + //generate signature + ECDSA_SIG *signature; + unsigned char *dig_ptr=Digest.data(); + signature = ECDSA_do_sign(dig_ptr, SHA256_DIGEST_LENGTH, ec_key); + if (signature == NULL) perror("ECDSA_SIG generation fail"); + + //verify signature + if (!(ECDSA_do_verify(dig_ptr, SHA256_DIGEST_LENGTH, signature, ec_key))) + perror("Openssl generated signature verify FAILED"); + + //Obtain R and S + const BIGNUM *PR = BN_new(); + const BIGNUM *PS = BN_new(); + ECDSA_SIG_get0(signature, &PR, &PS); + + //convert BN to generate TV + char* qx = BN_bn2hex(QX); + char* qy = BN_bn2hex(QY); + char* sig_r = BN_bn2hex(PR); + char* sig_s = BN_bn2hex(PS); + char* priv_key = BN_bn2hex(PRIV); //private key needed for debugging + + std::string sig_r_str=sig_r; + std::string sig_s_str=sig_s; + std::string qx_str=qx; + std::string qy_str=qy; + + string_to_hex(sig_r, (unsigned char *)sig_ret.r); + string_to_hex(sig_s, (unsigned char *)sig_ret.s); + string_to_hex(qx_str, (unsigned char *)sig_ret.Qx); + string_to_hex(qy_str, (unsigned char *)sig_ret.Qy); + + if (verb) { + for (int i=0; i