int kirk_CMD1(void* outbuff, void* inbuff, int size, int do_check) { if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED; KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff; if(header->mode != KIRK_MODE_CMD1) return KIRK_INVALID_MODE; header_keys keys; //0-15 AES key, 16-31 CMAC key AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)&keys, 16*2); //decrypt AES & CMAC key to temp buffer // HOAX WARRING! I have no idea why the hash check on last IPL block fails, so there is an option to disable checking if(do_check) { int ret = kirk_CMD10(inbuff, size); if(ret != KIRK_OPERATION_SUCCESS) return ret; } AES_ctx k1; AES_set_key(&k1, keys.AES, 128); AES_cbc_decrypt(&k1, inbuff+sizeof(KIRK_CMD1_HEADER)+header->data_offset, outbuff, header->data_size); return KIRK_OPERATION_SUCCESS; }
int aes_cbc_decrypt_update(AES_CTX *c, const uint8 in[16], uint8 out[16]) { if (c == NULL || in == NULL || out == NULL) return -1; AES_cbc_decrypt(in, out, 16, &c->key, c->iv); return 0; }
/** * we are running the algoritm backwards to eliminate the need to remember too much state. */ bool aes128_cbc_decrypt(const uint8_t* key, uint8_t* input, uint16_t input_len) { if (input_len < 16) return false; // the input contains at most the iv. if ((input_len % 16) != 0) return false; // the input_len should be a multiple of the block size. { AES_set_key(&ctx, key, input, AES_MODE_128); input += 16; // iv input_len -= 16; AES_convert_key(&ctx); AES_cbc_decrypt(&ctx, input, input, (int)input_len); } return true; }
int aes_cbc_decrypt_final(AES_CTX *c, const uint8 in[16], uint8 out[16], int *out_len) { if (c == NULL || in == NULL || out == NULL) return -1; AES_cbc_decrypt(in, out, 16, &c->key, c->iv); int padding_len = out[15]; if (padding_len < 1 || padding_len > 16) return -1; if (out_len != NULL) *out_len = 16 - padding_len; return 0; }
int kirk_forge(u8* inbuff, int insize) { KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff; AES_ctx cmac_key; u8 cmac_header_hash[16]; u8 cmac_data_hash[16]; int chk_size; if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED; if(!(header->mode == KIRK_MODE_CMD1 || header->mode == KIRK_MODE_CMD2 || header->mode == KIRK_MODE_CMD3)) return KIRK_INVALID_MODE; if(header->data_size == 0) return KIRK_DATA_SIZE_ZERO; if(header->mode == KIRK_MODE_CMD1){ header_keys keys; //0-15 AES key, 16-31 CMAC key AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)&keys, 32); //decrypt AES & CMAC key to temp buffer AES_set_key(&cmac_key, keys.CMAC, 128); AES_CMAC(&cmac_key, inbuff+0x60, 0x30, cmac_header_hash); if(memcmp(cmac_header_hash, header->CMAC_header_hash, 16) != 0) { return KIRK_HEADER_HASH_INVALID; } //Make sure data is 16 aligned chk_size = header->data_size; if(chk_size % 16) chk_size += 16 - (chk_size % 16); AES_CMAC(&cmac_key, inbuff+0x60, 0x30 + chk_size + header->data_offset, cmac_data_hash); if(memcmp(cmac_data_hash, header->CMAC_data_hash, 16) != 0) { //printf("data hash invalid, correcting...\n"); } else { printf("data hash is already valid!\n"); return 100; } // Forge collision for data hash memcpy(cmac_data_hash,header->CMAC_data_hash,0x10); AES_CMAC_forge(&cmac_key, inbuff+0x60, 0x30+ chk_size + header->data_offset, cmac_data_hash); //printf("Last row in bad file should be :\n"); for(i=0;i<0x10;i++) printf("%02x", cmac_data_hash[i]); //printf("\n\n"); return KIRK_OPERATION_SUCCESS; } return KIRK_SIG_CHECK_INVALID; //Checks for cmd 2 & 3 not included right now }
static void decrypt_payload(void *payload, size_t len, uint8_t encryptkey[16], uint8_t IV[16]){ AES_CTX ctx; int pad = (16 - len%16)% 16; /* blocks must be 16 bytes padded */ len += pad; #ifdef CRYPTO_DEBUG myprintf("Aes_decrypt (%x %d) = ", *(uint32_t *)payload, len); #endif AES_set_key(&ctx, encryptkey, IV, AES_MODE_128); AES_convert_key(&ctx); /* do the encryption in-place to spare memory */ AES_cbc_decrypt(&ctx, payload, payload, len); #ifdef CRYPTO_DEBUG myprintf("%x\n", *(uint32_t *)payload); #endif ZERO(ctx); }
int kirk_CMD10(void* inbuff, int insize) { if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED; KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff; if(!(header->mode == KIRK_MODE_CMD1 || header->mode == KIRK_MODE_CMD2 || header->mode == KIRK_MODE_CMD3)) return KIRK_INVALID_MODE; if(header->data_size == 0) return KIRK_DATA_SIZE_ZERO; if(header->mode == KIRK_MODE_CMD1) { header_keys keys; //0-15 AES key, 16-31 CMAC key AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)&keys, 32); //decrypt AES & CMAC key to temp buffer AES_ctx cmac_key; AES_set_key(&cmac_key, keys.CMAC, 128); u8 cmac_header_hash[16]; u8 cmac_data_hash[16]; AES_CMAC(&cmac_key, inbuff+0x60, 0x30, cmac_header_hash); //Make sure data is 16 aligned int chk_size = header->data_size; if(chk_size % 16) chk_size += 16 - (chk_size % 16); AES_CMAC(&cmac_key, inbuff+0x60, 0x30 + chk_size + header->data_offset, cmac_data_hash); if(memcmp(cmac_header_hash, header->CMAC_header_hash, 16) != 0) { printf("header hash invalid\n"); return KIRK_HEADER_HASH_INVALID; } if(memcmp(cmac_data_hash, header->CMAC_data_hash, 16) != 0) { printf("data hash invalid\n"); return KIRK_DATA_HASH_INVALID; } return KIRK_OPERATION_SUCCESS; } return KIRK_SIG_CHECK_INVALID; //Checks for cmd 2 & 3 not included right now }
int kirk_CMD7(void* outbuff, void* inbuff, int size) { if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED; KIRK_AES128CBC_HEADER *header = (KIRK_AES128CBC_HEADER*)inbuff; if(header->mode != KIRK_MODE_DECRYPT_CBC) return KIRK_INVALID_MODE; if(header->data_size == 0) return KIRK_DATA_SIZE_ZERO; u8* key = kirk_4_7_get_key(header->keyseed); if(key == (u8*)KIRK_INVALID_SIZE) return KIRK_INVALID_SIZE; //Set the key AES_ctx aesKey; AES_set_key(&aesKey, key, 128); AES_cbc_decrypt(&aesKey, inbuff+sizeof(KIRK_AES128CBC_HEADER), outbuff, size); return KIRK_OPERATION_SUCCESS; }
NS_INTERNAL void kr_cipher_decrypt(kr_cs_id cs, void *ctx, const uint8_t *msg, int len, uint8_t *out) { switch (cs) { #if ALLOW_NULL_CIPHERS case TLS_RSA_WITH_NULL_MD5: memmove(out, msg, len); return; #endif case TLS_RSA_WITH_RC4_128_MD5: case TLS_RSA_WITH_RC4_128_SHA: kr_rc4_crypt((kr_rc4_ctx *) ctx, msg, out, len); return; case TLS_RSA_WITH_AES_128_CBC_SHA: case TLS_RSA_WITH_AES_128_CBC_SHA256: AES_cbc_decrypt((AES_CTX *) ctx, msg, out, len); return; } abort(); }
/** * Take a base64 blob of data and decrypt it (using AES) into its * proper ASN.1 form. */ static int pem_decrypt(const char *where, const char *end, const char *password, SSLObjLoader *ssl_obj) { int ret = -1; int is_aes_256 = 0; char *start = NULL; uint8_t iv[IV_SIZE]; int i, pem_size; MD5_CTX md5_ctx; AES_CTX aes_ctx; uint8_t key[32]; /* AES256 size */ if (password == NULL || strlen(password) == 0) { #ifdef CONFIG_SSL_FULL_MODE printf("Error: Need a password for this PEM file\n"); TTY_FLUSH(); #endif goto error; } if ((start = strstr((const char *)where, aes_str[0]))) { /* AES128? */ start += strlen(aes_str[0]); } else if ((start = strstr((const char *)where, aes_str[1]))) { /* AES256? */ is_aes_256 = 1; start += strlen(aes_str[1]); } else { #ifdef CONFIG_SSL_FULL_MODE printf("Error: Unsupported password cipher\n"); TTY_FLUSH(); #endif goto error; } /* convert from hex to binary - assumes uppercase hex */ for (i = 0; i < IV_SIZE; i++) { char c = *start++ - '0'; iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4; c = *start++ - '0'; iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c); } while (*start == '\r' || *start == '\n') start++; /* turn base64 into binary */ pem_size = (int)(end - start); if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0) goto error; /* work out the key */ MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password)); MD5_Update(&md5_ctx, iv, SALT_SIZE); MD5_Final(key, &md5_ctx); if (is_aes_256) { MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, key, MD5_SIZE); MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password)); MD5_Update(&md5_ctx, iv, SALT_SIZE); MD5_Final(&key[MD5_SIZE], &md5_ctx); } /* decrypt using the key/iv */ AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128); AES_convert_key(&aes_ctx); AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len); ret = 0; error: return ret; }
int kirk_decrypt_keys(u8 *keys, void *inbuff) { AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)keys, 16*2); //decrypt AES & CMAC key to temp buffer return 0; }
static int AES_test(BI_CTX *bi_ctx) { AES_CTX aes_key; int res = 1; uint8_t key[TEST1_SIZE]; uint8_t iv[TEST1_SIZE]; { /* Case #1: Encrypting 16 bytes (1 block) using AES-CBC Key : 0x06a9214036b8a15b512e03d534120006 IV : 0x3dafba429d9eb430b422da802c9fac41 Plaintext : "Single block msg" Ciphertext: 0xe353779c1079aeb82708942dbe77181a */ char *in_str = "Single block msg"; uint8_t ct[TEST1_SIZE]; uint8_t enc_data[TEST1_SIZE]; uint8_t dec_data[TEST1_SIZE]; bigint *key_bi = bi_str_import( bi_ctx, "06A9214036B8A15B512E03D534120006"); bigint *iv_bi = bi_str_import( bi_ctx, "3DAFBA429D9EB430B422DA802C9FAC41"); bigint *ct_bi = bi_str_import( bi_ctx, "E353779C1079AEB82708942DBE77181A"); bi_export(bi_ctx, key_bi, key, TEST1_SIZE); bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE); bi_export(bi_ctx, ct_bi, ct, TEST1_SIZE); AES_set_key(&aes_key, key, iv, AES_MODE_128); AES_cbc_encrypt(&aes_key, (const uint8_t *)in_str, enc_data, sizeof(enc_data)); if (memcmp(enc_data, ct, sizeof(ct))) { printf("Error: AES ENCRYPT #1 failed\n"); goto end; } AES_set_key(&aes_key, key, iv, AES_MODE_128); AES_convert_key(&aes_key); AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data)); if (memcmp(dec_data, in_str, sizeof(dec_data))) { printf("Error: AES DECRYPT #1 failed\n"); goto end; } } { /* Case #2: Encrypting 32 bytes (2 blocks) using AES-CBC Key : 0xc286696d887c9aa0611bbb3e2025a45a IV : 0x562e17996d093d28ddb3ba695a2e6f58 Plaintext : 0x000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a 7586602d253cfff91b8266bea6d61ab1 */ uint8_t in_data[TEST2_SIZE]; uint8_t ct[TEST2_SIZE]; uint8_t enc_data[TEST2_SIZE]; uint8_t dec_data[TEST2_SIZE]; bigint *in_bi = bi_str_import(bi_ctx, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); bigint *key_bi = bi_str_import( bi_ctx, "C286696D887C9AA0611BBB3E2025A45A"); bigint *iv_bi = bi_str_import( bi_ctx, "562E17996D093D28DDB3BA695A2E6F58"); bigint *ct_bi = bi_str_import(bi_ctx, "D296CD94C2CCCF8A3A863028B5E1DC0A7586602D253CFFF91B8266BEA6D61AB1"); bi_export(bi_ctx, in_bi, in_data, TEST2_SIZE); bi_export(bi_ctx, key_bi, key, TEST1_SIZE); bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE); bi_export(bi_ctx, ct_bi, ct, TEST2_SIZE); AES_set_key(&aes_key, key, iv, AES_MODE_128); AES_cbc_encrypt(&aes_key, (const uint8_t *)in_data, enc_data, sizeof(enc_data)); if (memcmp(enc_data, ct, sizeof(ct))) { printf("Error: ENCRYPT #2 failed\n"); goto end; } AES_set_key(&aes_key, key, iv, AES_MODE_128); AES_convert_key(&aes_key); AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data)); if (memcmp(dec_data, in_data, sizeof(dec_data))) { printf("Error: DECRYPT #2 failed\n"); goto end; } } res = 0; printf("All AES tests passed\n"); end: return res; }