pkcs11: #439: 'SEQUENCE' of 'SET' issue when comparing cert attributes
Thanks to 'crank'. https://www.opensc-project.org/opensc/ticket/439 Some pkcs11 callers (i.e. netscape) will pass in the ASN.1 encoded SEQUENCE OF SET, while OpenSC just keeps the SET in the issuer/subject field.
This commit is contained in:
parent
16b4cb6a3f
commit
dfbc3996bf
@ -20,6 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "libopensc/log.h"
|
||||
#include "libopensc/asn1.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -807,13 +808,11 @@ pkcs15_bind_related_objects(struct pkcs15_fw_data *fw_data)
|
||||
}
|
||||
}
|
||||
|
||||
/* We deferred reading of the cert until needed, as it may be
|
||||
* a private object, so we must wait till login to read
|
||||
*/
|
||||
|
||||
/* We deferred reading of the cert until needed, as it may be
|
||||
* a private object, so we must wait till login to read */
|
||||
static int
|
||||
check_cert_data_read(struct pkcs15_fw_data *fw_data,
|
||||
struct pkcs15_cert_object *cert)
|
||||
check_cert_data_read(struct pkcs15_fw_data *fw_data, struct pkcs15_cert_object *cert)
|
||||
{
|
||||
int rv;
|
||||
struct pkcs15_pubkey_object *obj2;
|
||||
@ -823,8 +822,8 @@ check_cert_data_read(struct pkcs15_fw_data *fw_data,
|
||||
|
||||
if (cert->cert_data)
|
||||
return 0;
|
||||
if ((rv = sc_pkcs15_read_certificate(fw_data->p15_card,
|
||||
cert->cert_info, &cert->cert_data) < 0))
|
||||
rv = sc_pkcs15_read_certificate(fw_data->p15_card, cert->cert_info, &cert->cert_data);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
/* update the related public key object */
|
||||
@ -3014,6 +3013,8 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT
|
||||
}
|
||||
|
||||
|
||||
#define ASN1_SET_TAG (SC_ASN1_SET | SC_ASN1_TAG_CONSTRUCTED)
|
||||
#define ASN1_SEQ_TAG (SC_ASN1_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED)
|
||||
static int
|
||||
pkcs15_cert_cmp_attribute(struct sc_pkcs11_session *session,
|
||||
void *object, CK_ATTRIBUTE_PTR attr)
|
||||
@ -3021,38 +3022,43 @@ pkcs15_cert_cmp_attribute(struct sc_pkcs11_session *session,
|
||||
struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object;
|
||||
struct sc_pkcs11_card *p11card = session->slot->card;
|
||||
struct pkcs15_fw_data *fw_data = NULL;
|
||||
unsigned char *data = NULL;
|
||||
size_t len;
|
||||
unsigned char *data = NULL, *_data = NULL;
|
||||
size_t len, _len;
|
||||
|
||||
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[session->slot->fw_data_idx];
|
||||
if (!fw_data)
|
||||
return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetAttributeValue");
|
||||
|
||||
switch (attr->type) {
|
||||
/* Check the issuer. Some pkcs11 callers (i.e. netscape) will pass
|
||||
* in the ASN.1 encoded SEQUENCE OF SET ... while OpenSC just
|
||||
* keeps the SET in the issuer field. */
|
||||
/* Check the issuer/subject. Some pkcs11 callers (i.e. netscape) will pass
|
||||
* in the ASN.1 encoded SEQUENCE OF SET,
|
||||
* while OpenSC just keeps the SET in the issuer/subject field. */
|
||||
case CKA_ISSUER:
|
||||
if (check_cert_data_read(fw_data, cert) != 0)
|
||||
break;
|
||||
if (cert->cert_data->issuer_len == 0)
|
||||
break;
|
||||
data = (u8 *) attr->pValue;
|
||||
len = attr->ulValueLen;
|
||||
/* SEQUENCE is tag 0x30, SET is 0x31
|
||||
* I know this code is icky, but hey... this is netscape
|
||||
* we're dealing with :-) */
|
||||
if (cert->cert_data->issuer[0] == 0x31
|
||||
&& data[0] == 0x30 && len >= 2) {
|
||||
/* skip the length byte(s) */
|
||||
len = (data[1] & 0x80)? (data[1] & 0x7F) : 0;
|
||||
if (attr->ulValueLen < len + 2)
|
||||
break;
|
||||
data += len + 2;
|
||||
len = attr->ulValueLen - len - 2;
|
||||
}
|
||||
if (len == cert->cert_data->issuer_len
|
||||
&& !memcmp(cert->cert_data->issuer, data, len))
|
||||
|
||||
data = _data = (u8 *) attr->pValue;
|
||||
len = _len = attr->ulValueLen;
|
||||
if (cert->cert_data->issuer[0] == ASN1_SET_TAG && data[0] == ASN1_SEQ_TAG && len >= 2)
|
||||
data = sc_asn1_skip_tag(context, &_data, &_len, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, &len);
|
||||
|
||||
if (len == cert->cert_data->issuer_len && !memcmp(cert->cert_data->issuer, data, len))
|
||||
return 1;
|
||||
break;
|
||||
case CKA_SUBJECT:
|
||||
if (check_cert_data_read(fw_data, cert) != 0)
|
||||
break;
|
||||
if (cert->cert_data->subject_len == 0)
|
||||
break;
|
||||
|
||||
data = _data = (u8 *) attr->pValue;
|
||||
len = _len = attr->ulValueLen;
|
||||
if (cert->cert_data->subject[0] == ASN1_SET_TAG && data[0] == ASN1_SEQ_TAG && len >= 2)
|
||||
data = sc_asn1_skip_tag(context, &_data, &_len, SC_ASN1_CONS | SC_ASN1_TAG_SEQUENCE, &len);
|
||||
|
||||
if (len == cert->cert_data->subject_len && !memcmp(cert->cert_data->subject, data, len))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -72,6 +72,8 @@ enum {
|
||||
OPT_TOKEN_LABEL,
|
||||
OPT_APPLICATION_LABEL,
|
||||
OPT_APPLICATION_ID,
|
||||
OPT_ISSUER,
|
||||
OPT_SUBJECT,
|
||||
OPT_SO_PIN,
|
||||
OPT_INIT_TOKEN,
|
||||
OPT_INIT_PIN,
|
||||
@ -123,6 +125,8 @@ static const struct option options[] = {
|
||||
{ "delete-object", 0, NULL, 'b' },
|
||||
{ "application-label", 1, NULL, OPT_APPLICATION_LABEL },
|
||||
{ "application-id", 1, NULL, OPT_APPLICATION_ID },
|
||||
{ "issuer", 1, NULL, OPT_ISSUER },
|
||||
{ "subject", 1, NULL, OPT_SUBJECT },
|
||||
{ "type", 1, NULL, 'y' },
|
||||
{ "id", 1, NULL, 'd' },
|
||||
{ "label", 1, NULL, 'a' },
|
||||
@ -178,6 +182,8 @@ static const char *option_help[] = {
|
||||
"Delete an object",
|
||||
"Specify the application label of the data object (use with --type data)",
|
||||
"Specify the application ID of the data object (use with --type data)",
|
||||
"Specify the issuer in hexadecimal format (use with --type cert)",
|
||||
"Specify the subject in hexadecimal format (use with --type cert/privkey/pubkey)",
|
||||
"Specify the type of object (e.g. cert, privkey, pubkey, data)",
|
||||
"Specify the ID of the object",
|
||||
"Specify the label of the object",
|
||||
@ -225,6 +231,8 @@ static char * opt_puk = NULL;
|
||||
static char * opt_new_pin = NULL;
|
||||
static char * opt_application_label = NULL;
|
||||
static char * opt_application_id = NULL;
|
||||
static char * opt_issuer = NULL;
|
||||
static char * opt_subject = NULL;
|
||||
static char * opt_key_type = NULL;
|
||||
static int opt_is_private = 0;
|
||||
static int opt_test_hotplug = 0;
|
||||
@ -548,6 +556,12 @@ int main(int argc, char * argv[])
|
||||
case OPT_APPLICATION_ID:
|
||||
opt_application_id = optarg;
|
||||
break;
|
||||
case OPT_ISSUER:
|
||||
opt_issuer = optarg;
|
||||
break;
|
||||
case OPT_SUBJECT:
|
||||
opt_subject = optarg;
|
||||
break;
|
||||
case OPT_NEW_PIN:
|
||||
opt_new_pin = optarg;
|
||||
break;
|
||||
@ -787,7 +801,8 @@ int main(int argc, char * argv[])
|
||||
if (opt_object_class_str == NULL)
|
||||
util_fatal("You should specify type of the object to read");
|
||||
if (opt_object_id_len == 0 && opt_object_label == NULL &&
|
||||
opt_application_label == NULL && opt_application_id == NULL)
|
||||
opt_application_label == NULL && opt_application_id == NULL &&
|
||||
opt_issuer == NULL && opt_subject == NULL)
|
||||
util_fatal("You should specify at least one of the "
|
||||
"object ID, object label, application label or application ID\n");
|
||||
read_object(session);
|
||||
@ -2794,6 +2809,7 @@ static int read_object(CK_SESSION_HANDLE session)
|
||||
CK_ULONG len = 0;
|
||||
FILE *out;
|
||||
struct sc_object_id oid;
|
||||
unsigned char subject[0x400], issuer[0x400];
|
||||
|
||||
if (opt_object_class_str != NULL) {
|
||||
FILL_ATTR(attrs[nn_attrs], CKA_CLASS,
|
||||
@ -2826,6 +2842,24 @@ static int read_object(CK_SESSION_HANDLE session)
|
||||
nn_attrs++;
|
||||
}
|
||||
|
||||
if (opt_issuer != NULL) {
|
||||
size_t sz = sizeof(issuer);
|
||||
|
||||
if (sc_hex_to_bin(opt_issuer, issuer, &sz))
|
||||
util_fatal("Invalid 'issuer' hexadecimal value");
|
||||
FILL_ATTR(attrs[nn_attrs], CKA_ISSUER, issuer, sz);
|
||||
nn_attrs++;
|
||||
}
|
||||
|
||||
if (opt_subject != NULL) {
|
||||
size_t sz = sizeof(subject);
|
||||
|
||||
if (sc_hex_to_bin(opt_subject, subject, &sz))
|
||||
util_fatal("Invalid 'subject' hexadecimal value");
|
||||
FILL_ATTR(attrs[nn_attrs], CKA_SUBJECT, subject, sz);
|
||||
nn_attrs++;
|
||||
}
|
||||
|
||||
rv = find_object_with_attributes(session, &obj, attrs, nn_attrs, 0);
|
||||
if (rv != CKR_OK)
|
||||
p11_fatal("find_object_with_attributes()", rv);
|
||||
|
Loading…
Reference in New Issue
Block a user