/** * SmartCard-HSM PKCS#11 Module * * Copyright (c) 2017, CardContact Systems GmbH, Minden, Germany * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of CardContact Systems GmbH nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL CardContact Systems GmbH BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file opensc-minidriver-test.c * @author Andreas Schwier * @brief Test framework for the CSP minidriver implementation */ #include #include #include #include #include static int testscompleted = 0; static int testsfailed = 0; static char *reader = NULL; #include #include #include char *SystemErrorMsg(DWORD rc) { char *msg = "UNKNOWN"; if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, 0, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0)) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle("crypt32.dll"), rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); } return msg; } char *NTSTATUSErrorMsg(NTSTATUS nts) { char *msg = "UNKNOWN"; HMODULE hmod = GetModuleHandle("ntdll.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, nts, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); return msg; } char *SECURITY_STATUSErrorMsg(SECURITY_STATUS secstat) { char *msg = "UNKNOWN"; HMODULE hmod = GetModuleHandle("crypt32.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, secstat, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); return msg; } /* char *ErrorMsg(DWORD rc) { char *msg = "UNKNOWN"; HMODULE hmod; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, 0, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("bcrypt.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("ncrypt.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("crypt32.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("ntdll.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("kernel32.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("KernelBase.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("msvcrt.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); hmod = GetModuleHandle("cryptbase.dll"); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, hmod, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); return msg; } */ static char *verdict(int condition) { testscompleted++; if (condition) { return "Passed"; } else { testsfailed++; return "Failed"; } } LPVOID WINAPI CSP_ALLOC(__in SIZE_T Size) { return calloc(1, Size); } LPVOID WINAPI CSP_REALLOC(__in LPVOID Address, __in SIZE_T Size) { return realloc(Address, Size); } void WINAPI CSP_FREE(__in LPVOID Address) { free(Address); } int testSignRSA(NCRYPT_KEY_HANDLE hKey, DWORD padding, LPCWSTR hashAlg ) { BCRYPT_KEY_HANDLE hPubKey; SECURITY_STATUS secstat; BCRYPT_PKCS1_PADDING_INFO p1padinfo; BCRYPT_PSS_PADDING_INFO psspadinfo; BCRYPT_ALG_HANDLE hSignAlg; void *paddingInfo; PCCERT_CONTEXT certctx; NTSTATUS ntstat; unsigned char cert[4096],hash[64],signature[256],pubkeyblob[1024]; DWORD dwrc,dwlen,hashlen; printf(" RSA signing with %S and %s padding", hashAlg, (padding == BCRYPT_PAD_PKCS1 ? "V1.5" : "PSS")); memset(hash, 0xA5, sizeof(hash)); hashlen = sizeof(hash); if (!wcscmp(hashAlg, BCRYPT_SHA1_ALGORITHM)) { hashlen = 20; } else if (!wcscmp(hashAlg, BCRYPT_SHA256_ALGORITHM)) { hashlen = 32; } else if (!wcscmp(hashAlg, BCRYPT_SHA384_ALGORITHM)) { hashlen = 48; } else if (!wcscmp(hashAlg, BCRYPT_SHA512_ALGORITHM)) { hashlen = 64; } else if (!wcscmp(hashAlg, BCRYPT_MD5_ALGORITHM)) { hashlen = 16; } if (padding == BCRYPT_PAD_PKCS1) { memset(&p1padinfo, 0, sizeof(p1padinfo)); p1padinfo.pszAlgId = hashAlg; paddingInfo = &p1padinfo; } else { memset(&psspadinfo, 0, sizeof(psspadinfo)); psspadinfo.pszAlgId = hashAlg; psspadinfo.cbSalt = hashlen; paddingInfo = &psspadinfo; } // Export public key from smart card secstat = NCryptExportKey(hKey, 0, BCRYPT_RSAPUBLIC_BLOB, 0, pubkeyblob, sizeof(pubkeyblob), &dwlen, 0); if (secstat != ERROR_SUCCESS) { printf("\nNCryptExportKey failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } ntstat = BCryptOpenAlgorithmProvider(&hSignAlg, BCRYPT_RSA_ALGORITHM, NULL, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptOpenAlgorithmProvider failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } ntstat = BCryptImportKeyPair(hSignAlg, 0, BCRYPT_RSAPUBLIC_BLOB, &hPubKey, pubkeyblob, dwlen, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptImportKeyPair failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } secstat = NCryptSignHash(hKey, paddingInfo, hash, hashlen, signature, sizeof(signature), &dwlen, padding); if (secstat != ERROR_SUCCESS) { printf("\nNCryptSignHash failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } ntstat = BCryptVerifySignature(hPubKey, paddingInfo, hash, hashlen, signature, dwlen, padding); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptVerifySignature failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } BCryptDestroyKey(hPubKey); // Verify with certificate // Get certificate for key secstat = NCryptGetProperty(hKey, NCRYPT_CERTIFICATE_PROPERTY, cert, sizeof(cert), &dwlen, 0); if (secstat != ERROR_SUCCESS) { printf("\nNCryptGetProperty failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } certctx = CertCreateCertificateContext(X509_ASN_ENCODING, cert, dwlen); if (certctx == NULL) { dwrc = GetLastError(); printf("\nCertCreateCertificateContext failed: %04x %s\n", dwrc, SystemErrorMsg(dwrc)); return -1; } if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, &certctx->pCertInfo->SubjectPublicKeyInfo, 0, NULL, &hPubKey)) { dwrc = GetLastError(); printf("\nCryptImportPublicKeyInfoEx2 failed: %04x %s\n", dwrc, SystemErrorMsg(dwrc)); return -1; } secstat = NCryptSignHash(hKey, paddingInfo, hash, hashlen, signature, sizeof(signature), &dwlen, padding); if (secstat != ERROR_SUCCESS) { printf("\nNCryptSignHash failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } ntstat = BCryptVerifySignature(hPubKey, paddingInfo, hash, hashlen, signature, dwlen, padding); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptVerifySignature failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } BCryptDestroyKey(hPubKey); CertFreeCertificateContext(certctx); return 0; } int testSignECDSA(NCRYPT_KEY_HANDLE hKey, LPCWSTR hashAlg ) { BCRYPT_KEY_HANDLE hPubKey; SECURITY_STATUS secstat; PCCERT_CONTEXT certctx; // BCRYPT_ALG_HANDLE hSignAlg; NTSTATUS ntstat; unsigned char cert[4096],hash[64],signature[256]; // ,pubkeyblob[1024]; DWORD dwrc,dwlen,hashlen; printf(" ECDSA with %S", hashAlg); memset(hash, 0xA5, sizeof(hash)); hashlen = sizeof(hash); if (!wcscmp(hashAlg, BCRYPT_SHA1_ALGORITHM)) { hashlen = 20; } else if (!wcscmp(hashAlg, BCRYPT_SHA256_ALGORITHM)) { hashlen = 32; } else if (!wcscmp(hashAlg, BCRYPT_SHA384_ALGORITHM)) { hashlen = 48; } else if (!wcscmp(hashAlg, BCRYPT_SHA512_ALGORITHM)) { hashlen = 64; } else if (!wcscmp(hashAlg, BCRYPT_MD5_ALGORITHM)) { hashlen = 16; } #if 0 // Export public key from smart card secstat = NCryptExportKey(hKey, 0, BCRYPT_ECCPUBLIC_BLOB, 0, pubkeyblob, sizeof(pubkeyblob), &dwlen, 0); if (secstat != ERROR_SUCCESS) { printf("\nNCryptExportKey failed: %08lx %s\n", ntstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } ntstat = BCryptOpenAlgorithmProvider(&hSignAlg, BCRYPT_ECDSA_P256_ALGORITHM, NULL, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptOpenAlgorithmProvider failed: %ld\n", ntstat); return -1; } ntstat = BCryptImportKeyPair(hSignAlg, 0, BCRYPT_ECCPUBLIC_BLOB, &hPubKey, pubkeyblob, dwlen, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptImportKeyPair failed: %ld\n", ntstat); return -1; } secstat = NCryptSignHash(hKey, NULL, hash, hashlen, signature, dwlen, &dwlen, 0); if (secstat != ERROR_SUCCESS) { printf("\nNCryptSignHash failed: %08lx %s\n", ntstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } ntstat = BCryptVerifySignature(hPubKey, NULL, hash, hashlen, signature, dwlen, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptVerifySignature failed: %ld\n", ntstat); return -1; } BCryptDestroyKey(hPubKey); #endif // Get certificate for key secstat = NCryptGetProperty(hKey, NCRYPT_CERTIFICATE_PROPERTY, cert, sizeof(cert), &dwlen, 0); if (secstat != ERROR_SUCCESS) { printf("\nNCryptGetProperty failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } certctx = CertCreateCertificateContext(X509_ASN_ENCODING, cert, dwlen); if (certctx == NULL) { dwrc = GetLastError(); printf("\nCertCreateCertificateContext failed: %04x %s\n", dwrc, SystemErrorMsg(dwrc)); return -1; } if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, &certctx->pCertInfo->SubjectPublicKeyInfo, 0, NULL, &hPubKey)) { dwrc = GetLastError(); printf("\nCryptImportPublicKeyInfoEx2 failed: %04x %s\n", dwrc, SystemErrorMsg(dwrc)); return -1; } secstat = NCryptSignHash(hKey, NULL, hash, hashlen, signature, dwlen, &dwlen, 0); if (secstat != ERROR_SUCCESS) { printf("\nNCryptSignHash failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } ntstat = BCryptVerifySignature(hPubKey, NULL, hash, hashlen, signature, dwlen, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptVerifySignature failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } BCryptDestroyKey(hPubKey); CertFreeCertificateContext(certctx); return 0; } int testDecryptRSA(NCRYPT_KEY_HANDLE hKey, DWORD padding ) { BCRYPT_KEY_HANDLE hPubKey; SECURITY_STATUS secstat; BCRYPT_OAEP_PADDING_INFO oaeppadinfo; BCRYPT_ALG_HANDLE hSignAlg; void *paddingInfo; NTSTATUS ntstat; unsigned char secret[48],plain[256],cryptogram[256],pubkeyblob[1024]; DWORD dwlen,secretlen; printf(" RSA decryption with %s padding", (padding == BCRYPT_PAD_PKCS1 ? "V1.5" : "OAEP")); memset(secret, 0xA5, sizeof(secret)); secret[0] = 0x5A; secretlen = sizeof(secret); if (padding == BCRYPT_PAD_PKCS1) { paddingInfo = NULL; } else { memset(&oaeppadinfo, 0, sizeof(oaeppadinfo)); oaeppadinfo.pszAlgId = BCRYPT_SHA256_ALGORITHM; paddingInfo = &oaeppadinfo; } // Export public key from smart card secstat = NCryptExportKey(hKey, 0, BCRYPT_RSAPUBLIC_BLOB, 0, pubkeyblob, sizeof(pubkeyblob), &dwlen, 0); if (secstat != ERROR_SUCCESS) { printf("\nNCryptExportKey failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } ntstat = BCryptOpenAlgorithmProvider(&hSignAlg, BCRYPT_RSA_ALGORITHM, NULL, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptOpenAlgorithmProvider failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } ntstat = BCryptImportKeyPair(hSignAlg, 0, BCRYPT_RSAPUBLIC_BLOB, &hPubKey, pubkeyblob, dwlen, 0); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptImportKeyPair failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } ntstat = BCryptEncrypt(hPubKey, secret, secretlen, paddingInfo, NULL, 0, cryptogram, sizeof(cryptogram), &dwlen, padding); if (ntstat != ERROR_SUCCESS) { printf("\nBCryptEncrypt failed: %08lx %s", ntstat, NTSTATUSErrorMsg(ntstat)); return -1; } secstat = NCryptDecrypt(hKey, cryptogram, dwlen, paddingInfo, plain, sizeof(plain), &dwlen, padding); if (secstat != ERROR_SUCCESS) { printf("\nNCryptExportKey failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } BCryptDestroyKey(hPubKey); if ((secretlen != dwlen) || memcmp(plain, secret, secretlen)) { printf("\nDecrypted data does not match plain data\n"); return -1; } return 0; } int cryptoTests() { NCRYPT_PROV_HANDLE hProvider; NCRYPT_KEY_HANDLE hKey; NCryptKeyName *keyName; PVOID enumState = NULL; SECURITY_STATUS secstat; NCryptAlgorithmName *algos; DWORD dwlen, dwi; int rc; secstat = NCryptOpenStorageProvider(&hProvider, MS_SMART_CARD_KEY_STORAGE_PROVIDER, 0); if (secstat != ERROR_SUCCESS) { printf("NCryptOpenStorageProvider failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } secstat = NCryptEnumAlgorithms(hProvider, NCRYPT_CIPHER_OPERATION|NCRYPT_HASH_OPERATION|NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION|NCRYPT_SECRET_AGREEMENT_OPERATION, &dwlen, &algos, 0); if (secstat != ERROR_SUCCESS) { printf("NCryptEnumAlgorithms failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } for (dwi = 0; dwi < dwlen; dwi++) { printf("%S %lx %lx %lx\n", (algos + dwi)->pszName, (algos + dwi)->dwClass, (algos + dwi)->dwAlgOperations, (algos + dwi)->dwFlags); } NCryptFreeBuffer(algos); while (TRUE) { secstat = NCryptEnumKeys(hProvider, NULL, &keyName, &enumState, 0); if (secstat != ERROR_SUCCESS) { break; } printf("%S (%S)\n", keyName->pszName, keyName->pszAlgid); secstat = NCryptOpenKey(hProvider, &hKey, keyName->pszName, 0, 0); if (secstat != ERROR_SUCCESS) { printf("NCryptOpenKey failed: %08lx %s\n", secstat, SECURITY_STATUSErrorMsg(secstat)); return -1; } if ((keyName->dwLegacyKeySpec == AT_KEYEXCHANGE) || (keyName->dwLegacyKeySpec == AT_SIGNATURE)) { rc = testSignRSA(hKey, BCRYPT_PAD_PKCS1, BCRYPT_SHA1_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignRSA(hKey, BCRYPT_PAD_PKCS1, BCRYPT_SHA256_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignRSA(hKey, BCRYPT_PAD_PKCS1, BCRYPT_SHA384_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignRSA(hKey, BCRYPT_PAD_PKCS1, BCRYPT_SHA512_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignRSA(hKey, BCRYPT_PAD_PKCS1, BCRYPT_MD5_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignRSA(hKey, BCRYPT_PAD_PSS, BCRYPT_SHA1_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignRSA(hKey, BCRYPT_PAD_PSS, BCRYPT_SHA256_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testDecryptRSA(hKey, BCRYPT_PAD_PKCS1 ); printf(" - %s\n", verdict(rc == 0)); rc = testDecryptRSA(hKey, BCRYPT_PAD_OAEP ); printf(" - %s\n", verdict(rc == 0)); } else { rc = testSignECDSA(hKey, BCRYPT_SHA1_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignECDSA(hKey, BCRYPT_SHA256_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignECDSA(hKey, BCRYPT_SHA384_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignECDSA(hKey, BCRYPT_SHA512_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); rc = testSignECDSA(hKey, BCRYPT_MD5_ALGORITHM ); printf(" - %s\n", verdict(rc == 0)); } NCryptFreeObject(hKey); } NCryptFreeObject(hProvider); return 0; } int listReaders() { SCARDCONTEXT hSCardCtx; DWORD cch = 0; LPTSTR readers = NULL; if (SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hSCardCtx) != SCARD_S_SUCCESS) { printf("SCardEstablishContext() failed\n"); exit(1); } if (SCardListReaders(hSCardCtx, NULL, NULL, &cch) != SCARD_S_SUCCESS) { printf("SCardListReaders() failed\n"); exit(1); } readers = malloc(cch); reader = readers; if (SCardListReaders(hSCardCtx, NULL, readers, &cch) != SCARD_S_SUCCESS) { printf("SCardListReaders() failed\n"); exit(1); } while(*readers) { printf("%s\n", readers); readers += strlen(readers) + 1; } SCardReleaseContext(hSCardCtx); return 0; } int apiTests(char *reader) { HMODULE dlhandle; PFN_CARD_ACQUIRE_CONTEXT pcac; CARD_FREE_SPACE_INFO cardFreeSpaceInfo; CARD_CAPABILITIES cardCapabilities; CARD_DATA cardData; CARD_KEY_SIZES keySizes; CARD_FILE_INFO fileInfo; CONTAINER_INFO containerInfo; PIN_INFO pinInfo; LPSTR filenames; PBYTE pb; DWORD readernamelen, state, protocol, atrlen; unsigned char atr[36], cardid[16]; DWORD dwrc,dwlen,dwparam; BOOL flag; char *pinEnv = getenv("MINIDRIVER_PIN"); if (pinEnv) printf("Running tests using PIN=%s/len=%zd\n", pinEnv, strlen(pinEnv)); else printf("Running tests wihtout any PIN\n"); memset(&cardData, 0, sizeof(cardData)); cardData.dwVersion = 7; cardData.pwszCardName = L"TestCard"; cardData.pfnCspAlloc = CSP_ALLOC; cardData.pfnCspReAlloc = CSP_REALLOC; cardData.pfnCspFree = CSP_FREE; if (SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &cardData.hSCardCtx) != SCARD_S_SUCCESS) { printf("SCardEstablishContext() failed\n"); exit(1); } dlhandle = LoadLibrary("opensc-minidriver.dll"); if (!dlhandle) { dwrc = GetLastError(); printf("LoadLibrary failed %04x %s\n", dwrc, SystemErrorMsg(dwrc)); exit(1); } pcac = (PFN_CARD_ACQUIRE_CONTEXT)GetProcAddress(dlhandle, "CardAcquireContext"); readernamelen = 0; atrlen = sizeof(atr); if (SCardConnect(cardData.hSCardCtx, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &cardData.hScard, &protocol) != SCARD_S_SUCCESS) { printf("SCardStatus() failed\n"); exit(1); } if (SCardStatus(cardData.hScard, NULL, &readernamelen, &state, &protocol, atr, &atrlen) != SCARD_S_SUCCESS) { printf("SCardStatus() failed\n"); exit(1); } cardData.pbAtr = atr; cardData.cbAtr = atrlen; printf("Calling CardAcquireContext()"); dwrc = (*pcac)(&cardData, 0); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardQueryFreeSpace()"); cardFreeSpaceInfo.dwVersion = CARD_FREE_SPACE_INFO_CURRENT_VERSION; dwrc = (*cardData.pfnCardQueryFreeSpace)(&cardData, 0, &cardFreeSpaceInfo); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_FREE_SPACE)"); cardFreeSpaceInfo.dwVersion = CARD_FREE_SPACE_INFO_CURRENT_VERSION; dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_FREE_SPACE, (PBYTE)&cardFreeSpaceInfo, sizeof(cardFreeSpaceInfo), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardQueryCapabilities()"); cardCapabilities.dwVersion = CARD_CAPABILITIES_CURRENT_VERSION; dwrc = (*cardData.pfnCardQueryCapabilities)(&cardData, &cardCapabilities); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_CAPABILITIES)"); cardCapabilities.dwVersion = CARD_CAPABILITIES_CURRENT_VERSION; dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_CAPABILITIES, (PBYTE)&cardCapabilities, sizeof(cardCapabilities), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardQueryKeySizes()"); keySizes.dwVersion = CARD_KEY_SIZES_CURRENT_VERSION; dwrc = (*cardData.pfnCardQueryKeySizes)(&cardData, AT_SIGNATURE, 0, &keySizes); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_KEYSIZES)"); keySizes.dwVersion = CARD_KEY_SIZES_CURRENT_VERSION; dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_KEYSIZES, (PBYTE)&keySizes, sizeof(keySizes), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_READ_ONLY)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_READ_ONLY, (PBYTE)&flag, sizeof(flag), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && flag)); printf("Calling CardGetProperty(CP_CARD_CACHE_MODE)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_CACHE_MODE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == CP_CACHE_MODE_NO_CACHE))); printf("Calling CardGetProperty(CP_SUPPORTS_WIN_X509_ENROLLMENT)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_SUPPORTS_WIN_X509_ENROLLMENT, (PBYTE)&flag, sizeof(flag), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && !flag)); printf("Calling CardGetProperty(CP_CARD_GUID)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_GUID, (PBYTE)&cardid, sizeof(cardid), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_SERIAL_NO)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_SERIAL_NO, (PBYTE)&cardid, sizeof(cardid), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_PIN_INFO)"); pinInfo.dwVersion = PIN_INFO_CURRENT_VERSION; dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_PIN_INFO, (PBYTE)&pinInfo, sizeof(pinInfo), &dwlen, ROLE_USER); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_LIST_PINS)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_LIST_PINS, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (IS_PIN_SET(dwparam, ROLE_USER)))); /* let's continue the tests only for the ROLE_USER */ dwparam = 0; SET_PIN(dwparam, ROLE_USER); printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0))); printf("Calling CardGetProperty(CP_CARD_PIN_STRENGTH_VERIFY)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_PIN_STRENGTH_VERIFY, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, ROLE_USER); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == CARD_PIN_STRENGTH_PLAINTEXT))); printf("Calling CardGetProperty(CP_KEY_IMPORT_SUPPORT)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_KEY_IMPORT_SUPPORT, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0))); printf("Calling CardReadFile(cardid)"); dwrc = (*cardData.pfnCardReadFile)(&cardData, NULL, szCARD_IDENTIFIER_FILE, 0, &pb, &dwlen); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen == 16))); printf("Calling CardReadFile(cardcf)"); dwrc = (*cardData.pfnCardReadFile)(&cardData, NULL, szCACHE_FILE, 0, &pb, &dwlen); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen == 6))); printf("Calling CardReadFile(cardapps)"); dwrc = (*cardData.pfnCardReadFile)(&cardData, NULL, "cardapps", 0, &pb, &dwlen); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen == 8))); printf("Calling CardReadFile(mscp/cmapfile)"); dwrc = (*cardData.pfnCardReadFile)(&cardData, szBASE_CSP_DIR, szCONTAINER_MAP_FILE, 0, &pb, &dwlen); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen > 0))); printf("Calling CardReadFile(mscp/msroots)"); dwrc = (*cardData.pfnCardReadFile)(&cardData, szBASE_CSP_DIR, szROOT_STORE_FILE, 0, &pb, &dwlen); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen > 0))); printf("Calling CardGetFileInfo(mscp/cmapfile)"); fileInfo.dwVersion = CARD_FILE_INFO_CURRENT_VERSION; dwrc = (*cardData.pfnCardGetFileInfo)(&cardData, szBASE_CSP_DIR, szCONTAINER_MAP_FILE, &fileInfo); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen > 0))); printf("Calling CardReadFile(mscp/kxc00)"); dwrc = (*cardData.pfnCardReadFile)(&cardData, szBASE_CSP_DIR, szUSER_KEYEXCHANGE_CERT_PREFIX "00", 0, &pb, &dwlen); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen > 0))); printf("Calling CardEnumFiles(root)"); dwrc = (*cardData.pfnCardEnumFiles)(&cardData, NULL, &filenames, &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwlen > 0))); printf("Calling CardGetContainerInfo(0)"); containerInfo.dwVersion = CONTAINER_INFO_CURRENT_VERSION; dwrc = (*cardData.pfnCardGetContainerInfo)(&cardData, 0, 0, &containerInfo); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardAuthenticatePin(wszCARD_USER_USER)"); if (pinEnv) { dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, pinEnv, (DWORD)strlen(pinEnv), &dwparam); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == -1))); printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 2))); printf("Calling CardAuthenticatePin(wszCARD_USER_USER) - Wrong PIN"); dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, "3456", 4, &dwparam); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_W_WRONG_CHV) && (dwparam == 2))); printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0))); printf("Calling CardAuthenticatePin(wszCARD_USER_USER)"); dwrc = (*cardData.pfnCardAuthenticatePin)(&cardData, wszCARD_USER_USER, pinEnv, (DWORD)strlen(pinEnv), &dwparam); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == -1))); printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 2))); printf("Calling CardDeAuthenticate(wszCARD_USER_USER)"); dwrc = (*cardData.pfnCardDeauthenticate)(&cardData, wszCARD_USER_USER, 0); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); printf("Calling CardGetProperty(CP_CARD_AUTHENTICATED_STATE)"); dwrc = (*cardData.pfnCardGetProperty)(&cardData, CP_CARD_AUTHENTICATED_STATE, (PBYTE)&dwparam, sizeof(dwparam), &dwlen, 0); printf(" - %x : %s\n", dwrc, verdict((dwrc == SCARD_S_SUCCESS) && (dwparam == 0))); } else { printf(" - skip: missing set MINIDRIVER_PIN=abcd\n"); } printf("Calling CardDeleteContext()"); dwrc = (*cardData.pfnCardDeleteContext)(&cardData); printf(" - %x : %s\n", dwrc, verdict(dwrc == SCARD_S_SUCCESS)); SCardReleaseContext(cardData.hSCardCtx); return 0; } int main(int argc, char *argv[]) { if (argc == 1) { printf("Usage: opensc-minidriver-test [-l] [-r ] [-a] [-c]\n"); printf(" -l list readers\n"); printf(" -r define readers\n"); printf(" -a run API tests\n"); printf(" -c run crypto tests\n"); exit(1); } argc--; argv++; while (argc--) { if (!strcmp(*argv, "-l")) { listReaders(); } else if (!strcmp(*argv, "-r")) { if (argc == 0) { printf("Reader name missing in -r parameter\n"); exit(1); } argv++; argc--; reader = *argv; } else if (!strcmp(*argv, "-a")) { if (reader == NULL) { printf("Need a reader name set with -r or use -l to select first reader\n"); exit(1); } apiTests(reader); } else if (!strcmp(*argv, "-c")) { cryptoTests(); } else { printf("Unknown parameter %s\n", *argv); } argv++; } printf("Unit test finished.\n"); printf("%d tests performed.\n", testscompleted); printf("%d tests failed.\n", testsfailed); exit(testsfailed ? 1 : 0); }