static int _rngfips_ctx_reinit(struct fips_ctx *fctx) { int ret; /* strong */ ret = drbg_reseed(&fctx->strong_context); if (ret < 0) return gnutls_assert_val(ret); /* normal */ ret = drbg_reseed(&fctx->normal_context); if (ret < 0) return gnutls_assert_val(ret); /* nonce */ ret = drbg_reseed(&fctx->nonce_context); if (ret < 0) return gnutls_assert_val(ret); #ifdef HAVE_GETPID fctx->pid = getpid(); #endif return 0; }
/** * Generate pseudorandom bits using DRBG * * @v state Algorithm state * @v additional Additional input * @v additional_len Length of additional input * @v prediction_resist Prediction resistance is required * @v data Output buffer * @v len Length of output buffer * @ret rc Return status code * * This is the Generate_function defined in ANS X9.82 Part 3-2007 * Section 9.4 (NIST SP 800-90 Section 9.3). * * Requests must be for an integral number of bytes. Only a single * security strength is supported. Prediction resistance is supported * if requested. */ int drbg_generate ( struct drbg_state *state, const void *additional, size_t additional_len, int prediction_resist, void *data, size_t len ) { int rc; DBGC ( state, "DRBG %p generate\n", state ); /* Sanity checks */ assert ( state != NULL ); assert ( data != NULL ); /* 1. Using state_handle, obtain the current internal state * for the instantiation. If state_handle indicates an * invalid or empty internal state, then return an ERROR_FLAG. * * (Almost nothing to do since the memory holding the internal * state was passed in by the caller.) */ if ( ! state->valid ) { DBGC ( state, "DRBG %p not valid\n", state ); return -EINVAL; } /* 2. If requested_number_of_bits > * max_number_of_bits_per_request, then return an * ERROR_FLAG. */ if ( len > DRBG_MAX_GENERATED_LEN_BYTES ) { DBGC ( state, "DRBG %p request too long (%zd bytes)\n", state, len ); return -ERANGE; } /* 3. If requested_security_strength > the security_strength * indicated in the internal state, then return an * ERROR_FLAG. * * (Nothing to do since only a single security strength is * supported.) */ /* 4. If the length of the additional_input > * max_additional_input_length, then return an ERROR_FLAG. */ if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) { DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n", state, additional_len ); return -ERANGE; } /* 5. If prediction_resistance_request is set, and * prediction_resistance_flag is not set, then return an * ERROR_FLAG. * * (Nothing to do since prediction resistance is always * supported.) */ /* 6. Clear the reseed_required_flag. */ state->reseed_required = 0; step_7: /* 7. If reseed_required_flag is set, or if * prediction_resistance_request is set, then */ if ( state->reseed_required || prediction_resist ) { /* 7.1 status = Reseed_function ( state_handle, * prediction_resistance_request, * additional_input ) * 7.2 If status indicates an ERROR, then return * status. */ if ( ( rc = drbg_reseed ( state, additional, additional_len ) ) != 0 ) { DBGC ( state, "DRBG %p could not reseed: %s\n", state, strerror ( rc ) ); return rc; } /* 7.3 Using state_handle, obtain the new internal * state. * * (Nothing to do since the internal state has been * updated in-situ.) */ /* 7.4 additional_input = the Null string. */ additional = NULL; additional_len = 0; /* 7.5 Clear the reseed_required_flag. */ state->reseed_required = 0; } /* 8. ( status, pseudorandom_bits, new_working_state ) = * Generate_algorithm ( working_state, * requested_number_of_bits, additional_input ). */ rc = drbg_generate_algorithm ( state, additional, additional_len, data, len ); /* 9. If status indicates that a reseed is required before * the requested bits can be generated, then */ if ( rc != 0 ) { /* 9.1 Set the reseed_required_flag. */ state->reseed_required = 1; /* 9.2 If the prediction_resistance_flag is set, then * set the prediction_resistance_request * indication. */ prediction_resist = 1; /* 9.3 Go to step 7. */ goto step_7; } /* 10. Replace the old working_state in the internal state * indicated by state_handle with the values of * new_working_state. * * (Nothing to do since the working state has already been * updated in-situ.) */ /* 11. Return SUCCESS and pseudorandom_bits. */ return 0; }