Пример #1
0
static int decodeKeyAttributes(unsigned char *ka, int kalen, struct p15PrivateKeyDescription *p15)
{
	int tag,len;
	unsigned char *po, *obj;

	po = obj = ka;
	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag != ASN1_SEQUENCE) || (len <= 0)) {
		return -1;
	}

	po += len;

	if ((po - ka) >= kalen) {
		return 0;
	}

	obj = po;
	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag == ASN1_INTEGER) && (len > 0)) {
		if (asn1DecodeInteger(po, len, &p15->keysize) < 0) {
			return -1;
		}
	} else {
		p15->keysize = 2048;		// Save default for key size
	}
	return 0;
}
Пример #2
0
/**
 * Decode a TLV encoded PKCS#15 private key description into a structure
 *
 * The caller must use freePrivateKeyDescription() to free the allocated structure
 *
 * @param prkd      The first byte of the encoded structure
 * @param prkdlen   The length of the encoded structure
 * @param p15       Pointer to pointer updated with the newly allocated structure
 * @return          0 if successfull, -1 for structural errors
 */
int decodePrivateKeyDescription(unsigned char *prkd, size_t prkdlen, struct p15PrivateKeyDescription **p15)
{
	int rc,tag,len;
	unsigned char *po;

	rc = asn1Validate(prkd, prkdlen);

	if (rc != 0) {
		return -1;
	}

	*p15 = calloc(1, sizeof(struct p15PrivateKeyDescription));
	if (*p15 == NULL) {
		return -1;
	}

	po = prkd;

	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag != ASN1_SEQUENCE) && (tag != 0xA0)) {
		return -1;
	}

	(*p15)->keytype = (int)tag;
	rc = decodePrivateKeyAttributes(po, len, *p15);

	return rc;
}
Пример #3
0
/**
 * Decode a TLV encoded PKCS#15 certificate description into a structure
 *
 * The caller must use freeCertificateDescription() to free the allocated structure
 *
 * @param cd        The first byte of the encoded structure
 * @param cdlen     The length of the encoded structure
 * @param p15       Pointer to pointer updated with the newly allocated structure
 * @return          0 if successful, -1 for structural errors
 */
int decodeCertificateDescription(unsigned char *cd, size_t cdlen, struct p15CertificateDescription **p15)
{
	int rc,tag,len;
	unsigned char *po;

	rc = asn1Validate(cd, cdlen);

	if (rc != 0) {
		return -1;
	}

	*p15 = calloc(1, sizeof(struct p15CertificateDescription));
	if (*p15 == NULL) {
		return -1;
	}

	po = cd;

	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag != ASN1_SEQUENCE) && (tag != 0xA0)) {
		return -1;
	}

	(*p15)->certtype = (int)tag;
	rc = decodeCertificateAttributes(po, len, *p15);

	return rc;
}
Пример #4
0
static int decodeCommonCertificateAttributes(unsigned char *cca, int ccalen, struct p15CertificateDescription *p15)
{
	int tag,len;
	unsigned char *po, *obj, *id;

	if (ccalen <= 0)
		return 0;

	po = obj = cca;
	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag != ASN1_OCTET_STRING) || (len <= 0)) {
		return -1;
	}

	id = calloc(len, 1);
	if (id == NULL) {
		return -1;
	}
	memcpy(id, po, len);
	p15->id.val = id;
	p15->id.len = len;

	po += len;

	return 0;
}
Пример #5
0
static int decodeCertificateAttributes(unsigned char *cd, int cdlen, struct p15CertificateDescription *p15)
{
	int rc,tag,len;
	unsigned char *po, *obj;

	if (cdlen <= 0) {				// Nothing to decode
		return 0;
	}

	po = obj = cd;

	tag = asn1Tag(&po);
	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	len = asn1Length(&po);

	rc = decodeCommonObjectAttributes(po, len, &p15->coa);
	if (rc < 0) {
		return rc;
	}

	po += len;

	if ((po - cd) >= cdlen) {
		return 0;
	}

	obj = po;
	tag = asn1Tag(&po);
	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	len = asn1Length(&po);

	rc = decodeCommonCertificateAttributes(po, len, p15);
	if (rc < 0) {
		return rc;
	}

	po += len;

	return 0;
}
Пример #6
0
static int decodeCommonKeyAttributes(unsigned char *cka, int ckalen, struct p15PrivateKeyDescription *p15)
{
	int tag,len;
	unsigned char *po, *obj, *id;

	if (ckalen <= 0)
		return 0;

	po = obj = cka;
	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag != ASN1_OCTET_STRING) || (len <= 0)) {
		return -1;
	}

	id = calloc(len, 1);
	if (id == NULL) {
		return -1;
	}
	memcpy(id, po, len);
	p15->id.val = id;
	p15->id.len = len;

	po += len;

	if ((po - cka) >= ckalen) {
		return 0;
	}

	obj = po;
	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag != ASN1_BIT_STRING) || (len <= 1)) {
		return -1;
	}

	asn1DecodeFlags(po + 1, len - 1, &p15->usage);
	return 0;
}
int decodeECParamsFromSPKI(unsigned char *spki,
                           CK_ATTRIBUTE_PTR ecparams)
{
	int tag, length, buflen;
	unsigned char *value, *cursor;

	cursor = spki;				// spk is ASN.1 validated before, not need to check again

	// subjectPublicKeyInfo
	tag = asn1Tag(&cursor);

	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	buflen = asn1Length(&cursor);

	// algorithm
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	cursor = value;
	buflen = length;

	// algorithm
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	if (tag != ASN1_OBJECT_IDENTIFIER) {
		return -1;
	}

	ecparams->type = CKA_EC_PARAMS;
	ecparams->pValue = cursor;

	// parameters
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	ecparams->ulValueLen = (CK_ULONG)(cursor - (unsigned char *)ecparams->pValue);

	return 0;
}
Пример #8
0
static int decodeCommonObjectAttributes(unsigned char *coa, int coalen, struct p15CommonObjectAttributes *p15)
{
	int tag,len;
	unsigned char *po;
	char *label;

	po = coa;
	tag = asn1Tag(&po);

	if (tag == ASN1_UTF8String) {
		len = asn1Length(&po);
		label = calloc(len + 1, 1);
		if (label == NULL) {
			return -1;
		}
		memcpy(label, po, len);
		p15->label = label;
	}

	return 0;
}
Пример #9
0
static int decodePrivateKeyAttributes(unsigned char *prkd, int prkdlen, struct p15PrivateKeyDescription *p15)
{
	int rc,tag,len;
	unsigned char *po, *obj;

	if (prkdlen <= 0) {				// Nothing to decode
		return 0;
	}

	po = obj = prkd;

	tag = asn1Tag(&po);
	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	len = asn1Length(&po);

	rc = decodeCommonObjectAttributes(po, len, &p15->coa);
	if (rc < 0) {
		return rc;
	}

	po += len;

	if ((po - prkd) >= prkdlen) {
		return 0;
	}

	obj = po;
	tag = asn1Tag(&po);
	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	len = asn1Length(&po);

	rc = decodeCommonKeyAttributes(po, len, p15);
	if (rc < 0) {
		return rc;
	}

	po += len;

	if ((po - prkd) >= prkdlen) {
		return 0;
	}

	obj = po;
	tag = asn1Tag(&po);
	if (tag == 0xA0) {
		len = asn1Length(&po);
		po += len;

		if ((po - prkd) >= prkdlen) {
			return 0;
		}
		obj = po;
		tag = asn1Tag(&po);
	}

	len = asn1Length(&po);
	if ((tag != 0xA1) || (len <= 0)) {
		return -1;
	}

	tag = asn1Tag(&po);
	len = asn1Length(&po);

	if ((tag != ASN1_SEQUENCE) || (len <= 0)) {
		return -1;
	}

	rc = decodeKeyAttributes(po, len, p15);
	if (rc < 0) {
		return rc;
	}

	return 0;
}
int decodeModulusExponentFromSPKI(unsigned char *spki,
                                 CK_ATTRIBUTE_PTR modulus,
                                 CK_ATTRIBUTE_PTR exponent)
{
	int tag, length, buflen;
	unsigned char *value, *cursor;

	cursor = spki;				// spk is ASN.1 validated before, not need to check again

	// subjectPublicKeyInfo
	tag = asn1Tag(&cursor);

	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	buflen = asn1Length(&cursor);

	// algorithm
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	// subjectPublicKey
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	if (tag != ASN1_BIT_STRING) {
		return -1;
	}

	if (length < 6) {
		return -1;
	}

	cursor = value + 1;
	buflen = length - 1;

	if (asn1Validate(cursor, buflen) != 0) {
		return -1;
	}

	// Outer SEQUENCE
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	if (tag != ASN1_SEQUENCE) {
		return -1;
	}

	cursor = value;
	buflen = length;

	// Modulus
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	if (tag != ASN1_INTEGER) {
		return -1;
	}

	modulus->type = CKA_MODULUS;
	modulus->pValue = value;
	modulus->ulValueLen = length;

	// Exponent
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
		return -1;
	}

	if (tag != ASN1_INTEGER) {
		return -1;
	}

	exponent->type = CKA_PUBLIC_EXPONENT;
	exponent->pValue = value;
	exponent->ulValueLen = length;

	return 0;
}
Пример #11
0
static int decodeECDSASignature(unsigned char *data, int datalen,
								unsigned char *out, int outlen)
{
	int fieldsizebytes, i, r, taglen;
	unsigned char *po, *value;

	FUNC_CALLED();

	r = asn1Validate(data, datalen);

	if (r != 0) {
		FUNC_FAILS(-1, "Signature is not a valid TLV structure");
	}

	// Determine field size from length of signature
	if (datalen <= 58) {			// 192 bit curve = 24 * 2 + 10 byte maximum DER signature
		fieldsizebytes = 24;
	} else if (datalen <= 66) {		// 224 bit curve = 28 * 2 + 10 byte maximum DER signature
		fieldsizebytes = 28;
	} else if (datalen <= 74) {		// 256 bit curve = 32 * 2 + 10 byte maximum DER signature
		fieldsizebytes = 32;
	} else if (datalen <= 90) {		// 320 bit curve = 40 * 2 + 10 byte maximum DER signature
		fieldsizebytes = 40;
	} else {
		fieldsizebytes = 64;
	}

#ifdef DEBUG
	debug("Field size %d, signature buffer size %d\n", fieldsizebytes, outlen);
#endif

	if (outlen < (fieldsizebytes * 2)) {
		FUNC_FAILS(-1, "output too small for EC signature");
	}

	memset(out, 0, outlen);

	po = data;
	if (asn1Tag(&po) != ASN1_SEQUENCE) {
		FUNC_FAILS(-1, "Signature not encapsulated in SEQUENCE");
	}

	r = asn1Length(&po);
	if ((r < 8) || (r > 137)) {
		FUNC_FAILS(-1, "Invalid signature size");
	}

	for (i = 0; i < 2; i++) {
		if (asn1Tag(&po) != ASN1_INTEGER) {
			FUNC_FAILS(-1, "Coordinate not encapsulated in INTEGER");
		}

		taglen = asn1Length(&po);
		value = po;
		po += taglen;

		if (taglen > fieldsizebytes) { /* drop leading 00 if present */
			if (*value != 0x00) {
				FUNC_FAILS(-1, "Invalid value in coordinate");
			}
			value++;
			taglen--;
		}
		memcpy(out + fieldsizebytes * i + fieldsizebytes - taglen , value, taglen);
	}
	FUNC_RETURNS(fieldsizebytes << 1);
}
Пример #12
0
int check_2pay_sys(unsigned char *rsp, int lr)
{
	char *MC_RID = "\xA0\x00\x00\x00\x04";	      /* MasterCard RID */
	char *MC_UK_RID = "\xA0\x00\x00\x00\x05";     /* MasterCard UK RID */
	char *VISA_RID = "\xA0\x00\x00\x00\x03";      /* Visa RID */
	char *AMEX_RID = "\xA0\x00\x00\x00\x25";      /* AMEX RID */
	char *DISCOVER_RID = "\xA0\x00\x00\x03\x24";  /* AMEX RID */
	char *GIROGO_RID = "\xD2\x76\x00\x00\x25";    /* Geldkarte/GiroGo RID */
	unsigned char *fci_issuer_discret_data;
	int fci_issuer_discret_data_len = 0;
	unsigned char *aid = NULL;
	int aid_len;
	unsigned char *app_template = NULL;
	int app_template_len = 0;
	unsigned char *tmp_aid = NULL;
	int tmp_aid_len;
	unsigned char *app_label = NULL;
	int app_label_len = 0;
	int priority = 15;
	unsigned char *prio = NULL;
	int prio_len;
	unsigned char *d;

	fci_issuer_discret_data = asn1Find(rsp, "\x6F\xA5\xBF\x0C", 3);
	if (fci_issuer_discret_data == NULL)
		return -1;

	asn1Tag(&fci_issuer_discret_data);
	fci_issuer_discret_data_len = asn1Length(&fci_issuer_discret_data);

	while (fci_issuer_discret_data_len > 4) {
		app_template = asn1Find(fci_issuer_discret_data, "\x61", 1);
		if (app_template == NULL)
			break;

		asn1Tag(&app_template);
		app_template_len = asn1Length(&app_template);
		d = app_template;
		/* Decode the AID */
		tmp_aid = asn1Find(d, "\x4F", 1);
		if (tmp_aid == NULL)
			return -1;

		asn1Tag(&tmp_aid);
		tmp_aid_len = asn1Length(&tmp_aid);
		d = tmp_aid + tmp_aid_len;
		/* Decode the application label */
		app_label = asn1Find(d, "\x50", 1);
		if (app_label != NULL) {
			asn1Tag(&app_label);
			app_label_len = asn1Length(&app_label);
			d = app_label + app_label_len;
		}
		/* Decode the priority */
		prio = asn1Find(d, "\x87", 1);
		if (prio != NULL) {
			asn1Tag(&prio);
			prio_len = asn1Length(&prio);
			d = prio + prio_len;

			if (*prio < priority) {
				priority = *prio;
				aid = tmp_aid;
				aid_len = tmp_aid_len;
			}
		} else {
			aid = tmp_aid;
			aid_len = tmp_aid_len;
		}

		fci_issuer_discret_data_len -= app_template_len;
		fci_issuer_discret_data = d;
	}

	if (aid == NULL)
		return -1;

	/* We need at least the first five bytes of the AID (RID) */
	if (aid_len < 5)
		return -1;

	if ((memcmp(aid, MC_RID, 5) == 0) || (memcmp(aid, MC_UK_RID, 5) == 0))
		return 1;
	else if (memcmp(aid, VISA_RID, 5) == 0)
		return 2;
	else if (memcmp(aid, AMEX_RID, 5) == 0)
		return 3;
	else if (memcmp(aid, DISCOVER_RID, 5) == 0)
		return 4;
	else if (memcmp(aid, GIROGO_RID, 5) == 0)
		return 5;

	/* AID (RID) not supported */
	return -1;
}
Пример #13
0
int starcosDigest(struct p11Token_t *token, CK_MECHANISM_TYPE mech, unsigned char *data, size_t len)
{
	int rc;
	size_t chunk;
	unsigned short SW1SW2;
	unsigned char scr[1008],*algo, *po;

	FUNC_CALLED();

	rc = getAlgorithmIdForDigest(token, mech, &algo);
	if (rc != CKR_OK) {
		FUNC_FAILS(rc, "getAlgorithmIdForDigest() failed");
	}

	po = algo;
	asn1Tag(&po);
	rc = asn1Length(&po);
	rc += (int)(po - algo);

	rc = transmitAPDU(token->slot, 0x00, 0x22, 0x41, 0xAA,
		rc, algo,
		0, NULL, 0, &SW1SW2);

	if (rc < 0) {
		FUNC_FAILS(CKR_DEVICE_ERROR, "transmitAPDU failed");
	}

	if (SW1SW2 != 0x9000) {
		FUNC_FAILS(CKR_DEVICE_ERROR, "MANAGE SE failed");
	}

	if (len <= 1000) {
		scr[0] = 0x90;
		scr[1] = 0x00;
		memcpy(scr + 2, data, len);
		rc = asn1Encap(0x80, scr + 2, (int)len) + 2;

		rc = transmitAPDU(token->slot, 0x00, 0x2A, 0x90, 0xA0,
				rc, scr,
				0, NULL, 0, &SW1SW2);

		if (rc < 0) {
			FUNC_FAILS(CKR_DEVICE_ERROR, "transmitAPDU failed");
		}

		if (SW1SW2 != 0x9000) {
			FUNC_FAILS(CKR_DEVICE_ERROR, "Hash operation failed");
		}
	} else {
		scr[0] = 0x90;
		scr[1] = 0x00;

		rc = transmitAPDU(token->slot, 0x10, 0x2A, 0x90, 0xA0,
				2, scr,
				0, NULL, 0, &SW1SW2);

		if (rc < 0) {
			FUNC_FAILS(CKR_DEVICE_ERROR, "transmitAPDU failed");
		}

		if (SW1SW2 != 0x9000) {
			FUNC_FAILS(CKR_DEVICE_ERROR, "Hash operation failed");
		}

		while (len > 0) {
			chunk = (len > (size_t)token->drv->maxHashBlock ? (size_t)token->drv->maxHashBlock : len);

			memcpy(scr, data, chunk);
			rc = asn1Encap(0x80, scr, (int)chunk);

			rc = transmitAPDU(token->slot, len > chunk ? 0x10 : 0x00, 0x2A, 0x90, 0xA0,
					rc, scr,
					0, NULL, 0, &SW1SW2);

			if (rc < 0) {
				FUNC_FAILS(CKR_DEVICE_ERROR, "transmitAPDU failed");
			}

			if (SW1SW2 != 0x9000) {
				FUNC_FAILS(CKR_DEVICE_ERROR, "Hash operation failed");
			}

			len -= chunk;
			data += chunk;
		}
	}

	return CKR_OK;
}
Пример #14
0
int starcosDeterminePinUseCounter(struct p11Token_t *token, unsigned char recref, int *useCounter, int *lifeCycle)
{
	int rc,ucpathlen;
	unsigned short SW1SW2;
	unsigned char rec[256], *p,*fid,*ucpath;
	FUNC_CALLED();

	if (token->info.firmwareVersion.minor >= 5) {
		fid = (unsigned char *)"\x00\x13";		// EF.KEYD
		ucpath = (unsigned char *)"\x30\x7B\xA4\x9F\x22";
		ucpathlen = 4;		// 4 Tags (not bytes)
	} else {
		fid = (unsigned char *)"\x00\x15";		// EF.PWDD
		ucpath = (unsigned char *)"\x30\x7B\x9F\x22";
		ucpathlen = 3;		// 3 Tags (not bytes)
	}

	// Select EF
	rc = transmitAPDU(token->slot, 0x00, 0xA4, 0x02, 0x0C,
			2, fid,
			0, NULL, 0, &SW1SW2);

	if (rc < 0) {
		FUNC_FAILS(rc, "transmitAPDU failed");
	}

	if (SW1SW2 != 0x9000) {
		FUNC_FAILS(-1, "File not found");
	}

	// Read record, but leave 3 bytes to add encapsulating 30 81 FF later
	rc = transmitAPDU(token->slot, 0x00, 0xB2, recref, 0x04,
			0, NULL,
			0, rec, sizeof(rec) - 3, &SW1SW2);

	if (rc < 0) {
		FUNC_FAILS(rc, "transmitAPDU failed");
	}

	if (SW1SW2 != 0x9000) {
		FUNC_FAILS(-1, "Record not found");
	}

	rc = asn1Encap(0x30, rec, rc);
	rc = (int)asn1Validate(rec, rc);

	if (rc > 0) {
		FUNC_FAILS(rc, "ASN.1 structure invalid");
	}

	*useCounter = 0;
	p = asn1Find(rec, ucpath, ucpathlen);

	if (p) {
		asn1Tag(&p);
		asn1Length(&p);

		*useCounter = (*p == 0xFF ? 0 : *p);
	}

	p = asn1Find(rec, (unsigned char *)"\x30\x8A", 2);

	if (p) {
		asn1Tag(&p);
		asn1Length(&p);

		*lifeCycle = *p;
	}

	FUNC_RETURNS(CKR_OK);
}
Пример #15
0
int starcosReadTLVEF(struct p11Token_t *token, bytestring fid, unsigned char *content, size_t len)
{
	int rc, le, tl, ne, maxapdu;
	size_t ofs;
	unsigned short SW1SW2;
	unsigned char *po;

	FUNC_CALLED();

	// Select EF
	rc = transmitAPDU(token->slot, 0x00, 0xA4, 0x02, 0x0C,
			(int)fid->len, fid->val,
			0, NULL, 0, &SW1SW2);

	if (rc < 0) {
		FUNC_FAILS(rc, "transmitAPDU failed");
	}

	if (SW1SW2 != 0x9000) {
		FUNC_FAILS(-1, "File not found");
	}

	// Read first block to determine tag and length
	rc = transmitAPDU(token->slot, 0x00, 0xB0, 0x00, 0x00,
			0, NULL,
			0, content, (int)len, &SW1SW2);

	if (rc < 0) {
		FUNC_FAILS(rc, "transmitAPDU failed");
	}

	if (SW1SW2 != 0x9000) {
		FUNC_FAILS(-1, "Read EF failed");
	}

	ofs = rc;

	// Restrict the number of bytes in Le to either the maximum APDU size of STARCOS or
	// the maximum APDU size of the reader, if any.
	maxapdu = token->drv->maxRAPDU;
	if (token->slot->maxRAPDU && (token->slot->maxRAPDU < maxapdu))
		maxapdu = token->slot->maxRAPDU;
	maxapdu -= 2;		// Accommodate SW1/SW2

	le = 65536;			// Read all if no certificate found
	if ((*content == 0x30) || (*content == 0x5A)) {
		po = content;
		asn1Tag(&po);
		tl = asn1Length(&po);
		tl += (int)(po - content);
		le = tl - (int)ofs;
	}

	while ((rc > 0) && (ofs < len) && (le > 0)) {
		ne = le;
		// Restrict Ne to the maximum APDU length allowed
		if (((le != 65536) || token->slot->noExtLengthReadAll) && (le > maxapdu))
			ne = maxapdu;

		rc = transmitAPDU(token->slot, 0x00, 0xB0, (unsigned char)(ofs >> 8), (unsigned char)(ofs & 0xFF),
				0, NULL,
				ne, content + ofs, (int)(len - ofs), &SW1SW2);

		if (rc < 0) {
			FUNC_FAILS(rc, "transmitAPDU failed");
		}

		if ((SW1SW2 != 0x9000) && (SW1SW2 != 0x6B00) && (SW1SW2 != 0x6282)) {
			FUNC_FAILS(-1, "Read EF failed");
		}
		ofs += rc;
		if (le != 65536)
			le -= rc;
	}

	FUNC_RETURNS((int)ofs);
}