Example #1
0
        /**
         * Populate a passed in array with random data.
         *
         * @param output output array for generated bits.
         * @param additionalInput additional input to be added to the DRBG in this step.
         * @param predictionResistant true if a reseed should be forced, false otherwise.
         *
         * @return number of bits generated, -1 if a reseed required.
         */
        public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant)
        {
            if (mIsTdea)
            {
                if (mReseedCounter > TDEA_RESEED_MAX)
                {
                    return(-1);
                }

                if (DrbgUtilities.IsTooLarge(output, TDEA_MAX_BITS_REQUEST / 8))
                {
                    throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST, "output");
                }
            }
            else
            {
                if (mReseedCounter > AES_RESEED_MAX)
                {
                    return(-1);
                }

                if (DrbgUtilities.IsTooLarge(output, AES_MAX_BITS_REQUEST / 8))
                {
                    throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST, "output");
                }
            }

            if (predictionResistant)
            {
                CTR_DRBG_Reseed_algorithm(additionalInput);
                additionalInput = null;
            }

            if (additionalInput != null)
            {
                additionalInput = Block_Cipher_df(additionalInput, mSeedLength);
                CTR_DRBG_Update(additionalInput, mKey, mV);
            }
            else
            {
                additionalInput = new byte[mSeedLength];
            }

            byte[] tmp = new byte[mV.Length];

            mEngine.Init(true, new KeyParameter(ExpandKey(mKey)));

            for (int i = 0; i <= output.Length / tmp.Length; i++)
            {
                int bytesToCopy = ((output.Length - i * tmp.Length) > tmp.Length)
                                        ? tmp.Length
                        : (output.Length - i * mV.Length);

                if (bytesToCopy != 0)
                {
                    AddOneTo(mV);

                    mEngine.ProcessBlock(mV, 0, tmp, 0);

                    Array.Copy(tmp, 0, output, i * tmp.Length, bytesToCopy);
                }
            }

            CTR_DRBG_Update(additionalInput, mKey, mV);

            mReseedCounter++;

            return(output.Length * 8);
        }