Exemplo n.º 1
0
/* 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);
}
Exemplo n.º 2
0
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]);
}
Exemplo n.º 3
0
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;
            }
        }
    }
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/*
 * 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;
}
Exemplo n.º 7
0
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 {
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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);
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
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;
}