int ctr_generate(DRBG_CTX *dctx,
                 unsigned char *out, size_t outlen,
                 const unsigned char *adin, size_t adinlen)
{
    DRBG_CTR_CTX *cctx = &dctx->ctr;

    if (adin != NULL && adinlen != 0) {
        ctr_update(dctx, adin, adinlen, NULL, 0, NULL, 0);
        /* This means we reuse derived value */
        if (dctx->flags & RAND_DRBG_FLAG_CTR_USE_DF) {
            adin = NULL;
            adinlen = 1;
        }
    } else {
        adinlen = 0;
    }

    for ( ; ; ) {
        inc_128(cctx);
        if (outlen < 16) {
            /* Use K as temp space as it will be updated */
            AES_encrypt(cctx->V, cctx->K, &cctx->ks);
            memcpy(out, cctx->K, outlen);
            break;
        }
        AES_encrypt(cctx->V, out, &cctx->ks);
        out += 16;
        outlen -= 16;
        if (outlen == 0)
            break;
    }

    ctr_update(dctx, adin, adinlen, NULL, 0, NULL, 0);
    return 1;
}