Coverage Report

Created: 2025-11-11 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-nqApplet.c
Line
Count
Source
1
/*
2
 * PKCS15 emulation for JCOP4 Cards with NQ-Applet
3
 *
4
 * Copyright (C) 2021 jozsefd <jozsef.dojcsak@gmail.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
#include <stdlib.h>
22
#include <string.h>
23
24
#include "internal.h"
25
#include "opensc.h"
26
#include "cards.h"
27
#include "common/compat_strlcpy.h"
28
#include "log.h"
29
#include "pkcs15.h"
30
31
static const char name_Card[] = "NQ-Applet";
32
static const char name_Vendor[] = "NXP";
33
34
static int get_nqapplet_certificate(sc_card_t *card, u8 data_id, struct sc_pkcs15_der *cert_info)
35
79
{
36
79
  int rv;
37
79
  u8 buffer[3072];
38
79
  size_t cb_buffer = sizeof(buffer);
39
79
  LOG_FUNC_CALLED(card->ctx);
40
41
79
  rv = sc_get_data(card, data_id, buffer, cb_buffer);
42
79
  LOG_TEST_RET(card->ctx, rv, "GET DATA failed");
43
61
  if (rv == 0) {
44
30
    LOG_TEST_RET(card->ctx, SC_ERROR_FILE_NOT_FOUND, "No certificate data returned");
45
30
  }
46
47
31
  if (cert_info != NULL) {
48
31
    free(cert_info->value);
49
31
    cert_info->value = malloc(rv);
50
31
    if (cert_info->value != NULL) {
51
31
      cert_info->len = rv;
52
31
      memcpy(cert_info->value, buffer, rv);
53
31
    }
54
31
  }
55
31
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
56
31
}
57
58
static int add_nqapplet_pin(sc_pkcs15_card_t *p15card, const char *id, u8 reference)
59
53
{
60
53
  int rv;
61
53
  struct sc_pkcs15_auth_info pin_info;
62
53
  struct sc_pkcs15_object pin_obj;
63
53
  sc_card_t *card = p15card->card;
64
65
53
  LOG_FUNC_CALLED(card->ctx);
66
67
53
  memset(&pin_info, 0, sizeof(pin_info));
68
53
  memset(&pin_obj, 0, sizeof(pin_obj));
69
70
53
  sc_pkcs15_format_id(id, &pin_info.auth_id);
71
53
  pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
72
53
  pin_info.attrs.pin.reference = reference;
73
53
  pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
74
53
                             SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL | SC_PKCS15_PIN_AUTH_TYPE_PIN;
75
53
  pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_UTF8;
76
53
  pin_info.attrs.pin.min_length = 6;
77
53
  pin_info.attrs.pin.stored_length = 6;
78
53
  pin_info.attrs.pin.max_length = 6;
79
53
  pin_info.attrs.pin.pad_char = '\0';
80
53
  pin_info.tries_left = -1; // TODO
81
53
  pin_info.max_tries = 3;
82
83
53
  strlcpy(pin_obj.label, "UserPIN", sizeof(pin_obj.label));
84
53
  pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
85
86
53
  rv = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
87
53
  LOG_TEST_RET(card->ctx, rv, "sc_pkcs15emu_add_pin_obj failed");
88
89
53
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
90
53
}
91
92
static int add_nqapplet_certificate(sc_pkcs15_card_t *p15card, const char *id, const char *name, u8 data_id)
93
79
{
94
79
  int rv;
95
79
  struct sc_pkcs15_cert_info cert_info;
96
79
  struct sc_pkcs15_object cert_obj;
97
79
  sc_card_t *card = p15card->card;
98
99
79
  LOG_FUNC_CALLED(card->ctx);
100
101
79
  memset(&cert_info, 0, sizeof(cert_info));
102
79
  memset(&cert_obj, 0, sizeof(cert_obj));
103
104
79
  sc_pkcs15_format_id(id, &cert_info.id);
105
79
  rv = get_nqapplet_certificate(card, data_id, &cert_info.value);
106
79
  LOG_TEST_RET(card->ctx, rv, "Failed to get certificate");
107
108
31
  strlcpy(cert_obj.label, name, sizeof(cert_obj.label));
109
110
31
  rv = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
111
31
  LOG_TEST_RET(card->ctx, rv, "sc_pkcs15emu_add_x509_cert failed");
112
113
31
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
114
31
}
115
116
static int add_nqapplet_private_key(sc_pkcs15_card_t *p15card, const char *id, int reference,
117
                                    const char *name, const char *pin_id, unsigned int usage)
118
31
{
119
31
  int rv;
120
31
  struct sc_pkcs15_prkey_info prkey_info;
121
31
  struct sc_pkcs15_object prkey_obj;
122
31
  sc_card_t *card = p15card->card;
123
124
31
  LOG_FUNC_CALLED(card->ctx);
125
126
31
  memset(&prkey_info, 0, sizeof(prkey_info));
127
31
  memset(&prkey_obj, 0, sizeof(prkey_obj));
128
129
31
  sc_pkcs15_format_id(id, &prkey_info.id);
130
31
  prkey_info.usage = usage;
131
31
  prkey_info.native = 1;
132
31
  prkey_info.key_reference = reference;
133
31
  prkey_info.modulus_length = 3072;
134
135
31
  strlcpy(prkey_obj.label, name, sizeof(prkey_obj.label));
136
31
  prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
137
31
  sc_pkcs15_format_id(pin_id, &prkey_obj.auth_id);
138
139
31
  rv = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
140
31
  LOG_TEST_RET(card->ctx, rv, "sc_pkcs15emu_add_rsa_prkey failed");
141
142
31
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
143
31
}
144
145
static int add_nqapplet_objects(sc_pkcs15_card_t *p15card)
146
53
{
147
53
  int rv;
148
53
  sc_card_t *card = p15card->card;
149
150
53
  LOG_FUNC_CALLED(card->ctx);
151
152
  // 1) User PIN
153
53
  rv = add_nqapplet_pin(p15card, "1", 0x01);
154
53
  LOG_TEST_RET(card->ctx, rv, "Failed to add PIN 1");
155
156
  // 2.1) C.CH.Auth
157
53
  rv = add_nqapplet_certificate(p15card, "1", "C.CH.Auth", 0x00);
158
53
  LOG_TEST_RET(card->ctx, rv, "Failed to add Auth. certificate");
159
160
  // 2.2) PrK.CH.Auth
161
26
  rv = add_nqapplet_private_key(p15card, "1", 0x01, "PrK.CH.Auth", "1",
162
26
                                SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT);
163
26
  LOG_TEST_RET(card->ctx, rv, "Failed to add Auth. private key");
164
165
  // 3.1) C.CH.Encr
166
26
  rv = add_nqapplet_certificate(p15card, "2", "C.CH.Encr", 0x01);
167
26
  if (rv == SC_SUCCESS) {
168
    // 3.2) PrK.CH.Encr
169
5
    rv = add_nqapplet_private_key(p15card, "2", 0x02, "PrK.CH.Encr", "1", SC_PKCS15_PRKEY_USAGE_DECRYPT);
170
5
    LOG_TEST_RET(card->ctx, rv, "Failed to add Encr. private key");
171
21
  } else {
172
21
    sc_log(p15card->card->ctx, "The card has no C.CH.Encr, ignoring CH.Encr container");
173
21
  }
174
175
26
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
176
26
}
177
178
int sc_pkcs15emu_nqapplet_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *aid)
179
7.07k
{
180
7.07k
  int rv = SC_ERROR_WRONG_CARD;
181
7.07k
  sc_context_t *ctx;
182
7.07k
  sc_card_t *card;
183
184
7.07k
  if (!p15card || !p15card->card || !p15card->card->ctx) {
185
0
    return SC_ERROR_INVALID_ARGUMENTS;
186
0
  }
187
188
7.07k
  card = p15card->card;
189
7.07k
  ctx = card->ctx;
190
191
7.07k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
192
193
7.07k
  if (card->type < SC_CARD_TYPE_NQ_APPLET || card->type > SC_CARD_TYPE_NQ_APPLET_RFID) {
194
7.01k
    sc_log(p15card->card->ctx, "Unsupported card type: %d", card->type);
195
7.01k
    return SC_ERROR_WRONG_CARD;
196
7.01k
  }
197
198
53
  rv = add_nqapplet_objects(p15card);
199
53
  LOG_TEST_GOTO_ERR(ctx, rv, "Failed to add PKCS15");
200
201
26
  if (aid != NULL) {
202
0
    struct sc_file *file = sc_file_new();
203
0
    if (file != NULL) {
204
      /* PKCS11 depends on the file_app object, provide MF */
205
0
      sc_format_path("3f00", &file->path);
206
0
      sc_file_free(p15card->file_app);
207
0
      p15card->file_app = file;
208
0
    }
209
0
  }
210
211
26
  sc_pkcs15_free_tokeninfo(p15card->tokeninfo);
212
213
26
  p15card->tokeninfo = sc_pkcs15_tokeninfo_new();
214
26
  if (p15card->tokeninfo == NULL) {
215
0
    rv = SC_ERROR_OUT_OF_MEMORY;
216
0
    LOG_TEST_GOTO_ERR(ctx, rv, "unable to create tokeninfo struct");
217
26
  } else {
218
26
    char serial_hex[SC_MAX_SERIALNR * 2 + 2];
219
220
26
    sc_bin_to_hex(card->serialnr.value, card->serialnr.len, serial_hex, sizeof(serial_hex), 0);
221
26
    set_string(&p15card->tokeninfo->serial_number, serial_hex);
222
26
    set_string(&p15card->tokeninfo->label, name_Card);
223
26
    set_string(&p15card->tokeninfo->manufacturer_id, name_Vendor);
224
26
    p15card->tokeninfo->flags = SC_PKCS15_TOKEN_READONLY;
225
26
  }
226
227
26
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
228
27
err:
229
27
  sc_pkcs15_card_clear(p15card);
230
27
  LOG_FUNC_RETURN(ctx, rv);
231
27
}