Beispiel #1
0
 void setPiece(const size_t& begin,const size_t& end,ulong p) 
 {
  CALL("setPiece(const size_t& begin,const size_t& end,ulong p)");
  (base &= (inversePieceMask[begin][end])) |= (p << (sizeInBits() - end - 1)); 
  
  ASSERT(piece(begin,end) == p);
 };
void PIVKeyRecord::computeCrypt(PIVToken &pivToken, bool sign,	// MODIFY
	const AccessCredentials *cred,
	const byte_string &data, byte_string &output)
{
	if (data.size() != sizeInBits() / 8)
		CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);

	/* Allow all key usage, certificates determine validity */
	unsigned char algRef;
	switch (sizeInBits()) {
	case 1024:
		algRef = PIV_KEYALG_RSA_1024;
		break;
	case 2048:
		algRef = PIV_KEYALG_RSA_2048;
		break;
	default:
		/* Cannot use a key ~= 1024 or 2048 bits yet */
		CssmError::throwMe(CSSMERR_CSP_KEY_USAGE_INCORRECT);
		break;
	}

	/* Build the BER-Encoded message */
	/* Template: 0x7C L { 0x82 0x00, 0x81 L data } .. 2 tag+lengths + 1 tag-0 */
	TLVList commandList;
	commandList.push_back(TLV_ref(new TLV(0x81, data)));
	commandList.push_back(TLV_ref(new TLV(0x82)));
	TLV_ref command = TLV_ref(new TLV(0x7C, commandList));

	/* TODO: Evaluate result length handling */
	/* At least enough to contain BER-TLV */
	size_t resultLength = sizeInBits() / 8;
	resultLength += 1 + TLV::encodedLength(resultLength); // RESPONSE
	resultLength += 1 + 1; // Potential empty response-tlv
	resultLength += 1 + TLV::encodedLength(resultLength); // TLV containing response
	/* Round out resultLength to a multiple of 256 */
	resultLength = resultLength + resultLength % 256 + 256;
	// Ensure that there's enough space to prevent unnecessary resizing
	output.reserve(resultLength);

	PCSC::Transaction _(pivToken);
	pivToken.selectDefault();
	/* Support for the signing key w/ user-consent pin */
	if (cred)
	{
		uint32 size = cred->size();
		for (uint32 ix = 0; ix < size; ++ix)
		{
			const TypedList &sample = (*cred)[ix];
			if (sample.type() == CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
				&& sample.length() == 2)
			{
				CssmData &pin = sample[1].data();
				if (pin.Length > 0)
				{
					pivToken.verifyPIN(1, pin.Data, pin.Length);
					break;
				}
				else if (pin.Length == 0)
				{
					// %%% <rdar://4334623>
					// PIN previously verified by securityd;
					// continue to look at remaining samples
				}
				else
				{
					CssmError::throwMe(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED);
				}
			}
		}
	}

	byte_string commandString = command->encode();
	PIVError::check(pivToken.exchangeChainedAPDU(0x00, 0x87, algRef, keyRef, commandString, output));

	/* DECODE 0x7C */
	TLV_ref tlv;
	try {
		tlv = TLV::parse(output);
	} catch(...) {
		secure_zero(output);
		PIVError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
	}
	secure_zero(output);
	if(tlv->getTag() != (unsigned char*)"\x7C") {
		secdebug("piv", " %s: computeCrypt: missing response tag: 0x%.2X",
				 description(), 0x7C);
		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
	}
	byte_string tagData;
	try {
		TLVList list = tlv->getInnerValues();
		TLVList::const_iterator iter = find_if(list.begin(), list.end(), TagPredicate(0x82));
		if(iter != list.end())
			tagData = (*iter)->getValue();
	} catch(...) {
	}
	if(tagData.size() == 0) {
		secdebug("piv", " %s: computeCrypt: missing response value tag: 0x%.2X",
				 description(), 0x82);
		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
	}

	if(tagData.size() != sizeInBits() / 8) { // Not enough data at all..
		secure_zero(tagData);
		secdebug("piv", " %s: computeCrypt: expected contained response length: %ld, got: %ld",
				 description(), sizeInBits() / 8, tagData.size());
		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
	}

	output.swap(tagData);
	/* zero-out tagData */
	secure_zero(tagData);
}
Beispiel #3
0
 ulong piece(const size_t& begin,const size_t& end) const
 {
  CALL("subword(const size_t& begin,const size_t& end) const");
  ASSERT(begin <= end);
  return (base << begin) >> (sizeInBits() - end + begin - 1);
 };
Beispiel #4
0
void BELPICKeyRecord::computeCrypt(BELPICToken & belpicToken, bool sign,
				   const AccessCredentials * cred,
				   const unsigned char *data,
				   size_t dataLength, unsigned char *output,
				   size_t & outputLength)
{
	PCSC::Transaction _(belpicToken);
	belpicToken.selectKeyForSign(mKeyId);

	if (mPPDU == true)
	{
		belpicToken._verifyPIN(1, NULL, 0);
	} else if (cred)
	{
		uint32 size = cred->size();

		for (uint32 ix = 0; ix < size; ++ix)
		{
			const TypedList & sample = (*cred)[ix];

			if (sample.type() ==
			    CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
			    && sample.length() == 2)
				if (sample.type() ==
				    CSSM_SAMPLE_TYPE_PASSWORD)
				{
					CssmData & pin = sample[1].data();
					if (pin.Length >= BELPIC_MIN_PIN_LEN
					    && pin.Length <=
					    BELPIC_MAX_PIN_LEN)
					{
						belpicToken._verifyPIN(1,
								       pin.
								       Data,
								       pin.
								       Length);
						break;
					} else if (pin.Length == 0)
					{
						// %%% <rdar://4334623>
						// PIN previously verified by securityd;
						// continue to look at remaining samples
					} else
					{
						CssmError::
							throwMe
							(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED);
					}
				}
		}

	}

	if (dataLength > sizeInBits() / 8)
		CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);

	if (sign != mSignOnly)
		CssmError::throwMe(CSSMERR_CSP_KEY_USAGE_INCORRECT);

	size_t apduSize = dataLength + 5;
	unsigned char apdu[apduSize];
	size_t resultLength = sizeInBits() / 8 + 2;
	unsigned char result[resultLength];

	apdu[0] = 0x00;
	apdu[1] = 0x2A;
	apdu[2] = 0x9E;
	apdu[3] = 0x9A;
	apdu[4] = dataLength;
	memcpy(apdu + 5, data, dataLength);
	BELPICError::check(belpicToken.exchangeAPDU(apdu, apduSize, result,
						    resultLength));
	if (resultLength != sizeInBits() / 8 + 2)
	{
		secdebug("belpic",
			 " %s: computeCrypt: expected size: %ld, got: %ld",
			 mDescription, sizeInBits() / 8 + 2, resultLength);
		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
	}

	if (outputLength < resultLength - 2)
		CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);

	outputLength = resultLength - 2;
	memcpy(output, result, outputLength);
}