From: Paolo Bonzini <pbonzini@redhat.com>
To: Alon Levy <alon@pobox.com>, Ray Strode <halfline@gmail.com>,
qemu-devel@nongnu.org
Cc: "Ray Strode" <rstrode@redhat.com>,
"Michael Tokarev" <mjt@tls.msk.ru>,
qemu-stable@nongnu.org, "Nalin Dahyabhai" <nalin@redhat.com>,
"Marc-André Lureau" <marcandre.lureau@gmail.com>,
"Robert Relyea" <rrelyea@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 3/3] libcacard: don't free sign buffer while sign op is pending
Date: Mon, 20 Oct 2014 20:40:43 +0200 [thread overview]
Message-ID: <5445572B.9060800@redhat.com> (raw)
In-Reply-To: <544358DA.6040000@pobox.com>
On 10/19/2014 08:23 AM, Alon Levy wrote:
> On 10/19/2014 05:12 AM, Ray Strode wrote:
>> From: Ray Strode <rstrode@redhat.com>
>>
>> commit 57f97834efe0c208ffadc9d2959f3d3d55580e52 cleaned up
>> the cac_applet_pki_process_apdu function to have a single
>> exit point. Unfortunately, that commit introduced a bug
>> where the sign buffer can get free'd and nullified while
>> it's still being used.
>>
>> This commit corrects the bug by introducing a boolean to
>> track whether or not the sign buffer should be freed in
>> the function exit path.
>
> My bad, thanks for catching this.
>
> Reviewed-by: Alon Levy <alon@pobox.com>
Please Cc qemu-stable@nongnu.org if you send a pull request.
Paolo
>
>>
>> Signed-off-by: Ray Strode <rstrode@redhat.com>
>> ---
>> libcacard/cac.c | 10 +++++++---
>> 1 file changed, 7 insertions(+), 3 deletions(-)
>>
>> diff --git a/libcacard/cac.c b/libcacard/cac.c
>> index ae8c378..f38fdce 100644
>> --- a/libcacard/cac.c
>> +++ b/libcacard/cac.c
>> @@ -88,60 +88,61 @@ cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
>> }
>>
>> /*
>> * reset the inter call state between applet selects
>> */
>> static VCardStatus
>> cac_applet_pki_reset(VCard *card, int channel)
>> {
>> VCardAppletPrivate *applet_private;
>> CACPKIAppletData *pki_applet;
>> applet_private = vcard_get_current_applet_private(card, channel);
>> assert(applet_private);
>> pki_applet = &(applet_private->u.pki_data);
>>
>> pki_applet->cert_buffer = NULL;
>> g_free(pki_applet->sign_buffer);
>> pki_applet->sign_buffer = NULL;
>> pki_applet->cert_buffer_len = 0;
>> pki_applet->sign_buffer_len = 0;
>> return VCARD_DONE;
>> }
>>
>> static VCardStatus
>> cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
>> VCardResponse **response)
>> {
>> CACPKIAppletData *pki_applet;
>> VCardAppletPrivate *applet_private;
>> int size, next;
>> unsigned char *sign_buffer;
>> + bool retain_sign_buffer = FALSE;
>> vcard_7816_status_t status;
>> VCardStatus ret = VCARD_FAIL;
>>
>> applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
>> assert(applet_private);
>> pki_applet = &(applet_private->u.pki_data);
>>
>> switch (apdu->a_ins) {
>> case CAC_UPDATE_BUFFER:
>> *response = vcard_make_response(
>> VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
>> ret = VCARD_DONE;
>> break;
>> case CAC_GET_CERTIFICATE:
>> if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
>> *response = vcard_make_response(
>> VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
>> break;
>> }
>> assert(pki_applet->cert != NULL);
>> size = apdu->a_Le;
>> if (pki_applet->cert_buffer == NULL) {
>> pki_applet->cert_buffer = pki_applet->cert;
>> pki_applet->cert_buffer_len = pki_applet->cert_len;
>> }
>> size = MIN(size, pki_applet->cert_buffer_len);
>> next = MIN(255, pki_applet->cert_buffer_len - size);
>> *response = vcard_response_new_bytes(
>> card, pki_applet->cert_buffer, size,
>> apdu->a_Le, next ?
>> @@ -151,85 +152,88 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
>> pki_applet->cert_buffer += size;
>> pki_applet->cert_buffer_len -= size;
>> if ((*response == NULL) || (next == 0)) {
>> pki_applet->cert_buffer = NULL;
>> }
>> if (*response == NULL) {
>> *response = vcard_make_response(
>> VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
>> }
>> ret = VCARD_DONE;
>> break;
>> case CAC_SIGN_DECRYPT:
>> if (apdu->a_p2 != 0) {
>> *response = vcard_make_response(
>> VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
>> break;
>> }
>> size = apdu->a_Lc;
>>
>> sign_buffer = g_realloc(pki_applet->sign_buffer,
>> pki_applet->sign_buffer_len + size);
>> memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
>> size += pki_applet->sign_buffer_len;
>> switch (apdu->a_p1) {
>> case 0x80:
>> /* p1 == 0x80 means we haven't yet sent the whole buffer, wait for
>> * the rest */
>> pki_applet->sign_buffer = sign_buffer;
>> pki_applet->sign_buffer_len = size;
>> *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
>> + retain_sign_buffer = TRUE;
>> break;
>> case 0x00:
>> /* we now have the whole buffer, do the operation, result will be
>> * in the sign_buffer */
>> status = vcard_emul_rsa_op(card, pki_applet->key,
>> sign_buffer, size);
>> if (status != VCARD7816_STATUS_SUCCESS) {
>> *response = vcard_make_response(status);
>> break;
>> }
>> *response = vcard_response_new(card, sign_buffer, size, apdu->a_Le,
>> VCARD7816_STATUS_SUCCESS);
>> if (*response == NULL) {
>> *response = vcard_make_response(
>> VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
>> }
>> break;
>> default:
>> *response = vcard_make_response(
>> VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
>> break;
>> }
>> - g_free(sign_buffer);
>> - pki_applet->sign_buffer = NULL;
>> - pki_applet->sign_buffer_len = 0;
>> + if (!retain_sign_buffer) {
>> + g_free(sign_buffer);
>> + pki_applet->sign_buffer = NULL;
>> + pki_applet->sign_buffer_len = 0;
>> + }
>> ret = VCARD_DONE;
>> break;
>> case CAC_READ_BUFFER:
>> /* new CAC call, go ahead and use the old version for now */
>> /* TODO: implement */
>> *response = vcard_make_response(
>> VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
>> ret = VCARD_DONE;
>> break;
>> default:
>> ret = cac_common_process_apdu(card, apdu, response);
>> break;
>> }
>> return ret;
>> }
>>
>>
>> static VCardStatus
>> cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
>> VCardResponse **response)
>> {
>> VCardStatus ret = VCARD_FAIL;
>>
>> switch (apdu->a_ins) {
>> case CAC_UPDATE_BUFFER:
>> *response = vcard_make_response(
>> VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
>> ret = VCARD_DONE;
>> break;
>> case CAC_READ_BUFFER:
>>
>
>
>
prev parent reply other threads:[~2014-10-20 18:41 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-19 2:12 [Qemu-devel] [PATCH 0/3] A few smartcard patches Ray Strode
2014-10-19 2:12 ` [Qemu-devel] [PATCH 1/3] libcacard: introduce new vcard_emul_logout Ray Strode
2014-10-19 2:12 ` [Qemu-devel] [PATCH 2/3] libcacard: Lock NSS cert db when selecting an applet on an emulated card Ray Strode
2014-10-19 2:12 ` [Qemu-devel] [PATCH 3/3] libcacard: don't free sign buffer while sign op is pending Ray Strode
2014-10-19 6:23 ` Alon Levy
2014-10-20 18:40 ` Paolo Bonzini [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5445572B.9060800@redhat.com \
--to=pbonzini@redhat.com \
--cc=alon@pobox.com \
--cc=halfline@gmail.com \
--cc=marcandre.lureau@gmail.com \
--cc=mjt@tls.msk.ru \
--cc=nalin@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-stable@nongnu.org \
--cc=rrelyea@redhat.com \
--cc=rstrode@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).