/* Test one test vector, with unaligned data */ int ccmode_cbc_test_one_vector_unaligned(const struct ccmode_cbc *cbc, const struct ccmode_cbc_vector *v, int dec) { uint8_t pt[v->nblocks*cbc->block_size+1]; uint8_t ct[v->nblocks*cbc->block_size+1]; CC_MEMCPY(pt+1, v->pt, v->nblocks*cbc->block_size); CC_MEMCPY(ct+1, v->ct, v->nblocks*cbc->block_size); if (dec) return ccmode_cbc_test_one(cbc, v->keylen, v->key, v->iv, v->nblocks, ct+1, v->pt); else return ccmode_cbc_test_one(cbc, v->keylen, v->key, v->iv, v->nblocks, pt+1, v->ct); }
static void cmp_secure_functionalTests(void) { #define ARRAY_SIZE 10 // --- Bytes uint8_t array1[ARRAY_SIZE]={1,2,3,4,5,6,7,8,9,0}; uint8_t array2[ARRAY_SIZE]; CC_MEMCPY(array2,array1,sizeof(array1)); // Equal ok(cc_cmp_safe(sizeof(array1), array1,array2)==0, "array1 to array2"); ok(cc_cmp_safe(sizeof(array1), array2,array1)==0, "array2 to array1"); // length is zero ok(cc_cmp_safe(0, array2,array1)!=0, "Array of size 0"); // Equal but first byte array1[0]++; ok(cc_cmp_safe(sizeof(array1), array1,array2)!=0, "first byte"); array1[0]--; // Equal but last byte array1[sizeof(array1)-1]++; ok(cc_cmp_safe(sizeof(array1), array1,array2)!=0, "last byte"); array1[sizeof(array1)-1]--; // --- cc_units uint64_t u64_array1[ARRAY_SIZE]={}; for (size_t i=0;i<ARRAY_SIZE;i++) u64_array1[i]=i; uint64_t u64_array2[ARRAY_SIZE]; uint64_t tmp; CC_MEMCPY(u64_array2,u64_array1,sizeof(u64_array1)); // Equal ok(cc_cmp_safe(sizeof(u64_array1), u64_array1,u64_array2)==0, "array1 to array2"); ok(cc_cmp_safe(sizeof(u64_array1), u64_array2,u64_array1)==0, "array2 to array1"); // length is zero ok(cc_cmp_safe(0, u64_array2,u64_array1)!=0, "Array of size 0"); // Equal but first byte ((uint8_t *)u64_array1)[0]++; ok(cc_cmp_safe(sizeof(u64_array1),u64_array1,u64_array2)!=0, "first byte"); ((uint8_t *)u64_array1)[0]--; // Equal but last byte CC_LOAD64_BE(tmp,&u64_array1[ARRAY_SIZE-1]); CC_STORE64_BE(tmp^0x80,&u64_array1[ARRAY_SIZE-1]); ok(cc_cmp_safe(sizeof(u64_array1), u64_array1,u64_array2)!=0, "last byte"); CC_STORE64_BE(tmp,&u64_array1[ARRAY_SIZE-1]); }
void ccdigest_update(const struct ccdigest_info *di, ccdigest_ctx_t ctx, unsigned long len, const void *data) { const char * data_ptr = data; while (len > 0) { if (ccdigest_num(di, ctx) == 0 && len > di->block_size) { unsigned long nblocks = len / di->block_size; di->compress(ccdigest_state(di, ctx), nblocks, data_ptr); unsigned long nbytes = nblocks * di->block_size; len -= nbytes; data_ptr += nbytes; ccdigest_nbits(di, ctx) += nbytes * 8; } else { unsigned long n = di->block_size - ccdigest_num(di, ctx); if (len < n) n = len; CC_MEMCPY(ccdigest_data(di, ctx) + ccdigest_num(di, ctx), data_ptr, n); /* typecast: less than block size, will always fit into an int */ ccdigest_num(di, ctx) += (unsigned int)n; len -= n; data_ptr += n; if (ccdigest_num(di, ctx) == di->block_size) { di->compress(ccdigest_state(di, ctx), 1, ccdigest_data(di, ctx)); ccdigest_nbits(di, ctx) += ccdigest_num(di, ctx) * 8; ccdigest_num(di, ctx) = 0; } } } }
int ccmode_ctr_setctr(CC_UNUSED const struct ccmode_ctr *mode, ccctr_ctx *ctx, const void *ctr) { CCMODE_CTR_KEY_PAD_OFFSET(ctx) = CCMODE_CTR_KEY_ECB(ctx)->block_size; CC_MEMCPY(CCMODE_CTR_KEY_CTR(ctx), ctr, CCMODE_CTR_KEY_ECB(ctx)->block_size); return 0; }
static int generate(struct ccdrbg_state *drbg, size_t dataOutLength, void *dataOut, size_t additionalLength, const void *additional) { struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg; const struct ccdrbg_nisthmac_custom *custom = state->custom; const struct ccdigest_info *di = custom->di; int rc = validate_gen_params(state->reseed_counter, dataOutLength, additional==NULL?0:additionalLength); if(rc!=CCDRBG_STATUS_OK) return rc; // 2. If additional_input ≠ Null, then (Key, V) = HMAC_DRBG_Update (additional_input, Key, V). if (additional && additionalLength) hmac_dbrg_update(drbg, additionalLength, additional, 0, NULL, 0, NULL); // hmac_dbrg_generate_algorithm char *outPtr = (char *) dataOut; while (dataOutLength > 0) { if (!state->bytesLeft) { // 5. V=HMAC(K,V). cchmac(di, state->keysize, state->key, state->vsize, state->nextvptr, state->vptr); // Won't be returned // FIPS 140-2 4.9.2 Conditional Tests // "Each subsequent generation of an n-bit block shall be compared with the previously generated block. The test shall fail if any two compared n-bit blocks are equal." if (0==cc_cmp_safe(state->vsize, state->vptr, state->nextvptr)) { //The world as we know it has come to an end //the DRBG data structure is zeroized. subsequent calls to //DRBG ends up in NULL dereferencing and/or unpredictable state. //catastrophic error in SP 800-90A done(drbg); rc=CCDRBG_STATUS_ABORT; cc_abort(NULL); goto errOut; } CC_SWAP(state->nextvptr, state->vptr); state->bytesLeft = state->vsize; #if DRBG_NISTHMAC_DEBUG cc_print("generate blk: ", state->vsize, state->vptr); #endif } size_t outLength = dataOutLength > state->bytesLeft ? state->bytesLeft : dataOutLength; CC_MEMCPY(outPtr, state->vptr, outLength); state->bytesLeft -= outLength; outPtr += outLength; dataOutLength -= outLength; } // 6. (Key, V) = HMAC_DRBG_Update (additional_input, Key, V). hmac_dbrg_update(drbg, additionalLength, additional, 0, NULL, 0, NULL); // 7. reseed_counter = reseed_counter + 1. state->reseed_counter++; #if DRBG_NISTHMAC_DEBUG dumpState("generate end: ", state); cc_print("generate end nxt: ", state->vsize, state->nextvptr); #endif rc=CCDRBG_STATUS_OK; errOut: return rc; }
/* * NIST SP 800-90 March 2007 * 10.2.1.4.2 The Process Steps for Reseeding When a Derivation * Function is Used */ static int reseed(struct ccdrbg_state *rng, unsigned long entropyLength, const void *entropy, unsigned long additionalLength, const void *additional) { int err; uint32_t count; const char *input_string[2]; uint32_t length[2]; struct ccdrbg_nistctr_state *drbg=(struct ccdrbg_nistctr_state *)rng; uint32_t seed_material[CCADRBG_SEEDLEN_INTS(drbg)]; err =validate_inputs(drbg, entropyLength, additionalLength, 0); if(err!=CCDRBG_STATUS_OK) return err; if(drbg->use_df) { /* [1] seed_material = entropy || additional */ input_string[0] = entropy; /* typecast: guaranteed to fit by the above checks */ length[0] = (uint32_t)entropyLength; count = 1; if (additional && additionalLength) { input_string[count] = additional; /* typecast: guaranteed to fit by above checks */ length[count] = (uint32_t)additionalLength; ++count; } /* [2] seed_material = Block_Cipher_df(seed_material, seedlen) */ err = df(drbg, input_string, length, count, (uint8_t *)seed_material, sizeof(seed_material)); if (err) return err; } else { cc_clear(sizeof(seed_material),seed_material); cc_assert(additionalLength==0 || additionalLength==sizeof(seed_material)); //additionalLength is validated above CC_MEMCPY(seed_material, additional, additionalLength); cc_xor(CCADRBG_SEEDLEN(drbg), seed_material, seed_material, entropy); } /* [3] (Key, V) = Update(seed_material, Key, V) */ if (drbg_update(drbg, seed_material)) { return CCDRBG_STATUS_PARAM_ERROR; } /* [4] reseed_counter = 1 */ drbg->reseed_counter = 1; return CCDRBG_STATUS_OK; }
void ccpad_xts_decrypt(const struct ccmode_xts *xts, ccxts_ctx *key, ccxts_tweak *tweak, size_t nbytes, const void *in, void *out) { const unsigned char *cipher = in; unsigned char *plain = out; size_t tail = nbytes & 15; size_t head = nbytes - tail; if (tail) { cc_unit *T; T=xts->xts(key, tweak, (head >> 4) - 1, cipher, plain); uint8_t ctemp[16], ptemp[16]; /* Store current blocks tweak in ctemp, and advance tweak in context to next block. */ CC_MEMCPY(ctemp, T, 16); ccmode_xts_mult_alpha(T); cipher += head - 16; plain += head - 16; /* ptemp = tweak decrypt block m-1 */ xts->xts(key, tweak, 1, cipher, ptemp); /* Reset tweak in the context to the previous blocks tweak we stored. */ CC_MEMCPY(T, ctemp, 16); /* Pm = first ptlen % 16 bytes of PP */ size_t x; for (x = 0; x < tail; ++x) { ctemp[x] = cipher[16 + x]; plain[16 + x] = ptemp[x]; } for (; x < 16; ++x) { ctemp[x] = ptemp[x]; } /* Pm-1 = Tweak decrypt ctemp */ xts->xts(key, tweak, 1, ctemp, plain); } else {
struct ccperf_family *ccperf_family_cccmac(int argc, char *argv[]) { ccmode_factory_cbc_encrypt(&ccaes_generic_ltc_cbc_encrypt_mode, &ccaes_ltc_ecb_encrypt_mode); #ifdef CCAES_MUX_TEST CC_MEMCPY(&ccaes_mux_cbc_encrypt_mode, ccaes_ios_mux_cbc_encrypt_mode(), sizeof(struct ccmode_cbc)); #endif #if CCAES_INTEL if (CC_HAS_AESNI()) { CC_MEMCPY(&ccaes_intel_cbc_encrypt_mode, &ccaes_intel_cbc_encrypt_aesni_mode, sizeof(struct ccmode_cbc)); } else { CC_MEMCPY(&ccaes_intel_cbc_encrypt_mode, &ccaes_intel_cbc_encrypt_opt_mode, sizeof(struct ccmode_cbc)); } #endif F_GET_ALL(family, cccmac); F_SIZES(family, 6, 1024); family.size_kind=ccperf_size_bytes; return &family; }
void ccmode_cfb_init(const struct ccmode_cfb *cfb, cccfb_ctx *key, size_t rawkey_len, const void *rawkey, const void *iv) { /* tricky: the CMODE_CFB_KEY_IV macros require key->ecb to be set */ const struct ccmode_ecb *ecb = cfb->custom; CCMODE_CFB_KEY_ECB(key) = ecb; cc_unit *ivbuf = CCMODE_CFB_KEY_IV(key); if (iv) CC_MEMCPY(ivbuf, iv, ecb->block_size); else cc_zero(ecb->block_size, ivbuf); ecb->init(ecb, CCMODE_CFB_KEY_ECB_KEY(key), rawkey_len, rawkey); CCMODE_CFB_KEY_PAD_LEN(key) = ecb->block_size; // ecb->ecb(CCMODE_CFB_KEY_ECB_KEY(key), 1, iv, ivbuf); }
void cccmac_final(const struct ccmode_cbc *cbc, cccmac_ctx_t ctx, size_t nbytes, const void *in, void *out) { size_t nblocks = nbytes / CMAC_BLOCKSIZE; size_t final_bytes = nbytes % CMAC_BLOCKSIZE; uint8_t final_buf[CMAC_BLOCKSIZE]; void *subkey = cccmac_k2(ctx); cc_clear(CMAC_BLOCKSIZE, final_buf); if(nbytes && final_bytes == 0) { nblocks--; final_bytes = CMAC_BLOCKSIZE; subkey = cccmac_k1(ctx); } else { final_buf[final_bytes] = 0x80; } CC_MEMCPY(final_buf, ((const uint8_t *)in) + nblocks*CMAC_BLOCKSIZE, final_bytes); cc_xor(CMAC_BLOCKSIZE, final_buf, final_buf, subkey); cccmac_compress(cbc, ctx, nblocks, in, out); cccmac_compress(cbc, ctx, 1, final_buf, out); }
int ccrsa_eme_pkcs1v15_encode(struct ccrng_state *rng, size_t r_size, cc_unit *r, size_t s_size, const uint8_t *s) { cc_size n = ccrsa_n_from_size(r_size); uint8_t *out = ccrsa_block_start(r_size, r, 1); uint8_t *pad; size_t padlen; size_t i; for(uint8_t *p = (uint8_t *) r; p < out; p++) *p = 0; pad = out + 2; if ((r_size < 3) || ((r_size - 3) < s_size)) { return CCRSA_INVALID_INPUT; } padlen = r_size - s_size - 3; int result = ccrng_generate(rng, padlen, pad); if (result) { return result; } for(i=0; i<padlen; i++) { // pad can't have zero bytes while(pad[i] == 0) if((result = ccrng_generate(rng, 1, &pad[i])) != 0) return result; } out[0] = 0x00; out[1] = 0x02; out[2+padlen] = 0x00; CC_MEMCPY(out+3+padlen, s, s_size); ccn_swap(n, r); return 0; }
int ccnistkdf_fb_hmac_fixed(const struct ccdigest_info *di, int use_counter, size_t kdkLen, const void *kdk, size_t fixedDataLen, const void *fixedData, size_t ivLen, const void *iv, size_t dkLen, void *dk) { size_t h = di->output_size; size_t n = cc_div_ceiling(dkLen, h); uint8_t result_buf[n*h]; uint8_t *result = result_buf; const uint8_t *iv_local = iv; uint8_t iv_local_len = ivLen; if(n > UINT32_MAX) return -1; if(kdkLen == 0 || kdk == NULL) return -1; if(dkLen == 0 || dk == NULL) return -1; use_counter = (use_counter) ? 1: 0; cchmac_di_decl(di, hc); cchmac_state_cache(di, istate); cchmac_init(di, hc, kdkLen, kdk); cchmac_cache_state(di, hc, istate); for(size_t i = 1; i <= n; i++, result += h) { F(di, hc, istate, iv_local_len, iv_local, i*use_counter, fixedDataLen, fixedData, result); iv_local = result; iv_local_len = h; } CC_MEMCPY(dk, result_buf, dkLen); cc_clear(n*h,result_buf); cchmac_di_clear(di, hc); cc_clear(di->state_size, istate); return 0; }
static int nistctr_init(const struct ccdrbg_nistctr_custom *custom, struct ccdrbg_nistctr_state *drbg, char *keys, const void* entropy, unsigned long entropyLength, const void* nonce, unsigned long nonceLength, const void* ps, unsigned long psLength ) { int err; uint32_t count; char *buf; drbg->ecb = custom->ecb; drbg->keylen = custom->keylen; buf=keys; unsigned long bs=drbg->ecb->block_size; drbg->encryptedIV = (uint8_t *)buf; buf+=((drbg->keylen+bs*2-1)/bs)*bs; drbg->V = (uint32_t *)buf; buf+=bs; //CCADRBG_OUTLEN(drbg); drbg->nullInput = (uint32_t *)buf; buf+=drbg->keylen+bs; //CCADRBG_SEEDLEN(drbg); drbg->bcc.S = (uint32_t *)buf; buf+=bs; //CCADRBG_OUTLEN(drbg); drbg->key = (ccecb_ctx *)buf; buf+=drbg->ecb->size; drbg->df_key = (ccecb_ctx *)buf; // First initialize the struct drbg->strictFIPS = custom->strictFIPS; drbg->use_df = custom->use_df; #if NONFIPSINC128 if (strictFIPS) drbg->inc128 = increment_bigend_128; else drbg->inc128 = increment_bigend_128_NOFIPS; #endif for (count = 0; count < CCADRBG_SEEDLEN_INTS(drbg); count++) drbg->nullInput[count] = 0; // Reseed counter is set in [6] below. // V is set in [4] and [5] // Initialize the derivation function // //nonce is not checked, caller needs to make sure nonce is right as per NIST 800-90A section 8.6.7 int rc=validate_inputs(drbg, entropyLength, 0, psLength); if(rc!=CCDRBG_STATUS_OK){ done((struct ccdrbg_state *)drbg); return rc; } uint8_t K[CCADRBG_KEYLEN(drbg)]; uint32_t seed_material[CCADRBG_SEEDLEN_INTS(drbg)]; if(drbg->use_df) { uint32_t length[3]; const char *input_string[3]; df_initialize(drbg); /* [1] seed_material = entropy || nonce || ps */ input_string[0] = entropy; /* typecast: guaranteed to fit by above checks */ length[0] = (uint32_t)entropyLength; input_string[1] = nonce; /* typecast: guaranteed to fit by above checks */ length[1] = (uint32_t)nonceLength; count = 2; if (ps && psLength) { input_string[count] = ps; /* typecast: guaranteed to fit by above checks */ length[count] = (uint32_t) psLength; ++count; } /* [2] seed_material = Block_Cipher_df(seed_material, seedlen) */ err = df(drbg, input_string, length, count, (uint8_t *)seed_material, sizeof(seed_material)); if (err) { cc_clear(sizeof(seed_material),seed_material); done((struct ccdrbg_state *)drbg); return err; } } else { cc_clear(sizeof(seed_material),seed_material); cc_assert(psLength==0 || psLength==sizeof(seed_material)); //pslength is validated above CC_MEMCPY(seed_material, ps, psLength); cc_xor(CCADRBG_SEEDLEN(drbg), seed_material, seed_material, entropy); } /* [3] Key = 0^keylen */ cc_clear(sizeof(K), K); drbg->ecb->init(drbg->ecb, drbg->key, sizeof(K), K); /* [4] V = 0^outlen */ cc_clear(CCADRBG_OUTLEN(drbg),drbg->V); /* [5] (Key, V) = Update(seed_material, Key, V) */ if (drbg_update(drbg, seed_material)) { cc_clear(sizeof(seed_material),seed_material); done((struct ccdrbg_state *)drbg); return CCDRBG_STATUS_PARAM_ERROR; } cc_clear(sizeof(seed_material),seed_material); /* [6] reseed_counter = 1 */ drbg->reseed_counter = 1; return CCDRBG_STATUS_OK; }
static int generate(struct ccdrbg_state *rng, unsigned long dataOutLength, void *dataOut, unsigned long additionalLength, const void *additional) { int rc = CCDRBG_STATUS_OK; unsigned long i; unsigned long len; uint8_t *p; uint32_t *temp; const char *input_string[1]; uint32_t length[1]; struct ccdrbg_nistctr_state *drbg = (struct ccdrbg_nistctr_state *)rng; uint32_t buffer[CCADRBG_OUTLEN(drbg)]; uint32_t additional_buffer[CCADRBG_SEEDLEN_INTS(drbg)]; unsigned long blocks = dataOutLength / CCADRBG_OUTLEN(drbg); /* [1] If reseed_counter > reseed_interval ... */ rc = validate_gen_params(drbg, dataOutLength, (additional !=NULL)?additionalLength:0); cc_require(rc==CCDRBG_STATUS_OK, errOut); /* [2] If (addional_input != Null), then */ if (additional && additionalLength) { if(drbg->use_df) { input_string[0] = additional; /* typecast: guaranteed to fit by the checks above */ length[0] = (uint32_t)additionalLength; /* [2.1] additional = Block_Cipher_df(additional, seedlen) */ rc = df(drbg, input_string, length, 1, (uint8_t *)additional_buffer, sizeof(additional_buffer)); cc_require(rc==CCDRBG_STATUS_OK, errOut); } else { cc_clear(sizeof(additional_buffer), additional_buffer); cc_assert(additionalLength==0 || additionalLength==sizeof(additional_buffer)); //additionalLength is validated above CC_MEMCPY(additional_buffer, additional, additionalLength); } /* [2.2] (Key, V) = Update(additional, Key, V) */ rc=drbg_update(drbg, additional_buffer); cc_require(rc==CCDRBG_STATUS_OK, errOut); } if (blocks && check_int_alignment(dataOut)) { /* [3] temp = Null */ temp = (uint32_t *)dataOut; for (i = 0; i < blocks; ++i) { // Here is the conundrum that is FIPS. // In order to test the DRBG for CAVS one must NOT set strictFIPS // and thus not have a compliant DRBG. That is the only way to // ensure that the CAVS test will pass. On the other hand the // 'normal' usage of the DRBG MUST set the strictFIPS flag. So // that which is used by our customers is NOT what was tested. rc = generate_block(drbg, temp); cc_require(rc==CCDRBG_STATUS_OK, errOut); temp += CCADRBG_OUTLEN_INTS(drbg); dataOutLength -= CCADRBG_OUTLEN(drbg); } dataOut = (uint8_t *)temp; } /* [3] temp = Null */ temp = buffer; len = CCADRBG_OUTLEN(drbg); /* [4] While (len(temp) < requested_number_of_bits) do: */ p = dataOut; while (dataOutLength > 0) { // See note above. rc = generate_block(drbg, temp); cc_require(rc==CCDRBG_STATUS_OK, errOut); if (dataOutLength < CCADRBG_OUTLEN(drbg)) len = dataOutLength; memcpy(p, temp, len); p += len; dataOutLength -= len; } /* [6] (Key, V) = Update(additional, Key, V) */ rc = drbg_update(drbg, additional && additionalLength ? &additional_buffer[0] : &drbg->nullInput[0]); cc_require(rc==CCDRBG_STATUS_OK, errOut); /* [7] reseed_counter = reseed_counter + 1 */ ++drbg->reseed_counter; errOut: cc_clear(sizeof(additional_buffer),additional_buffer); return rc; }