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