1 /* 2 * Copyright (c) 2022 Yubico AB. All rights reserved. 3 * Use of this source code is governed by a BSD-style 4 * license that can be found in the LICENSE file. 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8 #include <assert.h> 9 #include <stdint.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <stdio.h> 13 #include <winscard.h> 14 15 #include "mutator_aux.h" 16 17 static const struct blob *reader_list; 18 static int (*xread)(void *, u_char *, size_t, int); 19 static int (*xwrite)(void *, const u_char *, size_t); 20 static void (*xconsume)(const void *, size_t); 21 22 LONG __wrap_SCardEstablishContext(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT); 23 LONG __wrap_SCardListReaders(SCARDCONTEXT, LPCSTR, LPSTR, LPDWORD); 24 LONG __wrap_SCardReleaseContext(SCARDCONTEXT); 25 LONG __wrap_SCardConnect(SCARDCONTEXT, LPCSTR, DWORD, DWORD, LPSCARDHANDLE, 26 LPDWORD); 27 LONG __wrap_SCardDisconnect(SCARDHANDLE, DWORD); 28 LONG __wrap_SCardTransmit(SCARDHANDLE, const SCARD_IO_REQUEST *, LPCBYTE, 29 DWORD, SCARD_IO_REQUEST *, LPBYTE, LPDWORD); 30 31 LONG 32 __wrap_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, 33 LPCVOID pvReserved2, LPSCARDCONTEXT phContext) 34 { 35 assert(dwScope == SCARD_SCOPE_SYSTEM); 36 assert(pvReserved1 == NULL); 37 assert(pvReserved2 == NULL); 38 39 *phContext = 1; 40 41 if (uniform_random(400) < 1) 42 return SCARD_E_NO_SERVICE; 43 if (uniform_random(400) < 1) 44 return SCARD_E_NO_SMARTCARD; 45 if (uniform_random(400) < 1) 46 return SCARD_E_NO_MEMORY; 47 if (uniform_random(400) < 1) 48 *phContext = 0; 49 50 return SCARD_S_SUCCESS; 51 } 52 53 LONG 54 __wrap_SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, 55 LPSTR mszReaders, LPDWORD pcchReaders) 56 { 57 assert(hContext == 1); 58 assert(mszGroups == NULL); 59 assert(mszReaders != NULL); 60 assert(pcchReaders != 0); 61 62 if (reader_list == NULL || uniform_random(400) < 1) 63 return SCARD_E_NO_READERS_AVAILABLE; 64 if (uniform_random(400) < 1) 65 return SCARD_E_NO_MEMORY; 66 67 memcpy(mszReaders, reader_list->body, reader_list->len > *pcchReaders ? 68 *pcchReaders : reader_list->len); 69 *pcchReaders = (DWORD)reader_list->len; /* on purpose */ 70 71 return SCARD_S_SUCCESS; 72 } 73 74 LONG 75 __wrap_SCardReleaseContext(SCARDCONTEXT hContext) 76 { 77 assert(hContext == 1); 78 79 return SCARD_S_SUCCESS; 80 } 81 82 LONG 83 __wrap_SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, 84 DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) 85 { 86 uint32_t r; 87 88 assert(hContext == 1); 89 xconsume(szReader, strlen(szReader) + 1); 90 assert(dwShareMode == SCARD_SHARE_SHARED); 91 assert(dwPreferredProtocols == SCARD_PROTOCOL_ANY); 92 assert(phCard != NULL); 93 assert(pdwActiveProtocol != NULL); 94 95 if ((r = uniform_random(400)) < 1) 96 return SCARD_E_UNEXPECTED; 97 98 *phCard = 1; 99 *pdwActiveProtocol = (r & 1) ? SCARD_PROTOCOL_T0 : SCARD_PROTOCOL_T1; 100 101 if (uniform_random(400) < 1) 102 *pdwActiveProtocol = SCARD_PROTOCOL_RAW; 103 104 return SCARD_S_SUCCESS; 105 } 106 107 LONG 108 __wrap_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) 109 { 110 assert(hCard == 1); 111 assert(dwDisposition == SCARD_LEAVE_CARD); 112 113 return SCARD_S_SUCCESS; 114 } 115 116 extern void consume(const void *body, size_t len); 117 118 LONG 119 __wrap_SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, 120 LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, 121 LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength) 122 { 123 void *ioh = (void *)NFC_DEV_HANDLE; 124 int n; 125 126 assert(hCard == 1); 127 xconsume(pioSendPci, sizeof(*pioSendPci)); 128 xwrite(ioh, pbSendBuffer, cbSendLength); 129 assert(pioRecvPci == NULL); 130 131 if (uniform_random(400) < 1 || 132 (n = xread(ioh, pbRecvBuffer, *pcbRecvLength, -1)) == -1) 133 return SCARD_E_UNEXPECTED; 134 *pcbRecvLength = (DWORD)n; 135 136 return SCARD_S_SUCCESS; 137 } 138 139 void 140 set_pcsc_parameters(const struct blob *reader_list_ptr) 141 { 142 reader_list = reader_list_ptr; 143 } 144 145 void 146 set_pcsc_io_functions(int (*read_f)(void *, u_char *, size_t, int), 147 int (*write_f)(void *, const u_char *, size_t), 148 void (*consume_f)(const void *, size_t)) 149 { 150 xread = read_f; 151 xwrite = write_f; 152 xconsume = consume_f; 153 } 154