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; }
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); }
/* * Class: tv_fun_common_crypt_Funcrypt * Method: sha1 * Signature: (Ljava/lang/String;JI)[Ljava/lang/Object; */ JNIEXPORT jbyteArray JNICALL android_native_aes(JNIEnv *env, jclass clazz, jbyteArray jarray, jlong jtimestamp, jint jmode) { //check input data unsigned int len = (unsigned int) ((*env)->GetArrayLength(env, jarray)); if (len <= 0 || len >= MAX_LEN) { return NULL; } unsigned char *data = (unsigned char*) (*env)->GetByteArrayElements(env, jarray, NULL); if (!data) { return NULL; } //计算填充长度,当为加密方式且长度不为16的整数倍时,则填充,与3DES填充类似(DESede/CBC/PKCS5Padding) unsigned int mode = (unsigned int) jmode; unsigned int rest_len = len % AES_BLOCK_SIZE; unsigned int padding_len = ( (ENCRYPT == mode) ? (AES_BLOCK_SIZE - rest_len) : 0); unsigned int src_len = len + padding_len; //设置输入 unsigned char *input = (unsigned char *) malloc(src_len); memset(input, 0, src_len); memcpy(input, data, len); if (padding_len > 0) { memset(input + len, (unsigned char) padding_len, padding_len); } //data不再使用 (*env)->ReleaseByteArrayElements(env, jarray, data, 0); //设置输出Buffer unsigned char * buff = (unsigned char*) malloc(src_len); if (!buff) { free(input); return NULL; } memset(buff, src_len, 0); //set key & iv unsigned int key_schedule[AES_BLOCK_SIZE * 4] = { 0 }; //>=53(这里取64) aes_key_setup(AES_KEY, key_schedule, AES_KEY_SIZE); //执行加解密计算(CBC mode) if (mode == ENCRYPT) { aes_encrypt_cbc(input, src_len, buff, key_schedule, AES_KEY_SIZE, AES_IV); } else { aes_decrypt_cbc(input, src_len, buff, key_schedule, AES_KEY_SIZE, AES_IV); } //解密时计算填充长度 if (ENCRYPT != mode) { unsigned char * ptr = buff; ptr += (src_len - 1); padding_len = (unsigned int) *ptr; if (padding_len > 0 && padding_len <= AES_BLOCK_SIZE) { src_len -= padding_len; } ptr = NULL; } //设置返回变量 jbyteArray bytes = (*env)->NewByteArray(env, src_len); (*env)->SetByteArrayRegion(env, bytes, 0, src_len, (jbyte*) buff); //内存释放 free(input); free(buff); return bytes; }
/* This does one block of ECB, using the CBC implementation - this allow to use the same context for both CBC and ECB */ aes_rval aes_decrypt(const unsigned char *in_blk, unsigned char *out_blk, aes_decrypt_ctx cx[1]) { return aes_decrypt_cbc(in_blk, NULL, 1, out_blk, cx); }
bool QAesWrap::decrypt(const QByteArray & in, QByteArray & out, AesMode mode,PaddingMode pad) const { if (in.isEmpty()) return false; out.clear(); int size = in.size(); out.resize(size); if (mode == AES_CTR) { aes_encrypt_ctr((unsigned char *)in.data(),size,(unsigned char *)out.data(),mpass,mbit,msalt); return true; } int last = size % AES_BLOCK_SIZE; int blocks = size / AES_BLOCK_SIZE; int useSize = blocks * AES_BLOCK_SIZE; if (blocks == 0 ) { out = in; return false; } QByteArray tdata; if (last > 0) { if(pad == ANSIX923 || pad == PKCS7) { out.clear(); return false; } tdata = in.right(last); } switch (mode) { case AES_ECB: ecbdecrypt((unsigned char *)in.data(),useSize,out); break; case AES_CBC: aes_decrypt_cbc((unsigned char *)in.data(),useSize,(unsigned char *)out.data(),mpass,mbit,msalt); break; default: return false; } if (last > 0) { for (int i = useSize, j = 0; i < size; ++i,++j) { out[i] = tdata.at(j); } } else { char ch = out.at(size-1); if (ch < 16) { //验证是否需要移除。 int removed = 0; int tsize = size - ch; bool isPad = true; if (pad == ANSIX923) { int mysize = size - 1; char tch; for (int i = tsize; i < mysize; ++i) { tch = out.at(i); if (tch != char(0x00)) { isPad = false; } } if (isPad) removed = ch; } else { char tch; for (int i = tsize; i < size; ++i) { tch = out.at(i); if (tch != ch) { isPad = false; } } if (isPad) removed = ch; } if (removed > 0) { out.remove(size - removed,removed); } } } return true; }
IOReturn IOPolledFileRead(IOPolledFileIOVars * vars, uint8_t * bytes, IOByteCount size, IOPolledFileCryptVars * cryptvars) { IOReturn err = kIOReturnSuccess; IOByteCount copy; // bytesWritten += size; do { copy = vars->bufferLimit - vars->bufferOffset; if (copy > size) copy = size; if (bytes) { bcopy(vars->buffer + vars->bufferHalf + vars->bufferOffset, bytes, copy); bytes += copy; } size -= copy; vars->bufferOffset += copy; // vars->position += copy; if ((vars->bufferOffset == vars->bufferLimit) && (vars->position < vars->readEnd)) { if (!vars->pollers->io) cryptvars = 0; err = IOPolledFilePollersIODone(vars->pollers, true); if (kIOReturnSuccess != err) break; if (vars->position & (vars->blockSize - 1)) HIBLOG("misaligned file pos %qx\n", vars->position); vars->position += vars->lastRead; vars->extentRemaining -= vars->lastRead; vars->bufferLimit = vars->lastRead; if (!vars->extentRemaining) { vars->currentExtent++; vars->extentRemaining = vars->currentExtent->length; vars->extentPosition = vars->position; if (!vars->extentRemaining) { err = kIOReturnOverrun; break; } } uint64_t length; uint64_t lastReadLength = vars->lastRead; uint64_t offset = (vars->position - vars->extentPosition + vars->currentExtent->start); if (vars->extentRemaining <= vars->bufferSize) length = vars->extentRemaining; else length = vars->bufferSize; if ((length + vars->position) > vars->readEnd) length = vars->readEnd - vars->position; vars->lastRead = length; if (length) { //if (length != vars->bufferSize) HIBLOG("short read of %qx ends@ %qx\n", length, offset + length); err = IOStartPolledIO(vars->pollers, kIOPolledRead, vars->bufferHalf, offset, length); if (kIOReturnSuccess != err) break; vars->pollers->io = true; } vars->bufferHalf = vars->bufferHalf ? 0 : vars->bufferSize; vars->bufferOffset = 0; #if CRYPTO if (cryptvars) { uint8_t thisVector[AES_BLOCK_SIZE]; AbsoluteTime startTime, endTime; // save initial vector for following decrypts bcopy(&cryptvars->aes_iv[0], &thisVector[0], AES_BLOCK_SIZE); bcopy(vars->buffer + vars->bufferHalf + lastReadLength - AES_BLOCK_SIZE, &cryptvars->aes_iv[0], AES_BLOCK_SIZE); // decrypt the buffer clock_get_uptime(&startTime); aes_decrypt_cbc(vars->buffer + vars->bufferHalf, &thisVector[0], lastReadLength / AES_BLOCK_SIZE, vars->buffer + vars->bufferHalf, &cryptvars->ctx.decrypt); clock_get_uptime(&endTime); ADD_ABSOLUTETIME(&vars->cryptTime, &endTime); SUB_ABSOLUTETIME(&vars->cryptTime, &startTime); vars->cryptBytes += lastReadLength; } #endif /* CRYPTO */ } } while (size); return (err); }