/************************* 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); }