static int dump_ef(sc_card_t * card, const char *path, u8 * buf, size_t * buf_len) { int rv; sc_file_t *file = NULL; sc_path_t scpath; sc_format_path(path, &scpath); rv = sc_select_file(card, &scpath, &file); if (rv < 0) { if (file) sc_file_free(file); return rv; } if (file->size > *buf_len) { sc_file_free(file); return SC_ERROR_BUFFER_TOO_SMALL; } rv = sc_read_binary(card, 0, buf, file->size, 0); sc_file_free(file); if (rv < 0) return rv; *buf_len = rv; return SC_SUCCESS; }
/* * On-board key generation. */ static int gpk_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { struct sc_cardctl_gpk_genkey args; sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; unsigned int keybits; sc_file_t *keyfile; int r, n; sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "path=%s, %d bits\n", sc_print_path(&key_info->path), key_info->modulus_length); if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "GPK supports generating only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } /* The caller is supposed to have chosen a key file path for us */ if (key_info->path.len == 0 || key_info->modulus_length == 0) return SC_ERROR_INVALID_ARGUMENTS; keybits = key_info->modulus_length; if ((r = sc_select_file(p15card->card, &key_info->path, &keyfile)) < 0) return r; #ifndef PK_INIT_IMMEDIATELY r = gpk_pkfile_init_public(profile, p15card, keyfile, SC_ALGORITHM_RSA, keybits, key_info->usage); if (r < 0) { sc_file_free(keyfile); return r; } if ((r = gpk_pkfile_init_private(p15card->card, keyfile, 5 * ((3 + keybits / 16 + 7) & ~7UL))) < 0) { sc_file_free(keyfile); return r; } #endif sc_file_free(keyfile); memset(&args, 0, sizeof(args)); /*args.exponent = 0x10001;*/ n = key_info->path.len; args.fid = (key_info->path.value[n-2] << 8) | key_info->path.value[n-1]; args.privlen = keybits; r = sc_card_ctl(p15card->card, SC_CARDCTL_GPK_GENERATE_KEY, &args); if (r < 0) return r; /* This is fairly weird. The GENERATE RSA KEY command returns * immediately, but obviously it needs more time to complete. * This is why we sleep here. */ sleep(20); pubkey->algorithm = SC_ALGORITHM_RSA; return gpk_read_rsa_key(p15card->card, &pubkey->u.rsa); }
/* * Generate key */ static int cflex_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { struct sc_cardctl_cryptoflex_genkey_info args; sc_card_t *card = p15card->card; sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; unsigned int keybits; unsigned char raw_pubkey[256]; sc_file_t *prkf = NULL, *pukf = NULL; int r; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptoflex supports only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } /* Get the public and private key file */ r = cflex_get_keyfiles(profile, card, &key_info->path, &prkf, &pukf); if (r < 0) return r; if (! prkf) return SC_ERROR_NOT_SUPPORTED; /* Make sure we authenticate first */ r = sc_pkcs15init_authenticate(profile, p15card, prkf, SC_AC_OP_CRYPTO); if (r < 0) goto out; keybits = key_info->modulus_length; /* Perform key generation */ memset(&args, 0, sizeof(args)); args.exponent = 0x10001; args.key_bits = keybits; args.key_num = key_info->key_reference; r = sc_card_ctl(card, SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY, &args); if (r < 0) goto out; /* extract public key */ pubkey->algorithm = SC_ALGORITHM_RSA; pubkey->u.rsa.modulus.len = keybits / 8; pubkey->u.rsa.modulus.data = malloc(keybits / 8); pubkey->u.rsa.exponent.len = 3; pubkey->u.rsa.exponent.data = malloc(3); memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3); if ((r = sc_select_file(card, &pukf->path, NULL)) < 0 || (r = sc_read_binary(card, 3, raw_pubkey, keybits / 8, 0)) < 0) goto out; invert_buf(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); out: if (pukf) sc_file_free(pukf); if (prkf) sc_file_free(prkf); return r; }
void sc_pkcs15_card_clear(sc_pkcs15_card_t *p15card) { if (p15card == NULL) return; p15card->version = 0; p15card->flags = 0; while (p15card->obj_list != NULL) sc_pkcs15_remove_object(p15card, p15card->obj_list); p15card->obj_list = NULL; while (p15card->df_list != NULL) sc_pkcs15_remove_df(p15card, p15card->df_list); p15card->df_list = NULL; if (p15card->file_app != NULL) { sc_file_free(p15card->file_app); p15card->file_app = NULL; } if (p15card->file_tokeninfo != NULL) { sc_file_free(p15card->file_tokeninfo); p15card->file_tokeninfo = NULL; } if (p15card->file_odf != NULL) { sc_file_free(p15card->file_odf); p15card->file_odf = NULL; } if (p15card->file_unusedspace != NULL) { sc_file_free(p15card->file_unusedspace); p15card->file_unusedspace = NULL; } if (p15card->label != NULL) { free(p15card->label); p15card->label = NULL; } if (p15card->serial_number != NULL) { free(p15card->serial_number); p15card->serial_number = NULL; } if (p15card->manufacturer_id != NULL) { free(p15card->manufacturer_id); p15card->manufacturer_id = NULL; } if (p15card->last_update != NULL) { free(p15card->last_update); p15card->last_update = NULL; } if (p15card->preferred_language != NULL) { free(p15card->preferred_language); p15card->preferred_language = NULL; } if (p15card->seInfo != NULL) { size_t i; for (i = 0; i < p15card->num_seInfo; i++) free(p15card->seInfo[i]); free(p15card->seInfo); p15card->seInfo = NULL; p15card->num_seInfo = 0; } }
static int create_file_cert(sc_card_t *card) { int r; int size = 0; sc_path_t path; sc_file_t *file = NULL; sc_format_path("3F00", &path); r = sc_select_file(card, &path, &file); if(r) goto out; if(file) { size = (file->size) - 32; sc_file_free(file); file = NULL; } else { size = 2048; } sc_format_path("0002", &path); r = sc_select_file(card, &path, NULL); if(r) { if(r != SC_ERROR_FILE_NOT_FOUND) goto out; file = sc_file_new(); if(file == NULL) { printf("Memory error.\n"); goto out; } file->type = SC_FILE_TYPE_WORKING_EF; file->ef_structure = SC_FILE_EF_TRANSPARENT; file->shareable = 0; file->size = size; r = sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_NONE, 0); if(r) goto out; r = sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_CHV, 0); if(r) goto out; r = sc_file_add_acl_entry(file, SC_AC_OP_ERASE, SC_AC_CHV, 0); if(r) goto out; file->path = path; r = sc_create_file(card, file); if(r) goto out; } out: if(file) sc_file_free(file); return r; }
static int do_cd(int argc, char **argv) { sc_path_t path; sc_file_t *file; int r; if (argc != 1) goto usage; if (strcmp(argv[0], "..") == 0) { path = current_path; if (path.len < 4) { printf("unable to go up, already in MF.\n"); return -1; } if (path.type == SC_PATH_TYPE_DF_NAME) { sc_format_path("3F00", &path); } else { path.len -= 2; } r = sc_select_file(card, &path, &file); if (r) { printf("unable to go up: %s\n", sc_strerror(r)); return -1; } if (current_file) sc_file_free(current_file); current_file = file; current_path = path; return 0; } if (arg_to_path(argv[0], &path, 0) != 0) goto usage; r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select DF", current_file); return -1; } if ((file->type != SC_FILE_TYPE_DF) && (card->type != SC_CARD_TYPE_BELPIC_EID)) { printf("Error: file is not a DF.\n"); sc_file_free(file); select_current_path_or_die(); return -1; } current_path = path; if (current_file) sc_file_free(current_file); current_file = file; return 0; usage: puts("Usage: cd <file_id>|aid:<DF name>"); return -1; }
/* * Store a private key object. */ static int muscle_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) { struct sc_context *ctx = p15card->card->ctx; sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; sc_file_t* prkf; struct sc_pkcs15_prkey_rsa *rsa; sc_cardctl_muscle_key_info_t info; int r; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Muscle supports RSA keys only."); return SC_ERROR_NOT_SUPPORTED; } /* Verification stuff */ /* Used for verification AND for obtaining private key acls */ r = sc_profile_get_file_by_path(profile, &key_info->path, &prkf); if(!prkf) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_NOT_SUPPORTED); r = sc_pkcs15init_authenticate(profile, p15card, prkf, SC_AC_OP_CRYPTO); if (r < 0) { sc_file_free(prkf); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_NOT_SUPPORTED); } sc_file_free(prkf); r = muscle_select_key_reference(profile, p15card, key_info); if (r < 0) { SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,r); } rsa = &key->u.rsa; info.keySize = rsa->modulus.len << 3; info.keyType = 0x03; /* CRT type */ info.keyLocation = key_info->key_reference * 2; /* Mult by 2 to preserve even/odd keynumber structure */ info.pLength = rsa->p.len; info.pValue = rsa->p.data; info.qLength = rsa->q.len; info.qValue = rsa->q.data; info.pqLength = rsa->iqmp.len; info.pqValue = rsa->iqmp.data; info.dp1Length = rsa->dmp1.len; info.dp1Value = rsa->dmp1.data; info.dq1Length = rsa->dmq1.len; info.dq1Value = rsa->dmq1.data; r = sc_card_ctl(p15card->card, SC_CARDCTL_MUSCLE_IMPORT_KEY, &info); if (r < 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to import key"); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,r); } return r; }
/* * Create the MF and global pin file if they don't exist. */ static int setcos_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card) { struct sc_context *ctx = p15card->card->ctx; sc_file_t *mf = profile->mf_info->file; sc_file_t *pinfile; int r; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); /* Create the MF if it doesn't exist yet */ r = sc_select_file(p15card->card, &mf->path, NULL); if (r == SC_ERROR_FILE_NOT_FOUND) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "MF doesn't exist, creating now"); /* Fix up the file's ACLs */ r = sc_pkcs15init_fixup_file(profile, p15card, mf); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "MF fixup failed"); mf->status = SC_FILE_STATUS_CREATION; r = sc_create_file(p15card->card, mf); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "MF creation failed"); } SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select MF"); /* Create the global pin file if it doesn't exist yet */ r = sc_profile_get_file(profile, "pinfile", &pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot get 'pinfile' from profile"); r = sc_select_file(p15card->card, &pinfile->path, NULL); if (r == SC_ERROR_FILE_NOT_FOUND) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Global pin file doesn't exist, creating now"); /* Fix up the file's ACLs */ r = sc_pkcs15init_fixup_file(profile, p15card, pinfile); if (r < 0) sc_file_free(pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Pinfile fixup failed"); /* Set life cycle state to SC_FILE_STATUS_CREATION, * which means that all ACs are ignored. */ pinfile->status = SC_FILE_STATUS_CREATION; r = sc_create_file(p15card->card, pinfile); if (r < 0) sc_file_free(pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Pinfile creation failed"); } sc_file_free(pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Select pinfile failed"); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static int do_cd(int argc, char **argv) { sc_path_t path; sc_file_t *file; int r; if (argc != 1) goto usage; if (strcmp(argv[0], "..") == 0) { if (current_path.len < 4) { printf("unable to go up, already in MF.\n"); return -1; } path = current_path; path.len -= 2; r = sc_select_file(card, &path, &file); if (r) { printf("unable to go up: %s\n", sc_strerror(r)); return -1; } sc_file_free(current_file); current_file = file; current_path = path; return 0; } if (arg_to_path(argv[0], &path, 0) != 0) goto usage; r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select DF", current_file); return -1; } if ((file->type != SC_FILE_TYPE_DF) && !(card->caps & SC_CARD_CAP_NO_FCI)) { printf("Error: file is not a DF.\n"); sc_file_free(file); r = sc_select_file(card, ¤t_path, NULL); if (r) { printf("unable to select parent file: %s\n", sc_strerror(r)); die(1); } return -1; } current_path = path; sc_file_free(current_file); current_file = file; return 0; usage: puts("Usage: cd <file_id>|aid:<DF name>"); return -1; }
static int parse_ddo(struct sc_pkcs15_card *p15card, const u8 * buf, size_t buflen) { struct sc_asn1_entry asn1_ddo[5]; sc_path_t odf_path, ti_path, us_path; int r; sc_copy_asn1_entry(c_asn1_ddo, asn1_ddo); sc_format_asn1_entry(asn1_ddo + 1, &odf_path, NULL, 0); sc_format_asn1_entry(asn1_ddo + 2, &ti_path, NULL, 0); sc_format_asn1_entry(asn1_ddo + 3, &us_path, NULL, 0); r = sc_asn1_decode(p15card->card->ctx, asn1_ddo, buf, buflen, NULL, NULL); if (r) { sc_error(p15card->card->ctx, "DDO parsing failed: %s\n", sc_strerror(r)); return r; } if (asn1_ddo[1].flags & SC_ASN1_PRESENT) { p15card->file_odf = sc_file_new(); if (p15card->file_odf == NULL) goto mem_err; p15card->file_odf->path = odf_path; } if (asn1_ddo[2].flags & SC_ASN1_PRESENT) { p15card->file_tokeninfo = sc_file_new(); if (p15card->file_tokeninfo == NULL) goto mem_err; p15card->file_tokeninfo->path = ti_path; } if (asn1_ddo[3].flags & SC_ASN1_PRESENT) { p15card->file_unusedspace = sc_file_new(); if (p15card->file_unusedspace == NULL) goto mem_err; p15card->file_unusedspace->path = us_path; } return 0; mem_err: if (p15card->file_odf != NULL) { sc_file_free(p15card->file_odf); p15card->file_odf = NULL; } if (p15card->file_tokeninfo != NULL) { sc_file_free(p15card->file_tokeninfo); p15card->file_tokeninfo = NULL; } if (p15card->file_unusedspace != NULL) { sc_file_free(p15card->file_unusedspace); p15card->file_unusedspace = NULL; } return SC_ERROR_OUT_OF_MEMORY; }
static int entersafe_select_fid(sc_card_t *card, unsigned int id_hi, unsigned int id_lo, sc_file_t **file_out) { int r; sc_file_t *file=0; sc_path_t path; memset(&path, 0, sizeof(sc_path_t)); path.type=SC_PATH_TYPE_FILE_ID; path.value[0]=id_hi; path.value[1]=id_lo; path.len=2; r = iso_ops->select_file(card,&path,&file); if(r && file) { if(file) sc_file_free(file); } SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); /* update cache */ if (file->type == SC_FILE_TYPE_DF) { card->cache.current_path.type = SC_PATH_TYPE_PATH; card->cache.current_path.value[0] = 0x3f; card->cache.current_path.value[1] = 0x00; if (id_hi == 0x3f && id_lo == 0x00){ card->cache.current_path.len = 2; }else{ card->cache.current_path.len = 4; card->cache.current_path.value[2] = id_hi; card->cache.current_path.value[3] = id_lo; } } if (file_out) { *file_out = file; } else { if(file) sc_file_free(file); } SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); }
/* * Create a new key file */ static int cflex_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj) { sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; sc_file_t *prkf = NULL, *pukf = NULL; size_t size; int r; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptoflex supports only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } /* Get the public and private key file */ r = cflex_get_keyfiles(profile, p15card->card, &key_info->path, &prkf, &pukf); if (r < 0) return r; /* Adjust the file sizes, if necessary */ switch (key_info->modulus_length) { case 512: size = 166; break; case 768: size = 246; break; case 1024: size = 326; break; case 2048: size = 646; break; default: sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported key size %u\n", key_info->modulus_length); r = SC_ERROR_INVALID_ARGUMENTS; goto out; } if (prkf->size < size) prkf->size = size; if (pukf->size < size + 4) pukf->size = size + 4; /* Now create the files */ if ((r = sc_pkcs15init_create_file(profile, p15card, prkf)) < 0 || (r = sc_pkcs15init_create_file(profile, p15card, pukf)) < 0) goto out; key_info->key_reference = 0; out: if (prkf) sc_file_free(prkf); if (pukf) sc_file_free(pukf); return r; }
static int do_update_record(int argc, char **argv) { u8 buf[240]; size_t buflen; int r, i, err = 1; int rec, offs; sc_path_t path; sc_file_t *file; if (argc != 4) return usage(do_update_record); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_record); rec = strtol(argv[1],NULL,10); offs = strtol(argv[2],NULL,10); printf("in: %i; %i; %s\n", rec, offs, argv[3]); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n"); goto err; } else if (rec < 1 || rec > file->record_count) { printf("Invalid record number %i\n", rec); goto err; } r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot read record %i; return %i\n", rec, r); goto err;; } buflen = sizeof(buf) - offs; i = parse_string_or_hexdata(argv[3], buf + offs, &buflen); if (!i) { printf("unable to parse data\n"); goto err; } r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot update record %i; return %i\n", rec, r); goto err; } printf("Total of %d bytes written to record %i at %i offset.\n", i, rec, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; }
static int create_sysdf(sc_profile_t *profile, sc_card_t *card, const char *name) { sc_file_t *file; sc_path_t path; int r; assert(profile && card && card->ctx && name); r = sc_profile_get_file(profile, name, &file); if (r == SC_SUCCESS) { assert(file); path = file->path; assert(path.len > 2); if (path.len > 2) path.len -= 2; r = sc_select_file(card, &path, NULL); if (r == SC_SUCCESS) r = sc_file_add_acl_entry(file, SC_AC_OP_CREATE, SC_AC_CHV, RTECP_USER_PIN_REF); if (r == SC_SUCCESS) r = sc_file_add_acl_entry(file, SC_AC_OP_DELETE, SC_AC_NEVER, SC_AC_KEY_REF_NONE); if (r == SC_SUCCESS) r = sc_create_file(card, file); assert(file); sc_file_free(file); } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Create %s failed: %s\n", name, sc_strerror(r)); return r; }
/* * Create private key file */ static int miocos_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; struct sc_file *file; int r; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys."); if (key_info->modulus_length != 1024) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys."); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "create private key ID:%s\n", sc_pkcs15_print_id(&key_info->id)); r = miocos_new_file(profile, p15card->card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot create key: failed to allocate new key object"); memcpy(&file->path, &key_info->path, sizeof(file->path)); file->id = file->path.value[file->path.len - 2] * 0x100 + file->path.value[file->path.len - 1]; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Path of private key file to create %s\n", sc_print_path(&file->path)); r = sc_pkcs15init_create_file(profile, p15card, file); sc_file_free(file); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
/* * Store a private key */ static int myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data; struct sc_file *file = NULL; int keybits = key_info->modulus_length, r; LOG_FUNC_CALLED(card->ctx); /* Check that the card supports the requested modulus length */ switch (object->type) { case SC_PKCS15_TYPE_PRKEY_RSA: if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); break; case SC_PKCS15_TYPE_PRKEY_EC: /* Here the information about curve is not available, that's why algorithm is checked without curve OID. */ if (sc_card_find_ec_alg(p15card->card, keybits, NULL) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type"); break; } sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id)); /* Get the private key file */ r = myeid_new_file(profile, card, object->type, key_info->key_reference, &file); LOG_TEST_RET(ctx, r, "Cannot get new MyEID private key file"); if (!file || !file->path.len) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot determine private key file"); sc_log(ctx, "Key file size %d", keybits); file->size = keybits; if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) file->ef_structure = SC_CARDCTL_MYEID_KEY_RSA; else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) file->ef_structure = SC_CARDCTL_MYEID_KEY_EC; memcpy(&key_info->path.value, &file->path.value, file->path.len); key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF; sc_log(ctx, "Path of MyEID private key file to create %s", sc_print_path(&file->path)); /* Now create the key file */ r = sc_pkcs15init_create_file(profile, p15card, file); sc_file_free(file); LOG_TEST_RET(ctx, r, "Cannot create MyEID private key file"); LOG_FUNC_RETURN(ctx, r); }
/* * Get private and public key file */ static int cflex_get_keyfiles(sc_profile_t *profile, sc_card_t *card, const sc_path_t *df_path, sc_file_t **prkf, sc_file_t **pukf) { sc_path_t path = *df_path; int r; /* Get the private key file */ r = sc_profile_get_file_by_path(profile, &path, prkf); if (r < 0) { char pbuf[SC_MAX_PATH_STRING_SIZE]; r = sc_path_print(pbuf, sizeof(pbuf), &path); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cannot find private key file info " "in profile (path=%s).", pbuf); return r; } /* Get the public key file */ path.len -= 2; sc_append_file_id(&path, 0x1012); r = sc_profile_get_file_by_path(profile, &path, pukf); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cannot find public key file info in profile."); sc_file_free(*prkf); return r; } return 0; }
/* * Store a private key * Private key file formats: (transparent file) * Non-CRT: * byte 0 0x05 * byte 1 Modulus length (in byte/4) * byte 2 Modulus (n) * byte 2+x private exponent (d) * * CRT: * byte 0 0x06 * byte 1 component length (in byte/2; component length is half * of modulus length * byte 2 Prime (p) * byte 2+x Prime (q) * byte 2+2*x Exponent 1 (d mod (p-1)) * byte 2+3*x Exponent 2 (d mod (q-1)) * byte 2+4*x Coefficient ((p ^ -1) mod q * * We use the CRT format, since that's what key generation does. * * Numbers are stored big endian. */ static int jcop_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) { sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; sc_file_t *keyfile; unsigned char keybuf[1024]; size_t size,base; int r; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } r = sc_profile_get_file_by_path(profile, &key_info->path, &keyfile); if (r < 0) return r; base=key_info->modulus_length / 16; size=2+5*base; keybuf[0]=6; keybuf[1]=base/4; jcop_bn2bin(&keybuf[2 + 0 * base], &key->u.rsa.p, base); jcop_bn2bin(&keybuf[2 + 1 * base], &key->u.rsa.q, base); jcop_bn2bin(&keybuf[2 + 2 * base], &key->u.rsa.dmp1, base); jcop_bn2bin(&keybuf[2 + 3 * base], &key->u.rsa.dmq1, base); jcop_bn2bin(&keybuf[2 + 4 * base], &key->u.rsa.iqmp, base); r = sc_pkcs15init_update_file(profile, p15card, keyfile, keybuf, size); sc_file_free(keyfile); return r; }
/* * Lock the pin file */ static int gpk_lock_pinfile(struct sc_profile *profile, sc_pkcs15_card_t *p15card, sc_file_t *pinfile) { struct sc_path path; struct sc_file *parent = NULL; int r; SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE); /* Select the parent DF */ path = pinfile->path; if (path.len >= 2) path.len -= 2; if (path.len == 0) sc_format_path("3F00", &path); if ((r = sc_select_file(p15card->card, &path, &parent)) < 0) return r; /* Present PINs etc as necessary */ r = sc_pkcs15init_authenticate(profile, p15card, parent, SC_AC_OP_LOCK); if (r >= 0) r = gpk_lock(p15card->card, pinfile, SC_AC_OP_WRITE); sc_file_free(parent); SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r); }
static int do_put(int argc, char **argv) { u8 buf[256]; int r, err = 1; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file = NULL; const char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) return usage(do_put); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_put); filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); outf = fopen(filename, "rb"); if (outf == NULL) { perror(filename); goto err; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = fread(buf, 1, c, outf); if (r < 0) { perror("fread"); goto err; } if (r != c) count = c = r; r = sc_update_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "update failed", file); goto err; } if (r != c) { printf("expecting %d, wrote only %d bytes.\n", c, r); goto err; } idx += c; count -= c; } printf("Total of %d bytes written.\n", idx); err = 0; err: sc_file_free(file); if (outf) fclose(outf); select_current_path_or_die(); return -err; }
/* * Card initialization. * For the cryptoflex, read the card's serial number from 3F00 0002 */ static int cryptoflex_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card) { sc_path_t path; sc_file_t *file; u8 buf[32]; char serial[128]; size_t len; int r; sc_format_path("3F000002", &path); if ((r = sc_select_file(p15card->card, &path, &file)) < 0) { if (r == SC_ERROR_FILE_NOT_FOUND) return 0; return r; } if ((len = file->size) > sizeof(buf)) len = sizeof(buf); sc_file_free(file); if ((r = sc_read_binary(p15card->card, 0, buf, len, 0)) < 0) return r; len = r; if (len == 0) return 0; if ((r = sc_bin_to_hex(buf, len, serial, sizeof(serial), '\0')) < 0) return r; sc_pkcs15init_set_serial(profile, serial); return 0; }
/* * Create a new key file */ static int jcop_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj) { sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; sc_file_t *keyfile = NULL; size_t bytes, mod_len, prv_len; int r; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } /* The caller is supposed to have chosen a key file path for us */ if (key_info->path.len == 0 || key_info->modulus_length == 0) return SC_ERROR_INVALID_ARGUMENTS; /* Get the file we're supposed to create */ r = sc_profile_get_file_by_path(profile, &key_info->path, &keyfile); if (r < 0) return r; mod_len = key_info->modulus_length / 8; bytes = mod_len / 2; prv_len = 2 + 5 * bytes; keyfile->size = prv_len; /* Fix up PIN references in file ACL */ r = sc_pkcs15init_fixup_file(profile, p15card, keyfile); if (r >= 0) r = sc_pkcs15init_create_file(profile, p15card, keyfile); sc_file_free(keyfile); return r; }
static sc_pkcs15_df_t * sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, unsigned int type) { sc_pkcs15_df_t *df; sc_file_t *file; int created = 0; while (1) { for (df = p15card->df_list; df; df = df->next) { if (df->type == type) { if (created) df->enumerated = 1; return df; } } assert(created == 0); file = sc_file_new(); if (!file) return NULL; sc_format_path("11001101", &file->path); sc_pkcs15_add_df(p15card, type, &file->path); sc_file_free(file); created++; } }
/* * Object deletion. */ static int cardos_delete_object(sc_profile_t *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const struct sc_path *path) { int r = SC_SUCCESS, stored_in_ef = 0, algorithm = 0; size_t keybits; sc_file_t *file = NULL; struct sc_pkcs15_prkey_info *key_info; struct sc_pkcs15_prkey_rsa key_obj; struct sc_context *ctx = p15card->card->ctx; uint8_t abignum[256]; LOG_FUNC_CALLED(ctx); /* * If we are deleting a private key, overwrite it so it can't be used. */ if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY) { key_info = obj->data; keybits = key_info->modulus_length & ~7UL; init_key_object(&key_obj, abignum, keybits >> 3); r = cardos_key_algorithm(key_info->usage, keybits, &algorithm); LOG_TEST_RET(ctx, r, "cardos_key_algorithm failed"); r = sc_select_file(p15card->card, &key_info->path, &file); LOG_TEST_RET(ctx, r, "Failed to store key: cannot select parent DF"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); sc_file_free(file); LOG_TEST_RET(ctx, r, "Failed to store key: UPDATE authentication failed"); r = cardos_put_key(profile, p15card, algorithm, key_info, &key_obj); LOG_TEST_RET(ctx, r, "cardos_put_key failed"); }
static int do_create(int argc, char **argv) { sc_path_t path; sc_file_t *file; unsigned int size; int r, op; if (argc != 2) return usage(do_create); if (arg_to_path(argv[0], &path, 1) != 0) return usage(do_create); /* %z isn't supported everywhere */ if (sscanf(argv[1], "%u", &size) != 1) return usage(do_create); file = sc_file_new(); file->id = (path.value[0] << 8) | path.value[1]; file->type = SC_FILE_TYPE_WORKING_EF; file->ef_structure = SC_FILE_EF_TRANSPARENT; file->size = (size_t) size; file->status = SC_FILE_STATUS_ACTIVATED; for (op = 0; op < SC_MAX_AC_OPS; op++) sc_file_add_acl_entry(file, op, SC_AC_NONE, 0); r = create_file(file); sc_file_free(file); return r; }
/* * Lock the pin file */ static int gpk_lock_pinfile(struct sc_profile *profile, sc_card_t *card, sc_file_t *pinfile) { struct sc_path path; struct sc_file *parent = NULL; int r; /* Select the parent DF */ path = pinfile->path; if (path.len >= 2) path.len -= 2; if (path.len == 0) sc_format_path("3F00", &path); if ((r = sc_select_file(card, &path, &parent)) < 0) return r; /* Present PINs etc as necessary */ r = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_LOCK); if (r >= 0) r = gpk_lock(card, pinfile, SC_AC_OP_WRITE); sc_file_free(parent); return r; }
static int do_mkdir(int argc, char **argv) { sc_path_t path; sc_file_t *file; unsigned int size; int r, op; if (argc != 2) return usage(do_mkdir); if (arg_to_path(argv[0], &path, 1) != 0) return usage(do_mkdir); if (sscanf(argv[1], "%u", &size) != 1) return usage(do_mkdir); file = sc_file_new(); file->id = (path.value[0] << 8) | path.value[1]; file->type = SC_FILE_TYPE_DF; file->size = size; file->status = SC_FILE_STATUS_ACTIVATED; for (op = 0; op < SC_MAX_AC_OPS; op++) sc_file_add_acl_entry(file, op, SC_AC_NONE, 0); r = create_file(file); sc_file_free(file); return r; }
static int cflex_delete_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) { sc_path_t path; sc_file_t *parent; int r = 0; /* Select the parent DF */ path = df->path; path.len -= 2; r = sc_select_file(p15card->card, &path, &parent); if (r < 0) return r; r = sc_pkcs15init_authenticate(profile, p15card, parent, SC_AC_OP_DELETE); sc_file_free(parent); if (r < 0) return r; /* cryptoflex has no ERASE AC */ memset(&path, 0, sizeof(path)); path.type = SC_PATH_TYPE_FILE_ID; path.value[0] = df->id >> 8; path.value[1] = df->id & 0xFF; path.len = 2; r = sc_delete_file(p15card->card, &path); return r; }
static int entersafe_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) { sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; sc_card_t *card = p15card->card; sc_entersafe_wkey_data data; sc_file_t *tfile; const sc_acl_entry_t *acl_entry; int r; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); if (key->algorithm != SC_ALGORITHM_RSA) /* ignore DSA keys */ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS); r = sc_profile_get_file(profile, "PKCS15-AODF", &tfile); if (r < 0) return r; acl_entry = sc_file_get_acl_entry(tfile, SC_AC_OP_UPDATE); if (acl_entry->method != SC_AC_NONE) { r = sc_pkcs15init_authenticate(profile, p15card, tfile, SC_AC_OP_UPDATE); if(r<0) r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } sc_file_free(tfile); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "cant verify pin"); data.key_id = (u8) kinfo->key_reference; data.usage=0x22; data.key_data.rsa=&key->u.rsa; return sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); }
/* * Create the PK file * XXX: Handle the UPDATE ACL = NEVER case just like for EFsc files */ static int gpk_pkfile_create(sc_profile_t *profile, sc_card_t *card, sc_file_t *file) { struct sc_file *found = NULL; int r; sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &file->path, &found); sc_ctx_suppress_errors_off(card->ctx); if (r == SC_ERROR_FILE_NOT_FOUND) { r = sc_pkcs15init_create_file(profile, card, file); if (r >= 0) r = sc_select_file(card, &file->path, &found); } else { /* XXX: make sure the file has correct type and size? */ } if (r >= 0) r = sc_pkcs15init_authenticate(profile, card, file, SC_AC_OP_UPDATE); if (found) sc_file_free(found); return r; }