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];
	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;
}
void BinaryCounter::start()
{
    for (int i=0; i<16; i++)
    {
        displayBinary(i);
        delay(300);
    }
}
Example #4
0
int sendApduDongle(dongleHandle handle, const unsigned char *apdu, size_t apduLength, unsigned char *out, size_t outLength, int *sw) 
{
	int result = -1;
#ifdef DEBUG_COMM
	printf("=> ");
	displayBinary((unsigned char*)apdu, apduLength);
#endif
	if (handle->transport == TRANSPORT_HID) {
		result = sendApduHid((libusb_device_handle*)handle->handle, handle->ledger, apdu, apduLength, out, outLength, sw);
	}
	else
	if (result < 0) {
		return -1;
	}
#ifdef DEBUG_COMM
	if (result > 0) {
		printf("<= ");
		displayBinary(out, result);
	}
#endif
	return result;
}
int main(int argc, char **argv) {
	bitcoinTransaction *transaction;
	int offset = 0;
	int result;
	int version = DEFAULT_VERSION;
	int lockTime = DEFAULT_LOCKTIME;
	int i;
	int currentIndex = 1;
	bitcoinInput *lastInput = NULL;
	unsigned char *buffer;


	if (argc < 6) {
		fprintf(stderr, "Usage : %s [version (or empty for default)] [locktime (or empty for default)] [dongle output data] [trusted input 1] [input script 1] ... [last trusted input] [last input script]\n", argv[0]);
		return 0;
	}
	if (((argc - 4) % 2) != 0) {
		fprintf(stderr, "Invalid number of trusted input / input script parameters\n");
		return 0;
	}
	if (strlen(argv[1]) != 0) {
		version = strtol(argv[1], NULL, 10);
		if (version < 0) {
			fprintf(stderr, "Invalid version\n");
			return 0;
		}
	}
	if (strlen(argv[2]) != 0) {
		lockTime = strtol(argv[2], NULL, 10);
		if (lockTime < 0) {
			fprintf(stderr, "Invalid lockTime\n");
			return 0;
		}
	}	
	transaction = (bitcoinTransaction*)malloc(sizeof(bitcoinTransaction));
	if (transaction == NULL) {
		fprintf(stderr, "Failed to allocate transaction\n");
		return 0;
	}
	memset(transaction, 0, sizeof(bitcoinTransaction));
	writeUint32LE(transaction->version, version);
	for (i=4; i<argc; i += 2) {
		unsigned char trustedInput[56];
		bitcoinInput *input;
		input = (bitcoinInput*)malloc(sizeof(bitcoinInput));
		if (input == NULL) {
			fprintf(stderr, "Failed to allocate input\n");
			freeTransaction(transaction);
			return 0;
		}
		memset(input, 0, sizeof(bitcoinInput));
		result = hexToBin(argv[i], trustedInput, sizeof(trustedInput));
		if (result <= 0) {
			fprintf(stderr, "Invalid trustedInput %d\n", currentIndex);
			freeTransaction(transaction);
			free(input);
			return 0;
		}
		if (lastInput == NULL) {
			transaction->inputs = input;
		}
		else {
			lastInput->next = input;
		}
		input->scriptLength = (strlen(argv[i + 1]) / 2);
		input->script = (unsigned char*)malloc(input->scriptLength);
		if (input->script == NULL) {
			fprintf(stderr, "Failed to allocate script\n");
			freeTransaction(transaction);
			free(input);			
			return 0;
		}
		result = hexToBin(argv[i + 1], input->script, input->scriptLength);
		if (result <= 0) {
			fprintf(stderr, "Invalid script %d\n", currentIndex);
			freeTransaction(transaction);
			free(input);			
			return 0;
		}
		memcpy(input->prevOut, trustedInput + 4, sizeof(input->prevOut));
		memset(input->sequence, DEFAULT_SEQUENCE, sizeof(input->sequence));
		lastInput = input;
		currentIndex++;
	}	
	buffer = (unsigned char*)malloc(BUFFER_SIZE);
	if (buffer == NULL) {
		fprintf(stderr, "Failed to allocate output buffer\n");
		freeTransaction(transaction);
	}
	offset = writeTransactionWithoutOutputLocktime(transaction, buffer, BUFFER_SIZE);
	freeTransaction(transaction);
	result = hexToBin(argv[3], buffer + offset, BUFFER_SIZE - offset);
	if (result <= 0) {
		fprintf(stderr, "Invalid output\n");
		freeTransaction(transaction);
		free(buffer);
	}
	offset += result;
	writeUint32LE(buffer + offset, lockTime);
	offset += 4;
	printf("Transaction : ");
	displayBinary(buffer, offset);
	free(buffer);
	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 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;
}