/src/opensc/src/libopensc/pkcs15-cardos.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * PKCS15 emulation layer for CardOS cards |
3 | | * Adapted from PKCS15 emulation layer for IAS/ECC card. |
4 | | * |
5 | | * Copyright (C) 2020, Douglas E. Engert <DEEngert@gmail.com> |
6 | | * Copyright (C) 2016, Viktor Tarasov <viktor.tarasov@gmail.com> |
7 | | * Copyright (C) 2004, Bud P. Bruegger <bud@comune.grosseto.it> |
8 | | * Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it> |
9 | | * Copyright (C) 2003, Olaf Kirch <okir@suse.de> |
10 | | * |
11 | | * This library is free software; you can redistribute it and/or |
12 | | * modify it under the terms of the GNU Lesser General Public |
13 | | * License as published by the Free Software Foundation; either |
14 | | * version 2.1 of the License, or (at your option) any later version. |
15 | | * |
16 | | * This library is distributed in the hope that it will be useful, |
17 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 | | * Lesser General Public License for more details. |
20 | | * |
21 | | * You should have received a copy of the GNU Lesser General Public |
22 | | * License along with this library; if not, write to the Free Software |
23 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
24 | | */ |
25 | | |
26 | | #ifdef HAVE_CONFIG_H |
27 | | #include "config.h" |
28 | | #endif |
29 | | |
30 | | #include <stdlib.h> |
31 | | #include <string.h> |
32 | | #include <stdio.h> |
33 | | |
34 | | #include "internal.h" |
35 | | #include "pkcs15.h" |
36 | | |
37 | | |
38 | | /* |
39 | | * Called after sc_pkcs15_bind_internal |
40 | | * Create new flags based on supported_algos. |
41 | | */ |
42 | | static int cardos_fix_token_info(sc_pkcs15_card_t *p15card) |
43 | 67 | { |
44 | 67 | sc_card_t *card; |
45 | 67 | struct sc_supported_algo_info (*saa)[SC_MAX_SUPPORTED_ALGORITHMS]; |
46 | 67 | struct sc_supported_algo_info *sa; |
47 | 67 | struct sc_cardctl_cardos_pass_algo_flags *passed = NULL; |
48 | 67 | int r = 0; |
49 | 67 | int i; |
50 | | |
51 | 67 | card = p15card->card; |
52 | | |
53 | 67 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
54 | | |
55 | 67 | passed = calloc(1, sizeof(struct sc_cardctl_cardos_pass_algo_flags)); |
56 | 67 | if (!passed) |
57 | 67 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); |
58 | | |
59 | 67 | passed->pass = 1; /* get used_flags and card_flags from card */ |
60 | 67 | r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); |
61 | 67 | if (r < 0) { |
62 | 0 | free(passed); |
63 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
64 | 0 | } |
65 | | |
66 | 67 | saa = &(p15card->tokeninfo->supported_algos); |
67 | | |
68 | 67 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Original Flags: 0x%8.8lx card->flags:0x%8.8lx", passed->used_flags, passed->card_flags); |
69 | | |
70 | 67 | if (passed->card_flags) { /* user forced the flags, use them */ |
71 | 0 | passed->new_flags = passed->card_flags; /* from card_atr flags */ |
72 | 67 | } else { |
73 | | |
74 | 150 | for (i = 0, sa = saa[0]; i < SC_MAX_SUPPORTED_ALGORITHMS; i++, sa++) { |
75 | | |
76 | 150 | if (sa->reference == 0 && sa->mechanism == 0 |
77 | 150 | && sa->operations == 0 && sa->algo_ref == 0) |
78 | 67 | break; |
79 | | |
80 | 83 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "supported_algos[%d] mechanism:0x%8.8x", i, sa->mechanism); |
81 | 83 | switch(sa->mechanism) { |
82 | 26 | case 0x01 : |
83 | | /* |
84 | | * Card appears to use lower 4 bits of reference as key, and upper |
85 | | * 4 bits as mech for card. |
86 | | * Also has a bug if mechanism = 1 (CKM_RSA_PKCS1) and reference 0x10 |
87 | | * bit is set mechanism should be 3 (CKM_RSA_X_509) |
88 | | * correct the mechanism in tokenInfo |
89 | | */ |
90 | 26 | if (sa->reference & 0x10) { |
91 | 16 | sc_log(card->ctx, "Changing mechanism to CKM_RSA_X_509 based on reference"); |
92 | 16 | passed->new_flags |= SC_ALGORITHM_RSA_RAW |
93 | 16 | | SC_ALGORITHM_RSA_PAD_NONE; |
94 | 16 | sa->mechanism = 0x03; |
95 | 16 | } else |
96 | 10 | passed->new_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; |
97 | 26 | break; |
98 | 10 | case 0x03 : |
99 | 10 | passed->new_flags |= SC_ALGORITHM_RSA_RAW |
100 | 10 | | SC_ALGORITHM_RSA_PAD_NONE; |
101 | 10 | break; |
102 | 10 | case 0x06 : |
103 | 10 | passed->new_flags |= SC_ALGORITHM_RSA_HASH_SHA1; |
104 | 10 | break; |
105 | 0 | case 0x1041: |
106 | 0 | passed->ec_flags |= SC_ALGORITHM_ECDSA_RAW; |
107 | | /* no old_ec_flags */ |
108 | | /* TODO turn on sizes from ec curves OIDS */ |
109 | 0 | break; |
110 | 37 | default: |
111 | 37 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "UNKNOWN MECH: 0x%8.8x", sa->mechanism); |
112 | 83 | } |
113 | | |
114 | 83 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", |
115 | 83 | passed->new_flags, passed->ec_flags); |
116 | 83 | } |
117 | | |
118 | 67 | if (passed->new_flags == 0) { |
119 | 51 | if (p15card->tokeninfo && p15card->tokeninfo->flags & SC_PKCS15_TOKEN_EID_COMPLIANT) { |
120 | 18 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EID_COMPLIANT flag found"); |
121 | 18 | passed->new_flags = (passed->used_flags & ~SC_ALGORITHM_SPECIFIC_FLAGS) | SC_ALGORITHM_RSA_PAD_PKCS1; |
122 | 18 | } else |
123 | 33 | passed->new_flags = passed->used_flags; /* from default cardos_init */ |
124 | 51 | } |
125 | 67 | } |
126 | | |
127 | 67 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Final New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", passed->new_flags, passed->ec_flags); |
128 | | |
129 | 67 | passed->pass = 2; /* tell card driver to use the new flags */ |
130 | 67 | r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); |
131 | | |
132 | 67 | free(passed); |
133 | 67 | LOG_FUNC_RETURN(card->ctx, r); |
134 | 67 | } |
135 | | |
136 | | static int |
137 | | cardos_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card) |
138 | 7.60k | { |
139 | 7.60k | if (p15card->card->type < SC_CARD_TYPE_CARDOS_BASE) |
140 | 191 | return SC_ERROR_WRONG_CARD; |
141 | | |
142 | 7.40k | if (p15card->card->type >= SC_CARD_TYPE_CARDOS_BASE + 1000) |
143 | 6.92k | return SC_ERROR_WRONG_CARD; |
144 | | |
145 | 484 | return SC_SUCCESS; |
146 | 7.40k | } |
147 | | |
148 | | |
149 | | static int |
150 | | sc_pkcs15emu_cardos_init(struct sc_pkcs15_card *p15card, struct sc_aid *aid) |
151 | 484 | { |
152 | 484 | sc_card_t *card = p15card->card; |
153 | 484 | int r; |
154 | | |
155 | 484 | LOG_FUNC_CALLED(card->ctx); |
156 | | |
157 | 484 | r = sc_pkcs15_bind_internal(p15card, aid); |
158 | 484 | LOG_TEST_RET(card->ctx, r, "sc_pkcs15_bind_internal failed"); |
159 | | |
160 | | /* If card has created algorithms, return */ |
161 | 84 | sc_log(card->ctx, " card->algorithms:%p card->algorithm_count:%d", card->algorithms, card->algorithm_count); |
162 | 84 | if (!card->algorithms && card->algorithm_count == 0) { |
163 | 67 | r = cardos_fix_token_info(p15card); |
164 | 67 | } |
165 | | |
166 | 84 | LOG_FUNC_RETURN(card->ctx, r); |
167 | 84 | } |
168 | | |
169 | | |
170 | | int |
171 | | sc_pkcs15emu_cardos_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid) |
172 | 7.60k | { |
173 | 7.60k | if (cardos_pkcs15emu_detect_card(p15card)) |
174 | 7.11k | return SC_ERROR_WRONG_CARD; |
175 | | |
176 | 484 | return sc_pkcs15emu_cardos_init(p15card, aid); |
177 | 7.60k | } |