[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