int RAND_DRBG_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
                       int prediction_resistance,
                       const unsigned char *adin, size_t adinlen)
{
    int r = 0;

    if (dctx->status != DRBG_STATUS_READY
            && dctx->status != DRBG_STATUS_RESEED) {
        if (dctx->status == DRBG_STATUS_ERROR)
            r = RAND_R_IN_ERROR_STATE;
        else if(dctx->status == DRBG_STATUS_UNINITIALISED)
            r = RAND_R_NOT_INSTANTIATED;
        goto end;
    }

    if (outlen > dctx->max_request) {
        r = RAND_R_REQUEST_TOO_LARGE_FOR_DRBG;
        return 0;
    }
    if (adinlen > dctx->max_adin) {
        r = RAND_R_ADDITIONAL_INPUT_TOO_LONG;
        goto end;
    }

    if (dctx->reseed_counter >= dctx->reseed_interval)
        dctx->status = DRBG_STATUS_RESEED;

    if (dctx->status == DRBG_STATUS_RESEED || prediction_resistance) {
        if (!RAND_DRBG_reseed(dctx, adin, adinlen)) {
            r = RAND_R_RESEED_ERROR;
            goto end;
        }
        adin = NULL;
        adinlen = 0;
    }

    if (!ctr_generate(dctx, out, outlen, adin, adinlen)) {
        r = RAND_R_GENERATE_ERROR;
        dctx->status = DRBG_STATUS_ERROR;
        goto end;
    }
    if (dctx->reseed_counter >= dctx->reseed_interval)
        dctx->status = DRBG_STATUS_RESEED;
    else
        dctx->reseed_counter++;
    return 1;

end:
    RANDerr(RAND_F_RAND_DRBG_GENERATE, r);
    return 0;
}