/src/opensc/src/pkcs15init/pkcs15-openpgp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * OpenPGP specific operation for PKCS15 initialization |
3 | | * |
4 | | * Copyright (c) 2012 Nguyen Hong Quan <ng.hong.quan@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 "config.h" |
22 | | |
23 | | #include <sys/types.h> |
24 | | #include <stdlib.h> |
25 | | #include <string.h> |
26 | | |
27 | | #include "libopensc/opensc.h" |
28 | | #include "libopensc/cardctl.h" |
29 | | #include "libopensc/internal.h" |
30 | | #include "libopensc/log.h" |
31 | | #include "libopensc/cards.h" |
32 | | #include "libopensc/asn1.h" |
33 | | #include "pkcs15-init.h" |
34 | | #include "profile.h" |
35 | | |
36 | | |
37 | | /** |
38 | | * Erase card: erase all EFs/DFs created by OpenSC |
39 | | * @param profile The sc_profile_t object with the configurable profile |
40 | | * information |
41 | | * @param p15card The card from which the opensc application should be |
42 | | * erased. |
43 | | * @return SC_SUCCESS on success and an error code otherwise |
44 | | **/ |
45 | | static int openpgp_erase(struct sc_profile *profile, sc_pkcs15_card_t *p15card) |
46 | 0 | { |
47 | 0 | return SC_ERROR_NOT_SUPPORTED; |
48 | 0 | } |
49 | | |
50 | | /** |
51 | | * Create application DF |
52 | | * @param profile sc_profile_t object with the configurable profile |
53 | | * information |
54 | | * @param p15card sc_card_t object to be used |
55 | | * @param df sc_file_t with the application DF to create |
56 | | * @return SC_SUCCESS on success and an error value otherwise |
57 | | **/ |
58 | | static int openpgp_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
59 | | sc_file_t *df) |
60 | 0 | { |
61 | 0 | return SC_ERROR_NOT_SUPPORTED; |
62 | 0 | } |
63 | | |
64 | | /** |
65 | | * Select PIN reference: do nothing special, the real PIN reference if |
66 | | * determined when the PIN is created. This is just helper function to |
67 | | * determine the next best file id of the PIN file. |
68 | | **/ |
69 | | static int openpgp_select_pin_reference(sc_profile_t *profile, |
70 | | sc_pkcs15_card_t *p15card, sc_pkcs15_auth_info_t *auth_info) |
71 | 0 | { |
72 | 0 | return SC_ERROR_NOT_SUPPORTED; |
73 | 0 | } |
74 | | |
75 | | /** |
76 | | * Create PIN and, if specified, PUK files |
77 | | * @param profile profile information for this card |
78 | | * @param card sc_card_t object to use |
79 | | * @param pin_obj sc_pkcs15_object_t for the PIN |
80 | | * @param pin PIN value |
81 | | * @param len_len PIN length |
82 | | * @param puk PUK value (optional) |
83 | | * @param puk_len PUK length (optional) |
84 | | * @return SC_SUCCESS on success and an error code otherwise |
85 | | **/ |
86 | | static int openpgp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
87 | | sc_file_t *df, sc_pkcs15_object_t *pin_obj, |
88 | | const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len) |
89 | 0 | { |
90 | 0 | return SC_ERROR_NOT_SUPPORTED; |
91 | 0 | } |
92 | | |
93 | | /** |
94 | | * Creates empty key file |
95 | | **/ |
96 | | static int openpgp_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
97 | | sc_pkcs15_object_t *obj) |
98 | 0 | { |
99 | | /* For OpenPGP card, the number of keys is fixed, |
100 | | * so this function does not really do anything. |
101 | | * It just present here to avoid pkcs15init's default routine, |
102 | | * which tries to do impossible things. */ |
103 | 0 | LOG_FUNC_CALLED(p15card->card->ctx); |
104 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); |
105 | 0 | } |
106 | | /** |
107 | | * Set algorithm and check if card supports it |
108 | | * @param p15card sc_pkcs15_card_t |
109 | | * @param type SC_PKCS15_TYPE_* |
110 | | * @param key_id openspgp id |
111 | | * @param &algorithm SC_OPENPGP_KEYALGO_* |
112 | | |
113 | | * @returns 0 or error |
114 | | */ |
115 | | |
116 | | static int |
117 | | openpgp_set_algorithm(sc_pkcs15_card_t *p15card, |
118 | | u8 key_id, unsigned long type, u8 *algo) |
119 | 0 | { |
120 | 0 | sc_card_t *card = p15card->card; |
121 | |
|
122 | 0 | if (card->type != SC_CARD_TYPE_OPENPGP_GNUK && |
123 | 0 | card->type < SC_CARD_TYPE_OPENPGP_V3) { |
124 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "only RSA is supported on this card"); |
125 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); |
126 | 0 | } |
127 | | |
128 | 0 | switch (key_id) { |
129 | 0 | case SC_OPENPGP_KEY_SIGN: |
130 | 0 | case SC_OPENPGP_KEY_AUTH: |
131 | 0 | switch (type) { |
132 | 0 | case SC_PKCS15_TYPE_PRKEY_EC: |
133 | 0 | case SC_PKCS15_TYPE_PUBKEY_EC: |
134 | 0 | *algo = SC_OPENPGP_KEYALGO_ECDSA; |
135 | 0 | return SC_SUCCESS; |
136 | 0 | break; |
137 | 0 | case SC_PKCS15_TYPE_PRKEY_EDDSA: |
138 | 0 | case SC_PKCS15_TYPE_PUBKEY_EDDSA: |
139 | 0 | *algo = SC_OPENPGP_KEYALGO_EDDSA; |
140 | 0 | return SC_SUCCESS; |
141 | 0 | break; |
142 | 0 | } |
143 | 0 | break; |
144 | 0 | case SC_OPENPGP_KEY_ENCR: |
145 | 0 | switch (type) { |
146 | 0 | case SC_PKCS15_TYPE_PRKEY_EC: |
147 | 0 | case SC_PKCS15_TYPE_PUBKEY_EC: |
148 | 0 | *algo = SC_OPENPGP_KEYALGO_ECDH; |
149 | 0 | return SC_SUCCESS; |
150 | 0 | break; |
151 | 0 | case SC_PKCS15_TYPE_PRKEY_XEDDSA: |
152 | 0 | case SC_PKCS15_TYPE_PUBKEY_XEDDSA: |
153 | 0 | *algo = SC_OPENPGP_KEYALGO_ECDH; |
154 | 0 | return SC_SUCCESS; |
155 | 0 | break; |
156 | 0 | } |
157 | 0 | break; |
158 | 0 | } |
159 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Invalid algorithm of openpgp slot"); |
160 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); |
161 | 0 | } |
162 | | |
163 | | /** |
164 | | * Stores an external key on the card. |
165 | | * @param profile profile information for this card |
166 | | * @param card sc_card_t object to use |
167 | | * @param obj sc_pkcs15_object_t object with pkcs15 information |
168 | | * @param key the private key |
169 | | * @return SC_SUCCESS on success and an error code otherwise |
170 | | **/ |
171 | | static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
172 | | sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) |
173 | 0 | { |
174 | 0 | sc_card_t *card = p15card->card; |
175 | 0 | sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; |
176 | 0 | sc_cardctl_openpgp_key_gen_store_info_t key_info = {0}; |
177 | 0 | int r; |
178 | |
|
179 | 0 | LOG_FUNC_CALLED(card->ctx); |
180 | |
|
181 | 0 | switch(obj->type) |
182 | 0 | { |
183 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
184 | 0 | memset(&key_info, 0, sizeof(sc_cardctl_openpgp_key_gen_store_info_t)); |
185 | 0 | key_info.algorithm = SC_OPENPGP_KEYALGO_RSA; |
186 | 0 | key_info.key_id = kinfo->id.value[0]; |
187 | 0 | key_info.u.rsa.exponent = key->u.rsa.exponent.data; |
188 | 0 | key_info.u.rsa.exponent_len = key->u.rsa.exponent.len * 8; /* use bits instead of bytes */ |
189 | 0 | key_info.u.rsa.p = key->u.rsa.p.data; |
190 | 0 | key_info.u.rsa.p_len = key->u.rsa.p.len; |
191 | 0 | key_info.u.rsa.q = key->u.rsa.q.data; |
192 | 0 | key_info.u.rsa.q_len = key->u.rsa.q.len; |
193 | 0 | key_info.u.rsa.modulus = key->u.rsa.modulus.data; |
194 | 0 | key_info.u.rsa.modulus_len = key->u.rsa.modulus.len * 8; /* use bits instead of bytes */ |
195 | 0 | r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_STORE_KEY, &key_info); |
196 | | |
197 | | /* nothing to free in key_info for RSA */ |
198 | 0 | break; |
199 | | |
200 | 0 | case SC_PKCS15_TYPE_PRKEY_EC: |
201 | 0 | case SC_PKCS15_TYPE_PRKEY_EDDSA: |
202 | 0 | case SC_PKCS15_TYPE_PRKEY_XEDDSA: |
203 | 0 | memset(&key_info, 0, sizeof(sc_cardctl_openpgp_key_gen_store_info_t)); |
204 | |
|
205 | 0 | r = openpgp_set_algorithm(p15card, kinfo->id.value[0], obj->type, &key_info.algorithm); |
206 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, "Key type not valid for key id"); |
207 | | |
208 | 0 | key_info.key_id = kinfo->id.value[0]; |
209 | 0 | key_info.u.ec.privateD = key->u.ec.privateD.data; |
210 | 0 | key_info.u.ec.privateD_len = key->u.ec.privateD.len; |
211 | | /* |
212 | | * key->u.ec.ecpointQ.len is optional with private key |
213 | | * PKCS11 does not pass it when creting private key object. |
214 | | * pkcs15init/pkcs15-lib.c will attempt to derive it from private key |
215 | | */ |
216 | 0 | if (key->u.ec.ecpointQ.len) { |
217 | 0 | key_info.u.ec.ecpointQ = malloc(key->u.ec.ecpointQ.len); |
218 | 0 | if (!key_info.u.ec.ecpointQ) |
219 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
220 | 0 | memcpy(key_info.u.ec.ecpointQ, key->u.ec.ecpointQ.value, key->u.ec.ecpointQ.len); |
221 | 0 | } |
222 | 0 | key_info.u.ec.ecpointQ_len = key->u.ec.ecpointQ.len; |
223 | 0 | key_info.u.ec.oid = key->u.ec.params.id; |
224 | 0 | key_info.key_type = key->algorithm; /* SC_SC_ALGORITHM_* */ |
225 | 0 | r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_STORE_KEY, &key_info); |
226 | |
|
227 | 0 | free(key_info.u.ec.ecpointQ); |
228 | 0 | break; |
229 | | |
230 | 0 | default: |
231 | 0 | r = SC_ERROR_NOT_SUPPORTED; |
232 | 0 | sc_log(card->ctx, "%s: Key generation failed: Unknown/unsupported key type.", strerror(r)); |
233 | 0 | } |
234 | | |
235 | 0 | err: |
236 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
237 | 0 | } |
238 | | |
239 | | /** |
240 | | * Generates a new RSA key pair on card. |
241 | | * @param card IN sc_card_t object to use |
242 | | * @param obj IN sc_pkcs15_object_t object with pkcs15 information |
243 | | * @param pukkey OUT the newly created public key |
244 | | * @return SC_SUCCESS on success and an error code otherwise |
245 | | **/ |
246 | | static int openpgp_generate_key_rsa(sc_card_t *card, sc_pkcs15_object_t *obj, |
247 | | sc_pkcs15_pubkey_t *pubkey) |
248 | 0 | { |
249 | 0 | sc_context_t *ctx = card->ctx; |
250 | 0 | sc_cardctl_openpgp_key_gen_store_info_t key_info; |
251 | 0 | sc_pkcs15_prkey_info_t *required = (sc_pkcs15_prkey_info_t *)obj->data; |
252 | 0 | sc_pkcs15_id_t *kid = &(required->id); |
253 | 0 | int r; |
254 | |
|
255 | 0 | LOG_FUNC_CALLED(ctx); |
256 | 0 | memset(&key_info, 0, sizeof(key_info)); |
257 | 0 | sc_log(ctx, "Key ID to be generated: %s", sc_dump_hex(kid->value, kid->len)); |
258 | | |
259 | | /* Accept KeyID = 45, which is default value set by pkcs15init */ |
260 | 0 | if (kid->len == 1 && kid->value[0] == 0x45) { |
261 | | /* Default key is authentication key. We choose this because the common use |
262 | | * is to generate from PKCS#11 (Firefox/Thunderbird) */ |
263 | 0 | sc_log(ctx, "Authentication key is to be generated."); |
264 | 0 | key_info.key_id = 3; |
265 | 0 | } |
266 | 0 | if (!key_info.key_id && (kid->len > 1 || kid->value[0] > 3)) { |
267 | 0 | sc_log(ctx, "Key ID must be 1, 2 or 3!"); |
268 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
269 | 0 | } |
270 | | |
271 | 0 | if (!key_info.key_id) |
272 | 0 | key_info.key_id = kid->value[0]; |
273 | |
|
274 | 0 | if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { |
275 | 0 | sc_log(card->ctx, "only RSA is currently supported"); |
276 | 0 | return SC_ERROR_NOT_SUPPORTED; |
277 | 0 | } |
278 | | |
279 | | |
280 | 0 | key_info.algorithm = SC_OPENPGP_KEYALGO_RSA; |
281 | | |
282 | | /* Prepare buffer */ |
283 | 0 | key_info.u.rsa.modulus_len = required->modulus_length; |
284 | 0 | key_info.u.rsa.modulus = calloc(1, BYTES4BITS(required->modulus_length)); |
285 | 0 | if (key_info.u.rsa.modulus == NULL) |
286 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY); |
287 | | |
288 | | /* The OpenPGP supports only 32-bit exponent. */ |
289 | 0 | key_info.u.rsa.exponent_len = 32; |
290 | 0 | key_info.u.rsa.exponent = calloc(1, BYTES4BITS(key_info.u.rsa.exponent_len)); |
291 | 0 | if (key_info.u.rsa.exponent == NULL) { |
292 | 0 | free(key_info.u.rsa.modulus); |
293 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY); |
294 | 0 | } |
295 | | |
296 | 0 | r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info); |
297 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, "on-card EC key generation failed"); |
298 | | |
299 | 0 | pubkey->algorithm = SC_ALGORITHM_RSA; |
300 | 0 | sc_log(ctx, "Set output modulus info"); |
301 | 0 | pubkey->u.rsa.modulus.len = BYTES4BITS(key_info.u.rsa.modulus_len); |
302 | 0 | pubkey->u.rsa.modulus.data = calloc(1, pubkey->u.rsa.modulus.len); |
303 | 0 | if (pubkey->u.rsa.modulus.data == NULL) |
304 | 0 | goto err; |
305 | 0 | memcpy(pubkey->u.rsa.modulus.data, key_info.u.rsa.modulus, BYTES4BITS(key_info.u.rsa.modulus_len)); |
306 | |
|
307 | 0 | sc_log(ctx, "Set output exponent info"); |
308 | 0 | pubkey->u.rsa.exponent.len = BYTES4BITS(key_info.u.rsa.exponent_len); |
309 | 0 | pubkey->u.rsa.exponent.data = calloc(1, pubkey->u.rsa.exponent.len); |
310 | 0 | if (pubkey->u.rsa.exponent.data == NULL) |
311 | 0 | goto err; |
312 | 0 | memcpy(pubkey->u.rsa.exponent.data, key_info.u.rsa.exponent, pubkey->u.rsa.exponent.len); |
313 | |
|
314 | 0 | err: |
315 | 0 | free(key_info.u.rsa.modulus); |
316 | 0 | key_info.u.rsa.modulus = NULL; |
317 | 0 | free(key_info.u.rsa.exponent); |
318 | 0 | key_info.u.rsa.exponent = NULL; |
319 | 0 | free(key_info.data); |
320 | 0 | LOG_FUNC_RETURN(ctx, r); |
321 | 0 | } |
322 | | |
323 | | |
324 | | /** |
325 | | * Generates a new ECC key pair on card. |
326 | | * @param card IN sc_card_t object to use |
327 | | * @param obj IN sc_pkcs15_object_t object with pkcs15 information |
328 | | * @param pukkey OUT the newly created public key |
329 | | * @return SC_SUCCESS on success and an error code otherwise |
330 | | **/ |
331 | | static int openpgp_generate_key_ec(sc_card_t *card, sc_pkcs15_object_t *obj, |
332 | | sc_pkcs15_pubkey_t *pubkey) |
333 | 0 | { |
334 | 0 | sc_context_t *ctx = card->ctx; |
335 | 0 | sc_cardctl_openpgp_key_gen_store_info_t key_info; |
336 | 0 | sc_pkcs15_prkey_info_t *required = (sc_pkcs15_prkey_info_t *)obj->data; |
337 | 0 | sc_pkcs15_id_t *kid = &(required->id); |
338 | 0 | struct sc_ec_parameters *info_ec = |
339 | 0 | (struct sc_ec_parameters *)required->params.data; |
340 | 0 | int r; |
341 | |
|
342 | 0 | LOG_FUNC_CALLED(ctx); |
343 | 0 | memset(&key_info, 0, sizeof(key_info)); |
344 | |
|
345 | 0 | sc_log(ctx, "Key ID to be generated: %s", sc_dump_hex(kid->value, kid->len)); |
346 | | |
347 | | /* Accept KeyID = 45, which is default value set by pkcs15init */ |
348 | 0 | if (kid->len == 1 && kid->value[0] == 0x45) { |
349 | | /* Default key is authentication key. We choose this because the common use |
350 | | * is to generate from PKCS#11 (Firefox/Thunderbird) */ |
351 | 0 | sc_log(ctx, "Authentication key is to be generated."); |
352 | 0 | key_info.key_id = 3; |
353 | 0 | } |
354 | 0 | if (!key_info.key_id && (kid->len > 1 || kid->value[0] > 3)) { |
355 | 0 | sc_log(ctx, "Key ID must be 1, 2 or 3!"); |
356 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
357 | 0 | } |
358 | | |
359 | 0 | if (!key_info.key_id) |
360 | 0 | key_info.key_id = kid->value[0]; |
361 | 0 | key_info.key_type = pubkey->algorithm; |
362 | | /* set algorithm id based on key reference and key type */ |
363 | 0 | switch (pubkey->algorithm) { |
364 | | /* EC is in 04||x||y format |
365 | | * (field_length + 7)/8 * 2 + 1 in bytes |
366 | | * len is ecpoint length + format byte |
367 | | * see section 7.2.14 of 3.3.1 specs |
368 | | * EDDSA and XEDDSA have no format byte and one number |
369 | | * (field_length + 7)/8 in bytes |
370 | | */ |
371 | | |
372 | 0 | case SC_ALGORITHM_EC: |
373 | 0 | key_info.algorithm = (key_info.key_id == SC_OPENPGP_KEY_ENCR) |
374 | 0 | ? SC_OPENPGP_KEYALGO_ECDH /* ECDH for slot 2 only */ |
375 | 0 | : SC_OPENPGP_KEYALGO_ECDSA; /* ECDSA for slot 1 and 3 */ |
376 | 0 | key_info.u.ec.ecpointQ_len = 1 + 2 * BYTES4BITS(required->field_length); |
377 | 0 | break; |
378 | 0 | case SC_ALGORITHM_EDDSA: |
379 | 0 | key_info.algorithm = SC_OPENPGP_KEYALGO_EDDSA; /* only sign */ |
380 | 0 | key_info.u.ec.ecpointQ_len = BYTES4BITS(required->field_length); |
381 | 0 | break; |
382 | 0 | case SC_ALGORITHM_XEDDSA: |
383 | | /* TODO may need to look at MSE, and how sign XEDDSA certificate */ |
384 | 0 | key_info.algorithm = SC_OPENPGP_KEYALGO_ECDH; /* but could be used to sign too */ |
385 | 0 | key_info.u.ec.ecpointQ_len = BYTES4BITS(required->field_length); |
386 | 0 | break; |
387 | 0 | } |
388 | | |
389 | | /* copying info_ec.id works for any EC ECDH EdDSA keys */ |
390 | 0 | if (info_ec->der.len > 2 && info_ec->der.len == (size_t)(info_ec->der.value[1] + 2)) |
391 | 0 | key_info.u.ec.oidv_len = info_ec->der.value[1]; |
392 | 0 | else |
393 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
394 | | |
395 | 0 | for (size_t i = 0; (i < key_info.u.ec.oidv_len) && (i + 2 < info_ec->der.len); i++) { |
396 | 0 | key_info.u.ec.oidv.value[i] = info_ec->der.value[i + 2]; |
397 | 0 | } |
398 | 0 | key_info.u.ec.oidv.value[key_info.data_len] = -1; |
399 | | |
400 | | /* copy id also */ |
401 | 0 | key_info.u.ec.oid = info_ec->id; |
402 | | |
403 | | /* generate key on card */ |
404 | 0 | r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info); |
405 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, "on-card EC key generation failed"); |
406 | | |
407 | | /* set pubkey according to response of card */ |
408 | 0 | sc_log(ctx, "Set output ecpoint info"); |
409 | |
|
410 | 0 | pubkey->algorithm = key_info.key_type; |
411 | 0 | pubkey->u.ec.ecpointQ.len = key_info.u.ec.ecpointQ_len; |
412 | 0 | pubkey->u.ec.ecpointQ.value = malloc(key_info.u.ec.ecpointQ_len); |
413 | 0 | if (pubkey->u.ec.ecpointQ.value == NULL) { |
414 | 0 | r = SC_ERROR_NOT_ENOUGH_MEMORY; |
415 | 0 | goto err; |
416 | 0 | } |
417 | | |
418 | 0 | memcpy(pubkey->u.ec.ecpointQ.value, key_info.u.ec.ecpointQ, key_info.u.ec.ecpointQ_len); |
419 | |
|
420 | 0 | err: |
421 | 0 | free(key_info.u.ec.ecpointQ); |
422 | |
|
423 | 0 | LOG_FUNC_RETURN(ctx, r); |
424 | 0 | } |
425 | | |
426 | | |
427 | | /** |
428 | | * Generates a new key pair using an existing key file. |
429 | | * @param profile IN profile information for this card |
430 | | * @param card IN sc_card_t object to use |
431 | | * @param obj IN sc_pkcs15_object_t object with pkcs15 information |
432 | | * @param pukkey OUT the newly created public key |
433 | | * @return SC_SUCCESS on success and an error code otherwise |
434 | | **/ |
435 | | static int openpgp_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
436 | | sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) |
437 | 0 | { |
438 | 0 | sc_card_t *card = p15card->card; |
439 | 0 | sc_context_t *ctx = card->ctx; |
440 | 0 | int r; |
441 | |
|
442 | 0 | LOG_FUNC_CALLED(ctx); |
443 | |
|
444 | 0 | switch(obj->type) |
445 | 0 | { |
446 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
447 | 0 | r = openpgp_generate_key_rsa(card, obj, pubkey); |
448 | 0 | break; |
449 | 0 | case SC_PKCS15_TYPE_PRKEY_EC: |
450 | 0 | if (card->type < SC_CARD_TYPE_OPENPGP_V3) { |
451 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "only RSA is supported on this card"); |
452 | 0 | return SC_ERROR_NOT_SUPPORTED; |
453 | 0 | } |
454 | 0 | r = openpgp_generate_key_ec(card, obj, pubkey); |
455 | 0 | break; |
456 | 0 | case SC_PKCS15_TYPE_PRKEY_EDDSA: |
457 | 0 | case SC_PKCS15_TYPE_PRKEY_XEDDSA: |
458 | 0 | if (card->type != SC_CARD_TYPE_OPENPGP_GNUK && card->type < SC_CARD_TYPE_OPENPGP_V3) { |
459 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EdDSA or XEDDSA are not supported on this card"); |
460 | 0 | return SC_ERROR_NOT_SUPPORTED; |
461 | 0 | } |
462 | 0 | r = openpgp_generate_key_ec(card, obj, pubkey); |
463 | 0 | break; |
464 | 0 | default: |
465 | 0 | r = SC_ERROR_NOT_SUPPORTED; |
466 | 0 | sc_log(card->ctx, "%s: Key generation failed: Unknown/unsupported key type.", strerror(r)); |
467 | 0 | } |
468 | | |
469 | 0 | LOG_FUNC_RETURN(ctx, r); |
470 | 0 | } |
471 | | |
472 | | static int openpgp_emu_update_any_df(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
473 | | unsigned operation, sc_pkcs15_object_t *obj) |
474 | 0 | { |
475 | 0 | LOG_FUNC_CALLED(p15card->card->ctx); |
476 | | /* After storing object, pkcs15init will call this function to update DF. |
477 | | * But OpenPGP has no other DF than OpenPGP-Application, so we do nothing. */ |
478 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); |
479 | 0 | } |
480 | | |
481 | | static int openpgp_emu_update_tokeninfo(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
482 | | sc_pkcs15_tokeninfo_t *tokeninfo) |
483 | 0 | { |
484 | 0 | LOG_FUNC_CALLED(p15card->card->ctx); |
485 | | /* When unbinding pkcs15init, this function will be called. |
486 | | * But for OpenPGP, token info does not need to change, we do nothing. */ |
487 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); |
488 | 0 | } |
489 | | |
490 | | static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, |
491 | | struct sc_pkcs15_object *obj, struct sc_pkcs15_der *content, |
492 | | struct sc_path *path) |
493 | 0 | { |
494 | 0 | sc_card_t *card = p15card->card; |
495 | 0 | sc_context_t *ctx = card->ctx; |
496 | 0 | sc_file_t *file = NULL; |
497 | 0 | sc_pkcs15_cert_info_t *cinfo; |
498 | 0 | sc_pkcs15_id_t *cid; |
499 | 0 | sc_pkcs15_data_info_t *dinfo; |
500 | 0 | u8 buf[254]; |
501 | 0 | int r; |
502 | |
|
503 | 0 | LOG_FUNC_CALLED(card->ctx); |
504 | |
|
505 | 0 | switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) { |
506 | 0 | case SC_PKCS15_TYPE_PRKEY: |
507 | 0 | case SC_PKCS15_TYPE_PUBKEY: |
508 | | /* For these two type, store_data just don't need to do anything. |
509 | | * All have been done already before this function is called */ |
510 | 0 | r = SC_SUCCESS; |
511 | 0 | break; |
512 | | |
513 | 0 | case SC_PKCS15_TYPE_CERT: |
514 | 0 | cinfo = (sc_pkcs15_cert_info_t *) obj->data; |
515 | 0 | cid = &(cinfo->id); |
516 | 0 | unsigned int tag = 0x7F21; |
517 | |
|
518 | 0 | if (cid->len != 1) { |
519 | 0 | sc_log(card->ctx, "ID=%s is not valid.", sc_dump_hex(cid->value, cid->len)); |
520 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); |
521 | 0 | } |
522 | | |
523 | | /* OpenPGP card v.2 contains only 1 certificate */ |
524 | 0 | if (cid->value[0] != 3 && p15card->card->type < SC_CARD_TYPE_OPENPGP_V3) { |
525 | 0 | sc_log(card->ctx, |
526 | 0 | "This version does not support certificate ID = %d (only ID=3 is supported).", |
527 | 0 | cid->value[0]); |
528 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); |
529 | 0 | } |
530 | | |
531 | | /* OpenPGP card < v.3 does not support SELECT DATA calls */ |
532 | 0 | if (p15card->card->type >= SC_CARD_TYPE_OPENPGP_V3) { |
533 | | /* Mapping [3..1] passed --id to [0..2] for param */ |
534 | 0 | u8 param = (u8) (2 - (cid->value[0] - 1)); |
535 | | /* check for unsigned underflow */ |
536 | 0 | if (param > 2) { |
537 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); |
538 | 0 | } |
539 | | |
540 | | /* Just update the certificate DO */ |
541 | 0 | r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_SELECT_DATA, ¶m); |
542 | 0 | LOG_TEST_RET(card->ctx, r, "Failed OpenPGP - select data"); |
543 | 0 | } |
544 | | |
545 | 0 | sc_format_path("7F21", path); |
546 | 0 | r = sc_select_file(card, path, &file); |
547 | |
|
548 | 0 | LOG_TEST_RET(card->ctx, r, "Cannot select cert file"); |
549 | 0 | r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); |
550 | 0 | sc_log(card->ctx, |
551 | 0 | "Data to write is %"SC_FORMAT_LEN_SIZE_T"u long", |
552 | 0 | content->len); |
553 | 0 | if (r >= 0 && content->len) |
554 | 0 | r = sc_put_data(p15card->card, tag, (const unsigned char *) content->value, content->len); |
555 | 0 | break; |
556 | | |
557 | 0 | case SC_PKCS15_TYPE_DATA_OBJECT: |
558 | 0 | dinfo = (sc_pkcs15_data_info_t *) obj->data; |
559 | | /* dinfo->app_label contains filename */ |
560 | 0 | sc_log(ctx, "===== App label %s", dinfo->app_label); |
561 | | /* Currently, we only support DO 0101. The reason is that when initializing this |
562 | | * pkcs15 emulation, PIN authentication is not applied and we can expose only this DO, |
563 | | * which is "read always". |
564 | | * If we support other DOs, they will not be exposed, and not helpful to user. |
565 | | * I haven't found a way to refresh the list of exposed DOs after verifying PIN yet. |
566 | | * http://sourceforge.net/mailarchive/message.php?msg_id=30646373 |
567 | | **/ |
568 | 0 | sc_log(ctx, "About to write to DO 0101"); |
569 | 0 | sc_format_path("0101", path); |
570 | 0 | r = sc_select_file(card, path, &file); |
571 | 0 | LOG_TEST_RET(card->ctx, r, "Cannot select private DO"); |
572 | 0 | r = sc_read_binary(card, 0, buf, sizeof(buf), 0); |
573 | 0 | if (r < 0) { |
574 | 0 | sc_log(ctx, "Cannot read DO 0101"); |
575 | 0 | break; |
576 | 0 | } |
577 | 0 | if (r > 0) { |
578 | 0 | sc_log(ctx, "DO 0101 is full."); |
579 | 0 | r = SC_ERROR_NOT_ENOUGH_MEMORY; |
580 | 0 | break; |
581 | 0 | } |
582 | 0 | r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); |
583 | 0 | if (r >= 0 && content->len) { |
584 | 0 | r = sc_update_binary(p15card->card, 0, |
585 | 0 | (const unsigned char *) content->value, |
586 | 0 | content->len, 0); |
587 | 0 | } |
588 | 0 | break; |
589 | | |
590 | 0 | default: |
591 | 0 | r = SC_ERROR_NOT_IMPLEMENTED; |
592 | 0 | } |
593 | | |
594 | 0 | sc_file_free(file); |
595 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
596 | 0 | } |
597 | | |
598 | | static struct sc_pkcs15init_operations sc_pkcs15init_openpgp_operations = { |
599 | | openpgp_erase, |
600 | | NULL, /* init_card */ |
601 | | openpgp_create_dir, |
602 | | NULL, /* create_domain */ |
603 | | openpgp_select_pin_reference, |
604 | | openpgp_create_pin, |
605 | | NULL, /* select key reference */ |
606 | | openpgp_create_key, |
607 | | openpgp_store_key, |
608 | | openpgp_generate_key, |
609 | | NULL, NULL, /* encode private/public key */ |
610 | | NULL, /* finalize_card */ |
611 | | NULL, /* delete_object */ |
612 | | NULL, |
613 | | openpgp_emu_update_any_df, |
614 | | openpgp_emu_update_tokeninfo, |
615 | | NULL, /* emu_write_info */ |
616 | | openpgp_store_data, /* emu_store_data */ |
617 | | NULL /* sanity_check */ |
618 | | }; |
619 | | |
620 | | struct sc_pkcs15init_operations *sc_pkcs15init_get_openpgp_ops(void) |
621 | 0 | { |
622 | 0 | return &sc_pkcs15init_openpgp_operations; |
623 | 0 | } |