bool storage_getRootNode(HDNode *node) { // root node is properly cached if (sessionRootNodeCached) { memcpy(node, &sessionRootNode, sizeof(HDNode)); return true; } // if storage has node, decrypt and use it if (storage.has_node) { if (!protectPassphrase()) { return false; } if (hdnode_from_xprv(storage.node.depth, storage.node.fingerprint, storage.node.child_num, storage.node.chain_code.bytes, storage.node.private_key.bytes, &sessionRootNode) == 0) { return false; } if (storage.has_passphrase_protection && storage.passphrase_protection && strlen(sessionPassphrase)) { // decrypt hd node uint8_t secret[64]; uint8_t salt[12]; memcpy(salt, "TREZORHD", 8); layoutProgressSwipe("Waking up", 0); pbkdf2_hmac_sha512((const uint8_t *)sessionPassphrase, strlen(sessionPassphrase), salt, 8, BIP39_PBKDF2_ROUNDS, secret, 64, get_root_node_callback); aes_decrypt_ctx ctx; aes_decrypt_key256(secret, &ctx); aes_cbc_decrypt(sessionRootNode.chain_code, sessionRootNode.chain_code, 32, secret + 32, &ctx); aes_cbc_decrypt(sessionRootNode.private_key, sessionRootNode.private_key, 32, secret + 32, &ctx); } memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } // if storage has mnemonic, convert it to node and use it if (storage.has_mnemonic) { if (!protectPassphrase()) { return false; } uint8_t seed[64]; layoutProgressSwipe("Waking up", 0); mnemonic_to_seed(storage.mnemonic, sessionPassphrase, seed, get_root_node_callback); // BIP-0039 if (hdnode_from_seed(seed, sizeof(seed), &sessionRootNode) == 0) { return false; } memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } return false; }
static int rj_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res) { struct int_ctx *cx = (struct int_ctx *) c->ptr; if (!cx->is_init) if (rj_real_init(cx, 0)) return PXE_CIPHER_INIT; if (dlen == 0) return 0; if (dlen & 15) return PXE_NOTBLOCKSIZE; memcpy(res, data, dlen); if (cx->mode == MODE_CBC) { aes_cbc_decrypt(&cx->ctx.rj, cx->iv, res, dlen); memcpy(cx->iv, data + dlen - 16, 16); } else aes_ecb_decrypt(&cx->ctx.rj, res, dlen); return 0; }
err_status_t aes_cbc_nist_decrypt(aes_cbc_ctx_t *c, unsigned char *data, unsigned int *bytes_in_data) { unsigned char *pad_end; int num_pad_bytes; err_status_t status; /* * cbc decrypt the padded data */ status = aes_cbc_decrypt(c, data, bytes_in_data); if (status) return status; /* * determine the number of padding bytes in the decrypted plaintext * - this value is always between 1 and 16, inclusive. */ num_pad_bytes = 1; pad_end = data + (*bytes_in_data - 1); while (*pad_end != 0xa0) { /* note: should check padding correctness */ pad_end--; num_pad_bytes++; } /* decrement data size */ *bytes_in_data -= num_pad_bytes; return err_status_ok; }
/** * Decrypt Decrypts data based on cipher text, cipher key and IV * @param b_input Cipher text * @param p_key Cipher key * @param p_iv Initialization vector * @return Decrypted data */ QByteArray AES::decrypt(QByteArray b_input, QByteArray p_key, QByteArray p_iv) { if (b_input.isEmpty()) { qDebug() << "Error while decryption: Cannot decrypt empty input"; return QByteArray(); } QByteArray result; int keySize = p_key.size(); int ivSize = p_iv.size(); if (keySize != 16 && keySize != 24 && keySize != 32) { qDebug() << "Error while decryption: Invalid keysize"; return QByteArray(); } if (ivSize != 16) { qDebug() << "Error while decryption: Invalid keysize"; return QByteArray(); } // 500KB blocks qint64 chunksCount = (b_input.size()/500000) + 1; for (int part = 0; part < chunksCount; part++) { // Out of range checks if (part*500000 > b_input.size()) { qDebug() << "Error while decryption: Skipped: Buffer overflow"; continue; } QByteArray p_chunk = b_input.mid(part*500000, 500000); int inputSize = p_chunk.size(); unsigned char key[keySize]; qByteArrayToUCharArray(p_key, key); unsigned char iv[ivSize]; qByteArrayToUCharArray(p_iv, iv); unsigned char encrypted[inputSize]; qByteArrayToUCharArray(p_chunk, encrypted); unsigned char decrypted[inputSize]; // Decrypted text aes_context context; aes_set_key(key, keySize * 8, &context); aes_cbc_decrypt(encrypted, decrypted, inputSize, iv, &context); QByteArray temp_result = uCharArrayToQByteArray(decrypted, inputSize); result.append( temp_result); } removePadding(&result); return result; }
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(); }
OSStatus AES_CBCFrame_Update( AES_CBCFrame_Context *inContext, const void *inSrc, size_t inSrcLen, void *inDst ) { OSStatus err; const uint8_t * src; const uint8_t * end; uint8_t * dst; size_t len; src = (const uint8_t *) inSrc; end = src + inSrcLen; dst = (uint8_t *) inDst; // Process whole blocks. len = inSrcLen & ~( (size_t)( kAES_CBCFrame_Size - 1 ) ); if( len > 0 ) { #if( AES_UTILS_USE_COMMON_CRYPTO ) err = CCCryptorReset( inContext->cryptor, inContext->iv ); require_noerr( err, exit ); err = CCCryptorUpdate( inContext->cryptor, src, len, dst, len, &len ); require_noerr( err, exit ); #elif( AES_UTILS_USE_GLADMAN_AES ) uint8_t iv[ kAES_CBCFrame_Size ]; memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed. if( inContext->encrypt ) aes_cbc_encrypt( src, dst, (int) len, iv, &inContext->ctx.encrypt ); else aes_cbc_decrypt( src, dst, (int) len, iv, &inContext->ctx.decrypt ); #elif( AES_UTILS_USE_USSL ) uint8_t iv[ kAES_CBCFrame_Size ]; memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed. if( inContext->encrypt ) aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, len, iv, (unsigned char *) src, dst ); else aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, len, iv, (unsigned char *) src, dst ); #else uint8_t iv[ kAES_CBCFrame_Size ]; memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed. AES_cbc_encrypt( src, dst, (unsigned long) len, &inContext->key, iv, inContext->mode ); #endif src += len; dst += len; } // The remaining bytes are just copied unencrypted. while( src != end ) *dst++ = *src++; err = kNoErr; #if( AES_UTILS_USE_COMMON_CRYPTO ) exit: #endif return( err ); }
int main(int argc, char *argv[]) { const char indata[] = "MyBloodyValentinMyBloodyValentin"; unsigned char data[32768]; char hex[256], base64[256]; int len; unsigned char iv[] = { 'Y', 'E', 'L', 'L', 'O', 'W', ' ', 'S', 'U', 'B', 'M', 'A', 'R', 'I', 'N', 'E' }; unsigned char key[] = { 'Y', 'E', 'L', 'L', 'O', 'W', ' ', 'S', 'U', 'B', 'M', 'A', 'R', 'I', 'N', 'E' }; len = strlen(indata); printf("// testing aes-128-ecb\n"); printf("Plaintext:\n"); hexdump(indata, len); memcpy(data, indata, len); aes_ecb_encrypt(data, len, key, sizeof(key)); printf("Ciphertext:\n"); hexdump(data, 16); base64[base64encode(data, len, base64)] = '\0'; printf("base64: %s\n", base64); aes_ecb_decrypt(data, len, key, sizeof(key)); data[len] = '\0'; printf("Decrypted plaintext: %s\n", data); hexdump(data, len); printf("// testing aes-128-cbc\n"); printf("Plaintext:\n"); hexdump(indata, len); memcpy(data, indata, len); aes_cbc_encrypt(data, len, key, sizeof(key), iv); printf("Ciphertext:\n"); hexdump(data, 16); base64[base64encode(data, len, base64)] = '\0'; printf("base64: %s\n", base64); aes_cbc_decrypt(data, len, key, sizeof(key), iv); data[len] = '\0'; printf("Decrypted plaintext: %s\n", data); hexdump(data, len); return 0; }
static void AES_cbc_encrypt(const uint8 *src, uint8 *dst, int len, AES_KEY *ctx, uint8 *iv, int enc) { memcpy(dst, src, len); if (enc) { aes_cbc_encrypt(ctx, iv, dst, len); memcpy(iv, dst + len - 16, 16); } else { aes_cbc_decrypt(ctx, iv, dst, len); memcpy(iv, src + len - 16, 16); } }
char * aes64decrypt(char *base64) { if(setkey == 0) { aes_set_key( &ctx, key, KEYLEN); setkey=1;} unsigned char iv[16]; memcpy(iv,iv_key,16); hb(); printf("%s\n\n",in); len=aes_cbc_decrypt(&ctx,iv,(unsigned char*)in,(unsigned char*)out,len); return out; }
// Must free() returned value char *aes_cbc_b64_decrypt(const unsigned char *in, int inlen, int *decrypt_len, PASSWORD_ID id) { *decrypt_len = 0; if (!in || inlen == 0) { return NULL; } // Unbase64 int ub64len; unsigned char *ub64 = unbase64((char *)in, inlen, &ub64len); if (!ub64 || (ub64len % N_BLOCK) || ub64len < N_BLOCK) { free(ub64); return NULL; } // Set cipher key aes_context ctx[1]; memset(ctx, 0, sizeof(ctx)); aes_set_key(memory_read_aeskey(id), 32, ctx); unsigned char dec_pad[ub64len - N_BLOCK]; aes_cbc_decrypt(ub64 + N_BLOCK, dec_pad, ub64len / N_BLOCK - 1, ub64, ctx); memset(ub64, 0, ub64len); free(ub64); // Strip PKCS7 padding int padlen = dec_pad[ub64len - N_BLOCK - 1]; if (ub64len - N_BLOCK - padlen <= 0) { memset(dec_pad, 0, sizeof(dec_pad)); return NULL; } char *dec = malloc(ub64len - N_BLOCK - padlen + 1); // +1 for null termination if (!dec) { memset(dec_pad, 0, sizeof(dec_pad)); return NULL; } memcpy(dec, dec_pad, ub64len - N_BLOCK - padlen); dec[ub64len - N_BLOCK - padlen] = '\0'; *decrypt_len = ub64len - N_BLOCK - padlen + 1; memset(dec_pad, 0, sizeof(dec_pad)); return dec; }
static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); int err, first, rounds = 6 + ctx->key_length / 4; struct blkcipher_walk walk; unsigned int blocks; desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; blkcipher_walk_init(&walk, dst, src, nbytes); err = blkcipher_walk_virt(desc, &walk); kernel_neon_begin(); for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr, (u8 *)ctx->key_dec, rounds, blocks, walk.iv, first); err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); } kernel_neon_end(); return err; }
QByteArray TinyAES::Decrypt(QByteArray p_input, QByteArray p_key, QByteArray p_iv) { int inputSize = p_input.size(); int keySize = p_key.size(); int ivSize = p_iv.size(); if (keySize != 16 && keySize != 24 && keySize != 32) return QByteArray(); if (ivSize != 16) return QByteArray(); unsigned char *key = new unsigned char[keySize](); QByteArrayToUCharArray(p_key, key); unsigned char *iv = new unsigned char[ivSize](); QByteArrayToUCharArray(p_iv, iv); unsigned char *encrypted = new unsigned char[inputSize](); QByteArrayToUCharArray(p_input, encrypted); unsigned char *decrypted = new unsigned char[inputSize](); // decrypted text aes_context context; aes_set_key(key, keySize * 8, &context); aes_cbc_decrypt(encrypted, decrypted, inputSize, iv, &context); QByteArray result = RemovePadding(UCharArrayToQByteArray(decrypted, inputSize)); delete []key; delete []iv; delete []decrypted; delete []encrypted; return result; }
double _performance_interval (int chunkNum, int chunkSize, int keybit_length, int isParallel) { int i = 0, j = 0; //key {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; UCHAR expandkey_128[BLOCK_SIZE * 11]= { 0x16,0x15,0x7e,0x2b,0xa6,0xd2,0xae,0x28, 0x88,0x15,0xf7,0xab,0x3c,0x4f,0xcf,0x09, 0xa8,0xf9,0x14,0xd0,0x89,0x25,0xee,0xc9, 0xc8,0x0c,0x3f,0xe1,0xa6,0x0c,0x63,0xb6, 0x63,0x5a,0x7b,0x0c,0xfe,0xea,0x19,0x13, 0x90,0x88,0x39,0xb0,0xb4,0xfb,0x4c,0x66, 0x5a,0x92,0x7d,0xdf,0x9d,0xb0,0x62,0x1f, 0x6e,0x62,0x20,0xa3,0x24,0x73,0x75,0xd6, 0x47,0x76,0xc0,0x12,0xc7,0x22,0x1f,0xc0, 0xf3,0xd2,0x42,0xbc,0x4a,0x11,0x55,0x75, 0x76,0xd8,0xfc,0x6e,0x80,0x54,0xdf,0xd2, 0x34,0xf0,0x5d,0x7c,0xb9,0xc3,0x17,0xc9, 0xfc,0x0a,0xa3,0x6e,0xf6,0x8c,0x23,0xbc, 0xb4,0xa4,0x82,0xae,0x8d,0x33,0x4a,0xb5, 0x13,0x44,0x88,0x90,0x0a,0x86,0x80,0xd2, 0x42,0x28,0xa1,0x12,0x39,0x97,0xc8,0x1b, 0xf7,0x13,0x1f,0x7c,0x19,0xc2,0x08,0x42, 0x48,0xae,0x21,0xc0,0x7b,0xbf,0x69,0x09, 0xeb,0x05,0x75,0xcc,0xee,0xd1,0x17,0x3e, 0x51,0x6c,0x29,0x82,0x33,0x11,0x48,0xc9, 0xa7,0x08,0x37,0x2b,0x05,0xd4,0x62,0xf2, 0xbf,0xbd,0x3e,0xbc,0x62,0x7d,0x61,0x4b }; //test_key_192 = {0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,0x62, // 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b}; UCHAR expandkey_192[BLOCK_SIZE * 13]= { 0xf7,0xb0,0x73,0x8e,0x52,0x64,0x0e,0xda,0x2b,0xf3,0x10,0xc8,0xe5,0x79,0x90,0x80, 0x6f,0xa0,0x8b,0xe9,0x3c,0x77,0x8c,0x44,0x04,0x72,0xcc,0x8e,0x02,0x22,0x00,0x01, 0x44,0x16,0x49,0xac,0xb7,0x10,0x57,0xe5,0x75,0x8a,0xc0,0x46,0xad,0x2c,0x9b,0xc8, 0xc2,0x9a,0x97,0xa3,0xd8,0xa6,0x5b,0x8e,0xe6,0xc9,0x2c,0xe1,0xba,0x72,0xb2,0x54, 0x58,0x22,0xb4,0xf3,0x5c,0xbb,0x9e,0xb5,0xfe,0x64,0xfb,0xf8,0xf3,0x06,0x1e,0x49, 0xa2,0xdf,0x65,0x4d,0x0d,0x62,0xe5,0xb1,0x31,0x9c,0x89,0xea,0x1a,0x3c,0xcc,0x2d, 0x3c,0xfe,0x6c,0x5b,0x2b,0xa0,0x45,0xc7,0x72,0xa5,0xb9,0xf8,0x04,0x99,0x2a,0x46, 0xf8,0xb7,0xdd,0xc5,0x76,0x3c,0x93,0xbe,0xa6,0x46,0x4f,0x0b,0xaf,0xbd,0x80,0xfc, 0xd0,0x7a,0xdc,0xb5,0x09,0xfb,0xcf,0xf7,0x93,0x43,0xec,0xa7,0x17,0x5e,0x29,0x9c, 0x9a,0xb8,0x23,0x50,0x84,0x1d,0xc5,0x3b,0x37,0x19,0x4b,0xd0,0x8e,0x8b,0x4e,0x7b, 0x44,0x45,0xb3,0x41,0xb9,0x92,0x05,0xab,0x5e,0xf1,0x92,0xce,0xd9,0x81,0x13,0x42, 0xe7,0x63,0x97,0x65,0x87,0x70,0x81,0x8c,0x43,0x39,0x30,0x12,0x1e,0xa5,0xe6,0x6b, 0xc4,0x49,0xb1,0x9e,0x5d,0x9c,0xd6,0x79,0x7c,0xa2,0xb4,0xfe,0xfd,0xd7,0xb6,0xea }; //char[] test_key_256 = {0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, // 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; UCHAR expandkey_256[BLOCK_SIZE * 15] = { 0x10,0xeb,0x3d,0x60,0xbe,0x71,0xca,0x15,0xf0,0xae,0x73,0x2b,0x81,0x77,0x7d,0x85, 0xd1,0x90,0x48,0xfe,0x0b,0x8d,0x18,0xe6,0x44,0xf3,0x6d,0x04,0x1e,0x63,0x6c,0x70, 0x49,0x3f,0xa2,0xad,0x24,0x3b,0xe2,0x63,0x8a,0x7c,0x42,0x55,0x04,0x91,0x70,0x5c, 0xf6,0x6c,0xc9,0x57,0xc0,0x07,0x4f,0x07,0x07,0xbb,0x6a,0x70,0x41,0x92,0x7f,0x13, 0x21,0xb6,0x68,0xb6,0x6d,0x04,0x40,0xce,0xae,0x47,0xa0,0x36,0x8e,0xed,0x32,0x09, 0x44,0x1e,0xad,0x34,0x36,0x6b,0x86,0x50,0xc7,0xbc,0x25,0x77,0x46,0x29,0x15,0x63, 0x36,0x6c,0x52,0x32,0x4c,0xb2,0x28,0x78,0xc3,0x43,0xe0,0xf8,0x20,0xaa,0x92,0x3f, 0x89,0xb2,0x40,0xc4,0x72,0x75,0x2b,0x64,0xf1,0xd7,0xa3,0x27,0x81,0x95,0x30,0x14, 0x33,0xa7,0x69,0xd6,0x7a,0xde,0x7a,0x4a,0x8f,0xf1,0xc8,0x80,0xe3,0xe9,0x72,0xc7, 0x22,0x3c,0xba,0x25,0xfb,0xc7,0x6b,0xa0,0x83,0xa2,0x88,0x43,0x70,0x42,0x93,0x33, 0x8b,0x80,0xfb,0x54,0x49,0x79,0x13,0x9c,0xf5,0x2f,0xb2,0xca,0x6c,0x18,0xba,0x47, 0x29,0x63,0x3d,0x6c,0xd9,0xfb,0xd1,0x85,0x78,0x65,0xe3,0xe3,0xf3,0xe0,0x1b,0x70, 0xf9,0x59,0x74,0x4a,0xc2,0xf9,0xe8,0xc8,0xbc,0x56,0xa1,0x56,0x99,0x37,0x08,0x8d, 0x58,0x77,0x10,0x42,0xf0,0x98,0xec,0xe9,0xa1,0x9e,0x32,0x66,0x8b,0x85,0xf8,0x93, 0xf6,0xbf,0xc6,0x8e,0x3b,0xa0,0x9c,0x82,0x7e,0xaf,0x49,0x9e,0x25,0x61,0xa9,0xdb }; UCHAR iv[BLOCK_SIZE]= {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; UCHAR** input = NULL; UCHAR** output= NULL; input = (UCHAR**)malloc(sizeof(UCHAR*) * chunkNum); output = (UCHAR**)malloc(sizeof(UCHAR*) * chunkNum); if(input == NULL || output==NULL) return -1; //random initialization time_t t; srand((unsigned) time(&t)); for(i=0; i < chunkNum; i++) { input[i] = (UCHAR*) malloc(sizeof(UCHAR) * chunkSize); output[i] = (UCHAR*) malloc(sizeof(UCHAR) * chunkSize); if(input[i] == NULL) return -1; for (j=0; j < chunkSize; j++) { input[i][j] = (UCHAR) (rand() % 26 + 'a'); } } //benchmark struct timespec start_time, end_time; size_t length = chunkSize; const UCHAR* expandkey = NULL; if(keybit_length == 192) { expandkey = expandkey_192; } else if(keybit_length == 256) { expandkey = expandkey_256; } else { expandkey = expandkey_128; } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time); if(isParallel <= 0){ for(i=0; i < chunkNum; i++) { aes_cbc_decrypt_old(input[i], output[i], expandkey, iv, length, keybit_length); //aes_cbc_decrypt_noparallel(input[i], output[i], expandkey, iv, length); } } else { for(i=0; i < chunkNum; i++) { aes_cbc_decrypt(input[i], output[i], expandkey, iv, length, keybit_length); } } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time); double interval_sec = timediff(start_time.tv_sec, start_time.tv_nsec, end_time.tv_sec, end_time.tv_nsec); printf("%f senconds", interval_sec); //clean: for(i=0; i < chunkNum; i++) { free(input[i]); free(output[i]); } free(input); free(output); return interval_sec; }
OSStatus AES_CBCFrame_Update2( AES_CBCFrame_Context * inContext, const void * inSrc1, size_t inLen1, const void * inSrc2, size_t inLen2, void * inDst ) { const uint8_t * src1 = (const uint8_t *) inSrc1; const uint8_t * end1 = src1 + inLen1; const uint8_t * src2 = (const uint8_t *) inSrc2; const uint8_t * end2 = src2 + inLen2; uint8_t * dst = (uint8_t *) inDst; OSStatus err; size_t len; size_t i; #if( !AES_UTILS_USE_COMMON_CRYPTO ) uint8_t iv[ kAES_CBCFrame_Size ]; #endif #if( AES_UTILS_USE_COMMON_CRYPTO ) if( ( inLen1 + inLen2 ) >= kAES_CBCFrame_Size ) { err = CCCryptorReset( inContext->cryptor, inContext->iv ); require_noerr( err, exit ); } #else memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed. #endif // Process all whole blocks from buffer 1. len = inLen1 & ~( (size_t)( kAES_CBCFrame_Size - 1 ) ); if( len > 0 ) { #if( AES_UTILS_USE_COMMON_CRYPTO ) err = CCCryptorUpdate( inContext->cryptor, src1, len, dst, len, &len ); require_noerr( err, exit ); #elif( AES_UTILS_USE_GLADMAN_AES ) if( inContext->encrypt ) aes_cbc_encrypt( src1, dst, (int) len, iv, &inContext->ctx.encrypt ); else aes_cbc_decrypt( src1, dst, (int) len, iv, &inContext->ctx.decrypt ); #elif( AES_UTILS_USE_USSL ) if( inContext->encrypt ) aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, len, iv, (unsigned char *) src1, dst ); else aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, len, iv, (unsigned char *) src1, dst ); #else AES_cbc_encrypt( src1, dst, (unsigned long) len, &inContext->key, iv, inContext->mode ); #endif src1 += len; dst += len; } // If there are any partial block bytes in buffer 1 and enough bytes in buffer 2 to fill a // block then combine them into a temporary buffer and encrypt it. if( ( src1 != end1 ) && ( ( ( end1 - src1 ) + ( end2 - src2 ) ) >= kAES_CBCFrame_Size ) ) { uint8_t buf[ kAES_CBCFrame_Size ]; for( i = 0; src1 != end1; ++i ) { buf[ i ] = *src1++; } for( ; ( i < kAES_CBCFrame_Size ) && ( src2 != end2 ); ++i ) { buf[ i ] = *src2++; } #if( AES_UTILS_USE_COMMON_CRYPTO ) err = CCCryptorUpdate( inContext->cryptor, buf, i, dst, i, &i ); require_noerr( err, exit ); #elif( AES_UTILS_USE_GLADMAN_AES ) if( inContext->encrypt ) aes_cbc_encrypt( buf, dst, (int) i, iv, &inContext->ctx.encrypt ); else aes_cbc_decrypt( buf, dst, (int) i, iv, &inContext->ctx.decrypt ); #elif( AES_UTILS_USE_USSL ) if( inContext->encrypt ) aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, i, iv, buf, dst ); else aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, i, iv, buf, dst ); #else AES_cbc_encrypt( buf, dst, (unsigned long) i, &inContext->key, iv, inContext->mode ); #endif dst += i; } // Process any remaining whole blocks in buffer 2. len = ( (size_t)( end2 - src2 ) ) & ~( (size_t)( kAES_CBCFrame_Size - 1 ) ); if( len > 0 ) { #if( AES_UTILS_USE_COMMON_CRYPTO ) err = CCCryptorUpdate( inContext->cryptor, src2, len, dst, len, &len ); require_noerr( err, exit ); #elif( AES_UTILS_USE_GLADMAN_AES ) if( inContext->encrypt ) aes_cbc_encrypt( src2, dst, (int) len, iv, &inContext->ctx.encrypt ); else aes_cbc_decrypt( src2, dst, (int) len, iv, &inContext->ctx.decrypt ); #elif( AES_UTILS_USE_USSL ) if( inContext->encrypt ) aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, len, iv, (unsigned char *) src2, dst ); else aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, len, iv, (unsigned char *) src2, dst ); #else AES_cbc_encrypt( src2, dst, (unsigned long) len, &inContext->key, iv, inContext->mode ); #endif src2 += len; dst += len; } // Any remaining bytes are just copied unencrypted. while( src1 != end1 ) *dst++ = *src1++; while( src2 != end2 ) *dst++ = *src2++; err = kNoErr; #if( AES_UTILS_USE_COMMON_CRYPTO ) exit: #endif return( err ); }
// Saves file with specified index and closes file descriptor (if force is 1, // attempts to save data even if file is not yet complete). Returns 0 on // success and -1 on error. int Saverestoredfile(int slot,int force) { int n,success; ushort filecrc; ulong l,length; uchar *bufout,*data,*tempdata,*salt,key[AESKEYLEN],iv[16]; t_fproc *pf; aes_decrypt_ctx ctx[1]; HANDLE hfile; if (slot<0 || slot>=NFILE) return -1; // Invalid index of file descriptor pf=fproc+slot; if (pf->busy==0 || pf->nblock==0) return -1; // Index points to unused descriptor if (pf->ndata!=pf->nblock && force==0) return -1; // Still incomplete data Message("",0); // If data is encrypted, decrypt it to temporary buffer. Decryption in place // is possible, but the whole data would be lost if password is incorrect. if (pf->mode & PBM_ENCRYPTED) { if (pf->datasize & 0x0000000F) { Reporterror("Encrypted data is not aligned"); return -1; }; if (Getpassword()!=0) return -1; // User cancelled decryption tempdata=(uchar *)GlobalAlloc(GMEM_FIXED,pf->datasize); if (tempdata==NULL) { Reporterror("Low memory, can't decrypt data"); return -1; }; n=strlen(password); salt=(uchar *)(pf->name)+32; // hack: put the salt & iv at the end of the name field derive_key((const uchar *)password, n, salt, 16, 524288, key, AESKEYLEN); memset(password,0,sizeof(password)); memset(ctx,0,sizeof(aes_decrypt_ctx)); if(aes_decrypt_key((const uchar *)key,AESKEYLEN,ctx) == EXIT_FAILURE) { memset(key,0,AESKEYLEN); Reporterror("Failed to set decryption key"); return -1; }; memset(key,0,AESKEYLEN); memcpy(iv, salt+16, 16); // the second 16-byte block in 'salt' is the IV if(aes_cbc_decrypt(pf->data,tempdata,pf->datasize,iv,ctx) == EXIT_FAILURE) { Reporterror("Failed to decrypt data"); memset(ctx,0,sizeof(aes_decrypt_ctx)); return -1; }; memset(ctx,0,sizeof(aes_decrypt_ctx)); filecrc=Crc16(tempdata,pf->datasize); if (filecrc!=(ushort)pf->filecrc) { Reporterror("Invalid password, please try again"); GlobalFree((HGLOBAL)tempdata); return -1; } else { GlobalFree((HGLOBAL)pf->data); pf->data=tempdata; pf->mode&=~PBM_ENCRYPTED; }; }; // If data is compressed, unpack it to temporary buffer. if ((pf->mode & PBM_COMPRESSED)==0) { // Data is not compressed. data=pf->data; length=pf->origsize; bufout=NULL; } else { // Data is compressed. Create temporary buffer. if (pf->origsize==0) pf->origsize=pf->datasize*4; // Weak attempt to recover bufout=(uchar *)GlobalAlloc(GMEM_FIXED,pf->origsize); if (bufout==NULL) { Reporterror("Low memory"); return -1; }; // Unpack data. length=pf->origsize; success=BZ2_bzBuffToBuffDecompress((char *)bufout,(uint *)&length, (char *)pf->data,pf->datasize,0,0); if (success!=BZ_OK) { GlobalFree((HGLOBAL)bufout); Reporterror("Unable to unpack data"); return -1; }; data=bufout; }; // Ask user for file name. if (Selectoutfile(pf->name)!=0) { // Cancelled by user if (bufout!=NULL) GlobalFree((HGLOBAL)bufout); return -1; }; // Open file and save data. hfile=CreateFile(outfile,GENERIC_WRITE,0,NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if (hfile==INVALID_HANDLE_VALUE) { if (bufout!=NULL) GlobalFree((HGLOBAL)bufout); Reporterror("Unable to create file"); return -1; }; WriteFile(hfile,data,length,&l,NULL); // Restore old modification date and time. SetFileTime(hfile,&pf->modified,&pf->modified,&pf->modified); // Close file and restore old basic attributes. CloseHandle(hfile); SetFileAttributes(outfile,pf->attributes); if (bufout!=NULL) GlobalFree((HGLOBAL)bufout); if (l!=length) { Reporterror("I/O error"); return -1; }; // Close file descriptor and report success. Closefproc(slot); Message("File saved",0); return 0; };
/* * storage_get_root_node() - Returns root node of device * * INPUT * - node: where to put the node that is found * OUTPUT * true/false whether root node was found */ bool storage_get_root_node(HDNode *node) { // root node is properly cached if(sessionRootNodeCached) { memcpy(node, &sessionRootNode, sizeof(HDNode)); return true; } // if storage has node, decrypt and use it if(shadow_config.storage.has_node) { if(!passphrase_protect()) { return false; } layout_loading(); if(hdnode_from_xprv(shadow_config.storage.node.depth, shadow_config.storage.node.fingerprint, shadow_config.storage.node.child_num, shadow_config.storage.node.chain_code.bytes, shadow_config.storage.node.private_key.bytes, &sessionRootNode) == 0) { return false; } if(shadow_config.storage.has_passphrase_protection && shadow_config.storage.passphrase_protection && strlen(sessionPassphrase)) { // decrypt hd node uint8_t secret[64]; /* Length of salt + 4 bytes are needed as workspace by pbkdf2_hmac_sha512 */ uint8_t salt[strlen(PBKDF2_HMAC_SHA512_SALT) + 4]; memcpy((char *)salt, PBKDF2_HMAC_SHA512_SALT, strlen(PBKDF2_HMAC_SHA512_SALT)); animating_progress_handler(); pbkdf2_hmac_sha512((const uint8_t *)sessionPassphrase, strlen(sessionPassphrase), salt, strlen(PBKDF2_HMAC_SHA512_SALT), BIP39_PBKDF2_ROUNDS, secret, 64, get_root_node_callback); aes_decrypt_ctx ctx; aes_decrypt_key256(secret, &ctx); aes_cbc_decrypt(sessionRootNode.chain_code, sessionRootNode.chain_code, 32, secret + 32, &ctx); aes_cbc_decrypt(sessionRootNode.private_key, sessionRootNode.private_key, 32, secret + 32, &ctx); } memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } // if storage has mnemonic, convert it to node and use it if(shadow_config.storage.has_mnemonic) { if(!passphrase_protect()) { return false; } if(storage_get_root_node_cache(node)) { return true; } layout_loading(); uint8_t seed[64]; animating_progress_handler(); mnemonic_to_seed(shadow_config.storage.mnemonic, sessionPassphrase, seed, get_root_node_callback); // BIP-0039 if(hdnode_from_seed(seed, sizeof(seed), &sessionRootNode) == 0) { return false; } storage_set_root_node_cache(&sessionRootNode); memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } return false; }
Ctrl_status sd_mmc_usb_read_10(uint8_t slot, uint32_t addr, uint16_t nb_sector) { bool b_first_step = true; uint16_t nb_step; #ifdef USE_ENCRYPTION aes_decrypt_ctx aes_ctx[1]; MD5_CTX md5_ctx; unsigned char IV[16]; #endif // USE_ENCRYPTION #ifdef CLEAR_ON_READ if (!sd_mmc_usb_check_sector(addr, nb_sector)) return CTRL_FAIL; #endif // Try to avoid reading if the beginning is "written" #ifdef FAKE_RW for (uint32_t sector = 0; sector < nb_sector; sector++) { bool cached = false; for (uint8_t i = 0; i < NUM_CACHED_SECTORS && i < cached_sector_count; i++) { if (cached_sectors[i].sector == sector) { if (!udi_msc_trans_block(true, cached_sectors[i].contents, SD_MMC_BLOCK_SIZE, NULL)) return CTRL_FAIL; cached = true; addr++; break; } } if (!cached) break; } #endif // FAKE_RW switch (sd_mmc_init_read_blocks(slot, addr, nb_sector)) { case SD_MMC_OK: break; case SD_MMC_ERR_NO_CARD: return CTRL_NO_PRESENT; default: return CTRL_FAIL; } // Pipeline the 2 transfer in order to speed-up the performances nb_step = nb_sector + 1; bool last_cached = false; uint8_t *cached_sector = NULL, *last_cached_sector = NULL; while (nb_step--) { bool cached = false; if (nb_step) { // Skip last step // MCI -> RAM #ifdef FAKE_RW for (uint8_t i = 0; i < NUM_CACHED_SECTORS && i < cached_sector_count; i++) { if (cached_sectors[i].sector == addr + nb_sector - nb_step) { cached_sector = cached_sectors[i].contents; cached = true; //ui_set_errorflag(); break; } } #endif // FAKE_RW if (SD_MMC_OK != sd_mmc_start_read_blocks(((nb_step % 2) == 0) ? sector_buf_0 : sector_buf_1, 1)) { return CTRL_FAIL; } } if (!b_first_step) { // Skip first step #ifdef USE_ENCRYPTION uint32_t sector = addr + nb_sector - nb_step - 1; if (!last_cached) { // Decrypt if (use_user_page_values() && sector >= CRYPT_START) { // We use md5(sector) for the IV, ie a known-constant // Though this is generally a bad idea (see, eg, Google: cryptsetup aes-cbc-plain), // it (luckily) works finehere as we don't enable write. // We work under the assumption that data will either fall in the form // a) public-knowledge (eg a boot partition) or // b) encrypted random data (eg your key and surrounding random crap to mask it). // In the first case, we don't care what you can glean from the ciphertext+plaintext+IV, // in the second, you can't glean anything because its all random data anyway. MD5_Init (&md5_ctx); MD5_Update (&md5_ctx, §or, sizeof(uint32_t)); MD5_Final (IV, &md5_ctx); aes_decrypt_key128(AES_KEY, aes_ctx); aes_cbc_decrypt(((nb_step % 2) == 0) ? sector_buf_1 : sector_buf_0, aes_buf, SD_MMC_BLOCK_SIZE, IV, aes_ctx); } } #endif // USE_ENCRYPTION // RAM -> USB if (!udi_msc_trans_block(true, last_cached ? last_cached_sector : #ifdef USE_ENCRYPTION (use_user_page_values() && sector >= CRYPT_START ? aes_buf : #endif // USE_ENCRYPTION (((nb_step % 2) == 0) ? sector_buf_1 : sector_buf_0)), SD_MMC_BLOCK_SIZE, NULL)) { return CTRL_FAIL; } } else { b_first_step = false; } if (nb_step) { // Skip last step if (SD_MMC_OK != sd_mmc_wait_end_of_read_blocks()) { return CTRL_FAIL; } } b_first_step = false; last_cached = cached; last_cached_sector = cached_sector; } return CTRL_GOOD; }
int verify(){ int i = 0; int errNo = 0; //key {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; char expectedOutput[] = { 0x12,0x29,0xbd,0x07,0xcb,0xa7,0x82,0xa4,0x6c,0x4c,0xb0,0x37,0x49,0x3d,0xbf,0x44, 0x19,0x80,0x66,0xa7,0xa7,0x33,0x8d,0xd0,0x28,0x88,0x5e,0x20,0xfc,0xa0,0xfb,0x60, 0xd2,0x2f,0x85,0x59,0x12,0x42,0xd7,0x22,0xdc,0x83,0x45,0x4f,0x3a,0xfa,0x7d,0xe0, 0x56,0x07,0x03,0xd9,0xe8,0x21,0xe6,0xfe,0x84,0x5c,0x5a,0x49,0x2a,0x61,0xca,0x6b, 0xa4,0xf7,0x1f,0xb0,0x78,0x5d,0x48,0x8c,0xb1,0x71,0x5a,0x83,0xc8,0xa7,0x4f,0x5d, 0x8e,0x19,0xc0,0x51,0x14,0x81,0xca,0xad,0xd5,0x31,0xed,0x1c,0xb4,0xc7,0xf7,0x0a, 0xbb,0xf5,0x82,0xba,0x30,0xda,0x1c,0xd9,0x73,0x27,0x51,0xd2,0xee,0x0a,0x50,0x87, 0xc1,0x37,0x38,0xa3,0x91,0x30,0xe0,0x92,0x5a,0x2a,0x52,0xa8,0x93,0x20,0xa4,0x39, 0xbb,0x26,0x78,0xb0,0x38,0x1a,0x31,0x30,0x2e,0x24,0x3a,0x92,0xca,0x99,0x81,0xb0, 0xad,0xb9,0xf3,0x51,0x6b,0x7e,0x23,0x9f,0x18,0x75,0x5d,0x55,0xf2,0x87,0x8f,0xe0, 0x82,0xa7,0xbc,0x12,0xb9,0x12,0x61,0xc8,0x38,0xe2,0x26,0x5f,0x2a,0x2d,0xb0,0x72, 0x1e,0x51,0xed,0xec,0x9f,0xdd,0xfa,0x4e,0x1c,0x8c,0x91,0xcf,0x5e,0x1c,0xfa,0x54, 0x5a,0xc9,0x95,0xcd,0x0f,0x93,0x6f,0x66,0x18,0xde,0x81,0x9f,0xa0,0x61,0x65,0xfa}; UCHAR expandkey[BLOCK_SIZE * 11]= { 0x16,0x15,0x7e,0x2b,0xa6,0xd2,0xae,0x28, 0x88,0x15,0xf7,0xab,0x3c,0x4f,0xcf,0x09, 0xa8,0xf9,0x14,0xd0,0x89,0x25,0xee,0xc9, 0xc8,0x0c,0x3f,0xe1,0xa6,0x0c,0x63,0xb6, 0x63,0x5a,0x7b,0x0c,0xfe,0xea,0x19,0x13, 0x90,0x88,0x39,0xb0,0xb4,0xfb,0x4c,0x66, 0x5a,0x92,0x7d,0xdf,0x9d,0xb0,0x62,0x1f, 0x6e,0x62,0x20,0xa3,0x24,0x73,0x75,0xd6, 0x47,0x76,0xc0,0x12,0xc7,0x22,0x1f,0xc0, 0xf3,0xd2,0x42,0xbc,0x4a,0x11,0x55,0x75, 0x76,0xd8,0xfc,0x6e,0x80,0x54,0xdf,0xd2, 0x34,0xf0,0x5d,0x7c,0xb9,0xc3,0x17,0xc9, 0xfc,0x0a,0xa3,0x6e,0xf6,0x8c,0x23,0xbc, 0xb4,0xa4,0x82,0xae,0x8d,0x33,0x4a,0xb5, 0x13,0x44,0x88,0x90,0x0a,0x86,0x80,0xd2, 0x42,0x28,0xa1,0x12,0x39,0x97,0xc8,0x1b, 0xf7,0x13,0x1f,0x7c,0x19,0xc2,0x08,0x42, 0x48,0xae,0x21,0xc0,0x7b,0xbf,0x69,0x09, 0xeb,0x05,0x75,0xcc,0xee,0xd1,0x17,0x3e, 0x51,0x6c,0x29,0x82,0x33,0x11,0x48,0xc9, 0xa7,0x08,0x37,0x2b,0x05,0xd4,0x62,0xf2, 0xbf,0xbd,0x3e,0xbc,0x62,0x7d,0x61,0x4b}; UCHAR iv[BLOCK_SIZE]= {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; UCHAR input[BLOCK_SIZE * 13]; UCHAR output[BLOCK_SIZE * 13]; size_t length = BLOCK_SIZE * 13; for (i=0; i < length; i++) { input[i] = (UCHAR) ('a' + i % 26); } UCHAR newIV[BLOCK_SIZE]; for (i = 0; i < BLOCK_SIZE; ++i) { newIV[i] = iv[i]; } int retLen = aes_cbc_decrypt_old(input, output, expandkey, newIV, length, 128); errNo = cmp_array(output, expectedOutput, length); if(!errNo) { printf("(old version) sanity test passed.\n"); } else { printf("(old version) sanity test failed!\n"); return errNo; } for (i = 0; i < BLOCK_SIZE; ++i) { newIV[i] = iv[i]; } aes_cbc_decrypt(input, output, expandkey, newIV, length, 128); errNo = cmp_array(output, expectedOutput, length); if(!errNo) { printf("(new version) sanity test passed.\n"); } else { printf("(new version) sanity test failed!\n"); } return errNo; }
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(); }