1

Using the windows-rs crate, I'm trying to import an RSA key pair as a BCRYPT_RSAFULLPRIVATE_BLOB following these instructions: https://learn.microsoft.com/en-us/windows/win32/seccng/key-import-and-export

To import a persisted key:

  1. Create a persisted key by using the NCryptCreatePersistedKey function.
  2. Set any desired properties on the key object by using the NCryptSetProperty function.
  3. Set the import key BLOB as a property on the key, with the BLOB type as the property name.
  4. Finalize the persisted key import by using the NCryptFinalizeKey function.

I'm doing:

unsafe {
    let mut h = NCRYPT_KEY_HANDLE(0);
    NCryptCreatePersistedKey(
        self.handle,
        &mut h,
        to_pcwstr(BCRYPT_RSA_ALGORITHM),
        to_pcwstr(key_name),
        CERT_KEY_SPEC(0),
        if overwrite {
            NCRYPT_OVERWRITE_KEY_FLAG
        } else {
            NCRYPT_FLAGS(0)
        },
    )?;

    let prop_handle = NCRYPT_HANDLE(h.0);

    println!("set export policy");
    let value =
        (NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG).to_be_bytes();
    let value: *const u8 = addr_of!(value[0]);
    NCryptSetProperty(
        prop_handle,
        to_pcwstr(NCRYPT_EXPORT_POLICY_PROPERTY),
        value,
        std::mem::size_of::<u32>() as u32,
        NCRYPT_PERSIST_FLAG | NCRYPT_SILENT_FLAG,
    )?;

    println!("set blob prop");
    NCryptSetProperty(
        prop_handle,
        to_pcwstr(BCRYPT_RSAFULLPRIVATE_BLOB),
        to_import.as_ptr(), // to_import is a Vec<u8>, structured as https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/ns-bcrypt-bcrypt_rsakey_blob
        to_import.len() as u32,
        NCRYPT_PERSIST_FLAG | NCRYPT_SILENT_FLAG,
    )?;
    println!("finalize key");
    NCryptFinalizeKey(h, NCRYPT_SILENT_FLAG)?;
    h
}

but I encounter a failure on the first call to NCryptSetProperty with NTE_NOT_SUPPORTED error code.

The storage used is StorageProviderType::Tpm as StorageProviderType::Soft doesn't work on my system for some reason (can't open it)

What am I missing? Can't we set NCRYPT_EXPORT_POLICY_PROPERTY for a RSA key?

Geob-o-matic
  • 5,940
  • 4
  • 35
  • 41
  • Is this a "how do I call the API" question? Then reproduce the problem in C. Or is it a "In C this works, what's wrong with my Rust translation" question? – Ben Voigt Jun 10 '22 at 14:55
  • @BenVoigt Thanks for your answer :) I've reproduce the error in C, when using MS_PLATFORM_CRYPTO_PROVIDER. It does work in C using MS_KEY_STORAGE_PROVIDER. But in Rust, I often encounter code: 0xC0000225 when opening this provider and I can't find any clue on why :-/ It works like once every now and then :-/ – Geob-o-matic Jun 13 '22 at 11:04
  • Which provider do you want to use? If you want Rust code behaving like the working C code (using MS_KEY_STORAGE_PROVIDER) then I suggest you add the working C version into your question; that will allow Rust users with experience in DLL calls to help you even if they know nothing about the cryptographic providers. – Ben Voigt Jun 13 '22 at 13:56
  • @BenVoigt Thanks for your answer again! I found out what was wrong with my code (https://users.rust-lang.org/t/why-the-compiler-didnt-catch-this-one-pointer-vs-lifetime/76987). But it doesn't explain why I can't set NCRYPT_EXPORT_POLICY_PROPERTY with a MS_PLATFORM_CRYPTO_PROVIDER (neither in Rust nor C) – Geob-o-matic Jun 15 '22 at 14:05

0 Answers0