/src/opensc/src/pkcs15init/pkcs15-isoApplet.c
Line | Count | Source |
1 | | /* |
2 | | * pkcs15-init driver for JavaCards with IsoApplet installed. |
3 | | * |
4 | | * Copyright (C) 2014 Philip Wendland <wendlandphilip@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 | | #include <assert.h> |
27 | | #include <stdarg.h> |
28 | | |
29 | | #include "../libopensc/log.h" |
30 | | #include "../libopensc/internal.h" |
31 | | #include "../libopensc/opensc.h" |
32 | | #include "../libopensc/cardctl.h" |
33 | | #include "../libopensc/asn1.h" |
34 | | #include "pkcs15-init.h" |
35 | | #include "profile.h" |
36 | | |
37 | 0 | #define ISOAPPLET_KEY_ID_MIN 0 |
38 | 0 | #define ISOAPPLET_KEY_ID_MAX 15 |
39 | | |
40 | | /* Curve parameters of a curve specified by the OID. */ |
41 | | struct ec_curve |
42 | | { |
43 | | const struct sc_lv_data oid; /* Object ID in hex, including structural information */ |
44 | | const struct sc_lv_data prime; |
45 | | const struct sc_lv_data coefficientA; |
46 | | const struct sc_lv_data coefficientB; |
47 | | const struct sc_lv_data basePointG; |
48 | | const struct sc_lv_data order; |
49 | | const struct sc_lv_data coFactor; |
50 | | }; |
51 | | |
52 | | /* OpenSC only works with named curves, but we need the |
53 | | * explicit parameters for ECC key generation or import. */ |
54 | | static const struct ec_curve curves[] = |
55 | | { |
56 | | { |
57 | | /* brainpoolP192r1 */ |
58 | | { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x03", 11}, |
59 | | { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x97", 24}, |
60 | | { (unsigned char *) "\x6A\x91\x17\x40\x76\xB1\xE0\xE1\x9C\x39\xC0\x31\xFE\x86\x85\xC1\xCA\xE0\x40\xE5\xC6\x9A\x28\xEF", 24}, |
61 | | { (unsigned char *) "\x46\x9A\x28\xEF\x7C\x28\xCC\xA3\xDC\x72\x1D\x04\x4F\x44\x96\xBC\xCA\x7E\xF4\x14\x6F\xBF\x25\xC9", 24}, |
62 | | { (unsigned char *) "\x04\xC0\xA0\x64\x7E\xAA\xB6\xA4\x87\x53\xB0\x33\xC5\x6C\xB0\xF0\x90\x0A\x2F\x5C\x48\x53\x37\x5F\xD6\x14\xB6\x90\x86\x6A\xBD\x5B\xB8\x8B\x5F\x48\x28\xC1\x49\x00\x02\xE6\x77\x3F\xA2\xFA\x29\x9B\x8F", 49}, |
63 | | { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x2F\x9E\x9E\x91\x6B\x5B\xE8\xF1\x02\x9A\xC4\xAC\xC1", 24}, |
64 | | { (unsigned char *) "\x00\x01", 2} |
65 | | }, |
66 | | |
67 | | { |
68 | | /* brainpoolP224r1 */ |
69 | | { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x05", 11}, |
70 | | { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD1\xD7\x87\xB0\x9F\x07\x57\x97\xDA\x89\xF5\x7E\xC8\xC0\xFF", 28}, |
71 | | { (unsigned char *) "\x68\xA5\xE6\x2C\xA9\xCE\x6C\x1C\x29\x98\x03\xA6\xC1\x53\x0B\x51\x4E\x18\x2A\xD8\xB0\x04\x2A\x59\xCA\xD2\x9F\x43", 28}, |
72 | | { (unsigned char *) "\x25\x80\xF6\x3C\xCF\xE4\x41\x38\x87\x07\x13\xB1\xA9\x23\x69\xE3\x3E\x21\x35\xD2\x66\xDB\xB3\x72\x38\x6C\x40\x0B", 28}, |
73 | | { (unsigned char *) "\x04\x0D\x90\x29\xAD\x2C\x7E\x5C\xF4\x34\x08\x23\xB2\xA8\x7D\xC6\x8C\x9E\x4C\xE3\x17\x4C\x1E\x6E\xFD\xEE\x12\xC0\x7D\x58\xAA\x56\xF7\x72\xC0\x72\x6F\x24\xC6\xB8\x9E\x4E\xCD\xAC\x24\x35\x4B\x9E\x99\xCA\xA3\xF6\xD3\x76\x14\x02\xCD", 57}, |
74 | | { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD0\xFB\x98\xD1\x16\xBC\x4B\x6D\xDE\xBC\xA3\xA5\xA7\x93\x9F", 28}, |
75 | | { (unsigned char *) "\x00\x01", 2} |
76 | | }, |
77 | | |
78 | | { |
79 | | /* brainpoolP256r1 */ |
80 | | { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x07", 11}, |
81 | | { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, |
82 | | { (unsigned char *) "\x7D\x5A\x09\x75\xFC\x2C\x30\x57\xEE\xF6\x75\x30\x41\x7A\xFF\xE7\xFB\x80\x55\xC1\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9", 32}, |
83 | | { (unsigned char *) "\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9\xBB\xD7\x7C\xBF\x95\x84\x16\x29\x5C\xF7\xE1\xCE\x6B\xCC\xDC\x18\xFF\x8C\x07\xB6", 32}, |
84 | | { (unsigned char *) "\x04\x8B\xD2\xAE\xB9\xCB\x7E\x57\xCB\x2C\x4B\x48\x2F\xFC\x81\xB7\xAF\xB9\xDE\x27\xE1\xE3\xBD\x23\xC2\x3A\x44\x53\xBD\x9A\xCE\x32\x62\x54\x7E\xF8\x35\xC3\xDA\xC4\xFD\x97\xF8\x46\x1A\x14\x61\x1D\xC9\xC2\x77\x45\x13\x2D\xED\x8E\x54\x5C\x1D\x54\xC7\x2F\x04\x69\x97", 65}, |
85 | | { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x71\x8C\x39\x7A\xA3\xB5\x61\xA6\xF7\x90\x1E\x0E\x82\x97\x48\x56\xA7", 32}, |
86 | | { (unsigned char *) "\x00\x01", 2} |
87 | | }, |
88 | | |
89 | | { |
90 | | /* brainpoolP320r1 */ |
91 | | { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x09", 11}, |
92 | | { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA6\xF6\xF4\x0D\xEF\x4F\x92\xB9\xEC\x78\x93\xEC\x28\xFC\xD4\x12\xB1\xF1\xB3\x2E\x27", 40}, |
93 | | { (unsigned char *) "\x3E\xE3\x0B\x56\x8F\xBA\xB0\xF8\x83\xCC\xEB\xD4\x6D\x3F\x3B\xB8\xA2\xA7\x35\x13\xF5\xEB\x79\xDA\x66\x19\x0E\xB0\x85\xFF\xA9\xF4\x92\xF3\x75\xA9\x7D\x86\x0E\xB4", 40}, |
94 | | { (unsigned char *) "\x52\x08\x83\x94\x9D\xFD\xBC\x42\xD3\xAD\x19\x86\x40\x68\x8A\x6F\xE1\x3F\x41\x34\x95\x54\xB4\x9A\xCC\x31\xDC\xCD\x88\x45\x39\x81\x6F\x5E\xB4\xAC\x8F\xB1\xF1\xA6", 40}, |
95 | | { (unsigned char *) "\x04\x43\xBD\x7E\x9A\xFB\x53\xD8\xB8\x52\x89\xBC\xC4\x8E\xE5\xBF\xE6\xF2\x01\x37\xD1\x0A\x08\x7E\xB6\xE7\x87\x1E\x2A\x10\xA5\x99\xC7\x10\xAF\x8D\x0D\x39\xE2\x06\x11\x14\xFD\xD0\x55\x45\xEC\x1C\xC8\xAB\x40\x93\x24\x7F\x77\x27\x5E\x07\x43\xFF\xED\x11\x71\x82\xEA\xA9\xC7\x78\x77\xAA\xAC\x6A\xC7\xD3\x52\x45\xD1\x69\x2E\x8E\xE1", 81}, |
96 | | { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA5\xB6\x8F\x12\xA3\x2D\x48\x2E\xC7\xEE\x86\x58\xE9\x86\x91\x55\x5B\x44\xC5\x93\x11", 40}, |
97 | | { (unsigned char *) "\x00\x01", 2} |
98 | | }, |
99 | | |
100 | | { |
101 | | /* prime192v1, secp192r1, ansiX9p192r1 */ |
102 | | { (unsigned char *) "\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x01", 10}, |
103 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, |
104 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 24}, |
105 | | { (unsigned char *) "\x64\x21\x05\x19\xE5\x9C\x80\xE7\x0F\xA7\xE9\xAB\x72\x24\x30\x49\xFE\xB8\xDE\xEC\xC1\x46\xB9\xB1", 24}, |
106 | | { (unsigned char *) "\x04\x18\x8D\xA8\x0E\xB0\x30\x90\xF6\x7C\xBF\x20\xEB\x43\xA1\x88\x00\xF4\xFF\x0A\xFD\x82\xFF\x10\x12\x07\x19\x2B\x95\xFF\xC8\xDA\x78\x63\x10\x11\xED\x6B\x24\xCD\xD5\x73\xF9\x77\xA1\x1E\x79\x48\x11", 49}, |
107 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x99\xDE\xF8\x36\x14\x6B\xC9\xB1\xB4\xD2\x28\x31", 24}, |
108 | | { (unsigned char *) "\x00\x01", 2} |
109 | | }, |
110 | | |
111 | | { |
112 | | /* prime224v1, nistp224 */ |
113 | | { (unsigned char *) "\x06\x05\x2b\x81\x04\x00\x21", 7}, |
114 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 28}, |
115 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE", 28}, |
116 | | { (unsigned char *) "\xB4\x05\x0A\x85\x0C\x04\xB3\xAB\xF5\x41\x32\x56\x50\x44\xB0\xB7\xD7\xBF\xD8\xBA\x27\x0B\x39\x43\x23\x55\xFF\xB4", 28}, |
117 | | { (unsigned char *) "\x04\xB7\x0E\x0C\xBD\x6B\xB4\xBF\x7F\x32\x13\x90\xB9\x4A\x03\xC1\xD3\x56\xC2\x11\x22\x34\x32\x80\xD6\x11\x5C\x1D\x21\xBD\x37\x63\x88\xB5\xF7\x23\xFB\x4C\x22\xDF\xE6\xCD\x43\x75\xA0\x5A\x07\x47\x64\x44\xD5\x81\x99\x85\x00\x7E\x34", 57}, |
118 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\xA2\xE0\xB8\xF0\x3E\x13\xDD\x29\x45\x5C\x5C\x2A\x3D", 28}, |
119 | | { (unsigned char *) "\x00\x01", 2} |
120 | | }, |
121 | | |
122 | | { |
123 | | /* prime256v1, secp256r1, ansiX9p256r1 */ |
124 | | { (unsigned char *) "\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x07", 10}, |
125 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, |
126 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 32}, |
127 | | { (unsigned char *) "\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B", 32}, |
128 | | { (unsigned char *) "\x04\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5", 65}, |
129 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32}, |
130 | | { (unsigned char *) "\x00\x01", 2} |
131 | | }, |
132 | | |
133 | | { |
134 | | /* prime384v1, secp384r1, ansiX9p384r1 */ |
135 | | { (unsigned char *) "\x06\x05\x2B\x81\x04\x00\x22", 7}, |
136 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, |
137 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFC", 48}, |
138 | | { (unsigned char *) "\xB3\x31\x2F\xA7\xE2\x3E\xE7\xE4\x98\x8E\x05\x6B\xE3\xF8\x2D\x19\x18\x1D\x9C\x6E\xFE\x81\x41\x12\x03\x14\x08\x8F\x50\x13\x87\x5A\xC6\x56\x39\x8D\x8A\x2E\xD1\x9D\x2A\x85\xC8\xED\xD3\xEC\x2A\xEF", 48}, |
139 | | { (unsigned char *) "\x04\xAA\x87\xCA\x22\xBE\x8B\x05\x37\x8E\xB1\xC7\x1E\xF3\x20\xAD\x74\x6E\x1D\x3B\x62\x8B\xA7\x9B\x98\x59\xF7\x41\xE0\x82\x54\x2A\x38\x55\x02\xF2\x5D\xBF\x55\x29\x6C\x3A\x54\x5E\x38\x72\x76\x0A\xB7\x36\x17\xDE\x4A\x96\x26\x2C\x6F\x5D\x9E\x98\xBF\x92\x92\xDC\x29\xF8\xF4\x1D\xBD\x28\x9A\x14\x7C\xE9\xDA\x31\x13\xB5\xF0\xB8\xC0\x0A\x60\xB1\xCE\x1D\x7E\x81\x9D\x7A\x43\x1D\x7C\x90\xEA\x0E\x5F", 97}, |
140 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC7\x63\x4D\x81\xF4\x37\x2D\xDF\x58\x1A\x0D\xB2\x48\xB0\xA7\x7A\xEC\xEC\x19\x6A\xCC\xC5\x29\x73", 48}, |
141 | | { (unsigned char *) "\x00\x01", 2} |
142 | | }, |
143 | | |
144 | | { |
145 | | /* secp192k1 */ |
146 | | { (unsigned char *) "\x06\x05\x2B\x81\x04\x00\x1F", 7}, |
147 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, |
148 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24}, |
149 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", 24}, |
150 | | { (unsigned char *) "\x04\xDB\x4F\xF1\x0E\xC0\x57\xE9\xAE\x26\xB0\x7D\x02\x80\xB7\xF4\x34\x1D\xA5\xD1\xB1\xEA\xE0\x6C\x7D\x9B\x2F\x2F\x6D\x9C\x56\x28\xA7\x84\x41\x63\xD0\x15\xBE\x86\x34\x40\x82\xAA\x88\xD9\x5E\x2F\x9D", 49}, |
151 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\x26\xF2\xFC\x17\x0F\x69\x46\x6A\x74\xDE\xFD\x8D", 24}, |
152 | | { (unsigned char *) "\x00\x01", 2} |
153 | | }, |
154 | | |
155 | | { |
156 | | /* secp256k1 */ |
157 | | { (unsigned char *) "\x06\x05\x2B\x81\x04\x00\x0A", 7}, |
158 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, |
159 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32}, |
160 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07", 32}, |
161 | | { (unsigned char *) "\x04\x79\xBE\x66\x7E\xF9\xDC\xBB\xAC\x55\xA0\x62\x95\xCE\x87\x0B\x07\x02\x9B\xFC\xDB\x2D\xCE\x28\xD9\x59\xF2\x81\x5B\x16\xF8\x17\x98\x48\x3A\xDA\x77\x26\xA3\xC4\x65\x5D\xA4\xFB\xFC\x0E\x11\x08\xA8\xFD\x17\xB4\x48\xA6\x85\x54\x19\x9C\x47\xD0\x8F\xFB\x10\xD4\xB8", 65}, |
162 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xBA\xAE\xDC\xE6\xAF\x48\xA0\x3B\xBF\xD2\x5E\x8C\xD0\x36\x41\x41", 32}, |
163 | | { (unsigned char *) "\x00\x01", 2} |
164 | | }, |
165 | | |
166 | | { |
167 | | { NULL, 0}, |
168 | | { NULL, 0}, |
169 | | { NULL, 0}, |
170 | | { NULL, 0}, |
171 | | { NULL, 0}, |
172 | | { NULL, 0}, |
173 | | { NULL, 0} |
174 | | } |
175 | | }; |
176 | | |
177 | | |
178 | | /* |
179 | | * Create DF, using default pkcs15init functions. |
180 | | */ |
181 | | static int |
182 | | isoApplet_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) |
183 | 0 | { |
184 | 0 | sc_card_t *card = p15card->card; |
185 | 0 | int r = SC_SUCCESS; |
186 | |
|
187 | 0 | LOG_FUNC_CALLED(card->ctx); |
188 | |
|
189 | 0 | if(!profile || !df || !p15card->card->ctx) |
190 | 0 | { |
191 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); |
192 | 0 | } |
193 | 0 | r = sc_pkcs15init_create_file(profile, p15card, df); |
194 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
195 | 0 | } |
196 | | |
197 | | /* |
198 | | * Select a PIN reference. |
199 | | * |
200 | | * Basically (as I understand it) the caller passes an auth_info object and the |
201 | | * auth_info->attrs.pin.reference is supposed to be set accordingly and return. |
202 | | * |
203 | | * The IsoApplet only supports a PIN and a PUK at the moment. |
204 | | * The reference for the PIN is 1, for the PUK 2. |
205 | | */ |
206 | | static int |
207 | | isoApplet_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
208 | | sc_pkcs15_auth_info_t *auth_info) |
209 | 0 | { |
210 | 0 | sc_card_t *card = p15card->card; |
211 | 0 | int preferred; |
212 | 0 | int current; |
213 | |
|
214 | 0 | LOG_FUNC_CALLED(card->ctx); |
215 | |
|
216 | 0 | if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
217 | 0 | { |
218 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OBJECT_NOT_VALID); |
219 | 0 | } |
220 | | |
221 | 0 | current = auth_info->attrs.pin.reference; |
222 | 0 | if (current < 0) |
223 | 0 | { |
224 | 0 | current = 0; |
225 | 0 | } |
226 | |
|
227 | 0 | if(current > 2) |
228 | 0 | { |
229 | | /* Only two PINs supported: User PIN and PUK. */ |
230 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_TOO_MANY_OBJECTS); |
231 | 0 | } |
232 | 0 | else |
233 | 0 | { |
234 | 0 | if(auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) |
235 | 0 | { |
236 | | /* PUK */ |
237 | 0 | preferred = 2; |
238 | 0 | } |
239 | 0 | else |
240 | 0 | { |
241 | | /* PIN */ |
242 | 0 | preferred = 1; |
243 | 0 | } |
244 | 0 | } |
245 | | |
246 | 0 | auth_info->attrs.pin.reference = preferred; |
247 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
248 | 0 | } |
249 | | |
250 | | /* |
251 | | * Create a PIN and store it on the card using CHANGE REFERENCE DATA for PIN transmission. |
252 | | * First, the PUK is transmitted, then the PIN. Now, the IsoApplet is in the |
253 | | * "STATE_OPERATIONAL_ACTIVATED" lifecycle state. |
254 | | */ |
255 | | static int |
256 | | isoApplet_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df, |
257 | | sc_pkcs15_object_t *pin_obj, |
258 | | const u8 *pin, size_t pin_len, |
259 | | const u8 *puk, size_t puk_len) |
260 | 0 | { |
261 | 0 | sc_card_t *card = p15card->card; |
262 | 0 | sc_pkcs15_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data; |
263 | 0 | struct sc_pkcs15_pin_attributes *pin_attrs = &auth_info->attrs.pin; |
264 | 0 | int r; |
265 | |
|
266 | 0 | LOG_FUNC_CALLED(card->ctx); |
267 | |
|
268 | 0 | if(!pin || !pin_len || !df) |
269 | 0 | { |
270 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); |
271 | 0 | } |
272 | | |
273 | 0 | if(pin_attrs->reference != 1 && pin_attrs->reference != 2) |
274 | 0 | { |
275 | | /* Reject PIN reference. */ |
276 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE); |
277 | 0 | } |
278 | | |
279 | | /* If we have a PUK, set it first. */ |
280 | 0 | if(puk && puk_len) |
281 | 0 | { |
282 | | /* The PUK has a incremented reference, i.e. pins are odd, puks are equal (+1). */ |
283 | 0 | r = sc_change_reference_data(p15card->card, SC_AC_CHV, |
284 | 0 | pin_attrs->reference+1, |
285 | 0 | NULL, 0, |
286 | 0 | puk, puk_len, NULL); |
287 | 0 | if(r < 0) |
288 | 0 | { |
289 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
290 | 0 | } |
291 | 0 | } |
292 | | |
293 | | /* Store PIN: (use CHANGE REFERENCE DATA). */ |
294 | 0 | r = sc_change_reference_data(p15card->card, SC_AC_CHV, |
295 | 0 | pin_attrs->reference, |
296 | 0 | NULL, 0, |
297 | 0 | pin, pin_len, NULL); |
298 | 0 | LOG_TEST_RET(card->ctx, r, "Failed to set PIN"); |
299 | | |
300 | 0 | sc_pkcs15_pincache_add(p15card, pin_obj, pin, pin_len); |
301 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
302 | 0 | } |
303 | | |
304 | | /* |
305 | | * @brief Get the curve parameters associated with the curve specified by an OID. |
306 | | * |
307 | | * @param[in] oid The DER encoded OID of the curve. |
308 | | * @param[in] oid_len The length of oid. |
309 | | * @param[out] curve_out The ec_curve containing the set of parameters. |
310 | | * |
311 | | * @returns SC_SUCCESS: If the curve was found. |
312 | | * SC_ERROR_INVALID_ARGUMENTS: If named_curve was null or the curve |
313 | | * was not found |
314 | | */ |
315 | | static int |
316 | | isoApplet_get_curve(u8 *oid, size_t oid_len, const struct ec_curve **curve_out) |
317 | 0 | { |
318 | 0 | int i; |
319 | |
|
320 | 0 | if(!oid) |
321 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
322 | | |
323 | | /* Search the curve parameters. */ |
324 | 0 | for (i = 0; curves[i].oid.value; i++) |
325 | 0 | { |
326 | 0 | if (oid_len == curves[i].oid.len && memcmp(oid, curves[i].oid.value, curves[i].oid.len) == 0) |
327 | 0 | { |
328 | 0 | *curve_out = &curves[i]; |
329 | 0 | return SC_SUCCESS; |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
334 | 0 | } |
335 | | |
336 | | |
337 | | /* |
338 | | * @brief Generate a RSA private key on the card. |
339 | | * |
340 | | * A MANAGE SECURITY ENVIRONMENT apdu must have been sent before. |
341 | | * This function uses card_ctl to access the card-isoApplet driver. |
342 | | * |
343 | | * @param[in] key_info |
344 | | * @param[in] card |
345 | | * @param[in] pubkey The public key of the generated key pair |
346 | | * returned by the card. |
347 | | * |
348 | | * @return SC_ERROR_INVALID_ARGUMENTS: Invalid key length. |
349 | | * SC_ERROR_OUT_OF_MEMORY |
350 | | */ |
351 | | static int |
352 | | isoApplet_generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, |
353 | | sc_pkcs15_pubkey_t *pubkey) |
354 | 0 | { |
355 | 0 | int rv; |
356 | 0 | size_t keybits; |
357 | 0 | struct sc_cardctl_isoApplet_genkey args; |
358 | |
|
359 | 0 | LOG_FUNC_CALLED(card->ctx); |
360 | |
|
361 | 0 | memset(&args, 0, sizeof(args)); |
362 | | |
363 | | /* Check key size: */ |
364 | 0 | keybits = key_info->modulus_length; |
365 | 0 | if (keybits != 2048 && keybits != 4096) |
366 | 0 | { |
367 | 0 | rv = SC_ERROR_INVALID_ARGUMENTS; |
368 | 0 | sc_log(card->ctx, "%s: RSA private key length is unsupported, correct length is 2048 or 4096", sc_strerror(rv)); |
369 | 0 | goto err; |
370 | 0 | } |
371 | | |
372 | | /* Generate the key. |
373 | | * Note: key size is not explicitly passed to the card. |
374 | | * Its derived from the algorithm reference. */ |
375 | 0 | args.algorithm_ref = keybits == 2048 ? SC_ISOAPPLET_ALG_REF_RSA_GEN_2048 : SC_ISOAPPLET_ALG_REF_RSA_GEN_4096; |
376 | 0 | args.priv_key_ref = key_info->key_reference; |
377 | |
|
378 | 0 | args.pubkey.rsa.modulus.len = keybits / 8; |
379 | 0 | args.pubkey.rsa.modulus.value = malloc(args.pubkey.rsa.modulus.len); |
380 | 0 | if (!args.pubkey.rsa.modulus.value) |
381 | 0 | { |
382 | 0 | rv = SC_ERROR_OUT_OF_MEMORY; |
383 | 0 | sc_log(card->ctx, "%s: Unable to allocate public key buffer.", sc_strerror(rv)); |
384 | 0 | goto err; |
385 | 0 | } |
386 | | |
387 | 0 | args.pubkey.rsa.exponent.len = 3; |
388 | 0 | args.pubkey.rsa.exponent.value = malloc(args.pubkey.rsa.exponent.len); |
389 | 0 | if(!args.pubkey.rsa.exponent.value) |
390 | 0 | { |
391 | 0 | rv = SC_ERROR_OUT_OF_MEMORY; |
392 | 0 | sc_log(card->ctx, "%s: Unable to allocate public key exponent buffer.", sc_strerror(rv)); |
393 | 0 | goto err; |
394 | 0 | } |
395 | | |
396 | 0 | rv = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_GENERATE_KEY, &args); |
397 | 0 | if (rv < 0) |
398 | 0 | { |
399 | 0 | sc_log(card->ctx, "%s: Error in card_ctl", sc_strerror(rv)); |
400 | 0 | goto err; |
401 | 0 | } |
402 | | |
403 | | /* extract the public key */ |
404 | 0 | pubkey->algorithm = SC_ALGORITHM_RSA; |
405 | 0 | pubkey->u.rsa.modulus.len = args.pubkey.rsa.modulus.len; |
406 | 0 | pubkey->u.rsa.modulus.data = args.pubkey.rsa.modulus.value; |
407 | 0 | pubkey->u.rsa.exponent.len = args.pubkey.rsa.exponent.len; |
408 | 0 | pubkey->u.rsa.exponent.data = args.pubkey.rsa.exponent.value; |
409 | 0 | rv = SC_SUCCESS; |
410 | 0 | LOG_FUNC_RETURN(card->ctx, rv); |
411 | 0 | err: |
412 | 0 | if (args.pubkey.rsa.modulus.value) |
413 | 0 | { |
414 | 0 | free(args.pubkey.rsa.modulus.value); |
415 | 0 | pubkey->u.rsa.modulus.data = NULL; |
416 | 0 | pubkey->u.rsa.modulus.len = 0; |
417 | 0 | } |
418 | 0 | if (args.pubkey.rsa.exponent.value) |
419 | 0 | { |
420 | 0 | free(args.pubkey.rsa.exponent.value); |
421 | 0 | pubkey->u.rsa.exponent.data = NULL; |
422 | 0 | pubkey->u.rsa.exponent.len = 0; |
423 | 0 | } |
424 | 0 | LOG_FUNC_RETURN(card->ctx, rv); |
425 | 0 | } |
426 | | |
427 | | /* |
428 | | * @brief Generate a EC private key on the card. |
429 | | * |
430 | | * A MANAGE SECURITY ENVIRONMENT apdu must have been sent before. |
431 | | * This function uses card_ctl to access the card-isoApplet driver. |
432 | | * |
433 | | * @param[in] key_info |
434 | | * @param[in] card |
435 | | * @param[in/out] pubkey The public key of the generated key pair |
436 | | * returned by the card. |
437 | | * |
438 | | * @return SC_ERROR_INVALID_ARGUMENTS: Invalid key length or curve. |
439 | | * SC_ERROR_OUT_OF_MEMORY |
440 | | * SC_ERROR_INCOMPATIBLE_KEY: The data returned by the card |
441 | | * was unexpected and can not be |
442 | | * handled. |
443 | | */ |
444 | | static int |
445 | | isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, |
446 | | sc_pkcs15_pubkey_t *pubkey) |
447 | 0 | { |
448 | 0 | int r; |
449 | 0 | const struct ec_curve *curve = NULL; |
450 | 0 | struct sc_ec_parameters *alg_id_params = NULL; |
451 | 0 | sc_cardctl_isoApplet_genkey_t args; |
452 | 0 | const struct sc_ec_parameters *info_ecp = |
453 | 0 | (struct sc_ec_parameters *) key_info->params.data; |
454 | |
|
455 | 0 | LOG_FUNC_CALLED(card->ctx); |
456 | |
|
457 | 0 | memset(&args, 0, sizeof(args)); |
458 | | |
459 | | /* Check key size: */ |
460 | 0 | if(key_info->field_length == 0) |
461 | 0 | { |
462 | 0 | sc_log(card->ctx, "Unknown field length."); |
463 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
464 | 0 | goto out; |
465 | 0 | } |
466 | | |
467 | 0 | r = isoApplet_get_curve(info_ecp->der.value, info_ecp->der.len, &curve); |
468 | 0 | if(r < 0) |
469 | 0 | { |
470 | 0 | sc_log(card->ctx, "EC key generation failed: Unsupported curve: [%s].", info_ecp->named_curve); |
471 | 0 | goto out; |
472 | 0 | } |
473 | | |
474 | | /* Generate the key. |
475 | | * Note: The field size is not explicitly passed to the card. |
476 | | * As we only support FP curves, the field length can be calculated from any parameter. */ |
477 | 0 | args.pubkey.ec.params.prime.value = curve->prime.value; |
478 | 0 | args.pubkey.ec.params.prime.len = curve->prime.len; |
479 | 0 | args.pubkey.ec.params.coefficientA.value = curve->coefficientA.value; |
480 | 0 | args.pubkey.ec.params.coefficientA.len = curve->coefficientA.len; |
481 | 0 | args.pubkey.ec.params.coefficientB.value = curve->coefficientB.value; |
482 | 0 | args.pubkey.ec.params.coefficientB.len = curve->coefficientB.len; |
483 | 0 | args.pubkey.ec.params.basePointG.value = curve->basePointG.value; |
484 | 0 | args.pubkey.ec.params.basePointG.len = curve->basePointG.len; |
485 | 0 | args.pubkey.ec.params.order.value = curve->order.value; |
486 | 0 | args.pubkey.ec.params.order.len = curve->order.len; |
487 | 0 | args.pubkey.ec.params.coFactor.value = curve->coFactor.value; |
488 | 0 | args.pubkey.ec.params.coFactor.len = curve->coFactor.len; |
489 | | /* The length of the public key point will be: |
490 | | * Uncompressed tag + 2 * field length in bytes. */ |
491 | 0 | args.pubkey.ec.ecPointQ.len = 1 + BYTES4BITS(key_info->field_length) * 2; |
492 | 0 | args.pubkey.ec.ecPointQ.value = malloc(args.pubkey.ec.ecPointQ.len); |
493 | 0 | if(!args.pubkey.ec.ecPointQ.value) |
494 | 0 | { |
495 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
496 | 0 | goto out; |
497 | 0 | } |
498 | | |
499 | 0 | args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN; |
500 | 0 | args.priv_key_ref = key_info->key_reference; |
501 | | |
502 | | /* On-card key generation */ |
503 | 0 | r = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_GENERATE_KEY, &args); |
504 | 0 | if (r < 0) |
505 | 0 | { |
506 | 0 | sc_log(card->ctx, "%s: Error in card_ctl.", sc_strerror(r)); |
507 | 0 | goto out; |
508 | 0 | } |
509 | | |
510 | | /* Extract and compose the public key. */ |
511 | 0 | pubkey->algorithm = SC_ALGORITHM_EC; |
512 | | |
513 | | /* der-encoded parameters */ |
514 | 0 | alg_id_params = calloc(1, sizeof(*alg_id_params)); |
515 | 0 | if(!alg_id_params) |
516 | 0 | { |
517 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
518 | 0 | goto out; |
519 | 0 | } |
520 | 0 | alg_id_params->der.len = curve->oid.len; |
521 | 0 | alg_id_params->der.value = malloc(alg_id_params->der.len); |
522 | 0 | if(!alg_id_params->der.value) |
523 | 0 | { |
524 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
525 | 0 | goto out; |
526 | 0 | } |
527 | 0 | memcpy(alg_id_params->der.value, curve->oid.value, curve->oid.len); |
528 | 0 | alg_id_params->type = 1; /* named curve */ |
529 | |
|
530 | 0 | pubkey->alg_id = malloc(sizeof(*pubkey->alg_id)); |
531 | 0 | if(!pubkey->alg_id) |
532 | 0 | { |
533 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
534 | 0 | goto out; |
535 | 0 | } |
536 | 0 | pubkey->alg_id->algorithm = SC_ALGORITHM_EC; |
537 | 0 | sc_init_oid(&pubkey->alg_id->oid); |
538 | 0 | pubkey->alg_id->params = alg_id_params; |
539 | | |
540 | | /* Extract ecpointQ */ |
541 | 0 | pubkey->u.ec.ecpointQ.len = args.pubkey.ec.ecPointQ.len; |
542 | 0 | pubkey->u.ec.ecpointQ.value = malloc(pubkey->u.ec.ecpointQ.len); |
543 | 0 | if(!pubkey->u.ec.ecpointQ.value) |
544 | 0 | { |
545 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
546 | 0 | goto out; |
547 | 0 | } |
548 | 0 | memcpy(pubkey->u.ec.ecpointQ.value, args.pubkey.ec.ecPointQ.value, args.pubkey.ec.ecPointQ.len); |
549 | | |
550 | | /* The OID is also written to the pubkey->u.ec.params */ |
551 | 0 | free(pubkey->u.ec.params.der.value); |
552 | 0 | pubkey->u.ec.params.der.value = malloc(alg_id_params->der.len); |
553 | 0 | if(!pubkey->u.ec.params.der.value) |
554 | 0 | { |
555 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
556 | 0 | goto out; |
557 | 0 | } |
558 | 0 | memcpy(pubkey->u.ec.params.der.value, alg_id_params->der.value, alg_id_params->der.len); |
559 | 0 | pubkey->u.ec.params.der.len = alg_id_params->der.len; |
560 | 0 | r = sc_pkcs15_fix_ec_parameters(card->ctx, &pubkey->u.ec.params); |
561 | 0 | out: |
562 | 0 | if(args.pubkey.ec.ecPointQ.value) |
563 | 0 | { |
564 | 0 | free(args.pubkey.ec.ecPointQ.value); |
565 | 0 | args.pubkey.ec.ecPointQ.value = NULL; |
566 | 0 | } |
567 | 0 | if(r < 0 && pubkey) |
568 | 0 | { |
569 | 0 | if(pubkey->alg_id) |
570 | 0 | { |
571 | 0 | free(pubkey->alg_id); |
572 | 0 | pubkey->alg_id = NULL; |
573 | 0 | } |
574 | 0 | if(pubkey->u.ec.params.der.value) |
575 | 0 | { |
576 | 0 | free(pubkey->u.ec.params.der.value); |
577 | 0 | pubkey->u.ec.params.der.value = NULL; |
578 | 0 | pubkey->u.ec.params.der.len = 0; |
579 | 0 | } |
580 | 0 | if(pubkey->u.ec.params.named_curve) |
581 | 0 | { |
582 | 0 | free(pubkey->u.ec.params.named_curve); |
583 | 0 | pubkey->u.ec.params.named_curve = NULL; |
584 | 0 | } |
585 | 0 | if(pubkey->u.ec.ecpointQ.value) |
586 | 0 | { |
587 | 0 | free(pubkey->u.ec.ecpointQ.value); |
588 | 0 | pubkey->u.ec.ecpointQ.value = NULL; |
589 | 0 | pubkey->u.ec.ecpointQ.len = 0; |
590 | 0 | } |
591 | 0 | memset(pubkey, 0, sizeof(sc_pkcs15_pubkey_t)); |
592 | 0 | } |
593 | 0 | if(r < 0 && alg_id_params) |
594 | 0 | { |
595 | 0 | if(alg_id_params->der.value) |
596 | 0 | { |
597 | 0 | free(alg_id_params->der.value); |
598 | 0 | alg_id_params->der.value = NULL; |
599 | 0 | } |
600 | 0 | free(alg_id_params); |
601 | 0 | pubkey->alg_id->params = NULL; |
602 | 0 | } |
603 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
604 | 0 | } |
605 | | |
606 | | static int |
607 | | isoApplet_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
608 | | sc_pkcs15_object_t *obj, |
609 | | sc_pkcs15_pubkey_t *pubkey) |
610 | 0 | { |
611 | 0 | int r; |
612 | 0 | sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; |
613 | 0 | sc_file_t *privKeyFile=NULL; |
614 | 0 | sc_card_t *card = p15card->card; |
615 | |
|
616 | 0 | LOG_FUNC_CALLED(card->ctx); |
617 | | |
618 | | /* Authentication stuff. */ |
619 | 0 | r = sc_profile_get_file_by_path(profile, &key_info->path, &privKeyFile); |
620 | 0 | if(r < 0 || !privKeyFile) |
621 | 0 | { |
622 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); |
623 | 0 | } |
624 | 0 | r = sc_pkcs15init_authenticate(profile, p15card, privKeyFile, SC_AC_OP_CREATE_EF); |
625 | 0 | if(r < 0) |
626 | 0 | { |
627 | 0 | sc_file_free(privKeyFile); |
628 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); |
629 | 0 | } |
630 | 0 | sc_file_free(privKeyFile); |
631 | | |
632 | | /* Generate the key. */ |
633 | 0 | switch(obj->type) |
634 | 0 | { |
635 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
636 | 0 | r = isoApplet_generate_key_rsa(key_info, card, pubkey); |
637 | 0 | break; |
638 | | |
639 | 0 | case SC_PKCS15_TYPE_PRKEY_EC: |
640 | 0 | r = isoApplet_generate_key_ec(key_info, card, pubkey); |
641 | 0 | break; |
642 | | |
643 | 0 | default: |
644 | 0 | r = SC_ERROR_NOT_SUPPORTED; |
645 | 0 | sc_log(card->ctx, "%s: Key generation failed: Unknown/unsupported key type.", strerror(r)); |
646 | 0 | } |
647 | | |
648 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
649 | 0 | } |
650 | | |
651 | | |
652 | | /* |
653 | | * Create a new key file. This is a no-op, because private keys are stored as key objects on the javacard. |
654 | | */ |
655 | | static int |
656 | | isoApplet_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj) |
657 | 0 | { |
658 | 0 | sc_card_t *card = p15card->card; |
659 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
660 | 0 | } |
661 | | |
662 | | /* |
663 | | * Select a key reference. |
664 | | */ |
665 | | static int |
666 | | isoApplet_select_key_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
667 | | sc_pkcs15_prkey_info_t *key_info) |
668 | 0 | { |
669 | 0 | int rv = SC_SUCCESS; |
670 | 0 | sc_card_t *card = p15card->card; |
671 | |
|
672 | 0 | LOG_FUNC_CALLED(card->ctx); |
673 | |
|
674 | 0 | if(key_info->key_reference < ISOAPPLET_KEY_ID_MIN) |
675 | 0 | { |
676 | 0 | key_info->key_reference = ISOAPPLET_KEY_ID_MIN; |
677 | 0 | rv = SC_SUCCESS; |
678 | 0 | } |
679 | 0 | if(key_info->key_reference > ISOAPPLET_KEY_ID_MAX) |
680 | 0 | { |
681 | 0 | rv = SC_ERROR_TOO_MANY_OBJECTS; |
682 | 0 | } |
683 | 0 | LOG_FUNC_RETURN(card->ctx, rv); |
684 | 0 | } |
685 | | |
686 | | /* |
687 | | * Store a usable private key on the card. |
688 | | */ |
689 | | static int |
690 | | isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *object, |
691 | | sc_pkcs15_prkey_t *key) |
692 | 0 | { |
693 | 0 | sc_card_t *card = p15card->card; |
694 | 0 | sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) object->data; |
695 | 0 | sc_file_t *privKeyFile=NULL; |
696 | 0 | sc_cardctl_isoApplet_import_key_t args; |
697 | 0 | int r; |
698 | |
|
699 | 0 | LOG_FUNC_CALLED(card->ctx); |
700 | | |
701 | | /* Authentication stuff. */ |
702 | 0 | r = sc_profile_get_file_by_path(profile, &key_info->path, &privKeyFile); |
703 | 0 | if(r < 0 || !privKeyFile) |
704 | 0 | { |
705 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); |
706 | 0 | } |
707 | 0 | r = sc_pkcs15init_authenticate(profile, p15card, privKeyFile, SC_AC_OP_CREATE_EF); |
708 | 0 | if(r < 0) |
709 | 0 | { |
710 | 0 | sc_file_free(privKeyFile); |
711 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); |
712 | 0 | } |
713 | 0 | sc_file_free(privKeyFile); |
714 | | |
715 | | /* Key import. */ |
716 | 0 | switch(object->type) |
717 | 0 | { |
718 | 0 | case SC_PKCS15_TYPE_PRKEY_RSA: |
719 | 0 | args.algorithm_ref = SC_ISOAPPLET_ALG_REF_RSA_GEN_2048; |
720 | 0 | if(!key->u.rsa.p.data |
721 | 0 | ||!key->u.rsa.q.data |
722 | 0 | ||!key->u.rsa.iqmp.data |
723 | 0 | ||!key->u.rsa.dmp1.data |
724 | 0 | ||!key->u.rsa.dmq1.data) |
725 | 0 | { |
726 | 0 | LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Only CRT RSA keys may be imported."); |
727 | 0 | } |
728 | 0 | args.privkey.rsa.p.value = key->u.rsa.p.data; |
729 | 0 | args.privkey.rsa.p.len = key->u.rsa.p.len; |
730 | 0 | args.privkey.rsa.q.value = key->u.rsa.q.data; |
731 | 0 | args.privkey.rsa.q.len = key->u.rsa.q.len; |
732 | 0 | args.privkey.rsa.iqmp.value = key->u.rsa.iqmp.data; |
733 | 0 | args.privkey.rsa.iqmp.len = key->u.rsa.iqmp.len; |
734 | 0 | args.privkey.rsa.dmp1.value = key->u.rsa.dmp1.data; |
735 | 0 | args.privkey.rsa.dmp1.len = key->u.rsa.dmp1.len; |
736 | 0 | args.privkey.rsa.dmq1.value = key->u.rsa.dmq1.data; |
737 | 0 | args.privkey.rsa.dmq1.len = key->u.rsa.dmq1.len; |
738 | 0 | break; |
739 | | |
740 | 0 | case SC_PKCS15_TYPE_PRKEY_EC: |
741 | 0 | { |
742 | 0 | const struct ec_curve *curve = NULL; |
743 | |
|
744 | 0 | args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN; |
745 | 0 | if(key->u.ec.params.der.len == 0 || key->u.ec.params.der.value == NULL) { |
746 | 0 | r = sc_pkcs15_fix_ec_parameters(card->ctx, &key->u.ec.params); |
747 | 0 | LOG_TEST_RET(card->ctx, r, "EC key storing failed: Unknown curve."); |
748 | 0 | } |
749 | 0 | r = isoApplet_get_curve(key->u.ec.params.der.value, key->u.ec.params.der.len, &curve); |
750 | 0 | LOG_TEST_RET(card->ctx, r, "EC key generation failed: Unsupported curve"); |
751 | 0 | args.privkey.ec.params.prime.value = curve->prime.value; |
752 | 0 | args.privkey.ec.params.prime.len = curve->prime.len; |
753 | 0 | args.privkey.ec.params.coefficientA.value = curve->coefficientA.value; |
754 | 0 | args.privkey.ec.params.coefficientA.len = curve->coefficientA.len; |
755 | 0 | args.privkey.ec.params.coefficientB.value = curve->coefficientB.value; |
756 | 0 | args.privkey.ec.params.coefficientB.len = curve->coefficientB.len; |
757 | 0 | args.privkey.ec.params.basePointG.value = curve->basePointG.value; |
758 | 0 | args.privkey.ec.params.basePointG.len = curve->basePointG.len; |
759 | 0 | args.privkey.ec.params.order.value = curve->order.value; |
760 | 0 | args.privkey.ec.params.order.len = curve->order.len; |
761 | 0 | args.privkey.ec.params.coFactor.value = curve->coFactor.value; |
762 | 0 | args.privkey.ec.params.coFactor.len = curve->coFactor.len; |
763 | 0 | args.privkey.ec.privateD.value = key->u.ec.privateD.data; |
764 | 0 | args.privkey.ec.privateD.len = key->u.ec.privateD.len; |
765 | 0 | } |
766 | 0 | break; |
767 | | |
768 | 0 | default: |
769 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); |
770 | 0 | } |
771 | 0 | args.priv_key_ref = key_info->key_reference; |
772 | |
|
773 | 0 | r = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_IMPORT_KEY, &args); |
774 | 0 | if (r < 0) |
775 | 0 | { |
776 | 0 | sc_log(card->ctx, "%s: Error in card_ctl", sc_strerror(r)); |
777 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
778 | 0 | } |
779 | | |
780 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
781 | 0 | } |
782 | | |
783 | | static struct sc_pkcs15init_operations sc_pkcs15init_isoApplet_operations = |
784 | | { |
785 | | NULL, /* erase_card */ |
786 | | NULL, /* init_card */ |
787 | | isoApplet_create_dir, /* create_dir */ |
788 | | NULL, /* create_domain */ |
789 | | isoApplet_select_pin_reference, /* pin_reference*/ |
790 | | isoApplet_create_pin, /* create_pin */ |
791 | | isoApplet_select_key_reference, /* key_reference */ |
792 | | isoApplet_create_key, /* create_key */ |
793 | | isoApplet_store_key, /* store_key */ |
794 | | isoApplet_generate_key, /* generate_key */ |
795 | | NULL, NULL, /* encode private/public key */ |
796 | | NULL, /* finalize */ |
797 | | NULL, /* delete_object */ |
798 | | NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ |
799 | | NULL, /* sanity_check*/ |
800 | | }; |
801 | | |
802 | | struct |
803 | | sc_pkcs15init_operations *sc_pkcs15init_get_isoApplet_ops(void) |
804 | 0 | { |
805 | 0 | return &sc_pkcs15init_isoApplet_operations; |
806 | 0 | } |