internal static void ApprovedModeCheck(bool approvedMode, string algorithmName)
 {
     if (approvedMode != IsInApprovedOnlyMode())
     {
         if (approvedMode)
         {
             throw new CryptoUnapprovedOperationError("attempt to use approved instance in unapproved thread: " + algorithmName);
         }
         else
         {
             throw new CryptoUnapprovedOperationError("attempt to use unapproved instance in approved thread: " + algorithmName);
         }
     }
     if (CryptoStatus.IsErrorStatus())
     {
         throw new CryptoOperationError(CryptoStatus.GetStatusMessage());
     }
 }
        public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant)
        {
            if (CryptoStatus.IsErrorStatus())
            {
                throw new CryptoOperationError(CryptoStatus.GetStatusMessage());
            }

            lock (this)
            {
                int rv;

                if (block.Length != output.Length)
                {
                    if (block.Length < output.Length)
                    {
                        block     = new byte[GetTestBlockSize(output.Length)];
                        nextBlock = new byte[block.Length];

                        if (initialAdditionalInput != null)
                        {
                            rv = drbg.Generate(block, initialAdditionalInput, predictionResistant);
                            initialAdditionalInput = null;
                        }
                        else
                        {
                            rv = drbg.Generate(block, null, predictionResistant);
                        }

                        if (rv < 0)
                        {
                            CryptoStatus.MoveToErrorStatus("DRBG unable to initialise");
                        }
                    }
                    else if (block.Length != MIN_RESOLUTION)
                    {
                        byte[] tmp = new byte[GetTestBlockSize(output.Length)];

                        Array.Copy(block, block.Length - tmp.Length, tmp, 0, tmp.Length);

                        block     = tmp;
                        nextBlock = new byte[GetTestBlockSize(output.Length)];
                    }
                }

                rv = drbg.Generate(nextBlock, additionalInput, predictionResistant);
                if (rv < 0)
                {
                    return(rv);
                }

                // FSM_STATE:5.2, "CONTINUOUS DRBG TEST", "The module is performing Continuous DRBG self-test"
                // FSM_TRANS:5.3, "CONDITIONAL TEST", "CONTINUOUS DRBG TEST", "Invoke Continuous DRBG test"
                if (areEqual(block, nextBlock, 0))
                {
                    CryptoStatus.MoveToErrorStatus("Duplicate block detected in DRBG output");
                }
                // FSM_TRANS:5.4, "CONTINUOUS DRBG TEST", "CONDITIONAL TEST", "Continuous DRBG test successful"

                // note we only return output bytes to output array when we are sure there is no issue.
                Array.Copy(nextBlock, 0, output, 0, output.Length);
                Array.Copy(nextBlock, 0, block, 0, block.Length);
            }

            if (CryptoStatus.IsErrorStatus())
            {
                throw new CryptoOperationError(CryptoStatus.GetStatusMessage());
            }

            return(output.Length);
        }