/** * WinPR: Windows Portable Runtime * Test for NCrypt library * * Copyright 2021 David Fort * * 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 #include #include #include #include #include #include #define TAG "testNCrypt" static void crypto_print_name(const BYTE* b, DWORD sz) { if (sz > INT32_MAX) return; BIO* bio = BIO_new_mem_buf(b, (int)sz); if (!bio) return; X509* x509 = d2i_X509_bio(bio, nullptr); if (!x509) goto bio_release; X509_NAME* name = X509_get_subject_name(x509); if (!name) goto x509_release; char* 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[]) { int rc = -1; DWORD providerCount = 0; NCryptProviderName* names = nullptr; WINPR_UNUSED(argc); WINPR_UNUSED(argv); SECURITY_STATUS 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] = WINPR_C_ARRAY_INIT; PVOID enumState = nullptr; size_t i = 0; NCryptKeyName* keyName = nullptr; 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, nullptr, &keyName, &enumState, NCRYPT_SILENT_FLAG)) == ERROR_SUCCESS) { NCRYPT_KEY_HANDLE phKey = 0; DWORD dwFlags = 0; DWORD cbOutput = 0; char keyNameStr[256] = WINPR_C_ARRAY_INIT; WCHAR reader[1024] = WINPR_C_ARRAY_INIT; PBYTE certBytes = nullptr; 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] = WINPR_C_ARRAY_INIT; (void)ConvertWCharNToUtf8(reader, cbOutput, readerStr, ARRAYSIZE(readerStr)); printf("\treader: %s\n", readerStr); } cbOutput = 0; status = NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, nullptr, 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); if (status != NTE_NO_MORE_ITEMS) { (void)fprintf(stderr, "NCryptEnumKeys returned %s [0x%08" PRIx32 "]\n", Win32ErrorCode2Tag(status), status); } } rc = 0; fail: NCryptFreeBuffer(names); return rc; }