| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | #ifdef HAVE_CONFIG_H |
|---|
| 26 | #include <config.h> |
|---|
| 27 | #endif |
|---|
| 28 | |
|---|
| 29 | #include <opensc/pkcs15.h> |
|---|
| 30 | #include <opensc/log.h> |
|---|
| 31 | #include <stdlib.h> |
|---|
| 32 | #include <string.h> |
|---|
| 33 | #include <stdio.h> |
|---|
| 34 | #include <compat_strlcpy.h> |
|---|
| 35 | |
|---|
| 36 | #ifdef ENABLE_ZLIB |
|---|
| 37 | #include <zlib.h> |
|---|
| 38 | #endif |
|---|
| 39 | |
|---|
| 40 | int sc_pkcs15emu_actalis_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *); |
|---|
| 41 | |
|---|
| 42 | static int (*set_security_env) (sc_card_t *, const sc_security_env_t *, int); |
|---|
| 43 | |
|---|
| 44 | static int set_sec_env(sc_card_t * card, const sc_security_env_t *env, |
|---|
| 45 | int se_num) |
|---|
| 46 | { |
|---|
| 47 | int r; |
|---|
| 48 | sc_security_env_t tenv = *env; |
|---|
| 49 | if (tenv.operation == SC_SEC_OPERATION_SIGN) |
|---|
| 50 | tenv.operation = SC_SEC_OPERATION_DECIPHER; |
|---|
| 51 | |
|---|
| 52 | if ((r = |
|---|
| 53 | card->ops->restore_security_env(card, 0x40)) == SC_SUCCESS) |
|---|
| 54 | return set_security_env(card, &tenv, se_num); |
|---|
| 55 | else |
|---|
| 56 | return r; |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | static int do_sign(sc_card_t * card, const u8 * in, size_t inlen, u8 * out, |
|---|
| 60 | size_t outlen) |
|---|
| 61 | { |
|---|
| 62 | return card->ops->decipher(card, in, inlen, out, outlen); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | static void set_string(char **strp, const char *value) |
|---|
| 66 | { |
|---|
| 67 | if (*strp) |
|---|
| 68 | free(*strp); |
|---|
| 69 | *strp = value ? strdup(value) : NULL; |
|---|
| 70 | } |
|---|
| 71 | |
|---|
| 72 | #if 1 |
|---|
| 73 | |
|---|
| 74 | |
|---|
| 75 | static int sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card, |
|---|
| 76 | const sc_pkcs15_id_t *id, const char *label, |
|---|
| 77 | const sc_path_t *path, int ref, int type, |
|---|
| 78 | unsigned int min_length, |
|---|
| 79 | unsigned int max_length, |
|---|
| 80 | int flags, int tries_left, const char pad_char, int obj_flags) |
|---|
| 81 | { |
|---|
| 82 | sc_pkcs15_pin_info_t info; |
|---|
| 83 | sc_pkcs15_object_t obj; |
|---|
| 84 | |
|---|
| 85 | memset(&info, 0, sizeof(info)); |
|---|
| 86 | memset(&obj, 0, sizeof(obj)); |
|---|
| 87 | |
|---|
| 88 | info.auth_id = *id; |
|---|
| 89 | info.min_length = min_length; |
|---|
| 90 | info.max_length = max_length; |
|---|
| 91 | info.stored_length = max_length; |
|---|
| 92 | info.type = type; |
|---|
| 93 | info.reference = ref; |
|---|
| 94 | info.flags = flags; |
|---|
| 95 | info.tries_left = tries_left; |
|---|
| 96 | info.magic = SC_PKCS15_PIN_MAGIC; |
|---|
| 97 | info.pad_char = pad_char; |
|---|
| 98 | |
|---|
| 99 | if (path) |
|---|
| 100 | info.path = *path; |
|---|
| 101 | if (type == SC_PKCS15_PIN_TYPE_BCD) |
|---|
| 102 | info.stored_length /= 2; |
|---|
| 103 | |
|---|
| 104 | strlcpy(obj.label, label, sizeof(obj.label)); |
|---|
| 105 | obj.flags = obj_flags; |
|---|
| 106 | |
|---|
| 107 | return sc_pkcs15emu_add_pin_obj(p15card, &obj, &info); |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | static int sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, |
|---|
| 111 | const sc_pkcs15_id_t *id, |
|---|
| 112 | const char *label, |
|---|
| 113 | int type, unsigned int modulus_length, int usage, |
|---|
| 114 | const sc_path_t *path, int ref, |
|---|
| 115 | const sc_pkcs15_id_t *auth_id, int obj_flags) |
|---|
| 116 | { |
|---|
| 117 | sc_pkcs15_prkey_info_t info; |
|---|
| 118 | sc_pkcs15_object_t obj; |
|---|
| 119 | |
|---|
| 120 | memset(&info, 0, sizeof(info)); |
|---|
| 121 | memset(&obj, 0, sizeof(obj)); |
|---|
| 122 | |
|---|
| 123 | info.id = *id; |
|---|
| 124 | info.modulus_length = modulus_length; |
|---|
| 125 | info.usage = usage; |
|---|
| 126 | info.native = 1; |
|---|
| 127 | info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE |
|---|
| 128 | | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE |
|---|
| 129 | | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE |
|---|
| 130 | | SC_PKCS15_PRKEY_ACCESS_LOCAL; |
|---|
| 131 | info.key_reference = ref; |
|---|
| 132 | |
|---|
| 133 | if (path) |
|---|
| 134 | info.path = *path; |
|---|
| 135 | |
|---|
| 136 | obj.flags = obj_flags; |
|---|
| 137 | strlcpy(obj.label, label, sizeof(obj.label)); |
|---|
| 138 | if (auth_id != NULL) |
|---|
| 139 | obj.auth_id = *auth_id; |
|---|
| 140 | |
|---|
| 141 | return sc_pkcs15emu_add_rsa_prkey(p15card, &obj, &info); |
|---|
| 142 | } |
|---|
| 143 | #endif |
|---|
| 144 | |
|---|
| 145 | static int sc_pkcs15emu_actalis_init(sc_pkcs15_card_t * p15card) |
|---|
| 146 | { |
|---|
| 147 | sc_card_t *card = p15card->card; |
|---|
| 148 | sc_path_t path; |
|---|
| 149 | sc_pkcs15_id_t id, auth_id; |
|---|
| 150 | unsigned char serial[9]; |
|---|
| 151 | int flags; |
|---|
| 152 | int r; |
|---|
| 153 | |
|---|
| 154 | #ifdef ENABLE_ZLIB |
|---|
| 155 | int i; |
|---|
| 156 | const char *certLabel[] = { |
|---|
| 157 | "User Non-repudiation Certificate", |
|---|
| 158 | "TSCA Certificate", |
|---|
| 159 | "CA Certificate" |
|---|
| 160 | }; |
|---|
| 161 | const char *certPath[] = |
|---|
| 162 | { "3F00300060006002", "3F00300060006003", "3F00300060006004" }; |
|---|
| 163 | #endif |
|---|
| 164 | |
|---|
| 165 | const char *keyPath = "3F00300040000008"; |
|---|
| 166 | const char *pinDfName = "05040200"; |
|---|
| 167 | |
|---|
| 168 | |
|---|
| 169 | const int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN |
|---|
| 170 | | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
|---|
| 171 | | SC_PKCS15_PRKEY_USAGE_ENCRYPT |
|---|
| 172 | | SC_PKCS15_PRKEY_USAGE_DECRYPT; |
|---|
| 173 | |
|---|
| 174 | const char *authPIN = "Authentication PIN"; |
|---|
| 175 | |
|---|
| 176 | |
|---|
| 177 | const char *authPRKEY = "Authentication Key"; |
|---|
| 178 | |
|---|
| 179 | |
|---|
| 180 | p15card->opts.use_cache = 1; |
|---|
| 181 | |
|---|
| 182 | |
|---|
| 183 | sc_format_path("3F0030000001", &path); |
|---|
| 184 | r = sc_select_file(card, &path, NULL); |
|---|
| 185 | if (r != SC_SUCCESS) |
|---|
| 186 | return SC_ERROR_WRONG_CARD; |
|---|
| 187 | |
|---|
| 188 | sc_read_binary(card, 0xC3, serial, 8, 0); |
|---|
| 189 | serial[8] = '\0'; |
|---|
| 190 | |
|---|
| 191 | |
|---|
| 192 | if( serial[0] != 'H' ) |
|---|
| 193 | return SC_ERROR_WRONG_CARD; |
|---|
| 194 | |
|---|
| 195 | |
|---|
| 196 | set_string(&p15card->label, "Actalis"); |
|---|
| 197 | set_string(&p15card->manufacturer_id, "Actalis"); |
|---|
| 198 | set_string(&p15card->serial_number, (char *)serial); |
|---|
| 199 | |
|---|
| 200 | #ifdef ENABLE_ZLIB |
|---|
| 201 | for (i = 0; i < 3; i++) { |
|---|
| 202 | unsigned char *compCert = NULL, *cert = NULL, size[2]; |
|---|
| 203 | unsigned int compLen, len; |
|---|
| 204 | sc_pkcs15_cert_info_t cert_info; |
|---|
| 205 | sc_pkcs15_object_t cert_obj; |
|---|
| 206 | sc_path_t cpath; |
|---|
| 207 | |
|---|
| 208 | memset(&cert_info, 0, sizeof(cert_info)); |
|---|
| 209 | memset(&cert_obj, 0, sizeof(cert_obj)); |
|---|
| 210 | |
|---|
| 211 | sc_format_path(certPath[i], &cpath); |
|---|
| 212 | |
|---|
| 213 | if (sc_select_file(card, &cpath, NULL) != SC_SUCCESS) |
|---|
| 214 | return SC_ERROR_WRONG_CARD; |
|---|
| 215 | |
|---|
| 216 | sc_read_binary(card, 2, size, 2, 0); |
|---|
| 217 | |
|---|
| 218 | compLen = (size[0] << 8) + size[1]; |
|---|
| 219 | |
|---|
| 220 | compCert = |
|---|
| 221 | (unsigned char *) malloc(compLen * |
|---|
| 222 | sizeof(unsigned char)); |
|---|
| 223 | len = 3 * compLen; |
|---|
| 224 | cert = |
|---|
| 225 | (unsigned char *) malloc(len * sizeof(unsigned char)); |
|---|
| 226 | |
|---|
| 227 | sc_read_binary(card, 4, compCert, compLen, 0); |
|---|
| 228 | |
|---|
| 229 | if (uncompress |
|---|
| 230 | (cert, (unsigned long int *) &len, compCert, |
|---|
| 231 | compLen) != Z_OK) |
|---|
| 232 | return SC_ERROR_INTERNAL; |
|---|
| 233 | |
|---|
| 234 | cpath.index = 0; |
|---|
| 235 | cpath.count = len; |
|---|
| 236 | |
|---|
| 237 | sc_pkcs15_cache_file(p15card, &cpath, cert, len); |
|---|
| 238 | |
|---|
| 239 | id.value[0] = i + 1; |
|---|
| 240 | id.len = 1; |
|---|
| 241 | |
|---|
| 242 | cert_info.id = id; |
|---|
| 243 | cert_info.path = cpath; |
|---|
| 244 | cert_info.authority = (i>0); |
|---|
| 245 | |
|---|
| 246 | strlcpy(cert_obj.label, certLabel[i], sizeof(cert_obj.label)); |
|---|
| 247 | cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; |
|---|
| 248 | |
|---|
| 249 | sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); |
|---|
| 250 | } |
|---|
| 251 | #endif |
|---|
| 252 | |
|---|
| 253 | |
|---|
| 254 | flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | |
|---|
| 255 | SC_PKCS15_PIN_FLAG_INITIALIZED | |
|---|
| 256 | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; |
|---|
| 257 | |
|---|
| 258 | sc_format_path(pinDfName, &path); |
|---|
| 259 | path.type = SC_PATH_TYPE_DF_NAME; |
|---|
| 260 | |
|---|
| 261 | id.value[0] = 1; |
|---|
| 262 | id.len = 1; |
|---|
| 263 | sc_pkcs15emu_add_pin(p15card, &id, |
|---|
| 264 | authPIN, &path, 0x81, |
|---|
| 265 | SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, |
|---|
| 266 | 5, 8, flags, 3, 0, |
|---|
| 267 | SC_PKCS15_CO_FLAG_MODIFIABLE | |
|---|
| 268 | SC_PKCS15_CO_FLAG_PRIVATE); |
|---|
| 269 | |
|---|
| 270 | sc_format_path(keyPath, &path); |
|---|
| 271 | id.value[0] = 1; |
|---|
| 272 | id.len = 1; |
|---|
| 273 | auth_id.value[0] = 1; |
|---|
| 274 | auth_id.len = 1; |
|---|
| 275 | sc_pkcs15emu_add_prkey(p15card, &id, |
|---|
| 276 | authPRKEY, |
|---|
| 277 | SC_PKCS15_TYPE_PRKEY_RSA, |
|---|
| 278 | 1024, authprkey_usage, |
|---|
| 279 | &path, 0x08, |
|---|
| 280 | &auth_id, |
|---|
| 281 | SC_PKCS15_CO_FLAG_PRIVATE); |
|---|
| 282 | |
|---|
| 283 | |
|---|
| 284 | sc_format_path("3F00", &path); |
|---|
| 285 | sc_select_file(card, &path, NULL); |
|---|
| 286 | { |
|---|
| 287 | |
|---|
| 288 | set_security_env = card->ops->set_security_env; |
|---|
| 289 | |
|---|
| 290 | card->ops->set_security_env = set_sec_env; |
|---|
| 291 | card->ops->compute_signature = do_sign; |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | return SC_SUCCESS; |
|---|
| 295 | |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | static int actalis_detect_card(sc_pkcs15_card_t * p15card) |
|---|
| 299 | { |
|---|
| 300 | sc_card_t *card = p15card->card; |
|---|
| 301 | |
|---|
| 302 | |
|---|
| 303 | if (strcmp(card->name, "CardOS M4")) |
|---|
| 304 | return SC_ERROR_WRONG_CARD; |
|---|
| 305 | |
|---|
| 306 | return SC_SUCCESS; |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | int sc_pkcs15emu_actalis_init_ex(sc_pkcs15_card_t * p15card, |
|---|
| 310 | sc_pkcs15emu_opt_t * opts) |
|---|
| 311 | { |
|---|
| 312 | if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK) |
|---|
| 313 | return sc_pkcs15emu_actalis_init(p15card); |
|---|
| 314 | else { |
|---|
| 315 | int r = actalis_detect_card(p15card); |
|---|
| 316 | if (r) |
|---|
| 317 | return SC_ERROR_WRONG_CARD; |
|---|
| 318 | return sc_pkcs15emu_actalis_init(p15card); |
|---|
| 319 | } |
|---|
| 320 | } |
|---|