internal static ErrorCode NCryptGetIntProperty(SafeNCryptHandle hObject, string pszProperty, ref int result) { int cbResult; ErrorCode errorCode; unsafe { fixed (int* pResult = &result) { errorCode = Interop.NCrypt.NCryptGetProperty( hObject, pszProperty, pResult, sizeof(int), out cbResult, CngPropertyOptions.None); } } if (errorCode == ErrorCode.ERROR_SUCCESS) { Debug.Assert(cbResult == sizeof(int)); } return errorCode; }
internal static extern unsafe ErrorCode NCryptSetProperty(SafeNCryptHandle hObject, string pszProperty, [In] void* pbInput, int cbInput, CngPropertyOptions dwFlags);
internal static extern unsafe ErrorCode NCryptGetProperty(SafeNCryptHandle hObject, string pszProperty, [Out] void* pbOutput, int cbOutput, out int pcbResult, CngPropertyOptions dwFlags);
private static void SetProperty(SafeNCryptHandle ncryptHandle, string propertyName, byte[] value) { Debug.Assert(!ncryptHandle.IsInvalid); unsafe { fixed (byte* pBlob = value) { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty( ncryptHandle, propertyName, pBlob, value.Length, CngPropertyOptions.None); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } } } }
internal static void SetCurveName(SafeNCryptHandle keyHandle, string curveName) { unsafe { byte[] curveNameBytes = new byte[(curveName.Length + 1) * sizeof(char)]; // +1 to add trailing null System.Text.Encoding.Unicode.GetBytes(curveName, 0, curveName.Length, curveNameBytes, 0); SetProperty(keyHandle, KeyPropertyName.ECCCurveName, curveNameBytes); } }
internal static string GetCurveName(SafeNCryptHandle ncryptHandle) { Debug.Assert(!ncryptHandle.IsInvalid); return GetPropertyAsString(ncryptHandle, KeyPropertyName.ECCCurveName, CngPropertyOptions.None); }
/// <summary> /// Retrieve a well-known CNG string property. (Note: desktop compat: this helper likes to return special values rather than throw exceptions for missing /// or ill-formatted property values. Only use it for well-known properties that are unlikely to be ill-formatted.) /// </summary> private static string GetPropertyAsString(SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) { Debug.Assert(!ncryptHandle.IsInvalid); byte[] value = GetProperty(ncryptHandle, propertyName, options); if (value == null) return null; // Desktop compat: return null if key not present. if (value.Length == 0) return string.Empty; // Desktop compat: return empty if property value is 0-length. unsafe { fixed (byte* pValue = value) { string valueAsString = Marshal.PtrToStringUni((IntPtr)pValue); return valueAsString; } } }
/// <summary> /// Returns a CNG key property. /// </summary> /// <returns> /// null - if property not defined on key. /// throws - for any other type of error. /// </returns> private static byte[] GetProperty(SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options) { Debug.Assert(!ncryptHandle.IsInvalid); unsafe { int numBytesNeeded; ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, null, 0, out numBytesNeeded, options); if (errorCode == ErrorCode.NTE_NOT_FOUND) return null; if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); byte[] propertyValue = new byte[numBytesNeeded]; fixed (byte* pPropertyValue = propertyValue) { errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, pPropertyValue, propertyValue.Length, out numBytesNeeded, options); } if (errorCode == ErrorCode.NTE_NOT_FOUND) return null; if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); Array.Resize(ref propertyValue, numBytesNeeded); return propertyValue; } }