Пример #1
0
        private static unsafe byte[] EncodeExtension(byte[] subjectKeyIdentifier)
        {
            if (subjectKeyIdentifier == null)
            {
                throw new ArgumentNullException("subjectKeyIdentifier");
            }
            if (subjectKeyIdentifier.Length == 0)
            {
                throw new ArgumentException("subjectKeyIdentifier");
            }

            byte[] encodedSubjectKeyIdentifier = null;
            fixed(byte *pb = subjectKeyIdentifier)
            {
                CAPI.CRYPTOAPI_BLOB pSubjectKeyIdentifier = new CAPI.CRYPTOAPI_BLOB();
                pSubjectKeyIdentifier.pbData = new IntPtr(pb);
                pSubjectKeyIdentifier.cbData = (uint)subjectKeyIdentifier.Length;

                if (!CAPI.EncodeObject(CAPI.szOID_SUBJECT_KEY_IDENTIFIER, new IntPtr(&pSubjectKeyIdentifier), out encodedSubjectKeyIdentifier))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }
            }

            return(encodedSubjectKeyIdentifier);
        }
Пример #2
0
        private void DecodeExtension()
        {
            uint cbDecoded = 0;
            SafeLocalAllocHandle decoded = null;

            bool result = CAPI.DecodeObject(new IntPtr(CAPI.X509_KEY_USAGE),
                                            m_rawData,
                                            out decoded,
                                            out cbDecoded);

            if (result == false)
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            CAPI.CRYPTOAPI_BLOB pKeyUsage = (CAPI.CRYPTOAPI_BLOB)Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CRYPTOAPI_BLOB));
            if (pKeyUsage.cbData > 4)
            {
                pKeyUsage.cbData = 4;
            }
            byte[] keyUsage = new byte[4];
            if (pKeyUsage.pbData != IntPtr.Zero)
            {
                Marshal.Copy(pKeyUsage.pbData, keyUsage, 0, (int)pKeyUsage.cbData);
            }
            m_keyUsages = BitConverter.ToUInt32(keyUsage, 0);
            m_decoded   = true;

            decoded.Dispose();
        }
Пример #3
0
 internal static unsafe byte[] EncodeOctetString(byte[] octets)
 {
     fixed(byte *numPtr = octets)
     {
         CAPI.CRYPTOAPI_BLOB cryptoapiBlob = new CAPI.CRYPTOAPI_BLOB();
         cryptoapiBlob.cbData = (uint)octets.Length;
         cryptoapiBlob.pbData = new IntPtr((void *)numPtr);
         byte[] encodedData = new byte[0];
         if (!CAPI.EncodeObject(new IntPtr(25L), new IntPtr((long)&cryptoapiBlob), out encodedData))
         {
             throw new CryptographicException(Marshal.GetLastWin32Error());
         }
         else
         {
             return(encodedData);
         }
     }
 }
Пример #4
0
        internal static string DecodeOctetString(byte[] encodedOctetString)
        {
            uint cbDecodedValue = 0U;
            SafeLocalAllocHandle decodedValue = (SafeLocalAllocHandle)null;

            if (!CAPI.DecodeObject(new IntPtr(25L), encodedOctetString, out decodedValue, out cbDecodedValue))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }
            if ((int)cbDecodedValue == 0)
            {
                return(string.Empty);
            }
            CAPI.CRYPTOAPI_BLOB cryptoapiBlob = (CAPI.CRYPTOAPI_BLOB)Marshal.PtrToStructure(decodedValue.DangerousGetHandle(), typeof(CAPI.CRYPTOAPI_BLOB));
            if ((int)cryptoapiBlob.cbData == 0)
            {
                return(string.Empty);
            }
            string str = Marshal.PtrToStringUni(cryptoapiBlob.pbData);

            decodedValue.Dispose();
            return(str);
        }
Пример #5
0
        private void DecodeExtension()
        {
            uint cbDecoded = 0;
            SafeLocalAllocHandle decoded = null;

            SafeLocalAllocHandle pb = X509Utils.StringToAnsiPtr(CAPI.szOID_SUBJECT_KEY_IDENTIFIER);
            bool result             = CAPI.DecodeObject(pb.DangerousGetHandle(),
                                                        m_rawData,
                                                        out decoded,
                                                        out cbDecoded);

            if (!result)
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            CAPI.CRYPTOAPI_BLOB pSubjectKeyIdentifier = (CAPI.CRYPTOAPI_BLOB)Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CRYPTOAPI_BLOB));
            byte[] hexArray = CAPI.BlobToByteArray(pSubjectKeyIdentifier);
            m_subjectKeyIdentifier = X509Utils.EncodeHexString(hexArray);

            m_decoded = true;
            decoded.Dispose();
            pb.Dispose();
        }
Пример #6
0
        internal unsafe SubjectIdentifier(CAPI.CRYPTOAPI_BLOB issuer, CAPI.CRYPTOAPI_BLOB serialNumber)
        {
            // If serial number is 0, then it is the special SKI encoding or NoSignature
            bool  isSKIorHashOnly = true;
            byte *pb = (byte *)serialNumber.pbData;

            for (uint i = 0; i < serialNumber.cbData; i++)
            {
                if (*pb++ != (byte)0)
                {
                    isSKIorHashOnly = false;
                    break;
                }
            }

            if (isSKIorHashOnly)
            {
                byte[] issuerBytes = new byte[issuer.cbData];
                Marshal.Copy(issuer.pbData, issuerBytes, 0, issuerBytes.Length);
                X500DistinguishedName dummyName = new X500DistinguishedName(issuerBytes);
                if (String.Compare(CAPI.DummySignerCommonName, dummyName.Name, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    Reset(SubjectIdentifierType.NoSignature, null);
                    return;
                }
            }

            if (isSKIorHashOnly)
            {
                // Decode disguised SKI in issuer field (See WinCrypt.h for more info).  Note that some certificates may contain
                // an all-zero serial number but not be encoded with an szOID_KEYID_RDN.  In order to allow use of signatures created
                // using these certificates, we will first try to find the szOID_KEYID_RDN, but if it does not exist, fall back to just
                // decoding the incoming issuer and serial number.
                m_type  = SubjectIdentifierType.SubjectKeyIdentifier;
                m_value = String.Empty;

                uint cbCertNameInfo = 0;
                SafeLocalAllocHandle pbCertNameInfo = SafeLocalAllocHandle.InvalidHandle;

                if (CAPI.DecodeObject(new IntPtr(CAPI.X509_NAME),
                                      issuer.pbData,
                                      issuer.cbData,
                                      out pbCertNameInfo,
                                      out cbCertNameInfo))
                {
                    using (pbCertNameInfo) {
                        checked {
                            CAPI.CERT_NAME_INFO certNameInfo = (CAPI.CERT_NAME_INFO)Marshal.PtrToStructure(pbCertNameInfo.DangerousGetHandle(), typeof(CAPI.CERT_NAME_INFO));
                            for (uint i = 0; i < certNameInfo.cRDN; i++)
                            {
                                CAPI.CERT_RDN certRdn = (CAPI.CERT_RDN)Marshal.PtrToStructure(new IntPtr((long)certNameInfo.rgRDN + (long)(i * Marshal.SizeOf(typeof(CAPI.CERT_RDN)))), typeof(CAPI.CERT_RDN));

                                for (uint j = 0; j < certRdn.cRDNAttr; j++)
                                {
                                    CAPI.CERT_RDN_ATTR certRdnAttr = (CAPI.CERT_RDN_ATTR)Marshal.PtrToStructure(new IntPtr((long)certRdn.rgRDNAttr + (long)(j * Marshal.SizeOf(typeof(CAPI.CERT_RDN_ATTR)))), typeof(CAPI.CERT_RDN_ATTR));

                                    if (String.Compare(CAPI.szOID_KEYID_RDN, certRdnAttr.pszObjId, StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        if (certRdnAttr.dwValueType == CAPI.CERT_RDN_OCTET_STRING)
                                        {
                                            byte[] ski = new byte[certRdnAttr.Value.cbData];
                                            Marshal.Copy(certRdnAttr.Value.pbData, ski, 0, ski.Length);
                                            Reset(SubjectIdentifierType.SubjectKeyIdentifier, X509Utils.EncodeHexString(ski));
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            CAPI.CERT_ISSUER_SERIAL_NUMBER IssuerAndSerial;
            IssuerAndSerial.Issuer       = issuer;
            IssuerAndSerial.SerialNumber = serialNumber;
            X509IssuerSerial issuerSerial = PkcsUtils.DecodeIssuerSerial(IssuerAndSerial);

            Reset(SubjectIdentifierType.IssuerAndSerialNumber, issuerSerial);
        }
Пример #7
0
        internal AlgorithmIdentifier(CAPI.CRYPT_ALGORITHM_IDENTIFIER algorithmIdentifier)
        {
            int  keyLength    = 0;
            uint cbParameters = 0;
            SafeLocalAllocHandle pbParameters = SafeLocalAllocHandle.InvalidHandle;

            byte[] parameters = new byte[0];

            uint algId = X509Utils.OidToAlgId(algorithmIdentifier.pszObjId);

            if (algId == CAPI.CALG_RC2)
            {
                if (algorithmIdentifier.Parameters.cbData > 0)
                {
                    if (!CAPI.DecodeObject(new IntPtr(CAPI.PKCS_RC2_CBC_PARAMETERS),
                                           algorithmIdentifier.Parameters.pbData,
                                           algorithmIdentifier.Parameters.cbData,
                                           out pbParameters,
                                           out cbParameters))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }

                    CAPI.CRYPT_RC2_CBC_PARAMETERS rc2Parameters = (CAPI.CRYPT_RC2_CBC_PARAMETERS)Marshal.PtrToStructure(pbParameters.DangerousGetHandle(), typeof(CAPI.CRYPT_RC2_CBC_PARAMETERS));
                    switch (rc2Parameters.dwVersion)
                    {
                    case CAPI.CRYPT_RC2_40BIT_VERSION:
                        keyLength = 40;
                        break;

                    case CAPI.CRYPT_RC2_56BIT_VERSION:
                        keyLength = 56;
                        break;

                    case CAPI.CRYPT_RC2_128BIT_VERSION:
                        keyLength = 128;
                        break;
                    }
                    // Retrieve IV if available.
                    if (rc2Parameters.fIV)
                    {
                        parameters = (byte[])rc2Parameters.rgbIV.Clone();
                    }
                }
            }
            else if (algId == CAPI.CALG_RC4 || algId == CAPI.CALG_DES || algId == CAPI.CALG_3DES)
            {
                // Retrieve the IV if available. For non RC2, the parameter contains the IV
                // (for RC4 the IV is really the salt). There are (128 - KeyLength) / 8
                // bytes of RC4 salt.
                if (algorithmIdentifier.Parameters.cbData > 0)
                {
                    if (!CAPI.DecodeObject(new IntPtr(CAPI.X509_OCTET_STRING),
                                           algorithmIdentifier.Parameters.pbData,
                                           algorithmIdentifier.Parameters.cbData,
                                           out pbParameters,
                                           out cbParameters))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }

                    if (cbParameters > Marshal.SizeOf(typeof(CAPI.CRYPTOAPI_BLOB)))
                    {
                        CAPI.CRYPTOAPI_BLOB blob = (CAPI.CRYPTOAPI_BLOB)Marshal.PtrToStructure(pbParameters.DangerousGetHandle(), typeof(CAPI.CRYPTOAPI_BLOB));

                        if (algId == CAPI.CALG_RC4)
                        {
                            if (blob.cbData > 0)
                            {
                                parameters = new byte[blob.cbData];
                                Marshal.Copy(blob.pbData, parameters, 0, parameters.Length);
                            }
                        }
                        else
                        {
                            // This should be the same as the RC4 code, but for compatibility
                            // * Allocate an array as big as the CRYPTOAPI_BLOB
                            // * Copy in the cbData value
                            // * Copy in the (pbData) value
                            //
                            // But don't copy in the pbData pointer value (or, rather, clear it out),
                            // among other things it makes decoding the same contents into two
                            // different EnvelopedCms objects say the parameters were different.
                            parameters = new byte[cbParameters];
                            Marshal.Copy(pbParameters.DangerousGetHandle(), parameters, 0, parameters.Length);
                            Array.Clear(parameters, sizeof(uint), (int)(parameters.Length - blob.cbData - sizeof(uint)));
                        }
                    }
                }

                // Determine key length.
                if (algId == CAPI.CALG_RC4)
                {
                    // For RC4, keyLength = 128 - (salt length * 8).
                    keyLength = 128 - ((int)parameters.Length * 8);
                }
                else if (algId == CAPI.CALG_DES)
                {
                    // DES key length is fixed at 64 (or 56 without the parity bits).
                    keyLength = 64;
                }
                else
                {
                    // 3DES key length is fixed at 192 (or 168 without the parity bits).
                    keyLength = 192;
                }
            }
            else
            {
                // Everything else, don't decode it as CAPI may not expose or know how.
                if (algorithmIdentifier.Parameters.cbData > 0)
                {
                    parameters = new byte[algorithmIdentifier.Parameters.cbData];
                    Marshal.Copy(algorithmIdentifier.Parameters.pbData, parameters, 0, parameters.Length);
                }
            }

            Reset(Oid.FromOidValue(algorithmIdentifier.pszObjId, OidGroup.All), keyLength, parameters);
            pbParameters.Dispose();
        }
Пример #8
0
        //
        // Constructors.
        //

        internal X500DistinguishedName(CAPI.CRYPTOAPI_BLOB encodedDistinguishedNameBlob) : base(new Oid(), encodedDistinguishedNameBlob)
        {
        }
Пример #9
0
        internal AlgorithmIdentifier(CAPI.CRYPT_ALGORITHM_IDENTIFIER algorithmIdentifier)
        {
            int  keyLength      = 0;
            uint cbDecodedValue = 0U;
            SafeLocalAllocHandle decodedValue = SafeLocalAllocHandle.InvalidHandle;

            byte[] numArray = new byte[0];
            uint   num      = X509Utils.OidToAlgId(algorithmIdentifier.pszObjId);

            switch (num)
            {
            case 26114U:
                if (algorithmIdentifier.Parameters.cbData > 0U)
                {
                    if (!CAPI.DecodeObject(new IntPtr(41L), algorithmIdentifier.Parameters.pbData, algorithmIdentifier.Parameters.cbData, out decodedValue, out cbDecodedValue))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }
                    CAPI.CRYPT_RC2_CBC_PARAMETERS rc2CbcParameters = (CAPI.CRYPT_RC2_CBC_PARAMETERS)Marshal.PtrToStructure(decodedValue.DangerousGetHandle(), typeof(CAPI.CRYPT_RC2_CBC_PARAMETERS));
                    switch (rc2CbcParameters.dwVersion)
                    {
                    case 52U:
                        keyLength = 56;
                        break;

                    case 58U:
                        keyLength = 128;
                        break;

                    case 160U:
                        keyLength = 40;
                        break;
                    }
                    if (rc2CbcParameters.fIV)
                    {
                        numArray = (byte[])rc2CbcParameters.rgbIV.Clone();
                        break;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }

            case 26625U:
            case 26113U:
            case 26115U:
                if (algorithmIdentifier.Parameters.cbData > 0U)
                {
                    if (!CAPI.DecodeObject(new IntPtr(25L), algorithmIdentifier.Parameters.pbData, algorithmIdentifier.Parameters.cbData, out decodedValue, out cbDecodedValue))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }
                    if (cbDecodedValue > 0U)
                    {
                        if ((int)num == 26625)
                        {
                            CAPI.CRYPTOAPI_BLOB cryptoapiBlob = (CAPI.CRYPTOAPI_BLOB)Marshal.PtrToStructure(decodedValue.DangerousGetHandle(), typeof(CAPI.CRYPTOAPI_BLOB));
                            if (cryptoapiBlob.cbData > 0U)
                            {
                                numArray = new byte[(IntPtr)cryptoapiBlob.cbData];
                                Marshal.Copy(cryptoapiBlob.pbData, numArray, 0, numArray.Length);
                            }
                        }
                        else
                        {
                            numArray = new byte[(IntPtr)cbDecodedValue];
                            Marshal.Copy(decodedValue.DangerousGetHandle(), numArray, 0, numArray.Length);
                        }
                    }
                }
                keyLength = (int)num != 26625 ? ((int)num != 26113 ? 192 : 64) : 128 - numArray.Length * 8;
                break;

            default:
                if (algorithmIdentifier.Parameters.cbData > 0U)
                {
                    numArray = new byte[(IntPtr)algorithmIdentifier.Parameters.cbData];
                    Marshal.Copy(algorithmIdentifier.Parameters.pbData, numArray, 0, numArray.Length);
                    break;
                }
                else
                {
                    break;
                }
            }
            this.Reset(new Oid(algorithmIdentifier.pszObjId), keyLength, numArray);
            decodedValue.Dispose();
        }
Пример #10
0
 internal CRYPT_OID_INFO(int size)
 {
     this.cbSize = (uint)size;
     this.pszOID = (string)null;
     this.pwszName = (string)null;
     this.dwGroupId = 0U;
     this.Algid = 0U;
     this.ExtraInfo = new CAPI.CRYPTOAPI_BLOB();
 }
Пример #11
0
        /// <summary>
        /// Protect
        /// </summary>
        public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
        {
            if (userData == null)
                throw new ArgumentNullException("userData");

            GCHandle pbDataIn = new GCHandle();
            GCHandle pOptionalEntropy = new GCHandle();
            CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB();

            try
            {
                pbDataIn = GCHandle.Alloc(userData, GCHandleType.Pinned);
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB();
                dataIn.cbData = (uint)userData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject();
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB();
                if (optionalEntropy != null)
                {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
                    entropy.cbData = (uint)optionalEntropy.Length;
                    entropy.pbData = pOptionalEntropy.AddrOfPinnedObject();
                }
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN;
                if (scope == DataProtectionScope.LocalMachine)
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE;
                unsafe
                {
                    if (!CAPI.CryptProtectData(new IntPtr(&dataIn),
                                                String.Empty,
                                                new IntPtr(&entropy),
                                                IntPtr.Zero,
                                                IntPtr.Zero,
                                                dwFlags,
                                                new IntPtr(&blob)))
                    {
                        int lastWin32Error = Marshal.GetLastWin32Error();

                        // One of the most common reasons that DPAPI operations fail is that the user
                        // profile is not loaded (for instance in the case of impersonation or running in a
                        // service.  In those cases, throw an exception that provides more specific details
                        // about what happened.
                        if (CAPI.ErrorMayBeCausedByUnloadedProfile(lastWin32Error))
                        {
                            throw new CryptographicException("Cryptography_DpApi_ProfileMayNotBeLoaded");
                        }
                        else
                        {
                            throw new CryptographicException(lastWin32Error);
                        }
                    }
                }

                // In some cases, the API would fail due to OOM but simply return a null pointer.
                if (blob.pbData == IntPtr.Zero)
                    throw new OutOfMemoryException();

                byte[] encryptedData = new byte[(int)blob.cbData];
                Marshal.Copy(blob.pbData, encryptedData, 0, encryptedData.Length);

                return encryptedData;
            }
            finally
            {
                if (pbDataIn.IsAllocated)
                    pbDataIn.Free();
                if (pOptionalEntropy.IsAllocated)
                    pOptionalEntropy.Free();
                if (blob.pbData != IntPtr.Zero)
                {
                    CAPI.ZeroMemory(blob.pbData, blob.cbData);
                    CAPI.LocalFree(blob.pbData);
                }
            }
        }
Пример #12
0
        public static byte[] Unprotect(byte[] encryptedData,
                                       byte[] optionalEntropy,
                                       DataProtectionScope scope)
        {
            if (encryptedData == null)
            {
                throw new ArgumentNullException("encryptedData");
            }
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows)
            {
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
            }

            GCHandle pbDataIn         = new GCHandle();
            GCHandle pOptionalEntropy = new GCHandle();

            CAPI.CRYPTOAPI_BLOB userData = new CAPI.CRYPTOAPI_BLOB();

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                pbDataIn = GCHandle.Alloc(encryptedData, GCHandleType.Pinned);
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB();
                dataIn.cbData = (uint)encryptedData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject();
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB();
                if (optionalEntropy != null)
                {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
                    entropy.cbData   = (uint)optionalEntropy.Length;
                    entropy.pbData   = pOptionalEntropy.AddrOfPinnedObject();
                }
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN;
                if (scope == DataProtectionScope.LocalMachine)
                {
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE;
                }
                unsafe {
                    if (!CAPI.CryptUnprotectData(new IntPtr(&dataIn),
                                                 IntPtr.Zero,
                                                 new IntPtr(&entropy),
                                                 IntPtr.Zero,
                                                 IntPtr.Zero,
                                                 dwFlags,
                                                 new IntPtr(&userData)))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }
                }

                // In some cases, the API would fail due to OOM but simply return a null pointer.
                if (userData.pbData == IntPtr.Zero)
                {
                    throw new OutOfMemoryException();
                }

                byte[] data = new byte[(int)userData.cbData];
                Marshal.Copy(userData.pbData, data, 0, data.Length);

                return(data);
            }
            catch (EntryPointNotFoundException) {
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
            }
            finally {
                if (pbDataIn.IsAllocated)
                {
                    pbDataIn.Free();
                }
                if (pOptionalEntropy.IsAllocated)
                {
                    pOptionalEntropy.Free();
                }
                if (userData.pbData != IntPtr.Zero)
                {
                    CAPI.CAPISafe.ZeroMemory(userData.pbData, userData.cbData);
                    CAPI.CAPISafe.LocalFree(userData.pbData);
                }
            }
        }
Пример #13
0
        internal AlgorithmIdentifier(CAPI.CRYPT_ALGORITHM_IDENTIFIER algorithmIdentifier)
        {
            int  keyLength    = 0;
            uint cbParameters = 0;
            SafeLocalAllocHandle pbParameters = SafeLocalAllocHandle.InvalidHandle;

            byte[] parameters = new byte[0];

            uint algId = X509Utils.OidToAlgId(algorithmIdentifier.pszObjId);

            if (algId == CAPI.CALG_RC2)
            {
                if (algorithmIdentifier.Parameters.cbData > 0)
                {
                    if (!CAPI.DecodeObject(new IntPtr(CAPI.PKCS_RC2_CBC_PARAMETERS),
                                           algorithmIdentifier.Parameters.pbData,
                                           algorithmIdentifier.Parameters.cbData,
                                           out pbParameters,
                                           out cbParameters))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }

                    CAPI.CRYPT_RC2_CBC_PARAMETERS rc2Parameters = (CAPI.CRYPT_RC2_CBC_PARAMETERS)Marshal.PtrToStructure(pbParameters.DangerousGetHandle(), typeof(CAPI.CRYPT_RC2_CBC_PARAMETERS));
                    switch (rc2Parameters.dwVersion)
                    {
                    case CAPI.CRYPT_RC2_40BIT_VERSION:
                        keyLength = 40;
                        break;

                    case CAPI.CRYPT_RC2_56BIT_VERSION:
                        keyLength = 56;
                        break;

                    case CAPI.CRYPT_RC2_128BIT_VERSION:
                        keyLength = 128;
                        break;
                    }
                    // Retrieve IV if available.
                    if (rc2Parameters.fIV)
                    {
                        parameters = (byte[])rc2Parameters.rgbIV.Clone();
                    }
                }
            }
            else if (algId == CAPI.CALG_RC4 || algId == CAPI.CALG_DES || algId == CAPI.CALG_3DES)
            {
                // Retrieve the IV if available. For non RC2, the parameter contains the IV
                // (for RC4 the IV is really the salt). There are (128 - KeyLength) / 8
                // bytes of RC4 salt.
                if (algorithmIdentifier.Parameters.cbData > 0)
                {
                    if (!CAPI.DecodeObject(new IntPtr(CAPI.X509_OCTET_STRING),
                                           algorithmIdentifier.Parameters.pbData,
                                           algorithmIdentifier.Parameters.cbData,
                                           out pbParameters,
                                           out cbParameters))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }

                    if (cbParameters > 0)
                    {
                        if (algId == CAPI.CALG_RC4)
                        {
                            CAPI.CRYPTOAPI_BLOB saltBlob = (CAPI.CRYPTOAPI_BLOB)Marshal.PtrToStructure(pbParameters.DangerousGetHandle(), typeof(CAPI.CRYPTOAPI_BLOB));
                            if (saltBlob.cbData > 0)
                            {
                                parameters = new byte[saltBlob.cbData];
                                Marshal.Copy(saltBlob.pbData, parameters, 0, parameters.Length);
                            }
                        }
                        else
                        {
                            parameters = new byte[cbParameters];
                            Marshal.Copy(pbParameters.DangerousGetHandle(), parameters, 0, parameters.Length);
                        }
                    }
                }

                // Determine key length.
                if (algId == CAPI.CALG_RC4)
                {
                    // For RC4, keyLength = 128 - (salt length * 8).
                    keyLength = 128 - ((int)parameters.Length * 8);
                }
                else if (algId == CAPI.CALG_DES)
                {
                    // DES key length is fixed at 64 (or 56 without the parity bits).
                    keyLength = 64;
                }
                else
                {
                    // 3DES key length is fixed at 192 (or 168 without the parity bits).
                    keyLength = 192;
                }
            }
            else
            {
                // Everything else, don't decode it as CAPI may not expose or know how.
                if (algorithmIdentifier.Parameters.cbData > 0)
                {
                    parameters = new byte[algorithmIdentifier.Parameters.cbData];
                    Marshal.Copy(algorithmIdentifier.Parameters.pbData, parameters, 0, parameters.Length);
                }
            }

            Reset(Oid.FromOidValue(algorithmIdentifier.pszObjId, OidGroup.All), keyLength, parameters);
            pbParameters.Dispose();
        }
Пример #14
0
        internal SubjectIdentifier(CAPI.CRYPTOAPI_BLOB issuer, CAPI.CRYPTOAPI_BLOB serialNumber)
        {
            bool  flag   = true;
            byte *numPtr = (byte *)(void *)serialNumber.pbData;

            for (uint index = 0U; index < serialNumber.cbData; ++index)
            {
                if ((int)*numPtr++ != 0)
                {
                    flag = false;
                    break;
                }
            }
            if (flag)
            {
                byte[] numArray = new byte[(IntPtr)issuer.cbData];
                Marshal.Copy(issuer.pbData, numArray, 0, numArray.Length);
                if (string.Compare("CN=Dummy Signer", new X500DistinguishedName(numArray).Name, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    this.Reset(SubjectIdentifierType.NoSignature, (object)null);
                    return;
                }
            }
            if (flag)
            {
                this.m_type  = SubjectIdentifierType.SubjectKeyIdentifier;
                this.m_value = (object)string.Empty;
                uint cbDecodedValue = 0U;
                SafeLocalAllocHandle decodedValue = SafeLocalAllocHandle.InvalidHandle;
                if (!CAPI.DecodeObject(new IntPtr(7L), issuer.pbData, issuer.cbData, out decodedValue, out cbDecodedValue))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }
                using (decodedValue)
                {
                    CAPI.CERT_NAME_INFO certNameInfo = (CAPI.CERT_NAME_INFO)Marshal.PtrToStructure(decodedValue.DangerousGetHandle(), typeof(CAPI.CERT_NAME_INFO));
                    for (uint index1 = 0U; index1 < certNameInfo.cRDN; ++index1)
                    {
                        CAPI.CERT_RDN certRdn = (CAPI.CERT_RDN)Marshal.PtrToStructure(new IntPtr((long)certNameInfo.rgRDN + (long)index1 * (long)Marshal.SizeOf(typeof(CAPI.CERT_RDN))), typeof(CAPI.CERT_RDN));
                        for (uint index2 = 0U; index2 < certRdn.cRDNAttr; ++index2)
                        {
                            CAPI.CERT_RDN_ATTR certRdnAttr = (CAPI.CERT_RDN_ATTR)Marshal.PtrToStructure(new IntPtr((long)certRdn.rgRDNAttr + (long)index2 * (long)Marshal.SizeOf(typeof(CAPI.CERT_RDN_ATTR))), typeof(CAPI.CERT_RDN_ATTR));
                            if (string.Compare("1.3.6.1.4.1.311.10.7.1", certRdnAttr.pszObjId, StringComparison.OrdinalIgnoreCase) == 0 && (int)certRdnAttr.dwValueType == 2)
                            {
                                byte[] numArray = new byte[(IntPtr)certRdnAttr.Value.cbData];
                                Marshal.Copy(certRdnAttr.Value.pbData, numArray, 0, numArray.Length);
                                this.Reset(SubjectIdentifierType.SubjectKeyIdentifier, (object)X509Utils.EncodeHexString(numArray));
                                return;
                            }
                        }
                    }
                }
                throw new CryptographicException(-2146889715);
            }
            else
            {
                CAPI.CERT_ISSUER_SERIAL_NUMBER pIssuerAndSerial;
                pIssuerAndSerial.Issuer       = issuer;
                pIssuerAndSerial.SerialNumber = serialNumber;
                this.Reset(SubjectIdentifierType.IssuerAndSerialNumber, (object)PkcsUtils.DecodeIssuerSerial(pIssuerAndSerial));
            }
        }
Пример #15
0
 internal AsnEncodedData(Oid oid, CAPI.CRYPTOAPI_BLOB encodedBlob) : this(oid, CAPI.BlobToByteArray(encodedBlob))
 {
 }
Пример #16
0
        public static byte[] Protect(byte[] userData,
                                     byte[] optionalEntropy,
                                     DataProtectionScope scope)
        {
            if (userData == null)
            {
                throw new ArgumentNullException("userData");
            }
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows)
            {
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
            }

            GCHandle pbDataIn         = new GCHandle();
            GCHandle pOptionalEntropy = new GCHandle();

            CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB();

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                pbDataIn = GCHandle.Alloc(userData, GCHandleType.Pinned);
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB();
                dataIn.cbData = (uint)userData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject();
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB();
                if (optionalEntropy != null)
                {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
                    entropy.cbData   = (uint)optionalEntropy.Length;
                    entropy.pbData   = pOptionalEntropy.AddrOfPinnedObject();
                }
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN;
                if (scope == DataProtectionScope.LocalMachine)
                {
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE;
                }
                unsafe {
                    if (!CAPI.CryptProtectData(new IntPtr(&dataIn),
                                               String.Empty,
                                               new IntPtr(&entropy),
                                               IntPtr.Zero,
                                               IntPtr.Zero,
                                               dwFlags,
                                               new IntPtr(&blob)))
                    {
                        int lastWin32Error = Marshal.GetLastWin32Error();

                        // One of the most common reasons that DPAPI operations fail is that the user
                        // profile is not loaded (for instance in the case of impersonation or running in a
                        // service.  In those cases, throw an exception that provides more specific details
                        // about what happened.
                        if (CAPI.ErrorMayBeCausedByUnloadedProfile(lastWin32Error))
                        {
                            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_ProfileMayNotBeLoaded"));
                        }
                        else
                        {
                            throw new CryptographicException(lastWin32Error);
                        }
                    }
                }

                // In some cases, the API would fail due to OOM but simply return a null pointer.
                if (blob.pbData == IntPtr.Zero)
                {
                    throw new OutOfMemoryException();
                }

                byte[] encryptedData = new byte[(int)blob.cbData];
                Marshal.Copy(blob.pbData, encryptedData, 0, encryptedData.Length);

                return(encryptedData);
            }
            catch (EntryPointNotFoundException) {
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
            }
            finally {
                if (pbDataIn.IsAllocated)
                {
                    pbDataIn.Free();
                }
                if (pOptionalEntropy.IsAllocated)
                {
                    pOptionalEntropy.Free();
                }
                if (blob.pbData != IntPtr.Zero)
                {
                    CAPI.CAPISafe.ZeroMemory(blob.pbData, blob.cbData);
                    CAPI.CAPISafe.LocalFree(blob.pbData);
                }
            }
        }
        public X509Certificate2Collection Find(X509FindType findType, object findValue, bool validOnly)
        {
            DiagnosticUtility.DebugAssert(!this.certStoreHandle.IsInvalid, "");

            uint dwFindType;
            SafeHGlobalHandle          pvFindPara   = SafeHGlobalHandle.InvalidHandle;
            SafeCertContextHandle      pCertContext = SafeCertContextHandle.InvalidHandle;
            X509Certificate2Collection result       = new X509Certificate2Collection();
            SafeHGlobalHandle          pvTemp       = SafeHGlobalHandle.InvalidHandle;
            string strFindValue;

            byte[] bytes;

            try
            {
                switch (findType)
                {
                case X509FindType.FindBySubjectName:
                    strFindValue = findValue as string;
                    if (strFindValue == null)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType())));
                    }

                    dwFindType = CAPI.CERT_FIND_SUBJECT_STR;
                    pvFindPara = SafeHGlobalHandle.AllocHGlobal(strFindValue);
                    break;

                case X509FindType.FindByThumbprint:
                    bytes = findValue as byte[];
                    if (bytes == null)
                    {
                        strFindValue = findValue as string;
                        if (strFindValue == null)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType())));
                        }

                        bytes = SecurityUtils.DecodeHexString(strFindValue);
                    }

                    CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB();
                    pvTemp      = SafeHGlobalHandle.AllocHGlobal(bytes);
                    blob.pbData = pvTemp.DangerousGetHandle();
                    blob.cbData = (uint)bytes.Length;
                    dwFindType  = CAPI.CERT_FIND_HASH;
                    pvFindPara  = SafeHGlobalHandle.AllocHGlobal(CAPI.CRYPTOAPI_BLOB.Size);
                    Marshal.StructureToPtr(blob, pvFindPara.DangerousGetHandle(), false);
                    break;

                case X509FindType.FindBySubjectDistinguishedName:
                    if (!(findValue is string))
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType())));
                    }

                    dwFindType = CAPI.CERT_FIND_ANY;
                    break;

                case X509FindType.FindByIssuerName:
                    strFindValue = findValue as string;
                    if (strFindValue == null)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType())));
                    }

                    dwFindType = CAPI.CERT_FIND_ISSUER_STR;
                    pvFindPara = SafeHGlobalHandle.AllocHGlobal(strFindValue);
                    break;

                case X509FindType.FindByIssuerDistinguishedName:
                    if (!(findValue is string))
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType())));
                    }

                    dwFindType = CAPI.CERT_FIND_ANY;
                    break;

                case X509FindType.FindBySerialNumber:
                    bytes = findValue as byte[];
                    if (bytes == null)
                    {
                        strFindValue = findValue as string;
                        if (strFindValue == null)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType())));
                        }

                        bytes = SecurityUtils.DecodeHexString(strFindValue);

                        // reverse bits
                        int len = bytes.Length;
                        for (int i = 0, j = len - 1; i < bytes.Length / 2; ++i, --j)
                        {
                            byte tmp = bytes[i];
                            bytes[i] = bytes[j];
                            bytes[j] = tmp;
                        }
                    }
                    findValue  = bytes;
                    dwFindType = CAPI.CERT_FIND_ANY;
                    break;

                case X509FindType.FindBySubjectKeyIdentifier:
                    bytes = findValue as byte[];
                    if (bytes == null)
                    {
                        strFindValue = findValue as string;
                        if (strFindValue == null)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType())));
                        }

                        bytes = SecurityUtils.DecodeHexString(strFindValue);
                    }
                    findValue  = bytes;
                    dwFindType = CAPI.CERT_FIND_ANY;
                    break;

                default:
                    // Fallback to CLR implementation
                    X509Store store = new X509Store(this.certStoreHandle.DangerousGetHandle());
                    try
                    {
                        return(store.Certificates.Find(findType, findValue, validOnly));
                    }
                    finally
                    {
                        store.Close();
                    }
                }

#pragma warning suppress 56523 // We are not interested in CRYPT_E_NOT_FOUND error, it return null anyway.
                pCertContext = CAPI.CertFindCertificateInStore(this.certStoreHandle,
                                                               CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                               0,
                                                               dwFindType,
                                                               pvFindPara,
                                                               pCertContext);

                while (pCertContext != null && !pCertContext.IsInvalid)
                {
                    X509Certificate2 cert;
                    if (TryGetMatchingX509Certificate(pCertContext.DangerousGetHandle(), findType,
                                                      dwFindType, findValue, validOnly, out cert))
                    {
                        result.Add(cert);
                    }

                    // CER
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try { }
                    finally
                    {
                        // Suppress the finalizer
#pragma warning suppress 56508 // CertFindCertificateInStore will release the prev one.
                        GC.SuppressFinalize(pCertContext);
#pragma warning suppress 56523 // We are not interested in CRYPT_E_NOT_FOUND error, it return null anyway.
                        pCertContext = CAPI.CertFindCertificateInStore(this.certStoreHandle,
                                                                       CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                                       0,
                                                                       dwFindType,
                                                                       pvFindPara,
                                                                       pCertContext);
                    }
                }
            }
            finally
            {
                if (pCertContext != null)
                {
                    pCertContext.Close();
                }
                pvFindPara.Close();
                pvTemp.Close();
            }
            return(result);
        }
Пример #18
0
        /// <summary>
        /// Unprotect
        /// </summary>
        public static byte[] Unprotect(byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope)
        {
            if (encryptedData == null)
                throw new ArgumentNullException("encryptedData");

            GCHandle pbDataIn = new GCHandle();
            GCHandle pOptionalEntropy = new GCHandle();
            CAPI.CRYPTOAPI_BLOB userData = new CAPI.CRYPTOAPI_BLOB();

            try
            {
                pbDataIn = GCHandle.Alloc(encryptedData, GCHandleType.Pinned);
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB();
                dataIn.cbData = (uint)encryptedData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject();
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB();
                if (optionalEntropy != null)
                {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
                    entropy.cbData = (uint)optionalEntropy.Length;
                    entropy.pbData = pOptionalEntropy.AddrOfPinnedObject();
                }
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN;
                if (scope == DataProtectionScope.LocalMachine)
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE;
                unsafe
                {
                    if (!CAPI.CryptUnprotectData(new IntPtr(&dataIn),
                                                 IntPtr.Zero,
                                                 new IntPtr(&entropy),
                                                 IntPtr.Zero,
                                                 IntPtr.Zero,
                                                 dwFlags,
                                                 new IntPtr(&userData)))
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                }

                // In some cases, the API would fail due to OOM but simply return a null pointer.
                if (userData.pbData == IntPtr.Zero)
                    throw new OutOfMemoryException();

                byte[] data = new byte[(int)userData.cbData];
                Marshal.Copy(userData.pbData, data, 0, data.Length);

                return data;
            }
            finally
            {
                if (pbDataIn.IsAllocated)
                    pbDataIn.Free();
                if (pOptionalEntropy.IsAllocated)
                    pOptionalEntropy.Free();
                if (userData.pbData != IntPtr.Zero)
                {
                    CAPI.ZeroMemory(userData.pbData, userData.cbData);
                    CAPI.LocalFree(userData.pbData);
                }
            }
        }
Пример #19
0
 internal CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA(int size)
 {
     this.cbSize = (uint)size;
     this.dwSignerIndex = 0U;
     this.blob = new CAPI.CRYPTOAPI_BLOB();
 }