[SmartcardServices-Changes] [135] branches/tokend/10.5

source_changes at macosforge.org source_changes at macosforge.org
Tue Nov 16 12:05:47 PST 2010


Revision: 135
          http://trac.macosforge.org/projects/smartcardservices/changeset/135
Author:   geddis at apple.com
Date:     2010-11-16 12:05:44 -0800 (Tue, 16 Nov 2010)
Log Message:
-----------
Post Source Code for CAC-NG v0.96 for 10.5

Added Paths:
-----------
    branches/tokend/10.5/CACNG/
    branches/tokend/10.5/CACNG/CACNGApplet.cpp
    branches/tokend/10.5/CACNG/CACNGApplet.h
    branches/tokend/10.5/CACNG/CACNGAttributeCoder.cpp
    branches/tokend/10.5/CACNG/CACNGAttributeCoder.h
    branches/tokend/10.5/CACNG/CACNGError.cpp
    branches/tokend/10.5/CACNG/CACNGError.h
    branches/tokend/10.5/CACNG/CACNGKeyHandle.cpp
    branches/tokend/10.5/CACNG/CACNGKeyHandle.h
    branches/tokend/10.5/CACNG/CACNGRecord.cpp
    branches/tokend/10.5/CACNG/CACNGRecord.h
    branches/tokend/10.5/CACNG/CACNGSchema.cpp
    branches/tokend/10.5/CACNG/CACNGSchema.h
    branches/tokend/10.5/CACNG/CACNGToken.cpp
    branches/tokend/10.5/CACNG/CACNGToken.h
    branches/tokend/10.5/CACNG/CompressionTool.cpp
    branches/tokend/10.5/CACNG/CompressionTool.h
    branches/tokend/10.5/CACNG/Info.plist
    branches/tokend/10.5/CACNG/Padding.cpp
    branches/tokend/10.5/CACNG/Padding.h
    branches/tokend/10.5/CACNG/TLV.cpp
    branches/tokend/10.5/CACNG/TLV.h
    branches/tokend/10.5/CACNG/TLV.inc
    branches/tokend/10.5/CACNG/byte_string.h
    branches/tokend/10.5/CACNG/cacng.cpp
    branches/tokend/10.5/CACNG/mds/
    branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities.mdsinfo
    branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities_common.mds
    branches/tokend/10.5/CACNG/mds/cacng_csp_primary.mdsinfo
    branches/tokend/10.5/CACNG/mds/cacng_dl_primary.mdsinfo
    branches/tokend/10.5/CACNG/mds/cacng_smartcard.mdsinfo

Added: branches/tokend/10.5/CACNG/CACNGApplet.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CACNGApplet.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGApplet.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,436 @@
+/*
+ *  CACNGApplet.cpp
+ *  Tokend
+ *
+ *  Created by harningt on 9/30/09.
+ *  Copyright 2009 TrustBearer Labs. All rights reserved.
+ *
+ */
+
+
+#include "CACNGApplet.h"
+#include <security_utilities/pcsc++.h>
+
+#include "CACNGToken.h"
+#include "CACNGError.h"
+
+#include "CompressionTool.h"
+
+#include "TLV.h"
+
+/* FOR KEYSIZE CALCULATION */
+#include <Security/Security.h>
+
+#define PIV_CLA_STANDARD				0x00
+#define PIV_INS_GET_DATA				0xCB	// [SP800731 7.1.2]
+
+//										0x00				0xCB
+#define PIV_GETDATA_APDU			PIV_CLA_STANDARD, PIV_INS_GET_DATA, 0x3F, 0xFF
+#define PIV_GETDATA_CONT_APDU	0x00, 0xC0, 0x00, 0x00
+
+#define PIV_GETDATA_RESPONSE_TAG		0x53
+#define PIV_GETDATA_TAG_CERTIFICATE		0x70
+#define PIV_GETDATA_TAG_CERTINFO		0x71
+#define PIV_GETDATA_TAG_MSCUID			0x72
+#define PIV_GETDATA_TAG_ERRORDETECTION	0xFE
+
+#define PIV_GETDATA_COMPRESSION_MASK	0x81
+
+CACNGCacApplet::CACNGCacApplet(CACNGToken &token, const byte_string &applet, const byte_string &object)
+:token(token), applet(applet), object(object)
+{
+}
+
+void CACNGCacApplet::select()
+{
+	byte_string result;
+	uint32_t code = token.exchangeAPDU(applet, result);
+	CACNGError::check(code);
+	if (!object.empty()) {
+		result.resize(0);
+		code = token.exchangeAPDU(object, result);
+		CACNGError::check(code);
+	}
+}
+
+CACNGIDObject::CACNGIDObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, const std::string &description)
+:token(token), applet(applet), keySize(0), description(description)
+{
+}
+
+
+size_t CACNGIDObject::getKeySize()
+{
+	if (keySize == ~(size_t)0)
+		CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+	if (keySize != 0)
+		return keySize;
+	byte_string cert = read();
+    SecCertificateRef certRef = 0;
+    SecKeyRef keyRef = 0;
+    /* Parse certificate for size */
+    CSSM_DATA certData;
+    certData.Data = (uint8_t*)&cert[0];
+    certData.Length = cert.size();
+    const CSSM_KEY *cssmKey = NULL;
+    OSStatus status = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_BER, &certRef);
+    if(status != noErr) goto done;
+    status = SecCertificateCopyPublicKey(certRef, &keyRef);
+    if(status != noErr) goto done;
+    status = SecKeyGetCSSMKey(keyRef, &cssmKey);
+    if(status != noErr) goto done;
+    keySize = cssmKey->KeyHeader.LogicalKeySizeInBits;
+done:
+    if(keyRef)
+        CFRelease(keyRef);
+    if(certRef)
+        CFRelease(certRef);
+	if (keySize == 0) {
+		keySize = ~(size_t)0;
+		CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+	}
+    return keySize;
+}
+
+CACNGCacIDObject::CACNGCacIDObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, const std::string &description)
+:CACNGIDObject(token, applet, description)
+{
+}
+
+/*
+ See NIST IR 6887 – 2003 EDITION, GSC-IS VERSION 2.1
+ 5.3.4 Generic Container Provider Virtual Machine Card Edge Interface
+ for a description of how this command works
+ 
+ READ BUFFER 0x80 0x52 Off/H Off/L 0x02 <buffer & number bytes to read> – 
+ */
+static size_t read_cac_buffer_size(CACNGToken &token, bool isTbuffer)
+{
+	unsigned char apdu[] = { 0x80, 0x52, 0x00, 0x00, 0x02, isTbuffer ? 0x01 : 0x02, 0x02 };
+	unsigned char result[4];
+	size_t resultLength = sizeof(result);
+	uint32_t cacresult = token.exchangeAPDU(apdu, sizeof(apdu), result, resultLength);
+	CACNGError::check(cacresult);
+	return result[0] | result[1] << 8;
+}
+
+static void read_cac_buffer(CACNGToken &token, bool isTbuffer, byte_string &result)
+{
+	size_t size = read_cac_buffer_size(token, isTbuffer);
+	result.resize(size + 2);
+    unsigned int offset, bytes_left;
+	const unsigned int MAX_READ = 0xFF;
+    for (offset = 2, bytes_left = size; bytes_left;)
+    {
+		//    resultLength = size + 2 - offset;
+        unsigned char toread = bytes_left > MAX_READ ? MAX_READ : bytes_left;
+		unsigned char apdu[] = {
+			0x80, 0x52, offset >> 8, offset & 0xFF, 0x02, isTbuffer ? 0x01 : 0x02, toread
+		};
+		size_t resultLength = toread + 2;
+        uint32_t cacresult = token.exchangeAPDU(apdu, sizeof(apdu),
+												&result[offset - 2],
+												resultLength);
+		
+        CACNGError::check(cacresult);
+		
+        if (resultLength - 2 != toread)
+			PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+		
+        resultLength -= 2;
+        offset += resultLength;
+        bytes_left -= resultLength;
+    }
+	/* Trim off status bytes */
+	result.resize(result.size() - 2);	
+}
+
+byte_string CACNGCacIDObject::read()
+{
+	byte_string result;
+	CssmData data;
+	if (token.cachedObject(0, description.c_str(), data))
+	{
+		result.assign((uint8_t*)data.data(), (uint8_t*)data.data() + data.length());
+		return result;
+	}
+	
+	PCSC::Transaction _(token);
+	token.select(applet);
+
+	read_cac_buffer(token, false, result);
+
+	if (result[0] != 0) {
+		/* The certificate is compressed */
+		result = CompressionTool::zlib_decompress(result.begin() + 1, result.end());
+	} else {
+		/* Remove marker byte */
+		result.erase(result.begin());
+	}
+
+	data.Data = &result[0];
+	data.Length = result.size();
+	token.cacheObject(0, description.c_str(), data);
+	return result;
+}
+
+byte_string CACNGCacIDObject::crypt(const byte_string &input)
+{
+	byte_string result;
+	if (input.size() > keySize / 8)
+		CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);
+	
+	//if (sign != mSignOnly)
+	//	CssmError::throwMe(CSSMERR_CSP_KEY_USAGE_INCORRECT);
+	
+	PCSC::Transaction _(token);
+	token.select(applet);
+
+	byte_string apdu;
+
+	size_t resultLength = keySize / 8 + 2;
+	result.resize(resultLength);
+	const size_t CHUNK_SIZE = 128;
+
+	for (unsigned i = 0; i < input.size(); i += CHUNK_SIZE)
+	{
+		const uint8_t next_chunk = min(input.size() - i, CHUNK_SIZE);
+		apdu.resize(5 + next_chunk);
+		apdu[0] = 0x80;
+		apdu[1] = 0x42;
+		apdu[2] = ((input.size() - i) > CHUNK_SIZE) ? 0x80 : 0x00;
+		apdu[3] = 0x00;
+		apdu[4] = next_chunk;
+		memcpy(&apdu[5], &input[i], next_chunk);
+		resultLength = result.size();
+		CACNGError::check(token.exchangeAPDU(&apdu[0], next_chunk + 5, &result[0],
+												resultLength));
+	}
+	if (resultLength != keySize / 8 + 2) {
+		secdebug("cac", " %s: computeCrypt: expected size: %ld, got: %ld",
+				 description.c_str(), keySize / 8 + 2, resultLength);
+		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+	}
+	/* Trim off status bytes */
+	result.resize(resultLength - 2);
+	return result;
+}
+
+CACNGPivApplet::CACNGPivApplet(CACNGToken &token, const byte_string &applet)
+:token(token), applet(applet)
+{
+}
+
+void CACNGPivApplet::select()
+{
+	byte_string result;
+	uint32_t code = token.exchangeAPDU(applet, result);
+	CACNGError::check(code);
+}
+
+CACNGPivIDObject::CACNGPivIDObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, const std::string &description, const byte_string &oid, uint8_t keyRef)
+:CACNGIDObject(token, applet, description), oid(oid), keyRef(keyRef)
+{
+}
+
+static void read_piv_object(CACNGToken &token, const byte_string &oid, byte_string &result)
+{
+	TLV oidValue(0x5C, oid);
+	byte_string tagged_oid = oidValue.encode();
+	static const unsigned char INITIAL_APDU[] = { PIV_GETDATA_APDU };
+	/* TODO: Build from ground-up */
+	byte_string initialApdu;
+	initialApdu.reserve(sizeof(INITIAL_APDU) + 1 + tagged_oid.size());
+	initialApdu.insert(initialApdu.begin(), INITIAL_APDU, INITIAL_APDU + sizeof(INITIAL_APDU));
+	initialApdu.push_back((uint8_t)tagged_oid.size());
+	initialApdu += tagged_oid;
+	
+	static const unsigned char CONTINUATION_APDU[] = { PIV_GETDATA_CONT_APDU, 0x00 /* LENGTH LOCATION */ };
+	byte_string continuationApdu(CONTINUATION_APDU, CONTINUATION_APDU + sizeof(CONTINUATION_APDU));
+
+	byte_string *apdu = &initialApdu;
+
+	uint32_t rx;
+	do
+	{
+		rx = token.exchangeAPDU(*apdu, result);
+		secdebug("pivtokend", "exchangeAPDU result %02X", rx);
+		
+		if ((rx & 0xFF00) != SCARD_BYTES_LEFT_IN_SW2 &&
+			(rx & 0xFF00) != SCARD_SUCCESS)
+			CACNGError::check(rx);
+		
+		// Switch to the continuation APDU after first exchange
+		apdu = &continuationApdu;
+		
+		// Number of bytes to fetch next time around is in the last byte returned.
+		// For all except the penultimate read, this is 0, indicating that the
+		// token should read all bytes.
+		apdu->back() = static_cast<unsigned char>(rx & 0xFF);
+	} while ((rx & 0xFF00) == SCARD_BYTES_LEFT_IN_SW2);
+
+	// Start to parse the BER-TLV encoded data. In the end, we only return the
+	// main data part of this but we need to step through the rest first
+	// The certficates are the only types we parse here
+	if (result.size()<=0)
+		return;
+	if (result[0] != PIV_GETDATA_RESPONSE_TAG)
+		CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+	
+}
+
+byte_string CACNGPivIDObject::read()
+{
+	byte_string result;
+	PCSC::Transaction _(token);
+	token.select(applet);
+
+	read_piv_object(token, oid, result);
+	/* Decode/decompress the certificate */
+	bool hasCertificateData = false;
+	bool isCompressed = false;
+	
+	// 00000000  53 82 04 84 70 82 04 78  78 da 33 68 62 db 61 d0 
+	TLV_ref tlv;
+	TLVList list;
+	try {
+		tlv = TLV::parse(result);
+		list = tlv->getInnerValues();
+	} catch(...) {
+		CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+	}
+
+	for(TLVList::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
+		const byte_string &tagString = (*iter)->getTag();
+		const byte_string &value = (*iter)->getValue();
+		if(tagString.size() != 1)
+			CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+		uint8_t tag = tagString[0];
+		switch (tag) {
+		case PIV_GETDATA_TAG_CERTIFICATE:			// 0x70
+			result = value;
+			hasCertificateData = true;
+			break;
+		case PIV_GETDATA_TAG_CERTINFO:				// 0x71
+			if(value.size() != 1)
+				CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+			secdebug("pivtokend", "CertInfo byte: %02X", value[0]);
+			isCompressed = value[0] & PIV_GETDATA_COMPRESSION_MASK;
+			break;
+		case PIV_GETDATA_TAG_MSCUID:				// 0x72 -- should be of length 3...
+			break;
+		case PIV_GETDATA_TAG_ERRORDETECTION:
+			break;
+		case 0:
+		case 0xFF:
+			break;
+		default:
+			CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+			break;
+		}
+	}
+	
+	/* No cert data ? */
+	if(!hasCertificateData)
+		CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+	if (isCompressed) {
+		return CompressionTool::zlib_decompress(result);
+	}
+	
+	return result;
+}
+
+byte_string CACNGPivIDObject::crypt(const byte_string &input)
+{
+	byte_string result;
+	/* Allow all key usage, certificates determine validity */
+	unsigned char algRef;
+	switch (keySize) {
+	case 1024:
+		algRef = 0x06;
+		break;
+	case 2048:
+		algRef = 0x07;
+		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(0x82)));
+	commandList.push_back(TLV_ref(new TLV(0x81, input)));
+	TLV_ref command = TLV_ref(new TLV(0x7C, commandList));
+
+	/* TODO: Evaluate result length handling */
+	/* At least enough to contain BER-TLV */
+	size_t resultLength = keySize / 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
+	result.reserve(resultLength);
+
+	byte_string commandString = command->encode();
+
+	PCSC::Transaction _(token);
+	token.select(applet);
+
+	CACNGError::check(token.exchangeChainedAPDU(0x00, 0x87, algRef, keyRef, commandString, result));
+
+	/* DECODE 0x7C */
+	TLV_ref tlv;
+	try {
+		tlv = TLV::parse(result);
+	} catch(...) {
+		secure_zero(result);
+		CACNGError::throwMe(SCARD_RETURNED_DATA_CORRUPTED);
+	}
+	secure_zero(result);
+	if(tlv->getTag() != (unsigned char*)"\x7C") {
+		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) {
+		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+	}
+	
+	if(tagData.size() != keySize / 8) { // Not enough data at all..
+		secure_zero(tagData);
+		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+	}
+	
+	result.swap(tagData);
+	/* zero-out tagData */
+	secure_zero(tagData);
+	
+	return result;
+}
+
+CACNGCacBufferObject::CACNGCacBufferObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, bool isTbuffer)
+:token(token), applet(applet), isTbuffer(isTbuffer)
+{
+}
+
+byte_string CACNGCacBufferObject::read()
+{
+	byte_string result;
+	
+	PCSC::Transaction _(token);
+	token.select(applet);
+	read_cac_buffer(token, isTbuffer, result);
+
+	return result;
+}

Added: branches/tokend/10.5/CACNG/CACNGApplet.h
===================================================================
--- branches/tokend/10.5/CACNG/CACNGApplet.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGApplet.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,135 @@
+/*
+ *  CACNGApplet.h
+ *  Tokend
+ *
+ *  Created by harningt on 9/30/09.
+ *  Copyright 2009 TrustBearer Labs. All rights reserved.
+ *
+ */
+#ifndef CACNGAPPLET_H
+#define CACNGAPPLET_H
+
+#include "byte_string.h"
+#include <security_utilities/utilities.h>
+
+#include <tr1/memory>
+using std::tr1::shared_ptr;
+
+class CACNGToken;
+
+class CACNGSelectable
+{
+	NOCOPY(CACNGSelectable)
+public:
+	CACNGSelectable() {}
+	virtual ~CACNGSelectable() {}
+
+protected:
+	virtual void select() = 0;
+	friend class CACNGToken;
+};
+
+class CACNGReadable
+{
+	NOCOPY(CACNGReadable)
+public:
+	CACNGReadable() {}
+	virtual ~CACNGReadable() {}
+	virtual byte_string read() = 0;
+};
+
+class CACNGCryptable
+{
+	NOCOPY(CACNGCryptable)
+public:
+	CACNGCryptable() {}
+	virtual ~CACNGCryptable() {}
+	virtual byte_string crypt(const byte_string &input) = 0;
+};
+
+class CACNGCacApplet : public CACNGSelectable
+{
+	NOCOPY(CACNGCacApplet);
+public:
+	CACNGCacApplet(CACNGToken &token, const byte_string &applet, const byte_string &object);
+	virtual ~CACNGCacApplet() {}
+
+protected:
+	void select();
+
+	CACNGToken &token;
+private:
+	const byte_string applet;
+	const byte_string object;
+};
+
+
+class CACNGPivApplet : public CACNGSelectable
+{
+	NOCOPY(CACNGPivApplet)
+public:
+	CACNGPivApplet(CACNGToken &token, const byte_string &applet);
+	virtual ~CACNGPivApplet() {}
+	
+protected:
+	CACNGToken &token;
+	void select();
+
+private:
+	const byte_string applet;
+};
+
+class CACNGIDObject : public CACNGReadable, public CACNGCryptable
+{
+	NOCOPY(CACNGIDObject);
+public:
+	CACNGIDObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, const std::string &description);
+
+	size_t getKeySize();
+protected:
+	CACNGToken &token;
+	shared_ptr<CACNGSelectable> applet;
+	
+	size_t keySize;
+	const std::string description;	
+};
+
+class CACNGCacIDObject : public CACNGIDObject
+{
+	NOCOPY(CACNGCacIDObject);
+public:
+	CACNGCacIDObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, const std::string &description);
+	virtual ~CACNGCacIDObject() {}
+	byte_string read();
+	byte_string crypt(const byte_string &input);
+};
+
+class CACNGPivIDObject : public CACNGIDObject
+{
+	NOCOPY(CACNGPivIDObject)
+public:
+	CACNGPivIDObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, const std::string &description, const byte_string &oid, uint8_t keyRef);
+	virtual ~CACNGPivIDObject() {}
+
+	byte_string read();
+	byte_string crypt(const byte_string &input);
+private:
+	const byte_string oid;
+	const uint8_t keyRef;
+};
+
+class CACNGCacBufferObject : public CACNGReadable
+{
+	NOCOPY(CACNGCacBufferObject);
+public:
+	CACNGCacBufferObject(CACNGToken &token, shared_ptr<CACNGSelectable> applet, bool isTbuffer);
+	virtual ~CACNGCacBufferObject() {}
+
+	byte_string read();
+private:
+	CACNGToken &token;
+	shared_ptr<CACNGSelectable> applet;
+	bool isTbuffer;
+};
+
+#endif /* CACNGAPPLET_H */

Added: branches/tokend/10.5/CACNG/CACNGAttributeCoder.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CACNGAttributeCoder.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGAttributeCoder.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGAttributeCoder.cpp
+ *  TokendMuscle
+ */
+
+#include "CACNGAttributeCoder.h"
+
+#include "Adornment.h"
+#include "MetaAttribute.h"
+#include "MetaRecord.h"
+#include "CACNGRecord.h"
+#include "CACNGToken.h"
+
+#include <Security/SecKeychainItem.h>
+#include <security_cdsa_utilities/cssmkey.h>
+
+using namespace Tokend;
+
+
+//
+// CACNGDataAttributeCoder
+//
+CACNGDataAttributeCoder::~CACNGDataAttributeCoder()
+{
+}
+
+void CACNGDataAttributeCoder::decode(TokenContext *tokenContext,
+	const MetaAttribute &metaAttribute, Record &record)
+{
+	CACNGRecord &cacRecord = dynamic_cast<CACNGRecord &>(record);
+	record.attributeAtIndex(metaAttribute.attributeIndex(),
+		cacRecord.getDataAttribute(tokenContext));
+}
+
+CACNGKeySizeAttributeCoder::~CACNGKeySizeAttributeCoder()
+{
+}
+
+void CACNGKeySizeAttributeCoder::decode(TokenContext *TokenContext,
+	const MetaAttribute &MetaAttribute, Record &record)
+{
+	CACNGKeyRecord &cacRecord = dynamic_cast<CACNGKeyRecord &>(record);
+	record.attributeAtIndex(MetaAttribute.attributeIndex(),
+							new Tokend::Attribute((uint32_t)cacRecord.sizeInBits()));
+}

Added: branches/tokend/10.5/CACNG/CACNGAttributeCoder.h
===================================================================
--- branches/tokend/10.5/CACNG/CACNGAttributeCoder.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGAttributeCoder.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGAttributeCoder.h
+ *  TokendMuscle
+ */
+
+#ifndef _CACNGATTRIBUTECODER_H_
+#define _CACNGATTRIBUTECODER_H_
+
+#include "AttributeCoder.h"
+#include <string>
+
+#include <PCSC/musclecard.h>
+
+
+//
+// A coder that reads the data of an object
+//
+class CACNGDataAttributeCoder : public Tokend::AttributeCoder
+{
+	NOCOPY(CACNGDataAttributeCoder)
+public:
+
+	CACNGDataAttributeCoder() {}
+	virtual ~CACNGDataAttributeCoder();
+
+	virtual void decode(Tokend::TokenContext *tokenContext,
+		const Tokend::MetaAttribute &metaAttribute, Tokend::Record &record);
+};
+
+//
+// A coder that produces the LogicalKeySizeInBits of a key
+//
+class CACNGKeySizeAttributeCoder : public Tokend::AttributeCoder
+{
+	NOCOPY(CACNGKeySizeAttributeCoder)
+public:
+	CACNGKeySizeAttributeCoder() {}
+	virtual ~CACNGKeySizeAttributeCoder();
+	
+	virtual void decode(Tokend::TokenContext *tokenContext, const Tokend::MetaAttribute &metaAttribute, Tokend::Record &record);
+};
+
+#endif /* !_CACNGATTRIBUTECODER_H_ */
+

Added: branches/tokend/10.5/CACNG/CACNGError.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CACNGError.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGError.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,91 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGError.cpp
+ *  TokendMuscle
+ */
+
+#include "CACNGError.h"
+
+#include <Security/cssmerr.h>
+
+//
+// CACNGError exceptions
+//
+CACNGError::CACNGError(uint16_t sw) : SCardError(sw)
+{
+	IFDEBUG(debugDiagnose(this));
+}
+
+CACNGError::~CACNGError() throw ()
+{
+}
+
+const char *CACNGError::what() const throw ()
+{ return "CACNG error"; }
+
+OSStatus CACNGError::osStatus() const
+{
+    switch (statusWord)
+    {
+	case CACNG_AUTHENTICATION_FAILED_0:
+	case CACNG_AUTHENTICATION_FAILED_1:
+	case CACNG_AUTHENTICATION_FAILED_2:
+	case CACNG_AUTHENTICATION_FAILED_3:
+        return CSSM_ERRCODE_OPERATION_AUTH_DENIED;
+    default:
+        return SCardError::osStatus();
+    }
+}
+
+void CACNGError::throwMe(uint16_t sw)
+{ throw CACNGError(sw); }
+
+#if !defined(NDEBUG)
+
+void CACNGError::debugDiagnose(const void *id) const
+{
+    secdebug("exception", "%p CACNGError %s (%04hX)",
+             id, errorstr(statusWord), statusWord);
+}
+
+const char *CACNGError::errorstr(uint16_t sw) const
+{
+	switch (sw)
+	{
+	case CACNG_AUTHENTICATION_FAILED_0:
+		return "Authentication failed, 0 retries left.";
+	case CACNG_AUTHENTICATION_FAILED_1:
+		return "Authentication failed, 1 retry left.";
+	case CACNG_AUTHENTICATION_FAILED_2:
+		return "Authentication failed, 2 retries left.";
+	case CACNG_AUTHENTICATION_FAILED_3:
+		return "Authentication failed, 3 retries left.";
+	default:
+		return SCardError::errorstr(sw);
+	}
+}
+
+#endif //NDEBUG
+

Added: branches/tokend/10.5/CACNG/CACNGError.h
===================================================================
--- branches/tokend/10.5/CACNG/CACNGError.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGError.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGError.h
+ *  TokendMuscle
+ */
+
+#ifndef _CACNGERROR_H_
+#define _CACNGERROR_H_
+
+#include "SCardError.h"
+
+/** Entered PIN is not correct and pin was blocked. */
+#define CACNG_AUTHENTICATION_FAILED_0        0x6300
+/** Entered PIN is not correct, 1 try left. */
+#define CACNG_AUTHENTICATION_FAILED_1        0x6301
+/** Entered PIN is not correct, 2 tries left. */
+#define CACNG_AUTHENTICATION_FAILED_2        0x6302
+/** Entered PIN is not correct, 3 tries left. */
+#define CACNG_AUTHENTICATION_FAILED_3        0x6303
+
+class CACNGError : public Tokend::SCardError
+{
+protected:
+    CACNGError(uint16_t sw);
+	virtual ~CACNGError() throw ();
+public:
+	OSStatus osStatus() const;
+	virtual const char *what () const throw ();
+
+    static void check(uint16_t sw)	{ if (sw != SCARD_SUCCESS) throwMe(sw); }
+    static void throwMe(uint16_t sw) __attribute__((noreturn));
+    
+protected:
+    IFDEBUG(void debugDiagnose(const void *id) const;)
+    IFDEBUG(const char *errorstr(uint16_t sw) const;)
+};
+
+#endif /* !_CACNGERROR_H_ */
+

Added: branches/tokend/10.5/CACNG/CACNGKeyHandle.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CACNGKeyHandle.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGKeyHandle.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,213 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGKeyHandle.cpp
+ *  TokendMuscle
+ */
+
+#include "CACNGKeyHandle.h"
+
+#include "CACNGRecord.h"
+#include "CACNGToken.h"
+
+#include "byte_string.h"
+#include "Padding.h"
+
+#include <security_utilities/debugging.h>
+#include <security_utilities/utilities.h>
+#include <security_cdsa_utilities/cssmerrors.h>
+#include <Security/cssmerr.h>
+
+
+//
+// CACNGKeyHandle
+//
+CACNGKeyHandle::CACNGKeyHandle(CACNGToken &cacToken,
+	const Tokend::MetaRecord &metaRecord, CACNGKeyRecord &cacKey) :
+	Tokend::KeyHandle(metaRecord, &cacKey),
+	mToken(cacToken),
+	mKey(cacKey)
+{
+}
+
+CACNGKeyHandle::~CACNGKeyHandle()
+{
+}
+
+void CACNGKeyHandle::getKeySize(CSSM_KEY_SIZE &keySize)
+{
+	secdebug("crypto", "getKeySize");
+	keySize.LogicalKeySizeInBits = mKey.sizeInBits();		// Logical key size in bits
+	keySize.EffectiveKeySizeInBits = mKey.sizeInBits();		// Effective key size in bits
+}
+
+uint32 CACNGKeyHandle::getOutputSize(const Context &context, uint32 inputSize,
+	bool encrypting)
+{
+	secdebug("crypto", "getOutputSize");
+	if (encrypting)
+		CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
+	return inputSize;       //accurate for crypto used on CACNG cards
+}
+
+void CACNGKeyHandle::generateSignature(const Context &context,
+	CSSM_ALGORITHMS alg, const CssmData &input, CssmData &signature)
+{
+	secdebug("crypto", "generateSignature alg: %u signOnly: %u",
+		context.algorithm(), alg);
+	IFDUMPING("crypto", context.dump("signature context"));
+
+	if (context.type() != CSSM_ALGCLASS_SIGNATURE)
+		CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT);
+
+	if (context.algorithm() != CSSM_ALGID_RSA)
+		CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
+
+	// Get padding, but default to pkcs1 style padding
+	uint32 padding = CSSM_PADDING_PKCS1;
+	context.getInt(CSSM_ATTRIBUTE_PADDING, padding);
+	
+	byte_string inputData(input.Data, input.Data + input.Length);
+
+	Padding::apply(inputData, mKey.sizeInBits() / 8, padding, alg);
+
+	// @@@ Switch to using tokend allocators
+	byte_string outputData(mKey.sizeInBits() / 8);
+	size_t outputLength = outputData.size();
+
+	// Sign the inputData using the token
+	mKey.computeCrypt(mToken, true, &inputData[0], inputData.size(),
+		&outputData[0], outputLength);
+
+	signature.Data = malloc_copy(outputData);
+	signature.Length = outputLength;
+}
+
+void CACNGKeyHandle::verifySignature(const Context &context,
+	CSSM_ALGORITHMS signOnly, const CssmData &input, const CssmData &signature)
+{
+	secdebug("crypto", "verifySignature");
+	CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
+}
+
+void CACNGKeyHandle::generateMac(const Context &context,
+	const CssmData &input, CssmData &output)
+{
+	secdebug("crypto", "generateMac");
+	CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
+}
+
+void CACNGKeyHandle::verifyMac(const Context &context,
+	const CssmData &input, const CssmData &compare)
+{
+	secdebug("crypto", "verifyMac");
+	CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
+}
+
+void CACNGKeyHandle::encrypt(const Context &context,
+	const CssmData &clear, CssmData &cipher)
+{
+	secdebug("crypto", "encrypt");
+	CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
+}
+
+void CACNGKeyHandle::decrypt(const Context &context,
+	const CssmData &cipher, CssmData &clear)
+{
+	secdebug("crypto", "decrypt alg: %u", context.algorithm());
+	IFDUMPING("crypto", context.dump("decrypt context"));
+
+	if (context.type() != CSSM_ALGCLASS_ASYMMETRIC)
+		CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT);
+
+	if (context.algorithm() != CSSM_ALGID_RSA)
+		CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
+
+	/* Check for supported padding */
+	uint32 padding = context.getInt(CSSM_ATTRIBUTE_PADDING);
+	if(!Padding::canRemove(padding))
+		CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
+
+	size_t keyLength = mKey.sizeInBits() / 8;
+	if (cipher.length() % keyLength != 0)
+		CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
+
+	// @@@ Add support for multiples of keyLength by doing multiple blocks
+	if (cipher.length() != keyLength)
+		CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
+
+	// @@@ Use a secure allocator for this.
+	byte_string outputData(keyLength);
+	uint8 *output = &outputData[0];
+	size_t outputLength = keyLength;
+
+	secdebug("crypto", "decrypt: card supports RSA_NOPAD");
+	// Decrypt the inputData using the token
+	mKey.computeCrypt(mToken, false, cipher.Data, cipher.Length, output,
+		outputLength);
+
+	if (outputLength != keyLength)
+		CssmError::throwMe(CSSMERR_CSP_INVALID_DATA);
+	Padding::remove(outputData, padding);
+
+	// @@@ Switch to using tokend allocators
+	clear.Data = malloc_copy(outputData);
+	clear.Length = outputData.size();
+}
+
+void CACNGKeyHandle::exportKey(const Context &context,
+	const AccessCredentials *cred, CssmKey &wrappedKey)
+{
+	secdebug("crypto", "exportKey");
+	CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
+}
+
+void CACNGKeyHandle::getAcl(const char *tag, uint32 &count, AclEntryInfo *&aclList)
+{
+	mKey.getAcl(tag, count, aclList);
+}
+
+void CACNGKeyHandle::getOwner(AclOwnerPrototype &owner)
+{
+	mKey.getOwner(owner);
+}
+
+//
+// CACNGKeyHandleFactory
+//
+CACNGKeyHandleFactory::~CACNGKeyHandleFactory()
+{
+}
+
+
+Tokend::KeyHandle *CACNGKeyHandleFactory::keyHandle(
+	Tokend::TokenContext *tokenContext, const Tokend::MetaRecord &metaRecord,
+	Tokend::Record &record) const
+{
+	CACNGKeyRecord &key = dynamic_cast<CACNGKeyRecord &>(record);
+	CACNGToken &cacToken = static_cast<CACNGToken &>(*tokenContext);
+	return new CACNGKeyHandle(cacToken, metaRecord, key);
+}
+
+

Added: branches/tokend/10.5/CACNG/CACNGKeyHandle.h
===================================================================
--- branches/tokend/10.5/CACNG/CACNGKeyHandle.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGKeyHandle.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGKeyHandle.h
+ *  TokendMuscle
+ */
+
+#ifndef _CACNGKEYHANDLE_H_
+#define _CACNGKEYHANDLE_H_
+
+#include "KeyHandle.h"
+
+class CACNGToken;
+class CACNGKeyRecord;
+
+
+//
+// A KeyHandle object which implements the crypto interface to muscle.
+//
+class CACNGKeyHandle: public Tokend::KeyHandle
+{
+	NOCOPY(CACNGKeyHandle)
+public:
+    CACNGKeyHandle(CACNGToken &cacToken, const Tokend::MetaRecord &metaRecord,
+		CACNGKeyRecord &cacKey);
+    ~CACNGKeyHandle();
+
+    virtual void getKeySize(CSSM_KEY_SIZE &keySize);
+    virtual uint32 getOutputSize(const Context &context, uint32 inputSize,
+		bool encrypting);
+    virtual void generateSignature(const Context &context,
+		CSSM_ALGORITHMS signOnly, const CssmData &input, CssmData &signature);
+    virtual void verifySignature(const Context &context,
+		CSSM_ALGORITHMS signOnly, const CssmData &input,
+			const CssmData &signature);
+    virtual void generateMac(const Context &context, const CssmData &input,
+		CssmData &output);
+    virtual void verifyMac(const Context &context, const CssmData &input,
+		const CssmData &compare);
+    virtual void encrypt(const Context &context, const CssmData &clear,
+		CssmData &cipher);
+    virtual void decrypt(const Context &context, const CssmData &cipher,
+		CssmData &clear);
+
+	virtual void exportKey(const Context &context,
+		const AccessCredentials *cred, CssmKey &wrappedKey);
+
+	virtual void getOwner(AclOwnerPrototype &owner);
+	virtual void getAcl(const char *tag, uint32 &count, AclEntryInfo *&auths);
+
+private:
+	CACNGToken &mToken;
+	CACNGKeyRecord &mKey;
+};
+
+
+//
+// A factory that creates CACNGKeyHandle objects.
+//
+class CACNGKeyHandleFactory : public Tokend::KeyHandleFactory
+{
+	NOCOPY(CACNGKeyHandleFactory)
+public:
+	CACNGKeyHandleFactory() {}
+	virtual ~CACNGKeyHandleFactory();
+
+	virtual Tokend::KeyHandle *keyHandle(Tokend::TokenContext *tokenContext,
+		const Tokend::MetaRecord &metaRecord, Tokend::Record &record) const;
+};
+
+
+#endif /* !_CACNGKEYHANDLE_H_ */
+
+

Added: branches/tokend/10.5/CACNG/CACNGRecord.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CACNGRecord.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGRecord.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,171 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGRecord.cpp
+ *  TokendMuscle
+ */
+
+#include "CACNGRecord.h"
+
+#include "CACNGError.h"
+#include "CACNGToken.h"
+#include "Attribute.h"
+#include "MetaAttribute.h"
+#include "MetaRecord.h"
+#include <security_cdsa_client/aclclient.h>
+#include <Security/SecKey.h>
+
+//
+// CACNGRecord
+//
+CACNGRecord::~CACNGRecord()
+{
+}
+
+
+//
+// CACNGCertificateRecord
+//
+CACNGCertificateRecord::~CACNGCertificateRecord()
+{
+}
+
+Tokend::Attribute *CACNGCertificateRecord::getDataAttribute(Tokend::TokenContext *tokenContext)
+{
+	byte_string result = identity->read();
+	
+	CssmData data(malloc_copy(result), result.size());
+	return new Tokend::Attribute(data.Data, data.Length);
+}
+
+//
+// CACNGKeyRecord
+//
+CACNGKeyRecord::CACNGKeyRecord(shared_ptr<CACNGIDObject> identity, const char *description, const Tokend::MetaRecord &metaRecord, bool signOnly, bool requireNewPin /* = false */)
+: CACNGRecord(description), identity(identity), mSignOnly(signOnly), requireNewPin(requireNewPin)
+{
+    attributeAtIndex(metaRecord.metaAttribute(kSecKeyDecrypt).attributeIndex(),
+                     //new Tokend::Attribute(!signOnly));
+ 					 new Tokend::Attribute(true));
+    attributeAtIndex(metaRecord.metaAttribute(kSecKeyUnwrap).attributeIndex(),
+                     //new Tokend::Attribute(!signOnly));
+					 new Tokend::Attribute(true));
+    attributeAtIndex(metaRecord.metaAttribute(kSecKeySign).attributeIndex(),
+                     //new Tokend::Attribute(signOnly));
+ 					 new Tokend::Attribute(true));
+}
+
+CACNGKeyRecord::~CACNGKeyRecord()
+{
+}
+
+
+void CACNGKeyRecord::computeCrypt(CACNGToken &token, bool sign,
+	const unsigned char *data, size_t dataLength, unsigned char *output,
+	size_t &outputLength)
+{
+	if (requireNewPin) {
+		token.verifyCachedPin(2);
+	}
+	byte_string result = identity->crypt(byte_string(data, data + dataLength));
+
+	if (outputLength < result.size())
+		CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);
+
+	outputLength = result.size();
+	memcpy(output, &result[0], outputLength);
+}
+
+void CACNGKeyRecord::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls)
+{
+	// 2010.03.01 -SG- added tmptag adjusting to API change in 10.6.0	
+	char tmptag[20];
+	const uint32 slot = 1;	// hardwired for now, but...
+	snprintf(tmptag, sizeof(tmptag), "PIN%d", slot);
+
+	if (!mAclEntries) {
+		mAclEntries.allocator(Allocator::standard());
+        // Anyone can read the DB record for this key (which is a reference
+		// CSSM_KEY)
+		mAclEntries.add(CssmClient::AclFactory::AnySubject(
+			mAclEntries.allocator()),
+			AclAuthorizationSet(CSSM_ACL_AUTHORIZATION_DB_READ, 0));
+		if (requireNewPin) {
+			mAclEntries.add(CssmClient::AclFactory::PinSubject(
+				mAclEntries.allocator(), 2),
+				AclAuthorizationSet(CSSM_ACL_AUTHORIZATION_SIGN, CSSM_ACL_AUTHORIZATION_DECRYPT, 0));
+			if (0x9000 != token->pinStatus(2)) {
+				CssmData prompt;
+				mAclEntries.add(CssmClient::AclFactory::PromptPWSubject(mAclEntries.allocator(), prompt),
+					AclAuthorizationSet(CSSM_ACL_AUTHORIZATION_SIGN, CSSM_ACL_AUTHORIZATION_DECRYPT, 0));
+			}
+		} else {
+		// Using this key to sign or decrypt will require PIN1
+			mAclEntries.add(CssmClient::AclFactory::PinSubject(
+				mAclEntries.allocator(), 1),
+				AclAuthorizationSet(CSSM_ACL_AUTHORIZATION_SIGN, CSSM_ACL_AUTHORIZATION_DECRYPT, 0), tmptag);
+		}
+	}
+	count = mAclEntries.size();
+	acls = mAclEntries.entries();
+}
+
+void CACNGKeyRecord::getOwner(AclOwnerPrototype &owner)
+{
+	if (!mAclOwner) {
+		mAclOwner.allocator(Allocator::standard());
+		mAclOwner = CssmClient::AclFactory::PinSubject(Allocator::standard(), requireNewPin ? 2 : 1);
+	}
+	owner = mAclOwner;
+}
+//
+// CACNGDataRecord
+//
+CACNGDataRecord::~CACNGDataRecord()
+{
+}
+
+Tokend::Attribute *CACNGDataRecord::getDataAttribute(Tokend::TokenContext *tokenContext)
+{
+	byte_string data = buffer->read();
+	return new Tokend::Attribute(&data[0], data.size());
+}
+
+void CACNGDataRecord::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls)
+{
+	char tmptag[20];
+	const uint32 slot = 1;	// hardwired for now, but...
+	snprintf(tmptag, sizeof(tmptag), "PIN%d", slot);
+	
+	if (!mAclEntries) {
+		mAclEntries.allocator(Allocator::standard());
+        // Reading this objects data requires PIN1
+		mAclEntries.add(CssmClient::AclFactory::PinSubject(
+			mAclEntries.allocator(), 1),
+			AclAuthorizationSet(CSSM_ACL_AUTHORIZATION_DB_READ, 0), tmptag);
+	}
+	count = mAclEntries.size();
+	acls = mAclEntries.entries();
+}
+

Added: branches/tokend/10.5/CACNG/CACNGRecord.h
===================================================================
--- branches/tokend/10.5/CACNG/CACNGRecord.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGRecord.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,108 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGRecord.h
+ *  TokendMuscle
+ */
+
+#ifndef _CACNGRECORD_H_
+#define _CACNGRECORD_H_
+
+#include "Record.h"
+#include "CACNGApplet.h"
+
+#include <security_cdsa_utilities/context.h>
+
+class CACNGToken;
+
+class CACNGRecord : public Tokend::Record
+{
+	NOCOPY(CACNGRecord)
+public:
+	CACNGRecord(const char *description) :
+		 mDescription(description) {}
+	~CACNGRecord();
+
+	virtual const char *description() { return mDescription; }
+
+protected:
+	const char *mDescription;
+};
+
+
+class CACNGCertificateRecord : public CACNGRecord
+{
+	NOCOPY(CACNGCertificateRecord)
+public:
+	CACNGCertificateRecord(
+		shared_ptr<CACNGIDObject> identity,
+		const char *description) :
+		CACNGRecord(description), identity(identity) {}
+	~CACNGCertificateRecord();
+
+	virtual Tokend::Attribute *getDataAttribute(Tokend::TokenContext *tokenContext);
+private:
+	shared_ptr<CACNGIDObject> identity;
+};
+
+class CACNGKeyRecord : public CACNGRecord
+{
+	NOCOPY(CACNGKeyRecord)
+public:
+	CACNGKeyRecord(shared_ptr<CACNGIDObject> identity, const char *description, const Tokend::MetaRecord &metaRecord, bool signOnly, bool requireNewPin = false);
+    ~CACNGKeyRecord();
+
+	size_t sizeInBits() const { return identity->getKeySize(); }
+	virtual void computeCrypt(CACNGToken &cacToken, bool sign, const unsigned char *data,
+		size_t dataLength, unsigned char *result, size_t &resultLength);
+
+	virtual void getOwner(AclOwnerPrototype &owner);
+    virtual void getAcl(const char *tag, uint32 &count,
+		AclEntryInfo *&aclList);
+private:
+	shared_ptr<CACNGIDObject> identity;
+	const bool mSignOnly;
+	AutoAclEntryInfoList mAclEntries;
+	AutoAclOwnerPrototype mAclOwner;
+	const bool requireNewPin;
+};
+
+class CACNGDataRecord : public CACNGRecord
+{
+	NOCOPY(CACNGDataRecord)
+public:
+	CACNGDataRecord(shared_ptr<CACNGReadable> buffer, const char *description) :
+		CACNGRecord(description), buffer(buffer) {}
+	~CACNGDataRecord();
+
+	virtual Tokend::Attribute *getDataAttribute(Tokend::TokenContext *tokenContext);
+    virtual void getAcl(const char *tag, uint32 &count, AclEntryInfo *&aclList);
+protected:
+	shared_ptr<CACNGReadable> buffer;
+	AutoAclEntryInfoList mAclEntries;
+};
+
+#endif /* !_CACNGRECORD_H_ */
+
+

Added: branches/tokend/10.5/CACNG/CACNGSchema.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CACNGSchema.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGSchema.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGSchema.cpp
+ *  TokendMuscle
+ */
+
+#include "CACNGSchema.h"
+
+#include "MetaAttribute.h"
+#include "MetaRecord.h"
+
+#include <Security/SecCertificate.h>
+#include <Security/SecKeychainItem.h>
+#include <Security/SecKey.h>
+
+using namespace Tokend;
+
+CACNGSchema::CACNGSchema() :
+	mKeyAlgorithmCoder(uint32(CSSM_ALGID_RSA))
+{
+}
+
+CACNGSchema::~CACNGSchema()
+{
+}
+
+Tokend::Relation *CACNGSchema::createKeyRelation(CSSM_DB_RECORDTYPE keyType)
+{
+	Relation *rn = createStandardRelation(keyType);
+
+	// Set up coders for key records.
+	MetaRecord &mr = rn->metaRecord();
+	mr.keyHandleFactory(&mCACNGKeyHandleFactory);
+
+	// Print name of a key might as well be the key name.
+	mr.attributeCoder(kSecKeyPrintName, &mDescriptionCoder);
+
+	// Other key valuess
+	mr.attributeCoder(kSecKeyKeyType, &mKeyAlgorithmCoder);
+	mr.attributeCoder(kSecKeyKeySizeInBits, &mKeySizeCoder);
+	mr.attributeCoder(kSecKeyEffectiveKeySize, &mKeySizeCoder);
+
+	// Key attributes
+	mr.attributeCoder(kSecKeyExtractable, &mFalseCoder);
+	mr.attributeCoder(kSecKeySensitive, &mTrueCoder);
+	mr.attributeCoder(kSecKeyModifiable, &mFalseCoder);
+	mr.attributeCoder(kSecKeyPrivate, &mTrueCoder);
+	mr.attributeCoder(kSecKeyNeverExtractable, &mTrueCoder);
+	mr.attributeCoder(kSecKeyAlwaysSensitive, &mTrueCoder);
+
+	// Key usage
+	mr.attributeCoder(kSecKeyEncrypt, &mFalseCoder);
+	mr.attributeCoder(kSecKeyWrap, &mFalseCoder);
+	mr.attributeCoder(kSecKeyVerify, &mFalseCoder);
+	mr.attributeCoder(kSecKeyDerive, &mFalseCoder);
+	mr.attributeCoder(kSecKeySignRecover, &mFalseCoder);
+	mr.attributeCoder(kSecKeyVerifyRecover, &mFalseCoder);
+
+	return rn;
+}
+
+void CACNGSchema::create()
+{
+	Schema::create();
+
+	createStandardRelation(CSSM_DL_DB_RECORD_X509_CERTIFICATE);
+	createKeyRelation(CSSM_DL_DB_RECORD_PRIVATE_KEY);
+    Relation *rn_gen = createStandardRelation(CSSM_DL_DB_RECORD_GENERIC);
+
+	// Create the generic table
+	MetaRecord &mr_gen = rn_gen->metaRecord();
+	mr_gen.attributeCoderForData(&mCACNGDataAttributeCoder);
+}
+

Added: branches/tokend/10.5/CACNG/CACNGSchema.h
===================================================================
--- branches/tokend/10.5/CACNG/CACNGSchema.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGSchema.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGSchema.h
+ *  TokendMuscle
+ */
+
+#ifndef _CACNGSCHEMA_H_
+#define _CACNGSCHEMA_H_
+
+#include "Schema.h"
+#include "CACNGAttributeCoder.h"
+#include "CACNGKeyHandle.h"
+
+namespace Tokend
+{
+	class Relation;
+	class MetaRecord;
+	class AttributeCoder;
+}
+
+class CACNGSchema : public Tokend::Schema
+{
+	NOCOPY(CACNGSchema)
+public:
+    CACNGSchema();
+    virtual ~CACNGSchema();
+
+	virtual void create();
+
+protected:
+	Tokend::Relation *createKeyRelation(CSSM_DB_RECORDTYPE keyType);
+
+private:
+	// Coders we need.
+	CACNGDataAttributeCoder mCACNGDataAttributeCoder;
+
+	Tokend::ConstAttributeCoder mKeyAlgorithmCoder;
+	CACNGKeySizeAttributeCoder mKeySizeCoder;
+
+	CACNGKeyHandleFactory mCACNGKeyHandleFactory;
+};
+
+#endif /* !_CACNGSCHEMA_H_ */
+

Added: branches/tokend/10.5/CACNG/CACNGToken.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CACNGToken.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGToken.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,729 @@
+/*
+ *  Copyright (c) 2004,2007 Apple Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGToken.cpp
+ *  TokendMuscle
+ */
+
+#include "CACNGToken.h"
+
+#include "Adornment.h"
+#include "AttributeCoder.h"
+#include "CACNGError.h"
+#include "CACNGRecord.h"
+#include "CACNGSchema.h"
+#include <security_cdsa_client/aclclient.h>
+#include <map>
+#include <vector>
+
+using CssmClient::AclFactory;
+
+#define PIV_CLA_STANDARD      0x00
+#define CLA_STANDARD      0x00
+#define INS_SELECT_FILE   0xA4
+#define INS_GET_DATA      0xCA
+
+#define SELECT_APPLET  CLA_STANDARD, INS_SELECT_FILE, 0x04, 0x00
+
+#define SELECT_CACNG_APPLET  SELECT_APPLET, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x79
+
+#define SELECT_CACNG_OBJECT  CLA_STANDARD, INS_SELECT_FILE, 0x02, 0x00, 0x02
+
+#define SELECT_CACNG_APPLET_PKI  SELECT_CACNG_APPLET, 0x01
+#define SELECT_CACNG_APPLET_PIN  SELECT_CACNG_APPLET, 0x03, 0x00
+
+static const unsigned char kSelectCardManagerApplet[] =
+	{ SELECT_APPLET, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00 };
+
+static const unsigned char kSelectCACNGAppletPKI[]   =
+	{ SELECT_CACNG_APPLET_PKI, 0x00 };
+
+static const unsigned char kSelectCACNGObjectPKIID[] =
+	{ SELECT_CACNG_OBJECT, 0x01, 0x00 };
+static const unsigned char kSelectCACNGObjectPKIESig[] =
+	{ SELECT_CACNG_OBJECT, 0x01, 0x01 };
+static const unsigned char kSelectCACNGObjectPKIECry[] =
+	{ SELECT_CACNG_OBJECT, 0x01, 0x02 };
+
+static const unsigned char kSelectCACNGObjectPN[]      =
+	{ SELECT_CACNG_OBJECT, 0x02, 0x00 };
+static const unsigned char kSelectCACNGObjectPL[]      =
+	{ SELECT_CACNG_OBJECT, 0x02, 0x01 };
+/* Unknown objects... */
+static const unsigned char kSelectCACNGObjectBS[]      =
+	{ SELECT_CACNG_OBJECT, 0x02, 0x02 };
+static const unsigned char kSelectCACNGObjectOB[]      =
+	{ SELECT_CACNG_OBJECT, 0x02, 0x03 };
+
+static const unsigned char kSelectCACNGAppletPIN[]     =
+	{ SELECT_CACNG_APPLET_PIN };
+
+
+#define SELECT_PIV_APPLET_VERS	0x10, 0x00, 0x01, 0x00
+#define SELECT_PIV_APPLET_SHORT	SELECT_APPLET, 0x07, 0xA0, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00
+#define SELECT_PIV_APPLET_LONG  SELECT_APPLET, 0x0B, 0xA0, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, SELECT_PIV_APPLET_VERS
+
+static const unsigned char kSelectPIVApplet[] =
+	{ SELECT_PIV_APPLET_LONG };
+
+//	X.509 Certificate for PIV Authentication 2.16.840.1.101.3.7.2.1.1 '5FC105' M
+#define PIV_OBJECT_ID_X509_CERTIFICATE_PIV_AUTHENTICATION	0x5F, 0xC1, 0x05
+
+static const unsigned char oidX509CertificatePIVAuthentication[] = { PIV_OBJECT_ID_X509_CERTIFICATE_PIV_AUTHENTICATION };
+
+#define PIV_KEYREF_PIV_AUTHENTICATION      0x9A
+
+CACNGToken::CACNGToken() :
+	mCacPinStatus(0),mPivPinStatus(0)
+{
+	mTokenContext = this;
+	mSession.open();
+
+	/* Change pin only works if one of the CACNG applets are selected. */
+	byte_string pinAppletId(kSelectCACNGAppletPIN, kSelectCACNGAppletPIN + sizeof(kSelectCACNGAppletPIN));
+	shared_ptr<CACNGSelectable> cacPinApplet(new CACNGCacApplet(*this, pinAppletId, byte_string()));
+	this->cacPinApplet = cacPinApplet;
+
+	byte_string cardManagerAppletId(kSelectCardManagerApplet, kSelectCardManagerApplet + sizeof(kSelectCardManagerApplet));
+	shared_ptr<CACNGSelectable> cardManagerApplet(new CACNGCacApplet(*this, cardManagerAppletId, byte_string()));
+	this->cardManagerApplet = cardManagerApplet;
+
+	byte_string selectPivApplet(kSelectPIVApplet, kSelectPIVApplet + sizeof(kSelectPIVApplet));
+	shared_ptr<CACNGSelectable> pivApplet(new CACNGPivApplet(*this, selectPivApplet));
+	this->pivApplet = pivApplet;
+}
+
+CACNGToken::~CACNGToken()
+{
+	delete mSchema;
+	/* XXX: Wipe out cached pin */
+	secure_resize(cached_piv_pin, 0);
+}
+
+bool CACNGToken::identify()
+{
+	try
+	{
+		byte_string pkiApplet(kSelectCACNGAppletPKI, kSelectCACNGAppletPKI + sizeof(kSelectCACNGAppletPKI));
+		byte_string pkiIdObject(kSelectCACNGObjectPKIID, kSelectCACNGObjectPKIID + sizeof(kSelectCACNGObjectPKIID));
+		byte_string pkiESigObject(kSelectCACNGObjectPKIESig, kSelectCACNGObjectPKIESig + sizeof(kSelectCACNGObjectPKIESig));
+		shared_ptr<CACNGSelectable> idApplet(new CACNGCacApplet(*this, pkiApplet, pkiIdObject));
+		shared_ptr<CACNGSelectable> eSigApplet(new CACNGCacApplet(*this, pkiApplet, pkiESigObject));
+		select(idApplet);
+		select(eSigApplet);
+		return true;
+	}
+	catch (const PCSC::Error &error)
+	{
+		if (error.error == SCARD_E_PROTO_MISMATCH)
+			return false;
+		throw;
+	}
+}
+
+void CACNGToken::select(shared_ptr<CACNGSelectable> &selectable)
+{
+	if (isInTransaction() &&
+		(currentSelectable == selectable))
+		return;
+	 /* XXX: Resets PIV pin status to match card behavior */
+//	if (selectable != pivApplet)
+		mPivPinStatus = 0;
+	selectable->select();
+	if (isInTransaction()) {
+		currentSelectable = selectable;
+	}
+}
+
+uint32_t CACNGToken::exchangeAPDU(const unsigned char *apdu, size_t apduLength,
+	unsigned char *result, size_t &resultLength)
+{
+	size_t savedLength = resultLength;
+
+	ISO7816Token::transmit(apdu, apduLength, result, resultLength);
+	if (resultLength == 2 && result[0] == 0x61)
+	{
+		resultLength = savedLength;
+		size_t expectedLength = result[1];
+		unsigned char getResult[] = { 0x00, 0xC0, 0x00, 0x00, expectedLength };
+		if (expectedLength == 0) expectedLength = 256;
+		ISO7816Token::transmit(getResult, sizeof(getResult), result, resultLength);
+		if (resultLength - 2 != expectedLength)
+        {
+            if (resultLength < 2)
+                PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+            else
+                CACNGError::throwMe((result[resultLength - 2] << 8)
+					+ result[resultLength - 1]);
+        }
+	}
+
+	if (resultLength < 2)
+		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+
+    return (result[resultLength - 2] << 8) + result[resultLength - 1];
+}
+
+void CACNGToken::didDisconnect()
+{
+	PCSC::Card::didDisconnect();
+	currentSelectable.reset();
+	mCacPinStatus = 0;
+	mPivPinStatus = 0;
+	/* XXX: Wipe out cached pin */
+	secure_resize(cached_piv_pin, 0);
+}
+
+void CACNGToken::didEnd()
+{
+	PCSC::Card::didEnd();
+	currentSelectable.reset();
+	mCacPinStatus = 0;
+	mPivPinStatus = 0;
+	/* XXX: Wipe out cached pin */
+	secure_resize(cached_piv_pin, 0);
+}
+
+void CACNGToken::changePIN(int pinNum,
+	const unsigned char *oldPin, size_t oldPinLength,
+	const unsigned char *newPin, size_t newPinLength)
+{
+	if (pinNum != 1)
+		CssmError::throwMe(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED);
+
+	if (oldPinLength < 4 || oldPinLength > 8 ||
+		newPinLength < 4 || newPinLength > 8)
+		CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
+
+	PCSC::Transaction _(*this);
+	select(cacPinApplet);
+
+	unsigned char apdu[] =
+	{
+		0x80, 0x24, 0x01, 0x00, 0x10,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+	};
+
+	memcpy(apdu + 5, oldPin, oldPinLength);
+	memcpy(apdu + 13, newPin, newPinLength);
+
+	unsigned char result[2];
+	size_t resultLength = sizeof(result);
+
+	mCacPinStatus = exchangeAPDU(apdu, sizeof(apdu), result, resultLength);
+	memset(apdu + 5, 0, 16);
+	CACNGError::check(mCacPinStatus);
+
+	/* XXX: Wipe out cached pin */
+	secure_resize(cached_piv_pin, 0);
+}
+
+uint32_t CACNGToken::cacPinStatus()
+{
+	if (mCacPinStatus && isInTransaction()) {
+		secdebug("adhoc", "returning cached PIN status 0x%x", mCacPinStatus);
+		return mCacPinStatus;
+	}
+	
+	PCSC::Transaction _(*this);
+	/* Verify pin only works if one of the CACNG applets are selected. */
+	select(cacPinApplet);
+
+	unsigned char result[2];
+	size_t resultLength = sizeof(result);
+	unsigned char apdu[] = { 0x00, 0x20, 0x00, 0x00 };
+	
+	mCacPinStatus = exchangeAPDU(apdu, 4, result, resultLength);
+	if ((mCacPinStatus & 0xFF00) != 0x6300
+		&& mCacPinStatus != SCARD_AUTHENTICATION_BLOCKED)
+		CACNGError::check(mCacPinStatus);
+	
+	secdebug("adhoc", "new PIN status=0x%x", mCacPinStatus);
+	return mCacPinStatus;
+}
+
+uint32_t CACNGToken::pivPinStatus()
+{
+	if (mPivPinStatus && isInTransaction()) {
+		secdebug("adhoc", "returning cached PIN status 0x%x", mPivPinStatus);
+		return mPivPinStatus;
+	}
+	if (currentSelectable != pivApplet)
+		return SCARD_NOT_AUTHORIZED;
+	PCSC::Transaction _(*this);
+	/* Check PIV pin only works if one of the PIV applets are selected. */
+	select(pivApplet);
+	
+	unsigned char result[2];
+	size_t resultLength = sizeof(result);
+	unsigned char apdu[] = { 0x00, 0x20, 0x00, 0x00 };
+	
+	mPivPinStatus = exchangeAPDU(apdu, 4, result, resultLength);
+	if ((mPivPinStatus & 0xFF00) != 0x6300
+		&& mPivPinStatus != SCARD_AUTHENTICATION_BLOCKED)
+		CACNGError::check(mPivPinStatus);
+	
+	secdebug("adhoc", "new PIN status=0x%x", mPivPinStatus);
+	return mPivPinStatus;
+}
+
+uint32_t CACNGToken::pinStatus(int pinNum)
+{
+	switch (pinNum) {
+	case 1:
+		return cacPinStatus();
+	case 2:
+		return pivPinStatus();
+	default:
+		CssmError::throwMe(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED);
+	}
+}
+
+static void verify_cac(CACNGToken &token, const unsigned char *pin, size_t pinLength)
+{
+	token.select(token.cacPinApplet);
+	
+	unsigned char apdu[] =
+	{
+		0x00, 0x20, 0x00, 0x00, 0x08,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+	};
+	
+#if defined(CACNG_PROTECTED_MODE)
+	memcpy(apdu + 5, "77777777", 8);
+#else
+	memcpy(apdu + 5, pin, pinLength);
+#endif
+	
+	unsigned char result[2];
+	size_t resultLength = sizeof(result);
+	
+	token.mCacPinStatus = token.exchangeAPDU(apdu, sizeof(apdu), result, resultLength);
+	memset(apdu + 5, 0, 8);
+	CACNGError::check(token.mCacPinStatus);	
+}
+
+
+
+static void verify_piv(CACNGToken &token, const unsigned char *pin, size_t pinLength)
+{
+	unsigned char apdu[] =
+	{
+		0x00, 0x20, 0x00, 0x80, 0x08,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+	};
+	
+#if defined(CACNG_PROTECTED_MODE)
+	memcpy(apdu + 5, "77777777", 8);
+#else
+	memcpy(apdu + 5, pin, pinLength);
+#endif
+	
+	unsigned char result[2];
+	size_t resultLength = sizeof(result);
+	token.select(token.pivApplet);
+	token.mPivPinStatus = token.exchangeAPDU(apdu, sizeof(apdu), result, resultLength);
+	memset(apdu + 5, 0, 8);
+	CACNGError::check(token.mPivPinStatus);
+}
+
+void CACNGToken::verifyPIN(int pinNum,
+	const unsigned char *pin, size_t pinLength)
+{
+	if (pinNum != 1 && pinNum != 2)
+		CssmError::throwMe(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED);
+	PCSC::Transaction _(*this);
+	switch (pinNum) {
+	case 1:
+		if (pinLength < 4 || pinLength > 8)
+			CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
+
+		/* Verify pin only works if one of the CACNG applets are selected. */
+		verify_cac(*this, pin, pinLength);
+
+		// Start a new transaction which we never get rid of until someone calls
+		// unverifyPIN()
+		begin();
+		break;
+	case 2:
+		if (pinLength < 1 || pinLength > 8)
+			CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE);
+		/* Verify pin only works if one of the CACNG applets are selected. */
+		verify_piv(*this, pin, pinLength);
+		/* XXX: CACHED PIN */
+		cached_piv_pin.assign(pin, pin + pinLength);
+		// Start a new transaction which we never get rid of until someone calls
+		// unverifyPIN()
+		begin();
+		break;
+	}
+}
+
+void CACNGToken::verifyCachedPin(int pinNum)
+{
+	if (pinNum != 2)
+		return;
+	/* XXX: PIN CACHE */
+	if (cached_piv_pin.empty())
+		return;
+	try {
+		verify_piv(*this, &cached_piv_pin[0], cached_piv_pin.size());
+	} catch (...) {
+		/* XXX: Wipe out cache if anything goes wrong */
+		secure_resize(cached_piv_pin, 0);
+		throw;
+	}
+}
+
+void CACNGToken::unverifyPIN(int pinNum)
+{
+	if (pinNum != -1)
+		CssmError::throwMe(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED);
+	/* XXX: Wipe out cached pin */
+	secure_resize(cached_piv_pin, 0);
+	end(SCARD_RESET_CARD);
+}
+
+uint32_t CACNGToken::getData(unsigned char *result, size_t &resultLength)
+{
+	PCSC::Transaction _(*this);
+	try
+	{
+		select(cardManagerApplet);
+	}
+	catch (const PCSC::Error &error)
+	{
+		return error.error;
+	}
+
+	unsigned char apdu[] = { 0x80, INS_GET_DATA, 0x9F, 0x7F, 0x2D };
+	return exchangeAPDU(apdu, sizeof(apdu), result, resultLength);
+}
+
+uint32 CACNGToken::probe(SecTokendProbeFlags flags,
+	char tokenUid[TOKEND_MAX_UID])
+{
+	uint32 score = Tokend::ISO7816Token::probe(flags, tokenUid);
+
+	bool doDisconnect = false; /*!(flags & kSecTokendProbeKeepToken); */
+
+	try
+	{
+//		PCSC::Card::reconnect(SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1);
+		if (!identify())
+			doDisconnect = true;
+		else
+		{
+			unsigned char result[0x2F];
+			size_t resultLength = sizeof(result);
+			(void)getData(result, resultLength);
+			/* Score of 200 to ensure that CACNG "wins" for Hybrid CACNG/PIV cards */
+				score = 300;
+				// Now stick in the bytes returned by getData into the
+				// tokenUid.
+			if(resultLength > 20)
+				{
+					sprintf(tokenUid,
+						"CACNG-%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X",
+						result[3], result[4], result[5], result[6], result[19],
+						result[20], result[15], result[16], result[17],
+						result[18]);
+				}
+			else
+			{
+				/* Cannot generated a tokenUid given the returned data.
+				 * Generate time-based tokenUid to permit basic caching */
+				unsigned char buffer[80];
+				time_t now;
+				struct tm* timestruct = localtime(&now);
+				/* Print out the # of seconds since EPOCH UTF */
+				strftime(reinterpret_cast<char *>(buffer), 80, "%s", timestruct);
+				snprintf(tokenUid, TOKEND_MAX_UID, "CACNG-%s", buffer);
+			}
+			Tokend::ISO7816Token::name(tokenUid);
+			secdebug("probe", "recognized %s", tokenUid);
+		}
+	}
+	catch (...)
+	{
+		doDisconnect = true;
+		score = 0;
+	}
+
+	if (doDisconnect)
+		disconnect();
+
+	return score;
+}
+
+void CACNGToken::establish(const CSSM_GUID *guid, uint32 subserviceId,
+	SecTokendEstablishFlags flags, const char *cacheDirectory,
+	const char *workDirectory, char mdsDirectory[PATH_MAX],
+	char printName[PATH_MAX])
+{
+	Tokend::ISO7816Token::establish(guid, subserviceId, flags,
+		cacheDirectory, workDirectory, mdsDirectory, printName);
+
+	mSchema = new CACNGSchema();
+	mSchema->create();
+
+	populate();
+}
+
+//
+// Database-level ACLs
+//
+void CACNGToken::getOwner(AclOwnerPrototype &owner)
+{
+	// we don't really know (right now), so claim we're owned by PIN #0
+	if (!mAclOwner)
+	{
+		mAclOwner.allocator(Allocator::standard());
+		mAclOwner = AclFactory::PinSubject(Allocator::standard(), 0);
+	}
+	owner = mAclOwner;
+}
+
+
+void CACNGToken::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls)
+{
+	Allocator &alloc = Allocator::standard();
+	
+	if (unsigned pin = pinFromAclTag(tag, "?")) {
+		static AutoAclEntryInfoList acl;
+		acl.clear();
+		acl.allocator(alloc);
+		uint32_t status = this->pinStatus(pin);
+		if (status == SCARD_SUCCESS)
+			acl.addPinState(pin, CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED);
+		else if (status >= CACNG_AUTHENTICATION_FAILED_0 && status <= CACNG_AUTHENTICATION_FAILED_3)
+			acl.addPinState(pin, 0, status - CACNG_AUTHENTICATION_FAILED_0);
+		else
+			acl.addPinState(pin, CSSM_ACL_PREAUTH_TRACKING_UNKNOWN);
+		count = acl.size();
+		acls = acl.entries();
+		return;
+	}
+
+	// mAclEntries sets the handle of each AclEntryInfo to the
+	// offset in the array.
+
+	// get pin list, then for each pin
+	if (!mAclEntries) {
+		mAclEntries.allocator(alloc);
+        // Anyone can read the attributes and data of any record on this token
+        // (it's further limited by the object itself).
+		mAclEntries.add(CssmClient::AclFactory::AnySubject(
+			mAclEntries.allocator()),
+			AclAuthorizationSet(CSSM_ACL_AUTHORIZATION_DB_READ, 0));
+        // We support PIN1 with either a passed in password
+        // subject or a prompted password subject.
+		mAclEntries.addPin(AclFactory::PWSubject(alloc), 1);
+		mAclEntries.addPin(AclFactory::PWSubject(alloc), 2);
+		mAclEntries.addPin(AclFactory::PromptPWSubject(alloc, CssmData()), 1);
+		mAclEntries.addPin(AclFactory::PromptPWSubject(alloc, CssmData()), 2);
+	}
+	count = mAclEntries.size();
+	acls = mAclEntries.entries();
+}
+
+
+#pragma mark ---------------- CACNG Specific --------------
+
+uint32_t CACNGToken::exchangeAPDU(const byte_string &apdu, byte_string &result)
+{
+	static const uint8_t GET_RESULT_TEMPLATE [] = { 0x00, 0xC0, 0x00, 0x00, 0xFF };
+	byte_string getResult(GET_RESULT_TEMPLATE, GET_RESULT_TEMPLATE + sizeof(GET_RESULT_TEMPLATE));
+	const int SIZE_INDEX = 4;
+	
+	transmit(apdu, result);
+	/* Keep pulling more data */
+	while (result.size() >= 2 && result[result.size() - 2] == 0x61)
+	{
+		size_t expectedLength = result[result.size() - 1];
+		if(expectedLength == 0) /* 256-byte case .. */
+			expectedLength = 256;
+		getResult[SIZE_INDEX] = expectedLength;
+		// Trim off status bytes
+		result.resize(result.size() - 2);
+		size_t appended = transmit(getResult, result);
+		if (appended != (expectedLength + 2))
+        {
+            if (appended < 2)
+                PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+            else
+                CACNGError::throwMe((result[result.size() - 2] << 8)
+								  + result[result.size() - 1]);
+        }
+	}
+	
+	if (result.size() < 2)
+		PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+	uint16_t ret = (result[result.size() - 2] << 8) + result[result.size() - 1];
+	// Trim off status bytes
+	result.resize(result.size() - 2);
+    return ret;
+}
+
+size_t CACNGToken::transmit(const byte_string::const_iterator &apduBegin, const byte_string::const_iterator &apduEnd, byte_string &result) {
+	const size_t BUFFER_SIZE = 1024;
+	size_t resultLength = BUFFER_SIZE;
+	size_t index = result.size();
+	/* To prevent data leaking, secure byte_string resize takes place */
+	secure_resize(result, result.size() + BUFFER_SIZE);
+	ISO7816Token::transmit(&(*apduBegin), (size_t)(apduEnd - apduBegin), &result[0]+ index, resultLength);
+	/* Trims the data, no expansion occurs */
+	result.resize(index + resultLength);
+	return resultLength;
+}
+
+
+uint32_t CACNGToken::exchangeChainedAPDU(
+	unsigned char cla, unsigned char ins,
+	unsigned char p1, unsigned char p2,
+	const byte_string &data,
+	byte_string &result)
+{
+	byte_string apdu;
+	apdu.reserve(5 + data.size());
+	apdu.resize(5);
+	apdu[0] = cla;
+	apdu[1] = ins;
+	apdu[2] = p1;
+	apdu[3] = p2;
+	
+	apdu[0] |= 0x10;
+	apdu += data;
+	const size_t BASE_CHUNK_LENGTH = 255;
+	size_t chunkLength;
+	byte_string::const_iterator iter;
+	/* Chain data and skip last chunk since its in the receiving end */
+	for(iter = data.begin(); (iter + BASE_CHUNK_LENGTH) < data.end(); iter += BASE_CHUNK_LENGTH) {
+		chunkLength = std::min(BASE_CHUNK_LENGTH, (size_t)(data.end() - iter));
+		apdu[4] = chunkLength & 0xFF;
+		/* Don't send Le */
+		transmit(apdu.begin(), apdu.begin() + 5 + chunkLength, result);
+		/* No real data should come back until chaining is complete */
+		if(result.size() != 2)
+			PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
+		else
+			CACNGError::check(result[result.size() - 2] << 8 | result[result.size() - 1]);
+		/* Trim off result SW */
+		result.resize(result.size() - 2);
+		// Trim off old data
+		apdu.erase(apdu.begin() + 5, apdu.begin() + 5 + chunkLength);
+	}
+	apdu[0] &= ~0x10;
+	apdu[4] = (apdu.size() - 5) & 0xFF;
+	/* LE BYTE? */
+	return exchangeAPDU(apdu, result);
+}
+
+
+void CACNGToken::populate()
+{
+	secdebug("populate", "CACNGToken::populate() begin");
+	Tokend::Relation &certRelation =
+		mSchema->findRelation(CSSM_DL_DB_RECORD_X509_CERTIFICATE);
+	Tokend::Relation &privateKeyRelation =
+		mSchema->findRelation(CSSM_DL_DB_RECORD_PRIVATE_KEY);
+	Tokend::Relation &dataRelation =
+		mSchema->findRelation(CSSM_DL_DB_RECORD_GENERIC);
+
+	byte_string pkiApplet(kSelectCACNGAppletPKI, kSelectCACNGAppletPKI + sizeof(kSelectCACNGAppletPKI));
+
+	shared_ptr<CACNGSelectable> idApplet(new CACNGCacApplet(*this, pkiApplet,
+		byte_string(kSelectCACNGObjectPKIID, kSelectCACNGObjectPKIID + sizeof(kSelectCACNGObjectPKIID))));
+	shared_ptr<CACNGSelectable> sigApplet(new CACNGCacApplet(*this, pkiApplet,
+		byte_string(kSelectCACNGObjectPKIESig, kSelectCACNGObjectPKIESig + sizeof(kSelectCACNGObjectPKIESig))));
+	shared_ptr<CACNGSelectable> encApplet(new CACNGCacApplet(*this, pkiApplet,
+		byte_string(kSelectCACNGObjectPKIECry, kSelectCACNGObjectPKIECry + sizeof(kSelectCACNGObjectPKIECry))));
+
+	shared_ptr<CACNGIDObject> idObject(new CACNGCacIDObject(*this, idApplet, "Identity Certificate"));
+	shared_ptr<CACNGIDObject> sigObject(new CACNGCacIDObject(*this, sigApplet, "Email Signature Certificate"));
+	shared_ptr<CACNGIDObject> encObject(new CACNGCacIDObject(*this, encApplet, "Email Encryption Certificate"));
+	RefPointer<Tokend::Record> idCert(new CACNGCertificateRecord(idObject, "Identity Certificate"));
+	RefPointer<Tokend::Record> eSigCert(new CACNGCertificateRecord(sigObject, "Email Signing Certificate"));
+	RefPointer<Tokend::Record> eCryCert(new CACNGCertificateRecord(encObject, "Email Encryption Certificate"));
+
+#if 1
+	certRelation.insertRecord(idCert);
+	certRelation.insertRecord(eSigCert);
+	certRelation.insertRecord(eCryCert);
+
+	RefPointer<Tokend::Record> idKey(new CACNGKeyRecord(idObject, "Identity Private Key",
+		privateKeyRelation.metaRecord(), true));
+	RefPointer<Tokend::Record> eSigKey(new CACNGKeyRecord(sigObject, "Email Signing Private Key",
+		privateKeyRelation.metaRecord(), true));
+	RefPointer<Tokend::Record> eCryKey(new CACNGKeyRecord(encObject, "Email Encryption Private Key",
+		privateKeyRelation.metaRecord(), false));
+
+	privateKeyRelation.insertRecord(idKey);
+	privateKeyRelation.insertRecord(eSigKey);
+	privateKeyRelation.insertRecord(eCryKey);
+
+	idKey->setAdornment(mSchema->publicKeyHashCoder().certificateKey(),
+                        new Tokend::LinkedRecordAdornment(idCert));
+	eSigKey->setAdornment(mSchema->publicKeyHashCoder().certificateKey(),
+                          new Tokend::LinkedRecordAdornment(eSigCert));
+	eCryKey->setAdornment(mSchema->publicKeyHashCoder().certificateKey(),
+                          new Tokend::LinkedRecordAdornment(eCryCert));
+#endif
+	static const char *applets[][3] = {
+		{(char*)kSelectCACNGObjectPN, "PNTB", "PNVB"},
+		{(char*)kSelectCACNGObjectPL, "PLTB", "PLVB"},
+		{(char*)kSelectCACNGObjectBS, "BSTB", "BSVB"},
+		{(char*)kSelectCACNGObjectOB, "OBTB", "OBVB"},
+		{NULL, NULL, NULL}
+	};
+	for (int i = 0; applets[i][0]; i++) {
+		shared_ptr<CACNGSelectable> applet(new CACNGCacApplet(
+			*this,
+			pkiApplet,
+			byte_string(applets[i][0], applets[i][0] + 7)));
+		shared_ptr<CACNGReadable> tbuffer(new CACNGCacBufferObject(*this, applet, true));
+		shared_ptr<CACNGReadable> vbuffer(new CACNGCacBufferObject(*this, applet, false));
+		dataRelation.insertRecord(new CACNGDataRecord(tbuffer, applets[i][1]));
+		dataRelation.insertRecord(new CACNGDataRecord(vbuffer, applets[i][2]));
+	}
+
+	/* PIV AUTH KEY */
+	byte_string pivAuthOid(oidX509CertificatePIVAuthentication, oidX509CertificatePIVAuthentication + sizeof(oidX509CertificatePIVAuthentication));
+	
+	shared_ptr<CACNGIDObject> pivAuthObject(new CACNGPivIDObject(*this, pivApplet, "Piv Authentication Certificate", pivAuthOid, PIV_KEYREF_PIV_AUTHENTICATION));
+	RefPointer<Tokend::Record> pivAuthCert(new CACNGCertificateRecord(pivAuthObject, "Piv Authentication Certificate"));
+
+	certRelation.insertRecord(pivAuthCert);
+	
+	RefPointer<Tokend::Record> pivAuthKey(new CACNGKeyRecord(pivAuthObject, "Piv Authentication Private Key",
+		privateKeyRelation.metaRecord(), true, true));
+	privateKeyRelation.insertRecord(pivAuthKey);
+
+	pivAuthKey->setAdornment(mSchema->publicKeyHashCoder().certificateKey(),
+                        new Tokend::LinkedRecordAdornment(pivAuthCert));
+	
+	secdebug("populate", "CACNGToken::populate() end");
+}
+

Added: branches/tokend/10.5/CACNG/CACNGToken.h
===================================================================
--- branches/tokend/10.5/CACNG/CACNGToken.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CACNGToken.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ *  CACNGToken.h
+ *  TokendMuscle
+ */
+
+#ifndef _CACNGTOKEN_H_
+#define _CACNGTOKEN_H_
+
+#include <Token.h>
+#include "TokenContext.h"
+
+#include <security_utilities/pcsc++.h>
+
+#include "byte_string.h"
+
+#include "CACNGApplet.h"
+
+class CACNGSchema;
+
+//
+// "The" token
+//
+class CACNGToken : public Tokend::ISO7816Token
+{
+	NOCOPY(CACNGToken)
+public:
+	CACNGToken();
+	~CACNGToken();
+
+	virtual void didDisconnect();
+	virtual void didEnd();
+
+    virtual uint32 probe(SecTokendProbeFlags flags,
+		char tokenUid[TOKEND_MAX_UID]);
+	virtual void establish(const CSSM_GUID *guid, uint32 subserviceId,
+		SecTokendEstablishFlags flags, const char *cacheDirectory,
+		const char *workDirectory, char mdsDirectory[PATH_MAX],
+		char printName[PATH_MAX]);
+	virtual void getOwner(AclOwnerPrototype &owner);
+	virtual void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls);
+
+	virtual void changePIN(int pinNum,
+		const unsigned char *oldPin, size_t oldPinLength,
+		const unsigned char *newPin, size_t newPinLength);
+	uint32_t pivPinStatus();
+	uint32_t cacPinStatus();
+	virtual uint32_t pinStatus(int pinNum);
+	virtual void verifyPIN(int pinNum, const unsigned char *pin, size_t pinLength);
+	void verifyCachedPin(int pinNum);
+	virtual void unverifyPIN(int pinNum);
+
+	bool identify();
+	void select(shared_ptr<CACNGSelectable> &obj);
+
+	uint32_t exchangeAPDU(const unsigned char *apdu, size_t apduLength,
+                          unsigned char *result, size_t &resultLength);
+
+	uint32_t getData(unsigned char *result, size_t &resultLength);
+
+	uint32_t exchangeAPDU(const byte_string& apdu, byte_string &result);
+	uint32_t exchangeChainedAPDU(
+		unsigned char cla, unsigned char ins,
+		unsigned char p1, unsigned char p2,
+		const byte_string &data,
+		byte_string &result);
+protected:
+	void populate();
+
+	size_t transmit(const byte_string &apdu, byte_string &result) {
+		return transmit(apdu.begin(), apdu.end(), result);
+	}
+	size_t transmit(const byte_string::const_iterator &apduBegin, const byte_string::const_iterator &apduEnd, byte_string &result);
+	
+public:
+	shared_ptr<CACNGSelectable> currentSelectable;
+	uint32_t mCacPinStatus;
+	uint32_t mPivPinStatus;
+	shared_ptr<CACNGSelectable> cacPinApplet;
+	shared_ptr<CACNGSelectable> cardManagerApplet;
+	shared_ptr<CACNGSelectable> pivApplet;
+
+	// temporary ACL cache hack - to be removed
+	AutoAclOwnerPrototype mAclOwner;
+	AutoAclEntryInfoList mAclEntries;
+
+	byte_string cached_piv_pin;
+};
+
+
+#endif /* !_CACNGTOKEN_H_ */
+

Added: branches/tokend/10.5/CACNG/CompressionTool.cpp
===================================================================
--- branches/tokend/10.5/CACNG/CompressionTool.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CompressionTool.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,48 @@
+/*
+ *  CompressionTool.cpp
+ *  Tokend
+ *
+ *  Created by harningt on 9/30/09.
+ *  Copyright 2009 TrustBearer Labs. All rights reserved.
+ *
+ */
+
+
+#include "CompressionTool.h"
+#include <security_cdsa_utilities/cssmerrors.h>
+#include <Security/cssmerr.h>
+
+#include <zlib.h>
+byte_string CompressionTool::zlib_decompress(const byte_string::const_iterator &begin, const byte_string::const_iterator &end)
+{
+	static const int CHUNK_SIZE = 4096;
+	byte_string output;
+	int ret;
+	z_stream strm;
+	memset(&strm, 0, sizeof(strm));
+	ret = inflateInit2(&strm, 15 + 32); /* Handle optional zlib/gzip headers */
+	if (ret != Z_OK)
+		CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
+	strm.avail_in = end - begin;
+	strm.next_in = (uint8_t*)&*begin;
+	do {
+		uint8_t buffer[CHUNK_SIZE];
+		strm.avail_out = sizeof(buffer);
+		strm.next_out = buffer;
+		ret = inflate(&strm, Z_NO_FLUSH);
+		switch (ret) {
+		case Z_NEED_DICT:
+			ret = Z_DATA_ERROR;
+		case Z_DATA_ERROR:
+		case Z_MEM_ERROR:
+			(void)inflateEnd(&strm);
+			CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
+		}
+		size_t available = sizeof(buffer) - strm.avail_out;
+		output.insert(output.end(), buffer, buffer + available);
+	} while (strm.avail_out == 0);
+	(void)inflateEnd(&strm);
+	if (ret != Z_STREAM_END)
+		CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
+	return output;
+}
\ No newline at end of file

Added: branches/tokend/10.5/CACNG/CompressionTool.h
===================================================================
--- branches/tokend/10.5/CACNG/CompressionTool.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/CompressionTool.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,19 @@
+/*
+ *  CompressionTool.h
+ *  Tokend
+ *
+ *  Created by harningt on 9/30/09.
+ *  Copyright 2009 TrustBearer Labs. All rights reserved.
+ *
+ */
+
+
+#include "byte_string.h"
+
+class CompressionTool {
+public:
+	static byte_string zlib_decompress(const byte_string &compressedData) {
+		return zlib_decompress(compressedData.begin(), compressedData.end());
+	}
+	static byte_string zlib_decompress(const byte_string::const_iterator &begin, const byte_string::const_iterator &end);
+};
\ No newline at end of file

Added: branches/tokend/10.5/CACNG/Info.plist
===================================================================
--- branches/tokend/10.5/CACNG/Info.plist	                        (rev 0)
+++ branches/tokend/10.5/CACNG/Info.plist	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>CACNG</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.apple.tokend.cacng</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>CACNG</string>
+	<key>CFBundlePackageType</key>
+	<string>????</string>
+	<key>CFBundleShortVersionString</key>
+	<string>2.1.1</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>

Added: branches/tokend/10.5/CACNG/Padding.cpp
===================================================================
--- branches/tokend/10.5/CACNG/Padding.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/Padding.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,159 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Padding.h"
+
+#include <Security/cssmerr.h>
+//#include "PIVUtilities.h"
+
+using namespace Security;
+
+/* PKCS#1 DigestInfo header for SHA1 */
+static const unsigned char sha1sigheader[] =
+{
+	0x30, // SEQUENCE
+	0x21, // LENGTH
+		0x30, // SEQUENCE
+		0x09, // LENGTH
+			0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1a, // SHA1 OID (1 4 14 3 2 26)
+			0x05, 0x00, // OPTIONAL ANY algorithm params (NULL)
+		0x04, 0x14 // OCTECT STRING (20 bytes)
+};
+
+/* PKCS#1 DigestInfo header for MD5 */
+static const unsigned char md5sigheader[] =
+{
+	0x30, // SEQUENCE
+	0x20, // LENGTH
+		0x30, // SEQUENCE
+		0x0C, // LENGTH
+			// MD5 OID (1 2 840 113549 2 5)
+			0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,
+			0x05, 0x00, // OPTIONAL ANY algorithm params (NULL)
+		0x04, 0x10 // OCTECT STRING (16 bytes)
+};
+
+void Padding::apply(byte_string &data, size_t keySize, CSSM_PADDING padding, CSSM_ALGORITHMS hashAlg) throw(CssmError) {
+	// Calculate which hash-header to use
+	const unsigned char *header;
+	size_t headerLength;
+	switch(hashAlg) {
+	case CSSM_ALGID_SHA1:
+		if (data.size() != 20)
+			CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);
+		header = sha1sigheader;
+		headerLength = sizeof(sha1sigheader);
+		break;
+	case CSSM_ALGID_MD5:
+		if (data.size() != 16)
+			CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);
+		header = md5sigheader;
+		headerLength = sizeof(md5sigheader);
+		break;
+	case CSSM_ALGID_NONE:
+		// Special case used by SSL it's an RSA signature, without the ASN1 stuff
+		header = NULL;
+		headerLength = 0;
+		break;
+	default:
+		CssmError::throwMe(CSSMERR_CSP_INVALID_DIGEST_ALGORITHM);
+	}
+	// Reserve memory and insert the header before the data
+	data.reserve(keySize);
+	if(headerLength > 0) {
+		data.insert(data.begin(), header, header + headerLength);
+	}
+	// Calculate and apply padding
+	switch (padding) {
+	case CSSM_PADDING_NONE:
+		if(data.size() != keySize)
+			CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);
+		break;
+	case CSSM_PADDING_PKCS1:
+		// Pad using PKCS1 v1.5 signature padding ( 00 01 FF FF.. 00 | M)
+		if(data.size() + 11 > keySize)
+			CssmError::throwMe(CSSMERR_CSP_BLOCK_SIZE_MISMATCH);
+		int markerByteLocation = keySize - data.size() - 1;
+		data.insert(data.begin(), keySize - data.size(), 0xFF);
+		data[0] = 0;
+		data[1] = 1;
+		data[markerByteLocation] = 0;
+		break;
+	default:
+		CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
+	}
+}
+
+void Padding::remove(byte_string &data, CSSM_PADDING padding) throw(CssmError) {
+	// Calculate and remove padding while validating
+	switch (padding) {
+	case CSSM_PADDING_NONE:
+		break;
+	case CSSM_PADDING_PKCS1:
+		unsigned i;
+		/* Handles PKCS1 v1.5
+		 * signatures         00 01 FF FF.. 00 | M
+		 * and encrypted data 00 02 NZ NZ.. 00 | M   (NZ = non-zero random value)
+		 */
+		if(data[0] != 0 || (data[1] != 1 && data[1] != 2))
+			CssmError::throwMe(CSSMERR_CSP_INVALID_DATA);
+		for(i = 2; i < data.size() && data[i] != 0x00; i++) {}
+		/* Assume empty data is invalid */
+		if(data.size() - i == 0)
+			CssmError::throwMe(CSSMERR_CSP_INVALID_DATA);
+		secure_erase(data, data.begin(), data.begin() + i + 1);
+		break;
+	default:
+		CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
+	}
+}
+
+bool Padding::canApply(CSSM_PADDING padding, CSSM_ALGORITHMS hashAlg) throw() {
+	switch(padding) {
+	case CSSM_PADDING_NONE:
+	case CSSM_PADDING_PKCS1:
+		break;
+	default:
+		return false;
+	}
+	switch(hashAlg) {
+	case CSSM_ALGID_NONE:
+	case CSSM_ALGID_SHA1:
+	case CSSM_ALGID_MD5:
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
+bool Padding::canRemove(CSSM_PADDING padding) throw() {
+	switch(padding) {
+	case CSSM_PADDING_NONE:
+	case CSSM_PADDING_PKCS1:
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
\ No newline at end of file

Added: branches/tokend/10.5/CACNG/Padding.h
===================================================================
--- branches/tokend/10.5/CACNG/Padding.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/Padding.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef PADDING_H
+#define PADDING_H
+
+#include "byte_string.h"
+#include <Security/cssmtype.h>
+#include <security_cdsa_utilities/cssmerrors.h>
+
+/** Utility class to unify padding/hash-header handling
+ *
+ */
+class Padding {
+public:
+	/** Applies padding and hash-headers for signing */
+	static void apply(byte_string &data, size_t keySize, CSSM_PADDING padding = CSSM_PADDING_NONE, CSSM_ALGORITHMS hashAlg = CSSM_ALGID_NONE) throw(CssmError);
+	/** Removes padding for decryption
+	 * Note: Securely eliminates data such that the 'leftover' bytes are not left to be read after data's destruction
+	 */
+	static void remove(byte_string &data, CSSM_PADDING padding = CSSM_PADDING_NONE) throw(CssmError);
+
+	/** Returns boolean whether a specific padding/hash-header can be applied */
+	static bool canApply(CSSM_PADDING padding = CSSM_PADDING_NONE, CSSM_ALGORITHMS hashAlg = CSSM_ALGID_NONE) throw();
+	/** Returns boolean whether a specific padding can be removed */
+	static bool canRemove(CSSM_PADDING padding) throw();
+};
+
+#endif
\ No newline at end of file

Added: branches/tokend/10.5/CACNG/TLV.cpp
===================================================================
--- branches/tokend/10.5/CACNG/TLV.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/TLV.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,185 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "TLV.h"
+
+#include <iomanip>
+#include <iostream>
+#include <limits>
+
+using namespace std;
+
+TLV::TLV() throw()
+:tag(), value(NULL), innerValues(NULL) {
+}
+
+TLV::TLV(unsigned char tag) throw()
+:tag(1, tag), value(NULL), innerValues(NULL) {
+}
+
+TLV::TLV(const byte_string& tag) throw()
+:tag(tag), value(NULL), innerValues(NULL) {
+}
+
+TLV::TLV(unsigned char tag, const byte_string& value) throw()
+:tag(1, tag), value(new byte_string(value)), innerValues(NULL) {
+}
+
+TLV::TLV(const byte_string& tag, const byte_string& value) throw()
+:tag(tag), value(new byte_string(value)), innerValues(NULL) {
+}
+
+TLV::TLV(uint8_t tag, const TLVList &tlv) throw()
+:tag(1, tag), value(NULL), innerValues(new TLVList(tlv)) {
+}
+
+TLV::TLV(const byte_string &tag, const TLVList &tlv) throw()
+:tag(tag), value(NULL), innerValues(new TLVList(tlv)) {
+}
+
+TLV_ref TLV::parse(const byte_string &in) throw(std::runtime_error) {
+	byte_string::const_iterator begin = in.begin();
+	return parse(begin, in.end());
+}
+
+byte_string TLV::encode() const throw() {
+	byte_string out;
+	encode(out);
+	return out;
+}
+
+void TLV::encode(byte_string &out) const throw() {
+	const byte_string &tag = getTag();
+	// Puts the tag
+	out += tag;
+	// Puts the length
+	encodeLength(valueLength(), out);
+
+#if 1
+	// Non-caching version since the TLV is expected to be
+	// thrown away after encoding
+	// If there is a value, put that
+	if(value.get()) {
+		out += *value;
+		return;
+	}
+	if(!innerValues.get())
+		return;
+	// Else if there are innerValues, encode those out
+	encodeSequence(*innerValues, out);
+#else
+	// Obtain the value in a cached manner
+	const byte_string &value = getValue();
+	out += value;
+#endif
+}
+
+const TLVList &TLV::getInnerValues() const throw(std::runtime_error) {
+	/* If there is a cached innervalues version, output it
+	 * else parse any existing TLV data and use that */
+	if(innerValues.get()) return *innerValues;
+	if(!value.get()) {
+		innerValues.reset(new TLVList());
+		return *innerValues;
+	}
+	innerValues.reset(new TLVList());
+	byte_string::const_iterator begin = value->begin();
+	parseSequence(begin, (byte_string::const_iterator)value->end(), *innerValues);
+
+	return *innerValues;
+}
+
+const byte_string &TLV::getValue() const throw() {
+	/* If there is a cached value version, output it
+	 * else encode any existing TLV data and use that */
+	if(value.get()) return *value;
+	if(!innerValues.get()) {
+		value.reset(new byte_string());
+		return *value;
+	}
+	value.reset(new byte_string());
+	encodeSequence(*innerValues, *value);
+	return *value;
+}
+
+size_t TLV::length() const throw() {
+	size_t innerLength = valueLength();
+	return tag.size() + encodedLength(innerLength) + innerLength;
+}
+
+void TLV::encodeLength(size_t value, byte_string &out) throw() {
+	/* Encode and output the length according to BER-TLV encoding rules */
+	static const size_t MAX_VALUE = std::numeric_limits<size_t>::max();
+	static const size_t highbyte = (MAX_VALUE ^ (MAX_VALUE >> 8));
+	static const size_t shiftbyte = (sizeof(size_t) - 1) * 8;
+	if (value < 0x80) {
+		out += (unsigned char)(value & 0x7F);
+		return;
+	}
+	size_t size = sizeof(value), i;
+	while(0 == (value & highbyte) && size > 0) {
+		value <<= 8;
+		size--;
+	}
+	out += (unsigned char)(0x80 | size);
+	for(i = 0; i < size; i++) {
+		out += (unsigned char)((value >> shiftbyte) & 0xFF);
+		value <<= 8;
+	}
+}
+
+size_t TLV::encodedLength(size_t value) throw() {
+	if(value < 0x80)
+		return 1;
+	/* Values larger than 0x7F must be encoded in the form (Length-Bytes) (Length) */
+	static const size_t MAX_VALUE = std::numeric_limits<size_t>::max();
+	/* EX: 0xFF000000 - for size_t == 32-bit */
+	static const size_t highbyte = (MAX_VALUE ^ (MAX_VALUE >> 8));
+	size_t size = sizeof(value);
+	/* Check for the highest byte that contains a value */
+	while(0 == (value & highbyte) && size > 0) {
+		value <<= 8;
+		size--;
+	}
+	/* + 1 for byte-size byte
+	 * Size encoded as (0x80 + N) [N-bytes]
+	 * Max size-bytes == 127
+	 */
+	return size + 1;
+}
+
+void TLV::encodeSequence(const TLVList &tlv, byte_string &out) throw() {
+	for(TLVList::const_iterator iter = tlv.begin(); iter < tlv.end(); iter++)
+		(*iter)->encode(out);
+}
+
+size_t TLV::valueLength() const throw() {
+	/* Calculate the length of a value, either by its actual value length
+	 * or calculated length based on contained TLV values */
+	if(value.get()) return value->size();
+	if(!innerValues.get()) return 0;
+	size_t retValue = 0;
+	for(TLVList::const_iterator iter = innerValues->begin(); iter < innerValues->end(); iter++)
+		retValue += (*iter)->length();
+	return retValue;
+}

Added: branches/tokend/10.5/CACNG/TLV.h
===================================================================
--- branches/tokend/10.5/CACNG/TLV.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/TLV.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,143 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef TLV_H
+#define TLV_H
+
+#include <tr1/memory>
+
+#include <stdexcept>
+
+#include <sstream>
+#include <vector>
+
+#ifndef NOCOPY
+#define NOCOPY(Type)    private: Type(const Type &); void operator = (const Type &);
+#endif
+
+#include "byte_string.h"
+
+class TLV;
+typedef std::tr1::shared_ptr<TLV> TLV_ref;
+typedef std::vector<TLV_ref> TLVList;
+
+/** Utility class to simplify TLV parsing and encoding
+ *  Condition of proper behavior (assume sizeof(size_t) => ptr size):
+ *  32-bit: Total data < 4GB
+ *  64-bit: Total data < 4GB * 4GB
+ */
+class TLV {
+	NOCOPY(TLV);
+public:
+	TLV() throw();
+	TLV(uint8_t tag) throw();
+	TLV(const byte_string &tag) throw();
+	TLV(uint8_t tag, const byte_string &value) throw();
+	TLV(const byte_string &tag, const byte_string &value) throw();
+	TLV(const byte_string &tag, const TLVList &tlv) throw();
+	TLV(uint8_t tag, const TLVList &tlv) throw();
+
+	/* Parses a byte_string as a TLV value - ignores trailing bytes
+	 * Throws an error if the encoding is invalid
+	 */
+	static TLV_ref parse(const byte_string &data) throw(std::runtime_error);
+
+	/* Parses an entire sequence of bytes as a TLV value
+	 * - ignores trailing bytes, iter points to byte after TLV
+	 * Can accept forward iterators to bytes or pointers to bytes for the range
+	 * Ex: byte_string::iterator, unsigned char *
+	 * Throws an error if the encoding is invalid
+	 */
+	template<typename ForwardIterator>
+	static TLV_ref parse(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error);
+
+	/* Obtains the tag of this TLV */
+	const byte_string &getTag() const throw() { return tag; }
+
+	/* Encodes this TLV into a new byte_string */
+	byte_string encode() const throw();
+	/* Encodes this TLV, appending the data to 'out' */
+	void encode(byte_string &out) const throw();
+	/* Decodes the value of this TLV as a sequence of TLVs */
+	const TLVList &getInnerValues() const throw(std::runtime_error);
+	/* Obtains the value of this TLV */
+	const byte_string &getValue() const throw();
+
+	/* Calculates the length of this TLV */
+	size_t length() const throw();
+
+private:
+	byte_string tag;
+	/* cached/assigned value as a string */
+	mutable std::auto_ptr<byte_string> value;
+	/* cached/assigned value as a TLV sequence */
+	mutable std::auto_ptr<TLVList> innerValues;
+
+	/* Parses an entire sequence of bytes as a sequence of TLV values, appending them to tlv
+	 * Can accept forward iterators to bytes or pointers to bytes for the range
+	 * Ex: byte_string::iterator, unsigned char *
+	 * Throws an error if the encoding is invalid
+	 */
+	template<typename ForwardIterator>
+	static void parseSequence(ForwardIterator &iter, const ForwardIterator &end, TLVList &tlv) throw(std::runtime_error);
+
+	/* Parses the ber-encoded length from a sequence of bytes
+	 * Can accept forward iterators to bytes or pointers to bytes for the range
+	 * Ex: byte_string::iterator, unsigned char *
+	 * Throws an error if the encoding is invalid
+	 */
+	template<typename ForwardIterator>
+	static size_t parseLength(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error);
+
+	/* ber-encodes an integer and writes it's output to 'out' */
+	static void encodeLength(size_t value, byte_string &out) throw();
+public:
+	/* Obtains the length of a ber-encoded integer that would contain the value */
+	static size_t encodedLength(size_t value) throw();
+private:
+	/* Encodes a sequence of TLVs, writing the to 'out' */
+	static void encodeSequence(const TLVList &tlv, byte_string &out) throw();
+
+	/* Calculates the total length of the value */
+	size_t valueLength() const throw();
+};
+
+class TagPredicate {
+public:
+	TagPredicate(uint8_t tag) throw()
+	:tag(1, tag) {
+	}
+	TagPredicate(const byte_string &tag) throw()
+	:tag(tag) {
+	}
+	bool operator() (const TLV_ref &tlv) throw() {
+		return this->tag == tlv->getTag();
+	}
+private:
+	byte_string tag;
+};
+
+/* TEMPLATE DEFINITIONS */
+#include "TLV.inc"
+
+#endif

Added: branches/tokend/10.5/CACNG/TLV.inc
===================================================================
--- branches/tokend/10.5/CACNG/TLV.inc	                        (rev 0)
+++ branches/tokend/10.5/CACNG/TLV.inc	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,104 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+template<typename ForwardIterator>
+void TLV::parseSequence(ForwardIterator &iter, const ForwardIterator &end, TLVList &tlv) throw(std::runtime_error) {
+	/* While there is still data inbetween the iterators */
+	while(iter < end) {
+		/* parse TLV structures and append them to the list */
+		TLV_ref ref = TLV::parse(iter, end);
+		tlv.push_back(ref);
+	}
+}
+
+template<typename ForwardIterator>
+TLV_ref TLV::parse(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error) {
+	byte_string tag;
+	uint8_t ch;
+	if(iter >= end) throw std::runtime_error("Invalid TLV-encoding");
+	/* Read the first byte as the tag */
+	ch = *iter++;
+	tag += ch;
+	if(iter >= end) throw std::runtime_error("Invalid TLV-encoding");
+	/* If the tag is flagged as a multibyte tag */
+	if((ch & 0x1F) == 0x1F) { /* Multibyte tag */
+		do {
+			ch = *iter++;
+			tag += ch;
+			if(iter >= end) throw std::runtime_error("Invalid TLV-encoding");
+			/* Read more until there are no more bytes w/o the high-bit set */
+		} while((ch & 0x80) != 0);
+	}
+	/* Parse the length of the contained value */
+	size_t length = parseLength(iter, end);
+	ForwardIterator begin = iter;
+	iter += length;
+	/* The iterator is permitted to be at the very and at this point */
+	if(iter > end) throw std::runtime_error("Invalid TLV-encoding");
+	/* Return a new TLV with the calculated tag and value */
+	return TLV_ref(new TLV(tag, byte_string(begin, iter)));
+}
+
+/*
+	BER-TLV
+	Reference: http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-4_annex-d.aspx
+
+	In short form, the length field consists of a single byte where the bit B8 shall be set to 0 and
+	the bits B7-B1 shall encode an integer equal to the number of bytes in the value field. Any length
+	from 0-127 can thus be encoded by 1 byte.
+
+	In long form, the length field consists of a leading byte where the bit B8 shall be set to 1 and
+	the B7-B1 shall not be all equal, thus encoding a positive integer equal to the number of subsequent
+	bytes in the length field. Those subsequent bytes shall encode an integer equal to the number of bytes
+	in the value field. Any length within the APDU limit (up to 65535) can thus be encoded by 3 bytes.
+
+	NOTE - ISO/IEC 7816 does not use the indefinite lengths specified by the basic encoding rules of
+	ASN.1 (see ISO/IEC 8825).
+
+	Sample data (from a certficate GET DATA):
+
+	00000000  53 82 04 84 70 82 04 78  78 da 33 68 62 db 61 d0
+	00000010  c4 ba 60 01 33 13 23 13  13 97 e2 dc 88 f7 0c 40
+	00000020  20 da 63 c0 cb c6 a9 d5  e6 d1 f6 9d 97 91 91 95
+	....
+	00000460  1f 22 27 83 ef fe ed 5e  7a f3 e8 b6 dc 6b 3f dc
+	00000470  4c be bc f5 bf f2 70 7e  6b d0 4c 00 80 0d 3f 1f
+	00000480  71 01 80 72 03 49 44 41
+
+*/
+template<typename ForwardIterator>
+size_t TLV::parseLength(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error) {
+	// Parse a BER length field. Returns the value of the length
+	uint8_t ch = *iter++;
+	if (!(ch & 0x80))	// single byte
+		return static_cast<uint32_t>(ch);
+	size_t result = 0;
+	uint8_t byteLen = ch & 0x7F;
+	for(;byteLen > 0; byteLen--) {
+		if(iter == end)
+			throw std::runtime_error("Invalid BER-encoded length");
+		ch = *iter++;
+		result = (result << 8) | static_cast<uint8_t>(ch);
+	}
+	return result;
+}

Added: branches/tokend/10.5/CACNG/byte_string.h
===================================================================
--- branches/tokend/10.5/CACNG/byte_string.h	                        (rev 0)
+++ branches/tokend/10.5/CACNG/byte_string.h	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef BYTE_STRING
+#define BYTE_STRING
+
+#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
+#include <vector>
+
+/** Utility definition and additional operators to make working with
+ * sequences of bytes more easy and less error/leak-prone
+ */
+typedef std::vector<uint8_t> byte_string;
+
+inline bool operator==(const byte_string &l, const byte_string::value_type &value) {
+	return l.size() == 1 && l.at(0) == value;
+}
+
+inline byte_string &operator+=(byte_string &l, const byte_string::value_type &value) {
+	l.push_back(value);
+	return l;
+}
+inline byte_string &operator+=(byte_string &l, const char &value) {
+	l.push_back(value);
+	return l;
+}
+
+inline byte_string &operator+=(byte_string &l, const byte_string::value_type *value) {
+	l.insert(l.end(), value, value + strlen((char*)value));
+	return l;
+}
+
+inline byte_string &operator+=(byte_string &l, const byte_string &r) {
+	l.insert(l.end(), r.begin(), r.end());
+	return l;
+}
+
+/* RHS must be null-terminated */
+inline bool operator==(const byte_string& l, const byte_string::value_type* r) {
+	byte_string::size_type lSize = l.size();
+	byte_string::size_type rSize = strlen((const char*)r);
+	if(lSize != rSize)
+		return false;
+	return equal(l.begin(), l.end(), r);
+}
+
+inline bool operator!=(const byte_string& l, const byte_string::value_type* r) {
+	return !(l == r);
+}
+
+inline unsigned char *malloc_copy(const byte_string::const_iterator &begin, const byte_string::const_iterator &end) {
+	size_t len = end - begin;
+	unsigned char *output = (unsigned char*)malloc(len);
+	if(!output)
+		return NULL;
+	memcpy(output, &*begin, len);
+	return output;
+}
+inline unsigned char *malloc_copy(const byte_string &l) {
+	return malloc_copy(l.begin(), l.end());
+}
+
+#include <algorithm>
+
+template<typename T>
+inline void secure_zero(T &l) {
+	std::fill(l.begin(), l.end(), typename T::value_type());
+}
+
+template<typename T>
+inline void secure_erase(T &data, const typename T::iterator &first, const typename T::iterator &last) {
+	/* Partly borrowing from alg used by normal 'erase' */
+	typename T::iterator newEnd(std::copy(last, data.end(), first));
+	// Filling w/ defaults to null values out
+	std::fill(newEnd, data.end(), typename T::value_type());
+	data.erase(newEnd, data.end());
+}
+
+template<typename T>
+inline void secure_resize(T &data, const size_t newSize) {
+	// Simple case where no re-allocation occurs
+	if(data.capacity() >= newSize) {
+		data.resize(newSize);
+		return;
+	}
+	// Re-allocation will occur, need to use temporary buffer...
+	T temporary(data);
+	secure_zero(data);
+	data.resize(newSize);
+	copy(temporary.begin(), temporary.end(), data.begin());
+	secure_zero(temporary);
+}
+
+#endif

Added: branches/tokend/10.5/CACNG/cacng.cpp
===================================================================
--- branches/tokend/10.5/CACNG/cacng.cpp	                        (rev 0)
+++ branches/tokend/10.5/CACNG/cacng.cpp	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ *  @APPLE_LICENSE_HEADER_START@
+ *  
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *  
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *  
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * cac.cpp - CACNGtokend main program
+ */
+
+#include "CACNGToken.h"
+
+int main(int argc, const char *argv[])
+{
+	secdebug("CACNG	.tokend", "main starting with %d arguments", argc);
+	secdelay("/tmp/delay/CACNG");
+
+#if 0
+	setenv("DEBUGSCOPE", "-mutex,walkers", 0);
+	setenv("DEBUGOPTIONS", "scope,thread,date", 0);
+	setenv("DEBUGDEST", "/var/tmp/securityd-log", 0);
+	setenv("DEBUGDUMP", "stdout", 0);
+#endif
+
+	token = new CACNGToken();
+	try {
+		int ret = SecTokendMain(argc, argv, token->callbacks(), token->support());
+		delete token;
+		return ret;
+	} catch (...) {
+		delete token;
+		return -1;
+	}
+}
+

Added: branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities.mdsinfo
===================================================================
--- branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities.mdsinfo	                        (rev 0)
+++ branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities.mdsinfo	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>Capabilities</key>
+	<string>file:cacng_csp_capabilities_common.mds</string>
+	<key>MdsFileDescription</key>
+	<string>CACNG Token CSPDL CSP Capabilities</string>
+	<key>MdsFileType</key>
+	<string>PluginSpecific</string>
+	<key>MdsRecordType</key>
+	<string>MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE</string>
+</dict>
+</plist>

Added: branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities_common.mds
===================================================================
--- branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities_common.mds	                        (rev 0)
+++ branches/tokend/10.5/CACNG/mds/cacng_csp_capabilities_common.mds	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,903 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_SHA1</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_OUTPUT_SIZE</string>
+				<key>AttributeValue</key>
+				<integer>20</integer>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_DIGEST</string>
+		<key>Description</key>
+		<string>SHA1 Digest</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_MD5</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_OUTPUT_SIZE</string>
+				<key>AttributeValue</key>
+				<integer>16</integer>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_DIGEST</string>
+		<key>Description</key>
+		<string>MD5 Digest</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_MD2</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_OUTPUT_SIZE</string>
+				<key>AttributeValue</key>
+				<integer>16</integer>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_DIGEST</string>
+		<key>Description</key>
+		<string>MD2 Digest</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>RSA Key Pair Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_DES</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_KEY_LENGTH</string>
+				<key>AttributeValue</key>
+				<integer>64</integer>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>DES Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_3DES_3KEY</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_KEY_LENGTH</string>
+				<key>AttributeValue</key>
+				<integer>192</integer>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>3DES Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RC2</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>RC2 Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RC4</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>RC4 Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RC5</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>RC5 Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_CAST</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>New item</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>CAST Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_BLOWFISH</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>Blowfish Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_SHA1HMAC</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>SHA1HMAC Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_MD5HMAC</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>MD5HMAC Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_AES</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_KEY_LENGTH</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>128</integer>
+					<integer>192</integer>
+					<integer>256</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>AES Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_ASC</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>ASC Key Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_FEE</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_KEY_LENGTH</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>31</integer>
+					<integer>127</integer>
+					<integer>128</integer>
+					<integer>161</integer>
+					<integer>192</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>FEE Key Pair Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_DSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_KEYGEN</string>
+		<key>Description</key>
+		<string>DSA Key Pair Generation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_PKCS5_PBKDF2</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_DERIVEKEY</string>
+		<key>Description</key>
+		<string>PKCS5 Key Derivation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_PKCS5_PBKDF1_MD5</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_DERIVEKEY</string>
+		<key>Description</key>
+		<string>PKCS5 PBKDF1 MD5 Key Derivation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_PKCS5_PBKDF1_MD2</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_DERIVEKEY</string>
+		<key>Description</key>
+		<string>PKCS5 PBKDF1 MD2 Key Derivation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_PKCS5_PBKDF1_SHA1</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_DERIVEKEY</string>
+		<key>Description</key>
+		<string>PKCS5 PBKDF1 SHA1 Key Derivation</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_DES</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_MODE</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>2</integer>
+					<integer>3</integer>
+					<integer>5</integer>
+					<integer>6</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SYMMETRIC</string>
+		<key>Description</key>
+		<string>DES Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_3DES_3KEY_EDE</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_MODE</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>2</integer>
+					<integer>3</integer>
+					<integer>5</integer>
+					<integer>6</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SYMMETRIC</string>
+		<key>Description</key>
+		<string>3DES EDE Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_AES</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_MODE</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>2</integer>
+					<integer>3</integer>
+					<integer>5</integer>
+					<integer>6</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SYMMETRIC</string>
+		<key>Description</key>
+		<string>AES Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RC4</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_MODE</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>0</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SYMMETRIC</string>
+		<key>Description</key>
+		<string>RC4 Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RC5</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_MODE</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>2</integer>
+					<integer>3</integer>
+					<integer>5</integer>
+					<integer>6</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SYMMETRIC</string>
+		<key>Description</key>
+		<string>RC5 Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_BLOWFISH</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_MODE</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>2</integer>
+					<integer>3</integer>
+					<integer>5</integer>
+					<integer>6</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SYMMETRIC</string>
+		<key>Description</key>
+		<string>Blowfish Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_CAST</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_MODE</string>
+				<key>AttributeValue</key>
+				<array>
+					<integer>2</integer>
+					<integer>3</integer>
+					<integer>5</integer>
+					<integer>6</integer>
+				</array>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SYMMETRIC</string>
+		<key>Description</key>
+		<string>CAST Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_ASYMMETRIC</string>
+		<key>Description</key>
+		<string>RSA Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_FEEDEXP</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_ASYMMETRIC</string>
+		<key>Description</key>
+		<string>FEEDExp Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_FEED</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_ASYMMETRIC</string>
+		<key>Description</key>
+		<string>FEED Encryption</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_SHA1WithRSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>SHA1 With RSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_MD5WithRSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>MD5 With RSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_MD2WithRSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>MD2 With RSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_RSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>Raw RSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_SHA1WithDSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>SHA1 With DSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_DSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>Raw DSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_FEE_MD5</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>MD5 with FEE Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_FEE_SHA1</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>SHA1 with FEE Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_FEE</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>Raw FEE Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_SHA1WithECDSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>SHA1 with ECDSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_ECDSA</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_SIGNATURE</string>
+		<key>Description</key>
+		<string>Raw ECDSA Signature</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_SHA1HMAC</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_OUTPUT_SIZE</string>
+				<key>AttributeValue</key>
+				<integer>20</integer>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_MAC</string>
+		<key>Description</key>
+		<string>SHA1HMAC MAC</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_SHA1HMAC_LEGACY</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_OUTPUT_SIZE</string>
+				<key>AttributeValue</key>
+				<integer>20</integer>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_MAC</string>
+		<key>Description</key>
+		<string>SHA1HMAC MAC Legacy</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+	<dict>
+		<key>AlgType</key>
+		<string>CSSM_ALGID_APPLE_YARROW</string>
+		<key>Attributes</key>
+		<array>
+			<dict>
+				<key>AttributeType</key>
+				<string>CSSM_ATTRIBUTE_NONE</string>
+				<key>AttributeValue</key>
+				<array/>
+			</dict>
+		</array>
+		<key>ContextType</key>
+		<string>CSSM_ALGCLASS_RANDOMGEN</string>
+		<key>Description</key>
+		<string>Yarrow PRNG</string>
+		<key>UseeTag</key>
+		<string>CSSM_USEE_NONE</string>
+	</dict>
+</array>
+</plist>

Added: branches/tokend/10.5/CACNG/mds/cacng_csp_primary.mdsinfo
===================================================================
--- branches/tokend/10.5/CACNG/mds/cacng_csp_primary.mdsinfo	                        (rev 0)
+++ branches/tokend/10.5/CACNG/mds/cacng_csp_primary.mdsinfo	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>AclSubjectTypes</key>
+	<array>
+		<string>CSSM_ACL_SUBJECT_TYPE_PASSWORD</string>
+		<string>CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD</string>
+		<string>CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD</string>
+	</array>
+	<key>AuthTags</key>
+	<!-- @@@ complete this -->
+	<array>
+		<string>CSSM_ACL_AUTHORIZATION_ANY</string>
+	</array>
+	<key>CspCustomFlags</key>
+	<integer>0</integer>
+	<key>CspFlags</key>
+	<!-- @@@ dynamic -->
+	<string>CSSM_CSP_STORES_PRIVATE_KEYS | CSSM_CSP_STORES_PUBLIC_KEYS | CSSM_CSP_STORES_CERTIFICATES | CSSM_CSP_STORES_GENERIC</string>
+	<key>CspType</key>
+	<string>CSSM_CSP_HARDWARE</string>
+	<key>MdsFileDescription</key>
+	<string>Token CSPDL CSP Primary info</string>
+	<key>MdsFileType</key>
+	<string>PluginSpecific</string>
+	<key>MdsRecordType</key>
+	<string>MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE</string>
+	<key>ModuleName</key>
+	<string>AppleSDCSPDL</string>
+	<key>ProductVersion</key>
+	<string>0.1</string>
+	<key>SampleTypes</key>
+	<array>
+		<string>CSSM_SAMPLE_TYPE_PASSWORD</string>
+		<string>CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD</string>
+		<string>CSSM_SAMPLE_TYPE_PROTECTED_PASSWORD</string>
+	</array>
+	<key>UseeTags</key>
+	<array/>
+	<key>Vendor</key>
+	<string>Apple Computer, Inc.</string>
+</dict>
+</plist>

Added: branches/tokend/10.5/CACNG/mds/cacng_dl_primary.mdsinfo
===================================================================
--- branches/tokend/10.5/CACNG/mds/cacng_dl_primary.mdsinfo	                        (rev 0)
+++ branches/tokend/10.5/CACNG/mds/cacng_dl_primary.mdsinfo	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>AclSubjectTypes</key>
+	<array>
+		<string>CSSM_ACL_SUBJECT_TYPE_PASSWORD</string>
+		<string>CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD</string>
+		<string>CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD</string>
+	</array>
+	<key>AuthTags</key>
+	<array>
+	<!-- @@@ complete this -->
+		<string>CSSM_ACL_AUTHORIZATION_ANY</string>
+	</array>
+	<key>ConjunctiveOps</key>
+	<array>
+		<string>CSSM_DB_NONE</string>
+		<string>CSSM_DB_AND</string>
+		<string>CSSM_DB_OR</string>
+	</array>
+	<key>DLType</key>
+	<string>CSSM_DL_FFS</string>
+	<key>MdsFileDescription</key>
+	<string>Token CSPDL DL Primary info</string>
+	<key>MdsFileType</key>
+	<string>PluginSpecific</string>
+	<key>MdsRecordType</key>
+	<string>MDS_CDSADIR_DL_PRIMARY_RECORDTYPE</string>
+	<key>ModuleName</key>
+	<string>AppleSDCSPDL</string>
+	<key>ProductVersion</key>
+	<string>0.1</string>
+	<key>QueryLimitsFlag</key>
+	<integer>0</integer>
+	<key>RelationalOps</key>
+	<array>
+		<string>CSSM_DB_EQUAL</string>
+		<string>CSSM_DB_LESS_THAN</string>
+		<string>CSSM_DB_GREATER_THAN</string>
+		<string>CSSM_DB_CONTAINS_FINAL_SUBSTRING</string>
+		<string>CSSM_DB_CONTAINS_INITIAL_SUBSTRING</string>
+		<string>CSSM_DB_CONTAINS</string>
+		<string></string>
+	</array>
+	<key>SampleTypes</key>
+	<array>
+		<string>CSSM_SAMPLE_TYPE_PASSWORD</string>
+		<string>CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD</string>
+		<string>CSSM_SAMPLE_TYPE_PROTECTED_PASSWORD</string>
+	</array>
+	<key>Vendor</key>
+	<string>Apple Computer, Inc.</string>
+</dict>
+</plist>

Added: branches/tokend/10.5/CACNG/mds/cacng_smartcard.mdsinfo
===================================================================
--- branches/tokend/10.5/CACNG/mds/cacng_smartcard.mdsinfo	                        (rev 0)
+++ branches/tokend/10.5/CACNG/mds/cacng_smartcard.mdsinfo	2010-11-16 20:05:44 UTC (rev 135)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>MdsFileDescription</key>
+	<string>SD/CSPDL Generic Smartcard Information</string>
+	<key>MdsRecordType</key>
+	<string>MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE</string>
+	<key>MdsFileType</key>
+	<string>PluginSpecific</string>
+	<key>ScVendor</key>
+	<string>Generic</string>
+	<key>ScVersion</key>
+	<string>unknown</string>
+	<key>ScFirmwareVersion</key>
+	<string>CACNGViewerPlugin</string>
+	<key>ScFlags</key>			<!-- @@@ dynamic -->
+	<integer>0</integer>
+	<key>ScCustomFlags</key>
+	<integer>0</integer>
+</dict>
+</plist>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/smartcardservices-changes/attachments/20101116/d4733192/attachment-0001.html>


More information about the SmartcardServices-Changes mailing list