Exemple #1
0
            private bool TryDecrypt(
                SafeSecKeyRefHandle privateKey,
                ReadOnlySpan <byte> data,
                Span <byte> destination,
                RSAEncryptionPadding padding,
                out int bytesWritten)
            {
                Debug.Assert(privateKey != null);

                if (padding.Mode != RSAEncryptionPaddingMode.Pkcs1 &&
                    padding.Mode != RSAEncryptionPaddingMode.Oaep)
                {
                    throw new CryptographicException(SR.Cryptography_InvalidPaddingMode);
                }

                int modulusSizeInBytes = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize);

                if (data.Length > modulusSizeInBytes)
                {
                    throw new CryptographicException(
                              SR.Format(SR.Cryptography_Padding_DecDataTooBig, modulusSizeInBytes));
                }

                if (padding.Mode == RSAEncryptionPaddingMode.Pkcs1 ||
                    padding == RSAEncryptionPadding.OaepSHA1)
                {
                    return(Interop.AppleCrypto.TryRsaDecrypt(privateKey, data, destination, padding, out bytesWritten));
                }

                Debug.Assert(padding.Mode == RSAEncryptionPaddingMode.Oaep);
                RsaPaddingProcessor processor = RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm);

                byte[] rented = ArrayPool <byte> .Shared.Rent(modulusSizeInBytes);

                Span <byte> unpaddedData = Span <byte> .Empty;

                try
                {
                    if (!Interop.AppleCrypto.TryRsaDecryptionPrimitive(privateKey, data, rented, out int paddedSize))
                    {
                        Debug.Fail($"Raw decryption failed with KeySize={KeySize} and a buffer length {rented.Length}");
                        throw new CryptographicException();
                    }

                    Debug.Assert(modulusSizeInBytes == paddedSize);
                    unpaddedData = new Span <byte>(rented, 0, paddedSize);
                    return(processor.DepadOaep(unpaddedData, destination, out bytesWritten));
                }
                finally
                {
                    CryptographicOperations.ZeroMemory(unpaddedData);
                    ArrayPool <byte> .Shared.Return(rented);
                }
            }
Exemple #2
0
        private static bool TryDecrypt(
            SafeRsaHandle key,
            ReadOnlySpan <byte> data,
            Span <byte> destination,
            Interop.Crypto.RsaPadding rsaPadding,
            RsaPaddingProcessor rsaPaddingProcessor,
            out int bytesWritten)
        {
            // If rsaPadding is PKCS1 or OAEP-SHA1 then no depadding method should be present.
            // If rsaPadding is NoPadding then a depadding method should be present.
            Debug.Assert(
                (rsaPadding == Interop.Crypto.RsaPadding.NoPadding) ==
                (rsaPaddingProcessor != null));

            // Caller should have already checked this.
            Debug.Assert(!key.IsInvalid);

            int rsaSize = Interop.Crypto.RsaSize(key);

            if (data.Length != rsaSize)
            {
                throw new CryptographicException(SR.Cryptography_RSA_DecryptWrongSize);
            }

            if (destination.Length < rsaSize)
            {
                bytesWritten = 0;
                return(false);
            }

            Span <byte> decryptBuf = destination;

            byte[] paddingBuf = null;

            if (rsaPaddingProcessor != null)
            {
                paddingBuf = CryptoPool.Rent(rsaSize);
                decryptBuf = paddingBuf;
            }

            try
            {
                int returnValue = Interop.Crypto.RsaPrivateDecrypt(data.Length, data, decryptBuf, key, rsaPadding);
                CheckReturn(returnValue);

                if (rsaPaddingProcessor != null)
                {
                    return(rsaPaddingProcessor.DepadOaep(paddingBuf, destination, out bytesWritten));
                }
                else
                {
                    // If the padding mode is RSA_NO_PADDING then the size of the decrypted block
                    // will be RSA_size. If any padding was used, then some amount (determined by the padding algorithm)
                    // will have been reduced, and only returnValue bytes were part of the decrypted
                    // body.  Either way, we can just use returnValue, but some additional bytes may have been overwritten
                    // in the destination span.
                    bytesWritten = returnValue;
                }

                return(true);
            }
            finally
            {
                if (paddingBuf != null)
                {
                    // DecryptBuf is paddingBuf if paddingBuf is not null, erase it before returning it.
                    // If paddingBuf IS null then decryptBuf was destination, and shouldn't be cleared.
                    CryptographicOperations.ZeroMemory(decryptBuf);
                    CryptoPool.Return(paddingBuf, clearSize: 0);
                }
            }
        }