1
Vote

GetKeys extension method doesn't pass openOptions to CngKey.Open

description

The following code results in a CryptoGraphicException with text "Keyset does not exist" when you specify CngKeyOpenOptions.MachineKey because the key container names returned are Machine keys and when CngKey.Open is called the option is not passed and it attempts to open the key name as a user key.
    [SecurityTreatAsSafe, SecurityCritical]
    public static IEnumerable GetKeys(this CngProvider provider, CngKeyOpenOptions openOptions)
    {
        using (SafeNCryptProviderHandle handle = provider.OpenProvider())
        {
            Security.Cryptography.NCryptNative.NCryptKeyName[] nameArray = Security.Cryptography.NCryptNative.EnumerateKeys(handle, openOptions);
            CngKey[] keyArray = new CngKey[nameArray.Length];
            for (int i = 0; i < keyArray.Length; i++)
            {
                keyArray[i] = CngKey.Open(nameArray[i].pszName, provider);
            }
            return keyArray;
        }
    }
The fix is:
    [SecurityTreatAsSafe, SecurityCritical]
    public static IEnumerable GetKeys(this CngProvider provider, CngKeyOpenOptions openOptions)
    {
        using (SafeNCryptProviderHandle handle = provider.OpenProvider())
        {
            Security.Cryptography.NCryptNative.NCryptKeyName[] nameArray = Security.Cryptography.NCryptNative.EnumerateKeys(handle, openOptions);
            CngKey[] keyArray = new CngKey[nameArray.Length];
            for (int i = 0; i < keyArray.Length; i++)
            {
                keyArray[i] = CngKey.Open(nameArray[i].pszName, provider, openOptions);
            }
            return keyArray;
        }
    }
This post looks awful because there is no editor formatting available at the moment in either IE8 or Chrome. Ugh.

comments