Coverage Report

Created: 2026-03-01 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-din-66291.c
Line
Count
Source
1
/*
2
 * PKCS15 emulation layer for DIN 66291–4 profile.
3
 *
4
 * Copyright (C) 2017, Frank Morgner
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
22
#ifdef HAVE_CONFIG_H
23
#include <config.h>
24
#endif
25
26
#include "internal.h"
27
#include "common/compat_strlcpy.h"
28
#include "log.h"
29
#include "pkcs15.h"
30
#include <stdlib.h>
31
#include <string.h>
32
33
static const unsigned char aid_CIA[] = {0xE8, 0x28, 0xBD, 0x08, 0x0F,
34
    0xA0, 0x00, 0x00, 0x01, 0x67, 0x45, 0x53, 0x49, 0x47, 0x4E};
35
static const unsigned char aid_ESIGN[] = {0xA0, 0x00, 0x00, 0x01, 0x67,
36
    0x45, 0x53, 0x49, 0x47, 0x4E};
37
static const unsigned char aid_gematik_egk[] = {0xD2, 0x76,
38
    0x00, 0x01, 0x44, 0x80, 0x00};
39
40
static int
41
sc_pkcs15emu_din_66291_init(sc_pkcs15_card_t *p15card)
42
1.85k
{
43
    /*  EF.C.CH.AUT
44
     *  fileIdentifier ´C5 00´
45
     *  shortFileIdentifier ´01´= 1 
46
     *  PrK.CH.AUT 
47
     *  keyIdentifier ´02´ = 2
48
     *  privateKey …, Moduluslänge 2048 Bit 
49
     *
50
     *  EF.C.CH.ENC 
51
     *  fileIdentifier ´C2 00´
52
     *  shortFileIdentifier ´02´= 2
53
     *  PrK.CH.ENC 
54
     *  keyIdentifier ´03´ = 3
55
     *  privateKey …, Moduluslänge 2048 Bit 
56
     */
57
1.85k
    sc_path_t path;
58
1.85k
    size_t i;
59
1.85k
    struct sc_pin_cmd_data data;
60
1.85k
    const unsigned char user_pin_ref = 0x02;
61
62
1.85k
    sc_path_set(&path, SC_PATH_TYPE_DF_NAME, aid_ESIGN, sizeof aid_ESIGN, 0, 0);
63
1.85k
    if (SC_SUCCESS != sc_select_file(p15card->card, &path, NULL))
64
29
        return SC_ERROR_WRONG_CARD;
65
66
1.82k
    memset(&data, 0, sizeof(data));
67
1.82k
    data.cmd = SC_PIN_CMD_GET_INFO;
68
1.82k
    data.pin_type = SC_AC_CHV;
69
1.82k
    data.pin_reference = user_pin_ref;
70
71
1.82k
    if (SC_SUCCESS == sc_pin_cmd(p15card->card, &data, NULL)) {
72
443
        const unsigned char user_pin_id = 1;
73
74
1.32k
        for (i = 0; i < 2; i++) {
75
886
            const char *pin_names[3] = { "PIN", "PUK" };
76
886
            const int pin_min[] = {6, 10};
77
886
            const int pin_max[] = {8, 8};
78
886
            const unsigned char user_puk_id = 2;
79
886
            const int pin_id[] = {user_pin_id, user_puk_id};
80
886
            const int pin_flags[] = {SC_PKCS15_PIN_FLAG_INITIALIZED,
81
886
                SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN|SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED};
82
886
            const int max_tries[] = {3, 10};
83
886
            struct sc_pkcs15_auth_info pin_info;
84
886
            struct sc_pkcs15_object pin_obj;
85
86
886
            memset(&pin_info, 0, sizeof(pin_info));
87
886
            memset(&pin_obj, 0, sizeof(pin_obj));
88
89
886
            pin_info.auth_id.value[0] = pin_id[i];
90
886
            pin_info.auth_id.len = 1;
91
886
            pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; 
92
886
            pin_info.attrs.pin.flags = pin_flags[i];
93
886
            pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
94
886
            pin_info.attrs.pin.min_length = pin_min[i];
95
886
            pin_info.attrs.pin.stored_length = pin_max[i];
96
886
            pin_info.attrs.pin.max_length = pin_max[i];
97
886
            pin_info.max_tries = max_tries[i];
98
99
886
            strlcpy(pin_obj.label, pin_names[i], sizeof(pin_obj.label));
100
101
            /* catch the differences between PIN and PUK */
102
886
            if (pin_flags[i] & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) {
103
443
                pin_info.tries_left = max_tries[i];
104
443
            } else {
105
443
                pin_info.attrs.pin.reference = user_pin_ref;
106
443
                pin_info.tries_left = data.pin1.tries_left;
107
443
                pin_info.logged_in = data.pin1.logged_in;
108
443
                pin_obj.auth_id.value[0] = user_puk_id;
109
443
                pin_obj.auth_id.len = 1;
110
443
            }
111
112
886
            if (0 > sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info)) {
113
0
                sc_pkcs15_card_clear(p15card);
114
0
                return SC_ERROR_INTERNAL;
115
0
            }
116
886
        }
117
118
1.32k
        for (i = 0; i < 2; i++) {
119
886
            struct sc_aid aid;
120
886
            const char *din_66291_cert_fids[] = { "C500", "C200"};
121
886
            const char prk_id[] = { 0x10, 0x11,};
122
886
            struct sc_pkcs15_cert_info cert_info;
123
886
            struct sc_pkcs15_object cert_obj;
124
886
            struct sc_pkcs15_prkey_info prkey_info;
125
886
            struct sc_pkcs15_object prkey_obj;
126
886
            const int prk_usage[2] = {
127
886
                SC_PKCS15_PRKEY_USAGE_ENCRYPT
128
886
                    | SC_PKCS15_PRKEY_USAGE_DECRYPT
129
886
                    | SC_PKCS15_PRKEY_USAGE_SIGN,
130
886
                SC_PKCS15_PRKEY_USAGE_NONREPUDIATION};
131
132
886
            memcpy(aid.value, aid_CIA, sizeof aid_CIA);
133
886
            aid.len = sizeof aid_CIA;
134
135
886
            memset(&prkey_info, 0, sizeof(prkey_info));
136
886
            memset(&prkey_obj, 0, sizeof(prkey_obj));
137
886
            memset(&cert_info, 0, sizeof(cert_info));
138
886
            memset(&cert_obj, 0, sizeof(cert_obj));
139
140
141
886
            sc_format_path(din_66291_cert_fids[i], &cert_info.path);
142
886
            if (SC_SUCCESS != sc_select_file(p15card->card, &cert_info.path, NULL))
143
588
                continue;
144
298
            cert_info.path.aid = aid;
145
146
298
            cert_info.id.value[0] = prk_id[i];
147
298
            cert_info.id.len = 1;
148
149
298
            if (0 > sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info))
150
0
                continue;
151
152
298
            if (i == 0) {
153
112
                sc_pkcs15_cert_t *cert;
154
112
                if (SC_SUCCESS == sc_pkcs15_read_certificate(p15card, &cert_info, 0, &cert)) {
155
0
                    static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }};
156
0
                    u8 *cn_name = NULL;
157
0
                    size_t cn_len = 0;
158
0
                    sc_pkcs15_get_name_from_dn(p15card->card->ctx, cert->subject,
159
0
                            cert->subject_len, &cn_oid, &cn_name, &cn_len);
160
0
                    if (cn_len > 0) {
161
0
                        char *token_name = malloc(cn_len+1);
162
0
                        if (token_name) {
163
0
                            memcpy(token_name, cn_name, cn_len);
164
0
                            token_name[cn_len] = '\0';
165
0
                            free(p15card->tokeninfo->label);
166
0
                            p15card->tokeninfo->label = token_name;
167
0
                        }
168
0
                    }
169
0
                    free(cn_name);
170
0
                    sc_pkcs15_free_certificate(cert);
171
0
                }
172
112
            }
173
174
298
            memset(&prkey_info, 0, sizeof(prkey_info));
175
298
            memset(&prkey_obj, 0, sizeof(prkey_obj));
176
177
298
            prkey_info.id.value[0] = prk_id[i];
178
298
            prkey_info.id.len = 1;
179
298
            prkey_info.usage  = prk_usage[i];
180
298
            prkey_info.native = 1;
181
298
            prkey_info.key_reference = prk_id[i];
182
298
            prkey_info.modulus_length = 2048;
183
298
            prkey_obj.auth_id.value[0] = user_pin_id;
184
298
            prkey_obj.auth_id.len = 1;
185
298
            prkey_obj.user_consent = 0;
186
298
            prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
187
188
298
            if (0 > sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info))
189
0
                continue;
190
298
        }
191
443
    }
192
193
1.82k
    return SC_SUCCESS;
194
1.82k
}
195
196
int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *aid)
197
7.50k
{
198
7.50k
    int r = SC_ERROR_WRONG_CARD;
199
7.50k
    sc_path_t path;
200
7.50k
    unsigned char *tokeninfo_content = NULL;
201
7.50k
    struct sc_file *file_tokeninfo = NULL;
202
7.50k
    struct sc_pkcs15_tokeninfo *tokeninfo = NULL;
203
7.50k
  sc_serial_number_t serial;
204
205
7.50k
    if (!p15card || ! p15card->card)
206
0
        return SC_ERROR_INVALID_ARGUMENTS;
207
208
7.50k
    SC_FUNC_CALLED(p15card->card->ctx, 1);
209
210
7.50k
    tokeninfo = sc_pkcs15_tokeninfo_new();
211
7.50k
    if (!p15card || !tokeninfo
212
7.50k
            || (aid && (aid->len != sizeof aid_CIA
213
0
                    || 0 != memcmp(aid->value, aid_CIA, sizeof aid_CIA))))
214
0
        goto err;
215
216
7.50k
    if (!p15card->tokeninfo
217
7.50k
            || !p15card->tokeninfo->profile_indication.name
218
0
            || 0 != strcmp("DIN V 66291",
219
7.50k
                p15card->tokeninfo->profile_indication.name)) {
220
        /* it is possible that p15card->tokeninfo has not been touched yet */
221
7.50k
        if (SC_SUCCESS == sc_path_set(&path, SC_PATH_TYPE_DF_NAME,
222
7.50k
                    aid_CIA, sizeof aid_CIA, 0, 0)
223
7.50k
                && SC_SUCCESS == sc_select_file(p15card->card, &path, NULL)) {
224
532
            sc_format_path("5032", &path);
225
532
            if (SC_SUCCESS != sc_select_file(p15card->card, &path, &file_tokeninfo))
226
401
                goto err;
227
228
131
            tokeninfo_content = malloc(file_tokeninfo->size);
229
131
            if (!tokeninfo_content)
230
0
                goto err;
231
131
            r = sc_read_binary(p15card->card, 0, tokeninfo_content, file_tokeninfo->size, 0);
232
131
            if (r < 0)
233
26
                goto err;
234
105
            r = sc_pkcs15_parse_tokeninfo(p15card->card->ctx, tokeninfo, tokeninfo_content, r);
235
105
            if (r != SC_SUCCESS)
236
57
                goto err;
237
238
48
            if (!tokeninfo->profile_indication.name
239
12
                    || 0 != strcmp("DIN V 66291",
240
48
                        tokeninfo->profile_indication.name)) {
241
48
                goto err;
242
48
            }
243
6.97k
        } else {
244
            /* BARMER eGK doesn't include MF / DF.CIA_ESIGN / EF.CIA_Info
245
             * just detect it via its specific AID */
246
6.97k
            if (SC_SUCCESS != sc_path_set(&path, SC_PATH_TYPE_DF_NAME,
247
6.97k
                        aid_gematik_egk, sizeof aid_gematik_egk, 0, 0)
248
6.97k
                    || SC_SUCCESS != sc_select_file(p15card->card, &path, NULL))
249
5.12k
                goto err;
250
251
1.85k
            tokeninfo->profile_indication.name = strdup("DIN V 66291");
252
1.85k
        }
253
7.50k
    }
254
255
1.85k
    if (SC_SUCCESS != sc_pkcs15emu_din_66291_init(p15card))
256
29
        goto err;
257
258
    /* save tokeninfo and file_tokeninfo */
259
1.82k
    sc_pkcs15_free_tokeninfo(p15card->tokeninfo);
260
1.82k
    sc_file_free(p15card->file_tokeninfo);
261
1.82k
    p15card->tokeninfo = tokeninfo;
262
1.82k
    p15card->file_tokeninfo = file_tokeninfo;
263
1.82k
    tokeninfo = NULL;
264
1.82k
    file_tokeninfo = NULL;
265
266
    /* get the card serial number */
267
1.82k
    if (!p15card->tokeninfo->serial_number
268
1.82k
            && SC_SUCCESS == sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &serial)) {
269
494
        char serial_hex[SC_MAX_SERIALNR*2+2];
270
494
        sc_bin_to_hex(serial.value, serial.len , serial_hex, sizeof serial_hex, 0);
271
494
        set_string(&p15card->tokeninfo->serial_number, serial_hex);
272
494
    }
273
274
1.82k
    r = SC_SUCCESS;
275
276
7.50k
err:
277
7.50k
    sc_pkcs15_free_tokeninfo(tokeninfo);
278
7.50k
    sc_file_free(file_tokeninfo);
279
7.50k
    free(tokeninfo_content);
280
281
7.50k
    return r;
282
1.82k
}