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; }
static int do_update_binary(int argc, char **argv) { u8 buf[240]; int r, err = 1, in_len; int offs; sc_path_t path; sc_file_t *file; char *in_str; if (argc < 2 || argc > 3) goto usage; if (arg_to_path(argv[0], &path, 0) != 0) goto usage; offs = strtol(argv[1],NULL,10); in_str = argv[2]; printf("in: %i; %s\n", offs, in_str); if (*in_str=='\"') { in_len = strlen(in_str)-2 >= sizeof(buf) ? sizeof(buf)-1 : strlen(in_str)-2; strncpy((char *) buf, in_str+1, in_len); } else { in_len = hex2binary(buf, sizeof(buf), in_str); if (!in_len) { printf("unable to parse hex value\n"); return -1; } } 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_TRANSPARENT) { printf("EF structure should be SC_FILE_EF_TRANSPARENT\n"); goto err; } r = sc_update_binary(card, offs, buf, in_len, 0); if (r < 0) { printf("Cannot update %04X; return %i\n", file->id, r); goto err; } printf("Total of %d bytes written to %04X at %i offset.\n", r, file->id, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; usage: printf("Usage: update <file id> offs <hex value> | <'\"' enclosed string>\n"); return -1; }
int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = sc_get_max_send_size(card); int r; if (card == NULL || card->ops == NULL || buf == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at index %d", count, idx); if (count == 0) return 0; #ifdef ENABLE_SM if (card->sm_ctx.ops.update_binary) { r = card->sm_ctx.ops.update_binary(card, idx, buf, count); if (r) LOG_FUNC_RETURN(card->ctx, r); } #endif if (card->ops->update_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_update_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_update_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } r = card->ops->update_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_pkcs15_object *obj, struct sc_pkcs15_der *content, struct sc_path *path) { sc_card_t *card = p15card->card; sc_file_t *file; sc_pkcs15_cert_info_t *cinfo; sc_pkcs15_id_t *cid; int r; LOG_FUNC_CALLED(card->ctx); switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) { case SC_PKCS15_TYPE_PRKEY: case SC_PKCS15_TYPE_PUBKEY: /* For these two type, store_data just don't need to do anything. * All have been done already before this function is called */ r = SC_SUCCESS; break; case SC_PKCS15_TYPE_CERT: cinfo = (sc_pkcs15_cert_info_t *) obj->data; cid = &(cinfo->id); if (cid->len != 1) { sc_log(card->ctx, "ID=%s is not valid.", sc_dump_hex(cid->value, cid->len)); LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); } /* OpenPGP card v.2 contains only 1 certificate */ if (cid->value[0] != 3) { sc_log(card->ctx, "This version does not support certificate ID = %d (only ID=3 is supported).", cid->value[0]); LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); } /* Just update the certificate DO */ sc_format_path("7F21", path); r = sc_select_file(card, path, &file); LOG_TEST_RET(card->ctx, r, "Cannot select cert file"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); if (r >= 0 && content->len) r = sc_update_binary(p15card->card, 0, (const unsigned char *) content->value, content->len, 0); break; default: r = SC_ERROR_NOT_IMPLEMENTED; } LOG_FUNC_RETURN(card->ctx, r); }
int card_helper_update_file(sc_card_t *card, const sc_path_t *path, u8 *buffer, size_t length) { int r = SC_SUCCESS; sc_file_t *file = NULL; int old_use_virtual_fs; /*!< backup of use_virtual_fs */ SC_FUNC_CALLED(card->ctx, 1); /* we backup use_virtual_fs */ old_use_virtual_fs = card_is_virtual_fs_active(card); /* we want to use card without virtual fs */ card_set_virtual_fs_state(card, 0); if(!buffer || length<=0) { r = SC_ERROR_INVALID_ARGUMENTS; goto chuf_end; } /* get file */ r = card_select_file(card, path, &file); if(r != SC_SUCCESS) goto chuf_end; if(file->size <= 0) { r = SC_ERROR_FILE_TOO_SMALL; goto chuf_end; } if (file->size<length) { r = SC_ERROR_OUT_OF_MEMORY; goto chuf_end; } r = sc_update_binary(card, 0, buffer, length, 0); if(r < 0) goto chuf_end; if (r == length) r = SC_SUCCESS; chuf_end: /* we restore use_virtual_fs */ card_set_virtual_fs_state(card, old_use_virtual_fs); if(file) { sc_file_free(file); file = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = card->max_send_size; int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_log(card->ctx, "called; %d bytes at index %d", count, idx); if (count == 0) return 0; #ifdef ENABLE_SM if (card->sm_ctx.ops.update_binary) { r = card->sm_ctx.ops.update_binary(card, idx, buf, count); if (r) LOG_FUNC_RETURN(card->ctx, r); } #endif if (card->ops->update_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_update_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_update_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } r = card->ops->update_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
static int do_update_binary(int argc, char **argv) { u8 buf[240]; size_t buflen = sizeof(buf); int r, err = 1; int offs; sc_path_t path; sc_file_t *file; if (argc != 3) return usage(do_update_binary); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_binary); offs = strtol(argv[1],NULL,10); printf("in: %i; %s\n", offs, argv[2]); r = parse_string_or_hexdata(argv[2], buf, &buflen); if (r < 0) { printf("unable to parse data\n"); return -1; } 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_TRANSPARENT) { printf("EF structure should be SC_FILE_EF_TRANSPARENT\n"); goto err; } r = sc_update_binary(card, offs, buf, buflen, 0); if (r < 0) { printf("Cannot update %04X; return %i\n", file->id, r); goto err; } printf("Total of %d bytes written to %04X at %i offset.\n", r, file->id, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; }
static int miocos_update_private_key(struct sc_profile *profile, sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) { int r; u8 buf[266]; memcpy(buf, "\x30\x82\x01\x06\x80\x81\x80", 7); memcpy(buf + 7, rsa->modulus.data, 128); memcpy(buf + 7 + 128, "\x82\x81\x80", 3); memcpy(buf + 10 + 128, rsa->d.data, 128); r = sc_update_binary(card, 0, buf, sizeof(buf), 0); return r; }
static int update_transparent(sc_card_t *card, sc_file_t *file) { u8 *rec, *buf = NULL, *tmp; size_t rec_size, buf_size = 0; int i, r; for (i = 0; i < card->app_count; i++) { r = encode_dir_record(card->ctx, card->app[i], &rec, &rec_size); if (r) { if (buf) free(buf); return r; } if (!rec_size) continue; tmp = (u8 *) realloc(buf, buf_size + rec_size); if (!tmp) { if (rec) free(rec); if (buf) free(buf); return SC_ERROR_OUT_OF_MEMORY; } buf = tmp; memcpy(buf + buf_size, rec, rec_size); buf_size += rec_size; free(rec); rec=NULL; } if (file->size > buf_size) { tmp = (u8 *) realloc(buf, file->size); if (!tmp) { free(buf); return SC_ERROR_OUT_OF_MEMORY; } buf = tmp; memset(buf + buf_size, 0, file->size - buf_size); buf_size = file->size; } r = sc_update_binary(card, 0, buf, buf_size, 0); free(buf); LOG_TEST_RET(card->ctx, r, "Unable to update EF(DIR)"); return SC_SUCCESS; }
static void handle_writecert(sc_card_t *card, int cert, char *file) { sc_path_t p; sc_file_t *f; FILE *fp; X509 *c; u8 buf[1536], *q; int i, len; printf("\nReading Cert from %s: ", file); fflush(stdout); if((fp=fopen(file,"r"))==NULL){ printf("Cannot open file, %s\n", strerror(errno)); return; } c=PEM_read_X509(fp,NULL,NULL,NULL); fclose(fp); if(c==NULL){ printf("file does not conatin PEM-encoded certificate\n"); return; } printf("OK\nStoring Cert into Card-Certificate %d: ", cert); fflush(stdout); q=buf; len=i2d_X509(c,NULL); if(len>0 && len<=(int)sizeof(buf)) i2d_X509(c,&q); X509_free(c); if(len<=0 || len>(int)sizeof(buf)){ printf("certificate too long or invalid (Len=%d)\n", len); return; } sc_format_path(certlist[cert].path,&p); if((i=sc_select_file(card,&p,&f))<0){ printf("cannot select certfile, %s\n", sc_strerror(i)); return; } if((i=sc_update_binary(card,0,buf,len,0))<0){ printf("cannot store cert, %s\n", sc_strerror(i)); return; } printf("OK\n"); }
int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = card->max_send_size > 0 ? card->max_send_size : 255; int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "called; %d bytes at index %d\n", count, idx); if (count == 0) return 0; if (card->ops->update_binary == NULL) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_update_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_update_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_written); } } sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_written); } r = card->ops->update_binary(card, idx, buf, count, flags); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); }
static int update_ef(sc_card_t *card, u8 prefix, u8 id, int erase, const u8 *buf, size_t buflen) { sc_file_t *file = NULL; sc_file_t newfile; sc_path_t path; u8 fid[2]; int r; fid[0] = prefix; fid[1] = id; sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, -1); r = sc_select_file(card, &path, NULL); if ((r == SC_SUCCESS) && erase) { r = sc_delete_file(card, &path); r = SC_ERROR_FILE_NOT_FOUND; } if (r == SC_ERROR_FILE_NOT_FOUND) { 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) 0; file->status = SC_FILE_STATUS_ACTIVATED; r = sc_create_file(card, file); sc_file_free(file); if (r < 0) { return r; } } r = sc_update_binary(card, 0, buf, buflen, 0); return r; }
static int sc_hsm_update_ef(sc_pkcs15_card_t *p15card, u8 prefix, u8 id, int erase, u8 *buf, size_t buflen) { sc_card_t *card = p15card->card; sc_file_t *file = NULL; sc_file_t newfile; sc_path_t path; u8 fid[2]; int r; fid[0] = prefix; fid[1] = id; sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, -1); r = sc_select_file(card, &path, NULL); if ((r == SC_SUCCESS) && erase) { r = sc_delete_file(card, &path); LOG_TEST_RET(card->ctx, r, "Could not delete file"); r = SC_ERROR_FILE_NOT_FOUND; } if (r == SC_ERROR_FILE_NOT_FOUND) { 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) 0; file->status = SC_FILE_STATUS_ACTIVATED; r = sc_create_file(card, file); sc_file_free(file); LOG_TEST_RET(card->ctx, r, "Could not create file"); } r = sc_update_binary(card, 0, buf, buflen, 0); LOG_FUNC_RETURN(card->ctx, r); }
int main(int argc, char *argv[]) { int r, c, long_optind = 0; sc_context_param_t ctx_param; sc_card_t *card = NULL; sc_context_t *ctx = NULL; sc_file_t *file = NULL; sc_path_t path; RSA *rsa = NULL; BIGNUM *bn = NULL; BIO *mem = NULL; static const char *pin = NULL; static const char *puk = NULL; while (1) { c = getopt_long(argc, argv, "r:wgol:ix:y:nut:fj:k:hv", \ options, &long_optind); if (c == -1) break; if (c == '?' || c == 'h') util_print_usage_and_die(app_name, options, option_help, NULL); switch (c) { case 'r': opt_reader = optarg; break; case 'w': opt_wait = 1; break; case 'g': if(keylen == 0) keylen = 1536; break; case 'o': overwrite = 1; break; case 'l': keylen = atoi(optarg); break; case 'i': install_pin = 1; break; case 'x': util_get_pin(optarg, &pin); break; case 'y': util_get_pin(optarg, &puk); break; case 'n': new_pin = 1; break; case 'u': unlock = 1; break; case 't': cert = optarg; break; case 'f': finalize = 1; break; case 'j': get_filename = optarg; break; case 'k': put_filename = optarg; break; case 'v': verbose++; break; } } memset(&ctx_param, 0, sizeof(ctx_param)); ctx_param.ver = 0; ctx_param.app_name = argv[0]; r = sc_context_create(&ctx, &ctx_param); if (r) { printf("Failed to establish context: %s\n", sc_strerror(r)); return 1; } if (verbose > 1) { ctx->debug = verbose; sc_ctx_log_to_file(ctx, "stderr"); } if (opt_driver != NULL) { r = sc_set_card_driver(ctx, opt_driver); if (r) { printf("Driver '%s' not found!\n", opt_driver); goto out; } } r = util_connect_card(ctx, &card, opt_reader, opt_wait, 0); if (r) goto out; sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); if(r) goto out; if(install_pin) { sc_format_path("AAAA", &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("Not enougth memory.\n"); goto out; } file->type = SC_FILE_TYPE_INTERNAL_EF; file->ef_structure = SC_FILE_EF_TRANSPARENT; file->shareable = 0; file->id = 0xAAAA; file->size = 37; 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_NONE, 0); if(r) goto out; r = sc_file_add_acl_entry(file, SC_AC_OP_ERASE, SC_AC_NONE, 0); if(r) goto out; /* sc_format_path("3F00AAAA", &(file->path)); */ file->path = path; r = sc_create_file(card, file); if(r) goto out; } if(pin != NULL) { sc_changekey_t ck; struct sc_pin_cmd_pin pin_cmd; int ret; memset(&pin_cmd, 0, sizeof(pin_cmd)); memset(&ck, 0, sizeof(ck)); memcpy(ck.key_template, "\x1e\x00\x00\x10", 4); pin_cmd.encoding = SC_PIN_ENCODING_GLP; pin_cmd.len = strlen(pin); pin_cmd.data = (u8*)pin; pin_cmd.max_length = 8; ret = sc_build_pin(ck.new_key.key_value, sizeof(ck.new_key.key_value), &pin_cmd, 1); if(ret < 0) goto out; ck.new_key.key_len = ret; r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_CHANGE_KEY, &ck); if(r) goto out; } if(puk != NULL) { sc_changekey_t ck; struct sc_pin_cmd_pin puk_cmd; int ret; memset(&puk_cmd, 0, sizeof(puk_cmd)); memset(&ck, 0, sizeof(ck)); memcpy(ck.key_template, "\x1e\x00\x00\x20", 4); puk_cmd.encoding = SC_PIN_ENCODING_GLP; puk_cmd.len = strlen(puk); puk_cmd.data = (u8*)puk; puk_cmd.max_length = 8; ret = sc_build_pin(ck.new_key.key_value, sizeof(ck.new_key.key_value), &puk_cmd, 1); if(ret < 0) goto out; ck.new_key.key_len = ret; r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_CHANGE_KEY, &ck); if(r) goto out; } } if(new_pin) { if(change_pin(card, 0, pin, puk)) printf("Wrong pin.\n"); goto out; } if(unlock) { if(unlock_pin(card, 0, puk, pin)) printf("Error unblocking pin.\n"); goto out; } printf("verify pin.\n"); { if(verify_pin(card, 0, pin)) { printf("Wrong pin.\n"); goto out; } } if(keylen) { size_t lg; struct sc_pkcs15_pubkey key; struct sc_pkcs15_pubkey_rsa *dst = &(key.u.rsa); u8 *pdata; memset(&key, 0, sizeof(key)); key.algorithm = SC_ALGORITHM_RSA; printf("Generate key of length %d.\n", keylen); #if OPENSSL_VERSION_NUMBER>=0x00908000L rsa = RSA_new(); bn = BN_new(); mem = BIO_new(BIO_s_mem()); if(rsa == NULL || bn == NULL || mem == NULL) { printf("Not enougth memory.\n"); goto out; } if(!BN_set_word(bn, RSA_F4) || !RSA_generate_key_ex(rsa, keylen, bn, NULL)) #else rsa = RSA_generate_key(keylen, RSA_F4, NULL, NULL); mem = BIO_new(BIO_s_mem()); if(mem == NULL) { printf("Not enougth memory.\n"); goto out; } if (!rsa) #endif { printf("RSA_generate_key_ex return %ld\n", ERR_get_error()); goto out; } RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); if(!i2d_RSAPrivateKey_bio(mem, rsa)) { printf("i2d_RSAPrivateKey_bio return %ld\n", ERR_get_error()); goto out; } lg = BIO_get_mem_data(mem, &pdata); sc_format_path("0001", &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("Not enougth memory.\n"); goto out; } file->type = SC_FILE_TYPE_WORKING_EF; file->ef_structure = SC_FILE_EF_TRANSPARENT; file->shareable = 0; file->size = ((lg/4)+1)*4; r = sc_file_add_acl_entry(file, SC_AC_OP_READ, SC_AC_CHV, 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; printf("File key creation %s, size %"SC_FORMAT_LEN_SIZE_T"d.\n", file->path.value, file->size); r = sc_create_file(card, file); if(r) goto out; } else { if(!overwrite) { printf("Key file already exist,"\ " use -o to replace it.\n"); goto out; } } printf("Private key length is %"SC_FORMAT_LEN_SIZE_T"d\n", lg); printf("Write private key.\n"); r = sc_update_binary(card,0,pdata,lg,0); if(r<0) goto out; printf("Private key correctly written.\n"); r = create_file_cert(card); if(r) goto out; { const BIGNUM *rsa_n, *rsa_e; RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); if (!do_convert_bignum(&dst->modulus, rsa_n) || !do_convert_bignum(&dst->exponent, rsa_e)) goto out; } r = sc_pkcs15_encode_pubkey(ctx, &key, &pdata, &lg); if(r) goto out; printf("Public key length %"SC_FORMAT_LEN_SIZE_T"d\n", lg); sc_format_path("3F000002", &path); r = sc_select_file(card, &path, NULL); if(r) goto out; printf("Write public key.\n"); r = sc_update_binary(card,0,pdata,lg,0); if(r<0) goto out; printf("Public key correctly written.\n"); } if(cert) { BIO *bio; X509 *xp; u8 *pdata; bio = BIO_new(BIO_s_file()); if (BIO_read_filename(bio, cert) <= 0) { BIO_free(bio); printf("Can't open file %s.\n", cert); goto out; } xp = PEM_read_bio_X509(bio, NULL, NULL, NULL); BIO_free(bio); if (xp == NULL) { print_openssl_error(); goto out; } else { int lg = cert2der(xp, &pdata); sc_format_path("0002", &path); r = sc_select_file(card, &path, NULL); if(r) goto out; /* FIXME: verify if the file has a compatible size... */ printf("Write certificate %s.\n", cert); r = sc_update_binary(card,0,pdata,lg,0); if(r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { if(verify_pin(card, 0, pin)) { printf("Wrong pin.\n"); } else { r = sc_update_binary(card,0,pdata,lg,0); } } if(r<0) { if(pdata) free(pdata); goto out; } if(xp) X509_free(xp); if(pdata) free(pdata); printf("Certificate correctly written.\n"); } } if(finalize) { int mode = SC_CARDCTRL_LIFECYCLE_USER; if(card->atr.value[10] != 0x82) { sc_format_path("0001", &path); r = sc_select_file(card, &path, NULL); if(r) { printf("This card don't have private key"\ " and can't be finalize.\n"); goto out; } printf("Finalize card...\n"); if(sc_card_ctl(card, SC_CARDCTL_WESTCOS_AUT_KEY, NULL) || sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &mode)) { printf("Error finalizing card,"\ " card isn't secure.\n"); goto out; } } printf("Card correctly finalized.\n"); } if(get_filename) { FILE *fp; u8 *b; if(file) { sc_file_free(file); file = NULL; } sc_format_path(get_filename, &path); r = sc_select_file(card, &path, &file); if(r) { printf("Error file not found.\n"); goto out; } b = malloc(file->size); if(b == NULL) { printf("Not enougth memory.\n"); goto out; } r = sc_read_binary(card, 0, b, file->size, 0); if(r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { if(verify_pin(card, 0, pin)) { printf("Wrong pin.\n"); goto out; } r = sc_read_binary(card, 0, b, file->size, 0); } if(r<0) { printf("Error reading file.\n"); goto out; } fp = fopen(get_filename, "wb"); fwrite(b, 1, file->size, fp); fclose(fp); free(b); } if(put_filename) { FILE *fp; u8 *b; if(file) { sc_file_free(file); file = NULL; } sc_format_path(put_filename, &path); r = sc_select_file(card, &path, &file); if(r) { printf("File not found.\n"); goto out; } b = malloc(file->size); if(b == NULL) { printf("Not enougth memory.\n"); goto out; } memset(b, 0, file->size); fp = fopen(put_filename, "rb"); fread(b, 1, file->size, fp); fclose(fp); r = sc_update_binary(card, 0, b, file->size, 0); if(r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { if(verify_pin(card, 0, pin)) { printf("Wrong pin.\n"); } else { r = sc_update_binary(card, 0, b, file->size, 0); } } if(r<0) { free(b); printf("Error writing file.\n"); goto out; } free(b); } out: if(mem) BIO_free(mem); if(bn) BN_free(bn); if(rsa) RSA_free(rsa); if(file) sc_file_free(file); if (card) { sc_unlock(card); sc_disconnect_card(card); } sc_release_context(ctx); return EXIT_SUCCESS; }
static int cflex_create_pin_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_path_t *df_path, int ref, const u8 *pin, size_t pin_len, int pin_tries, const u8 *puk, size_t puk_len, int puk_tries, sc_file_t **file_ret, int unprotected) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_object *pin_obj = NULL; unsigned char buffer[23]; sc_path_t path; sc_file_t *dummies[2], *file; int r, ndummies; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); if (file_ret) *file_ret = NULL; /* Build the CHV path */ path = *df_path; path.value[path.len++] = ref - 1; path.value[path.len++] = 0; /* See if the CHV already exists */ r = sc_select_file(p15card->card, &path, NULL); if (r >= 0) return SC_ERROR_FILE_ALREADY_EXISTS; /* Get the file definition from the profile */ if (sc_profile_get_file_by_path(profile, &path, &file) < 0 && sc_profile_get_file(profile, (ref == 1)? "CHV1" : "CHV2", &file) < 0 && sc_profile_get_file(profile, "CHV", &file) < 0) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND, "profile does not define pin file ACLs"); file->path = path; file->size = 23; file->id = (ref == 1)? 0x0000 : 0x0100; if (unprotected) { sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, SC_AC_NONE, SC_AC_KEY_REF_NONE); } /* Build the contents of the file */ buffer[0] = buffer[1] = buffer[2] = 0xFF; put_pin(profile, buffer + 3, pin, pin_len, pin_tries); put_pin(profile, buffer + 13, puk, puk_len, puk_tries); /* For updating the file, create a dummy CHV files if * necessary */ ndummies = cflex_create_dummy_chvs(profile, p15card, file, SC_AC_OP_UPDATE, dummies); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, ndummies, "Unable to create dummy CHV file"); if (!unprotected) { struct sc_pin_cmd_data pin_cmd; memset(&pin_cmd, 0, sizeof(pin_cmd)); pin_cmd.cmd = SC_PIN_CMD_VERIFY; pin_cmd.pin_type = SC_AC_CHV; pin_cmd.pin_reference = ref; pin_cmd.pin1.data = dummy_pin_value; pin_cmd.pin1.len = sizeof(dummy_pin_value); r = sc_pin_cmd(p15card->card, &pin_cmd, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot verify dummy PIN"); }; if (ref == 2) { /* Cache dummy SOPIN value */ r = sc_pkcs15_find_pin_by_type_and_reference(p15card, NULL, SC_AC_CHV, ref, &pin_obj); if (!r && pin_obj) sc_pkcs15_pincache_add(p15card, pin_obj, dummy_pin_value, sizeof(dummy_pin_value)); } r = sc_pkcs15init_create_file(profile, p15card, file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Failed to create PIN file"); r = sc_update_binary(p15card->card, 0, buffer, 23, 0); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Failed to update PIN file"); if (r < 0 || file_ret == NULL) sc_file_free(file); else *file_ret = file; /* Delete the dummy CHV files */ cflex_delete_dummy_chvs(profile, p15card, ndummies, dummies); if (pin_obj) { /* Cache new SOPIN value */ sc_pkcs15_pincache_add(p15card, pin_obj, pin, pin_len); } SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r); }
static int entersafe_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card) { struct sc_card *card = p15card->card; int ret; {/* MF */ sc_file_t *mf_file; sc_entersafe_create_data mf_data; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ret = sc_profile_get_file(profile, "MF", &mf_file); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,ret,"Get MF info failed"); mf_data.type = SC_ENTERSAFE_MF_DATA; mf_data.data.df.file_id[0]=0x3F; mf_data.data.df.file_id[1]=0x00; mf_data.data.df.file_count=0x04; mf_data.data.df.flag=0x11; mf_data.data.df.ikf_size[0]=(mf_file->size>>8)&0xFF; mf_data.data.df.ikf_size[1]=mf_file->size&0xFF; mf_data.data.df.create_ac=0x10; mf_data.data.df.append_ac=0xC0; mf_data.data.df.lock_ac=0x10; memcpy(mf_data.data.df.aid,mf_file->name,mf_file->namelen); sc_file_free(mf_file); ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &mf_data); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,ret,"Create MF failed"); } {/* EF(DIR) */ sc_file_t *dir_file; size_t fid,size; sc_entersafe_create_data ef_data; u8 *buff=0; /* get dir profile */ ret = sc_profile_get_file(profile, "dir", &dir_file); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,ret,"Get EF(DIR) info failed"); fid=dir_file->id; size=dir_file->size; sc_file_free(dir_file); ef_data.type=SC_ENTERSAFE_EF_DATA; ef_data.data.ef.file_id[0]=(fid>>8)&0xFF; ef_data.data.ef.file_id[1]=fid&0xFF; ef_data.data.ef.size[0]=(size>>8)&0xFF; ef_data.data.ef.size[1]=size&0xFF; ef_data.data.ef.attr[0]=0x00; ef_data.data.ef.attr[1]=0x00; ef_data.data.ef.name=0x00; memset(ef_data.data.ef.ac,0x10,sizeof(ef_data.data.ef.ac)); memset(ef_data.data.ef.sm,0x00,sizeof(ef_data.data.ef.sm)); ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &ef_data); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,ret,"Create EF(DIR) failed"); /* fill file by 0 */ buff = calloc(1,size); if(!buff) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); memset(buff,0,size); ret = sc_update_binary(card,0,buff,size,0); free(buff); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL,ret,"Initialize EF(DIR) failed"); } SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); }
static int do_put(int argc, char **argv) { u8 buf[256]; int r, err = 0; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file; const char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) goto usage; if (arg_to_path(argv[0], &path, 0) != 0) goto usage; if (argc == 2) filename = argv[1]; else { sprintf((char *) buf, "%02X%02X", path.value[0], path.value[1]); filename = (char *) buf; } outf = fopen(filename, "rb"); if (outf == NULL) { perror(filename); return -1; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); fclose(outf); return -1; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = fread(buf, 1, c, outf); if (r < 0) { perror("fread"); err = 1; 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); err = 1; goto err; } if (r != c) { printf("expecting %d, wrote only %d bytes.\n", c, r); err = 1; goto err; } idx += c; count -= c; } printf("Total of %d bytes written.\n", idx); err: 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); } if (outf) fclose(outf); return -err; usage: printf("Usage: put <file id> [input file]\n"); return -1; }
static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_pkcs15_object *obj, struct sc_pkcs15_der *content, struct sc_path *path) { sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; sc_file_t *file; sc_pkcs15_cert_info_t *cinfo; sc_pkcs15_id_t *cid; sc_pkcs15_data_info_t *dinfo; u8 buf[254]; int r; LOG_FUNC_CALLED(card->ctx); switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) { case SC_PKCS15_TYPE_PRKEY: case SC_PKCS15_TYPE_PUBKEY: /* For these two type, store_data just don't need to do anything. * All have been done already before this function is called */ r = SC_SUCCESS; break; case SC_PKCS15_TYPE_CERT: cinfo = (sc_pkcs15_cert_info_t *) obj->data; cid = &(cinfo->id); if (cid->len != 1) { sc_log(card->ctx, "ID=%s is not valid.", sc_dump_hex(cid->value, cid->len)); LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); } /* OpenPGP card v.2 contains only 1 certificate */ if (cid->value[0] != 3) { sc_log(card->ctx, "This version does not support certificate ID = %d (only ID=3 is supported).", cid->value[0]); LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); } /* Just update the certificate DO */ sc_format_path("7F21", path); r = sc_select_file(card, path, &file); LOG_TEST_RET(card->ctx, r, "Cannot select cert file"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); sc_log(card->ctx, "Data to write is %d long", content->len); if (r >= 0 && content->len) r = sc_put_data(p15card->card, 0x7F21, (const unsigned char *) content->value, content->len); break; case SC_PKCS15_TYPE_DATA_OBJECT: dinfo = (sc_pkcs15_data_info_t *) obj->data; /* dinfo->app_label contains filename */ sc_log(ctx, "===== App label %s", dinfo->app_label); /* Currently, we only support DO 0101. The reason is that when initializing this * pkcs15 emulation, PIN authentication is not applied and we can expose only this DO, * which is "read always". * If we support other DOs, they will not be exposed, and not helpful to user. * I haven't found a way to refresh the list of exposed DOs after verifying PIN yet. * http://sourceforge.net/mailarchive/message.php?msg_id=30646373 **/ sc_log(ctx, "About to write to DO 0101"); sc_format_path("0101", path); r = sc_select_file(card, path, &file); LOG_TEST_RET(card->ctx, r, "Cannot select private DO"); r = sc_read_binary(card, 0, buf, sizeof(buf), 0); if (r < 0) { sc_log(ctx, "Cannot read DO 0101"); break; } if (r > 0) { sc_log(ctx, "DO 0101 is full."); r = SC_ERROR_TOO_MANY_OBJECTS; break; } r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); if (r >= 0 && content->len) { r = sc_update_binary(p15card->card, 0, (const unsigned char *) content->value, content->len, 0); } break; default: r = SC_ERROR_NOT_IMPLEMENTED; } LOG_FUNC_RETURN(card->ctx, r); }