Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/bcrypt/bcrypt_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 9fb9b6adf87..73071d70992 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1404,7 +1404,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP *ret_key = key; return STATUS_SUCCESS; } - else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB )) + else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ) || !wcscmp( type, BCRYPT_PUBLIC_KEY_BLOB )) { BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/ncrypt/Makefile.in | 1 + dlls/ncrypt/main.c | 101 +++++++++++++--------------------- dlls/ncrypt/ncrypt_internal.h | 30 ++-------- dlls/ncrypt/tests/ncrypt.c | 2 + 4 files changed, 45 insertions(+), 89 deletions(-)
diff --git a/dlls/ncrypt/Makefile.in b/dlls/ncrypt/Makefile.in index ad3ed409961..58ec6b3456b 100644 --- a/dlls/ncrypt/Makefile.in +++ b/dlls/ncrypt/Makefile.in @@ -1,5 +1,6 @@ IMPORTLIB = ncrypt MODULE = ncrypt.dll +IMPORTS = bcrypt
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 68d9d884618..2804708f10f 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -88,20 +88,14 @@ SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
static SECURITY_STATUS free_key_object(struct key *key) { - switch (key->alg) - { - case RSA: - { - free(key->rsa.modulus); - free(key->rsa.public_exp); - free(key->rsa.prime1); - free(key->rsa.prime2); - break; - } - default: - WARN("invalid key %p\n", key); - return NTE_INVALID_HANDLE; - } + NTSTATUS bcrypt_ret; + + bcrypt_ret = BCryptDestroyKey(key->bcrypt_key); + if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE; + + bcrypt_ret = BCryptCloseAlgorithmProvider(key->alg_prov, 0); + if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE; + return ERROR_SUCCESS; }
@@ -246,6 +240,7 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H BYTE *data, DWORD datasize, DWORD flags) { BCRYPT_KEY_BLOB *header = (BCRYPT_KEY_BLOB *)data; + struct object *key_object;
TRACE("(%#Ix, %#Ix, %s, %p, %p, %p, %lu, %#lx): stub\n", provider, decrypt_key, wine_dbgstr_w(type), params, handle, data, datasize, flags); @@ -270,70 +265,48 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H return NTE_BAD_FLAGS; }
- switch (header->Magic) + if(!(key_object = allocate_object(KEY))) + { + ERR("Error allocating memory\n"); + return NTE_NO_MEMORY; + } + + key_object->key.storage_prov = provider; + switch(header->Magic) { + case BCRYPT_RSAFULLPRIVATE_MAGIC: + case BCRYPT_RSAPRIVATE_MAGIC: case BCRYPT_RSAPUBLIC_MAGIC: { - DWORD expected_size; - struct object *object; - struct key *key; - BYTE *public_exp, *modulus; - BCRYPT_RSAKEY_BLOB *rsaheader = (BCRYPT_RSAKEY_BLOB *)data; - - if (datasize < sizeof(*rsaheader)) + NTSTATUS ret; + BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data; + ret = BCryptOpenAlgorithmProvider(&key_object->key.alg_prov, BCRYPT_RSA_ALGORITHM, NULL, 0); + if(ret != ERROR_SUCCESS) { - ERR("Invalid buffer size.\n"); - return NTE_BAD_DATA; + ERR("Error opening algorithm provider\n"); + return NTE_INTERNAL_ERROR; } - - expected_size = sizeof(*rsaheader) + rsaheader->cbPublicExp + rsaheader->cbModulus; - if (datasize != expected_size) + ret = BCryptImportKeyPair(key_object->key.alg_prov, NULL, type, &key_object->key.bcrypt_key, data, datasize, 0); + if(ret != ERROR_SUCCESS) { - ERR("Invalid buffer size.\n"); - return NTE_BAD_DATA; + ERR("Error importing keypair with bcrypt %#lx\n", ret); + return NTE_INTERNAL_ERROR; }
- if (!(object = allocate_object(KEY))) - { - ERR("Error allocating memory.\n"); - return NTE_NO_MEMORY; - } - - key = &object->key; - key->alg = RSA; - key->rsa.bit_length = rsaheader->BitLength; - key->rsa.public_exp_size = rsaheader->cbPublicExp; - key->rsa.modulus_size = rsaheader->cbModulus; - if (!(key->rsa.public_exp = malloc(rsaheader->cbPublicExp))) - { - ERR("Error allocating memory.\n"); - free(object); - return NTE_NO_MEMORY; - } - if (!(key->rsa.modulus = malloc(rsaheader->cbModulus))) - { - ERR("Error allocating memory.\n"); - free(key->rsa.public_exp); - free(object); - return NTE_NO_MEMORY; - } - - public_exp = &data[sizeof(*rsaheader)]; /* The public exp is after the header. */ - modulus = &public_exp[rsaheader->cbPublicExp]; /* The modulus is after the public exponent. */ - memcpy(key->rsa.public_exp, public_exp, rsaheader->cbPublicExp); - memcpy(key->rsa.modulus, modulus, rsaheader->cbModulus); - - set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)L"RSA", sizeof(L"RSA")); - set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&key->rsa.bit_length, sizeof(key->rsa.bit_length)); - set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider)); - *handle = (NCRYPT_KEY_HANDLE)object; + set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE)); + set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); + set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength)); break; } default: - FIXME("Unhandled key magic %#lx.\n", header->Magic); + { + FIXME("Unhandled key magic %#lx\n", header->Magic); return NTE_INVALID_PARAMETER; + break; + } }
+ *handle = (NCRYPT_KEY_HANDLE)key_object; return ERROR_SUCCESS; }
diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h index 3966dd73ed6..2d916d4fbd8 100644 --- a/dlls/ncrypt/ncrypt_internal.h +++ b/dlls/ncrypt/ncrypt_internal.h @@ -16,34 +16,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-enum key_algorithm -{ - DH, - DSA, - ECC, - RSA, -}; - -struct rsa_key -{ - DWORD bit_length; - DWORD public_exp_size; - BYTE *public_exp; - DWORD modulus_size; - BYTE *modulus; - DWORD prime1_size; - BYTE *prime1; - DWORD prime2_size; - BYTE *prime2; -}; +#include <ncrypt.h> +#include <bcrypt.h>
struct key { - enum key_algorithm alg; - union - { - struct rsa_key rsa; - }; + NCRYPT_PROV_HANDLE storage_prov; + BCRYPT_ALG_HANDLE alg_prov; + BCRYPT_KEY_HANDLE bcrypt_key; };
struct storage_provider diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index d1bcbbcab2a..8080e465527 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -123,6 +123,7 @@ static void test_key_import_rsa(void) ok(key, "got null handle\n"); NCryptFreeObject(key);
+ todo_wine{ ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob_with_invalid_publicexp_size, sizeof(rsa_key_blob_with_invalid_publicexp_size), 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret); @@ -132,6 +133,7 @@ static void test_key_import_rsa(void)
ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob, sizeof(rsa_key_blob) + 1, 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret); + }
NCryptFreeObject(prov); }
On Tue, 2022-03-01 at 19:34 -0300, Santino Mazza wrote: Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/ncrypt/Makefile.in | 1 + dlls/ncrypt/main.c | 101 +++++++++++++--------------------- dlls/ncrypt/ncrypt_internal.h | 30 ++-------- dlls/ncrypt/tests/ncrypt.c | 2 + 4 files changed, 45 insertions(+), 89 deletions(-)
diff --git a/dlls/ncrypt/Makefile.in b/dlls/ncrypt/Makefile.in index ad3ed409961..58ec6b3456b 100644 --- a/dlls/ncrypt/Makefile.in +++ b/dlls/ncrypt/Makefile.in @@ -1,5 +1,6 @@ IMPORTLIB = ncrypt MODULE = ncrypt.dll +IMPORTS = bcrypt
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 68d9d884618..2804708f10f 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -88,20 +88,14 @@ SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
static SECURITY_STATUS free_key_object(struct key *key) { - switch (key->alg) - { - case RSA: - { - free(key->rsa.modulus); - free(key->rsa.public_exp); - free(key->rsa.prime1); - free(key->rsa.prime2); - break; - } - default: - WARN("invalid key %p\n", key); - return NTE_INVALID_HANDLE; - } + NTSTATUS bcrypt_ret; + + bcrypt_ret = BCryptDestroyKey(key->bcrypt_key); + if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE;
+ bcrypt_ret = BCryptCloseAlgorithmProvider(key->alg_prov, 0); + if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE; +
There's no need to check for failure here. If BCryptDestroyKey() would fail you would leak the algorithm handle.
return ERROR_SUCCESS; }
@@ -246,6 +240,7 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H BYTE *data, DWORD datasize, DWORD flags) { BCRYPT_KEY_BLOB *header = (BCRYPT_KEY_BLOB *)data; + struct object *key_object;
TRACE("(%#Ix, %#Ix, %s, %p, %p, %p, %lu, %#lx): stub\n", provider, decrypt_key, wine_dbgstr_w(type), params, handle, data, datasize, flags); @@ -270,70 +265,48 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H return NTE_BAD_FLAGS; }
- switch (header->Magic) + if(!(key_object = allocate_object(KEY))) + { + ERR("Error allocating memory\n"); + return NTE_NO_MEMORY; + } + + key_object->key.storage_prov = provider; + switch(header->Magic) { + case BCRYPT_RSAFULLPRIVATE_MAGIC: + case BCRYPT_RSAPRIVATE_MAGIC: case BCRYPT_RSAPUBLIC_MAGIC: { - DWORD expected_size; - struct object *object; - struct key *key; - BYTE *public_exp, *modulus; - BCRYPT_RSAKEY_BLOB *rsaheader = (BCRYPT_RSAKEY_BLOB *)data; - - if (datasize < sizeof(*rsaheader)) + NTSTATUS ret; + BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data; + ret = BCryptOpenAlgorithmProvider(&key_object->key.alg_prov, BCRYPT_RSA_ALGORITHM, NULL, 0); + if(ret != ERROR_SUCCESS) { - ERR("Invalid buffer size.\n"); - return NTE_BAD_DATA; + ERR("Error opening algorithm provider\n"); + return NTE_INTERNAL_ERROR;
Should we return the error from BCryptOpenAlgorithmProvider() here?
} - - expected_size = sizeof(*rsaheader) + rsaheader->cbPublicExp + rsaheader->cbModulus; - if (datasize != expected_size) + ret = BCryptImportKeyPair(key_object->key.alg_prov, NULL, type, &key_object->key.bcrypt_key, data, datasize, 0); + if(ret != ERROR_SUCCESS) { - ERR("Invalid buffer size.\n"); - return NTE_BAD_DATA; + ERR("Error importing keypair with bcrypt %#lx\n", ret); + return NTE_INTERNAL_ERROR;
And return the error from BCryptImportKeyPair() here?
}
- if (!(object = allocate_object(KEY))) - { - ERR("Error allocating memory.\n"); - return NTE_NO_MEMORY; - } - - key = &object->key; - key->alg = RSA; - key->rsa.bit_length = rsaheader->BitLength; - key->rsa.public_exp_size = rsaheader->cbPublicExp; - key->rsa.modulus_size = rsaheader->cbModulus; - if (!(key->rsa.public_exp = malloc(rsaheader->cbPublicExp))) - { - ERR("Error allocating memory.\n"); - free(object); - return NTE_NO_MEMORY; - } - if (!(key->rsa.modulus = malloc(rsaheader->cbModulus))) - { - ERR("Error allocating memory.\n"); - free(key->rsa.public_exp); - free(object); - return NTE_NO_MEMORY; - } - - public_exp = &data[sizeof(*rsaheader)]; /* The public exp is after the header. */ - modulus = &public_exp[rsaheader->cbPublicExp]; /* The modulus is after the public exponent. */ - memcpy(key->rsa.public_exp, public_exp, rsaheader->cbPublicExp); - memcpy(key->rsa.modulus, modulus, rsaheader->cbModulus); - - set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)L"RSA", sizeof(L"RSA")); - set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&key->rsa.bit_length, sizeof(key->rsa.bit_length)); - set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider)); - *handle = (NCRYPT_KEY_HANDLE)object; + set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE)); + set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); + set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength)); break; } default: - FIXME("Unhandled key magic %#lx.\n", header->Magic); + { + FIXME("Unhandled key magic %#lx\n", header->Magic); return NTE_INVALID_PARAMETER; + break; + } }
+ *handle = (NCRYPT_KEY_HANDLE)key_object; return ERROR_SUCCESS; }
diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h index 3966dd73ed6..2d916d4fbd8 100644 --- a/dlls/ncrypt/ncrypt_internal.h +++ b/dlls/ncrypt/ncrypt_internal.h @@ -16,34 +16,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-enum key_algorithm -{ - DH, - DSA, - ECC, - RSA, -}; - -struct rsa_key -{ - DWORD bit_length; - DWORD public_exp_size; - BYTE *public_exp; - DWORD modulus_size; - BYTE *modulus; - DWORD prime1_size; - BYTE *prime1; - DWORD prime2_size; - BYTE *prime2; -}; +#include <ncrypt.h> +#include <bcrypt.h>
struct key { - enum key_algorithm alg; - union - { - struct rsa_key rsa; - }; + NCRYPT_PROV_HANDLE storage_prov; + BCRYPT_ALG_HANDLE alg_prov; + BCRYPT_KEY_HANDLE bcrypt_key; };
struct storage_provider diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index d1bcbbcab2a..8080e465527 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -123,6 +123,7 @@ static void test_key_import_rsa(void) ok(key, "got null handle\n"); NCryptFreeObject(key);
+ todo_wine{ ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob_with_invalid_publicexp_size, sizeof(rsa_key_blob_with_invalid_publicexp_size), 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret); @@ -132,6 +133,7 @@ static void test_key_import_rsa(void)
ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob, sizeof(rsa_key_blob) + 1, 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret); + }
NCryptFreeObject(prov); }
You should restructure your patches so that you don't have to reintroduce todo_wine statements.
On 2/3/22 06:27, Hans Leidekker wrote:
On Tue, 2022-03-01 at 19:34 -0300, Santino Mazza wrote: Signed-off-by: Santino Mazza mazzasantino1206@gmail.com
dlls/ncrypt/Makefile.in | 1 + dlls/ncrypt/main.c | 101 +++++++++++++--------------------- dlls/ncrypt/ncrypt_internal.h | 30 ++-------- dlls/ncrypt/tests/ncrypt.c | 2 + 4 files changed, 45 insertions(+), 89 deletions(-)
diff --git a/dlls/ncrypt/Makefile.in b/dlls/ncrypt/Makefile.in index ad3ed409961..58ec6b3456b 100644 --- a/dlls/ncrypt/Makefile.in +++ b/dlls/ncrypt/Makefile.in @@ -1,5 +1,6 @@ IMPORTLIB = ncrypt MODULE = ncrypt.dll +IMPORTS = bcrypt
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 68d9d884618..2804708f10f 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -88,20 +88,14 @@ SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
static SECURITY_STATUS free_key_object(struct key *key) {
- switch (key->alg)
- {
- case RSA:
- {
free(key->rsa.modulus);
free(key->rsa.public_exp);
free(key->rsa.prime1);
free(key->rsa.prime2);
break;
- }
- default:
WARN("invalid key %p\n", key);
return NTE_INVALID_HANDLE;
- }
- NTSTATUS bcrypt_ret;
- bcrypt_ret = BCryptDestroyKey(key->bcrypt_key);
- if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE;
- bcrypt_ret = BCryptCloseAlgorithmProvider(key->alg_prov, 0);
- if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE;
There's no need to check for failure here. If BCryptDestroyKey() would fail you would leak the algorithm handle.
return ERROR_SUCCESS; }
@@ -246,6 +240,7 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H BYTE *data, DWORD datasize, DWORD flags) { BCRYPT_KEY_BLOB *header = (BCRYPT_KEY_BLOB *)data;
- struct object *key_object;
TRACE("(%#Ix, %#Ix, %s, %p, %p, %p, %lu, %#lx): stub\n", provider, decrypt_key, wine_dbgstr_w(type), params, handle, data, datasize, flags); @@ -270,70 +265,48 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H return NTE_BAD_FLAGS; }
- switch (header->Magic)
- if(!(key_object = allocate_object(KEY)))
- {
ERR("Error allocating memory\n");
return NTE_NO_MEMORY;
- }
- key_object->key.storage_prov = provider;
- switch(header->Magic)
{
- case BCRYPT_RSAFULLPRIVATE_MAGIC:
- case BCRYPT_RSAPRIVATE_MAGIC:
case BCRYPT_RSAPUBLIC_MAGIC: {
DWORD expected_size;
struct object *object;
struct key *key;
BYTE *public_exp, *modulus;
BCRYPT_RSAKEY_BLOB *rsaheader = (BCRYPT_RSAKEY_BLOB *)data;
if (datasize < sizeof(*rsaheader))
NTSTATUS ret;
BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data;
ret = BCryptOpenAlgorithmProvider(&key_object->key.alg_prov, BCRYPT_RSA_ALGORITHM, NULL, 0);
if(ret != ERROR_SUCCESS)
{
ERR("Invalid buffer size.\n");
return NTE_BAD_DATA;
ERR("Error opening algorithm provider\n");
return NTE_INTERNAL_ERROR;
Should we return the error from BCryptOpenAlgorithmProvider() here?
}
expected_size = sizeof(*rsaheader) + rsaheader->cbPublicExp + rsaheader->cbModulus;
if (datasize != expected_size)
ret = BCryptImportKeyPair(key_object->key.alg_prov, NULL, type, &key_object->key.bcrypt_key, data, datasize, 0);
if(ret != ERROR_SUCCESS)
{
ERR("Invalid buffer size.\n");
return NTE_BAD_DATA;
ERR("Error importing keypair with bcrypt %#lx\n", ret);
return NTE_INTERNAL_ERROR;
And return the error from BCryptImportKeyPair() here?
}
if (!(object = allocate_object(KEY)))
{
ERR("Error allocating memory.\n");
return NTE_NO_MEMORY;
}
key = &object->key;
key->alg = RSA;
key->rsa.bit_length = rsaheader->BitLength;
key->rsa.public_exp_size = rsaheader->cbPublicExp;
key->rsa.modulus_size = rsaheader->cbModulus;
if (!(key->rsa.public_exp = malloc(rsaheader->cbPublicExp)))
{
ERR("Error allocating memory.\n");
free(object);
return NTE_NO_MEMORY;
}
if (!(key->rsa.modulus = malloc(rsaheader->cbModulus)))
{
ERR("Error allocating memory.\n");
free(key->rsa.public_exp);
free(object);
return NTE_NO_MEMORY;
}
public_exp = &data[sizeof(*rsaheader)]; /* The public exp is after the header. */
modulus = &public_exp[rsaheader->cbPublicExp]; /* The modulus is after the public exponent. */
memcpy(key->rsa.public_exp, public_exp, rsaheader->cbPublicExp);
memcpy(key->rsa.modulus, modulus, rsaheader->cbModulus);
set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)L"RSA", sizeof(L"RSA"));
set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&key->rsa.bit_length, sizeof(key->rsa.bit_length));
set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider));
*handle = (NCRYPT_KEY_HANDLE)object;
set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE));
set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM));
set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength));
break; } default:
FIXME("Unhandled key magic %#lx.\n", header->Magic);
- {
FIXME("Unhandled key magic %#lx\n", header->Magic);
return NTE_INVALID_PARAMETER;
break;
- }
}
- *handle = (NCRYPT_KEY_HANDLE)key_object;
return ERROR_SUCCESS; }
diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h index 3966dd73ed6..2d916d4fbd8 100644 --- a/dlls/ncrypt/ncrypt_internal.h +++ b/dlls/ncrypt/ncrypt_internal.h @@ -16,34 +16,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-enum key_algorithm -{
- DH,
- DSA,
- ECC,
- RSA,
-};
-struct rsa_key -{
- DWORD bit_length;
- DWORD public_exp_size;
- BYTE *public_exp;
- DWORD modulus_size;
- BYTE *modulus;
- DWORD prime1_size;
- BYTE *prime1;
- DWORD prime2_size;
- BYTE *prime2;
-}; +#include <ncrypt.h> +#include <bcrypt.h>
struct key {
- enum key_algorithm alg;
- union
- {
struct rsa_key rsa;
- };
- NCRYPT_PROV_HANDLE storage_prov;
- BCRYPT_ALG_HANDLE alg_prov;
- BCRYPT_KEY_HANDLE bcrypt_key;
};
struct storage_provider diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index d1bcbbcab2a..8080e465527 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -123,6 +123,7 @@ static void test_key_import_rsa(void) ok(key, "got null handle\n"); NCryptFreeObject(key);
- todo_wine{
ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob_with_invalid_publicexp_size, sizeof(rsa_key_blob_with_invalid_publicexp_size), 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret); @@ -132,6 +133,7 @@ static void test_key_import_rsa(void)
ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob, sizeof(rsa_key_blob) + 1, 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret);
- }
NCryptFreeObject(prov); }
You should restructure your patches so that you don't have to reintroduce todo_wine statements.
Hello Hans, thanks for your review. About returning the errors of bcrypt from a ncrypt function (Like the calls to BCryptOpenAlgorithmProvider() from NCryptImportKey), I try to prevent doing that because both functions return two different types of errors, ncrypt returns SECURITY_STATUS and bcrypt returns NTSTATUS.
On Thu, 2022-03-03 at 13:54 -0300, Santino Mazza wrote:
Hello Hans, thanks for your review. About returning the errors of bcrypt from a ncrypt function (Like the calls to BCryptOpenAlgorithmProvider() from NCryptImportKey), I try to prevent doing that because both functions return two different types of errors, ncrypt returns SECURITY_STATUS and bcrypt returns NTSTATUS.
The errors may need translation of course. I don't think we can avoid this if we're going to use bcrypt.
On 2/3/22 06:27, Hans Leidekker wrote:
On Tue, 2022-03-01 at 19:34 -0300, Santino Mazza wrote: Signed-off-by: Santino Mazza mazzasantino1206@gmail.com
dlls/ncrypt/Makefile.in | 1 + dlls/ncrypt/main.c | 101 +++++++++++++--------------------- dlls/ncrypt/ncrypt_internal.h | 30 ++-------- dlls/ncrypt/tests/ncrypt.c | 2 + 4 files changed, 45 insertions(+), 89 deletions(-)
diff --git a/dlls/ncrypt/Makefile.in b/dlls/ncrypt/Makefile.in index ad3ed409961..58ec6b3456b 100644 --- a/dlls/ncrypt/Makefile.in +++ b/dlls/ncrypt/Makefile.in @@ -1,5 +1,6 @@ IMPORTLIB = ncrypt MODULE = ncrypt.dll +IMPORTS = bcrypt
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 68d9d884618..2804708f10f 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -88,20 +88,14 @@ SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
static SECURITY_STATUS free_key_object(struct key *key) {
- switch (key->alg)
- {
- case RSA:
- {
free(key->rsa.modulus);
free(key->rsa.public_exp);
free(key->rsa.prime1);
free(key->rsa.prime2);
break;
- }
- default:
WARN("invalid key %p\n", key);
return NTE_INVALID_HANDLE;
- }
- NTSTATUS bcrypt_ret;
- bcrypt_ret = BCryptDestroyKey(key->bcrypt_key);
- if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE;
- bcrypt_ret = BCryptCloseAlgorithmProvider(key->alg_prov, 0);
- if(bcrypt_ret != ERROR_SUCCESS) return NTE_INVALID_HANDLE;
There's no need to check for failure here. If BCryptDestroyKey() would fail you would leak the algorithm handle.
return ERROR_SUCCESS; }
@@ -246,6 +240,7 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H BYTE *data, DWORD datasize, DWORD flags) { BCRYPT_KEY_BLOB *header = (BCRYPT_KEY_BLOB *)data;
- struct object *key_object;
TRACE("(%#Ix, %#Ix, %s, %p, %p, %p, %lu, %#lx): stub\n", provider, decrypt_key, wine_dbgstr_w(type), params, handle, data, datasize, flags); @@ -270,70 +265,48 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H return NTE_BAD_FLAGS; }
- switch (header->Magic)
- if(!(key_object = allocate_object(KEY)))
- {
ERR("Error allocating memory\n");
return NTE_NO_MEMORY;
- }
- key_object->key.storage_prov = provider;
- switch(header->Magic)
{
- case BCRYPT_RSAFULLPRIVATE_MAGIC:
- case BCRYPT_RSAPRIVATE_MAGIC:
case BCRYPT_RSAPUBLIC_MAGIC: {
DWORD expected_size;
struct object *object;
struct key *key;
BYTE *public_exp, *modulus;
BCRYPT_RSAKEY_BLOB *rsaheader = (BCRYPT_RSAKEY_BLOB *)data;
if (datasize < sizeof(*rsaheader))
NTSTATUS ret;
BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data;
ret = BCryptOpenAlgorithmProvider(&key_object->key.alg_prov, BCRYPT_RSA_ALGORITHM, NULL, 0);
if(ret != ERROR_SUCCESS)
{
ERR("Invalid buffer size.\n");
return NTE_BAD_DATA;
ERR("Error opening algorithm provider\n");
return NTE_INTERNAL_ERROR;
Should we return the error from BCryptOpenAlgorithmProvider() here?
}
expected_size = sizeof(*rsaheader) + rsaheader->cbPublicExp + rsaheader->cbModulus;
if (datasize != expected_size)
ret = BCryptImportKeyPair(key_object->key.alg_prov, NULL, type, &key_object->key.bcrypt_key, data, datasize, 0);
if(ret != ERROR_SUCCESS)
{
ERR("Invalid buffer size.\n");
return NTE_BAD_DATA;
ERR("Error importing keypair with bcrypt %#lx\n", ret);
return NTE_INTERNAL_ERROR;
And return the error from BCryptImportKeyPair() here?
}
if (!(object = allocate_object(KEY)))
{
ERR("Error allocating memory.\n");
return NTE_NO_MEMORY;
}
key = &object->key;
key->alg = RSA;
key->rsa.bit_length = rsaheader->BitLength;
key->rsa.public_exp_size = rsaheader->cbPublicExp;
key->rsa.modulus_size = rsaheader->cbModulus;
if (!(key->rsa.public_exp = malloc(rsaheader->cbPublicExp)))
{
ERR("Error allocating memory.\n");
free(object);
return NTE_NO_MEMORY;
}
if (!(key->rsa.modulus = malloc(rsaheader->cbModulus)))
{
ERR("Error allocating memory.\n");
free(key->rsa.public_exp);
free(object);
return NTE_NO_MEMORY;
}
public_exp = &data[sizeof(*rsaheader)]; /* The public exp is after the header. */
modulus = &public_exp[rsaheader->cbPublicExp]; /* The modulus is after the public exponent. */
memcpy(key->rsa.public_exp, public_exp, rsaheader->cbPublicExp);
memcpy(key->rsa.modulus, modulus, rsaheader->cbModulus);
set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)L"RSA", sizeof(L"RSA"));
set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&key->rsa.bit_length, sizeof(key->rsa.bit_length));
set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider));
*handle = (NCRYPT_KEY_HANDLE)object;
set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE));
set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM));
set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength));
break; } default:
FIXME("Unhandled key magic %#lx.\n", header->Magic);
- {
FIXME("Unhandled key magic %#lx\n", header->Magic);
return NTE_INVALID_PARAMETER;
break;
- }
}
- *handle = (NCRYPT_KEY_HANDLE)key_object;
return ERROR_SUCCESS; }
diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h index 3966dd73ed6..2d916d4fbd8 100644 --- a/dlls/ncrypt/ncrypt_internal.h +++ b/dlls/ncrypt/ncrypt_internal.h @@ -16,34 +16,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-enum key_algorithm -{
- DH,
- DSA,
- ECC,
- RSA,
-};
-struct rsa_key -{
- DWORD bit_length;
- DWORD public_exp_size;
- BYTE *public_exp;
- DWORD modulus_size;
- BYTE *modulus;
- DWORD prime1_size;
- BYTE *prime1;
- DWORD prime2_size;
- BYTE *prime2;
-}; +#include <ncrypt.h> +#include <bcrypt.h>
struct key {
- enum key_algorithm alg;
- union
- {
struct rsa_key rsa;
- };
- NCRYPT_PROV_HANDLE storage_prov;
- BCRYPT_ALG_HANDLE alg_prov;
- BCRYPT_KEY_HANDLE bcrypt_key;
};
struct storage_provider diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index d1bcbbcab2a..8080e465527 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -123,6 +123,7 @@ static void test_key_import_rsa(void) ok(key, "got null handle\n"); NCryptFreeObject(key);
- todo_wine{
ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob_with_invalid_publicexp_size, sizeof(rsa_key_blob_with_invalid_publicexp_size), 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret); @@ -132,6 +133,7 @@ static void test_key_import_rsa(void)
ret = NCryptImportKey(prov, 0, BCRYPT_PUBLIC_KEY_BLOB, NULL, &key, rsa_key_blob, sizeof(rsa_key_blob) + 1, 0); ok(ret == NTE_BAD_DATA, "got %#lx\n", ret);
- }
NCryptFreeObject(prov); }
You should restructure your patches so that you don't have to reintroduce todo_wine statements.
Oh, and about the todo_statements. Right now I didn't implemented the logic for validating an invalid key blob, so I will do that and then resubmit the patches in the correct order.
Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/ncrypt/main.c | 52 ++++++++++++++++++++++++++++++++------ dlls/ncrypt/tests/ncrypt.c | 5 ++-- 2 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 2804708f10f..43eff5974ca 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -30,14 +30,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(ncrypt);
-SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key, - const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags) -{ - FIXME("(%#Ix, %p, %s, %s, %#lx, %#lx): stub\n", provider, key, wine_dbgstr_w(algid), - wine_dbgstr_w(name), keyspec, flags); - return NTE_NOT_SUPPORTED; -} - SECURITY_STATUS WINAPI NCryptDecrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding, BYTE *output, DWORD outsize, DWORD *result, DWORD flags) { @@ -355,6 +347,50 @@ SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE handle, const WCHAR *name return set_object_property(object, name, input, insize); }
+SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key, + const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags) +{ + struct object *key_object; + TRACE("(%#Ix, %p, %s, %s, %#lx, %#lx)\n", provider, key, wine_dbgstr_w(algid), + wine_dbgstr_w(name), keyspec, flags); + + if(!provider) return NTE_INVALID_HANDLE; + if(!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER); + if(name) FIXME("Persistant keys not supported\n"); + + if(!(key_object = allocate_object(KEY))) + { + ERR("Error allocating memory\n"); + return NTE_NO_MEMORY; + } + + key_object->key.storage_prov = provider; + if(!lstrcmpiW(algid, BCRYPT_RSA_ALGORITHM)) + { + NTSTATUS ret = BCryptOpenAlgorithmProvider(&key_object->key.alg_prov, BCRYPT_RSA_ALGORITHM, NULL, 0); + DWORD default_bitlength = 1024; + + if(ret != ERROR_SUCCESS) + { + ERR("Error opening algorithm provider\n"); + NCryptFreeObject((NCRYPT_HANDLE)key_object); + return NTE_INTERNAL_ERROR; + } + + set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE)); + set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); + set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlength, sizeof(default_bitlength)); + } + else + { + FIXME("Algorithm not handled %s\n", wine_dbgstr_w(algid)); + return NTE_NOT_SUPPORTED; + } + + *key = (NCRYPT_KEY_HANDLE)key_object; + return ERROR_SUCCESS; +} + SECURITY_STATUS WINAPI NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size, BYTE *signature, DWORD signature_size, DWORD flags) { diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index 8080e465527..608bf59197e 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -231,6 +231,7 @@ static void test_set_property(void) { ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0); ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret); + } NCryptFreeObject(key);
key = 0; @@ -242,6 +243,8 @@ static void test_set_property(void) ret = NCryptSetProperty(key, NCRYPT_LENGTH_PROPERTY, (BYTE *)&keylength, sizeof(keylength), 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
+ todo_wine + { ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0); ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret);
@@ -263,7 +266,6 @@ static void test_create_persisted_key(void) ret = NCryptOpenStorageProvider(&prov, NULL, 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
- todo_wine { key = 0; ret = NCryptCreatePersistedKey(0, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0); ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret); @@ -294,7 +296,6 @@ static void test_create_persisted_key(void) NCryptFinalizeKey(key, 0); NCryptFreeObject(key); NCryptFreeObject(prov); - } }
START_TEST(ncrypt)
On Tue, 2022-03-01 at 19:34 -0300, Santino Mazza wrote: Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/ncrypt/main.c | 52 ++++++++++++++++++++++++++++++++------ dlls/ncrypt/tests/ncrypt.c | 5 ++-- 2 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 2804708f10f..43eff5974ca 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -30,14 +30,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(ncrypt);
-SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key, - const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags) -{ - FIXME("(%#Ix, %p, %s, %s, %#lx, %#lx): stub\n", provider, key, wine_dbgstr_w(algid), - wine_dbgstr_w(name), keyspec, flags); - return NTE_NOT_SUPPORTED; -} - SECURITY_STATUS WINAPI NCryptDecrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding, BYTE *output, DWORD outsize, DWORD *result, DWORD flags) { @@ -355,6 +347,50 @@ SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE handle, const WCHAR *name return set_object_property(object, name, input, insize); }
+SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key, + const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags) +{ + struct object *key_object; + TRACE("(%#Ix, %p, %s, %s, %#lx, %#lx)\n", provider, key, wine_dbgstr_w(algid), + wine_dbgstr_w(name), keyspec, flags); + + if(!provider) return NTE_INVALID_HANDLE; + if(!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER); + if(name) FIXME("Persistant keys not supported\n");
Please add a space after 'if' like in the rest of this file.
+ + if(!(key_object = allocate_object(KEY))) + { + ERR("Error allocating memory\n"); + return NTE_NO_MEMORY; + } + + key_object->key.storage_prov = provider;
Why do you need to store the provider handle here? Note that's it's also set as a key property.
+ if(!lstrcmpiW(algid, BCRYPT_RSA_ALGORITHM)) + { + NTSTATUS ret = BCryptOpenAlgorithmProvider(&key_object->key.alg_prov, BCRYPT_RSA_ALGORITHM, NULL, 0); + DWORD default_bitlength = 1024; + + if(ret != ERROR_SUCCESS) + { + ERR("Error opening algorithm provider\n"); + NCryptFreeObject((NCRYPT_HANDLE)key_object); + return NTE_INTERNAL_ERROR; + } + + set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE)); + set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); + set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlength, sizeof(default_bitlength)); + } + else + { + FIXME("Algorithm not handled %s\n", wine_dbgstr_w(algid)); + return NTE_NOT_SUPPORTED; + } + + *key = (NCRYPT_KEY_HANDLE)key_object; + return ERROR_SUCCESS; +} + SECURITY_STATUS WINAPI NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size, BYTE *signature, DWORD signature_size, DWORD flags) { diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index 8080e465527..608bf59197e 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -231,6 +231,7 @@ static void test_set_property(void) { ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0); ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret); + } NCryptFreeObject(key);
key = 0; @@ -242,6 +243,8 @@ static void test_set_property(void) ret = NCryptSetProperty(key, NCRYPT_LENGTH_PROPERTY, (BYTE *)&keylength, sizeof(keylength), 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
+ todo_wine + { ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0); ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret);
@@ -263,7 +266,6 @@ static void test_create_persisted_key(void) ret = NCryptOpenStorageProvider(&prov, NULL, 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
- todo_wine { key = 0; ret = NCryptCreatePersistedKey(0, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0); ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret); @@ -294,7 +296,6 @@ static void test_create_persisted_key(void) NCryptFinalizeKey(key, 0); NCryptFreeObject(key); NCryptFreeObject(prov); - } }
START_TEST(ncrypt)
El mié, 2 mar 2022 a la(s) 06:28, Hans Leidekker (hans@codeweavers.com) escribió:
Why do you need to store the provider handle here? Note that's it's also set as a key property.
For internal usage it's going to be more straightforward (and fast? I
don't think it's going to make a big difference) to have it saved on a struct member. But I admit it looks a little repetitive and that it could get out of control at some point (by having to take into consideration the struct member and also the property at the same time), I was thinking into making the struct member a pointer to the value of the property, but nothing guarantees that the memory address of the properties addresses will stay the same when adding new properties. Do you have some suggestions? For now I will just remove the struct member and use properties.
El jue, 3 mar 2022 a la(s) 17:16, Santino Mazza (mazzasantino1206@gmail.com) escribió:
El mié, 2 mar 2022 a la(s) 06:28, Hans Leidekker (hans@codeweavers.com) escribió:
Why do you need to store the provider handle here? Note that's it's also set as a key property.
For internal usage it's going to be more straightforward (and fast? I
don't think it's going to make a big difference) to have it saved on a struct member. But I admit it looks a little repetitive and that it could get out of control at some point (by having to take into consideration the struct member and also the property at the same time), I was thinking into making the struct member a pointer to the value of the property, but nothing guarantees that the memory address of the properties addresses will stay the same when adding new properties. Do you have some suggestions? For now I will just remove the struct member and use properties.
I messed up the last phrase. I meant that nothing guarantees that the address of the properties array will stay the same when adding a new property.
Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/ncrypt/tests/ncrypt.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index 608bf59197e..e6473cd1e31 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -298,6 +298,32 @@ static void test_create_persisted_key(void) NCryptFreeObject(prov); }
+static void test_finalize_key(void) +{ + NCRYPT_PROV_HANDLE prov; + NCRYPT_KEY_HANDLE key; + SECURITY_STATUS ret; + + ret = NCryptOpenStorageProvider(&prov, NULL, 0); + ok(ret == ERROR_SUCCESS, "got %#lx\n", ret); + + ret = NCryptCreatePersistedKey(prov, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0); + ok(ret == ERROR_SUCCESS, "got %#lx\n", ret); + + todo_wine + { + ret = NCryptFinalizeKey(key, 0); + ok(ret == ERROR_SUCCESS, "got %#lx\n", ret); + + ret = NCryptFinalizeKey(key, 0); + ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret); + + ret = NCryptFinalizeKey(0, 0); + ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret); + } + NCryptFreeObject(key); +} + START_TEST(ncrypt) { test_key_import_rsa(); @@ -305,4 +331,5 @@ START_TEST(ncrypt) test_get_property(); test_set_property(); test_create_persisted_key(); + test_finalize_key(); }
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/ncrypt/main.c | 57 ++++++++++++++++++++++++++++++----- dlls/ncrypt/ncrypt_internal.h | 7 +++++ dlls/ncrypt/tests/ncrypt.c | 4 +-- 3 files changed, 58 insertions(+), 10 deletions(-)
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 43eff5974ca..958f6924c18 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -66,12 +66,6 @@ SECURITY_STATUS WINAPI NCryptEnumKeys(NCRYPT_PROV_HANDLE provider, const WCHAR * return NTE_NOT_SUPPORTED; }
-SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE key, DWORD flags) -{ - FIXME("(%#Ix, %#lx): stub\n", key, flags); - return NTE_NOT_SUPPORTED; -} - SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf) { FIXME("(%p): stub\n", buf); @@ -282,9 +276,10 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H if(ret != ERROR_SUCCESS) { ERR("Error importing keypair with bcrypt %#lx\n", ret); - return NTE_INTERNAL_ERROR; + return NTE_BAD_DATA; }
+ key_object->key.type = ASYMMETRIC; set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE)); set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength)); @@ -377,6 +372,7 @@ SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCR return NTE_INTERNAL_ERROR; }
+ key_object->key.type = ASYMMETRIC; set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE)); set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlength, sizeof(default_bitlength)); @@ -391,6 +387,53 @@ SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCR return ERROR_SUCCESS; }
+SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE key, DWORD flags) +{ + struct object *key_object = (struct object*)key; + DWORD key_length; + struct object_property *prop; + NTSTATUS ret; + + TRACE("(%#Ix, %#lx): stub\n", key, flags); + + if(!key) return NTE_INVALID_HANDLE; + if(key_object->key.finalized_key) return NTE_INVALID_HANDLE; + + prop = get_object_property(key_object, NCRYPT_LENGTH_PROPERTY); + if(!prop) return NTE_INVALID_HANDLE; + + key_length = *(DWORD *)prop->value; + if(key_object->key.type == ASYMMETRIC) + { + ret = BCryptGenerateKeyPair(key_object->key.alg_prov, &key_object->key.bcrypt_key, key_length, 0); + if(ret != ERROR_SUCCESS) + { + ERR("Error generating key pair\n"); + return NTE_INTERNAL_ERROR; + } + + ret = BCryptFinalizeKeyPair(key_object->key.bcrypt_key, 0); + if(ret != ERROR_SUCCESS) + { + ERR("Error finalizing key pair\n"); + return NTE_INTERNAL_ERROR; + } + } + else if(key_object->key.type == SYMMETRIC) + { + FIXME("Symmetric keys not implemented\n"); + return NTE_NOT_SUPPORTED; + } + else + { + ERR("Got handle with invalid key type"); + return NTE_INVALID_HANDLE; + } + + key_object->key.finalized_key = 1; + return ERROR_SUCCESS; +} + SECURITY_STATUS WINAPI NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size, BYTE *signature, DWORD signature_size, DWORD flags) { diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h index 2d916d4fbd8..1163277ccaa 100644 --- a/dlls/ncrypt/ncrypt_internal.h +++ b/dlls/ncrypt/ncrypt_internal.h @@ -19,8 +19,15 @@ #include <ncrypt.h> #include <bcrypt.h>
+enum key_type { + SYMMETRIC, + ASYMMETRIC +}; + struct key { + enum key_type type; + DWORD finalized_key; NCRYPT_PROV_HANDLE storage_prov; BCRYPT_ALG_HANDLE alg_prov; BCRYPT_KEY_HANDLE bcrypt_key; diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index e6473cd1e31..926efc0370a 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -310,8 +310,6 @@ static void test_finalize_key(void) ret = NCryptCreatePersistedKey(prov, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
- todo_wine - { ret = NCryptFinalizeKey(key, 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
@@ -320,7 +318,7 @@ static void test_finalize_key(void)
ret = NCryptFinalizeKey(0, 0); ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret); - } + NCryptFreeObject(key); }
On Tue, 2022-03-01 at 19:34 -0300, Santino Mazza wrote: Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/ncrypt/main.c | 57 ++++++++++++++++++++++++++++++----- dlls/ncrypt/ncrypt_internal.h | 7 +++++ dlls/ncrypt/tests/ncrypt.c | 4 +-- 3 files changed, 58 insertions(+), 10 deletions(-)
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c index 43eff5974ca..958f6924c18 100644 --- a/dlls/ncrypt/main.c +++ b/dlls/ncrypt/main.c @@ -66,12 +66,6 @@ SECURITY_STATUS WINAPI NCryptEnumKeys(NCRYPT_PROV_HANDLE provider, const WCHAR * return NTE_NOT_SUPPORTED; }
-SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE key, DWORD flags) -{ - FIXME("(%#Ix, %#lx): stub\n", key, flags); - return NTE_NOT_SUPPORTED; -} - SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf) { FIXME("(%p): stub\n", buf); @@ -282,9 +276,10 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H if(ret != ERROR_SUCCESS) { ERR("Error importing keypair with bcrypt %#lx\n", ret); - return NTE_INTERNAL_ERROR; + return NTE_BAD_DATA;
This doesn't belong in this patch.
} + key_object->key.type = ASYMMETRIC;
Or this.
set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE));
set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength)); @@ -377,6 +372,7 @@ SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCR return NTE_INTERNAL_ERROR; }
+ key_object->key.type = ASYMMETRIC; set_object_property(key_object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(NCRYPT_PROV_HANDLE)); set_object_property(key_object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM)); set_object_property(key_object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlength, sizeof(default_bitlength)); @@ -391,6 +387,53 @@ SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCR return ERROR_SUCCESS; }
+SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE key, DWORD flags) +{ + struct object *key_object = (struct object*)key; + DWORD key_length; + struct object_property *prop; + NTSTATUS ret; + + TRACE("(%#Ix, %#lx): stub\n", key, flags); + + if(!key) return NTE_INVALID_HANDLE; + if(key_object->key.finalized_key) return NTE_INVALID_HANDLE; + + prop = get_object_property(key_object, NCRYPT_LENGTH_PROPERTY); + if(!prop) return NTE_INVALID_HANDLE; + + key_length = *(DWORD *)prop->value; + if(key_object->key.type == ASYMMETRIC) + { + ret = BCryptGenerateKeyPair(key_object->key.alg_prov, &key_object->key.bcrypt_key, key_length, 0); + if(ret != ERROR_SUCCESS) + { + ERR("Error generating key pair\n"); + return NTE_INTERNAL_ERROR; + } +
It may be better to call BCryptGenerateKeyPair() when the key is created, to catch errors early. This needs some tests.
+ ret = BCryptFinalizeKeyPair(key_object->key.bcrypt_key, 0); + if(ret != ERROR_SUCCESS) + { + ERR("Error finalizing key pair\n"); + return NTE_INTERNAL_ERROR; + } + } + else if(key_object->key.type == SYMMETRIC) + { + FIXME("Symmetric keys not implemented\n");
Does native support symmetric keys?
+ return NTE_NOT_SUPPORTED; + } + else + { + ERR("Got handle with invalid key type"); + return NTE_INVALID_HANDLE; + } + + key_object->key.finalized_key = 1; + return ERROR_SUCCESS; +} + SECURITY_STATUS WINAPI NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size, BYTE *signature, DWORD signature_size, DWORD flags) { diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h index 2d916d4fbd8..1163277ccaa 100644 --- a/dlls/ncrypt/ncrypt_internal.h +++ b/dlls/ncrypt/ncrypt_internal.h @@ -19,8 +19,15 @@ #include <ncrypt.h> #include <bcrypt.h>
+enum key_type { + SYMMETRIC, + ASYMMETRIC +}; + struct key { + enum key_type type; + DWORD finalized_key; NCRYPT_PROV_HANDLE storage_prov; BCRYPT_ALG_HANDLE alg_prov; BCRYPT_KEY_HANDLE bcrypt_key; diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c index e6473cd1e31..926efc0370a 100644 --- a/dlls/ncrypt/tests/ncrypt.c +++ b/dlls/ncrypt/tests/ncrypt.c @@ -310,8 +310,6 @@ static void test_finalize_key(void) ret = NCryptCreatePersistedKey(prov, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
- todo_wine - { ret = NCryptFinalizeKey(key, 0); ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
@@ -320,7 +318,7 @@ static void test_finalize_key(void)
ret = NCryptFinalizeKey(0, 0); ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret); - } + NCryptFreeObject(key); }
El mié, 2 mar 2022 a la(s) 06:29, Hans Leidekker (hans@codeweavers.com) escribió:
It may be better to call BCryptGenerateKeyPair() when the key is created, to catch errors early. This needs some tests.
For this we should find a way to check if the property requested by NCryptSetProperty or NCryptGetProperty belongs to the bcrypt object and make the call also to BCryptSetProperty or BCryptGetProperty and get the data from there. I'm a little worried about the amount of for loops this is going to have. lol.
Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/bcrypt/tests/bcrypt.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index e7619897cfd..1588b72c3fd 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -1971,6 +1971,24 @@ static UCHAR rsaFullPrivateBlob[] = 0x9d, 0xe2, 0xcc, 0x5a, 0xf1, 0x68, 0x30, 0xe5, 0xbc, 0x8d, 0xad, };
+ +static UCHAR rsaPublicBlobWithInvalidPublicExpSize[] = +{ + 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0xc7, 0x8f, 0xac, 0x2a, 0xce, 0xbf, 0xc9, 0x6c, 0x7b, + 0x85, 0x74, 0x71, 0xbb, 0xff, 0xbb, 0x9b, 0x20, 0x03, 0x79, 0x17, 0x34, + 0xe7, 0x26, 0x91, 0x5c, 0x1f, 0x1b, 0x03, 0x3d, 0x46, 0xdf, 0xb6, 0xf2, + 0x10, 0x55, 0xf0, 0x39, 0x55, 0x0a, 0xe3, 0x9c, 0x0c, 0x63, 0xc2, 0x14, + 0x03, 0x94, 0x51, 0x0d, 0xb4, 0x22, 0x09, 0xf2, 0x5c, 0xb2, 0xd1, 0xc3, + 0xac, 0x6f, 0xa8, 0xc4, 0xac, 0xb8, 0xbc, 0x59, 0xe7, 0xed, 0x77, 0x6e, + 0xb1, 0x80, 0x58, 0x7d, 0xb2, 0x94, 0x46, 0xe5, 0x00, 0xe2, 0xb7, 0x33, + 0x48, 0x7a, 0xd3, 0x78, 0xe9, 0x26, 0x01, 0xc7, 0x00, 0x7b, 0x41, 0x6d, + 0x94, 0x3a, 0xe1, 0x50, 0x2b, 0x9f, 0x6b, 0x1c, 0x08, 0xa3, 0xfc, 0x0a, + 0x44, 0x81, 0x09, 0x41, 0x80, 0x23, 0x7b, 0xf6, 0x3f, 0xaf, 0x91, 0xa1, + 0x87, 0x75, 0x33, 0x15, 0xb8, 0xde, 0x32, 0x30, 0xb4, 0x5e, 0xfd +}; + static void test_RSA(void) { static UCHAR hash[] = @@ -2076,7 +2094,7 @@ static void test_RSA(void) ok(size == size2, "got %lu expected %lu\n", size2, size); HeapFree(GetProcessHeap(), 0, buf);
- /* export public key */ + /* import/export public key */ size = 0; ret = BCryptExportKey(key, NULL, BCRYPT_RSAPUBLIC_BLOB, NULL, 0, &size, 0); ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); @@ -2096,6 +2114,12 @@ static void test_RSA(void) ret = BCryptDestroyKey(key); ok(!ret, "got %#lx\n", ret);
+ todo_wine + { + ret = BCryptImportKeyPair(alg, NULL, BCRYPT_RSAPUBLIC_BLOB, &key, rsaPublicBlobWithInvalidPublicExpSize, sizeof(rsaPublicBlobWithInvalidPublicExpSize), 0); + ok(ret == NTE_BAD_DATA, "got %#lx\n", ret); + } + ret = BCryptImportKeyPair(alg, NULL, BCRYPT_RSAPUBLIC_BLOB, &key, buf, size, 0); ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); HeapFree(GetProcessHeap(), 0, buf);
Signed-off-by: Hans Leidekker hans@codeweavers.com
On Tue, 2022-03-01 at 19:34 -0300, Santino Mazza wrote:
Signed-off-by: Santino Mazza mazzasantino1206@gmail.com
dlls/bcrypt/bcrypt_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 9fb9b6adf87..73071d70992 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1404,7 +1404,7 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP *ret_key = key; return STATUS_SUCCESS; }
- else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ))
- else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ) || !wcscmp( type, BCRYPT_PUBLIC_KEY_BLOB ))
{ BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
According to the documentation BCRYPT_PUBLIC_KEY_BLOB is not necessarily an RSA key.