Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP4:Update
opensc.35661
opensc-CVE-2023-40661-4of12.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File opensc-CVE-2023-40661-4of12.patch of Package opensc.35661
From aadd82bb071e574fc57263a103e3bf06ebbd8de7 Mon Sep 17 00:00:00 2001 From: "Ingo Struck (git commits)" <gitlab@ingostruck.de> Date: Sat, 21 Jan 2023 22:15:10 +0100 Subject: [PATCH] Handle reader limits for SC Card unwrap operations Fixes #2514 --- src/libopensc/card-sc-hsm.c | 181 ++++++++++++++++++++++++-------------------- src/libopensc/reader-pcsc.c | 90 +++++++++++++-------- 2 files changed, 157 insertions(+), 114 deletions(-) --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -144,9 +144,7 @@ static int sc_hsm_select_file_ex(sc_card if (file_out == NULL) { // Versions before 0.16 of the SmartCard-HSM do not support P2='0C' rv = sc_hsm_select_file_ex(card, in_path, forceselect, &file); - if (file != NULL) { - sc_file_free(file); - } + sc_file_free(file); return rv; } @@ -180,9 +178,7 @@ static int sc_hsm_select_file_ex(sc_card LOG_TEST_RET(card->ctx, rv, "Could not select SmartCard-HSM application"); if (priv) { - if (priv->dffcp != NULL) { - sc_file_free(priv->dffcp); - } + sc_file_free(priv->dffcp); // Cache the FCP returned when selecting the applet sc_file_dup(&priv->dffcp, *file_out); } @@ -729,12 +725,12 @@ static int sc_hsm_pin_cmd(sc_card_t *car u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE]; #ifdef ENABLE_SM if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) { - sc_log(card->ctx, + sc_log(card->ctx, "Session PIN generation only supported in SM"); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } #else - sc_log(card->ctx, + sc_log(card->ctx, "Session PIN generation only supported in SM"); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); #endif @@ -745,7 +741,7 @@ static int sc_hsm_pin_cmd(sc_card_t *car apdu.le = 0; if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS || sc_check_sw(card, apdu.sw1, apdu.sw2) != SC_SUCCESS) { - sc_log(card->ctx, + sc_log(card->ctx, "Generating session PIN failed"); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } @@ -755,12 +751,12 @@ static int sc_hsm_pin_cmd(sc_card_t *car apdu.resplen); data->pin2.len = apdu.resplen; } else { - sc_log(card->ctx, + sc_log(card->ctx, "Buffer too small for session PIN"); } } } else { - sc_log(card->ctx, + sc_log(card->ctx, "Session PIN not supported for this PIN (0x%02X)", data->pin_reference); } @@ -847,47 +843,61 @@ static int sc_hsm_write_ef(sc_card_t *ca LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } - p = cmdbuff; - *p++ = 0x54; - *p++ = 0x02; - *p++ = (idx >> 8) & 0xFF; - *p++ = idx & 0xFF; - *p++ = 0x53; - if (count < 128) { - *p++ = (u8) count; - len = 6; - } else if (count < 256) { - *p++ = 0x81; - *p++ = (u8) count; - len = 7; - } else { - *p++ = 0x82; - *p++ = (count >> 8) & 0xFF; - *p++ = count & 0xFF; - len = 8; - } + size_t bytes_left = count; + // 8 bytes are required for T54(4) and T53(4) + size_t blk_size = card->max_send_size - 8; + size_t to_send = 0; + size_t offset = (size_t) idx; + do { + len = 0; + to_send = bytes_left >= blk_size ? blk_size : bytes_left; + p = cmdbuff; + // ASN1 0x54 offset + *p++ = 0x54; + *p++ = 0x02; + *p++ = (offset >> 8) & 0xFF; + *p++ = offset & 0xFF; + // ASN1 0x53 to_send + *p++ = 0x53; + if (to_send < 128) { + *p++ = (u8)to_send; + len = 6; + } else if (to_send < 256) { + *p++ = 0x81; + *p++ = (u8)to_send; + len = 7; + } else { + *p++ = 0x82; + *p++ = (to_send >> 8) & 0xFF; + *p++ = to_send & 0xFF; + len = 8; + } - if (buf != NULL) - memcpy(p, buf, count); - len += count; + if (buf != NULL) + memcpy(p, buf+offset, to_send); + len += to_send; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, fid >> 8, fid & 0xFF); + apdu.data = cmdbuff; + apdu.datalen = len; + apdu.lc = len; - sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, fid >> 8, fid & 0xFF); - apdu.data = cmdbuff; - apdu.datalen = len; - apdu.lc = len; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(ctx, r, "Check SW error"); - r = sc_transmit_apdu(card, &apdu); - free(cmdbuff); - LOG_TEST_RET(ctx, r, "APDU transmit failed"); + bytes_left -= to_send; + offset += to_send; + } while (0 < bytes_left); - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_RET(ctx, r, "Check SW error"); +err: + free(cmdbuff); LOG_FUNC_RETURN(ctx, count); } - static int sc_hsm_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) @@ -1249,7 +1259,7 @@ static int sc_hsm_initialize(sc_card_t * return SC_ERROR_INVALID_ARGUMENTS; } *p++ = 0x81; // User PIN - *p++ = (u8) params->user_pin_len; + *p++ = (u8)params->user_pin_len; memcpy(p, params->user_pin, params->user_pin_len); p += params->user_pin_len; @@ -1415,12 +1425,11 @@ static int sc_hsm_unwrap_key(sc_card_t * LOG_FUNC_CALLED(card->ctx); - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT, 0x74, params->key_id, 0x93); - apdu.cla = 0x80; - apdu.lc = params->wrapped_key_length; - apdu.data = params->wrapped_key; - apdu.datalen = params->wrapped_key_length; + r = sc_hsm_write_ef(card, 0x2F10, 0, params->wrapped_key, params->wrapped_key_length); + LOG_TEST_RET(card->ctx, r, "Create EF failed"); + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x74, params->key_id, 0x93); + apdu.cla = 0x80; r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(ctx, r, "APDU transmit failed"); @@ -1612,17 +1621,10 @@ static int sc_hsm_init(struct sc_card *c int flags,ext_flags; sc_file_t *file = NULL; sc_path_t path; - sc_hsm_private_data_t *priv = card->drv_data; + sc_hsm_private_data_t *priv = NULL; LOG_FUNC_CALLED(card->ctx); - if (!priv) { - priv = calloc(1, sizeof(sc_hsm_private_data_t)); - if (!priv) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); - card->drv_data = priv; - } - flags = SC_ALGORITHM_RSA_RAW|SC_ALGORITHM_RSA_PAD_PSS|SC_ALGORITHM_ONBOARD_KEY_GEN; _sc_card_add_rsa_alg(card, 1024, flags, 0); @@ -1654,6 +1656,46 @@ static int sc_hsm_init(struct sc_card *c card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT|SC_CARD_CAP_ISO7816_PIN_INFO; + // APDU Buffer limits + // JCOP 2.4.1r3 1462 + // JCOP 2.4.2r3 1454 + // JCOP 3 1232 + // MicroSD with JCOP 3 478 / 506 - handled in reader-pcsc.c + // Reiner SCT 1014 - handled in reader-pcsc.c + + // Use JCOP 3 card limits for sending + card->max_send_size = 1232; + // Assume that card supports sending with extended length APDU and without limit + card->max_recv_size = 0; + + if (card->type == SC_CARD_TYPE_SC_HSM_SOC + || card->type == SC_CARD_TYPE_SC_HSM_GOID) { + card->max_recv_size = 0x0630; // SoC Proxy forces this limit + } else { + // Adjust to the limits set by the reader + if (card->reader->max_send_size < card->max_send_size) { + if (18 >= card->reader->max_send_size) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCONSISTENT_CONFIGURATION); + + // 17 byte header and TLV because of odd ins in UPDATE BINARY + card->max_send_size = card->reader->max_send_size - 17; + } + + if (0 < card->reader->max_recv_size) { + if (3 >= card->reader->max_recv_size) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCONSISTENT_CONFIGURATION); + card->max_recv_size = card->reader->max_recv_size - 2; + } + } + + priv = card->drv_data; + if (!priv) { + priv = calloc(1, sizeof(sc_hsm_private_data_t)); + if (!priv) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + card->drv_data = priv; + } + sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); if (sc_hsm_select_file_ex(card, &path, 0, &file) == SC_SUCCESS && file && file->prop_attr && file->prop_attr_len >= 2) { @@ -1686,25 +1728,6 @@ static int sc_hsm_init(struct sc_card *c } sc_file_free(file); - // APDU Buffer limits - // JCOP 2.4.1r3 1462 - // JCOP 2.4.2r3 1454 - // JCOP 3 1232 - // MicroSD with JCOP 3 478 / 506 - // Reiner SCT 1014 - - card->max_send_size = 1232 - 17; // 1232 buffer size - 17 byte header and TLV because of odd ins in UPDATE BINARY - - if (!strncmp("Secure Flash Card", card->reader->name, 17)) { - card->max_send_size = 478 - 17; - card->max_recv_size = 506 - 2; - } else if (card->type == SC_CARD_TYPE_SC_HSM_SOC - || card->type == SC_CARD_TYPE_SC_HSM_GOID) { - card->max_recv_size = 0x0630; // SoC Proxy forces this limit - } else { - card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit - } - priv->EF_C_DevAut = NULL; priv->EF_C_DevAut_len = 0; @@ -1730,13 +1753,11 @@ static int sc_hsm_finish(sc_card_t * car #ifdef ENABLE_SM sc_sm_stop(card); #endif - if (priv->serialno) { + if (priv) { free(priv->serialno); - } - if (priv->dffcp) { sc_file_free(priv->dffcp); + free(priv->EF_C_DevAut); } - free(priv->EF_C_DevAut); free(priv); return SC_SUCCESS; --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -309,7 +309,7 @@ static int pcsc_transmit(sc_reader_t *re * The buffer for the returned data needs to be at least 2 bytes * larger than the expected data length to store SW1 and SW2. */ rsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2; - rbuf = malloc(rbuflen); + rbuf = malloc(rbuflen); if (rbuf == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto out; @@ -384,7 +384,7 @@ static int refresh_attributes(sc_reader_ } LOG_FUNC_RETURN(reader->ctx, SC_SUCCESS); } - + /* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */ if (rv == (LONG)SCARD_E_UNKNOWN_READER #ifdef SCARD_E_NO_READERS_AVAILABLE @@ -424,7 +424,7 @@ static int refresh_attributes(sc_reader_ if (priv->reader_state.cbAtr > SC_MAX_ATR_SIZE) return SC_ERROR_INTERNAL; - /* Some cards have a different cold (after a powerup) and warm (after a reset) ATR */ + /* Some cards have a different cold (after a powerup) and warm (after a reset) ATR */ if (memcmp(priv->reader_state.rgbAtr, reader->atr.value, priv->reader_state.cbAtr) != 0) { reader->atr.len = priv->reader_state.cbAtr; memcpy(reader->atr.value, priv->reader_state.rgbAtr, reader->atr.len); @@ -553,7 +553,7 @@ static int pcsc_reconnect(sc_reader_t * priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED, protocol, action, &active_proto); - + PCSC_TRACE(reader, "SCardReconnect returned", rv); if (rv != SCARD_S_SUCCESS) { PCSC_TRACE(reader, "SCardReconnect failed", rv); @@ -590,7 +590,7 @@ static void initialize_uid(sc_reader_t * sc_log_hex(reader->ctx, "UID", reader->uid.value, reader->uid.len); } else { - sc_log(reader->ctx, "unable to get UID"); + sc_log(reader->ctx, "unable to get UID"); } } } @@ -1250,11 +1250,11 @@ static void detect_reader_features(sc_re sc_log(ctx, "Reader has a display: %04X", caps->wLcdLayout); reader->capabilities |= SC_READER_CAP_DISPLAY; } - else { + else { sc_log(ctx, "Reader does not have a display."); } } - else { + else { sc_log(ctx, "Returned PIN properties structure has bad length (%lu/%"SC_FORMAT_LEN_SIZE_T"u)", (unsigned long)rcount, @@ -1276,34 +1276,56 @@ static void detect_reader_features(sc_re } } + size_t max_send_size = 0; + size_t max_recv_size = 0; if (priv->get_tlv_properties) { /* Try to set reader max_send_size and max_recv_size based on * detected max_data */ - int max_data = part10_detect_max_data(reader, card_handle); - - if (max_data > 0) { - sc_log(ctx, "Reader supports transceiving %d bytes of data", - max_data); - if (!priv->gpriv->force_max_send_size) - reader->max_send_size = max_data; - else - sc_log(ctx, "Sending is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data" - " in configuration file", reader->max_send_size); - if (!priv->gpriv->force_max_recv_size) - reader->max_recv_size = max_data; - else - sc_log(ctx, "Receiving is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data" - " in configuration file", reader->max_recv_size); - } else { - sc_log(ctx, "Assuming that the reader supports transceiving " - "short length APDUs only"); - } + max_send_size = max_recv_size = part10_detect_max_data(reader, card_handle); /* debug the product and vendor ID of the reader */ part10_get_vendor_product(reader, card_handle, NULL, NULL); } + else { + /* Try to set default limits based on device name */ + if (!strncmp("REINER SCT cyberJack", reader->name, 20)) { + max_send_size = 1014; + max_recv_size = 1014; + } + else if (!strncmp("Secure Flash Card", reader->name, 17)) { + max_send_size = 478; + max_recv_size = 506; + } + } + + if (max_send_size > 0) { + sc_log(ctx, "Reader supports sending %"SC_FORMAT_LEN_SIZE_T"u bytes of data", + max_send_size); + if (!priv->gpriv->force_max_send_size) + reader->max_send_size = max_send_size; + else + sc_log(ctx, "Sending is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data" + " in configuration file", reader->max_send_size); + } else { + sc_log(ctx, "Assuming that the reader supports sending " + "short length APDUs only"); + } + + if (max_recv_size > 0) { + sc_log(ctx, "Reader supports receiving %"SC_FORMAT_LEN_SIZE_T"u bytes of data", + max_recv_size); + if (!priv->gpriv->force_max_recv_size) + reader->max_recv_size = max_recv_size; + else + sc_log(ctx, "Receiving is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data" + " in configuration file", reader->max_recv_size); + } else { + sc_log(ctx, "Assuming that the reader supports receiving " + "short length APDUs only"); + } + + if (gpriv->SCardGetAttrib != NULL) { - if(gpriv->SCardGetAttrib != NULL) { rcount = sizeof(rbuf.buf); if (gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_NAME, rbuf.buf, &rcount) == SCARD_S_SUCCESS @@ -1314,7 +1336,7 @@ static void detect_reader_features(sc_re } rcount = sizeof i; - if(gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_IFD_VERSION, + if (gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_IFD_VERSION, (u8 *) &i, &rcount) == SCARD_S_SUCCESS && rcount == sizeof i) { reader->version_major = (i >> 24) & 0xFF; @@ -1324,7 +1346,7 @@ static void detect_reader_features(sc_re } int pcsc_add_reader(sc_context_t *ctx, - char *reader_name, size_t reader_name_len, + char *reader_name, size_t reader_name_len, sc_reader_t **out_reader) { int ret = SC_ERROR_INTERNAL; @@ -1584,7 +1606,7 @@ static int pcsc_wait_for_event(sc_contex LOG_FUNC_CALLED(ctx); - if (!event_reader && !event && reader_states) { + if (!event_reader && !event && reader_states) { sc_log(ctx, "free allocated reader states"); free(*reader_states); *reader_states = NULL; @@ -1694,7 +1716,7 @@ static int pcsc_wait_for_event(sc_contex state = rsp->dwEventState; rsp->dwCurrentState = rsp->dwEventState; if (state & SCARD_STATE_CHANGED) { - /* check for hotplug events */ + /* check for hotplug events */ if (!strcmp(rsp->szReader, "\\\\?PnP?\\Notification")) { sc_log(ctx, "detected hotplug event"); /* Windows sends hotplug event on both, attaching and @@ -1865,7 +1887,7 @@ static int part10_build_verify_pin_block u8 tmp; unsigned int tmp16; unsigned int off; - PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf; + PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf; /* PIN verification control message */ pin_verify->bTimerOut = SC_CCID_PIN_TIMEOUT; @@ -1964,7 +1986,7 @@ static int part10_build_modify_pin_block sc_apdu_t *apdu = data->apdu; u8 tmp; unsigned int tmp16; - PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf; + PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf; struct sc_pin_cmd_pin *pin_ref = data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? &data->pin2 : &data->pin1; @@ -2550,7 +2572,7 @@ int pcsc_use_reader(sc_context_t *ctx, v gpriv->attached_reader = NULL; gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle; - card_handle = *(SCARDHANDLE *)pcsc_card_handle; + card_handle = *(SCARDHANDLE *)pcsc_card_handle; if(SCARD_S_SUCCESS == gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_DEVICE_SYSTEM_NAME_A, (LPBYTE)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor