Coverage Report

Created: 2026-01-09 06:47

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
568
{
132
568
  struct sc_pin_cmd_data data;
133
134
568
  memset(&data, 0, sizeof(data));
135
568
  data.cmd = SC_PIN_CMD_VERIFY;
136
568
  data.pin_type = type;
137
568
  data.pin_reference = ref;
138
568
  data.pin1.data = pin;
139
568
  data.pin1.len = pinlen;
140
141
568
  return sc_pin_cmd(card, &data, tries_left);
142
568
}
143
144
int sc_logout(sc_card_t *card)
145
0
{
146
0
  if (card->ops->logout == NULL)
147
0
    return SC_ERROR_NOT_SUPPORTED;
148
0
  return card->ops->logout(card);
149
0
}
150
151
int sc_change_reference_data(sc_card_t *card, unsigned int type,
152
           int ref, const u8 *old, size_t oldlen,
153
           const u8 *newref, size_t newlen,
154
           int *tries_left)
155
250
{
156
250
  struct sc_pin_cmd_data data;
157
158
250
  memset(&data, 0, sizeof(data));
159
250
  data.cmd = SC_PIN_CMD_CHANGE;
160
250
  data.pin_type = type;
161
250
  data.pin_reference = ref;
162
250
  data.pin1.data = old;
163
250
  data.pin1.len = oldlen;
164
250
  data.pin2.data = newref;
165
250
  data.pin2.len = newlen;
166
167
250
  return sc_pin_cmd(card, &data, tries_left);
168
250
}
169
170
int sc_reset_retry_counter(sc_card_t *card, unsigned int type, int ref,
171
         const u8 *puk, size_t puklen, const u8 *newref,
172
         size_t newlen)
173
0
{
174
0
  struct sc_pin_cmd_data data;
175
176
0
  memset(&data, 0, sizeof(data));
177
0
  data.cmd = SC_PIN_CMD_UNBLOCK;
178
0
  data.pin_type = type;
179
0
  data.pin_reference = ref;
180
0
  data.pin1.data = puk;
181
0
  data.pin1.len = puklen;
182
0
  data.pin2.data = newref;
183
0
  data.pin2.len = newlen;
184
185
0
  return sc_pin_cmd(card, &data, NULL);
186
0
}
187
188
/*
189
 * This is the new style pin command, which takes care of all PIN
190
 * operations.
191
 * If a PIN was given by the application, the card driver should
192
 * send this PIN to the card. If no PIN was given, the driver should
193
 * ask the reader to obtain the pin(s) via the pin pad
194
 */
195
int sc_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
196
    int *tries_left)
197
3.62k
{
198
3.62k
  int r, debug;
199
200
3.62k
  if (card == NULL) {
201
0
    return SC_ERROR_INVALID_ARGUMENTS;
202
0
  }
203
3.62k
  LOG_FUNC_CALLED(card->ctx);
204
205
3.62k
  debug = card->ctx->debug;
206
3.62k
  if (data->cmd != SC_PIN_CMD_GET_INFO
207
883
      && card->ctx->debug < SC_LOG_DEBUG_PIN) {
208
883
    card->ctx->debug = 0;
209
883
  }
210
211
3.62k
  if (card->ops->pin_cmd) {
212
3.62k
    r = card->ops->pin_cmd(card, data, tries_left);
213
3.62k
  } else if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) {
214
    /* Card driver doesn't support new style pin_cmd, fall
215
     * back to old interface */
216
217
0
    r = SC_ERROR_NOT_SUPPORTED;
218
0
    switch (data->cmd) {
219
0
    case SC_PIN_CMD_VERIFY:
220
0
      if (card->ops->verify != NULL)
221
0
        r = card->ops->verify(card,
222
0
          data->pin_type,
223
0
          data->pin_reference,
224
0
          data->pin1.data,
225
0
          (size_t) data->pin1.len,
226
0
          tries_left);
227
0
      break;
228
0
    case SC_PIN_CMD_CHANGE:
229
0
      if (card->ops->change_reference_data != NULL)
230
0
        r = card->ops->change_reference_data(card,
231
0
          data->pin_type,
232
0
          data->pin_reference,
233
0
          data->pin1.data,
234
0
          (size_t) data->pin1.len,
235
0
          data->pin2.data,
236
0
          (size_t) data->pin2.len,
237
0
          tries_left);
238
0
      break;
239
0
    case SC_PIN_CMD_UNBLOCK:
240
0
      if (card->ops->reset_retry_counter != NULL)
241
0
        r = card->ops->reset_retry_counter(card,
242
0
          data->pin_type,
243
0
          data->pin_reference,
244
0
          data->pin1.data,
245
0
          (size_t) data->pin1.len,
246
0
          data->pin2.data,
247
0
          (size_t) data->pin2.len);
248
0
      break;
249
0
    }
250
0
    if (r == SC_ERROR_NOT_SUPPORTED)
251
0
      sc_log(card->ctx,  "unsupported PIN operation (%d)",
252
0
          data->cmd);
253
0
  } else {
254
0
    sc_log(card->ctx,  "Use of pin pad not supported by card driver");
255
0
    r = SC_ERROR_NOT_SUPPORTED;
256
0
  }
257
3.62k
  card->ctx->debug = debug;
258
259
3.62k
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
260
3.62k
}
261
262
/*
263
 * This function will copy a PIN, convert and pad it as required
264
 *
265
 * Note about the SC_PIN_ENCODING_GLP encoding:
266
 * PIN buffers are always 16 nibbles (8 bytes) and look like this:
267
 *   0x2 + len + pin_in_BCD + paddingnibbles
268
 * in which the paddingnibble = 0xF
269
 * E.g. if PIN = 12345, then sbuf = {0x25, 0x12, 0x34, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF}
270
 * E.g. if PIN = 123456789012, then sbuf = {0x2C, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0xFF}
271
 * Reference: Global Platform - Card Specification - version 2.0.1' - April 7, 2000
272
 */
273
int sc_build_pin(u8 *buf, size_t buflen, struct sc_pin_cmd_pin *pin, int pad)
274
282
{
275
282
  size_t i = 0, j, pin_len = pin->len;
276
277
282
  if (pin->max_length && pin_len > pin->max_length)
278
0
    return SC_ERROR_INVALID_ARGUMENTS;
279
280
282
  if (pin->encoding == SC_PIN_ENCODING_GLP) {
281
0
    while (pin_len > 0 && pin->data[pin_len - 1] == 0xFF)
282
0
      pin_len--;
283
0
    if (pin_len > 12)
284
0
      return SC_ERROR_INVALID_ARGUMENTS;
285
0
    for (i = 0; i < pin_len; i++) {
286
0
      if (pin->data[i] < '0' || pin->data[i] > '9')
287
0
        return SC_ERROR_INVALID_ARGUMENTS;
288
0
    }
289
0
    buf[0] = 0x20 | (u8) pin_len;
290
0
    buf++;
291
0
    buflen--;
292
0
  }
293
294
  /* PIN given by application, encode if required */
295
282
  if (pin->encoding == SC_PIN_ENCODING_ASCII) {
296
282
    if (pin_len > buflen)
297
0
      return SC_ERROR_BUFFER_TOO_SMALL;
298
282
    memcpy(buf, pin->data, pin_len);
299
282
    i = pin_len;
300
282
  } else if (pin->encoding == SC_PIN_ENCODING_BCD || pin->encoding == SC_PIN_ENCODING_GLP) {
301
0
    if (pin_len > 2 * buflen)
302
0
      return SC_ERROR_BUFFER_TOO_SMALL;
303
0
    for (i = j = 0; j < pin_len; j++) {
304
0
      if (!isdigit(pin->data[j])) {
305
0
        return SC_ERROR_INVALID_DATA;
306
0
      }
307
0
      buf[i] <<= 4;
308
0
      buf[i] |= pin->data[j] & 0xf;
309
0
      if (j & 1)
310
0
        i++;
311
0
    }
312
0
    if (j & 1) {
313
0
      buf[i] <<= 4;
314
0
      buf[i] |= pin->pad_char & 0xf;
315
0
      i++;
316
0
    }
317
0
  }
318
319
  /* Pad to maximum PIN length if requested */
320
282
  if (pad || pin->encoding == SC_PIN_ENCODING_GLP) {
321
32
    size_t pad_length = pin->pad_length;
322
32
    u8     pad_char   = pin->encoding == SC_PIN_ENCODING_GLP ? 0xFF : pin->pad_char;
323
324
32
    if (pin->encoding == SC_PIN_ENCODING_BCD)
325
0
      pad_length >>= 1;
326
32
    if (pin->encoding == SC_PIN_ENCODING_GLP)
327
0
      pad_length = 8;
328
329
32
    if (pad_length > buflen)
330
0
      return SC_ERROR_BUFFER_TOO_SMALL;
331
332
32
    if (pad_length && i < pad_length) {
333
20
      memset(buf + i, pad_char, pad_length - i);
334
20
      i = pad_length;
335
20
    }
336
32
  }
337
338
282
  return (int)i;
339
282
}
340
341
int
342
sc_encrypt_sym(struct sc_card *card, const u8 *plaintext, size_t plaintext_len,
343
    u8 *out, size_t *outlen)
344
0
{
345
0
  int r;
346
347
0
  if (card == NULL)
348
0
    return SC_ERROR_INVALID_ARGUMENTS;
349
350
0
  LOG_FUNC_CALLED(card->ctx);
351
0
  if (card->ops->encrypt_sym == NULL)
352
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
353
0
  r = card->ops->encrypt_sym(card, plaintext, plaintext_len, out, outlen);
354
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
355
0
}
356
357
int
358
sc_decrypt_sym(struct sc_card *card, const u8 *data, size_t data_len,
359
    u8 *out, size_t *outlen)
360
0
{
361
0
  int r;
362
363
0
  if (card == NULL)
364
0
    return SC_ERROR_INVALID_ARGUMENTS;
365
366
0
  LOG_FUNC_CALLED(card->ctx);
367
0
  if (card->ops->decrypt_sym == NULL)
368
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
369
0
  r = card->ops->decrypt_sym(card, data, data_len, out, outlen);
370
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
371
0
}