Coverage Report

Created: 2025-10-13 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-masktech.c
Line
Count
Source
1
/*
2
 * card-masktech.c: Support for Masktech smart cards using the MTCOS operating system.
3
 *
4
 * Copyright (C) 2011-2015 MaskTech GmbH Fischerstrasse 19, 87435 Kempten, Germany
5
 * Copyright (C) 2011 Andrey Uvarov (X-Infotech) <andrejs.uvarovs@x-infotech.com>
6
 * Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.com>
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
27
#include <stdlib.h>
28
#include <string.h>
29
30
#include "internal.h"
31
#include "cardctl.h"
32
#include "iso7816.h"
33
34
static struct sc_atr_table masktech_atrs[] = {
35
  {"3B:89:80:01:4D:54:43:4F:53:70:02:00:04:31",
36
   "FF:FF:FF:FF:FF:FF:FF:FF:FF:FC:FF:FC:F4:F5" , NULL,
37
   SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
38
  {"3B:88:80:01:00:00:00:00:77:81:80:00:6E", "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:EE:FF:EE", NULL,
39
   SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
40
  {"3B:9D:13:81:31:60:35:80:31:C0:69:4D:54:43:4F:53:73:02:00:00:40",
41
   "FF:FF:FF:FF:FF:FF:FD:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FC:F0:F0", NULL,
42
   SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
43
  {NULL, NULL, NULL, 0, 0, NULL}
44
};
45
46
static struct sc_card_operations *iso_ops;
47
static struct sc_card_operations masktech_ops;
48
static struct sc_card_driver masktech_drv = {
49
  "MaskTech Smart Card",
50
  "MaskTech",
51
  &masktech_ops,
52
  masktech_atrs, 0, NULL
53
};
54
55
struct masktech_private_data {
56
  /* save the key reference set at set_masktech_set_security_env to recover it as the signature step */
57
  int rsa_key_ref;
58
59
};
60
61
static int masktech_match_card(sc_card_t * card)
62
7.98k
{
63
  /* check if the ATR is in the known ATR */
64
7.98k
  if (_sc_match_atr(card, masktech_atrs, &card->type) < 0)
65
7.96k
    return 0;
66
67
21
  return 1;
68
7.98k
}
69
70
static int masktech_init(sc_card_t * card)
71
21
{
72
21
  unsigned long flags;
73
21
  struct masktech_private_data *data;
74
75
21
  sc_log(card->ctx,  "masktech_init()\n");
76
77
  /* private data kept during the live of the driver */
78
21
  if (!(data = (struct masktech_private_data *) malloc(sizeof(*data))))
79
0
    return SC_ERROR_OUT_OF_MEMORY;
80
21
  card->drv_data = data;
81
82
  /* supported RSA keys and how padding is done */
83
21
  flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
84
21
  _sc_card_add_rsa_alg(card, 1024, flags, 0);
85
21
  _sc_card_add_rsa_alg(card, 2048, flags, 0);
86
21
  _sc_card_add_rsa_alg(card, 3072, flags, 0);
87
21
  card->caps |= SC_CARD_CAP_APDU_EXT;
88
21
  return SC_SUCCESS;
89
21
}
90
91
92
static int masktech_finish(sc_card_t *card)
93
21
{
94
  /* free the private data */
95
21
  if (card->drv_data) {
96
21
    free(card->drv_data);
97
21
    card->drv_data = NULL;
98
21
  }
99
21
  return 0;
100
21
}
101
102
static int masktech_set_security_env(sc_card_t *card,
103
                                     const sc_security_env_t *env,
104
                                     int se_num)
105
0
{
106
0
  struct masktech_private_data *private_data;
107
0
  sc_log(card->ctx,  "masktech_set_security_env(), keyRef = 0x%0x, algo = 0x%0lx\n",
108
0
     *env->key_ref, env->algorithm_flags);
109
110
0
  private_data = (struct masktech_private_data *) card->drv_data;
111
0
  if (!private_data)
112
0
    return SC_ERROR_INTERNAL;
113
114
  /* save the key reference */
115
0
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
116
0
    if (env->key_ref_len != 1) {
117
0
      sc_log(card->ctx,  "Invalid key reference supplied.\n");
118
0
      return SC_ERROR_NOT_SUPPORTED;
119
0
    }
120
0
    private_data->rsa_key_ref = env->key_ref[0];
121
0
  }
122
123
0
  return iso_ops->set_security_env(card, env, se_num);
124
0
}
125
126
static int masktech_compute_signature(sc_card_t *card,
127
                                      const u8 * data,
128
                                      size_t datalen,
129
                                      u8 * out,
130
                                      size_t outlen)
131
0
{
132
133
0
  struct masktech_private_data *private_data;
134
0
  u8 sha256hash[32];
135
0
  static const u8 hdr_sha256[] = {
136
0
    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
137
0
    0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
138
0
  };
139
0
  assert(card != NULL && data != NULL && out != NULL);
140
0
  sc_log(card->ctx,  "masktech_compute_signature()\n");
141
142
  /* retrieve the key reference */
143
0
  private_data = (struct masktech_private_data *) card->drv_data;
144
0
  if (!private_data)
145
0
    return SC_ERROR_INTERNAL;
146
147
0
  if (private_data->rsa_key_ref == 0x88)
148
0
  {
149
    /* for this key reference, the card supports only SHA256 hash and the hash is computed using a digest info */
150
    /* check that it is a SHA256 with digest info*/
151
0
    if ((datalen != sizeof(hdr_sha256) + 32) || (memcmp(hdr_sha256, data, sizeof(hdr_sha256)) != 0))
152
0
    {
153
0
      sc_log(card->ctx,  "It is not a SHA256 with digestinfo\n");
154
0
      return SC_ERROR_NOT_SUPPORTED;
155
0
    }
156
    /* extract the SHA-256 hash */
157
0
    memcpy(sha256hash, (u8 *)(data+(datalen-32)), 32);//only last 32 byte => sha256
158
    /* default ISO 7816 functions */
159
0
    return iso_ops->compute_signature(card, sha256hash, 32, out, outlen);
160
0
  }
161
0
  else
162
0
  {
163
    /* default ISO 7816 functions */
164
0
    return iso_ops->compute_signature(card, data, datalen, out, outlen);
165
0
  }
166
0
}
167
168
static int masktech_decipher(sc_card_t *card,
169
                             const u8 * crgram,
170
                             size_t crgram_len,
171
                             u8 * out,
172
                             size_t outlen)
173
0
{
174
0
  int r;
175
0
  sc_apdu_t apdu;
176
0
  u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE];
177
178
0
  assert(card != NULL && crgram != NULL && out != NULL);
179
0
  sc_log(card->ctx,  "masktech_decipher()\n");
180
181
0
  if (crgram_len > SC_MAX_EXT_APDU_BUFFER_SIZE) {
182
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
183
0
  }
184
185
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86);
186
0
  apdu.resp = rbuf;
187
0
  apdu.resplen = sizeof(rbuf);
188
  /* the card doesn't support anything else here (+1 / -1 is not working) */
189
0
  apdu.le = 65536;
190
191
0
  apdu.data = crgram;
192
0
  apdu.lc = crgram_len;
193
0
  apdu.datalen = crgram_len;
194
195
0
  r = sc_transmit_apdu(card, &apdu);
196
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
197
0
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
198
0
    size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
199
200
0
    memcpy(out, apdu.resp, len);
201
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)len);
202
0
  }
203
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
204
0
}
205
206
/* unblock pin cmd */
207
static int masktech_pin_unblock(sc_card_t *card,
208
                            struct sc_pin_cmd_data *data,
209
                            int *tries_left)
210
0
{
211
0
  int rv = 0;
212
0
  struct sc_pin_cmd_data verify_data;
213
0
  struct sc_pin_cmd_data reset_data;
214
215
  /* Build a SC_PIN_CMD_VERIFY APDU on PUK */
216
0
  memset(&verify_data, 0, sizeof(verify_data));
217
0
  verify_data.cmd = SC_PIN_CMD_VERIFY;
218
0
  verify_data.pin_type = 1;
219
0
  verify_data.pin_reference = 0x83;
220
0
  verify_data.pin1 = data->pin1;
221
0
  verify_data.flags = data->flags;
222
0
  verify_data.pin1.prompt = data->pin1.prompt;
223
224
0
  rv = iso_ops->pin_cmd(card, &verify_data, tries_left);
225
0
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed - verify unblock PIN");
226
227
  /* Build a SC_PIN_CMD_UNBLOCK APDU */
228
0
  memset(&reset_data, 0, sizeof(reset_data));
229
0
  reset_data.cmd = SC_PIN_CMD_UNBLOCK;
230
0
  reset_data.pin_type = 1;
231
0
  reset_data.pin_reference = 0x91;
232
  /* pin1 is set to null on purpose and flag set to implicit change
233
   => if there is a pinpad reader, do not ask for pin1 */
234
0
  reset_data.pin2 = data->pin2;
235
0
  reset_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE;
236
0
  reset_data.pin2.prompt = data->pin2.prompt;
237
238
0
  rv = iso_ops->pin_cmd(card, &reset_data, tries_left);
239
0
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed - reset unblock PIN");
240
241
0
  return 0;
242
0
}
243
244
static int masktech_pin_change(sc_card_t *card,
245
                            struct sc_pin_cmd_data *data,
246
                            int *tries_left)
247
0
{
248
0
  int rv = 0;
249
0
  struct sc_pin_cmd_data verify_data;
250
0
  struct sc_pin_cmd_data change_data;
251
252
  /* Build a SC_PIN_CMD_VERIFY APDU */
253
0
  memset(&verify_data, 0, sizeof(verify_data));
254
0
  verify_data.cmd = SC_PIN_CMD_VERIFY;
255
0
  verify_data.pin_type = 1;
256
0
  verify_data.pin_reference = data->pin_reference;
257
0
  verify_data.pin1 = data->pin1;
258
0
  verify_data.flags = data->flags;
259
0
  verify_data.pin1.prompt = data->pin1.prompt;
260
261
0
  rv = iso_ops->pin_cmd(card, &verify_data, tries_left);
262
0
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed - verify change PIN");
263
264
  /* Build a SC_PIN_CMD_CHANGE APDU */
265
0
  memset(&change_data, 0, sizeof(change_data));
266
0
  change_data.cmd = SC_PIN_CMD_CHANGE;
267
0
  change_data.pin_type = 1;
268
0
  change_data.pin_reference = data->pin_reference;
269
  /* pin1 is set to null on purpose and flag set to implicit change
270
   => if there is a pinpad reader, do not ask for pin1 */
271
0
  change_data.pin2 = data->pin2;
272
0
  change_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE;
273
0
  change_data.pin2.prompt = data->pin2.prompt;
274
275
0
  rv = iso_ops->pin_cmd(card, &change_data, tries_left);
276
0
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed - change PIN");
277
278
0
  return 0;
279
0
}
280
281
static int masktech_pin_cmd(sc_card_t *card,
282
                            struct sc_pin_cmd_data *data,
283
                            int *tries_left)
284
19
{
285
19
  int       rv;
286
19
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
287
288
19
  switch(data->cmd)
289
19
  {
290
0
  case SC_PIN_CMD_UNBLOCK:
291
0
    rv = masktech_pin_unblock(card, data, tries_left);
292
0
    break;
293
0
  case SC_PIN_CMD_CHANGE:
294
0
    rv = masktech_pin_change(card, data, tries_left);
295
0
    break;
296
19
  default:
297
19
    rv = iso_ops->pin_cmd(card, data, tries_left);
298
19
    break;
299
19
  }
300
19
  return rv;
301
302
303
19
}
304
305
static int masktech_get_serialnr(sc_card_t * card, sc_serial_number_t * serial)
306
19
{
307
19
  struct sc_apdu apdu;
308
19
  unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE-2];
309
19
  int rv;
310
311
19
  if (!serial)
312
19
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
313
314
  /* Get smart card serial number */
315
19
  card->cla = 0x80;
316
19
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x08, 0x00, 0x00);
317
19
  apdu.resplen = sizeof(apdu_resp);
318
19
  apdu.resp = apdu_resp;
319
320
19
  rv = sc_transmit_apdu(card, &apdu);
321
19
  card->cla = 0x00;
322
323
19
  LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
324
325
18
  if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
326
11
    return SC_ERROR_INTERNAL;
327
328
7
  if (SC_MAX_SERIALNR < apdu.resplen)
329
1
  {
330
1
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
331
1
  }
332
  /* cache serial number */
333
6
  card->serialnr.len = apdu.resplen;
334
6
  memcpy(card->serialnr.value, apdu.resp, card->serialnr.len);
335
336
  /* copy and return serial number */
337
6
  if (serial)
338
6
    memcpy(serial, &card->serialnr, sizeof(*serial));
339
340
6
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
341
6
}
342
343
344
static int masktech_card_ctl(sc_card_t * card, unsigned long cmd, void *ptr)
345
19
{
346
19
  sc_log(card->ctx,  "masktech_card_ctl()\n");
347
19
  switch (cmd) {
348
19
    case SC_CARDCTL_GET_SERIALNR:
349
19
      return masktech_get_serialnr(card, (sc_serial_number_t *) ptr);
350
0
    default:
351
0
      return SC_ERROR_NOT_SUPPORTED;
352
19
  }
353
19
}
354
355
static struct sc_card_driver *sc_get_driver(void)
356
16.0k
{
357
358
16.0k
  if (iso_ops == NULL)
359
1
    iso_ops = sc_get_iso7816_driver()->ops;
360
361
16.0k
  masktech_ops = *iso_ops;
362
363
16.0k
  masktech_ops.match_card = masktech_match_card;
364
16.0k
  masktech_ops.init = masktech_init;
365
16.0k
  masktech_ops.finish = masktech_finish;
366
16.0k
  masktech_ops.set_security_env = masktech_set_security_env;
367
16.0k
  masktech_ops.compute_signature = masktech_compute_signature;
368
16.0k
  masktech_ops.decipher = masktech_decipher;
369
16.0k
  masktech_ops.pin_cmd = masktech_pin_cmd;
370
16.0k
  masktech_ops.card_ctl = masktech_card_ctl;
371
16.0k
  return &masktech_drv;
372
16.0k
}
373
374
struct sc_card_driver *sc_get_masktech_driver(void)
375
16.0k
{
376
16.0k
  return sc_get_driver();
377
16.0k
}