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
__wrap_SCardEstablishContext(DWORD dwScope,LPCVOID pvReserved1,LPCVOID pvReserved2,LPSCARDCONTEXT phContext)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
__wrap_SCardListReaders(SCARDCONTEXT hContext,LPCSTR mszGroups,LPSTR mszReaders,LPDWORD pcchReaders)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
__wrap_SCardReleaseContext(SCARDCONTEXT hContext)75 __wrap_SCardReleaseContext(SCARDCONTEXT hContext)
76 {
77 assert(hContext == 1);
78
79 return SCARD_S_SUCCESS;
80 }
81
82 LONG
__wrap_SCardConnect(SCARDCONTEXT hContext,LPCSTR szReader,DWORD dwShareMode,DWORD dwPreferredProtocols,LPSCARDHANDLE phCard,LPDWORD pdwActiveProtocol)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
__wrap_SCardDisconnect(SCARDHANDLE hCard,DWORD dwDisposition)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
__wrap_SCardTransmit(SCARDHANDLE hCard,const SCARD_IO_REQUEST * pioSendPci,LPCBYTE pbSendBuffer,DWORD cbSendLength,SCARD_IO_REQUEST * pioRecvPci,LPBYTE pbRecvBuffer,LPDWORD pcbRecvLength)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
set_pcsc_parameters(const struct blob * reader_list_ptr)140 set_pcsc_parameters(const struct blob *reader_list_ptr)
141 {
142 reader_list = reader_list_ptr;
143 }
144
145 void
set_pcsc_io_functions(int (* read_f)(void *,u_char *,size_t,int),int (* write_f)(void *,const u_char *,size_t),void (* consume_f)(const void *,size_t))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