1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-30 17:21:21 +00:00

add more checks for improbable cases; rework gui testing app

This commit is contained in:
Pavol Rusnak 2014-08-07 14:34:33 +02:00
parent b9ed9a9cd4
commit 8820ae9873
6 changed files with 122 additions and 39 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*~ *~
test-openssl test-openssl
tests tests
build-*/

46
bip32.c
View File

@ -31,27 +31,38 @@
#include "ripemd160.h" #include "ripemd160.h"
#include "base58.h" #include "base58.h"
void hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *public_key, HDNode *out) int hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *public_key, HDNode *out)
{ {
curve_point c;
if (!ecdsa_read_pubkey(public_key, &c)) { // invalid pubkey
return 0;
}
out->depth = depth; out->depth = depth;
out->fingerprint = fingerprint; out->fingerprint = fingerprint;
out->child_num = child_num; out->child_num = child_num;
memcpy(out->chain_code, chain_code, 32); memcpy(out->chain_code, chain_code, 32);
memset(out->private_key, 0, 32); memset(out->private_key, 0, 32);
memcpy(out->public_key, public_key, 33); memcpy(out->public_key, public_key, 33);
return 1;
} }
void hdnode_from_xprv(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *private_key, HDNode *out) int hdnode_from_xprv(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *private_key, HDNode *out)
{ {
bignum256 a;
bn_read_be(private_key, &a);
if (bn_is_zero(&a) || !bn_is_less(&a, &order256k1)) { // == 0 or >= order
return 0;
}
out->depth = depth; out->depth = depth;
out->fingerprint = fingerprint; out->fingerprint = fingerprint;
out->child_num = child_num; out->child_num = child_num;
memcpy(out->chain_code, chain_code, 32); memcpy(out->chain_code, chain_code, 32);
memcpy(out->private_key, private_key, 32); memcpy(out->private_key, private_key, 32);
hdnode_fill_public_key(out); hdnode_fill_public_key(out);
return 1;
} }
void hdnode_from_seed(uint8_t *seed, int seed_len, HDNode *out) int hdnode_from_seed(uint8_t *seed, int seed_len, HDNode *out)
{ {
uint8_t I[32 + 32]; uint8_t I[32 + 32];
memset(out, 0, sizeof(HDNode)); memset(out, 0, sizeof(HDNode));
@ -59,9 +70,15 @@ void hdnode_from_seed(uint8_t *seed, int seed_len, HDNode *out)
out->fingerprint = 0x00000000; out->fingerprint = 0x00000000;
out->child_num = 0; out->child_num = 0;
hmac_sha512((uint8_t *)"Bitcoin seed", 12, seed, seed_len, I); hmac_sha512((uint8_t *)"Bitcoin seed", 12, seed, seed_len, I);
memcpy(out->chain_code, I + 32, 32);
memcpy(out->private_key, I, 32); memcpy(out->private_key, I, 32);
bignum256 a;
bn_read_be(out->private_key, &a);
if (bn_is_zero(&a) || !bn_is_less(&a, &order256k1)) { // == 0 or >= order
return 0;
}
memcpy(out->chain_code, I + 32, 32);
hdnode_fill_public_key(out); hdnode_fill_public_key(out);
return 1;
} }
int hdnode_private_ckd(HDNode *inout, uint32_t i) int hdnode_private_ckd(HDNode *inout, uint32_t i)
@ -90,8 +107,17 @@ int hdnode_private_ckd(HDNode *inout, uint32_t i)
memcpy(inout->private_key, I, 32); memcpy(inout->private_key, I, 32);
bn_read_be(inout->private_key, &b); bn_read_be(inout->private_key, &b);
if (!bn_is_less(&b, &order256k1)) { // >= order
return 0;
}
bn_addmod(&a, &b, &order256k1); bn_addmod(&a, &b, &order256k1);
if (bn_is_zero(&a)) {
return 0;
}
inout->depth++; inout->depth++;
inout->child_num = i; inout->child_num = i;
bn_write_be(&a, inout->private_key); bn_write_be(&a, inout->private_key);
@ -128,8 +154,20 @@ int hdnode_public_ckd(HDNode *inout, uint32_t i)
hmac_sha512(inout->chain_code, 32, data, sizeof(data), I); hmac_sha512(inout->chain_code, 32, data, sizeof(data), I);
memcpy(inout->chain_code, I + 32, 32); memcpy(inout->chain_code, I + 32, 32);
bn_read_be(I, &c); bn_read_be(I, &c);
if (!bn_is_less(&c, &order256k1)) { // >= order
return 0;
}
scalar_multiply(&c, &b); // b = c * G scalar_multiply(&c, &b); // b = c * G
point_add(&a, &b); // b = a + b point_add(&a, &b); // b = a + b
#if USE_PUBKEY_VALIDATE
if (!ecdsa_validate_pubkey(&b)) {
return 0;
}
#endif
inout->public_key[0] = 0x02 | (b.y.val[0] & 0x01); inout->public_key[0] = 0x02 | (b.y.val[0] & 0x01);
bn_write_be(&b.x, inout->public_key + 1); bn_write_be(&b.x, inout->public_key + 1);

View File

@ -35,11 +35,11 @@ typedef struct {
uint8_t public_key[33]; uint8_t public_key[33];
} HDNode; } HDNode;
void hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *public_key, HDNode *out); int hdnode_from_xpub(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *public_key, HDNode *out);
void hdnode_from_xprv(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *private_key, HDNode *out); int hdnode_from_xprv(uint32_t depth, uint32_t fingerprint, uint32_t child_num, uint8_t *chain_code, uint8_t *private_key, HDNode *out);
void hdnode_from_seed(uint8_t *seed, int seed_len, HDNode *out); int hdnode_from_seed(uint8_t *seed, int seed_len, HDNode *out);
#define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000)) #define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000))

View File

@ -7,6 +7,7 @@ extern "C" {
#include "../ecdsa.h" #include "../ecdsa.h"
} }
bool root_set = false;
HDNode root; HDNode root;
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
@ -28,7 +29,6 @@ MainWindow::~MainWindow()
void MainWindow::on_buttonLoad_clicked() void MainWindow::on_buttonLoad_clicked()
{ {
ui->listAccount->clear();
if (!mnemonic_check(ui->editMnemonic->text().toLocal8Bit().data())) { if (!mnemonic_check(ui->editMnemonic->text().toLocal8Bit().data())) {
QMessageBox::critical(this, "Error", "Text is not a valid BIP39 mnemonic.", QMessageBox::Ok); QMessageBox::critical(this, "Error", "Text is not a valid BIP39 mnemonic.", QMessageBox::Ok);
return; return;
@ -36,22 +36,26 @@ void MainWindow::on_buttonLoad_clicked()
uint8_t seed[64]; uint8_t seed[64];
mnemonic_to_seed(ui->editMnemonic->text().toLocal8Bit().data(), ui->editPassphrase->text().toLocal8Bit().data(), seed, 0); mnemonic_to_seed(ui->editMnemonic->text().toLocal8Bit().data(), ui->editPassphrase->text().toLocal8Bit().data(), seed, 0);
hdnode_from_seed(seed, 64, &root); hdnode_from_seed(seed, 64, &root);
for (int i = 1; i <= 10; i++) { root_set = true;
ui->listAccount->addItem(QString("Account #") + QString::number(i)); ui->spinAccount->setValue(1);
} on_spinAccount_valueChanged(1);
} }
void MainWindow::on_listAccount_clicked(const QModelIndex &index) void MainWindow::on_spinAccount_valueChanged(int arg1)
{ {
if (!root_set) return;
const char addr_version = 0x00, wif_version = 0x80; const char addr_version = 0x00, wif_version = 0x80;
char buf[64]; char buf[128];
HDNode node; HDNode node;
// external chain // external chain
for (int chain = 0; chain < 2; chain++) { for (int chain = 0; chain < 2; chain++) {
QTableWidget *list = chain == 0 ? ui->listAddress : ui->listChange; QTableWidget *list = chain == 0 ? ui->listAddress : ui->listChange;
node = root; node = root;
hdnode_private_ckd(&node, 44 | 0x80000000); hdnode_private_ckd(&node, 44 | 0x80000000);
hdnode_private_ckd(&node, index.row() | 0x80000000); hdnode_private_ckd(&node, 0 | 0x80000000); // bitcoin
hdnode_private_ckd(&node, (arg1 - 1) | 0x80000000);
hdnode_serialize_private(&node, buf); QString xprv = QString(buf); ui->lineXprv->setText(xprv);
hdnode_serialize_public(&node, buf); QString xpub = QString(buf); ui->lineXpub->setText(xpub);
hdnode_private_ckd(&node, chain); // external / internal hdnode_private_ckd(&node, chain); // external / internal
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
HDNode node2 = node; HDNode node2 = node;

View File

@ -18,7 +18,7 @@ public:
private slots: private slots:
void on_buttonLoad_clicked(); void on_buttonLoad_clicked();
void on_listAccount_clicked(const QModelIndex &index); void on_spinAccount_valueChanged(int arg1);
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;

View File

@ -6,13 +6,14 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>1000</width>
<height>600</height> <height>600</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>DejaVu Sans Mono</family> <family>DejaVu Sans Mono</family>
<pointsize>8</pointsize>
</font> </font>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -20,10 +21,10 @@
</property> </property>
<widget class="QWidget" name="centralWidget"> <widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2"> <item row="4" column="1" colspan="3">
<widget class="QLineEdit" name="editMnemonic"/> <widget class="QLineEdit" name="lineXpub"/>
</item> </item>
<item row="0" column="2"> <item row="1" column="2">
<widget class="QLineEdit" name="editPassphrase"> <widget class="QLineEdit" name="editPassphrase">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@ -33,7 +34,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="3"> <item row="1" column="3">
<widget class="QPushButton" name="buttonLoad"> <widget class="QPushButton" name="buttonLoad">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@ -52,23 +53,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0" rowspan="2"> <item row="7" column="0" colspan="4">
<widget class="QListWidget" name="listAccount">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QTableWidget" name="listAddress"> <widget class="QTableWidget" name="listAddress">
<column> <column>
<property name="text"> <property name="text">
@ -87,7 +72,7 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="2" column="1" colspan="3"> <item row="9" column="0" colspan="4">
<widget class="QTableWidget" name="listChange"> <widget class="QTableWidget" name="listChange">
<column> <column>
<property name="text"> <property name="text">
@ -106,15 +91,70 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="labelMnemonic">
<property name="text">
<string>Mnemonic:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="labelPassphrase">
<property name="text">
<string>Passphrase:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelExternal">
<property name="text">
<string>External Chain:</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="labelInternal">
<property name="text">
<string>Internal Chain:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinAccount">
<property name="maximumSize">
<size>
<width>130</width>
<height>16777215</height>
</size>
</property>
<property name="prefix">
<string>Account #</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLineEdit" name="editMnemonic"/>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="lineXprv"/>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<tabstops> <tabstops>
<tabstop>editMnemonic</tabstop> <tabstop>editMnemonic</tabstop>
<tabstop>editPassphrase</tabstop>
<tabstop>buttonLoad</tabstop> <tabstop>buttonLoad</tabstop>
<tabstop>listAccount</tabstop> <tabstop>spinAccount</tabstop>
<tabstop>listAddress</tabstop> <tabstop>listAddress</tabstop>
<tabstop>listChange</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections/>