bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) { /* Data is what the "inner" HMAC function processes. It consists of the previous HMAC result plus the seed. */ char data[mdlen + seedlen]; memset(data, 0, mdlen); memcpy(data + mdlen, seed, seedlen); char hash[mdlen]; while(outlen > 0) { /* Inner HMAC */ if(!hmac_sha512(data, sizeof data, secret, secretlen, data)) return false; /* Outer HMAC */ if(outlen >= mdlen) { if(!hmac_sha512(data, sizeof data, secret, secretlen, out)) return false; out += mdlen; outlen -= mdlen; } else { if(!hmac_sha512(data, sizeof data, secret, secretlen, hash)) return false; memcpy(out, hash, outlen); out += outlen; outlen = 0; } } return true; }
void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) { char j[SHA512_DIGESTSIZE], k[SHA512_DIGESTSIZE]; char init[128]; char counter[4]; int c, i; /* iteration 1 */ memset (counter, 0, 4); counter[3] = (char) b; memcpy (init, salt, salt_len); /* salt */ memcpy (&init[salt_len], counter, 4); /* big-endian block number */ hmac_sha512 (pwd, pwd_len, init, salt_len + 4, j, SHA512_DIGESTSIZE); memcpy (u, j, SHA512_DIGESTSIZE); /* remaining iterations */ for (c = 1; c < iterations; c++) { hmac_sha512 (pwd, pwd_len, j, SHA512_DIGESTSIZE, k, SHA512_DIGESTSIZE); for (i = 0; i < SHA512_DIGESTSIZE; i++) { u[i] ^= k[i]; j[i] = k[i]; } } /* Prevent possible leaks. */ burn (j, sizeof(j)); burn (k, sizeof(k)); }
Gc_rc gc_hmac_sha512 (const void *key, size_t keylen, const void *in, size_t inlen, char *resbuf) { hmac_sha512 (key, keylen, in, inlen, resbuf); return GC_OK; }
void fsm_msgCipherKeyValue(CipherKeyValue *msg) { if (!msg->has_key) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No key provided"); return; } if (!msg->has_value) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No value provided"); return; } if (msg->value.size % 16) { fsm_sendFailure(FailureType_Failure_SyntaxError, "Value length must be a multiple of 16"); return; } if (!protectPin(true)) { layoutHome(); return; } HDNode *node = fsm_getRootNode(); if (!node) return; fsm_deriveKey(node, msg->address_n, msg->address_n_count); bool encrypt = msg->has_encrypt && msg->encrypt; bool ask_on_encrypt = msg->has_ask_on_encrypt && msg->ask_on_encrypt; bool ask_on_decrypt = msg->has_ask_on_decrypt && msg->ask_on_decrypt; if ((encrypt && ask_on_encrypt) || (!encrypt && ask_on_decrypt)) { layoutCipherKeyValue(encrypt, msg->key); if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "CipherKeyValue cancelled"); layoutHome(); return; } } uint8_t data[256 + 4]; strlcpy((char *)data, msg->key, sizeof(data)); strlcat((char *)data, ask_on_encrypt ? "E1" : "E0", sizeof(data)); strlcat((char *)data, ask_on_decrypt ? "D1" : "D0", sizeof(data)); hmac_sha512(node->private_key, 32, data, strlen((char *)data), data); RESP_INIT(Success); if (encrypt) { aes_encrypt_ctx ctx; aes_encrypt_key256(data, &ctx); aes_cbc_encrypt(msg->value.bytes, resp->payload.bytes, msg->value.size, data + 32, &ctx); } else { aes_decrypt_ctx ctx; aes_decrypt_key256(data, &ctx); aes_cbc_decrypt(msg->value.bytes, resp->payload.bytes, msg->value.size, data + 32, &ctx); } resp->has_payload = true; resp->payload.size = msg->value.size; msg_write(MessageType_MessageType_Success, resp); layoutHome(); }
void hdnode_from_seed(uint8_t version_byte, uint32_t version, uint8_t *seed, int seed_len, HDNode *out) { uint8_t I[32 + 32]; out->version = version; out->depth = 0; out->fingerprint = 0x00000000; out->child_num = 0; hmac_sha512((uint8_t *)"Bitcoin seed", 12, seed, seed_len, I); memcpy(out->chain_code, I + 32, 32); memcpy(out->private_key, I, 32); hdnode_fill_public_key(out); out->version_byte = version_byte; hdnode_fill_address(out); }
int hdnode_public_ckd(HDNode *inout, uint32_t i) { uint8_t data[1 + 32 + 4]; uint8_t I[32 + 32]; uint8_t fingerprint[32]; curve_point a, b; bignum256 c; if (i & 0x80000000) { // private derivation return 0; } else { // public derivation memcpy(data, inout->public_key, 33); } write_be(data + 33, i); sha256_Raw(inout->public_key, 33, fingerprint); ripemd160(fingerprint, 32, fingerprint); inout->fingerprint = (fingerprint[0] << 24) + (fingerprint[1] << 16) + (fingerprint[2] << 8) + fingerprint[3]; memset(inout->private_key, 0, 32); if (!ecdsa_read_pubkey(inout->public_key, &a)) { return 0; } hmac_sha512(inout->chain_code, 32, data, sizeof(data), I); memcpy(inout->chain_code, I + 32, 32); bn_read_be(I, &c); if (!bn_is_less(&c, &order256k1)) { // >= order return 0; } scalar_multiply(&c, &b); // b = c * G 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); bn_write_be(&b.x, inout->public_key + 1); inout->depth++; inout->child_num = i; return 1; }
//------------------------------------------------------------------------------ // returns message signature generated from a URI path, a nonce // and postdata, message signature is created as a follows: // // hmac_sha512(path + sha256(nonce + postdata), b64decode(secret)) // // and the result is converted in a base64 string: std::string KClient::signature(const std::string& path, const std::string& nonce, const std::string& postdata) const { // add path to data to encrypt std::vector<unsigned char> data(path.begin(), path.end()); // concatenate nonce and postdata and compute SHA256 std::vector<unsigned char> nonce_postdata = sha256(nonce + postdata); // concatenate path and nonce_postdata (path + sha256(nonce + postdata)) data.insert(data.end(), nonce_postdata.begin(), nonce_postdata.end()); // and compute HMAC return b64_encode( hmac_sha512(data, b64_decode(secret_)) ); }
int hdnode_private_ckd(HDNode *inout, uint32_t i) { uint8_t data[1 + 32 + 4]; uint8_t I[32 + 32]; uint8_t fingerprint[32]; bignum256 a, b; if (i & 0x80000000) { // private derivation data[0] = 0; memcpy(data + 1, inout->private_key, 32); } else { // public derivation memcpy(data, inout->public_key, 33); } write_be(data + 33, i); sha256_Raw(inout->public_key, 33, fingerprint); ripemd160(fingerprint, 32, fingerprint); inout->fingerprint = (fingerprint[0] << 24) + (fingerprint[1] << 16) + (fingerprint[2] << 8) + fingerprint[3]; bn_read_be(inout->private_key, &a); hmac_sha512(inout->chain_code, 32, data, sizeof(data), I); memcpy(inout->chain_code, I + 32, 32); memcpy(inout->private_key, I, 32); bn_read_be(inout->private_key, &b); if (!bn_is_less(&b, &order256k1)) { // >= order return 0; } bn_addmod(&a, &b, &order256k1); if (bn_is_zero(&a)) { return 0; } inout->depth++; inout->child_num = i; bn_write_be(&a, inout->private_key); hdnode_fill_public_key(inout); return 1; }
int hdnode_from_seed(const uint8_t *seed, int seed_len, HDNode *out) { uint8_t I[32 + 32]; memset(out, 0, sizeof(HDNode)); out->depth = 0; out->fingerprint = 0x00000000; out->child_num = 0; hmac_sha512((uint8_t *)"Bitcoin seed", 12, seed, seed_len, I); 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); return 1; }
int fko_set_spa_hmac(fko_ctx_t ctx, const char * const hmac_key, const int hmac_key_len) { unsigned char hmac[SHA512_DIGEST_STR_LEN] = {0}; char *hmac_base64 = NULL; int hmac_digest_str_len = 0; int hmac_digest_len = 0; /* Must be initialized */ if(!CTX_INITIALIZED(ctx)) return(FKO_ERROR_CTX_NOT_INITIALIZED); if(hmac_key_len > MAX_DIGEST_BLOCK_LEN) return(FKO_ERROR_INVALID_HMAC_KEY_LEN); if(ctx->hmac_type == FKO_HMAC_MD5) { hmac_md5(ctx->encrypted_msg, ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len); hmac_digest_len = MD5_DIGEST_LEN; hmac_digest_str_len = MD5_DIGEST_STR_LEN; } else if(ctx->hmac_type == FKO_HMAC_SHA1) { hmac_sha1(ctx->encrypted_msg, ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len); hmac_digest_len = SHA1_DIGEST_LEN; hmac_digest_str_len = SHA1_DIGEST_STR_LEN; } else if(ctx->hmac_type == FKO_HMAC_SHA256) { hmac_sha256(ctx->encrypted_msg, ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len); hmac_digest_len = SHA256_DIGEST_LEN; hmac_digest_str_len = SHA256_DIGEST_STR_LEN; } else if(ctx->hmac_type == FKO_HMAC_SHA384) { hmac_sha384(ctx->encrypted_msg, ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len); hmac_digest_len = SHA384_DIGEST_LEN; hmac_digest_str_len = SHA384_DIGEST_STR_LEN; } else if(ctx->hmac_type == FKO_HMAC_SHA512) { hmac_sha512(ctx->encrypted_msg, ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len); hmac_digest_len = SHA512_DIGEST_LEN; hmac_digest_str_len = SHA512_DIGEST_STR_LEN; } hmac_base64 = calloc(1, MD_HEX_SIZE(hmac_digest_len)+1); if (hmac_base64 == NULL) return(FKO_ERROR_MEMORY_ALLOCATION); b64_encode(hmac, hmac_base64, hmac_digest_len); strip_b64_eq(hmac_base64); if(ctx->msg_hmac != NULL) free(ctx->msg_hmac); ctx->msg_hmac = strdup(hmac_base64); ctx->msg_hmac_len = strnlen(ctx->msg_hmac, hmac_digest_str_len); free(hmac_base64); switch(ctx->msg_hmac_len) { case MD5_B64_LEN: break; case SHA1_B64_LEN: break; case SHA256_B64_LEN: break; case SHA384_B64_LEN: break; case SHA512_B64_LEN: break; default: return(FKO_ERROR_INVALID_DATA_HMAC_LEN_VALIDFAIL); } return FKO_SUCCESS; }
int main(void) { static const char *vectors[] = { /* HMAC-SHA-224 */ "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22", "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44", "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea", "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a", "0e2aea68a90c8d37c988bcdb9fca6fa8", "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e", "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1", /* HMAC-SHA-256 */ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", "a3b6167473100ee06e0c796c2955552b", "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2", /* HMAC-SHA-384 */ "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c" "faea9ea9076ede7f4af152e8b2fa9cb6", "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e" "8e2240ca5e69e2c78b3239ecfab21649", "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b" "2a5ab39dc13814b94e3ab6e101a34f27", "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e" "6801dd23c4a7d679ccf8a386c674cffb", "3abf34c3503b2a23a46efc619baef897", "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6" "0c2ef6ab4030fe8296248df163f44952", "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5" "a678cc31e799176d3860e6110c46523e", /* HMAC-SHA-512 */ "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde" "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854", "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554" "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737", "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39" "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb", "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db" "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd", "415fad6271580a531d4179bc891d87a6", "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352" "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598", "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944" "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58" }; static char *messages[] = { "Hi There", "what do ya want for nothing?", NULL, NULL, "Test With Truncation", "Test Using Larger Than Block-Size Key - Hash Key First", "This is a test using a larger than block-size key " "and a larger than block-size data. The key needs" " to be hashed before being used by the HMAC algorithm." }; unsigned char mac[SHA512_DIGEST_SIZE]; unsigned char *keys[7]; unsigned int keys_len[7] = {20, 4, 20, 25, 20, 131, 131}; unsigned int messages2and3_len = 50; unsigned int mac_224_size, mac_256_size, mac_384_size, mac_512_size; int i; for (i = 0; i < 7; i++) { keys[i] = malloc(keys_len[i]); if (keys[i] == NULL) { fprintf(stderr, "Can't allocate memory\n"); return 1; } } memset(keys[0], 0x0b, keys_len[0]); strcpy((char *) keys[1], "Jefe"); memset(keys[2], 0xaa, keys_len[2]); for (i = 0; i < (int) keys_len[3]; i++) keys[3][i] = (unsigned char) i + 1; memset(keys[4], 0x0c, keys_len[4]); memset(keys[5], 0xaa, keys_len[5]); memset(keys[6], 0xaa, keys_len[6]); messages[2] = malloc(messages2and3_len + 1); messages[3] = malloc(messages2and3_len + 1); if (messages[2] == NULL || messages[3] == NULL) { fprintf(stderr, "Can't allocate memory\n"); return 1; } messages[2][messages2and3_len] = '\0'; messages[3][messages2and3_len] = '\0'; memset(messages[2], 0xdd, messages2and3_len); memset(messages[3], 0xcd, messages2and3_len); printf("HMAC-SHA-2 IETF Validation tests\n\n"); for (i = 0; i < 7; i++) { if (i != 4) { mac_224_size = SHA224_DIGEST_SIZE; mac_256_size = SHA256_DIGEST_SIZE; mac_384_size = SHA384_DIGEST_SIZE; mac_512_size = SHA512_DIGEST_SIZE; } else { mac_224_size = 128 / 8; mac_256_size = 128 / 8; mac_384_size = 128 / 8; mac_512_size = 128 / 8; } printf("Test %d:\n", i + 1); hmac_sha224(keys[i], keys_len[i], (unsigned char *) messages[i], strlen(messages[i]), mac, mac_224_size); test(vectors[i], mac, mac_224_size); hmac_sha256(keys[i], keys_len[i], (unsigned char *) messages[i], strlen(messages[i]), mac, mac_256_size); test(vectors[7 + i], mac, mac_256_size); hmac_sha384(keys[i], keys_len[i], (unsigned char *) messages[i], strlen(messages[i]), mac, mac_384_size); test(vectors[14 + i], mac, mac_384_size); hmac_sha512(keys[i], keys_len[i], (unsigned char *) messages[i], strlen(messages[i]), mac, mac_512_size); test(vectors[21 + i], mac, mac_512_size); } printf("All tests passed.\n"); return 0; }
int main (int argc, char *argv[]) { { char *key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; size_t key_len = 20; char *data = "Hi There"; size_t data_len = 8; char *digest = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54"; char out[64]; if (hmac_sha512 (key, key_len, data, data_len, out) != 0) { printf ("call failure\n"); return 1; } if (memcmp (digest, out, 64) != 0) { size_t i; printf ("hash 1 mismatch. expected:\n"); for (i = 0; i < 64; i++) printf ("%02x ", digest[i] & 0xFF); printf ("\ncomputed:\n"); for (i = 0; i < 64; i++) printf ("%02x ", out[i] & 0xFF); printf ("\n"); return 1; } } { char *key = "Jefe"; size_t key_len = 4; char *data = "what do ya want for nothing?"; size_t data_len = 28; char *digest = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37"; char out[64]; if (hmac_sha512 (key, key_len, data, data_len, out) != 0) { printf ("call failure\n"); return 1; } if (memcmp (digest, out, 64) != 0) { size_t i; printf ("hash 2 mismatch. expected:\n"); for (i = 0; i < 64; i++) printf ("%02x ", digest[i] & 0xFF); printf ("\ncomputed:\n"); for (i = 0; i < 64; i++) printf ("%02x ", out[i] & 0xFF); printf ("\n"); return 1; } } { char *key = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; size_t key_len = 20; char *data = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD"; size_t data_len = 50; char *digest = "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb"; char out[64]; if (hmac_sha512 (key, key_len, data, data_len, out) != 0) { printf ("call failure\n"); return 1; } if (memcmp (digest, out, 64) != 0) { size_t i; printf ("hash 3 mismatch. expected:\n"); for (i = 0; i < 64; i++) printf ("%02x ", digest[i] & 0xFF); printf ("\ncomputed:\n"); for (i = 0; i < 64; i++) printf ("%02x ", out[i] & 0xFF); printf ("\n"); return 1; } } return 0; }
int main(int argc, char **argv, char **env) { // hmac-sha test printf("***** HMAC-SHA TEST *****\n"); hash_t *hash; hash = (hash_t *)malloc(sizeof(hash_t) * MAX_LEN); char *key = "testkeyhellofoobar"; char *msg = "testmsghellofoobar"; size_t hash_len; int i; hash_len = hmac_sha1((hash_t *)key, (hash_t *)msg, hash); printf("SHA1(%s, %s) (len = %ld)\n= ", key, msg, hash_len); for (i = 0; i < hash_len; i++) printf("%02x", hash[i]); printf("\n"); hash_len = hmac_sha256((hash_t *)key, (hash_t *)msg, hash); printf("SHA256(%s, %s) (len = %ld)\n= ", key, msg, hash_len); for (i = 0; i < hash_len; i++) printf("%02x", hash[i]); printf("\n"); hash_len = hmac_sha512((hash_t *)key, (hash_t *)msg, hash); printf("SHA512(%s, %s) (len = %ld)\n= ", key, msg, hash_len); for (i = 0; i < hash_len; i++) printf("%02x", hash[i]); printf("\n"); free(hash); // totp test printf("\n***** TOTP TEST *****\n"); time_t t; t = time(NULL); char *token; size_t len; len = 6; token = (char *)malloc(sizeof(char) * len); printf("len = %ld\n", len); printf("t = %ld\n", t); totp_hmac_sha1(key, t, len, token); printf("sha1(%s): %s\n", key, token); totp_hmac_sha256(key, t, len, token); printf("sha256(%s): %s\n", key, token); totp_hmac_sha512(key, t, len, token); printf("sha512(%s): %s\n", key, token); free(token); return 0; }
void fsm_msgCipherKeyValue(CipherKeyValue *msg) { if (!storage_is_initialized()) { fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); return; } if(!msg->has_key) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No key provided"); return; } if(!msg->has_value) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No value provided"); return; } if(msg->value.size % 16) { fsm_sendFailure(FailureType_Failure_SyntaxError, "Value length must be a multiple of 16"); return; } if(!pin_protect_cached()) { go_home(); return; } const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count); if(!node) { return; } bool encrypt = msg->has_encrypt && msg->encrypt; bool ask_on_encrypt = msg->has_ask_on_encrypt && msg->ask_on_encrypt; bool ask_on_decrypt = msg->has_ask_on_decrypt && msg->ask_on_decrypt; if((encrypt && ask_on_encrypt) || (!encrypt && ask_on_decrypt)) { if(!confirm_cipher(encrypt, msg->key)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "CipherKeyValue cancelled"); go_home(); return; } } uint8_t data[256 + 4]; strlcpy((char *)data, msg->key, sizeof(data)); strlcat((char *)data, ask_on_encrypt ? "E1" : "E0", sizeof(data)); strlcat((char *)data, ask_on_decrypt ? "D1" : "D0", sizeof(data)); hmac_sha512(node->private_key, 32, data, strlen((char *)data), data); RESP_INIT(CipheredKeyValue); if(encrypt) { aes_encrypt_ctx ctx; aes_encrypt_key256(data, &ctx); aes_cbc_encrypt(msg->value.bytes, resp->value.bytes, msg->value.size, ((msg->iv.size == 16) ? (msg->iv.bytes) : (data + 32)), &ctx); } else { aes_decrypt_ctx ctx; aes_decrypt_key256(data, &ctx); aes_cbc_decrypt(msg->value.bytes, resp->value.bytes, msg->value.size, ((msg->iv.size == 16) ? (msg->iv.bytes) : (data + 32)), &ctx); } resp->has_value = true; resp->value.size = msg->value.size; msg_write(MessageType_MessageType_CipheredKeyValue, resp); go_home(); }