int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_SET_OPERATION_MODE; in[apduSize++] = 0x01; in[apduSize++] = 0x00; in[apduSize++] = 0x01; in[apduSize++] = 0x01; result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("New mode set\n"); return 1; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; unsigned char encodedKey[100]; int encodedKeyLength; uint32_t index; int result; int sw; int apduSize; if (argc < 3) { fprintf(stderr, "Usage : %s [encoded private key hex] [index (base 16)]\n", argv[0]); return 0; } encodedKeyLength = hexToBin(argv[1], encodedKey, sizeof(encodedKey)); if (encodedKeyLength < 0) { fprintf(stderr, "Invalid encoded key\n"); return 0; } errno = 0; index = strtoll(argv[2], NULL, 16); if (errno != 0) { fprintf(stderr, "Invalid index\n"); return 0; } initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_DERIVE_BIP32_KEY; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = encodedKeyLength; memcpy(in + apduSize, encodedKey, encodedKeyLength); apduSize += encodedKeyLength; writeUint32BE(in + apduSize, index); apduSize += sizeof(index); in[OFFSET_CDATA] = (apduSize - 5); result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("Encoded private key : "); displayBinary(out, result); return 1; }
int main(int argc, char **argv) { dongleHandle dongle; int pos; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; if (argc < 2) { fprintf(stderr, "Usage : %s [Point Of Sale data (SEEDKEY or ENCRYPTEDSEED)]\n", argv[0]); return 0; } pos = convertPos(argv[1]); if (pos < 0) { fprintf(stderr, "Invalid Point Of Sale data\n"); return 0; } initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_GET_POS_SEED; in[apduSize++] = pos; in[apduSize++] = 0x00; in[apduSize++] = 0x00; result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } apduSize = 0; if (pos == POS_SEEDKEY) { printf("Seed encryption key : "); displayBinary(out, 16); } else if (pos == POS_ENCRYPTEDSEED) { printf("Encrypted seed : "); displayBinary(out, 32); } return 1; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_GET_OPERATION_MODE; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = 0x01; result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("Current operation mode : "); switch(out[0]) { case MODE_WALLET: printf("Wallet\n"); break; case MODE_RELAXED_WALLET: printf("Relaxed wallet\n"); break; case MODE_SERVER: printf("Server\n"); break; case MODE_DEVELOPER: printf("Developer\n"); break; default: printf("UNKNOWN %.2x\n", out[0]); break; } return 1; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char pin[8]; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; if (argc < 2) { fprintf(stderr, "Usage : %s [hex PIN]\n", argv[0]); return 0; } result = hexToBin(argv[1], pin, sizeof(pin)); if (result == 0) { fprintf(stderr, "Invalid PIN\n"); return 0; } initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_VERIFY_PIN; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = result; memcpy(in + apduSize, pin, result); apduSize += result; result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("PIN verified\n"); if ((out[0] & 0x01) != 0) { printf("Powercycle to read the generated seed\n"); } return 1; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; int result; int sw; int i; int apduSize; if (argc < 2) { fprintf(stderr, "Usage : %s [number of random bytes to get]\n", argv[0]); return 0; } result = atoi(argv[1]); if (result == 0) { fprintf(stderr, "Invalid size\n"); return 0; } initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_GET_RANDOM; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = result; result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("Random : "); for (i=0; i<result; i++) { printf("%.2x", out[i]); } printf("\n"); return 1; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_GET_FIRMWARE_VERSION; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = 0x00; result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw == SW_UNKNOWN) { // Initial firmware did not support this command out[0] = 0x00; out[1] = 0x00; out[2] = 0x01; out[3] = 0x04; out[4] = 0x03; out[5] = 0x01; out[6] = 0x43; } else if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("Firmware version %s %d.%d.%d\n", (out[1] != 0 ? "Ledger" : ""), out[2], out[3], out[4]); if (result > 5) { printf("Loader ID %d.%d.%d\n", (out[5] & 0x0F), (out[6] >> 4), (out[6] & 0x0F)); }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; char address[100]; int64_t amount; int64_t fees; unsigned int keyPath[10]; int keyPathLength; int i; if (argc < 5) { fprintf(stderr, "Usage : %s [output address] [amount (in BTC string)] [fees (in BTC string)] [key path for change address in a/b/c format using n' for hardened nodes]\n", argv[0]); return 0; } address[sizeof(address) - 1] = '\0'; strncpy(address, argv[1], sizeof(address) - 1); if (parseStringAmount(argv[2], &amount) < 0) { fprintf(stderr, "Invalid amount\n"); return 0; } if (parseStringAmount(argv[3], &fees) < 0) { fprintf(stderr, "Invalid fees\n"); return 0; } keyPathLength = convertPath(argv[4], keyPath); if (keyPathLength < 0) { fprintf(stderr, "Invalid key path\n"); return 0; } initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_HASH_INPUT_FINALIZE; in[apduSize++] = 0x02; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = strlen(address); memcpy(in + apduSize, address, strlen(address)); apduSize += strlen(address); writeHexAmountBE(amount, in + apduSize); apduSize += sizeof(amount); writeHexAmountBE(fees, in + apduSize); apduSize += sizeof(fees); in[apduSize++] = keyPathLength; for (i=0; i<keyPathLength; i++) { writeUint32BE(in + apduSize, keyPath[i]); apduSize += 4; } in[OFFSET_CDATA] = (apduSize - 5); result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } apduSize = 0; printf("Output data : "); displayBinary(out + 1, out[0]); apduSize = 1 + out[0]; if (out[apduSize] == 0x00) { printf("Input finalized, proceed with signing\n"); } else if (out[apduSize] == 0x01) { printf("Input finalized, please powercycle to get the second factor then proceed with signing\n"); } else { fprintf(stderr, "Invalid transaction state %.2x\n", out[apduSize]); return 0; } return 1; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; char pin[100]; uint32_t lockTime; unsigned char sigHashType; unsigned int keyPath[10]; int keyPathLength; int i; if (argc < 5) { fprintf(stderr, "Usage : %s [key path in a/b/c format using n' for hardened nodes] [second factor ascii, or empty string] [locktime or empty for default] [sighashType or empty for SIGHASH_ALL]\n", argv[0]); return 0; } keyPathLength = convertPath(argv[1], keyPath); if (keyPathLength < 0) { fprintf(stderr, "Invalid key path\n"); return 0; } if (strlen(argv[2]) > sizeof(pin) - 1) { fprintf(stderr, "Invalid second factor\n"); return 0; } pin[sizeof(pin) - 1] = '\0'; strncpy(pin, argv[2], sizeof(pin) - 1); if (strlen(argv[3]) == 0) { lockTime = 0; } else { result = strtol(argv[3], NULL, 10); if (result < 0) { fprintf(stderr, "Invalid chain index\n"); return 0; } lockTime = result; } if (strlen(argv[4]) == 0) { sigHashType = 0x01; } else { result = hexToBin(argv[4], &sigHashType, sizeof(sigHashType)); if (result < 0) { fprintf(stderr, "Invalid sigHashType\n"); return 0; } } initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_HASH_SIGN; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = keyPathLength; for (i=0; i<keyPathLength; i++) { writeUint32BE(in + apduSize, keyPath[i]); apduSize += 4; } in[apduSize++] = strlen(pin); memcpy(in + apduSize, pin, strlen(pin)); apduSize += strlen(pin); writeUint32BE(in + apduSize, lockTime); apduSize += sizeof(lockTime); in[apduSize++] = sigHashType; in[OFFSET_CDATA] = (apduSize - 5); printf("Singing, please wait ...\n"); result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("Signature + hashtype : "); displayBinary(out, result); return 1; }
int main(int argc, char **argv) { dongleHandle dongle = NULL; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; uint32_t signingIndex; unsigned char newTransaction; bitcoinTransaction **transactions = NULL; prevout *prevouts = NULL; int transactionsNumber = 0; int status = 0; int i; initDongle(); if (argc < 5) { fprintf(stderr, "Usage : %s [NEW for a new transaction|CONTINUE to keep on signing inputs in a previous transaction] [index of input to sign] [redeem script to use or empty to use the default one] [list of transactions output to use in this transaction]\n", argv[0]); fprintf(stderr, "Transaction outputs are coded as [hex transaction:output index] to generate a trusted input, or [-hex transaction:output index] to use the prevout directly for an output you don't own (relaxed wallet mode)\n"); goto cleanup; } if (strcasecmp(argv[1], "new") == 0) { newTransaction = 0x01; } else if (strcasecmp(argv[1], "continue") == 0) { newTransaction = 0x00; } else { fprintf(stderr, "Invalid transaction usage %s\n", argv[1]); goto cleanup; } result = strtol(argv[2], NULL, 10); if (result < 0) { fprintf(stderr, "Invalid input to sign index\n"); goto cleanup; } signingIndex = result; transactionsNumber = argc - 1 - 3; transactions = (bitcoinTransaction**)malloc(sizeof(bitcoinTransaction*) * transactionsNumber); if (transactions == NULL) { fprintf(stderr, "Couldn't allocate transactions list\n"); goto cleanup; } for (i=0; i<transactionsNumber; i++) { transactions[i] = NULL; } prevouts = (prevout*)malloc(sizeof(prevout) * transactionsNumber); if (prevouts == NULL) { fprintf(stderr, "Couldn't allocate prevouts list\n"); goto cleanup; } dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } // Parse each provided transaction, get the associated trusted input when necessary for (i=0; i<transactionsNumber; i++) { uint32_t index; unsigned char untrusted; untrusted = (argv[4 + i][0] == '-'); transactions[i] = parseTransactionStringWithIndex(argv[4 + i] + (untrusted ? 1 : 0), &index); if (transactions[i] == NULL) { fprintf(stderr, "Invalid transaction %d\n", i + 1); goto cleanup; } if (untrusted) { fprintf(stderr, "Untrusted mode not supported\n"); goto cleanup; } else { result = getTrustedInput(dongle, transactions[i], index, prevouts[i].prevout, sizeof(prevouts[i].prevout)); if (result < 0) { fprintf(stderr, "Error getting trusted input %d\n", i + 1); goto cleanup; } prevouts[i].isTrusted = 1; printf("Trusted input #%d\n", (i + 1)); displayBinary(prevouts[i].prevout, result); } prevouts[i].outputIndex = index; } // Then start building a fake transaction with the inputs we want apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_HASH_INPUT_START; in[apduSize++] = 0x00; in[apduSize++] = (newTransaction ? 0x00 : 0x80); in[apduSize++] = 0x00; memcpy(in + apduSize, DEFAULT_VERSION, sizeof(DEFAULT_VERSION)); apduSize += sizeof(DEFAULT_VERSION); apduSize += writeVarint(transactionsNumber, (in + apduSize), (sizeof(in) - apduSize)); in[OFFSET_CDATA] = (apduSize - 5); result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } // Each input for (i=0; i<transactionsNumber; i++) { int scriptLength; unsigned char *script; apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_HASH_INPUT_START; in[apduSize++] = 0x80; in[apduSize++] = 0x00; in[apduSize++] = 0x00; if (prevouts[i].isTrusted) { in[apduSize++] = 0x01; in[apduSize++] = sizeof(prevouts[i].prevout); memcpy(in + apduSize, prevouts[i].prevout, sizeof(prevouts[i].prevout)); apduSize += sizeof(prevouts[i].prevout); } else { in[apduSize++] = 0x00; in[apduSize++] = PREVOUT_SIZE; memcpy(in + apduSize, prevouts[i].prevout, PREVOUT_SIZE); apduSize += PREVOUT_SIZE; } // Get the script length - use either the output script if signing the current index // Or a null script if (i == signingIndex) { if (strlen(argv[3]) != 0) { scriptLength = strlen(argv[3]) / 2; script = (unsigned char*)malloc(scriptLength); if (script == NULL) { fprintf(stderr, "Failed to allocate script\n"); goto cleanup; } scriptLength = hexToBin(argv[3], script, scriptLength); if (scriptLength <= 0) { free(script); fprintf(stderr, "Invalid redeem script\n"); goto cleanup; } } else { int j; bitcoinOutput *output = transactions[i]->outputs; for (j=0; j<prevouts[i].outputIndex; j++) { output = output->next; } scriptLength = output->scriptLength; script = output->script; } } else { scriptLength = 0; script = NULL; } apduSize += writeVarint(scriptLength, (in + apduSize), (sizeof(in) - apduSize)); if (scriptLength != 0) { memcpy(in + apduSize, script, scriptLength); apduSize += scriptLength; } if (strlen(argv[3]) != 0) { free(script); } memcpy(in + apduSize, DEFAULT_SEQUENCE, sizeof(DEFAULT_SEQUENCE)); apduSize += sizeof(DEFAULT_SEQUENCE); in[OFFSET_CDATA] = (apduSize - 5); result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } } printf("Transaction submitted, waiting to be finalized\n"); status = 1; cleanup: if (dongle != NULL) { closeDongle(dongle); } exitDongle(); if (transactions != NULL) { for (i = 0; i < transactionsNumber; i++) { if (transactions[i] != NULL) { freeTransaction(transactions[i]); } } } if (prevouts != NULL) { free(prevouts); } return status; }
int main(int argc, char **argv) { libusb_context *ctx = NULL; dongleHandle dongle; int option; int address; int bus; ETERM *tuplep; ETERM *functionp; unsigned char buf[1024]; const char* func_name; address = -1; bus = -1; while ((option = getopt(argc, argv, "p:b:")) != -1) { switch (option) { case 'p': address = atoi(optarg); break; case 'b': bus = atoi(optarg); break; default: return 1; } } if (bus == -1 || address == -1) { return 1; } erl_init(NULL, 0); initDongle(ctx); dongle = getDongle(ctx, address, bus); if (dongle == NULL) { ERL_WRITE_ERROR("not_found"); exitDongle(ctx); return 1; } while (read_cmd(buf) > 0) { tuplep = erl_decode(buf); functionp = erl_element(1, tuplep); func_name = (const char*)ERL_ATOM_PTR(functionp); if (strncmp(func_name, "derive", 6) == 0){ hsm_derive(dongle, tuplep); } else if (strncmp(func_name, "import", 6) == 0){ hsm_import(dongle, tuplep); } else if (strncmp(func_name, "pin", 3) == 0){ hsm_pin(dongle, tuplep); } else if (strncmp(func_name, "pubkey", 6) == 0){ hsm_pubkey(dongle, tuplep); } else if (strncmp(func_name, "random", 6) == 0){ hsm_random(dongle, tuplep); } else if (strncmp(func_name, "sign", 4) == 0){ hsm_sign(dongle, tuplep); } else if (strncmp(func_name, "verify", 6) == 0){ hsm_verify(dongle, tuplep); } else if (strncmp(func_name, "close", 5) == 0){ break; } else { ERL_WRITE_ERROR("undef") } erl_free_compound(tuplep); erl_free_term(functionp); } closeDongle(dongle); exitDongle(ctx); ETERM *atom; atom = erl_mk_atom("closed"); unsigned char closed_buf[erl_term_len(atom)]; erl_encode(atom, closed_buf); write_cmd(closed_buf, erl_term_len(atom)); erl_free_term(atom); fprintf(stderr, "CLOSED"); return 0; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; int result; int sw; int apduSize; char message[140]; unsigned int keyPath[10]; int keyPathLength; int i; if (argc < 3) { fprintf(stderr, "Usage : %s [key path in a/b/c format using n' for hardened nodes] [message]\n", argv[0]); return 0; } keyPathLength = convertPath(argv[1], keyPath); if (keyPathLength < 0) { fprintf(stderr, "Invalid key path\n"); return 0; } if (strlen(argv[2]) > sizeof(message) - 1) { fprintf(stderr, "Invalid message\n"); return 0; } message[sizeof(message) - 1] = '\0'; strncpy(message, argv[2], sizeof(message) - 1); initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_SIGN_MESSAGE; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = keyPathLength; for (i=0; i<keyPathLength; i++) { writeUint32BE(in + apduSize, keyPath[i]); apduSize += 4; } in[apduSize++] = strlen(message); memcpy(in + apduSize, message, strlen(message)); apduSize += strlen(message); in[OFFSET_CDATA] = (apduSize - 5); result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); closeDongle(dongle); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } apduSize = 0; if (out[apduSize] == 0x00) { printf("Message signature prepared, proceed with signing\n"); } else if (out[apduSize] == 0x01) { printf("Message signature prepared, please powercycle to get the second factor then proceed with signing\n"); } else { fprintf(stderr, "Invalid transaction state %.2x\n", out[apduSize]); return 0; } return 1; }
int main(int argc, char **argv) { dongleHandle dongle; unsigned char in[260]; unsigned char out[260]; unsigned char encodedKey[100]; unsigned char hash[32]; unsigned char signature[100]; int encodedKeyLength; int hashLength; int signatureLength; int result; int sw; int apduSize; if (argc < 4) { fprintf(stderr, "Usage : %s [uncompressed public key hex] [hash to sign hex] [signature to verify hex]\n", argv[0]); return 0; } encodedKeyLength = hexToBin(argv[1], encodedKey, sizeof(encodedKey)); if (encodedKeyLength < 0) { fprintf(stderr, "Invalid encoded key\n"); return 0; } hashLength = hexToBin(argv[2], hash, sizeof(hash)); if (hashLength < 0) { fprintf(stderr, "Invalid hash length\n"); return 0; } signatureLength = hexToBin(argv[3], signature, sizeof(signature)); if (signatureLength < 0) { fprintf(stderr, "Invalid signature\n"); return 0; } initDongle(); dongle = getFirstDongle(); if (dongle == NULL) { fprintf(stderr, "No dongle found\n"); return 0; } apduSize = 0; in[apduSize++] = BTCHIP_CLA; in[apduSize++] = BTCHIP_INS_SIGNVERIFY_IMMEDIATE; in[apduSize++] = 0x80; in[apduSize++] = 0x00; in[apduSize++] = 0x00; in[apduSize++] = encodedKeyLength; memcpy(in + apduSize, encodedKey, encodedKeyLength); apduSize += encodedKeyLength; in[apduSize++] = hashLength; memcpy(in + apduSize, hash, hashLength); apduSize += hashLength; memcpy(in + apduSize, signature, signatureLength); apduSize += signatureLength; in[OFFSET_CDATA] = (apduSize - 5); result = sendApduDongle(dongle, in, apduSize, out, sizeof(out), &sw); exitDongle(); if (result < 0) { fprintf(stderr, "I/O error\n"); return 0; } if (sw != SW_OK) { fprintf(stderr, "Dongle application error : %.4x\n", sw); return 0; } printf("Signature verified.\n"); return 1; }