diff options
Diffstat (limited to '')
-rw-r--r-- | winpr/libwinpr/ncrypt/test/TestNCryptSmartcard.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/winpr/libwinpr/ncrypt/test/TestNCryptSmartcard.c b/winpr/libwinpr/ncrypt/test/TestNCryptSmartcard.c new file mode 100644 index 0000000..247a033 --- /dev/null +++ b/winpr/libwinpr/ncrypt/test/TestNCryptSmartcard.c @@ -0,0 +1,156 @@ +/** + * 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 = NULL; + X509* x509 = NULL; + BIO* bio = NULL; + char* ret = NULL; + + 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 = calloc(1024, sizeof(char)); + if (!ret) + goto bio_release; + + char* ret2 = X509_NAME_oneline(name, ret, 1024); + + printf("\t%s\n", ret2); + free(ret); + +x509_release: + X509_free(x509); +bio_release: + BIO_free(bio); +} + +int TestNCryptSmartcard(int argc, char* argv[]) +{ + SECURITY_STATUS status = 0; + DWORD providerCount = 0; + NCryptProviderName* names = NULL; + + status = NCryptEnumStorageProviders(&providerCount, &names, NCRYPT_SILENT_FLAG); + if (status != ERROR_SUCCESS) + return -1; + + for (size_t j = 0; j < providerCount; j++) + { + const NCryptProviderName* name = &names[j]; + NCRYPT_PROV_HANDLE provider = 0; + char providerNameStr[256] = { 0 }; + PVOID enumState = NULL; + size_t i = 0; + NCryptKeyName* keyName = NULL; + + if (ConvertWCharToUtf8(name->pszName, providerNameStr, ARRAYSIZE(providerNameStr)) < 0) + continue; + printf("provider %" PRIuz ": %s\n", j, providerNameStr); + + status = NCryptOpenStorageProvider(&provider, name->pszName, 0); + if (status != ERROR_SUCCESS) + continue; + + while ((status = NCryptEnumKeys(provider, NULL, &keyName, &enumState, + NCRYPT_SILENT_FLAG)) == ERROR_SUCCESS) + { + NCRYPT_KEY_HANDLE phKey = 0; + DWORD dwFlags = 0; + DWORD cbOutput = 0; + char keyNameStr[256] = { 0 }; + WCHAR reader[1024] = { 0 }; + PBYTE certBytes = NULL; + + if (ConvertWCharToUtf8(keyName->pszName, keyNameStr, ARRAYSIZE(keyNameStr)) < 0) + continue; + + printf("\tkey %" PRIuz ": %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 }; + + ConvertWCharNToUtf8(reader, cbOutput, readerStr, ARRAYSIZE(readerStr)); + printf("\treader: %s\n", readerStr); + } + + cbOutput = 0; + status = + NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, NULL, 0, &cbOutput, dwFlags); + if (status != ERROR_SUCCESS) + { + WLog_ERR(TAG, "unable to retrieve certificate len 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: + NCryptFreeBuffer(keyName); + NCryptFreeObject((NCRYPT_HANDLE)phKey); + i++; + } + + NCryptFreeBuffer(enumState); + NCryptFreeObject((NCRYPT_HANDLE)provider); + } + + NCryptFreeBuffer(names); + return 0; +} |