From 73c42402b9e9a8d3f10b539c44d564c28f9b1cd2 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Fri, 20 Feb 2015 20:22:05 +0100 Subject: [PATCH] implement SignIdentity workflow --- firmware/crypto.c | 27 ++++++++++++++++++++++ firmware/crypto.h | 2 ++ firmware/fsm.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ firmware/fsm.h | 1 + firmware/layout2.c | 12 ++++++++++ firmware/layout2.h | 1 + firmware/messages.c | 2 ++ 7 files changed, 100 insertions(+) diff --git a/firmware/crypto.c b/firmware/crypto.c index d0f9f48357..9015b462fe 100644 --- a/firmware/crypto.c +++ b/firmware/crypto.c @@ -340,3 +340,30 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t layoutProgressUpdate(true); return 1; } + +int cryptoIdentityFingerprint(const IdentityType *identity, uint8_t *hash) +{ + SHA256_CTX ctx; + sha256_Init(&ctx); + sha256_Update(&ctx, (const uint8_t *)&(identity->index), sizeof(uint32_t)); + if (identity->has_proto && identity->proto[0]) { + sha256_Update(&ctx, (const uint8_t *)(identity->proto), strlen(identity->proto)); + sha256_Update(&ctx, (const uint8_t *)"://", 3); + } + if (identity->has_user && identity->user[0]) { + sha256_Update(&ctx, (const uint8_t *)(identity->user), strlen(identity->user)); + sha256_Update(&ctx, (const uint8_t *)"@", 1); + } + if (identity->has_host && identity->host[0]) { + sha256_Update(&ctx, (const uint8_t *)(identity->host), strlen(identity->host)); + } + if (identity->has_port && identity->port[0]) { + sha256_Update(&ctx, (const uint8_t *)":", 1); + sha256_Update(&ctx, (const uint8_t *)(identity->port), strlen(identity->port)); + } + if (identity->has_path && identity->path[0]) { + sha256_Update(&ctx, (const uint8_t *)(identity->path), strlen(identity->path)); + } + sha256_Final(hash, &ctx); + return 1; +} diff --git a/firmware/crypto.h b/firmware/crypto.h index 4353aa635e..89878003c7 100644 --- a/firmware/crypto.h +++ b/firmware/crypto.h @@ -48,4 +48,6 @@ int cryptoMultisigPubkeyIndex(const MultisigRedeemScriptType *multisig, const ui int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t *hash); +int cryptoIdentityFingerprint(const IdentityType *identity, uint8_t *hash); + #endif diff --git a/firmware/fsm.c b/firmware/fsm.c index 6a4e07d711..4ea436c5b4 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -620,6 +620,61 @@ void fsm_msgVerifyMessage(VerifyMessage *msg) layoutHome(); } +void fsm_msgSignIdentity(SignIdentity *msg) +{ + RESP_INIT(SignedIdentity); + + layoutSignIdentity(&(msg->identity), msg->has_challenge_visual ? msg->challenge_visual : 0); + if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { + fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign identity cancelled"); + layoutHome(); + return; + } + + if (!protectPin(true)) { + layoutHome(); + return; + } + + uint8_t hash[32]; + if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { + fsm_sendFailure(FailureType_Failure_Other, "Invalid identity"); + layoutHome(); + return; + } + uint32_t address_n[5]; + address_n[0] = 0x80000000 | 46; + address_n[1] = 0x80000000 | hash[ 0] | (hash[ 1] << 8) | (hash[ 2] << 16) | (hash[ 3] << 24); + address_n[2] = 0x80000000 | hash[ 4] | (hash[ 5] << 8) | (hash[ 6] << 16) | (hash[ 7] << 24); + address_n[3] = 0x80000000 | hash[ 8] | (hash[ 9] << 8) | (hash[10] << 16) | (hash[11] << 24); + address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | (hash[15] << 24); + + const HDNode *node = fsm_getDerivedNode(address_n, 5); + if (!node) return; + + uint8_t message[128]; + memcpy(message, msg->challenge_hidden.bytes, msg->challenge_hidden.size); + const int len = strlen(msg->challenge_visual); + memcpy(message + msg->challenge_hidden.size, msg->challenge_visual, len); + + layoutProgressSwipe("Signing", 0); + if (cryptoMessageSign(message, msg->challenge_hidden.size + len, node->private_key, resp->signature.bytes) == 0) { + resp->has_address = true; + uint8_t addr_raw[21]; + ecdsa_get_address_raw(node->public_key, 0x00, addr_raw); // hardcoded Bitcoin address type + base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address)); + resp->has_public_key = true; + resp->public_key.size = 33; + memcpy(resp->public_key.bytes, node->public_key, 33); + resp->has_signature = true; + resp->signature.size = 65; + msg_write(MessageType_MessageType_SignedIdentity, resp); + } else { + fsm_sendFailure(FailureType_Failure_Other, "Error signing identity"); + } + layoutHome(); +} + void fsm_msgEncryptMessage(EncryptMessage *msg) { if (!msg->has_pubkey) { diff --git a/firmware/fsm.h b/firmware/fsm.h index 6b7bde8e39..021eeb31a3 100644 --- a/firmware/fsm.h +++ b/firmware/fsm.h @@ -49,6 +49,7 @@ void fsm_msgGetAddress(GetAddress *msg); void fsm_msgEntropyAck(EntropyAck *msg); void fsm_msgSignMessage(SignMessage *msg); void fsm_msgVerifyMessage(VerifyMessage *msg); +void fsm_msgSignIdentity(SignIdentity *msg); void fsm_msgEncryptMessage(EncryptMessage *msg); void fsm_msgDecryptMessage(DecryptMessage *msg); //void fsm_msgPassphraseAck(PassphraseAck *msg); diff --git a/firmware/layout2.c b/firmware/layout2.c index 73819d0a2a..6eda7a3355 100644 --- a/firmware/layout2.c +++ b/firmware/layout2.c @@ -261,3 +261,15 @@ void layoutAddress(const char *address, const char *desc) oledRefresh(); } + +void layoutSignIdentity(const IdentityType *identity, const char *challenge) +{ + layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", + "Sign identity?", + identity->has_proto ? identity->proto : NULL, + identity->has_user ? identity->user : NULL, + identity->has_host ? identity->host : NULL, + challenge, + NULL, + NULL); +} diff --git a/firmware/layout2.h b/firmware/layout2.h index b109863079..790737a329 100644 --- a/firmware/layout2.h +++ b/firmware/layout2.h @@ -36,5 +36,6 @@ void layoutCipherKeyValue(bool encrypt, const char *key); void layoutEncryptMessage(const uint8_t *msg, uint32_t len, bool signing); void layoutDecryptMessage(const uint8_t *msg, uint32_t len, const char *address); void layoutAddress(const char *address, const char *desc); +void layoutSignIdentity(const IdentityType *identity, const char *challenge); #endif diff --git a/firmware/messages.c b/firmware/messages.c index 0692ff5c07..8c11cbeabe 100644 --- a/firmware/messages.c +++ b/firmware/messages.c @@ -60,6 +60,7 @@ static const struct MessagesMap_t MessagesMap[] = { {'n', 'i', MessageType_MessageType_GetAddress, GetAddress_fields, (void (*)(void *))fsm_msgGetAddress}, {'n', 'i', MessageType_MessageType_EntropyAck, EntropyAck_fields, (void (*)(void *))fsm_msgEntropyAck}, {'n', 'i', MessageType_MessageType_SignMessage, SignMessage_fields, (void (*)(void *))fsm_msgSignMessage}, + {'n', 'i', MessageType_MessageType_SignIdentity, SignIdentity_fields, (void (*)(void *))fsm_msgSignIdentity}, {'n', 'i', MessageType_MessageType_VerifyMessage, VerifyMessage_fields, (void (*)(void *))fsm_msgVerifyMessage}, {'n', 'i', MessageType_MessageType_EncryptMessage, EncryptMessage_fields, (void (*)(void *))fsm_msgEncryptMessage}, {'n', 'i', MessageType_MessageType_DecryptMessage, DecryptMessage_fields, (void (*)(void *))fsm_msgDecryptMessage}, @@ -80,6 +81,7 @@ static const struct MessagesMap_t MessagesMap[] = { {'n', 'o', MessageType_MessageType_Address, Address_fields, 0}, {'n', 'o', MessageType_MessageType_EntropyRequest, EntropyRequest_fields, 0}, {'n', 'o', MessageType_MessageType_MessageSignature, MessageSignature_fields, 0}, + {'n', 'o', MessageType_MessageType_SignedIdentity, SignedIdentity_fields, 0}, {'n', 'o', MessageType_MessageType_EncryptedMessage, EncryptedMessage_fields, 0}, {'n', 'o', MessageType_MessageType_DecryptedMessage, DecryptedMessage_fields, 0}, {'n', 'o', MessageType_MessageType_PassphraseRequest, PassphraseRequest_fields, 0},