Esempio n. 1
0
            public override bool TrySignHash(ReadOnlySpan <byte> hash, Span <byte> destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten)
            {
                if (string.IsNullOrEmpty(hashAlgorithm.Name))
                {
                    throw HashAlgorithmNameNullOrEmpty();
                }
                if (padding == null)
                {
                    throw new ArgumentNullException(nameof(padding));
                }

                RsaPaddingProcessor processor = null;

                if (padding.Mode == RSASignaturePaddingMode.Pss)
                {
                    processor = RsaPaddingProcessor.OpenProcessor(hashAlgorithm);
                }
                else if (padding != RSASignaturePadding.Pkcs1)
                {
                    throw new CryptographicException(SR.Cryptography_InvalidPaddingMode);
                }

                SecKeyPair keys = GetKeys();

                if (keys.PrivateKey == null)
                {
                    throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
                }

                int keySize = KeySize;
                int rsaSize = RsaPaddingProcessor.BytesRequiredForBitCount(keySize);

                if (processor == null)
                {
                    Interop.AppleCrypto.PAL_HashAlgorithm palAlgId =
                        PalAlgorithmFromAlgorithmName(hashAlgorithm, out int expectedSize);

                    if (hash.Length != expectedSize)
                    {
                        // Windows: NTE_BAD_DATA ("Bad Data.")
                        // OpenSSL: RSA_R_INVALID_MESSAGE_LENGTH ("invalid message length")
                        throw new CryptographicException(
                                  SR.Format(
                                      SR.Cryptography_BadHashSize_ForAlgorithm,
                                      hash.Length,
                                      expectedSize,
                                      hashAlgorithm.Name));
                    }

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

                    return(Interop.AppleCrypto.TryGenerateSignature(
                               keys.PrivateKey,
                               hash,
                               destination,
                               palAlgId,
                               out bytesWritten));
                }

                Debug.Assert(padding.Mode == RSASignaturePaddingMode.Pss);

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

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

                Span <byte> buf = new Span <byte>(rented, 0, rsaSize);

                processor.EncodePss(hash, buf, keySize);

                try
                {
                    return(Interop.AppleCrypto.TryRsaSignaturePrimitive(keys.PrivateKey, buf, destination, out bytesWritten));
                }
                finally
                {
                    CryptographicOperations.ZeroMemory(buf);
                    ArrayPool <byte> .Shared.Return(rented);
                }
            }
Esempio n. 2
0
        // Conveniently, Encrypt() and Decrypt() are identical save for the actual P/Invoke call to CNG. Thus, both
        // array-based APIs invoke this common helper with the "encrypt" parameter determining whether encryption or decryption is done.
        private unsafe byte[] EncryptOrDecrypt(byte[] data, RSAEncryptionPadding padding, bool encrypt)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (padding == null)
            {
                throw new ArgumentNullException(nameof(padding));
            }

            int modulusSizeInBytes = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize);

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

            if (encrypt &&
                padding.Mode == RSAEncryptionPaddingMode.Pkcs1 &&
                data.Length > modulusSizeInBytes - Pkcs1PaddingOverhead)
            {
                throw new CryptographicException(
                          SR.Format(SR.Cryptography_Encryption_MessageTooLong, modulusSizeInBytes - Pkcs1PaddingOverhead));
            }

            using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
            {
                if (encrypt && data.Length == 0)
                {
                    byte[] rented = ArrayPool <byte> .Shared.Rent(modulusSizeInBytes);

                    Span <byte> paddedMessage = new Span <byte>(rented, 0, modulusSizeInBytes);

                    try
                    {
                        if (padding == RSAEncryptionPadding.Pkcs1)
                        {
                            RsaPaddingProcessor.PadPkcs1Encryption(data, paddedMessage);
                        }
                        else if (padding.Mode == RSAEncryptionPaddingMode.Oaep)
                        {
                            RsaPaddingProcessor processor =
                                RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm);

                            processor.PadOaep(data, paddedMessage);
                        }
                        else
                        {
                            throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode);
                        }

                        return(EncryptOrDecrypt(keyHandle, paddedMessage, AsymmetricPaddingMode.NCRYPT_NO_PADDING_FLAG, null, encrypt));
                    }
                    finally
                    {
                        CryptographicOperations.ZeroMemory(paddedMessage);
                        ArrayPool <byte> .Shared.Return(rented);
                    }
                }

                switch (padding.Mode)
                {
                case RSAEncryptionPaddingMode.Pkcs1:
                    return(EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, null, encrypt));

                case RSAEncryptionPaddingMode.Oaep:
                    IntPtr namePtr = Marshal.StringToHGlobalUni(padding.OaepHashAlgorithm.Name);
                    try
                    {
                        var paddingInfo = new BCRYPT_OAEP_PADDING_INFO()
                        {
                            pszAlgId = namePtr,

                            // It would nice to put randomized data here but RSAEncryptionPadding does not at this point provide support for this.
                            pbLabel = IntPtr.Zero,
                            cbLabel = 0,
                        };
                        return(EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_OAEP_FLAG, &paddingInfo, encrypt));
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(namePtr);
                    }

                default:
                    throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Validate the current curve.
        /// </summary>
        /// <exception cref="CryptographicException">
        ///     if the curve parameters are not valid for the current CurveType.
        /// </exception>
        public void Validate()
        {
            if (IsNamed)
            {
                if (HasAnyExplicitParameters())
                {
                    throw new CryptographicException(SR.Cryptography_InvalidECNamedCurve);
                }

                if (Oid == null ||
                    (string.IsNullOrEmpty(Oid.FriendlyName) && string.IsNullOrEmpty(Oid.Value)))
                {
                    throw new CryptographicException(SR.Cryptography_InvalidCurveOid);
                }
            }
            else if (IsExplicit)
            {
                bool hasErrors = false;

                if (A == null ||
                    B == null || B.Length != A.Length ||
                    G.X == null || G.X.Length != A.Length ||
                    G.Y == null || G.Y.Length != A.Length ||
                    Order == null || Order.Length == 0 ||
                    Cofactor == null || Cofactor.Length == 0)
                {
                    hasErrors = true;
                }

                if (IsPrime)
                {
                    if (!hasErrors)
                    {
                        if (Prime == null || Prime.Length != A.Length)
                        {
                            hasErrors = true;
                        }
                    }

                    if (hasErrors)
                    {
                        throw new CryptographicException(SR.Cryptography_InvalidECPrimeCurve);
                    }
                }
                else if (IsCharacteristic2)
                {
                    if (!hasErrors)
                    {
                        if (Polynomial == null || Polynomial.Length == 0)
                        {
                            hasErrors = true;
                        }
                    }

                    if (hasErrors)
                    {
                        throw new CryptographicException(SR.Cryptography_InvalidECCharacteristic2Curve);
                    }
                }
            }
            else
            {
                // Implicit; if there are any values, throw
                Debug.Assert(CurveType == ECCurveType.Implicit);
                if (HasAnyExplicitParameters() || Oid != null)
                {
                    throw new CryptographicException(SR.Format(SR.Cryptography_CurveNotSupported, CurveType.ToString()));
                }
            }
        }