FreeRDP/winpr/libwinpr/ncrypt/test/TestNCryptSmartcard.c
2022-01-17 16:27:53 +01:00

151 lines
3.9 KiB
C

/**
* WinPR: Windows Portable Runtime
* Test for NCrypt library
*
* Copyright 2021 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/error.h>
#include <winpr/ncrypt.h>
#include <winpr/string.h>
#include <winpr/wlog.h>
#include <winpr/smartcard.h>
#include <openssl/bio.h>
#include <openssl/x509.h>
#define TAG "testNCrypt"
static void crypto_print_name(const BYTE *b, DWORD sz)
{
X509_NAME* name;
X509* x509;
BIO* bio;
char *ret;
bio = BIO_new_mem_buf(b, sz);
if (!bio)
return;
x509 = d2i_X509_bio(bio, NULL);
if (!x509)
goto bio_release;
name = X509_get_subject_name(x509);
if (!name)
goto x509_release;
ret = malloc(1024);
if (!ret)
goto bio_release;
ret = X509_NAME_oneline(name, ret, 1024);
printf("\t%s\n", ret);
free(ret);
x509_release:
X509_free(x509);
bio_release:
BIO_free(bio);
}
int TestNCryptSmartcard(int argc, char* argv[])
{
SECURITY_STATUS status;
size_t j = 0;
DWORD providerCount;
NCryptProviderName *names;
status = NCryptEnumStorageProviders(&providerCount, &names, NCRYPT_SILENT_FLAG);
if (status != ERROR_SUCCESS)
return -1;
for (j = 0; j < providerCount; j++)
{
NCRYPT_PROV_HANDLE provider;
char providerNameStr[256] = { 0 };
PVOID enumState = NULL;
size_t i = 0;
NCryptKeyName* keyName = NULL;
if (WideCharToMultiByte(CP_UTF8, 0, names[j].pszName, -1, providerNameStr, sizeof(providerNameStr), NULL,
FALSE) <= 0)
continue;
printf("provider %ld: %s\n", j, providerNameStr);
status = NCryptOpenStorageProvider(&provider, names[j].pszName, 0);
if (status != ERROR_SUCCESS)
continue;
while ((status = NCryptEnumKeys(provider, NULL, &keyName, &enumState, NCRYPT_SILENT_FLAG)) ==
ERROR_SUCCESS)
{
NCRYPT_KEY_HANDLE phKey;
DWORD dwFlags = 0, cbOutput;
char keyNameStr[256] = { 0 };
WCHAR reader[1024] = { 0 };
PBYTE certBytes = NULL;
if (WideCharToMultiByte(CP_UTF8, 0, keyName->pszName, -1, keyNameStr, sizeof(keyNameStr), NULL,
FALSE) <= 0)
continue;
printf("\tkey %ld: %s\n", i, keyNameStr);
status =
NCryptOpenKey(provider, &phKey, keyName->pszName, keyName->dwLegacyKeySpec, dwFlags);
if (status != ERROR_SUCCESS)
{
WLog_ERR(TAG, "unable to open key %s", keyNameStr);
continue;
}
status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, (PBYTE)reader, sizeof(reader), &cbOutput, dwFlags);
if (status == ERROR_SUCCESS)
{
char readerStr[1024] = { 0 };
if (WideCharToMultiByte(CP_UTF8, 0, reader, cbOutput, readerStr, sizeof(readerStr), NULL, FALSE) > 0)
printf("\treader: %s\n", readerStr);
}
status = NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, NULL, 0, &cbOutput, dwFlags);
if (status != ERROR_SUCCESS)
{
/* WLog_ERR(TAG, "unable to retrieve certificate for key '%s'", keyNameStr); */
goto endofloop;
}
certBytes = calloc(1, cbOutput);
status = NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, certBytes, cbOutput,
&cbOutput, dwFlags);
if (status != ERROR_SUCCESS)
{
WLog_ERR(TAG, "unable to retrieve certificate for key %s", keyNameStr);
goto endofloop;
}
crypto_print_name(certBytes, cbOutput);
free(certBytes);
endofloop:
NCryptFreeObject((NCRYPT_HANDLE)phKey);
i++;
}
NCryptFreeObject((NCRYPT_HANDLE)enumState);
NCryptFreeObject((NCRYPT_HANDLE)provider);
}
return 0;
}