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; }
void QAesWrap::initPadding(const QByteArray & in,QByteArray & out,AesMode mode,PaddingMode pad) const { int size = in.size(); int last = size % AES_BLOCK_SIZE; const BYTE * data = (unsigned char *)in.data(); if (last == 0) { out.resize(size); if (mode == AES_ECB) { ecbencrypt(data,size,0,out); } else { aes_encrypt_cbc(data,size,0,(unsigned char *)out.data(),mpass,mbit,msalt); } return; } int blocks = size / AES_BLOCK_SIZE; BYTE datablocks[AES_BLOCK_SIZE] = {0}; memcpy(datablocks,(data + blocks * AES_BLOCK_SIZE),last); uchar ch = uchar(AES_BLOCK_SIZE - last); switch (pad) { case ANSIX923: case PKCS7: { size = blocks * AES_BLOCK_SIZE; out.resize((blocks +1) * AES_BLOCK_SIZE); if (pad == ANSIX923) { memset(&datablocks[last],0,(ch -1)); datablocks[AES_BLOCK_SIZE -1] = ch; } else { memset(&datablocks[last],ch,ch); } if (mode == AES_ECB) { ecbencrypt(data,size,datablocks,out); } else { aes_encrypt_cbc(data,size,datablocks,(unsigned char *)out.data(),mpass,mbit,msalt); } } break; default: { if (blocks <= 0) { out = in; return; } out.resize(size); size = blocks * AES_BLOCK_SIZE; if (mode == AES_ECB) { ecbencrypt(data,size,0,out); } else { aes_encrypt_cbc(data,size,0,(unsigned char *)out.data(),mpass,mbit,msalt); } for (int i = 0,j = size; i < last; ++i, ++j) { out[j] = datablocks[i]; } } break; } }
/* 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_encrypt(const unsigned char *in_blk, unsigned char *out_blk, aes_encrypt_ctx cx[1]) { return aes_encrypt_cbc(in_blk, NULL, 1, out_blk, cx); }
IOReturn IOPolledFileWrite(IOPolledFileIOVars * vars, const uint8_t * bytes, IOByteCount size, IOPolledFileCryptVars * cryptvars) { IOReturn err = kIOReturnSuccess; IOByteCount copy; bool flush = false; do { if (!bytes && !size) { // seek to end of block & flush size = vars->position & (vars->blockSize - 1); if (size) size = vars->blockSize - size; flush = true; // use some garbage for the fill bytes = vars->buffer + vars->bufferOffset; } copy = vars->bufferLimit - vars->bufferOffset; if (copy > size) copy = size; else flush = true; if (bytes) { bcopy(bytes, vars->buffer + vars->bufferHalf + vars->bufferOffset, copy); bytes += copy; } else bzero(vars->buffer + vars->bufferHalf + vars->bufferOffset, copy); size -= copy; vars->bufferOffset += copy; vars->position += copy; if (flush && vars->bufferOffset) { uint64_t offset = (vars->position - vars->bufferOffset - vars->extentPosition + vars->currentExtent->start); uint32_t length = (vars->bufferOffset); #if CRYPTO if (cryptvars && vars->encryptStart && (vars->position > vars->encryptStart) && ((vars->position - length) < vars->encryptEnd)) { AbsoluteTime startTime, endTime; uint64_t encryptLen, encryptStart; encryptLen = vars->position - vars->encryptStart; if (encryptLen > length) encryptLen = length; encryptStart = length - encryptLen; if (vars->position > vars->encryptEnd) encryptLen -= (vars->position - vars->encryptEnd); clock_get_uptime(&startTime); // encrypt the buffer aes_encrypt_cbc(vars->buffer + vars->bufferHalf + encryptStart, &cryptvars->aes_iv[0], encryptLen / AES_BLOCK_SIZE, vars->buffer + vars->bufferHalf + encryptStart, &cryptvars->ctx.encrypt); clock_get_uptime(&endTime); ADD_ABSOLUTETIME(&vars->cryptTime, &endTime); SUB_ABSOLUTETIME(&vars->cryptTime, &startTime); vars->cryptBytes += encryptLen; // save initial vector for following encrypts bcopy(vars->buffer + vars->bufferHalf + encryptStart + encryptLen - AES_BLOCK_SIZE, &cryptvars->aes_iv[0], AES_BLOCK_SIZE); } #endif /* CRYPTO */ err = IOPolledFilePollersIODone(vars->pollers, true); if (kIOReturnSuccess != err) break; if (vars->position & (vars->blockSize - 1)) HIBLOG("misaligned file pos %qx\n", vars->position); //if (length != vars->bufferSize) HIBLOG("short write of %qx ends@ %qx\n", length, offset + length); err = IOStartPolledIO(vars->pollers, kIOPolledWrite, vars->bufferHalf, offset, length); if (kIOReturnSuccess != err) break; vars->pollers->io = true; vars->extentRemaining -= vars->bufferOffset; if (!vars->extentRemaining) { vars->currentExtent++; vars->extentRemaining = vars->currentExtent->length; vars->extentPosition = vars->position; } vars->bufferHalf = vars->bufferHalf ? 0 : vars->bufferSize; vars->bufferOffset = 0; if (vars->bufferSize <= vars->extentRemaining) vars->bufferLimit = vars->bufferSize; else vars->bufferLimit = vars->extentRemaining; if (!vars->extentRemaining) { err = kIOReturnOverrun; break; } flush = false; } } while (size); return (err); }