Coverage Report

Created: 2025-11-24 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/pkcs15init/pkcs15-rutoken.c
Line
Count
Source
1
/*
2
 * Rutoken S specific operation for PKCS15 initialization
3
 *
4
 * Copyright (C) 2007  Pavel Mironchik <rutoken@rutoken.ru>
5
 * Copyright (C) 2007  Eugene Hermann <rutoken@rutoken.ru>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "config.h"
23
24
#include <sys/types.h>
25
#include <stddef.h>
26
#include <stdlib.h>
27
#include <string.h>
28
29
#include "libopensc/opensc.h"
30
#include "libopensc/cardctl.h"
31
#include "libopensc/log.h"
32
#include "libopensc/pkcs15.h"
33
#include "pkcs15-init.h"
34
#include "profile.h"
35
36
static const sc_SecAttrV2_t wn_sec_attr = {
37
  0x43, 1, 1, 0, 0, 0, 0, -1,
38
  2, 0, 0, 0,
39
  2
40
};
41
static const sc_SecAttrV2_t p2_sec_attr = {
42
  0x43, 1, 1, 0, 0, 0, 0, -1,
43
  1, 0, 0, 0,
44
  2
45
};
46
static const sc_SecAttrV2_t p1_sec_attr = {
47
  0x43, -1, 1, 0, 0, 0, 0, -1,
48
  0, 0, 0, 0,
49
  1
50
};
51
52
static const struct
53
{
54
  u8                     id, options, flags, try, pass[8];
55
  sc_SecAttrV2_t const*  p_sattr;
56
} do_pins[] =
57
    {
58
      { SC_RUTOKEN_DEF_ID_GCHV_USER, SC_RUTOKEN_OPTIONS_GACCESS_USER,
59
        SC_RUTOKEN_FLAGS_COMPACT_DO, 0xFF,
60
        { '1', '2', '3', '4', '5', '6', '7', '8' }, &p2_sec_attr
61
      },
62
      { SC_RUTOKEN_DEF_ID_GCHV_ADMIN, SC_RUTOKEN_OPTIONS_GACCESS_ADMIN,
63
        SC_RUTOKEN_FLAGS_COMPACT_DO, 0xFF,
64
        { '8', '7', '6', '5', '4', '3', '2', '1' }, &p1_sec_attr
65
      }
66
    };
67
68
/*
69
 * Create a DF
70
 */
71
static int
72
rutoken_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
73
    sc_file_t *df)
74
17
{
75
17
  if (!profile || !p15card || !p15card->card || !p15card->card->ctx || !df)
76
0
    return SC_ERROR_INVALID_ARGUMENTS;
77
17
  SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE);
78
17
  return sc_pkcs15init_create_file(profile, p15card, df);
79
17
}
80
81
/*
82
 * Select a PIN reference
83
 */
84
static int
85
rutoken_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
86
      sc_pkcs15_auth_info_t *auth_info)
87
37
{
88
37
  int pin_ref;
89
37
  unsigned int so_pin_flag;
90
91
37
  if (!profile || !p15card || !p15card->card || !p15card->card->ctx || !auth_info)
92
0
    return SC_ERROR_INVALID_ARGUMENTS;
93
94
37
  SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE);
95
96
37
  if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
97
0
    return SC_ERROR_OBJECT_NOT_VALID;
98
99
37
  pin_ref = auth_info->attrs.pin.reference;
100
37
  so_pin_flag = auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN;
101
102
37
  sc_log(p15card->card->ctx,  "PIN reference %i%s\n",
103
37
      pin_ref, so_pin_flag ? " SO PIN flag" : "");
104
105
37
  if ((pin_ref == SC_RUTOKEN_DEF_ID_GCHV_ADMIN && so_pin_flag)
106
36
      || (pin_ref == SC_RUTOKEN_DEF_ID_GCHV_USER && !so_pin_flag)
107
37
  )
108
18
    return SC_SUCCESS;
109
19
  else
110
19
    return SC_ERROR_NOT_SUPPORTED;
111
37
}
112
113
/*
114
 * Create a PIN object within the given DF
115
 */
116
static int
117
rutoken_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
118
      sc_file_t *df, sc_pkcs15_object_t *pin_obj,
119
      const unsigned char *pin, size_t pin_len,
120
      const unsigned char *puk, size_t puk_len)
121
0
{
122
0
  sc_context_t *ctx;
123
0
  sc_pkcs15_auth_info_t *auth_info;
124
0
  size_t i;
125
126
0
  (void)puk; /* no warning */
127
0
  if (!profile || !p15card || !p15card->card || !p15card->card->ctx
128
0
      || !df || !pin_obj || !pin_obj->data || !pin || !pin_len)
129
0
    return SC_ERROR_INVALID_ARGUMENTS;
130
131
0
  ctx = p15card->card->ctx;
132
0
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
133
134
0
  if (puk_len != 0)
135
0
  {
136
0
    sc_log(ctx, 
137
0
        "Do not enter User unblocking PIN (PUK): %s\n",
138
0
        sc_strerror(SC_ERROR_NOT_SUPPORTED));
139
0
    return SC_ERROR_NOT_SUPPORTED;
140
0
  }
141
142
0
  auth_info = (sc_pkcs15_auth_info_t *)pin_obj->data;
143
0
  if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
144
0
                return SC_ERROR_OBJECT_NOT_VALID;
145
146
0
  for (i = 0; i < sizeof(do_pins)/sizeof(do_pins[0]); ++i)
147
0
    if (auth_info->attrs.pin.reference == do_pins[i].id)
148
0
    {
149
0
      if (pin_len == sizeof(do_pins[i].pass)
150
0
          &&  memcmp(do_pins[i].pass, pin, pin_len) == 0
151
0
      )
152
0
        return SC_SUCCESS;
153
0
      else
154
0
      {
155
0
        sc_log(ctx,  "Incorrect PIN\n");
156
0
        break;
157
0
      }
158
0
    }
159
0
  sc_log(ctx, 
160
0
      "PIN reference %i not found in standard (Rutoken) PINs\n",
161
0
      auth_info->attrs.pin.reference);
162
0
  return SC_ERROR_NOT_SUPPORTED;
163
0
}
164
165
/*
166
 * Initialization routine
167
 */
168
169
static int create_pins(sc_card_t *card)
170
0
{
171
0
  sc_DO_V2_t param_do;
172
0
  size_t i;
173
0
  int r = SC_SUCCESS;
174
175
0
  for (i = 0; i < sizeof(do_pins)/sizeof(do_pins[0]); ++i)
176
0
  {
177
0
    memset(&param_do, 0, sizeof(param_do));
178
0
    param_do.HDR.OTID.byObjectType  = SC_RUTOKEN_TYPE_CHV;
179
0
    param_do.HDR.OTID.byObjectID    = do_pins[i].id;
180
0
    param_do.HDR.OP.byObjectOptions = do_pins[i].options;
181
0
    param_do.HDR.OP.byObjectFlags   = do_pins[i].flags;
182
0
    param_do.HDR.OP.byObjectTry     = do_pins[i].try;
183
0
    param_do.HDR.wDOBodyLen = sizeof(do_pins[i].pass);
184
    /* assert(do_pins[i].p_sattr != NULL); */
185
    /* assert(sizeof(*param_do.HDR.SA_V2)) */
186
    /* assert(sizeof(param_do.HDR.SA_V2) == sizeof(*do_pins[i].p_sattr)); */
187
0
    memcpy(param_do.HDR.SA_V2, *do_pins[i].p_sattr,
188
0
        sizeof(*do_pins[i].p_sattr));
189
    /* assert(do_pins[i].pass); */
190
    /* assert(sizeof(*param_do.abyDOBody)) */
191
    /* assert(sizeof(param_do.abyDOBody) >= sizeof(do_pins[i].pass)); */
192
0
    memcpy(param_do.abyDOBody, do_pins[i].pass, sizeof(do_pins[i].pass));
193
194
0
    r = sc_card_ctl(card, SC_CARDCTL_RUTOKEN_CREATE_DO, &param_do);
195
0
    if (r != SC_SUCCESS) break;
196
0
  }
197
0
  return r;
198
0
}
199
200
static int create_typical_fs(sc_card_t *card)
201
0
{
202
0
  sc_file_t *df;
203
0
  int r;
204
205
0
  df = sc_file_new();
206
0
  if (!df)
207
0
    return SC_ERROR_OUT_OF_MEMORY;
208
0
  df->type = SC_FILE_TYPE_DF;
209
0
  do
210
0
  {
211
0
    r = sc_file_set_sec_attr(df, wn_sec_attr, sizeof(wn_sec_attr));
212
0
    if (r != SC_SUCCESS) break;
213
214
    /* Create MF  3F00 */
215
0
    df->id = 0x3F00;
216
0
    sc_format_path("3F00", &df->path);
217
0
    r = sc_create_file(card, df);
218
0
    if (r != SC_SUCCESS) break;
219
220
    /* Create     3F00/0000 */
221
0
    df->id = 0x0000;
222
0
    sc_append_file_id(&df->path, df->id);
223
0
    r = sc_create_file(card, df);
224
0
    if (r != SC_SUCCESS) break;
225
226
    /* Create     3F00/0000/0000 */
227
0
    df->id = 0x0000;
228
0
    sc_append_file_id(&df->path, df->id);
229
0
    r = sc_create_file(card, df);
230
0
    if (r != SC_SUCCESS) break;
231
232
    /* Create USER PIN and SO PIN*/
233
0
    r = create_pins(card);
234
0
    if (r != SC_SUCCESS) break;
235
236
    /* VERIFY USER PIN */
237
0
    r = sc_verify(card, SC_AC_CHV, do_pins[0].id,
238
0
        do_pins[0].pass, sizeof(do_pins[0].pass), NULL);
239
0
    if (r != SC_SUCCESS) break;
240
241
    /* Create     3F00/0000/0000/0001 */
242
0
    df->id = 0x0001;
243
0
    sc_append_file_id(&df->path, df->id);
244
0
    r = sc_create_file(card, df);
245
0
    if (r != SC_SUCCESS) break;
246
247
0
    sc_format_path("3F0000000000", &df->path);
248
0
    r = sc_select_file(card, &df->path, NULL);
249
0
    if (r != SC_SUCCESS) break;
250
251
    /* Create     3F00/0000/0000/0002 */
252
0
    df->id = 0x0002;
253
0
    sc_append_file_id(&df->path, df->id);
254
0
    r = sc_create_file(card, df);
255
0
    if (r != SC_SUCCESS) break;
256
257
0
    sc_format_path("3F000000", &df->path);
258
0
    r = sc_select_file(card, &df->path, NULL);
259
0
    if (r != SC_SUCCESS) break;
260
261
    /* Create     3F00/0000/0001 */
262
0
    df->id = 0x0001;
263
0
    sc_append_file_id(&df->path, df->id);
264
0
    r = sc_create_file(card, df);
265
0
    if (r != SC_SUCCESS) break;
266
267
    /* RESET ACCESS RIGHTS */
268
0
    r = sc_logout(card);
269
0
  } while(0);
270
0
  sc_file_free(df);
271
0
  return r;
272
0
}
273
274
/*
275
 * Erase everything that's on the card
276
 */
277
static int
278
rutoken_erase(struct sc_profile *profile, sc_pkcs15_card_t *p15card)
279
0
{
280
0
  sc_card_t *card;
281
0
  int ret, ret_end;
282
283
0
  if (!profile || !p15card || !p15card->card || !p15card->card->ctx)
284
0
    return SC_ERROR_INVALID_ARGUMENTS;
285
286
0
  card = p15card->card;
287
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
288
289
  /* ret = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL); */
290
0
  ret = sc_card_ctl(card, SC_CARDCTL_RUTOKEN_FORMAT_INIT, NULL);
291
0
  if (ret == SC_SUCCESS)
292
0
  {
293
0
    ret = create_typical_fs(card);
294
0
    if (ret != SC_SUCCESS)
295
0
      sc_log(card->ctx, 
296
0
          "Failed to create typical fs: %s\n",
297
0
          sc_strerror(ret));
298
0
    ret_end = sc_card_ctl(card, SC_CARDCTL_RUTOKEN_FORMAT_END, NULL);
299
0
    if (ret_end != SC_SUCCESS)
300
0
      ret = ret_end;
301
0
  }
302
0
  if (ret != SC_SUCCESS)
303
0
    sc_log(card->ctx, 
304
0
        "Failed to erase: %s\n", sc_strerror(ret));
305
0
  else
306
0
    sc_free_apps(card);
307
0
  return ret;
308
0
}
309
310
static struct sc_pkcs15init_operations sc_pkcs15init_rutoken_operations = {
311
  rutoken_erase,                  /* erase_card */
312
  NULL,                           /* init_card */
313
  rutoken_create_dir,             /* create_dir */
314
  NULL,                           /* create_domain */
315
  rutoken_select_pin_reference,   /* select_pin_reference */
316
  rutoken_create_pin,             /* create_pin */
317
  NULL,                           /* select_key_reference */
318
  NULL,                           /* create_key */
319
  NULL,                           /* store_key */
320
  NULL,                           /* generate_key */
321
  NULL,                           /* encode_private_key */
322
  NULL,                           /* encode_public_key */
323
  NULL,                           /* finalize_card */
324
  NULL,                           /* delete_object */
325
  NULL, NULL, NULL, NULL, NULL,   /* pkcs15init emulation */
326
  NULL                            /* sanity_check */
327
};
328
329
struct sc_pkcs15init_operations* sc_pkcs15init_get_rutoken_ops(void)
330
101
{
331
101
  return &sc_pkcs15init_rutoken_operations;
332
101
}
333