diff --git a/firmware/fsm.c b/firmware/fsm.c index 2ca2f51..21f6982 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -775,6 +775,54 @@ void fsm_msgSignIdentity(SignIdentity *msg) layoutHome(); } +void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg) +{ + RESP_INIT(ECDHSessionKey); + + if (!storage_isInitialized()) { + fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); + return; + } + + // TODO: consider adding appropriate UI for manual confirmation? + + 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 | 17; + 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 char *curve = SECP256K1_NAME; + if (msg->has_ecdsa_curve_name) { + curve = msg->ecdsa_curve_name; + } + + const HDNode *node = fsm_getDerivedNode(curve, address_n, 5); + if (!node) return; + + if (cryptoGetECDHSessionKey(node, msg->peer_public_key.bytes, resp->session_key.bytes) == 0) { + resp->has_session_key = true; + resp->session_key.size = 65; + msg_write(MessageType_MessageType_ECDHSessionKey, resp); + } else { + fsm_sendFailure(FailureType_Failure_Other, "Error getting ECDH session key"); + } + layoutHome(); +} + /* ECIES disabled void fsm_msgEncryptMessage(EncryptMessage *msg) { diff --git a/firmware/fsm.h b/firmware/fsm.h index a106b39..b361ad7 100644 --- a/firmware/fsm.h +++ b/firmware/fsm.h @@ -51,6 +51,7 @@ void fsm_msgEntropyAck(EntropyAck *msg); void fsm_msgSignMessage(SignMessage *msg); void fsm_msgVerifyMessage(VerifyMessage *msg); void fsm_msgSignIdentity(SignIdentity *msg); +void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg); void fsm_msgEncryptMessage(EncryptMessage *msg); void fsm_msgDecryptMessage(DecryptMessage *msg); //void fsm_msgPassphraseAck(PassphraseAck *msg); diff --git a/firmware/messages.c b/firmware/messages.c index a12911a..ee323b8 100644 --- a/firmware/messages.c +++ b/firmware/messages.c @@ -63,6 +63,7 @@ static const struct MessagesMap_t MessagesMap[] = { {'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_GetECDHSessionKey, GetECDHSessionKey_fields, (void (*)(void *))fsm_msgGetECDHSessionKey}, /* ECIES disabled {'n', 'i', MessageType_MessageType_EncryptMessage, EncryptMessage_fields, (void (*)(void *))fsm_msgEncryptMessage}, {'n', 'i', MessageType_MessageType_DecryptMessage, DecryptMessage_fields, (void (*)(void *))fsm_msgDecryptMessage}, @@ -86,6 +87,7 @@ static const struct MessagesMap_t MessagesMap[] = { {'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_ECDHSessionKey, ECDHSessionKey_fields, 0}, /* ECIES disabled {'n', 'o', MessageType_MessageType_EncryptedMessage, EncryptedMessage_fields, 0}, {'n', 'o', MessageType_MessageType_DecryptedMessage, DecryptedMessage_fields, 0},