Coverage Report

Created: 2025-11-09 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/muscle.c
Line
Count
Source
1
/*
2
 * muscle.c: Support for MuscleCard Applet from musclecard.com
3
 *
4
 * Copyright (C) 2006, Identity Alliance, Thomas Harning <support@identityalliance.com>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include <string.h>
26
27
#include "internal.h"
28
#include "muscle.h"
29
30
0
#define MSC_RSA_PUBLIC    0x01
31
#define MSC_RSA_PRIVATE   0x02
32
#define MSC_RSA_PRIVATE_CRT 0x03
33
34
static msc_id inputId = { { 0xFF, 0xFF, 0xFF, 0xFF } };
35
static msc_id outputId = { { 0xFF, 0xFF, 0xFF, 0xFE } };
36
37
36.7k
int msc_list_objects(sc_card_t* card, u8 next, mscfs_file_t* file) {
38
36.7k
  sc_apdu_t apdu;
39
36.7k
  u8 fileData[14];
40
36.7k
  int r;
41
42
36.7k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x58, next, 0x00);
43
36.7k
  apdu.le = 14;
44
36.7k
  apdu.resplen = 14;
45
36.7k
  apdu.resp = fileData;
46
36.7k
  r = sc_transmit_apdu(card, &apdu);
47
36.7k
  if (r)
48
40
    return r;
49
50
36.6k
  if(apdu.sw1 == 0x9C && apdu.sw2 == 0x12) {
51
111
    return 0;
52
111
  }
53
36.5k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
54
36.5k
  if (r)
55
1.00k
    return r;
56
35.5k
  if(apdu.resplen == 0) /* No more left */
57
94
    return 0;
58
35.4k
  if (apdu.resplen != 14) {
59
19
    sc_log(card->ctx,
60
19
       "expected 14 bytes, got %"SC_FORMAT_LEN_SIZE_T"u.\n",
61
19
       apdu.resplen);
62
19
    return SC_ERROR_UNKNOWN_DATA_RECEIVED;
63
19
  }
64
35.4k
  memcpy(file->objectId.id, fileData, 4);
65
35.4k
  file->size = bebytes2ulong(fileData + 4);
66
35.4k
  file->read = bebytes2ushort(fileData + 8);
67
35.4k
  file->write = bebytes2ushort(fileData + 10);
68
35.4k
  file->delete = bebytes2ushort(fileData + 12);
69
70
35.4k
  return 1;
71
35.4k
}
72
73
int msc_partial_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength)
74
326
{
75
326
  u8 buffer[9];
76
326
  sc_apdu_t apdu;
77
326
  int r;
78
79
326
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x56, 0x00, 0x00);
80
81
326
  sc_log(card->ctx,
82
326
    "READ: Offset: %x\tLength: %"SC_FORMAT_LEN_SIZE_T"u\n", offset,
83
326
     dataLength);
84
326
  memcpy(buffer, objectId.id, 4);
85
326
  ulong2bebytes(buffer + 4, offset);
86
326
  buffer[8] = (u8)dataLength;
87
326
  apdu.data = buffer;
88
326
  apdu.datalen = 9;
89
326
  apdu.lc = 9;
90
326
  apdu.le = dataLength;
91
326
  apdu.resplen = dataLength;
92
326
  apdu.resp = data;
93
326
  r = sc_transmit_apdu(card, &apdu);
94
326
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
95
309
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && dataLength <= apdu.resplen)
96
227
    return (int)dataLength;
97
82
  if (apdu.sw1 == 0x9C) {
98
4
    if (apdu.sw2 == 0x07) {
99
1
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_NOT_FOUND);
100
3
    } else if (apdu.sw2 == 0x06) {
101
1
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED);
102
2
    } else if (apdu.sw2 == 0x0F) {
103
      /* GUESSED */
104
1
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
105
1
    }
106
4
  }
107
79
  sc_log(card->ctx,
108
79
    "got strange SWs: 0x%02X 0x%02X\n", apdu.sw1, apdu.sw2);
109
79
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
110
79
}
111
112
int msc_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength)
113
326
{
114
326
  int r = 0;
115
326
  unsigned int i;
116
326
  size_t max_read_unit = MSC_MAX_READ;
117
118
553
  for (i = 0; i < dataLength; i += r) {
119
326
    r = msc_partial_read_object(card, objectId, offset + i, data + i, MIN(dataLength - i, max_read_unit));
120
326
    LOG_TEST_RET(card->ctx, r, "Error in partial object read");
121
227
    if (r == 0)
122
0
      break;
123
227
  }
124
227
  return (int)dataLength;
125
326
}
126
127
int msc_zero_object(sc_card_t *card, msc_id objectId, size_t dataLength)
128
0
{
129
0
  u8 zeroBuffer[MSC_MAX_APDU];
130
0
  size_t i;
131
0
  size_t max_write_unit = MIN(MSC_MAX_APDU, MSC_MAX_SEND - 9); /* - 9 for object ID+length */
132
133
0
  memset(zeroBuffer, 0, max_write_unit);
134
0
  for(i = 0; i < dataLength; i += max_write_unit) {
135
0
    int r = msc_partial_update_object(card, objectId, i, zeroBuffer, MIN(dataLength - i, max_write_unit));
136
0
    LOG_TEST_RET(card->ctx, r, "Error in zeroing file update");
137
0
  }
138
0
  return 0;
139
0
}
140
141
int msc_create_object(sc_card_t *card, msc_id objectId, size_t objectSize, unsigned short readAcl, unsigned short writeAcl, unsigned short deleteAcl)
142
0
{
143
0
  u8 buffer[14];
144
0
  sc_apdu_t apdu;
145
0
  int r;
146
147
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x5A, 0x00, 0x00);
148
0
  apdu.lc = 14;
149
0
  apdu.data = buffer,
150
0
  apdu.datalen = 14;
151
152
0
  memcpy(buffer, objectId.id, 4);
153
0
  ulong2bebytes(buffer + 4, objectSize);
154
0
  ushort2bebytes(buffer + 8, readAcl);
155
0
  ushort2bebytes(buffer + 10, writeAcl);
156
0
  ushort2bebytes(buffer + 12, deleteAcl);
157
0
  r = sc_transmit_apdu(card, &apdu);
158
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
159
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
160
0
    return (int)objectSize;
161
0
  if(apdu.sw1 == 0x9C) {
162
0
    if(apdu.sw2 == 0x01) {
163
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_MEMORY_FAILURE);
164
0
    } else if(apdu.sw2 == 0x08) {
165
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_ALREADY_EXISTS);
166
0
    } else if(apdu.sw2 == 0x06) {
167
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED);
168
0
    }
169
0
  }
170
0
  if (card->ctx->debug >= 2) {
171
0
    sc_log(card->ctx,  "got strange SWs: 0x%02X 0x%02X\n",
172
0
         apdu.sw1, apdu.sw2);
173
0
  }
174
0
  msc_zero_object(card, objectId, objectSize);
175
0
  return (int)objectSize;
176
0
}
177
178
/* Update up to MSC_MAX_READ - 9 bytes */
179
int msc_partial_update_object(sc_card_t *card, msc_id objectId, size_t offset, const u8 *data, size_t dataLength)
180
0
{
181
0
  u8 buffer[MSC_MAX_APDU];
182
0
  sc_apdu_t apdu;
183
0
  int r;
184
185
0
  if (dataLength + 9 > MSC_MAX_APDU)
186
0
    return SC_ERROR_INVALID_ARGUMENTS;
187
188
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x54, 0x00, 0x00);
189
0
  apdu.lc = dataLength + 9;
190
0
  if (card->ctx->debug >= 2)
191
0
    sc_log(card->ctx,
192
0
       "WRITE: Offset: %zx\tLength: %"SC_FORMAT_LEN_SIZE_T"u\n",
193
0
       offset, dataLength);
194
195
0
  memcpy(buffer, objectId.id, 4);
196
0
  ulong2bebytes(buffer + 4, offset);
197
0
  buffer[8] = (u8)dataLength;
198
0
  memcpy(buffer + 9, data, dataLength);
199
0
  apdu.data = buffer;
200
0
  apdu.datalen = apdu.lc;
201
0
  r = sc_transmit_apdu(card, &apdu);
202
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
203
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
204
0
    return (int)dataLength;
205
0
  if(apdu.sw1 == 0x9C) {
206
0
    if(apdu.sw2 == 0x07) {
207
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_NOT_FOUND);
208
0
    } else if(apdu.sw2 == 0x06) {
209
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED);
210
0
    } else if(apdu.sw2 == 0x0F) {
211
      /* GUESSED */
212
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
213
0
    }
214
0
  }
215
0
  if (card->ctx->debug >= 2) {
216
0
    sc_log(card->ctx,  "got strange SWs: 0x%02X 0x%02X\n",
217
0
         apdu.sw1, apdu.sw2);
218
0
  }
219
0
  return (int)dataLength;
220
0
}
221
222
int msc_update_object(sc_card_t *card, msc_id objectId, int offset, const u8 *data, size_t dataLength)
223
0
{
224
0
  int r;
225
0
  size_t i;
226
0
  size_t max_write_unit = MSC_MAX_SEND - 9;
227
0
  for(i = 0; i < dataLength; i += max_write_unit) {
228
0
    r = msc_partial_update_object(card, objectId, offset + i, data + i, MIN(dataLength - i, max_write_unit));
229
0
    LOG_TEST_RET(card->ctx, r, "Error in partial object update");
230
0
  }
231
0
  return (int)dataLength;
232
0
}
233
234
int msc_delete_object(sc_card_t *card, msc_id objectId, int zero)
235
0
{
236
0
  sc_apdu_t apdu;
237
0
  int r;
238
239
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x52, 0x00, zero ? 0x01 : 0x00);
240
0
  apdu.lc = 4;
241
0
  apdu.data = objectId.id;
242
0
  apdu.datalen = 4;
243
0
  r = sc_transmit_apdu(card, &apdu);
244
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
245
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
246
0
    return 0;
247
0
  if(apdu.sw1 == 0x9C) {
248
0
    if(apdu.sw2 == 0x07) {
249
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_NOT_FOUND);
250
0
    } else if(apdu.sw2 == 0x06) {
251
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED);
252
0
    }
253
0
  }
254
0
  if (card->ctx->debug >= 2) {
255
0
    sc_log(card->ctx,  "got strange SWs: 0x%02X 0x%02X\n",
256
0
         apdu.sw1, apdu.sw2);
257
0
  }
258
0
  return 0;
259
0
}
260
261
int msc_select_applet(sc_card_t *card, u8 *appletId, size_t appletIdLength)
262
6.10k
{
263
6.10k
  sc_apdu_t apdu;
264
6.10k
  int r;
265
266
6.10k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
267
6.10k
  apdu.lc = appletIdLength;
268
6.10k
  apdu.data = appletId;
269
6.10k
  apdu.datalen = appletIdLength;
270
6.10k
  apdu.resplen = 0;
271
6.10k
  apdu.le = 0;
272
273
6.10k
  r = sc_transmit_apdu(card, &apdu);
274
6.10k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
275
6.08k
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
276
519
    return 1;
277
278
5.56k
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,  SC_ERROR_CARD_CMD_FAILED);
279
5.56k
}
280
281
/* Truncate the nulls at the end of a PIN, useful in padding is unnecessarily added */
282
0
static void truncatePinNulls(const u8* pin, size_t *pinLength) {
283
0
  for(; *pinLength > 0; (*pinLength)--) {
284
0
    if(pin[*pinLength - 1]) break;
285
0
  }
286
0
}
287
288
int msc_verify_pin(sc_card_t *card, int pinNumber, const u8 *pinValue, int pinLength, int *tries)
289
0
{
290
0
  sc_apdu_t apdu;
291
0
  int r;
292
293
0
  const int bufferLength = MSC_MAX_PIN_LENGTH;
294
0
  u8 buffer[MSC_MAX_PIN_LENGTH];
295
296
0
  if (pinLength > MSC_MAX_PIN_LENGTH)
297
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
298
299
0
  r = msc_verify_pin_apdu(card, &apdu, buffer, bufferLength, pinNumber, pinValue, pinLength);
300
0
  LOG_TEST_RET(card->ctx, r, "APDU verification failed");
301
302
0
  if(tries)
303
0
    *tries = -1;
304
0
  r = sc_transmit_apdu(card, &apdu);
305
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
306
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
307
0
    return 0;
308
0
  } else if(apdu.sw1 == 0x63) { /* Invalid auth */
309
0
    if(tries)
310
0
      *tries = apdu.sw2 & 0x0F;
311
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT);
312
0
  } else if(apdu.sw1 == 0x9C && apdu.sw2 == 0x02) {
313
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT);
314
0
  } else if(apdu.sw1 == 0x69 && apdu.sw2 == 0x83) {
315
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_AUTH_METHOD_BLOCKED);
316
0
  }
317
318
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,  SC_ERROR_PIN_CODE_INCORRECT);
319
0
}
320
321
/* USE ISO_VERIFY due to tries return */
322
int msc_verify_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, u8* buffer, size_t bufferLength, int pinNumber, const u8 *pinValue, size_t pinLength)
323
0
{
324
0
  if (!buffer || bufferLength < (size_t)pinLength || pinLength > MSC_MAX_PIN_LENGTH)
325
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
326
327
0
  truncatePinNulls(pinValue, &pinLength);
328
329
0
  memcpy(buffer, pinValue, pinLength);
330
0
  sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, 0x42, pinNumber, 0);
331
0
  apdu->lc = pinLength;
332
0
  apdu->data = buffer;
333
0
  apdu->datalen = pinLength;
334
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
335
0
}
336
337
int msc_unblock_pin(sc_card_t *card, int pinNumber, const u8 *pukValue, int pukLength, int *tries)
338
0
{
339
0
  sc_apdu_t apdu;
340
0
  int r;
341
0
  const int bufferLength = MSC_MAX_PIN_LENGTH;
342
0
  u8 buffer[MSC_MAX_PIN_LENGTH];
343
344
0
  if (pukLength > MSC_MAX_PIN_LENGTH)
345
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
346
347
0
  r = msc_unblock_pin_apdu(card, &apdu, buffer, bufferLength, pinNumber, pukValue, pukLength);
348
0
  LOG_TEST_RET(card->ctx, r, "APDU unblock failed");
349
350
0
  if(tries)
351
0
    *tries = -1;
352
0
  r = sc_transmit_apdu(card, &apdu);
353
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
354
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
355
0
    return 0;
356
0
  } else if(apdu.sw1 == 0x63) { /* Invalid auth */
357
0
    if(tries)
358
0
      *tries = apdu.sw2 & 0x0F;
359
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT);
360
0
  } else if(apdu.sw1 == 0x9C && apdu.sw2 == 0x02) {
361
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT);
362
0
  } else if(apdu.sw1 == 0x69 && apdu.sw2 == 0x83) {
363
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_AUTH_METHOD_BLOCKED);
364
0
  }
365
366
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,  SC_ERROR_PIN_CODE_INCORRECT);
367
0
}
368
369
int msc_unblock_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, u8* buffer, size_t bufferLength, int pinNumber, const u8 *pukValue, size_t pukLength)
370
0
{
371
0
  if (!buffer || bufferLength < (size_t)pukLength || pukLength > MSC_MAX_PIN_LENGTH)
372
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
373
374
0
  truncatePinNulls(pukValue, &pukLength);
375
376
0
  memcpy(buffer, pukValue, pukLength);
377
0
  sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, 0x46, pinNumber, 0);
378
0
  apdu->lc = pukLength;
379
0
  apdu->data = buffer;
380
0
  apdu->datalen = pukLength;
381
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
382
0
}
383
384
int msc_change_pin(sc_card_t *card, int pinNumber, const u8 *pinValue, int pinLength, const u8 *newPin, int newPinLength, int *tries)
385
0
{
386
0
  sc_apdu_t apdu;
387
0
  int r;
388
0
  const int bufferLength = (MSC_MAX_PIN_LENGTH + 1) * 2;
389
0
  u8 buffer[(MSC_MAX_PIN_LENGTH + 1) * 2];
390
391
0
  r = msc_change_pin_apdu(card, &apdu, buffer, bufferLength, pinNumber, pinValue, pinLength, newPin, newPinLength);
392
0
  LOG_TEST_RET(card->ctx, r, "APDU change failed");
393
0
  if(tries)
394
0
    *tries = -1;
395
0
  r = sc_transmit_apdu(card, &apdu);
396
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
397
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
398
0
    return 0;
399
0
  } else if(apdu.sw1 == 0x63) { /* Invalid auth */
400
0
    if(tries)
401
0
      *tries = apdu.sw2 & 0x0F;
402
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT);
403
0
  } else if(apdu.sw1 == 0x9C && apdu.sw2 == 0x02) {
404
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT);
405
0
  } else if(apdu.sw1 == 0x69 && apdu.sw2 == 0x83) {
406
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_AUTH_METHOD_BLOCKED);
407
0
  }
408
409
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,  SC_ERROR_PIN_CODE_INCORRECT);
410
0
}
411
412
/* USE ISO_VERIFY due to tries return */
413
int msc_change_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, u8* buffer, size_t bufferLength, int pinNumber, const u8 *pinValue, size_t pinLength, const u8 *newPin, size_t newPinLength)
414
0
{
415
0
  u8 *ptr;
416
0
  if (pinLength > MSC_MAX_PIN_LENGTH || newPinLength > MSC_MAX_PIN_LENGTH
417
0
    || !buffer || bufferLength < pinLength + newPinLength + 2UL)
418
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
419
420
0
  truncatePinNulls(pinValue, &pinLength);
421
0
  truncatePinNulls(newPin, &newPinLength);
422
423
0
  ptr = buffer;
424
425
0
  sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, 0x44, pinNumber, 0);
426
0
  *ptr = pinLength;
427
0
  ptr++;
428
0
  memcpy(ptr, pinValue, pinLength);
429
0
  ptr += pinLength;
430
0
  *ptr = newPinLength;
431
0
  ptr++;
432
0
  memcpy(ptr, newPin, newPinLength);
433
0
  apdu->lc = pinLength + newPinLength + 2;
434
0
  apdu->datalen = apdu->lc;
435
0
  apdu->data = buffer;
436
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
437
0
}
438
439
int msc_get_challenge(sc_card_t *card, unsigned short dataLength, unsigned short seedLength, u8 *seedData, u8 *outputData)
440
0
{
441
0
  sc_apdu_t apdu;
442
0
  int r, location, cse;
443
0
  size_t len;
444
0
  u8 *buffer, *ptr;
445
446
0
  location = (dataLength < MSC_MAX_READ) ? 1 : 2; /* 1 == APDU, 2 == (seed in 0xFFFFFFFE, out in 0xFFFFFFFF) */
447
0
  cse = (location == 1) ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT;
448
0
  len = seedLength + 4;
449
450
0
  if (seedLength >= MSC_MAX_SEND - 4 || dataLength >= MSC_MAX_READ - 9)/* Output buffer doesn't seem to operate as desired.... nobody can read/delete */
451
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
452
453
0
  buffer = malloc(len);
454
0
  if(!buffer) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
455
0
  ptr = buffer;
456
0
  ushort2bebytes(ptr, dataLength);
457
0
  ptr+=2;
458
0
  ushort2bebytes(ptr, seedLength);
459
0
  ptr+=2;
460
0
  if(seedLength > 0) {
461
0
    memcpy(ptr, seedData, seedLength);
462
0
  }
463
0
  sc_format_apdu(card, &apdu, cse, 0x62, 0x00, location);
464
0
  apdu.data = buffer;
465
0
  apdu.datalen = len;
466
0
  apdu.lc = len;
467
468
0
  if(location == 1) {
469
0
    u8* outputBuffer = malloc(dataLength + 2);
470
0
    if(outputBuffer == NULL) {
471
0
      free(buffer);
472
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
473
0
    };
474
0
    apdu.le = dataLength + 2;
475
0
    apdu.resp = outputBuffer;
476
0
    apdu.resplen = dataLength + 2;
477
0
  }
478
0
  r = sc_transmit_apdu(card, &apdu);
479
0
  if(location == 1) {
480
0
    memcpy(outputData, apdu.resp + 2, dataLength);
481
0
    free(apdu.resp);
482
0
  }
483
0
  free(buffer);
484
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
485
0
  if(location == 1) {
486
0
    if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
487
0
      return SC_SUCCESS;
488
0
    } else {
489
0
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
490
0
      if (r) {
491
0
        if (card->ctx->debug >= 2) {
492
0
          sc_log(card->ctx,  "got strange SWs: 0x%02X 0x%02X\n",
493
0
               apdu.sw1, apdu.sw2);
494
0
        }
495
0
        LOG_FUNC_RETURN(card->ctx, r);
496
0
      }
497
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
498
0
    }
499
0
  } else {
500
0
    if(apdu.sw1 != 0x90 || apdu.sw2 != 0x00) {
501
0
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
502
0
      if (r) {
503
0
        if (card->ctx->debug >= 2) {
504
0
          sc_log(card->ctx,  "got strange SWs: 0x%02X 0x%02X\n",
505
0
               apdu.sw1, apdu.sw2);
506
0
        }
507
0
        LOG_FUNC_RETURN(card->ctx, r);
508
0
      }
509
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
510
0
    }
511
0
    r = msc_read_object(card, inputId, 2, outputData, dataLength);
512
0
    if(r < 0)
513
0
      LOG_FUNC_RETURN(card->ctx, r);
514
0
    msc_delete_object(card, inputId,0);
515
0
    LOG_FUNC_RETURN(card->ctx, r);
516
0
  }
517
0
}
518
519
int msc_generate_keypair(sc_card_t *card, int privateKey, int publicKey, int algorithm, size_t keySize, int options)
520
0
{
521
0
  sc_apdu_t apdu;
522
0
  u8 buffer[16]; /* Key pair payload length */
523
0
  u8 *ptr = buffer;
524
0
  int r;
525
0
  unsigned short prRead = 0xFFFF, prWrite = 0x0002, prCompute = 0x0002,
526
0
    puRead = 0x0000, puWrite = 0x0002, puCompute = 0x0000;
527
528
0
  if (privateKey > 0x0F || publicKey > 0x0F)
529
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
530
531
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x30, privateKey, publicKey);
532
533
0
  *ptr = algorithm; ptr++;
534
535
0
  ushort2bebytes(ptr, keySize);
536
0
  ptr+=2;
537
538
0
  ushort2bebytes(ptr, prRead);
539
0
  ptr+=2;
540
0
  ushort2bebytes(ptr, prWrite);
541
0
  ptr+=2;
542
0
  ushort2bebytes(ptr, prCompute);
543
0
  ptr+=2;
544
545
0
  ushort2bebytes(ptr, puRead);
546
0
  ptr+=2;
547
0
  ushort2bebytes(ptr, puWrite);
548
0
  ptr+=2;
549
0
  ushort2bebytes(ptr, puCompute);
550
0
  ptr+=2;
551
552
0
  *ptr = 0; /* options; -- no options for now, they need extra data */
553
554
0
  apdu.data = buffer;
555
0
  apdu.datalen = 16;
556
0
  apdu.lc = 16;
557
558
0
  r = sc_transmit_apdu(card, &apdu);
559
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
560
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
561
0
    return 0;
562
0
  }
563
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
564
0
  if (r) {
565
0
    if (card->ctx->debug >= 2) {
566
0
      sc_log(card->ctx,  "got strange SWs: 0x%02X 0x%02X\n",
567
0
           apdu.sw1, apdu.sw2);
568
0
    }
569
0
    LOG_FUNC_RETURN(card->ctx, r);
570
0
  }
571
0
  LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
572
0
}
573
574
int msc_extract_key(sc_card_t *card,
575
      int keyLocation)
576
0
{
577
0
  sc_apdu_t apdu;
578
0
  u8 encoding = 0;
579
0
  int r;
580
581
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x34, keyLocation, 0x00);
582
0
  apdu.data = &encoding;
583
0
  apdu.datalen = 1;
584
0
  apdu.lc = 1;
585
0
  r = sc_transmit_apdu(card, &apdu);
586
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
587
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
588
0
    return 0;
589
0
  }
590
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
591
0
  if (r) {
592
0
    if (card->ctx->debug >= 2) {
593
0
      sc_log(card->ctx,  "got strange SWs: 0x%02X 0x%02X\n",
594
0
           apdu.sw1, apdu.sw2);
595
0
    }
596
0
    LOG_FUNC_RETURN(card->ctx, r);
597
0
  }
598
0
  LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
599
0
}
600
601
int msc_extract_rsa_public_key(sc_card_t *card,
602
      int keyLocation,
603
      size_t* modLength,
604
      u8** modulus,
605
      size_t* expLength,
606
      u8** exponent)
607
0
{
608
0
  int r;
609
0
  u8 buffer[1024]; /* Should be plenty... */
610
0
  int fileLocation = 1;
611
612
0
  r = msc_extract_key(card, keyLocation);
613
0
  if(r < 0) LOG_FUNC_RETURN(card->ctx, r);
614
615
  /* Read keyType, keySize, and what should be the modulus size */
616
0
  r = msc_read_object(card, inputId, fileLocation, buffer, 5);
617
0
  fileLocation += 5;
618
0
  if(r < 0) LOG_FUNC_RETURN(card->ctx, r);
619
620
0
  if(buffer[0] != MSC_RSA_PUBLIC) LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
621
0
  *modLength = (buffer[3] << 8) | buffer[4];
622
  /* Read the modulus and the exponent length */
623
624
0
  if (*modLength + 2 > sizeof buffer)
625
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
626
0
  r = msc_read_object(card, inputId, fileLocation, buffer, *modLength + 2);
627
0
  fileLocation += *modLength + 2;
628
0
  if(r < 0) LOG_FUNC_RETURN(card->ctx, r);
629
630
0
  *modulus = malloc(*modLength);
631
0
  if(!*modulus) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
632
0
  memcpy(*modulus, buffer, *modLength);
633
0
  *expLength = (buffer[*modLength] << 8) | buffer[*modLength + 1];
634
0
  if (*expLength > sizeof buffer) {
635
0
    free(*modulus); *modulus = NULL;
636
0
    return SC_ERROR_OUT_OF_MEMORY;
637
0
  }
638
0
  r = msc_read_object(card, inputId, fileLocation, buffer, *expLength);
639
0
  if(r < 0) {
640
0
    free(*modulus); *modulus = NULL;
641
0
    LOG_FUNC_RETURN(card->ctx, r);
642
0
  }
643
0
  *exponent = malloc(*expLength);
644
0
  if(!*exponent) {
645
0
    free(*modulus);
646
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
647
0
  }
648
0
  memcpy(*exponent, buffer, *expLength);
649
0
  return 0;
650
0
}
651
652
653
654
/* For the moment, only support streaming data to the card
655
  in blocks, not through file IO */
656
int msc_compute_crypt_init(sc_card_t *card,
657
      int keyLocation,
658
      int cipherMode,
659
      int cipherDirection,
660
      const u8* initData,
661
      u8* outputData,
662
      size_t dataLength,
663
      size_t* outputDataLength)
664
0
{
665
0
  sc_apdu_t apdu;
666
0
  u8 buffer[MSC_MAX_APDU];
667
0
  u8 *ptr;
668
0
  int r;
669
670
0
  u8 outputBuffer[MSC_MAX_APDU + 2];
671
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x36, keyLocation, 0x01); /* Init */
672
0
  apdu.data = buffer;
673
0
  apdu.datalen = dataLength + 5;
674
0
  apdu.lc = dataLength + 5;
675
676
0
  memset(outputBuffer, 0, sizeof(outputBuffer));
677
0
  apdu.resp = outputBuffer;
678
0
  apdu.resplen = dataLength + 2;
679
0
  apdu.le = dataLength + 2;
680
0
  ptr = buffer;
681
0
  *ptr = cipherMode; ptr++;
682
0
  *ptr = cipherDirection; ptr++;
683
0
  *ptr = 0x01; ptr++; /* DATA LOCATION: APDU */
684
0
  *ptr = (dataLength >> 8) & 0xFF; ptr++;
685
0
  *ptr = dataLength & 0xFF; ptr++;
686
0
  memcpy(ptr, initData, dataLength);
687
688
0
  r = sc_transmit_apdu(card, &apdu);
689
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
690
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
691
0
    short receivedData = outputBuffer[0] << 8 | outputBuffer[1];
692
0
    *outputDataLength = receivedData;
693
694
0
    if (receivedData > MSC_MAX_APDU)
695
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
696
0
    memcpy(outputData, outputBuffer + 2, receivedData);
697
0
    return 0;
698
0
  }
699
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
700
0
  if (r) {
701
0
    if (card->ctx->debug >= 2) {
702
0
      sc_log(card->ctx,  "init: got strange SWs: 0x%02X 0x%02X\n",
703
0
           apdu.sw1, apdu.sw2);
704
0
    }
705
0
    LOG_FUNC_RETURN(card->ctx, r);
706
0
  }
707
0
  LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
708
0
}
709
710
int msc_compute_crypt_final(
711
      sc_card_t *card,
712
      int keyLocation,
713
      const u8* inputData,
714
      u8* outputData,
715
      size_t dataLength,
716
      size_t* outputDataLength)
717
0
{
718
0
  sc_apdu_t apdu;
719
0
  u8 buffer[MSC_MAX_APDU];
720
0
  u8 outputBuffer[MSC_MAX_APDU + 2];
721
0
  u8 *ptr;
722
0
  int r;
723
724
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x36, keyLocation, 0x03); /* Final */
725
726
0
  apdu.data = buffer;
727
0
  apdu.datalen = dataLength + 3;
728
0
  apdu.lc = dataLength + 3;
729
730
0
  memset(outputBuffer, 0, sizeof(outputBuffer));
731
0
  apdu.resp = outputBuffer;
732
0
  apdu.resplen = dataLength + 2;
733
0
  apdu.le = dataLength +2;
734
0
  ptr = buffer;
735
0
  *ptr = 0x01; ptr++; /* DATA LOCATION: APDU */
736
0
  *ptr = (dataLength >> 8) & 0xFF; ptr++;
737
0
  *ptr = dataLength & 0xFF; ptr++;
738
0
  memcpy(ptr, inputData, dataLength);
739
740
0
  r = sc_transmit_apdu(card, &apdu);
741
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
742
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
743
0
    short receivedData = outputBuffer[0] << 8 | outputBuffer[1];
744
0
    *outputDataLength = receivedData;
745
746
0
    if (receivedData > MSC_MAX_APDU)
747
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
748
0
    memcpy(outputData, outputBuffer + 2, receivedData);
749
0
    return 0;
750
0
  }
751
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
752
0
  if (r) {
753
0
    if (card->ctx->debug >= 2) {
754
0
      sc_log(card->ctx,  "final: got strange SWs: 0x%02X 0x%02X\n",
755
0
           apdu.sw1, apdu.sw2);
756
0
    }
757
0
    LOG_FUNC_RETURN(card->ctx, r);
758
0
  }
759
0
  LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
760
0
}
761
762
/* Stream data to the card through file IO */
763
static int msc_compute_crypt_final_object(
764
      sc_card_t *card,
765
      int keyLocation,
766
      const u8* inputData,
767
      u8* outputData,
768
      size_t dataLength,
769
      size_t* outputDataLength)
770
0
{
771
0
  sc_apdu_t apdu;
772
0
  u8 buffer[MSC_MAX_APDU];
773
0
  u8 *ptr;
774
0
  int r;
775
776
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x36, keyLocation, 0x03); /* Final */
777
778
0
  apdu.data = buffer;
779
0
  apdu.datalen = 1;
780
0
  apdu.lc = 1;
781
782
0
  ptr = buffer;
783
0
  *ptr = 0x02;
784
0
  ptr++; /* DATA LOCATION: OBJECT */
785
0
  *ptr = (dataLength >> 8) & 0xFF;
786
0
  ptr++;
787
0
  *ptr = dataLength & 0xFF;
788
0
  ptr++;
789
0
  memcpy(ptr, inputData, dataLength);
790
791
0
  r = msc_create_object(card, outputId, dataLength + 2, 0x02, 0x02, 0x02);
792
0
  if(r < 0) {
793
0
    if(r == SC_ERROR_FILE_ALREADY_EXISTS) {
794
0
      r = msc_delete_object(card, outputId, 0);
795
0
      if(r < 0) {
796
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
797
0
      }
798
0
      r = msc_create_object(card, outputId, dataLength + 2, 0x02, 0x02, 0x02);
799
0
      if(r < 0) {
800
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
801
0
      }
802
0
    }
803
0
  }
804
805
0
  r = msc_update_object(card, outputId, 0, buffer + 1, dataLength + 2);
806
0
  if(r < 0) return r;
807
808
0
  r = sc_transmit_apdu(card, &apdu);
809
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
810
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
811
0
    r = msc_read_object(card, inputId, 2, outputData, dataLength);
812
0
    if (r >= 0)
813
0
      *outputDataLength = r;
814
0
    msc_delete_object(card, outputId, 0);
815
0
    msc_delete_object(card, inputId, 0);
816
0
    return r;
817
0
  }
818
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
819
0
  if (r) {
820
0
    if (card->ctx->debug >= 2) {
821
0
      sc_log(card->ctx,  "final: got strange SWs: 0x%02X 0x%02X\n",
822
0
           apdu.sw1, apdu.sw2);
823
0
    }
824
0
  } else {
825
0
    r = SC_ERROR_CARD_CMD_FAILED;
826
0
  }
827
  /* this is last ditch cleanup */
828
0
  msc_delete_object(card, outputId, 0);
829
830
0
  LOG_FUNC_RETURN(card->ctx, r);
831
0
}
832
833
int msc_compute_crypt(sc_card_t *card,
834
      int keyLocation,
835
      int cipherMode,
836
      int cipherDirection,
837
      const u8* data,
838
      u8* outputData,
839
      size_t dataLength,
840
      size_t outputDataLength)
841
0
{
842
0
  size_t left = dataLength;
843
0
  const u8* inPtr = data;
844
0
  u8* outPtr = outputData;
845
0
  int toSend;
846
0
  int r;
847
848
0
  size_t received = 0;
849
850
0
  if (outputDataLength < dataLength)
851
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
852
853
  /* Don't send data during init... apparently current version does not support it */
854
0
  toSend = 0;
855
0
  r = msc_compute_crypt_init(card,
856
0
    keyLocation,
857
0
    cipherMode,
858
0
    cipherDirection,
859
0
    inPtr,
860
0
    outPtr,
861
0
    toSend,
862
0
    &received);
863
0
  if(r < 0) LOG_FUNC_RETURN(card->ctx, r);
864
0
  left -= toSend;
865
0
  inPtr += toSend;
866
0
  outPtr += received;
867
868
0
  toSend = MIN((int)left, MSC_MAX_APDU - 5);
869
  /* If the card supports extended APDUs, or the data fits in
870
           one normal APDU, use it for the data exchange */
871
0
  if (left < (MSC_MAX_SEND - 4) || (card->caps & SC_CARD_CAP_APDU_EXT) != 0) {
872
0
    r = msc_compute_crypt_final(card,
873
0
      keyLocation,
874
0
      inPtr,
875
0
      outPtr,
876
0
      toSend,
877
0
      &received);
878
0
    if(r < 0) LOG_FUNC_RETURN(card->ctx, r);
879
0
  } else { /* Data is too big: use objects */
880
0
    r = msc_compute_crypt_final_object(card,
881
0
      keyLocation,
882
0
      inPtr,
883
0
      outPtr,
884
0
      toSend,
885
0
      &received);
886
0
    if(r < 0) LOG_FUNC_RETURN(card->ctx, r);
887
0
  }
888
0
  outPtr += received;
889
890
0
  return (int)(outPtr - outputData); /* Amt received */
891
0
}
892
893
/* USED IN KEY ITEM WRITING */
894
#define CPYVAL(valName) \
895
0
  ushort2bebytes(p, data->valName ## Length); p+= 2; \
896
0
  memcpy(p, data->valName ## Value, data->valName ## Length); p+= data->valName ## Length
897
898
int msc_import_key(sc_card_t *card,
899
  int keyLocation,
900
  sc_cardctl_muscle_key_info_t *data)
901
0
{
902
0
  unsigned short readAcl = 0xFFFF,
903
0
    writeAcl = 0x0002,
904
0
    use = 0x0002,
905
0
    keySize = data->keySize;
906
0
  size_t bufferSize = 0;
907
0
  u8 *buffer, *p;
908
0
  u8 apduBuffer[6];
909
0
  sc_apdu_t apdu;
910
0
  int r;
911
912
0
  if (data->keyType != 0x02 && data->keyType != 0x03)
913
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
914
915
0
  if(data->keyType == 0x02) {
916
0
    if( (data->pLength == 0 || !data->pValue)
917
0
    || (data->modLength == 0 || !data->modValue))
918
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
919
0
  } else if(data->keyType == 0x03) {
920
0
    if( (data->pLength == 0 || !data->pValue)
921
0
    || (data->qLength == 0 || !data->qValue)
922
0
    || (data->pqLength == 0 || !data->pqValue)
923
0
    || (data->dp1Length == 0 || !data->dp1Value)
924
0
    || (data->dq1Length == 0 || !data->dq1Value))
925
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
926
0
  } else {
927
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
928
0
  }
929
930
0
  if(data->keyType == 0x02) {
931
0
    bufferSize = 4 + 4 + data->pLength + data->modLength;
932
0
  } else if(data->keyType == 0x03) {
933
0
    bufferSize = 4 + 10
934
0
      + data->pLength + data->qLength + data->pqLength
935
0
      + data->dp1Length + data->dq1Length;
936
0
  }
937
0
  buffer = malloc(bufferSize);
938
0
  if(!buffer) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
939
0
  p = buffer;
940
0
  *p = 0x00; p++; /* Encoding plain */
941
0
  *p = data->keyType; p++; /* RSA_PRIVATE */
942
0
  ushort2bebytes(p, keySize); p+=2; /* key size */
943
944
0
  if(data->keyType == 0x02) {
945
0
    CPYVAL(mod);
946
0
    CPYVAL(p);
947
0
  } else if(data->keyType == 0x03) {
948
0
    CPYVAL(p);
949
0
    CPYVAL(q);
950
0
    CPYVAL(pq);
951
0
    CPYVAL(dp1);
952
0
    CPYVAL(dq1);
953
0
  }
954
955
0
  r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
956
0
  if(r < 0) {
957
0
    if(r == SC_ERROR_FILE_ALREADY_EXISTS) {
958
0
      r = msc_delete_object(card, outputId, 0);
959
0
      if(r < 0) {
960
0
        free(buffer);
961
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
962
0
      }
963
0
      r = msc_create_object(card, outputId, bufferSize, 0x02, 0x02, 0x02);
964
0
      if(r < 0) {
965
0
        free(buffer);
966
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
967
0
      }
968
0
    }
969
0
  }
970
971
0
  r = msc_update_object(card, outputId, 0, buffer, bufferSize);
972
0
  free(buffer);
973
0
  if(r < 0) return r;
974
975
976
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x32, keyLocation, 0x00);
977
0
  apdu.lc = 6;
978
0
  apdu.data = apduBuffer;
979
0
  apdu.datalen = 6;
980
0
  p = apduBuffer;
981
0
  ushort2bebytes(p, readAcl); p+=2;
982
0
  ushort2bebytes(p, writeAcl); p+=2;
983
0
  ushort2bebytes(p, use);
984
0
  r = sc_transmit_apdu(card, &apdu);
985
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
986
0
  if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
987
0
    msc_delete_object(card, outputId, 0);
988
0
    return 0;
989
0
  }
990
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
991
0
  if (r) {
992
0
    if (card->ctx->debug >= 2) {
993
0
      sc_log(card->ctx,  "keyimport: got strange SWs: 0x%02X 0x%02X\n",
994
0
           apdu.sw1, apdu.sw2);
995
0
    }
996
    /* this is last ditch cleanup */
997
0
    msc_delete_object(card, outputId, 0);
998
0
    LOG_FUNC_RETURN(card->ctx, r);
999
0
  }
1000
  /* this is last ditch cleanup */
1001
0
  msc_delete_object(card, outputId, 0);
1002
1003
0
  LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
1004
0
}
1005
#undef CPYVAL