int sc_write_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) LOG_FUNC_RETURN(card->ctx, 0); if (card->ops->write_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_write_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_write_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->write_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
int sc_write_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; assert(card != NULL && card->ops != NULL && buf != NULL); sc_log(card->ctx, "called; %d bytes at index %d", count, idx); if (count == 0) LOG_FUNC_RETURN(card->ctx, 0); if (card->ops->write_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_write_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_write_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->write_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
int sc_write_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->write_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_write_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_write_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->write_binary(card, idx, buf, count, flags); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); }
/* * Initialize pin file */ static int gpk_init_pinfile(struct sc_profile *profile, sc_pkcs15_card_t *p15card, sc_file_t *file) { const sc_acl_entry_t *acl; unsigned char buffer[GPK_MAX_PINS * 8], *blk; struct sc_file *pinfile; unsigned int so_attempts[2], user_attempts[2]; unsigned int npins, i, j, cks; int r; SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE); /* Set defaults */ so_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PIN); so_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PUK); user_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PIN); user_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PUK); sc_file_dup(&pinfile, file); if (pinfile == NULL) return SC_ERROR_OUT_OF_MEMORY; /* Create the PIN file. */ acl = sc_file_get_acl_entry(pinfile, SC_AC_OP_WRITE); if (acl->method != SC_AC_NEVER) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "PIN file most be protected by WRITE=NEVER"); sc_file_free(pinfile); return SC_ERROR_INVALID_ARGUMENTS; } sc_file_add_acl_entry(pinfile, SC_AC_OP_WRITE, SC_AC_NONE, 0); if (pinfile->size == 0) pinfile->size = GPK_MAX_PINS * 8; sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Now create file"); /* Now create the file */ if ((r = sc_pkcs15init_create_file(profile, p15card, pinfile)) < 0 || (r = sc_select_file(p15card->card, &pinfile->path, NULL)) < 0) { goto out; } /* Set up the PIN file contents. * We assume the file will contain pairs of PINs/PUKs */ npins = pinfile->size / 8; memset(buffer, 0, sizeof(buffer)); for (i = 0, blk = buffer; i < npins; blk += 8, i += 1) { /* Determine the number of PIN/PUK presentation * attempts. If the profile defines a SO PIN, * it will be stored in the first PIN/PUK pair. */ blk[0] = user_attempts[i & 1]; if (i < 2 && so_attempts[0]) blk[0] = so_attempts[i & 1]; if ((i & 1) == 0) { /* This is a PIN. If there's room in the file, * the next will be a PUK so take note of the * unlock code */ if (i + 1 < npins) blk[2] = GPK_PIN_SCOPE | (i + 1); } /* Compute the CKS */ for (j = 0, cks = 0; j < 8; j++) cks ^= blk[j]; blk[3] = ~cks; } r = sc_write_binary(p15card->card, 0, buffer, npins * 8, 0); if (r >= 0) r = gpk_lock_pinfile(profile, p15card, pinfile); out: sc_file_free(pinfile); SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r); }
int write_binary_rec(sc_card_t *card, unsigned char sfid, u8 *ef, size_t ef_len) { int r; size_t write = MAX_SM_APDU_DATA_SIZE, wrote = 0; sc_apdu_t apdu; #ifdef ENABLE_SM struct iso_sm_ctx *iso_sm_ctx = card->sm_ctx.info.cmd_data; #endif if (!card) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } #ifdef ENABLE_SM if (write > SC_MAX_APDU_BUFFER_SIZE-2 || (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT && write > (((SC_MAX_APDU_BUFFER_SIZE-2 /* for encrypted APDUs we usually get authenticated status * bytes (4B), a MAC (11B) and a cryptogram with padding * indicator (3B without data). The cryptogram is always * padded to the block size. */ -18) / iso_sm_ctx->block_length) * iso_sm_ctx->block_length - 1))) sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT, ISO_WRITE_BINARY, ISO_P1_FLAG_SFID|sfid, 0); else #endif sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, ISO_WRITE_BINARY, ISO_P1_FLAG_SFID|sfid, 0); if (write > ef_len) { apdu.datalen = ef_len; apdu.lc = ef_len; } else { apdu.datalen = write; apdu.lc = write; } apdu.data = ef; r = sc_transmit_apdu(card, &apdu); /* emulate the behaviour of sc_write_binary */ if (r >= 0) r = apdu.datalen; while (1) { if (r < 0 || r > ef_len) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not write EF."); goto err; } wrote += r; apdu.data += r; if (wrote >= ef_len) break; r = sc_write_binary(card, wrote, ef, write, 0); } r = SC_SUCCESS; err: return r; }