/**
 * 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;
}
Beispiel #2
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;
}
int IsEMVCard(int fd,uint64_t *pStatus) {
	unsigned char cmd_buffer[261];
	unsigned char rsp_buffer[258];
	size_t rx_frame_size;
	uint8_t rx_last_bits;
	char *SELECT_2PAY_SYS = "\x00\xA4\x04\x00\x0E\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31\x00";
	int rc;

	/* Select 2PAY.SYS.DDF01 */
	rc = feclr_transceive(fd, 0,
			      SELECT_2PAY_SYS, 20, 0,
			      rsp_buffer, sizeof(rsp_buffer),
			      &rx_frame_size, &rx_last_bits,
			      0,
			      pStatus);
	if (rc < 0) {
		return rc;
	}

	if (!verify_icc_response(rsp_buffer, rx_frame_size, 0x9000)) {
		if (asn1Validate(rsp_buffer, rx_frame_size - 2) == 0) {
			rc = check_2pay_sys(rsp_buffer, rx_frame_size);
			printf(" check_2pay_sys rc value = %d\n",rc);
			if (rc == 1) {
				/* MASTER Card detected */
				printf(" MASTER Card detected\n");
				return 1;
			} else if (rc == 2) {
				/* VISA Card detected */
				printf("VISA Card detected\n");
				return 1;
			} else if (rc == 3) {
				/* AMEX Card detected */
				printf("AMEX Card detected\n");
				return 1;
			} else if (rc == 4) {
				/* DISCOVER Card detected */
				printf("DISCOVER Card detected\n");
				return 1;
			} else if (rc == 5) {
				/* GIROGO Card detected */
				printf("GIROGO Card detected\n");
				visualization_girogo();
				return 0;
			}
		}
	}
	return 0;
}
/**
 * Populate the attribute CKA_ISSUER, CKA_SUBJECT and CKA_SERIAL from certificate
 */
int populateIssuerSubjectSerial(struct p11Object_t *object)
{
	CK_ATTRIBUTE attr = { CKA_VALUE, NULL, 0 };
	struct p11Attribute_t *pattr;
	int tag, length, buflen;
	unsigned char *value, *cursor, *obj;

	attr.type = CKA_VALUE;
	if (findAttribute(object, &attr, &pattr) < 0) {
		return -1;
	}

	cursor = pattr->attrData.pValue;
	buflen = pattr->attrData.ulValueLen;

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

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

	cursor = value;
	buflen = length;

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

	cursor = value;
	buflen = length;

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

	if (tag == 0xA0) {				// Skip optional cert type
		obj = cursor;
		if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
			return -1;
		}
	}

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

	attr.type = CKA_SERIAL_NUMBER;
	attr.pValue = obj;
	attr.ulValueLen = (CK_ULONG)(cursor - obj);

	addAttribute(object, &attr);

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

	obj = cursor;
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {	// Decode Issuer
		return -1;
	}

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

	attr.type = CKA_ISSUER;
	attr.pValue = obj;
	attr.ulValueLen = (CK_ULONG)(cursor - obj);

	addAttribute(object, &attr);

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

	obj = cursor;
	if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {	// Decode Subject
		return -1;
	}

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

	attr.type = CKA_SUBJECT;
	attr.pValue = obj;
	attr.ulValueLen = (CK_ULONG)(cursor - obj);

	addAttribute(object, &attr);

	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;
}
int getSubjectPublicKeyInfo(struct p11Object_t *object, unsigned char **spki)
{
	CK_ATTRIBUTE attr = { CKA_VALUE, NULL, 0 };
	struct p11Attribute_t *pattr;
	int tag, length, buflen;
	unsigned char *value, *cursor;

	attr.type = CKA_VALUE;
	if (findAttribute(object, &attr, &pattr) < 0) {
		return -1;
	}

	cursor = pattr->attrData.pValue;
	buflen = pattr->attrData.ulValueLen;

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

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

	cursor = value;
	buflen = length;

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

	cursor = value;
	buflen = length;

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

	if (tag == 0xA0) {				// Skip optional cert type
		if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) {
			return -1;
		}
	}

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

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

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

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

	*spki =cursor;

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

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

	return 0;
}
Beispiel #7
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);
}
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);
}