Coverage Report

Created: 2026-06-06 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/sec.c
Line
Count
Source
1
/*
2
 * sec.c: Cryptography and security (ISO7816-8) functions
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
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 <stdio.h>
26
#include <string.h>
27
#include <assert.h>
28
#include <ctype.h>
29
#ifdef HAVE_UNISTD_H
30
#include <unistd.h>
31
#endif
32
33
#include "internal.h"
34
35
int sc_decipher(sc_card_t *card,
36
    const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
37
0
{
38
0
  int r;
39
40
0
  if (card == NULL) {
41
0
    return SC_ERROR_INVALID_ARGUMENTS;
42
0
  }
43
0
  if (crgram == NULL || out == NULL) {
44
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
45
0
  }
46
0
  LOG_FUNC_CALLED(card->ctx);
47
0
  if (card->ops->decipher == NULL)
48
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
49
0
  r = card->ops->decipher(card, crgram, crgram_len, out, outlen);
50
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
51
0
}
52
53
int sc_compute_signature(sc_card_t *card,
54
       const u8 * data, size_t datalen,
55
       u8 * out, size_t outlen)
56
0
{
57
0
  int r;
58
59
0
  if (card == NULL) {
60
0
    return SC_ERROR_INVALID_ARGUMENTS;
61
0
  }
62
0
  LOG_FUNC_CALLED(card->ctx);
63
0
  if (card->ops->compute_signature == NULL)
64
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
65
0
  r = card->ops->compute_signature(card, data, datalen, out, outlen);
66
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
67
0
}
68
69
int sc_unwrap(sc_card_t *card,
70
    const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
71
0
{
72
0
  int r;
73
74
0
  if (card == NULL || crgram == NULL) {
75
0
    return SC_ERROR_INVALID_ARGUMENTS;
76
0
  }
77
0
  LOG_FUNC_CALLED(card->ctx);
78
0
  if (card->ops->unwrap == NULL)
79
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
80
0
  r = card->ops->unwrap(card, crgram, crgram_len);
81
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
82
0
}
83
84
int sc_wrap(sc_card_t *card,
85
    const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
86
0
{
87
0
  int r;
88
89
0
  if (card == NULL) {
90
0
    return SC_ERROR_INVALID_ARGUMENTS;
91
0
  }
92
0
  LOG_FUNC_CALLED(card->ctx);
93
0
  if (card->ops->wrap == NULL)
94
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
95
0
  r = card->ops->wrap(card, out, outlen);
96
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
97
0
}
98
99
int sc_set_security_env(sc_card_t *card,
100
      const sc_security_env_t *env,
101
      int se_num)
102
0
{
103
0
  int r;
104
105
0
  if (card == NULL) {
106
0
    return SC_ERROR_INVALID_ARGUMENTS;
107
0
  }
108
0
  LOG_FUNC_CALLED(card->ctx);
109
0
  if (card->ops->set_security_env == NULL)
110
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
111
0
  r = card->ops->set_security_env(card, env, se_num);
112
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
113
0
}
114
115
int sc_restore_security_env(sc_card_t *card, int se_num)
116
0
{
117
0
  int r;
118
119
0
  if (card == NULL) {
120
0
    return SC_ERROR_INVALID_ARGUMENTS;
121
0
  }
122
0
  LOG_FUNC_CALLED(card->ctx);
123
0
  if (card->ops->restore_security_env == NULL)
124
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
125
0
  r = card->ops->restore_security_env(card, se_num);
126
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
127
0
}
128
129
int sc_verify(sc_card_t *card, unsigned int type, int ref,
130
        const u8 *pin, size_t pinlen, int *tries_left)
131
722
{
132
722
  struct sc_pin_cmd_data data;
133
134
722
  memset(&data, 0, sizeof(data));
135
722
  data.cmd = SC_PIN_CMD_VERIFY;
136
722
  data.pin_type = type;
137
722
  data.pin_reference = ref;
138
722
  data.pin1.data = pin;
139
722
  data.pin1.len = pinlen;
140
141
722
  int r = sc_pin_cmd(card, &data);
142
722
  if (tries_left)
143
722
    *tries_left = data.pin1.tries_left;
144
145
722
  return r;
146
722
}
147
148
int sc_logout(sc_card_t *card)
149
0
{
150
0
  if (card->ops->logout == NULL)
151
0
    return SC_ERROR_NOT_SUPPORTED;
152
0
  return card->ops->logout(card);
153
0
}
154
155
int sc_change_reference_data(sc_card_t *card, unsigned int type,
156
           int ref, const u8 *old, size_t oldlen,
157
           const u8 *newref, size_t newlen,
158
           int *tries_left)
159
0
{
160
0
  struct sc_pin_cmd_data data;
161
162
0
  memset(&data, 0, sizeof(data));
163
0
  data.cmd = SC_PIN_CMD_CHANGE;
164
0
  data.pin_type = type;
165
0
  data.pin_reference = ref;
166
0
  data.pin1.data = old;
167
0
  data.pin1.len = oldlen;
168
0
  data.pin2.data = newref;
169
0
  data.pin2.len = newlen;
170
171
0
  int r = sc_pin_cmd(card, &data);
172
0
  if (tries_left)
173
0
    *tries_left = data.pin1.tries_left;
174
175
0
  return r;
176
0
}
177
178
int sc_reset_retry_counter(sc_card_t *card, unsigned int type, int ref,
179
         const u8 *puk, size_t puklen, const u8 *newref,
180
         size_t newlen)
181
0
{
182
0
  struct sc_pin_cmd_data data;
183
184
0
  memset(&data, 0, sizeof(data));
185
0
  data.cmd = SC_PIN_CMD_UNBLOCK;
186
0
  data.pin_type = type;
187
0
  data.pin_reference = ref;
188
0
  data.pin1.data = puk;
189
0
  data.pin1.len = puklen;
190
0
  data.pin2.data = newref;
191
0
  data.pin2.len = newlen;
192
193
0
  return sc_pin_cmd(card, &data);
194
0
}
195
196
/*
197
 * This is the new style pin command, which takes care of all PIN
198
 * operations.
199
 * If a PIN was given by the application, the card driver should
200
 * send this PIN to the card. If no PIN was given, the driver should
201
 * ask the reader to obtain the pin(s) via the pin pad
202
 */
203
int sc_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data)
204
1.34k
{
205
1.34k
  int r, debug;
206
207
1.34k
  if (card == NULL) {
208
0
    return SC_ERROR_INVALID_ARGUMENTS;
209
0
  }
210
1.34k
  LOG_FUNC_CALLED(card->ctx);
211
212
1.34k
  debug = card->ctx->debug;
213
1.34k
  if (data->cmd != SC_PIN_CMD_GET_INFO
214
722
      && card->ctx->debug < SC_LOG_DEBUG_PIN) {
215
722
    card->ctx->debug = 0;
216
722
  }
217
218
1.34k
  if (card->ops->pin_cmd) {
219
1.34k
    r = card->ops->pin_cmd(card, data);
220
1.34k
  } else if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) {
221
    /* Card driver doesn't support new style pin_cmd, fall
222
     * back to old interface */
223
224
0
    r = SC_ERROR_NOT_SUPPORTED;
225
0
    switch (data->cmd) {
226
0
    case SC_PIN_CMD_VERIFY:
227
0
      if (card->ops->verify != NULL)
228
0
        r = card->ops->verify(card,
229
0
          data->pin_type,
230
0
          data->pin_reference,
231
0
          data->pin1.data,
232
0
          (size_t) data->pin1.len,
233
0
          &data->pin1.tries_left);
234
0
      break;
235
0
    case SC_PIN_CMD_CHANGE:
236
0
      if (card->ops->change_reference_data != NULL)
237
0
        r = card->ops->change_reference_data(card,
238
0
          data->pin_type,
239
0
          data->pin_reference,
240
0
          data->pin1.data,
241
0
          (size_t) data->pin1.len,
242
0
          data->pin2.data,
243
0
          (size_t) data->pin2.len,
244
0
          &data->pin1.tries_left);
245
0
      break;
246
0
    case SC_PIN_CMD_UNBLOCK:
247
0
      if (card->ops->reset_retry_counter != NULL)
248
0
        r = card->ops->reset_retry_counter(card,
249
0
          data->pin_type,
250
0
          data->pin_reference,
251
0
          data->pin1.data,
252
0
          (size_t) data->pin1.len,
253
0
          data->pin2.data,
254
0
          (size_t) data->pin2.len);
255
0
      break;
256
0
    }
257
0
    if (r == SC_ERROR_NOT_SUPPORTED)
258
0
      sc_log(card->ctx,  "unsupported PIN operation (%d)",
259
0
          data->cmd);
260
0
  } else {
261
0
    sc_log(card->ctx,  "Use of pin pad not supported by card driver");
262
0
    r = SC_ERROR_NOT_SUPPORTED;
263
0
  }
264
1.34k
  card->ctx->debug = debug;
265
266
1.34k
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
267
1.34k
}
268
269
/*
270
 * This function will copy a PIN, convert and pad it as required
271
 *
272
 * Note about the SC_PIN_ENCODING_GLP encoding:
273
 * PIN buffers are always 16 nibbles (8 bytes) and look like this:
274
 *   0x2 + len + pin_in_BCD + paddingnibbles
275
 * in which the paddingnibble = 0xF
276
 * E.g. if PIN = 12345, then sbuf = {0x25, 0x12, 0x34, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF}
277
 * E.g. if PIN = 123456789012, then sbuf = {0x2C, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0xFF}
278
 * Reference: Global Platform - Card Specification - version 2.0.1' - April 7, 2000
279
 */
280
int sc_build_pin(u8 *buf, size_t buflen, struct sc_pin_cmd_pin *pin, int pad)
281
0
{
282
0
  size_t i = 0, j, pin_len = pin->len;
283
284
0
  if (pin->max_length && pin_len > pin->max_length)
285
0
    return SC_ERROR_INVALID_ARGUMENTS;
286
287
0
  if (pin->encoding == SC_PIN_ENCODING_GLP) {
288
0
    while (pin_len > 0 && pin->data[pin_len - 1] == 0xFF)
289
0
      pin_len--;
290
0
    if (pin_len > 12)
291
0
      return SC_ERROR_INVALID_ARGUMENTS;
292
0
    for (i = 0; i < pin_len; i++) {
293
0
      if (pin->data[i] < '0' || pin->data[i] > '9')
294
0
        return SC_ERROR_INVALID_ARGUMENTS;
295
0
    }
296
0
    buf[0] = 0x20 | (u8) pin_len;
297
0
    buf++;
298
0
    buflen--;
299
0
  }
300
301
  /* PIN given by application, encode if required */
302
0
  if (pin->encoding == SC_PIN_ENCODING_ASCII) {
303
0
    if (pin_len > buflen)
304
0
      return SC_ERROR_BUFFER_TOO_SMALL;
305
0
    memcpy(buf, pin->data, pin_len);
306
0
    i = pin_len;
307
0
  } else if (pin->encoding == SC_PIN_ENCODING_BCD || pin->encoding == SC_PIN_ENCODING_GLP) {
308
0
    if (pin_len > 2 * buflen)
309
0
      return SC_ERROR_BUFFER_TOO_SMALL;
310
0
    for (i = j = 0; j < pin_len; j++) {
311
0
      if (!isdigit(pin->data[j])) {
312
0
        return SC_ERROR_INVALID_DATA;
313
0
      }
314
0
      buf[i] <<= 4;
315
0
      buf[i] |= pin->data[j] & 0xf;
316
0
      if (j & 1)
317
0
        i++;
318
0
    }
319
0
    if (j & 1) {
320
0
      buf[i] <<= 4;
321
0
      buf[i] |= pin->pad_char & 0xf;
322
0
      i++;
323
0
    }
324
0
  }
325
326
  /* Pad to maximum PIN length if requested */
327
0
  if (pad || pin->encoding == SC_PIN_ENCODING_GLP) {
328
0
    size_t pad_length = pin->pad_length;
329
0
    u8     pad_char   = pin->encoding == SC_PIN_ENCODING_GLP ? 0xFF : pin->pad_char;
330
331
0
    if (pin->encoding == SC_PIN_ENCODING_BCD)
332
0
      pad_length >>= 1;
333
0
    if (pin->encoding == SC_PIN_ENCODING_GLP)
334
0
      pad_length = 8;
335
336
0
    if (pad_length > buflen)
337
0
      return SC_ERROR_BUFFER_TOO_SMALL;
338
339
0
    if (pad_length && i < pad_length) {
340
0
      memset(buf + i, pad_char, pad_length - i);
341
0
      i = pad_length;
342
0
    }
343
0
  }
344
345
0
  return (int)i;
346
0
}
347
348
int
349
sc_encrypt_sym(struct sc_card *card, const u8 *plaintext, size_t plaintext_len,
350
    u8 *out, size_t *outlen)
351
0
{
352
0
  int r;
353
354
0
  if (card == NULL)
355
0
    return SC_ERROR_INVALID_ARGUMENTS;
356
357
0
  LOG_FUNC_CALLED(card->ctx);
358
0
  if (card->ops->encrypt_sym == NULL)
359
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
360
0
  r = card->ops->encrypt_sym(card, plaintext, plaintext_len, out, outlen);
361
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
362
0
}
363
364
int
365
sc_decrypt_sym(struct sc_card *card, const u8 *data, size_t data_len,
366
    u8 *out, size_t *outlen)
367
0
{
368
0
  int r;
369
370
0
  if (card == NULL)
371
0
    return SC_ERROR_INVALID_ARGUMENTS;
372
373
0
  LOG_FUNC_CALLED(card->ctx);
374
0
  if (card->ops->decrypt_sym == NULL)
375
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
376
0
  r = card->ops->decrypt_sym(card, data, data_len, out, outlen);
377
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
378
0
}