/* does one encryption or decryption in ECB mode and compare result */ int ccmode_ecb_test_one(const struct ccmode_ecb *ecb, size_t keylen, const void *keydata, unsigned long nblocks, const void *in, const void *out) { unsigned char temp[nblocks*ecb->block_size]; ccecb_ctx_decl(ecb->size, key); ecb->init(ecb, key, keylen, keydata); ecb->ecb(key, nblocks, in, temp); #ifdef _INTERNAL_DEBUG_ { char k[keylen*2+1]; char i[ecb->block_size*nblocks*2+1]; char o[ecb->block_size*nblocks*2+1]; char t[ecb->block_size*nblocks*2+1]; cc_bin2hex(keylen, k, keydata); cc_bin2hex(ecb->block_size*nblocks, i, in); cc_bin2hex(ecb->block_size*nblocks, o, out); cc_bin2hex(ecb->block_size*nblocks, t, temp); fprintf(stderr, "k: %s, i: %s, o:%s, t:%s\n", k, i, o, t); } #endif return memcmp(out, temp, ecb->block_size*nblocks); }
void CCAESCmac(const void *key, const uint8_t *data, size_t dataLength, /* length of data in bytes */ void *macOut) /* MAC written here */ { uint8_t X[16],Y[16], M_last[16], padded[16]; uint8_t K1[16], K2[16]; int flag; size_t n; const struct ccmode_ecb *aesmode = getCipherMode(kCCAlgorithmAES128, kCCModeECB, kCCEncrypt).ecb; ccecb_ctx_decl(aesmode->size, ctx); CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); // CMacInit aesmode->init(aesmode, ctx, 16, key); aesmode->ecb(ctx, 1, Y, X); ccGenAESSubKey(aesmode, ctx, K1, K2); // CMacUpdates (all in this case) n = (dataLength+15) / 16; /* n is number of rounds */ if ( 0 == n ) { n = 1; flag = 0; } else { if ( (dataLength%16) == 0 ) flag = 1; else flag = 0; } if ( flag ) { /* last block is complete block */ xor_128(&data[16*(n-1)],K1,M_last); } else { ccAESCMacPadding(&data[16*(n-1)],padded,dataLength%16); xor_128(padded,K2,M_last); } memset(X, 0, 16); for (size_t i=0; i<n-1; i++ ) { xor_128(X,&data[16*i],Y); /* Y := Mi (+) X */ aesmode->ecb(ctx, 1, Y, X); } // CMacFinal xor_128(X,M_last,Y); aesmode->ecb(ctx, 1, Y, X); memcpy(macOut, X, 16); }
/* Initialize a block of 'nblocks' of zeroes, Does 'loops' consecutive encryption (ECB) in place, then 'loops' decryption (ECB) in place, result should be zeroes. */ int ccmode_ecb_test_key_self(const struct ccmode_ecb *encrypt, const struct ccmode_ecb *decrypt, unsigned long nblocks, size_t keylen, const void *keydata, unsigned long loops) { unsigned char temp[nblocks*encrypt->block_size]; unsigned char zeroes[nblocks*encrypt->block_size]; ccecb_ctx_decl(decrypt->size, dkey); ccecb_ctx_decl(encrypt->size, ekey); cc_zero(nblocks*encrypt->block_size,temp); cc_zero(nblocks*encrypt->block_size,zeroes); encrypt->init(encrypt, ekey, keylen, keydata); decrypt->init(decrypt, dkey, keylen, keydata); for (unsigned long i=0; i<loops; i++) encrypt->ecb(ekey, nblocks, temp, temp); for (unsigned long i=0; i<loops; i++) decrypt->ecb(dkey, nblocks, temp, temp); return memcmp(zeroes, temp, encrypt->block_size*nblocks); }
static double perf_ccecb_init(unsigned long loops, unsigned long size CC_UNUSED, const void *arg) { const struct ccecb_perf_test *test=arg; const struct ccmode_ecb *ecb=test->ecb; size_t keylen=test->keylen; unsigned char keyd[keylen]; cc_zero(keylen,keyd); ccecb_ctx_decl(ecb->size, key); perf_start(); while(loops--) ccecb_init(ecb, key, keylen, keyd); return perf_time(); }
static double perf_ccecb_update(unsigned long loops, unsigned long size, const void *arg) { const struct ccecb_perf_test *test=arg; const struct ccmode_ecb *ecb=test->ecb; size_t keylen=test->keylen; unsigned long nblocks=size/ecb->block_size; unsigned char keyd[keylen]; unsigned char temp[nblocks*ecb->block_size]; cc_zero(keylen,keyd); ccecb_ctx_decl(ecb->size, key); ccecb_init(ecb, key, keylen, keyd); perf_start(); while(loops--) ccecb_update(ecb,key, nblocks, temp, temp); return perf_time(); }
static int df(struct ccdrbg_nistctr_state *drbg, const char *input_string[], uint32_t L[], uint32_t input_string_count, uint8_t *output_string, unsigned long N) { unsigned long j, k, blocks; uint64_t sum_L; uint32_t *temp; uint32_t *X; uint32_t buffer[CCADRBG_TEMPLEN_INTS(drbg)]; /* declare a key */ ccecb_ctx_decl(drbg->ecb->size, key); /* * NIST SP 800-90 March 2007 10.4.2 states that 512 bits is * the maximum length for the approved block cipher algorithms. * * Also states that L(sum_L) and N are 32 bits integers. */ cc_assert(drbg->ecb->block_size<=512/8); uint32_t output_buffer[512 / 8 / sizeof(uint32_t)]; if (N > sizeof(output_buffer) || N < 1) { ccecb_ctx_clear(drbg->ecb->size, key); return -1; } sum_L = 0; for (j = 0; j < input_string_count; ++j) sum_L += L[j]; //sum_L is the sum of the all input data-lengths. Since maximum parameters lengths are set properly //in the header file, sum_L cannot be more than 32 bits. But a change to those parameters by //someone who is not aware of this summation here, would be a disaster. //Therefore, we make sum_L 64 bits and we perform the test here. if(sum_L > 0xFFFFffff) return -1; /* [6] temp = Null string */ temp = buffer; /* [9] while len(temp) < keylen + outlen, do */ for (j = 0; j < CCADRBG_TEMPLEN_BLOCKS(drbg); ++j) { /* [9.2] temp = temp || BCC(K, (IV || S)) */ /* Since we have precomputed BCC(K, IV), we start with that... */ memcpy(&temp[0], &drbg->encryptedIV[j*CCADRBG_OUTLEN(drbg)+0], CCADRBG_OUTLEN(drbg)); /* typecast: ok, checks above */ bcc_init(drbg, (uint32_t)sum_L, (uint32_t)N, temp); /* Compute the rest of BCC(K, (IV || S)) */ for (k = 0; k < input_string_count; ++k) df_bcc_update(drbg, input_string[k], L[k], temp); df_bcc_final(drbg, temp); temp += CCADRBG_OUTLEN_INTS(drbg); } /* [6] temp = Null string */ temp = buffer; /* [10] K = Leftmost keylen bits of temp */ drbg->ecb->init(drbg->ecb, key, CCADRBG_KEYLEN(drbg), &temp[0]); /* [11] X = next outlen bits of temp */ X = &temp[CCADRBG_KEYLEN_INTS(drbg)]; /* [12] temp = Null string */ temp = output_buffer; /* [13] While len(temp) < number_of_bits_to_return, do */ blocks = (N / CCADRBG_OUTLEN(drbg)); if (N & (CCADRBG_OUTLEN(drbg) - 1)) ++blocks; for (j = 0; j < blocks; ++j) { /* [13.1] X = Block_Encrypt(K, X) */ drbg->ecb->ecb(key, 1, X, temp); X = temp; temp += CCADRBG_OUTLEN_INTS(drbg); } /* [14] requested_bits = Leftmost number_of_bits_to_return of temp */ memcpy(output_string, output_buffer, N); ccecb_ctx_clear(drbg->ecb->size, key); cc_clear(sizeof(buffer), buffer); cc_clear(sizeof(output_buffer), output_buffer); return 0; }