aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1]) { switch(key_len) { #ifdef AES_ERR_CHK case 16: case 128: return aes_decrypt_key128(in_key, cx); case 24: case 192: return aes_decrypt_key192(in_key, cx); case 32: case 256: return aes_decrypt_key256(in_key, cx); default: return aes_error; #else case 16: case 128: aes_decrypt_key128(in_key, cx); return; case 24: case 192: aes_decrypt_key192(in_key, cx); return; case 32: case 256: aes_decrypt_key256(in_key, cx); return; #endif } }
aes_rval aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) { switch(key_len) { #if defined( AES_ERR_CHK ) case 16: case 128: return aes_decrypt_key128(key, cx); case 24: case 192: return aes_decrypt_key192(key, cx); case 32: case 256: return aes_decrypt_key256(key, cx); default: return aes_error; #else case 16: case 128: aes_decrypt_key128(key, cx); return; case 24: case 192: aes_decrypt_key192(key, cx); return; case 32: case 256: aes_decrypt_key256(key, cx); return; #endif } }
OSStatus AES_CBCFrame_Init( AES_CBCFrame_Context * inContext, const uint8_t inKey[ kAES_CBCFrame_Size ], const uint8_t inIV[ kAES_CBCFrame_Size ], Boolean inEncrypt ) { #if( AES_UTILS_USE_COMMON_CRYPTO ) OSStatus err; inContext->cryptor = NULL; err = CCCryptorCreate( inEncrypt ? kCCEncrypt : kCCDecrypt, kCCAlgorithmAES128, 0, inKey, kAES_CTR_Size, NULL, &inContext->cryptor ); check_noerr( err ); if( err ) return( err ); #elif( AES_UTILS_USE_GLADMAN_AES ) aes_init(); if( inEncrypt ) aes_encrypt_key128( inKey, &inContext->ctx.encrypt ); else aes_decrypt_key128( inKey, &inContext->ctx.decrypt ); inContext->encrypt = inEncrypt; #elif( AES_UTILS_USE_USSL ) if( inEncrypt ) aes_setkey_enc( &inContext->ctx, (unsigned char *) inKey, kAES_CBCFrame_Size * 8 ); else aes_setkey_dec( &inContext->ctx, (unsigned char *) inKey, kAES_CBCFrame_Size * 8 ); inContext->encrypt = inEncrypt; #else if( inEncrypt ) AES_set_encrypt_key( inKey, kAES_CBCFrame_Size * 8, &inContext->key ); else AES_set_decrypt_key( inKey, kAES_CBCFrame_Size * 8, &inContext->key ); inContext->mode = inEncrypt ? AES_ENCRYPT : AES_DECRYPT; #endif memcpy( inContext->iv, inIV, kAES_CBCFrame_Size ); return( kNoErr ); }
static void aes128_cbc_decrypt_init(aes_decrypt_ctx *cx, uint8_t *mac, const uint8_t *key, const uint8_t *iv) { if (iv != NULL) memcpy(mac, iv, 16); else memset(mac, 0, 16); aes_decrypt_key128(key, cx); }
AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) { switch(key_len) { case 16: case 128: return aes_decrypt_key128(key, cx); case 24: case 192: return aes_decrypt_key192(key, cx); case 32: case 256: return aes_decrypt_key256(key, cx); default: return EXIT_FAILURE; } }
/* * Expand the cipher key into the decryption key schedule. * * Return the number of rounds for the given cipher key size. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4 * (Nr + 1). * * Parameters: * rk AES key schedule 32-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ int rijndael_key_setup_dec_amd64(uint32_t rk[], const uint32_t cipherKey[], int keyBits) { switch (keyBits) { case 128: aes_decrypt_key128((unsigned char *)&cipherKey[0], rk); return (10); case 192: aes_decrypt_key192((unsigned char *)&cipherKey[0], rk); return (12); case 256: aes_decrypt_key256((unsigned char *)&cipherKey[0], rk); return (14); default: /* should never get here */ break; } return (0); }
static bool aes_operation(bool encrypt, const uint8_t *kek, size_t kek_len, uint8_t *block) { uint64_t iv[2] = { 0 }; if (encrypt) { aes_encrypt_ctx encrypt_ctx[1]; switch(kek_len) { #if AES128_KEK case 16: aes_encrypt_key128(kek, encrypt_ctx); break; #endif #if AES192_KEK case 24: aes_encrypt_key192(kek, encrypt_ctx); break; #endif #if AES256_KEK case 32: aes_encrypt_key256(kek, encrypt_ctx); break; #endif default: return false; } aes_encrypt_cbc(block, (uint8_t*)iv, 1, block, encrypt_ctx); } else { aes_decrypt_ctx decrypt_ctx[1]; switch(kek_len) { #if AES128_KEK case 16: aes_decrypt_key128(kek, decrypt_ctx); break; #endif #if AES192_KEK case 24: aes_decrypt_key192(kek, decrypt_ctx); break; #endif #if AES256_KEK case 32: aes_decrypt_key256(kek, decrypt_ctx); break; #endif default: return false; } aes_decrypt_cbc(block, (uint8_t*)iv, 1, block, decrypt_ctx); } return true; }
OSStatus AES_ECB_Init( AES_ECB_Context *inContext, uint32_t inMode, const uint8_t inKey[ kAES_ECB_Size ] ) { #if( AES_UTILS_USE_COMMON_CRYPTO ) OSStatus err; inContext->cryptor = NULL; err = CCCryptorCreate( inMode, kCCAlgorithmAES128, kCCOptionECBMode, inKey, kAES_ECB_Size, NULL, &inContext->cryptor ); check_noerr( err ); if( err ) return( err ); #elif( AES_UTILS_USE_GLADMAN_AES ) aes_init(); if( inMode == kAES_ECB_Mode_Encrypt ) aes_encrypt_key128( inKey, &inContext->ctx.encrypt ); else aes_decrypt_key128( inKey, &inContext->ctx.decrypt ); inContext->encrypt = inMode; #elif( AES_UTILS_USE_USSL ) if( inMode == kAES_ECB_Mode_Encrypt ) aes_setkey_enc( &inContext->ctx, (unsigned char *) inKey, kAES_ECB_Size * 8 ); else aes_setkey_dec( &inContext->ctx, (unsigned char *) inKey, kAES_ECB_Size * 8 ); inContext->mode = inMode; #else AES_set_encrypt_key( inKey, kAES_ECB_Size * 8, &inContext->key ); inContext->cryptFunc = ( inMode == kAES_ECB_Mode_Encrypt ) ? AES_encrypt : AES_decrypt; #endif return( kNoErr ); }
main(int argc, char **argv) { char *plain; char *cipher; char *decrypt; uint32_t ITERATIONS; uint32_t NUM_BLOCKS; uint32_t data_size; char key[32]; char iv[16]; int checksum=0; int i, j, iterations; uint64_t t0, t1, t2, sum=0, max_time=0, min_time=-1, sum1=0, max_time1=0, min_time1=-1; float time, time_max, time_min, time1, time_max1, time_min1; cpu_freq = getFreq(); if (cpu_freq == 0) { fprintf(stderr, "this appears to be an iPhone device, where cpu_freq can not be detected. set to 800MHz.\n"); cpu_freq = 800000000; } else { fprintf(stderr, "device max CPU clock rate = %.2f MHz\n", cpu_freq/1.e6); } mach_timebase_info_data_t info; kern_return_t err = mach_timebase_info( &info ); if (argc!=3) { fprintf(stderr, "usage : %s iterations num_16bytes_block\n", argv[0]); exit(1); } ITERATIONS = atoi(argv[1]); NUM_BLOCKS = atoi(argv[2]); data_size = 16*NUM_BLOCKS; plain = malloc(data_size); cipher = malloc(data_size); decrypt = malloc(data_size); if ((plain==NULL) || (cipher==NULL) || (decrypt==NULL)) { fprintf(stderr,"malloc error.\n"); exit(1); } for (i=0;i<data_size;i++) plain[i] = random(); for (i=0;i<32;i++) key[i] = random(); for (i=0;i<16;i++) iv[i] = random(); aes_encrypt_key128(key, &encrypt_ctx); aes_decrypt_key128(key, &decrypt_ctx); for (iterations=0;iterations<ITERATIONS;iterations++) { t0 = mach_absolute_time(); // encrypt aes_encrypt_cbc(plain, iv, NUM_BLOCKS, cipher, &encrypt_ctx); t1 = mach_absolute_time(); // decrypt aes_decrypt_cbc(cipher, iv, NUM_BLOCKS, decrypt, &decrypt_ctx); t2 = mach_absolute_time(); for (i=0;i<(16*NUM_BLOCKS);i++) if (plain[i]!=decrypt[i]) { fprintf(stderr,"error : decrypt != plain. i = %d\n", i); exit(1); } sum += (t1-t0); sum1 += (t2-t1); t2-=t1; t1-=t0; if (t1>max_time) max_time = t1; if (t1<min_time) min_time = t1; if (t2>max_time1) max_time1 = t2; if (t2<min_time1) min_time1 = t2; } time = sum * 1e-9* ((double) info.numer)/((double) info.denom); time_max = max_time * 1e-9* ((double) info.numer)/((double) info.denom); time_min = min_time * 1e-9* ((double) info.numer)/((double) info.denom); time1 = sum1 * 1e-9* ((double) info.numer)/((double) info.denom); time_max1 = max_time1 * 1e-9* ((double) info.numer)/((double) info.denom); time_min1 = min_time1 * 1e-9* ((double) info.numer)/((double) info.denom); printf("%d bytes per cbc call\n", data_size); printf(" aes_encrypt_cbc : time elapsed = %8.2f usecs, %7.2f MBytes/sec, %8.2f cycles/byte\n", 1.e6*time/ITERATIONS,data_size*ITERATIONS/1024./1024./time, time*1.*cpu_freq/ITERATIONS/data_size); printf(" best iteration : time elapsed = %8.2f usecs, %7.2f MBytes/sec, %8.2f cycles/byte\n", 1.e6*time_min,data_size/1024./1024./time_min, time_min*1.*cpu_freq/data_size); printf(" worst iteration : time elapsed = %8.2f usecs, %7.2f MBytes/sec, %8.2f cycles/byte\n", 1.e6*time_max,data_size/1024./1024./time_max, time_max*1.*cpu_freq/data_size); printf("\n"); printf(" aes_decrypt_cbc : time elapsed = %8.2f usecs, %7.2f MBytes/sec, %8.2f cycles/byte\n", 1.e6*time1/ITERATIONS,data_size*ITERATIONS/1024./1024./time1, time1*1.*cpu_freq/ITERATIONS/data_size); printf(" best iteration : time elapsed = %8.2f usecs, %7.2f MBytes/sec, %8.2f cycles/byte\n", 1.e6*time_min1,data_size/1024./1024./time_min1, time_min1*1.*cpu_freq/data_size); printf(" worst iteration : time elapsed = %8.2f usecs, %7.2f MBytes/sec, %8.2f cycles/byte\n", 1.e6*time_max1,data_size/1024./1024./time_max1, time_max1*1.*cpu_freq/data_size); free(plain); free(cipher); free(decrypt); }
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; }