示例#1
0
        /************************* PUBLIC METHODS ************************/

        /// <include file='doc\cryptoapiTransform.uex' path='docs/doc[@for="CryptoAPITransform.TransformBlock"]/*' />
        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
        {
            // Note: special handling required if I'm decrypting & using PKCS#7 padding
            // Because the padding adds to the end of the last block, I have to buffer
            // an entire block's worth of bytes in case what I just transformed turns out to be the last block
            // Then in TransformFinalBlock we strip off the PKCS pad.

            if (_KeyHandleProtector.IsClosed)
            {
                throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
            }

            // First, let's do some bounds checking since the actual crypto is implemented
            // in unmanaged.

            if (inputBuffer == null)
            {
                throw new ArgumentNullException("inputBuffer");
            }

            if (outputBuffer == null)
            {
                throw new ArgumentNullException("outputBuffer");
            }

            if (inputOffset < 0)
            {
                throw new ArgumentOutOfRangeException("inputOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            }
            if ((inputCount <= 0) || (inputCount % InputBlockSize != 0) || (inputCount > inputBuffer.Length))
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"));
            }
            if ((inputBuffer.Length - inputCount) < inputOffset)
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            }

            // Note: there is no need to do the bounds check for the outputBuffer
            // since it will happen in the Buffer.InternalBlockCopy() operation and we are unconcerned
            // about the perf characteristics of the error case.

            byte[] transformedBytes;
            // fDone = true only on Final Block, not here
            if (encryptOrDecrypt == CryptoAPITransformMode.Encrypt)
            {
                // if we're encrypting we can always push out the bytes because no padding mode
                // removes bytes during encryption
                bool incremented = false;
                try {
                    if (_KeyHandleProtector.TryAddRef(ref incremented))
                    {
                        transformedBytes = _EncryptData(_KeyHandleProtector.Handle, inputBuffer, inputOffset, inputCount, false);
                    }
                    else
                    {
                        throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                    }
                }
                finally {
                    if (incremented)
                    {
                        _KeyHandleProtector.Release();
                    }
                }
                if (outputBuffer.Length < outputOffset + transformedBytes.Length)
                {
                    throw new CryptographicException(Environment.GetResourceString("Cryptography_InsufficientBuffer"));
                }
                Buffer.InternalBlockCopy(transformedBytes, 0, outputBuffer, outputOffset, transformedBytes.Length);
                return(transformedBytes.Length);
            }
            else
            {
                // For de-padding PKCS#7-padded ciphertext, we want to buffer the *input* bytes not
                // the output bytes.  Why?  Because we want to be able to guarantee that we can throw the
                // "Final" flag to CAPI when processing the last block, and that requires that we have PKCS#7
                // valid output, so we have to cache the input ciphertext.
                if (PaddingValue != PaddingMode.PKCS7)
                {
                    // like encryption, if we're not using PKCS padding on decrypt we can write out all
                    // the bytes.  Note that we cannot depad a block partially padded with Zeros because
                    // we can't tell if those zeros are plaintext or pad.
                    bool incremented = false;
                    try {
                        if (_KeyHandleProtector.TryAddRef(ref incremented))
                        {
                            transformedBytes = _DecryptData(_KeyHandleProtector.Handle, inputBuffer, inputOffset, inputCount, false);
                        }
                        else
                        {
                            throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                        }
                    }
                    finally {
                        if (incremented)
                        {
                            _KeyHandleProtector.Release();
                        }
                    }
                    if (outputBuffer.Length < outputOffset + transformedBytes.Length)
                    {
                        throw new CryptographicException(Environment.GetResourceString("Cryptography_InsufficientBuffer"));
                    }
                    Buffer.InternalBlockCopy(transformedBytes, 0, outputBuffer, outputOffset, transformedBytes.Length);
                    return(transformedBytes.Length);
                }
                else
                {
                    // OK, now we're in the special case.  Check to see if this is the *first* block we've seen
                    // If so, buffer it and return null zero bytes

                    int blockSizeInBytes = BlockSizeValue / 8;
                    if (_depadBuffer == null)
                    {
                        _depadBuffer = new byte[InputBlockSize];
                        // copy the last InputBlockSize*8 bytes to _depadBufffer
                        // everything else gets processed and returned
                        int  inputToProcess = inputCount - InputBlockSize;
                        bool incremented    = false;
                        try {
                            if (_KeyHandleProtector.TryAddRef(ref incremented))
                            {
                                transformedBytes = _DecryptData(_KeyHandleProtector.Handle, inputBuffer, inputOffset, inputToProcess, false);
                            }
                            else
                            {
                                throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                            }
                        }
                        finally {
                            if (incremented)
                            {
                                _KeyHandleProtector.Release();
                            }
                        }
                        Buffer.InternalBlockCopy(inputBuffer, inputOffset + inputToProcess, _depadBuffer, 0, InputBlockSize);
                        Buffer.InternalBlockCopy(transformedBytes, 0, outputBuffer, outputOffset, transformedBytes.Length);
                        return(transformedBytes.Length); // we copied 0 bytes into the outputBuffer
                    }
                    else
                    {
                        // we already have a depad buffer, so we need to decrypt that info first & copy it out
                        bool incremented = false;
                        try {
                            if (_KeyHandleProtector.TryAddRef(ref incremented))
                            {
                                transformedBytes = _DecryptData(_KeyHandleProtector.Handle, _depadBuffer, 0, _depadBuffer.Length, false);
                            }
                            else
                            {
                                throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                            }
                        }
                        finally {
                            if (incremented)
                            {
                                _KeyHandleProtector.Release();
                            }
                        }
                        int retval = transformedBytes.Length;
                        Buffer.InternalBlockCopy(transformedBytes, 0, outputBuffer, outputOffset, retval);
                        outputOffset += OutputBlockSize;
                        int inputToProcess = inputCount - InputBlockSize;
                        incremented = false;
                        try {
                            if (_KeyHandleProtector.TryAddRef(ref incremented))
                            {
                                transformedBytes = _DecryptData(_KeyHandleProtector.Handle, inputBuffer, inputOffset, inputToProcess, false);
                            }
                            else
                            {
                                throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                            }
                        }
                        finally {
                            if (incremented)
                            {
                                _KeyHandleProtector.Release();
                            }
                        }
                        Buffer.InternalBlockCopy(inputBuffer, inputOffset + inputToProcess, _depadBuffer, 0, InputBlockSize);
                        Buffer.InternalBlockCopy(transformedBytes, 0, outputBuffer, outputOffset, transformedBytes.Length);
                        return(retval + transformedBytes.Length);
                    }
                }
            }
        }
        /************************* PUBLIC METHODS ************************/

        /// <include file='doc\DSACryptoServiceProvider.uex' path='docs/doc[@for="DSACryptoServiceProvider.ExportParameters"]/*' />
        public override DSAParameters ExportParameters(bool includePrivateParameters)
        {
            int hr;

            if (_CSPHandleProtector.IsClosed || _KeyHandleProtector.IsClosed)
            {
                throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
            }

            DSACspObject  dsaKey    = new DSACspObject();
            DSAParameters dsaParams = new DSAParameters();

            if (includePrivateParameters)
            {
                bool incremented = false;
                try {
                    if (_KeyHandleProtector.TryAddRef(ref incremented))
                    {
                        hr = _ExportKey(_KeyHandleProtector.Handle, PRIVATEKEYBLOB, dsaKey);
                    }
                    else
                    {
                        throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                    }
                }
                finally {
                    if (incremented)
                    {
                        _KeyHandleProtector.Release();
                    }
                }
                if (hr != 0)
                {
                    throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_ExportKey"));
                }
                // Must reverse after export from CAPI!
                ReverseDSACspObject(dsaKey);
                dsaParams.P = dsaKey.P;
                dsaParams.Q = dsaKey.Q;
                dsaParams.G = dsaKey.G;
                dsaParams.Y = dsaKey.Y;
                dsaParams.X = dsaKey.X;
                if (dsaKey.J != null)
                {
                    dsaParams.J = dsaKey.J;
                }
                if (dsaKey.seed != null)
                {
                    dsaParams.Seed    = dsaKey.seed;
                    dsaParams.Counter = dsaKey.counter;
                }
            }
            else
            {
                bool incremented = false;
                try {
                    if (_KeyHandleProtector.TryAddRef(ref incremented))
                    {
                        hr = _ExportKey(_KeyHandleProtector.Handle, PUBLICKEYBLOB, dsaKey);
                    }
                    else
                    {
                        throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                    }
                }
                finally {
                    if (incremented)
                    {
                        _KeyHandleProtector.Release();
                    }
                }
                if (hr != 0)
                {
                    throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_ExportKey"));
                }
                // Must reverse (into network byte order) after export from CAPI!
                ReverseDSACspObject(dsaKey);
                dsaParams.P = dsaKey.P;
                dsaParams.Q = dsaKey.Q;
                dsaParams.G = dsaKey.G;
                dsaParams.Y = dsaKey.Y;
                if (dsaKey.J != null)
                {
                    dsaParams.J = dsaKey.J;
                }
                if (dsaKey.seed != null)
                {
                    dsaParams.Seed    = dsaKey.seed;
                    dsaParams.Counter = dsaKey.counter;
                }
                // zeroize private key material
                if (dsaKey.X != null)
                {
                    Array.Clear(dsaKey.X, 0, dsaKey.X.Length);
                }
            }
            return(dsaParams);
        }
        /************************* PUBLIC METHODS ************************/

        /// <include file='doc\RSACryptoServiceProvider.uex' path='docs/doc[@for="RSACryptoServiceProvider.ExportParameters"]/*' />
        public override RSAParameters ExportParameters(bool includePrivateParameters)
        {
            int hr;

            if (_CSPHandleProtector.IsClosed || _KeyHandleProtector.IsClosed)
            {
                throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
            }

            RSACspObject  rsaKey    = new RSACspObject();
            RSAParameters rsaParams = new RSAParameters();

            if (includePrivateParameters)
            {
                bool incremented = false;
                try {
                    if (_KeyHandleProtector.TryAddRef(ref incremented))
                    {
                        hr = _ExportKey(_KeyHandleProtector.Handle, PRIVATEKEYBLOB, rsaKey);
                    }
                    else
                    {
                        throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                    }
                }
                finally {
                    if (incremented)
                    {
                        _KeyHandleProtector.Release();
                    }
                }
                if (hr != 0)
                {
                    throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_ExportKey"));
                }
                // Must reverse after export!
                ReverseRSACspObject(rsaKey);
                rsaParams.Modulus  = rsaKey.Modulus;
                rsaParams.Exponent = ConvertIntToByteArray(rsaKey.Exponent);
                rsaParams.P        = rsaKey.P;
                rsaParams.Q        = rsaKey.Q;
                rsaParams.DP       = rsaKey.dp;
                rsaParams.DQ       = rsaKey.dq;
                rsaParams.InverseQ = rsaKey.InverseQ;
                rsaParams.D        = rsaKey.d;
            }
            else
            {
                bool incremented = false;
                try {
                    if (_KeyHandleProtector.TryAddRef(ref incremented))
                    {
                        hr = _ExportKey(_KeyHandleProtector.Handle, PUBLICKEYBLOB, rsaKey);
                    }
                    else
                    {
                        throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic_ObjectName1"));
                    }
                }
                finally {
                    if (incremented)
                    {
                        _KeyHandleProtector.Release();
                    }
                }
                if (hr != 0)
                {
                    throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_ExportKey"));
                }
                // Must reverse after export!
                ReverseRSACspObject(rsaKey);
                rsaParams.Modulus  = rsaKey.Modulus;
                rsaParams.Exponent = ConvertIntToByteArray(rsaKey.Exponent);
                // zeroize private info
                if (rsaKey.d != null)
                {
                    Array.Clear(rsaKey.d, 0, rsaKey.d.Length);
                }
                if (rsaKey.P != null)
                {
                    Array.Clear(rsaKey.P, 0, rsaKey.P.Length);
                }
                if (rsaKey.Q != null)
                {
                    Array.Clear(rsaKey.Q, 0, rsaKey.Q.Length);
                }
                if (rsaKey.dp != null)
                {
                    Array.Clear(rsaKey.dp, 0, rsaKey.dp.Length);
                }
                if (rsaKey.dq != null)
                {
                    Array.Clear(rsaKey.dq, 0, rsaKey.dq.Length);
                }
                if (rsaKey.InverseQ != null)
                {
                    Array.Clear(rsaKey.InverseQ, 0, rsaKey.InverseQ.Length);
                }
            }
            return(rsaParams);
        }