[SmartcardServices-Changes] [140] trunk/SmartCardServices/src/PKCS11dotNetV2

source_changes at macosforge.org source_changes at macosforge.org
Mon Feb 20 05:53:32 PST 2012


Revision: 140
          http://trac.macosforge.org/projects/smartcardservices/changeset/140
Author:   ludovic.rousseau at gmail.com
Date:     2012-02-20 05:52:47 -0800 (Mon, 20 Feb 2012)
Log Message:
-----------
Move all sources files in main directory

Added Paths:
-----------
    trunk/SmartCardServices/src/PKCS11dotNetV2/Array.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/Array.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/Except.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am
    trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/MarshallerCfg.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/application.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/application.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/config.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_global.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/des.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/des.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/digest.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/digest.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/error.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/error.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/event.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/event.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/ha_config.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/log.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/log.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/md5.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/md5.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11f.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11t.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/platconfig.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/resource.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/session.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/session.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/slot.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/slot.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/template.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/template.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/thread.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/thread.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/timer.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/timer.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/util.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/util.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.h

Removed Paths:
-------------
    trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/Array.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Array.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Array.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,974 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable:4201)
+#endif
+
+#include <string.h>
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+#include <stdexcept>
+#include "MarshallerCfg.h"
+#include "Except.h"
+#include "Array.h"
+
+// Determine Processor Endianess
+#include <limits.h>
+#if (UINT_MAX == 0xffffffffUL)
+   typedef unsigned int _u4;
+#else
+#  if (ULONG_MAX == 0xffffffffUL)
+     typedef unsigned long _u4;
+#  else
+#    if (USHRT_MAX == 0xffffffffUL)
+       typedef unsigned short _u4;
+#    endif
+#  endif
+#endif
+
+_u4 _endian = 1;
+
+bool isLittleEndian = (*((unsigned char *)(&_endian))) ? true  : false;
+bool isBigEndian    = (*((unsigned char *)(&_endian))) ? false : true;
+MARSHALLER_NS_BEGIN
+
+
+static u4 ToBigEndian(u4 val)
+{
+    if (isBigEndian)
+    {
+	    return val;
+    }
+    else
+    {
+        u4 res;
+        res =  val << 24;
+        res |= (val << 8) & 0x00FF0000;
+        res |= (val >> 8) & 0x0000FF00;
+        res |= val >> 24;
+
+        return res;
+    }
+}
+
+static u2 ToBigEndian(u2 val)
+{
+    if (isBigEndian)
+    {
+    	return val;
+    }
+    else
+    {
+        return (u2)((val << 8) | (val >> 8));
+    }
+}
+
+static u8 ToBigEndian(u8 val)
+{
+    if (isBigEndian)
+    {
+    	return val;
+    }
+    else
+    {
+	    u4 val1 = (u4)(val >> 32);
+	    u4 val2 = (u4)val;
+
+        val1 = ToBigEndian(val1);
+        val2 = ToBigEndian(val2);
+
+	    return (u8)(((u8)val2 << 32) | val1);
+    }
+}
+
+u2 ComputeUTF8Length(M_SAL_IN lpCharPtr str)
+{
+    u4 nCharProcessed = 0;
+    u4 pair;
+    u4 count;
+    u2 leftOver;
+    u4 charIndex;
+
+    count = 0;
+    leftOver = 0;
+    charIndex = 0;
+
+    while (nCharProcessed < (u4)strlen(str)) {
+        u2 ch = (u2)str[charIndex++];
+
+        if (leftOver == 0) {
+			if ((ch >= 0xD800) && (ch <= 0xDBFF)) {
+				// This is a low-part of a surrogate pair.
+				leftOver = (u2)ch;
+                nCharProcessed++;
+				continue;
+			} else {
+				// This is a regular character.
+				pair = (u4)ch;
+			}
+		} else if ((ch >= 0xDC00) && (ch <= 0xDFFF)) {
+			// This is a high-part of a surrogate pair. We now have a complete surrogate pair.
+			pair = ((leftOver - (u4)0xD800) << 10) + (((u4)ch) - (u4)0xDC00) + (u4)0x10000;
+			leftOver = 0;
+		} else {
+            goto error;
+		}
+
+        // Encode the character pair value.
+		if (pair < (u4)0x0080) {
+            count++;
+		} else if (pair < (u4)0x0800) {
+            count += 2;
+		} else if (pair < (u4)0x10000) {
+            count += 3;
+		} else {
+            count += 4;
+		}
+
+        nCharProcessed++;
+    }
+
+    if (leftOver != 0) {
+        goto error;
+    }
+
+	return (u2)count;
+
+error:;
+    throw Exception("Error while compute UTF8 encoding length");
+}
+
+void UTF8Encode(M_SAL_IN lpCharPtr str, u1Array &utf8Data)
+{
+    u4 nCharProcessed = 0;
+    u4 pair;
+    u2 leftOver;
+    u1* bytes = utf8Data.GetBuffer();
+    u4 byteCount;
+    u4 byteIndex = 0;
+    u4 charIndex = 0;
+
+    byteCount = utf8Data.GetLength();
+
+    leftOver = 0;
+
+    while (nCharProcessed < (u4)strlen(str)) {
+        u2 ch = str[charIndex++];
+
+        if (leftOver == 0) {
+			if ((ch >= 0xD800) && (ch <= 0xDBFF)) {
+				// This is a low-part of a surrogate pair.
+				leftOver = (u2)ch;
+                nCharProcessed++;
+				continue;
+			} else {
+				// This is a regular character.
+				pair = (u4)ch;
+			}
+		} else if ((ch >= 0xDC00) && (ch <= 0xDFFF)) {
+			// This is a high-part of a surrogate pair. We now have a complete surrogate pair.
+			pair = ((leftOver - (u4)0xD800) << 10) + (((u4)ch) - (u4)0xDC00) + (u4)0x10000;
+			leftOver = 0;
+		} else {
+            goto error;
+		}
+
+        // Encode the character pair value.
+		if (pair < (u4)0x0080) {
+            if (byteIndex >= byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)pair;
+		} else if (pair < (u4)0x0800) {
+            if ((byteIndex + 2) > byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)(0xC0 | (pair >> 6));
+			bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+		} else if (pair < (u4)0x10000) {
+            if ((byteIndex + 3) > byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)(0xE0 | (pair >> 12));
+			bytes[byteIndex++] = (u1)(0x80 | ((pair >> 6) & 0x3F));
+			bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+		} else {
+            if ((byteIndex + 4) > byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)(0xF0 | (pair >> 18));
+			bytes[byteIndex++] = (u1)(0x80 | ((pair >> 12) & 0x3F));
+			bytes[byteIndex++] = (u1)(0x80 | ((pair >> 6) & 0x3F));
+			bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+		}
+
+        nCharProcessed++;
+    }
+
+end:;
+    // we do accept byteIndex <= byteCount (dest buffer length > what is really necessary).
+    if (byteIndex > byteCount) {
+        goto error;
+    }
+
+    if (leftOver != 0) {
+        goto error;
+    }
+
+    return;
+
+error:;
+    throw Exception("Error while performing UTF8 encoding");
+}
+
+u2 ComputeLPSTRLength(u1Array &array, u4 offset, u4 len)
+{
+	if ((u8)(offset + len) > (u8)array.GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	} else {
+		u2 charlen = 0;
+		u4 i;
+		u1* buff = array.GetBuffer();
+
+		for (i = 0; i < len;) {
+			if ((buff[i + offset] & 0x80) == 0) {
+				i += 1;
+			}
+			else if ((buff[i + offset] & 0xE0) == 0xC0) {
+				i += 2;
+			}
+			else if ((buff[i + offset] & 0xF0) == 0xE0) {
+				i += 3;
+			}
+			else {
+				throw Exception("Error parsing UTF-8 bytes");
+			}
+			charlen++;
+		}
+		return charlen;
+	}
+}
+
+void UTF8Decode(u1Array &array, u4 offset, u4 len, M_SAL_INOUT lpCharPtr &charData)
+{
+	if ((u8)(offset + len) > (u8)array.GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	} else {
+		u4 i = 0;
+		u4 pos = 0;
+		u1* buff = array.GetBuffer();
+
+		for (i = 0; i < len;) {
+			if ((buff[i + offset] & 0x80) == 0) {
+				charData[pos] = buff[i + offset];
+				i += 1;
+			}
+			else if ((buff[i + offset] & 0xE0) == 0xC0) {
+				charData[pos] = ((buff[i + offset] & 0x1F) << 6) | (buff[i+1 + offset] & 0x3F);
+				i += 2;
+			}
+			else if ((buff[i + offset] & 0xF0) == 0xE0) {
+				charData[pos] = ((buff[i + offset] & 0x0F) << 12) | ((buff[i+1 + offset] & 0x3F) << 6) | (buff[i+2 + offset] & 0x3F);
+				i += 3;
+			}
+			else{
+				throw Exception("Error parsing UTF-8 bytes");
+			}
+			pos++;
+		}
+	}
+}
+
+// *******************
+// String Array class
+// *******************
+StringArray::StringArray(s4 nelement)
+{
+    this->_length = nelement;
+
+	if (nelement < 0) {
+        nelement = 0;
+    }
+
+	this->buffer = new std::string*[nelement];
+
+	// we need to initialize the buffer to zeros
+	for(s4 i=0;i<nelement;i++)
+		this->buffer[i] = NULL;
+
+}
+
+StringArray::StringArray(const StringArray &rhs)
+{
+	s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+
+	this->buffer = new std::string*[len];
+
+	for(s4 i=0;i<len;i++)
+		this->buffer[i] = rhs.buffer[i];
+
+}
+
+StringArray::~StringArray(void)
+{
+    // delete the strings in the StringArray
+    for(u4 i = 0; i < GetLength(); i++){
+        if (buffer[i] != NULL) {
+            delete buffer[i];
+            buffer[i] = NULL;
+        }
+    }
+
+	delete[] buffer;
+}
+
+u1 StringArray::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+u4 StringArray::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+std::string* StringArray::GetStringAt(u4 index)
+{
+	if (index >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[index];
+}
+
+void StringArray::SetStringAt(u4 index, M_SAL_IN std::string* str)
+{
+	if (index >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+	this->buffer[index] = str;
+}
+
+// *******************
+// Byte Array class
+// *******************
+
+u1Array::u1Array()
+{
+  this->_length = 0;
+// JCD
+  this->buffer = NULL;//new u1[0];
+// JCD
+}
+
+u1Array::u1Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u1[nelement];
+}
+
+u1Array::u1Array(const u1Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u1[len];
+    memcpy(this->buffer, rhs.buffer, len);
+}
+
+u1Array::u1Array(u1Array &array, u4 offset, u4 len)
+{
+	if ((u8)(offset + len) > array.GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	} else {
+		this->_length = len;
+		this->buffer = new u1[len];
+		memcpy(this->buffer, array.buffer + offset, len);
+	}
+}
+
+u1Array::~u1Array(void)
+{
+    if (this->buffer != NULL) {
+        delete[] this->buffer;
+        this->buffer = NULL;
+    }
+}
+
+u1 u1Array::IsNull(void) const
+{
+    return (this->_length < 0);
+}
+
+void u1Array::SetU1At(u4 pos, u1 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+
+u1 u1Array::ReadU1At(u4 pos) const
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u1Array::GetLength(void) const
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u1Array::SetBuffer(const u1* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength());
+}
+
+const u1* u1Array::GetBuffer(void) const
+{
+    return this->buffer;
+}
+
+u1* u1Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+// 1 byte add
+u1Array& u1Array::operator +(u1 val)
+{
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u1));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u1));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u1 val)
+{
+    u1* tempBuffer = new u1[this->GetLength() + sizeof(u1)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u1));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u1);
+    return *this;
+}
+
+// 2 bytes add
+u1Array& u1Array::operator +(u2 val)
+{
+    val = ToBigEndian(val);
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u2));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u2));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u2 val)
+{
+    val = ToBigEndian(val);
+    u1* tempBuffer = new u1[this->GetLength() + sizeof(u2)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u2));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u2);
+    return *this;
+}
+
+// 4 bytes add
+u1Array& u1Array::operator +(u4 val)
+{
+    val = ToBigEndian(val);
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u4));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u4));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u4 val)
+{
+    val = ToBigEndian(val);
+    u1* tempBuffer = new u1[this->GetLength() + sizeof(u4)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u4));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u4);
+    return *this;
+}
+
+// 8 bytes add
+u1Array& u1Array::operator +(u8 val)
+{
+	val = ToBigEndian(val);
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u8));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u8));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u8 val)
+{
+	val = ToBigEndian(val);
+	u1* tempBuffer = new u1[this->GetLength() + sizeof(u8)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u8));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u8);
+    return *this;
+}
+
+
+// bytes array add
+u1Array& u1Array::operator =(const u1Array &bArray)
+{
+    delete[] buffer; buffer = 0;
+    _length = bArray._length;
+    buffer = new u1[_length > 0 ? _length : 0];
+    if(_length>0)
+        memcpy(buffer, bArray.buffer, _length);
+    return *this;
+}
+
+u1Array& u1Array::operator +(u1Array &bArray)
+{
+    s4 len;
+    if (IsNull() && bArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + bArray.GetLength();
+    }
+    u1Array* newArray = new u1Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], bArray.buffer, bArray.GetLength());
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u1Array &bArray)
+{
+    u1* tempBuffer = new u1[this->GetLength() + bArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], bArray.buffer, bArray.GetLength());
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && bArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + bArray.GetLength();
+    }
+    return *this;
+}
+
+u1Array& u1Array::Append(std::string* str)
+{
+	if (str == NULL) {
+        *this += (u2)0xFFFF;
+    } else {
+		u2 strLen = ComputeUTF8Length((lpCharPtr)str->c_str());
+        *this += strLen;
+        u1Array strArray(strLen);
+		UTF8Encode((lpCharPtr)str->c_str(), strArray);
+        *this += strArray;
+    }
+    return *this;
+}
+
+// *******************
+// UShort Array class
+// *******************
+u2Array::u2Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u2[nelement];
+}
+
+u2Array::u2Array(const u2Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u2[len];
+    memcpy(this->buffer, rhs.buffer, len * sizeof(u2));
+}
+
+u2Array::~u2Array(void)
+{
+    delete[] this->buffer;
+}
+
+u1 u2Array::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+void u2Array::SetU2At(u4 pos, u2 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+u2 u2Array::ReadU2At(u4 pos)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u2Array::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u2Array::SetBuffer(u2* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength() * sizeof(u2));
+}
+
+u2* u2Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+// 2 bytes add
+u2Array& u2Array::operator +(u2 val)
+{
+    u2Array* newArray = new u2Array(this->GetLength() + 1);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u2));
+	newArray->buffer[this->GetLength()] = val;
+    return *newArray;
+}
+
+u2Array& u2Array::operator +=(u2 val)
+{
+    u2* tempBuffer = new u2[this->GetLength() + 1];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u2));
+	tempBuffer[this->GetLength()] = val;
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + 1;
+    return *this;
+}
+
+// Char array add
+u2Array& u2Array::operator +(u2Array &cArray)
+{
+    s4 len;
+	if (IsNull() && cArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + cArray.GetLength();
+    }
+    u2Array* newArray = new u2Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u2));
+    memcpy(&newArray->buffer[this->GetLength() * sizeof(u2)], cArray.buffer, cArray.GetLength() * sizeof(u2));
+    return *newArray;
+}
+
+u2Array& u2Array::operator +=(u2Array &cArray)
+{
+    u2* tempBuffer = new u2[this->GetLength() + cArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u2));
+    memcpy(&tempBuffer[this->GetLength() * sizeof(u2)], cArray.buffer, cArray.GetLength() * sizeof(u2));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && cArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + cArray.GetLength();
+    }
+    return *this;
+}
+
+// *******************
+// Int Array class
+// *******************
+u4Array::u4Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u4[nelement];
+}
+
+u4Array::u4Array(const u4Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u4[len];
+    memcpy(this->buffer, rhs.buffer, len * sizeof(u4));
+}
+
+u4Array::~u4Array(void)
+{
+    delete[] this->buffer;
+}
+
+u1 u4Array::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+void u4Array::SetU4At(u4 pos, u4 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+u4 u4Array::ReadU4At(u4 pos)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u4Array::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u4Array::SetBuffer(u4* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength() * sizeof(u4));
+}
+
+u4* u4Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+// 4 bytes add
+u4Array& u4Array::operator +(u4 val)
+{
+    u4Array* newArray = new u4Array(this->GetLength() + 1);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u4));
+	newArray->buffer[this->GetLength()] = val;
+    return *newArray;
+}
+
+u4Array& u4Array::operator +=(u4 val)
+{
+    u4* tempBuffer = new u4[this->GetLength() + 1];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u4));
+	tempBuffer[this->GetLength()] = val;
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + 1;
+    return *this;
+}
+
+// UInt array add
+u4Array& u4Array::operator +(u4Array &iArray)
+{
+    s4 len;
+	if (IsNull() && iArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + iArray.GetLength();
+    }
+    u4Array* newArray = new u4Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u4));
+    memcpy(&newArray->buffer[this->GetLength() * sizeof(u4)], iArray.buffer, iArray.GetLength() * sizeof(u4));
+    return *newArray;
+}
+
+u4Array& u4Array::operator +=(u4Array &iArray)
+{
+    u4* tempBuffer = new u4[this->GetLength() + iArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u4));
+    memcpy(&tempBuffer[this->GetLength() * sizeof(u4)], iArray.buffer, iArray.GetLength() * sizeof(u4));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && iArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + iArray.GetLength();
+    }
+    return *this;
+}
+
+
+// *******************
+// Long Array class
+// *******************
+u8Array::u8Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u8[nelement];
+}
+
+u8Array::u8Array(const u8Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u8[len];
+    memcpy(this->buffer, rhs.buffer, len * sizeof(u8));
+}
+
+u8Array::~u8Array(void)
+{
+    delete[] this->buffer;
+}
+
+u1 u8Array::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+void u8Array::SetU8At(u4 pos, u8 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+u8 u8Array::ReadU8At(u4 pos)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u8Array::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u8Array::SetBuffer(u8* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength() * sizeof(u8));
+}
+
+u8* u8Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+u8Array& u8Array::operator +(u8 val)
+{
+    u8Array* newArray = new u8Array(this->GetLength() + 1);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u8));
+	newArray->buffer[this->GetLength()] = val;
+    return *newArray;
+}
+
+u8Array& u8Array::operator +=(u8 val)
+{
+    u8* tempBuffer = new u8[this->GetLength() + 1];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u8));
+	tempBuffer[this->GetLength()] = val;
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + 1;
+    return *this;
+}
+
+u8Array& u8Array::operator +(u8Array &iArray)
+{
+    s4 len;
+	if (IsNull() && iArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + iArray.GetLength();
+    }
+    u8Array* newArray = new u8Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u8));
+    memcpy(&newArray->buffer[this->GetLength() * sizeof(u8)], iArray.buffer, iArray.GetLength() * sizeof(u8));
+    return *newArray;
+}
+
+u8Array& u8Array::operator +=(u8Array &iArray)
+{
+    u8* tempBuffer = new u8[this->GetLength() + iArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u8));
+    memcpy(&tempBuffer[this->GetLength() * sizeof(u8)], iArray.buffer, iArray.GetLength() * sizeof(u8));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && iArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + iArray.GetLength();
+    }
+    return *this;
+}
+
+MARSHALLER_NS_END
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/Array.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Array.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Array.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,180 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_array_h
+#define _include_marshaller_array_h
+
+MARSHALLER_NS_BEGIN
+
+class SMARTCARDMARSHALLER_DLLAPI StringArray
+{
+
+private:
+	std::string** buffer;
+    s4 _length;
+
+public:
+    StringArray(s4 nelement);
+    StringArray(const StringArray &rhs);
+    ~StringArray(void);
+
+    u1 IsNull(void);
+    u4 GetLength(void);
+
+	std::string* GetStringAt(u4 index);
+	void  SetStringAt(u4 index,M_SAL_IN std::string* str);
+};
+
+#define s8Array u8Array
+class SMARTCARDMARSHALLER_DLLAPI u8Array
+{
+
+private:
+    u8* buffer;
+    s4 _length;
+
+public:
+    u8Array(s4 nelement);
+    u8Array(const u8Array &rhs);
+    ~u8Array(void);
+
+    u1 IsNull(void);
+    u4 GetLength(void);
+
+    void  SetBuffer(u8* buffer);
+    u8*   GetBuffer(void);
+
+	u8 ReadU8At(u4 pos);
+    void SetU8At(u4 pos, u8 val);
+
+    u8Array& operator +(u8 val);
+    u8Array& operator +=(u8 val);
+    u8Array& operator +(u8Array &cArray);
+    u8Array& operator +=(u8Array &cArray);
+
+};
+
+#define s4Array u4Array
+class SMARTCARDMARSHALLER_DLLAPI u4Array
+{
+
+private:
+    u4* buffer;
+    s4 _length;
+
+public:
+    u4Array(s4 nelement);
+    u4Array(const u4Array &rhs);
+    ~u4Array(void);
+
+    u1 IsNull(void);
+    u4 GetLength(void);
+
+    void  SetBuffer(u4* buffer);
+    u4*   GetBuffer(void);
+
+	u4 ReadU4At(u4 pos);
+    void SetU4At(u4 pos, u4 val);
+
+    u4Array& operator +(u4 val);
+    u4Array& operator +=(u4 val);
+    u4Array& operator +(u4Array &cArray);
+    u4Array& operator +=(u4Array &cArray);
+};
+
+#define s2Array u2Array
+#define charArray u2Array
+class SMARTCARDMARSHALLER_DLLAPI u2Array
+{
+
+private:
+    u2* buffer;
+    s4 _length;
+
+public:
+    u2Array(s4 nelement);
+    u2Array(const u2Array &rhs);
+    ~u2Array(void);
+
+    u1    IsNull(void);
+    u4    GetLength(void);
+
+    void  SetBuffer(u2* buffer);
+    u2*   GetBuffer(void);
+
+	u2    ReadU2At(u4 pos);
+    void  SetU2At(u4 pos, u2 val);
+
+    u2Array& operator +(u2 val);
+    u2Array& operator +=(u2 val);
+    u2Array& operator +(u2Array &cArray);
+    u2Array& operator +=(u2Array &cArray);
+};
+
+#define s1Array u1Array
+#define MemoryStream u1Array
+class SMARTCARDMARSHALLER_DLLAPI u1Array
+{
+
+private:
+    u1* buffer;
+    s4 _length;
+
+public:
+    u1Array();
+    u1Array(s4 nelement);
+    u1Array(const u1Array &rhs);
+	u1Array(u1Array &array, u4 offset, u4 len);
+    ~u1Array(void);
+
+    u1  IsNull(void) const;
+    u4  GetLength(void) const;
+
+    void  SetBuffer(const u1* buffer);
+    const u1*  GetBuffer(void) const;
+    u1*  GetBuffer(void);
+
+    u1   ReadU1At(u4 pos) const;
+	void SetU1At(u4 pos, u1 val);
+
+	u1Array& Append(std::string* str);
+
+    u1Array& operator +(u1 val);
+    u1Array& operator +=(u1 val);
+    u1Array& operator +(u2 val);
+    u1Array& operator +=(u2 val);
+    u1Array& operator +(u4 val);
+    u1Array& operator +=(u4 val);
+	u1Array& operator +(u8 val);
+    u1Array& operator +=(u8 val);
+    u1Array& operator =(const u1Array &bArray);
+    u1Array& operator +(u1Array &bArray);
+    u1Array& operator +=(u1Array &bArray);
+};
+
+extern u2 ComputeUTF8Length(M_SAL_IN lpCharPtr str);
+extern void UTF8Encode(M_SAL_IN lpCharPtr str, u1Array &utf8Data);
+extern u2 ComputeLPSTRLength(u1Array &array, u4 offset, u4 len);
+extern void UTF8Decode(u1Array &array, u4 offset, u4 len, M_SAL_INOUT lpCharPtr &charData);
+
+MARSHALLER_NS_END
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/Except.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Except.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Except.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,338 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_except_h
+#define _include_marshaller_except_h
+
+MARSHALLER_NS_BEGIN
+
+// .NET specific exception classes
+class Exception  : public std::runtime_error{
+
+public:
+	explicit Exception(std::string msg): std::runtime_error(msg) { }
+	const char *what() const throw(){
+		return std::runtime_error::what();
+	}
+};
+
+class SystemException : public Exception{
+
+public:
+	explicit SystemException(std::string msg) : Exception(msg) { }
+	explicit SystemException(char *msg) : Exception(NULL != msg ? msg : "") { }
+};
+
+class ArgumentException : public Exception{
+
+public:
+	explicit ArgumentException(std::string msg) : Exception(msg) { }
+	explicit ArgumentException();
+	explicit ArgumentException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArgumentNullException : public Exception{
+
+public:
+	explicit ArgumentNullException(std::string msg) : Exception(msg) { }
+	explicit ArgumentNullException();
+	explicit ArgumentNullException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArgumentOutOfRangeException : public Exception{
+
+public:
+	explicit ArgumentOutOfRangeException(std::string msg) : Exception(msg) { }
+	explicit ArgumentOutOfRangeException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class IndexOutOfRangeException : public Exception{
+
+public:
+	explicit IndexOutOfRangeException(std::string  msg) : Exception(msg) { }
+	explicit IndexOutOfRangeException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class InvalidCastException : public Exception{
+
+public:
+	explicit InvalidCastException(std::string  msg) : Exception(msg) { }
+	explicit InvalidCastException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class InvalidOperationException : public Exception{
+
+public:
+	explicit InvalidOperationException(std::string msg) : Exception(msg) { }
+	explicit InvalidOperationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NotImplementedException : public Exception{
+
+public:
+	explicit NotImplementedException(std::string msg) : Exception(msg) { }
+	explicit NotImplementedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NotSupportedException : public Exception{
+
+public:
+	explicit NotSupportedException(std::string msg) : Exception(msg) { }
+	explicit NotSupportedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NullReferenceException : public Exception{
+
+public:
+	explicit NullReferenceException(std::string msg) : Exception(msg) { }
+	explicit NullReferenceException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class OutOfMemoryException : public Exception{
+
+public:
+	explicit OutOfMemoryException(std::string msg) : Exception(msg) { }
+	explicit OutOfMemoryException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class UnauthorizedAccessException : public Exception{
+
+public:
+	explicit UnauthorizedAccessException(std::string msg) : Exception(msg) { }
+	explicit UnauthorizedAccessException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ObjectDisposedException : public Exception{
+
+public:
+	explicit ObjectDisposedException(std::string msg) : Exception(msg) { }
+	explicit ObjectDisposedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ApplicationException : public Exception{
+
+public:
+	explicit ApplicationException(std::string msg) : Exception(msg) { }
+	explicit ApplicationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArithmeticException : public Exception{
+
+public:
+	explicit ArithmeticException(std::string msg) : Exception(msg) { }
+	explicit ArithmeticException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArrayTypeMismatchException : public Exception{
+
+public:
+	explicit ArrayTypeMismatchException(std::string msg) : Exception(msg) { }
+	explicit ArrayTypeMismatchException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class BadImageFormatException : public Exception{
+
+public:
+	explicit BadImageFormatException(std::string msg) : Exception(msg) { }
+	explicit BadImageFormatException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class CryptographicException : public Exception{
+
+public:
+	explicit CryptographicException(std::string msg) : Exception(msg) { }
+	explicit CryptographicException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class DirectoryNotFoundException : public Exception{
+
+public:
+	explicit DirectoryNotFoundException(std::string msg) : Exception(msg) { }
+	explicit DirectoryNotFoundException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class DivideByZeroException : public Exception{
+
+public:
+	explicit DivideByZeroException(std::string msg) : Exception(msg) { }
+	explicit DivideByZeroException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class FileNotFoundException : public Exception{
+
+public:
+	explicit FileNotFoundException(std::string msg) : Exception(msg) { }
+	explicit FileNotFoundException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class FormatException : public Exception{
+
+public:
+	explicit FormatException(std::string msg) : Exception(msg) { }
+	explicit FormatException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class IOException : public Exception{
+
+public:
+	explicit IOException(std::string msg) : Exception(msg) { }
+	explicit IOException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class RankException : public Exception{
+
+public:
+	explicit RankException(std::string msg) : Exception(msg) { }
+	explicit RankException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class RemotingException : public Exception{
+
+private:
+	s4 resultCode;	// this code is for PCSC releated error/success codes
+
+public:
+	explicit RemotingException(std::string msg) : Exception(msg) {
+		this->resultCode = 0;
+	}
+	explicit RemotingException(char *msg) : Exception(NULL != msg ? msg : "") {
+		this->resultCode = 0;
+	}
+	explicit RemotingException(std::string msg,s4 resultCode) : Exception(msg){
+		this->resultCode = resultCode;
+	}
+	explicit RemotingException(char *msg,s4 resultCode) : Exception(NULL != msg ? msg : ""){
+		this->resultCode = resultCode;
+	}
+	explicit RemotingException(s4 resultCode) : Exception(""){
+		this->resultCode = resultCode;
+	}
+	s4 getResultCode(){
+		return this->resultCode;
+	}
+};
+
+class StackOverflowException : public Exception{
+
+public:
+	explicit StackOverflowException(std::string msg) : Exception(msg) { }
+	explicit StackOverflowException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class TypeLoadException : public Exception{
+
+public:
+	explicit TypeLoadException(std::string msg) : Exception(msg) { }
+	explicit TypeLoadException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MemberAccessException : public Exception{
+
+public:
+	explicit MemberAccessException(std::string msg) : Exception(msg) { }
+	explicit MemberAccessException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingFieldException : public Exception{
+
+public:
+	explicit MissingFieldException(std::string msg) : Exception(msg) { }
+	explicit MissingFieldException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingMemberException : public Exception{
+
+public:
+	explicit MissingMemberException(std::string msg) : Exception(msg) { }
+	explicit MissingMemberException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingMethodException : public Exception{
+
+public:
+	explicit MissingMethodException(std::string msg) : Exception(msg) { }
+	explicit MissingMethodException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class OverflowException : public Exception{
+
+public:
+	explicit OverflowException(std::string msg) : Exception(msg) { }
+	explicit OverflowException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class SecurityException : public Exception{
+
+public:
+	explicit SecurityException(std::string msg) : Exception(msg) { }
+	explicit SecurityException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class VerificationException : public Exception{
+
+public:
+	explicit VerificationException(std::string msg) : Exception(msg) { }
+	explicit VerificationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class SerializationException : public Exception{
+
+public:
+	explicit SerializationException(std::string msg) : Exception(msg) { }
+	explicit SerializationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+

Deleted: trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am	2011-03-21 14:21:33 UTC (rev 139)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am	2012-02-20 13:52:47 UTC (rev 140)
@@ -1,3 +0,0 @@
-SUBDIRS = PKCS11Module2
-
-EXTRA_DIST = autogen.sh c-mac.sh LGPL-2.1

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,136 @@
+lib_LTLIBRARIES = libgtop11dotnet.la
+
+libgtop11dotnet_la_LDFLAGS = -shared
+
+libgtop11dotnet_la_SOURCES = \
+	$(top_srcdir)/cppMarshaller/Array.cpp \
+	$(top_srcdir)/cppMarshaller/Array.h \
+	$(top_srcdir)/cppMarshaller/Except.h \
+	$(top_srcdir)/cppMarshaller/MarshallerCfg.h \
+	$(top_srcdir)/cppMarshaller/Marshaller.cpp \
+	$(top_srcdir)/cppMarshaller/Marshaller.h \
+	$(top_srcdir)/cppMarshaller/PCSC.cpp \
+	$(top_srcdir)/cppMarshaller/PCSC.h \
+	algo_des.cpp \
+	algo_des.h \
+	algo_md5.cpp \
+	algo_md5.h \
+	algo_sha1.cpp \
+	algo_sha1.h \
+	algo_sha256.cpp \
+	algo_sha256.h \
+	algo_utils.cpp \
+	algo_utils.h \
+	application.cpp \
+	application.h \
+	attrcert.cpp \
+	attrcert.h \
+	beroctet.cpp \
+	beroctet.h \
+	cardcache.cpp \
+	cardcache.h \
+	cardmoduleservice.cpp \
+	cardmoduleservice.h \
+	certificateobject.cpp \
+	certificateobject.h \
+	cert_utils.cpp \
+	cert_utils.h \
+	config.h \
+	critsect.cpp \
+	critsect.h \
+	dataobject.cpp \
+	dataobject.h \
+	des.cpp \
+	des.h \
+	digest.cpp \
+	digest.h \
+	error.cpp \
+	error.h \
+	event.cpp \
+	event.h \
+	keyobject.cpp \
+	keyobject.h \
+	md5.cpp \
+	md5.h \
+	mutex.cpp \
+	mutex.h \
+	pkcs11.cpp \
+	pkcs11f.h \
+	pkcs11.h \
+	pkcs11t.h \
+	platconfig.h \
+	privatekeyobject.cpp \
+	privatekeyobject.h \
+	publickeyobject.cpp \
+	publickeyobject.h \
+	resource.h \
+	rsa/cr_digit.cpp \
+	rsa/cr_digit.h \
+	rsa/cr_global.h \
+	rsa/cr_nn.cpp \
+	rsa/cr_nn.h \
+	rsa/cr_random.cpp \
+	rsa/cr_random.h \
+	rsa/cr_rsa.cpp \
+	rsa/cr_rsa.h \
+	rsa/ha_config.h \
+	rsaprivatekeyobject.cpp \
+	rsaprivatekeyobject.h \
+	rsapublickeyobject.cpp \
+	rsapublickeyobject.h \
+	sctoken.cpp \
+	sctoken.h \
+	secretkeyobject.cpp \
+	secretkeyobject.h \
+	session.cpp \
+	session.h \
+	sha1.cpp \
+	sha1.h \
+	sha256.cpp \
+	sha256.h \
+	slot.cpp \
+	slot.h \
+	stdafx.cpp \
+	stdafx.h \
+	storageobject.cpp \
+	storageobject.h \
+	symmalgo.cpp \
+	symmalgo.h \
+	tdes.cpp \
+	tdes.h \
+	template.cpp \
+	template.h \
+	thread.cpp \
+	thread.h \
+	timer.cpp \
+	timer.h \
+	transaction.cpp \
+	transaction.h \
+	util.cpp \
+	util.h \
+	x509cert.cpp \
+	x509cert.h \
+	x509pubkeycertobject.cpp \
+	x509pubkeycertobject.h \
+	log.h \
+	log.cpp
+
+AM_CPPFLAGS = -DINCLUDE_EVENTING=1 -DCRYPTOKI_EXPORTS=1 \
+	-DUNIX $(PTHREAD_CFLAGS) \
+	-Wall \
+	-Wextra \
+	-pedantic
+
+INCLUDES = \
+	-I$(top_srcdir)/cppMarshaller \
+	-I$(top_srcdir)/PKCS11Module2 \
+	-I$(top_srcdir)/PKCS11Module2/rsa \
+	$(PCSC_CFLAGS)
+
+LIBS = $(PCSC_LIBS) $(PTHREAD_LIBS) -lz
+
+# see http://wiki.cacert.org/wiki/Pkcs11TaskForce
+install-exec-hook:
+	$(MKDIR_P) $(DESTDIR)/$(prefix)/lib/pkcs11
+	cd $(DESTDIR)/$(prefix)/lib/pkcs11 ; rm -f libgtop11dotnet. at DYN_LIB_EXT@ ; $(LN_S) ../libgtop11dotnet. at DYN_LIB_EXT@
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,1782 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable:4201)
+#else
+#define DBG_UNREFERENCED_LOCAL_VARIABLE(a)
+#endif
+
+#ifdef INCLUDE_VLD
+#include <vld.h>
+#endif
+
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+
+#ifndef WIN32
+#include <strings.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdexcept>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#ifndef _XCL_
+#include "PCSC.h"
+#else // _XCL_
+#include "xcl_broker.h"
+#endif // _XCL_
+#include "Marshaller.h"
+#include "Except.h"
+
+#include "log.h"
+
+MARSHALLER_NS_BEGIN
+
+#define SUPPORT_BETA_VERSION
+
+#define APDU_TO_CARD_MAX_SIZE                                   0xFF
+
+#define HIVECODE_NAMESPACE_SYSTEM                               0x00D25D1C
+#define HIVECODE_NAMESPACE_SYSTEM_IO                            0x00D5E6DB
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CHANNELS     0x0000886E
+#define HIVECODE_NAMESPACE_NETCARD_FILESYSTEM                   0x00A1AC39
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING              0x00EB3DD9
+#define HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY         0x00ACF53B
+#define HIVECODE_NAMESPACE_SYSTEM_COLLECTIONS                   0x00C5A010
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CONTEXTS     0x001F4994
+#define HIVECODE_NAMESPACE_SYSTEM_SECURITY                      0x00964145
+#define HIVECODE_NAMESPACE_SYSTEM_REFLECTION                    0x0008750F
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION         0x008D3B3D
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_MESSAGING    0x00DEB940
+#define HIVECODE_NAMESPACE_SYSTEM_DIAGNOSTICS                   0x0097995F
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_COMPILERSERVICES      0x00F63E11
+#define HIVECODE_NAMESPACE_SYSTEM_TEXT                          0x00702756
+
+#define HIVECODE_TYPE_SYSTEM_VOID           0xCE81
+#define HIVECODE_TYPE_SYSTEM_INT32          0x61C0
+#define HIVECODE_TYPE_SYSTEM_INT32_ARRAY    0x61C1
+#define HIVECODE_TYPE_SYSTEM_BOOLEAN        0x2227
+#define HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY  0x2228
+#define HIVECODE_TYPE_SYSTEM_SBYTE          0x767E
+#define HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY    0x767F
+#define HIVECODE_TYPE_SYSTEM_UINT16         0xD98B
+#define HIVECODE_TYPE_SYSTEM_UINT16_ARRAY   0xD98C
+#define HIVECODE_TYPE_SYSTEM_UINT32         0x95E7
+#define HIVECODE_TYPE_SYSTEM_UINT32_ARRAY   0x95E8
+#define HIVECODE_TYPE_SYSTEM_BYTE           0x45A2
+#define HIVECODE_TYPE_SYSTEM_BYTE_ARRAY     0x45A3
+#define HIVECODE_TYPE_SYSTEM_CHAR           0x958E
+#define HIVECODE_TYPE_SYSTEM_CHAR_ARRAY     0x958F
+#define HIVECODE_TYPE_SYSTEM_INT16          0xBC39
+#define HIVECODE_TYPE_SYSTEM_INT16_ARRAY    0xBC3A
+#define HIVECODE_TYPE_SYSTEM_STRING         0x1127
+#define HIVECODE_TYPE_SYSTEM_STRING_ARRAY   0x1128
+#define HIVECODE_TYPE_SYSTEM_INT64			0xDEFB
+#define HIVECODE_TYPE_SYSTEM_INT64_ARRAY	0xDEFC
+#define HIVECODE_TYPE_SYSTEM_UINT64			0x71AF
+#define HIVECODE_TYPE_SYSTEM_UINT64_ARRAY	0x71B0
+
+#define HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM 0xFED7
+
+// for port discovery lookup.
+#define CARDMANAGER_SERVICE_PORT                                                    1
+#define CARDMANAGER_SERVICE_NAME                                                    "ContentManager"
+#define HIVECODE_NAMESPACE_SMARTCARD                                                0x00F5EFBF
+#define HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER                                      0xB18C
+#define HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT                  0x7616
+
+#define HIVECODE_TYPE_SYSTEM_EXCEPTION                                      0xD4B0
+#define HIVECODE_TYPE_SYSTEM_SYSTEMEXCEPTION                                0x28AC
+#define HIVECODE_TYPE_SYSTEM_OUTOFMEMORYEXCEPTION                           0xE14E
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTEXCEPTION                              0xAB8C
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTNULLEXCEPTION                          0x2138
+#define HIVECODE_TYPE_SYSTEM_NULLREFERENCEEXCEPTION                         0xC5B8
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION                    0x6B11
+#define HIVECODE_TYPE_SYSTEM_NOTSUPPORTEDEXCEPTION                          0xAA74
+#define HIVECODE_TYPE_SYSTEM_INVALIDCASTEXCEPTION                           0xD24F
+#define HIVECODE_TYPE_SYSTEM_INVALIDOPERATIONEXCEPTION                      0xFAB4
+#define HIVECODE_TYPE_SYSTEM_NOTIMPLEMENTEDEXCEPTION                        0x3CE5
+#define HIVECODE_TYPE_SYSTEM_OBJECTDISPOSEDEXCEPTION                        0x0FAC
+#define HIVECODE_TYPE_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION                    0x4697
+#define HIVECODE_TYPE_SYSTEM_INDEXOUTOFRANGEEXCEPTION                       0xBF1D
+#define HIVECODE_TYPE_SYSTEM_FORMATEXCEPTION                                0xF3BF
+#define HIVECODE_TYPE_SYSTEM_ARITHMETICEXCEPTION                            0x6683
+#define HIVECODE_TYPE_SYSTEM_OVERFLOWEXCEPTION                              0x20A0
+#define HIVECODE_TYPE_SYSTEM_BADIMAGEFORMATEXCEPTION                        0x530A
+#define HIVECODE_TYPE_SYSTEM_APPLICATIONEXCEPTION                           0xB1EA
+#define HIVECODE_TYPE_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION                     0x3F88
+#define HIVECODE_TYPE_SYSTEM_DIVIDEBYZEROEXCEPTION                          0xDFCF
+#define HIVECODE_TYPE_SYSTEM_MEMBERACCESSEXCEPTION                          0xF5F3
+#define HIVECODE_TYPE_SYSTEM_MISSINGMEMBEREXCEPTION                         0x20BB
+#define HIVECODE_TYPE_SYSTEM_MISSINGFIELDEXCEPTION                          0x7366
+#define HIVECODE_TYPE_SYSTEM_MISSINGMETHODEXCEPTION                         0x905B
+#define HIVECODE_TYPE_SYSTEM_RANKEXCEPTION                                  0xB2AE
+#define HIVECODE_TYPE_SYSTEM_STACKOVERFLOWEXCEPTION                         0x0844
+#define HIVECODE_TYPE_SYSTEM_TYPELOADEXCEPTION                              0x048E
+#define HIVECODE_TYPE_SYSTEM_IO_IOEXCEPTION                                 0x3BBE
+#define HIVECODE_TYPE_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION                  0x975A
+#define HIVECODE_TYPE_SYSTEM_IO_FILENOTFOUNDEXCEPTION                       0x07EB
+#define HIVECODE_TYPE_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION             0xD52A
+#define HIVECODE_TYPE_SYSTEM_RUNTIME_SERIALIZATION_SERIALIZATIONEXCEPTION   0xA1D2
+#define HIVECODE_TYPE_SYSTEM_SECURITY_SECURITYEXCEPTION						0x31AF
+#define HIVECODE_TYPE_SYSTEM_SECURITY_VERIFICATIONEXCEPTION					0x67F1
+#define HIVECODE_TYPE_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION   0x8FEB
+
+#ifdef SMARTCARDMARSHALLER_EXPORTS
+
+BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
+{
+   UNREFERENCED_PARAMETER(hModule);
+   UNREFERENCED_PARAMETER(lpReserved);
+
+   switch (ul_reason_for_call)
+   {
+   case DLL_PROCESS_ATTACH:
+   case DLL_THREAD_ATTACH:
+   case DLL_THREAD_DETACH:
+   case DLL_PROCESS_DETACH:
+      break;
+   }
+   return TRUE;
+}
+
+#endif
+
+static u2 ComReadU2At(u1Array &array, u4 pos)
+{
+   if ((u8)(pos + sizeof(u2)) > (u8)array.GetLength()) {
+      throw ArgumentOutOfRangeException((lpCharPtr)"");
+   }
+   u1* buff = array.GetBuffer();
+   return (u2)((((u2)buff[pos]) << 8) + buff[pos + 1]);
+}
+
+u4 ComReadU4At(u1Array &array, u4 pos);
+u4 ComReadU4At(u1Array &array, u4 pos)
+{
+   if ((u8)(pos + sizeof(u4)) > (u8)array.GetLength()) {
+      throw ArgumentOutOfRangeException((lpCharPtr)"");
+   }
+   u1* buff = array.GetBuffer();
+   return (u4)((((u4)buff[pos]) << 24) + (((u4)buff[pos + 1]) << 16) + (((u4)buff[pos + 2]) << 8) + buff[pos + 3]);
+}
+
+static u8 ComReadU8At(u1Array &array, u4 pos)
+{
+   if ((u8)(pos + sizeof(u8)) > (u8)array.GetLength()) {
+      throw ArgumentOutOfRangeException((lpCharPtr)"");
+   }
+   u1* buff = array.GetBuffer();
+
+   u1 b1 = buff[pos];
+   u1 b2 = buff[pos + 1];
+   u1 b3 = buff[pos + 2];
+   u1 b4 = buff[pos + 3];
+   u1 b5 = buff[pos + 4];
+   u1 b6 = buff[pos + 5];
+   u1 b7 = buff[pos + 6];
+   u1 b8 = buff[pos + 7];
+
+   return (((u8)b1 << 56) | ((u8)b2 << 48) | ((u8)b3 << 40) | ((u8)b4 << 32) | ((u8)b5 << 24) | ((u8)b6 << 16) | ((u8)b7 << 8) | b8);
+}
+
+static void ProcessException(u1Array answer, u4 protocolOffset)
+{
+   u4 exceptionNamespace;
+   u4 exceptionName;
+   char* chst = NULL;
+
+   try {
+      exceptionNamespace = ComReadU4At(answer, protocolOffset + 0);
+      exceptionName      = ComReadU2At(answer, protocolOffset + 4);
+
+      if (answer.GetLength() > (protocolOffset + 6)) {
+         u2 strLen = ComReadU2At(answer, protocolOffset + 6);
+         if ((strLen > 0) && (strLen != 0xFFFF)) {
+            u2 len = ComputeLPSTRLength(answer, protocolOffset + 8, strLen);
+            chst = new char[len + 1];
+            chst[len] = '\0';
+            UTF8Decode(answer, protocolOffset + 8, strLen, chst);
+         }
+      }
+   } catch (...) {
+      // someone is messing with the protocol
+      if (chst != NULL) {
+         delete[] chst;
+      }
+      throw RemotingException((lpCharPtr)"");
+   }
+
+   if (chst == NULL) {
+      // prepare empty string
+      chst = new char[1];
+      chst[0] = '\0';
+   }
+
+   // create a string object on the stack.
+   // when exception is thrown the exception object is copied on
+   // a temporary location and live till used by catch block
+   //
+   // it is not a good idea to pass chst as a parameter of exception object
+   // as there will be no way to delete it.
+   std::string chstr(chst);
+
+   delete[] chst;
+
+   switch (exceptionNamespace)
+   {
+   case HIVECODE_NAMESPACE_SYSTEM:
+      {
+         switch(exceptionName){
+
+   case (u2)HIVECODE_TYPE_SYSTEM_EXCEPTION:
+      throw Exception(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_SYSTEMEXCEPTION:
+      throw SystemException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_OUTOFMEMORYEXCEPTION:
+      throw OutOfMemoryException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTEXCEPTION:
+      throw ArgumentException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTNULLEXCEPTION:
+      throw ArgumentNullException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_NULLREFERENCEEXCEPTION:
+      throw NullReferenceException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION:
+      throw ArgumentOutOfRangeException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_NOTSUPPORTEDEXCEPTION:
+      throw NotSupportedException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_INVALIDCASTEXCEPTION:
+      throw InvalidCastException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_INVALIDOPERATIONEXCEPTION:
+      throw InvalidOperationException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_NOTIMPLEMENTEDEXCEPTION:
+      throw NotImplementedException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_OBJECTDISPOSEDEXCEPTION:
+      throw ObjectDisposedException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION:
+      throw UnauthorizedAccessException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_INDEXOUTOFRANGEEXCEPTION:
+      throw IndexOutOfRangeException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_FORMATEXCEPTION:
+      throw FormatException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARITHMETICEXCEPTION:
+      throw ArithmeticException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_OVERFLOWEXCEPTION:
+      throw OverflowException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_BADIMAGEFORMATEXCEPTION:
+      throw BadImageFormatException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_APPLICATIONEXCEPTION:
+      throw ApplicationException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION:
+      throw ArrayTypeMismatchException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_DIVIDEBYZEROEXCEPTION:
+      throw DivideByZeroException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MEMBERACCESSEXCEPTION:
+      throw MemberAccessException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MISSINGMEMBEREXCEPTION:
+      throw MissingMemberException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MISSINGFIELDEXCEPTION:
+      throw MissingFieldException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MISSINGMETHODEXCEPTION:
+      throw MissingMethodException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_RANKEXCEPTION:
+      throw RankException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_STACKOVERFLOWEXCEPTION:
+      throw StackOverflowException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_TYPELOADEXCEPTION:
+      throw TypeLoadException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_IO:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_IO_IOEXCEPTION:
+      throw IOException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION:
+      throw DirectoryNotFoundException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_IO_FILENOTFOUNDEXCEPTION:
+      throw FileNotFoundException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_SECURITY:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_SECURITYEXCEPTION:
+      throw SecurityException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_VERIFICATIONEXCEPTION:
+      throw VerificationException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION:
+      throw RemotingException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_RUNTIME_SERIALIZATION_SERIALIZATIONEXCEPTION:
+      throw SerializationException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION:
+      throw CryptographicException(chstr);
+         }
+      }
+      break;
+   }
+
+   // custom exception from the card application or someone is messing with the protocol
+   // no means of translation.
+   throw Exception(chstr);
+}
+
+u4 CheckForException(u1Array answer, u4 nameSpace, u2 type);
+u4 CheckForException(u1Array answer, u4 nameSpace, u2 type)
+{
+   u1 protocolAnswerPrefix = answer.ReadU1At(0);
+
+#ifdef SUPPORT_BETA_VERSION
+   if (protocolAnswerPrefix == 0) {
+      // beta version protocol (namespace & type systematically returned)
+      if ((ComReadU4At(answer, 0) != nameSpace) || (ComReadU2At(answer, 4) != type)) {
+         ProcessException(answer, 0);
+      }
+      // skip namespace & type
+      return (4 + 2);
+   }
+#endif
+
+   // new protocol
+   if (protocolAnswerPrefix != 0x01) {
+      if (protocolAnswerPrefix == 0xFF) {
+         // exception info expected in the buffer
+         ProcessException(answer, 1);
+      } else {
+         // someone is messing with the protocol
+         throw RemotingException((lpCharPtr)"");
+      }
+   }
+
+   // skip return type info (protocolAnswerPrefix: 0x01 = ok, 0xFF = exception)
+   return 1;
+}
+
+SmartCardMarshaller::SmartCardMarshaller(SCARDHANDLE cardHandle, u2 portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode)
+{
+   this->uri = NULL;
+   this->pcsc = NULL;
+   this->portNumber = portNumber;
+   this->nameSpaceHivecode = nameSpaceHivecode;
+   this->typeHivecode = typeHivecode;
+   this->ProcessInputStream  = NULL;
+   this->ProcessOutputStream = NULL;
+
+#ifndef _XCL_
+   this->pcsc = new PCSC(cardHandle);
+#else // _XCL_
+    this->pcsc = new XCLBroker(cardHandle);
+#endif // _XCL_
+
+   try {
+      this->uri = new std::string(uri->c_str());
+   } catch (...) {
+      delete this->pcsc;
+      throw;
+   }
+}
+
+SmartCardMarshaller::SmartCardMarshaller(M_SAL_IN std::string* readerName, u2 portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index)
+{
+   //Log::begin( "SmartCardMarshaller::SmartCardMarshaller" );
+
+   this->uri = NULL;
+   this->pcsc = NULL;
+   this->portNumber = portNumber;
+   this->nameSpaceHivecode = nameSpaceHivecode;
+   this->typeHivecode = typeHivecode;
+   this->ProcessInputStream  = NULL;
+   this->ProcessOutputStream = NULL;
+
+#ifdef WIN32
+   if ((readerName == NULL) || (_stricmp("selfdiscover", readerName->c_str()) == 0))
+   {
+#else
+   if ((readerName == NULL) || (strncasecmp("selfdiscover", readerName->c_str(),readerName->length()) == 0))
+   {
+#endif
+      //Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index) ..." );
+#ifndef _XCL_
+      this->pcsc = new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index);
+#else // _XCL
+        this->pcsc = new XCLBroker(readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index);
+#endif // _XCL_
+      //Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index) ok" );
+   }
+   else
+   {
+      //Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName ) ..." );
+#ifndef _XCL_
+      this->pcsc = new PCSC( readerName );
+#else // _XCL_
+        this->pcsc = new XCLBroker(readerName);
+#endif // _XCL_
+      //Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName ) ok" );
+   }
+
+   try
+   {
+      //Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new std::string(uri->c_str()) ..." );
+      this->uri = new std::string(uri->c_str());
+      //Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new std::string(uri->c_str()) ok" );
+   }
+   catch (...)
+   {
+      //Log::error( "SmartCardMarshaller::SmartCardMarshaller", "(...)" );
+      delete this->pcsc;
+      throw;
+   }
+
+   //Log::end( "SmartCardMarshaller::SmartCardMarshaller" );
+}
+
+std::string* SmartCardMarshaller::GetReaderName(void)
+{
+   return this->pcsc->GetReaderName();
+}
+
+SCARDHANDLE SmartCardMarshaller::GetCardHandle(void)
+{
+   return this->pcsc->GetCardHandle();
+}
+
+void SmartCardMarshaller::DoTransact(bool flag)
+{
+   this->pcsc->DoTransact(flag);
+}
+
+SmartCardMarshaller::~SmartCardMarshaller(void)
+{
+   if (this->uri != NULL) {
+      delete this->uri;
+      this->uri = NULL;
+   }
+
+   if (this->pcsc != NULL) {
+      delete this->pcsc;
+      this->pcsc = NULL;
+   }
+}
+
+void SmartCardMarshaller::UpdatePCSCCardHandle(SCARDHANDLE hCard)
+{
+   this->pcsc->SetCardHandle(hCard);
+}
+
+static void ProcessByReferenceArguments(u1 type, u1Array* dataArray, u4* offsetPtr, va_list* markerPtr, u1 isIn)
+{
+   //va_list marker = *markerPtr;
+   u4 offset = *offsetPtr;
+
+   switch (type) {
+
+        case MARSHALLER_TYPE_REF_BOOL:
+        case MARSHALLER_TYPE_REF_U1:
+        case MARSHALLER_TYPE_REF_S1:
+           {
+              u1* val = va_arg(/*marker*/*markerPtr, u1*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = (*dataArray).ReadU1At(offset);
+              }
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_CHAR:
+        case MARSHALLER_TYPE_REF_U2:
+        case MARSHALLER_TYPE_REF_S2:
+           {
+              u2* val = va_arg(/*marker*/*markerPtr, u2*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = ComReadU2At(*dataArray, offset);
+              }
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_U4:
+        case MARSHALLER_TYPE_REF_S4:
+           {
+              u4* val = va_arg(/*marker*/*markerPtr, u4*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = ComReadU4At(*dataArray, offset);
+              }
+              offset += sizeof(u4);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_U8:
+        case MARSHALLER_TYPE_REF_S8:
+           {
+              u8* val = va_arg(/*marker*/*markerPtr, u8*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = ComReadU8At(*dataArray, offset);
+              }
+              offset += sizeof(u8);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_STRING:
+           {
+              std::string** val = va_arg(/*marker*/*markerPtr, std::string**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 offset += sizeof(u2);
+                 if (*val != NULL) {
+                    offset += ComputeUTF8Length((lpCharPtr)((*val)->c_str()));
+                 }
+                 (*dataArray).Append(*val);
+              } else {
+                 u2 len = ComReadU2At(*dataArray, offset);
+                 offset += sizeof(u2);
+                 if (len == 0xFFFF) {
+                    *val = NULL;
+                 } else {
+                    // store result
+                    u2 l = ComputeLPSTRLength(*dataArray, offset, len);
+                    char* chstr = new char[l + 1];
+                    try {
+                       chstr[l] = '\0';
+                       UTF8Decode(*dataArray, offset, len, chstr);
+                       *val = new std::string(chstr);
+                    } catch (...) {
+                       delete[] chstr;
+                       throw;
+                    }
+                    delete[] chstr;
+                    offset += len;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S1ARRAY:
+        case MARSHALLER_TYPE_REF_BOOLARRAY:
+        case MARSHALLER_TYPE_REF_U1ARRAY:
+           {
+              u1Array** val = va_arg(/*marker*/*markerPtr, u1Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u1* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u1) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u1Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u1Array(-1);
+                    } else {
+                       refArray = new u1Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU1At(i, dataArray->ReadU1At(offset));
+                          offset += sizeof(u1);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S2ARRAY:
+        case MARSHALLER_TYPE_REF_U2ARRAY:
+           {
+              u2Array** val = va_arg(/*marker*/*markerPtr, u2Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u2* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u2) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u2Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u2Array(-1);
+                    } else {
+                       refArray = new u2Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU2At(i, ComReadU2At(*dataArray, offset));
+                          offset += sizeof(u2);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S4ARRAY:
+        case MARSHALLER_TYPE_REF_U4ARRAY:
+           {
+              u4Array** val = va_arg(/*marker*/*markerPtr, u4Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u4* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u4) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u4Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u4Array(-1);
+                    } else {
+                       refArray = new u4Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU4At(i, ComReadU4At(*dataArray, offset));
+                          offset += sizeof(u4);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S8ARRAY:
+        case MARSHALLER_TYPE_REF_U8ARRAY:
+           {
+              u8Array** val = va_arg(/*marker*/*markerPtr, u8Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u8* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u8) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u8Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u8Array(-1);
+                    } else {
+                       refArray = new u8Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU8At(i, ComReadU8At(*dataArray, offset));
+                          offset += sizeof(u4);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        default:
+           {
+              if (isIn == TRUE) {
+                 throw Exception("Un-recognized input argument type");
+              } else {
+                 throw Exception("Un-recognized byref argument type");
+              }
+           }
+           break;
+   }
+
+   //*markerPtr = marker;
+   *offsetPtr = offset;
+}
+
+
+static void ProcessOutputArguments(u1 type, u1Array* answerPtr, u4* offsetPtr, va_list* markerPtr)
+{
+   switch (type) {
+
+        case MARSHALLER_TYPE_IN_BOOL:
+        case MARSHALLER_TYPE_IN_S1:
+        case MARSHALLER_TYPE_IN_U1:
+        case MARSHALLER_TYPE_IN_CHAR:
+        case MARSHALLER_TYPE_IN_S2:
+        case MARSHALLER_TYPE_IN_U2:
+        case MARSHALLER_TYPE_IN_S4:
+        case MARSHALLER_TYPE_IN_U4:
+        case MARSHALLER_TYPE_IN_STRING:
+        case MARSHALLER_TYPE_IN_MEMORYSTREAM:
+        case MARSHALLER_TYPE_IN_BOOLARRAY:
+        case MARSHALLER_TYPE_IN_S1ARRAY:
+        case MARSHALLER_TYPE_IN_U1ARRAY:
+        case MARSHALLER_TYPE_IN_CHARARRAY:
+        case MARSHALLER_TYPE_IN_S2ARRAY:
+        case MARSHALLER_TYPE_IN_U2ARRAY:
+        case MARSHALLER_TYPE_IN_S4ARRAY:
+        case MARSHALLER_TYPE_IN_U4ARRAY:
+        case MARSHALLER_TYPE_IN_S8ARRAY:
+        case MARSHALLER_TYPE_IN_U8ARRAY:
+        case MARSHALLER_TYPE_IN_STRINGARRAY:
+           {
+              // ignore input argument (slot size = 4 bytes)
+              //va_list marker = *markerPtr;
+              /*u4 v = */va_arg(/*marker*/*markerPtr, u4);
+              //*markerPtr = marker;
+
+              /*DBG_UNREFERENCED_LOCAL_VARIABLE(v);*/
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S8:
+        case MARSHALLER_TYPE_IN_U8:
+           {
+              // ignore input argument (slot size = 8 bytes)
+              //va_list marker = *markerPtr;
+              /*u8 v = */va_arg(/*marker*/*markerPtr, u8);
+              //*markerPtr = marker;
+
+              /*DBG_UNREFERENCED_LOCAL_VARIABLE(v);*/
+           }
+           break;
+
+        default:
+           ProcessByReferenceArguments(type, answerPtr, offsetPtr, markerPtr, FALSE);
+           break;
+   }
+}
+
+static u4 ProcessReturnType(u1 type, u1Array* answerPtr, va_list* markerPtr)
+{
+   u1Array answer = *answerPtr;
+   u4 offset = 0;
+   //va_list marker = *markerPtr;
+
+   switch (type) {
+
+      // void (can happen for the method return param)
+        case MARSHALLER_TYPE_RET_VOID:
+           {
+              if (answer.GetLength() > 0) {
+#ifdef SUPPORT_BETA_VERSION
+                 if (answer.ReadU1At(0) == 0x00) {
+                    // beta version protocol
+                    ProcessException(answer, 0);
+                 }
+#endif
+                 // new protocol
+                 ProcessException(answer, 1);
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_BOOL:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BOOLEAN);
+              u1* valToReturn = va_arg(/*marker*/*markerPtr, u1*);
+              if (answer.ReadU1At(offset) == 0) {
+                 *valToReturn = FALSE;
+              } else {
+                 *valToReturn = TRUE;
+              }
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S1:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_SBYTE);
+              s1* valToReturn = va_arg(/*marker*/*markerPtr, s1*);
+              *valToReturn = answer.ReadU1At(offset);
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U1:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BYTE);
+              u1* valToReturn = va_arg(/*marker*/*markerPtr, u1*);
+              *valToReturn = answer.ReadU1At(offset);
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_CHAR:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_CHAR);
+              char* valToReturn = va_arg(/*marker*/*markerPtr, char*);
+              *valToReturn = (char)ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S2:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT16);
+              s2* valToReturn = va_arg(/*marker*/*markerPtr, s2*);
+              *valToReturn = ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U2:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT16);
+              u2* valToReturn = va_arg(/*marker*/*markerPtr, u2*);
+              *valToReturn = ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S4:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
+              s4* valToReturn = va_arg(/*marker*/*markerPtr, s4*);
+              *valToReturn = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U4:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT32);
+              u4* valToReturn = va_arg(/*marker*/*markerPtr, u4*);
+              *valToReturn = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S8:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT64);
+              s8* valToReturn = va_arg(/*marker*/*markerPtr, s8*);
+              *valToReturn = ComReadU8At(answer, offset);
+              offset += sizeof(u8);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U8:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT64);
+              u8* valToReturn = va_arg(/*marker*/*markerPtr, u8*);
+              *valToReturn = ComReadU8At(answer, offset);
+              offset += sizeof(u8);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_STRING:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_STRING);
+              std::string** valToReturn = va_arg(/*marker*/*markerPtr, std::string**);
+              u2 len = ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+              if (len == 0xFFFF) {
+                 *valToReturn = NULL;
+              } else {
+                 // store result
+                 u2 l = ComputeLPSTRLength(answer, offset, len);
+                 char* chstr = new char[l + 1];
+                 try {
+                    chstr[l] = '\0';
+                    UTF8Decode(answer, offset, len, chstr);
+                    *valToReturn = new std::string(chstr);
+                 } catch (...) {
+                    delete[] chstr;
+                    throw;
+                 }
+                 delete[] chstr;
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_BOOLARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY);
+              u1Array** valToReturn = va_arg(/*marker*/*markerPtr, u1Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u1Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u1Array(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S1ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY);
+              s1Array** valToReturn = va_arg(/*marker*/*markerPtr, s1Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s1Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s1Array(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U1ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY);
+              u1Array** valToReturn = va_arg(/*marker*/*markerPtr, u1Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u1Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u1Array(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_CHARARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_CHAR_ARRAY);
+              charArray** valToReturn = va_arg(/*marker*/*markerPtr, charArray**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new charArray(-1);
+              } else {
+                 // store result
+                 *valToReturn = new charArray(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+                       offset += sizeof(s2);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S2ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT16_ARRAY);
+              s2Array** valToReturn = va_arg(/*marker*/*markerPtr, s2Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s2Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s2Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+                       offset += sizeof(s2);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U2ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT16_ARRAY);
+              u2Array** valToReturn = va_arg(/*marker*/*markerPtr, u2Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u2Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u2Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+                       offset += sizeof(u2);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S4ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32_ARRAY);
+              s4Array** valToReturn = va_arg(/*marker*/*markerPtr, s4Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s4Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s4Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU4At(answer, offset);
+                       offset += sizeof(s4);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U4ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT32_ARRAY);
+              u4Array** valToReturn = va_arg(/*marker*/*markerPtr, u4Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u4Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u4Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU4At(answer, offset);
+                       offset += sizeof(u4);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S8ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT64_ARRAY);
+              s8Array** valToReturn = va_arg(/*marker*/*markerPtr, s8Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s8Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s8Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU8At(answer, offset);
+                       offset += sizeof(s8);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U8ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT64_ARRAY);
+              u8Array** valToReturn = va_arg(/*marker*/*markerPtr, u8Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u8Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u8Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU8At(answer, offset);
+                       offset += sizeof(u8);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_STRINGARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_STRING_ARRAY);
+              StringArray** valToReturn = va_arg(/*marker*/*markerPtr, StringArray**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new StringArray(-1);
+              } else {
+                 // store result
+                 *valToReturn = new StringArray(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       u2 lenStr = ComReadU2At(answer, offset);
+                       offset += sizeof(u2);
+                       if (lenStr != 0xFFFF) {
+                          u2 blen = ComputeLPSTRLength(answer, offset, lenStr);
+                          char* lpstr = new char[blen + 1];
+                          try {
+                             lpstr[blen] = '\0';
+                             UTF8Decode(answer, offset, lenStr, lpstr);
+                             offset += lenStr;
+
+                             (*valToReturn)->SetStringAt(j, new std::string(lpstr));
+                          } catch (...) {
+                             delete[] lpstr;
+                             throw;
+                          }
+                          delete[] lpstr;
+                       }
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_MEMORYSTREAM:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM_IO, HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM);
+              MemoryStream** valToReturn = va_arg(/*marker*/*markerPtr, MemoryStream**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new MemoryStream(-1);
+              } else {
+                 // store result
+                 *valToReturn = new MemoryStream(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        default:
+           {
+              throw Exception("Un-recognized return type");
+           }
+           break;
+   }
+
+   //*markerPtr = marker;
+   return offset;
+}
+
+static void ProcessInputArguments(u1 type, u1Array* invokeAPDU_data, va_list* markerPtr)
+{
+   //va_list marker = *markerPtr;
+
+   switch (type) {
+
+        case MARSHALLER_TYPE_IN_BOOL:
+        case MARSHALLER_TYPE_IN_S1:
+        case MARSHALLER_TYPE_IN_U1:
+           {
+              u1 val = (u1)va_arg(/*marker*/*markerPtr, s4);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_CHAR:
+        case MARSHALLER_TYPE_IN_S2:
+        case MARSHALLER_TYPE_IN_U2:
+           {
+              u2 val = (u2)va_arg(/*marker*/*markerPtr, s4);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S4:
+        case MARSHALLER_TYPE_IN_U4:
+           {
+              u4 val = (u4)va_arg(/*marker*/*markerPtr, s4);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S8:
+        case MARSHALLER_TYPE_IN_U8:
+           {
+              u8 val = (u8)va_arg(/*marker*/*markerPtr,u8);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_STRING:
+           {
+              std::string* val = va_arg(/*marker*/*markerPtr, std::string*);
+              (*invokeAPDU_data).Append(val);
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_MEMORYSTREAM:
+        case MARSHALLER_TYPE_IN_BOOLARRAY:
+        case MARSHALLER_TYPE_IN_S1ARRAY:
+        case MARSHALLER_TYPE_IN_U1ARRAY:
+           {
+              u1Array* val = va_arg(/*marker*/*markerPtr, u1Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u1* valBuf = val->GetBuffer();
+                 // add length
+                 *invokeAPDU_data += valLen;
+                 // add data
+                 for(u4 v = 0; v < valLen; v++)
+                    *invokeAPDU_data += valBuf[v];
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_CHARARRAY:
+        case MARSHALLER_TYPE_IN_S2ARRAY:
+        case MARSHALLER_TYPE_IN_U2ARRAY:
+           {
+              u2Array* val = va_arg(/*marker*/*markerPtr, u2Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u2* valBuf = val->GetBuffer();
+                 *invokeAPDU_data += valLen;
+                 for(u4 v = 0; v < valLen; v++) {
+                    *invokeAPDU_data += valBuf[v];
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S4ARRAY:
+        case MARSHALLER_TYPE_IN_U4ARRAY:
+           {
+              u4Array* val = va_arg(/*marker*/*markerPtr, u4Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u4* valBuf = val->GetBuffer();
+                 *invokeAPDU_data += valLen;
+                 for(u4 v = 0; v < valLen; v++) {
+                    *invokeAPDU_data += valBuf[v];
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S8ARRAY:
+        case MARSHALLER_TYPE_IN_U8ARRAY:
+           {
+              u8Array* val = va_arg(/*marker*/*markerPtr, u8Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u8* valBuf = val->GetBuffer();
+                 *invokeAPDU_data += valLen;
+                 for(u4 v = 0; v < valLen; v++) {
+                    *invokeAPDU_data += valBuf[v];
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_STRINGARRAY:
+           {
+              StringArray* val = va_arg(/*marker*/*markerPtr, StringArray*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 *invokeAPDU_data += valLen;
+                 // add data
+                 for (u4 j = 0; j < valLen; j++) {
+                    std::string* str = val->GetStringAt(j);
+                    if(str == NULL){ // add null pointer
+                       *invokeAPDU_data += (u2)0xFFFF;
+                    }else{
+                       (*invokeAPDU_data).Append(str);
+                    }
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        default:
+           u4 offset = 0;
+           ProcessByReferenceArguments(type, invokeAPDU_data, &offset, /*markerPtr*/markerPtr, TRUE);
+           // do not adjust markerPtr.
+           return;
+
+   }
+
+   //*markerPtr = marker;
+}
+
+void SmartCardMarshaller::Invoke(s4 nParam, ...)
+{
+   // Allow selfdiscovery of port
+   if (this->portNumber == 0) {
+      s4 _s4 = 0;
+      u4 nameSpaceHivecode = this->nameSpaceHivecode;
+      u2 typeHivecode      = this->typeHivecode;
+      std::string* uri     = this->uri;
+
+      this->portNumber		= CARDMANAGER_SERVICE_PORT;
+      this->nameSpaceHivecode = HIVECODE_NAMESPACE_SMARTCARD;
+      this->typeHivecode		= HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
+      this->uri				= new std::string(CARDMANAGER_SERVICE_NAME);
+
+      try {
+
+         // call the GetAssociatedPort method.
+         Invoke(3, HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT, MARSHALLER_TYPE_IN_S4, nameSpaceHivecode, MARSHALLER_TYPE_IN_S2, typeHivecode, MARSHALLER_TYPE_IN_STRING, uri, MARSHALLER_TYPE_RET_S4, &_s4);
+
+      } catch (...) {
+
+         delete this->uri;
+
+         this->portNumber		= (u2)_s4;
+         this->nameSpaceHivecode = nameSpaceHivecode;
+         this->typeHivecode		= typeHivecode;
+         this->uri				= uri;
+
+         throw;
+      }
+
+      delete this->uri;
+
+      this->portNumber		= (u2)_s4;
+      this->nameSpaceHivecode = nameSpaceHivecode;
+      this->typeHivecode		= typeHivecode;
+      this->uri				= uri;
+   }
+
+   u1Array invokeAPDU(0);
+
+   va_list marker;
+
+   va_start(marker, nParam);
+
+   // add 0xD8
+   invokeAPDU += (u1)0xD8;
+
+   // add port number
+   invokeAPDU += (u2)this->portNumber;
+
+   // add 0x6F
+   invokeAPDU += (u1)0x6F;
+
+   // add namespace Hivecode
+   invokeAPDU += this->nameSpaceHivecode;
+
+   // add type hivecode
+   invokeAPDU += this->typeHivecode;
+
+   // NOTE : va_arg(marker,type)
+   // As per ISO C++ if the pritives types
+   // char,short,byte are passed as argument to varidic method
+   // they are upcasted to int.
+   //
+   // On windows if you use va_arg(marker,u2), no warning will be issued
+   // and there will be no complain at run time, whereas
+   // On Linux (with g++) if you use va_arg(markey,u2), a warning will be issued
+   // saying that it is invalid to do this and run time will fail and it does fail
+   // with message "Segmentation fault".
+   //
+   // So va_arg for all int primitive types (char, short, byte and their unsigned values)
+   // should have s4 as the type.
+
+   // add method name
+   u2 methodID = (u2)va_arg(marker, s4);
+   invokeAPDU += methodID;
+
+   // add uri
+   u1Array uriArray(ComputeUTF8Length((lpCharPtr)this->uri->c_str()));
+   UTF8Encode((lpCharPtr)this->uri->c_str(), uriArray);
+   invokeAPDU += (u2)uriArray.GetLength();
+   invokeAPDU += uriArray;
+
+   u1Array invokeAPDU_data(0);
+
+   // process input arguments
+   for (s4 iParam = 0; iParam < nParam; iParam++) {
+      u1 type = (u1)va_arg(marker, s4);
+      ProcessInputArguments(type, &invokeAPDU_data, &marker);
+   }
+
+   if(ProcessInputStream != NULL){
+      u1Array invokeAPDU_data_Modified(0);
+      ProcessInputStream(invokeAPDU_data,invokeAPDU_data_Modified);
+      invokeAPDU += invokeAPDU_data_Modified;
+   }else{
+      invokeAPDU += invokeAPDU_data;
+   }
+
+   u1Array answer_o(0);
+
+   this->pcsc->BeginTransaction();
+
+   try {
+
+      if(invokeAPDU.GetLength() > (s4)APDU_TO_CARD_MAX_SIZE)
+      {
+         u4 offset = 0;
+         u4 size = invokeAPDU.GetLength() -1 - 2 - 1 - 4 - 2 - 2 - 2 -  uriArray.GetLength();
+
+         u1 first = TRUE;
+
+         u4 dataToSendLength = invokeAPDU.GetLength();
+         u4 invokeApduStartOffset = 0;
+
+         while(dataToSendLength > 0){
+
+            u4 encodedSize = size;
+            u4 encodedOffset = (u4)offset;
+
+            u4 subCommandMaxAllowed = APDU_TO_CARD_MAX_SIZE -1 - 2 - 8;
+
+            u4 length = dataToSendLength > subCommandMaxAllowed ? subCommandMaxAllowed : dataToSendLength;
+
+            u1Array subApdu(0);
+
+            if(first == TRUE){
+               u4 usefulDataLength = length -1 - 2 -1 -4 -2 -2 -2 - uriArray.GetLength();
+
+               subApdu += (u1)0xD8;
+               subApdu += (u2)0xFFFF;
+               subApdu += encodedSize;
+               subApdu += usefulDataLength;
+
+               if ((u8)(invokeApduStartOffset + length) > (u8)invokeAPDU.GetLength()) {
+                  throw ArgumentOutOfRangeException((lpCharPtr)"");
+               }
+
+               for(u4 j = invokeApduStartOffset; j < (invokeApduStartOffset + length); j++) {
+                  subApdu += invokeAPDU.GetBuffer()[j];
+               }
+
+               first = FALSE;
+               offset += usefulDataLength;
+
+            }else{
+
+               subApdu += (u1)0xD8;
+               subApdu += (u2)0xFFFF;
+               subApdu += encodedOffset;
+               subApdu += length;
+
+               if ((u8)(invokeApduStartOffset + length) > (u8)invokeAPDU.GetLength()) {
+                  throw ArgumentOutOfRangeException((lpCharPtr)"");
+               }
+
+               for(u4 j = invokeApduStartOffset; j < (invokeApduStartOffset + length); j++) {
+                  subApdu += invokeAPDU.GetBuffer()[j];
+               }
+
+               offset += length;
+            }
+
+            size = 0;
+            invokeApduStartOffset = invokeApduStartOffset + length;
+            dataToSendLength = dataToSendLength - length;
+
+            u1Array apduToSend(5);
+
+            apduToSend.GetBuffer()[0] = 0x80;
+            apduToSend.GetBuffer()[1] = 0xC2;
+            apduToSend.GetBuffer()[2] = 0x00;
+            apduToSend.GetBuffer()[3] = 0x00;
+            apduToSend.GetBuffer()[4] = (u1)subApdu.GetLength();
+            apduToSend += subApdu;
+
+            this->pcsc->ExchangeData(apduToSend, answer_o);
+         }
+      }else{
+
+         // construct call
+         u1Array apdu(5);
+         apdu.GetBuffer()[0] = 0x80;
+         apdu.GetBuffer()[1] = 0xC2;
+         apdu.GetBuffer()[2] = 0x00;
+         apdu.GetBuffer()[3] = 0x00;
+         apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
+         apdu += invokeAPDU;
+
+         this->pcsc->ExchangeData(apdu, answer_o);
+      }
+   } catch (...) {
+      this->pcsc->EndTransaction();
+      throw;
+   }
+
+   this->pcsc->EndTransaction();
+
+   u1Array answer(0);
+
+   if ((ProcessOutputStream != NULL) && (answer_o.GetLength() > 0) && (answer_o.ReadU1At(0) == 0x01)){
+      u1Array answerI(0);
+      u1Array answerM(0);
+
+      for(u4 i = 1; i < answer_o.GetLength(); i++){
+         answerI += answer_o.GetBuffer()[i];
+      }
+
+      ProcessOutputStream(answerI, answerM);
+
+      answer += answer_o.GetBuffer()[0];
+
+      for(u4 i=0;i<answerM.GetLength();i++){
+         answer += answerM.GetBuffer()[i];
+      }
+
+   } else {
+      for(u4 i=0;i<answer_o.GetLength();i++)
+         answer += answer_o.GetBuffer()[i];
+   }
+
+   // analyze return type
+   u4 offset = ProcessReturnType((u1)va_arg(marker, s4), &answer, &marker);
+
+   va_end(marker);
+
+   // process byref types
+   va_start(marker, nParam);
+
+   // skip method name param
+   u2 methodID2 = (u2)va_arg(marker, s4);
+
+   if (methodID2 == methodID) {
+      for (s4 iParam = 0; iParam < nParam; iParam++) {
+         u1 type = (u1)va_arg(marker, s4);
+         ProcessOutputArguments(type, &answer, &offset, &marker);
+      }
+   }
+
+   va_end(marker);
+}
+
+void SmartCardMarshaller::SetInputStream(pCommunicationStream inStream){
+   this->ProcessInputStream = inStream;
+}
+
+void  SmartCardMarshaller::SetOutputStream(pCommunicationStream outStream){
+   this->ProcessOutputStream = outStream;
+}
+
+MARSHALLER_NS_END
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Marshaller.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,77 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_h
+#define _include_marshaller_h
+
+#ifdef _XCL_
+#include "xcl_broker.h"
+#endif // _XCL_
+
+MARSHALLER_NS_BEGIN
+
+typedef void (*pCommunicationStream)(u1Array& st,u1Array& stM);
+
+class SMARTCARDMARSHALLER_DLLAPI SmartCardMarshaller
+{
+
+private:
+    u4            nameSpaceHivecode;
+    u2            typeHivecode;
+    u2            portNumber;
+    std::string*  uri;
+#ifndef _XCL_
+    PCSC*         pcsc;
+#else 	// _XCL_
+    XCLBroker*    pcsc;
+#endif 	// _XCL_
+
+    pCommunicationStream ProcessInputStream;
+    pCommunicationStream ProcessOutputStream;
+
+public:
+    // Existing PCSC connection
+    SmartCardMarshaller(SCARDHANDLE pcscCardHandle, u2 portNumber,M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode);
+
+    // PCSC compatible readers
+    SmartCardMarshaller(M_SAL_IN std::string* readerName, u2 portNumber,M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index);
+
+    // destructor
+    ~SmartCardMarshaller(void);
+
+    // Remoting marshalling method
+    void Invoke(s4 nParam, ...);
+
+    void UpdatePCSCCardHandle(SCARDHANDLE hCard);
+
+    void SetInputStream(pCommunicationStream inStream);
+    void SetOutputStream(pCommunicationStream outStream);
+
+    std::string* GetReaderName();
+    SCARDHANDLE GetCardHandle();
+    void DoTransact(bool flag);
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/MarshallerCfg.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/MarshallerCfg.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/MarshallerCfg.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,167 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshallercfg_h
+#define _include_marshallercfg_h
+
+#ifdef SMARTCARDMARSHALLER_EXPORTS
+	#define SMARTCARDMARSHALLER_DLLAPI __declspec(dllexport)
+#else
+	#define SMARTCARDMARSHALLER_DLLAPI
+#endif
+
+#ifdef M_SAL_ANNOTATIONS
+#include <specstrings.h>
+#define M_SAL_IN		__in
+#define M_SAL_OUT		__out
+#define M_SAL_INOUT		__inout
+#else
+#define M_SAL_IN
+#define M_SAL_OUT
+#define M_SAL_INOUT
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef WIN32
+#include <inttypes.h>
+#endif
+
+// data types
+typedef unsigned char       u1;
+typedef unsigned short      u2;
+typedef unsigned int        u4;
+typedef char                s1;
+typedef short               s2;
+typedef int                 s4;
+
+#ifdef WIN32
+typedef unsigned __int64    u8;
+typedef __int64             s8;
+typedef LPSTR               lpCharPtr;
+typedef LPTSTR				lpTCharPtr;
+typedef LPBYTE				lpByte;
+typedef const lpByte        lpCByte;
+#else
+typedef uint64_t u8;
+typedef int64_t s8;
+typedef char*				 lpTCharPtr;
+typedef char*                lpCharPtr;
+typedef unsigned char*       lpByte;
+typedef const lpByte		 lpCByte;
+#endif
+
+// Marshaller argument type constants
+#define MARSHALLER_TYPE_IN_VOID				0
+#define MARSHALLER_TYPE_IN_BOOL				1
+#define MARSHALLER_TYPE_IN_S1				2
+#define MARSHALLER_TYPE_IN_U1				3
+#define MARSHALLER_TYPE_IN_CHAR				4
+#define MARSHALLER_TYPE_IN_S2				5
+#define MARSHALLER_TYPE_IN_U2				6
+#define MARSHALLER_TYPE_IN_S4				7
+#define MARSHALLER_TYPE_IN_U4				8
+#define MARSHALLER_TYPE_IN_S8				9
+#define MARSHALLER_TYPE_IN_U8				10
+#define MARSHALLER_TYPE_IN_STRING			11
+
+#define MARSHALLER_TYPE_IN_BOOLARRAY		21
+#define MARSHALLER_TYPE_IN_S1ARRAY			22
+#define MARSHALLER_TYPE_IN_U1ARRAY			23
+#define MARSHALLER_TYPE_IN_CHARARRAY		24
+#define MARSHALLER_TYPE_IN_S2ARRAY			25
+#define MARSHALLER_TYPE_IN_U2ARRAY			26
+#define MARSHALLER_TYPE_IN_S4ARRAY			27
+#define MARSHALLER_TYPE_IN_U4ARRAY			28
+#define MARSHALLER_TYPE_IN_S8ARRAY			29
+#define MARSHALLER_TYPE_IN_U8ARRAY			30
+#define MARSHALLER_TYPE_IN_STRINGARRAY		31
+
+#define MARSHALLER_TYPE_IN_MEMORYSTREAM     40
+
+#define MARSHALLER_TYPE_REF_BOOL			50
+#define MARSHALLER_TYPE_REF_S1				51
+#define MARSHALLER_TYPE_REF_U1				52
+#define MARSHALLER_TYPE_REF_CHAR			53
+#define MARSHALLER_TYPE_REF_S2				54
+#define MARSHALLER_TYPE_REF_U2				55
+#define MARSHALLER_TYPE_REF_S4				56
+#define MARSHALLER_TYPE_REF_U4				57
+#define MARSHALLER_TYPE_REF_S8				58
+#define MARSHALLER_TYPE_REF_U8				59
+#define MARSHALLER_TYPE_REF_STRING			60
+
+#define MARSHALLER_TYPE_REF_BOOLARRAY		61
+#define MARSHALLER_TYPE_REF_S1ARRAY			62
+#define MARSHALLER_TYPE_REF_U1ARRAY			63
+#define MARSHALLER_TYPE_REF_CHARARRAY		64
+#define MARSHALLER_TYPE_REF_S2ARRAY			65
+#define MARSHALLER_TYPE_REF_U2ARRAY			66
+#define MARSHALLER_TYPE_REF_S4ARRAY			67
+#define MARSHALLER_TYPE_REF_U4ARRAY			68
+#define MARSHALLER_TYPE_REF_S8ARRAY			69
+#define MARSHALLER_TYPE_REF_U8ARRAY			70
+#define MARSHALLER_TYPE_REF_STRINGARRAY		71
+
+// Marshaller return type arguments
+#define MARSHALLER_TYPE_RET_VOID			MARSHALLER_TYPE_IN_VOID
+#define MARSHALLER_TYPE_RET_BOOL			MARSHALLER_TYPE_IN_BOOL
+#define MARSHALLER_TYPE_RET_S1				MARSHALLER_TYPE_IN_S1
+#define MARSHALLER_TYPE_RET_U1				MARSHALLER_TYPE_IN_U1
+#define MARSHALLER_TYPE_RET_CHAR			MARSHALLER_TYPE_IN_CHAR
+#define MARSHALLER_TYPE_RET_S2				MARSHALLER_TYPE_IN_S2
+#define MARSHALLER_TYPE_RET_U2				MARSHALLER_TYPE_IN_U2
+#define MARSHALLER_TYPE_RET_S4				MARSHALLER_TYPE_IN_S4
+#define MARSHALLER_TYPE_RET_U4				MARSHALLER_TYPE_IN_U4
+#define MARSHALLER_TYPE_RET_S8				MARSHALLER_TYPE_IN_S8
+#define MARSHALLER_TYPE_RET_U8				MARSHALLER_TYPE_IN_U8
+#define MARSHALLER_TYPE_RET_STRING			MARSHALLER_TYPE_IN_STRING
+
+#define MARSHALLER_TYPE_RET_BOOLARRAY		MARSHALLER_TYPE_IN_BOOLARRAY
+#define MARSHALLER_TYPE_RET_S1ARRAY			MARSHALLER_TYPE_IN_S1ARRAY
+#define MARSHALLER_TYPE_RET_U1ARRAY			MARSHALLER_TYPE_IN_U1ARRAY
+#define MARSHALLER_TYPE_RET_CHARARRAY		MARSHALLER_TYPE_IN_CHARARRAY
+#define MARSHALLER_TYPE_RET_S2ARRAY			MARSHALLER_TYPE_IN_S2ARRAY
+#define MARSHALLER_TYPE_RET_U2ARRAY			MARSHALLER_TYPE_IN_U2ARRAY
+#define MARSHALLER_TYPE_RET_S4ARRAY			MARSHALLER_TYPE_IN_S4ARRAY
+#define MARSHALLER_TYPE_RET_U4ARRAY			MARSHALLER_TYPE_IN_U4ARRAY
+#define MARSHALLER_TYPE_RET_S8ARRAY			MARSHALLER_TYPE_IN_S8ARRAY
+#define MARSHALLER_TYPE_RET_U8ARRAY			MARSHALLER_TYPE_IN_U8ARRAY
+#define MARSHALLER_TYPE_RET_STRINGARRAY		MARSHALLER_TYPE_IN_STRINGARRAY
+
+#define MARSHALLER_TYPE_RET_MEMORYSTREAM    MARSHALLER_TYPE_IN_MEMORYSTREAM
+
+// namespace for the module
+// in case compiler does not support namespace, the defines can be undefined
+#define MARSHALLER_NS_BEGIN namespace Marshaller {
+#define MARSHALLER_NS_END }
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,559 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable : 4201)
+#else
+#define DBG_UNREFERENCED_LOCAL_VARIABLE(a)
+#endif
+
+#ifdef __APPLE__
+#include <PCSC/wintypes.h>
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+
+#ifndef WIN32
+#include <strings.h>
+#endif
+#include <string.h>
+#include <stdexcept>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#include "PCSC.h"
+#include "Except.h"
+
+
+#ifdef __sun
+typedef LPSTR LPTSTR;
+#endif
+
+// JCD
+#include "log.h"
+
+
+
+MARSHALLER_NS_BEGIN
+
+extern u4 CheckForException(u1Array answer, u4 nameSpace, u2 type);
+extern u4 ComReadU4At(u1Array &array, u4 pos);
+
+#define SUPPORT_BETA_VERSION
+
+const u1 isNetCardAPDU[] = {0x80,0xC2,0x00,0x00,0x1C,0xD8,0x00,0x01,0x6F,0x00,0xF5,0xEF,0xBF,0xB1,0x8C,0xDD,0xC2,0x00,0x0E,0x43,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x4D,0x61,0x6E,0x61,0x67,0x65,0x72};
+
+#define APDU_TO_CARD_MAX_SIZE                                                       0xFF
+#define CARDMANAGER_SERVICE_PORT                                                    1
+#define CARDMANAGER_SERVICE_NAME                                                    "ContentManager"
+
+#define HIVECODE_NAMESPACE_SMARTCARD                                                0x00F5EFBF
+#define HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER                                      0xB18C
+#define HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT                  0x7616
+#define HIVECODE_NAMESPACE_SYSTEM                                                   0x00D25D1C
+#define HIVECODE_TYPE_SYSTEM_INT32                                                  0x61C0
+
+
+// *******************
+// PCSC class
+// *******************
+PCSC::PCSC(M_SAL_IN std::string* readerName)
+{
+   DWORD activeProtocol;
+   LONG lReturn;
+
+   this->hContext      = 0;
+   this->hCard	        = 0;
+
+   lReturn = SCardEstablishContext(0, NULL, NULL, &this->hContext);
+   if(lReturn != SCARD_S_SUCCESS) {
+      throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
+   }
+
+   lReturn = SCardConnect(this->hContext, (LPTSTR)readerName->c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &this->hCard, &activeProtocol);
+   if (lReturn != SCARD_S_SUCCESS) {
+      throw RemotingException((lpCharPtr)"PCSC: SCardConnect error",lReturn);
+   }
+
+   this->readerName = new std::string(readerName->c_str());
+}
+
+PCSC::PCSC(M_SAL_IN std::string* inputReaderName, u2* portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index)
+{
+   Log::begin( "PCSC::PCSC" );
+
+   std::string selfDiscover("selfdiscover");
+   std::string* identifiedReaderName;
+   LPTSTR pReaderList = NULL;
+   LONG lReturn;
+
+   if (inputReaderName == NULL) {
+      inputReaderName = &selfDiscover;
+   }
+
+   identifiedReaderName = NULL;
+   this->hContext    = 0;
+   this->hCard       = 0;
+
+   lReturn = SCardEstablishContext(0, NULL, NULL, &this->hContext);
+   Log::log( "PCSC::PCSC - SCardEstablishContext <%#02x>", lReturn );
+   if(lReturn != SCARD_S_SUCCESS)
+   {
+      Log::log( "PCSC::PCSC - ## ERROR ## SCardEstablishContext <%#02x>", lReturn );
+      throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
+   }
+
+   // self-discovery mechanism
+#ifdef WIN32
+   if (_stricmp("selfdiscover", inputReaderName->c_str()) == 0) {
+#else
+   if (strncasecmp("selfdiscover", inputReaderName->c_str(),inputReaderName->length()) == 0) {
+#endif
+      // In Windows SCARD_AUTOALLOCATE (-1) as a value of readerListChatLength
+      // would signal the SCardListReaders to determine the size of reader string
+      // This is not available in Linux so we call the SCardListReaders twice. First
+      // to get the length and then the reader names.
+#ifdef WIN32
+      DWORD readerListCharLength = SCARD_AUTOALLOCATE;
+      lReturn = SCardListReaders(this->hContext, NULL, (LPTSTR)&pReaderList, &readerListCharLength);
+      Log::log( "PCSC::PCSC - SCardListReaders <%#02x>", lReturn );
+
+#else
+      DWORD readerListCharLength = 0;
+
+      lReturn = SCardListReaders(this->hContext,NULL,NULL,&readerListCharLength);
+      if(lReturn != SCARD_S_SUCCESS)
+         throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);
+
+      pReaderList = (lpCharPtr)malloc(sizeof(char)*readerListCharLength);
+      lReturn = SCardListReaders(this->hContext, NULL,pReaderList, &readerListCharLength);
+#endif
+
+
+      if(lReturn != SCARD_S_SUCCESS)
+      {
+         Log::log( "PCSC::PCSC - ## ERROR ## SCardListReaders <%#02x>", lReturn );
+         throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);
+      }
+      else
+      {
+         u4 count = 0;
+         u1 foundReader = FALSE;
+         SCARDHANDLE finalCardHandle = 0;
+         try
+         {
+            lpTCharPtr pReader = pReaderList;
+            while ('\0' != *pReader )
+            {
+               size_t readerNameLen = strlen((const char*)pReader);
+               SCARD_READERSTATE readerStates[1];
+               readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
+               readerStates[0].szReader = pReader;
+               if (SCardGetStatusChange(this->hContext, 0, readerStates, 1) == SCARD_S_SUCCESS)
+               {
+                  if ((readerStates[0].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+                  {
+                     // we found a card in this reader
+                     if (identifiedReaderName != NULL)
+                     {
+                        delete identifiedReaderName;
+                        identifiedReaderName = NULL;
+                     }
+
+                     identifiedReaderName = new std::string((lpCharPtr)pReader);
+                     DWORD activeProtocol;
+
+                     Log::log( "PCSC::PCSC SCardConnect..." );
+                     lReturn = SCardConnect(this->hContext, (LPTSTR)identifiedReaderName->c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &this->hCard, &activeProtocol);
+                     Log::log( "PCSC::PCSC - SCardConnect <%#02x>", lReturn );
+
+                     if (lReturn == SCARD_S_SUCCESS)
+                     {
+                        // try to identify if we're dealing with a .NetCard
+                        u1 answerData[258];
+                        DWORD answerLen = 258;
+
+                        Log::log( "PCSC::PCSC SCardTransmit..." );
+                        lReturn = SCardTransmit(hCard, SCARD_PCI_T0, isNetCardAPDU, sizeof(isNetCardAPDU), NULL, (LPBYTE)answerData, &answerLen);
+                        Log::log( "PCSC::PCSC - SCardTransmit <%#02x>", lReturn );
+
+                        if (lReturn == SCARD_S_SUCCESS)
+                        {
+                           u1 rethrowException = FALSE;
+                           try {
+                              if (answerData[answerLen - 2] == 0x61)
+                              {
+                                 if (answerData[answerLen - 1] > 10)
+                                 {
+                                    u1Array invokeAPDU(0);
+                                    invokeAPDU += (u1)0xD8;
+                                    invokeAPDU += (u2)CARDMANAGER_SERVICE_PORT;
+                                    invokeAPDU += (u1)0x6F;
+                                    invokeAPDU += (u4)HIVECODE_NAMESPACE_SMARTCARD;
+                                    invokeAPDU += (u2)HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
+                                    invokeAPDU += (u2)HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT;
+                                    std::string* cmServiceUri = new std::string(CARDMANAGER_SERVICE_NAME);
+                                    invokeAPDU.Append(cmServiceUri);
+                                    delete cmServiceUri;
+                                    invokeAPDU += (u4)nameSpaceHivecode;
+                                    invokeAPDU += (u2)typeHivecode;
+                                    invokeAPDU.Append(uri);
+
+                                    // construct call
+                                    if(invokeAPDU.GetLength() <= (s4)APDU_TO_CARD_MAX_SIZE) {
+                                       u1Array apdu(5);
+                                       apdu.GetBuffer()[0] = 0x80;
+                                       apdu.GetBuffer()[1] = 0xC2;
+                                       apdu.GetBuffer()[2] = 0x00;
+                                       apdu.GetBuffer()[3] = 0x00;
+                                       apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
+                                       apdu += invokeAPDU;
+
+                                       u1Array answer(0);
+
+                                       Log::log( "PCSC::PCSC - ExchangeData..." );
+                                       this->ExchangeData(apdu, answer);
+                                       Log::log( "PCSC::PCSC - ExchangeData ok" );
+
+                                       Log::log( "PCSC::PCSC - CheckForException..." );
+                                       u4 protocolOffset = CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
+                                       Log::log( "PCSC::PCSC - CheckForException ok" );
+
+                                       u4 discoveredPortNumber = ComReadU4At(answer, protocolOffset);
+                                       if ((*portNumber == 0) || (discoveredPortNumber == *portNumber))
+                                       {
+                                          *portNumber = (u2)discoveredPortNumber;
+
+                                          if (foundReader == TRUE)
+                                          {
+                                             if (index == 0)
+                                             {
+                                                // this is the second reader/card/app that matches - we error at this point
+                                                rethrowException = TRUE;
+                                                char errorMessage[255];
+                                                strcpy(errorMessage, "At least 2 cards posses \"");
+                                                strcat(errorMessage, uri->c_str());
+                                                strcat(errorMessage, "\" service\r\nRemove conflicting cards from your system");
+
+                                                Log::error( "PCSC::PCSC", errorMessage );
+
+                                                throw RemotingException(errorMessage);
+                                             }
+                                          }
+
+                                          foundReader = TRUE;
+                                          finalCardHandle = this->hCard;
+
+                                          // Advance to the next value.
+                                          count++;
+
+                                          if (count == index)
+                                          {
+                                             // we enumerate one by one the valid readers - so stop here
+                                             break;
+                                          }
+
+                                          pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+                                          continue;
+                                       }
+                                    }
+                                 }
+                              }
+                           }
+                           catch (...)
+                           {
+                              if (rethrowException == TRUE)
+                              {
+                                 throw;
+                              }
+                              else
+                              {
+                                 // swallow exception
+                              }
+                           }
+
+                           SCardDisconnect(this->hCard, SCARD_LEAVE_CARD);
+                           this->hCard = 0;
+                        }
+                        // this is not a .NetCard, or the service was not found - let's try another reader/card
+                        else
+                        {
+                           Log::error( "PCSC::PCSC", "SCardTransmit failed" );
+                        }
+                     }
+                     else
+                     {
+                        Log::error( "PCSC::PCSC", "SCardConnect failed" );
+                     }
+                  }
+                  else
+                  {
+                     Log::error( "PCSC::PCSC", "SCARD_STATE_PRESENT not present" );
+                  }
+               }
+               else
+               {
+                  Log::error( "PCSC::PCSC", "SCardGetStatusChange != SCARD_S_SUCCESS" );
+               }
+
+               // Advance to the next value.
+               pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+            }
+         } catch (...) {
+            if (identifiedReaderName != NULL) {
+               delete identifiedReaderName;
+            }
+
+#ifdef WIN32
+            lReturn = SCardFreeMemory(this->hContext, pReaderList);
+            if(lReturn != SCARD_S_SUCCESS) {
+               throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
+            }
+#else
+            if(pReaderList != NULL)
+               free(pReaderList);
+#endif
+            throw;
+         }
+
+         // have we found anything ?
+         if (foundReader == FALSE) {
+            if (identifiedReaderName != NULL) {
+               delete identifiedReaderName;
+            }
+
+#ifdef WIN32
+            lReturn = SCardFreeMemory(this->hContext, pReaderList);
+            if(lReturn != SCARD_S_SUCCESS) {
+               throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
+            }
+#else
+            if(pReaderList != NULL)
+               free(pReaderList);
+#endif
+
+            throw RemotingException((lpCharPtr)"Could not find any Cryptoflex .NET smart card",SCARD_E_NO_SMARTCARD);
+         }
+
+         this->hCard = finalCardHandle;
+      }
+
+      this->readerName = new std::string(identifiedReaderName->c_str());
+
+      delete identifiedReaderName;
+
+   } else {
+      this->readerName = new std::string(inputReaderName->c_str());
+   }
+
+   Log::end( "PCSC::PCSC" );
+}
+
+PCSC::PCSC(SCARDHANDLE cardHandle)
+{
+   this->hContext   = 0;
+   this->hCard		 = cardHandle;
+   this->readerName = NULL;
+   this->fDoTransact = true;
+}
+
+std::string* PCSC::GetReaderName(void)
+{
+   return this->readerName;
+}
+
+void PCSC::BeginTransaction(void)
+{
+   if(fDoTransact) // TODO: TEST RETURN CODE!!
+      SCardBeginTransaction(this->hCard);
+}
+
+void PCSC::EndTransaction(void)
+{
+   if(fDoTransact) // TODO: TEST RETURN CODE!!
+      SCardEndTransaction(this->hCard, SCARD_LEAVE_CARD);
+}
+
+SCARDHANDLE PCSC::GetCardHandle(void)
+{
+   return this->hCard;
+}
+
+void PCSC::SetCardHandle(SCARDHANDLE hCard)
+{
+   this->hCard = hCard;
+}
+
+void PCSC::DoTransact(bool flag)
+{
+   this->fDoTransact = flag;
+}
+
+void PCSC::ExchangeData(u1Array &dataIn, u1Array &dataout)
+{
+   u1 answerData[258];
+
+   // check validity of handle
+   if (this->hCard == 0) {
+      throw RemotingException((lpCharPtr)"PCSC: Invalid card handle", SCARD_E_INVALID_HANDLE);
+   }
+
+#ifdef __DEBUG_APDU__
+   //FILE *pFile = fopen("C:\\AxaltoProtocolAnalyzer.txt","a");
+   FILE *pFile = fopen("C:\\Gemalto.NET.PKCS11.log","a");
+#endif
+
+   try {
+
+      BeginTransaction();
+
+      DWORD answerLen = sizeof(answerData);
+
+#ifdef __DEBUG_APDU__
+      fprintf(pFile, "\nCmd DataIn\n");
+      for(int i=0; i < (s4)dataIn.GetLength(); i++) {
+         fprintf(pFile, "%02x",dataIn.GetBuffer()[i]);
+      }
+      fprintf(pFile, "\n");
+      unsigned long ulStart = GetTickCount( );
+#endif
+
+      s4 lReturn = SCardTransmit(hCard, SCARD_PCI_T0, dataIn.GetBuffer(), dataIn.GetLength(), NULL, (lpByte)answerData, &answerLen);
+      if (lReturn != SCARD_S_SUCCESS) {
+         throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error",lReturn);
+      }
+
+      if (answerLen < 2) {
+         throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
+      }
+
+      if (answerLen > 2) {
+         u1Array temp(answerLen - 2);
+         temp.SetBuffer(answerData);
+         dataout += temp;
+#ifdef __DEBUG_APDU__
+         fprintf(pFile, "Cmd DataOut\n");
+         for(int i=0; i< (s4)temp.GetLength(); i++) {
+            fprintf(pFile, "%02x",temp.GetBuffer()[i]);
+         }
+         fprintf(pFile, "\n");
+#endif
+      }
+
+      u1 sw1 = answerData[answerLen - 2];
+      u1 sw2 = answerData[answerLen - 1];
+
+#ifdef __DEBUG_APDU__
+      fprintf( pFile, "Cmd Status => %02x%02x\n", sw1, sw2 );
+      fprintf( pFile, "Cmd Time   => %ld ms\n", GetTickCount( ) - ulStart );
+#endif
+
+      while ((sw1 == 0x61) || (sw1 == 0x9F))
+      {
+         u1 GetResponse[5];
+         if (sw1 == 0x9F) {
+            GetResponse[0] = 0xA0;
+         } else {
+            GetResponse[0] = 0x00;
+         }
+         GetResponse[1] = 0xC0;
+         GetResponse[2] = 0x00;
+         GetResponse[3] = 0x00;
+         GetResponse[4] = sw2;
+         answerLen = 258;
+
+#ifdef __DEBUG_APDU__
+         fprintf(pFile, "GetResponse DataIn\n");
+         for(int i=0; i<5; i++) {
+            fprintf(pFile, "%02x",GetResponse[i]);
+         }
+         fprintf(pFile, "\n");
+         ulStart = GetTickCount( );
+#endif
+
+         lReturn = SCardTransmit(hCard, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen);
+         if (lReturn != SCARD_S_SUCCESS) {
+            throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error",lReturn);
+         }
+
+         if (answerLen < 2) {
+            throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
+         }
+
+         if (answerLen > 2) {
+            u1Array temp(answerLen - 2);
+            temp.SetBuffer(answerData);
+            dataout += temp;
+#ifdef __DEBUG_APDU__
+            fprintf(pFile, "GetResponse DataOut\n");
+            for(int i=0; i< (s4)temp.GetLength(); i++) {
+               fprintf(pFile, "%02x ",temp.GetBuffer()[i]);
+            }
+            fprintf(pFile, "\n");
+
+#endif
+         }
+         sw1 = answerData[answerLen - 2];
+         sw2 = answerData[answerLen - 1];
+
+#ifdef __DEBUG_APDU__
+         fprintf( pFile, "GetResponse Status => %02x%02x\n ", sw1, sw2 );
+         fprintf( pFile, "GetResponse Time   => %ld ms\n", GetTickCount( ) - ulStart );
+#endif
+      }
+   } catch (...) {
+#ifdef __DEBUG_APDU__
+      fflush(pFile);
+      fclose(pFile);
+#endif
+      EndTransaction();
+      throw;
+   }
+
+#ifdef __DEBUG_APDU__
+   fflush(pFile);
+   fclose(pFile);
+#endif
+
+   EndTransaction();
+}
+
+PCSC::~PCSC(void)
+{
+   // we cleanup the various context and card handle only if we allocated it (depends of constructor)
+   if (hContext != 0) {
+      if (hCard != 0) {
+         SCardDisconnect(hCard, SCARD_LEAVE_CARD);
+         hCard = 0;
+      }
+      SCardReleaseContext(hContext);
+      hContext = 0;
+   }
+
+   if (this->readerName != NULL) {
+      delete this->readerName;
+      this->readerName = NULL;
+   }
+}
+
+MARSHALLER_NS_END
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PCSC.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,53 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_pcsc_h
+#define _include_marshaller_pcsc_h
+
+MARSHALLER_NS_BEGIN
+
+class PCSC
+{
+
+private:
+    SCARDCONTEXT hContext;
+    SCARDHANDLE  hCard;
+    std::string*    readerName;
+    bool fDoTransact;
+
+public:
+    PCSC(SCARDHANDLE cardHandle);
+	PCSC(M_SAL_IN std::string* readerName);
+	PCSC(M_SAL_IN std::string* readerName, u2* portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index);
+    SCARDHANDLE GetCardHandle(void);
+    void SetCardHandle(SCARDHANDLE hCard);
+    void DoTransact(bool flag);
+    std::string* GetReaderName(void);
+    void BeginTransaction(void);
+    void EndTransaction(void);
+    void ExchangeData(u1Array &dataIn, u1Array &dataout);
+    ~PCSC(void);
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,410 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+typedef struct _DES_Context
+{
+    u4 encrypt_subkeys[32];
+    u4 decrypt_subkeys[32];
+} _DES_Context;
+
+typedef struct _3DES_Context
+{
+    u4 encrypt_subkeys[96];
+    u4 decrypt_subkeys[96];
+} _3DES_Context;
+
+/*
+ * The s-box values are permuted according to the 'primitive function P'
+ * and are rotated one bit to the left.
+ */
+static const u4 sbox1[64] =
+{
+  0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+  0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+  0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+  0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+  0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+  0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+  0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+  0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const u4 sbox2[64] =
+{
+  0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+  0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+  0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+  0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+  0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+  0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+  0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+  0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const u4 sbox3[64] =
+{
+  0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+  0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+  0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+  0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+  0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+  0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+  0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+  0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const u4 sbox4[64] =
+{
+  0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+  0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+  0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+  0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+  0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+  0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+  0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+  0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const u4 sbox5[64] =
+{
+  0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+  0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+  0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+  0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+  0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+  0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+  0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+  0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const u4 sbox6[64] =
+{
+  0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+  0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+  0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+  0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+  0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+  0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+  0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+  0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const u4 sbox7[64] =
+{
+  0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+  0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+  0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+  0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+  0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+  0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+  0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+  0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const u4 sbox8[64] =
+{
+  0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+  0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+  0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+  0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+  0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+  0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+  0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+  0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+static const u4 leftkey_swap[16] =
+{
+  0x00000000, 0x00000001, 0x00000100, 0x00000101,
+  0x00010000, 0x00010001, 0x00010100, 0x00010101,
+  0x01000000, 0x01000001, 0x01000100, 0x01000101,
+  0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const u4 rightkey_swap[16] =
+{
+  0x00000000, 0x01000000, 0x00010000, 0x01010000,
+  0x00000100, 0x01000100, 0x00010100, 0x01010100,
+  0x00000001, 0x01000001, 0x00010001, 0x01010001,
+  0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+static const u1 encrypt_rotate_tab[16] =
+{
+  1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+#define DO_PERMUTATION(a, temp, b, offset, mask)	\
+    temp = ((a>>offset) ^ b) & mask;			\
+    b ^= temp;						\
+    a ^= temp<<offset;
+
+#define INITIAL_PERMUTATION(left, temp, right)		\
+    DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)	\
+    DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)	\
+    DO_PERMUTATION(right, temp, left, 2, 0x33333333)	\
+    DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)	\
+    right =  (right << 1) | (right >> 31);		\
+    temp  =  (left ^ right) & 0xaaaaaaaa;		\
+    right ^= temp;					\
+    left  ^= temp;					\
+    left  =  (left << 1) | (left >> 31);
+
+#define FINAL_PERMUTATION(left, temp, right)		\
+    left  =  (left << 31) | (left >> 1);		\
+    temp  =  (left ^ right) & 0xaaaaaaaa;		\
+    left  ^= temp;					\
+    right ^= temp;					\
+    right  =  (right << 31) | (right >> 1);		\
+    DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)	\
+    DO_PERMUTATION(right, temp, left, 2, 0x33333333)	\
+    DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)	\
+    DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)
+
+#define DES_ROUND(from, to, work, subkey)		\
+    work = from ^ *subkey++;				\
+    to ^= sbox8[  work	    & 0x3f ];			\
+    to ^= sbox6[ (work>>8)  & 0x3f ];			\
+    to ^= sbox4[ (work>>16) & 0x3f ];			\
+    to ^= sbox2[ (work>>24) & 0x3f ];			\
+    work = ((from << 28) | (from >> 4)) ^ *subkey++;	\
+    to ^= sbox7[  work	    & 0x3f ];			\
+    to ^= sbox5[ (work>>8)  & 0x3f ];			\
+    to ^= sbox3[ (work>>16) & 0x3f ];			\
+    to ^= sbox1[ (work>>24) & 0x3f ];
+
+#define READ_64BIT_DATA(data, left, right)					\
+    left  = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];	\
+    right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
+
+#define WRITE_64BIT_DATA(data, left, right)					\
+    data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; 		\
+    data[2] = (left >> 8) &0xff; data[3] = left &0xff;				\
+    data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff;		\
+    data[6] = (right >> 8) &0xff; data[7] = right &0xff;
+
+
+static void algo_DES_KeySchedule(const u1 * rawkey, u4 * subkey)
+{
+    u4 left, right, work;
+    u1 round;
+
+    READ_64BIT_DATA (rawkey, left, right)
+
+    DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f)
+    DO_PERMUTATION (right, work, left, 0, 0x10101010)
+
+    left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2)
+        | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf])
+        | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6)
+        | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4);
+
+    left &= 0x0fffffff;
+
+    right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2)
+        | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf])
+        | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6)
+        | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4);
+
+    right &= 0x0fffffff;
+
+    for (round = 0; round < 16; ++round) {
+
+        left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+        right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+
+        *subkey++ = ((left << 4) & 0x24000000)
+            | ((left << 28) & 0x10000000)
+            | ((left << 14) & 0x08000000)
+            | ((left << 18) & 0x02080000)
+            | ((left << 6) & 0x01000000)
+            | ((left << 9) & 0x00200000)
+            | ((left >> 1) & 0x00100000)
+            | ((left << 10) & 0x00040000)
+            | ((left << 2) & 0x00020000)
+            | ((left >> 10) & 0x00010000)
+            | ((right >> 13) & 0x00002000)
+            | ((right >> 4) & 0x00001000)
+            | ((right << 6) & 0x00000800)
+            | ((right >> 1) & 0x00000400)
+            | ((right >> 14) & 0x00000200)
+            | (right & 0x00000100)
+            | ((right >> 5) & 0x00000020)
+            | ((right >> 10) & 0x00000010)
+            | ((right >> 3) & 0x00000008)
+            | ((right >> 18) & 0x00000004)
+            | ((right >> 26) & 0x00000002)
+            | ((right >> 24) & 0x00000001);
+
+        *subkey++ = ((left << 15) & 0x20000000)
+            | ((left << 17) & 0x10000000)
+            | ((left << 10) & 0x08000000)
+            | ((left << 22) & 0x04000000)
+            | ((left >> 2) & 0x02000000)
+            | ((left << 1) & 0x01000000)
+            | ((left << 16) & 0x00200000)
+            | ((left << 11) & 0x00100000)
+            | ((left << 3) & 0x00080000)
+            | ((left >> 6) & 0x00040000)
+            | ((left << 15) & 0x00020000)
+            | ((left >> 4) & 0x00010000)
+            | ((right >> 2) & 0x00002000)
+            | ((right << 8) & 0x00001000)
+            | ((right >> 14) & 0x00000808)
+            | ((right >> 9) & 0x00000400)
+            | ((right) & 0x00000200)
+            | ((right << 7) & 0x00000100)
+            | ((right >> 7) & 0x00000020)
+            | ((right >> 3) & 0x00000011)
+            | ((right << 2) & 0x00000004)
+            | ((right >> 21) & 0x00000002);
+    }
+}
+
+static void algo_DES_Setkey(_DES_Context *ctx, const u1 * key)
+{
+    u1 i;
+
+    algo_DES_KeySchedule(key, ctx->encrypt_subkeys);
+
+    for(i = 0; i < 32; i += 2) {
+        ctx->decrypt_subkeys[i]	= ctx->encrypt_subkeys[30-i];
+        ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
+    }
+}
+
+static void algo_DES_Set2keys(_3DES_Context *ctx, const u1 * key1, const u1 * key2)
+{
+    u1 i;
+
+    algo_DES_KeySchedule(key1, ctx->encrypt_subkeys);
+    algo_DES_KeySchedule(key2, &(ctx->decrypt_subkeys[32]));
+
+    for(i = 0; i < 32; i += 2) {
+        ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i];
+        ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
+
+        ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
+        ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
+
+        ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i];
+        ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1];
+
+        ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i];
+        ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1];
+    }
+}
+
+static void algo_DES_Set3keys(_3DES_Context *ctx, const u1 * key1, const u1 * key2, const u1 * key3)
+{
+    u1 i;
+
+    algo_DES_KeySchedule(key1, ctx->encrypt_subkeys);
+    algo_DES_KeySchedule(key2, &(ctx->decrypt_subkeys[32]));
+    algo_DES_KeySchedule(key3, &(ctx->encrypt_subkeys[64]));
+
+    for(i = 0; i < 32; i += 2) {
+        ctx->decrypt_subkeys[i]	 = ctx->encrypt_subkeys[94-i];
+        ctx->decrypt_subkeys[i+1]  = ctx->encrypt_subkeys[95-i];
+        ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
+        ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
+        ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i];
+        ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i];
+    }
+}
+
+void algo_DES_DESProcess(u1* key, u1* from, u1* to, u1 mode)
+{
+    _DES_Context ctx;
+    u4 left, right, work;
+    u4 *keys;
+
+    algo_DES_Setkey(&ctx, key);
+
+    keys = (mode == TRUE) ? ctx.encrypt_subkeys : ctx.decrypt_subkeys;
+
+    READ_64BIT_DATA(from, left, right)
+    INITIAL_PERMUTATION(left, work, right)
+
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+    FINAL_PERMUTATION(right, work, left)
+    WRITE_64BIT_DATA(to, right, left)
+}
+
+void algo_DES_3DESProcess(u1 keyLength, u1* key, u1 * from, u1 * to, u1 mode)
+{
+    _3DES_Context ctx;
+    u4 left, right, work;
+    u4 *keys;
+
+    if (keyLength == 0x10) {
+        algo_DES_Set2keys(&ctx, &key[0], &key[8]);
+    } else {
+        algo_DES_Set3keys(&ctx, &key[0], &key[8], &key[16]);
+    }
+
+    keys = (mode == TRUE) ? ctx.encrypt_subkeys : ctx.decrypt_subkeys;
+
+    READ_64BIT_DATA(from, left, right)
+    INITIAL_PERMUTATION(left, work, right)
+
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+    FINAL_PERMUTATION(right, work, left)
+    WRITE_64BIT_DATA(to, right, left)
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_des.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,28 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_des_h
+#define _include_algo_des_h
+
+extern void algo_DES_DESProcess(u1* key, u1* input, u1* output, u1 mode);
+extern void algo_DES_3DESProcess(u1 keyLength, u1* key, u1* input, u1* output, u1 mode);
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,225 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_md5.h"
+
+const u1 md5_padding[64] = {
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define md5_S(x,n)              ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define md5_P(a,b,c,d,k,s,t)    {a += F(b,c,d) + data[k] + t; a = md5_S(a,s) + b;}
+
+void algo_md5_starts(algo_md5_context* ctx)
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->digest[0] = 0x67452301;
+    ctx->digest[1] = 0xEFCDAB89;
+    ctx->digest[2] = 0x98BADCFE;
+    ctx->digest[3] = 0x10325476;
+}
+
+
+static void algo_md5_compress(algo_md5_context *ctx, u4* data)
+{
+    u4 A, B, C, D;
+
+    // big endian processing
+    if (IS_BIG_ENDIAN)
+    {
+        u1 i;
+        for (i = 0; i < (MD5_BLOCK_LENGTH / sizeof(u4)); i++) {
+            data[i] = swapbytes_u4(data[i]);
+        }
+    }
+
+    A = ctx->digest[0];
+    B = ctx->digest[1];
+    C = ctx->digest[2];
+    D = ctx->digest[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+    md5_P(A, B, C, D,  0,  7, 0xD76AA478);
+    md5_P(D, A, B, C,  1, 12, 0xE8C7B756);
+    md5_P(C, D, A, B,  2, 17, 0x242070DB);
+    md5_P(B, C, D, A,  3, 22, 0xC1BDCEEE);
+    md5_P(A, B, C, D,  4,  7, 0xF57C0FAF);
+    md5_P(D, A, B, C,  5, 12, 0x4787C62A);
+    md5_P(C, D, A, B,  6, 17, 0xA8304613);
+    md5_P(B, C, D, A,  7, 22, 0xFD469501);
+    md5_P(A, B, C, D,  8,  7, 0x698098D8);
+    md5_P(D, A, B, C,  9, 12, 0x8B44F7AF);
+    md5_P(C, D, A, B, 10, 17, 0xFFFF5BB1);
+    md5_P(B, C, D, A, 11, 22, 0x895CD7BE);
+    md5_P(A, B, C, D, 12,  7, 0x6B901122);
+    md5_P(D, A, B, C, 13, 12, 0xFD987193);
+    md5_P(C, D, A, B, 14, 17, 0xA679438E);
+    md5_P(B, C, D, A, 15, 22, 0x49B40821);
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+    md5_P(A, B, C, D,  1,  5, 0xF61E2562);
+    md5_P(D, A, B, C,  6,  9, 0xC040B340);
+    md5_P(C, D, A, B, 11, 14, 0x265E5A51);
+    md5_P(B, C, D, A,  0, 20, 0xE9B6C7AA);
+    md5_P(A, B, C, D,  5,  5, 0xD62F105D);
+    md5_P(D, A, B, C, 10,  9, 0x02441453);
+    md5_P(C, D, A, B, 15, 14, 0xD8A1E681);
+    md5_P(B, C, D, A,  4, 20, 0xE7D3FBC8);
+    md5_P(A, B, C, D,  9,  5, 0x21E1CDE6);
+    md5_P(D, A, B, C, 14,  9, 0xC33707D6);
+    md5_P(C, D, A, B,  3, 14, 0xF4D50D87);
+    md5_P(B, C, D, A,  8, 20, 0x455A14ED);
+    md5_P(A, B, C, D, 13,  5, 0xA9E3E905);
+    md5_P(D, A, B, C,  2,  9, 0xFCEFA3F8);
+    md5_P(C, D, A, B,  7, 14, 0x676F02D9);
+    md5_P(B, C, D, A, 12, 20, 0x8D2A4C8A);
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+    md5_P(A, B, C, D,  5,  4, 0xFFFA3942);
+    md5_P(D, A, B, C,  8, 11, 0x8771F681);
+    md5_P(C, D, A, B, 11, 16, 0x6D9D6122);
+    md5_P(B, C, D, A, 14, 23, 0xFDE5380C);
+    md5_P(A, B, C, D,  1,  4, 0xA4BEEA44);
+    md5_P(D, A, B, C,  4, 11, 0x4BDECFA9);
+    md5_P(C, D, A, B,  7, 16, 0xF6BB4B60);
+    md5_P(B, C, D, A, 10, 23, 0xBEBFBC70);
+    md5_P(A, B, C, D, 13,  4, 0x289B7EC6);
+    md5_P(D, A, B, C,  0, 11, 0xEAA127FA);
+    md5_P(C, D, A, B,  3, 16, 0xD4EF3085);
+    md5_P(B, C, D, A,  6, 23, 0x04881D05);
+    md5_P(A, B, C, D,  9,  4, 0xD9D4D039);
+    md5_P(D, A, B, C, 12, 11, 0xE6DB99E5);
+    md5_P(C, D, A, B, 15, 16, 0x1FA27CF8);
+    md5_P(B, C, D, A,  2, 23, 0xC4AC5665);
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+    md5_P(A, B, C, D,  0,  6, 0xF4292244);
+    md5_P(D, A, B, C,  7, 10, 0x432AFF97);
+    md5_P(C, D, A, B, 14, 15, 0xAB9423A7);
+    md5_P(B, C, D, A,  5, 21, 0xFC93A039);
+    md5_P(A, B, C, D, 12,  6, 0x655B59C3);
+    md5_P(D, A, B, C,  3, 10, 0x8F0CCC92);
+    md5_P(C, D, A, B, 10, 15, 0xFFEFF47D);
+    md5_P(B, C, D, A,  1, 21, 0x85845DD1);
+    md5_P(A, B, C, D,  8,  6, 0x6FA87E4F);
+    md5_P(D, A, B, C, 15, 10, 0xFE2CE6E0);
+    md5_P(C, D, A, B,  6, 15, 0xA3014314);
+    md5_P(B, C, D, A, 13, 21, 0x4E0811A1);
+    md5_P(A, B, C, D,  4,  6, 0xF7537E82);
+    md5_P(D, A, B, C, 11, 10, 0xBD3AF235);
+    md5_P(C, D, A, B,  2, 15, 0x2AD7D2BB);
+    md5_P(B, C, D, A,  9, 21, 0xEB86D391);
+
+#undef F
+
+    ctx->digest[0] += A;
+    ctx->digest[1] += B;
+    ctx->digest[2] += C;
+    ctx->digest[3] += D;
+}
+
+void algo_md5_update(algo_md5_context* ctx, u1* input, u4 length)
+{
+    u4 left, fill;
+
+    if (!length) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = MD5_BLOCK_LENGTH - left;
+
+    ctx->total[0] += length;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if(ctx->total[0] < length) {
+        ctx->total[1]++;
+    }
+
+    if (left && (length >= fill)) {
+        memcpy(ctx->input + left,input,fill);
+        algo_md5_compress(ctx, (u4*)ctx->input);
+        length -= fill;
+        input  += fill;
+        left = 0;
+    }
+
+    while(length >= MD5_BLOCK_LENGTH) {
+        algo_md5_compress(ctx, (u4*)input);
+        length -= MD5_BLOCK_LENGTH;
+        input  += MD5_BLOCK_LENGTH;
+    }
+
+    if (length) {
+        memcpy(ctx->input + left,input,length);
+    }
+}
+
+void algo_md5_finish(algo_md5_context *ctx)
+{
+    u4 last, padn;
+    u4 msglen[2];
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        msglen[0] = (ctx->total[0] << 3);
+        msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+    }
+    // big endian processing
+    else
+    {
+        msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+        msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+    }
+
+    last = ctx->total[0] & 0x3F;
+    padn = (last < (MD5_BLOCK_LENGTH - sizeof(msglen))) ? ((MD5_BLOCK_LENGTH - sizeof(msglen)) - last) : (((2 * MD5_BLOCK_LENGTH) - sizeof(msglen)) - last);
+
+    algo_md5_update(ctx, (u1*)md5_padding, padn);
+    algo_md5_update(ctx, (u1*)msglen, sizeof(msglen));
+
+	// big endian processing
+    if (IS_BIG_ENDIAN)
+    {
+        u1 i;
+        for (i = 0; i < (MD5_HASH_LENGTH / sizeof(u4)); i++) {
+            ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+        }
+    }
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_md5.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,38 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_md5_h
+#define _include_algo_md5_h
+
+typedef struct algo_md5_context{
+    u4 total[2];
+    u4* digest;
+    u1* input;
+} algo_md5_context;
+
+#define MD5_HASH_LENGTH 16
+#define MD5_BLOCK_LENGTH 64
+
+extern void algo_md5_starts(algo_md5_context* ctx);
+extern void algo_md5_update(algo_md5_context* ctx, u1* input, u4 length);
+extern void algo_md5_finish(algo_md5_context* ctx);
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,254 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_sha1.h"
+
+const u1 sha1_padding[64] = {
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define sha1_S(x,n)             ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define sha1_R(t)               (temp = data[(t - 3) & 0x0F] ^ data[(t - 8) & 0x0F] ^ data[(t - 14) & 0x0F] ^ data[t & 0x0F], (data[t & 0x0F] = sha1_S(temp,1)))
+
+#define sha1_P(a,b,c,d,e,x)     {e += sha1_S(a,5) + F(b,c,d) + K + x; b = sha1_S(b,30);}
+
+void algo_sha1_starts(algo_sha1_context *ctx)
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->digest[0] = 0x67452301;
+    ctx->digest[1] = 0xEFCDAB89;
+    ctx->digest[2] = 0x98BADCFE;
+    ctx->digest[3] = 0x10325476;
+    ctx->digest[4] = 0xC3D2E1F0;
+}
+
+static void algo_sha1_compress(algo_sha1_context *ctx, u4* data)
+{
+    u4 temp, A, B, C, D, E;
+    u1 i;
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        for (i = 0; i < (SHA1_BLOCK_LENGTH / sizeof(u4)); i++) {
+            data[i] = swapbytes_u4(data[i]);
+        }
+    }
+
+    A = ctx->digest[0];
+    B = ctx->digest[1];
+    C = ctx->digest[2];
+    D = ctx->digest[3];
+    E = ctx->digest[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+    sha1_P(A, B, C, D, E, data[0]);
+    sha1_P(E, A, B, C, D, data[1]);
+    sha1_P(D, E, A, B, C, data[2]);
+    sha1_P(C, D, E, A, B, data[3]);
+    sha1_P(B, C, D, E, A, data[4]);
+    sha1_P(A, B, C, D, E, data[5]);
+    sha1_P(E, A, B, C, D, data[6]);
+    sha1_P(D, E, A, B, C, data[7]);
+    sha1_P(C, D, E, A, B, data[8]);
+    sha1_P(B, C, D, E, A, data[9]);
+    sha1_P(A, B, C, D, E, data[10]);
+    sha1_P(E, A, B, C, D, data[11]);
+    sha1_P(D, E, A, B, C, data[12]);
+    sha1_P(C, D, E, A, B, data[13]);
+    sha1_P(B, C, D, E, A, data[14]);
+    sha1_P(A, B, C, D, E, data[15]);
+    sha1_P(E, A, B, C, D, sha1_R(16));
+    sha1_P(D, E, A, B, C, sha1_R(17));
+    sha1_P(C, D, E, A, B, sha1_R(18));
+    sha1_P(B, C, D, E, A, sha1_R(19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+    sha1_P(A, B, C, D, E, sha1_R(20));
+    sha1_P(E, A, B, C, D, sha1_R(21));
+    sha1_P(D, E, A, B, C, sha1_R(22));
+    sha1_P(C, D, E, A, B, sha1_R(23));
+    sha1_P(B, C, D, E, A, sha1_R(24));
+    sha1_P(A, B, C, D, E, sha1_R(25));
+    sha1_P(E, A, B, C, D, sha1_R(26));
+    sha1_P(D, E, A, B, C, sha1_R(27));
+    sha1_P(C, D, E, A, B, sha1_R(28));
+    sha1_P(B, C, D, E, A, sha1_R(29));
+    sha1_P(A, B, C, D, E, sha1_R(30));
+    sha1_P(E, A, B, C, D, sha1_R(31));
+    sha1_P(D, E, A, B, C, sha1_R(32));
+    sha1_P(C, D, E, A, B, sha1_R(33));
+    sha1_P(B, C, D, E, A, sha1_R(34));
+    sha1_P(A, B, C, D, E, sha1_R(35));
+    sha1_P(E, A, B, C, D, sha1_R(36));
+    sha1_P(D, E, A, B, C, sha1_R(37));
+    sha1_P(C, D, E, A, B, sha1_R(38));
+    sha1_P(B, C, D, E, A, sha1_R(39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+    sha1_P(A, B, C, D, E, sha1_R(40));
+    sha1_P(E, A, B, C, D, sha1_R(41));
+    sha1_P(D, E, A, B, C, sha1_R(42));
+    sha1_P(C, D, E, A, B, sha1_R(43));
+    sha1_P(B, C, D, E, A, sha1_R(44));
+    sha1_P(A, B, C, D, E, sha1_R(45));
+    sha1_P(E, A, B, C, D, sha1_R(46));
+    sha1_P(D, E, A, B, C, sha1_R(47));
+    sha1_P(C, D, E, A, B, sha1_R(48));
+    sha1_P(B, C, D, E, A, sha1_R(49));
+    sha1_P(A, B, C, D, E, sha1_R(50));
+    sha1_P(E, A, B, C, D, sha1_R(51));
+    sha1_P(D, E, A, B, C, sha1_R(52));
+    sha1_P(C, D, E, A, B, sha1_R(53));
+    sha1_P(B, C, D, E, A, sha1_R(54));
+    sha1_P(A, B, C, D, E, sha1_R(55));
+    sha1_P(E, A, B, C, D, sha1_R(56));
+    sha1_P(D, E, A, B, C, sha1_R(57));
+    sha1_P(C, D, E, A, B, sha1_R(58));
+    sha1_P(B, C, D, E, A, sha1_R(59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+    sha1_P(A, B, C, D, E, sha1_R(60));
+    sha1_P(E, A, B, C, D, sha1_R(61));
+    sha1_P(D, E, A, B, C, sha1_R(62));
+    sha1_P(C, D, E, A, B, sha1_R(63));
+    sha1_P(B, C, D, E, A, sha1_R(64));
+    sha1_P(A, B, C, D, E, sha1_R(65));
+    sha1_P(E, A, B, C, D, sha1_R(66));
+    sha1_P(D, E, A, B, C, sha1_R(67));
+    sha1_P(C, D, E, A, B, sha1_R(68));
+    sha1_P(B, C, D, E, A, sha1_R(69));
+    sha1_P(A, B, C, D, E, sha1_R(70));
+    sha1_P(E, A, B, C, D, sha1_R(71));
+    sha1_P(D, E, A, B, C, sha1_R(72));
+    sha1_P(C, D, E, A, B, sha1_R(73));
+    sha1_P(B, C, D, E, A, sha1_R(74));
+    sha1_P(A, B, C, D, E, sha1_R(75));
+    sha1_P(E, A, B, C, D, sha1_R(76));
+    sha1_P(D, E, A, B, C, sha1_R(77));
+    sha1_P(C, D, E, A, B, sha1_R(78));
+    sha1_P(B, C, D, E, A, sha1_R(79));
+
+#undef K
+#undef F
+
+    ctx->digest[0] += A;
+    ctx->digest[1] += B;
+    ctx->digest[2] += C;
+    ctx->digest[3] += D;
+    ctx->digest[4] += E;
+}
+
+void algo_sha1_update(algo_sha1_context* ctx, u1* input, u4 length)
+{
+    u4 left, fill;
+
+    if (!length) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = SHA1_BLOCK_LENGTH - left;
+
+    ctx->total[0] += length;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if(ctx->total[0] < length) {
+        ctx->total[1]++;
+    }
+
+    if (left && (length >= fill)) {
+        //CopyVolatile(input, ctx->input + left, fill);
+        memcpy(ctx->input + left,input,fill);
+        algo_sha1_compress(ctx, (u4*)ctx->input);
+        length -= fill;
+        input  += fill;
+        left = 0;
+    }
+
+    while(length >= SHA1_BLOCK_LENGTH) {
+        algo_sha1_compress(ctx, (u4*)input);
+        length -= SHA1_BLOCK_LENGTH;
+        input  += SHA1_BLOCK_LENGTH;
+    }
+
+    if (length) {
+        //CopyVolatile(input, ctx->input + left, length);
+        memcpy(ctx->input + left,input,length);
+    }
+}
+
+void algo_sha1_finish(algo_sha1_context *ctx)
+{
+    u4 last, padn;
+    u4 msglen[2];
+    u1 i;
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+        msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+    }
+    else
+    {
+        msglen[0] = (ctx->total[0] << 3);
+        msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+    }
+
+    last = ctx->total[0] & 0x3F;
+    padn = (last < (SHA1_BLOCK_LENGTH - sizeof(msglen))) ? ((SHA1_BLOCK_LENGTH - sizeof(msglen)) - last) : (((2 * SHA1_BLOCK_LENGTH) - sizeof(msglen)) - last);
+
+    algo_sha1_update(ctx, (u1*)sha1_padding, padn);
+    algo_sha1_update(ctx, (u1*)msglen, 8);
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        for (i = 0; i < (SHA1_HASH_LENGTH / sizeof(u4)); i++) {
+            ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+        }
+    }
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha1.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_sha1_h
+#define _include_algo_sha1_h
+
+typedef struct algo_sha1_context
+{
+    u4 total[2];
+    u4* digest;
+    u1* input;
+} algo_sha1_context;
+
+#define SHA1_HASH_LENGTH  20
+#define SHA1_BLOCK_LENGTH 64
+
+extern void algo_sha1_starts(algo_sha1_context* ctx);
+extern void algo_sha1_update(algo_sha1_context* ctx, u1* input, u4 length);
+extern void algo_sha1_finish(algo_sha1_context* ctx);
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,370 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_sha256.h"
+
+const u1 sha256_padding[64] =
+{
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define SHR(x,n)  ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define SHA256_S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
+#define SHA256_S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
+#define SHA256_S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^  ROTR(x,22))
+#define SHA256_S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^  ROTR(x,25))
+
+#define SHA256_F0(x,y,z) ((x & y) | (z & (x | y)))
+#define SHA256_F1(x,y,z) (z ^ (x & (y ^ z)))
+
+void algo_sha256_starts(algo_sha256_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->digest[0] = 0x6A09E667;
+    ctx->digest[1] = 0xBB67AE85;
+    ctx->digest[2] = 0x3C6EF372;
+    ctx->digest[3] = 0xA54FF53A;
+    ctx->digest[4] = 0x510E527F;
+    ctx->digest[5] = 0x9B05688C;
+    ctx->digest[6] = 0x1F83D9AB;
+    ctx->digest[7] = 0x5BE0CD19;
+}
+
+#ifdef _SHA256_SIZE_OPTIMIZED_VERSION
+
+    static algo_sha256_context* algo_sha256_tmpCtx;
+
+    static void sha256_P(u4 a, u4 b, u4 c, u4* d, u4 e, u4 f, u4 g, u4* h, u1 i, u4 K)
+    {
+        u4 temp1;
+        u4 temp2;
+
+	    if (i > 15) {
+    	    algo_sha256_tmpCtx->processingBuffer[i] = SHA256_S1(algo_sha256_tmpCtx->processingBuffer[i -  2]) + algo_sha256_tmpCtx->processingBuffer[i -  7] + SHA256_S0(algo_sha256_tmpCtx->processingBuffer[i - 15]) + algo_sha256_tmpCtx->processingBuffer[i - 16];
+	    }
+
+	    temp1 = *h + SHA256_S3(e) + SHA256_F1(e,f,g) + K + algo_sha256_tmpCtx->processingBuffer[i];
+	    temp2 = SHA256_S2(a) + SHA256_F0(a,b,c);
+
+        *d += temp1;
+	    *h = temp1 + temp2;
+    }
+
+    static void algo_sha256_compress(algo_sha256_context *ctx, u4* input)
+    {
+
+        u4 A, B, C, D, E, F, G, H;
+        u1 i;
+
+        // little endian processing
+        if (IS_LITTLE_ENDIAN)
+        {
+            for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+                ctx->processingBuffer[i] = swapbytes_u4(input[i]);
+            }
+        }
+        A = ctx->digest[0];
+        B = ctx->digest[1];
+        C = ctx->digest[2];
+        D = ctx->digest[3];
+        E = ctx->digest[4];
+        F = ctx->digest[5];
+        G = ctx->digest[6];
+        H = ctx->digest[7];
+
+        algo_sha256_tmpCtx = ctx;
+
+        sha256_P(A, B, C, &D, E, F, G, &H, 0, 0x428A2F98);
+        sha256_P(H, A, B, &C, D, E, F, &G, 1, 0x71374491);
+        sha256_P(G, H, A, &B, C, D, E, &F, 2, 0xB5C0FBCF);
+        sha256_P(F, G, H, &A, B, C, D, &E, 3, 0xE9B5DBA5);
+        sha256_P(E, F, G, &H, A, B, C, &D, 4, 0x3956C25B);
+        sha256_P(D, E, F, &G, H, A, B, &C, 5, 0x59F111F1);
+        sha256_P(C, D, E, &F, G, H, A, &B, 6, 0x923F82A4);
+        sha256_P(B, C, D, &E, F, G, H, &A, 7, 0xAB1C5ED5);
+        sha256_P(A, B, C, &D, E, F, G, &H, 8, 0xD807AA98);
+        sha256_P(H, A, B, &C, D, E, F, &G, 9, 0x12835B01);
+        sha256_P(G, H, A, &B, C, D, E, &F, 10, 0x243185BE);
+        sha256_P(F, G, H, &A, B, C, D, &E, 11, 0x550C7DC3);
+        sha256_P(E, F, G, &H, A, B, C, &D, 12, 0x72BE5D74);
+        sha256_P(D, E, F, &G, H, A, B, &C, 13, 0x80DEB1FE);
+        sha256_P(C, D, E, &F, G, H, A, &B, 14, 0x9BDC06A7);
+        sha256_P(B, C, D, &E, F, G, H, &A, 15, 0xC19BF174);
+        sha256_P(A, B, C, &D, E, F, G, &H, 16, 0xE49B69C1);
+        sha256_P(H, A, B, &C, D, E, F, &G, 17, 0xEFBE4786);
+        sha256_P(G, H, A, &B, C, D, E, &F, 18, 0x0FC19DC6);
+        sha256_P(F, G, H, &A, B, C, D, &E, 19, 0x240CA1CC);
+        sha256_P(E, F, G, &H, A, B, C, &D, 20, 0x2DE92C6F);
+        sha256_P(D, E, F, &G, H, A, B, &C, 21, 0x4A7484AA);
+        sha256_P(C, D, E, &F, G, H, A, &B, 22, 0x5CB0A9DC);
+        sha256_P(B, C, D, &E, F, G, H, &A, 23, 0x76F988DA);
+        sha256_P(A, B, C, &D, E, F, G, &H, 24, 0x983E5152);
+        sha256_P(H, A, B, &C, D, E, F, &G, 25, 0xA831C66D);
+        sha256_P(G, H, A, &B, C, D, E, &F, 26, 0xB00327C8);
+        sha256_P(F, G, H, &A, B, C, D, &E, 27, 0xBF597FC7);
+        sha256_P(E, F, G, &H, A, B, C, &D, 28, 0xC6E00BF3);
+        sha256_P(D, E, F, &G, H, A, B, &C, 29, 0xD5A79147);
+        sha256_P(C, D, E, &F, G, H, A, &B, 30, 0x06CA6351);
+        sha256_P(B, C, D, &E, F, G, H, &A, 31, 0x14292967);
+        sha256_P(A, B, C, &D, E, F, G, &H, 32, 0x27B70A85);
+        sha256_P(H, A, B, &C, D, E, F, &G, 33, 0x2E1B2138);
+        sha256_P(G, H, A, &B, C, D, E, &F, 34, 0x4D2C6DFC);
+        sha256_P(F, G, H, &A, B, C, D, &E, 35, 0x53380D13);
+        sha256_P(E, F, G, &H, A, B, C, &D, 36, 0x650A7354);
+        sha256_P(D, E, F, &G, H, A, B, &C, 37, 0x766A0ABB);
+        sha256_P(C, D, E, &F, G, H, A, &B, 38, 0x81C2C92E);
+        sha256_P(B, C, D, &E, F, G, H, &A, 39, 0x92722C85);
+        sha256_P(A, B, C, &D, E, F, G, &H, 40, 0xA2BFE8A1);
+        sha256_P(H, A, B, &C, D, E, F, &G, 41, 0xA81A664B);
+        sha256_P(G, H, A, &B, C, D, E, &F, 42, 0xC24B8B70);
+        sha256_P(F, G, H, &A, B, C, D, &E, 43, 0xC76C51A3);
+        sha256_P(E, F, G, &H, A, B, C, &D, 44, 0xD192E819);
+        sha256_P(D, E, F, &G, H, A, B, &C, 45, 0xD6990624);
+        sha256_P(C, D, E, &F, G, H, A, &B, 46, 0xF40E3585);
+        sha256_P(B, C, D, &E, F, G, H, &A, 47, 0x106AA070);
+        sha256_P(A, B, C, &D, E, F, G, &H, 48, 0x19A4C116);
+        sha256_P(H, A, B, &C, D, E, F, &G, 49, 0x1E376C08);
+        sha256_P(G, H, A, &B, C, D, E, &F, 50, 0x2748774C);
+        sha256_P(F, G, H, &A, B, C, D, &E, 51, 0x34B0BCB5);
+        sha256_P(E, F, G, &H, A, B, C, &D, 52, 0x391C0CB3);
+        sha256_P(D, E, F, &G, H, A, B, &C, 53, 0x4ED8AA4A);
+        sha256_P(C, D, E, &F, G, H, A, &B, 54, 0x5B9CCA4F);
+        sha256_P(B, C, D, &E, F, G, H, &A, 55, 0x682E6FF3);
+        sha256_P(A, B, C, &D, E, F, G, &H, 56, 0x748F82EE);
+        sha256_P(H, A, B, &C, D, E, F, &G, 57, 0x78A5636F);
+        sha256_P(G, H, A, &B, C, D, E, &F, 58, 0x84C87814);
+        sha256_P(F, G, H, &A, B, C, D, &E, 59, 0x8CC70208);
+        sha256_P(E, F, G, &H, A, B, C, &D, 60, 0x90BEFFFA);
+        sha256_P(D, E, F, &G, H, A, B, &C, 61, 0xA4506CEB);
+        sha256_P(C, D, E, &F, G, H, A, &B, 62, 0xBEF9A3F7);
+        sha256_P(B, C, D, &E, F, G, H, &A, 63, 0xC67178F2);
+
+        ctx->digest[0] += A;
+        ctx->digest[1] += B;
+        ctx->digest[2] += C;
+        ctx->digest[3] += D;
+        ctx->digest[4] += E;
+        ctx->digest[5] += F;
+        ctx->digest[6] += G;
+        ctx->digest[7] += H;
+    }
+
+#else
+
+    #define SHA256_R(t)                                       \
+    (                                                         \
+        ctx->processingBuffer[t] = SHA256_S1(ctx->processingBuffer[t -  2]) + ctx->processingBuffer[t -  7] +    \
+                SHA256_S0(ctx->processingBuffer[t - 15]) + ctx->processingBuffer[t - 16]      \
+    )
+
+    #define SHA256_P(a,b,c,d,e,f,g,h,x,K)                         \
+    {                                                             \
+        temp1 = h + SHA256_S3(e) + SHA256_F1(e,f,g) + K + x;      \
+        temp2 = SHA256_S2(a) + SHA256_F0(a,b,c);                  \
+        d += temp1; h = temp1 + temp2;                            \
+    }
+
+    static void algo_sha256_compress(algo_sha256_context *ctx, u4* input)
+    {
+        u4 temp1, temp2;
+        u4 A, B, C, D, E, F, G, H;
+        u1 i;
+
+        // little endian processing
+        if (IS_LITTLE_ENDIAN)
+        {
+            for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+                ctx->processingBuffer[i] = swapbytes_u4(input[i]);
+            }
+        }
+        else
+        {
+            for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+                ctx->processingBuffer[i] = input[i];
+            }
+        }
+
+        A = ctx->digest[0];
+        B = ctx->digest[1];
+        C = ctx->digest[2];
+        D = ctx->digest[3];
+        E = ctx->digest[4];
+        F = ctx->digest[5];
+        G = ctx->digest[6];
+        H = ctx->digest[7];
+
+        SHA256_P( A, B, C, D, E, F, G, H, ctx->processingBuffer[ 0], 0x428A2F98 );
+        SHA256_P( H, A, B, C, D, E, F, G, ctx->processingBuffer[ 1], 0x71374491 );
+        SHA256_P( G, H, A, B, C, D, E, F, ctx->processingBuffer[ 2], 0xB5C0FBCF );
+        SHA256_P( F, G, H, A, B, C, D, E, ctx->processingBuffer[ 3], 0xE9B5DBA5 );
+        SHA256_P( E, F, G, H, A, B, C, D, ctx->processingBuffer[ 4], 0x3956C25B );
+        SHA256_P( D, E, F, G, H, A, B, C, ctx->processingBuffer[ 5], 0x59F111F1 );
+        SHA256_P( C, D, E, F, G, H, A, B, ctx->processingBuffer[ 6], 0x923F82A4 );
+        SHA256_P( B, C, D, E, F, G, H, A, ctx->processingBuffer[ 7], 0xAB1C5ED5 );
+        SHA256_P( A, B, C, D, E, F, G, H, ctx->processingBuffer[ 8], 0xD807AA98 );
+        SHA256_P( H, A, B, C, D, E, F, G, ctx->processingBuffer[ 9], 0x12835B01 );
+        SHA256_P( G, H, A, B, C, D, E, F, ctx->processingBuffer[10], 0x243185BE );
+        SHA256_P( F, G, H, A, B, C, D, E, ctx->processingBuffer[11], 0x550C7DC3 );
+        SHA256_P( E, F, G, H, A, B, C, D, ctx->processingBuffer[12], 0x72BE5D74 );
+        SHA256_P( D, E, F, G, H, A, B, C, ctx->processingBuffer[13], 0x80DEB1FE );
+        SHA256_P( C, D, E, F, G, H, A, B, ctx->processingBuffer[14], 0x9BDC06A7 );
+        SHA256_P( B, C, D, E, F, G, H, A, ctx->processingBuffer[15], 0xC19BF174 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(16), 0xE49B69C1 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(17), 0xEFBE4786 );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(18), 0x0FC19DC6 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(19), 0x240CA1CC );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(20), 0x2DE92C6F );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(21), 0x4A7484AA );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(22), 0x5CB0A9DC );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(23), 0x76F988DA );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(24), 0x983E5152 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(25), 0xA831C66D );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(26), 0xB00327C8 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(27), 0xBF597FC7 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(28), 0xC6E00BF3 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(29), 0xD5A79147 );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(30), 0x06CA6351 );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(31), 0x14292967 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(32), 0x27B70A85 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(33), 0x2E1B2138 );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(34), 0x4D2C6DFC );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(35), 0x53380D13 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(36), 0x650A7354 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(37), 0x766A0ABB );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(38), 0x81C2C92E );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(39), 0x92722C85 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(40), 0xA2BFE8A1 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(41), 0xA81A664B );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(42), 0xC24B8B70 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(43), 0xC76C51A3 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(44), 0xD192E819 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(45), 0xD6990624 );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(46), 0xF40E3585 );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(47), 0x106AA070 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(48), 0x19A4C116 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(49), 0x1E376C08 );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(50), 0x2748774C );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(51), 0x34B0BCB5 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(52), 0x391C0CB3 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(53), 0x4ED8AA4A );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(54), 0x5B9CCA4F );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(55), 0x682E6FF3 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(56), 0x748F82EE );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(57), 0x78A5636F );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(58), 0x84C87814 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(59), 0x8CC70208 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(60), 0x90BEFFFA );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(61), 0xA4506CEB );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(62), 0xBEF9A3F7 );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(63), 0xC67178F2 );
+
+        ctx->digest[0] += A;
+        ctx->digest[1] += B;
+        ctx->digest[2] += C;
+        ctx->digest[3] += D;
+        ctx->digest[4] += E;
+        ctx->digest[5] += F;
+        ctx->digest[6] += G;
+        ctx->digest[7] += H;
+    }
+
+#endif
+
+
+void algo_sha256_update(algo_sha256_context *ctx, u1 *input, u4 length )
+{
+    u4 left, fill;
+
+    if(!length ) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = SHA256_BLOCK_LENGTH - left;
+
+    ctx->total[0] += length;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < length )
+        ctx->total[1]++;
+
+    if( left && length >= fill )
+    {
+        memcpy(ctx->input + left,input,fill);
+
+        algo_sha256_compress( ctx,(u4*)ctx->input );
+        length -= fill;
+        input  += fill;
+        left = 0;
+    }
+
+    while( length >= SHA256_BLOCK_LENGTH )
+    {
+        algo_sha256_compress( ctx, (u4*)input );
+        length -= SHA256_BLOCK_LENGTH;
+        input  += SHA256_BLOCK_LENGTH;
+    }
+
+    if( length ){
+        memcpy(ctx->input + left,input,length);
+    }
+}
+
+void algo_sha256_finish(algo_sha256_context *ctx)
+{
+    u4 last, padn;
+    u4 msglen[2];
+    u1 i;
+
+    // little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+        msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+    }
+    else
+    {
+        msglen[0] = (ctx->total[0] << 3);
+        msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+    }
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    algo_sha256_update( ctx, (u1*)sha256_padding, padn );
+    algo_sha256_update( ctx, (u1*)msglen, 8 );
+
+    // little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        for (i = 0; i < (SHA256_HASH_LENGTH / sizeof(u4)); i++) {
+            ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+        }
+    }
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_sha256.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,40 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_sha256_h
+#define _include_algo_sha256_h
+
+#define SHA256_HASH_LENGTH  32
+#define SHA256_BLOCK_LENGTH 64
+
+typedef struct algo_sha256_context
+{
+    u4  total[2];
+    u4  processingBuffer[SHA256_BLOCK_LENGTH];
+    u4* digest;
+    u1* input;
+} algo_sha256_context;
+
+extern void algo_sha256_starts(algo_sha256_context* ctx);
+extern void algo_sha256_update(algo_sha256_context* ctx, u1* input, u4 length);
+extern void algo_sha256_finish(algo_sha256_context* ctx);
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,34 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+
+u4 swapbytes_u4(u4 val)
+{
+    u4 res;
+    res =  val << 24;
+    res |= (val << 8) & 0x00FF0000;
+    res |= (val >> 8) & 0x0000FF00;
+    res |= val >> 24;
+    return (res);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/algo_utils.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,27 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_utils_h
+#define _include_algo_utils_h
+
+extern u4 swapbytes_u4(u4 val);
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/application.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/application.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/application.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,744 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+#include "cardmoduleservice.h"
+
+#include <string>
+
+#include <assert.h>
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "session.h"
+#include "slot.h"
+#include "application.h"
+#include "log.h"
+
+#ifdef _XCL_
+#include <xcl_utils.h>
+#endif // _XCL_
+
+#ifdef __sun
+typedef LPSTR LPTSTR;
+#endif
+
+// Initialization of Static fields
+SCARDCONTEXT Application::_hContext = 0;
+
+Slot* Application::_slotCache[CONFIG_MAX_SLOT] = {
+   NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,
+   NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR
+};
+
+CK_ULONG Application::_numSlots = 0;
+
+#ifdef _XCL_
+xCL_DeviceHandle Application::_deviceHandle = 0; // asadali
+#endif // _XCL_
+
+
+/*
+*/
+#ifndef _XCL_
+CK_RV Application::InitApplication( )
+{
+   //Log::begin( "Application::InitApplication" );
+
+   // do the enumeration of slots
+   CK_ULONG hResult = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &Application::_hContext );
+
+   //Log::log( "Application::InitApplication - SCardEstablishContext <%#02x>", hResult );
+   //Log::log( "Application::InitApplication - Application::_hContext <%#02x>", Application::_hContext );
+
+   if( SCARD_S_SUCCESS != hResult )
+   {
+      return CKR_GENERAL_ERROR;
+   }
+
+#ifdef __APPLE__
+   /* Apple bug 5256035 */
+   {
+      SCARDHANDLE h;
+      DWORD p;
+      SCardConnect(Application::_hContext, "fake reader", SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &h, &p);
+   }
+#endif
+
+   //Log::end( "Application::InitApplication" );
+
+   return CKR_OK;
+}
+
+#else // _XCL_
+
+CK_RV Application::InitApplication( )
+{
+    //Log::begin( "Application::InitApplication" );
+    u4 deviceID;
+    u4 rv;
+    xCL_DevicePtr deviceList;
+    xCL_DevicePtr device;
+    u4 numberOfDevices;
+    u4 i;
+
+    PRINT_MSG("IN Application::Init");
+
+    rv = xCL_InterfaceInit();
+
+    rv = xCL_DiscoverDevices(&deviceList, &numberOfDevices);
+    if (rv == 0 && numberOfDevices != 0)
+    {
+        // Pick the first device, with ID=0
+        device = deviceList + 0;
+        deviceID = device->deviceID ;
+        PRINT_DATA(NULL, 0, (char*)device->uniqueName);
+
+        // Create device handle
+        rv = xCL_CreateHandleFromDeviceID(deviceID, &Application::_deviceHandle);
+        if (rv == 0)
+        {
+            PRINT_MSG("IN Application::Init , device handle created");
+        }
+
+        // Free memory for all devices
+        for (i=0; i<numberOfDevices; i++)
+        {
+            rv = xCL_FreeDeviceMemory(deviceList + i);
+        }
+    }
+    return CKR_OK;
+}
+
+#endif // _XCL_
+
+
+/*
+*/
+
+#ifndef _XCL_
+
+CK_RV Application::Enumerate( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+   //Log::begin( "Application::Enumerate" );
+
+   CK_ULONG   slotNb              = 0;
+   LPTSTR     pReader             = NULL;
+   CK_LONG    hResult             = 0;
+   CK_SLOT_ID sid                 = 0;
+
+   if( NULL_PTR == pulCount )
+   {
+      //Log::error( "Application::Enumerate", "CKR_ARGUMENTS_BAD" );
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   // Get the supported readers from the current cache
+   std::string currentCache[ CONFIG_MAX_SLOT ];
+   for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      currentCache[ i ] = "";
+      if( NULL_PTR != Application::_slotCache[ i ] )
+      {
+         currentCache[ i ] = *(Application::_slotCache[ i ]->_readerName);
+         //Log::log( "Application::Enumerate - currentCache[ %d ] <%s>", i, currentCache[ i ].c_str( ) );
+      }
+   }
+
+   // Get the readers from the PCSC layer
+   DWORD readerListCharLength = 0;
+   hResult = SCardListReaders( Application::_hContext, NULL, NULL, &readerListCharLength );
+   //Log::log( "Application::Enumerate - readerListCharLength <%#02x>", readerListCharLength );
+   //Log::log( "Application::Enumerate - SCardListReaders <%#02x>", hResult );
+   if( SCARD_S_SUCCESS != hResult )
+   {
+      //Log::error( "Application::Enumerate", "CKR_GENERAL_ERROR" );
+      return CKR_GENERAL_ERROR;
+   }
+
+   LPTSTR pReaderList = (lpCharPtr)malloc( sizeof(char) * readerListCharLength );
+   if( NULL == pReaderList )
+   {
+      //Log::error( "Application::Enumerate", "CKR_HOST_MEMORY" );
+      return CKR_HOST_MEMORY;
+   }
+   memset( pReaderList, 0, sizeof(char) * readerListCharLength );
+
+   hResult = SCardListReaders( Application::_hContext, NULL, pReaderList, &readerListCharLength);
+   //Log::log( "Application::Enumerate - SCardListReaders 2 <%#02x>", hResult );
+   if( SCARD_S_SUCCESS != hResult )
+   {
+      free( pReaderList );
+      //Log::error( "Application::Enumerate", "CKR_GENERAL_ERROR" );
+      return CKR_GENERAL_ERROR;
+   }
+
+   // Construct the PCSC reader list
+   std::string currentPcscList[ CONFIG_MAX_SLOT ];
+   for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      currentPcscList[ i ] = "";
+   }
+   pReader = pReaderList; //readers;
+   int i = 0;
+   while( pReader && ( '\0' != *pReader ) )
+   {
+      currentPcscList[ i ] = pReader;
+      //Log::log( "Application::Enumerate - PCSC List[ %d ] <%s>", i, currentPcscList[ i ].c_str( ) );
+      i++;
+      if( i > CONFIG_MAX_SLOT )
+      {
+         /*
+         free( pReaderList );
+         //Log::error( "Application::Enumerate", "CKR_HOST_MEMORY" );
+         return CKR_HOST_MEMORY;
+         */
+         break;
+      }
+
+      // Advance to the next value.
+      size_t readerNameLen = strlen( (const char*)pReader );
+      pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+   }
+   free( pReaderList );
+
+   // Does a reader desappeared ?
+   for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      if( NULL_PTR != Application::_slotCache[ i ] )
+      {
+         //printf( "Application::_slotCache[ %lu ]->_readerName <%s>\n", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+
+         bool bFound = false;
+         for( int j = 0 ; j < CONFIG_MAX_SLOT; j++ )
+         {
+            //printf( "currentPcscList[ %d ] <%s>\n", j, currentPcscList[ j ].c_str( ) );
+
+            if( 0 == (Application::_slotCache[ i ]->_readerName)->compare( currentPcscList[ j ] ) )
+            {
+               bFound = true;
+               //printf( "!! Found !!\n" );
+               break;
+            }
+         }
+         if( false == bFound )
+         {
+            // Not found into the PCSC reader list
+            deleteSlot( i );
+            //printf( "!! Not Found -> delete !!\n" );
+         }
+      }
+   }
+
+   // Does a new reader appears ?
+   //printf( "\n\nDoes a new reader appears ?\n" );
+   for( int i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      if( false == currentPcscList[ i ].empty( ) )
+      {
+         //printf( "currentPcscList[ %d ] <%s>\n", i, currentPcscList[ i ].c_str( ) );
+
+         bool bFound = false;
+         for( int j = 0 ; j < CONFIG_MAX_SLOT; j++ )
+         {
+            if( 0 != Application::_slotCache[ j ] )
+            {
+               //printf( "   Application::_slotCache[ %d ] <%s>\n", j, Application::_slotCache[ j ]->_readerName->c_str( ) );
+               if( 0 == ( currentPcscList[ i ].compare( *(Application::_slotCache[ j ]->_readerName) ) ) )
+               {
+                  bFound = true;
+                  //printf( "   !! Found !!\n" );
+                  break;
+               }
+            }
+         }
+         if( false == bFound )
+         {
+            //printf( "!! Not Found -> add !!\n" );
+
+            CK_RV rv = addSlot( currentPcscList[ i ] );
+            if( CKR_OK != rv )
+            {
+               //Log::error( "Application::Enumerate", "addSlot failed" );
+               return rv;
+            }
+         }
+      }
+   }
+
+
+   // Scan Reader List
+   slotNb = 0;
+   Application::_numSlots = 0;
+   for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+   {
+      // Existing Slots only are scanned
+      if (Application::_slotCache[i] != NULL_PTR)
+      {
+         //Log::log( "Application::Enumerate - New Cache[ %d ] <%s>", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+         Application::_numSlots++;
+
+         SCARD_READERSTATE readerStates;
+         memset( &readerStates, 0, sizeof( SCARD_READERSTATE ) );
+         readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+         readerStates.szReader = Application::_slotCache[i]->_readerName->c_str();
+
+         // Lets check if token is present or not
+         if (SCardGetStatusChange(Application::_hContext, 100, &readerStates, 1) == SCARD_S_SUCCESS)
+         {
+            if ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+            {
+               // We found a card in this reader
+               Application::_slotCache[i]->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+               //Log::log( "Application::Enumerate - New Cache[ %d ] - Name <%s> - Token present", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+            }
+            else
+            {
+               // No card in this reader
+               Application::_slotCache[i]->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+               //Log::log( "Application::Enumerate - New Cache[ %d ] - Name <%s> - Token NOT present", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+            }
+         }
+
+         // Slots with Token Present
+         if((tokenPresent == TRUE) &&
+            (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+         {
+            slotNb++;
+         }
+         // All slots
+         else if (tokenPresent == FALSE)
+         {
+            slotNb++;
+         }
+      }
+   }
+
+   // If pSlotList is not NULL then *pulCount contains the buffer size of pSlotList
+   // so we need to check if size passed is valid or not.
+   if((pSlotList != NULL_PTR)&&(*pulCount < slotNb))
+   {
+      *pulCount = slotNb;
+      //Log::error( "Application::Enumerate", "CKR_BUFFER_TOO_SMALL" );
+      return CKR_BUFFER_TOO_SMALL;
+   }
+
+   *pulCount = slotNb;
+
+   // Fill slot list if not NULL
+   if (pSlotList != NULL_PTR)
+   {
+      for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+      {
+         // Existing Slots only are scanned
+         if (Application::_slotCache[i] != NULL_PTR)
+         {
+            CK_BBOOL IsFound = FALSE;
+
+            // Slots with Token Present
+            if((tokenPresent == TRUE) &&
+               (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+            {
+               IsFound = TRUE;
+            }
+
+            // All slots
+            else if (tokenPresent == FALSE)
+            {
+               IsFound = TRUE;
+            }
+
+            // Fill Slot List
+            if(IsFound == TRUE)
+            {
+               pSlotList[sid++] = Application::_slotCache[i]->_slotId;
+            }
+         }
+      }
+   }
+
+   //Log::end( "Application::Enumerate" );
+
+   return CKR_OK;
+}
+
+#else // _XCL_
+
+CK_RV Application::Enumerate( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+    PRINT_MSG("IN Application::Enumerate");
+
+    LPTSTR     pReaderList         = NULL;
+    CK_SLOT_ID slotIdx             = 0;
+    CK_ULONG   slotNb              = 0;
+    LPTSTR     pReader             = NULL;
+    CK_LONG    hResult             = 0;
+    CK_SLOT_ID sid                 = 0;
+
+    if(pulCount == NULL_PTR){
+        return CKR_ARGUMENTS_BAD;
+    }
+
+    DWORD readerListCharLength = SCARD_AUTOALLOCATE;
+
+    // asadali
+    // Get reader list, For now only ONE SEG-Lite token ...
+    pReaderList = (char *) malloc(64);
+    strcpy(pReaderList, "xCL_Token");
+    readerListCharLength = strlen(pReaderList);
+    *(pReaderList + readerListCharLength) = '\0';
+    *(pReaderList + readerListCharLength + 1) = '\0';
+
+    // Get Reader List if not already Get
+    if (Application::_numSlots == 0)
+    {
+        // clear the slot cache
+        //CSlot::ClearCache();
+
+        pReader = pReaderList;
+
+        while ('\0' != *pReader )
+        {
+            size_t readerNameLen = strlen((const char*)pReader);
+            size_t sd;
+
+            Slot* slot         = new Slot();
+            slot->_slotId      = slotIdx++;
+
+            // fill in the slot description
+            for(sd = 0; sd < readerNameLen; sd++)
+            {
+                slot->_slotInfo.slotDescription[sd] = pReader[sd];
+            }
+
+            if(slotIdx > CONFIG_MAX_SLOT){
+                return CKR_HOST_MEMORY;
+            }
+
+            slotNb++;
+
+            slot->_readerName  = new std::string(pReader);
+
+// GD            Application::AddSlotToCache(slot);
+                Application::addSlot (slot);
+
+            // Advance to the next value.
+            pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+        }
+
+        free(pReaderList);
+        Application::_numSlots = slotNb;
+    }
+
+    // Scan Reader List
+    slotNb = 0;
+
+    for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+    {
+        // Existing Slots only are scanned
+        if (Application::_slotCache[i] != NULL_PTR)
+        {
+            SCARD_READERSTATE readerStates;
+
+            readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+            readerStates.szReader = Application::_slotCache[i]->_readerName->c_str();
+
+            // Lets check if token is present or not
+
+            // asadali
+            if (xCL_IsTokenPresent())
+            {
+                // We found a card in this reader
+                Application::_slotCache[i]->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+            }
+            else
+            {
+                // No card in reader
+                Application::_slotCache[i]->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+            }
+
+            // Slots with Token Present
+            if((tokenPresent == TRUE) &&
+               (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+            {
+                slotNb++;
+            }
+            // All slots
+            else if (tokenPresent == FALSE)
+            {
+                slotNb++;
+            }
+        }
+    }
+
+    // If pSlotList is not NULL then *pulCount contains the buffer size of pSlotList
+    // so we need to check if size passed is valid or not.
+    if((pSlotList != NULL_PTR)&&(*pulCount < slotNb))
+    {
+        *pulCount = slotNb;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+
+    *pulCount = slotNb;
+
+    // Fill slot list if not NULL
+    if (pSlotList != NULL_PTR)
+    {
+        for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+        {
+            // Existing Slots only are scanned
+            if (Application::_slotCache[i] != NULL_PTR)
+            {
+                CK_BBOOL IsFound = FALSE;
+
+                // Slots with Token Present
+                if((tokenPresent == TRUE) &&
+                   (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+                {
+                    IsFound = TRUE;
+                }
+
+                // All slots
+                else if (tokenPresent == FALSE)
+                {
+                    IsFound = TRUE;
+                }
+
+                // Fill Slot List
+                if(IsFound == TRUE)
+                {
+                    pSlotList[sid++] = Application::_slotCache[i]->_slotId;
+                }
+            }
+        }
+    }
+
+    return CKR_OK;
+}
+
+#endif // _XCL_
+
+/*
+*/
+CK_RV Application::GetSlotFromSlotId( CK_SLOT_ID slotId, Slot** slot )
+{
+   if(((int)slotId < 0) || (slotId >= CONFIG_MAX_SLOT))
+   {
+      return CKR_SLOT_ID_INVALID;
+   }
+
+   if (Application::_slotCache[slotId] != NULL_PTR)
+   {
+      *slot = Application::_slotCache[slotId];
+      return CKR_OK;
+   }
+
+   return CKR_SLOT_ID_INVALID;
+}
+
+
+/*
+*/
+void Application::ClearCache(void)
+{
+   Log::begin( "Application::ClearCache" );
+
+   // initialize the slot cache
+   for( int sid = 0 ; sid < CONFIG_MAX_SLOT ; sid++ )
+   {
+      Slot* slot = Application::_slotCache[ sid ];
+      if( NULL_PTR != slot )
+      {
+#ifdef INCLUDE_EVENTING
+         if(slot->_tracker != NULL_PTR)
+         {
+            slot->_tracker->stop( );
+         }
+#endif
+         delete slot;
+         Application::_slotCache[sid] = NULL_PTR;
+      }
+   }
+
+   // set the number of actual slots present to zero
+   Application::_numSlots = 0;
+
+#ifdef INCLUDE_EVENTING
+   // we should just signal all the events
+   CryptokiEvent.Signal();
+#endif
+
+   Log::end( "Application::ClearCache" );
+}
+
+
+/*
+*/
+void Application::Release( void )
+{
+   if( 0 != Application::_hContext )
+   {
+#ifndef _XCL_
+      SCardReleaseContext( Application::_hContext );
+#endif // _XCL_
+      Application::_hContext = 0;
+   }
+}
+
+
+/*
+*/
+void Application::End( void )
+{
+   Application::ClearCache( );
+   Application::Release( );
+}
+
+
+/*
+*/
+void Application::deleteSlot( int i )
+{
+   if( NULL_PTR != Application::_slotCache[ i ] )
+   {
+#ifdef INCLUDE_EVENTING
+      if( NULL_PTR != (Application::_slotCache[ i ]->_tracker) )
+      {
+         (Application::_slotCache[ i ])->_tracker->stop( );
+      }
+#endif
+      delete (Application::_slotCache[ i ]);
+      Application::_slotCache[ i ] = NULL_PTR;
+
+#ifdef INCLUDE_EVENTING
+      // we should just signal all the events
+      CryptokiEvent.Signal( );
+#endif
+
+   }
+}
+
+
+/*
+*/
+
+#ifndef _XCL_
+
+CK_RV Application::addSlot( std::string& a_readerName )
+{
+   int iSlotID = -1;
+   for( int j = 0 ; j < CONFIG_MAX_SLOT ; j++ )
+   {
+      if( NULL_PTR == Application::_slotCache[ j ] )
+      {
+         iSlotID = j;
+         break;
+      }
+   }
+   if( -1 == iSlotID )
+   {
+      return CKR_HOST_MEMORY;
+   }
+
+   Slot* slot = new Slot( );
+   slot->_readerName  = new std::string( a_readerName );
+
+   // Fill in the slot description
+   size_t l = ( a_readerName.length( ) > sizeof( slot->_slotInfo.slotDescription ) ) ? sizeof( slot->_slotInfo.slotDescription ) : a_readerName.length( );
+   for( size_t i = 0 ; i < l ; i++ )
+   {
+      slot->_slotInfo.slotDescription[ i ] = a_readerName[ i ];
+   }
+
+   // Add Slot in Cache
+   slot->_slotId = iSlotID;
+   Application::_slotCache[ iSlotID ] = slot;
+
+#ifdef INCLUDE_EVENTING
+   SCARD_READERSTATE readerStates;
+
+   readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+   readerStates.szReader = slot->_readerName->c_str();
+
+   if (SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+   {
+      if ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)
+      {
+         // we not found a card in this reader
+         slot->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+      }
+      else
+      {
+         // we found a card in this reader
+         slot->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+      }
+   }
+
+   // Start the monitoring also
+   slot->_tracker = new CardMonitoringThread(slot->_readerName->c_str());
+   slot->_tracker->SetSlot(slot);
+   slot->_tracker->start();
+
+#endif
+
+   return CKR_OK;
+}
+
+#else // _XCL_
+
+void Application::addSlot( Slot* slot )
+{
+    PRINT_MSG("IN Application::AddslotToCache");
+
+    // Add Slot in Cache
+    Application::_slotCache[slot->_slotId] = slot;
+
+#ifdef INCLUDE_EVENTING
+    SCARD_READERSTATE readerStates;
+
+    readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+    readerStates.szReader = slot->_readerName->c_str();
+
+    // asadali
+    if (xCL_IsTokenPresent())
+    {
+        // we found a card in this reader
+        slot->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+    }
+    else
+    {
+        // No card in reader
+        slot->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+    }
+
+    // Start the monitoring also
+    slot->_tracker = new CardMonitoringThread(slot->_readerName->c_str());
+    slot->_tracker->SetSlot(slot);
+    slot->_tracker->start();
+#endif
+}
+
+#endif // _XCL_

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/application.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/application.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/application.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,66 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_application_h
+#define _include_application_h
+
+#include <vector>
+#include <list>
+
+#ifdef _XCL_
+#include <xcl_utils.h>
+#endif // _XCL_
+
+using namespace std;
+
+class Application {
+
+public:
+   static CK_ULONG _numSlots;
+   static Slot* _slotCache[CONFIG_MAX_SLOT];
+   static SCARDCONTEXT _hContext;
+
+#ifdef _XCL_
+    static xCL_DeviceHandle _deviceHandle;
+#endif // _XCL_
+
+public:
+   static CK_RV InitApplication(void);
+
+   static CK_RV Enumerate(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+
+   static CK_RV GetSlotFromSlotId(CK_SLOT_ID slotId, Slot** slot);
+
+//   static void AddSlotToCache(Slot* slot);
+	static void addSlot( Slot* slot );
+
+   static void ClearCache();
+
+   static void Release( void );
+   static void End( void );
+   //static void ReleaseThreads( void );
+
+   static void deleteSlot( int i );
+   static CK_RV addSlot( std::string& a_readerName );
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,221 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+//#pragma warning(disable : 4251)
+
+#include "stdafx.h"
+#include "platconfig.h"
+//#include "config.h"
+//#include "dbg.h"
+
+
+
+#include <numeric>
+#include <functional>
+#include "attrcert.h"
+#include "digest.h"
+#include "sha1.h"
+
+using namespace std;
+
+namespace
+{
+
+    class JoinWith
+        : public binary_function<string, string, string>
+    {
+    public:
+
+        explicit
+        JoinWith(second_argument_type const &rGlue)
+            : m_Glue(rGlue)
+        {}
+
+
+        result_type
+        operator()(string const &rFirst,
+                   string const &rSecond) const
+        {
+            return rFirst + m_Glue + rSecond;
+        }
+
+    private:
+
+        second_argument_type const m_Glue;
+    };
+
+    string
+    Combine(vector<string> const &rvsNames)
+    {
+        static string::value_type const cBlank = ' ';
+        static string const sBlank(1, cBlank);
+
+        if(!rvsNames.empty())
+            return accumulate(rvsNames.begin() + 1, rvsNames.end(),
+                              *rvsNames.begin(), JoinWith(sBlank));
+        else
+            return string();
+    }
+
+} // namespace
+
+CAttributedCertificate::CAttributedCertificate(BEROctet::Blob const &cert) : m_x509cert(cert)
+{
+}
+
+CAttributedCertificate::CAttributedCertificate(const unsigned char * cert, size_t length)
+                                            : m_x509cert(cert, static_cast<unsigned long>(length))
+{
+}
+
+CAttributedCertificate::~CAttributedCertificate()
+{
+}
+
+BEROctet::Blob
+CAttributedCertificate::Modulus() const
+{
+    return m_x509cert.Modulus();
+}
+
+BEROctet::Blob
+CAttributedCertificate::PublicExponent() const
+{
+    return m_x509cert.PublicExponent();
+}
+
+BEROctet::Blob
+CAttributedCertificate::Subject() const
+{
+    return m_x509cert.Subject();
+}
+
+BEROctet::Blob
+CAttributedCertificate::Issuer() const
+{
+    return m_x509cert.Issuer();
+}
+
+BEROctet::Blob
+CAttributedCertificate::SerialNumber() const
+{
+    return m_x509cert.SerialNumber();
+}
+
+string
+CAttributedCertificate::DerivedName() const
+{
+    string sDerivedName(Combine(m_x509cert.UTF8SubjectCommonName()));
+    if(sDerivedName.empty())
+        sDerivedName.assign("Smart Card User");
+    return sDerivedName;
+}
+
+string
+CAttributedCertificate::DerivedLabel() const
+{
+    return Combine(m_x509cert.SubjectCommonName());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId() const
+{
+    return DerivedId(m_x509cert.Modulus());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId(BEROctet::Blob const & data)
+{
+    return DerivedId(data.c_str(), data.size());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId(unsigned char const * data, size_t length)
+{
+    CSHA1 sha1;
+    u1 hash[20];
+    sha1.HashCore(const_cast<CK_BYTE_PTR>(data), 0, static_cast<CK_LONG>(length));
+    sha1.HashFinal(hash);
+
+    return BEROctet::Blob(hash, 20);
+}
+
+string
+CAttributedCertificate::DerivedUniqueName() const
+{
+    return DerivedUniqueName(m_x509cert.Modulus());
+}
+
+string
+CAttributedCertificate::DerivedUniqueName(BEROctet::Blob const & data)
+{
+    return DerivedUniqueName(data.c_str(), data.size());
+}
+
+string
+CAttributedCertificate::DerivedUniqueName(unsigned char const * data, size_t length)
+{
+    CSHA1 sha1;
+    u1 hash[20];
+    sha1.HashCore(const_cast<CK_BYTE_PTR>(data), 0, static_cast<CK_LONG>(length));
+    sha1.HashFinal(hash);
+
+    // Format as a GUID
+
+    char name[40];
+
+    u1 *id = hash;
+
+    int i, n = 0;
+    char *c = name;
+
+    for(i=0; i<4; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<2; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<2; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<2; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<6; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+
+    return string(name);
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/attrcert.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,84 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_attrcert_h
+#define _include_attrcert_h
+
+#include "x509cert.h"
+
+
+class CAttributedCertificate
+{
+
+public:
+    explicit CAttributedCertificate(BEROctet::Blob const &cert);
+    CAttributedCertificate(const unsigned char * cert, size_t length);
+
+    virtual ~CAttributedCertificate();
+
+    BEROctet::Blob
+    Modulus() const;
+
+    BEROctet::Blob
+    PublicExponent() const;
+
+    BEROctet::Blob
+    Subject() const;
+
+    BEROctet::Blob
+    Issuer() const;
+
+    BEROctet::Blob
+    SerialNumber() const;
+
+    std::string
+    DerivedName() const;
+
+    std::string
+    DerivedLabel() const;
+
+    BEROctet::Blob
+    DerivedId() const;
+
+    static BEROctet::Blob
+    DerivedId(BEROctet::Blob const & data);
+
+    static BEROctet::Blob
+    DerivedId(unsigned char const * data, size_t length);
+
+    std::string
+    DerivedUniqueName() const;
+
+    static std::string
+    DerivedUniqueName(BEROctet::Blob const & data);
+
+    static std::string
+    DerivedUniqueName(unsigned char const * data, size_t length);
+
+private:
+    X509Cert m_x509cert;
+
+};
+
+
+#endif // _include_attrcert_h
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,741 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This implementation is based on X.690 specification. Access to this
+// specification is a pre-requisite to understand the logic. The spec
+// can be purchased from International Telecommunication Union (ITU)
+// at http://www.itu.int
+
+// This code is based on class in ACS baseline.
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "beroctet.h"
+
+using namespace std;
+
+BEROctet::BEROctet() : m_tcClass(tcUniversal),
+                       m_fConstructed(fBerPcPrimitive),
+                       m_dwTag(dwBerUnivZero),
+                       m_fDefinite(true),
+                       m_fModified(true)
+{
+}
+
+BEROctet::BEROctet(BEROctet const &oct)
+{
+    *this = oct;
+}
+
+BEROctet::BEROctet(Blob const &blb)
+{
+    Decode(blb);
+}
+
+BEROctet::BEROctet(TagClass tcClass, bool fConstructed, unsigned int dwTag, bool fDefinite) :
+                                                                       m_tcClass(tcClass),
+                                                                       m_fConstructed(fConstructed),
+                                                                       m_dwTag(dwTag),
+                                                                       m_fDefinite(fDefinite),
+                                                                       m_fModified(true)
+{
+    if(!m_fDefinite && !m_fConstructed)
+        throw runtime_error("BERPrimitiveIndefiniteLength");
+}
+
+BEROctet::~BEROctet(void)
+{
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+        delete m_SubOctetList[i];
+}
+
+BEROctet& BEROctet::operator=(BEROctet const &Oct)
+{
+
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+        delete m_SubOctetList[i];
+
+    m_SubOctetList.resize(0);
+    m_blbData.resize(0);
+
+    m_fModified    = Oct.m_fModified;
+    m_blbOrigOctet = Oct.m_blbOrigOctet;
+
+    m_fConstructed = Oct.m_fConstructed;
+    m_tcClass      = Oct.m_tcClass;
+    m_dwTag        = Oct.m_dwTag;
+    m_fDefinite    = Oct.m_fDefinite;
+
+
+    if(m_fConstructed)
+    {
+        for(std::vector<BEROctet const*>::size_type i=0; i<Oct.m_SubOctetList.size(); i++)
+            m_SubOctetList.push_back(new BEROctet(*Oct.m_SubOctetList[i]));
+    }
+    else
+        m_blbData = Oct.m_blbData;
+
+    return *this;
+}
+
+// Returns a the data part of the octet
+
+BEROctet::Blob BEROctet::Data() const
+{
+
+    if(m_fConstructed)
+    {
+
+        // Traverse the tree
+
+        Blob data;
+
+        for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+            data += m_SubOctetList[i]->Octet();
+
+        return data;
+    }
+    else
+        return m_blbData;
+
+}
+
+// Sets the data part of the octet
+
+void BEROctet::Data(Blob const &blb)
+{
+
+    if(m_fConstructed)
+        throw runtime_error("BERInconsistentOperation");
+
+    m_blbData = blb;
+    m_fModified = true;
+
+}
+
+// If the octet is a constructed type, this returns list of sub-octets
+
+vector<BEROctet*> BEROctet::SubOctetList() const
+{
+    if(!m_fConstructed)
+        throw runtime_error("BERInconsistentOperation");
+
+    return m_SubOctetList;
+}
+
+// Insert an octet as a sub-octet of a constructed octet
+
+void BEROctet::Insert(BEROctet const &oct)
+{
+    if(!m_fConstructed)
+        throw runtime_error("BERInconsistentOperation");
+
+    BEROctet *pOct = new BEROctet(oct);
+    m_SubOctetList.push_back(pOct);
+    m_fModified = true;
+
+}
+
+// Returns the whole octet
+
+BEROctet::Blob BEROctet::Octet() const
+{
+    if(Modified())
+    {
+
+        Blob blbOct = IdentOctets(m_tcClass, m_fConstructed, m_dwTag);
+        Blob blbData = Data();
+
+        if(m_fDefinite)
+            blbOct += LengthOctets(static_cast<unsigned int>(blbData.size()));
+        else
+            blbOct += 0x80;    // Indefinite length octet
+
+        blbOct += blbData;
+
+        if(!m_fDefinite)
+        {
+
+            // Terminate with end-of-contents octet
+
+            BEROctet blbZero;
+            blbOct += blbZero.Octet();
+        }
+
+        return blbOct;
+    }
+    else
+        return m_blbOrigOctet;
+
+}
+
+// Returns the class of the octet
+
+TagClass BEROctet::Class() const
+{
+    return m_tcClass;
+}
+
+// Returns true if the octet is constructet, false otherwise
+
+bool BEROctet::Constructed() const
+{
+    return m_fConstructed;
+}
+
+// Returns the tag of the octet
+
+unsigned int BEROctet::Tag() const
+{
+    return m_dwTag;
+}
+
+// Decode the contents of an OID
+
+string BEROctet::ObjectID() const
+{
+
+    if(m_tcClass!=tcUniversal || m_dwTag!=dwBerUnivObjectIdent)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(!m_blbData.size())
+        throw runtime_error("BEREmptyOctet");
+
+    string OID;
+
+    // The scratch buffer "text" below needs to be large enough to hold
+    // the decimal encoding of two 32 bit integers, including a space
+    // and the terminating zero.
+
+    char text[40];
+
+    unsigned int subid;
+    const unsigned char *c = m_blbData.data();
+    const unsigned char *Last = c + m_blbData.size();
+    bool First = true;
+
+    while(c<Last)
+    {
+        subid = (*c)&0x7F;
+        while((*c)&0x80)
+        {
+            c++;
+            if(c>=Last)
+                throw runtime_error("BERUnexpectedEndOfOctet");
+            if(subid>0x01FFFFFF)
+                throw runtime_error("BEROIDSubIdentifierOverflow");
+            subid = (subid<<7) | ((*c)&0x7F);
+        }
+        if(First)
+        {
+            unsigned int X,Y;
+            if(subid<40)
+                X=0;
+            else if(subid<80)
+                X=1;
+            else
+                X=2;
+            Y = subid-X*40;
+            sprintf(text,"%d %d",X,Y);
+            OID = text;
+            First = false;
+        }
+        else
+        {
+            sprintf(text," %d",subid);
+            OID += text;
+        }
+        c++;
+    }
+
+    return OID;
+}
+
+// Encode an OID
+
+void BEROctet::ObjectID(string const &str)
+{
+
+    if(m_tcClass!=tcUniversal)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(m_dwTag==dwBerUnivZero)
+        m_dwTag = dwBerUnivObjectIdent;
+
+    if(m_dwTag!=dwBerUnivObjectIdent)
+        throw runtime_error("BERInconsistentOperation");
+
+    char *oid = 0;
+
+    try
+    {
+#if defined(_WIN32)
+        oid = _strdup(str.c_str());
+#else
+        oid = strdup(str.c_str());
+#endif
+        char *s;
+
+        if(0==(s = strtok(oid," ")))
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        unsigned int X,Y,dwSubOID;
+
+        if(sscanf(s,"%u",&X)!=1)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(X>2)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(0==(s = strtok(0," ")))
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(sscanf(s,"%u",&Y)!=1)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(X<2 && Y>39)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        dwSubOID = X*40;
+        if(Y>0xFFFFFFFF-dwSubOID)
+            throw runtime_error("BERDataOverflow");
+
+        dwSubOID += Y;
+
+        Blob blbData;
+
+        while(true)
+        {
+
+            unsigned char buf[2*sizeof(dwSubOID)];
+            int n=0;
+            while(dwSubOID>0x7F)
+            {
+                buf[n] = static_cast<unsigned char>(dwSubOID & 0x7F);
+                dwSubOID >>=7;
+                n++;
+            }
+            buf[n] = static_cast<unsigned char>(dwSubOID & 0x7F);
+            n++;
+
+            for(int i=0; i<n; i++)
+            {
+                unsigned char b = buf[n-i-1];
+                if((i+1)<n) b |= 0x80;
+                blbData += b;
+            }
+
+            if(0==(s = strtok(0," ")))
+                break;
+            if(sscanf(s,"%u",&dwSubOID)!=1)
+                break;
+        }
+
+        Data(blbData);
+
+    }
+    catch(...)
+    {
+        if(oid)
+            free(oid);
+        throw;
+    }
+
+    if(oid)
+        free(oid);
+
+}
+
+// Decode a Time octet. Output format: "YYYYMMDDHHMMSS"
+
+// We here apply the convention from RFC 2459 that the 2 digit year
+// encoded in UTCTime is in the range 1950-2049.
+
+string BEROctet::Time() const
+{
+
+    static const Blob::size_type UnivUTCTimeSize = 13;
+    static const Blob::size_type UnivGenTimeSize = 15;
+
+    if(m_tcClass!=tcUniversal)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(m_dwTag==dwBerUnivUTCTime)
+    {
+        // UTCTime
+
+        if(m_blbData.size()!=UnivUTCTimeSize)
+            throw runtime_error("BERInconsistentDataLength");
+
+        string strCentury, strYear((char*)m_blbData.data(),2);
+        int iYear;
+        if(sscanf(strYear.c_str(),"%d",&iYear)!=1)
+            throw runtime_error("FormatDecodingError");
+
+        if(iYear>=50) strCentury = "19";
+        else strCentury = "20";
+
+        // Add century and strip off the 'Z'
+
+        return strCentury + string((char*)m_blbData.data(),UnivUTCTimeSize-1);
+    }
+    else if(m_dwTag==dwBerUnivGenTime)
+    {
+        // GeneralizedTime
+
+        if(m_blbData.size()!=UnivGenTimeSize)
+            throw runtime_error("BERInconsistentDataLength");
+
+        // Return the string as is, stripping off the 'Z'
+
+        return string((char*)m_blbData.data(),UnivGenTimeSize-1);
+    }
+    else
+        throw runtime_error("BERInconsistentOperation");
+
+}
+
+// Encode a Time. Input format: "YYYYMMDDHHMMSS"
+
+// If the Tag is not set to be either UTC Time or Generalized Time,
+// we apply the convention from RFC 2459 where years in the range
+// 1950-2049 are encoded as UTC Time and years later are encoded as
+// Generalized time. In this case, years < 1950 are not allowed.
+
+void BEROctet::Time(string const &str)
+{
+    static const Blob::size_type ExpectedSize = 14;
+
+    if(m_tcClass!=tcUniversal)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(str.size()!=ExpectedSize)
+        throw runtime_error("IllegalParameter");
+
+    // If m_dwTag is zero, chose appropriate tag according to year
+
+    int iYear;
+    if(sscanf(str.substr(0,4).c_str(),"%d",&iYear)!=1)
+        throw runtime_error("IllegalParameter");
+
+    if(m_dwTag==dwBerUnivZero)
+    {
+        if(iYear<1950)
+            throw runtime_error("IllegalParameter");
+        else if(iYear<2050)
+            m_dwTag = dwBerUnivUTCTime;
+        else
+            m_dwTag = dwBerUnivGenTime;
+    }
+
+    Blob blbData;
+
+    if(m_dwTag==dwBerUnivUTCTime)
+        blbData.assign(((unsigned char*)str.data()+2),str.size()-2);
+
+    else if(m_dwTag==dwBerUnivGenTime)
+        blbData.assign((unsigned char*)str.data(),str.size());
+
+    else
+        throw runtime_error("BERInconsistentOperation");
+
+    blbData += 'Z';
+
+    Data(blbData);
+
+}
+
+// SearchOID returns all the constructed octets that contain a particular OID
+
+void BEROctet::SearchOID(string const &OID, vector<BEROctet const*> &result) const
+{
+
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+    {
+
+        if(m_SubOctetList[i]->Class()==tcUniversal &&
+           m_SubOctetList[i]->Tag()==dwBerUnivObjectIdent)
+        {
+            if(OID==m_SubOctetList[i]->ObjectID())
+                result.push_back(this);
+        }
+        else if(m_SubOctetList[i]->Constructed())
+            m_SubOctetList[i]->SearchOID(OID,result);
+    }
+
+    return;
+
+}
+
+// SearchOIDNext returns all the octets following a particular OID
+
+void BEROctet::SearchOIDNext(string const &OID, vector<BEROctet const*> &result) const
+{
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+    {
+        if(m_SubOctetList[i]->Class()==tcUniversal &&
+           m_SubOctetList[i]->Tag()==dwBerUnivObjectIdent)
+        {
+            if(OID==m_SubOctetList[i]->ObjectID())
+            {
+                if((i+1) < m_SubOctetList.size())
+                    result.push_back(m_SubOctetList[i+1]);
+            }
+        }
+        else if(m_SubOctetList[i]->Constructed())
+            m_SubOctetList[i]->SearchOIDNext(OID,result);
+    }
+
+    return;
+
+}
+
+// Construct the Identifier octets
+
+BEROctet::Blob BEROctet::IdentOctets(TagClass tcClass, bool fConstructed, unsigned int dwTag)
+{
+
+    unsigned char bLeadingOct;
+    switch(tcClass)
+    {
+
+    case tcUniversal:
+        bLeadingOct = 0x00;
+        break;
+
+    case tcApplication:
+        bLeadingOct = 0x40;
+        break;
+
+    case tcContext:
+        bLeadingOct = 0x80;
+        break;
+
+    case tcPrivate:
+        bLeadingOct = 0xC0;
+        break;
+
+    default:
+        throw runtime_error("BERIllegalClass");
+    }
+
+    if(fConstructed)
+        bLeadingOct |= 0x20;
+
+    int n = 0;
+    unsigned char buf[sizeof(dwTag)];
+
+    if(dwTag<=30)
+        bLeadingOct |= dwTag;
+
+    else
+    {
+        bLeadingOct |= 0x1F;
+        while(dwTag>0)
+        {
+            buf[n] = static_cast<unsigned char>(dwTag & 0x000000FF);
+            dwTag >>= 8;
+            n++;
+        }
+    }
+
+    Blob IdentOcts(&bLeadingOct,1);
+
+    for(int i=0; i<n; i++)
+        IdentOcts +=buf[n-i-1];
+
+    return IdentOcts;
+
+}
+
+// Construct the Length octets
+
+BEROctet::Blob BEROctet::LengthOctets(unsigned int dwLength)
+{
+
+    int n = 0;
+    unsigned char buf[sizeof(dwLength)];
+    unsigned char bLeadingOct;
+
+    if(dwLength<=0x7F)
+        bLeadingOct = static_cast<unsigned char>(dwLength);
+    else
+    {
+        bLeadingOct = 0x80;
+        while(dwLength>0)
+        {
+            buf[n] = static_cast<unsigned char>(dwLength & 0x000000FF);
+            dwLength >>= 8;
+            n++;
+        }
+        bLeadingOct |= n;
+    }
+
+    Blob LengthOcts(&bLeadingOct,1);
+    for(int i=0; i<n; i++)
+        LengthOcts +=buf[n-i-1];
+
+    return LengthOcts;
+
+}
+
+// Decodes recursively a BER octet.
+
+void BEROctet::Decode(Blob const &blb)
+{
+
+    if(!blb.size())
+        throw runtime_error("BEREmptyOctet");
+
+    size_t BufferSize = blb.size();
+
+    m_fConstructed = (blb[0]&0x20) ? true : false;
+
+    switch(blb[0]&0xC0)
+    {
+
+    case 0x00:
+        m_tcClass = tcUniversal;
+        break;
+
+    case 0x40:
+        m_tcClass = tcApplication;
+        break;
+
+    case 0x80:
+        m_tcClass = tcContext;
+        break;
+
+    case 0xC0:
+        m_tcClass = tcPrivate;
+        break;
+
+    default:
+        throw runtime_error("BERIllegalClass");
+    }
+
+    const unsigned char *c = blb.data();
+    const unsigned char *Last = c + blb.size() - 1;
+    m_dwTag = *c & 0x1F;
+
+    if(m_dwTag>30)
+    {
+        m_dwTag = 0;
+
+        c++;
+        if(c>Last)
+            throw runtime_error("BERUnexpectedEndOfOctet");
+
+        while (*c & 0x80)
+        {
+            m_dwTag = (m_dwTag << 7) | ((*c) & 0x7F);
+            c++;
+            if(c>Last)
+                throw runtime_error("BERUnexpectedEndOfOctet");
+        }
+
+        if(m_dwTag > 0x01FFFFFF)
+            throw runtime_error("BERTagValueOverflow");
+
+        m_dwTag = (m_dwTag << 7) | ((*c) & 0x7F);
+
+    }
+
+    c++;
+    if(c>Last)
+        throw runtime_error("BERUnexpectedEndOfOctet");
+
+    size_t DataSize;
+
+    if((*c)&0x80)
+    {
+        int n = (*c) & 0x7F;
+        if(n)
+        {
+            DataSize = 0;
+            for(int i=0; i<n; i++)
+            {
+                c++; if(c>Last)
+                    throw runtime_error("BERUnexpectedEndOfOctet");
+                if(DataSize>0x007FFFFF)
+                    throw runtime_error("BERDataOverflow");
+                DataSize = (DataSize<<8) | (*c);
+            }
+        }
+        else
+            throw runtime_error("BERUnexpectedIndefiniteLength");
+    }
+    else DataSize = *c;
+
+    c++;
+
+    const unsigned char *bpData = c;
+
+    size_t OctetSize = DataSize + (bpData-blb.data());
+
+    m_blbOrigOctet = blb.substr(0,OctetSize);
+    m_fModified = false;
+
+    if(OctetSize>static_cast<unsigned int>(BufferSize))
+        throw runtime_error("BERInconsistentDataLength");
+
+    for(std::vector<BEROctet const*>::size_type  i=0; i<m_SubOctetList.size(); i++)
+        delete m_SubOctetList[i];
+
+    m_SubOctetList.resize(0);
+    m_blbData = Blob();
+
+    if(m_fConstructed)
+    {
+
+        // Constructed type
+
+        while(DataSize)
+        {
+
+            BEROctet *suboct = new BEROctet(Blob(bpData,DataSize));
+
+            m_SubOctetList.push_back(suboct);
+
+            Blob blbSubOct = suboct->Octet();
+
+            bpData += blbSubOct.size();
+            DataSize -= blbSubOct.size();
+        }
+    }
+    else
+        m_blbData = Blob(bpData,DataSize);
+
+}
+
+bool BEROctet::Modified() const
+{
+    if(m_fModified)
+        return true;
+
+    if(m_fConstructed)
+        for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+            if(m_SubOctetList[i]->Modified()) return true;
+
+    return false;
+
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/beroctet.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,221 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_beroctet_h
+#define _include_beroctet_h
+
+#include <string>
+#include <vector>
+#include <stdexcept>
+
+enum TagClass {tcAny = -1, tcUniversal = 0, tcApplication = 1, tcContext = 2, tcPrivate = 3};
+
+// Defined tags
+
+const unsigned int dwBerUnivZero          = 0;
+const unsigned int dwBerUnivBool          = 1;
+const unsigned int dwBerUnivInteger       = 2;
+const unsigned int dwBerUnivBitString     = 3;
+const unsigned int dwBerUnivOctetString   = 4;
+const unsigned int dwBerUnivNull          = 5;
+const unsigned int dwBerUnivObjectIdent   = 6;
+const unsigned int dwBerUnivObjectDesc    = 7;
+const unsigned int dwBerUnivReal          = 9;
+const unsigned int dwBerUnivEnum          = 10;
+const unsigned int dwBerUnivUTF8String    = 12;
+const unsigned int dwBerUnivSequence      = 16;
+const unsigned int dwBerUnivSet           = 17;
+const unsigned int dwBerUnivPrintString   = 19;
+const unsigned int dwBerUnivIA5String     = 22;
+const unsigned int dwBerUnivUTCTime       = 23;
+const unsigned int dwBerUnivGenTime       = 24;
+const unsigned int dwBerGraphicString     = 25;
+const unsigned int dwBerISO646String      = 26;
+const unsigned int dwBerGeneralString     = 27;
+const unsigned int dwBerUniversalString   = 28;
+const unsigned int dwBerCharacterString   = 29;
+const unsigned int dwBerBMPString         = 30;
+const unsigned int dwBerDate              = 31;
+const unsigned int dwBerTimeOfDay         = 32;
+const unsigned int dwBerDateTime          = 33;
+const unsigned int dwBerDuration          = 34;
+
+const char OID_pkcs1[]                            = "1 2 840 113549 1 1";
+const char OID_pkcs1_rsaEncryption[]              = "1 2 840 113549 1 1 1";
+const char OID_pkcs1_md2WithRSAEncryption[]       = "1 2 840 113549 1 1 2";
+const char OID_pkcs1_md4WithRSAEncryption[]       = "1 2 840 113549 1 1 3";
+const char OID_pkcs1_md5WithRSAEncryption[]       = "1 2 840 113549 1 1 4";
+const char OID_pkcs1_sha1WithRSAEncryption[]      = "1 2 840 113549 1 1 5";
+const char OID_pkcs1_sha256WithRSAEncryption[]    = "1 2 840 113549 1 1 11";
+
+const char OID_pkcs7_data[]                       = "1 2 840 113549 1 7 1";
+const char OID_pkcs7_signedData[]                 = "1 2 840 113549 1 7 2";
+const char OID_pkcs7_envelopedData[]              = "1 2 840 113549 1 7 3";
+const char OID_pkcs7_signedAndEnvelopedData[]     = "1 2 840 113549 1 7 4";
+const char OID_pkcs7_digestedData[]               = "1 2 840 113549 1 7 5";
+const char OID_pkcs7_encryptedData[]              = "1 2 840 113549 1 7 6";
+
+const char OID_pkcs9_emailAddress[]               = "1 2 840 113549 1 9 1";
+const char OID_pkcs9_unstructuredName[]           = "1 2 840 113549 1 9 2";
+const char OID_pkcs9_contentType[]                = "1 2 840 113549 1 9 3";
+const char OID_pkcs9_messageDigest[]              = "1 2 840 113549 1 9 4";
+const char OID_pkcs9_signingTime[]                = "1 2 840 113549 1 9 5";
+const char OID_pkcs9_countersignature[]           = "1 2 840 113549 1 9 6";
+const char OID_pkcs9_challengePassword[]          = "1 2 840 113549 1 9 7";
+const char OID_pkcs9_unstructuredAddress[]        = "1 2 840 113549 1 9 8";
+const char OID_pkcs9_extendedCertificateAttr[]    = "1 2 840 113549 1 9 9";
+const char OID_pkcs9_sMIMECapabilities[]          = "1 2 840 113549 1 9 15";
+const char OID_pkcs9_id_smime[]                   = "1 2 840 113549 1 9 16";
+
+const char OID_digestAlogrithm_md2[]              = "1 2 840 113549 2 2";
+const char OID_digestAlogrithm_md4[]              = "1 2 840 113549 2 4";
+const char OID_digestAlogrithm_md5[]              = "1 2 840 113549 2 5";
+
+const char OID_RC2_CBC[]                          = "1 2 840 113549 3 2";
+const char OID_dES_EDE3_CBC[]                     = "1 2 840 113549 3 7";
+
+const char OID_ms_enrollmentAgent[]               = "1 3 6 1 4 1 311 20 2 1";
+const char OID_ms_smartCardLogin[]                = "1 3 6 1 4 1 311 20 2 2";
+
+const char OID_id_kp_serverAuth[]                 = "1 3 6 1 5 5 7 3 1";
+const char OID_id_kp_clientAuth[]                 = "1 3 6 1 5 5 7 3 2";
+const char OID_id_kp_codeSigning[]                = "1 3 6 1 5 5 7 3 3";
+const char OID_id_kp_emailProtection[]            = "1 3 6 1 5 5 7 3 4";
+const char OID_id_kp_ipsecEndSystem[]             = "1 3 6 1 5 5 7 3 5";
+const char OID_id_kp_ipsecTunnel[]                = "1 3 6 1 5 5 7 3 6";
+const char OID_id_kp_ipsecUser[]                  = "1 3 6 1 5 5 7 3 7";
+const char OID_id_kp_timeStamping[]               = "1 3 6 1 5 5 7 3 8";
+
+const char OID_md4WithRSA[]                       = "1 3 14 3 2 2";
+const char OID_md5WithRSA[]                       = "1 3 14 3 2 3";
+const char OID_md4WithRSAEncryption[]             = "1 3 14 3 2 4";
+const char OID_desECB[]                           = "1 3 14 3 2 6";
+const char OID_desCBC[]                           = "1 3 14 3 2 7";
+const char OID_desOFB[]                           = "1 3 14 3 2 8";
+const char OID_desCFB[]                           = "1 3 14 3 2 9";
+const char OID_desMAC[]                           = "1 3 14 3 2 10";
+const char OID_rsaSignature[]                     = "1 3 14 3 2 11";
+const char OID_mdc2WithRSASignature[]             = "1 3 14 3 2 14";
+const char OID_shaWithRSASignature[]              = "1 3 14 3 2 15";
+const char OID_desEDE[]                           = "1 3 14 3 2 17";
+const char OID_sha[]                              = "1 3 14 3 2 18";
+const char OID_rsaKeyTransport[]                  = "1 3 14 3 2 22";
+const char OID_md2WithRSASignature[]              = "1 3 14 3 2 24";
+const char OID_md5WithRSASignature[]              = "1 3 14 3 2 25";
+const char OID_sha1[]                             = "1 3 14 3 2 26";
+const char OID_sha1WithRSASignature[]             = "1 3 14 3 2 29";
+
+const char OID_id_at_organizationName[]           = "2 5 4 10";
+const char OID_id_at_organizationalUnitName[]     = "2 5 4 11";
+const char OID_id_at_commonName[]                 = "2 5 4 3";
+const char OID_id_at_countryName[]                = "2 5 4 6";
+const char OID_id_at_localityName[]               = "2 5 4 7";
+const char OID_id_at_stateOrProvinceName[]        = "2 5 4 8";
+const char OID_id_ce_subjectDirectoryAttributes[] = "2 5 29 9";
+const char OID_id_ce_subjectKeyIdentifier[]       = "2 5 29 14";
+const char OID_id_ce_keyUsage[]                   = "2 5 29 15";
+const char OID_id_ce_privateKeyUsagePeriod[]      = "2 5 29 16";
+const char OID_id_ce_subjectAltName[]             = "2 5 29 17";
+const char OID_id_ce_issuerAltName[]              = "2 5 29 18";
+const char OID_id_ce_basicConstraints[]           = "2 5 29 19";
+const char OID_id_ce_cRLNumber[]                  = "2 5 29 20";
+const char OID_id_ce_reasonCode[]                 = "2 5 29 21";
+const char OID_id_ce_instructionCode[]            = "2 5 29 23";
+const char OID_id_ce_invalidityDate[]             = "2 5 29 24";
+const char OID_id_ce_deltaCRLIndicator[]          = "2 5 29 27";
+const char OID_id_ce_issuingDistributionPoint[]   = "2 5 29 28";
+const char OID_id_ce_certificateIssuer[]          = "2 5 29 29";
+const char OID_id_ce_nameConstraints[]            = "2 5 29 30";
+const char OID_id_ce_cRLDistributionPoints[]      = "2 5 29 31";
+const char OID_id_ce_certificatePolicies[]        = "2 5 29 32";
+const char OID_id_ce_policyMappings[]             = "2 5 29 33";
+const char OID_id_ce_policyConstraints[]          = "2 5 29 36";
+const char OID_id_ce_authorityKeyIdentifier[]     = "2 5 29 35";
+const char OID_id_ce_extKeyUsage[]                = "2 5 29 37";
+
+const char OID_sha256[]                           = "2 16 840 1 101 3 4 2 1";
+const char OID_Netscape_certificate_type[]        = "2 16 840 1 113730 1 1";
+//
+////
+
+const bool fBerPcPrimitive = false;
+const bool fBerPcConstructed = true;
+
+class BEROctet
+{
+
+public:
+    typedef std::basic_string<unsigned char> Blob;
+
+    BEROctet();
+    BEROctet(BEROctet const &oct);
+    BEROctet(Blob const &blb);
+    BEROctet(TagClass tcClass, bool fConstructed, unsigned int dwTag, bool fDefinite=true);
+    ~BEROctet();
+
+    BEROctet& operator=(BEROctet const &oct);
+
+    Blob Data() const;
+    void Data(Blob const &data);
+    std::vector<BEROctet*> SubOctetList() const;
+    void Insert(BEROctet const &oct);
+
+    Blob Octet() const;
+
+    TagClass Class() const;
+    bool Constructed() const;
+    unsigned int Tag() const;
+
+    std::string ObjectID() const;
+    void ObjectID(std::string const &str);
+
+    std::string Time() const;
+    void Time(std::string const &str);
+
+    void SearchOID(std::string const &OID, std::vector<BEROctet const*> &result) const;
+    void SearchOIDNext(std::string const &OID, std::vector<BEROctet const*> &result) const;
+
+private:
+    static Blob IdentOctets(TagClass tcClass, bool fConstructed, unsigned int dwTag);
+    static Blob LengthOctets(unsigned int dwLength);
+
+    void Decode(Blob const &blb);
+    bool Modified() const;               // =true if octet or sub-octets are modified since decoding
+
+    Blob m_blbOrigOctet;            // Original octet that was decoded
+
+    TagClass m_tcClass;                  // Tag class
+    bool m_fConstructed;                 // =true if a constructed octed, false if primitive
+    unsigned int m_dwTag;                       // Tag
+    bool m_fDefinite;                    // =true for definite form of length octet, false if indefinite
+    bool m_fModified;                    // =true if octet is modified since decoded, false otherwise
+
+    Blob m_blbData;                 // Data octets (When primitive)
+    std::vector<BEROctet*> m_SubOctetList;  // List of sub-octets (when constructed)
+
+};
+
+
+#endif // _include_beroctet_h
+
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,312 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <memory>
+#include "stdafx.h"
+#include "cardcache.h"
+#include "error.h"
+#include "log.h"
+
+
+#define KEYSPEC_KEYEXCHANGE  0x01
+#define KEYSPEC_SIGNATURE    0x02
+#define MAX_RETRY 2
+#define LOW_MEMORY_LIMIT 25000
+
+
+/* Constructor
+*/
+CardCache::CardCache( CardModuleService * mscm ) : _mscm( mscm )
+{
+   if( !mscm )
+   {
+      throw CkError( CKR_FUNCTION_FAILED );
+   }
+}
+
+/*
+*/
+void CardCache::ManageGC( void )
+{
+   try
+   {
+      if( NULL != _mscm )
+      {
+         s4 freeMemory = _mscm->GetMemory( );
+
+         if ( freeMemory < LOW_MEMORY_LIMIT )
+         {
+             //printf( "\nCardCache::ManageGC - ForceGarbageCollector\n" );
+             Log::error( "CardCache::ManageGC", "ForceGarbageCollector" );
+            _mscm->ForceGarbageCollector( );
+         }
+      }
+   }
+   catch( ... )
+   {
+   }
+}
+
+
+/* WriteFile
+Write the incoming data into the incoming pointed path into the smartcard
+and then into the cache
+*/
+void CardCache::WriteFile( std::string const & path, u1Array const & data )
+{
+   int ntry = 0;
+   while( ntry < MAX_RETRY )
+   {
+      try
+      {
+         ntry++;
+         _mscm->WriteFile( const_cast< std::string* >( &path ), const_cast< u1Array* >( &data ) );
+         ManageGC( );
+         _fileCache[ path ] = data;
+         break;
+      }
+      catch( Marshaller::Exception & x )
+      {
+         CK_RV rv = CkError::CheckMarshallerException( x );
+         if( CKR_DEVICE_MEMORY == rv )
+         {
+            Log::error( "CardCache::WriteFile", "ForceGarbageCollector" );
+           _mscm->ForceGarbageCollector( );
+            if( ntry >= MAX_RETRY )
+            {
+               _fileCache.erase( path );
+               throw CkError( rv );
+            }
+         }
+         else
+         {
+            _fileCache.erase( path );
+            throw CkError( rv );
+         }
+      }
+      catch( ... )
+      {
+         _fileCache.erase( path );
+         throw CkError( CKR_FUNCTION_FAILED );
+      }
+   }
+}
+
+
+/* ReadFile
+*/
+const u1Array & CardCache::ReadFile( std::string const & path )
+{
+   //Log::log( "***** CardCache::ReadFile - path <%s>", path.c_str( ) );
+
+   // V2+ cards may throw OutOfMemoryException from ReadFile, however
+   // it may recover from this by forcing the garbage collection to
+   // occur. In fact as a result of a ReadFile command that throws
+   // OutOfMemoryException, GC has already occured, so the command may
+   // be re-tried with high chance of success.
+
+   map<string, u1Array>::const_iterator ifile = _fileCache.find( path );
+   if( ifile == _fileCache.end( ) )
+   {
+      //Log::log( "****** CardCache::ReadFile - read card" );
+
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ntry++;
+            auto_ptr< u1Array > data( _mscm->ReadFile( const_cast< std::string* >( &path ), 0 ) );
+            ManageGC( );
+            _fileCache[ path ] = *data;
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "CardCache::ReadFile", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+         catch( ... )
+         {
+            throw CkError( CKR_FUNCTION_FAILED );
+         }
+      }
+   }
+
+   return _fileCache[ path ];
+}
+
+
+/* ClearFile
+Erase a file from the cache
+*/
+void CardCache::ClearFile( std::string const &path )
+{
+   _fileCache.erase( path );
+}
+
+
+/* ReadContainer
+Read the contained pointed by the incoming index from the smartcard
+and compute an instance into the cache
+*/
+const CardCache::Container& CardCache::ReadContainer( int const &ctrIndex ) const
+{
+   map< int, Container >::const_iterator icont = _contCache.find( ctrIndex );
+   if( icont == _contCache.end( ) )
+   {
+      try
+      {
+         Container cont;
+         auto_ptr< u1Array > cInfo( _mscm->GetCAPIContainer( ctrIndex ) );
+         u4 offset = 2;
+         for( int ikeySpec = 0; ikeySpec < 2 ; ++ikeySpec )
+         {
+            if( offset < cInfo->GetLength( ) )
+            {
+               u1 keySpec = cInfo->ReadU1At( offset );
+               offset += 2;
+               u1 expontLen = cInfo->ReadU1At( offset );
+               offset++;
+               u1Array publicExponent( expontLen );
+               memcpy( publicExponent.GetBuffer( ), cInfo->GetBuffer( ) + offset, expontLen );
+               offset += ( expontLen + 1 );
+               u4 modulusLen = cInfo->ReadU1At( offset ) << 4; // Modulus Len
+               offset++;
+               u1Array modulus( modulusLen );
+               memcpy( modulus.GetBuffer( ), cInfo->GetBuffer( ) + offset, modulusLen );
+
+               if( keySpec == KEYSPEC_KEYEXCHANGE )
+               {
+                  cont.exchModulus = modulus;
+                  cont.exchPublicExponent = publicExponent;
+               }
+               else if( keySpec == KEYSPEC_SIGNATURE )
+               {
+                  cont.signModulus = modulus;
+                  cont.signPublicExponent = publicExponent;
+               }
+               offset += modulusLen;
+               offset += 2;
+            }
+         }
+         _contCache[ ctrIndex ] = cont;
+      }
+      catch( ... )
+      {
+         _contCache[ ctrIndex ] = Container( ); // Empty
+      }
+   }
+   return _contCache[ ctrIndex ];
+}
+
+
+/* ClearContainer
+Erase the container pointed by the incoming index from the cache
+*/
+void CardCache::ClearContainer( int const &ctrIndex )
+{
+   _contCache.erase( ctrIndex );
+}
+
+
+/* FileList
+Retreive the list of the files contained into the incoming directory path
+and returns a string vectors
+*/
+const vector< std::string > & CardCache::FileList( std::string const &dir )
+{
+   map< std::string, vector< std::string > >::const_iterator idir = _fileList.find( dir );
+   if( idir == _fileList.end( ) )
+   {
+      vector< std::string > vfile;
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ntry++;
+            auto_ptr<StringArray> files( _mscm->GetFiles( const_cast<string*>( &dir ) ) );
+            ManageGC( );
+            for( u4 i = 0; i < files->GetLength( ) ; i++ )
+            {
+               vfile.push_back( *files->GetStringAt( i ) );
+            }
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "CardCache::FileList", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+         catch( ... )
+         {
+            throw CkError( CKR_FUNCTION_FAILED );
+         }
+      }
+      _fileList[ dir ] = vfile;
+   }
+
+   return _fileList[ dir ];
+}
+
+
+/* ClearFileList
+Erase the dir from the cache
+*/
+void CardCache::ClearFileList( std::string const & dir )
+{
+   _fileList.erase( dir );
+}
+
+
+/* ClearAll
+Erase all cache
+*/
+void CardCache::ClearAll( )
+{
+   _fileCache.clear( );
+   _contCache.clear( );
+   _fileList.clear( );
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cardcache.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,65 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_cardcache_h
+#define _include_cardcache_h
+
+
+#include "cardmoduleservice.h"
+
+
+#include <map>
+#include <string>
+#include <vector>
+
+class CardCache
+{
+public:
+   struct Container
+   {
+      u1Array exchPublicExponent;
+      u1Array exchModulus;
+      u1Array signPublicExponent;
+      u1Array signModulus;
+   };
+
+   CardCache(CardModuleService *  mscm);
+   void WriteFile(std::string const & path, u1Array const & data);
+   const u1Array & ReadFile(std::string const & path);
+   void ClearFile(std::string const & path);
+
+   const Container & ReadContainer( int const &ctrIndex ) const;
+   void ClearContainer(int const &ctrIndex);
+
+   const std::vector<std::string> & FileList(std::string const & dir);
+   void ClearFileList(std::string const & dir);
+
+   void ClearAll();
+
+private:
+   void ManageGC( void );
+   CardModuleService * _mscm;
+   mutable std::map<std::string, u1Array> _fileCache;
+   mutable std::map<int, Container> _contCache;
+   mutable std::map<std::string, vector<string> > _fileList;
+
+};
+
+#endif // _include_cardcache_h

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,350 @@
+// Machine generated C++ stub file (.cpp) for remote object CardModuleService
+// Created on : 06/05/2008 12:22:51
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+#include "cardmoduleservice.h"
+
+using namespace std;
+using namespace Marshaller;
+
+
+// Constructors
+CardModuleService::CardModuleService(string* uri) : SmartCardMarshaller(NULL, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(string* uri, u4 index) : SmartCardMarshaller(NULL, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, index) { return; }
+CardModuleService::CardModuleService(u2 portNumber, string* uri) : SmartCardMarshaller(NULL, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(u2 portNumber, string* uri, u4 index) : SmartCardMarshaller(NULL, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, index) { return; }
+CardModuleService::CardModuleService(string* readerName, string* uri) : SmartCardMarshaller(readerName, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(string* readerName, u2 portNumber, string* uri) : SmartCardMarshaller(readerName, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(SCARDHANDLE cardHandle, string* uri) : SmartCardMarshaller(cardHandle, 0, uri, (u4)0xC04B4E, (u2)0x7FBD) { return; }
+CardModuleService::CardModuleService(SCARDHANDLE cardHandle, u2 portNumber, string* uri) : SmartCardMarshaller(cardHandle, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD) { return; }
+
+// Extra method (Microsoft CardModule only)
+void CardModuleService::UpdateCardHandle(SCARDHANDLE cardHandle)
+{
+    UpdatePCSCCardHandle(cardHandle);
+}
+
+// Pre-defined methods
+std::string* CardModuleService::GetReader(void){return GetReaderName();}
+SCARDHANDLE CardModuleService::GetPcscCardHandle(void){return GetCardHandle();}
+void CardModuleService::DoSCardTransact(bool flag){DoTransact(flag);}
+
+// Exposed methods
+
+void CardModuleService::ChangeReferenceData(u1 mode,u1 role,u1Array* oldPin,u1Array* newPin,s4 maxTries){
+	Invoke(5, 0xE08A, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, oldPin, MARSHALLER_TYPE_IN_U1ARRAY, newPin, MARSHALLER_TYPE_IN_S4, maxTries, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+s4 CardModuleService::GetTriesRemaining(u1 role){
+	s4 _s4 = 0;
+	Invoke(1, 0x6D08, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_S4, &_s4);
+	return _s4;
+}
+
+
+void CardModuleService::CreateCAPIContainer(u1 ctrIndex,u1 keyImport,u1 keySpec,s4 keySize,u1Array* keyValue){
+	Invoke(5, 0x0234, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_BOOL, keyImport, MARSHALLER_TYPE_IN_U1, keySpec, MARSHALLER_TYPE_IN_S4, keySize, MARSHALLER_TYPE_IN_U1ARRAY, keyValue, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeleteCAPIContainer(u1 ctrIndex){
+	Invoke(1, 0xF152, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetCAPIContainer(u1 ctrIndex){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0x9B2E, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1Array* CardModuleService::PrivateKeyDecrypt(u1 ctrIndex,u1 keyType,u1Array* encryptedData){
+	u1Array* _u1Array = NULL;
+	Invoke(3, 0x6144, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, keyType, MARSHALLER_TYPE_IN_U1ARRAY, encryptedData, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::CreateFile(string* path,u1Array* acls,s4 initialSize){
+	Invoke(3, 0xBEF1, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, acls, MARSHALLER_TYPE_IN_S4, initialSize, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::CreateDirectory(string* path,u1Array* acls){
+	Invoke(2, 0xACE9, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, acls, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::WriteFile(string* path,u1Array* data){
+	Invoke(2, 0xF20E, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::ReadFile(string* path,s4 maxBytesToRead){
+	u1Array* _u1Array = NULL;
+	Invoke(2, 0x744C, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_S4, maxBytesToRead, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::DeleteFile(string* path){
+	Invoke(1, 0x6E2B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeleteDirectory(string* path){
+	Invoke(1, 0x9135, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+StringArray* CardModuleService::GetFiles(string* path){
+	StringArray* _StringArray = NULL;
+	Invoke(1, 0xE72B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_STRINGARRAY, &_StringArray);
+	return _StringArray;
+}
+
+
+u1Array* CardModuleService::GetFileProperties(string* path){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0xA01B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::ChangeAuthenticatorEx(u1 mode,u1 oldRole,u1Array* oldPin,u1 newRole,u1Array* newPin,s4 maxTries){
+	Invoke(6, 0x9967, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, oldRole, MARSHALLER_TYPE_IN_U1ARRAY, oldPin, MARSHALLER_TYPE_IN_U1, newRole, MARSHALLER_TYPE_IN_U1ARRAY, newPin, MARSHALLER_TYPE_IN_S4, maxTries, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetContainerProperty(u1 ctrIndex,u1 property,u1 flags){
+	u1Array* _u1Array = NULL;
+	Invoke(3, 0x279C, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::SetContainerProperty(u1 ctrIndex,u1 property,u1Array* data,u1 flags){
+	Invoke(4, 0x98D1, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::SetCardProperty(u1 property,u1Array* data,u1 flags){
+	Invoke(3, 0xB0E4, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+s4 CardModuleService::GetMemory(){
+	s4 _s4 = 0;
+	Invoke(0, 0x1DB4, MARSHALLER_TYPE_RET_S4, &_s4);
+	return _s4;
+}
+
+
+void CardModuleService::ForceGarbageCollector(){
+	Invoke(0, 0x3D38, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::RecursiveDelete(string* path){
+	Invoke(1, 0xEDD5, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::Select(MemoryStream* AID){
+	Invoke(1, 0x32E1, MARSHALLER_TYPE_IN_MEMORYSTREAM, AID, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::Verify(u1 P1,u1 P2,u1Array* pin){
+	Invoke(3, 0xD845, MARSHALLER_TYPE_IN_U1, P1, MARSHALLER_TYPE_IN_U1, P2, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+u1 CardModuleService::get_AdminPersonalized(){
+	u1 _u1 = 0;
+	Invoke(0, 0xCFBE, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+
+u1 CardModuleService::get_UserPersonalized(){
+	u1 _u1 = 0;
+	Invoke(0, 0xE710, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+
+u1Array* CardModuleService::GetChallenge(){
+	u1Array* _u1Array = NULL;
+	Invoke(0, 0xFA3B, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+s8 CardModuleService::get_AuthenticationDelay(){
+	s8 _s8 = 0;
+	Invoke(0, 0x5321, MARSHALLER_TYPE_RET_S8, &_s8);
+	return _s8;
+}
+
+void CardModuleService::ExternalAuthenticate(u1Array* response){
+	Invoke(1, 0x24FE, MARSHALLER_TYPE_IN_U1ARRAY, response, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::VerifyPin(u1 role,u1Array* pin){
+	Invoke(2, 0x506B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1 CardModuleService::IsAuthenticated(u1 role){
+	u1 _u1 = 0;
+	Invoke(1, 0x9B0B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+
+s4Array* CardModuleService::QueryFreeSpace(){
+	s4Array* _s4Array = NULL;
+	Invoke(0, 0x00E5, MARSHALLER_TYPE_RET_S4ARRAY, &_s4Array);
+	return _s4Array;
+}
+
+
+s4Array* CardModuleService::QueryKeySizes(){
+	s4Array* _s4Array = NULL;
+	Invoke(0, 0x5EE4, MARSHALLER_TYPE_RET_S4ARRAY, &_s4Array);
+	return _s4Array;
+}
+
+
+void CardModuleService::LogOut(u1 role){
+	Invoke(1, 0xC4E4, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+
+
+void CardModuleService::SerializeData(string* filename){
+	Invoke(1, 0x9AEA, MARSHALLER_TYPE_IN_STRING, filename, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeSerializeData(string* filename){
+	Invoke(1, 0xA373, MARSHALLER_TYPE_IN_STRING, filename, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::get_SerialNumber(){
+	u1Array* _u1Array = NULL;
+	Invoke(0, 0xD017, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+string* CardModuleService::get_Version(){
+	string* _string = NULL;
+	Invoke(0, 0xDEEC, MARSHALLER_TYPE_RET_STRING, &_string);
+	return _string;
+}
+
+
+void CardModuleService::SetHostVersion(u4 hostVersion){
+	Invoke(1, 0xD9B1, MARSHALLER_TYPE_IN_U4, hostVersion, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetChallengeEx(u1 role){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0x8F0B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1Array* CardModuleService::AuthenticateEx(u1 mode,u1 role,u1Array* pin){
+	u1Array* _u1Array = NULL;
+	Invoke(3, 0x5177, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::DeauthenticateEx(u1 roles){
+	Invoke(1, 0xBD7B, MARSHALLER_TYPE_IN_U1, roles, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetCardProperty(u1 property,u1 flags){
+	u1Array* _u1Array = NULL;
+	Invoke(2, 0x8187, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1Array* CardModuleService::BM_GetBioHeader(u1 role){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0x4838, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1 CardModuleService::BM_BioMatch(u1 role,u1Array* verificationData){
+	u1 _u1 = 0;
+	Invoke(2, 0x2D3D, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, verificationData, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+u1Array* CardModuleService::BM_GetRoles(){
+	u1Array* _u1Array = NULL;
+	Invoke(0, 0xA77A, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+u1 CardModuleService::get_BM_DefaultRole(){
+	u1 _u1 = 0;
+	Invoke(0, 0x17FD, MARSHALLER_TYPE_RET_U1, &_u1);
+	return _u1;
+}
+
+
+void CardModuleService::set_BM_DefaultRole(u1 value){
+	Invoke(1, 0x4F1E, MARSHALLER_TYPE_IN_U1, value, MARSHALLER_TYPE_RET_VOID);
+}
+
+u1 CardModuleService::get_BM_AuthPinAllowed(){
+	u1 _u1 = 0;
+	Invoke(0, 0x9063, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+string* CardModuleService::BM_GetVerifUIName(){
+	string* _string = NULL;
+	Invoke(0, 0x7BB7, MARSHALLER_TYPE_RET_STRING, &_string);
+	return _string;
+}
+
+
+string* CardModuleService::BM_GetEnrollUIName(){
+	string* _string = NULL;
+	Invoke(0, 0x0D17, MARSHALLER_TYPE_RET_STRING, &_string);
+	return _string;
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cardmoduleservice.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,98 @@
+// Machine generated C++ stub file (.h) for remote object CardModuleService
+// Created on : 06/05/2008 12:22:51
+
+
+#ifndef _include_CardModuleService_h
+#define _include_CardModuleService_h
+
+#include <string>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#include "PCSC.h"
+#include "Marshaller.h"
+
+#ifdef CardModuleService_EXPORTS
+#define CardModuleService_API __declspec(dllexport)
+#else
+#define CardModuleService_API
+#endif
+
+using namespace std;
+using namespace Marshaller;
+
+class CardModuleService_API CardModuleService : private SmartCardMarshaller {
+public:
+	// Constructors
+	CardModuleService(string* uri);
+	CardModuleService(string* uri, u4 index);
+	CardModuleService(u2 portNumber, string* uri);
+	CardModuleService(u2 portNumber, string* uri, u4 index);
+	CardModuleService(string* readerName, string* uri);
+	CardModuleService(string* readerName, u2 portNumber, string* uri);
+	CardModuleService(SCARDHANDLE cardHandle, string* uri);
+	CardModuleService(SCARDHANDLE cardHandle, u2 portNumber, string* uri);
+
+    // Extra method (Microsoft CardModule only)
+    void UpdateCardHandle(SCARDHANDLE cardHandle);
+
+	// Pre-defined methods
+	string* GetReader(void);
+	SCARDHANDLE GetPcscCardHandle(void);
+    void DoSCardTransact(bool flag);
+
+	// Exposed methods
+	void ChangeReferenceData(u1 mode,u1 role,u1Array* oldPin,u1Array* newPin,s4 maxTries);
+	s4 GetTriesRemaining(u1 role);
+	void CreateCAPIContainer(u1 ctrIndex,u1 keyImport,u1 keySpec,s4 keySize,u1Array* keyValue);
+	void DeleteCAPIContainer(u1 ctrIndex);
+	u1Array* GetCAPIContainer(u1 ctrIndex);
+	u1Array* PrivateKeyDecrypt(u1 ctrIndex,u1 keyType,u1Array* encryptedData);
+	void CreateFile(string* path,u1Array* acls,s4 initialSize);
+	void CreateDirectory(string* path,u1Array* acls);
+	void WriteFile(string* path,u1Array* data);
+	u1Array* ReadFile(string* path,s4 maxBytesToRead);
+	void DeleteFile(string* path);
+	void DeleteDirectory(string* path);
+	StringArray* GetFiles(string* path);
+	u1Array* GetFileProperties(string* path);
+	void ChangeAuthenticatorEx(u1 mode,u1 oldRole,u1Array* oldPin,u1 newRole,u1Array* newPin,s4 maxTries);
+	u1Array* GetContainerProperty(u1 ctrIndex,u1 property,u1 flags);
+	void SetContainerProperty(u1 ctrIndex,u1 property,u1Array* data,u1 flags);
+	void SetCardProperty(u1 property,u1Array* data,u1 flags);
+	s4 GetMemory();
+	void ForceGarbageCollector();
+	void RecursiveDelete(string* path);
+	void Select(MemoryStream* AID);
+	void Verify(u1 P1,u1 P2,u1Array* pin);
+	u1 get_AdminPersonalized();
+	u1 get_UserPersonalized();
+	u1Array* GetChallenge();
+	s8 get_AuthenticationDelay();
+	void ExternalAuthenticate(u1Array* response);
+	void VerifyPin(u1 role,u1Array* pin);
+	u1 IsAuthenticated(u1 role);
+	s4Array* QueryFreeSpace();
+	s4Array* QueryKeySizes();
+	void LogOut(u1 role);
+	void SerializeData(string* filename);
+	void DeSerializeData(string* filename);
+	u1Array* get_SerialNumber();
+	string* get_Version();
+	void SetHostVersion(u4 hostVersion);
+	u1Array* GetChallengeEx(u1 role);
+	u1Array* AuthenticateEx(u1 mode,u1 role,u1Array* pin);
+	void DeauthenticateEx(u1 roles);
+	u1Array* GetCardProperty(u1 property,u1 flags);
+
+	u1Array* BM_GetBioHeader(u1 role);
+	u1 BM_BioMatch(u1 role,u1Array* verificationData);
+	u1Array* BM_GetRoles();
+	u1 get_BM_DefaultRole();
+	void set_BM_DefaultRole(u1 value);
+	u1 get_BM_AuthPinAllowed();
+	string* BM_GetVerifUIName();
+	string* BM_GetEnrollUIName();
+};
+
+
+#endif

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,879 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cert_utils.h"
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+CCertUtils::CCertUtils(void)
+{
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+CCertUtils::~CCertUtils(void)
+{
+}
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::IsSequence(BYTE *content)
+{
+   return (content[0] == 0x30);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::IsInteger(BYTE *content)
+{
+   return (content[0] == 0x02);
+}
+
+
+//------------------------------------------------------------------------------
+// int ExtractContent(ASN1 *pAsn1)
+//
+// Description : Extract contents of a Asn1 block 'pAsn1->Asn1' and place it
+//              in 'pAsn1->Content'.
+//
+// Remarks     : Field Asn1.pData is allocated by calling function.
+//
+// In          : pAsn1->Asn1.pData
+//
+// Out         : This fileds are filled (if RV_SUCCESS) :
+//                - Tag
+//                - Asn1.usLen
+//                - Content.usLen
+//                - Content.pData
+//
+// Responses   : RV_SUCCESS : All is OK.
+//               RV_INVALID_DATA : Asn1 block format not supported.
+//
+//------------------------------------------------------------------------------
+int CCertUtils::ExtractContent(ASN1 *pAsn1)
+
+{
+   BYTE
+      *pData;
+   int
+      NbBytes,
+      i;
+
+   pData = pAsn1->Asn1.pData;
+
+   if ((pData[0] & 0x1F) == 0x1F)
+   {
+      // High-tag-number : not supported
+      return(RV_INVALID_DATA);
+   }
+   else
+   {
+      pAsn1->Tag = pData[0];
+   }
+
+   if (pData[1] == 0x80)
+   {
+      // Constructed, indefinite-length method : not supported
+      return(RV_INVALID_DATA);
+   }
+   else if (pData[1] > 0x82)
+   {
+      // Constructed, definite-length method : too long
+      return(RV_INVALID_DATA);
+   }
+   else if (pData[1] < 0x80)
+   {
+      // Primitive, definite-length method
+
+      pAsn1->Content.usLen = pData[1];
+      pAsn1->Content.pData = &pData[2];
+
+      pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2;
+   }
+   else
+   {
+      // Constructed, definite-length method
+
+      NbBytes = pData[1] & 0x7F;
+
+      pAsn1->Content.usLen = 0;
+      for (i = 0; i < NbBytes; i++)
+      {
+          pAsn1->Content.usLen = (pAsn1->Content.usLen << 8) + pData[2+i];
+      }
+      pAsn1->Content.pData = &pData[2+NbBytes];
+
+      pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2 + NbBytes;
+   }
+
+   return(RV_SUCCESS);
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::MemReverse(BYTE *pbOut, BYTE *pbIn, DWORD dwLen)
+{
+   DWORD i;
+
+   for (i = 0; i < dwLen; i++)
+   {
+      pbOut[i] = pbIn[dwLen - i -1];
+   }
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::ConvAscii (BYTE  *pIn,
+                          DWORD  dwLen,
+                          BYTE  *pOut
+                         )
+{
+#define tohex(x)  (((x) >= 0xA) ? ((x) - 0xA + 'A') : ((x) + '0'))
+   register DWORD i;
+
+   for(i=0; i < dwLen; i++)
+   {
+      pOut[i*2] = tohex((pIn[i] >> 4) & 0xF);
+      pOut[i*2+1] =  tohex(pIn[i] & 0xF);
+   }
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::ConvHex (BYTE  *pIn,
+                        DWORD  dwLen,
+                        BYTE  *pOut
+                       )
+{
+#define fromhex(x) (x-((x>='0')&&(x<='9')?'0':((x>='A')&&(x<='F')?'7':'W')))
+   register DWORD i;
+
+   for(i=0; i < dwLen; i+=2)
+   {
+      pOut[i/2] = (fromhex(pIn[i]) << 4) + fromhex(pIn[i+1]);
+   }
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+BYTE* CCertUtils::GetDERLength(BYTE *content, DWORD *len)
+{
+   DWORD NBBytesForLength = 0;
+   unsigned short usLen = 0,i=0;
+
+
+   if(content == NULL){
+      *len = 0;
+      return NULL;
+   }
+   if(content[1] < 0x80){
+      *len = content[1];
+      return &content[2];
+   }
+
+   NBBytesForLength = content[1] & 0x7F;
+
+   usLen = 0;
+   for (i = 0; i < NBBytesForLength; i++)
+   {
+       usLen = (usLen << 8) + content[2+i];
+   }
+
+   *len = usLen;
+   return &content[2+NBBytesForLength];
+
+}
+
+
+//------------------------------------------------------------------------------
+// bool ParseCertificateValue(BYTE *pCert,          DWORD  dwCertLen,
+//                            BYTE *pSerialNumber,  DWORD *pdwSerialNumberLen,
+//                            BYTE *pIssuer,        DWORD *pdwIssuerLen,
+//                            BYTE *pSubject,       DWORD *pdwSubjectLen
+//                           )
+//
+// In          : pCert : Value of a valid X509 certificate.
+//               dwCertLen : Length of value.
+//
+// Out         : pSerialNumber : Field 'SerialNumber'
+//               pusSerialNumberLen : Serial number length
+//               pIssuer : Field 'Issuer'
+//               pusIssuerLen : Issuer length
+//               pSubject : Field 'Subject'
+//               pusSubjectLen : Subject length
+//
+// Responses   : true: All is OK.
+//               false: Parsing fails.
+//
+//------------------------------------------------------------------------------
+bool CCertUtils::ParseCertificateValue(BYTE *pCert,         DWORD /*dwCertLen*/,
+                                       BYTE *pSerialNumber, DWORD *pdwSerialNumberLen,
+                                       BYTE *pIssuer,       DWORD *pdwIssuerLen,
+                                       BYTE *pSubject,      DWORD *pdwSubjectLen
+                                      )
+
+{
+   ASN1
+      Value,
+      tbsCert,
+      serialNumberPart,
+      signaturePart,
+      issuerPart,
+      validityPart,
+      subjectPart;
+   bool
+      bValuesToBeReturned;
+   BYTE
+      *pCurrent;
+   int
+      rv;
+   DWORD
+      SerialNumberLen,
+      IssuerLen,
+      SubjectLen;
+
+
+   bValuesToBeReturned =   (pSerialNumber != NULL)
+                        && (pIssuer != NULL)
+                        && (pSubject != NULL);
+
+
+   Value.Asn1.pData = pCert;
+   rv = ExtractContent(&Value);
+   if (rv != RV_SUCCESS) return false;
+
+   tbsCert.Asn1.pData = Value.Content.pData;
+   rv = ExtractContent(&tbsCert);
+   if (rv != RV_SUCCESS) return false;
+
+
+   pCurrent = tbsCert.Content.pData;
+   if (pCurrent[0] == TAG_OPTION_VERSION)
+   {
+      // We have A0 03 02 01 vv  where vv is the version
+      pCurrent += 5;
+   }
+
+   serialNumberPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&serialNumberPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+   signaturePart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&signaturePart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+   issuerPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&issuerPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+   validityPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&validityPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+   subjectPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&subjectPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+   SerialNumberLen = serialNumberPart.Content.usLen;
+   IssuerLen = issuerPart.Asn1.usLen;
+   SubjectLen = subjectPart.Asn1.usLen;
+
+   if (bValuesToBeReturned)
+   {
+      if (    (*pdwSerialNumberLen < SerialNumberLen)
+           || (*pdwIssuerLen < IssuerLen)
+           || (*pdwSubjectLen < SubjectLen)
+         )
+      {
+         return(false);
+      }
+      memcpy(pSerialNumber, serialNumberPart.Content.pData, SerialNumberLen);
+      memcpy(pIssuer, issuerPart.Asn1.pData, IssuerLen);
+      memcpy(pSubject, subjectPart.Asn1.pData, SubjectLen);
+      *pdwSerialNumberLen = SerialNumberLen;
+      *pdwIssuerLen = IssuerLen;
+      *pdwSubjectLen = SubjectLen;
+   }
+   else
+   {
+      *pdwSerialNumberLen = SerialNumberLen;
+      *pdwIssuerLen = IssuerLen;
+      *pdwSubjectLen = SubjectLen;
+   }
+
+   return(true);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::MakeCertificateLabel(BYTE  *pCert,
+                                      DWORD  /*dwCertLen*/,
+                                      BYTE  *pLabel,
+                                      DWORD *pdwLabelLen
+                                     )
+{
+   ASN1
+        AttributeTypePart,
+        AttributeValuePart,
+        AVA,
+        RDN,
+      Value,
+      tbsCert,
+      serialNumberPart,
+      signaturePart,
+      issuerPart,
+      validityPart,
+      subjectPart;
+    BLOC
+        OrganizationName,
+        CommonName;
+   bool
+      bValuesToBeReturned;
+   BYTE
+      *pCurrentRDN,
+      *pCurrent;
+   int
+      rv;
+
+    OrganizationName.pData = NULL;
+    OrganizationName.usLen = 0;
+    CommonName.pData = NULL;
+    CommonName.usLen = 0;
+
+    bValuesToBeReturned =   (pLabel != NULL);
+
+   Value.Asn1.pData = pCert;
+   rv = ExtractContent(&Value);
+   if (rv != RV_SUCCESS) return false;
+
+   tbsCert.Asn1.pData = Value.Content.pData;
+   rv = ExtractContent(&tbsCert);
+   if (rv != RV_SUCCESS) return false;
+
+
+   pCurrent = tbsCert.Content.pData;
+   if (pCurrent[0] == TAG_OPTION_VERSION)
+   {
+      /* We have A0 03 02 01 vv  where vv is the version                      */
+      pCurrent += 5;
+   }
+
+   serialNumberPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&serialNumberPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+   signaturePart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&signaturePart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+   issuerPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&issuerPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+   validityPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&validityPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+   subjectPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&subjectPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+    // Search field 'OrganizationName' in 'Issuer'
+   pCurrent = issuerPart.Content.pData;
+
+   while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'OrganisationName'
+            if (!memcmp("\x55\x04\x0A",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                OrganizationName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+   // If no 'OrganizationName' is 'Issuer' search for 'CommonName' in 'Subject'
+   if (OrganizationName.usLen == 0)
+   {
+      pCurrent = issuerPart.Content.pData;
+
+      while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+      {
+         RDN.Asn1.pData = pCurrent;
+         rv = ExtractContent(&RDN);
+         if (rv != RV_SUCCESS) return false;
+
+         pCurrentRDN = RDN.Content.pData;
+
+         while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+         {
+               AVA.Asn1.pData = pCurrentRDN;
+               rv = ExtractContent(&AVA);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeTypePart.Asn1.pData = AVA.Content.pData;
+               rv = ExtractContent(&AttributeTypePart);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                      + AttributeTypePart.Content.usLen;
+               rv = ExtractContent(&AttributeValuePart);
+               if (rv != RV_SUCCESS) return false;
+
+               // Search 'CommonName'
+               if (!memcmp("\x55\x04\x03",
+                              AttributeTypePart.Content.pData,
+                              AttributeTypePart.Content.usLen)
+                  )
+               {
+                  OrganizationName = AttributeValuePart.Content;
+               }
+
+               pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+         }
+
+         pCurrent = RDN.Content.pData + RDN.Content.usLen;
+      }
+   }
+
+   // Search 'CommonName' in 'Subject'
+   pCurrent = subjectPart.Content.pData;
+
+   while (pCurrent < subjectPart.Content.pData + subjectPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'CommonName'
+            if (!memcmp("\x55\x04\x03",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                CommonName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+    if (bValuesToBeReturned)
+    {
+        if (    (*pdwLabelLen < (DWORD)(OrganizationName.usLen + CommonName.usLen))
+           )
+        {
+            return(false);
+        }
+
+        if (CommonName.usLen > 0)
+        {
+           memcpy(pLabel,
+                CommonName.pData,
+                CommonName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen],
+                "'s ",
+                3
+               );
+           memcpy(&pLabel[CommonName.usLen+3],
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen],
+                " ID",
+                3
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
+        }
+        else
+        {
+           memcpy(pLabel,
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[OrganizationName.usLen],
+                " ID",
+                3
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + 3;
+        }
+    }
+    else
+    {
+        if (CommonName.usLen > 0)
+        {
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
+        }
+        else
+        {
+           *pdwLabelLen = OrganizationName.usLen + 3;
+        }
+    }
+
+    return(true);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::MakeCertificateLabelEx(BYTE  *pCert,
+                                        DWORD  /*dwCertLen*/,
+                                        BYTE  *pLabel,
+                                        DWORD *pdwLabelLen
+                                       )
+{
+   ASN1
+        AttributeTypePart,
+        AttributeValuePart,
+        AVA,
+        RDN,
+      Value,
+      tbsCert,
+      serialNumberPart,
+      signaturePart,
+      issuerPart,
+      validityPart,
+      subjectPart;
+    BLOC
+        OrganizationName,
+        CommonName;
+   bool
+      bValuesToBeReturned;
+   BYTE
+      *pCurrentRDN,
+      *pCurrent,
+      szSerialNumber[256] = "";
+   int
+      rv;
+
+    OrganizationName.pData = NULL;
+    OrganizationName.usLen = 0;
+    CommonName.pData = NULL;
+    CommonName.usLen = 0;
+
+    bValuesToBeReturned =   (pLabel != NULL);
+
+   Value.Asn1.pData = pCert;
+   rv = ExtractContent(&Value);
+   if (rv != RV_SUCCESS) return false;
+
+   tbsCert.Asn1.pData = Value.Content.pData;
+   rv = ExtractContent(&tbsCert);
+   if (rv != RV_SUCCESS) return false;
+
+
+   pCurrent = tbsCert.Content.pData;
+   if (pCurrent[0] == TAG_OPTION_VERSION)
+   {
+      /* We have A0 03 02 01 vv  where vv is the version                      */
+      pCurrent += 5;
+   }
+
+   serialNumberPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&serialNumberPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+   memset(szSerialNumber, 0x00, sizeof(szSerialNumber));
+
+   ConvAscii(serialNumberPart.Asn1.pData, serialNumberPart.Asn1.usLen, szSerialNumber);
+
+   signaturePart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&signaturePart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+   issuerPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&issuerPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+   validityPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&validityPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+   subjectPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&subjectPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+    // Search field 'OrganizationName' in 'Issuer'
+   pCurrent = issuerPart.Content.pData;
+
+   while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'OrganisationName'
+            if (!memcmp("\x55\x04\x0A",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                OrganizationName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+   // If no 'OrganizationName' is 'Issuer' search for 'CommonName' in 'Subject'
+   if (OrganizationName.usLen == 0)
+   {
+      pCurrent = issuerPart.Content.pData;
+
+      while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+      {
+         RDN.Asn1.pData = pCurrent;
+         rv = ExtractContent(&RDN);
+         if (rv != RV_SUCCESS) return false;
+
+         pCurrentRDN = RDN.Content.pData;
+
+         while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+         {
+               AVA.Asn1.pData = pCurrentRDN;
+               rv = ExtractContent(&AVA);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeTypePart.Asn1.pData = AVA.Content.pData;
+               rv = ExtractContent(&AttributeTypePart);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                      + AttributeTypePart.Content.usLen;
+               rv = ExtractContent(&AttributeValuePart);
+               if (rv != RV_SUCCESS) return false;
+
+               // Search 'CommonName'
+               if (!memcmp("\x55\x04\x03",
+                              AttributeTypePart.Content.pData,
+                              AttributeTypePart.Content.usLen)
+                  )
+               {
+                  OrganizationName = AttributeValuePart.Content;
+               }
+
+               pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+         }
+
+         pCurrent = RDN.Content.pData + RDN.Content.usLen;
+      }
+   }
+
+   // Search 'CommonName' in 'Subject'
+   pCurrent = subjectPart.Content.pData;
+
+   while (pCurrent < subjectPart.Content.pData + subjectPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'CommonName'
+            if (!memcmp("\x55\x04\x03",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                CommonName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+    if (bValuesToBeReturned)
+    {
+        if (    (*pdwLabelLen < (DWORD)(OrganizationName.usLen + CommonName.usLen))
+           )
+        {
+            return(false);
+        }
+
+        if (CommonName.usLen > 0)
+        {
+           memcpy(pLabel,
+                CommonName.pData,
+                CommonName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen],
+                "'s ",
+                3
+               );
+           memcpy(&pLabel[CommonName.usLen+3],
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen],
+                " ID - ",
+                6
+               );
+           memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen+6],
+                szSerialNumber,
+                strlen((char *)szSerialNumber)
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + (DWORD)strlen((char *)szSerialNumber) + 9;
+        }
+        else
+        {
+           memcpy(pLabel,
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[OrganizationName.usLen],
+                " ID - ",
+                6
+               );
+           memcpy(&pLabel[OrganizationName.usLen+6],
+                szSerialNumber,
+                strlen((char *)szSerialNumber)
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + (DWORD)strlen((char *)szSerialNumber) + 6;
+        }
+    }
+    else
+    {
+        if (CommonName.usLen > 0)
+        {
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + (DWORD)strlen((char *)szSerialNumber) + 9;
+        }
+        else
+        {
+           *pdwLabelLen = OrganizationName.usLen + (DWORD)strlen((char *)szSerialNumber) + 6;
+        }
+    }
+
+    return(true);
+}
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cert_utils.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,119 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#pragma once
+
+#define CERT_TYPE_UNKNOWN     (0)
+#define CERT_TYPE_USER        (1)
+#define CERT_TYPE_CA_ROOT     (2)
+
+#define CERT_USAGE_UNKNOWN    (0)
+#define CERT_USAGE_EXCHANGE   (AT_KEYEXCHANGE)
+#define CERT_USAGE_SIGNATURE  (AT_SIGNATURE)
+
+// Errors code
+#define RV_SUCCESS					0	// Info
+#define RV_COMPRESSION_FAILED		1	// Warning
+#define RV_MALLOC_FAILED			2	// Error
+#define RV_BAD_DICTIONARY			3	// Error
+#define RV_INVALID_DATA				4	// Error
+#define RV_BLOC_TOO_LONG			5	// Warning
+#define RV_FILE_OPEN_FAILED         6	// Error
+#define RV_BUFFER_TOO_SMALL         7	// Error
+
+#define TAG_OPTION_VERSION          0xA0
+
+/*------------------------------------------------------------------------------
+                          Types definitions
+------------------------------------------------------------------------------*/
+typedef unsigned char   TAG;
+typedef TAG*            TAG_PTR;
+typedef BYTE*           BYTE_PTR;
+
+typedef struct
+{
+   USHORT   usLen;
+   BYTE_PTR pData;
+} BLOC, * BLOC_PTR;
+
+typedef struct
+{
+   BLOC Asn1;
+   BLOC Content;
+   TAG  Tag;
+} ASN1, * ASN1_PTR;
+
+
+class CCertUtils
+{
+public:
+   CCertUtils(void);
+   ~CCertUtils(void);
+
+void MemReverse                 (BYTE *pbOut,
+                                 BYTE *pbIn,
+                                 DWORD dwLen
+                                );
+
+void ConvAscii                  (BYTE  *pIn,
+                                 DWORD  dwLen,
+                                 BYTE  *pOut
+                                );
+
+void ConvHex                    (BYTE  *pIn,
+                                 DWORD  dwLen,
+                                 BYTE  *pOut
+                                );
+
+BYTE *GetDERLength              (BYTE  *content,
+                                 DWORD *len
+                                );
+
+bool ParseCertificateValue      (BYTE                   *pCert,
+                                 DWORD                  dwCertLen,
+                                 BYTE                   *pSerialNumber,
+                                 DWORD                  *pdwSerialNumberLen,
+                                 BYTE                   *pIssuer,
+                                 DWORD                  *pdwIssuerLen,
+                                 BYTE                   *pSubject,
+                                 DWORD                  *pdwSubjectLen
+                                );
+
+bool MakeCertificateLabel       (BYTE                   *pCert,
+                                 DWORD                  dwCertLen,
+                                 BYTE                   *pLabel,
+                                 DWORD                  *pdwLabelLen
+                                );
+
+bool MakeCertificateLabelEx     (BYTE                   *pCert,
+                                 DWORD                  dwCertLen,
+                                 BYTE                   *pLabel,
+                                 DWORD                  *pdwLabelLen
+                                );
+
+
+private:
+int ExtractContent       (ASN1 *pAsn1);
+
+bool IsSequence          (BYTE *content);
+
+bool IsInteger           (BYTE *content);
+};
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,258 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+//#include "dbg.h"
+#include "util.h"
+
+#include "certificateobject.h"
+
+CertificateObject::CertificateObject() : StorageObject()
+{
+   this->_trusted   = CK_FALSE;
+   this->_checkSum  = NULL_PTR;
+   this->_startDate = NULL_PTR;
+   this->_endDate   = NULL_PTR;
+
+   this->_class = CKO_CERTIFICATE;
+
+   this->_ctrIndex = 0xFF;
+   this->_keySpec  = 0xFF;
+}
+
+CertificateObject::~CertificateObject()
+{
+   if(this->_checkSum != NULL_PTR)
+      delete this->_checkSum;
+
+   if(this->_startDate != NULL_PTR)
+      delete this->_startDate;
+
+   if(this->_endDate != NULL_PTR)
+      delete this->_endDate;
+
+}
+
+bool CertificateObject::IsEqual(const StorageObject * that) const
+{
+   if(_uniqueId != 0 && that->_uniqueId != 0)
+      return (_uniqueId == that->_uniqueId);
+
+   // Only objects that have been stored under p11 directory
+   // will have a non-zero _uniqueId. For other objects, do
+   // a deep comparison based on other attributes.
+   if(_class != that->_class)
+      return false;
+
+   const CertificateObject * thatCert = static_cast<const CertificateObject*>(that);
+   return ( (_ctrIndex == thatCert->_ctrIndex) &&
+      (_keySpec == thatCert->_keySpec) &&
+      (_checkValue == thatCert->_checkValue));
+}
+
+CK_BBOOL CertificateObject::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_CERTIFICATE_TYPE:
+           return (this->_certType == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_CERTIFICATE_CATEGORY:
+           return (this->_certCategory == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_TRUSTED:
+           return (this->_trusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_CHECK_VALUE:
+           return Util::CompareU1Arrays(this->_checkSum,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_START_DATE:
+           return Util::CompareU1Arrays(this->_startDate,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_END_DATE:
+           return Util::CompareU1Arrays(this->_endDate,attribute.pValue,attribute.ulValueLen);
+
+        default:
+           return StorageObject::Compare(attribute);
+   }
+}
+
+CK_RV CertificateObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   CK_RV rv = CKR_OK;
+
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   if(objCreation == CK_FALSE){
+      switch(attribute.type){
+            case CKA_CERTIFICATE_TYPE:
+            case CKA_CERTIFICATE_CATEGORY:
+               return CKR_ATTRIBUTE_READ_ONLY;
+      }
+   }
+
+   switch(attribute.type){
+
+        case CKA_CERTIFICATE_TYPE:
+           {
+              CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_certType = utemp;}
+           }
+           break;
+
+        case CKA_CERTIFICATE_CATEGORY:
+           {
+              CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_certCategory = utemp;}
+           }
+           break;
+
+        case CKA_TRUSTED:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_trusted = btemp; }
+           }
+           break;
+
+        case CKA_CHECK_VALUE:
+           if(this->_checkSum != NULL_PTR){
+              delete this->_checkSum;
+           }
+           this->_checkSum = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        case CKA_START_DATE:
+           {
+              u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){
+                 if(this->_startDate != NULL_PTR){
+                    delete this->_startDate;
+                 }
+                 this->_startDate = dtemp;
+              }
+           }
+           break;
+
+        case CKA_END_DATE:
+           {
+              u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){
+                 if(this->_endDate != NULL_PTR){
+                    delete this->_endDate;
+                 }
+                 this->_endDate = dtemp;
+              }
+           }
+           break;
+
+        default:
+           return StorageObject::SetAttribute(attribute,objCreation);
+   }
+
+   return rv;
+}
+
+CK_RV CertificateObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type){
+
+        case CKA_CERTIFICATE_TYPE:
+           return StorageObject::PutULongInAttribute(this->_certType,attribute);
+
+        case CKA_CERTIFICATE_CATEGORY:
+           return StorageObject::PutULongInAttribute(this->_certCategory,attribute);
+
+        case CKA_TRUSTED:
+           return StorageObject::PutBBoolInAttribute(this->_trusted,attribute);
+
+        case CKA_CHECK_VALUE:
+           return StorageObject::PutU1ArrayInAttribute(this->_checkSum,attribute);
+
+        case CKA_START_DATE:
+           return StorageObject::PutU1ArrayInAttribute(this->_startDate,attribute);
+
+        case CKA_END_DATE:
+           return StorageObject::PutU1ArrayInAttribute(this->_endDate,attribute);
+
+        default:
+           return StorageObject::GetAttribute(attribute);
+   }
+}
+
+void CertificateObject::Serialize(std::vector<u1> *to)
+{
+   StorageObject::Serialize(to);
+
+   Util::PushULongInVector(to,this->_certType);
+
+   Util::PushULongInVector(to,this->_certCategory);
+
+   Util::PushBBoolInVector(to,this->_trusted);
+
+   Util::PushByteArrayInVector(to,this->_startDate);
+
+   Util::PushByteArrayInVector(to,this->_endDate);
+
+   Util::PushByteArrayInVector(to,this->_checkSum);
+
+   // serialize the extra fields
+
+   PKCS11_ASSERT(_checkValue != 0);
+   PKCS11_ASSERT(_ctrIndex < 100);
+   PKCS11_ASSERT(_keySpec == 1 || _keySpec == 2 );
+
+   Util::PushULongLongInVector(to,this->_checkValue);
+
+   Util::PushBBoolInVector(to,this->_ctrIndex);
+
+   Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void CertificateObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   StorageObject::Deserialize(from,idx);
+
+   this->_certType = Util::ReadULongFromVector(from,idx);
+
+   this->_certCategory = Util::ReadULongFromVector(from,idx);
+
+   this->_trusted = Util::ReadBBoolFromVector(from,idx);
+
+   this->_startDate = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_endDate = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_checkSum = Util::ReadByteArrayFromVector(from,idx);
+
+   // serialize the extra fields
+
+   this->_checkValue = Util::ReadULongLongFromVector(from,idx);
+
+   this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+   this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/certificateobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,57 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_certificateobject_h
+#define _include_certificateobject_h
+
+#include "storageobject.h"
+
+class CertificateObject : public StorageObject{
+
+public:
+    CK_ULONG        _certType;
+    CK_BBOOL        _trusted;
+    CK_ULONG        _certCategory;
+    u1Array*        _checkSum;
+    u1Array*        _startDate;
+    u1Array*        _endDate;
+
+    // extra fields
+    std::string     _certName;
+    u8              _checkValue;
+    CK_BYTE         _ctrIndex;
+    CK_BYTE         _keySpec;
+
+public:
+    CertificateObject();
+    virtual ~CertificateObject();
+
+    virtual bool IsEqual(const StorageObject * that) const;
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/config.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/config.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/config.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,26 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_config_h
+#define _include_config_h
+
+#define CONFIG_MAX_SLOT                     16
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,132 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_digit.h"
+
+/**
+ * Computes a = b * c, where b and c are digits.
+ *
+ * Lengths: a[2].
+ */
+void NN_DigitMult (NN_DIGIT a[2], NN_DIGIT b, NN_DIGIT c)
+{
+    NN_DIGIT t, u;
+    NN_HALF_DIGIT bHigh, bLow, cHigh, cLow;
+
+    bHigh = (NN_HALF_DIGIT)HIGH_HALF (b);
+    bLow = (NN_HALF_DIGIT)LOW_HALF (b);
+    cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
+    cLow = (NN_HALF_DIGIT)LOW_HALF (c);
+
+    a[0] = (NN_DIGIT)bLow * (NN_DIGIT)cLow;
+    t = (NN_DIGIT)bLow * (NN_DIGIT)cHigh;
+    u = (NN_DIGIT)bHigh * (NN_DIGIT)cLow;
+    a[1] = (NN_DIGIT)bHigh * (NN_DIGIT)cHigh;
+
+    if ((t += u) < u)
+        a[1] += TO_HIGH_HALF (1);
+    u = TO_HIGH_HALF (t);
+
+    if ((a[0] += u) < u)
+        a[1]++;
+    a[1] += HIGH_HALF (t);
+
+    return ;
+}
+
+/**
+ * Sets a = b / c, where a and c are digits.
+ *
+ * Lengths: b[2].
+ * Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be
+ * normalized.
+ */
+void NN_DigitDiv (NN_DIGIT *a, NN_DIGIT b[2], NN_DIGIT c)
+{
+    NN_DIGIT t[2], u, v;
+    NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
+
+    cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
+    cLow = (NN_HALF_DIGIT)LOW_HALF (c);
+
+    t[0] = b[0];
+    t[1] = b[1];
+
+    /**
+     * Underestimate high half of quotient and subtract.
+     */
+    if (cHigh == MAX_NN_HALF_DIGIT)
+        aHigh = (NN_HALF_DIGIT)HIGH_HALF (t[1]);
+    else
+        aHigh = (NN_HALF_DIGIT)(t[1] / (cHigh + 1));
+
+    u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow;
+    v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh;
+    if ((t[0] -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u)))
+        t[1]--;
+    t[1] -= HIGH_HALF (u);
+    t[1] -= v;
+
+    /**
+     * Correct estimate.
+     */
+    while ((t[1] > cHigh) ||
+         ((t[1] == cHigh) && (t[0] >= TO_HIGH_HALF (cLow))))
+    {
+        if ((t[0] -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow))
+            t[1]--;
+        t[1] -= cHigh;
+        aHigh++;
+    }
+
+    /**
+     * Underestimate low half of quotient and subtract.
+     */
+    if (cHigh == MAX_NN_HALF_DIGIT)
+        aLow = (NN_HALF_DIGIT)LOW_HALF (t[1]);
+    else
+        aLow = (NN_HALF_DIGIT)((TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) / (cHigh + 1));
+
+    u = (NN_DIGIT)aLow * (NN_DIGIT)cLow;
+    v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh;
+    if ((t[0] -= u) > (MAX_NN_DIGIT - u))
+        t[1]--;
+    if ((t[0] -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v)))
+        t[1]--;
+    t[1] -= HIGH_HALF (v);
+
+    /**
+     * Correct estimate.
+     */
+    while ((t[1] > 0) || ((t[1] == 0) && t[0] >= c))
+    {
+        if ((t[0] -= c) > (MAX_NN_DIGIT - c))
+            t[1]--;
+        aLow++;
+    }
+
+    *a = TO_HIGH_HALF (aHigh) + aLow;
+
+    return ;
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_digit.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,28 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_DIGIT_H_
+#define _CR_DIGIT_H_
+
+void NN_DigitMult(NN_DIGIT [2], NN_DIGIT, NN_DIGIT) ;
+void NN_DigitDiv(NN_DIGIT *, NN_DIGIT [2], NN_DIGIT) ;
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_global.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_global.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_global.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,55 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_GLOBAL_H_
+#define _CR_GLOBAL_H_
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+typedef unsigned long int UINT4;
+
+/* Error codes.
+ */
+#define RE_CONTENT_ENCODING		0x0400
+#define RE_DATA					0x0401
+#define RE_DIGEST_ALGORITHM		0x0402
+#define RE_ENCODING				0x0403
+#define RE_KEY					0x0404
+#define RE_KEY_ENCODING			0x0405
+#define RE_LEN					0x0406
+#define RE_MODULUS_LEN			0x0407
+#define RE_NEED_RANDOM			0x0408
+#define RE_PRIVATE_KEY			0x0409
+#define RE_PUBLIC_KEY			0x040a
+#define RE_SIGNATURE			0x040b
+#define RE_SIGNATURE_ENCODING	0x040c
+#define RE_ENCRYPTION_ALGORITHM 0x040d
+
+#define R_memset(x, y, z)   memset(x, y, z)
+#define R_memcpy(x, y, z)   memcpy(x, y, z)
+#define R_memcmp(x, y, z)   memcmp(x, y, z)
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,695 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_rsa.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_digit.h"
+
+static NN_DIGIT NN_AddDigitMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
+static NN_DIGIT NN_SubDigitMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
+
+static unsigned int NN_DigitBits(NN_DIGIT);
+
+/**
+ * Decodes character string b into a, where character string is ordered
+ * from most to least significant.
+ *
+ * Lengths: a[digits], b[len].
+ * Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
+ * significant bytes are truncated.)
+ */
+void NN_Decode (NN_DIGIT *a,
+                unsigned int digits,
+                const unsigned char *b,
+                unsigned int len)
+{
+    NN_DIGIT t;
+    int j;
+    unsigned int i, u;
+
+    for (i = 0, j = len - 1; i < digits && j >= 0; i++)
+    {
+        t = 0;
+        for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
+            t |= ((NN_DIGIT)b[j]) << u;
+        a[i] = t;
+    }
+
+    for (; i < digits; i++)
+        a[i] = 0;
+
+    return ;
+}
+
+/**
+ * Encodes b into character string a, where character string is ordered
+ * from most to least significant.
+ *
+ * Lengths: a[len], b[digits].
+ * Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
+ * digits are truncated.)
+ */
+void NN_Encode (unsigned char *a,
+                unsigned int len,
+                NN_DIGIT *b,
+                unsigned int digits)
+{
+    NN_DIGIT t;
+    int j;
+    unsigned int i, u;
+
+    for (i = 0, j = len - 1; i < digits && j >= 0; i++)
+    {
+        t = b[i];
+        for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
+            a[j] = (unsigned char)(t >> u);
+    }
+
+    for (; j >= 0; j--)
+        a[j] = 0;
+
+    return ;
+}
+
+/**
+ * Assigns a = b.
+ *
+ * Lengths: a[digits], b[digits].
+ */
+void NN_Assign (NN_DIGIT *a, NN_DIGIT *b, unsigned int digits)
+{
+    unsigned int i;
+
+    for (i = 0; i < digits; i++)
+        a[i] = b[i];
+
+    return ;
+}
+
+/**
+ * Assigns a = 0.
+ *
+ * Lengths: a[digits].
+ */
+void NN_AssignZero (NN_DIGIT *a, unsigned int digits)
+{
+    unsigned int i;
+
+    for (i = 0; i < digits; i++)
+        a[i] = 0;
+
+    return ;
+}
+
+/**
+ * Assigns a = 2^b.
+ *
+ * Lengths: a[digits].
+ * Requires b < digits * NN_DIGIT_BITS.
+ */
+void NN_Assign2Exp (NN_DIGIT *a, unsigned int b, unsigned int digits)
+{
+    NN_AssignZero (a, digits);
+
+    if (b >= digits * NN_DIGIT_BITS)
+        return;
+
+    a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
+
+    return ;
+}
+
+/**
+ * Computes a = b + c. Returns carry.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ */
+NN_DIGIT NN_Add (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT ai, carry;
+    unsigned int i;
+
+    carry = 0;
+
+    for (i = 0; i < digits; i++)
+    {
+        if ((ai = b[i] + carry) < carry)
+            ai = c[i];
+        else if ((ai += c[i]) < c[i])
+            carry = 1;
+        else
+            carry = 0;
+        a[i] = ai;
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = b - c. Returns borrow.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ */
+NN_DIGIT NN_Sub (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT ai, borrow;
+    unsigned int i;
+
+    borrow = 0;
+
+    for (i = 0; i < digits; i++)
+    {
+        if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
+            ai = MAX_NN_DIGIT - c[i];
+        else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i]))
+            borrow = 1;
+        else
+            borrow = 0;
+
+        a[i] = ai;
+    }
+
+    return (borrow);
+}
+
+/**
+ * Computes a = b * c.
+ *
+ * Lengths: a[2*digits], b[digits], c[digits].
+ * Assumes digits < MAX_NN_DIGITS.
+ */
+void NN_Mult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT t[2*MAX_NN_DIGITS];
+    unsigned int bDigits, cDigits, i;
+
+    NN_AssignZero (t, 2 * digits);
+
+    bDigits = NN_Digits (b, digits);
+    cDigits = NN_Digits (c, digits);
+
+    for (i = 0; i < bDigits; i++)
+        t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
+
+    NN_Assign (a, t, 2 * digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+
+/**
+ * Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
+ *
+ * Lengths: a[digits], b[digits].
+ * Requires c < NN_DIGIT_BITS.
+ */
+NN_DIGIT NN_LShift (NN_DIGIT *a, NN_DIGIT *b, unsigned int c, unsigned int digits)
+{
+    NN_DIGIT bi, carry;
+    unsigned int i, t;
+
+    if (c >= NN_DIGIT_BITS)
+        return (0);
+
+    t = NN_DIGIT_BITS - c;
+
+    carry = 0;
+
+    for (i = 0; i < digits; i++)
+    {
+        bi = b[i];
+        a[i] = (bi << c) | carry;
+        carry = c ? (bi >> t) : 0;
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
+ *
+ * Lengths: a[digits], b[digits].
+ * Requires: c < NN_DIGIT_BITS.
+ */
+NN_DIGIT NN_RShift (NN_DIGIT *a, NN_DIGIT *b, unsigned int c, unsigned int digits)
+{
+    NN_DIGIT bi, carry;
+    int i;
+    unsigned int t;
+
+    if (c >= NN_DIGIT_BITS)
+        return (0);
+
+    t = NN_DIGIT_BITS - c;
+
+    carry = 0;
+
+    for (i = digits - 1; i >= 0; i--)
+    {
+        bi = b[i];
+        a[i] = (bi >> c) | carry;
+        carry = c ? (bi << t) : 0;
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = c div d and b = c mod d.
+ *
+ * Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
+ * Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
+ *         dDigits < MAX_NN_DIGITS.
+ */
+void NN_Div (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c,
+             unsigned int cDigits, NN_DIGIT *d, unsigned int dDigits)
+{
+    NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
+    int i;
+    unsigned int ddDigits, shift;
+
+    ddDigits = NN_Digits (d, dDigits);
+    if (ddDigits == 0)
+        return;
+
+    /**
+     * Normalize operands.
+     */
+    shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
+    NN_AssignZero (cc, ddDigits);
+    cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
+    NN_LShift (dd, d, shift, ddDigits);
+    t = dd[ddDigits-1];
+
+    NN_AssignZero (a, cDigits);
+
+    for (i = cDigits-ddDigits; i >= 0; i--)
+    {
+        /**
+         * Underestimate quotient digit and subtract.
+         */
+        if (t == MAX_NN_DIGIT)
+            ai = cc[i+ddDigits];
+        else
+            NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
+
+        cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
+
+        /**
+         * Correct estimate.
+         */
+        while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0))
+        {
+            ai++;
+            cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
+        }
+
+        a[i] = ai;
+    }
+
+    /**
+     * Restore result.
+     */
+    NN_AssignZero (b, dDigits);
+    NN_RShift (b, cc, shift, ddDigits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)cc, 0, sizeof (cc));
+    R_memset ((POINTER)dd, 0, sizeof (dd));
+
+    return ;
+}
+
+/**
+ * Computes a = b mod c.
+ *
+ * Lengths: a[cDigits], b[bDigits], c[cDigits].
+ * Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
+ */
+void NN_Mod (NN_DIGIT *a, NN_DIGIT *b, unsigned int bDigits,
+             NN_DIGIT *c, unsigned int cDigits)
+{
+    NN_DIGIT t[2 * MAX_NN_DIGITS];
+
+    NN_Div (t, a, b, bDigits, c, cDigits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+
+/**
+ * Computes a = b * c mod d.
+ *
+ * Lengths: a[digits], b[digits], c[digits], d[digits].
+ * Assumes d > 0, digits < MAX_NN_DIGITS.
+ */
+void NN_ModMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_DIGIT *d,
+                 unsigned int digits)
+{
+    NN_DIGIT t[2*MAX_NN_DIGITS];
+
+    NN_Mult (t, b, c, digits);
+    NN_Mod (a, t, 2 * digits, d, digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+
+/**
+ * Computes a = b^c mod d.
+ *
+ * Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
+ * Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
+ *
+ * NOTE:
+ * PGP 2.5's mpilib contains a faster modular exponentiation routine, mp_modexp.
+ * If USEMPILIB is defined, NN_ModExp is replaced in the PGP 2.5 sources with a
+ * stub call to mp_modexp.  If USEMPILIB is not defined, we'll get a pure (albeit
+ * slower) RSAREF implementation.
+ *
+ * The RSAREF 2.0 license, clause 1(c), permits "...modify[ing] the Program in any
+ * manner for porting or performance improvement purposes..."
+ */
+
+#ifndef USEMPILIB
+void NN_ModExp (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c,
+                unsigned int cDigits, NN_DIGIT *d,
+                unsigned int dDigits)
+{
+    NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
+    int i;
+    unsigned int ciBits, j, s;
+
+    /**
+     * Store b, b^2 mod d, and b^3 mod d.
+     */
+    NN_Assign (bPower[0], b, dDigits);
+    NN_ModMult (bPower[1], bPower[0], b, d, dDigits);
+    NN_ModMult (bPower[2], bPower[1], b, d, dDigits);
+
+    NN_ASSIGN_DIGIT (t, 1, dDigits);
+
+    cDigits = NN_Digits (c, cDigits);
+    for (i = cDigits - 1; i >= 0; i--)
+    {
+        ci = c[i];
+        ciBits = NN_DIGIT_BITS;
+
+        /**
+         * Scan past leading zero bits of most significant digit.
+         */
+        if (i == (int)(cDigits - 1))
+        {
+            while (! DIGIT_2MSB (ci))
+            {
+                ci <<= 2;
+                ciBits -= 2;
+            }
+        }
+
+        for (j = 0; j < ciBits; j += 2, ci <<= 2)
+        {
+            /**
+             * Compute t = t^4 * b^s mod d, where s = two MSB's of ci.
+             */
+            NN_ModMult (t, t, t, d, dDigits);
+            NN_ModMult (t, t, t, d, dDigits);
+
+            if ((s = DIGIT_2MSB (ci)) != 0)
+                NN_ModMult (t, t, bPower[s-1], d, dDigits);
+        }
+    }
+
+    NN_Assign (a, t, dDigits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)bPower, 0, sizeof (bPower));
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+#endif
+
+/**
+ * Compute a = 1/b mod c, assuming inverse exists.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ * Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
+ */
+void NN_ModInv (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT	q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS],
+                u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS],
+                v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS];
+    int u1Sign;
+
+    /**
+     * Apply extended Euclidean algorithm, modified to avoid negative
+     * numbers.
+     */
+    NN_ASSIGN_DIGIT (u1, 1, digits);
+    NN_AssignZero (v1, digits);
+    NN_Assign (u3, b, digits);
+    NN_Assign (v3, c, digits);
+    u1Sign = 1;
+
+    while (! NN_Zero (v3, digits))
+    {
+        NN_Div (q, t3, u3, digits, v3, digits);
+        NN_Mult (w, q, v1, digits);
+        NN_Add (t1, u1, w, digits);
+        NN_Assign (u1, v1, digits);
+        NN_Assign (v1, t1, digits);
+        NN_Assign (u3, v3, digits);
+        NN_Assign (v3, t3, digits);
+        u1Sign = -u1Sign;
+    }
+
+    /**
+     * Negate result if sign is negative.
+     */
+    if (u1Sign < 0)
+        NN_Sub (a, c, u1, digits);
+    else
+        NN_Assign (a, u1, digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)q, 0, sizeof (q));
+    R_memset ((POINTER)t1, 0, sizeof (t1));
+    R_memset ((POINTER)t3, 0, sizeof (t3));
+    R_memset ((POINTER)u1, 0, sizeof (u1));
+    R_memset ((POINTER)u3, 0, sizeof (u3));
+    R_memset ((POINTER)v1, 0, sizeof (v1));
+    R_memset ((POINTER)v3, 0, sizeof (v3));
+    R_memset ((POINTER)w, 0, sizeof (w));
+
+    return ;
+}
+
+/**
+ * Computes a = gcd(b, c).
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ * Assumes b > c, digits < MAX_NN_DIGITS.
+ */
+void NN_Gcd (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
+
+    NN_Assign (u, b, digits);
+    NN_Assign (v, c, digits);
+
+    while (! NN_Zero (v, digits))
+    {
+        NN_Mod (t, u, digits, v, digits);
+        NN_Assign (u, v, digits);
+        NN_Assign (v, t, digits);
+    }
+
+    NN_Assign (a, u, digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+    R_memset ((POINTER)u, 0, sizeof (u));
+    R_memset ((POINTER)v, 0, sizeof (v));
+}
+
+/**
+ * Returns sign of a - b.
+ *
+ * Lengths: a[digits], b[digits].
+ */
+int NN_Cmp (NN_DIGIT *a, NN_DIGIT *b, unsigned int digits)
+{
+    int i;
+
+    for (i = digits - 1; i >= 0; i--)
+    {
+        if (a[i] > b[i])
+            return (1);
+        if (a[i] < b[i])
+            return (-1);
+    }
+
+    return (0);
+}
+
+/**
+ * Returns nonzero iff a is zero.
+ *
+ * Lengths: a[digits].
+ */
+int NN_Zero (NN_DIGIT *a, unsigned int digits)
+{
+    unsigned int i;
+
+    for (i = 0; i < digits; i++)
+      if (a[i])
+        return (0);
+
+    return (1);
+}
+
+/**
+ * Returns the significant length of a in bits.
+ *
+ * Lengths: a[digits].
+ */
+unsigned int NN_Bits (NN_DIGIT *a, unsigned int digits)
+{
+    if ((digits = NN_Digits (a, digits)) == 0)
+        return (0);
+
+    return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
+}
+
+/**
+ * Returns the significant length of a in digits.
+ *
+ * Lengths: a[digits].
+ */
+unsigned int NN_Digits (NN_DIGIT *a, unsigned int digits)
+{
+    int i;
+
+    for (i = digits - 1; i >= 0; i--)
+        if (a[i])
+            break;
+
+    return (i + 1);
+}
+
+/**
+ * Computes a = b + c*d, where c is a digit. Returns carry.
+ *
+ * Lengths: a[digits], b[digits], d[digits].
+ */
+static NN_DIGIT NN_AddDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c,
+                                 NN_DIGIT *d, unsigned int digits)
+{
+    NN_DIGIT carry, t[2];
+    unsigned int i;
+
+    if (c == 0)
+        return (0);
+
+    carry = 0;
+    for (i = 0; i < digits; i++)
+    {
+        NN_DigitMult (t, c, d[i]);
+        if ((a[i] = b[i] + carry) < carry)
+            carry = 1;
+        else
+            carry = 0;
+        if ((a[i] += t[0]) < t[0])
+            carry++;
+        carry += t[1];
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = b - c*d, where c is a digit. Returns borrow.
+ *
+ * Lengths: a[digits], b[digits], d[digits].
+ */
+static NN_DIGIT NN_SubDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c,
+                                 NN_DIGIT *d, unsigned int digits)
+{
+    NN_DIGIT borrow, t[2];
+    unsigned int i;
+
+    if (c == 0)
+        return (0);
+
+    borrow = 0;
+    for (i = 0; i < digits; i++)
+    {
+        NN_DigitMult (t, c, d[i]);
+        if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
+            borrow = 1;
+        else
+            borrow = 0;
+        if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
+            borrow++;
+        borrow += t[1];
+    }
+
+    return (borrow);
+}
+
+/**
+ *  Returns the significant length of a in bits, where a is a digit.
+ */
+static unsigned int NN_DigitBits (NN_DIGIT a)
+{
+    unsigned int i;
+
+    for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)
+        if (a == 0)
+            break;
+
+    return (i);
+}
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_nn.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,147 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_NN_H_
+#define _CR_NN_H_
+
+
+/**
+ * Type definitions.
+ */
+typedef UINT4 NN_DIGIT;
+typedef UINT2 NN_HALF_DIGIT;
+
+/**
+ * Constants:
+ *
+ * Note: MAX_NN_DIGITS is long enough to hold any RSA modulus, plus
+ * one more digit as required by R_GeneratePEMKeys (for n and phiN,
+ * whose lengths must be even). All natural numbers have at most
+ * MAX_NN_DIGITS digits, except for double-length intermediate values
+ * in NN_Mult (t), NN_ModMult (t), NN_ModInv (w), and NN_Div (c).
+ */
+
+/**
+ * Length of digit in bits
+ */
+#define NN_DIGIT_BITS		32
+#define NN_HALF_DIGIT_BITS	16
+
+/**
+ * Length of digit in bytes
+ */
+#define NN_DIGIT_LEN		(NN_DIGIT_BITS / 8)
+
+/**
+ * Maximum length in digits
+ */
+#define MAX_NN_DIGITS \
+  ((MAX_RSA_MODULUS_LEN + NN_DIGIT_LEN - 1) / NN_DIGIT_LEN + 1)
+
+/**
+ *  Maximum digits
+ */
+#define MAX_NN_DIGIT		0xffffffff
+#define MAX_NN_HALF_DIGIT	0xffff
+
+/**
+ * Some macros:
+ */
+#define LOW_HALF(x) ((x) & MAX_NN_HALF_DIGIT)
+#define HIGH_HALF(x) (((x) >> NN_HALF_DIGIT_BITS) & MAX_NN_HALF_DIGIT)
+#define TO_HIGH_HALF(x) (((NN_DIGIT)(x)) << NN_HALF_DIGIT_BITS)
+#define DIGIT_MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 1)) & 1)
+#define DIGIT_2MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 2)) & 3)
+
+#define NN_ASSIGN_DIGIT(a, b, digits) {NN_AssignZero (a, digits); a[0] = b;}
+#define NN_EQUAL(a, b, digits) (! NN_Cmp (a, b, digits))
+#define NN_EVEN(a, digits) (((digits) == 0) || ! (a[0] & 1))
+
+
+/**
+ * Declaration of conversion functions:
+ *
+   NN_Decode (a, digits, b, len)   Decodes character string b into a.
+   NN_Encode (a, len, b, digits)   Encodes a into character string b.
+
+   ASSIGNMENTS
+   NN_Assign (a, b, digits)        Assigns a = b.
+   NN_ASSIGN_DIGIT (a, b, digits)  Assigns a = b, where b is a digit.
+   NN_AssignZero (a, b, digits)    Assigns a = 0.
+   NN_Assign2Exp (a, b, digits)    Assigns a = 2^b.
+
+   ARITHMETIC OPERATIONS
+   NN_Add (a, b, c, digits)        Computes a = b + c.
+   NN_Sub (a, b, c, digits)        Computes a = b - c.
+   NN_Mult (a, b, c, digits)       Computes a = b * c.
+   NN_LShift (a, b, c, digits)     Computes a = b * 2^c.
+   NN_RShift (a, b, c, digits)     Computes a = b / 2^c.
+   NN_Div (a, b, c, cDigits, d, dDigits)  Computes a = c div d and b = c mod d.
+
+   NUMBER THEORY
+   NN_Mod (a, b, bDigits, c, cDigits)  Computes a = b mod c.
+   NN_ModMult (a, b, c, d, digits) Computes a = b * c mod d.
+   NN_ModExp (a, b, c, cDigits, d, dDigits)  Computes a = b^c mod d.
+   NN_ModInv (a, b, c, digits)     Computes a = 1/b mod c.
+   NN_Gcd (a, b, c, digits)        Computes a = gcd (b, c).
+
+   OTHER OPERATIONS
+   NN_EVEN (a, digits)             Returns 1 iff a is even.
+   NN_Cmp (a, b, digits)           Returns sign of a - b.
+   NN_EQUAL (a, digits)            Returns 1 iff a = b.
+   NN_Zero (a, digits)             Returns 1 iff a = 0.
+   NN_Digits (a, digits)           Returns significant length of a in digits.
+   NN_Bits (a, digits)             Returns significant length of a in bits.
+ *
+ */
+
+/**
+ * The third parameter changed from 'unsigned char *'
+ */
+void NN_Decode(NN_DIGIT *, unsigned int, const unsigned char *, unsigned int);
+
+void NN_Encode(unsigned char *, unsigned int, NN_DIGIT *, unsigned int);
+
+void NN_Assign(NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_AssignZero(NN_DIGIT *, unsigned int);
+void NN_Assign2Exp(NN_DIGIT *, unsigned int, unsigned int);
+
+NN_DIGIT NN_Add(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+NN_DIGIT NN_Sub(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Mult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Div(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+NN_DIGIT NN_LShift(NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int);
+NN_DIGIT NN_RShift(NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int);
+
+void NN_Mod(NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+void NN_ModMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_ModExp(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+void NN_ModInv(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Gcd(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+
+int NN_Cmp(NN_DIGIT *, NN_DIGIT *, unsigned int);
+int NN_Zero(NN_DIGIT *, unsigned int);
+unsigned int NN_Bits(NN_DIGIT *, unsigned int);
+unsigned int NN_Digits(NN_DIGIT *, unsigned int);
+
+
+#endif /* _CR_NN_H_ */
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,170 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "ha_config.h"
+#include "cr_random.h"
+#include "cr_global.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "md5.h"
+
+#include "cr_rsa.h"
+
+#define RANDOM_BYTES_NEEDED 256
+
+int R_GenerateBytes(
+    unsigned char *block,				/* block			*/
+    unsigned int blockLen,				/* length of block	*/
+    R_RANDOM_STRUCT *randomStruct)		/* random structure */
+{
+    unsigned int available, i;
+
+    if (randomStruct->bytesNeeded)
+    {
+        return (RE_NEED_RANDOM);
+    }
+
+    available = randomStruct->outputAvailable;
+
+    while (blockLen > available)
+    {
+        R_memcpy( (POINTER)block,
+                  (POINTER)&randomStruct->output[16-available],
+                  available) ;
+        block += available;
+        blockLen -= available;
+
+        // Generate new output
+        CMD5* md4Ctx = new CMD5();
+        md4Ctx->HashCore(randomStruct->state,0,16);
+        md4Ctx->HashFinal(randomStruct->output);
+        delete md4Ctx;
+
+        available = 16;
+
+        /**
+         * increment state
+         */
+        for (i = 0; i < 16; i++)
+        {
+            if (randomStruct->state[15-i]++)
+                break;
+        }
+    }
+
+    R_memcpy((POINTER)block, (POINTER)&randomStruct->output[16-available], blockLen);
+    randomStruct->outputAvailable = available - blockLen;
+
+    return (0);
+}
+
+
+int R_RandomInit(R_RANDOM_STRUCT *randomStruct)
+{
+    randomStruct->bytesNeeded = RANDOM_BYTES_NEEDED;
+    R_memset ((POINTER)randomStruct->state, 0, sizeof (randomStruct->state));
+    randomStruct->outputAvailable = 0;
+
+    return (0);
+}
+
+
+int R_RandomUpdate(
+    R_RANDOM_STRUCT *randomStruct,            /* random structure			*/
+    unsigned char *block,                     /* block of values to mix in	*/
+    unsigned int blockLen)                    /* length of block			*/
+{
+    unsigned char digest[16];
+    unsigned int i, x;
+
+    CMD5* md5Ctx = new CMD5();
+    md5Ctx->HashCore(block,0,blockLen);
+    md5Ctx->HashFinal(digest);
+    delete md5Ctx;
+
+    /* add digest to state */
+    x = 0;
+    for (i = 0; i < 16; i++)
+    {
+        x += randomStruct->state[15-i] + digest[15-i];
+        randomStruct->state[15-i] = (unsigned char)x;
+        x >>= 8;
+    }
+
+    if (randomStruct->bytesNeeded < blockLen)
+        randomStruct->bytesNeeded = 0;
+    else
+        randomStruct->bytesNeeded -= blockLen;
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)digest, 0, sizeof (digest));
+    x = 0;
+
+    return (0);
+}
+
+
+int R_GetRandomBytesNeeded(
+    unsigned int *bytesNeeded,             /* number of mix-in bytes needed */
+    R_RANDOM_STRUCT *randomStruct)         /* random structure				*/
+{
+    *bytesNeeded = randomStruct->bytesNeeded;
+    return (0);
+}
+
+
+void R_RandomFinal(R_RANDOM_STRUCT *randomStruct)
+{
+    R_memset((POINTER)randomStruct, 0, sizeof (*randomStruct)) ;
+}
+
+
+/**
+ * Initialize the random structure with all zero seed bytes.
+ *
+ * NOTE: that this will cause the output of the "random" process
+ * to be the same every time. To produce random bytes, the random
+ * struct needs random seeds.
+ */
+void InitRandomStruct(R_RANDOM_STRUCT *randomStruct)
+{
+    static unsigned char seedByte = 0;
+    unsigned int bytesNeeded;
+
+    R_RandomInit (randomStruct);
+
+    /**
+     * Initialize with all zero seed bytes, which will not yield
+     * an actual random number output.
+     */
+    int iCondition = 1;
+    while( iCondition )
+    {
+        R_GetRandomBytesNeeded (&bytesNeeded, randomStruct);
+        if (bytesNeeded == 0)
+            break;
+
+        R_RandomUpdate (randomStruct, &seedByte, 1);
+    }
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_random.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,46 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_RANDOM_H_
+#define _CR_RANDOM_H_
+
+
+/**
+ * RSA Random structure.
+ */
+typedef struct {
+    unsigned int  bytesNeeded;
+    unsigned char state[16];
+    unsigned int  outputAvailable;
+    unsigned char output[16];
+} R_RANDOM_STRUCT;
+
+
+int  R_GenerateBytes(unsigned char *, unsigned int, R_RANDOM_STRUCT *);
+
+int  R_RandomInit(R_RANDOM_STRUCT *randomStruct) ;
+void InitRandomStruct(R_RANDOM_STRUCT *randomStruct) ;
+int  R_GetRandomBytesNeeded(unsigned int *bytesNeeded, R_RANDOM_STRUCT *randomStruct) ;
+int  R_RandomUpdate(R_RANDOM_STRUCT *randomStruct, unsigned char *block, unsigned int blockLen) ;
+void R_RandomFinal(R_RANDOM_STRUCT *randomStruct) ;
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,375 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_rsa.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_random.h"
+
+#include "ha_config.h"
+
+/**
+ * RSA private-key decryption, according to PKCS #1.
+ */
+int RSAPrivateDecrypt(
+    unsigned char *output,				/* output block				*/
+    unsigned int *outputLen,            /* length of output block	*/
+    unsigned char *input,               /* input block				*/
+    unsigned int inputLen,              /* length of input block	*/
+    R_RSA_PRIVATE_KEY *privateKey)      /* RSA private key			*/
+{
+    int status;
+    unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen, pkcsBlockLen;
+
+    modulusLen = (privateKey->bits + 7) / 8;
+    if (inputLen > modulusLen)
+        return (RE_LEN);
+
+    //if (status = RSAPrivateBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey))
+    status = RSAPrivateBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey);
+    if ( status )
+        return (status);
+
+    if (pkcsBlockLen != modulusLen)
+        return (RE_LEN);
+
+    /* Require block type 2.
+    */
+    if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 2))
+        return (RE_DATA);
+
+    for (i = 2; i < modulusLen-1; i++)
+    {
+        if (pkcsBlock[i] == 0)
+            break;
+    }
+
+    i++;
+    if (i >= modulusLen)
+        return (RE_DATA);
+
+    *outputLen = modulusLen - i;
+
+    if (*outputLen + 11 > modulusLen)
+        return (RE_DATA);
+
+    R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (0);
+}
+
+
+/**
+ * Raw RSA private-key operation. Output has same length as modulus.
+ *
+ * Assumes inputLen < length of modulus.
+ * Requires input < modulus.
+ */
+int RSAPrivateBlock (
+    unsigned char *output,              /* output block				*/
+    unsigned int *outputLen,            /* length of output block	*/
+    unsigned char *input,               /* input block				*/
+    unsigned int inputLen,              /* length of input block	*/
+    R_RSA_PRIVATE_KEY *privateKey)      /* RSA private key			*/
+{
+    NN_DIGIT	c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS],
+                dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS],
+                mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS],
+                q[MAX_NN_DIGITS], qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS] ;
+
+    unsigned int cDigits, nDigits, pDigits;
+    unsigned int len_Mod, len_Prime ;
+
+    len_Mod = (privateKey->bits + 7) / 8  ;
+    len_Prime = (((privateKey->bits + 1) / 2) + 7) / 8 ;
+
+    NN_Decode (c, MAX_NN_DIGITS, input, inputLen);
+    NN_Decode (n, MAX_NN_DIGITS, privateKey->modulus, len_Mod);
+    NN_Decode (p, MAX_NN_DIGITS, privateKey->prime[0], len_Prime);
+    NN_Decode (q, MAX_NN_DIGITS, privateKey->prime[1], len_Prime);
+    NN_Decode (dP, MAX_NN_DIGITS, privateKey->primeExponent[0], len_Prime);
+    NN_Decode (dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], len_Prime);
+    NN_Decode (qInv, MAX_NN_DIGITS, privateKey->coefficient, len_Prime);
+
+    cDigits = NN_Digits (c, MAX_NN_DIGITS);
+    nDigits = NN_Digits (n, MAX_NN_DIGITS);
+    pDigits = NN_Digits (p, MAX_NN_DIGITS);
+
+    if (NN_Cmp (c, n, nDigits) >= 0)
+        return (RE_DATA);
+
+    /**
+     * Compute mP = cP^dP mod p  and  mQ = cQ^dQ mod q. (Assumes q has
+     * length at most pDigits, i.e., p > q.)
+     */
+    NN_Mod (cP, c, cDigits, p, pDigits);
+    NN_Mod (cQ, c, cDigits, q, pDigits);
+    NN_ModExp (mP, cP, dP, pDigits, p, pDigits);
+    NN_AssignZero (mQ, nDigits);
+    NN_ModExp (mQ, cQ, dQ, pDigits, q, pDigits);
+
+    /**
+     * Chinese Remainder Theorem:
+     * m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ.
+     */
+    if (NN_Cmp (mP, mQ, pDigits) >= 0)
+    {
+        NN_Sub (t, mP, mQ, pDigits);
+    }
+    else
+    {
+        NN_Sub (t, mQ, mP, pDigits);
+        NN_Sub (t, p, t, pDigits);
+    }
+    NN_ModMult (t, t, qInv, p, pDigits);
+    NN_Mult (t, t, q, pDigits);
+    NN_Add (t, t, mQ, nDigits);
+
+    *outputLen = (privateKey->bits + 7) / 8;
+    NN_Encode (output, *outputLen, t, nDigits);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)c, 0, sizeof (c));
+    R_memset ((POINTER)cP, 0, sizeof (cP));
+    R_memset ((POINTER)cQ, 0, sizeof (cQ));
+    R_memset ((POINTER)dP, 0, sizeof (dP));
+    R_memset ((POINTER)dQ, 0, sizeof (dQ));
+    R_memset ((POINTER)mP, 0, sizeof (mP));
+    R_memset ((POINTER)mQ, 0, sizeof (mQ));
+    R_memset ((POINTER)p, 0, sizeof (p));
+    R_memset ((POINTER)q, 0, sizeof (q));
+    R_memset ((POINTER)qInv, 0, sizeof (qInv));
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return (0);
+}
+
+
+/**
+ * RSA public-key encryption, according to PKCS #1.
+ */
+int RSAPublicEncrypt(
+    unsigned char *output,				/* output block				*/
+    unsigned int *outputLen,			/* length of output block	*/
+    unsigned char *input,				/* input block				*/
+    unsigned int inputLen,				/* length of input block	*/
+    R_RSA_PUBLIC_KEY *publicKey,		/* RSA public key			*/
+    R_RANDOM_STRUCT *randomStruct)		/* random structure			*/
+{
+    int status;
+    unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen;
+
+    modulusLen = (publicKey->bits + 7) / 8;
+    if (inputLen + 11 > modulusLen)
+    {
+        return (RE_LEN);
+    }
+
+    /**
+     * block type 2
+     */
+    pkcsBlock[0] = 0;
+    pkcsBlock[1] = 2;
+
+    for (i = 2; i < modulusLen - inputLen - 1; i++)
+    {
+        /**
+         * Find nonzero random byte.
+         */
+        do {
+          R_GenerateBytes (&byte, 1, randomStruct);
+        } while (byte == 0);
+
+        pkcsBlock[i] = byte;
+    }
+
+    /**
+     * separator
+     */
+    pkcsBlock[i++] = 0;
+    R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
+    status = RSAPublicBlock(output, outputLen, pkcsBlock, modulusLen, publicKey);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    byte = 0;
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (status);
+}
+
+
+/**
+ * Raw RSA public-key operation. Output has same length as modulus.
+ *
+ * Assumes inputLen < length of modulus.
+ * Requires input < modulus.
+ */
+int RSAPublicBlock(
+    unsigned char *output,				/* output block				*/
+    unsigned int *outputLen,			/* length of output block	*/
+    unsigned char *input,				/* input block				*/
+    unsigned int inputLen,				/* length of input block	*/
+    R_RSA_PUBLIC_KEY *publicKey)		/* RSA public key			*/
+{
+    unsigned int eDigits, nDigits;
+    NN_DIGIT c[MAX_NN_DIGITS],
+             e[MAX_NN_DIGITS],
+             m[MAX_NN_DIGITS],
+             n[MAX_NN_DIGITS] ;
+
+    unsigned int len_Mod ;
+
+    len_Mod = (publicKey->bits + 7) / 8  ;
+
+    NN_Decode (m, MAX_NN_DIGITS, input, inputLen);
+    NN_Decode (n, MAX_NN_DIGITS, publicKey->modulus, len_Mod);
+    NN_Decode (e, MAX_NN_DIGITS, publicKey->exponent, len_Mod);
+    nDigits = NN_Digits (n, MAX_NN_DIGITS);
+    eDigits = NN_Digits (e, MAX_NN_DIGITS);
+
+    if (NN_Cmp (m, n, nDigits) >= 0)
+    {
+        return (RE_DATA);
+    }
+
+    /**
+     * Compute c = m^e mod n.
+     */
+    NN_ModExp (c, m, e, eDigits, n, nDigits);
+
+    *outputLen = (publicKey->bits + 7) / 8;
+    NN_Encode (output, *outputLen, c, nDigits);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)c, 0, sizeof (c));
+    R_memset ((POINTER)m, 0, sizeof (m));
+
+    return (0);
+}
+
+
+/**
+ * RSA public-key decryption, according to PKCS #1.
+ */
+int RSAPublicDecrypt(
+    unsigned char *output,              /* output block				*/
+    unsigned int *outputLen,            /* length of output block	*/
+    unsigned char *input,               /* input block				*/
+    unsigned int inputLen,              /* length of input block	*/
+    R_RSA_PUBLIC_KEY *publicKey)        /* RSA public key			*/
+{
+    int status;
+    unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen, pkcsBlockLen;
+
+    modulusLen = (publicKey->bits + 7) / 8;
+    if (inputLen > modulusLen)
+        return (RE_LEN);
+
+    status = RSAPublicBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey) ;
+    if (status)
+        return (status);
+
+    if (pkcsBlockLen != modulusLen)
+        return (RE_LEN);
+
+    /**
+     * Require block type 1.
+     */
+    if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1))
+        return (RE_DATA);
+
+    for (i = 2; i < modulusLen-1; i++)
+    {
+        if (pkcsBlock[i] != 0xff)
+            break;
+    }
+
+    /* separator */
+    if (pkcsBlock[i++] != 0)
+        return (RE_DATA);
+
+    *outputLen = modulusLen - i;
+
+    if (*outputLen + 11 > modulusLen)
+        return (RE_DATA);
+
+    R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (0);
+}
+
+/* RSA private-key encryption, according to PKCS #1.
+ */
+int RSAPrivateEncrypt(
+    unsigned char *output,                                      /* output block */
+    unsigned int *outputLen,                          /* length of output block */
+    unsigned char *input,                                        /* input block */
+    unsigned int inputLen,                             /* length of input block */
+    R_RSA_PRIVATE_KEY *privateKey)                           /* RSA private key */
+{
+    int status;
+    unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen;
+
+    modulusLen = (privateKey->bits + 7) / 8;
+    if (inputLen + 11 > modulusLen)
+        return (RE_LEN);
+
+    pkcsBlock[0] = 0;
+    /* block type 1 */
+    pkcsBlock[1] = 1;
+
+    for (i = 2; i < modulusLen - inputLen - 1; i++)
+    pkcsBlock[i] = 0xff;
+
+    /* separator */
+    pkcsBlock[i++] = 0;
+
+    R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
+
+    status = RSAPrivateBlock(output, outputLen, pkcsBlock, modulusLen, privateKey);
+
+    /* Zeroize potentially sensitive information.
+    */
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (status);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cr_rsa.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,157 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_RSA_H_
+#define _CR_RSA_H_
+
+#include "cr_random.h"
+
+/**
+ * RSA key lengths.
+ */
+#define MIN_RSA_MODULUS_BITS	512
+#define MAX_RSA_MODULUS_BITS	2048
+#define MAX_RSA_MODULUS_LEN		((MAX_RSA_MODULUS_BITS + 7) / 8)
+#define MAX_RSA_PRIME_BITS		((MAX_RSA_MODULUS_BITS + 1) / 2)
+#define MAX_RSA_PRIME_LEN		((MAX_RSA_PRIME_BITS + 7) / 8)
+
+
+/**
+ * RSA public key struct.
+ */
+typedef struct {
+    unsigned int bits;                           /* length in bits of modulus */
+    unsigned char modulus[MAX_RSA_MODULUS_LEN];                    /* modulus */
+    unsigned char exponent[MAX_RSA_MODULUS_LEN];           /* public exponent */
+} R_RSA_PUBLIC_KEY;
+
+
+/**
+ * RSA private key struct.
+ *
+ * The size of arrays for key should be:
+ *
+ * modulus			[MAX_RSA_MODULUS_LEN]
+ * publicExponent	[MAX_RSA_MODULUS_LEN]
+ * exponent			[MAX_RSA_MODULUS_LEN]
+ * prime[2]			[MAX_RSA_PRIME_LEN]
+ * primeExponent[2]	[MAX_RSA_PRIME_LEN]
+ * coefficient		[MAX_RSA_PRIME_LEN]
+ */
+typedef struct {
+  unsigned int bits;                           /* length in bits of modulus */
+  unsigned char modulus[MAX_RSA_MODULUS_LEN];                    /* modulus */
+  unsigned char publicExponent[MAX_RSA_MODULUS_LEN];     /* public exponent */
+  unsigned char exponent[MAX_RSA_MODULUS_LEN];          /* private exponent */
+  unsigned char prime[2][MAX_RSA_PRIME_LEN];               /* prime factors */
+  unsigned char primeExponent[2][MAX_RSA_PRIME_LEN];   /* exponents for CRT */
+  unsigned char coefficient[MAX_RSA_PRIME_LEN];          /* CRT coefficient */
+} R_RSA_PRIVATE_KEY;
+
+
+/**
+ * RSA prototype key.
+ */
+typedef struct {
+    unsigned int bits;						/* length in bits of modulus		*/
+    int useFermat4;							/* public exponent (1 = F4, 0 = 3)	*/
+} R_RSA_PROTO_KEY;
+
+
+ /**
+ * ------------------------------------------------------------------------
+ * RSA Interfaces
+ * ------------------------------------------------------------------------
+ */
+
+typedef struct
+{
+    DWORD  modulusLength;          /* length (bits) of modulus         */
+    BYTE* modulus;                /* modulus                          */
+    DWORD  publicExponentLength;   /* length (bits) of public exponent */
+    BYTE* publicExponent;         /* public exponent                  */
+} rsaPublicKey_t ;
+
+typedef struct
+{
+    DWORD  modulusLength;          /* length (bits) of modulus         */
+    BYTE* modulus;                /* modulus                          */
+    DWORD  publicExponentLength;   /* length (bits) of public exponent */
+    BYTE* publicExponent;         /* public exponent                  */
+    BYTE* privateExponent;        /* private exponent                 */
+    BYTE* prime[2];               /* prime factors                    */
+    BYTE* primeExponent[2];       /* exponents for CRT                */
+    BYTE* coefficient;            /* CRT coefficient                  */
+} rsaPrivateKey_t ;
+
+
+/**
+ * RSA function declaration for private/public key operation
+ */
+
+int RSAPrivateDecrypt(
+    unsigned char *output,                   /* output block				*/
+    unsigned int *outputLen,                 /* length of output block		*/
+    unsigned char *input,                    /* input block					*/
+    unsigned int inputLen,                   /* length of input block		*/
+    R_RSA_PRIVATE_KEY *privateKey);			 /* RSA private key				*/
+
+int RSAPrivateEncrypt(
+    unsigned char *output,                   /* output block                */
+    unsigned int *outputLen,                 /* length of output block      */
+    unsigned char *input,                    /* input block                 */
+    unsigned int inputLen,                   /* length of input block       */
+    R_RSA_PRIVATE_KEY *privateKey) ;         /* RSA private key				*/
+
+int RSAPrivateBlock(
+    unsigned char *output,                   /* output block				*/
+    unsigned int *outputLen,                 /* length of output block		*/
+    unsigned char *input,                    /* input block					*/
+    unsigned int inputLen,                   /* length of input block		*/
+    R_RSA_PRIVATE_KEY *privateKey) ;         /* RSA private key				*/
+
+
+int RSAPublicEncrypt(
+    unsigned char *output,					 /* output block				*/
+    unsigned int *outputLen,				 /* length of output block		*/
+    unsigned char *input,					 /* input block					*/
+    unsigned int inputLen,					 /* length of input block		*/
+    R_RSA_PUBLIC_KEY *publicKey,			 /* RSA public key				*/
+    R_RANDOM_STRUCT *randomStruct) ;		 /* random structure			*/
+
+
+int RSAPublicBlock(
+    unsigned char *output,					 /* output block				*/
+    unsigned int *outputLen,				 /* length of output block		*/
+    unsigned char *input,					 /* input block					*/
+    unsigned int inputLen,					 /* length of input block		*/
+    R_RSA_PUBLIC_KEY *publicKey) ;			 /* RSA public key				*/
+
+
+int RSAPublicDecrypt(
+    unsigned char *output,                    /* output block				*/
+    unsigned int *outputLen,                  /* length of output block		*/
+    unsigned char *input,                     /* input block				*/
+    unsigned int inputLen,                    /* length of input block		*/
+    R_RSA_PUBLIC_KEY *publicKey) ;            /* RSA public key				*/
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,112 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// Copied from ACS
+
+#include "stdafx.h"
+#include "critsect.h"
+
+#if !defined (_WIN32)
+#include <stdexcept>
+#endif
+
+CCriticalSection::CCriticalSection()
+{
+    Init();
+}
+
+/*
+CCriticalSection::CCriticalSection(bool)
+{
+    Init();
+}
+*/
+
+CCriticalSection::~CCriticalSection(void)
+{
+#if defined (_WIN32)
+
+    DeleteCriticalSection(&m_CriticalSection);
+
+#else
+
+    pthread_mutex_destroy(&m_Mutex);
+
+#endif
+}
+
+
+void CCriticalSection::Enter()
+{
+#if defined (_WIN32)
+
+    EnterCriticalSection(&m_CriticalSection);
+
+#else
+
+    if(pthread_equal(m_OwnerThread,pthread_self())) m_RefCount++;
+    else {
+        int Stat = pthread_mutex_lock(&m_Mutex);
+        if(Stat)
+            throw std::runtime_error("pthread_mutex_lock");
+
+        m_OwnerThread = pthread_self();
+        m_RefCount = 1;
+    }
+
+#endif
+}
+
+void CCriticalSection::Leave()
+{
+
+#if defined (_WIN32)
+
+    LeaveCriticalSection(&m_CriticalSection);
+
+#else
+
+    if(pthread_equal(m_OwnerThread,pthread_self())) {
+        m_RefCount--;
+        if(!m_RefCount) {
+            m_OwnerThread = 0;
+            pthread_mutex_unlock(&m_Mutex);
+        }
+    }
+
+#endif
+
+    return;
+}
+
+void CCriticalSection::Init()
+{
+#if defined (_WIN32)
+
+	InitializeCriticalSection(&m_CriticalSection);
+
+#else
+
+    pthread_mutex_init(&m_Mutex,0);
+    m_OwnerThread = 0;
+    m_RefCount = 0;
+
+#endif
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/critsect.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,95 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// Copied from ACS
+
+#ifndef _include_critsect_h
+#define _include_critsect_h
+
+#if defined(_WIN32)
+
+#include <windows.h>
+
+#else
+
+#include <pthread.h>
+
+#endif
+
+class CCriticalSection
+{
+
+public:
+
+    // A non-default constructor with a dummy parameter is added since
+    // it is needed when CCriticalSection is used as static member in
+    // template classes to instantiate properly with GCC. See for instance
+    // http://gcc.gnu.org/ml/gcc-bugs/2005-01/msg03798.html
+
+    CCriticalSection();
+    //explicit CCriticalSection(bool dummy);
+    ~CCriticalSection();
+    void Enter();
+    void Leave();
+
+private:
+    void Init();
+
+#if defined(_WIN32)
+
+	CRITICAL_SECTION m_CriticalSection;
+
+#else
+
+    pthread_mutex_t m_Mutex;
+    pthread_t m_OwnerThread;
+    unsigned long m_RefCount;
+
+#endif
+
+};
+
+// Convenience class to manage locking
+
+class CCriticalSectionLocker
+{
+public:
+    CCriticalSectionLocker(CCriticalSection & cs) : m_cs(&cs)
+    {
+        m_cs->Enter();
+    }
+    CCriticalSectionLocker(CCriticalSection * cs) : m_cs(cs)
+    {
+        if(m_cs)
+            m_cs->Enter();
+    }
+   ~CCriticalSectionLocker()
+    {
+        if(m_cs)
+            m_cs->Leave();
+    }
+
+private:
+    CCriticalSection * m_cs;
+};
+
+
+#endif // _include_critsect_h
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,175 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+#include "dataobject.h"
+
+DataObject::DataObject() : StorageObject()
+{
+   this->_class    = CKO_DATA;
+   this->_appName  = NULL_PTR;
+   this->_objId    = NULL_PTR;
+   this->_objValue = NULL_PTR;
+}
+
+DataObject::~DataObject(){
+
+   if(this->_appName != NULL_PTR){
+      delete this->_appName;
+   }
+
+   if(this->_objId != NULL_PTR){
+      delete this->_objId;
+   }
+
+   if(this->_objValue != NULL_PTR){
+      delete this->_objValue;
+   }
+}
+
+CK_BBOOL DataObject::Compare(CK_ATTRIBUTE attribute)
+{
+   CK_BBOOL bRet = CK_FALSE;
+
+   switch(attribute.type)
+   {
+   case CKA_APPLICATION:
+      bRet = Util::CompareU1Arrays(this->_appName,attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_OBJECT_ID:
+      bRet = Util::CompareU1Arrays(this->_objId,attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_VALUE:
+      bRet = Util::CompareU1Arrays(this->_objValue,attribute.pValue,attribute.ulValueLen);
+      break;
+
+   default:
+      bRet = StorageObject::Compare( attribute );
+      break;
+   }
+
+   return bRet;
+}
+
+CK_RV DataObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+   switch(attribute.type){
+
+        case CKA_APPLICATION:
+           {
+              u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){
+                 if(this->_appName != NULL_PTR){
+                    delete this->_appName;
+                 }
+                 this->_appName = stemp;
+              }
+           }
+           break;
+
+
+        case CKA_OBJECT_ID:
+           if(this->_objId != NULL_PTR){
+              delete this->_objId;
+           }
+           this->_objId = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        case CKA_VALUE:
+           if(this->_objValue != NULL_PTR){
+              delete this->_objValue;
+           }
+           this->_objValue = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        default:
+           return StorageObject::SetAttribute(attribute,objCreation);
+
+   }
+
+   return rv;
+}
+
+CK_RV DataObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   CK_RV ulRet = CKR_OK;
+   switch(attribute->type)
+   {
+   case CKA_APPLICATION:
+      ulRet = StorageObject::PutU1ArrayInAttribute(this->_appName,attribute);
+      break;
+
+   case CKA_OBJECT_ID:
+      ulRet = StorageObject::PutU1ArrayInAttribute(this->_objId,attribute);
+      break;
+
+   case CKA_VALUE:
+      ulRet = StorageObject::PutU1ArrayInAttribute(this->_objValue,attribute);
+      break;
+
+   default:
+      ulRet = StorageObject::GetAttribute(attribute);
+      break;
+   }
+
+   return ulRet;
+}
+
+
+void DataObject::Serialize(std::vector<u1>* to)
+{
+   // first go ahead and serialize the fields in base class
+   StorageObject::Serialize(to);
+
+   // serialize label attribute
+   Util::PushByteArrayInVector(to,this->_appName);
+
+   // serialize label attribute
+   Util::PushByteArrayInVector(to,this->_objId);
+
+   // serialize label attribute
+   Util::PushByteArrayInVector(to,this->_objValue);
+}
+
+void DataObject::Deserialize(std::vector<u1> from,CK_ULONG_PTR idx)
+{
+   // first go ahead and de-serialize the fields in base class
+   StorageObject::Deserialize(from,idx);
+
+   this->_appName = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_objId = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_objValue = Util::ReadByteArrayFromVector(from,idx);
+}
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/dataobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,51 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_dataobject_h
+#define _include_dataobject_h
+
+#include "storageobject.h"
+
+class DataObject : public StorageObject
+{
+
+public:
+    u1Array* _appName;
+    u1Array* _objId;
+    u1Array* _objValue;
+
+public:
+
+    DataObject();
+    virtual ~DataObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+
+};
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/des.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/des.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/des.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,54 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+#include "des.h"
+
+CDES::CDES(){
+    this->_blockSize = 8;
+}
+
+CDES::~CDES(){
+}
+
+void CDES::TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                  CK_BYTE_PTR input,CK_LONG input_offset,
+                                  CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    // encryprtMode == ENCRYPT then we need to XOR input with iv
+    if(iv != NULL_PTR && this->_encryptMode == ENCRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            input[input_offset+i] ^= iv[i];
+        }
+    }
+
+    algo_DES_DESProcess(key,&input[input_offset],&output[output_offset],(u1)encryptMode);
+
+    if(iv != NULL_PTR && this->_encryptMode == DECRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            output[output_offset+i] ^= iv[i];
+        }
+    }
+
+
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/des.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/des.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/des.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,42 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_des_h
+#define _include_des_h
+
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+class CDES : public CSymmAlgo
+{
+
+public:
+    CDES();
+    ~CDES();
+
+private:
+    void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                   CK_BYTE_PTR input,CK_LONG input_offset,
+                                   CK_BYTE_PTR output,CK_LONG output_offset);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/digest.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/digest.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/digest.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,74 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+
+CDigest::CDigest(){
+    this->_counter       = 0;
+    this->_workingOffset = 0;
+    this->_workingLength = 0;
+}
+
+CDigest::~CDigest(){
+    free(this->_hashValue);
+    free(this->_workingBuffer);
+}
+
+void CDigest::HashCore(CK_BYTE_PTR data,CK_LONG offset,CK_LONG count)
+{
+    while (count > 0)
+    {
+        // prepare working buffer.
+        if ((_workingOffset + count) >= this->_blockLength){
+            _workingLength = this->_blockLength - _workingOffset;
+        }
+        else{
+            _workingLength = count;
+        }
+
+        memcpy(&_workingBuffer[_workingOffset],&data[offset],_workingLength);
+
+        _workingOffset += _workingLength;
+        count -= _workingLength;
+        offset += _workingLength;
+
+        if ((_workingOffset == this->_blockLength) && (count > 0)){
+
+            TransformBlock(_workingBuffer,_counter,_hashValue);
+
+            _counter += this->_blockLength;
+            _workingOffset = 0;
+        }
+    }
+}
+
+void CDigest::HashFinal(CK_BYTE_PTR hash)
+{
+    TransformFinalBlock(_workingBuffer,_workingOffset,_counter,_hashValue);
+    memcpy(hash,_hashValue,this->_hashLength);
+}
+
+CK_LONG CDigest::HashLength(void)
+{
+    return this->_hashLength;
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/digest.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/digest.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/digest.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,49 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_digest_h
+#define _include_digest_h
+
+class CDigest
+{
+protected:
+    CK_BYTE_PTR  _workingBuffer;
+    CK_LONG      _workingOffset;
+    CK_LONG      _workingLength;
+    CK_LONG      _counter;
+    CK_BYTE_PTR  _hashValue;
+    CK_LONG      _hashLength;
+    CK_LONG      _blockLength;
+
+    virtual void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result) = 0;
+    virtual void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result) = 0;
+
+public:
+    CDigest();
+    virtual ~CDigest();
+
+    void HashCore(CK_BYTE_PTR data,CK_LONG offset,CK_LONG count);
+    void HashFinal(CK_BYTE_PTR hash);
+    CK_LONG HashLength(void);
+};
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/error.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/error.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/error.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,340 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "error.h"
+#include "log.h"
+
+
+#define ERROR_MEMORY "Persistent"
+
+
+/* CheckMarshallerException
+*/
+CK_RV CkError::CheckMarshallerException( Marshaller::Exception &x )
+{
+   UnauthorizedAccessException* uae = dynamic_cast< UnauthorizedAccessException* >( &x );
+   if( uae )
+   {
+      Log::log( "CheckMarshallerException", "## Error ## UnauthorizedAccessException <%s>", x.what( ) );
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   OutOfMemoryException* oome = dynamic_cast< OutOfMemoryException* >( &x );
+   if( oome )
+   {
+      Log::log( "CheckMarshallerException", "## Error ## OutOfMemoryException <%s>", x.what( ) );
+      return CKR_DEVICE_MEMORY;
+   }
+
+   if( NULL != x.what( ) )
+   {
+      if( 0 == strcmp( x.what( ), ERROR_MEMORY ) )
+      {
+         Log::log( "CheckMarshallerException", "## Error ## OutOfMemoryException %s <%s>", ERROR_MEMORY, x.what( ) );
+         return CKR_DEVICE_MEMORY;
+      }
+   }
+
+   {
+      DirectoryNotFoundException * e = dynamic_cast<DirectoryNotFoundException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## DirectoryNotFoundException <%s>", x.what( ) );
+         return CKR_TOKEN_NOT_RECOGNIZED;
+      }
+   }
+   {
+      FileNotFoundException * e = dynamic_cast<FileNotFoundException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## FileNotFoundException <%s>", x.what( ) );
+         return CKR_TOKEN_NOT_RECOGNIZED;
+      }
+   }
+   {
+      IOException * e = dynamic_cast<IOException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## IOException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      RemotingException * e = dynamic_cast<RemotingException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## RemotingException <%s>", x.what( ) );
+         return CKR_TOKEN_NOT_PRESENT;
+      }
+   }
+
+   {
+      CryptographicException * e = dynamic_cast<CryptographicException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## CryptographicException <%s>", x.what( ) );
+         return CKR_DEVICE_MEMORY;
+      }
+   }
+
+   {
+      SystemException * e = dynamic_cast<SystemException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## SystemException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArgumentException * e = dynamic_cast<ArgumentException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArgumentException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArgumentNullException * e = dynamic_cast<ArgumentNullException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArgumentNullException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArgumentOutOfRangeException * e = dynamic_cast<ArgumentOutOfRangeException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArgumentOutOfRangeException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      IndexOutOfRangeException * e = dynamic_cast<IndexOutOfRangeException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## IndexOutOfRangeException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      InvalidCastException * e = dynamic_cast<InvalidCastException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## InvalidCastException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      InvalidOperationException * e = dynamic_cast<InvalidOperationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## InvalidOperationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      NotImplementedException * e = dynamic_cast<NotImplementedException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## NotImplementedException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      NotSupportedException * e = dynamic_cast<NotSupportedException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## NotSupportedException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      NullReferenceException * e = dynamic_cast<NullReferenceException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## NullReferenceException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ObjectDisposedException * e = dynamic_cast<ObjectDisposedException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ObjectDisposedException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ApplicationException * e = dynamic_cast<ApplicationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ApplicationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArithmeticException * e = dynamic_cast<ArithmeticException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArithmeticException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArrayTypeMismatchException * e = dynamic_cast<ArrayTypeMismatchException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArrayTypeMismatchException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      BadImageFormatException * e = dynamic_cast<BadImageFormatException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## BadImageFormatException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      DirectoryNotFoundException * e = dynamic_cast<DirectoryNotFoundException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## DirectoryNotFoundException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      DivideByZeroException * e = dynamic_cast<DivideByZeroException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## DivideByZeroException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      FormatException * e = dynamic_cast<FormatException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## FormatException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      RankException * e = dynamic_cast<RankException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## RankException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      RemotingException * e = dynamic_cast<RemotingException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## RemotingException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      StackOverflowException * e = dynamic_cast<StackOverflowException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## StackOverflowException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      TypeLoadException * e = dynamic_cast<TypeLoadException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## TypeLoadException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MemberAccessException * e = dynamic_cast<MemberAccessException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MemberAccessException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MissingFieldException * e = dynamic_cast<MissingFieldException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MissingFieldException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MissingMemberException * e = dynamic_cast<MissingMemberException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MissingMemberException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MissingMethodException * e = dynamic_cast<MissingMethodException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MissingMethodException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      OverflowException * e = dynamic_cast<OverflowException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## OverflowException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      SecurityException * e = dynamic_cast<SecurityException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## SecurityException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      VerificationException * e = dynamic_cast<VerificationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## VerificationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      SerializationException * e = dynamic_cast<SerializationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## SerializationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+
+   return CKR_FUNCTION_FAILED;
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/error.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/error.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/error.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,62 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_error_h
+#define _include_error_h
+
+#include <string>
+#include <stdexcept>
+#include "cardmoduleservice.h"
+#include "platconfig.h"
+#include "Except.h"
+
+class PcscError : public std::runtime_error
+{
+public:
+    PcscError() : std::runtime_error(""), _err(0) {}
+    PcscError(unsigned long err) : std::runtime_error(""), _err(err) {}
+    PcscError(const std::string & message, unsigned long err = 0) : std::runtime_error(message), _err(err) {}
+
+    unsigned long Error() const {return _err;}
+
+private:
+    unsigned long _err;
+
+};
+
+
+class CkError : public std::runtime_error
+{
+public:
+    CkError() : std::runtime_error(""), _err(0) {}
+    CkError(CK_RV err) : std::runtime_error(""), _err(err) {}
+    CkError(const std::string & message, unsigned long err = 0) : std::runtime_error(message), _err(err) {}
+
+    CK_RV Error() const {return _err;}
+
+    static CK_RV CheckMarshallerException( Marshaller::Exception & x );
+
+private:
+    unsigned long _err;
+
+};
+
+#endif // _include_error_h
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/event.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/event.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/event.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,141 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+//#include "dbg.h"
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/time.h>
+#endif
+#include "event.h"
+
+CEvent::CEvent(CK_ULONG timeOut)
+{
+	#ifdef WIN32
+    m_eventHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
+    #else
+    pthread_mutex_init(&m_Mutex,0);
+    pthread_cond_init(&m_Condition,0);
+    #endif
+    m_timeOut     = timeOut;
+}
+
+CEvent::~CEvent(void)
+{
+	#ifdef WIN32
+    CloseHandle(m_eventHandle);
+    #else
+    pthread_mutex_destroy(&m_Mutex);
+    pthread_cond_destroy(&m_Condition);
+    #endif
+}
+
+void CEvent::Signal()
+{
+	#ifdef WIN32
+
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    PulseEvent(m_eventHandle);
+
+    #else
+
+    if(pthread_cond_broadcast(&m_Condition) == 0)
+    {
+    	//assert(FALSE);
+    }
+
+    #endif
+
+}
+
+void CEvent::Set()
+{
+	#ifdef WIN32
+
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    SetEvent(m_eventHandle);
+
+    #else
+
+    if(pthread_cond_signal( &m_Condition ) != 0)
+    {
+    	//assert(FALSE);
+    }
+
+
+    #endif
+}
+
+void CEvent::Reset()
+{
+	#ifdef WIN32
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    ResetEvent(m_eventHandle);
+    #endif
+}
+
+void CEvent::Wait()
+{
+	#ifdef WIN32
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    DWORD rv = WaitForSingleObject(m_eventHandle,m_timeOut);
+
+    if(rv == WAIT_TIMEOUT)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    #else
+
+    struct timeval CurrTime;
+
+    gettimeofday(&CurrTime, NULL);
+
+    timespec Abstime;
+
+    // Calculate absolute time to time out.
+
+    Abstime.tv_sec = CurrTime.tv_sec + m_timeOut/1000;
+    Abstime.tv_nsec = CurrTime.tv_usec*1000 + (m_timeOut % 1000)*1000000;
+
+    if(Abstime.tv_nsec>999999999) {
+        Abstime.tv_sec++;
+        Abstime.tv_nsec -= 1000000000;
+    }
+
+    if(pthread_cond_timedwait(&m_Condition,&m_Mutex,&Abstime) == 0)
+    {
+    	//assert(FALSE);
+    }
+
+    #endif
+}
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/event.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/event.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/event.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,57 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_event_h
+#define _include_event_h
+
+#ifdef INCLUDE_EVENTING
+
+class CEvent
+{
+
+private:
+    #ifdef WIN32
+    HANDLE      m_eventHandle;
+    #else
+    pthread_mutex_t m_Mutex;
+    pthread_cond_t  m_Condition;
+    #endif
+    CK_ULONG    m_timeOut;
+
+public:
+    CEvent(CK_ULONG timeOut);
+    ~CEvent(void);
+
+    void Signal(void);
+    void Set(void);
+    void Reset(void);
+    void Wait(void);  // Throws CK_RV exception on error
+
+    #ifdef WIN32
+    HANDLE GetHandle() { return m_eventHandle;}
+    #endif
+};
+
+extern CEvent CryptokiEvent;
+
+#endif
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/ha_config.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/ha_config.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/ha_config.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,42 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _HA_CONFIG_H_
+#define _HA_CONFIG_H_
+
+/**
+ * Global typedefs for use in various Host Agent components.
+ * TODO: Choose a single set and use it consistently.
+ */
+
+typedef signed char     s8_t;
+typedef signed short    s16_t;
+typedef signed long     s32_t;
+
+typedef unsigned char   u8_t ;
+typedef unsigned short  u16_t ;
+typedef unsigned long   u32_t ;
+
+typedef unsigned char   u1 ;
+typedef unsigned short  u2 ;
+typedef unsigned int    u4 ;
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,258 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "keyobject.h"
+
+KeyObject::KeyObject() : StorageObject()
+{
+    this->_keyType          = 0;
+    this->_id               = NULL_PTR;
+    this->_startDate        = NULL_PTR;
+    this->_endDate          = NULL_PTR;
+    this->_allowedMechanism = NULL_PTR;
+
+    this->_local         = CK_FALSE;
+    this->_mechanismType = CK_UNAVAILABLE_INFORMATION;//-1;
+}
+
+KeyObject::~KeyObject()
+{
+    if(this->_startDate != NULL_PTR){
+        delete this->_startDate;
+    }
+
+    if(this->_endDate != NULL_PTR){
+        delete this->_endDate;
+    }
+
+    if(this->_id != NULL_PTR){
+        delete this->_id;
+    }
+}
+
+CK_BBOOL KeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type)
+    {
+        case CKA_KEY_TYPE:
+            return (this->_keyType == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_ID:
+            return Util::CompareU1Arrays(this->_id,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_START_DATE:
+            return Util::CompareU1Arrays(this->_startDate,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_END_DATE:
+            return Util::CompareU1Arrays(this->_endDate,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_LOCAL:
+            return (this->_local == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_DERIVE:
+            return (this->_derive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_MECHANISM_TYPE:
+            return (this->_mechanismType == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_ALLOWED_MECHANISMS:
+            return Util::CompareU4Arrays(this->_allowedMechanism,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return StorageObject::Compare(attribute);
+
+    }
+}
+
+CK_RV KeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_KEY_TYPE:
+            case CKA_LOCAL:
+            case CKA_MECHANISM_TYPE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+
+        case CKA_KEY_TYPE:
+            {
+                CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_keyType = utemp;}
+            }
+            break;
+
+        case CKA_ID:
+            if(this->_id != NULL_PTR){
+                delete this->_id;
+            }
+            this->_id = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_START_DATE:
+            {
+                u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_startDate != NULL_PTR){
+                        delete this->_startDate;
+                    }
+                    this->_startDate = dtemp;
+                }
+            }
+            break;
+
+        case CKA_END_DATE:
+           {
+                u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_endDate != NULL_PTR){
+                        delete this->_endDate;
+                    }
+                    this->_endDate = dtemp;
+                }
+            }
+            break;
+
+        case CKA_LOCAL:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_local = btemp; }
+            }
+            break;
+
+        case CKA_DERIVE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_derive = btemp; }
+            }
+            break;
+
+        case CKA_MECHANISM_TYPE:
+            {
+                CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_mechanismType = utemp;}
+            }
+            break;
+
+        case CKA_ALLOWED_MECHANISMS:
+            if(this->_allowedMechanism != NULL_PTR){
+                delete this->_allowedMechanism;
+            }
+            this->_allowedMechanism = new u4Array(attribute.ulValueLen/4);
+            memcpy((u1*)this->_allowedMechanism->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+            break;
+
+        default:
+            return StorageObject::SetAttribute(attribute,objCreation);
+
+    }
+
+    return rv;
+}
+
+CK_RV KeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type)
+    {
+        case CKA_KEY_TYPE:
+            return StorageObject::PutULongInAttribute(this->_keyType,attribute);
+
+        case CKA_ID:
+            return StorageObject::PutU1ArrayInAttribute(this->_id,attribute);
+
+        case CKA_START_DATE:
+            return StorageObject::PutU1ArrayInAttribute(this->_startDate,attribute);
+
+        case CKA_END_DATE:
+            return StorageObject::PutU1ArrayInAttribute(this->_endDate,attribute);
+
+        case CKA_LOCAL:
+            return StorageObject::PutBBoolInAttribute(this->_local,attribute);
+
+        case CKA_DERIVE:
+            return StorageObject::PutBBoolInAttribute(this->_derive,attribute);
+
+        case CKA_MECHANISM_TYPE:
+            return StorageObject::PutULongInAttribute(this->_mechanismType,attribute);
+
+        case CKA_ALLOWED_MECHANISMS:
+            return StorageObject::PutU4ArrayInAttribute(this->_allowedMechanism,attribute);
+
+        default:
+            return StorageObject::GetAttribute(attribute);
+    }
+}
+
+void KeyObject::Serialize(std::vector<u1> *to)
+{
+    StorageObject::Serialize(to);
+
+    Util::PushULongInVector(to,this->_keyType);
+
+    Util::PushByteArrayInVector(to,this->_id);
+
+    Util::PushByteArrayInVector(to,this->_startDate);
+
+    Util::PushByteArrayInVector(to,this->_endDate);
+
+    Util::PushBBoolInVector(to,this->_local);
+
+    Util::PushBBoolInVector(to,this->_derive);
+
+    Util::PushULongInVector(to,this->_mechanismType);
+
+    Util::PushIntArrayInVector(to,this->_allowedMechanism);
+}
+
+void KeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    StorageObject::Deserialize(from,idx);
+
+    this->_keyType = Util::ReadULongFromVector(from,idx);
+
+    this->_id = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_startDate = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_endDate = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_local = Util::ReadBBoolFromVector(from,idx);
+
+    this->_derive = Util::ReadBBoolFromVector(from,idx);
+
+    this->_mechanismType = Util::ReadULongFromVector(from,idx);
+
+    this->_allowedMechanism = Util::ReadIntArrayFromVector(from,idx);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/keyobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,52 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_keyobject_h
+#define _include_keyobject_h
+
+#include "storageobject.h"
+
+class KeyObject : public StorageObject
+{
+public:
+    CK_ULONG    _keyType;
+    u1Array*    _id;
+    u1Array*    _startDate;
+    u1Array*    _endDate;
+    CK_BBOOL    _derive;
+    CK_BBOOL    _local;
+    CK_ULONG    _mechanismType;
+    u4Array*    _allowedMechanism;
+
+public:
+    KeyObject();
+    virtual ~KeyObject();
+
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/log.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/log.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/log.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,2207 @@
+
+/* ---------------- Gemalto Debug -------------- */
+
+
+#include <string.h>
+#include "log.h"
+
+
+// Define to unable if you want to activate trace into the code or at compilation time
+//#define __DEBUG_GEMALTO__
+
+#ifdef WIN32
+#include <windows.h>
+#define LOG_FILE_NAME "c:\\Gemalto.NET.PKCS11.log"
+#else
+#define LOG_FILE_NAME "/tmp/Gemalto.NET.PKCS11.log"
+#endif
+
+
+#define T_BOOL 0
+#define T_BYTES 1
+#define T_LONG 2
+#define T_KEY_TYPE 3
+#define T_CERTIFICATE_TYPE 4
+#define T_CLASS 5
+#define T_DATE 6
+#define T_KEY_GEN_MECHANISM 7
+#define T_UNKNOWN 8
+
+unsigned long Log::m_ulStart = 0;
+
+/* Log a message into the log file
+*/
+void Log::log( const char * format, ... )
+{
+#ifdef __DEBUG_GEMALTO__
+   // Try to open the file
+   FILE* pLog = fopen( LOG_FILE_NAME, "a" );
+   if( NULL == pLog )
+   {
+      // The file does not exit. Nothing to log
+      return;
+   }
+
+   // Write the message to the log file
+   va_list args;
+   va_start( args, format );
+   vfprintf( pLog, format, args );
+   va_end( args );
+   fprintf(pLog, "\n");
+
+#ifndef WIN32
+   // Write the message to stderr stream
+   va_start( args, format );
+	vfprintf( stderr, format, args );
+   va_end( args );
+	fprintf( stderr, "\n");
+#else
+   // Get the size of the buffer necessary to write the message
+   // The size must be extended to include the '\n' and the '\0' characters.
+   va_start( args, format );
+   size_t len = _vscprintf( format, args );
+   va_end( args );
+
+   // Allocate the buffer for the message
+   char *buffer = new char[ len + 2 ];
+   memset( buffer, '\0', len + 2 );
+
+   // Write the message into the buffer.
+   va_start( args, format );
+   vsprintf_s( buffer, len + 1, format, args );
+   va_end( args );
+   buffer[ len ] = '\n';
+
+   // Write the message to the console
+   OutputDebugString( buffer );
+
+   // Release the buffer
+   delete[] buffer;
+#endif
+
+   va_end( args );
+
+   // Close the file
+   fclose( pLog );
+#endif
+}
+
+/*
+
+#ifdef __DEBUG_GEMALTO__
+void Log::log( const char * format, ... )
+{
+   // Try to open the file
+   FILE* pLog = fopen( LOG_FILE_NAME, "a" );
+   if( NULL == pLog )
+   {
+      // The file does not exit. Nothing to log
+      return;
+   }
+
+   // Get the size of the buffer necessary to write the message
+   // The size must be extended to include the '\n' and the '\0' characters.
+   va_list args;
+   va_start( args, format );
+#ifdef WIN32
+   size_t len = _vscprintf( format, args );
+#else
+   char tmp[1];
+   int len = vsnprintf( tmp, sizeof(tmp), format, args );
+#endif
+   va_end( args );
+
+   // Allocate the buffer for the message
+   char *buffer = new char[ len + 2 ];
+   memset( buffer, '\0', len + 2 );
+
+   // Write the message into the buffer.
+   va_start( args, format );
+#ifdef WIN32
+   vsprintf_s( buffer, len + 1, format, args );
+#else
+   vsprintf( buffer, format, args );
+#endif
+   va_end( args );
+   buffer[ len ] = '\n';
+
+   // Write the message to the console
+#ifdef WIN32
+   OutputDebugString( buffer );
+#else
+   printf( buffer );
+#endif
+
+   // Write the message to the log file
+   fputs( buffer, pLog );
+   fflush( pLog );
+
+   // Close the file
+   fclose( pLog );
+
+   // Release the buffer
+   delete[] buffer;
+}
+#else
+void Log::log( const char*, ... )
+{
+}
+#endif
+*/
+
+
+
+/*
+*/
+void Log::begin( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - <BEGIN>", a_pMethod );
+#else
+	(void)a_pMethod;
+#endif
+}
+
+
+/*
+*/
+void Log::end( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - <END>", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::in( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - [IN]", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::out( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - [OUT]", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::error( const char* a_pMethod, const char* a_pError )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - ## Error ## %s", a_pMethod, a_pError );
+#endif
+}
+
+
+
+void Log::logCK_UTF8CHAR_PTR( const char* a_pName, const unsigned char* a_pBuffer, const std::size_t& a_Size )
+{
+#ifdef __DEBUG_GEMALTO__
+   std::string s = "";
+   if( NULL_PTR != a_pBuffer )
+   {
+      toString( a_pBuffer, a_Size, s );
+   }
+   log( "%s - <%#02x> - size <%ld> - buffer <%s>", a_pName, a_pBuffer, a_Size, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_INFO_PTR( const char* a_pMethod, CK_MECHANISM_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR != pInfo )
+	{
+	   std::string flags = "";
+	   CK_FLAGS f = pInfo->flags;
+	   mechanismFlagsToString( f, flags );
+
+      log( "%s - CK_MECHANISM_INFO - ulMinKeySize <%#02x> - ulMaxKeySize <%#02x> - flags <%s>", a_pMethod, pInfo->ulMinKeySize, pInfo->ulMaxKeySize, flags.c_str( ) );
+   }
+   else
+   {
+      log( "%s - CK_MECHANISM_INFO - NULL_PTR", a_pMethod );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_INFO( const char* a_pMethod, const CK_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR != pInfo )
+   {
+	   std::string s = "";
+	   CK_INFOToString( pInfo, s );
+      log( "%s - CK_INFO <%s>", a_pMethod, s.c_str( ) );
+   }
+   else
+   {
+      log( "%s - CK_INFO <NULL_PTR>", a_pMethod );
+   }
+#endif
+}
+
+
+void Log::logCK_RV( const char* a_pMethod, const CK_RV& rv )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( CKR_OK == rv )
+   {
+      log( "%s - [RV] <0x00> (CKR_OK)", a_pMethod );
+   }
+   else
+  {
+      std::string s = "";
+      CK_RVToString( rv, s );
+      log( "%s - [RV] <%#02x> (%s)", a_pMethod, rv, s.c_str( ) );
+   }
+#endif
+}
+
+
+void Log::logCK_C_INITIALIZE_ARGS_PTR( const char* a_pMethod, CK_C_INITIALIZE_ARGS_PTR a_pArgs )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR != a_pArgs )
+   {
+		//log( a_pMethod, "pInitArgs->CreateMutex <%#02x>", a_pArgs.CreateMutex );
+		log( "%s - CK_C_INITIALIZE_ARGS - DestroyMutex <%#02x> - LockMutex <%#02x> - UnlockMutex <%#02x> - flags <%#02x> - pReserved <%#02x>",
+         a_pMethod, a_pArgs->DestroyMutex, a_pArgs->LockMutex, a_pArgs->UnlockMutex, a_pArgs->flags, a_pArgs->pReserved );
+   }
+   else
+   {
+		log( "%s - CK_C_INITIALIZE_ARGS - CreateMutex <NULL_PTR> - DestroyMutex <NULL_PTR> - LockMutex <NULL_PTR> - UnlockMutex <NULL_PTR> - flags <NULL_PTR> - pReserved <NULL_PTR>", a_pMethod );
+   }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_SLOT_ID_PTR( const char* a_pMethod, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR == pSlotList )
+   {
+      log( "%s - CK_SLOT_ID_PTR - pulCount <%#02x> (%ld) - pSlotList <NULL_PTR>", a_pMethod, pulCount, ( NULL_PTR != pulCount ) ? *pulCount : 0 );
+   }
+   else
+   {
+      std::string sList = "";
+      if( NULL_PTR != pulCount )
+      {
+	      for( size_t i = 0 ; i < (size_t)*pulCount ; i++ )
+	      {
+		      std::string s = "";
+		      toString( (unsigned long) pSlotList[ i ], s );
+		      sList += s;
+		      if( i != (size_t)( *pulCount - 1 ) )
+		      {
+			      sList += ", " ;
+		      }
+	      }
+      }
+      log( "%s - CK_SLOT_ID_PTR - pulCount <%#02x> (%ld) - pSlotList <%#02x> (%s)", a_pMethod, pulCount, ( NULL_PTR != pulCount ) ? *pulCount : 0, pSlotList, sList.c_str( ) );
+   }
+#endif
+}
+
+
+void Log::logCK_SLOT_INFO_PTR( const char* a_pMethod, CK_SLOT_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR != pInfo )
+	{
+	   std::string slotDescription = "";
+	   toString( pInfo->slotDescription, 64, slotDescription );
+
+	   std::string manufacturerID = "";
+	   toString( pInfo->manufacturerID, 32, manufacturerID );
+
+	   std::string flags = "";
+	   CK_FLAGS f = pInfo->flags;
+	   slotFlagsToString( f, flags );
+
+	   std::string hardwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->hardwareVersion), hardwareVersion );
+
+	   std::string firmwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->firmwareVersion), firmwareVersion );
+
+      log( "%s - CK_SLOT_INFO_PTR - slotDescription <%s> - manufacturerID <%s> - flags <%s> - hardwareVersion <%s> - firmwareVersion <%s>",
+		   a_pMethod, slotDescription.c_str( ), manufacturerID.c_str( ), flags.c_str( ), hardwareVersion.c_str( ), firmwareVersion.c_str( ) );
+   }
+   else
+   {
+      log( "%s - CK_SLOT_INFO_PTR - NULL_PTR", a_pMethod );
+   }
+#endif
+}
+
+
+void Log::logCK_TOKEN_INFO_PTR( const char* a_pMethod, CK_TOKEN_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR != pInfo )
+	{
+	   std::string label = "";
+	   toString( pInfo->label, 32, label );
+
+	   std::string manufacturerID = "";
+	   toString( pInfo->manufacturerID, 32, manufacturerID );
+
+	   std::string model = "";
+	   toString( pInfo->model, 16, model );
+
+	   std::string serialNumber = "";
+	   toString( pInfo->serialNumber, 16, serialNumber );
+
+	   std::string hardwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->hardwareVersion), hardwareVersion );
+
+	   std::string firmwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->firmwareVersion), firmwareVersion );
+
+	   std::string utcTime = "";
+	   toString( pInfo->utcTime, 16, utcTime );
+
+	   log( "%s - CK_TOKEN_INFO_PTR - <%#02x> - label <%s> - manufacturerID <%s> - model <%s> - serialNumber <%s> - flags <%#02x> - ulMaxSessionCount <%#02x> - ulSessionCount <%#02x> - \
+		   ulMaxRwSessionCount <%#02x> - ulRwSessionCount <%#02x> - ulMaxPinLen <%#02x> - ulMinPinLen <%#02x> - ulTotalPublicMemory <%#02x> - \
+		   ulFreePublicMemory <%#02x> - ulTotalPrivateMemory <%#02x> - ulFreePrivateMemory <%#02x> - hardwareVersion <%s> - \
+		   firmwareVersion <%s> - utcTime <%s>",
+		   a_pMethod,
+         pInfo,
+         label.c_str( ),
+		   manufacturerID.c_str( ),
+		   model.c_str( ),
+		   serialNumber.c_str( ),
+		   pInfo->flags,
+		   pInfo->ulMaxSessionCount,
+		   pInfo->ulSessionCount,
+		   pInfo->ulMaxRwSessionCount,
+		   pInfo->ulRwSessionCount,
+		   pInfo->ulMaxPinLen,
+		   pInfo->ulMinPinLen,
+		   pInfo->ulTotalPublicMemory,
+		   pInfo->ulFreePublicMemory,
+		   pInfo->ulTotalPrivateMemory,
+		   pInfo->ulFreePrivateMemory,
+		   hardwareVersion.c_str( ),
+		   firmwareVersion.c_str( ),
+		   utcTime.c_str( ) );
+	}
+   else
+   {
+      log( "%s - CK_TOKEN_INFO_PTR - <NULL_PTR>", a_pMethod );
+   }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_TYPE( const char* a_pMethod, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+   std::string s = "";
+   if( ( NULL_PTR != pMechanismList ) && ( NULL_PTR != pulCount ) )
+   {
+		CK_MECHANISM_TYPEToString( pMechanismList, *pulCount, s );
+	}
+   log( "%s - CK_MECHANISM_TYPE_PTR - pulCount <%#02x> (%ld) - pMechanismList <%#02x> (%s)", a_pMethod, pulCount, ( ( NULL_PTR != pulCount ) ? *pulCount : 0 ), pMechanismList, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_TYPE( const char* a_pMethod, CK_MECHANISM_TYPE & ulMechanism )
+{
+#ifdef __DEBUG_GEMALTO__
+   std::string s = "";
+	CK_MECHANISM_TYPEToString( ulMechanism, s );
+   log( "%s - CK_MECHANISM_TYPE <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logSessionFlags( const char* a_pMethod, CK_FLAGS & flags )
+{
+#ifdef __DEBUG_GEMALTO__
+	std::string s = "";
+	sessionFlagsToString( flags, s );
+	log( "%s - CK_FLAGS <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_SESSION_INFO_PTR( const char* a_pMethod, CK_SESSION_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR != pInfo )
+   {
+      std::string s = "";
+	   CK_SESSION_INFOToString( pInfo, s );
+	   log( "%s - CK_SESSION_INFO <%#02x> (%s)", a_pMethod, pInfo, s.c_str( ) );
+   }
+   else
+	{
+	   log( "%s - CK_SESSION_INFO <NULL_PTR>", a_pMethod );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_USER_TYPE( const char* a_pMethod, CK_USER_TYPE &userType )
+{
+#ifdef __DEBUG_GEMALTO__
+	std::string s = "";
+	CK_USER_TYPEToString( userType, s );
+	log( "%s - CK_USER_TYPE <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_PTR( const char* a_pMethod, CK_MECHANISM_PTR pMechanism )
+{
+#ifdef __DEBUG_GEMALTO__
+	std::string s = "";
+   CK_MECHANISMToString( pMechanism, s );
+	log( "%s - CK_MECHANISM_PTR <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_ATTRIBUTE_PTR( const char* a_pMethod, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG& ulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - pTemplate <%#02x> - ulCount <%ld>", a_pMethod, pTemplate, ulCount );
+	if( NULL_PTR != pTemplate )
+	{
+	   for( size_t i = 0; i < (size_t)ulCount; i++ )
+	   {
+		   CK_ATTRIBUTE a = pTemplate[ i ];
+		   std::string attribute = "";
+		   CK_ATTRIBUTEToString( &a, attribute );
+
+         log( "%s	- Attribute #%d - %s", a_pMethod, i, attribute.c_str( ) );
+	   }
+   }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISMToString( CK_MECHANISM_PTR m, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == m )
+	{
+		return;
+	}
+
+	std::string mechanismType = "";
+	CK_MECHANISM_TYPE t = m->mechanism;
+	CK_MECHANISM_TYPEToString( t, mechanismType );
+
+	std::string mechanismParam = "";
+	toString( (const unsigned char*)m->pParameter, m->ulParameterLen, mechanismParam );
+
+	toString( result,
+		"Type <%s> - Parameter <%s> - ParameterLen <%#02x>",
+		mechanismType.c_str( ),
+		mechanismParam.c_str( ),
+		m->ulParameterLen );
+#endif
+}
+
+
+void Log::CK_ATTRIBUTEToString( const CK_ATTRIBUTE_PTR a, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == a )
+	{
+		return;
+	}
+
+	std::string t = "";
+	int type = T_UNKNOWN;
+	CK_ATTRIBUTE_TYPEToString( a->type, t, type );
+
+	if( ( (CK_ULONG)(-1) ) == a->ulValueLen )
+	{
+		toString( result, "Type <%s> - Length <-1> - Value <UNKNOWN>", t.c_str( ) );
+		return;
+	}
+
+	std::string v = "";
+	if( NULL_PTR == a->pValue )
+	{
+		v = "null";
+	}
+	else
+	{
+		switch( type )
+		{
+		case T_BOOL:
+			toString( ((bool*)a->pValue)[0], v );
+			break;
+
+		case T_BYTES:
+			toString( (CK_BYTE_PTR) a->pValue, a->ulValueLen, v );
+			break;
+
+		case T_LONG:
+			toString( ((CK_ULONG*)a->pValue)[0], v );
+			break;
+
+		case T_KEY_TYPE:
+			CK_KEY_TYPEToString( ((CK_KEY_TYPE *)a->pValue)[0], v );
+			break;
+
+		case T_CERTIFICATE_TYPE:
+			CK_CERTIFICATE_TYPEToString( ((CK_CERTIFICATE_TYPE *)a->pValue)[0], v );
+			break;
+
+		case T_CLASS:
+			CK_OBJECT_CLASSToString( ((CK_OBJECT_CLASS *)a->pValue)[0], v );
+			break;
+
+		case T_DATE:
+			CK_DATEToString( (CK_DATE*) a->pValue, v );
+			break;
+
+		case T_KEY_GEN_MECHANISM:
+			CK_MECHANISM_TYPEToString( ((CK_MECHANISM_TYPE *)a->pValue)[0], v );
+			break;
+
+		default:
+			v = "UNPREDICTABLE VALUE";
+		}
+	}
+
+	toString( result, "Type <%s> - Length <%#02x> - Value <%s>", t.c_str( ), a->ulValueLen, v.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::CK_ATTRIBUTE_TYPEToString( const CK_ATTRIBUTE_TYPE& a, std::string &t, int& type )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( a )
+	{
+	case CKA_CLASS:
+		t = "CKA_CLASS";
+		type = T_CLASS;
+		break;
+
+	case CKA_TOKEN:
+		t = "CKA_TOKEN";
+		type = T_BOOL;
+		break;
+
+	case CKA_PRIVATE:
+		t = "CKA_PRIVATE";
+		type = T_BOOL;
+		break;
+
+	case CKA_LABEL:
+		t = "CKA_LABEL";
+		type = T_BYTES;
+		break;
+
+	case CKA_APPLICATION:
+		t = "CKA_APPLICATION";
+		type = T_BYTES;
+		break;
+
+	case CKA_VALUE:
+		t = "CKA_VALUE";
+		type = T_BYTES;
+		break;
+
+	case CKA_CERTIFICATE_TYPE:
+		t = "CKA_CERTIFICATE_TYPE";
+		type = T_CERTIFICATE_TYPE;
+		break;
+
+	case CKA_ISSUER:
+		t = "CKA_ISSUER";
+		type = T_BYTES;
+		break;
+
+	case CKA_SERIAL_NUMBER:
+		t = "CKA_SERIAL_NUMBER";
+		type = T_BYTES;
+		break;
+
+	case CKA_KEY_TYPE:
+		t = "CKA_KEY_TYPE";
+		type = T_KEY_TYPE;
+		break;
+
+	case CKA_SUBJECT:
+		t = "CKA_SUBJECT";
+		type = T_BYTES;
+		break;
+
+	case CKA_ID:
+		t = "CKA_ID";
+		type = T_BYTES;
+		break;
+
+	case CKA_SENSITIVE:
+		t = "CKA_SENSITIVE";
+		type = T_BOOL;
+		break;
+
+	case CKA_ENCRYPT:
+		t = "CKA_ENCRYPT";
+		type = T_BOOL;
+		break;
+
+	case CKA_DECRYPT:
+		t = "CKA_DECRYPT";
+		type = T_BOOL;
+		break;
+
+	case CKA_WRAP:
+		t = "CKA_WRAP";
+		type = T_BOOL;
+		break;
+
+	case CKA_UNWRAP:
+		t = "CKA_UNWRAP";
+		type = T_BOOL;
+		break;
+
+	case CKA_SIGN:
+		t = "CKA_SIGN";
+		type = T_BOOL;
+		break;
+
+	case CKA_SIGN_RECOVER:
+		t = "CKA_SIGN_RECOVER";
+		type = T_BOOL;
+		break;
+
+	case CKA_VERIFY:
+		t = "CKA_VERIFY";
+		type = T_BOOL;
+		break;
+
+	case CKA_VERIFY_RECOVER:
+		t = "CKA_VERIFY_RECOVER";
+		type = T_BOOL;
+		break;
+
+	case CKA_DERIVE:
+		t = "CKA_DERIVE";
+		type = T_BOOL;
+		break;
+
+	case CKA_START_DATE:
+		t = "CKA_START_DATE";
+		type = T_DATE;
+		break;
+
+	case CKA_END_DATE:
+		t = "CKA_END_DATE";
+		type = T_DATE;
+		break;
+
+	case CKA_MODULUS:
+		t = "CKA_MODULUS";
+		type = T_BYTES;
+		break;
+
+	case CKA_MODULUS_BITS:
+		t = "CKA_MODULUS_BITS";
+		type = T_LONG;
+		break;
+
+	case CKA_PUBLIC_EXPONENT:
+		t = "CKA_PUBLIC_EXPONENT";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIVATE_EXPONENT:
+		t = "CKA_PRIVATE_EXPONENT";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIME_1:
+		t = "CKA_PRIME_1";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIME_2:
+		t = "CKA_PRIME_2";
+		type = T_BYTES;
+		break;
+
+	case CKA_EXPONENT_1:
+		t = "CKA_EXPONENT_1";
+		type = T_BYTES;
+		break;
+
+	case CKA_EXPONENT_2:
+		t = "CKA_EXPONENT_2";
+		type = T_BYTES;
+		break;
+
+	case CKA_COEFFICIENT:
+		t = "CKA_COEFFICIENT";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIME:
+		t = "CKA_PRIME";
+		type = T_BYTES;
+		break;
+
+	case CKA_SUBPRIME:
+		t = "CKA_SUBPRIME";
+		type = T_BYTES;
+		break;
+
+	case CKA_BASE:
+		t = "CKA_BASE";
+		type = T_BYTES;
+		break;
+
+	case CKA_VALUE_BITS:
+		t = "CKA_VALUE_BITS";
+		type = T_BYTES;
+		break;
+
+	case CKA_VALUE_LEN:
+		t = "CKA_VALUE_LEN";
+		type = T_LONG;
+		break;
+
+	case CKA_EXTRACTABLE:
+		t = "CKA_EXTRACTABLE";
+		type = T_BOOL;
+		break;
+
+	case CKA_LOCAL:
+		t = "CKA_LOCAL";
+		type = T_BOOL;
+		break;
+
+	case CKA_NEVER_EXTRACTABLE:
+		t = "CKA_NEVER_EXTRACTABLE";
+		type = T_BOOL;
+		break;
+
+	case CKA_ALWAYS_SENSITIVE:
+		t = "CKA_ALWAYS_SENSITIVE";
+		type = T_BOOL;
+		break;
+
+	case CKA_MODIFIABLE:
+		t = "CKA_MODIFIABLE";
+		type = T_BOOL;
+		break;
+
+	case CKA_ECDSA_PARAMS:
+		t = "CKA_ECDSA_PARAMS";
+		type = T_BYTES;
+		break;
+
+	case CKA_EC_POINT:
+		t = "CKA_EC_POINT";
+		type = T_BYTES;
+		break;
+
+	case CKA_VENDOR_DEFINED:
+		t = "CKA_VENDOR_DEFINED";
+		type = T_BYTES;
+		break;
+
+		//case CKA_KEY_GEN_MECHANISM:
+		//	t = "CKA_KEY_GEN_MECHANISM";
+		//	type = T_KEY_GEN_MECHANISM;
+		//	break;
+
+	default:
+		toString( t, "UNKNOWN TYPE <%#02x>", a );
+		type = T_UNKNOWN;
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_DATEToString( const CK_DATE* t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == t )
+	{
+		return;
+	}
+
+	std::string year = "";
+	toString( t->year, 4, year );
+
+	std::string month = "";
+	toString( t->month, 2, month );
+
+	std::string day = "";
+	toString( t->day, 2, day );
+
+	result = "Year <" + year + "> - Month <" + month + "> - Day <" + day + ">";
+#endif
+}
+
+
+/*
+*/
+void Log::CK_OBJECT_CLASSToString( const CK_OBJECT_CLASS& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKO_DATA:
+		result = "CKO_DATA";
+		break;
+
+	case CKO_CERTIFICATE:
+		result = "CKO_CERTIFICATE";
+		break;
+
+	case CKO_PUBLIC_KEY:
+		result = "CKO_PUBLIC_KEY";
+		break;
+
+	case CKO_PRIVATE_KEY:
+		result = "CKO_PRIVATE_KEY";
+		break;
+
+	case CKO_SECRET_KEY:
+		result = "CKO_SECRET_KEY";
+		break;
+
+	case CKO_VENDOR_DEFINED:
+		result = "CKO_VENDOR_DEFINED";
+		break;
+
+	default:
+		toString( result, "UNKNOWN OBJECT CLASS <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_KEY_TYPEToString( const CK_KEY_TYPE& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKK_RSA:
+		result = "CKK_RSA";
+		break;
+
+	case CKK_DSA:
+		result = "CKK_DSA";
+		break;
+
+	case CKK_ECDSA:
+		result = "CKK_ECDSA";
+		break;
+
+	case CKK_DH:
+		result = "CKK_DH";
+		break;
+
+	case CKK_KEA:
+		result = "CKK_KEA";
+		break;
+
+	case CKK_GENERIC_SECRET:
+		result = "CKK_GENERIC_SECRET";
+		break;
+
+	case CKK_RC2:
+		result = "CKK_RC2";
+		break;
+
+	case CKK_RC4:
+		result = "CKK_RC4";
+		break;
+
+	case CKK_DES:
+		result = "CKK_DES";
+		break;
+
+	case CKK_DES2:
+		result = "CKK_DES2";
+		break;
+
+	case CKK_DES3:
+		result = "CKK_DES3";
+		break;
+
+	case CKK_CAST:
+		result = "CKK_CAST";
+		break;
+
+	case CKK_CAST3:
+		result = "CKK_CAST3";
+		break;
+
+	case CKK_CAST5:
+		result = "CKK_CAST5/128";
+		break;
+
+	case CKK_RC5:
+		result = "CKK_RC5";
+		break;
+
+	case CKK_IDEA:
+		result = "CKK_IDEA";
+		break;
+
+	case CKK_SKIPJACK:
+		result = "CKK_SKIPJACK";
+		break;
+
+	case CKK_BATON:
+		result = "CKK_BATON";
+		break;
+
+	case CKK_JUNIPER:
+		result = "CKK_JUNIPER";
+		break;
+
+	case CKK_CDMF:
+		result = "CKK_CDMF";
+		break;
+
+	case CKK_VENDOR_DEFINED:
+		result = "CKK_VENDOR_DEFINED";
+		break;
+
+	default:
+		toString( result, "UNKNOWN KEY TYPE <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_CERTIFICATE_TYPEToString( const CK_CERTIFICATE_TYPE &t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKC_X_509:
+		result = "CKC_X_509";
+		break;
+
+	case CKC_VENDOR_DEFINED:
+		result = "CKC_VENDOR_DEFINED";
+		break;
+
+	default:
+		toString( result, "UNKNOWN CERTIFICATE TYPE <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_INFOToString( CK_INFO_PTR pInfo, std::string& result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pInfo )
+	{
+		return;
+	}
+
+	std::string cryptokiVersion = "";
+	CK_VERSIONToString( &(pInfo->cryptokiVersion), cryptokiVersion );
+
+	std::string manufacturerID = "";
+	toString( pInfo->manufacturerID, 32, manufacturerID );
+
+	std::string flags = "";
+	CK_FLAGS f = pInfo->flags;
+	toString( f, flags );
+
+	std::string libraryDescription = "";
+	toString( pInfo->libraryDescription, 32, libraryDescription );
+
+	std::string libraryVersion = "";
+	CK_VERSIONToString( &(pInfo->libraryVersion), libraryVersion );
+
+	result = "cryptokiVersion <" + cryptokiVersion
+		+ "> - manufacturerID <" + manufacturerID
+		+ "> - flags <" + flags
+		+ "> - libraryDescription <" + libraryDescription
+		+ "> - libraryVersion <" + libraryVersion
+		+ ">";
+#endif
+}
+
+
+/*
+*/
+void Log::CK_RVToString( const CK_RV& rv, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( rv )
+	{
+	case CKR_OK:
+		result = "CKR_OK";
+		break;
+	case CKR_CANCEL:
+		result = "CKR_CANCEL";
+		break;
+	case CKR_HOST_MEMORY:
+		result = "CKR_HOST_MEMORY";
+		break;
+	case CKR_SLOT_ID_INVALID:
+		result = "CKR_SLOT_ID_INVALID";
+		break;
+	case CKR_GENERAL_ERROR:
+		result = "CKR_GENERAL_ERROR";
+		break;
+	case CKR_FUNCTION_FAILED:
+		result = "CKR_FUNCTION_FAILED";
+		break;
+	case CKR_ARGUMENTS_BAD:
+		result = "CKR_ARGUMENTS_BAD";
+		break;
+	case CKR_NO_EVENT:
+		result = "CKR_NO_EVENT";
+		break;
+	case CKR_NEED_TO_CREATE_THREADS:
+		result = "CKR_NEED_TO_CREATE_THREADS";
+		break;
+	case CKR_CANT_LOCK:
+		result = "CKR_CANT_LOCK";
+		break;
+	case CKR_ATTRIBUTE_READ_ONLY:
+		result = "CKR_ATTRIBUTE_READ_ONLY";
+		break;
+	case CKR_ATTRIBUTE_SENSITIVE:
+		result = "CKR_ATTRIBUTE_SENSITIVE";
+		break;
+	case CKR_ATTRIBUTE_TYPE_INVALID:
+		result = "CKR_ATTRIBUTE_TYPE_INVALID";
+		break;
+	case CKR_ATTRIBUTE_VALUE_INVALID:
+		result = "CKR_ATTRIBUTE_VALUE_INVALID";
+		break;
+	case CKR_DATA_INVALID:
+		result = "CKR_DATA_INVALID";
+		break;
+	case CKR_DATA_LEN_RANGE:
+		result = "CKR_DATA_LEN_RANGE";
+		break;
+	case CKR_DEVICE_ERROR:
+		result = "CKR_DEVICE_ERROR";
+		break;
+	case CKR_DEVICE_MEMORY:
+		result = "CKR_DEVICE_MEMORY";
+		break;
+	case CKR_DEVICE_REMOVED:
+		result = "CKR_DEVICE_REMOVED";
+		break;
+	case CKR_ENCRYPTED_DATA_INVALID:
+		result = "CKR_ENCRYPTED_DATA_INVALID";
+		break;
+	case CKR_ENCRYPTED_DATA_LEN_RANGE:
+		result = "CKR_ENCRYPTED_DATA_LEN_RANGE";
+		break;
+	case CKR_FUNCTION_CANCELED:
+		result = "CKR_FUNCTION_CANCELED";
+		break;
+	case CKR_FUNCTION_NOT_PARALLEL:
+		result = "CKR_FUNCTION_NOT_PARALLEL";
+		break;
+	case CKR_FUNCTION_NOT_SUPPORTED:
+		result = "CKR_FUNCTION_NOT_SUPPORTED";
+		break;
+	case CKR_KEY_HANDLE_INVALID:
+		result = "CKR_KEY_HANDLE_INVALID";
+		break;
+	case CKR_KEY_SIZE_RANGE:
+		result = "CKR_KEY_SIZE_RANGE";
+		break;
+	case CKR_KEY_TYPE_INCONSISTENT:
+		result = "CKR_KEY_TYPE_INCONSISTENT";
+		break;
+	case CKR_KEY_NOT_NEEDED:
+		result = "CKR_KEY_NOT_NEEDED";
+		break;
+	case CKR_KEY_CHANGED:
+		result = "CKR_KEY_CHANGED";
+		break;
+	case CKR_KEY_NEEDED:
+		result = "CKR_KEY_NEEDED";
+		break;
+	case CKR_KEY_INDIGESTIBLE:
+		result = "CKR_KEY_INDIGESTIBLE";
+		break;
+	case CKR_KEY_FUNCTION_NOT_PERMITTED:
+		result = "CKR_KEY_FUNCTION_NOT_PERMITTED";
+		break;
+	case CKR_KEY_NOT_WRAPPABLE:
+		result = "CKR_KEY_NOT_WRAPPABLE";
+		break;
+	case CKR_KEY_UNEXTRACTABLE:
+		result = "CKR_KEY_UNEXTRACTABLE";
+		break;
+	case CKR_MECHANISM_INVALID:
+		result = "CKR_MECHANISM_INVALID";
+		break;
+	case CKR_MECHANISM_PARAM_INVALID:
+		result = "CKR_MECHANISM_PARAM_INVALID";
+		break;
+	case CKR_OBJECT_HANDLE_INVALID:
+		result = "CKR_OBJECT_HANDLE_INVALID";
+		break;
+	case CKR_OPERATION_ACTIVE:
+		result = "CKR_OPERATION_ACTIVE";
+		break;
+	case CKR_OPERATION_NOT_INITIALIZED:
+		result = "CKR_OPERATION_NOT_INITIALIZED";
+		break;
+	case CKR_PIN_INCORRECT:
+		result = "CKR_PIN_INCORRECT";
+		break;
+	case CKR_PIN_INVALID:
+		result = "CKR_PIN_INVALID";
+		break;
+	case CKR_PIN_LEN_RANGE:
+		result = "CKR_PIN_LEN_RANGE";
+		break;
+	case CKR_PIN_EXPIRED:
+		result = "CKR_PIN_EXPIRED";
+		break;
+	case CKR_PIN_LOCKED:
+		result = "CKR_PIN_LOCKED";
+		break;
+	case CKR_SESSION_CLOSED:
+		result = "CKR_SESSION_CLOSED";
+		break;
+	case CKR_SESSION_COUNT:
+		result = "CKR_SESSION_COUNT";
+		break;
+	case CKR_SESSION_HANDLE_INVALID:
+		result = "CKR_SESSION_HANDLE_INVALID";
+		break;
+	case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
+		result = "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
+		break;
+	case CKR_SESSION_READ_ONLY:
+		result = "CKR_SESSION_READ_ONLY";
+		break;
+	case CKR_SESSION_EXISTS:
+		result = "CKR_SESSION_EXISTS";
+		break;
+	case CKR_SESSION_READ_ONLY_EXISTS:
+		result = "CKR_SESSION_READ_ONLY_EXISTS";
+		break;
+	case CKR_SESSION_READ_WRITE_SO_EXISTS:
+		result = "CKR_SESSION_READ_WRITE_SO_EXISTS";
+		break;
+	case CKR_SIGNATURE_INVALID:
+		result = "CKR_SIGNATURE_INVALID";
+		break;
+	case CKR_SIGNATURE_LEN_RANGE:
+		result = "CKR_SIGNATURE_LEN_RANGE";
+		break;
+	case CKR_TEMPLATE_INCOMPLETE:
+		result = "CKR_TEMPLATE_INCOMPLETE";
+		break;
+	case CKR_TEMPLATE_INCONSISTENT:
+		result = "CKR_TEMPLATE_INCONSISTENT";
+		break;
+	case CKR_TOKEN_NOT_PRESENT:
+		result = "CKR_TOKEN_NOT_PRESENT";
+		break;
+	case CKR_TOKEN_NOT_RECOGNIZED:
+		result = "CKR_TOKEN_NOT_RECOGNIZED";
+		break;
+	case CKR_TOKEN_WRITE_PROTECTED:
+		result = "CKR_TOKEN_WRITE_PROTECTED";
+		break;
+	case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
+		result = "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
+		break;
+	case CKR_UNWRAPPING_KEY_SIZE_RANGE:
+		result = "CKR_UNWRAPPING_KEY_SIZE_RANGE";
+		break;
+	case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
+		result = "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
+		break;
+	case CKR_USER_ALREADY_LOGGED_IN:
+		result = "CKR_USER_ALREADY_LOGGED_IN";
+		break;
+	case CKR_USER_NOT_LOGGED_IN:
+		result = "CKR_USER_NOT_LOGGED_IN";
+		break;
+	case CKR_USER_PIN_NOT_INITIALIZED:
+		result = "CKR_USER_PIN_NOT_INITIALIZED";
+		break;
+	case CKR_USER_TYPE_INVALID:
+		result = "CKR_USER_TYPE_INVALID";
+		break;
+	case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
+		result = "CKR_USER_ANOTHER_ALREADY_LOGGED_IN";
+		break;
+	case CKR_USER_TOO_MANY_TYPES:
+		result = "CKR_USER_TOO_MANY_TYPES";
+		break;
+	case CKR_WRAPPED_KEY_INVALID:
+		result = "CKR_WRAPPED_KEY_INVALID";
+		break;
+	case CKR_WRAPPED_KEY_LEN_RANGE:
+		result = "CKR_WRAPPED_KEY_LEN_RANGE";
+		break;
+	case CKR_WRAPPING_KEY_HANDLE_INVALID:
+		result = "CKR_WRAPPING_KEY_HANDLE_INVALID";
+		break;
+	case CKR_WRAPPING_KEY_SIZE_RANGE:
+		result = "CKR_WRAPPING_KEY_SIZE_RANGE";
+		break;
+	case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
+		result = "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
+		break;
+	case CKR_RANDOM_SEED_NOT_SUPPORTED:
+		result = "CKR_RANDOM_SEED_NOT_SUPPORTED";
+		break;
+	case CKR_RANDOM_NO_RNG:
+		result = "CKR_RANDOM_NO_RNG";
+		break;
+	case CKR_BUFFER_TOO_SMALL:
+		result = "CKR_BUFFER_TOO_SMALL";
+		break;
+	case CKR_SAVED_STATE_INVALID:
+		result = "CKR_SAVED_STATE_INVALID";
+		break;
+	case CKR_INFORMATION_SENSITIVE:
+		result = "CKR_INFORMATION_SENSITIVE";
+		break;
+	case CKR_STATE_UNSAVEABLE:
+		result = "CKR_STATE_UNSAVEABLE";
+		break;
+	case CKR_CRYPTOKI_NOT_INITIALIZED:
+		result = "CKR_CRYPTOKI_NOT_INITIALIZED";
+		break;
+	case CKR_CRYPTOKI_ALREADY_INITIALIZED:
+		result = "CKR_CRYPTOKI_ALREADY_INITIALIZED";
+		break;
+	case CKR_MUTEX_BAD:
+		result = "CKR_MUTEX_BAD";
+		break;
+	case CKR_MUTEX_NOT_LOCKED:
+		result = "CKR_MUTEX_NOT_LOCKED";
+		break;
+	case CKR_VENDOR_DEFINED:
+		result = "CKR_VENDOR_DEFINED";
+		break;
+	default:
+		toString( result, "UNKNOWN ERROR <%#02x>", rv );
+	}
+#endif
+}
+
+/*
+*/
+void Log::toString( std::string &result, const char * format, ... )
+{
+#ifdef __DEBUG_GEMALTO__
+	result = "";
+
+   // Get the size of the buffer necessary to write the message
+   // The size must be extended to include the '\n' and the '\0' characters.
+   va_list args;
+   va_start( args, format );
+#ifdef WIN32
+   size_t len = _vscprintf( format, args );
+#else
+   char tmp[1];
+   int len = vsnprintf( tmp, sizeof(tmp), format, args );
+#endif
+   va_end( args );
+
+   // Allocate the buffer for the message
+   char *buffer = new char[ len + 2 ];
+   memset( buffer, '\0', len + 2 );
+
+   // Write the message into the buffer.
+   va_start( args, format );
+#ifdef WIN32
+   vsprintf_s( buffer, len + 1, format, args );
+#else
+   vsprintf( buffer, format, args );
+#endif
+   va_end( args );
+
+   // Write the message to the string
+   result = buffer;
+
+   // Release the buffer
+   delete[] buffer;
+#endif
+}
+
+
+/*
+*/
+void Log::toString( const unsigned char* buffer, std::size_t size, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( ( NULL == buffer ) || ( 1 > size ) )
+	{
+		//result.assign( "null" );
+		return;
+	}
+
+    std::ostringstream oss;
+	oss.rdbuf( )->str( "" );
+
+    // Afficher en héxadécimal et en majuscule
+    oss << std::hex << std::uppercase;
+
+    // Remplir les blancs avec des zéros
+    oss << std::setfill('0');
+
+    for( std::size_t i = 0; i < size; ++i )
+    {
+        // Séparer chaque octet par un espace
+        if (i != 0)
+            oss << ' ';
+
+        // Afficher sa valeur hexadécimale précédée de "0x"
+        // setw(2) permet de forcer l'affichage à 2 caractères
+        oss << /*"0x" <<*/ std::setw(2) << static_cast<int>( buffer[i] );
+    }
+
+    result.assign( oss.str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::toString( const unsigned long &l, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	classtoString<unsigned long>( l, result );
+#endif
+}
+
+
+template<typename T> void Log::classtoString( const T & value, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL == &value )
+	{
+		return;
+	}
+	std::ostringstream str;
+	str << value;
+	result.assign( str.str( ) );
+#endif
+}
+
+
+void Log::slotFlagsToString( const CK_FLAGS& f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	result = "";
+
+	// Slot Information Flags
+	if( f & CKF_TOKEN_PRESENT )
+	{
+		result += "CKF_TOKEN_PRESENT";
+	}
+
+	if( f & CKF_REMOVABLE_DEVICE )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_REMOVABLE_DEVICE";
+	}
+
+	if( f & CKF_HW_SLOT )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_HW_SLOT";
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_VERSIONToString( CK_VERSION_PTR pVersion, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pVersion )
+	{
+		return;
+	}
+
+	toString( result, "%#02x - %#02x", pVersion->major, pVersion->minor );
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_TYPEToString( CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG mechanismListLen, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pMechanismList )
+	{
+		return;
+	}
+
+	result = "";
+
+	for( size_t i = 0 ; i < (size_t)mechanismListLen; i++ )
+	{
+		std::string m = "";
+		CK_MECHANISM_TYPEToString( pMechanismList[ i ], m );
+		result += m;
+		if( i != (size_t)( mechanismListLen - 1 ) )
+		{
+			result +=", ";
+		}
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_TYPEToString( const CK_MECHANISM_TYPE &t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKM_RSA_PKCS_KEY_PAIR_GEN:
+		result = "CKM_RSA_PKCS_KEY_PAIR_GEN";
+		break;
+	case CKM_RSA_PKCS:
+		result = "CKM_RSA_PKCS";
+		break;
+	case CKM_RSA_9796:
+		result = "CKM_RSA_9796";
+		break;
+	case CKM_RSA_X_509:
+		result = "CKM_RSA_X_509";
+		break;
+	case CKM_MD2_RSA_PKCS:
+		result = "CKM_MD2_RSA_PKCS";
+		break;
+	case CKM_MD5_RSA_PKCS:
+		result = "CKM_MD5_RSA_PKCS";
+		break;
+	case CKM_SHA1_RSA_PKCS:
+		result = "CKM_SHA1_RSA_PKCS";
+		break;
+	case CKM_DSA_KEY_PAIR_GEN:
+		result = "CKM_DSA_KEY_PAIR_GEN";
+		break;
+	case CKM_DSA:
+		result = "CKM_DSA";
+		break;
+	case CKM_DSA_SHA1:
+		result = "CKM_DSA_SHA1";
+		break;
+	case CKM_DH_PKCS_KEY_PAIR_GEN:
+		result = "CKM_DH_PKCS_KEY_PAIR_GEN";
+		break;
+	case CKM_DH_PKCS_DERIVE:
+		result = "CKM_DH_PKCS_DERIVE";
+		break;
+	case CKM_RC2_KEY_GEN:
+		result = "CKM_RC2_KEY_GEN";
+		break;
+	case CKM_RC2_ECB:
+		result = "CKM_RC2_ECB";
+		break;
+	case CKM_RC2_CBC:
+		result = "CKM_RC2_CBC";
+		break;
+	case CKM_RC2_MAC:
+		result = "CKM_RC2_MAC";
+		break;
+	case CKM_RC2_MAC_GENERAL:
+		result = "CKM_RC2_MAC_GENERAL";
+		break;
+	case CKM_RC2_CBC_PAD:
+		result = "CKM_RC2_CBC_PAD";
+		break;
+	case CKM_RC4_KEY_GEN:
+		result = "CKM_RC4_KEY_GEN";
+		break;
+	case CKM_RC4:
+		result = "CKM_RC4";
+		break;
+	case CKM_DES_KEY_GEN:
+		result = "CKM_DES_KEY_GEN";
+		break;
+	case CKM_DES_ECB:
+		result = "CKM_DES_ECB";
+		break;
+	case CKM_DES_CBC:
+		result = "CKM_DES_CBC";
+		break;
+	case CKM_DES_MAC:
+		result = "CKM_DES_MAC";
+		break;
+	case CKM_DES_MAC_GENERAL:
+		result = "CKM_DES_MAC_GENERAL";
+		break;
+	case CKM_DES_CBC_PAD:
+		result = "CKM_DES_CBC_PAD";
+		break;
+	case CKM_DES2_KEY_GEN:
+		result = "CKM_DES2_KEY_GEN";
+		break;
+	case CKM_DES3_KEY_GEN:
+		result = "CKM_DES3_KEY_GEN";
+		break;
+	case CKM_DES3_ECB:
+		result = "CKM_DES3_ECB";
+		break;
+	case CKM_DES3_CBC:
+		result = "CKM_DES3_CBC";
+		break;
+	case CKM_DES3_MAC:
+		result = "CKM_DES3_MAC";
+		break;
+	case CKM_DES3_MAC_GENERAL:
+		result = "CKM_DES3_MAC_GENERAL";
+		break;
+	case CKM_DES3_CBC_PAD:
+		result = "CKM_DES3_CBC_PAD";
+		break;
+	case CKM_CDMF_KEY_GEN:
+		result = "CKM_CDMF_KEY_GEN";
+		break;
+	case CKM_CDMF_ECB:
+		result = "CKM_CDMF_ECB";
+		break;
+	case CKM_CDMF_CBC:
+		result = "CKM_CDMF_CBC";
+		break;
+	case CKM_CDMF_MAC:
+		result = "CKM_CDMF_MAC";
+		break;
+	case CKM_CDMF_MAC_GENERAL:
+		result = "CKM_CDMF_MAC_GENERAL";
+		break;
+	case CKM_CDMF_CBC_PAD:
+		result = "CKM_CDMF_CBC_PAD";
+		break;
+	case CKM_MD2:
+		result = "CKM_MD2";
+		break;
+	case CKM_MD2_HMAC:
+		result = "CKM_MD2_HMAC";
+		break;
+	case CKM_MD2_HMAC_GENERAL:
+		result = "CKM_MD2_HMAC_GENERAL";
+		break;
+	case CKM_MD5:
+		result = "CKM_MD5";
+		break;
+	case CKM_MD5_HMAC:
+		result = "CKM_MD5_HMAC";
+		break;
+	case CKM_MD5_HMAC_GENERAL:
+		result = "CKM_MD5_HMAC_GENERAL";
+		break;
+	case CKM_SHA_1:
+		result = "CKM_SHA_1";
+		break;
+	case CKM_SHA_1_HMAC:
+		result = "CKM_SHA_1_HMAC";
+		break;
+	case CKM_SHA_1_HMAC_GENERAL:
+		result = "CKM_SHA_1_HMAC_GENERAL";
+		break;
+	case CKM_CAST_KEY_GEN:
+		result = "CKM_CAST_KEY_GEN";
+		break;
+	case CKM_CAST_ECB:
+		result = "CKM_CAST_ECB";
+		break;
+	case CKM_CAST_CBC:
+		result = "CKM_CAST_CBC";
+		break;
+	case CKM_CAST_MAC:
+		result = "CKM_CAST_MAC";
+		break;
+	case CKM_CAST_MAC_GENERAL:
+		result = "CKM_CAST_MAC_GENERAL";
+		break;
+	case CKM_CAST_CBC_PAD:
+		result = "CKM_CAST_CBC_PAD";
+		break;
+	case CKM_CAST3_KEY_GEN:
+		result = "CKM_CAST3_KEY_GEN";
+		break;
+	case CKM_CAST3_ECB:
+		result = "CKM_CAST3_ECB";
+		break;
+	case CKM_CAST3_CBC:
+		result = "CKM_CAST3_CBC";
+		break;
+	case CKM_CAST3_MAC:
+		result = "CKM_CAST3_MAC";
+		break;
+	case CKM_CAST3_MAC_GENERAL:
+		result = "CKM_CAST3_MAC_GENERAL";
+		break;
+	case CKM_CAST3_CBC_PAD:
+		result = "CKM_CAST3_CBC_PAD";
+		break;
+		/*case CKM_CAST5_KEY_GEN:
+		result = "CKM_CAST5_KEY_GEN";
+		break;*/
+	case CKM_CAST128_KEY_GEN:
+		result = "CKM_CAST128_KEY_GEN/CKM_CAST5_KEY_GEN";
+		break;
+		/*case CKM_CAST5_ECB:
+		result = "CKM_CAST5_ECB";
+		break;*/
+	case CKM_CAST128_ECB:
+		result = "CKM_CAST128_ECB/CKM_CAST5_ECB";
+		break;
+		/*case CKM_CAST5_CBC:
+		result = "CKM_CAST5_CBC";
+		break;*/
+	case CKM_CAST128_CBC:
+		result = "CKM_CAST128_CBC/CKM_CAST5_CBC";
+		break;
+		/*case CKM_CAST5_MAC:
+		result = "CKM_CAST5_MAC";
+		break;*/
+	case CKM_CAST128_MAC:
+		result = "CKM_CAST128_MAC/CKM_CAST5_MAC";
+		break;
+		/*case CKM_CAST5_MAC_GENERAL:
+		result = "CKM_CAST5_MAC_GENERAL";
+		break;*/
+	case CKM_CAST128_MAC_GENERAL:
+		result = "CKM_CAST128_MAC_GENERAL/CKM_CAST5_MAC_GENERAL";
+		break;
+		/*case CKM_CAST5_CBC_PAD:
+		result = "CKM_CAST5_CBC_PAD";
+		break;*/
+	case CKM_CAST128_CBC_PAD:
+		result = "CKM_CAST128_CBC_PAD/CKM_CAST5_CBC_PAD";
+		break;
+	case CKM_RC5_KEY_GEN:
+		result = "CKM_RC5_KEY_GEN";
+		break;
+	case CKM_RC5_ECB:
+		result = "CKM_RC5_ECB";
+		break;
+	case CKM_RC5_CBC:
+		result = "CKM_RC5_CBC";
+		break;
+	case CKM_RC5_MAC:
+		result = "CKM_RC5_MAC";
+		break;
+	case CKM_RC5_MAC_GENERAL:
+		result = "CKM_RC5_MAC_GENERAL";
+		break;
+	case CKM_RC5_CBC_PAD:
+		result = "CKM_RC5_CBC_PAD";
+		break;
+	case CKM_IDEA_KEY_GEN:
+		result = "CKM_IDEA_KEY_GEN";
+		break;
+	case CKM_IDEA_ECB:
+		result = "CKM_IDEA_ECB";
+		break;
+	case CKM_IDEA_CBC:
+		result = "CKM_IDEA_CBC";
+		break;
+	case CKM_IDEA_MAC:
+		result = "CKM_IDEA_MAC";
+		break;
+	case CKM_IDEA_MAC_GENERAL:
+		result = "CKM_IDEA_MAC_GENERAL";
+		break;
+	case CKM_IDEA_CBC_PAD:
+		result = "CKM_IDEA_CBC_PAD";
+		break;
+	case CKM_GENERIC_SECRET_KEY_GEN:
+		result = "CKM_GENERIC_SECRET_KEY_GEN";
+		break;
+	case CKM_CONCATENATE_BASE_AND_KEY:
+		result = "CKM_CONCATENATE_BASE_AND_KEY";
+		break;
+	case CKM_CONCATENATE_BASE_AND_DATA:
+		result = "CKM_CONCATENATE_BASE_AND_DATA";
+		break;
+	case CKM_CONCATENATE_DATA_AND_BASE:
+		result = "CKM_CONCATENATE_DATA_AND_BASE";
+		break;
+	case CKM_XOR_BASE_AND_DATA:
+		result = "CKM_XOR_BASE_AND_DATA";
+		break;
+	case CKM_EXTRACT_KEY_FROM_KEY:
+		result = "CKM_EXTRACT_KEY_FROM_KEY";
+		break;
+	case CKM_SSL3_PRE_MASTER_KEY_GEN:
+		result = "CKM_SSL3_PRE_MASTER_KEY_GEN";
+		break;
+	case CKM_SSL3_MASTER_KEY_DERIVE:
+		result = "CKM_SSL3_MASTER_KEY_DERIVE";
+		break;
+	case CKM_SSL3_KEY_AND_MAC_DERIVE:
+		result = "CKM_SSL3_KEY_AND_MAC_DERIVE";
+		break;
+	case CKM_SSL3_MD5_MAC:
+		result = "CKM_SSL3_MD5_MAC";
+		break;
+	case CKM_SSL3_SHA1_MAC:
+		result = "CKM_SSL3_SHA1_MAC";
+		break;
+	case CKM_MD5_KEY_DERIVATION:
+		result = "CKM_MD5_KEY_DERIVATION";
+		break;
+	case CKM_MD2_KEY_DERIVATION:
+		result = "CKM_MD2_KEY_DERIVATION";
+		break;
+	case CKM_SHA1_KEY_DERIVATION:
+		result = "CKM_SHA1_KEY_DERIVATION";
+		break;
+	case CKM_PBE_MD2_DES_CBC:
+		result = "CKM_PBE_MD2_DES_CBC";
+		break;
+	case CKM_PBE_MD5_DES_CBC:
+		result = "CKM_PBE_MD5_DES_CBC";
+		break;
+	case CKM_PBE_MD5_CAST_CBC:
+		result = "CKM_PBE_MD5_CAST_CBC";
+		break;
+	case CKM_PBE_MD5_CAST3_CBC:
+		result = "CKM_PBE_MD5_CAST3_CBC";
+		break;
+		/*case CKM_PBE_MD5_CAST5_CBC:
+		result = "CKM_PBE_MD5_CAST5_CBC";
+		break;*/
+	case CKM_PBE_MD5_CAST128_CBC:
+		result = "CKM_PBE_MD5_CAST128_CBC/CKM_PBE_MD5_CAST5_CBC";
+		break;
+		/*case CKM_PBE_SHA1_CAST5_CBC:
+		result = "CKM_PBE_SHA1_CAST5_CBC";
+		break;*/
+	case CKM_PBE_SHA1_CAST128_CBC:
+		result = "CKM_PBE_SHA1_CAST128_CBC/CKM_PBE_SHA1_CAST5_CBC";
+		break;
+	case CKM_PBE_SHA1_RC4_128:
+		result = "CKM_PBE_SHA1_RC4_128";
+		break;
+	case CKM_PBE_SHA1_RC4_40:
+		result = "CKM_PBE_SHA1_RC4_40";
+		break;
+	case CKM_PBE_SHA1_DES3_EDE_CBC:
+		result = "CKM_PBE_SHA1_DES3_EDE_CBC";
+		break;
+	case CKM_PBE_SHA1_DES2_EDE_CBC:
+		result = "CKM_PBE_SHA1_DES2_EDE_CBC";
+		break;
+	case CKM_PBE_SHA1_RC2_128_CBC:
+		result = "CKM_PBE_SHA1_RC2_128_CBC";
+		break;
+	case CKM_PBE_SHA1_RC2_40_CBC:
+		result = "CKM_PBE_SHA1_RC2_40_CBC";
+		break;
+	case CKM_PBA_SHA1_WITH_SHA1_HMAC:
+		result = "CKM_PBA_SHA1_WITH_SHA1_HMAC";
+		break;
+	case CKM_KEY_WRAP_LYNKS:
+		result = "CKM_KEY_WRAP_LYNKS";
+		break;
+	case CKM_KEY_WRAP_SET_OAEP:
+		result = "CKM_KEY_WRAP_SET_OAEP";
+		break;
+	case CKM_SKIPJACK_KEY_GEN:
+		result = "CKM_SKIPJACK_KEY_GEN";
+		break;
+	case CKM_SKIPJACK_ECB64:
+		result = "CKM_SKIPJACK_ECB64";
+		break;
+	case CKM_SKIPJACK_CBC64:
+		result = "CKM_SKIPJACK_CBC64";
+		break;
+	case CKM_SKIPJACK_OFB64:
+		result = "CKM_SKIPJACK_OFB64";
+		break;
+	case CKM_SKIPJACK_CFB64:
+		result = "CKM_SKIPJACK_CFB64";
+		break;
+	case CKM_SKIPJACK_CFB32:
+		result = "CKM_SKIPJACK_CFB32";
+		break;
+	case CKM_SKIPJACK_CFB16:
+		result = "CKM_SKIPJACK_CFB16";
+		break;
+	case CKM_SKIPJACK_CFB8:
+		result = "CKM_SKIPJACK_CFB8";
+		break;
+	case CKM_SKIPJACK_WRAP:
+		result = "CKM_SKIPJACK_WRAP";
+		break;
+	case CKM_SKIPJACK_PRIVATE_WRAP:
+		result = "CKM_SKIPJACK_PRIVATE_WRAP";
+		break;
+	case CKM_SKIPJACK_RELAYX:
+		result = "CKM_SKIPJACK_RELAYX";
+		break;
+	case CKM_KEA_KEY_PAIR_GEN:
+		result = "CKM_KEA_KEY_PAIR_GEN";
+		break;
+	case CKM_KEA_KEY_DERIVE:
+		result = "CKM_KEA_KEY_DERIVE";
+		break;
+	case CKM_FORTEZZA_TIMESTAMP:
+		result = "CKM_FORTEZZA_TIMESTAMP";
+		break;
+	case CKM_BATON_KEY_GEN:
+		result = "CKM_BATON_KEY_GEN";
+		break;
+	case CKM_BATON_ECB128:
+		result = "CKM_BATON_ECB128";
+		break;
+	case CKM_BATON_ECB96:
+		result = "CKM_BATON_ECB96";
+		break;
+	case CKM_BATON_CBC128:
+		result = "CKM_BATON_CBC128";
+		break;
+	case CKM_BATON_COUNTER:
+		result = "CKM_BATON_COUNTER";
+		break;
+	case CKM_BATON_SHUFFLE:
+		result = "CKM_BATON_SHUFFLE";
+		break;
+	case CKM_BATON_WRAP:
+		result = "CKM_RSA_9796";
+		break;
+	case CKM_ECDSA:
+		result = "CKM_ECDSA";
+		break;
+	case CKM_ECDSA_SHA1:
+		result = "CKM_ECDSA_SHA1";
+		break;
+	case CKM_JUNIPER_KEY_GEN:
+		result = "CKM_JUNIPER_KEY_GEN";
+		break;
+	case CKM_JUNIPER_ECB128:
+		result = "CKM_JUNIPER_ECB128";
+		break;
+	case CKM_JUNIPER_CBC128:
+		result = "CKM_JUNIPER_CBC128";
+		break;
+	case CKM_JUNIPER_COUNTER:
+		result = "CKM_JUNIPER_COUNTER";
+		break;
+	case CKM_JUNIPER_SHUFFLE:
+		result = "CKM_JUNIPER_SHUFFLE";
+		break;
+	case CKM_JUNIPER_WRAP:
+		result = "CKM_JUNIPER_WRAP";
+		break;
+	case CKM_FASTHASH:
+		result = "CKM_FASTHASH";
+		break;
+	case CKM_VENDOR_DEFINED:
+		result = "CKM_VENDOR_DEFINED";
+		break;
+	case CKM_SHA256:
+		result = "CKM_SHA256";
+		break;
+	case CKM_SHA256_RSA_PKCS:
+		result = "CKM_SHA256_RSA_PKCS";
+		break;
+	default:
+		toString( result, "UNKNOWN MECHANISM <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_INFOToString( CK_MECHANISM_INFO_PTR pInfo, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pInfo )
+	{
+		 return;
+	}
+
+	std::string flags = "";
+	CK_FLAGS f = pInfo->flags;
+	mechanismFlagsToString( f, flags );
+
+	toString( result, "ulMinKeySize <%#02x> - ulMaxKeySize <%#02x> - flags <%s>", pInfo->ulMinKeySize, pInfo->ulMaxKeySize, flags.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::mechanismFlagsToString( const CK_FLAGS& f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( f & CKF_EXTENSION )
+	{
+		result += "CKF_EXTENSION";
+	}
+	if( f & CKF_DERIVE )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_DERIVE";
+	}
+	if( f & CKF_UNWRAP )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_UNWRAP";
+	}
+	if( f & CKF_WRAP )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_WRAP";
+	}
+	if( f & CKF_GENERATE_KEY_PAIR )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_GENERATE_KEY_PAIR";
+	}
+	if( f & CKF_GENERATE )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_GENERATE";
+	}
+	if( f & CKF_VERIFY_RECOVER )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_VERIFY_RECOVER";
+	}
+	if( f & CKF_VERIFY )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_VERIFY";
+	}
+	if( f & CKF_SIGN_RECOVER )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_SIGN_RECOVER";
+	}
+	if( f & CKF_HW )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_HW";
+	}
+	if( f & CKF_ENCRYPT )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_ENCRYPT";
+	}
+	if( f & CKF_DECRYPT )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_DECRYPT";
+	}
+	if( f & CKF_DIGEST )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_DIGEST";
+	}
+	if( f & CKF_SIGN )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_SIGN";
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::sessionFlagsToString( const CK_FLAGS &f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	result = "";
+
+	// Session information flags
+	if( f & CKF_SERIAL_SESSION )
+	{
+		result += "CKF_SERIAL_SESSION";
+	}
+
+	if( f & CKF_RW_SESSION )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_RW_SESSION";
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_SESSION_INFOToString( CK_SESSION_INFO_PTR pInfo, std::string& result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pInfo )
+	{
+		return;
+	}
+
+	std::string flags = "";
+	CK_FLAGS f = pInfo->flags;
+	sessionFlagsToString( f, flags );
+
+	toString( result, "slotID <%#02x> - state <%#02x> - flags <%#02x> (%s) - ulDeviceError <%#02x>",
+				pInfo->slotID,
+				pInfo->state,
+				pInfo->flags,
+				flags.c_str( ),
+				pInfo->ulDeviceError );
+#endif
+}
+
+/*
+*/
+void Log::CK_USER_TYPEToString( const CK_USER_TYPE& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKU_USER:
+		result = "CKU_USER";
+		break;
+
+	case CKU_SO:
+		result  = "CKU_SO";
+		break;
+
+	default:
+		toString( result, "UNKNOWN USER TYPE <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::start( void )
+{
+#ifdef __DEBUG_GEMALTO__
+#ifdef WIN32
+   m_ulStart = GetTickCount( );
+#endif
+#endif
+}
+
+
+/*
+*/
+void Log::stop( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+#ifdef WIN32
+   unsigned long ulTickCount = GetTickCount( ) - m_ulStart;
+   Log::log( "%s - Spend <%ld> milliseconds", a_pMethod, ulTickCount );
+#endif
+#endif
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/log.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/log.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/log.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,96 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_log_h
+#define _include_log_h
+
+#include <string>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include "platconfig.h"
+
+
+class Log
+{
+public:
+
+   static void log( const char * format, ... );
+
+   static void error( const char*, const char* );
+   static void in( const char* a_pMethod );
+   static void out( const char* a_pMethod );
+   static void begin( const char* a_pMethod );
+   static void end( const char* a_pMethod );
+
+   static void start( void );
+   static void stop( const char* a_pMethod );
+
+   static void logCK_SLOT_ID_PTR( const char*, CK_SLOT_ID_PTR, CK_ULONG_PTR );
+   static void logCK_SLOT_INFO_PTR( const char*, CK_SLOT_INFO_PTR );
+   static void logCK_C_INITIALIZE_ARGS_PTR( const char*, CK_C_INITIALIZE_ARGS_PTR );
+   static void logCK_INFO( const char*, const CK_INFO_PTR );
+   static void logCK_RV( const char*, const CK_RV & );
+   static void logCK_UTF8CHAR_PTR( const char*, const unsigned char*, const std::size_t& );
+   static void logCK_TOKEN_INFO_PTR( const char*, CK_TOKEN_INFO_PTR );
+   static void logCK_MECHANISM_TYPE( const char*, CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR );
+   static void logCK_MECHANISM_TYPE( const char*, CK_MECHANISM_TYPE & );
+   static void logCK_SESSION_INFO_PTR( const char*, CK_SESSION_INFO_PTR );
+   static void logCK_USER_TYPE( const char*, CK_USER_TYPE & );
+   static void logCK_ATTRIBUTE_PTR( const char*, CK_ATTRIBUTE_PTR, CK_ULONG & );
+   static void logSessionFlags( const char*, CK_FLAGS & );
+   static void logCK_MECHANISM_INFO_PTR( const char*, CK_MECHANISM_INFO_PTR );
+   static void logCK_MECHANISM_PTR( const char*, CK_MECHANISM_PTR );
+
+   static void CK_MECHANISMToString( CK_MECHANISM_PTR, std::string & );
+   static void CK_CERTIFICATE_TYPEToString( const CK_CERTIFICATE_TYPE &, std::string & );
+   static void CK_KEY_TYPEToString( const CK_KEY_TYPE&, std::string & );
+   static void CK_OBJECT_CLASSToString( const CK_OBJECT_CLASS&, std::string & );
+   static void CK_DATEToString( const CK_DATE*, std::string & );
+   static void CK_INFOToString( CK_INFO_PTR pInfo, std::string &result );
+   static void slotFlagsToString( const CK_FLAGS& f, std::string &result );
+   static void mechanismFlagsToString( const CK_FLAGS &, std::string & );
+   static void sessionFlagsToString( const CK_FLAGS & , std::string & );
+   static void CK_VERSIONToString( CK_VERSION_PTR pVersion, std::string& result );
+   static void CK_RVToString( const CK_RV& rv, std::string &result );
+   static void CK_MECHANISM_TYPEToString( CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG mechanismListLen, std::string &result );
+   static void CK_MECHANISM_TYPEToString( const CK_MECHANISM_TYPE &, std::string & );
+   static void CK_MECHANISM_INFOToString( CK_MECHANISM_INFO_PTR pInfo, std::string &result );
+   static void CK_SESSION_INFOToString( CK_SESSION_INFO_PTR, std::string& );
+   static void CK_USER_TYPEToString( const CK_USER_TYPE&, std::string & );
+   static void CK_ATTRIBUTEToString( const CK_ATTRIBUTE_PTR, std::string & );
+   static void CK_ATTRIBUTE_TYPEToString( const CK_ATTRIBUTE_TYPE& , std::string &, int& );
+
+   static void toStringHex( const unsigned char* buffer, const std::size_t& size, std::string &result );
+   static void toString( std::string &result, const char * format, ... );
+   static void toString( const unsigned char* buffer, std::size_t size, std::string &result );
+   static void toString( const unsigned long &l, std::string &result );
+
+   template<typename T> static void classtoString( const T & value, std::string &result );
+
+   static unsigned long m_ulStart;
+
+
+};
+
+
+#endif

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/md5.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/md5.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/md5.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,74 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "md5.h"
+
+CMD5::CMD5(){
+    this->_hashValue     = (CK_BYTE_PTR)malloc(MD5_HASH_LENGTH);
+    this->_workingBuffer = (CK_BYTE_PTR)malloc(MD5_BLOCK_LENGTH);
+    this->_hashLength    = MD5_HASH_LENGTH;
+    this->_blockLength   = MD5_BLOCK_LENGTH;
+}
+
+CMD5::~CMD5(){
+}
+
+void CMD5::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_md5_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_md5_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    algo_md5_update(&ctx, data, MD5_BLOCK_LENGTH);
+}
+
+void CMD5::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_md5_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_md5_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    // allocate tempory working buffer
+    ctx.input = (u1*)malloc(MD5_BLOCK_LENGTH);
+    memset(ctx.input,0,MD5_BLOCK_LENGTH);
+
+    algo_md5_update(&ctx,data,length);
+    algo_md5_finish(&ctx);
+
+    free(ctx.input);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/md5.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/md5.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/md5.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_md5_h
+#define _include_md5_h
+
+#include "MarshallerCfg.h"
+#include "algo_md5.h"
+
+class CMD5 : public CDigest
+{
+private:
+    void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+    void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+    CMD5();
+    ~CMD5();
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,144 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include <string>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include "mutex.h"
+
+CMutex::CMutex()
+{
+#ifdef WIN32
+    m_hMutex = NULL;
+#endif
+    m_strName = "";
+}
+
+CMutex::CMutex(const char* nm)
+{
+    m_strName = nm;
+
+#ifdef WIN32
+    m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
+
+    if(m_hMutex == NULL)
+    {
+        assert(FALSE); //throw ThreadException("Failed to create mutex");
+    }
+#else
+    pthread_mutex_init(&m_hMutex,0);
+    m_ownerThread = 0;
+    m_refCount = 0;
+#endif
+}
+
+#ifdef WIN32
+void CMutex::create(const char* nm)
+#else
+void CMutex::create(const char*)
+#endif
+{
+
+#ifdef WIN32
+    if(m_hMutex != NULL)
+    {
+        CloseHandle(m_hMutex);
+        m_hMutex = NULL;
+    }
+
+    m_strName = nm;
+    m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
+
+    if(m_hMutex == NULL)
+    {
+        assert(FALSE); //throw ThreadException("Failed to create mutex");
+    }
+#else
+    if(pthread_equal(m_ownerThread,pthread_self()))
+    {
+        m_refCount++;
+    }
+    else
+    {
+        if(pthread_mutex_lock(&m_hMutex) == 0)
+        {
+            //assert(FALSE);
+        }
+        m_ownerThread = pthread_self();
+        m_refCount = 1;
+    }
+
+
+#endif
+}
+
+#ifdef WIN32
+unsigned long* CMutex::getMutexHandle()
+{
+    return m_hMutex;
+}
+#endif
+
+std::string CMutex::getName()
+{
+    return m_strName;
+}
+
+void CMutex::release()
+{
+#ifdef WIN32
+    if(m_hMutex != NULL)
+    {
+        CloseHandle(m_hMutex);
+        m_hMutex = NULL;
+    }
+#else
+    if(pthread_equal(m_ownerThread,pthread_self()))
+    {
+        m_refCount--;
+
+        if(!m_refCount)
+        {
+            m_ownerThread = 0;
+            pthread_mutex_unlock(&m_hMutex);
+        }
+    }
+#endif
+}
+
+CMutex::~CMutex()
+{
+#ifdef WIN32
+    if(m_hMutex != NULL)
+    {
+        CloseHandle(m_hMutex);
+    }
+#else
+    pthread_mutex_destroy(&m_hMutex);
+#endif
+}
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/mutex.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,54 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_mutex_h
+#define _include_mutex_h
+
+#ifdef INCLUDE_EVENTING
+
+class CMutex
+{
+private:
+    // unsigned long* to the low-level mutex object
+#ifdef WIN32
+    unsigned long* m_hMutex;
+#else
+    pthread_mutex_t m_hMutex;
+    pthread_t 		m_ownerThread;
+    unsigned long 	m_refCount;
+#endif
+    // name to identify the mutex
+    std::string m_strName;
+
+public:
+    CMutex();
+    CMutex(const char* nm);
+    ~CMutex();
+
+    void create(const char* nm);
+    unsigned long* getMutexHandle();
+    std::string getName();
+    void release();
+};
+
+#endif
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,2741 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define CRYPTOKIVERSION_INTERFACE_MAJOR  0x02
+#define CRYPTOKIVERSION_INTERFACE_MINOR  0x14
+
+#define CRYPTOKIVERSION_LIBRARY_MAJOR    0x02
+#define CRYPTOKIVERSION_LIBRARY_MINOR    0x00
+
+#define LIBRARY_DESCRIPTION             "CF .NET PKCS#11 Module"
+#define MANUFACTURER_ID                 "Gemalto"
+
+#include <string>
+
+#include "stdafx.h"
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+#include "error.h"
+#include "platconfig.h"
+#include "config.h"
+#include "digest.h"
+#include "symmalgo.h"
+#include "thread.h"
+#include "event.h"
+#include "mutex.h"
+#include "session.h"
+#include "slot.h"
+#include "application.h"
+#include "critsect.h"
+#include "log.h"
+
+
+static CK_BBOOL _isInitialized = FALSE;
+
+
+// This libarary is thread protected by a single critical section
+// This coarse grained approach is for simplicty, the alternative
+// require significant work.
+CCriticalSection _critSect;
+
+CCriticalSection _critSectAPI;
+
+
+static const CK_FUNCTION_LIST FunctionList = {
+   { CRYPTOKIVERSION_LIBRARY_MAJOR, CRYPTOKIVERSION_LIBRARY_MINOR },
+
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+
+#define CK_PKCS11_FUNCTION_INFO(func) func,
+
+#include "pkcs11f.h"
+
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+};
+
+
+#define PKCS11_TRY \
+   if (!_isInitialized) { \
+   return CKR_CRYPTOKI_NOT_INITIALIZED; } \
+   CCriticalSectionLocker __cslock(_critSect); \
+   try
+
+
+#define PKCS11_CATCH(rv) \
+   catch(CkError & err) { rv = err.Error(); } \
+   catch(PcscError & ) { rv = CKR_FUNCTION_FAILED; } \
+   catch(Marshaller::Exception & exc) { rv = CkError::CheckMarshallerException(exc); } \
+   catch(...) { rv = CKR_GENERAL_ERROR; }
+
+
+// Put all static initializations here to ensure they
+// occur in correct order.
+
+CEvent CryptokiEvent(0xFFFFFFFF);
+
+// CStartStopControl to support clean up at DLL unload
+class CStartStopControl
+{
+public:
+   CStartStopControl() {};
+   ~CStartStopControl() {
+      Application::End( );
+   }
+} foo;
+
+
+extern "C"
+{
+
+
+   /**
+   * C_Initialize initializes the Cryptoki library.
+   *
+   * @param pInitArgs
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Initialize )( CK_VOID_PTR pInitArgs )
+   {     
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Initialize" );
+         Log::in( "C_Initialize" );
+         Log::log( "C_Initialize - pInitArgs <%#02x>", pInitArgs );
+         //SLog::log( S"C_Initialize - isInitialized <%#02x>", _isInitialized );
+
+         // Already Initialized
+         if( TRUE == _isInitialized )
+         {
+            Log::error( "C_Initialize", "CKR_CRYPTOKI_ALREADY_INITIALIZED" );
+            rv = CKR_CRYPTOKI_ALREADY_INITIALIZED;
+         }
+         else if( NULL_PTR != pInitArgs )
+         {
+            CK_C_INITIALIZE_ARGS initArgs = *(CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
+
+            Log::logCK_C_INITIALIZE_ARGS_PTR( "C_Initialize", (CK_C_INITIALIZE_ARGS_PTR)pInitArgs );
+
+            if( NULL_PTR != initArgs.pReserved )
+            {
+               Log::error( "C_Initialize", "CKR_ARGUMENTS_BAD" );
+               rv = CKR_ARGUMENTS_BAD;
+            }
+            else if( initArgs.flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS )
+            {
+               Log::error( "C_Initialize", "CKR_NEED_TO_CREATE_THREADS" );
+               rv = CKR_NEED_TO_CREATE_THREADS;
+            }
+            else if( initArgs.flags & CKF_OS_LOCKING_OK )
+            {
+               if( initArgs.CreateMutex || initArgs.DestroyMutex || initArgs.LockMutex || initArgs.UnlockMutex )
+               {
+                  Log::error( "C_Initialize", "CKR_CANT_LOCK" );
+                  rv = CKR_CANT_LOCK;
+               }
+            }
+            else if( initArgs.CreateMutex || initArgs.DestroyMutex || initArgs.LockMutex || initArgs.UnlockMutex )
+            {
+               if( !initArgs.CreateMutex || !initArgs.DestroyMutex || !initArgs.LockMutex || !initArgs.UnlockMutex )
+               {
+                  Log::error( "C_Initialize", "CKR_ARGUMENTS_BAD" );
+                  rv = CKR_ARGUMENTS_BAD;
+               }
+               else if( !( initArgs.flags & CKF_OS_LOCKING_OK ) )
+               {
+                  Log::error( "C_Initialize", "CKR_CANT_LOCK" );
+                  rv = CKR_CANT_LOCK;
+               }
+            }
+         }
+
+         if (rv == CKR_OK)
+         {
+            Application::InitApplication( );
+            _isInitialized = TRUE;
+         }
+
+         Log::log( "C_Initialize - isInitialized <%#02x>", _isInitialized );
+
+         Log::logCK_RV( "C_Initialize", rv );
+         Log::end( "C_Initialize\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_Finalize indicates that an application is done with the
+   * Cryptoki library.
+   *
+   * @param pReserved reserved.Should be NULL_PTR
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Finalize )( CK_VOID_PTR pReserved )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Finalize" );
+         Log::in( "C_Finalize" );
+         Log::log( "C_Finalize - pReserved <%#02x>", pReserved );
+
+         // Not Initialized
+         if( !_isInitialized )
+         {
+            Log::error( "C_Finalize", "CKR_CRYPTOKI_NOT_INITIALIZED" );
+            rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+         }
+         else if( NULL_PTR != pReserved )
+         {
+            Log::error( "C_Finalize", "CKR_ARGUMENTS_BAD" );
+            rv = CKR_ARGUMENTS_BAD;
+         }
+         else
+         {
+            _isInitialized = FALSE;
+            Application::End( );
+         }
+
+         Log::logCK_RV( "C_Finalize", rv );
+         Log::end( "C_Finalize\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetInfo returns general information about Cryptoki.
+   *
+   * @param pInfo location that receives information
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetInfo )( CK_INFO_PTR pInfo )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetInfo" );
+         Log::in( "C_GetInfo" );
+         Log::logCK_INFO( "C_GetInfo", pInfo );
+
+         if( FALSE == _isInitialized )
+         {
+            rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+         }
+         else if( NULL_PTR == pInfo )
+         {
+            rv = CKR_ARGUMENTS_BAD;
+         }
+         else
+         {
+            pInfo->cryptokiVersion.major = CRYPTOKIVERSION_INTERFACE_MAJOR;
+            pInfo->cryptokiVersion.minor = CRYPTOKIVERSION_INTERFACE_MINOR;
+            pInfo->flags = 0;
+            memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription));
+            memcpy(pInfo->libraryDescription, LIBRARY_DESCRIPTION, strlen(LIBRARY_DESCRIPTION));
+            memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
+            memcpy(pInfo->manufacturerID, MANUFACTURER_ID, strlen(MANUFACTURER_ID));
+            pInfo->libraryVersion.major  = CRYPTOKIVERSION_LIBRARY_MAJOR;
+            pInfo->libraryVersion.minor  = CRYPTOKIVERSION_LIBRARY_MINOR;
+         }
+
+         Log::logCK_RV( "C_GetInfo", rv );
+         Log::out( "C_GetInfo" );
+         Log::logCK_INFO( "C_GetInfo", pInfo );
+         Log::end( "C_GetInfo\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+   /**
+   * C_GetFunctionList returns the function list.
+   *
+   * @param ppFunctionList receives pointer to function list
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_GetFunctionList )( CK_FUNCTION_LIST_PTR_PTR ppFunctionList )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetFunctionList" );
+         Log::in( "C_GetFunctionList" );
+         Log::log( "C_GetFunctionList - CK_FUNCTION_LIST_PTR_PTR <%#02x>", ppFunctionList );
+
+         if( NULL_PTR == ppFunctionList )
+         {
+            rv = CKR_ARGUMENTS_BAD;
+         }
+         else
+         {
+            // this is the only function which an application can call before calling C_Initialize
+            *ppFunctionList = (CK_FUNCTION_LIST_PTR)&FunctionList;
+         }
+
+         Log::logCK_RV( "C_GetFunctionList", rv );
+         Log::out( "C_GetFunctionList" );
+         Log::log( "C_GetFunctionList - CK_FUNCTION_LIST_PTR_PTR <%#02x>", ppFunctionList );
+         Log::end( "C_GetFunctionList\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetSlotList obtains a list of slots in the system.
+   *
+   * @param tokenPresent only slots with tokens
+   * @param pSlotList    receives array of slot IDs
+   * @param pulCount     receives number of slots
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetSlotList )( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetSlotList" );
+         Log::in( "C_GetSlotList" );
+         Log::log( "C_GetSlotList - tokenPresent <%d>", tokenPresent );
+         Log::logCK_SLOT_ID_PTR( "C_GetSlotList", pSlotList, pulCount );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Application::Enumerate( tokenPresent, pSlotList, pulCount );
+         }
+         PKCS11_CATCH( rv )
+         Log::stop( "C_GetSlotList" );
+
+         Log::logCK_RV( "C_GetSlotList", rv );
+         Log::out( "C_GetSlotList" );
+         Log::logCK_SLOT_ID_PTR( "C_GetSlotList", pSlotList, pulCount );
+         Log::end( "C_GetSlotList\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetSlotInfo obtains information about a particular slot in
+   * the system.
+   *
+   * @param slotId the ID of the slot
+   * @param pInfo  received the slot information
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetSlotInfo )( CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetSlotInfo" );
+         Log::in( "C_GetSlotInfo" );
+         Log::log( "C_GetSlotInfo - slotID <%ld>", slotID );
+         Log::logCK_SLOT_INFO_PTR( "C_GetSlotInfo", pInfo );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+           //if(Application::_numSlots == 0)
+           // {
+           //    //CK_ULONG slotCount = 0;
+           //    //Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+           //    CK_ULONG slotCount = 32;
+           //    CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR) malloc( sizeof( CK_SLOT_ID ) * slotCount );
+           //    Application::Enumerate( CK_FALSE, slots, &slotCount );
+           //    free(slots);
+           // }
+
+            Slot* pSlot = NULL_PTR;
+            rv = Application::GetSlotFromSlotId( slotID, &pSlot );
+
+            if(rv == CKR_OK)
+            {
+               rv = pSlot->GetInfo( pInfo );
+            }
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_GetSlotInfo" );
+
+         Log::logCK_RV( "C_GetSlotInfo", rv );
+         Log::out( "C_GetSlotInfo" );
+         Log::logCK_SLOT_INFO_PTR( "C_GetSlotInfo", pInfo );
+         Log::end( "C_GetSlotInfo\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetTokenInfo obtains information about a particular token
+   * in the system.
+   *
+   * @param slotID ID of the token's slot
+   * @param pInfo  receives the token information
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetTokenInfo )( CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetTokenInfo" );
+         Log::in( "C_GetTokenInfo" );
+         Log::log( "C_GetTokenInfo - slotID <%ld>", slotID );
+         Log::logCK_TOKEN_INFO_PTR( "C_GetTokenInfo", pInfo );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            //if(Application::_numSlots == 0)
+            //{
+            //   //CK_ULONG slotCount = 0;
+            //   //Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            //   CK_ULONG slotCount = 32;
+            //   CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR) malloc( sizeof( CK_SLOT_ID ) * slotCount );
+            //   Application::Enumerate( CK_FALSE, slots, &slotCount );
+            //   free(slots);
+            //}
+
+            Slot* slot = NULL_PTR;
+            rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+            if(rv == CKR_OK)
+            {
+               rv = slot->GetTokenInfo(pInfo);
+            }
+         }
+         //PKCS11_CATCH(rv)
+         catch( CkError & e )
+         {
+            rv = e.Error( );
+            //Log::log( "C_GetTokenInfo - ## Error ## CkError <%s> <%#02x>", e.what( ), e.Error( ) );
+         }
+         catch( PcscError & /*e*/ )
+         {
+            rv = CKR_FUNCTION_FAILED;
+            //Log::log( "C_GetTokenInfo - ## Error ## PcscError <%s> <%#02x> <%#02x>", e.what( ), e.Error( ), rv );
+         }
+         catch( Marshaller::Exception & e )
+         {
+            rv = CkError::CheckMarshallerException( e );
+            //Log::log( "C_GetTokenInfo - ## Error ## PcscError <%s> <%#02x>", e.what( ), rv );
+         }
+         catch( ... )
+         {
+            rv = CKR_GENERAL_ERROR;
+            //Log::log( "C_GetTokenInfo - ## Error ## (...) <%#02x>", rv );
+         }
+         Log::stop( "C_GetTokenInfo" );
+
+         Log::logCK_RV( "C_GetTokenInfo", rv );
+         Log::out( "C_GetTokenInfo" );
+         Log::logCK_TOKEN_INFO_PTR( "C_GetTokenInfo", pInfo );
+         Log::end( "C_GetTokenInfo\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetMechanismList obtains a list of mechanism types
+   * supported by a token.
+   *
+   * @param slotID ID of token's slot
+   * @param pMechanismList gets mech. array
+   * @param pulCount get number of mechs
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetMechanismList )( CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetMechanismList" );
+         Log::in( "C_GetMechanismList" );
+         Log::log( "C_GetMechanismList - slotID <%#02x>", slotID );
+         Log::logCK_MECHANISM_TYPE( "C_GetMechanismList", pMechanismList, pulCount );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            //if(Application::_numSlots == 0)
+            //{
+            //   //CK_ULONG slotCount = 0;
+            //   //Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            //   CK_ULONG slotCount = 32;
+            //   CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR) malloc( sizeof( CK_SLOT_ID ) * slotCount );
+            //   Application::Enumerate( CK_FALSE, slots, &slotCount );
+            //   free(slots);
+            //}
+
+            Slot* slot = NULL_PTR;
+            rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+            if(rv == CKR_OK)
+            {
+               rv = slot->GetMechanismList(pMechanismList,pulCount);
+            }
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_GetMechanismList" );
+
+         Log::logCK_RV( "C_GetMechanismList", rv );
+         Log::out( "C_GetMechanismList" );
+         Log::logCK_MECHANISM_TYPE( "C_GetMechanismList", pMechanismList, pulCount );
+         Log::end( "C_GetMechanismList\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetMechanismInfo obtains information about a particular
+   * mechanism possibly supported by a token.
+   *
+   * @param slotID ID of the token's slot
+   * @param type  type of mechanism
+   * @param pInfo receives mechanism info
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetMechanismInfo )( CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetMechanismInfo" );
+         Log::in( "C_GetMechanismInfo" );
+         Log::log( "C_GetMechanismInfo - slotID <%#02x>", slotID );
+         Log::logCK_MECHANISM_TYPE( "C_GetMechanismInfo", type );
+         Log::logCK_MECHANISM_INFO_PTR( "C_GetMechanismInfo", pInfo );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            //if(Application::_numSlots == 0)
+            //{
+            //   //CK_ULONG slotCount = 0;
+            //   //Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            //   CK_ULONG slotCount = 32;
+            //   CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR) malloc( sizeof( CK_SLOT_ID ) * slotCount );
+            //   Application::Enumerate( CK_FALSE, slots, &slotCount );
+            //   free(slots);
+            //}
+
+            Slot* slot = NULL_PTR;
+            rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+            if(rv == CKR_OK)
+            {
+               rv = slot->GetMechanismInfo(type,pInfo);
+            }
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_GetMechanismInfo" );
+
+         Log::logCK_RV( "C_GetMechanismInfo", rv );
+         Log::out( "C_GetMechanismInfo" );
+         Log::logCK_MECHANISM_INFO_PTR( "C_GetMechanismInfo", pInfo );
+         Log::end( "C_GetMechanismInfo\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_InitToken initializes a token.
+   *
+   * @param slotID ID of the token's slot
+   * @param pPin   the SO's initial PIN
+   * @param ulPinLen length in bytes of the PIN
+   * @param pLabel 32-byte token label (blank padded) pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_InitToken )( CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_InitToken" );
+         Log::in( "C_InitToken" );
+         Log::log( "C_InitToken - slotID <%#02x>", slotID );
+         Log::logCK_UTF8CHAR_PTR( "C_InitToken - pPin", pPin, ulPinLen );
+         Log::logCK_UTF8CHAR_PTR( "C_InitToken - pLabel", pLabel, 32 );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            //if(Application::_numSlots == 0)
+            //{
+            //   //CK_ULONG slotCount = 0;
+            //   //Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            //   CK_ULONG slotCount = 32;
+            //   CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR) malloc( sizeof( CK_SLOT_ID ) * slotCount );
+            //   Application::Enumerate( CK_FALSE, slots, &slotCount );
+            //   free(slots);
+            //}
+
+            Slot* slot = NULL_PTR;
+            rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+            if(rv == CKR_OK)
+            {
+               rv = slot->InitToken(pPin,ulPinLen,pLabel);
+            }
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_InitToken" );
+
+         Log::logCK_RV( "C_InitToken", rv );
+         Log::end( "C_InitToken\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_InitPIN initializes the normal user's PIN.
+   *
+   * @param hSession the session's handle
+   * @param pPin the noraml user's PIN
+   * @param ulPinLen length in bytes of the PIN
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_InitPIN )( CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_InitPIN" );
+         Log::in( "C_InitPIN" );
+         Log::log( "C_InitPIN - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_InitPIN - pPin", pPin, ulPinLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::InitPIN( hSession, pPin, ulPinLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_InitPIN" );
+
+         Log::logCK_RV( "C_InitPIN", rv );
+         Log::end( "C_InitPIN\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+      return rv;
+   }
+
+
+   /**
+   * C_SetPIN modifies the PIN of the user who is logged in.
+   *
+   * @param hSession   the session's handle
+   * @param pOldPin     the old PIN
+   * @param ulOldPin    length of the old PIN
+   * @param pNewPin     the new PIN
+   * @param ulNewLen    length of the new PIN
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SetPIN )( CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_SetPIN" );
+         Log::in( "C_SetPIN" );
+         Log::log( "C_SetPIN - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_SetPIN - pOldPin", pOldPin, ulOldLen );
+         Log::logCK_UTF8CHAR_PTR( "C_SetPIN - pNewPin", pNewPin, ulNewLen );
+
+         Log::start( );
+         CK_RV rv = CKR_OK;
+         PKCS11_TRY
+         {
+            rv = Slot::SetPIN( hSession, pOldPin, ulOldLen, pNewPin, ulNewLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_SetPIN" );
+
+         Log::logCK_RV( "C_SetPIN", rv );
+         Log::end( "C_SetPIN\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_OpenSession opens a session between an application and a
+   * token.
+   *
+   * @param slotID       the slot's ID
+   * @param flags        from CK_SESSION_INFO
+   * @param pApplication passed to callback
+   * @param Notify       callback function
+   * @param phSession    gets session handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_OpenSession )( CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_OpenSession" );
+         Log::in( "C_OpenSession" );
+         Log::log( "C_OpenSession - slotID <%#02x>", slotID );
+         Log::logSessionFlags( "C_OpenSession", flags );
+         Log::log( "C_OpenSession - pApplication <%#02x>", pApplication );
+         Log::log( "C_OpenSession - Notify <%#02x>", Notify );
+         Log::log( "C_OpenSession - phSession <%#02x> (%#02x)", phSession, ( ( NULL_PTR != phSession ) ? *phSession : 0 ) );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            //if(Application::_numSlots == 0)
+            //{
+            //   //CK_ULONG slotCount = 0;
+            //   //Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            //   CK_ULONG slotCount = 32;
+            //   CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR) malloc( sizeof( CK_SLOT_ID ) * slotCount );
+            //   Application::Enumerate( CK_FALSE, slots, &slotCount );
+            //   free(slots);
+            //}
+
+            Slot* slot = NULL_PTR;
+            rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+            if(rv == CKR_OK)
+            {
+               PKCS11_ASSERT(slot != NULL_PTR);
+               rv = slot->OpenSession(flags,pApplication,Notify,phSession);
+            }
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_OpenSession" );
+
+         Log::logCK_RV( "C_OpenSession", rv );
+         Log::out( "C_OpenSession" );
+         Log::log( "C_OpenSession - phSession <%#02x> (%ld)", phSession, ( ( NULL_PTR != phSession ) ? *phSession : 0 ) );
+         Log::end( "C_OpenSession\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_CloseSession closes a session between an application and a
+   * token.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CloseSession )( CK_SESSION_HANDLE hSession )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_CloseSession" );
+         Log::in( "C_CloseSession" );
+         Log::log( "C_CloseSession - hSession <%#02x>", hSession );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::CloseSession(hSession);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_CloseSession" );
+
+         Log::logCK_RV( "C_CloseSession", rv );
+         Log::end( "C_CloseSession\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_CloseAllSessions closes all sessions with a token.
+   *
+   * @param slotID the token's slot
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CloseAllSessions )( CK_SLOT_ID slotID )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_CloseAllSessions" );
+         Log::in( "C_CloseAllSessions" );
+         Log::log( "C_CloseAllSessions - slotID <%#02x>", slotID );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            //if(Application::_numSlots == 0)
+            //{
+            //   //CK_ULONG slotCount = 0;
+            //   //Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            //   CK_ULONG slotCount = 32;
+            //   CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR) malloc( sizeof( CK_SLOT_ID ) * slotCount );
+            //   Application::Enumerate( CK_FALSE, slots, &slotCount );
+            //   free(slots);
+            //}
+
+            Slot* slot = NULL_PTR;
+            rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+            if(rv == CKR_OK)
+            {
+               rv = slot->CloseAllSessions();
+            }
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_CloseAllSessions" );
+
+         Log::logCK_RV( "C_CloseAllSessions", rv );
+         Log::end( "C_CloseAllSessions\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetSessionInfo obtains information about the session.
+   *
+   * @param hSession the session's handle
+   * @param receives session info
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetSessionInfo )( CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetSessionInfo" );
+         Log::in( "C_GetSessionInfo" );
+         Log::log( "C_GetSessionInfo - hSession <%#02x>", hSession );
+         Log::logCK_SESSION_INFO_PTR( "C_GetSessionInfo", pInfo );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::GetSessionInfo(hSession,pInfo);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_GetSessionInfo" );
+
+         Log::logCK_RV( "C_GetSessionInfo", rv );
+         Log::out( "C_GetSessionInfo" );
+         Log::logCK_SESSION_INFO_PTR( "C_GetSessionInfo", pInfo );
+         Log::end( "C_GetSessionInfo\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetOperationState obtains the state of the cryptographic operation
+   * in a session.
+   *
+   * @param hSession session's handle
+   * @param pOperationState gets State
+   * @param pulOperationStateLen gets state length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetOperationState )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_GetOperationState" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+      Log::logCK_RV( "C_GetOperationState", rv );
+      Log::end( "C_GetOperationState\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_SetOperationState restores the state of the cryptographic
+   * operation in a session.
+   *
+   * @param hSession session's handle
+   * @param pOperationState hold state
+   * @param ulOperationStateLen holds state length
+   * @param hEncryptionKey en/decryption key
+   * @param hAuthenticationKey sig/verify key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SetOperationState )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_SetOperationState" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+      Log::logCK_RV( "C_SetOperationState", rv );
+      Log::end( "C_SetOperationState\n" );
+      return rv;
+   }
+
+   /**
+   * C_Login logs a user into a token.
+   *
+   * @param hSession the session's handle
+   * @param userType the user type
+   * @param pPin the user's PIN
+   * @param ulPinLen the length of the PIN
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Login )( CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Login" );
+         Log::in( "C_Login" );
+         Log::log( "C_Login - hSession <%#02x>", hSession );
+         Log::logCK_USER_TYPE( "C_Login", userType );
+         Log::logCK_UTF8CHAR_PTR( "C_Login - pPin", pPin, ulPinLen );
+         Log::log( "C_Login - ulPinLen <%ld>", ulPinLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::Login(hSession,userType,pPin,ulPinLen);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_Login" );
+
+         Log::logCK_RV( "C_Login", rv );
+         Log::end( "C_Login\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_Logout logs a user out from a token.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Logout )( CK_SESSION_HANDLE hSession )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Logout" );
+         Log::in( "C_Logout" );
+         Log::log( "C_Logout - hSession <%#02x>", hSession );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::Logout(hSession);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_Logout" );
+
+         Log::logCK_RV( "C_Logout", rv );
+         Log::end( "C_Logout\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_CreateObject creates a new object.
+   *
+   * @param hSession  the session's handle
+   * @param pTemplate the object's template
+   * @param ulCount   attributes in template
+   * @param phObject  gets new object's handle.
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CreateObject )( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_CreateObject" );
+         Log::in( "C_CreateObject" );
+         Log::log( "C_CreateObject - hSession <%#02x>", hSession );
+         Log::logCK_ATTRIBUTE_PTR( "C_CreateObject", pTemplate, ulCount );
+         Log::log( "C_CreateObject - phObject <%#02x>", phObject );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::CreateObject( hSession, pTemplate, ulCount, phObject );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_CreateObject" );
+
+         Log::logCK_RV( "C_CreateObject", rv );
+         Log::out( "C_CreateObject" );
+         Log::log( "C_CreateObject - phObject <%#02x> (%#02x)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+         Log::end( "C_CreateObject\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /* C_CopyObject copies an object, creating a new object for the
+   * copy. */
+   CK_DEFINE_FUNCTION(CK_RV,C_CopyObject )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_CopyObject" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_CopyObject", rv );
+      Log::end( "C_CopyObject\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_DestroyObject destroys an object.
+   *
+   * @param hSession the session's handle
+   * @param hObject the object's handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DestroyObject )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_DestroyObject" );
+         Log::in( "C_DestroyObject" );
+         Log::log( "C_DestroyObject - hSession <%#02x>", hSession );
+         Log::log( "C_DestroyObject - hObject <%#02x>", hObject );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::DestroyObject( hSession, hObject );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_DestroyObject" );
+
+         Log::logCK_RV( "C_DestroyObject", rv );
+         Log::end( "C_DestroyObject\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /* C_GetObjectSize gets the size of an object in bytes. */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetObjectSize )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ULONG_PTR )
+   {
+      Log::begin( "C_GetObjectSize" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_GetObjectSize", rv );
+      Log::end( "C_GetObjectSize\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_GetAttributeValue obtains the value of one or more object
+   * attributes.
+   *
+   * @param hSession    the session's handle
+   * @param hObject     the object's handle
+   * @param pTemplate   specifies attrs; gets vals
+   * @param ulCount     attributes in template
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetAttributeValue )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GetAttributeValue" );
+         Log::in( "C_GetAttributeValue" );
+         Log::log( "C_GetAttributeValue - hSession <%#02x>", hSession );
+         Log::logCK_ATTRIBUTE_PTR( "C_GetAttributeValue", pTemplate, ulCount );
+         Log::log( "C_GetAttributeValue - hObject <%#02x>", hObject );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::GetAttributeValue(hSession,hObject,pTemplate,ulCount);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_GetAttributeValue" );
+
+         Log::logCK_RV( "C_GetAttributeValue", rv );
+         Log::out( "C_GetAttributeValue" );
+         Log::logCK_ATTRIBUTE_PTR( "C_GetAttributeValue", pTemplate, ulCount );
+         Log::end( "C_GetAttributeValue\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_SetAttributeValue modifies the value of one or more object
+   * attributes
+   *
+   * @param   hSession    the session's handle
+   * @param   hObject     the object's handle
+   * @param   pTemplate   specifies attrs and values
+   * @param   ulCount     attributes in template
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SetAttributeValue )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_SetAttributeValue" );
+         Log::in( "C_SetAttributeValue" );
+         Log::log( "C_SetAttributeValue - hSession <%#02x>", hSession );
+         Log::logCK_ATTRIBUTE_PTR( "C_SetAttributeValue", pTemplate, ulCount );
+         Log::log( "C_SetAttributeValue - hObject <%#02x>", hObject );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::SetAttributeValue( hSession, hObject, pTemplate, ulCount );
+         }
+         PKCS11_CATCH( rv )
+         Log::stop( "C_SetAttributeValue" );
+
+         Log::logCK_RV( "C_SetAttributeValue", rv );
+         Log::end( "C_SetAttributeValue\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_FindObjectsInit initializes a search for token and session
+   * objects that match a template.
+   *
+   * @param hSession the session's handle
+   * @param pTemplate attribute values to match
+   * @param ulCount atrs in search template
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsInit )( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_FindObjectsInit" );
+         Log::in( "C_FindObjectsInit" );
+         Log::log( "C_FindObjectsInit - hSession <%#02x>", hSession );
+         Log::logCK_ATTRIBUTE_PTR( "C_FindObjectsInit", pTemplate, ulCount );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::FindObjectsInit(hSession,pTemplate,ulCount);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_FindObjectsInit" );
+
+         Log::logCK_RV( "C_FindObjectsInit", rv );
+         Log::end( "C_FindObjectsInit\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+      return rv;
+   }
+
+
+   /**
+   * C_FindObjects continues a search for token and session
+   * objects that match a template, obtaining additional object
+   * handles.
+   *
+   * @param hSession                session's handle
+   * @param phObject                gets obj. handles
+   * @param ulMaxObjectCount        max handles to get
+   * @param pulObjectCount          actual # returned
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_FindObjects )(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_FindObjects" );
+         Log::in( "C_FindObjects" );
+         Log::log( "C_FindObjects - hSession <%#02x>", hSession );
+         Log::log( "C_FindObjects - phObject <%#02x> (%#02x)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+         Log::log( "C_FindObjects - ulMaxObjectCount <%#02x>", ulMaxObjectCount );
+         Log::log( "C_FindObjects - pulObjectCount <%#02x> (%#02x)", pulObjectCount, ( ( NULL_PTR != pulObjectCount ) ? *pulObjectCount : 0 ) );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::FindObjects( hSession, phObject, ulMaxObjectCount, pulObjectCount );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_FindObjects" );
+
+         Log::logCK_RV( "C_FindObjects", rv );
+         Log::out( "C_FindObjects" );
+         Log::log( "C_FindObjects - phObject <%#02x> (%#02x)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+         Log::log( "C_FindObjects - pulObjectCount <%#02x> (%#02x)", pulObjectCount, ( ( NULL_PTR != pulObjectCount ) ? *pulObjectCount : 0 ) );
+         Log::end( "C_FindObjects\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_FindObjectsFinal finishes a search for token and session
+   * objects.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsFinal )( CK_SESSION_HANDLE hSession )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_FindObjectsFinal" );
+         Log::in( "C_FindObjectsFinal" );
+         Log::log( "C_FindObjectsFinal - hSession <%#02x>", hSession );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::FindObjectsFinal(hSession);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_FindObjectsFinal" );
+
+         Log::logCK_RV( "C_FindObjectsFinal", rv );
+         Log::end( "C_FindObjectsFinal\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_EncryptInit initializes an encryption operation.
+   *
+   * @param hSession          the session's handle
+   * @param pMechanism        the encryption mechanism
+   * @param hKey              handle of encryption key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_EncryptInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_EncryptInit" );
+         Log::in( "C_EncryptInit" );
+         Log::log( "C_EncryptInit - hSession <%#02x>", hSession );
+         Log::logCK_MECHANISM_PTR( "C_EncryptInit", pMechanism );
+         Log::log( "C_EncryptInit - hKey <%#02x>", hKey );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::EncryptInit(hSession,pMechanism,hKey);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_EncryptInit" );
+
+         Log::logCK_RV( "C_EncryptInit", rv );
+         Log::end( "C_EncryptInit\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_Encrypt encrypts single-part data.
+   *
+   * @param hSession               session's handle
+   * @param pData                  the plaintext data
+   * @param ulDataLen              bytes of plaintext
+   * @param pEncryptedData         gets ciphertext
+   * @param pulEncryptedData Len   gets c-text size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Encrypt )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Encrypt" );
+         Log::in( "C_Encrypt" );
+         Log::log( "C_Encrypt - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pData", pData, ulDataLen );
+         Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pEncryptedData", pEncryptedData, (NULL_PTR == pulEncryptedDataLen) ? 0 : *pulEncryptedDataLen );
+
+         Log::start( );      
+         PKCS11_TRY
+         {
+            rv = Slot::Encrypt( hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_Encrypt" );
+
+         Log::logCK_RV( "C_Encrypt", rv );
+         Log::out( "C_Encrypt" );
+         Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pEncryptedData", pEncryptedData, (NULL_PTR == pulEncryptedDataLen) ? 0 : *pulEncryptedDataLen );
+         Log::end( "C_Encrypt\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_EncryptUpdate continues a multiple-part encryption
+   * operation.
+   *
+   * @param hSession                  session's handle
+   * @param pPart                     the plaintext data
+   * @param ulPartLen                 plaintext data len
+   * @param pEncryptedPart            gets ciphertext
+   * @param pulEncryptedPartLen       gets c-text size
+   *
+   */
+   CK_DEFINE_FUNCTION(CK_RV,C_EncryptUpdate)( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_EncryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_EncryptUpdate", rv );
+      Log::end( "C_EncryptUpdate\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_EncryptFinal finishes a multiple-part encryption
+   * operation.
+   *
+   * @param hSession                   session handle
+   * @param pLastEncryptedPart         last c-text
+   * @param pulLastEncryptedPartLen    gets last size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_EncryptFinal )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_EncryptFinal" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_EncryptFinal", rv );
+      Log::end( "C_EncryptFinal\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptInit initializes a decryption operation.
+   *
+   * @param hSession the session's handle
+   * @param pMechanism the decryption mechanism
+   * @param hKey handle of decrypting key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_DecryptInit" );
+         Log::in( "C_DecryptInit" );
+         Log::log( "C_DecryptInit - hSession <%#02x>", hSession );
+         Log::logCK_MECHANISM_PTR( "C_DecryptInit", pMechanism );
+         Log::log( "C_DecryptInit - hKey <%#02x>", hKey );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::DecryptInit( hSession, pMechanism, hKey );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_DecryptInit" );
+
+         Log::logCK_RV( "C_DecryptInit", rv );
+         Log::end( "C_DecryptInit\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+
+   /**
+   * C_Decrypt decrypts encrypted data in a single part.
+   *
+   * @param hSession                   session's handle
+   * @param pEncryptedData             ciphertext
+   * @param ulEncryptedDataLen         ciphertext length
+   * @param pData                      gets plaintext
+   * @param pulDataLen                 gets p-text size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Decrypt )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Decrypt" );
+         Log::in( "C_Decrypt" );
+         Log::log( "C_Decrypt - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pEncryptedData", pEncryptedData, ulEncryptedDataLen );
+         Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pData", pData, (NULL_PTR == pulDataLen) ? 0 : *pulDataLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::Decrypt(hSession,pEncryptedData,ulEncryptedDataLen,pData,pulDataLen);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_Decrypt" );
+
+         Log::logCK_RV( "C_Decrypt", rv );
+         Log::out( "C_Decrypt" );
+         Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pData", pData, (NULL_PTR == pulDataLen) ? 0 : *pulDataLen );
+         Log::end( "C_Decrypt\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptUpdate continues a multiple-part decryption
+   * operation.
+   *
+   * @param hSession           session's handle
+   * @param pEncryptedPart     encrypted data
+   * @param ulEncryptedPart    input length
+   * @param pPart              gets plaintext
+   * @param pulPartLen         p-text size
+   */
+   CK_DEFINE_FUNCTION(CK_RV,C_DecryptUpdate)( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptUpdate", rv );
+      Log::end( "C_DecryptUpdate\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptFinal finishes a multiple-part decryption
+   * operation.
+   *
+   * @param hSession           the session's handle
+   * @param pLastPart          gets plaintext
+   * @param pulLastPartLen     p-text size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptFinal )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptFinal" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptFinal", rv );
+      Log::end( "C_DecryptFinal\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_DigestInit initializes a message-digesting operation.
+   *
+   * @param hSession the session's handle
+   * @param pMechanism the digesting mechanism
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+          Log::begin( "C_DigestInit" );
+         Log::in( "C_DigestInit" );
+         Log::log( "C_DigestInit - hSession <%#02x>", hSession );
+         Log::logCK_MECHANISM_PTR( "C_DigestInit", pMechanism );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::DigestInit(hSession,pMechanism);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_DigestInit" );
+
+         Log::logCK_RV( "C_DigestInit", rv );
+         Log::end( "C_DigestInit\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_Digest digests data in a single part.
+   *
+   * @param hSession      the session's handle
+   * @param pData         data to be digested
+   * @param ulDataLen     bytes of data to digest
+   * @param pDigest       gets the message digest
+   * @param pulDigestLen  gets digest length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Digest )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Digest" );
+         Log::in( "C_Digest" );
+         Log::log( "C_Digest - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_Digest - pData", pData, ulDataLen );
+         Log::logCK_UTF8CHAR_PTR( "C_Digest - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::Digest( hSession, pData, ulDataLen, pDigest, pulDigestLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_Digest" );
+
+         Log::logCK_RV( "C_Digest", rv );
+         Log::out( "C_Digest" );
+         Log::logCK_UTF8CHAR_PTR( "C_Digest - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+         Log::end( "C_Digest\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_DigestUpdate continues a multiple-part message-digesting
+   * operation.
+   *
+   * @param hSession       the session's handle
+   * @param pPart          data to be digested
+   * @param ulPartLen      bytes of data to be digested
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_DigestUpdate" );
+         Log::in( "C_DigestUpdate" );
+         Log::log( "C_DigestUpdate - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_DigestUpdate - pPart", pPart, ulPartLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::DigestUpdate( hSession, pPart, ulPartLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_DigestUpdate" );
+
+         Log::logCK_RV( "C_DigestUpdate", rv );
+         Log::end( "C_DigestUpdate\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /* C_DigestKey continues a multi-part message-digesting
+   * operation, by digesting the value of a secret key as part of
+   * the data already digested. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestKey )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_DigestKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DigestKey", rv );
+      Log::end( "C_DigestKey\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_DigestFinal finishes a multiple-part message-digesting
+   * operation.
+   *
+   * @param hSession       the session's handle
+   * @param pDigest        gets the message digest
+   * @param pulDigestLen   gets byte count of digest
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_DigestFinal" );
+         Log::in( "C_DigestFinal" );
+         Log::log( "C_DigestFinal - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_DigestFinal - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::DigestFinal( hSession, pDigest, pulDigestLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_DigestFinal" );
+
+         Log::logCK_RV( "C_DigestFinal", rv );
+         Log::out( "C_DigestFinal" );
+         Log::logCK_UTF8CHAR_PTR( "C_DigestFinal - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+         Log::end( "C_DigestFinal\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_SignInit initializes a signature (private key encryption)
+   * operation, where the signature is (will be) an appendix to
+   * the data, and plaintext cannot be recovered from the
+   * signature.
+   *
+   * @param hSession           the session's handle
+   * @param pMechanism         the signature mechanism
+   * @param hKey               handle of signature key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_SignInit" );
+         Log::in( "C_SignInit" );
+         Log::log( "C_SignInit - hSession <%#02x>", hSession );
+         Log::logCK_MECHANISM_PTR( "C_SignInit", pMechanism );
+         Log::log( "C_SignInit - hKey <%#02x>", hKey );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::SignInit(hSession,pMechanism,hKey);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_SignInit" );
+         
+         Log::logCK_RV( "C_SignInit", rv );
+         Log::end( "C_SignInit\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_Sign signs (encrypts with private key) data in a single
+   * part, where the signature is (will be) an appendix to the
+   * data, and plaintext cannot be recovered from the signature.
+   *
+   * @param hSession          the session's handle
+   * @param pData             the data to sign
+   * @param ulDataLen         count of bytes to sign
+   * @param pSignature        gets the signature
+   * @param pulSignatureLen   gets signature length
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Sign )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Sign" );
+         Log::in( "C_Sign" );
+         Log::log( "C_Sign - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_Sign - pData", pData, ulDataLen );
+         Log::logCK_UTF8CHAR_PTR( "C_Sign - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::Sign( hSession, pData, ulDataLen, pSignature, pulSignatureLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_Sign" );
+         
+         Log::logCK_RV( "C_Sign", rv );
+         Log::out( "C_Sign" );
+         Log::logCK_UTF8CHAR_PTR( "C_Sign - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+         Log::end( "C_Sign\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_SignUpdate continues a multiple-part signature operation,
+   * where the signature is (will be) an appendix to the data,
+   * and plaintext cannot be recovered from the signature.
+   *
+   * @param hSession       the session's handle
+   * @param pPart          the data to sign
+   * @param ulPartLen      count of bytes to sign
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_SignUpdate" );
+         Log::in( "C_SignUpdate" );
+         Log::log( "C_SignUpdate - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_SignUpdate - pPart", pPart, ulPartLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::SignUpdate(hSession,pPart,ulPartLen);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_SignUpdate" );
+
+         Log::logCK_RV( "C_SignUpdate", rv );
+         Log::end( "C_SignUpdate\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_SignFinal finishes a multiple-part signature operation,
+   * returning the signature.
+   *
+   * @param hSession           the session's handle
+   * @param pSignature         gets the signature
+   * @param pulSignatureLen    gets signature length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_SignFinal" );
+         Log::in( "C_SignFinal" );
+         Log::log( "C_SignFinal - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_SignFinal - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv =  Slot::SignFinal(hSession,pSignature,pulSignatureLen);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_SignFinal" );
+
+         Log::logCK_RV( "C_SignFinal", rv );
+         Log::out( "C_SignFinal" );
+         Log::logCK_UTF8CHAR_PTR( "C_SignFinal - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+         Log::end( "C_SignFinal\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /* C_SignRecoverInit initializes a signature operation, where
+   * the data can be recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignRecoverInit )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_SignRecoverInit" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SignRecoverInit", rv );
+      Log::end( "C_SignRecoverInit\n" );
+      return rv;
+   }
+
+
+   /* C_SignRecover signs data in a single operation, where the data can be recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignRecover )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_SignRecover" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SignRecover", rv );
+      Log::end( "C_SignRecover\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_VerifyInit initializes a verification operation, where the
+   * signature is an appendix to the data, and plaintext cannot
+   * cannot be recovered from the signature (e.g. DSA).
+   *
+   * @param hSession      the session's handle
+   * @param pMechanism    the verification mechanism
+   * @param hKey          verification key
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_VerifyInit" );
+         Log::in( "C_VerifyInit" );
+         Log::log( "C_VerifyInit - hSession <%#02x>", hSession );
+         Log::logCK_MECHANISM_PTR( "C_VerifyInit", pMechanism );
+         Log::log( "C_VerifyInit - hKey <%#02x>", hKey );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::VerifyInit( hSession, pMechanism, hKey );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_VerifyInit" );
+
+         Log::logCK_RV( "C_VerifyInit", rv );
+         Log::end( "C_VerifyInit\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_Verify verifies a signature in a single-part operation,
+   * where the signature is an appendix to the data, and plaintext
+   * cannot be recovered from the signature.
+   *
+   * @param hSession           the session's handle
+   * @param pData              signed data
+   * @param ulDataLen          length of signed data
+   * @param pSignature         signature
+   * @param ulSignatureLen     signature length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Verify )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_Verify" );
+         Log::in( "C_Verify" );
+         Log::log( "C_Verify - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_Verify - pData", pData, ulDataLen );
+         Log::logCK_UTF8CHAR_PTR( "C_Verify - pSignature", pSignature, ulSignatureLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::Verify(hSession,pData,ulDataLen,pSignature,ulSignatureLen);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_Verify" );
+         
+         Log::logCK_RV( "C_Verify", rv );
+         Log::out( "C_Verify" );
+         Log::logCK_UTF8CHAR_PTR( "C_Verify - pSignature", pSignature, ulSignatureLen );
+         Log::end( "C_Verify\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /* C_VerifyUpdate continues a multiple-part verification
+   * operation, where the signature is an appendix to the data,
+   * and plaintext cannot be recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_VerifyUpdate" );
+         Log::in( "C_VerifyUpdate" );
+         Log::log( "C_VerifyUpdate - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_VerifyUpdate - pPart", pPart, ulPartLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::VerifyUpdate(hSession,pPart,ulPartLen);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_VerifyUpdate" );
+
+         Log::logCK_RV( "C_VerifyUpdate", rv );
+         Log::end( "C_VerifyUpdate\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /* C_VerifyFinal finishes a multiple-part verification
+   * operation, checking the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_VerifyFinal" );
+         Log::in( "C_VerifyFinal" );
+         Log::log( "C_VerifyFinal - hSession <%#02x>", hSession );
+         Log::logCK_UTF8CHAR_PTR( "C_VerifyFinal - pSignature", pSignature, ulSignatureLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::VerifyFinal(hSession,pSignature,ulSignatureLen);
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_VerifyFinal" );
+         
+         Log::logCK_RV( "C_VerifyFinal", rv );
+         Log::end( "C_VerifyFinal\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /* C_VerifyRecoverInit initializes a signature verification
+   * operation, where the data is recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyRecoverInit )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_VerifyRecoverInit" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_VerifyRecoverInit", rv );
+      Log::end( "C_VerifyRecoverInit\n" );
+      return rv;
+   }
+
+
+   /* C_VerifyRecover verifies a signature in a single-part
+   * operation, where the data is recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyRecover )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_VerifyRecover" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_VerifyRecover", rv );
+      Log::end( "C_VerifyRecover\n" );
+      return rv;
+   }
+
+
+   /* C_DigestEncryptUpdate continues a multiple-part digesting and encryption operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestEncryptUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DigestEncryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DigestEncryptUpdate", rv );
+      Log::end( "C_DigestEncryptUpdate\n" );
+      return rv;
+   }
+
+
+   /* C_DecryptDigestUpdate continues a multiple-part decryption and digesting operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptDigestUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptDigestUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptDigestUpdate", rv );
+      Log::end( "C_DecryptDigestUpdate\n" );
+      return rv;
+   }
+
+
+   /* C_SignEncryptUpdate continues a multiple-part signing and encryption operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignEncryptUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_SignEncryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SignEncryptUpdate", rv );
+      Log::end( "C_SignEncryptUpdate\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptVerifyUpdate continues a multiple-part decryption and verify operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptVerifyUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR , CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptVerifyUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptVerifyUpdate", rv );
+      Log::end( "C_DecryptVerifyUpdate\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_GenerateKey generates a secret key, creating a new key object.
+   *
+   * @param    hSession,    the session's handle
+   * @param    pMechanism   key generation mech.
+   * @param    pTemplate    template for new key
+   * @param    ulCount      # of attrs in template
+   * @param    phKey        gets handle of new key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GenerateKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_GenerateKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_GenerateKey", rv );
+      Log::end( "C_GenerateKey\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_GenerateKeyPair generates a public-key/private-key pair,
+   * creating new key objects.
+   *
+   * @param hSession,                    session handle
+   * @param pMechanism,                  key-gen mech.
+   * @param pPublicKeyTemplate,          template for pub. key
+   * @param ulPublicKeyAttributeCount,   # pub. attrs.
+   * @param pPrivateKeyTemplate,         template for priv. key
+   * @param ulPrivateKeyAttributeCount,  # priv. attrs.
+   * @param phPublicKey,                 gets pub. key handle
+   * @param phPrivateKey                 gets priv key handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GenerateKeyPair )(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GenerateKeyPair" );
+         Log::in( "C_GenerateKeyPair" );
+         Log::log( "C_GenerateKeyPair - hSession <%#02x>", hSession );
+         Log::logCK_MECHANISM_PTR( "C_GenerateKeyPair", pMechanism );
+         Log::logCK_ATTRIBUTE_PTR( "C_GenerateKeyPair", pPublicKeyTemplate, ulPublicKeyAttributeCount );
+         Log::logCK_ATTRIBUTE_PTR( "C_GenerateKeyPair", pPrivateKeyTemplate, ulPrivateKeyAttributeCount );
+         Log::log( "C_GenerateKeyPair - phPublicKey <%#02x>", (phPublicKey == NULL_PTR) ? 0 : *phPublicKey );
+         Log::log( "C_GenerateKeyPair - phPrivateKey <%#02x>", (phPrivateKey == NULL_PTR) ? 0 : *phPrivateKey );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::GenerateKeyPair( hSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_GenerateKeyPair" );
+
+         Log::logCK_RV( "C_GenerateKeyPair", rv );
+         Log::out( "C_GenerateKeyPair" );
+         Log::log( "C_GenerateKeyPair - phPublicKey <%#02x>", (phPublicKey == NULL_PTR) ? 0 : *phPublicKey );
+         Log::log( "C_GenerateKeyPair - phPrivateKey <%#02x>", (phPrivateKey == NULL_PTR) ? 0 : *phPrivateKey );
+         Log::end( "C_GenerateKeyPair\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_WrapKey wraps (i.e., encrypts) a key.
+   *
+   * @param hSession              the session's handle
+   * @param pMechanism            the wrapping mechanism
+   * @param hWrappingKey          wrapping key
+   * @param hKey                  key to be wrapped
+   * @param pWrapperKey           gets wrapped key
+   * @param pulWrappedKeyLen      gets wrapped key size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_WrapKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_WrapKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_WrapKey", rv );
+      Log::end( "C_WrapKey\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+   * key object.
+   *
+   * @param   hSession           session's handle
+   * @param   pMechanism         unwrapping mech.
+   * @param   hUnwrappingKey     unwrapping key
+   * @param   pWrappedKey        the wrapped key
+   * @param   ulWrappedKeyLen    wrapped key len
+   * @param   pTemplate          new key template
+   * @param   ulAttributeCount   template length
+   * @param   phKey              gets new handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_UnwrapKey )(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_UnwrapKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_UnwrapKey", rv );
+      Log::end( "C_UnwrapKey\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_DeriveKey derives a key from a base key, creating a new key
+   * object.
+   *
+   * @param hSession              session's handle
+   * @param pMechanism            key deriv. mech.
+   * @param hBaseKey              base key
+   * @param pTemplate             new key template
+   * @param ulAttributeCount      template length
+   * @param phKey                 gets new handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DeriveKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_DeriveKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DeriveKey", rv );
+      Log::end( "C_DeriveKey\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_SeedRandom mixes additional seed material into the token's
+   * random number generator.
+   *
+   * @param hSession   the session's handle
+   * @param pSeed      the seed material
+   * @param ulSeedLen  length of seed material
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_SeedRandom )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG )
+   {
+      Log::begin( "C_SeedRandom" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_RANDOM_SEED_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SeedRandom", rv );
+      Log::end( "C_SeedRandom\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_GenerateRandom generates random data.
+   *
+   * @param hSession       the session's handle
+   * @param RandomData     receives the random data
+   * @param ulRandomLen    # of bytes to generate
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GenerateRandom )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen )
+   {
+      CCriticalSectionLocker cslock( _critSectAPI );
+      
+      CK_RV rv = CKR_OK;
+      
+      try
+      {
+         Log::begin( "C_GenerateRandom" );
+         Log::in( "C_GenerateRandom" );
+         Log::logCK_UTF8CHAR_PTR( "C_GenerateRandom", pRandomData, ulRandomLen );
+
+         Log::start( );
+         PKCS11_TRY
+         {
+            rv = Slot::GenerateRandom( hSession, pRandomData, ulRandomLen );
+         }
+         PKCS11_CATCH(rv)
+         Log::stop( "C_GenerateRandom" );
+         
+         Log::logCK_RV( "C_GenerateRandom", rv );
+         Log::out( "C_GenerateRandom" );
+         Log::logCK_UTF8CHAR_PTR( "C_GenerateRandom", pRandomData, ulRandomLen );
+         Log::end( "C_GenerateRandom\n" );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+      }
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetFunctionStatus is a legacy function; it obtains an
+   * updated status of a function running in parallel with an
+   * application.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetFunctionStatus )( CK_SESSION_HANDLE )
+   {
+      Log::begin( "C_GetFunctionStatus" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_GetFunctionStatus", rv );
+      Log::end( "C_GetFunctionStatus\n" );
+      return rv;
+   }
+
+
+   /**
+   * C_CancelFunction is a legacy function; it cancels a function
+   * running in parallel.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CancelFunction )( CK_SESSION_HANDLE )
+   {
+      Log::begin( "C_CancelFunction" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_CancelFunction", rv );
+      Log::end( "C_CancelFunction\n" );
+      return rv;
+   }
+
+   /* Functions added in for Cryptoki Version 2.01 or later */
+
+   /**
+   * C_WaitForSlotEvent waits for a slot event (token insertion,
+   * removal, etc.) to occur.
+   *
+   * @param flags      blocking/nonblocking flag
+   * @param pSlot      location that receives the slot ID
+   * @param pReserved  reserved.  Should be NULL_PTR
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_WaitForSlotEvent )( CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved )
+   {
+      //Log::begin("C_WaitForSlotEvent");
+
+      // Not Initialized
+      if (!_isInitialized)
+      {
+         Log::error( "C_WaitForSlotEvent", "CKR_CRYPTOKI_NOT_INITIALIZED" );
+         return CKR_CRYPTOKI_NOT_INITIALIZED;
+      }
+
+      if((pReserved != NULL_PTR) || (pSlot == NULL_PTR))
+      {
+         Log::error( "C_WaitForSlotEvent", "CKR_ARGUMENTS_BAD" );
+         return CKR_ARGUMENTS_BAD;
+      }
+
+      *pSlot = CK_UNAVAILABLE_INFORMATION;// -1;
+
+#ifdef INCLUDE_EVENTING
+      CMutex mut("a");
+
+      CK_SLOT_ID sid = 0;
+      for(;sid<CONFIG_MAX_SLOT;sid++)
+      {
+         Slot* slot = Application::_slotCache[sid];
+         if(slot != NULL_PTR)
+         {
+            if(slot->GetEvent())
+            {
+               *pSlot = slot->GetSlotId();
+               slot->SetEvent(CK_FALSE);
+               break;
+            }
+         }
+      }
+
+      mut.release();
+
+      if(*pSlot == (CK_SLOT_ID)-1)
+      {
+
+         if(flags & CKF_DONT_BLOCK)
+         {
+            //Log::log("CKR_NO_EVENT");
+            return CKR_NO_EVENT;
+         }
+         else
+         {
+            CryptokiEvent.Wait();
+            //Log::log("CryptokiEvent signal received in WaitForSlotEvent..");
+
+            CMutex mut("b");
+
+            CK_SLOT_ID sid = 0;
+
+            for(;sid<CONFIG_MAX_SLOT;sid++)
+            {
+               Slot* slot = Application::_slotCache[sid];
+
+               if(slot != NULL_PTR)
+               {
+                  if(slot->GetEvent())
+                  {
+                     *pSlot = slot->GetSlotId();
+                     Log::log( "C_WaitForSlotEvent - SlotID <%#02x>\n", *pSlot );
+                     slot->SetEvent(CK_FALSE);
+                     break;
+                  }
+               }
+            }
+
+            mut.release();
+
+            if(*pSlot == (CK_SLOT_ID)-1)
+            {
+               //Log::log("CKR_NO_EVENT");
+               return CKR_NO_EVENT;
+            }
+         }
+      }
+
+      return CKR_OK;
+#else
+      return CKR_NO_EVENT;
+#endif
+   }
+
+} // extern "C"

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,300 @@
+/* pkcs11.h include file for PKCS #11. */
+/* $Revision: 1.5 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined.  These
+ * macros are described below, and typical definitions for them
+ * are also given.  Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for Cryptoki structures should be set.  The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this.  You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object.  It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable Cryptoki library function definition out of a
+ * return type and a function name.  It should be used in the
+ * following fashion to define the exposed Cryptoki functions in
+ * a Cryptoki library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ *   CK_VOID_PTR pReserved
+ * )
+ * {
+ *   ...
+ * }
+ *
+ * If you're using Microsoft Developer Studio 5.0 to define a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ *   returnType __declspec(dllexport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to define a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ *   returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ *   returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name.  It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ *   CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ *   returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ *   returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ *   returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name.  It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ *   returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ *   returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ *   returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV.  It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ *   returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ *   returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ *   returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y)      x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST  1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+  extern CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points.  That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST  1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+  typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points.  A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library.  This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+  __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+  CK_VERSION    version;  /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11f.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11f.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11f.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,903 @@
+/* pkcs11f.h include file for PKCS #11. */
+/* $Revision: 1.5 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This header file contains pretty much everything about all the */
+/* Cryptoki function prototypes.  Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_VOID_PTR   pInitArgs  /* if this is not NULL_PTR, it gets
+                            * cast to CK_C_INITIALIZE_ARGS_PTR
+                            * and dereferenced */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_VOID_PTR   pReserved  /* reserved.  Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_INFO_PTR   pInfo  /* location that receives information */
+);
+#endif
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_FUNCTION_LIST_PTR_PTR ppFunctionList  /* receives pointer to
+                                            * function list */
+);
+#endif
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_BBOOL       tokenPresent,  /* only slots with tokens? */
+  CK_SLOT_ID_PTR pSlotList,     /* receives array of slot IDs */
+  CK_ULONG_PTR   pulCount       /* receives number of slots */
+);
+#endif
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID       slotID,  /* the ID of the slot */
+  CK_SLOT_INFO_PTR pInfo    /* receives the slot information */
+);
+#endif
+
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID        slotID,  /* ID of the token's slot */
+  CK_TOKEN_INFO_PTR pInfo    /* receives the token information */
+);
+#endif
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID            slotID,          /* ID of token's slot */
+  CK_MECHANISM_TYPE_PTR pMechanismList,  /* gets mech. array */
+  CK_ULONG_PTR          pulCount         /* gets # of mechs. */
+);
+#endif
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID            slotID,  /* ID of the token's slot */
+  CK_MECHANISM_TYPE     type,    /* type of mechanism */
+  CK_MECHANISM_INFO_PTR pInfo    /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+  CK_SLOT_ID      slotID,    /* ID of the token's slot */
+  CK_UTF8CHAR_PTR pPin,      /* the SO's initial PIN */
+  CK_ULONG        ulPinLen,  /* length in bytes of the PIN */
+  CK_UTF8CHAR_PTR pLabel     /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_UTF8CHAR_PTR   pPin,      /* the normal user's PIN */
+  CK_ULONG          ulPinLen   /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_UTF8CHAR_PTR   pOldPin,   /* the old PIN */
+  CK_ULONG          ulOldLen,  /* length of the old PIN */
+  CK_UTF8CHAR_PTR   pNewPin,   /* the new PIN */
+  CK_ULONG          ulNewLen   /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID            slotID,        /* the slot's ID */
+  CK_FLAGS              flags,         /* from CK_SESSION_INFO */
+  CK_VOID_PTR           pApplication,  /* passed to callback */
+  CK_NOTIFY             Notify,        /* callback function */
+  CK_SESSION_HANDLE_PTR phSession      /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID     slotID  /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE   hSession,  /* the session's handle */
+  CK_SESSION_INFO_PTR pInfo      /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,             /* session's handle */
+  CK_BYTE_PTR       pOperationState,      /* gets state */
+  CK_ULONG_PTR      pulOperationStateLen  /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR      pOperationState,      /* holds state */
+  CK_ULONG         ulOperationStateLen,  /* holds state length */
+  CK_OBJECT_HANDLE hEncryptionKey,       /* en/decryption key */
+  CK_OBJECT_HANDLE hAuthenticationKey    /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_USER_TYPE      userType,  /* the user type */
+  CK_UTF8CHAR_PTR   pPin,      /* the user's PIN */
+  CK_ULONG          ulPinLen   /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,   /* the object's template */
+  CK_ULONG          ulCount,     /* attributes in template */
+  CK_OBJECT_HANDLE_PTR phObject  /* gets new object's handle. */
+);
+#endif
+
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,    /* the session's handle */
+  CK_OBJECT_HANDLE     hObject,     /* the object's handle */
+  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new object */
+  CK_ULONG             ulCount,     /* attributes in template */
+  CK_OBJECT_HANDLE_PTR phNewObject  /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_OBJECT_HANDLE  hObject    /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_OBJECT_HANDLE  hObject,   /* the object's handle */
+  CK_ULONG_PTR      pulSize    /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_OBJECT_HANDLE  hObject,    /* the object's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs; gets vals */
+  CK_ULONG          ulCount     /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_OBJECT_HANDLE  hObject,    /* the object's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs and values */
+  CK_ULONG          ulCount     /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,  /* attribute values to match */
+  CK_ULONG          ulCount     /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE    hSession,          /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject,          /* gets obj. handles */
+ CK_ULONG             ulMaxObjectCount,  /* max handles to get */
+ CK_ULONG_PTR         pulObjectCount     /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the encryption mechanism */
+  CK_OBJECT_HANDLE  hKey         /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pData,               /* the plaintext data */
+  CK_ULONG          ulDataLen,           /* bytes of plaintext */
+  CK_BYTE_PTR       pEncryptedData,      /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedDataLen  /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,           /* session's handle */
+  CK_BYTE_PTR       pPart,              /* the plaintext data */
+  CK_ULONG          ulPartLen,          /* plaintext data len */
+  CK_BYTE_PTR       pEncryptedPart,     /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,                /* session handle */
+  CK_BYTE_PTR       pLastEncryptedPart,      /* last c-text */
+  CK_ULONG_PTR      pulLastEncryptedPartLen  /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the decryption mechanism */
+  CK_OBJECT_HANDLE  hKey         /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,           /* session's handle */
+  CK_BYTE_PTR       pEncryptedData,     /* ciphertext */
+  CK_ULONG          ulEncryptedDataLen, /* ciphertext length */
+  CK_BYTE_PTR       pData,              /* gets plaintext */
+  CK_ULONG_PTR      pulDataLen          /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pEncryptedPart,      /* encrypted data */
+  CK_ULONG          ulEncryptedPartLen,  /* input length */
+  CK_BYTE_PTR       pPart,               /* gets plaintext */
+  CK_ULONG_PTR      pulPartLen           /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,       /* the session's handle */
+  CK_BYTE_PTR       pLastPart,      /* gets plaintext */
+  CK_ULONG_PTR      pulLastPartLen  /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism  /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,     /* the session's handle */
+  CK_BYTE_PTR       pData,        /* data to be digested */
+  CK_ULONG          ulDataLen,    /* bytes of data to digest */
+  CK_BYTE_PTR       pDigest,      /* gets the message digest */
+  CK_ULONG_PTR      pulDigestLen  /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pPart,     /* data to be digested */
+  CK_ULONG          ulPartLen  /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_OBJECT_HANDLE  hKey       /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,     /* the session's handle */
+  CK_BYTE_PTR       pDigest,      /* gets the message digest */
+  CK_ULONG_PTR      pulDigestLen  /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the signature mechanism */
+  CK_OBJECT_HANDLE  hKey         /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pData,           /* the data to sign */
+  CK_ULONG          ulDataLen,       /* count of bytes to sign */
+  CK_BYTE_PTR       pSignature,      /* gets the signature */
+  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pPart,     /* the data to sign */
+  CK_ULONG          ulPartLen  /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pSignature,      /* gets the signature */
+  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism, /* the signature mechanism */
+  CK_OBJECT_HANDLE  hKey        /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pData,           /* the data to sign */
+  CK_ULONG          ulDataLen,       /* count of bytes to sign */
+  CK_BYTE_PTR       pSignature,      /* gets the signature */
+  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ *  cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */
+  CK_OBJECT_HANDLE  hKey         /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,       /* the session's handle */
+  CK_BYTE_PTR       pData,          /* signed data */
+  CK_ULONG          ulDataLen,      /* length of signed data */
+  CK_BYTE_PTR       pSignature,     /* signature */
+  CK_ULONG          ulSignatureLen  /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pPart,     /* signed data */
+  CK_ULONG          ulPartLen  /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,       /* the session's handle */
+  CK_BYTE_PTR       pSignature,     /* signature to verify */
+  CK_ULONG          ulSignatureLen  /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */
+  CK_OBJECT_HANDLE  hKey         /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pSignature,      /* signature to verify */
+  CK_ULONG          ulSignatureLen,  /* signature length */
+  CK_BYTE_PTR       pData,           /* gets signed data */
+  CK_ULONG_PTR      pulDataLen       /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pPart,               /* the plaintext data */
+  CK_ULONG          ulPartLen,           /* plaintext length */
+  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */
+  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */
+  CK_BYTE_PTR       pPart,               /* gets plaintext */
+  CK_ULONG_PTR      pulPartLen           /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pPart,               /* the plaintext data */
+  CK_ULONG          ulPartLen,           /* plaintext length */
+  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */
+  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */
+  CK_BYTE_PTR       pPart,               /* gets plaintext */
+  CK_ULONG_PTR      pulPartLen           /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,    /* the session's handle */
+  CK_MECHANISM_PTR     pMechanism,  /* key generation mech. */
+  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new key */
+  CK_ULONG             ulCount,     /* # of attrs in template */
+  CK_OBJECT_HANDLE_PTR phKey        /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,                    /* session
+                                                     * handle */
+  CK_MECHANISM_PTR     pMechanism,                  /* key-gen
+                                                     * mech. */
+  CK_ATTRIBUTE_PTR     pPublicKeyTemplate,          /* template
+                                                     * for pub.
+                                                     * key */
+  CK_ULONG             ulPublicKeyAttributeCount,   /* # pub.
+                                                     * attrs. */
+  CK_ATTRIBUTE_PTR     pPrivateKeyTemplate,         /* template
+                                                     * for priv.
+                                                     * key */
+  CK_ULONG             ulPrivateKeyAttributeCount,  /* # priv.
+                                                     * attrs. */
+  CK_OBJECT_HANDLE_PTR phPublicKey,                 /* gets pub.
+                                                     * key
+                                                     * handle */
+  CK_OBJECT_HANDLE_PTR phPrivateKey                 /* gets
+                                                     * priv. key
+                                                     * handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,      /* the wrapping mechanism */
+  CK_OBJECT_HANDLE  hWrappingKey,    /* wrapping key */
+  CK_OBJECT_HANDLE  hKey,            /* key to be wrapped */
+  CK_BYTE_PTR       pWrappedKey,     /* gets wrapped key */
+  CK_ULONG_PTR      pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,          /* session's handle */
+  CK_MECHANISM_PTR     pMechanism,        /* unwrapping mech. */
+  CK_OBJECT_HANDLE     hUnwrappingKey,    /* unwrapping key */
+  CK_BYTE_PTR          pWrappedKey,       /* the wrapped key */
+  CK_ULONG             ulWrappedKeyLen,   /* wrapped key len */
+  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */
+  CK_ULONG             ulAttributeCount,  /* template length */
+  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,          /* session's handle */
+  CK_MECHANISM_PTR     pMechanism,        /* key deriv. mech. */
+  CK_OBJECT_HANDLE     hBaseKey,          /* base key */
+  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */
+  CK_ULONG             ulAttributeCount,  /* template length */
+  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pSeed,     /* the seed material */
+  CK_ULONG          ulSeedLen  /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_BYTE_PTR       RandomData,  /* receives the random data */
+  CK_ULONG          ulRandomLen  /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+/* Functions added in for Cryptoki Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_FLAGS flags,        /* blocking/nonblocking flag */
+  CK_SLOT_ID_PTR pSlot,  /* location that receives the slot ID */
+  CK_VOID_PTR pRserved   /* reserved.  Should be NULL_PTR */
+);
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11t.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11t.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/pkcs11t.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,1701 @@
+/* pkcs11t.h include file for PKCS #11. */
+/* $Revision: 1.5 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file. */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE CK_FALSE
+#endif
+
+#ifndef TRUE
+#define TRUE CK_TRUE
+#endif
+#endif
+
+typedef unsigned short CK_USHORT;
+
+/* an unsigned 8-bit value */
+typedef unsigned char     CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE           CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE           CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE           CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int          CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG          CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE    0
+
+
+typedef CK_BYTE     CK_PTR   CK_BYTE_PTR;
+typedef CK_CHAR     CK_PTR   CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR   CK_UTF8CHAR_PTR;
+typedef CK_ULONG    CK_PTR   CK_ULONG_PTR;
+typedef void        CK_PTR   CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+
+typedef struct CK_VERSION {
+  CK_BYTE       major;  /* integer portion of version number */
+  CK_BYTE       minor;  /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+  /* manufacturerID and libraryDecription have been changed from
+   * CK_CHAR to CK_UTF8CHAR for v2.10 */
+  CK_VERSION    cryptokiVersion;     /* Cryptoki interface ver */
+  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */
+  CK_FLAGS      flags;               /* must be zero */
+
+  /* libraryDescription and libraryVersion are new for v2.0 */
+  CK_UTF8CHAR   libraryDescription[32];  /* blank padded */
+  CK_VERSION    libraryVersion;          /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR    CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER       0
+
+
+typedef CK_ULONG          CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+  /* slotDescription and manufacturerID have been changed from
+   * CK_CHAR to CK_UTF8CHAR for v2.10 */
+  CK_UTF8CHAR   slotDescription[64];  /* blank padded */
+  CK_UTF8CHAR   manufacturerID[32];   /* blank padded */
+  CK_FLAGS      flags;
+
+  /* hardwareVersion and firmwareVersion are new for v2.0 */
+  CK_VERSION    hardwareVersion;  /* version of hardware */
+  CK_VERSION    firmwareVersion;  /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ *      Bit Flag              Mask        Meaning
+ */
+#define CKF_TOKEN_PRESENT     0x00000001  /* a token is there */
+#define CKF_REMOVABLE_DEVICE  0x00000002  /* removable devices*/
+#define CKF_HW_SLOT           0x00000004  /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+  /* label, manufacturerID, and model have been changed from
+   * CK_CHAR to CK_UTF8CHAR for v2.10 */
+  CK_UTF8CHAR   label[32];           /* blank padded */
+  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */
+  CK_UTF8CHAR   model[16];           /* blank padded */
+  CK_CHAR       serialNumber[16];    /* blank padded */
+  CK_FLAGS      flags;               /* see below */
+
+  /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+   * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+   * changed from CK_USHORT to CK_ULONG for v2.0 */
+  CK_ULONG      ulMaxSessionCount;     /* max open sessions */
+  CK_ULONG      ulSessionCount;        /* sess. now open */
+  CK_ULONG      ulMaxRwSessionCount;   /* max R/W sessions */
+  CK_ULONG      ulRwSessionCount;      /* R/W sess. now open */
+  CK_ULONG      ulMaxPinLen;           /* in bytes */
+  CK_ULONG      ulMinPinLen;           /* in bytes */
+  CK_ULONG      ulTotalPublicMemory;   /* in bytes */
+  CK_ULONG      ulFreePublicMemory;    /* in bytes */
+  CK_ULONG      ulTotalPrivateMemory;  /* in bytes */
+  CK_ULONG      ulFreePrivateMemory;   /* in bytes */
+
+  /* hardwareVersion, firmwareVersion, and time are new for
+   * v2.0 */
+  CK_VERSION    hardwareVersion;       /* version of hardware */
+  CK_VERSION    firmwareVersion;       /* version of firmware */
+  CK_CHAR       utcTime[16];           /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ *      Bit Flag                    Mask        Meaning
+ */
+#define CKF_RNG                     0x00000001  /* has random #
+                                                 * generator */
+#define CKF_WRITE_PROTECTED         0x00000002  /* token is
+                                                 * write-
+                                                 * protected */
+#define CKF_LOGIN_REQUIRED          0x00000004  /* user must
+                                                 * login */
+#define CKF_USER_PIN_INITIALIZED    0x00000008  /* normal user's
+                                                 * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0.  If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED  0x00000020
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0.  If it is set, that means
+ * that the token has some sort of clock.  The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN          0x00000040
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0.  If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0.  If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS  0x00000200
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED       0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. This flag is deprecated in v2.11 and
+   onwards. */
+#define CKF_SECONDARY_AUTHENTICATION  0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW       0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY       0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED          0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED   0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW         0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY         0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED            0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED     0x00800000
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session */
+typedef CK_ULONG          CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO    0
+/* Normal user */
+#define CKU_USER  1
+/* Context specific (added in v2.20) */
+#define CKU_CONTEXT_SPECIFIC   2
+
+/* Not defined in PKCS#11, Add by KS */
+#define CKU_NONE 99
+#define CO_OBJECT_HANDLE_MASK  0x0000FFFF
+#define CO_SESSION_OBJECT      0x00000000
+#define CO_TOKEN_OBJECT        0x10000000
+
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_STATE;
+#define CKS_RO_PUBLIC_SESSION  0
+#define CKS_RO_USER_FUNCTIONS  1
+#define CKS_RW_PUBLIC_SESSION  2
+#define CKS_RW_USER_FUNCTIONS  3
+#define CKS_RW_SO_FUNCTIONS    4
+
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+  CK_SLOT_ID    slotID;
+  CK_STATE      state;
+  CK_FLAGS      flags;          /* see below */
+
+  /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+   * v2.0 */
+  CK_ULONG      ulDeviceError;  /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ *      Bit Flag                Mask        Meaning
+ */
+#define CKF_RW_SESSION          0x00000002  /* session is r/w */
+#define CKF_SERIAL_SESSION      0x00000004  /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object  */
+typedef CK_ULONG          CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes.  It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+/* CKO_MECHANISM is new for v2.20 */
+#define CKO_DATA              0x00000000
+#define CKO_CERTIFICATE       0x00000001
+#define CKO_PUBLIC_KEY        0x00000002
+#define CKO_PRIVATE_KEY       0x00000003
+#define CKO_SECRET_KEY        0x00000004
+#define CKO_HW_FEATURE        0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_MECHANISM         0x00000007
+#define CKO_VENDOR_DEFINED    0x80000000
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG          CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+/* CKH_USER_INTERFACE is new for v2.20 */
+#define CKH_MONOTONIC_COUNTER  0x00000001
+#define CKH_CLOCK           0x00000002
+#define CKH_USER_INTERFACE  0x00000003
+#define CKH_VENDOR_DEFINED  0x80000000
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG          CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA             0x00000000
+#define CKK_DSA             0x00000001
+#define CKK_DH              0x00000002
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA           0x00000003
+#define CKK_EC              0x00000003
+#define CKK_X9_42_DH        0x00000004
+#define CKK_KEA             0x00000005
+
+#define CKK_GENERIC_SECRET  0x00000010
+#define CKK_RC2             0x00000011
+#define CKK_RC4             0x00000012
+#define CKK_DES             0x00000013
+#define CKK_DES2            0x00000014
+#define CKK_DES3            0x00000015
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST            0x00000016
+#define CKK_CAST3           0x00000017
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5           0x00000018
+#define CKK_CAST128         0x00000018
+#define CKK_RC5             0x00000019
+#define CKK_IDEA            0x0000001A
+#define CKK_SKIPJACK        0x0000001B
+#define CKK_BATON           0x0000001C
+#define CKK_JUNIPER         0x0000001D
+#define CKK_CDMF            0x0000001E
+#define CKK_AES             0x0000001F
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKK_BLOWFISH        0x00000020
+#define CKK_TWOFISH         0x00000021
+
+#define CKK_VENDOR_DEFINED  0x80000000
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG          CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+/* CKC_WTLS is new for v2.20 */
+#define CKC_X_509           0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
+#define CKC_WTLS            0x00000002
+#define CKC_VENDOR_DEFINED  0x80000000
+
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
+
+/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
+   consists of an array of values. */
+#define CKF_ARRAY_ATTRIBUTE    0x40000000
+
+/* The following attribute types are defined: */
+#define CKA_CLASS              0x00000000
+#define CKA_TOKEN              0x00000001
+#define CKA_PRIVATE            0x00000002
+#define CKA_LABEL              0x00000003
+#define CKA_APPLICATION        0x00000010
+#define CKA_VALUE              0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID          0x00000012
+
+#define CKA_CERTIFICATE_TYPE   0x00000080
+#define CKA_ISSUER             0x00000081
+#define CKA_SERIAL_NUMBER      0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER          0x00000083
+#define CKA_OWNER              0x00000084
+#define CKA_ATTR_TYPES         0x00000085
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED            0x00000086
+
+/* CKA_CERTIFICATE_CATEGORY ...
+ * CKA_CHECK_VALUE are new for v2.20 */
+#define CKA_CERTIFICATE_CATEGORY        0x00000087
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN   0x00000088
+#define CKA_URL                         0x00000089
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008A
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008B
+#define CKA_CHECK_VALUE                 0x00000090
+
+#define CKA_KEY_TYPE           0x00000100
+#define CKA_SUBJECT            0x00000101
+#define CKA_ID                 0x00000102
+#define CKA_SENSITIVE          0x00000103
+#define CKA_ENCRYPT            0x00000104
+#define CKA_DECRYPT            0x00000105
+#define CKA_WRAP               0x00000106
+#define CKA_UNWRAP             0x00000107
+#define CKA_SIGN               0x00000108
+#define CKA_SIGN_RECOVER       0x00000109
+#define CKA_VERIFY             0x0000010A
+#define CKA_VERIFY_RECOVER     0x0000010B
+#define CKA_DERIVE             0x0000010C
+#define CKA_START_DATE         0x00000110
+#define CKA_END_DATE           0x00000111
+#define CKA_MODULUS            0x00000120
+#define CKA_MODULUS_BITS       0x00000121
+#define CKA_PUBLIC_EXPONENT    0x00000122
+#define CKA_PRIVATE_EXPONENT   0x00000123
+#define CKA_PRIME_1            0x00000124
+#define CKA_PRIME_2            0x00000125
+#define CKA_EXPONENT_1         0x00000126
+#define CKA_EXPONENT_2         0x00000127
+#define CKA_COEFFICIENT        0x00000128
+#define CKA_PRIME              0x00000130
+#define CKA_SUBPRIME           0x00000131
+#define CKA_BASE               0x00000132
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS         0x00000133
+#define CKA_SUBPRIME_BITS      0x00000134
+#define CKA_SUB_PRIME_BITS     CKA_SUBPRIME_BITS
+/* (To retain backwards-compatibility) */
+
+#define CKA_VALUE_BITS         0x00000160
+#define CKA_VALUE_LEN          0x00000161
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE        0x00000162
+#define CKA_LOCAL              0x00000163
+#define CKA_NEVER_EXTRACTABLE  0x00000164
+#define CKA_ALWAYS_SENSITIVE   0x00000165
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM  0x00000166
+
+#define CKA_MODIFIABLE         0x00000170
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS       0x00000180
+#define CKA_EC_PARAMS          0x00000180
+
+#define CKA_EC_POINT           0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * are new for v2.10. Deprecated in v2.11 and onwards. */
+#define CKA_SECONDARY_AUTH     0x00000200
+#define CKA_AUTH_PIN_FLAGS     0x00000201
+
+/* CKA_ALWAYS_AUTHENTICATE ...
+ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
+#define CKA_ALWAYS_AUTHENTICATE  0x00000202
+
+#define CKA_WRAP_WITH_TRUSTED    0x00000210
+#define CKA_WRAP_TEMPLATE        (CKF_ARRAY_ATTRIBUTE|0x00000211)
+#define CKA_UNWRAP_TEMPLATE      (CKF_ARRAY_ATTRIBUTE|0x00000212)
+
+/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_HW_FEATURE_TYPE    0x00000300
+#define CKA_RESET_ON_INIT      0x00000301
+#define CKA_HAS_RESET          0x00000302
+
+/* The following attributes are new for v2.20 */
+#define CKA_PIXEL_X                     0x00000400
+#define CKA_PIXEL_Y                     0x00000401
+#define CKA_RESOLUTION                  0x00000402
+#define CKA_CHAR_ROWS                   0x00000403
+#define CKA_CHAR_COLUMNS                0x00000404
+#define CKA_COLOR                       0x00000405
+#define CKA_BITS_PER_PIXEL              0x00000406
+#define CKA_CHAR_SETS                   0x00000480
+#define CKA_ENCODING_METHODS            0x00000481
+#define CKA_MIME_TYPES                  0x00000482
+#define CKA_MECHANISM_TYPE              0x00000500
+#define CKA_REQUIRED_CMS_ATTRIBUTES     0x00000501
+#define CKA_DEFAULT_CMS_ATTRIBUTES      0x00000502
+#define CKA_SUPPORTED_CMS_ATTRIBUTES    0x00000503
+#define CKA_ALLOWED_MECHANISMS          (CKF_ARRAY_ATTRIBUTE|0x00000600)
+
+#define CKA_VENDOR_DEFINED     0x80000000
+
+// Gemalto CKA
+#define CKA_GEMALTO_CTRINDEX   0x80000001
+#define CKA_GEMALTO_KEYSPEC    0x80000002
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+  CK_ATTRIBUTE_TYPE type;
+  CK_VOID_PTR       pValue;
+
+  /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+  CK_ULONG          ulValueLen;  /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+  CK_CHAR       year[4];   /* the year ("1900" - "9999") */
+  CK_CHAR       month[2];  /* the month ("01" - "12") */
+  CK_CHAR       day[2];    /* the day   ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN      0x00000000
+#define CKM_RSA_PKCS                   0x00000001
+#define CKM_RSA_9796                   0x00000002
+#define CKM_RSA_X_509                  0x00000003
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0.  They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS               0x00000004
+#define CKM_MD5_RSA_PKCS               0x00000005
+#define CKM_SHA1_RSA_PKCS              0x00000006
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS         0x00000007
+#define CKM_RIPEMD160_RSA_PKCS         0x00000008
+#define CKM_RSA_PKCS_OAEP              0x00000009
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000A
+#define CKM_RSA_X9_31                  0x0000000B
+#define CKM_SHA1_RSA_X9_31             0x0000000C
+#define CKM_RSA_PKCS_PSS               0x0000000D
+#define CKM_SHA1_RSA_PKCS_PSS          0x0000000E
+
+#define CKM_DSA_KEY_PAIR_GEN           0x00000010
+#define CKM_DSA                        0x00000011
+#define CKM_DSA_SHA1                   0x00000012
+#define CKM_DH_PKCS_KEY_PAIR_GEN       0x00000020
+#define CKM_DH_PKCS_DERIVE             0x00000021
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN      0x00000030
+#define CKM_X9_42_DH_DERIVE            0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE     0x00000032
+#define CKM_X9_42_MQV_DERIVE           0x00000033
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_RSA_PKCS            0x00000040
+#define CKM_SHA384_RSA_PKCS            0x00000041
+#define CKM_SHA512_RSA_PKCS            0x00000042
+#define CKM_SHA256_RSA_PKCS_PSS        0x00000043
+#define CKM_SHA384_RSA_PKCS_PSS        0x00000044
+#define CKM_SHA512_RSA_PKCS_PSS        0x00000045
+
+#define CKM_RC2_KEY_GEN                0x00000100
+#define CKM_RC2_ECB                    0x00000101
+#define CKM_RC2_CBC                    0x00000102
+#define CKM_RC2_MAC                    0x00000103
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL            0x00000104
+#define CKM_RC2_CBC_PAD                0x00000105
+
+#define CKM_RC4_KEY_GEN                0x00000110
+#define CKM_RC4                        0x00000111
+#define CKM_DES_KEY_GEN                0x00000120
+#define CKM_DES_ECB                    0x00000121
+#define CKM_DES_CBC                    0x00000122
+#define CKM_DES_MAC                    0x00000123
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL            0x00000124
+#define CKM_DES_CBC_PAD                0x00000125
+
+#define CKM_DES2_KEY_GEN               0x00000130
+#define CKM_DES3_KEY_GEN               0x00000131
+#define CKM_DES3_ECB                   0x00000132
+#define CKM_DES3_CBC                   0x00000133
+#define CKM_DES3_MAC                   0x00000134
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL           0x00000135
+#define CKM_DES3_CBC_PAD               0x00000136
+#define CKM_CDMF_KEY_GEN               0x00000140
+#define CKM_CDMF_ECB                   0x00000141
+#define CKM_CDMF_CBC                   0x00000142
+#define CKM_CDMF_MAC                   0x00000143
+#define CKM_CDMF_MAC_GENERAL           0x00000144
+#define CKM_CDMF_CBC_PAD               0x00000145
+
+/* the following four DES mechanisms are new for v2.20 */
+#define CKM_DES_OFB64                  0x00000150
+#define CKM_DES_OFB8                   0x00000151
+#define CKM_DES_CFB64                  0x00000152
+#define CKM_DES_CFB8                   0x00000153
+
+#define CKM_MD2                        0x00000200
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC                   0x00000201
+#define CKM_MD2_HMAC_GENERAL           0x00000202
+
+#define CKM_MD5                        0x00000210
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC                   0x00000211
+#define CKM_MD5_HMAC_GENERAL           0x00000212
+
+#define CKM_SHA_1                      0x00000220
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC                 0x00000221
+#define CKM_SHA_1_HMAC_GENERAL         0x00000222
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128                  0x00000230
+#define CKM_RIPEMD128_HMAC             0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL     0x00000232
+#define CKM_RIPEMD160                  0x00000240
+#define CKM_RIPEMD160_HMAC             0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL     0x00000242
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256                     0x00000250
+#define CKM_SHA256_HMAC                0x00000251
+#define CKM_SHA256_HMAC_GENERAL        0x00000252
+#define CKM_SHA384                     0x00000260
+#define CKM_SHA384_HMAC                0x00000261
+#define CKM_SHA384_HMAC_GENERAL        0x00000262
+#define CKM_SHA512                     0x00000270
+#define CKM_SHA512_HMAC                0x00000271
+#define CKM_SHA512_HMAC_GENERAL        0x00000272
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN               0x00000300
+#define CKM_CAST_ECB                   0x00000301
+#define CKM_CAST_CBC                   0x00000302
+#define CKM_CAST_MAC                   0x00000303
+#define CKM_CAST_MAC_GENERAL           0x00000304
+#define CKM_CAST_CBC_PAD               0x00000305
+#define CKM_CAST3_KEY_GEN              0x00000310
+#define CKM_CAST3_ECB                  0x00000311
+#define CKM_CAST3_CBC                  0x00000312
+#define CKM_CAST3_MAC                  0x00000313
+#define CKM_CAST3_MAC_GENERAL          0x00000314
+#define CKM_CAST3_CBC_PAD              0x00000315
+#define CKM_CAST5_KEY_GEN              0x00000320
+#define CKM_CAST128_KEY_GEN            0x00000320
+#define CKM_CAST5_ECB                  0x00000321
+#define CKM_CAST128_ECB                0x00000321
+#define CKM_CAST5_CBC                  0x00000322
+#define CKM_CAST128_CBC                0x00000322
+#define CKM_CAST5_MAC                  0x00000323
+#define CKM_CAST128_MAC                0x00000323
+#define CKM_CAST5_MAC_GENERAL          0x00000324
+#define CKM_CAST128_MAC_GENERAL        0x00000324
+#define CKM_CAST5_CBC_PAD              0x00000325
+#define CKM_CAST128_CBC_PAD            0x00000325
+#define CKM_RC5_KEY_GEN                0x00000330
+#define CKM_RC5_ECB                    0x00000331
+#define CKM_RC5_CBC                    0x00000332
+#define CKM_RC5_MAC                    0x00000333
+#define CKM_RC5_MAC_GENERAL            0x00000334
+#define CKM_RC5_CBC_PAD                0x00000335
+#define CKM_IDEA_KEY_GEN               0x00000340
+#define CKM_IDEA_ECB                   0x00000341
+#define CKM_IDEA_CBC                   0x00000342
+#define CKM_IDEA_MAC                   0x00000343
+#define CKM_IDEA_MAC_GENERAL           0x00000344
+#define CKM_IDEA_CBC_PAD               0x00000345
+#define CKM_GENERIC_SECRET_KEY_GEN     0x00000350
+#define CKM_CONCATENATE_BASE_AND_KEY   0x00000360
+#define CKM_CONCATENATE_BASE_AND_DATA  0x00000362
+#define CKM_CONCATENATE_DATA_AND_BASE  0x00000363
+#define CKM_XOR_BASE_AND_DATA          0x00000364
+#define CKM_EXTRACT_KEY_FROM_KEY       0x00000365
+#define CKM_SSL3_PRE_MASTER_KEY_GEN    0x00000370
+#define CKM_SSL3_MASTER_KEY_DERIVE     0x00000371
+#define CKM_SSL3_KEY_AND_MAC_DERIVE    0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH  0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN     0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE      0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE     0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH   0x00000377
+
+/* CKM_TLS_PRF is new for v2.20 */
+#define CKM_TLS_PRF                    0x00000378
+
+#define CKM_SSL3_MD5_MAC               0x00000380
+#define CKM_SSL3_SHA1_MAC              0x00000381
+#define CKM_MD5_KEY_DERIVATION         0x00000390
+#define CKM_MD2_KEY_DERIVATION         0x00000391
+#define CKM_SHA1_KEY_DERIVATION        0x00000392
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_KEY_DERIVATION      0x00000393
+#define CKM_SHA384_KEY_DERIVATION      0x00000394
+#define CKM_SHA512_KEY_DERIVATION      0x00000395
+
+#define CKM_PBE_MD2_DES_CBC            0x000003A0
+#define CKM_PBE_MD5_DES_CBC            0x000003A1
+#define CKM_PBE_MD5_CAST_CBC           0x000003A2
+#define CKM_PBE_MD5_CAST3_CBC          0x000003A3
+#define CKM_PBE_MD5_CAST5_CBC          0x000003A4
+#define CKM_PBE_MD5_CAST128_CBC        0x000003A4
+#define CKM_PBE_SHA1_CAST5_CBC         0x000003A5
+#define CKM_PBE_SHA1_CAST128_CBC       0x000003A5
+#define CKM_PBE_SHA1_RC4_128           0x000003A6
+#define CKM_PBE_SHA1_RC4_40            0x000003A7
+#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003A8
+#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003A9
+#define CKM_PBE_SHA1_RC2_128_CBC       0x000003AA
+#define CKM_PBE_SHA1_RC2_40_CBC        0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2                0x000003B0
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003C0
+
+/* WTLS mechanisms are new for v2.20 */
+#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003D0
+#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003D1
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003D2
+#define CKM_WTLS_PRF                        0x000003D3
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003D4
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003D5
+
+#define CKM_KEY_WRAP_LYNKS             0x00000400
+#define CKM_KEY_WRAP_SET_OAEP          0x00000401
+
+/* CKM_CMS_SIG is new for v2.20 */
+#define CKM_CMS_SIG                    0x00000500
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN           0x00001000
+#define CKM_SKIPJACK_ECB64             0x00001001
+#define CKM_SKIPJACK_CBC64             0x00001002
+#define CKM_SKIPJACK_OFB64             0x00001003
+#define CKM_SKIPJACK_CFB64             0x00001004
+#define CKM_SKIPJACK_CFB32             0x00001005
+#define CKM_SKIPJACK_CFB16             0x00001006
+#define CKM_SKIPJACK_CFB8              0x00001007
+#define CKM_SKIPJACK_WRAP              0x00001008
+#define CKM_SKIPJACK_PRIVATE_WRAP      0x00001009
+#define CKM_SKIPJACK_RELAYX            0x0000100a
+#define CKM_KEA_KEY_PAIR_GEN           0x00001010
+#define CKM_KEA_KEY_DERIVE             0x00001011
+#define CKM_FORTEZZA_TIMESTAMP         0x00001020
+#define CKM_BATON_KEY_GEN              0x00001030
+#define CKM_BATON_ECB128               0x00001031
+#define CKM_BATON_ECB96                0x00001032
+#define CKM_BATON_CBC128               0x00001033
+#define CKM_BATON_COUNTER              0x00001034
+#define CKM_BATON_SHUFFLE              0x00001035
+#define CKM_BATON_WRAP                 0x00001036
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN         0x00001040
+#define CKM_EC_KEY_PAIR_GEN            0x00001040
+
+#define CKM_ECDSA                      0x00001041
+#define CKM_ECDSA_SHA1                 0x00001042
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE               0x00001050
+#define CKM_ECDH1_COFACTOR_DERIVE      0x00001051
+#define CKM_ECMQV_DERIVE               0x00001052
+
+#define CKM_JUNIPER_KEY_GEN            0x00001060
+#define CKM_JUNIPER_ECB128             0x00001061
+#define CKM_JUNIPER_CBC128             0x00001062
+#define CKM_JUNIPER_COUNTER            0x00001063
+#define CKM_JUNIPER_SHUFFLE            0x00001064
+#define CKM_JUNIPER_WRAP               0x00001065
+#define CKM_FASTHASH                   0x00001070
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN                0x00001080
+#define CKM_AES_ECB                    0x00001081
+#define CKM_AES_CBC                    0x00001082
+#define CKM_AES_MAC                    0x00001083
+#define CKM_AES_MAC_GENERAL            0x00001084
+#define CKM_AES_CBC_PAD                0x00001085
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKM_BLOWFISH_KEY_GEN           0x00001090
+#define CKM_BLOWFISH_CBC               0x00001091
+#define CKM_TWOFISH_KEY_GEN            0x00001092
+#define CKM_TWOFISH_CBC                0x00001093
+
+
+/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
+#define CKM_DES_ECB_ENCRYPT_DATA       0x00001100
+#define CKM_DES_CBC_ENCRYPT_DATA       0x00001101
+#define CKM_DES3_ECB_ENCRYPT_DATA      0x00001102
+#define CKM_DES3_CBC_ENCRYPT_DATA      0x00001103
+#define CKM_AES_ECB_ENCRYPT_DATA       0x00001104
+#define CKM_AES_CBC_ENCRYPT_DATA       0x00001105
+
+#define CKM_DSA_PARAMETER_GEN          0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN      0x00002001
+#define CKM_X9_42_DH_PARAMETER_GEN     0x00002002
+
+#define CKM_VENDOR_DEFINED             0x80000000
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism  */
+typedef struct CK_MECHANISM {
+  CK_MECHANISM_TYPE mechanism;
+  CK_VOID_PTR       pParameter;
+
+  /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+   * v2.0 */
+  CK_ULONG          ulParameterLen;  /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+    CK_ULONG    ulMinKeySize;
+    CK_ULONG    ulMaxKeySize;
+    CK_FLAGS    flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ *      Bit Flag               Mask        Meaning */
+#define CKF_HW                 0x00000001  /* performed by HW */
+
+// Added by KS
+#define CKF_SW                 0x00000000 /* performed by SW */
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0.  They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT            0x00000100
+#define CKF_DECRYPT            0x00000200
+#define CKF_DIGEST             0x00000400
+#define CKF_SIGN               0x00000800
+#define CKF_SIGN_RECOVER       0x00001000
+#define CKF_VERIFY             0x00002000
+#define CKF_VERIFY_RECOVER     0x00004000
+#define CKF_GENERATE           0x00008000
+#define CKF_GENERATE_KEY_PAIR  0x00010000
+#define CKF_WRAP               0x00020000
+#define CKF_UNWRAP             0x00040000
+#define CKF_DERIVE             0x00080000
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P             0x00100000
+#define CKF_EC_F_2M            0x00200000
+#define CKF_EC_ECPARAMETERS    0x00400000
+#define CKF_EC_NAMEDCURVE      0x00800000
+#define CKF_EC_UNCOMPRESS      0x01000000
+#define CKF_EC_COMPRESS        0x02000000
+
+#define CKF_EXTENSION          0x80000000 /* FALSE for this version */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG          CK_RV;
+
+#define CKR_OK                                0x00000000
+#define CKR_CANCEL                            0x00000001
+#define CKR_HOST_MEMORY                       0x00000002
+#define CKR_SLOT_ID_INVALID                   0x00000003
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR                     0x00000005
+#define CKR_FUNCTION_FAILED                   0x00000006
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD                     0x00000007
+#define CKR_NO_EVENT                          0x00000008
+#define CKR_NEED_TO_CREATE_THREADS            0x00000009
+#define CKR_CANT_LOCK                         0x0000000A
+
+#define CKR_ATTRIBUTE_READ_ONLY               0x00000010
+#define CKR_ATTRIBUTE_SENSITIVE               0x00000011
+#define CKR_ATTRIBUTE_TYPE_INVALID            0x00000012
+#define CKR_ATTRIBUTE_VALUE_INVALID           0x00000013
+#define CKR_DATA_INVALID                      0x00000020
+#define CKR_DATA_LEN_RANGE                    0x00000021
+#define CKR_DEVICE_ERROR                      0x00000030
+#define CKR_DEVICE_MEMORY                     0x00000031
+#define CKR_DEVICE_REMOVED                    0x00000032
+#define CKR_ENCRYPTED_DATA_INVALID            0x00000040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE          0x00000041
+#define CKR_FUNCTION_CANCELED                 0x00000050
+#define CKR_FUNCTION_NOT_PARALLEL             0x00000051
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED            0x00000054
+
+#define CKR_KEY_HANDLE_INVALID                0x00000060
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE                    0x00000062
+#define CKR_KEY_TYPE_INCONSISTENT             0x00000063
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED                    0x00000064
+#define CKR_KEY_CHANGED                       0x00000065
+#define CKR_KEY_NEEDED                        0x00000066
+#define CKR_KEY_INDIGESTIBLE                  0x00000067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED        0x00000068
+#define CKR_KEY_NOT_WRAPPABLE                 0x00000069
+#define CKR_KEY_UNEXTRACTABLE                 0x0000006A
+
+#define CKR_MECHANISM_INVALID                 0x00000070
+#define CKR_MECHANISM_PARAM_INVALID           0x00000071
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID             0x00000082
+#define CKR_OPERATION_ACTIVE                  0x00000090
+#define CKR_OPERATION_NOT_INITIALIZED         0x00000091
+#define CKR_PIN_INCORRECT                     0x000000A0
+#define CKR_PIN_INVALID                       0x000000A1
+#define CKR_PIN_LEN_RANGE                     0x000000A2
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED                       0x000000A3
+#define CKR_PIN_LOCKED                        0x000000A4
+
+#define CKR_SESSION_CLOSED                    0x000000B0
+#define CKR_SESSION_COUNT                     0x000000B1
+#define CKR_SESSION_HANDLE_INVALID            0x000000B3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED    0x000000B4
+#define CKR_SESSION_READ_ONLY                 0x000000B5
+#define CKR_SESSION_EXISTS                    0x000000B6
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS          0x000000B7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS      0x000000B8
+
+#define CKR_SIGNATURE_INVALID                 0x000000C0
+#define CKR_SIGNATURE_LEN_RANGE               0x000000C1
+#define CKR_TEMPLATE_INCOMPLETE               0x000000D0
+#define CKR_TEMPLATE_INCONSISTENT             0x000000D1
+#define CKR_TOKEN_NOT_PRESENT                 0x000000E0
+#define CKR_TOKEN_NOT_RECOGNIZED              0x000000E1
+#define CKR_TOKEN_WRITE_PROTECTED             0x000000E2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID     0x000000F0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE         0x000000F1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT  0x000000F2
+#define CKR_USER_ALREADY_LOGGED_IN            0x00000100
+#define CKR_USER_NOT_LOGGED_IN                0x00000101
+#define CKR_USER_PIN_NOT_INITIALIZED          0x00000102
+#define CKR_USER_TYPE_INVALID                 0x00000103
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN    0x00000104
+#define CKR_USER_TOO_MANY_TYPES               0x00000105
+
+#define CKR_WRAPPED_KEY_INVALID               0x00000110
+#define CKR_WRAPPED_KEY_LEN_RANGE             0x00000112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID       0x00000113
+#define CKR_WRAPPING_KEY_SIZE_RANGE           0x00000114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT    0x00000115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED         0x00000120
+
+/* These are new to v2.0 */
+#define CKR_RANDOM_NO_RNG                     0x00000121
+
+/* These are new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID             0x00000130
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL                  0x00000150
+#define CKR_SAVED_STATE_INVALID               0x00000160
+#define CKR_INFORMATION_SENSITIVE             0x00000170
+#define CKR_STATE_UNSAVEABLE                  0x00000180
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED          0x00000190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED      0x00000191
+#define CKR_MUTEX_BAD                         0x000001A0
+#define CKR_MUTEX_NOT_LOCKED                  0x000001A1
+
+/* This is new to v2.20 */
+#define CKR_FUNCTION_REJECTED                 0x00000200
+
+#define CKR_VENDOR_DEFINED                    0x80000000
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+  CK_SESSION_HANDLE hSession,     /* the session's handle */
+  CK_NOTIFICATION   event,
+  CK_VOID_PTR       pApplication  /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+  CK_VOID_PTR_PTR ppMutex  /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+  CK_VOID_PTR pMutex  /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+  CK_VOID_PTR pMutex  /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+  CK_VOID_PTR pMutex  /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+  CK_CREATEMUTEX CreateMutex;
+  CK_DESTROYMUTEX DestroyMutex;
+  CK_LOCKMUTEX LockMutex;
+  CK_UNLOCKMUTEX UnlockMutex;
+  CK_FLAGS flags;
+  CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ *      Bit Flag                           Mask       Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
+#define CKF_OS_LOCKING_OK                  0x00000002
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK     1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE  is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
+ * are new for v2.20 */
+#define CKG_MGF1_SHA1         0x00000001
+#define CKG_MGF1_SHA256       0x00000002
+#define CKG_MGF1_SHA384       0x00000003
+#define CKG_MGF1_SHA512       0x00000004
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE  is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED    0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+        CK_MECHANISM_TYPE hashAlg;
+        CK_RSA_PKCS_MGF_TYPE mgf;
+        CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+        CK_VOID_PTR pSourceData;
+        CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+        CK_MECHANISM_TYPE    hashAlg;
+        CK_RSA_PKCS_MGF_TYPE mgf;
+        CK_ULONG             sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+/* CK_EC_KDF_TYPE is new for v2.11. */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL                 0x00000001
+#define CKD_SHA1_KDF             0x00000002
+
+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+  CK_EC_KDF_TYPE kdf;
+  CK_ULONG ulSharedDataLen;
+  CK_BYTE_PTR pSharedData;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+
+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+  CK_EC_KDF_TYPE kdf;
+  CK_ULONG ulSharedDataLen;
+  CK_BYTE_PTR pSharedData;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_ECMQV_DERIVE_PARAMS {
+  CK_EC_KDF_TYPE kdf;
+  CK_ULONG ulSharedDataLen;
+  CK_BYTE_PTR pSharedData;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+  CK_OBJECT_HANDLE publicKey;
+} CK_ECMQV_DERIVE_PARAMS;
+
+typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* The following X9.42 DH key derivation functions are defined
+   (besides CKD_NULL already defined : */
+#define CKD_SHA1_KDF_ASN1        0x00000003
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004
+
+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+  CK_X9_42_DH_KDF_TYPE kdf;
+  CK_ULONG ulOtherInfoLen;
+  CK_BYTE_PTR pOtherInfo;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+  CK_X9_42_DH_KDF_TYPE kdf;
+  CK_ULONG ulOtherInfoLen;
+  CK_BYTE_PTR pOtherInfo;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
+  CK_X9_42_DH_KDF_TYPE kdf;
+  CK_ULONG ulOtherInfoLen;
+  CK_BYTE_PTR pOtherInfo;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+  CK_OBJECT_HANDLE publicKey;
+} CK_X9_42_MQV_DERIVE_PARAMS;
+
+typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+  CK_BBOOL      isSender;
+  CK_ULONG      ulRandomLen;
+  CK_BYTE_PTR   pRandomA;
+  CK_BYTE_PTR   pRandomB;
+  CK_ULONG      ulPublicDataLen;
+  CK_BYTE_PTR   pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms.  An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG          CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+  /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+   * v2.0 */
+  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */
+
+  CK_BYTE       iv[8];            /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */
+  CK_ULONG      ulMacLength;      /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+  CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+  CK_ULONG      ulWordsize;  /* wordsize in bits */
+  CK_ULONG      ulRounds;    /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+  CK_ULONG      ulWordsize;  /* wordsize in bits */
+  CK_ULONG      ulRounds;    /* number of rounds */
+  CK_BYTE_PTR   pIv;         /* pointer to IV */
+  CK_ULONG      ulIvLen;     /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+  CK_ULONG      ulWordsize;   /* wordsize in bits */
+  CK_ULONG      ulRounds;     /* number of rounds */
+  CK_ULONG      ulMacLength;  /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+  CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms.  Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG          CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
+typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
+  CK_BYTE      iv[8];
+  CK_BYTE_PTR  pData;
+  CK_ULONG     length;
+} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+  CK_BYTE      iv[16];
+  CK_BYTE_PTR  pData;
+  CK_ULONG     length;
+} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+  CK_ULONG      ulPasswordLen;
+  CK_BYTE_PTR   pPassword;
+  CK_ULONG      ulPublicDataLen;
+  CK_BYTE_PTR   pPublicData;
+  CK_ULONG      ulPAndGLen;
+  CK_ULONG      ulQLen;
+  CK_ULONG      ulRandomLen;
+  CK_BYTE_PTR   pRandomA;
+  CK_BYTE_PTR   pPrimeP;
+  CK_BYTE_PTR   pBaseG;
+  CK_BYTE_PTR   pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+  CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+  CK_ULONG      ulOldWrappedXLen;
+  CK_BYTE_PTR   pOldWrappedX;
+  CK_ULONG      ulOldPasswordLen;
+  CK_BYTE_PTR   pOldPassword;
+  CK_ULONG      ulOldPublicDataLen;
+  CK_BYTE_PTR   pOldPublicData;
+  CK_ULONG      ulOldRandomLen;
+  CK_BYTE_PTR   pOldRandomA;
+  CK_ULONG      ulNewPasswordLen;
+  CK_BYTE_PTR   pNewPassword;
+  CK_ULONG      ulNewPublicDataLen;
+  CK_BYTE_PTR   pNewPublicData;
+  CK_ULONG      ulNewRandomLen;
+  CK_BYTE_PTR   pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+  CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+  CK_BYTE_PTR      pInitVector;
+  CK_UTF8CHAR_PTR  pPassword;
+  CK_ULONG         ulPasswordLen;
+  CK_BYTE_PTR      pSalt;
+  CK_ULONG         ulSaltLen;
+  CK_ULONG         ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+  CK_BYTE       bBC;     /* block contents byte */
+  CK_BYTE_PTR   pX;      /* extra data */
+  CK_ULONG      ulXLen;  /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
+  CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_RANDOM_DATA {
+  CK_BYTE_PTR  pClientRandom;
+  CK_ULONG     ulClientRandomLen;
+  CK_BYTE_PTR  pServerRandom;
+  CK_ULONG     ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+  CK_SSL3_RANDOM_DATA RandomInfo;
+  CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+  CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+  CK_OBJECT_HANDLE hClientMacSecret;
+  CK_OBJECT_HANDLE hServerMacSecret;
+  CK_OBJECT_HANDLE hClientKey;
+  CK_OBJECT_HANDLE hServerKey;
+  CK_BYTE_PTR      pIVClient;
+  CK_BYTE_PTR      pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+  CK_ULONG                ulMacSizeInBits;
+  CK_ULONG                ulKeySizeInBits;
+  CK_ULONG                ulIVSizeInBits;
+  CK_BBOOL                bIsExport;
+  CK_SSL3_RANDOM_DATA     RandomInfo;
+  CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+/* CK_TLS_PRF_PARAMS is new for version 2.20 */
+typedef struct CK_TLS_PRF_PARAMS {
+  CK_BYTE_PTR  pSeed;
+  CK_ULONG     ulSeedLen;
+  CK_BYTE_PTR  pLabel;
+  CK_ULONG     ulLabelLen;
+  CK_BYTE_PTR  pOutput;
+  CK_ULONG_PTR pulOutputLen;
+} CK_TLS_PRF_PARAMS;
+
+typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
+
+/* WTLS is new for version 2.20 */
+typedef struct CK_WTLS_RANDOM_DATA {
+  CK_BYTE_PTR pClientRandom;
+  CK_ULONG    ulClientRandomLen;
+  CK_BYTE_PTR pServerRandom;
+  CK_ULONG    ulServerRandomLen;
+} CK_WTLS_RANDOM_DATA;
+
+typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
+
+typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
+  CK_MECHANISM_TYPE   DigestMechanism;
+  CK_WTLS_RANDOM_DATA RandomInfo;
+  CK_BYTE_PTR         pVersion;
+} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+  CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_WTLS_PRF_PARAMS {
+  CK_MECHANISM_TYPE DigestMechanism;
+  CK_BYTE_PTR       pSeed;
+  CK_ULONG          ulSeedLen;
+  CK_BYTE_PTR       pLabel;
+  CK_ULONG          ulLabelLen;
+  CK_BYTE_PTR       pOutput;
+  CK_ULONG_PTR      pulOutputLen;
+} CK_WTLS_PRF_PARAMS;
+
+typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_OUT {
+  CK_OBJECT_HANDLE hMacSecret;
+  CK_OBJECT_HANDLE hKey;
+  CK_BYTE_PTR      pIV;
+} CK_WTLS_KEY_MAT_OUT;
+
+typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_PARAMS {
+  CK_MECHANISM_TYPE       DigestMechanism;
+  CK_ULONG                ulMacSizeInBits;
+  CK_ULONG                ulKeySizeInBits;
+  CK_ULONG                ulIVSizeInBits;
+  CK_ULONG                ulSequenceNumber;
+  CK_BBOOL                bIsExport;
+  CK_WTLS_RANDOM_DATA     RandomInfo;
+  CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_WTLS_KEY_MAT_PARAMS;
+
+typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
+
+/* CMS is new for version 2.20 */
+typedef struct CK_CMS_SIG_PARAMS {
+  CK_OBJECT_HANDLE      certificateHandle;
+  CK_MECHANISM_PTR      pSigningMechanism;
+  CK_MECHANISM_PTR      pDigestMechanism;
+  CK_UTF8CHAR_PTR       pContentType;
+  CK_BYTE_PTR           pRequestedAttributes;
+  CK_ULONG              ulRequestedAttributesLen;
+  CK_BYTE_PTR           pRequiredAttributes;
+  CK_ULONG              ulRequiredAttributesLen;
+} CK_CMS_SIG_PARAMS;
+
+typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+  CK_BYTE_PTR pData;
+  CK_ULONG    ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+  CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism.  It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED        0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+        CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE           saltSource;
+        CK_VOID_PTR                                pSaltSourceData;
+        CK_ULONG                                   ulSaltSourceDataLen;
+        CK_ULONG                                   iterations;
+        CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+        CK_VOID_PTR                                pPrfData;
+        CK_ULONG                                   ulPrfDataLen;
+        CK_UTF8CHAR_PTR                            pPassword;
+        CK_ULONG_PTR                               ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/platconfig.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/platconfig.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/platconfig.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,97 @@
+/* cryptoki.h include file for PKCS #11. */
+/* $Revision: 1.5 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This is a sample file containing the top level include directives
+ * for building Win32 Cryptoki libraries and applications.
+ */
+
+#ifndef _include_platconfig_h
+#define _include_platconfig_h
+
+#ifndef NULL_PTR
+    #define NULL_PTR 0
+#endif
+
+#ifdef _WIN32
+
+#pragma pack(push, plcryptoki, 1)
+
+/* Specifies that the function is a DLL entry point. */
+#define CK_IMPORT_SPEC __declspec(dllimport)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_EXPORT_SPEC __declspec(dllexport)
+#else
+#define CK_EXPORT_SPEC CK_IMPORT_SPEC
+#endif
+
+/* Ensures the calling convention for Win32 builds */
+#define CK_CALL_SPEC __cdecl
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+  returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+  returnType (CK_CALL_SPEC CK_PTR name)
+
+#ifdef _DEBUG
+    #define PKCS11_ASSERT(X)        assert(X)
+#else
+    #define PKCS11_ASSERT(X)
+#endif
+
+#include "pkcs11.h"
+
+#pragma pack(pop, plcryptoki)
+
+#else
+
+#define CK_IMPORT_SPEC
+#define CK_EXPORT_SPEC
+#define CK_CALL_SPEC
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+  returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+  returnType (CK_CALL_SPEC CK_PTR name)
+
+#define PKCS11_ASSERT(X)
+
+#include "pkcs11.h"
+
+#endif
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,372 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "privatekeyobject.h"
+
+PrivateKeyObject :: PrivateKeyObject() : KeyObject()
+{
+    this->_class                = CKO_PRIVATE_KEY;
+
+    this->_subject              = NULL_PTR;
+    this->_sensitive            = CK_TRUE;
+    this->_decrypt              = CK_TRUE;
+    this->_sign                 = CK_TRUE;
+    this->_signRecover          = CK_TRUE;
+    this->_unwrap               = CK_FALSE;
+    this->_extractable          = CK_FALSE;
+    this->_alwaysSensitive      = CK_TRUE;
+    this->_neverExtractable     = CK_TRUE;
+    this->_wrapWithTrusted      = CK_FALSE;
+    this->_alwaysAuthenticate   = CK_FALSE;
+
+    this->_ctrIndex = 0xFF; //-1;
+    this->_keyType  = CK_UNAVAILABLE_INFORMATION; //-1;
+}
+
+PrivateKeyObject :: ~PrivateKeyObject(){
+
+    if(this->_subject != NULL_PTR){
+        delete this->_subject;
+    }
+}
+
+bool PrivateKeyObject::IsEqual(const StorageObject * that) const
+{
+    if(_uniqueId != 0 && that->_uniqueId != 0)
+        return (_uniqueId == that->_uniqueId);
+
+    // Only objects that have been stored under p11 directory
+    // will have a non-zero _uniqueId. For other objects, do
+    // a deep comparison based on other attributes.
+    if(_class != that->_class)
+        return false;
+
+    const PrivateKeyObject * thatCert = static_cast<const PrivateKeyObject*>(that);
+    return ( (_ctrIndex == thatCert->_ctrIndex) &&
+             (_keySpec == thatCert->_keySpec) &&
+             (_checkValue == thatCert->_checkValue));
+}
+
+CK_BBOOL PrivateKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+
+        case CKA_SENSITIVE:
+            return (this->_sensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_DECRYPT:
+            return (this->_decrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SIGN:
+            return (this->_sign == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SIGN_RECOVER:
+            return (this->_signRecover == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_UNWRAP:
+            return (this->_unwrap == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_EXTRACTABLE:
+            return (this->_extractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ALWAYS_SENSITIVE:
+            return (this->_alwaysSensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_NEVER_EXTRACTABLE:
+            return (this->_neverExtractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_WRAP_WITH_TRUSTED:
+            return (this->_wrapWithTrusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ALWAYS_AUTHENTICATE:
+            return (this->_alwaysAuthenticate == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SUBJECT:
+            return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return KeyObject::Compare(attribute);
+
+    }
+}
+
+CK_RV PrivateKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type){
+
+        case CKA_SENSITIVE:
+            return StorageObject::PutBBoolInAttribute(this->_sensitive,attribute);
+
+        case CKA_DECRYPT:
+            return StorageObject::PutBBoolInAttribute(this->_decrypt,attribute);
+
+        case CKA_SIGN:
+            return StorageObject::PutBBoolInAttribute(this->_sign,attribute);
+
+        case CKA_SIGN_RECOVER:
+            return StorageObject::PutBBoolInAttribute(this->_signRecover,attribute);
+
+        case CKA_UNWRAP:
+            return StorageObject::PutBBoolInAttribute(this->_unwrap,attribute);
+
+        case CKA_EXTRACTABLE:
+            return StorageObject::PutBBoolInAttribute(this->_extractable,attribute);
+
+        case CKA_ALWAYS_SENSITIVE:
+            return StorageObject::PutBBoolInAttribute(this->_alwaysSensitive,attribute);
+
+        case CKA_NEVER_EXTRACTABLE:
+            return StorageObject::PutBBoolInAttribute(this->_neverExtractable,attribute);
+
+        case CKA_WRAP_WITH_TRUSTED:
+            return StorageObject::PutBBoolInAttribute(this->_wrapWithTrusted,attribute);
+
+        case CKA_ALWAYS_AUTHENTICATE:
+            return StorageObject::PutBBoolInAttribute(this->_alwaysAuthenticate,attribute);
+
+        case CKA_SUBJECT:
+            return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+        default:
+            return KeyObject::GetAttribute(attribute);
+    }
+}
+
+CK_RV PrivateKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE)
+    {
+        switch(attribute.type)
+        {
+            case CKA_ALWAYS_AUTHENTICATE:
+            case CKA_ALWAYS_SENSITIVE:
+            case CKA_NEVER_EXTRACTABLE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+
+            case CKA_DECRYPT:
+            case CKA_EXTRACTABLE:
+            case CKA_SENSITIVE:
+            case CKA_SIGN:
+            case CKA_SIGN_RECOVER:
+            case CKA_UNWRAP:
+            case CKA_WRAP_WITH_TRUSTED:
+                if(*(CK_BBOOL*)attribute.pValue == CK_TRUE){
+                    return CKR_ATTRIBUTE_READ_ONLY;
+                }
+                break;
+        }
+    }
+
+    switch(attribute.type){
+
+        case CKA_SENSITIVE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+
+                    if((objCreation == CK_FALSE) && (this->_sensitive == CK_TRUE) && (btemp == CK_FALSE)){
+                        rv = CKR_ATTRIBUTE_READ_ONLY;
+                    }else{
+                        this->_sensitive = btemp;
+
+                        if(btemp == CK_FALSE){
+                            this->_alwaysSensitive = CK_FALSE;
+                        }
+                    }
+                }
+            }
+            break;
+
+        case CKA_DECRYPT:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_decrypt = btemp; }
+            }
+            break;
+
+        case CKA_SIGN:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_sign = btemp; }
+            }
+            break;
+
+        case CKA_SIGN_RECOVER:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_signRecover = btemp; }
+            }
+            break;
+
+        case CKA_UNWRAP:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_unwrap = btemp; }
+            }
+            break;
+
+        case CKA_EXTRACTABLE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+
+                    if((objCreation == CK_FALSE) && (this->_extractable == CK_FALSE) && (btemp == CK_TRUE)){
+                        rv = CKR_ATTRIBUTE_READ_ONLY;
+                    }else{
+                        this->_extractable = btemp;
+
+                        if(btemp == CK_TRUE){
+                            this->_neverExtractable = CK_FALSE;
+                        }
+                    }
+                }
+            }
+            break;
+
+        case CKA_ALWAYS_SENSITIVE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_alwaysSensitive = btemp; }
+            }
+            break;
+
+
+        case CKA_NEVER_EXTRACTABLE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_neverExtractable = btemp; }
+            }
+            break;
+
+        case CKA_WRAP_WITH_TRUSTED:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_wrapWithTrusted = btemp; }
+            }
+            break;
+
+        case CKA_ALWAYS_AUTHENTICATE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_alwaysAuthenticate = btemp; }
+            }
+            break;
+
+        case CKA_SUBJECT:
+            if(this->_subject != NULL_PTR){
+                delete this->_subject;
+            }
+            this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+
+            break;
+
+        default:
+            return KeyObject::SetAttribute(attribute,objCreation);
+    }
+
+    return rv;
+}
+
+void PrivateKeyObject::Serialize(std::vector<u1> *to)
+{
+    KeyObject::Serialize(to);
+
+    Util::PushBBoolInVector(to,this->_sensitive);
+
+    Util::PushBBoolInVector(to,this->_decrypt);
+
+    Util::PushBBoolInVector(to,this->_sign);
+
+    Util::PushBBoolInVector(to,this->_signRecover);
+
+    Util::PushBBoolInVector(to,this->_unwrap);
+
+    Util::PushBBoolInVector(to,this->_extractable);
+
+    Util::PushBBoolInVector(to,this->_alwaysSensitive);
+
+    Util::PushBBoolInVector(to,this->_neverExtractable);
+
+    Util::PushBBoolInVector(to,this->_wrapWithTrusted);
+
+    Util::PushBBoolInVector(to,this->_alwaysAuthenticate);
+
+    Util::PushByteArrayInVector(to,this->_subject);
+
+    // serialize the extra fields
+
+    PKCS11_ASSERT(_checkValue != 0);
+    PKCS11_ASSERT(_ctrIndex < 100);
+    PKCS11_ASSERT(_keySpec == 1 || _keySpec == 2 );
+
+    Util::PushULongLongInVector(to,this->_checkValue);
+
+    Util::PushBBoolInVector(to,this->_ctrIndex);
+
+    Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void PrivateKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    KeyObject::Deserialize(from,idx);
+
+    this->_sensitive = Util::ReadBBoolFromVector(from,idx);
+
+    this->_decrypt = Util::ReadBBoolFromVector(from,idx);
+
+    this->_sign = Util::ReadBBoolFromVector(from,idx);
+
+    this->_signRecover = Util::ReadBBoolFromVector(from,idx);
+
+    this->_unwrap = Util::ReadBBoolFromVector(from,idx);
+
+    this->_extractable = Util::ReadBBoolFromVector(from,idx);
+
+    this->_alwaysSensitive = Util::ReadBBoolFromVector(from,idx);
+
+    this->_neverExtractable = Util::ReadBBoolFromVector(from,idx);
+
+    this->_wrapWithTrusted = Util::ReadBBoolFromVector(from,idx);
+
+    this->_alwaysAuthenticate = Util::ReadBBoolFromVector(from,idx);
+
+    this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+    // deserialize extra fields
+
+    this->_checkValue = Util::ReadULongLongFromVector(from,idx);
+
+    this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+    this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/privatekeyobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,63 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_privatekeyobject_h
+#define _include_privatekeyobject_h
+
+#include "keyobject.h"
+
+class PrivateKeyObject : public KeyObject
+{
+
+public:
+    u1Array*     _subject;
+    CK_BBOOL     _sensitive;
+    CK_BBOOL     _decrypt;
+    CK_BBOOL     _sign;
+    CK_BBOOL     _signRecover;
+    CK_BBOOL     _unwrap;
+    CK_BBOOL     _extractable;
+    CK_BBOOL     _alwaysSensitive;
+    CK_BBOOL     _neverExtractable;
+    CK_BBOOL     _wrapWithTrusted;
+    CK_BBOOL     _alwaysAuthenticate;
+
+    // extra fields which are not part of PKCS#11
+    // but are needed as extra information in card
+    u8          _checkValue;
+    CK_BYTE     _ctrIndex;
+    CK_BYTE     _keySpec;
+
+public:
+    PrivateKeyObject();
+    virtual ~PrivateKeyObject();
+
+    virtual bool IsEqual(const StorageObject * that) const;
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,205 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "publickeyobject.h"
+
+PublicKeyObject :: PublicKeyObject() : KeyObject()
+{
+   this->_class         = CKO_PUBLIC_KEY;
+
+   this->_encrypt       = CK_TRUE;
+   this->_verify        = CK_TRUE;
+   this->_verifyRecover = CK_TRUE;
+   this->_wrap          = CK_FALSE;
+
+   this->_subject       = NULL_PTR;
+
+   this->_ctrIndex = 0xFF; //-1;
+   this->_keyType  = CK_UNAVAILABLE_INFORMATION; //-1;
+}
+
+PublicKeyObject :: ~PublicKeyObject(){
+
+   if(this->_subject != NULL_PTR){
+      delete this->_subject;
+   }
+}
+
+CK_BBOOL PublicKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_ENCRYPT:
+           return (this->_encrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VERIFY:
+           return (this->_verify == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VERIFY_RECOVER:
+           return (this->_verifyRecover == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_WRAP:
+           return (this->_wrap == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SUBJECT:
+           return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+        default:
+           return KeyObject::Compare(attribute);
+   }
+}
+
+CK_RV PublicKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type){
+
+        case CKA_ENCRYPT:
+           return StorageObject::PutBBoolInAttribute(this->_encrypt,attribute);
+
+        case CKA_VERIFY:
+           return StorageObject::PutBBoolInAttribute(this->_verify,attribute);
+
+        case CKA_VERIFY_RECOVER:
+           return StorageObject::PutBBoolInAttribute(this->_verifyRecover,attribute);
+
+        case CKA_WRAP:
+           return StorageObject::PutBBoolInAttribute(this->_wrap,attribute);
+
+        case CKA_SUBJECT:
+           return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+        default:
+           return KeyObject::GetAttribute(attribute);
+
+   }
+}
+
+CK_RV PublicKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+   if(objCreation == CK_FALSE){
+      switch(attribute.type){
+            case CKA_ENCRYPT:
+            case CKA_TRUSTED:
+            case CKA_VERIFY:
+            case CKA_VERIFY_RECOVER:
+            case CKA_WRAP:
+               if(*(CK_BBOOL*)attribute.pValue == CK_TRUE){
+                  return CKR_ATTRIBUTE_READ_ONLY;
+               }
+               break;
+      }
+   }
+
+   switch(attribute.type){
+
+        case CKA_ENCRYPT:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_encrypt = btemp; }
+           }
+           break;
+
+        case CKA_VERIFY:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_verify = btemp; }
+           }
+           break;
+
+        case CKA_VERIFY_RECOVER:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_verifyRecover = btemp; }
+           }
+           break;
+
+        case CKA_WRAP:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_wrap = btemp; }
+           }
+           break;
+
+        case CKA_SUBJECT:
+           if(this->_subject != NULL_PTR){
+              delete this->_subject;
+           }
+           this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        default:
+           return KeyObject::SetAttribute(attribute,objCreation);
+   }
+
+   return rv;
+}
+
+void PublicKeyObject::Serialize(std::vector<u1> *to)
+{
+   KeyObject::Serialize(to);
+
+   Util::PushBBoolInVector(to,this->_encrypt);
+
+   Util::PushBBoolInVector(to,this->_verify);
+
+   Util::PushBBoolInVector(to,this->_verifyRecover);
+
+   Util::PushBBoolInVector(to,this->_wrap);
+
+   Util::PushByteArrayInVector(to,this->_subject);
+
+   // serialize the extra fields
+   Util::PushBBoolInVector(to,this->_ctrIndex);
+
+   Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void PublicKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   KeyObject::Deserialize(from,idx);
+
+   this->_encrypt = Util::ReadBBoolFromVector(from,idx);
+
+   this->_verify = Util::ReadBBoolFromVector(from,idx);
+
+   this->_verifyRecover = Util::ReadBBoolFromVector(from,idx);
+
+   this->_wrap = Util::ReadBBoolFromVector(from,idx);
+
+   this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+   // deserialize extra fields
+   this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+   this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/publickeyobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,56 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_publickeyobject_h
+#define _include_publickeyobject_h
+
+#include "keyobject.h"
+
+class PublicKeyObject : public KeyObject
+{
+
+public:
+    u1Array*     _subject;
+    CK_BBOOL     _encrypt;
+    CK_BBOOL     _verify;
+    CK_BBOOL     _verifyRecover;
+    CK_BBOOL     _wrap;
+    CK_BBOOL     _trusted;
+
+    // extra fields which are not part of PKCS#11
+    // but are needed as extra information in card
+    CK_BYTE     _ctrIndex;
+    CK_BYTE     _keySpec;
+
+public:
+    PublicKeyObject();
+    virtual ~PublicKeyObject();
+
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/resource.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/resource.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/resource.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by PKCS11Module.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,282 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "rsaprivatekeyobject.h"
+
+RSAPrivateKeyObject :: RSAPrivateKeyObject() : PrivateKeyObject()
+{
+    this->_modulus        = NULL_PTR;
+    this->_publicExponent = NULL_PTR;
+    this->_d              = NULL_PTR;
+    this->_p              = NULL_PTR;
+    this->_q              = NULL_PTR;
+    this->_dp             = NULL_PTR;
+    this->_dq             = NULL_PTR;
+    this->_inverseQ       = NULL_PTR;
+
+    this->_keyType        = CKK_RSA;
+
+}
+
+RSAPrivateKeyObject :: ~RSAPrivateKeyObject()
+{
+    if(this->_modulus != NULL_PTR){
+        delete this->_modulus;
+    }
+
+    if(this->_publicExponent != NULL_PTR){
+        delete this->_publicExponent;
+    }
+
+    if(this->_d != NULL_PTR){
+        delete this->_d;
+    }
+
+    if(this->_p != NULL_PTR){
+        delete this->_p;
+    }
+
+    if(this->_q != NULL_PTR){
+        delete this->_q;
+    }
+
+    if(this->_dp != NULL_PTR){
+        delete this->_dp;
+    }
+
+    if(this->_dq != NULL_PTR){
+        delete this->_dq;
+    }
+
+    if(this->_inverseQ != NULL_PTR){
+        delete this->_inverseQ;
+    }
+}
+
+CK_BBOOL RSAPrivateKeyObject ::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+
+        case CKA_MODULUS:
+            return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PUBLIC_EXPONENT:
+            return Util::CompareU1Arrays(this->_publicExponent,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PRIVATE_EXPONENT:
+            return Util::CompareU1Arrays(this->_d,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PRIME_1:
+            return Util::CompareU1Arrays(this->_p,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PRIME_2:
+            return Util::CompareU1Arrays(this->_q,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_EXPONENT_1:
+            return Util::CompareU1Arrays(this->_dp,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_EXPONENT_2:
+            return Util::CompareU1Arrays(this->_dq,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_COEFFICIENT:
+            return Util::CompareU1Arrays(this->_inverseQ,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return PrivateKeyObject::Compare(attribute);
+    }
+}
+
+CK_RV RSAPrivateKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_PUBLIC_EXPONENT:
+            case CKA_MODULUS:
+            case CKA_PRIVATE_EXPONENT:
+            case CKA_PRIME_1:
+            case CKA_PRIME_2:
+            case CKA_EXPONENT_1:
+            case CKA_EXPONENT_2:
+            case CKA_COEFFICIENT:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+
+         case CKA_MODULUS:
+            if(this->_modulus != NULL_PTR){
+                delete this->_modulus;
+            }
+            this->_modulus = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         case CKA_PUBLIC_EXPONENT:
+            if(this->_publicExponent != NULL_PTR){
+                delete this->_publicExponent;
+            }
+            this->_publicExponent = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         case CKA_PRIVATE_EXPONENT:
+            if(this->_d != NULL_PTR){
+                delete this->_d;
+            }
+            this->_d = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         case CKA_EXPONENT_1:
+            if(this->_dp != NULL_PTR){
+                delete this->_dp;
+            }
+            this->_dp = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_EXPONENT_2:
+            if(this->_dq != NULL_PTR){
+                delete this->_dq;
+            }
+            this->_dq = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_PRIME_1:
+            if(this->_p != NULL_PTR){
+                delete this->_p;
+            }
+            this->_p = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_PRIME_2:
+            if(this->_q != NULL_PTR){
+                delete this->_q;
+            }
+            this->_q = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_COEFFICIENT:
+            if( this->_inverseQ != NULL_PTR )
+            {
+                delete this->_inverseQ;
+            }
+            this->_inverseQ = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         default:
+             return PrivateKeyObject::SetAttribute(attribute,objCreation);
+
+    }
+
+    return CKR_OK;
+}
+
+CK_RV RSAPrivateKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type){
+
+        case CKA_MODULUS:
+            return StorageObject::PutU1ArrayInAttribute(this->_modulus,attribute);
+
+        case CKA_PUBLIC_EXPONENT:
+            return StorageObject::PutU1ArrayInAttribute(this->_publicExponent,attribute);
+
+        case CKA_PRIVATE_EXPONENT:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_d,attribute);
+
+        case CKA_PRIME_1:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_p,attribute);
+
+        case CKA_PRIME_2:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_q,attribute);
+
+        case CKA_EXPONENT_1:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_dp,attribute);
+
+        case CKA_EXPONENT_2:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_dq,attribute);
+
+        case CKA_COEFFICIENT:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_inverseQ,attribute);
+
+        default:
+            return PrivateKeyObject::GetAttribute(attribute);
+    }
+}
+
+void RSAPrivateKeyObject::Serialize(std::vector<u1> *to)
+{
+    PrivateKeyObject::Serialize(to);
+
+    // since keys will reside in the key container we are not going
+    // to marshal the key values except modulus and public exponent
+
+    Util::PushByteArrayInVector(to,this->_modulus);
+
+    Util::PushByteArrayInVector(to,this->_publicExponent);
+}
+
+void RSAPrivateKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    PrivateKeyObject::Deserialize(from,idx);
+
+    this->_modulus = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_publicExponent = Util::ReadByteArrayFromVector(from,idx);
+}
+
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/rsaprivatekeyobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,53 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_rsaprivatekeyobject_h
+#define _include_rsaprivatekeyobject_h
+
+#include "privatekeyobject.h"
+
+class RSAPrivateKeyObject : public PrivateKeyObject
+{
+
+public:
+    u1Array*    _publicExponent;
+    u1Array*    _modulus;
+    u1Array*    _d;
+    u1Array*    _p;
+    u1Array*    _q;
+    u1Array*    _dp;
+    u1Array*    _dq;
+    u1Array*    _inverseQ;
+
+public:
+     RSAPrivateKeyObject();
+    virtual ~RSAPrivateKeyObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,152 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "rsapublickeyobject.h"
+
+RSAPublicKeyObject :: RSAPublicKeyObject() : PublicKeyObject()
+{
+   this->_modulus    = NULL_PTR;
+   this->_modulusLen = 0;
+   this->_exponent   = NULL_PTR;
+
+   this->_keyType        = CKK_RSA;
+}
+
+RSAPublicKeyObject :: ~RSAPublicKeyObject()
+{
+   if(this->_modulus != NULL_PTR)
+      delete this->_modulus;
+
+   if(this->_exponent != NULL_PTR)
+      delete this->_exponent;
+}
+
+CK_BBOOL RSAPublicKeyObject ::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_MODULUS:
+           return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_MODULUS_BITS:
+           return (this->_modulusLen == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_PUBLIC_EXPONENT:
+           return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+        default:
+           return PublicKeyObject::Compare(attribute);
+   }
+}
+
+CK_RV RSAPublicKeyObject ::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type){
+
+        case CKA_MODULUS:
+           return StorageObject::PutU1ArrayInAttribute(this->_modulus,attribute);
+
+        case CKA_MODULUS_BITS:
+           return StorageObject::PutULongInAttribute(this->_modulusLen,attribute);
+
+        case CKA_PUBLIC_EXPONENT:
+           return StorageObject::PutU1ArrayInAttribute(this->_exponent,attribute);
+
+        default:
+           return PublicKeyObject::GetAttribute(attribute);
+   }
+}
+
+CK_RV RSAPublicKeyObject ::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+   if(objCreation == CK_FALSE){
+      switch(attribute.type){
+            case CKA_PUBLIC_EXPONENT:
+            case CKA_MODULUS:
+            case CKA_MODULUS_BITS:
+               return CKR_ATTRIBUTE_READ_ONLY;
+      }
+   }
+
+   switch(attribute.type){
+
+        case CKA_MODULUS:
+           if(this->_modulus != NULL_PTR){
+              delete this->_modulus;
+           }
+           this->_modulus = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           this->_modulusLen = _modulus->GetLength()*8;
+           break;
+
+        case CKA_PUBLIC_EXPONENT:
+           if(this->_exponent != NULL_PTR){
+              delete this->_exponent;
+           }
+           this->_exponent = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        case CKA_MODULUS_BITS:
+           {
+              CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_modulusLen = utemp;}
+           }
+           break;
+
+        default:
+           return PublicKeyObject::SetAttribute(attribute,objCreation);
+   }
+
+   return rv;
+}
+
+void RSAPublicKeyObject ::Serialize(std::vector<u1> *to)
+{
+   PublicKeyObject::Serialize(to);
+
+   Util::PushByteArrayInVector(to,this->_modulus);
+
+   Util::PushByteArrayInVector(to,this->_exponent);
+
+   Util::PushULongInVector(to,this->_modulusLen);
+}
+
+void RSAPublicKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   PublicKeyObject::Deserialize(from,idx);
+
+   this->_modulus = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_exponent = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_modulusLen = Util::ReadULongFromVector(from,idx);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/rsapublickeyobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,49 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_rsapublickeyobject_h
+#define _include_rsapublickeyobject_h
+
+#include "publickeyobject.h"
+
+class RSAPublicKeyObject : public PublicKeyObject
+{
+
+public:
+    u1Array*    _modulus;
+    CK_ULONG    _modulusLen;
+    u1Array*    _exponent;
+
+public:
+    RSAPublicKeyObject();
+    virtual ~RSAPublicKeyObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,4813 @@
+
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+#include <stdexcept>
+#include "cardmoduleservice.h"
+#include <Except.h>
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <memory>
+#include "session.h"
+#include "symmalgo.h"
+#include "tdes.h"
+#include "util.h"
+#include "zlib.h"
+#include "x509cert.h"
+#include "attrcert.h"
+#include "dataobject.h"
+#include "secretkeyobject.h"
+#include "transaction.h"
+#include "cardcache.h"
+#include "error.h"
+#include "timer.h"
+#include "md5.h"
+#include "log.h"
+
+
+#ifdef WIN32
+#include "BioMan.h"
+#else
+#define SCARD_CTL_CODE(code) (0x42000000 + (code))
+#endif
+
+// Helper functions to manage contents of cmapfile
+
+static void CMapFileClear(u1Array & file, u1 index);
+static void CMapFileSetName(u1Array & file, u1 index, string const & name);
+static u1 CMapFileGetFlag(u1Array const & file, u1 index);
+static void CMapFileSetFlag(u1Array & file, u1 index, u1 flag);
+static u2 CMapFileGetSignSize(u1Array const & file, u1 index);
+static void CMapFileSetSignSize(u1Array & file, u1 index, u2 size);
+static u2 CMapFileGetExchSize(u1Array const & file, u1 index);
+static void CMapFileSetExchSize(u1Array & file, u1 index, u2 size);
+
+// software RSA specific inclusion [they would be refined once I go and re-factor RSA algo as per Cryptoki naming convention]
+//#include "crypto_public.h"
+//#include "cr_rsa.h"
+
+#include "sctoken.h"
+
+#define BITS_0_7(l)  ((BYTE)(l & 0xff))
+#define BITS_8_15(l) ((BYTE)(((WORD)l & 0xff00) >> 8))
+
+#define MAX_RETRY 2
+
+#define CARD_PROPERTY_PIN_INFO_EX 0x87
+#define CARD_PROPERTY_PIN_INFO 0x07
+#define CARD_PROPERTY_EXTERNAL_PIN 0x01
+#define CARD_PROPERTY_NO_PIN 0x03
+#define CARD_PROPERTY_PIN_POLICY 0x80
+#define CARD_ROLE_USER 0x01
+#define CARD_SERIAL_NUMBER 0x06
+
+#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
+//#define FEATURE_VERIFY_PIN_START 0x01
+//#define FEATURE_VERIFY_PIN_FINISH 0x02
+//#define FEATURE_MODIFY_PIN_START 0x03
+//#define FEATURE_MODIFY_PIN_FINISH 0x04
+//#define FEATURE_GET_KEY_PRESSED 0x05
+#define FEATURE_VERIFY_PIN_DIRECT 0x06
+//#define FEATURE_MODIFY_PIN_DIRECT 0x07
+//#define FEATURE_MCT_READERDIRECT 0x08
+//#define FEATURE_MCT_UNIVERSAL 0x09
+//#define FEATURE_IFD_PIN_PROP 0x0A
+//#define FEATURE_ABORT 0x0B
+
+#define UVM_PIN_ONLY 1
+#define UVM_FP_ONLY 2
+#define UVM_PIN_OR_FP 3
+#define UVM_PIN_AND_FP 4
+
+#define PIN_TYPE_REGULAR 0
+#define PIN_TYPE_EXTERNAL 1
+
+#define AUTHENTICATE_ERROR 0
+#define AUTHENTICATE_REGULAR 1
+#define AUTHENTICATE_PINPAD 2
+#define AUTHENTICATE_BIO 3
+
+#define LOW_FREE_MEMORY_ALLOWED 25000
+
+#pragma pack(push, mdnet, 1)
+
+typedef struct PIN_VERIFY_STRUCTURE
+{
+   BYTE bTimerOut;                  /* timeout is seconds (00 means use default timeout) */
+   BYTE bTimerOut2;                 /* timeout in seconds after first key stroke */
+   BYTE bmFormatString;             /* formatting options */
+   BYTE bmPINBlockString;           /* bits 7-4 bit size of PIN length in APDU,
+                                    * bits 3-0 PIN block size in bytes after
+                                    * justification and formatting */
+   BYTE bmPINLengthFormat;          /* bits 7-5 RFU,
+                                    * bit 4 set if system units are bytes, clear if
+                                    * system units are bits,
+                                    * bits 3-0 PIN length position in system units
+                                    */
+   BYTE bPINMaxExtraDigit1;         /* Max PIN size*/
+   BYTE bPINMaxExtraDigit2;         /* Min PIN size*/
+   BYTE bEntryValidationCondition;  /* Conditions under which PIN entry should
+                                    * be considered complete */
+   BYTE bNumberMessage;             /* Number of messages to display for PIN
+                                    verification */
+   USHORT wLangId;                  /* Language for messages */
+   BYTE bMsgIndex;                  /* Message index (should be 00) */
+   BYTE bTeoPrologue[3];            /* T=1 block prologue field to use (fill with 00) */
+   ULONG ulDataLength;              /* length of Data to be sent to the ICC */
+   BYTE abData[13];                 /* Data to send to the ICC */
+} PIN_VERIFY_STRUCTURE;
+
+#pragma pack(pop, mdnet)
+
+// Try/catch macros for all public methods
+#define TOKEN_TRY try
+#define TOKEN_CATCH(rv) \
+   catch(CkError & err) { rv = err.Error(); } \
+   catch(PcscError & ) { rv = CKR_FUNCTION_FAILED; } \
+   catch(Marshaller::Exception & exc) { rv = CkError::CheckMarshallerException(exc); } \
+   catch(...) { rv = CKR_GENERAL_ERROR; } \
+   if(rv==CKR_USER_NOT_LOGGED_IN || rv==CKR_PIN_INCORRECT || rv==CKR_PIN_LOCKED) \
+   _roleLogged = CKU_NONE; \
+
+namespace {
+   class CardTransaction
+   {
+   private:
+      Token * _token;
+
+   public:
+      CardTransaction(Token * token) : _token(token)
+      {
+         _token->CardBeginTransaction();
+      }
+
+      ~CardTransaction() throw()
+      {
+         try
+         {
+            _token->CardEndTransaction();
+         }
+         catch(...) {}
+      }
+   };
+}
+
+Token::Token(std::string* reader) : _mscm(0),
+_supportGarbageCollection(true),
+_cardCache(0),
+_fPinChanged(false),
+_fContainerChanged(false),
+_fFileChanged(false),
+_version(0)
+{
+   //Log::begin( "Token::Token" );
+
+   m_dwIoctlVerifyPIN = 0;
+
+   m_sReaderName = "";
+   if( NULL != reader )
+   {
+      m_sReaderName = (*reader).c_str( );
+   }
+
+   std::string svcname("MSCM");
+   _mscm = new CardModuleService( reader, 5, &svcname );
+
+   _mscm->DoSCardTransact(false);  // Turn off transaction handling since it is performed at application level
+
+   // Transact card
+   CardTransaction ct(this);
+
+   _cardCache = new CardCache(_mscm);
+
+   // Get seed for RNG from card. This is the first command to
+   // card. If it fails, assume the card is not a .NET card.
+   try
+   {
+      auto_ptr<u1Array> challenge(_mscm->GetChallenge( ));
+      Util::SeedRandom(*challenge);
+   }
+   catch(...)
+   {
+      Log::error( "Token::Token", "GetChallenge - CKR_TOKEN_NOT_RECOGNIZED" );
+      throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+   }
+
+   this->_roleLogged   = CKU_NONE;
+
+   // flush TokenInfo
+   memset(&this->_tokenInfo, 0x00, sizeof(this->_tokenInfo));
+
+   this->_tokenInfo.ulMaxSessionCount      = CK_EFFECTIVELY_INFINITE;
+   this->_tokenInfo.ulSessionCount         = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulMaxRwSessionCount    = CK_EFFECTIVELY_INFINITE;
+   this->_tokenInfo.ulRwSessionCount       = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulMaxPinLen            = MAX_PIN_LEN;
+   this->_tokenInfo.ulMinPinLen            = MIN_PIN_LEN;
+
+   this->_tokenInfo.ulTotalPublicMemory    = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulTotalPrivateMemory   = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulFreePrivateMemory    = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulFreePublicMemory     = CK_UNAVAILABLE_INFORMATION;
+
+   // Version of the Card Operating system
+   this->_tokenInfo.hardwareVersion.major  = 2;
+   this->_tokenInfo.hardwareVersion.minor  = 0;
+
+   // (TBD) Version of Card Module application
+   // there is mess which have been created by reading it from file etc ?
+   this->_tokenInfo.firmwareVersion.major  = 2;
+   this->_tokenInfo.firmwareVersion.minor  = 0;
+
+   this->_tokenInfo.flags  = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED;
+
+   // Check if the smart card is in SSO mode
+   m_bIsSSO = isSSO( );
+
+   // Check if PinPad device is supported
+   m_bIsPinPadSupported = isPinPadSupported( );
+
+   // Get the card configuration (mode, PIN type)
+   m_bCardMode = UVM_PIN_ONLY;
+   m_bTypePIN = PIN_TYPE_REGULAR;
+   getCardConfiguration( m_bCardMode, m_bTypePIN );
+   
+   m_bIsNoPinSupported = false;
+   if( m_bTypePIN == 0x03 )
+   {
+      m_bIsNoPinSupported = true;
+   }
+
+   bool bIsAuthenticated = this->isAuthenticated( );
+
+   Log::log( "Token::Token - PIN type <%ld> (0 = regular ; 1 = external ; 2 = challenge/response ; 3 = no pin)", m_bTypePIN );
+   Log::log( "Token::Token - Card mode <%ld> (1 = pin only ; 2 = fp only ; 3 = fp or pin ; 4 = fp and pin)", m_bCardMode );
+   Log::log( "Token::Token - IsNoPinSupported <%d>", m_bIsNoPinSupported );
+   Log::log( "Token::Token - IsSSO <%d>", m_bIsSSO );
+   Log::log( "Token::Token - IsAuthenticated <%d>", bIsAuthenticated );
+
+   // Is login required ?
+   if(   ( true == m_bIsNoPinSupported ) 
+      || ( ( true == m_bIsSSO ) && ( true == bIsAuthenticated ) )
+      )
+   {
+      this->_tokenInfo.flags &= ~CKF_LOGIN_REQUIRED;
+      Log::log( "Token::Token - No login required" );
+   }
+
+   // Check if the CKF_PROTECTED_AUTHENTICATION_PATH flag must be raised
+   if( ( m_bTypePIN == PIN_TYPE_EXTERNAL ) && ( ( ( m_bCardMode == UVM_PIN_ONLY ) && m_bIsPinPadSupported ) || ( m_bCardMode != UVM_PIN_ONLY ) ) )
+   {
+      Log::log( "Token::Token - Enable CKF_PROTECTED_AUTHENTICATION_PATH" );
+      this->_tokenInfo.flags  |= CKF_PROTECTED_AUTHENTICATION_PATH;
+   }
+
+   // we need to check if token is initialized or not.
+   // Initialization would essentially mean that we create
+   // the necessary file structure.
+
+   // Get current value of \cardcf file
+   std::string sCardcf("cardcf");
+
+   //Log::log( "Token::Token - ReadFile ..." );
+   auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardcf,0));
+   //Log::log( "Token::Token - ReadFile ..." );
+
+   if(fileData->GetLength() < 6)
+   {
+      Log::error( "Token::Token", " (fileData->GetLength() < 6) - CKR_TOKEN_NOT_RECOGNIZED" );
+      throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+   }
+   CK_ULONG cardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+
+   //Log::log( "Token::Token - get serial number" );
+   //m_u1aSerialNumber = _mscm->GetCardProperty( CARD_SERIAL_NUMBER, 0 );
+
+   this->_initialized  = this->IsInitialized();
+
+   if(_initialized)
+   {
+      //Log::log( "Token::Token - DeserializeTokenInfo ..." );
+      this->DeserializeTokenInfo();
+      //Log::log( "Token::Token - DeserializeTokenInfo ok" );
+   }
+   else
+   {
+      //Log::log( "Token::Token - PopulateDefaultTokenInfo ..." );
+      // fill up the tokenInfo
+      this->PopulateDefaultTokenInfo();
+      //Log::log( "Token::Token - PopulateDefaultTokenInfo ok" );
+   }
+
+   // Set current values unequal to the stored to force the initial syncronization
+   _cardCfTimer = 0;
+   _cardCf = cardCf;
+   _publCardCf = ~cardCf;
+   _privCardCf = ~cardCf;
+   _cacheCardCf = ~cardCf;
+
+   //printf( "\nToken::Token - ManageGC( true )\n" );
+   //ManageGC( true );
+
+   //Log::end( "Token::Token" );
+}
+
+Token::~Token()
+{
+   Log::begin( "Token::~Token" );
+
+   ManageGC( true );
+
+   delete _cardCache;
+   
+   delete this->_mscm;
+   
+   //if( NULL != m_u1aSerialNumber )
+   //{
+   //   delete m_u1aSerialNumber;
+   //}
+
+   Clear();
+
+   Log::end( "Token::~Token" );
+}
+
+
+
+void Token::ManageGC( bool bForceGarbage )
+{
+   if(!_supportGarbageCollection)
+      return;
+   try
+   {
+      if( true == bForceGarbage )
+      {
+         //printf( "\nToken::ManageGC - ForceGarbageCollector (true)\n" );
+
+         Log::log( "Token::ManageGC - ForceGarbageCollector" );
+         _mscm->ForceGarbageCollector( );
+      }
+      else
+      {
+         s4 freeMemory = _mscm->GetMemory( );
+         if( freeMemory < LOW_FREE_MEMORY_ALLOWED )
+         {
+            //printf( "\nToken::ManageGC - ForceGarbageCollector\n" );
+
+            Log::log( "Token::ManageGC - ForceGarbageCollector (low)" );
+            _mscm->ForceGarbageCollector( );
+         }
+      }
+   }
+   catch(...)
+   {
+      _supportGarbageCollection = false;
+   }
+}
+
+
+void Token::Clear()
+{
+   for(size_t i=0;i<_objects.size();i++)
+      delete _objects[i];
+   _objects.clear( );
+}
+
+
+void Token::BeginTransaction()
+{
+   // To improve performance, avoid checking cardcf unless there could possibly
+   // have been an update by external application, based on the time it was last
+   // known to be up-do-date, which means at end of previous transaction.
+
+   static const unsigned long maximumCardCfCheckInterval = 100;  // 100 milliseconds.
+
+   CardBeginTransaction();
+   try
+   {
+      _fPinChanged = false;
+      _fContainerChanged = false;
+      _fFileChanged = false;
+
+      unsigned long tick = CTimer::ClockTicks();
+
+      // First check d.t possible timer wrap around every ~50 days.
+      if(_cardCfTimer > tick || _cardCfTimer + maximumCardCfCheckInterval < tick)
+      {
+         // Read cache file.
+         std::string sCardcf("cardcf");
+         auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardcf,0));
+         //ManageGC( );
+         if(fileData->GetLength() < 6)
+            throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+
+         _cardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+      }
+
+      if(   ( _publCardCf != _cardCf ) 
+         || (    ( _privCardCf != _cardCf ) 
+              && (    ( CKU_USER == _roleLogged )
+                   || ( true == m_bIsNoPinSupported ) 
+                   || ( ( true == m_bIsSSO ) && ( true == this->isAuthenticated( ) ) )
+                  )
+             )
+         )
+      //if((_publCardCf != _cardCf) ||
+      //   ((_privCardCf != _cardCf) && (_roleLogged == CKU_USER)))
+      {
+         // Card changed, so re-synchronize
+         Resynchronize();
+      }
+   }
+   catch(...)
+   {
+      CardEndTransaction();
+      throw;
+   }
+}
+
+void Token::EndTransaction( )
+{
+   try
+   {
+      // Update \cardcf if card has changed.
+      if(_fPinChanged || _fContainerChanged || _fFileChanged)
+      {
+         //  cardcf format:
+         //  typedef struct _CARD_CACHE_FILE_FORMAT
+         //  {
+         //      BYTE bVersion;
+         //      BYTE bPinsFreshness;
+         //      WORD wContainersFreshness;
+         //      WORD wFilesFreshness;
+         //  } CARD_CACHE_FILE_FORMAT, *PCARD_CACHE_FILE_FORMAT;
+
+         //  Read cache file.
+         std::string sCardCf("cardcf");
+         auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardCf,0));
+
+         BYTE bPinsFreshness = fileData->ReadU1At(1);
+         WORD wContainersFreshness = LittleEndianToInt<WORD>(fileData->GetBuffer(),2);
+         WORD wFilesFreshness = LittleEndianToInt<WORD>(fileData->GetBuffer(),4);
+
+         if(_fPinChanged)
+            bPinsFreshness++;
+         if(_fContainerChanged)
+            wContainersFreshness++;
+         if(_fFileChanged)
+            wFilesFreshness++;
+
+         fileData->SetU1At(1, bPinsFreshness);
+         IntToLittleEndian<WORD>(wContainersFreshness, fileData->GetBuffer(),2);
+         IntToLittleEndian<WORD>(wFilesFreshness, fileData->GetBuffer(),4);
+
+
+         // Write cache file back
+         _mscm->WriteFile(&sCardCf, fileData.get());
+
+         ManageGC( );
+
+         // As a result of own update, our own cache is still valid
+         // as long as it was valid before.
+         CK_ULONG newCardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+
+         if(_publCardCf == _cardCf)
+            _publCardCf = newCardCf;
+         if(_privCardCf == _cardCf)
+            _privCardCf = newCardCf;
+         if(_cacheCardCf == _cardCf)
+            _cacheCardCf = newCardCf;
+
+         _cardCf = newCardCf;
+         _cardCfTimer = CTimer::ClockTicks();
+      }
+      else
+         _cardCfTimer = CTimer::ClockTicks();
+   }
+   catch( CkError x )
+   {
+      CK_RV rv = x.Error( );
+      Log::log( "## Error ## Token::EndTransaction - WriteFile failed <%ld>\n", rv );
+   }
+   catch( ... )
+   {
+   }
+
+   CardEndTransaction( );
+}
+
+void Token::Resynchronize()
+{
+   //printf( "\nToken::Resynchronize\n" );
+
+   // To be called at initial creation and also whenever
+   // it is detected that card has been changed.
+   // When re-sync, one have to maintain the object handles
+   // of the objects that have not been deleted. Therefore,
+   // build a new object list and compare with the existing.
+
+   if(_cacheCardCf != _cardCf)
+   {
+      _cardCache->ClearAll();
+      _cacheCardCf = _cardCf;
+   }
+
+   map<int, ContainerInfo> contMap;
+   BuildContainerInfoMap(contMap);
+
+   vector<StorageObject*> newObjects;
+   vector<string> toDelete;
+
+   SynchronizePublicObjects(newObjects, toDelete, contMap);
+   SynchronizeCertificates(newObjects, contMap);
+
+   _publCardCf = _cardCf;
+
+   if(   ( CKU_USER == _roleLogged )
+      || ( true == m_bIsNoPinSupported ) 
+      || ( ( true == m_bIsSSO ) && ( true == this->isAuthenticated( ) ) )
+      )
+   {
+      CK_RV rv = CKR_OK;
+      TOKEN_TRY
+      {
+         SynchronizePrivateObjects(newObjects, toDelete, contMap);
+         SynchronizePrivateKeys(newObjects, contMap);
+         _privCardCf = _cardCf;
+      }
+      TOKEN_CATCH(rv);
+   }
+
+   // Build the new list with new objects occupying the
+   // position as the old objects. StorageObject::IsEqual
+   // is used to compare two objects.
+   vector<StorageObject*> objects(_objects.size(), 0);
+   for(size_t iobj = 0; iobj<_objects.size(); ++iobj)
+   {
+      if(!_objects[iobj])
+         continue;
+      for(size_t inew = 0; inew < newObjects.size(); ++inew)
+      {
+         if(newObjects[inew] && newObjects[inew]->IsEqual(_objects[iobj]))
+         {
+            // Transfer ownership
+            objects[iobj] = newObjects[inew];
+            newObjects[inew] = 0;
+            break;
+         }
+      }
+   }
+
+   // Add the potential new objects, which are those left in
+   // newObjects. Add them to the end of the list
+   for(size_t inew = 0; inew < newObjects.size(); ++inew)
+   {
+      if(newObjects[inew])
+         objects.push_back(newObjects[inew]);
+   }
+
+   // Delete the objects in the old object list
+   for(size_t iobj = 0; iobj<_objects.size(); ++iobj)
+      delete _objects[iobj];
+
+   // Store the new list as current
+   _objects = objects;
+
+   // Store the list of files to delete, then delete these if logged in.
+   _toDelete = toDelete;
+
+   if(   ( CKU_USER == _roleLogged )
+      || ( true == m_bIsNoPinSupported ) 
+      || ( ( true == m_bIsSSO ) && ( true == this->isAuthenticated( ) ) )
+      )
+   //if(   ( CKU_USER == _roleLogged )
+   {
+      PerformDeferredDelete();
+   }
+}
+
+u1Array* Token::ComputeCryptogram(u1Array* challenge,u1Array* pin)
+{
+
+   // time to prepare the master key.
+   // Only accept correct length, otherwise
+   // return a zero valued response that is
+   // sure to fail authentication.
+
+   CK_BYTE expectedCryptogram[8];
+   memset(expectedCryptogram,0x00,8);  // Default
+
+   if(pin->GetLength() == 24)
+   {
+      // compute the response
+      CK_BYTE iv[8];
+      memset(iv,0,8);
+
+      CTripleDES tdes;
+
+      tdes.SetEncryptMode(ENCRYPT);
+      tdes.SetIV(iv);
+      tdes.SetCipherMode(CIPHER_MODE_ECB);
+      tdes.SetPaddingMode(PADDING_MODE_NONE);
+      tdes.SetKey(pin->GetBuffer(),24);
+      tdes.TransformFinalBlock(challenge->GetBuffer(),0,8,expectedCryptogram,0);
+   }
+   u1Array* response = new u1Array(8);
+   response->SetBuffer(expectedCryptogram);
+
+   return response;
+}
+
+CK_RV Token::DoPINValidityChecks(u1Array* pin, bool fCheckCharaceters){
+
+   if((pin->GetLength() < MIN_PIN_LEN) || (pin->GetLength() > MAX_PIN_LEN)){
+      return CKR_PIN_LEN_RANGE;
+   }
+
+   if(fCheckCharaceters)
+   {
+      // check if pin is valid
+      for (u4 i = 0; i < pin->GetLength(); i++){
+         if ((pin->GetBuffer()[i] < 0x20) ||
+            (pin->GetBuffer()[i] > 0x7D) ||
+            (pin->GetBuffer()[i] == 0x24)||
+            (pin->GetBuffer()[i] == 0x40)||
+            (pin->GetBuffer()[i] == 0x60))
+         {
+            return CKR_PIN_INVALID;
+         }
+      }
+   }
+   return CKR_OK;
+}
+
+CK_RV Token::InitPIN(u1Array* soPIN,u1Array* userPIN)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      rv = Token::DoPINValidityChecks(userPIN);
+
+      if(rv != CKR_OK){
+         throw CkError(rv);
+      }
+
+      auto_ptr<u1Array> challenge(_mscm->GetChallenge());
+      auto_ptr<u1Array> cryptogram(ComputeCryptogram(challenge.get(), soPIN));
+
+      try{
+
+         this->_mscm->ChangeReferenceData(MODE_UNBLOCK_PIN,CARD_ROLE_USER,cryptogram.get(),userPIN,MAX_USER_PIN_TRIES);
+         this->RegisterPinUpdate();
+
+         // Log in user to update token info
+         this->_mscm->VerifyPin(CARD_ROLE_USER, userPIN);
+
+         if(_initialized)
+            DeserializeTokenInfo();
+         else
+            Initialize();
+
+         // Save User PIN Initialized flag, the other PIN flags are not stored
+         this->_tokenInfo.flags |= CKF_USER_PIN_INITIALIZED;
+         SerializeTokenInfo();
+         this->_mscm->LogOut(CARD_ROLE_USER);
+
+         // Reset some User PIN flags
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+
+      }
+      catch(Marshaller::RemotingException&){
+         rv = CKR_TOKEN_NOT_PRESENT;
+      }
+      catch(Marshaller::UnauthorizedAccessException&){
+
+         // incorrect pin
+         s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+         // blocked
+         if(triesRemaining == 0){
+            // update tokeninfo flahs
+            this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+         }else if(triesRemaining == 1){
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+            this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+         }else if(triesRemaining < MAX_SO_PIN_TRIES){
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+            this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+         }
+
+         rv = CKR_PIN_INCORRECT;
+
+      }
+      catch(std::runtime_error&){
+         rv = CKR_DEVICE_ERROR;
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::SetPIN(u1Array* oldPIN,u1Array* newPIN)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+
+      bool fCheckCharacters = (_roleLogged != CKU_SO);
+      rv = Token::DoPINValidityChecks(newPIN, fCheckCharacters);
+
+      if(rv != CKR_OK){
+         throw CkError(rv);
+      }
+
+      CK_BYTE  role       = 0;
+      s4 maxTries         = 0;
+
+      auto_ptr<u1Array> oldPINTemp;
+      auto_ptr<u1Array> newPINTemp;
+
+      if(this->_roleLogged == CKU_SO){
+
+         role = CARD_ROLE_ADMIN;
+         maxTries = MAX_SO_PIN_TRIES;
+
+         u1Array* challenge = this->_mscm->GetChallenge();
+
+         oldPINTemp = auto_ptr<u1Array>(this->ComputeCryptogram(challenge,oldPIN));
+
+         delete challenge;
+
+         // new PIN has to be 24 bytes
+         // if not we just pad rest of bytes as zeros
+         newPINTemp = auto_ptr<u1Array>(new u1Array(24));
+         memset(newPINTemp->GetBuffer(),0,24);
+         memcpy(newPINTemp->GetBuffer(),newPIN->GetBuffer(),newPIN->GetLength());
+
+      }else{
+
+         role = CARD_ROLE_USER;
+         maxTries = MAX_USER_PIN_TRIES;
+
+         oldPINTemp = auto_ptr<u1Array>(new u1Array(oldPIN->GetLength()));
+         oldPINTemp->SetBuffer(oldPIN->GetBuffer());
+
+         newPINTemp = auto_ptr<u1Array>(new u1Array(newPIN->GetLength()));
+         newPINTemp->SetBuffer(newPIN->GetBuffer());
+      }
+
+      try{
+         this->_mscm->ChangeReferenceData(MODE_CHANGE_PIN,role,oldPINTemp.get(),newPINTemp.get(),maxTries);
+         this->RegisterPinUpdate();
+      }
+      catch(Marshaller::RemotingException&){
+         rv = CKR_TOKEN_NOT_PRESENT;
+      }
+      catch(Marshaller::UnauthorizedAccessException&){
+
+         // incorrect pin
+         s4 triesRemaining = this->_mscm->GetTriesRemaining(role);
+
+         if(role == CARD_ROLE_ADMIN){
+
+            // blocked
+            if(triesRemaining == 0){
+               // update tokeninfo flahs
+               this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+            }else if(triesRemaining == 1){
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+               this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+            }else if(triesRemaining < MAX_SO_PIN_TRIES){
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+               this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+            }
+
+         }else{
+
+            // blocked
+            if(triesRemaining == 0){
+               // update tokeninfo flahs
+               this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+            }else if(triesRemaining == 1){
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+               this->_tokenInfo.flags |= CKF_USER_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+            }else if(triesRemaining < MAX_USER_PIN_TRIES){
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+               this->_tokenInfo.flags |= CKF_USER_PIN_COUNT_LOW;
+            }
+         }
+
+         rv = triesRemaining ? CKR_PIN_INCORRECT : CKR_PIN_LOCKED;
+
+
+      }
+      catch(std::runtime_error&){
+         rv = CKR_DEVICE_ERROR;
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::InitToken(u1Array* pin,u1Array* label)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+
+      // Check that label does not contain null-characters
+      PKCS11_ASSERT(label->GetLength() == 32);
+      for(u4 i = 0; i<label->GetLength(); ++i)
+      {
+         if(!label->ReadU1At(i))
+            throw CkError(CKR_ARGUMENTS_BAD);
+      }
+
+      // first check if pin is locked or not
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+      // blocked
+      if(triesRemaining == 0){
+         throw CkError(CKR_PIN_LOCKED);
+      }
+
+      // Change User PIN to random
+      R_RANDOM_STRUCT & randomStruc = Util::RandomStruct();
+      u1Array randomPin(MAX_PIN_LEN);
+      R_GenerateBytes(randomPin.GetBuffer(), MAX_PIN_LEN, &randomStruc);
+      // Make a number to comply with rules in DoPINValidityChecks
+      for(u4 i = 0; i < MAX_PIN_LEN; ++i)
+         randomPin.SetU1At(i, '0' + randomPin.ReadU1At(i)%10);   // Not 100% random any more....
+
+      rv = InitPIN(pin, &randomPin);
+      if(rv != CKR_OK)
+         throw CkError(rv);
+
+      // actual authentication
+      rv = this->AuthenticateAdmin(pin);
+      if(rv != CKR_OK){
+         throw CkError(rv);
+      }
+
+      // this seems strange the reason,
+      // I am doing this is to use DeleteObject
+      // method which expects the user to be logged
+      // in
+      this->_roleLogged = CKU_USER;
+
+      // TODO: InitToken should not care to do the regular token initialization
+      // in particular if it needs to clean up a token that will not load.....
+      // It should delete files directly as well as containers.
+      BeginTransaction();
+      try
+      {
+         if(!_initialized)
+            Initialize();
+
+         //Log::log("Deleting all token objects....");
+
+         // destroy all the token objects
+         for(size_t t=0; t<_objects.size(); t++){
+            if(this->_objects[t] != NULL_PTR){
+               // what if DeleteObject has failed for any reason ?
+               this->DeleteObject(CO_TOKEN_OBJECT | static_cast<CK_OBJECT_HANDLE>(t+1));
+            }
+         }
+
+         // Update the token's label and flags attribute.
+         // Re-fetch first to be sure _tokenInfo is valid
+         DeserializeTokenInfo();
+         _tokenInfo.flags |= CKF_TOKEN_INITIALIZED;
+         _tokenInfo.flags &= ~CKF_USER_PIN_INITIALIZED;
+         memcpy(_tokenInfo.label, label->GetBuffer(), 32);
+         SerializeTokenInfo();
+
+         _mscm->LogOut(CARD_ROLE_ADMIN);
+         _roleLogged = CKU_NONE;
+      }
+      catch(...)
+      {
+         _roleLogged = CKU_NONE;
+         try { _mscm->LogOut(CARD_ROLE_ADMIN); } catch(...) {}
+         EndTransaction();
+         throw;
+      }
+      EndTransaction();
+
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+bool Token::IsInitialized()
+{
+   bool result = false;
+
+   // the way we determine that token is not initialized
+   // is to check for the existence of p11 directory in the root
+   // since GetFiles() does not return directory I have base my judgement
+   // on the IOException or DirectoryNotFoundException for tinfo
+   std::string tinfo("p11\\tinfo");
+
+   try{
+      //ManageGC( );
+      _cardCache->ReadFile(tinfo);
+      result = true;
+   }
+   catch(...){}
+
+   return result;
+
+}
+
+void Token::CreateDirIfNotPresent(std::string* /*parent*/,std::string* dir,u1Array* acls)
+{
+
+   try{
+      this->_mscm->CreateDirectory(dir,acls);
+   }
+   catch(std::runtime_error&){
+      // ignore the exception as the directory may already be present
+      // TBD : May it more robust
+   }
+}
+
+void Token::Initialize()
+{
+   PKCS11_ASSERT(!_initialized);
+
+   std::string root("");
+   std::string p11("p11");
+
+   u1Array acls(3);
+   acls.GetBuffer()[0] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+   acls.GetBuffer()[1] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+   acls.GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+   // create p11 directory
+   this->CreateDirIfNotPresent(&root,&p11,&acls);
+
+   // create token info
+   std::string tinfo("p11\\tinfo");
+   _cardCache->ClearFileList("p11");
+   this->_mscm->CreateFile(&tinfo,&acls,0);
+
+   // Serialize default token Info
+   this->SerializeTokenInfo();
+
+   this->RegisterFileUpdate();
+
+   this->_initialized = true;
+
+}
+
+void Token::ReadAndPopulateObjects(vector<StorageObject*> & objects, vector<string> & toDelete,
+                                   string const & prefix, map<int, ContainerInfo> & contMap)
+{
+
+   CK_ULONG cls;
+
+   vector<string> files(_cardCache->FileList("p11"));
+
+   for(u4 i=0;i<files.size();i++)
+   {
+      std::string aFile(files[i]);
+
+      if(aFile.find(prefix) != 0) // Must start with <prefix>
+         continue;
+
+      std::string filePath("p11\\");
+
+      filePath.append(aFile);
+      const u1Array & fileData = _cardCache->ReadFile(filePath);
+
+      if (aFile.substr(prefix.size(), 3) == "dat")
+      {
+         cls = CKO_DATA;
+      }
+      //else if (aFile.substr(prefix.size(), 3) == "cer")
+      //{
+      //    cls = CKO_CERTIFICATE;
+      //}
+      else if (aFile.substr(prefix.size(), 3) == "kxc")
+      {
+         cls = CKO_CERTIFICATE;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "ksc")
+      {
+         cls = CKO_CERTIFICATE;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "puk")
+      {
+         cls = CKO_PUBLIC_KEY;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "prk")
+      {
+         cls = CKO_PRIVATE_KEY;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "sec")
+      {
+         cls = CKO_SECRET_KEY;
+      }
+      else
+      {
+         cls = CKO_VENDOR_DEFINED;
+      }
+
+      StorageObject* object = NULL_PTR;
+
+      switch(cls){
+
+            case CKO_DATA:
+               object = new DataObject();
+               break;
+
+            case CKO_PUBLIC_KEY:
+               object = new RSAPublicKeyObject();
+               break;
+
+            case CKO_PRIVATE_KEY:
+               object = new RSAPrivateKeyObject();
+               break;
+
+            case CKO_SECRET_KEY:
+               object = new SecretKeyObject();
+               break;
+
+            case CKO_CERTIFICATE:
+               object = new X509PubKeyCertObject();
+               ((X509PubKeyCertObject*)object)->_certName = aFile.substr(prefix.size(), aFile.size()-prefix.size());
+               break;
+
+            default:
+               continue;
+      }
+
+      vector<u1> from;
+      for(u4 u=0;u<fileData.GetLength();u++){
+         from.push_back(fileData.GetBuffer()[u]);
+      }
+
+      CK_ULONG idx = 0;
+
+      object->Deserialize(from,&idx);
+
+      // put the fileName for the object
+      // as it is not deserialized
+      object->_fileName = filePath;
+
+      bool fAddObject = true;
+
+      // For CKO_PRIVATE_KEY and CKO_CERTIFICATE, check that the objects
+      // actually exists in the container. If they don't, flag that the
+      // file shall be deleted.
+      if(cls == CKO_PRIVATE_KEY)
+      {
+         PrivateKeyObject * privKey = static_cast<PrivateKeyObject*>(object);
+         map<int, ContainerInfo>::iterator icont = contMap.find(privKey->_ctrIndex);
+         if(icont != contMap.end() && icont->second._cmapEntry)
+         {
+            KeyPair & keyPair = (privKey->_keySpec == KEYSPEC_KEYEXCHANGE) ?
+               icont->second._exchKP : icont->second._signKP;
+            if(keyPair._checkValue == privKey->_checkValue)
+            {
+               // Object exist in the container. Flag that there exists a P11 private
+               // key for this key pair so that it will not be instantiated twice.
+               keyPair._fP11PrivKeyExists = true;
+            }
+            else
+               fAddObject = false;
+         }
+         else
+            fAddObject = false;
+      }
+      else if(cls == CKO_CERTIFICATE)
+      {
+         X509PubKeyCertObject * cert = static_cast<X509PubKeyCertObject*>(object);
+         map<int, ContainerInfo>::iterator icont = contMap.find(cert->_ctrIndex);
+         if(icont != contMap.end() && icont->second._cmapEntry)
+         {
+            u1Array certValue;
+            KeyPair & keyPair = (cert->_keySpec == KEYSPEC_KEYEXCHANGE) ?
+               icont->second._exchKP : icont->second._signKP;
+
+            certValue = keyPair._cert;
+            if(certValue.GetLength())
+            {
+               u8 checkValue = 0;
+               try
+               {
+                  X509Cert x509cert(certValue.GetBuffer(), certValue.GetLength());
+                  BEROctet::Blob modulus(x509cert.Modulus());
+                  checkValue = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+                  if(cert->_checkValue == checkValue)
+                  {
+                     // Correct certificate! Assign the value and register it.
+                     // Flag that there exists a P11 certificate object for this
+                     // key pair so that it will not be instantiated twice.
+                     cert->_value = new u1Array();
+                     *cert->_value = certValue;
+                     keyPair._fP11CertExists = true;
+                  }
+                  else
+                     fAddObject = false;
+               }
+               catch(...)
+               {
+                  // Not valid X509 certificate, ignore it.
+                  fAddObject = false;
+               }
+            }
+            else
+               fAddObject = false;
+         }
+         else
+            fAddObject = false;
+      }
+
+      if(fAddObject)
+         objects.push_back(object);
+      else
+      {
+         delete object;
+         toDelete.push_back(filePath);
+      }
+   }
+}
+
+void Token::SynchronizePublicObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchrnoizing Public Objects...");
+
+   if(!_initialized){
+      //Log::log("Token not initialized, hence no objects.");
+      return;
+   }
+
+   ReadAndPopulateObjects(objects, toDelete, "pub", contMap);
+   //ManageGC();
+}
+
+void Token::SynchronizePrivateObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchronizing Private Objects...");
+
+   if(!_initialized){
+      //Log::log("Token not initialized, hence no objects.");
+      return;
+   }
+
+   ReadAndPopulateObjects(objects, toDelete, "pri", contMap);
+   //ManageGC();
+}
+
+void Token::BuildContainerInfoMap(map<int, ContainerInfo> & contMap)
+{
+   contMap.clear();
+
+   // Step 1: Populate map from existence of files named mscp\kxc## and mscp\ksc##
+   string mscpDir("mscp");
+   vector<string> mscpFiles(_cardCache->FileList(mscpDir));
+
+   for(u4 ifile = 0; ifile < mscpFiles.size(); ++ifile)
+   {
+      std::string aFile(mscpFiles[ifile]);
+      if(aFile.size() != 5 || aFile[0] != 'k' || aFile[2] != 'c')
+         continue;
+
+      u1 keySpec;
+      if(aFile[1] == 'x')
+         keySpec = KEYSPEC_KEYEXCHANGE;
+      else if(aFile[1] == 's')
+         keySpec = KEYSPEC_SIGNATURE;
+      else
+         continue;
+
+      int ctrIndex;
+      if(sscanf(aFile.substr(3, 2).c_str(), "%d", &ctrIndex) != 1)
+         continue;
+      if(ctrIndex <0)
+         continue;
+
+      // Read certificate file
+
+      std::string aFilePath = mscpDir + "\\" + aFile;
+
+      auto_ptr<u1Array> value(ReadCertificateFile(aFilePath));
+
+      if(keySpec == KEYSPEC_SIGNATURE)
+      {
+         contMap[ctrIndex]._signKP._cert = *value;
+         contMap[ctrIndex]._signKP._certName = aFile;
+      }
+      else
+      {
+         contMap[ctrIndex]._exchKP._cert = *value;
+         contMap[ctrIndex]._exchKP._certName = aFile;
+      }
+   }
+
+   // Step 2: Update map from valid cmapfile entries
+
+   std::string nameCMapFile("mscp\\cmapfile");
+   const u1Array & fileData = _cardCache->ReadFile(nameCMapFile);
+   u4 contentLen = fileData.GetLength();
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   vector<ContainerInfo> vContInfo;
+   for(int ctrIndex = 0; ctrIndex < entries; ++ctrIndex)
+   {
+      if(!(CMapFileGetFlag(fileData, ctrIndex) & 0x01))
+         continue;       // Skip not valid containers.
+
+      // Valid cmapfile entry for this ctrIndex
+      contMap[ctrIndex]._cmapEntry = true;
+
+      if(CMapFileGetSignSize(fileData, ctrIndex) || CMapFileGetExchSize(fileData, ctrIndex))
+      {
+         // Exchange
+         const CardCache::Container & cont = _cardCache->ReadContainer(ctrIndex);
+         u4 modulusLength = cont.exchModulus.GetLength();
+         if(modulusLength && CMapFileGetExchSize(fileData, ctrIndex) == modulusLength*8)
+         {
+            contMap[ctrIndex]._exchKP._modulus = cont.exchModulus;
+            contMap[ctrIndex]._exchKP._publicExponent = cont.exchPublicExponent;
+            contMap[ctrIndex]._exchKP._checkValue = Util::MakeCheckValue(cont.exchModulus.GetBuffer(), modulusLength);
+         }
+
+         // Signature
+         modulusLength = cont.signModulus.GetLength();
+         if(modulusLength && CMapFileGetSignSize(fileData, ctrIndex) == modulusLength*8)
+         {
+            contMap[ctrIndex]._signKP._modulus = cont.signModulus;
+            contMap[ctrIndex]._signKP._publicExponent = cont.signPublicExponent;
+            contMap[ctrIndex]._signKP._checkValue = Util::MakeCheckValue(cont.signModulus.GetBuffer(), modulusLength);
+         }
+      }
+   }
+}
+
+void Token::SynchronizeCertificates(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchronizing  Certificates...");
+
+   // Look for certificates in mscp that are not represented by P11 objects
+   for(map<int, ContainerInfo>::const_iterator icont = contMap.begin(); icont != contMap.end(); ++icont)
+   {
+      if(!icont->second._cmapEntry)
+         continue;   // Not corresponding to a valid cmapfile entry, ignore it.
+
+      u1 ctrIndex = static_cast<u1>(icont->first);
+
+      for(int ikeySpec = 0; ikeySpec < 2; ++ikeySpec)
+      {
+         u1 keySpec = (ikeySpec == 0) ? KEYSPEC_KEYEXCHANGE : KEYSPEC_SIGNATURE;
+         const KeyPair & keyPair = (ikeySpec == 0) ? icont->second._exchKP : icont->second._signKP;
+
+         // Certificates that have already been represented by object
+         // stored under p11 directory shall not be instantiated again.
+         if(keyPair._fP11CertExists)
+            continue;
+
+         if(keyPair._cert.GetLength())
+         {
+            if(!FindCertificate(objects, ctrIndex, keySpec))
+            {
+               //Log::log("Handling enrollement done from CSP...");
+
+               u8 checkValue = 0;
+               string strLabel;
+               BEROctet::Blob blId;
+               try
+               {
+                  CAttributedCertificate attrCert(keyPair._cert.GetBuffer(), keyPair._cert.GetLength());
+
+                  strLabel = attrCert.DerivedName();
+                  blId = attrCert.DerivedId();
+
+                  BEROctet::Blob modulus(attrCert.Modulus());
+                  checkValue = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+               }
+               catch(...)
+               {
+                  // Not valid X509 certificate, ignore it
+                  continue;
+               }
+
+               X509PubKeyCertObject* cert = new X509PubKeyCertObject();
+               cert->_value = new u1Array();
+               *cert->_value = keyPair._cert;
+               cert->_checkValue = checkValue;
+               cert->_certName = keyPair._certName;
+               cert->_keySpec = keySpec;
+               cert->_ctrIndex = ctrIndex;
+
+               cert->_tokenObject = CK_TRUE;
+               cert->_private = CK_FALSE;
+
+               cert->_label = new u1Array(static_cast<s4>(strLabel.size()));
+               cert->_label->SetBuffer(reinterpret_cast<const u1*>(strLabel.c_str()));
+
+               // If there is already a corresponding private key, assign
+               // the same id attribute, otherwise use the one derived from cert.
+               RSAPrivateKeyObject * priv = static_cast<RSAPrivateKeyObject*>(FindPrivateKey(objects, ctrIndex, keySpec));
+               if(priv && priv->_id->GetLength())
+               {
+                  cert->_id = new u1Array();
+                  *cert->_id = *priv->_id;
+               }
+               else
+               {
+                  cert->_id = new u1Array(static_cast<s4>(blId.size()));
+                  cert->_id->SetBuffer(reinterpret_cast<const u1*>(blId.c_str()));
+               }
+
+               // prepare object attributes from the parsed certificate
+               this->PrepareCertAttributesFromRawData(cert);
+
+               // Register this object
+               objects.push_back(cert);
+            }
+         }
+      }
+   }
+}
+
+void Token::SynchronizePrivateKeys(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchronizing  Private Keys...");
+
+   // Look for private keys in cmapfile that are not represented by P11 objects
+   for(map<int, ContainerInfo>::const_iterator icont = contMap.begin(); icont != contMap.end(); ++icont)
+   {
+      if(!icont->second._cmapEntry)
+         continue;   // Not corresponding to a valid cmapfile entry, ignore it.
+
+      u1 ctrIndex = static_cast<u1>(icont->first);
+
+      for(int ikeySpec = 0; ikeySpec < 2; ++ikeySpec)
+      {
+         u1 keySpec = (ikeySpec == 0) ? KEYSPEC_KEYEXCHANGE : KEYSPEC_SIGNATURE;
+         const KeyPair & keyPair = (ikeySpec == 0) ? icont->second._exchKP :  icont->second._signKP;
+
+         // Private keys that have already been represented by object
+         // stored under p11 directory shall not be instantiated again.
+         if(keyPair._fP11PrivKeyExists)
+            continue;
+
+         if(keyPair._checkValue)
+         {
+            if(!FindPrivateKey(objects, ctrIndex, keySpec))
+            {
+               //Log::log("Handling enrollement done from CSP...");
+
+               RSAPrivateKeyObject* priv = new RSAPrivateKeyObject();
+
+               // If there is a corresponding certificate, use its label, id and subject attribute
+
+               // TODO: Should check type before cast, however since there
+               // are no other certificate types than X509 here, this is safe
+               X509PubKeyCertObject * cert = static_cast<X509PubKeyCertObject*>(FindCertificate(objects, ctrIndex, keySpec));
+               if(cert)
+               {
+                  // If cert exist, inherit label and id from cert
+                  priv->_label = new u1Array();
+                  *priv->_label = *cert->_label;
+                  priv->_id = new u1Array();
+                  *priv->_id = *cert->_id;
+                  priv->_subject = new u1Array();
+                  *priv->_subject = *cert->_subject;
+               }
+               else
+               {
+                  BEROctet::Blob blId(CAttributedCertificate::DerivedId(keyPair._modulus.GetBuffer(),
+                     keyPair._modulus.GetLength()));
+                  priv->_id = new u1Array(static_cast<s4>(blId.size()));
+                  priv->_id->SetBuffer(blId.c_str());
+               }
+
+               priv->_ctrIndex = ctrIndex;
+               priv->_keySpec  = keySpec;
+               priv->_tokenObject = CK_TRUE;
+               priv->_private = CK_TRUE;
+               priv->_decrypt = CK_TRUE;
+               priv->_unwrap = CK_TRUE;
+               priv->_derive = CK_FALSE;
+               priv->_sign = CK_TRUE;
+               priv->_signRecover = CK_FALSE;
+               priv->_publicExponent = new u1Array();
+               *priv->_publicExponent = keyPair._publicExponent;
+               priv->_modulus = new u1Array();
+               *priv->_modulus = keyPair._modulus;
+               priv->_checkValue = keyPair._checkValue;
+
+               // add this in the token object list
+               objects.push_back(priv);
+            }
+         }
+      }
+   }
+}
+
+void Token::PrepareCertAttributesFromRawData(X509PubKeyCertObject* certObject)
+{
+
+   u1*           pCertValue = NULL;
+   unsigned long dwCertLen = 0;
+   u1Array*      sernbP = NULL;
+   u1Array*      issuerP = NULL;
+   u1Array*      subjectP = NULL;
+
+   pCertValue = certObject->_value->GetBuffer();
+   dwCertLen  = certObject->_value->GetLength();
+
+   // Parse Certifcate to extract SerNB, Issuer & Subject
+   // Create check value from modulus
+
+   try {
+      X509Cert x509cert(pCertValue, dwCertLen);
+
+      BEROctet::Blob blSerNum(x509cert.SerialNumber());
+      BEROctet::Blob blIssuer(x509cert.Issuer());
+      BEROctet::Blob blSubject(x509cert.Subject());
+      BEROctet::Blob modulus(x509cert.Modulus());
+
+      sernbP   = new u1Array(static_cast<s4>(blSerNum.size()));
+      sernbP->SetBuffer(const_cast<u1*>(blSerNum.data()));
+
+      issuerP  = new u1Array(static_cast<s4>(blIssuer.size()));
+      issuerP->SetBuffer(const_cast<u1*>(blIssuer.data()));
+
+      subjectP = new u1Array(static_cast<s4>(blSubject.size()));
+      subjectP->SetBuffer(const_cast<u1*>(blSubject.data()));
+
+      certObject->_serialNumber = sernbP;
+      certObject->_issuer       = issuerP;
+      certObject->_subject      = subjectP;
+   }
+   catch(...) {} // On parse error, these attributes can't be set.
+
+}
+
+
+CK_RV Token::AuthenticateUser(Marshaller::u1Array *pin)
+{
+   CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;
+
+   try
+   {
+      // first check if pin is locked or not
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_USER);
+
+      // blocked
+      if(triesRemaining == 0)
+      {
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+
+         return CKR_PIN_LOCKED;
+      }
+
+      int iCase = howToAuthenticate( pin->GetLength( ) );
+      switch( iCase )
+      {
+      case AUTHENTICATE_REGULAR:
+         Log::log( "Token::AuthenticateUser - Normal login" );
+         this->_mscm->VerifyPin( CARD_ROLE_USER, pin );
+         rv = CKR_OK;
+         break;
+
+      case AUTHENTICATE_PINPAD:
+         Log::log( "Token::AuthenticateUser - PinPad" );
+         rv = verifyPinWithPinPad( );
+         break;
+
+      case AUTHENTICATE_BIO:
+#ifdef WIN32
+         Log::log( "Token::AuthenticateUser - BIO" );
+         rv = verifyPinWithBio( /*pin*/ );
+#else
+      Log::log( "Token::AuthenticateUser - BIO not supported !!" );
+      rv = CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+         break;
+
+      default:
+         Log::log( "Token::AuthenticateUser - Unknown !!" );
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+         break;
+      }
+   }
+   catch(Marshaller::RemotingException&)
+   {
+      rv = CKR_TOKEN_NOT_PRESENT;
+   }
+   catch(Marshaller::UnauthorizedAccessException&)
+   {
+      rv = CKR_PIN_INCORRECT;
+   }
+   catch(std::runtime_error&)
+   {
+      rv = CKR_DEVICE_ERROR;
+   }
+
+   if( CKR_OK == rv )
+   {
+      this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+      this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+      this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+      this->_roleLogged = CKU_USER;
+   }
+   else
+   {
+      // incorrect pin
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_USER);
+
+      // blocked
+      if(triesRemaining == 0)
+      {
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+      }
+      else if(triesRemaining == 1)
+      {
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags |= CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+      }
+      else if(triesRemaining < MAX_USER_PIN_TRIES)
+      {
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags |= CKF_USER_PIN_COUNT_LOW;
+      }
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+BYTE Token::howToAuthenticate( BYTE bPinLen )
+{
+   BYTE bRet = AUTHENTICATE_REGULAR;
+
+   // Get the card mode (1=PIN, 2=FingerPrint, 3=PIN or FP, 4=PIN and FP)
+   // The default mode is PIN
+   //BYTE bCardMode = UVM_PIN_ONLY;
+   //BYTE bTypePIN = PIN_TYPE_REGULAR;
+   //getCardConfiguration( bCardMode, bTypePIN );
+   Log::log( "Token::AuthenticateUser - PIN type <%ld> (0 = regular ; 1 = external)", m_bTypePIN );
+   Log::log( "Token::AuthenticateUser - Card mode <%ld> (1 = pin only ; 2 = fp only ; 3 = fp or pin ; 4 = fp and pin)", m_bCardMode );
+   Log::log( "Token::AuthenticateUser - PIN len <%ld>", bPinLen );
+
+   if( PIN_TYPE_EXTERNAL == m_bTypePIN )
+   {
+      if( UVM_PIN_ONLY == m_bCardMode )
+      {
+         if( true == m_bIsPinPadSupported )
+         {
+            if( 0 == bPinLen )
+            {
+               Log::log( "Token::AuthenticateUser - External PIN && UVM1 && PINpad support && null len -> PIN pad" );
+               bRet = AUTHENTICATE_PINPAD;
+            }
+            else
+            {
+               Log::log( "Token::AuthenticateUser - External PIN && UVM1 && PINpad support && valid len -> PIN normal" );
+               bRet = AUTHENTICATE_REGULAR;
+            }
+         }
+         else
+         {
+            Log::log( "Token::AuthenticateUser - External PIN && UVM1 && NO PINpad support -> ERROR !!!" );
+            bRet = AUTHENTICATE_ERROR;
+         }
+      }
+      else
+      {
+         Log::log( "Token::AuthenticateUser - External PIN && (UVM2 || UVM3 || UVM4) -> Bio" );
+         bRet = AUTHENTICATE_BIO;
+      }
+   }
+   else
+   {
+      if( ( 0 != bPinLen ) && ( ( UVM_PIN_ONLY == m_bCardMode ) || ( UVM_PIN_OR_FP == m_bCardMode ) ) )
+      {
+         Log::log( "Token::AuthenticateUser - Regular PIN && (UVM1 || UVM3)  && valid len -> PIN normal" );
+         bRet = AUTHENTICATE_REGULAR;
+      }
+      else
+      {
+         Log::log( "Token::AuthenticateUser - Regular PIN && (UVM2 || UVM4)  && NO valid len -> ERROR !!!" );
+         bRet = AUTHENTICATE_ERROR;
+      }
+   }
+
+   return bRet;
+}
+
+
+CK_RV Token::AuthenticateAdmin(Marshaller::u1Array *pin)
+{
+   //Log::log("Logging as Admin...");
+
+   CK_RV rv = CKR_OK;
+
+   u1Array* challenge = NULL_PTR;
+   u1Array* response = NULL_PTR;
+
+   try{
+
+      // first check if pin is locked or not
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+      // blocked
+      if(triesRemaining == 0){
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+
+         return CKR_PIN_LOCKED;
+      }
+
+      challenge = this->_mscm->GetChallenge();
+
+      response = this->ComputeCryptogram(challenge,pin);
+
+      this->_mscm->ExternalAuthenticate(response);
+
+      this->_roleLogged = CKU_SO;
+   }
+   catch(Marshaller::RemotingException&){
+      rv = CKR_TOKEN_NOT_PRESENT;
+   }
+   catch(Marshaller::UnauthorizedAccessException&){
+
+      // incorrect pin
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+      // blocked
+      if(triesRemaining == 0){
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+      }else if(triesRemaining == 1){
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+      }else if(triesRemaining < MAX_SO_PIN_TRIES){
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+      }
+
+      return CKR_PIN_INCORRECT;
+
+   }
+   catch(std::runtime_error&)
+   {
+      rv = CKR_DEVICE_ERROR;
+   }
+
+   if(challenge != NULL_PTR)
+      delete challenge;
+
+   if(response != NULL_PTR)
+      delete response;
+
+   return rv;
+}
+
+CK_RV Token::Logout()
+{
+   CK_RV rv = CKR_OK;
+   
+   if(   ( true == m_bIsNoPinSupported ) 
+      || ( ( true == m_bIsSSO ) && ( true == this->isAuthenticated( ) ) )
+      )
+   {
+      this->_roleLogged = CKU_NONE;
+      return rv;
+   }
+
+   TOKEN_TRY
+   {
+      if(this->_roleLogged == CKU_NONE)
+      {
+         throw CkError(CKR_USER_NOT_LOGGED_IN);
+      }
+
+      this->_roleLogged = CKU_NONE;
+
+      u1 role = (this->_roleLogged == CKU_USER) ? CARD_ROLE_USER : CARD_ROLE_ADMIN;
+
+      try
+      {
+         // For the user
+         if( CARD_ROLE_USER == role )
+         {
+            // We log out if the SSO mode is not activated
+            if( false == m_bIsSSO )
+            {
+               this->_mscm->LogOut( role );
+            }
+         }
+         // For the admin
+         else
+         {
+            // We always log out
+            this->_mscm->LogOut( role );
+         }
+
+         //this->_roleLogged = CKU_NONE;
+      }
+      catch(Marshaller::RemotingException&)
+      {
+         rv = CKR_TOKEN_NOT_PRESENT;
+      }
+      catch(std::runtime_error&)
+      {
+         rv = CKR_DEVICE_ERROR;
+      }
+
+   }
+   TOKEN_CATCH(rv)
+
+      return rv;
+}
+
+CK_RV Token::Login(CK_ULONG userType,u1Array* pin)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      if(userType == CKU_USER){
+         if((this->_tokenInfo.flags & CKF_USER_PIN_INITIALIZED) != CKF_USER_PIN_INITIALIZED){
+            throw CkError(CKR_USER_PIN_NOT_INITIALIZED);
+         }
+
+         if(this->_roleLogged == CKU_SO){
+            throw CkError(CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+         }else if(this->_roleLogged == CKU_USER){
+            throw CkError(CKR_USER_ALREADY_LOGGED_IN);
+         }
+
+         rv =  AuthenticateUser(pin);
+
+      }else if(userType == CKU_SO){
+
+         if(this->_roleLogged == CKU_SO){
+            throw CkError(CKR_USER_ALREADY_LOGGED_IN);
+         }else if(this->_roleLogged == CKU_USER){
+            throw CkError(CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+         }
+
+         rv = AuthenticateAdmin(pin);
+      }
+      else
+         rv = CKR_USER_TYPE_INVALID;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+
+/* SerializeTokenInfo
+*/
+void Token::SerializeTokenInfo()
+{
+
+   vector<u1> dataToSerialize;
+
+   // Version
+   Util::PushBBoolInVector(&dataToSerialize, _version);
+
+   // label
+   u1Array* label = new u1Array(32);
+   label->SetBuffer(this->_tokenInfo.label);
+   Util::PushByteArrayInVector(&dataToSerialize,label);
+   delete label;
+
+   // manufacturerId
+   u1Array* manuId = new u1Array(32);
+   manuId->SetBuffer(this->_tokenInfo.manufacturerID);
+   Util::PushByteArrayInVector(&dataToSerialize,manuId);
+   delete manuId;
+
+   // model
+   u1Array* model = new u1Array(16);
+   model->SetBuffer(this->_tokenInfo.model);
+   Util::PushByteArrayInVector(&dataToSerialize,model);
+   delete model;
+
+   // serial Number
+   u1Array* serialNumber = new u1Array(16);
+   serialNumber->SetBuffer(this->_tokenInfo.serialNumber);
+   Util::PushByteArrayInVector(&dataToSerialize,serialNumber);
+   delete serialNumber;
+
+   // rest of the tokenInfo struct (flags)
+   CK_FLAGS flags;
+
+   flags = this->_tokenInfo.flags;
+   flags &= ~CKF_PROTECTED_AUTHENTICATION_PATH;
+
+   Util::PushULongInVector(&dataToSerialize, flags);
+
+   std::string tinfo("p11\\tinfo");
+
+   u1Array objData((s4)dataToSerialize.size());
+
+   for(u4 i=0;i<dataToSerialize.size();i++){
+      objData.SetU1At(i,dataToSerialize.at(i));
+   }
+
+   //ManageGC( );
+
+   try
+   {
+      _cardCache->WriteFile(tinfo,objData);
+      RegisterFileUpdate();
+   }
+   catch( CkError x )
+   {
+      CK_RV rv = x.Error( );
+      Log::log( "## Error ## Token::SerializeTokenInfo - WriteFile failed <%ld>\n", rv );
+      throw;
+   }
+}
+
+void Token::DeserializeTokenInfo()
+{
+   std::string tinfo("p11\\tinfo");
+
+   const u1Array & fileData = this->_cardCache->ReadFile(tinfo);
+
+   vector<u1> from;
+   for(u4 u=0;u<fileData.GetLength();u++){
+      from.push_back(fileData.GetBuffer()[u]);
+   }
+
+   CK_ULONG idx = 0;
+
+   // Format version. Shall be 0 for this version
+   _version = Util::ReadBBoolFromVector(from,&idx);
+
+   // label
+   u1Array* label = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.label,label->GetBuffer(),label->GetLength());
+   delete label;
+
+   // manuid
+   u1Array* manuId = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.manufacturerID,manuId->GetBuffer(),manuId->GetLength());
+   delete manuId;
+
+   // model
+   u1Array* model = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.model,model->GetBuffer(),model->GetLength());
+   delete model;
+
+   // serial number
+   u1Array* serialNum = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.serialNumber,serialNum->GetBuffer(),serialNum->GetLength());
+
+   // Check MSCM's serial number. If this is larger than 8 bytes, do not
+   // use stored value since serial number may already have been truncated
+   // if the card was P11 enabled prior to this fix in revision 548361.
+
+   //Log::log( "Token::DeserializeTokenInfo - get serial numner" );
+   //u1Array* serialNumber = NULL;
+   //serialNumber = _mscm->GetCardProperty( CARD_SERIAL_NUMBER, 0 );
+   ////auto_ptr<u1Array> serialNumber(_mscm->get_SerialNumber());
+
+   //if(m_u1aSerialNumber->GetLength() > 8)
+   if(serialNum->GetLength() > 8)
+   {
+      CMD5 md5;
+      CK_BYTE hash[16];
+      md5.HashCore(serialNum->GetBuffer(), 0, serialNum->GetLength());
+      md5.HashFinal(hash);
+      Util::ConvAscii(hash, 8, _tokenInfo.serialNumber);
+   }
+
+   delete serialNum;
+   
+   //if( NULL != serialNumber )
+   //{
+   //   delete serialNumber;
+   //}
+
+   // flags
+   CK_FLAGS flags;
+
+   flags = this->_tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH;
+
+   this->_tokenInfo.flags = Util::ReadULongFromVector(from,&idx);
+
+   this->_tokenInfo.flags |= flags;
+}
+
+void Token::PopulateDefaultTokenInfo()
+{
+   CK_ULONG idx;
+
+   // initialize the token information
+
+   this->_version = 0;
+
+   for(idx=0;idx<32;idx++){
+      this->_tokenInfo.label[idx] = ' ';
+   }
+
+   this->_tokenInfo.label[0] = 'C';
+   this->_tokenInfo.label[1] = 'F';
+   this->_tokenInfo.label[2] = '.';
+   this->_tokenInfo.label[3] = 'N';
+   this->_tokenInfo.label[4] = 'E';
+   this->_tokenInfo.label[5] = 'T';
+   this->_tokenInfo.label[6] = ' ';
+   this->_tokenInfo.label[7] = 'P';
+   this->_tokenInfo.label[8] = '1';
+   this->_tokenInfo.label[9] = '1';
+
+   this->_tokenInfo.manufacturerID[0] = 'G';
+   this->_tokenInfo.manufacturerID[1] = 'e';
+   this->_tokenInfo.manufacturerID[2] = 'm';
+   this->_tokenInfo.manufacturerID[3] = 'a';
+   this->_tokenInfo.manufacturerID[4] = 'l';
+   this->_tokenInfo.manufacturerID[5] = 't';
+   this->_tokenInfo.manufacturerID[6] = 'o';
+
+   for(idx=7;idx<32;idx++){
+      this->_tokenInfo.manufacturerID[idx] = ' ';
+   }
+
+   this->_tokenInfo.model[0] = '.';
+   this->_tokenInfo.model[1] = 'N';
+   this->_tokenInfo.model[2] = 'E';
+   this->_tokenInfo.model[3] = 'T';
+   this->_tokenInfo.model[4] = ' ';
+   this->_tokenInfo.model[5] = 'C';
+   this->_tokenInfo.model[6] = 'a';
+   this->_tokenInfo.model[7] = 'r';
+   this->_tokenInfo.model[8] = 'd';
+
+   for(idx=9;idx<16;idx++){
+      this->_tokenInfo.model[idx] = ' ';
+   }
+
+   for(idx=0;idx<16;idx++){
+      this->_tokenInfo.serialNumber[idx] = ' ';
+   }
+
+   // If serial number length is too big to fit in 16 (hex) digit field,
+   // then use the 8 first bytes of MD5 hash of the original serial number.
+   Log::log( "Token::PopulateDefaultTokenInfo - get serial numner" );
+   u1Array* u1aSerialNumber = 0;
+   // Try first to load the serial number in a V2+ way
+   try
+   {
+      u1aSerialNumber = _mscm->GetCardProperty( CARD_SERIAL_NUMBER, 0 );
+   }
+   catch( ... )
+   {
+      u1aSerialNumber = 0;
+   }
+   // Try at last to get the serial number in a old V2 way
+   if( 0 == u1aSerialNumber )
+   {
+      u1aSerialNumber = _mscm->get_SerialNumber( );
+   }
+
+   //auto_ptr<u1Array> serialNumber(_mscm->get_SerialNumber());
+   if(u1aSerialNumber->GetLength() > 8)
+   {
+      CMD5 md5;
+      CK_BYTE hash[16];
+      md5.HashCore(u1aSerialNumber->GetBuffer(), 0, u1aSerialNumber->GetLength());
+      md5.HashFinal(hash);
+      Util::ConvAscii(hash, 8, _tokenInfo.serialNumber);
+   }
+   else
+      Util::ConvAscii(u1aSerialNumber->GetBuffer(),u1aSerialNumber->GetLength(),this->_tokenInfo.serialNumber);
+
+   if( NULL != u1aSerialNumber )
+   {
+      delete u1aSerialNumber;
+   }
+}
+
+CK_RV Token::GenerateRandom(CK_BYTE_PTR randomData,CK_ULONG len)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      // usng the challenge as the random data
+      u1Array* random = NULL_PTR;
+
+      random = this->_mscm->GetChallenge();
+
+      // now requested length can be more or less than the
+      // 8 bytes which challenge generates.
+      CK_ULONG minLen = len < 8 ? len : 8;
+      memcpy(randomData,random->GetBuffer(),minLen);
+
+      // lets put soft ramdom as the rest of the bytes
+      unsigned int uSeed;
+
+      memcpy((BYTE *)&uSeed, random->GetBuffer(), sizeof(unsigned int));
+      srand(uSeed);
+
+      if(len > 8)
+      {
+         for(u4 i=8;i<len;i++)
+         {
+            randomData[i] = (BYTE)(rand() % RAND_MAX);
+         }
+      }
+
+      delete random;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_ULONG Token::FindObjects(Session* session,CK_OBJECT_HANDLE_PTR phObject,
+                            CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount)
+{
+   CK_RV rv = CKR_OK;
+   CK_ULONG idx = 0;
+   TOKEN_TRY
+   {
+
+      for(s4 i=0;(i < static_cast<s4>(_objects.size())) && (idx < ulMaxObjectCount);i++){
+
+         if(this->_objects[i] == NULL_PTR){
+            continue;
+         }
+
+         if(session->_tokenObjectsReturnedInSearch[i+1]){
+            continue;
+         }
+
+         if( this->_objects[ i ]->_private == CK_TRUE )
+         {
+            if( false == m_bIsNoPinSupported )
+            {
+               if(   ( CKU_USER != _roleLogged )
+                  && ( ( true == m_bIsSSO ) && ( false == isAuthenticated( ) ) )
+                  )
+               {
+                  continue;
+               }
+            }
+         }
+         //if((this->_objects[i]->_private == CK_TRUE) &&
+         //   (this->_roleLogged != CKU_USER))
+         //{
+         //   continue;
+         //}
+
+         if(session->_searchTempl == NULL_PTR){
+            phObject[idx++] = CO_TOKEN_OBJECT | (i+1);
+            *pulObjectCount = *pulObjectCount + 1;
+            session->_tokenObjectsReturnedInSearch[i+1] = true;
+         }
+         else{
+            CK_BBOOL match = CK_TRUE;
+
+            vector<CK_ATTRIBUTE> attributes = session->_searchTempl->_attributes;
+            for(CK_ULONG a=0;a<attributes.size();a++){
+               if(this->_objects[i]->Compare(attributes.at(a)) == CK_FALSE){
+                  match = CK_FALSE;
+                  break;
+               }
+            }
+
+            if(match == CK_TRUE){
+               phObject[idx++] = CO_TOKEN_OBJECT | (i+1);
+               *pulObjectCount = *pulObjectCount + 1;
+               session->_tokenObjectsReturnedInSearch[i+1] = true;
+            }
+         }
+      }
+   }
+   TOKEN_CATCH(rv)
+      return idx;
+}
+
+
+string Token::FindFreeFileName(StorageObject* object)
+{
+   std::string fileName(object->_private ? "pri" : "pub");
+
+   switch(object->_class){
+        case CKO_DATA:
+           fileName.append("dat");
+           break;
+
+        case CKO_PUBLIC_KEY:
+           fileName.append("puk");
+           break;
+
+        case CKO_PRIVATE_KEY:
+           fileName.append("prk");
+           break;
+
+        case CKO_CERTIFICATE:
+           fileName.append(((X509PubKeyCertObject*)object)->_certName);
+           break;
+
+        case CKO_SECRET_KEY:
+           fileName.append("sec");
+           break;
+
+        default:
+           throw CkError(CKR_FUNCTION_FAILED);
+   }
+
+   if(object->_class != CKO_CERTIFICATE)
+   {
+
+
+      // Find free name
+      map<CK_LONG, bool> occupied;
+
+      if(_initialized)
+      {
+         // get the file names in above dir
+         vector<string> files(_cardCache->FileList("p11"));
+
+         for(u4 i=0;i<files.size();i++)
+         {
+            std::string fn(files[i]);
+            if(fn.find(fileName) == 0)
+            {
+               CK_LONG idx = atoi(fn.substr(fileName.size(), 2).c_str());
+               occupied[idx] = true;
+            }
+         }
+      }
+
+      s4 i = 0;
+      while(occupied.find(i) != occupied.end())
+         i++;
+      fileName.append(Util::MakeIntString(i, 2));
+   }
+
+   return fileName;
+
+}
+
+
+/* WriteObject
+*/
+CK_RV Token::WriteObject( StorageObject* object )
+{
+   //ManageGC( );
+
+   CK_RV rv = CKR_OK;
+
+   std::string fileName( "p11\\" + FindFreeFileName( object ) );
+
+   // This object is stored under p11 directory, assign a unique ID for future identification.
+   object->_uniqueId = Util::MakeUniqueId( );
+
+   vector<u1> to;
+   object->Serialize( &to );
+
+   u1Array objData( (s4)to.size( ) );
+   for( u4 i = 0 ; i < to.size( ) ; i++ )
+   {
+      objData.SetU1At( i, to.at( i ) );
+   }
+
+   u1Array acls( 3 );
+   acls.GetBuffer( )[ 0 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+   acls.GetBuffer( )[ 1 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+
+   if( object->_private )
+   {
+      acls.GetBuffer( )[ 2 ] = 0; // everyone acl
+   }
+   else
+   {
+      // public objects can be written or read by everyone provide the session is correct
+
+      // NOTE: Breaking PKCS#11 Compliance
+      // In the card you can not create public objects unless you are logged in
+      // even for R/W Pulblic session
+
+      acls.GetBuffer( )[ 2 ] = CARD_PERMISSION_READ; // everyone acl
+   }
+
+   if( !_initialized )
+   {
+      Initialize( );
+   }
+
+   _cardCache->ClearFileList( "p11" );
+
+   // No try/catch. It is managed by the calling method.
+   //ManageGC( );
+   this->_mscm->CreateFile( &fileName, &acls, 0 );
+
+   try
+   {
+      //ManageGC( );
+      this->_cardCache->WriteFile( fileName, objData );
+
+      RegisterFileUpdate( );
+      object->_fileName = fileName;
+   }
+   catch( CkError x )
+   {
+      rv = x.Error( );
+      Log::log( "## ERROR ## Token::WriteObject - WriteFile failed <%ld>\n", rv );
+   }
+
+   if( CKR_OK != rv )
+   {
+      try
+      {
+         _mscm->DeleteFile( &fileName );
+      }
+      catch( ... )
+      {
+         Log::log( "## ERROR ## Token::WriteObject - DeleteFile failed\n" );
+      }
+   }
+
+   return rv;
+}
+
+
+CK_RV Token::AddObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject)
+{
+   //ManageGC();
+
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      CK_RV rv = WriteObject(stobj.get());
+      if(rv == CKR_OK)
+      {
+         *phObject = CO_TOKEN_OBJECT | RegisterStorageObject(stobj.get());
+         stobj.release();
+      }
+   }
+   TOKEN_CATCH(rv)
+   //ManageGC( true );
+      return rv;
+}
+
+
+/* AddPrivateKeyObject
+*/
+CK_RV Token::AddPrivateKeyObject( auto_ptr< StorageObject > &stobj, CK_OBJECT_HANDLE_PTR phObject )
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPrivateKeyObject *object = static_cast< RSAPrivateKeyObject* >( stobj.get( ) );
+      if( !object->_private )
+      {
+         throw CkError( CKR_ATTRIBUTE_VALUE_INVALID );
+      }
+
+      // Public key modulus is mandatory, so unless provided by the template,
+      // see if there is a public key with matching CKA_ID. Otherwise return
+      // CKR_TEMPLATE_INCOMPLETE.
+
+      RSAPublicKeyObject* rsaPub = NULL_PTR;
+      if( !object->_modulus )
+      {
+         // Search for corresponding public key to make criteria that is used here is to match the CKA_ID
+         CK_BBOOL foundPub = CK_FALSE;
+         for( s4 i = 0 ; i < static_cast< s4 >( _objects.size( ) ) ; i++ )
+         {
+            if( this->_objects[ i ] != NULL_PTR )
+            {
+               if( this->_objects[ i ]->_class == CKO_PUBLIC_KEY )
+               {
+                  rsaPub = (RSAPublicKeyObject*)this->_objects[ i ];
+                  foundPub = Util::CompareByteArrays( rsaPub->_id->GetBuffer( ), object->_id->GetBuffer( ), rsaPub->_id->GetLength( ) );
+                  if( foundPub == CK_TRUE )
+                  {
+                     break;
+                  }
+               }
+            }
+         }
+
+         if( !foundPub )
+         {
+            throw CkError(CKR_TEMPLATE_INCOMPLETE); // Sorry, now other choice...
+         }
+      }
+
+      u1Array publExp;
+      u4 modLength = 0;
+      if( object->_modulus != NULL_PTR )
+      {
+         publExp = *object->_publicExponent;
+         modLength = object->_modulus->GetLength( );
+         object->_checkValue = Util::MakeCheckValue( object->_modulus->GetBuffer( ), modLength );
+      }
+      else
+      {
+         PKCS11_ASSERT( rsaPub );
+         publExp = *rsaPub->_exponent;
+         modLength = rsaPub->_modulus->GetLength();
+         object->_checkValue = Util::MakeCheckValue(rsaPub->_modulus->GetBuffer(), modLength);
+      }
+      if(publExp.GetLength() < 1 || publExp.GetLength() > 4)
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      if( (modLength*8 < RSA_KEY_MIN_LENGTH) ||
+         (modLength*8 > RSA_KEY_MAX_LENGTH) )
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      if(publExp.GetLength() < 4)
+      {
+         // Pad with zeros in the front since big endian
+         u1Array exp(4);
+         memset(exp.GetBuffer(), 0, exp.GetLength());
+         size_t i = 4 - publExp.GetLength();
+         memcpy(exp.GetBuffer()+i, publExp.GetBuffer(), publExp.GetLength());
+         publExp = exp;
+      }
+
+      // Look for existing matching certificate
+      // First, read the container map record file
+      std::string  nameCMapFile("mscp\\cmapfile");
+      const u1Array & fileData(_cardCache->ReadFile(nameCMapFile));
+
+      object->_keySpec = KEYSPEC_KEYEXCHANGE;   // Default
+
+      // NOTE: If it finds a matching certificate, the keySpec
+      // will be modified to match that of the certificate.
+      CK_BYTE ctrIdx = GetContainerForPrivateKey(fileData, object->_checkValue, &object->_keySpec);
+      if(ctrIdx > 99)
+      {
+         Log::error( "Token::AddPrivateKeyObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+         throw CkError(CKR_DEVICE_MEMORY);
+      }
+      object->_ctrIndex = ctrIdx;
+
+      auto_ptr<u1Array> keyValue;
+
+      if( ( object->_modulus->GetLength( ) / 2 ) != object->_inverseQ->GetLength( ) )
+      {
+         // Pad with zeros in the front since big endian
+         u1Array val( (s4)( object->_modulus->GetLength( ) / 2 ) );
+         memset( val.GetBuffer( ), 0, val.GetLength( ) );
+         size_t i = val.GetLength( )- object->_inverseQ->GetLength( );
+         memcpy( val.GetBuffer( ) + i, object->_inverseQ->GetBuffer(), object->_inverseQ->GetLength( ) );
+         *(object->_inverseQ) = val;
+      }
+
+      // compute the total length;
+      s4 keyLength = object->_p->GetLength() +
+         object->_q->GetLength() +
+         object->_inverseQ->GetLength() +
+         object->_dp->GetLength() +
+         object->_dq->GetLength() +
+         object->_d->GetLength();
+
+      if(object->_modulus != NULL_PTR){
+         keyLength += object->_modulus->GetLength();
+         //keyLength += object->_publicExponent->GetLength();
+         keyLength += 4; // public exponent expected by card is on 4 bytes
+      }else{
+         keyLength += rsaPub->_modulus->GetLength();
+         //keyLength += rsaPub->_exponent->GetLength();
+         keyLength += 4; // public exponent expected by card is on 4 bytes
+      }
+
+      s4 offset = 0;
+
+      // Prepare the keyValue
+      keyValue = auto_ptr<u1Array>(new u1Array(keyLength));
+      memset(keyValue->GetBuffer(),0,keyValue->GetLength()); // let's zeroed it
+
+      memcpy(keyValue->GetBuffer(),object->_p->GetBuffer(),object->_p->GetLength());
+
+      offset += object->_p->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_q->GetBuffer(),object->_q->GetLength());
+
+      offset += object->_q->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_inverseQ->GetBuffer(),object->_inverseQ->GetLength());
+
+      offset += object->_inverseQ->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_dp->GetBuffer(),object->_dp->GetLength());
+
+      offset += object->_dp->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_dq->GetBuffer(),object->_dq->GetLength());
+
+      offset += object->_dq->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_d->GetBuffer(),object->_d->GetLength());
+
+      offset += object->_d->GetLength();
+
+      u4 modulusLen = 0;
+
+      string contName;
+      if(object->_modulus != NULL_PTR){
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],object->_modulus->GetBuffer(),object->_modulus->GetLength());
+
+         offset += object->_modulus->GetLength();
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],publExp.GetBuffer(),publExp.GetLength());
+
+         modulusLen = object->_modulus->GetLength();
+
+         contName = CAttributedCertificate::DerivedUniqueName(object->_modulus->GetBuffer(),
+            object->_modulus->GetLength());
+
+      }else{
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],rsaPub->_modulus->GetBuffer(),rsaPub->_modulus->GetLength());
+
+         offset += rsaPub->_modulus->GetLength();
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],publExp.GetBuffer(),publExp.GetLength());
+
+         modulusLen = rsaPub->_modulus->GetLength();
+
+         contName = CAttributedCertificate::DerivedUniqueName(rsaPub->_modulus->GetBuffer(),
+            rsaPub->_modulus->GetLength());
+
+      }
+
+      //try
+      //{
+      this->_cardCache->ClearContainer(ctrIdx);  // Invalidate cache
+      //this->_mscm->CreateCAPIContainer(ctrIdx,CK_TRUE,object->_keySpec,(modulusLen*8),keyValue.get());
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            //ManageGC( );
+            ntry++;
+            this->_mscm->CreateCAPIContainer(ctrIdx,CK_TRUE,object->_keySpec,(modulusLen*8),keyValue.get());
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::AddPrivateKeyObject", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  Log::error( "Token::AddPrivateKeyObject", "Throw Exception CKR_DEVICE_MEMORY" );
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+      this->RegisterContainerUpdate();
+      /*}
+      catch(...)
+      {
+      Log::error( "Token::AddPrivateKeyObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+
+      throw CkError(CKR_DEVICE_MEMORY);
+      }*/
+
+      object->_ctrIndex = ctrIdx;
+
+      rv = this->AddObject(stobj,phObject);
+      if(rv == CKR_OK)
+      {
+         try
+         {
+            auto_ptr<u1Array> newCMap( UpdateCMap( ctrIdx, fileData, (modulusLen*8), object->_keySpec, CK_TRUE, contName ) );
+            this->_cardCache->WriteFile( nameCMapFile, *newCMap );
+            this->RegisterFileUpdate( );
+         }
+         catch( CkError x )
+         {
+            rv = x.Error( );
+            Log::log( "## Error ## Token::AddPrivateKeyObject - WriteFile <%ld>\n", rv );
+
+            try
+            {
+               DeleteObject( *phObject );
+            }
+            catch( ... )
+            {
+            }
+
+            throw CkError( rv );
+         }
+      }
+   }
+   TOKEN_CATCH( rv )
+   //ManageGC( true );
+
+      return rv;
+}
+
+
+/* DeleteCMapRecord
+*/
+void Token::DeleteCMapRecord( CK_BYTE ctrIndex )
+{
+   // Read the container map record file
+   std::string nameCMapFile( "mscp\\cmapfile" );
+
+   try
+   {
+      u1Array fileData( _cardCache->ReadFile( nameCMapFile ) );
+
+      s4 entries = ( fileData.GetLength( ) / SIZE_CONTAINERMAPRECORD );
+      if( ctrIndex >= entries )
+      {
+         return; // Silently ignore if doesn't exist
+      }
+
+      // Nullify the entries at ctrIndex
+      CMapFileClear( fileData, ctrIndex );
+
+      // Set default container
+      SetDefaultContainer( fileData, 0xFF );
+
+      //ManageGC( );
+
+      // Write the updated content back to cmap
+      this->_cardCache->WriteFile( nameCMapFile, fileData );
+      this->RegisterFileUpdate( );
+   }
+   catch( CkError x )
+   {
+      /*CK_RV rv =*/ x.Error( );
+      Log::error( "Token::DeleteCMapRecord", "WriteFile failed" );
+      throw;
+   }
+   /*
+   catch(Marshaller::RemotingException&){
+   // TBD
+   }
+   catch(Marshaller::UnauthorizedAccessException&){
+   // TBD
+   }
+   catch(std::runtime_error&){
+   // TBD
+   }
+   */
+}
+
+void Token::RemoveKeyFromCMapRecord(CK_BYTE ctrIndex, u1 keySpec)
+{
+
+   try{
+      // read the container map record file
+      std::string nameCMapFile("mscp\\cmapfile");
+      u1Array fileData(_cardCache->ReadFile(nameCMapFile));
+
+      s4 entries = (fileData.GetLength() / SIZE_CONTAINERMAPRECORD);
+      if(ctrIndex >= entries)
+      {
+         PKCS11_ASSERT(0);
+         return; // Silently ignore if doesn't exist
+      }
+
+      // Clear the key size corresponding to keyspec
+      if(keySpec == KEYSPEC_KEYEXCHANGE)
+         CMapFileSetExchSize(fileData, ctrIndex, 0);
+      else if(keySpec == KEYSPEC_SIGNATURE)
+         CMapFileSetSignSize(fileData, ctrIndex, 0);
+      else
+         return;  // unknown key spec
+
+      //ManageGC();
+
+      // now write the updated content back to cmap
+      this->_cardCache->WriteFile(nameCMapFile,fileData);
+      this->RegisterFileUpdate();
+
+   }
+   catch( CkError x )
+   {
+      /*CK_RV rv =*/ x.Error( );
+      Log::error( "Token::RemoveKeyFromCMapRecord", "WriteFile failed" );
+   }
+   /*
+   catch(Marshaller::RemotingException&){
+   // TBD
+   }
+   catch(Marshaller::UnauthorizedAccessException&){
+   // TBD
+   }
+   catch(std::runtime_error&){
+   // TBD
+   }
+   */
+}
+
+void Token::SetDefaultContainer(u1Array & contents, CK_BYTE ctrIndex)
+{
+
+   s4 entries = (contents.GetLength() / SIZE_CONTAINERMAPRECORD);
+
+   if(ctrIndex == 0xFF)
+   {
+      for (s4 i=0;i<entries;i++)
+      {
+         if((CMapFileGetFlag(contents, i) & 0x03) == 0x03)
+            return;  // A valid container already default, finished
+      }
+
+      // Find first best suitable. Look for one with keys
+      for (s4 i=0;i<entries;i++)
+      {
+         u1 flags = CMapFileGetFlag(contents, i);
+         if((flags & 0x01) && (CMapFileGetExchSize(contents, i) || CMapFileGetSignSize(contents, i)))
+         {
+            CMapFileSetFlag(contents, i, (flags | 0x02));
+            return;
+         }
+      }
+
+      // If no container with keys, then assign any valid container as default
+      for (s4 i=0;i<entries;i++)
+      {
+         u1 flags = CMapFileGetFlag(contents, i);
+         if(flags & 0x01)
+         {
+            CMapFileSetFlag(contents, i, (flags | 0x02));
+            return;
+         }
+      }
+   }
+   else
+   {
+      // Assign specific container as default
+      PKCS11_ASSERT(ctrIndex < entries);
+      if(ctrIndex >= entries)
+         return;
+      // Remove existing default container
+      for (s4 i=0;i<entries;i++)
+      {
+         u1 flags = CMapFileGetFlag(contents, i);
+         CMapFileSetFlag(contents, i, (flags & ~0x02));
+      }
+      CMapFileSetFlag(contents, ctrIndex, CMapFileGetFlag(contents, ctrIndex) | 0x02);
+   }
+}
+
+CK_RV Token::AddCertificateObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      X509PubKeyCertObject * object = static_cast<X509PubKeyCertObject*>(stobj.get());
+
+      if(object->_private)
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      //CheckAvailableSpace();
+
+      // Make check value and look for possibly existing private key(s)
+
+      BEROctet::Blob modulus;
+      try
+      {
+         X509Cert x509cert(object->_value->GetBuffer(), object->_value->GetLength());
+         modulus =x509cert.Modulus();
+      }
+      catch(...)
+      {
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+      }
+
+      object->_checkValue   = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+      string contName(CAttributedCertificate::DerivedUniqueName(modulus));
+
+      std::string nameCMapFile("mscp\\cmapfile");
+      const u1Array & fileData(_cardCache->ReadFile(nameCMapFile));
+
+      object->_keySpec = KEYSPEC_KEYEXCHANGE;   // Default
+
+      // NOTE: If it finds a matching private key, the keySpec
+      // will be modified to match that of the private key.
+      CK_BYTE ctrIdx = GetContainerForCert(fileData, object->_checkValue, &object->_keySpec);
+      if(ctrIdx > 99)
+      {
+         Log::error( "Token::AddCertificateObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+
+         throw CkError(CKR_DEVICE_MEMORY);
+      }
+      object->_ctrIndex = ctrIdx;
+
+      if(object->_keySpec == KEYSPEC_KEYEXCHANGE)
+         object->_certName = "kxc";
+      else
+         object->_certName = "ksc";
+      object->_certName.append(Util::MakeIntString(ctrIdx, 2));
+
+      string fileName("mscp\\");
+      fileName.append(object->_certName);
+
+      unsigned long ccLen = object->_value->GetLength();
+      autoarray<u1> cc(new u1[ccLen+4]);
+
+      cc[0] = 0x01;
+      cc[1] = 0x00;
+      cc[2] = BITS_0_7(ccLen);
+      cc[3] = BITS_8_15(ccLen);
+
+      // compress the certificate
+      //         compress((u1*)&cc[4],&ccLen,object->_value->GetBuffer(),ccLen);
+      compress2((u1*)&cc[4],&ccLen,object->_value->GetBuffer(),ccLen, 6); // Set level=6, same as Minidriver
+
+      auto_ptr<u1Array> compressedCert(new u1Array((ccLen + 4)));
+      compressedCert->SetBuffer(cc.get());
+
+      auto_ptr<u1Array> acls(new u1Array(3));
+      acls->GetBuffer()[0] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+      acls->GetBuffer()[1] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+      acls->GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+      //ManageGC();
+
+      _cardCache->ClearFileList("mscp");
+      this->_mscm->CreateFile(&fileName,acls.get(),0);
+      try
+      {
+         this->_cardCache->WriteFile(fileName,*compressedCert);
+         this->RegisterFileUpdate();
+      }
+      catch( CkError x )
+      {
+         rv = x.Error( );
+         Log::error( "Token::AddCertificateObject", "WriteFile failed" );
+      }
+
+      if( CKR_OK != rv )
+      {
+         try
+         {
+            _mscm->DeleteFile( &fileName );
+         }
+         catch( ... )
+         {
+         }
+
+         throw CkError( rv );
+      }
+
+      rv = AddObject(stobj ,phObject);
+      if(rv == CKR_OK)
+      {
+         //ManageGC();
+
+         try
+         {
+            auto_ptr<u1Array> newCMap(UpdateCMap(ctrIdx,fileData, contName));
+            _cardCache->WriteFile(nameCMapFile,*newCMap);
+            RegisterFileUpdate();
+         }
+         catch( CkError x )
+         {
+            rv = x.Error( );
+            Log::error( "Token::AddCertificateObject", "WriteFile 2 failed" );
+         }
+
+         if( CKR_OK != rv )
+         {
+            try
+            {
+               _mscm->DeleteFile( &fileName );
+            }
+            catch( ... )
+            {
+            }
+
+            try
+            {
+               DeleteObject( *phObject );
+            }
+            catch( ... )
+            {
+            }
+
+            throw CkError( rv );
+         }
+      }
+   }
+   TOKEN_CATCH(rv)
+   
+      //ManageGC( true );
+      return rv;
+}
+
+CK_RV Token::DeleteObject( CK_OBJECT_HANDLE hObject )
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      StorageObject * obj = GetObject(hObject);
+
+      // some more checks
+      if( CK_TRUE == obj->_private )
+      {
+         if( false == m_bIsNoPinSupported )
+         {
+            if(   ( CKU_USER != _roleLogged )
+               && ( ( true == m_bIsSSO ) && ( false == isAuthenticated( ) ) )
+               )
+            {
+               throw CkError(CKR_USER_NOT_LOGGED_IN);
+            }
+         }
+      }
+      //if((this->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+      //   throw CkError(CKR_USER_NOT_LOGGED_IN);
+      //}
+
+      if(obj->_class == CKO_CERTIFICATE){
+
+         //Log::log("Deleting the certificate.");
+
+         CertificateObject * cert = static_cast<CertificateObject*>(obj);
+         CK_BYTE ctrIdx = cert->_ctrIndex;
+
+         if(ctrIdx != 0xFF){
+
+            // Delete the file under mscp
+
+            string fileName("mscp\\");
+            fileName.append(cert->_certName);
+            _cardCache->ClearFile(fileName);
+            try
+            {
+               _cardCache->ClearFileList("mscp");
+               _mscm->DeleteFile(&fileName);
+               RegisterFileUpdate();
+            }
+            catch(FileNotFoundException &) {}
+
+            // Check if there exist private key(s) or other
+            // certificate (with different key spec) in the container
+            u1 otherKeySpec = (cert->_keySpec == KEYSPEC_KEYEXCHANGE) ? KEYSPEC_SIGNATURE : KEYSPEC_KEYEXCHANGE;
+
+            bool fOtherCertExist = (FindCertificate(_objects, ctrIdx, otherKeySpec) != 0);
+
+            bool fPrivKeysExist = false;
+            if(FindPrivateKey(_objects, ctrIdx, KEYSPEC_KEYEXCHANGE) || FindPrivateKey(_objects, ctrIdx, KEYSPEC_SIGNATURE))
+               fPrivKeysExist = true;
+
+            // If there are no longer any objects associated with this
+            // container, then free this CMap record
+            if(!fOtherCertExist && !fPrivKeysExist)
+            {
+               //Log::log("Deleting container ",ctrIdx);
+               DeleteCMapRecord(ctrIdx);
+            }
+         }
+      }
+      if(obj->_class == CKO_PRIVATE_KEY){
+
+         //Log::log("Deleting the private key.");
+
+         RSAPrivateKeyObject * privKey = static_cast<RSAPrivateKeyObject*>(obj);
+         CK_BYTE ctrIdx = privKey->_ctrIndex;
+
+         if(ctrIdx != 0xFF){
+
+
+            // Check if there exist certificate(s) or other
+            // private key (with different key spec) in the container
+            u1 otherKeySpec = (privKey->_keySpec == KEYSPEC_KEYEXCHANGE) ? KEYSPEC_SIGNATURE : KEYSPEC_KEYEXCHANGE;
+
+            bool fOtherKeyExist = (FindPrivateKey(_objects, ctrIdx, otherKeySpec) != 0);
+
+            bool fCertsExist = false;
+            if(FindCertificate(_objects, ctrIdx, KEYSPEC_KEYEXCHANGE) || FindCertificate(_objects, ctrIdx, KEYSPEC_SIGNATURE))
+               fCertsExist = true;
+
+            if(fOtherKeyExist)
+            {
+               // To not delete the other key, overwrite this one with dummy data
+               // TODO
+               // this->_mscm->CreateCAPIContainer(ctrIdx,.....);
+               RegisterContainerUpdate();
+            }
+            else
+            {
+               _cardCache->ClearContainer(ctrIdx);   // Invalidate cache
+               _mscm->DeleteCAPIContainer(ctrIdx);
+               RegisterContainerUpdate();
+            }
+
+            // Check if the record in cmapfile shall be cleared,
+            // depending on if there are other keys in it.
+            // empty the corresponding record in cmapfile
+
+            if(fOtherKeyExist || fCertsExist)
+            {
+               //Log::log("Removing key from container ",ctrIdx);
+               RemoveKeyFromCMapRecord(ctrIdx, privKey->_keySpec);
+            }
+            else
+            {
+               //Log::log("Deleting container ",ctrIdx);
+               DeleteCMapRecord(ctrIdx);
+            }
+         }
+      }
+
+      // delete the file from card
+      if(!obj->_fileName.empty())
+      {
+         _cardCache->ClearFile(obj->_fileName);
+         try
+         {
+            _cardCache->ClearFileList("p11");
+            this->_mscm->DeleteFile(&obj->_fileName);
+            this->RegisterFileUpdate();
+         }
+         catch(FileNotFoundException &) {}
+      }
+
+      UnregisterStorageObject(obj);
+      delete obj;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::GetAttributeValue(CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount)
+{
+   CK_RV rv  = CKR_OK;
+   CK_RV arv = CKR_OK;
+   TOKEN_TRY
+   {
+
+      //Log::log("Get Attributes of token object..");
+
+      StorageObject * obj = GetObject(hObject);
+
+      if( CK_TRUE == obj->_private )
+      {
+         if( false == m_bIsNoPinSupported )
+         {
+            if(   ( CKU_USER != _roleLogged )
+               && ( ( true == m_bIsSSO ) && ( false == isAuthenticated( ) ) )
+               )
+            {
+               for(u4 i=0;i<ulCount;i++)
+               {
+                  pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+               }
+               throw CkError(CKR_USER_NOT_LOGGED_IN);
+            }
+         }
+      }
+      //if((this->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE))
+      //{
+      //   for(u4 i=0;i<ulCount;i++){
+      //      pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+      //   }
+      //   throw CkError(CKR_USER_NOT_LOGGED_IN);
+      //}
+
+      for(u4 i=0;i<ulCount;i++){
+         rv = obj->GetAttribute(&pTemplate[i]);
+         if(rv != CKR_OK){
+            arv = rv;
+         }
+      }
+   }
+   TOKEN_CATCH(arv)
+      return arv;
+}
+
+
+CK_RV Token::SetAttributeValue( CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+{
+   CK_RV rv = CKR_OK;
+   CK_RV arv = CKR_OK;
+   TOKEN_TRY
+   {
+      StorageObject* pObj = GetObject( hObject );
+      // ??? pObj == NULL_PTR
+
+      // Check if we have a proper session
+      if( CK_TRUE == pObj->_private )
+      {
+         if( false == m_bIsNoPinSupported )
+         {
+            if(   ( CKU_USER != _roleLogged )
+               && ( ( true == m_bIsSSO ) && ( false == isAuthenticated( ) ) )
+               )
+            {
+               throw CkError(CKR_USER_NOT_LOGGED_IN);
+            }
+         }
+      }
+      // if( ( this->_roleLogged != CKU_USER ) && ( pObj->_private == CK_TRUE ) )
+      //{
+      //   throw CkError( CKR_USER_NOT_LOGGED_IN );
+      //}
+
+      if( pObj->_modifiable == CK_FALSE )
+      {
+         throw CkError(CKR_ATTRIBUTE_READ_ONLY);
+      }
+
+      for( u4 i = 0 ; i < ulCount ; i++ )
+      {
+         rv = pObj->SetAttribute( pTemplate[ i ], CK_FALSE );
+         if( rv != CKR_OK )
+         {
+            arv = rv;
+         }
+      }
+
+      if( arv == CKR_OK )
+      {
+         // If the object is not yet represented by a file under
+         // "p11" directory, this file must be created first.
+
+         bool fCreate = false;
+
+         // The object is represented by a P11 file if and only if
+         // the _uniqueId has been assigned a value.
+         if( pObj->_uniqueId == 0 )
+         {
+            fCreate = true;
+            if(!_initialized)
+               Initialize();
+
+            u1Array acls(3);
+            acls.GetBuffer( )[ 0 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+            acls.GetBuffer( )[ 1 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+
+            if(pObj->_private)
+               acls.GetBuffer()[2] = 0; // everyone acl
+            else
+               acls.GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+            string fileName("p11\\" + FindFreeFileName(pObj));
+            _cardCache->ClearFileList("p11");
+            _mscm->CreateFile(&fileName,&acls,0);
+            RegisterFileUpdate();
+            pObj->_fileName = fileName;
+            pObj->_uniqueId = Util::MakeUniqueId();
+         }
+
+         // marshall this object back to the card
+         vector<u1> to;
+         pObj->Serialize(&to);
+
+         u1Array objData((s4)to.size());
+
+         for(u4 i=0;i<to.size();i++){
+            objData.SetU1At(i,to.at(i));
+         }
+
+         //ManageGC();
+
+         try
+         {
+            this->_cardCache->WriteFile(pObj->_fileName,objData);
+            this->RegisterFileUpdate();
+         }
+         catch( CkError x )
+         {
+            arv = x.Error( );
+            Log::error( "Token::SetAttributeValue", "WriteFile failed" );
+         }
+
+         if( CKR_OK != arv )
+         {
+            if(fCreate)   // Restore state of object prior to update attempt.
+            {
+               pObj->_fileName.clear();
+               pObj->_uniqueId = 0;
+            }
+         }
+      }
+   }
+   TOKEN_CATCH(arv)
+      return arv;
+}
+
+
+CK_BYTE Token::GetAvailableContainerIndex(u1Array const & cmapContents)
+{
+   u4  contentLen = cmapContents.GetLength();
+
+   // cmap file does not contain anything
+   // so index is 0
+   if(contentLen == 0){
+      return 0;
+   }
+
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   for(s4 i=0;i<entries;i++){
+      // lets find out which entry has all zeros
+      // which denotes available index
+
+      // as per minidriver specification
+      // if bit 0 of flags should be set for it to be
+      // a valid entry
+      if((CMapFileGetFlag(cmapContents, i) & 0x01) != 0x01){
+         return i;
+      }
+   }
+
+   // reaching here means that cmap file has entries
+   // which are all occupied, in that the available
+   // index would be entries
+   return entries;
+}
+
+CK_BYTE Token::GetContainerForCert(u1Array const & cmapContents, u8 checkValue, u1 * keySpec)
+{
+   // Look for existing matching private key
+   vector <PrivateKeyObject*> vPriv(FindPrivateKeys(_objects, checkValue));
+   for(size_t ipriv = 0; ipriv < vPriv.size(); ++ipriv)
+   {
+      // See it the corresponding container/keyspec is already occupied by a certificate.
+      // If it isn't, this is free for use.
+      if(!FindCertificate(_objects, vPriv[ipriv]->_ctrIndex, vPriv[ipriv]->_keySpec))
+      {
+         *keySpec = vPriv[ipriv]->_keySpec;
+         return vPriv[ipriv]->_ctrIndex;
+      }
+   }
+   // No matching private key, find new container
+
+   return GetAvailableContainerIndex(cmapContents);
+}
+
+CK_BYTE Token::GetContainerForPrivateKey(u1Array const & cmapContents, u8 checkValue, u1 * keySpec)
+{
+   // Look for existing matching certificate
+   vector <CertificateObject*> vCert(FindCertificates(_objects, checkValue));
+   for(size_t icert = 0; icert < vCert.size(); ++icert)
+   {
+      // See it the corresponding container/keyspec is already occupied by a key.
+      // If it isn't, this is free for use.
+      if(!FindPrivateKey(_objects, vCert[icert]->_ctrIndex, vCert[icert]->_keySpec))
+      {
+         *keySpec = vCert[icert]->_keySpec;
+         return vCert[icert]->_ctrIndex;
+      }
+   }
+   // No matching certificate, find new container
+
+   return GetAvailableContainerIndex(cmapContents);
+}
+
+auto_ptr<u1Array> Token::UpdateCMap(CK_BYTE ctrIdx, u1Array const & contents, string const & contName )
+{
+   u4  contentLen = contents.GetLength();
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   u4 newCMapSize = SIZE_CONTAINERMAPRECORD * entries;
+
+   if(ctrIdx >= entries){
+      entries = ctrIdx + 1;
+      newCMapSize = entries * SIZE_CONTAINERMAPRECORD;
+   }
+
+   //autoarray<u1> updatedContents(new u1[newCMapSize]);
+
+   auto_ptr<u1Array> updatedContents(new u1Array(newCMapSize));
+
+   memset(updatedContents->GetBuffer(), 0, newCMapSize);
+   memcpy(updatedContents->GetBuffer(), contents.GetBuffer(), contentLen);
+
+   u1 flags = CMapFileGetFlag(*updatedContents, ctrIdx);
+   if(!(flags & 0x01))
+   {
+      // Container record is new, set container Name (UNICODE string)
+      CMapFileSetName(*updatedContents, ctrIdx, contName);
+      CMapFileSetFlag(*updatedContents, ctrIdx, flags | 0x01);
+   }
+
+   SetDefaultContainer(*updatedContents, 0xFF);
+
+   return updatedContents;
+}
+
+auto_ptr<u1Array> Token::UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,u4 keySize,u1 keySpec,CK_BBOOL isDefault, string const & contName)
+{
+   u4  contentLen = contents.GetLength();
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   u4 newCMapSize = SIZE_CONTAINERMAPRECORD * entries;
+
+   if(ctrIdx >= entries){
+      entries = ctrIdx + 1;
+      newCMapSize = entries * SIZE_CONTAINERMAPRECORD;
+   }
+
+   auto_ptr<u1Array> updatedContents(new u1Array(newCMapSize));
+
+   memset(updatedContents->GetBuffer(), 0, newCMapSize);
+   memcpy(updatedContents->GetBuffer(), contents.GetBuffer(), contentLen);
+
+   u1 flags = CMapFileGetFlag(*updatedContents, ctrIdx);
+   if(!(flags & 0x01))
+   {
+      // Container record is new, set container Name (UNICODE string)
+      CMapFileSetName(*updatedContents, ctrIdx, contName);
+      CMapFileSetFlag(*updatedContents, ctrIdx, flags | 0x01);
+   }
+
+   // Default container
+   SetDefaultContainer(*updatedContents, isDefault ? ctrIdx : 0xFF);
+
+   // Container Key Size
+   if (keySpec == KEYSPEC_SIGNATURE){
+      CMapFileSetSignSize(*updatedContents, ctrIdx, keySize);
+   }else{
+      CMapFileSetExchSize(*updatedContents, ctrIdx, keySize);
+   }
+
+   return updatedContents;
+}
+
+vector <PrivateKeyObject*> Token::FindPrivateKeys(vector<StorageObject*> const & objects, u8 checkValue)
+{
+   // checkValue is derived from the modulus and is sufficiently
+   // long (8 bytes) to be a unique handle to the key pair / certificate
+   vector <PrivateKeyObject*> vPriv;
+
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++){
+      if(objects[i] && objects[i]->_class == CKO_PRIVATE_KEY){
+         PrivateKeyObject * privObject = (PrivateKeyObject*)objects[i];
+         if(privObject->_checkValue == checkValue)
+            vPriv.push_back(privObject);
+      }
+   }
+   return vPriv;
+}
+
+PrivateKeyObject * Token::FindPrivateKey(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec)
+{
+   vector <PrivateKeyObject*> vPriv;
+
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+   {
+      if(objects[i] && objects[i]->_class == CKO_PRIVATE_KEY)
+      {
+         PrivateKeyObject * privObject = (PrivateKeyObject*)objects[i];
+         if(privObject->_ctrIndex == ctrdIdx && privObject->_keySpec == keySpec)
+            return privObject;  // Is supposed to be only one.
+      }
+   }
+   return 0;
+}
+
+vector <CertificateObject*> Token::FindCertificates(vector<StorageObject*> const & objects, u8 checkValue)
+{
+   // checkValue is derived from the modulus and is sufficiently
+   // long (8 bytes) to be a unique handle to the key pair / certificate
+   vector <CertificateObject*> vCert;
+
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+   {
+      if(objects[i] && objects[i]->_class == CKO_CERTIFICATE)
+      {
+         CertificateObject * certObject = (CertificateObject*)objects[i];
+         if(certObject->_checkValue == checkValue)
+            vCert.push_back(certObject);
+      }
+   }
+   return vCert;
+}
+
+CertificateObject * Token::FindCertificate(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec)
+{
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+   {
+      if(objects[i] && objects[i]->_class == CKO_CERTIFICATE)
+      {
+         CertificateObject * certObject = (CertificateObject*)objects[i];
+         if(certObject->_ctrIndex == ctrdIdx && certObject->_keySpec == keySpec)
+            return certObject;
+      }
+   }
+   return 0;
+}
+
+CK_RV Token::GenerateKeyPair(auto_ptr<StorageObject> & stobjRsaPub, auto_ptr<StorageObject> & stobjRsaPriv,
+                             CK_OBJECT_HANDLE_PTR phPubKey,CK_OBJECT_HANDLE_PTR phPrivKey)
+{
+
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPublicKeyObject * rsaPubObject = static_cast<RSAPublicKeyObject*>(stobjRsaPub.get());
+      RSAPrivateKeyObject * rsaPrivObject = static_cast<RSAPrivateKeyObject*>(stobjRsaPriv.get());
+
+      if( (rsaPubObject->_modulusLen < RSA_KEY_MIN_LENGTH) ||
+         (rsaPubObject->_modulusLen > RSA_KEY_MAX_LENGTH) )
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      //CheckAvailableSpace(); // HACK !!
+
+      //Log::log("Generating KeyPair on the smartcard...");
+
+      std::string nameCMapFile;
+
+      // TBD (Start a pc/sc transaction here)
+
+      // let's first read the container record file to
+      // see which container is available.
+      // No need to search for matching certificate,
+      // since this can not exist one yet!! ;)
+      nameCMapFile = "mscp\\cmapfile";
+      const u1Array & fileData = this->_cardCache->ReadFile(nameCMapFile);
+
+      CK_BYTE ctrIdx = this->GetAvailableContainerIndex(fileData);
+      if(ctrIdx == 0xFF)
+         throw CkError(CKR_DEVICE_MEMORY);
+
+      // create a capi container.
+      // KEYSPEC_KEYEXCHANGE by default.
+      this->_cardCache->ClearContainer(ctrIdx);   // Invalidate cache
+      //this->_mscm->CreateCAPIContainer(ctrIdx,CK_FALSE,KEYSPEC_KEYEXCHANGE,rsaPubObject->_modulusLen,NULL_PTR);
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ntry++;
+            this->_mscm->CreateCAPIContainer(ctrIdx,CK_FALSE,KEYSPEC_KEYEXCHANGE,rsaPubObject->_modulusLen,NULL_PTR);
+            //ManageGC( );
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::GenerateKeyPair", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  Log::error( "Token::GenerateKeyPair", "Throw Exception CKR_DEVICE_MEMORY" );
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+      this->RegisterContainerUpdate();
+
+      rsaPubObject->_ctrIndex = ctrIdx;
+      rsaPubObject->_keySpec = KEYSPEC_KEYEXCHANGE;
+
+      rsaPrivObject->_ctrIndex = ctrIdx;
+      rsaPrivObject->_keySpec = KEYSPEC_KEYEXCHANGE;
+
+      // populate these objects with the key material
+      const CardCache::Container & cont = _cardCache->ReadContainer(ctrIdx);
+
+      rsaPubObject->_exponent = new u1Array();
+      *rsaPubObject->_exponent = cont.exchPublicExponent;
+      rsaPubObject->_modulus = new u1Array();
+      *rsaPubObject->_modulus = cont.exchModulus;
+      rsaPubObject->_local = CK_TRUE;
+
+
+      // Copy these modulus and exponent in the private key component also
+      rsaPrivObject->_publicExponent = new u1Array();
+      *rsaPrivObject->_publicExponent = cont.exchPublicExponent;
+
+      rsaPrivObject->_modulus = new u1Array();
+      *rsaPrivObject->_modulus = cont.exchModulus;
+      rsaPrivObject->_checkValue = Util::MakeCheckValue(cont.exchModulus.GetBuffer(),
+         cont.exchModulus.GetLength());
+      rsaPrivObject->_local = CK_TRUE;
+
+      string contName(CAttributedCertificate::DerivedUniqueName(cont.exchModulus.GetBuffer(),
+         cont.exchModulus.GetLength()));
+
+      // now its time to add the corresponding objects to
+      // the card (as files)
+
+      // The public key may be a session object, in that case, don't save it.
+
+      if( rsaPubObject->_tokenObject )
+      {
+         rv = this->AddObject( stobjRsaPub, phPubKey );
+      }
+
+      if( CKR_OK == rv )
+      {
+         rv = this->AddObject( stobjRsaPriv, phPrivKey );
+
+         if( CKR_OK == rv )
+         {
+            try
+            {
+               auto_ptr<u1Array> newCMap( UpdateCMap( ctrIdx, fileData, rsaPubObject->_modulusLen, KEYSPEC_KEYEXCHANGE, CK_TRUE, contName ) );
+               _cardCache->WriteFile( nameCMapFile, *newCMap );
+               RegisterFileUpdate( );
+            }
+            catch( CkError x )
+            {
+               rv = x.Error( );
+               Log::error( "Token::SetAttributeValue", "WriteFile failed" );
+            }
+
+            if( CKR_OK != rv )
+            {
+               if( rsaPubObject->_tokenObject )
+               {
+                  DeleteObject( *phPubKey );
+                  // ???
+               }
+               DeleteObject( *phPrivKey );
+
+               throw CkError( rv );
+            }
+         }
+         else if( rsaPubObject->_tokenObject )
+         {
+            DeleteObject( *phPubKey );
+         }
+      }
+   }
+   TOKEN_CATCH(rv)
+   //printf( "\nToken::GenerateKeyPair - ManageGC( true )\n" );
+      ManageGC( true );
+      return rv;
+}
+
+
+CK_RV Token::GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      *object = GetObject(hObject);
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::Encrypt(StorageObject* pubObj,u1Array* dataToEncrypt,CK_ULONG mechanism,CK_BYTE_PTR pEncryptedData)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPublicKeyObject* object = (RSAPublicKeyObject*)pubObj;
+
+      if(mechanism == CKM_RSA_PKCS){
+         // first do the length checks
+         if(dataToEncrypt->GetLength() > (object->_modulus->GetLength() - 11)){
+            throw CkError(CKR_DATA_LEN_RANGE);
+         }
+
+         rsaPublicKey_t key;
+
+         key.modulus = object->_modulus->GetBuffer() ;
+         key.modulusLength = object->_modulus->GetLength() * 8 ;
+         key.publicExponent = object->_exponent->GetBuffer();
+         key.publicExponentLength =  object->_exponent->GetLength() * 8;
+
+         u4 outLength = object->_modulus->GetLength();
+
+         DWORD rv ;
+         DWORD size ;
+         DWORD pubSize ;
+         R_RSA_PUBLIC_KEY	rsaKeyPublic ;
+
+         rsaKeyPublic.bits = key.modulusLength ;
+
+         size = (key.modulusLength + 7) / 8 ;
+         memcpy(rsaKeyPublic.modulus, key.modulus, size) ;
+
+         pubSize = (key.publicExponentLength + 7) / 8 ;
+         memset(rsaKeyPublic.exponent, 0, size) ;
+         memcpy(&rsaKeyPublic.exponent[size - pubSize], key.publicExponent, pubSize) ;
+
+         R_RANDOM_STRUCT & randomStruct = Util::RandomStruct();
+
+         rv = RSAPublicEncrypt(
+            pEncryptedData,
+            &outLength,
+            dataToEncrypt->GetBuffer(),
+            dataToEncrypt->GetLength(),
+            &rsaKeyPublic,
+            &randomStruct);
+
+      }else{
+
+         u4 modulusLen = object->_modulus->GetLength();
+
+         if(dataToEncrypt->GetLength() > (modulusLen)){
+            throw CkError(CKR_DATA_LEN_RANGE);
+         }
+
+         // pre-pad with zeros
+         u1Array* messageToEncrypt = new u1Array(modulusLen);
+         memset(messageToEncrypt->GetBuffer(),0,modulusLen);
+
+         s4 offsetMsgToEncrypt = modulusLen - dataToEncrypt->GetLength();
+
+         for(u4 i=0,j=offsetMsgToEncrypt;i<dataToEncrypt->GetLength();i++,j++){
+            messageToEncrypt->GetBuffer()[j] = dataToEncrypt->GetBuffer()[i];
+         }
+
+         // just block transform now
+         s4 size ;
+         s4 pubSize ;
+         R_RSA_PUBLIC_KEY	rsaKeyPublic ;
+
+         //Build the RSA public key context
+         rsaKeyPublic.bits = object->_modulus->GetLength() * 8;
+
+         size = (rsaKeyPublic.bits  + 7) / 8 ;
+         memcpy(rsaKeyPublic.modulus,object->_modulus->GetBuffer(),size) ;
+
+         pubSize = ((object->_exponent->GetLength() * 8) + 7) / 8 ;
+         memset(rsaKeyPublic.exponent, 0, size) ;
+         memcpy(&rsaKeyPublic.exponent[size - pubSize], object->_exponent->GetBuffer(), pubSize) ;
+
+         u4 outputLen = size;
+
+         rv = RSAPublicBlock(pEncryptedData,&outputLen,messageToEncrypt->GetBuffer(),size,&rsaKeyPublic);
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::Decrypt(StorageObject* privObj,u1Array* dataToDecrypt,CK_ULONG mechanism,CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      u1Array* data = NULL_PTR;
+
+      RSAPrivateKeyObject * rsaKey = static_cast<RSAPrivateKeyObject*>(privObj);
+
+      //data = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, dataToDecrypt);
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ntry++;
+            data = this->_mscm->PrivateKeyDecrypt( rsaKey->_ctrIndex, rsaKey->_keySpec, dataToDecrypt );
+            //ManageGC( );
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::Decrypt", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+
+
+
+
+      if(mechanism == CKM_RSA_PKCS){
+
+         u1* decryptedMessage = (u1*)data->GetBuffer();
+
+#define PKCS_EMEV15_PADDING_TAG   0x2
+
+         if ((decryptedMessage[0] != 0x00) || (decryptedMessage[1] != PKCS_EMEV15_PADDING_TAG))
+         {
+            // TBD: Lookup correct error message
+            // invalid message padding
+            rv = CKR_ENCRYPTED_DATA_INVALID;
+         }else{
+
+            // seach message padding separator
+            u4 mPos = 2 + 8;
+            while ((decryptedMessage[mPos] != 0x00) && (mPos < data->GetLength()))
+            {
+               mPos++;
+            }
+
+            // point on message itself.
+            mPos++;
+            u1Array* finalDecryptedMessage = new u1Array(data->GetLength() - mPos);
+            memcpy(finalDecryptedMessage->GetBuffer(),(u1*)&decryptedMessage[mPos],finalDecryptedMessage->GetLength());
+
+            delete data;
+
+            data = finalDecryptedMessage;
+         }
+      }
+      // else... CKM_RSA_X_509: Ignore padding
+
+      if(data){
+         if(*pulDataLen >= data->GetLength())
+            memcpy(pData,data->GetBuffer(),data->GetLength());
+         else
+            rv = CKR_BUFFER_TOO_SMALL;
+         *pulDataLen = data->GetLength();
+         delete data;
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::Verify(StorageObject* pubObj,u1Array* dataToVerify,CK_ULONG mechanism,u1Array* signature)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPublicKeyObject* object = (RSAPublicKeyObject*)pubObj;
+
+      if(((mechanism == CKM_RSA_PKCS) && (dataToVerify->GetLength() > (object->_modulus->GetLength() - 11))) ||
+         ((mechanism == CKM_RSA_X_509) && (dataToVerify->GetLength() > object->_modulus->GetLength())))
+      {
+         throw CkError(CKR_DATA_LEN_RANGE);
+      }
+
+      if(signature->GetLength() != object->_modulus->GetLength()){
+         throw CkError(CKR_SIGNATURE_LEN_RANGE);
+      }
+
+      s4 size ;
+      s4 pubSize ;
+      R_RSA_PUBLIC_KEY	rsaKeyPublic ;
+
+      //Build the RSA public key context
+      rsaKeyPublic.bits = object->_modulus->GetLength() * 8;
+
+      size = (rsaKeyPublic.bits  + 7) / 8 ;
+      memcpy(rsaKeyPublic.modulus,object->_modulus->GetBuffer(),size) ;
+
+      pubSize = ((object->_exponent->GetLength() * 8) + 7) / 8 ;
+      memset(rsaKeyPublic.exponent, 0, size) ;
+      memcpy(&rsaKeyPublic.exponent[size - pubSize], object->_exponent->GetBuffer(), pubSize) ;
+
+      u4 messageToVerifyLen = size;
+      u1Array* messageToVerify = new u1Array(messageToVerifyLen);
+
+      RSAPublicBlock(messageToVerify->GetBuffer(),&messageToVerifyLen,signature->GetBuffer(),size,&rsaKeyPublic);
+
+      switch(mechanism){
+
+            case CKM_RSA_PKCS:
+               rv = VerifyRSAPKCS1v15(messageToVerify,dataToVerify,size);
+               break;
+
+            case CKM_RSA_X_509:
+               rv = VerifyRSAX509(messageToVerify,dataToVerify,size);
+               break;
+
+
+            case CKM_SHA1_RSA_PKCS:
+               rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_SHA_1);
+               break;
+
+            case CKM_SHA256_RSA_PKCS:
+               rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_SHA256);
+               break;
+
+            case CKM_MD5_RSA_PKCS:
+               rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_MD5);
+               break;
+
+            default:
+               PKCS11_ASSERT(CK_FALSE);
+               rv = CKR_GENERAL_ERROR;
+               break;
+      }
+
+      delete messageToVerify;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::VerifyHash(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen,CK_ULONG hashAlgo)
+{
+   u1 DER_SHA1_Encoding[]   = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
+   u1 DER_SHA256_Encoding[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+   u1 DER_MD5_Encoding[]    = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
+
+   s4  DER_Encoding_Len = 0;
+
+   switch(hashAlgo){
+        case CKM_SHA_1:
+           DER_Encoding_Len = sizeof(DER_SHA1_Encoding);
+           break;
+
+        case CKM_SHA256:
+           DER_Encoding_Len = sizeof(DER_SHA256_Encoding);
+           break;
+
+        case CKM_MD5:
+           DER_Encoding_Len = sizeof(DER_MD5_Encoding);
+           break;
+
+   }
+
+   u1* msg  = messageToVerify->GetBuffer();
+   u1* hash = dataToVerify->GetBuffer();
+
+   // Check the decoded value against the expected data.
+   if ((msg[0] != 0x00) || (msg[1] != 0x01)){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   s4 posn = modulusLen - DER_Encoding_Len - dataToVerify->GetLength();
+
+   for(s4 i = 2; i < (posn - 1); i++)
+   {
+      if(msg[i] != 0xFF){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   if(msg[posn - 1] != 0x00){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   for (u4 i = 0; i < dataToVerify->GetLength(); i++){
+      if (msg[posn + i + DER_Encoding_Len] != hash[i]){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   return CKR_OK;
+}
+
+CK_RV Token::VerifyRSAX509(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen)
+{
+   // reach the first non-zero bytes in decrypted signature
+   // and data
+   u4 pos1=0;
+   u4 pos2=0;
+
+   for(;pos1<dataToVerify->GetLength();pos1++){
+      if(dataToVerify->GetBuffer()[pos1] != 0)
+         break;
+   }
+
+   for(;pos2<messageToVerify->GetLength();pos2++){
+      if(messageToVerify->GetBuffer()[pos2] != 0)
+         break;
+   }
+
+   if((dataToVerify->GetLength() - pos1) != (modulusLen - pos2)){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   for(u4 i=pos1,j=pos2;i<(modulusLen - pos2);i++,j++){
+      if(dataToVerify->GetBuffer()[i] != messageToVerify->GetBuffer()[j]){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   return CKR_OK;
+}
+
+CK_RV Token::VerifyRSAPKCS1v15(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen)
+{
+   // skip past the pkcs block formatting data
+   u4 pos = 2;
+   for(;pos<modulusLen;pos++)
+   {
+      if(messageToVerify->GetBuffer()[pos] == 0x00)
+      {
+         pos++;
+         break;
+      }
+   }
+
+   if(dataToVerify->GetLength() != (modulusLen - pos)){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   for(u4 i=0, j=pos;i< (modulusLen - pos); i++,j++){
+      if(dataToVerify->GetBuffer()[i] != messageToVerify->GetBuffer()[j]){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   return CKR_OK;
+}
+
+
+CK_RV Token::Sign(StorageObject* privObj,u1Array* dataToSign,CK_ULONG mechanism,CK_BYTE_PTR pSignature)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      u1Array* messageToSign = NULL_PTR;
+
+      // TODO: Should check if cast is safe
+      RSAPrivateKeyObject * rsaKey = static_cast<RSAPrivateKeyObject*>(privObj);
+      CK_ULONG modulusLen = rsaKey->_modulus->GetLength();
+
+      if(((mechanism == CKM_RSA_PKCS) && (dataToSign->GetLength() > modulusLen - 11)) ||
+         ((mechanism == CKM_RSA_X_509) && (dataToSign->GetLength() > modulusLen)))
+      {
+         throw CkError(CKR_DATA_LEN_RANGE);
+      }
+
+      switch(mechanism){
+
+            case CKM_RSA_PKCS:
+               messageToSign = PadRSAPKCS1v15(dataToSign,modulusLen);
+               break;
+
+            case CKM_RSA_X_509:
+               messageToSign = PadRSAX509(dataToSign,modulusLen);
+               break;
+
+            case CKM_SHA1_RSA_PKCS:
+               messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_SHA_1);
+               break;
+
+            case CKM_SHA256_RSA_PKCS:
+               messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_SHA256);
+               break;
+
+            case CKM_MD5_RSA_PKCS:
+               messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_MD5);
+               break;
+      }
+
+      u1Array* signatureData = NULL_PTR;
+
+      //signatureData = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, messageToSign);
+
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ntry++;
+            signatureData = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, messageToSign);
+            //ManageGC( );
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::Sign", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+      memcpy(pSignature,signatureData->GetBuffer(),signatureData->GetLength());
+
+      delete signatureData;
+      delete messageToSign;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+// these methods should be moved to rsa library
+// once we have it
+u1Array* Token::PadRSAPKCS1v15(u1Array* dataToSign,CK_ULONG modulusLen)
+{
+   u1Array* messageToSign = new u1Array(modulusLen);
+   memset(messageToSign->GetBuffer(),0,modulusLen);
+
+   messageToSign->SetU1At(1,1);
+
+   s4 offsetMessageToSign = modulusLen - dataToSign->GetLength() - 3;
+
+   for(s4 i=0;i<offsetMessageToSign;i++){
+      messageToSign->SetU1At(2+i,0xFF);
+   }
+
+   offsetMessageToSign += 3;
+
+   memcpy((u1*)&messageToSign->GetBuffer()[offsetMessageToSign],dataToSign->GetBuffer(),dataToSign->GetLength());
+
+   return messageToSign;
+}
+
+u1Array* Token::PadRSAX509(u1Array* dataToSign,CK_ULONG modulusLen)
+{
+
+   u1Array* messageToSign = new u1Array(modulusLen);
+   memset(messageToSign->GetBuffer(),0,modulusLen);
+
+   s4 offsetMessageToSign = modulusLen - dataToSign->GetLength();
+
+   memcpy((u1*)&messageToSign->GetBuffer()[offsetMessageToSign],dataToSign->GetBuffer(),dataToSign->GetLength());
+
+   return messageToSign;
+}
+
+u1Array* Token::EncodeHashForSigning(u1Array* hashedData,CK_ULONG modulusLen,CK_ULONG hashAlgo)
+{
+   u1 DER_SHA1_Encoding[]   = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
+   u1 DER_SHA256_Encoding[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+   u1 DER_MD5_Encoding[]    = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
+
+   u1* DER_Encoding = NULL_PTR;
+   s4  DER_Encoding_Len = 0;
+
+   switch(hashAlgo){
+        case CKM_SHA_1:
+           DER_Encoding_Len = sizeof(DER_SHA1_Encoding);
+           DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+           memcpy(DER_Encoding,DER_SHA1_Encoding,DER_Encoding_Len);
+           break;
+
+        case CKM_SHA256:
+           DER_Encoding_Len = sizeof(DER_SHA256_Encoding);
+           DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+           memcpy(DER_Encoding,DER_SHA256_Encoding,DER_Encoding_Len);
+           break;
+
+        case CKM_MD5:
+           DER_Encoding_Len = sizeof(DER_MD5_Encoding);
+           DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+           memcpy(DER_Encoding,DER_MD5_Encoding,DER_Encoding_Len);
+           break;
+
+   }
+
+   u1Array* messageToSign = new u1Array(modulusLen);
+   memset(messageToSign->GetBuffer(),0,modulusLen);
+
+   messageToSign->SetU1At(1,1);
+
+   // caluclate pos
+   s4 pos = modulusLen - DER_Encoding_Len - hashedData->GetLength();
+
+   for(s4 i=2;i<(pos - 1);i++){
+      messageToSign->SetU1At(i,0xFF);
+   }
+
+   memcpy((u1*)&messageToSign->GetBuffer()[pos],DER_Encoding,DER_Encoding_Len);
+   memcpy((u1*)&messageToSign->GetBuffer()[pos+DER_Encoding_Len],hashedData->GetBuffer(),hashedData->GetLength());
+
+   delete DER_Encoding;
+
+   return messageToSign;
+}
+
+bool Token::PerformDeferredDelete()
+{
+   bool fSync = true;
+   //PKCS11_ASSERT(this->_roleLogged != CKU_NONE);
+
+   if(_toDelete.empty())
+      return fSync;
+
+   _cardCache->ClearFileList("mscp");
+   _cardCache->ClearFileList("p11");
+
+   // Delete files that are pending to be deleted
+   vector<string>::iterator ifile = _toDelete.begin();
+   while(ifile != _toDelete.end())
+   {
+      try
+      {
+         _cardCache->ClearFile(*ifile);
+         _mscm->DeleteFile(&(*ifile));
+         RegisterFileUpdate();
+         ifile = _toDelete.erase(ifile);
+      }
+      catch(FileNotFoundException &)
+      {
+         ifile = _toDelete.erase(ifile);
+      }
+      catch(...)
+      {
+         // Failed to delete, keep it in the list.
+         fSync = false;
+         ++ifile;
+      }
+   }
+   return fSync;
+}
+
+s4 Token::RegisterStorageObject(StorageObject * object)
+{
+   // add this in the token object list
+
+   for(size_t k = 0; k<_objects.size(); k++)
+   {
+      PKCS11_ASSERT(_objects[k] != object);
+   }
+
+
+   size_t t = 0;
+   while(t < _objects.size())
+   {
+      if(!_objects[t])
+      {
+         _objects[t] = object;
+         return static_cast<s4>(t+1);
+      }
+      ++t;
+   }
+   // Expand list
+   _objects.push_back(object);
+   return static_cast<s4>(_objects.size());
+}
+
+void Token::UnregisterStorageObject(StorageObject * object)
+{
+   size_t t = 0;
+   while(t<_objects.size())
+   {
+      if(_objects[t] == object)
+      {
+         _objects[t] = 0;
+         break;
+      }
+      ++t;
+   }
+}
+
+auto_ptr<u1Array> Token::ReadCertificateFile(string const & path)
+{
+   // Read certificate file
+
+   const u1Array & compressedCert = _cardCache->ReadFile(path);
+
+   // Decompress
+   unsigned long origLen = compressedCert.ReadU1At(3) * 256 + compressedCert.ReadU1At(2);
+   autoarray<u1> origData(new u1[origLen]);
+   auto_ptr<u1Array> value(new u1Array(origLen));
+   uncompress(value->GetBuffer(), &origLen, compressedCert.GetBuffer()+4, compressedCert.GetLength() - 4);
+   return value;
+
+}
+
+void Token::RegisterPinUpdate()
+{
+   _fPinChanged = true;
+}
+
+void Token::RegisterContainerUpdate()
+{
+   _fContainerChanged = true;
+}
+
+void Token::RegisterFileUpdate()
+{
+   _fFileChanged = true;
+}
+
+//void Token::CheckAvailableSpace()
+//{
+//   return;
+//
+//   //u4 highWaterMark = 20000;
+//   //auto_ptr<u4Array> freeSpace(_mscm->QueryFreeSpace());
+//
+//   //u4 availSpace = freeSpace->ReadU4At(2);
+//   //if(availSpace < highWaterMark)
+//   //    throw CkError(CKR_DEVICE_MEMORY);
+//
+//}
+
+
+/*
+*/
+bool Token::isAuthenticated( void )
+{
+   bool bRet = false;
+   try
+   {
+      if( NULL != _mscm )
+      {
+         bRet = (bool)(_mscm->IsAuthenticated( CARD_ROLE_USER ));
+      }
+   }
+   catch( ... )
+   {
+      Log::error( "Token::isAuthenticated",  "isAuthenticated" );
+      bRet = false;
+   }
+   return bRet;
+}
+
+
+/*
+*/
+bool Token::isNoPinSupported( void )
+{
+   return m_bIsNoPinSupported;
+/*
+bool bIsNoPinSupported = false;
+
+   u1Array* pinProperties = new u1Array( 0 );
+   try
+   {
+      pinProperties = _mscm->GetCardProperty( CARD_PROPERTY_PIN_INFO, CARD_ROLE_USER );
+
+      if( CARD_PROPERTY_NO_PIN == pinProperties->GetBuffer( )[ 0 ] )
+      {
+         bIsNoPinSupported = true;
+      }
+   }
+   catch( ... )
+   {
+   }
+
+   delete pinProperties;
+
+   return bIsNoPinSupported;
+*/
+}
+
+
+/*
+*/
+bool Token::isSSO( void )
+{
+   bool bRet = false;
+   u1Array* ba = 0;
+   try
+   {
+      ba = _mscm->GetCardProperty( CARD_PROPERTY_PIN_POLICY, 0 );
+   }
+   catch( ... )
+   {
+      bRet = false;
+   }
+   if( 0 != ba )
+   {
+      bRet = (bool)(ba->GetBuffer( )[9]);
+
+      /*
+      log2( "Max Attempts <%d>", ba->GetBuffer( )[0] );
+      log2( "Min Length <%d>", ba->GetBuffer( )[1] );
+      log2( "Max Length <%d>", ba->GetBuffer( )[2] );
+      log2( "Char Set <0x%02X>", ba->GetBuffer( )[3] );
+      log2( "Complexity rule 1 <%d>", ba->GetBuffer( )[4] );
+      log2( "Complexity rule 2 <%d>", ba->GetBuffer( )[5] );
+      log2( "Adjacent allowed <%s>", ba->GetBuffer( )[6] ? "Yes" : "No" );
+      log2( "History <%d>", ba->GetBuffer( )[7] );
+      log2( "Unblock allowed <%s>", ba->GetBuffer( )[8] ? "Yes" : "No" );
+      log2( "SSO allowed <%s>", ba->GetBuffer( )[9] ? "Yes" : "No" );
+
+      std::string s6 = ba->GetBuffer( )[6] ? "YES" : "NO";
+      std::string s8 = ba->GetBuffer( )[8] ? "YES" : "NO";
+      std::string s9 = ba->GetBuffer( )[9] ? "YES" : "NO";
+      std::string s3 = "";
+      translateToHex( ba->GetBuffer( )[3], s3 );
+
+      if( ( ba->GetBuffer( )[0] != m_iMaxAttemps )
+      || ( ba->GetBuffer( )[1] != m_iMinLength )
+      || ( ba->GetBuffer( )[2] != m_iMaxLength )
+      || ( s3 != m_stCharSet )
+      || ( ba->GetBuffer( )[4] != m_iComplexityRule1 )
+      || ( ba->GetBuffer( )[5] != m_iComplexityRule2 )
+      || ( s6 != m_stAdjacentAllowed )
+      || ( ba->GetBuffer( )[7] != m_iHistory )
+      || ( s8 != m_stAllowUnblock )
+      || ( s9 != m_stAllowSSO ) )
+      {
+      bRet = false;
+      error( "check pin policy" );
+      }
+      */
+
+      delete ba;
+   }
+   return bRet;
+}
+
+
+/*
+*/
+void Token::CardBeginTransaction( )
+{
+#ifndef _XCL_
+
+   //Log::begin( "Token::CardBeginTransaction" );
+
+   //Log::log( "Token::CardBeginTransaction - _mscm->GetPcscCardHandle..." );
+   SCARDHANDLE hCard = _mscm->GetPcscCardHandle( );
+   //Log::log( "Token::CardBeginTransaction - hCard <%#02x>", hCard );
+
+   if( !hCard )
+   {
+      Log::error( "Token::CardBeginTransaction",  "CKR_FUNCTION_FAILED" );
+      throw CkError( CKR_FUNCTION_FAILED );
+   }
+
+   LONG hResult = SCardBeginTransaction( hCard );
+   while( SCARD_W_RESET_CARD == hResult )
+   {
+      _roleLogged = CKU_NONE;
+      DWORD dwActiveProtocol;
+
+      //Log::log( "Token::CardBeginTransaction - SCardReconnect..." );
+      LONG hr = SCardReconnect( hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, &dwActiveProtocol );
+      //Log::log( "Token::CardBeginTransaction - hr <%#02x>", hr );
+      if( SCARD_S_SUCCESS == hr )
+      {
+         //Log::log( "Token::CardBeginTransaction - SCardBeginTransaction..." );
+         hResult = SCardBeginTransaction( hCard );
+         //Log::log( "Token::CardBeginTransaction - hResult <%#02x>", hResult );
+      }
+      else
+      {
+         Log::log( "Token::CardBeginTransaction - ## ERROR ## PcscError <%#02x>", hr );
+         Log::error( "Token::CardBeginTransaction",  "PcscError" );
+         throw PcscError( hr );
+      }
+   };
+
+
+   if( hResult != SCARD_S_SUCCESS )
+   {
+      Log::log( "Token::CardBeginTransaction - ## ERROR ## hResult <%#02x>", hResult );
+      Log::error( "Token::CardBeginTransaction",  "PcscError" );
+      throw PcscError( hResult );
+   }
+
+   //Log::end( "Token::CardBeginTransaction" );
+#endif
+}
+
+
+void Token::CardEndTransaction()
+{
+#ifndef _XCL_
+
+   //Log::begin( "Token::CardEndTransaction" );
+
+   SCARDHANDLE hCard = _mscm->GetPcscCardHandle( );//_mscm->GetSCardHandle();
+   if(!hCard)
+      throw CkError(CKR_FUNCTION_FAILED);
+
+   LONG hResult = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
+#ifdef __APPLE__
+   while((hResult == SCARD_W_RESET_CARD) || (hResult == SCARD_W_REMOVED_CARD))
+#else
+   while(hResult == SCARD_W_RESET_CARD)
+#endif
+   {
+      _roleLogged = CKU_NONE;
+      DWORD dwActiveProtocol;
+      LONG hr = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,SCARD_LEAVE_CARD,&dwActiveProtocol);
+      if(hr == SCARD_S_SUCCESS)
+         hResult = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
+      else
+         throw PcscError(hr);
+   }
+   if(hResult != SCARD_S_SUCCESS && hResult != SCARD_E_NOT_TRANSACTED) // SCARD_E_NOT_TRANSACTED shouldn't occur, still ignore it.
+      throw PcscError(hResult);
+
+   //Log::end( "Token::CardEndTransaction" );
+#endif
+}
+
+StorageObject * Token::GetObject(CK_OBJECT_HANDLE hObject)
+{
+   CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+   if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || !_objects[idx-1])
+      throw CkError(CKR_OBJECT_HANDLE_INVALID);
+
+   return _objects[idx-1];
+}
+
+
+void CMapFileClear(u1Array & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD;
+   memset(file.GetBuffer()+idx, 0, SIZE_CONTAINERMAPRECORD);
+}
+
+void CMapFileSetName(u1Array & file, u1 index, string const & name)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_GUID_INFO;
+   memset(file.GetBuffer()+idx, 0, 80);
+   const size_t length = name.size() > 39 ? 39 : name.size();
+   for(size_t i = 0; i<length; i++)
+      file.SetU1At(idx + 2*i, name[i]); // Convert to wchar, little endian.
+}
+
+u1 CMapFileGetFlag(u1Array const & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_FLAGS;
+   return file.ReadU1At(idx);
+}
+
+void CMapFileSetFlag(u1Array & file, u1 index, u1 flag)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_FLAGS;
+   file.SetU1At(idx, flag);
+}
+
+u2 CMapFileGetSignSize(u1Array const & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_SIG_KEY_SIZE;
+   return LittleEndianToInt<u2>(file.GetBuffer(), idx);
+}
+
+void CMapFileSetSignSize(u1Array & file, u1 index, u2 size)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_SIG_KEY_SIZE;
+   IntToLittleEndian<u2>(size, file.GetBuffer(), idx);
+}
+
+u2 CMapFileGetExchSize(u1Array const & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_EXC_KEY_SIZE;
+   return LittleEndianToInt<u2>(file.GetBuffer(), idx);
+}
+
+void CMapFileSetExchSize(u1Array & file, u1 index, u2 size)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_EXC_KEY_SIZE;
+   IntToLittleEndian<u2>(size, file.GetBuffer(), idx);
+}
+
+
+/*
+*/
+bool Token::isPinPadSupported( void )
+{
+   // Get Reader Features
+   BYTE  outBuffer[256];
+   memset( outBuffer, 0, sizeof( outBuffer ) );
+   DWORD dwLen = 0;
+   LONG lRet = SCardControl( _mscm->GetPcscCardHandle( ), CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, outBuffer, sizeof(outBuffer), &dwLen );
+
+   // Search IOCTL of Verify PIN feature
+   int i = 0;
+   bool isVerifyPin = false;
+   m_dwIoctlVerifyPIN = 0;
+   if ( ( SCARD_S_SUCCESS == lRet ) && ( dwLen > 0 ) )
+   {
+      while( ( i + 6 ) <= (int)dwLen )
+      {
+         // Search Verify PIN feature Tag
+         if (  (outBuffer[i] == FEATURE_VERIFY_PIN_DIRECT)
+            &&(outBuffer[i+1] == 4)
+            )
+         {
+            m_dwIoctlVerifyPIN += (outBuffer[i+2] << 24);
+            m_dwIoctlVerifyPIN += (outBuffer[i+3] << 16);
+            m_dwIoctlVerifyPIN += (outBuffer[i+4] << 8);
+            m_dwIoctlVerifyPIN += outBuffer[i+5];
+
+            isVerifyPin = true;
+
+            break;
+         }
+         else
+         {
+            i += (outBuffer[i+1] + 2);
+         }
+      }
+   }
+
+   return (isVerifyPin);
+}
+
+
+///*
+//*/
+//bool Token::isPinExternalSupported( void )
+//{
+//   bool bIsPinExternalSupported = false;
+//
+//   u1Array* pinProperties = new u1Array( 0 );
+//   try
+//   {
+//      pinProperties = _mscm->GetardProperty( CARD_PROPERTY_PIN_INFO, CARD_ROLE_USER );
+//
+//      if( CARD_PROPERTY_EXTERNAL_PIN == pinProperties->GetBuffer( )[ 0 ] )
+//      {
+//         bIsPinExternalSupported = true;
+//      }
+//   }
+//   catch( ... )
+//   {
+//   }
+//
+//   delete pinProperties;
+//
+//   return bIsPinExternalSupported;
+//}
+
+/*
+*/
+CK_RV Token::verifyPinWithPinPad( void )
+{
+   DWORD PinId = CARD_ROLE_USER;
+   LONG                 lRet;
+   BYTE                 offset;
+   DWORD                dwSendLen;
+   PIN_VERIFY_STRUCTURE pin_verify;
+   BYTE                 inBuffer[256];
+   DWORD                dwInLen = 0;
+   BYTE                 outBuffer[256];
+   DWORD                dwOutLen = 0;
+
+   pin_verify.bTimerOut = 30;                               /* Time out between key stroke = max(bTimerOut, bTimerOut2). Must be between 15 and 40 sec.*/
+   pin_verify.bTimerOut2 = 00;
+
+   pin_verify.bmFormatString = 0x82;                        /* Padding V2=0x82 */
+
+   pin_verify.bmPINBlockString = 0x06;
+   pin_verify.bmPINLengthFormat = 0x00;
+   pin_verify.bPINMaxExtraDigit1 = 0x08;                    /* Max */
+   pin_verify.bPINMaxExtraDigit2 = 0x04;                    /* Min */
+   pin_verify.bEntryValidationCondition = 0x02;             /* validation key pressed */
+   pin_verify.bNumberMessage = 0x01;
+   pin_verify.wLangId = 0x0904;
+   pin_verify.bMsgIndex = 0x00;
+   pin_verify.bTeoPrologue[0] = 0x00;
+   pin_verify.bTeoPrologue[1] = 0x00;
+   pin_verify.bTeoPrologue[2] = 0x00;                       /* pin_verify.ulDataLength = 0x00; we don't know the size yet */
+
+   offset = 0;
+   pin_verify.abData[offset++] = 0x00;                      /* CLA */ /*********************************/
+   pin_verify.abData[offset++] = 0x20;                      /* INS: VERIFY */
+   pin_verify.abData[offset++] = 0x00;                      /* P1: always 0 */
+   pin_verify.abData[offset++] = (BYTE)PinId;               /* P2: PIN reference */
+   pin_verify.abData[offset++] = 0x08;                      /* Lc: 8 data bytes */
+
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+
+   pin_verify.ulDataLength = offset;                        /* APDU size */
+   dwSendLen = sizeof(PIN_VERIFY_STRUCTURE);
+
+   // Select MSCM Application
+   inBuffer[0] = 0x00;   //CLA
+   inBuffer[1] = 0xA4;   //INS
+   inBuffer[2] = 0x04;   //P1
+   inBuffer[3] = 0x00;   //P2
+   inBuffer[4] = 0x04;   //Li
+
+   memcpy(&inBuffer[5], "MSCM", 4);
+
+   dwInLen = 5 + inBuffer[4];
+
+   dwOutLen = sizeof(outBuffer);
+   memset(outBuffer, 0x00, sizeof(outBuffer));
+
+   lRet = SCardTransmit(_mscm->GetPcscCardHandle(),
+      SCARD_PCI_T0,
+      inBuffer,
+      dwInLen,
+      NULL,
+      outBuffer,
+      &dwOutLen
+      );
+
+   // Send Verify command to the reader
+   dwOutLen = 0;
+   memset(outBuffer, 0x00, sizeof(outBuffer));
+
+   lRet = SCardControl(_mscm->GetPcscCardHandle(),
+      m_dwIoctlVerifyPIN,
+      (BYTE *)&pin_verify,
+      dwSendLen,
+      outBuffer,
+      sizeof(outBuffer),
+      &dwOutLen
+      );
+
+   Log::log( "Token::verifyPinWithPinPad - sw <%#02x %#02x>", outBuffer[ 0 ], outBuffer[ 1 ] );
+
+   CK_RV rv = CKR_FUNCTION_FAILED;
+   if( ( 0x90 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+   {
+      rv = CKR_OK;
+   }
+   else if( ( 0x63 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+   {
+      rv = CKR_PIN_INCORRECT;
+   }
+   // operation was cancelled by the \x91Cancel\x92 button
+   else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x01 == outBuffer[ 1 ] ) )
+   {
+      //return SCARD_W_CANCELLED_BY_USER;
+      rv = CKR_FUNCTION_CANCELED;
+   }
+   // operation timed out
+   else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+   {
+      //return SCARD_E_TIMEOUT;
+      rv = CKR_FUNCTION_CANCELED;
+   }
+   // operation timed out
+   else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x03 == outBuffer[ 1 ] ) )
+   {
+      //return SCARD_E_TIMEOUT;
+      rv = CKR_PIN_INCORRECT;
+   }
+
+   Log::log( "Token::verifyPinWithPinPad - rv <%#02x>", rv );
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Token::verifyPinWithBio( void /*Marshaller::u1Array *pin*/ )
+{
+   Log::log( "Token::verifyPinWithBio - <BEGIN>" );
+
+   CK_RV rv = CKR_GENERAL_ERROR;
+
+#ifdef WIN32
+   // Get the current OS version
+   OSVERSIONINFO osvi;
+   memset( &osvi, 0, sizeof( OSVERSIONINFO ) );
+   osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+   GetVersionEx(&osvi);
+   // Check if the Os is W7 or W2K8R2
+   if( ( 6 == osvi.dwMajorVersion ) && ( osvi.dwMinorVersion >= 1 ) )
+   {
+      Log::log( "Token::verifyPinWithBio - Os is W7 or W2K8R2" );
+
+      CardEndTransaction( );
+
+      // The OS is W7 or W2K8R2
+      HMODULE hDll = NULL;
+      LRESULT lRes = GSC_OK;
+      LRESULT (WINAPI *ptr_SetUITitles) (WCHAR*, WCHAR*);
+      LRESULT (WINAPI *ptr_AuthenticateUserCard) ();
+
+      // Load DLL
+      hDll = LoadLibraryA("GemSelCert.dll");
+      Log::log( "Token::verifyPinWithBio - load lib" );
+
+      if( 0 != hDll )
+      {
+         // Set UI Titles
+         ptr_SetUITitles = (LRESULT (WINAPI *) (WCHAR*, WCHAR*))GetProcAddress(hDll,"SetUITitles");
+         if( NULL != ptr_SetUITitles )
+         {
+            ptr_SetUITitles(L"Smartcard Security", L"User authentication");
+            Log::log( "Token::verifyPinWithBio - ptr_SetUITitles" );
+
+            // Authenticate Card User
+            ptr_AuthenticateUserCard = (LRESULT (WINAPI *)())GetProcAddress(hDll,"AuthenticateUserCard");
+            if( NULL != ptr_AuthenticateUserCard )
+            {
+               lRes = ptr_AuthenticateUserCard();
+               Log::log( "Token::verifyPinWithBio - ptr_AuthenticateUserCard" );
+
+               switch(lRes)
+               {
+               case GSC_OK:
+                  rv = CKR_OK;
+                  Log::log( "Token::verifyPinWithBio - CKR_OK" );
+                  break;
+
+               case GSC_CANCEL:
+                  rv = CKR_FUNCTION_CANCELED;
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_CANCELED" );
+                  break;
+
+               case GSC_NO_CERT:
+                  rv = CKR_KEY_NEEDED;
+                  Log::log( "Token::verifyPinWithBio - CKR_KEY_NEEDED" );
+                  break;
+
+               case GSC_NO_CARD:
+                  rv = CKR_TOKEN_NOT_RECOGNIZED;
+                  Log::log( "Token::verifyPinWithBio - CKR_TOKEN_NOT_RECOGNIZED" );
+                  break;
+
+               case GSC_WRONG_PIN:
+                  rv = CKR_PIN_INCORRECT;
+                  Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+                  break;
+
+               case GSC_READ_CARD:
+                  rv = CKR_FUNCTION_FAILED;
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+                  break;
+
+               case GSC_WRITE_CARD:
+                  rv = CKR_FUNCTION_FAILED;
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+                  break;
+
+               default:
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+                  rv = CKR_FUNCTION_FAILED;
+                  break;
+               }
+            }
+         }
+
+         // Release DLL
+         FreeLibrary(hDll);
+         Log::log( "Token::verifyPinWithBio - FreeLibrary" );
+      }
+
+      CardBeginTransaction( );
+   }
+   // The OS is Vista or XP
+   else
+   {
+      Log::log( "Token::verifyPinWithBio - Os is Vista or XP" );
+
+      CBioMan* pBioMan = NULL;
+      DWORD dwRes = BIO_ERR_NOT_SUPPORTED;
+
+      // Init BioMan helper
+      pBioMan = new CBioMan( );
+      Log::log( "Token::verifyPinWithBio - new" );
+      pBioMan->Connect( this->_mscm );
+      Log::log( "Token::verifyPinWithBio - connect" );
+
+      // Biometrics Verification
+      dwRes = pBioMan->VerifyBio( );
+      Log::log( "Token::verifyPinWithBio - verify bio" );
+
+      delete pBioMan;
+      Log::log( "Token::verifyPinWithBio - delete" );
+
+      // Error ?
+      switch( dwRes )
+      {
+      case BIO_ERR_SUCCESS:
+         Log::log( "Token::verifyPinWithBio - CKR_OK" );
+         rv = CKR_OK;
+         break;
+
+      case BIO_ERR_NO_CARD:
+         Log::log( "Token::verifyPinWithBio - CKR_TOKEN_NOT_PRESENT" );
+         rv = CKR_TOKEN_NOT_PRESENT;
+         break;
+
+      case BIO_ERR_NOT_SUPPORTED:
+      case BIO_ERR_NO_FINGER:
+         Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_NOT_SUPPORTED" );
+         //this->_mscm->VerifyPin( CARD_ROLE_USER, pin );
+         rv = CKR_FUNCTION_NOT_SUPPORTED; //CKR_OK;
+         break;
+
+      case BIO_ERR_BIO_NOT_CHECKED:
+      case BIO_ERR_PIN_NOT_CHECKED:
+         Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+         rv = CKR_PIN_INCORRECT;
+         break;
+
+      case BIO_ERR_BIO_LAST:
+      case BIO_ERR_PIN_LAST:
+         Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+         rv = CKR_PIN_INCORRECT;
+         break;
+
+      case BIO_ERR_BLOCKED:
+         Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+         rv = CKR_PIN_INCORRECT;
+         break;
+
+      case BIO_ERR_ABORT:
+         Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+         rv = CKR_FUNCTION_FAILED;
+         break;
+
+      default:
+         Log::log( "Token::verifyPinWithBio - CKR_GENERAL_ERROR" );
+         rv = CKR_GENERAL_ERROR;
+         break;
+      }
+   }
+#endif
+
+   Log::log( "Token::verifyPinWithBio - <END>" );
+
+   return rv;
+}
+
+
+/*
+*/
+void Token::getCardConfiguration( BYTE& a_bMode, BYTE &a_bTypePIN )
+{
+   a_bMode = UVM_PIN_ONLY;
+   a_bTypePIN = PIN_TYPE_REGULAR;
+
+   u1Array* ba = new u1Array( 0 );
+
+   try
+   {
+      ba = _mscm->GetCardProperty( CARD_PROPERTY_PIN_INFO_EX, CARD_ROLE_USER );
+
+      DWORD dwFlagsEx = (DWORD)(
+         ba->GetBuffer( )[ 12 ] +
+         ( ( ba->GetBuffer( )[ 13 ] ) << 8 ) +
+         ( ( ba->GetBuffer( )[ 14 ] ) << 16 ) +
+         ( ( ba->GetBuffer( )[ 15 ] ) << 24 )
+         );
+      //Log::log( "Token::getCardMode - dwFlagsEx <%#08x>", dwFlagsEx );
+
+      WORD wActiveMode = (WORD)( ba->GetBuffer( )[ 12 ] + ( ( ba->GetBuffer( )[ 13 ] ) << 8 ) );
+      //Log::log( "Token::getCardMode - Active mode <%ld>", wActiveMode );
+
+      a_bMode = (BYTE)wActiveMode;
+
+      a_bTypePIN = (BYTE)ba->GetBuffer( )[ 0 ];
+   }
+   catch( ... )
+   {
+      Log::log( "Token::getCardMode - PIN_INFO_EX not supported - Default values used" );
+      a_bMode = UVM_PIN_ONLY;
+      a_bTypePIN = PIN_TYPE_REGULAR;
+   }
+
+   delete ba;
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/sctoken.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,258 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_token_h
+#define _include_token_h
+
+#include <memory>
+#include <string>
+#include <list>
+#include <map>
+#include "cardmoduleservice.h"
+#include "rsapublickeyobject.h"
+#include "rsaprivatekeyobject.h"
+#include "x509pubkeycertobject.h"
+#include "cr_rsa.h"
+
+// This class represents the data in the card/token
+
+#define FILE_TYPE_RAW_CERT          0
+#define FILE_TYPE_DATA              1
+#define FILE_TYPE_CERT              2
+#define FILE_TYPE_SECRETKEY         3
+#define FILE_TYPE_PUBLICKEY         4
+#define FILE_TYPE_PRIVATEKEY        5
+
+#define CARD_ROLE_EVERYONE      0x00
+#define CARD_ROLE_USER          0x01
+#define CARD_ROLE_ADMIN         0x02
+
+#define CARD_PERMISSION_READ    0x04
+#define CARD_PERMISSION_WRITE   0x02
+#define CARD_PERMISSION_EXECUTE 0x01
+
+#define KEYSPEC_KEYEXCHANGE  0x01
+#define KEYSPEC_SIGNATURE    0x02
+
+#define KEY_TAG_UNKNOWN         0x00
+#define KEY_TAG_EXPONENT        0x01
+#define KEY_TAG_MODULUS         0x02
+#define KEY_TAG_KEYSPEC         0x03
+#define KEY_TAG_MINBITLEN       0x04
+#define KEY_TAG_MAXBITLEN       0x05
+#define KEY_TAG_DEFAULTBITLEN   0x06
+#define KEY_TAG_INCREMENTBITLEN 0x07
+
+#define MODE_CHANGE_PIN         0x00
+#define MODE_UNBLOCK_PIN        0x01
+
+#define MAX_USER_PIN_TRIES      0x05
+#define MAX_SO_PIN_TRIES        0x05
+
+#define MIN_PIN_LEN             4
+#define MAX_PIN_LEN             24
+
+#define RSA_KEY_MIN_LENGTH 512
+#define RSA_KEY_MAX_LENGTH 2048
+
+// Constants defining layout of the records in cmapfile
+#define SIZE_CONTAINERMAPRECORD 86
+#define IDX_GUID_INFO 0
+#define IDX_FLAGS 80
+#define IDX_SIG_KEY_SIZE 82
+#define IDX_EXC_KEY_SIZE 84
+
+// Helper structs used when sync'ing CAPI containers
+// against P11 data.
+
+struct KeyPair
+{
+    KeyPair() : _checkValue(0), _fP11PrivKeyExists(false), _fP11CertExists(false) {}
+
+    u1Array _publicExponent;
+    u1Array _modulus;
+    u8 _checkValue;
+    u1Array _cert;
+    string _certName;
+    bool _fP11PrivKeyExists;
+    bool _fP11CertExists;
+};
+
+struct ContainerInfo
+{
+    ContainerInfo() : _cmapEntry(false) {}
+
+    bool _cmapEntry;        // True if it represents a valid entry in cmapfile
+    KeyPair _signKP;
+    KeyPair _exchKP;
+};
+
+class CardCache;
+
+class Token {
+
+private:
+    CardModuleService*      _mscm;
+
+    bool                    _initialized;
+    bool                    _supportGarbageCollection;
+    vector<StorageObject*>  _objects;
+    vector<string>          _toDelete;          // List of files to be deleted at next login
+    CardCache *             _cardCache;
+    unsigned long           _cardCfTimer;       // Timer indicating when _cardCf was last known to be up-to-date
+    CK_ULONG                _cardCf;            // Current state from \cardcf
+    CK_ULONG                _publCardCf;        // Reflects state of public cached objects
+    CK_ULONG                _privCardCf;        // Reflects state of private cached objects
+    CK_ULONG                _cacheCardCf;       // Reflects state of card cache (_cardCache)
+
+    bool                    _fPinChanged;
+    bool                    _fContainerChanged;
+    bool                    _fFileChanged;
+   
+    BYTE m_bCardMode;
+    BYTE m_bTypePIN;
+    //u1Array* m_u1aSerialNumber;
+
+public:
+    CK_BBOOL                _version;
+    CK_TOKEN_INFO           _tokenInfo;
+    CK_ULONG                _roleLogged;
+    //bool m_isPinExternal;
+    bool m_bIsPinPadSupported;
+    bool m_bIsSSO;
+    bool m_bIsNoPinSupported;
+
+public:
+    Token(std::string* reader);
+    ~Token();
+
+    CardModuleService* /*const*/ GetMiniDriverService( void ) { return _mscm; };
+
+    void Clear();
+    void BeginTransaction();
+    void EndTransaction();
+    void CardBeginTransaction();
+    void CardEndTransaction();
+    void ManageGC( bool bForceGarbage = false );
+
+    CK_RV Login(CK_ULONG userType,u1Array* pin);
+    CK_RV Logout();
+    CK_RV GenerateRandom(CK_BYTE_PTR randomData,CK_ULONG len);
+    CK_RV AddObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV AddPrivateKeyObject(auto_ptr<StorageObject> & stobj,CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV AddCertificateObject(auto_ptr<StorageObject> & stobj,CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV DeleteObject(CK_OBJECT_HANDLE hObject);
+    CK_ULONG FindObjects(Session* session,CK_OBJECT_HANDLE_PTR phObject,
+                         CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount);
+
+    CK_RV GetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    CK_RV SetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+
+    CK_RV GenerateKeyPair(auto_ptr<StorageObject> & stobjRsaPub, auto_ptr<StorageObject> & stobjRsaPriv,
+                          CK_OBJECT_HANDLE_PTR phPubKey,CK_OBJECT_HANDLE_PTR phPrivKey);
+
+    CK_RV GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object);
+
+    CK_RV Sign(StorageObject* privObj,u1Array* dataToSign,CK_ULONG mechanism,CK_BYTE_PTR pSignature);
+    CK_RV Decrypt(StorageObject* privObj,u1Array* dataToDecrypt,CK_ULONG mechanism,CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+    CK_RV Verify(StorageObject* pubObj,u1Array* dataToVerify,CK_ULONG mechanism,u1Array* signature);
+    CK_RV Encrypt(StorageObject* pubObj,u1Array* dataToEncrypt,CK_ULONG mechanism,CK_BYTE_PTR pEncryptedData);
+
+    CK_RV InitToken(u1Array* pin,u1Array* label);
+    CK_RV InitPIN(u1Array* soPIN,u1Array* userPIN);
+    CK_RV SetPIN(u1Array* oldPIN,u1Array* newPIN);
+
+    bool isAuthenticated( void );
+    bool isSSO( void );
+    bool isNoPinSupported( void );
+
+private:
+
+   void getCardConfiguration( BYTE& a_bMode, BYTE &a_bTypePIN );
+   BYTE howToAuthenticate( BYTE bPinLen );
+   bool isPinPadSupported( void );
+   //bool isPinExternalSupported( void );
+   CK_RV verifyPinWithPinPad( void );
+   CK_RV verifyPinWithBio( void /*Marshaller::u1Array *pin*/ );
+   DWORD m_dwIoctlVerifyPIN;
+
+   std::string m_sReaderName;
+    void Initialize();
+    void Resynchronize();
+    CK_RV AuthenticateUser(u1Array* pin);
+    CK_RV AuthenticateAdmin(u1Array* key);
+    void CreateDirIfNotPresent(std::string* parent,std::string* dir,u1Array* acls);
+    bool IsInitialized();
+    void PopulateDefaultTokenInfo();
+    void SerializeTokenInfo();
+    void DeserializeTokenInfo();
+    CK_BYTE GetAvailableContainerIndex(u1Array const & cmapContents);
+    CK_BYTE GetContainerForCert(u1Array const & cmapContents, u8 checkValue, u1 * keySpec);
+    CK_BYTE GetContainerForPrivateKey(u1Array const & cmapContents, u8 checkValue, u1 * keySpec);
+
+    auto_ptr<u1Array> UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,string const & contName);
+    auto_ptr<u1Array> UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,u4 keySize,u1 keySpec,
+                                 CK_BBOOL isDefault, string const & contName);
+
+    vector <PrivateKeyObject*> FindPrivateKeys(vector<StorageObject*> const & objects, u8 checkValue);
+    PrivateKeyObject* FindPrivateKey(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec);
+    vector <CertificateObject*> FindCertificates(vector<StorageObject*> const & objects, u8 checkValue);
+    CertificateObject* FindCertificate(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec);
+
+    u1Array* PadRSAPKCS1v15(u1Array* dataToSign,CK_ULONG modulusLen);
+    u1Array* PadRSAX509(u1Array* dataToSign,CK_ULONG modulusLen);
+    u1Array* EncodeHashForSigning(u1Array* hashedData,CK_ULONG modulusLen,CK_ULONG hashAlgo);
+
+    CK_BBOOL IsSynchronized();
+    void SynchronizeCertificates(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap);
+    void SynchronizePrivateKeys(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap);
+    void PrepareCertAttributesFromRawData(X509PubKeyCertObject* certObject);
+    bool PerformDeferredDelete();
+    string FindFreeFileName(StorageObject* object);
+    CK_RV WriteObject(StorageObject* object);
+
+    void ReadAndPopulateObjects(vector<StorageObject*> & objects, vector<string> & toDelete,
+                                std::string const & prefix, map<int, ContainerInfo> & contMap);
+    void SynchronizePublicObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap);
+    void SynchronizePrivateObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap);
+    void BuildContainerInfoMap(map<int, ContainerInfo> & contMap);
+    void DeleteCMapRecord(CK_BYTE ctrdIdx);
+    void RemoveKeyFromCMapRecord(CK_BYTE ctrIndex, u1 keySpec);
+    void SetDefaultContainer(u1Array & contents, CK_BYTE ctrIndex);
+    u1Array* ComputeCryptogram(u1Array* challenge,u1Array* pin);
+    CK_RV VerifyRSAPKCS1v15(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen);
+    CK_RV VerifyRSAX509(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen);
+    CK_RV VerifyHash(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen,CK_ULONG hashAlgo);
+
+    static CK_RV DoPINValidityChecks(u1Array* pin, bool fCheckCharaceters = true);
+    s4 RegisterStorageObject(StorageObject * object);
+    void UnregisterStorageObject(StorageObject * object);
+    auto_ptr<u1Array> ReadCertificateFile(string const & path);
+    void RegisterPinUpdate();
+    void RegisterContainerUpdate();
+    void RegisterFileUpdate();
+    //void CheckAvailableSpace();
+    StorageObject * GetObject(CK_OBJECT_HANDLE hObject);
+
+};
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,308 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "secretkeyobject.h"
+
+SecretKeyObject::SecretKeyObject() : KeyObject()
+{
+   this->_sensitive        = CK_FALSE;
+   this->_encrypt          = CK_FALSE;
+   this->_decrypt          = CK_FALSE;
+   this->_sign             = CK_FALSE;
+   this->_verify           = CK_FALSE;
+   this->_wrap             = CK_FALSE;
+   this->_unwrap           = CK_FALSE;
+   this->_extractable      = CK_FALSE;
+   this->_alwaysSensitive  = CK_FALSE;
+   this->_neverExtractable = CK_FALSE;
+   this->_checkSum         = NULL_PTR;
+   this->_wrapWithTrusted  = CK_FALSE;
+   this->_trusted          = CK_FALSE;
+
+   this->_value            = NULL_PTR;
+   this->_valueLength      = 0;
+
+   this->_class            = CKO_SECRET_KEY;
+}
+
+SecretKeyObject::~SecretKeyObject(){
+
+   if(this->_value != NULL_PTR){
+      delete this->_value;
+   }
+}
+
+CK_BBOOL SecretKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_SENSITIVE:
+           return (this->_sensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ENCRYPT:
+           return (this->_encrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_DECRYPT:
+           return (this->_decrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SIGN:
+           return (this->_sign == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VERIFY:
+           return (this->_verify == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_UNWRAP:
+           return (this->_unwrap == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_EXTRACTABLE:
+           return (this->_extractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ALWAYS_SENSITIVE:
+           return (this->_alwaysSensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_NEVER_EXTRACTABLE:
+           return (this->_neverExtractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_CHECK_VALUE:
+           return Util::CompareU1Arrays(this->_checkSum,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_WRAP_WITH_TRUSTED:
+           return (this->_wrapWithTrusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_TRUSTED:
+           return (this->_trusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VALUE:
+           return Util::CompareU1Arrays(this->_value,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_VALUE_LEN:
+           return (this->_valueLength == *(CK_ULONG*)attribute.pValue);
+
+        default:
+           return KeyObject::Compare(attribute);
+   }
+}
+
+CK_RV SecretKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type)
+   {
+   case CKA_SENSITIVE:
+      return StorageObject::PutBBoolInAttribute(this->_sensitive,attribute);
+
+   case CKA_ENCRYPT:
+      return StorageObject::PutBBoolInAttribute(this->_encrypt,attribute);
+
+   case CKA_DECRYPT:
+      return StorageObject::PutBBoolInAttribute(this->_decrypt,attribute);
+
+   case CKA_SIGN:
+      return StorageObject::PutBBoolInAttribute(this->_sign,attribute);
+
+   case CKA_VERIFY:
+      return StorageObject::PutBBoolInAttribute(this->_verify,attribute);
+
+   case CKA_UNWRAP:
+      return StorageObject::PutBBoolInAttribute(this->_unwrap,attribute);
+
+   case CKA_EXTRACTABLE:
+      return StorageObject::PutBBoolInAttribute(this->_extractable,attribute);
+
+   case CKA_ALWAYS_SENSITIVE:
+      return StorageObject::PutBBoolInAttribute(this->_alwaysSensitive,attribute);
+
+   case CKA_NEVER_EXTRACTABLE:
+      return StorageObject::PutBBoolInAttribute(this->_neverExtractable,attribute);
+
+   case CKA_CHECK_VALUE:
+      return StorageObject::PutU1ArrayInAttribute(this->_checkSum,attribute);
+
+   case CKA_WRAP_WITH_TRUSTED:
+      return StorageObject::PutBBoolInAttribute(this->_wrapWithTrusted,attribute);
+
+   case CKA_TRUSTED:
+      return StorageObject::PutBBoolInAttribute(this->_trusted,attribute);
+
+   case CKA_VALUE:
+      if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+         attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+         return CKR_ATTRIBUTE_SENSITIVE;
+      }
+      return StorageObject::PutU1ArrayInAttribute(this->_value,attribute);
+
+   case CKA_VALUE_LEN:
+      return StorageObject::PutULongInAttribute(this->_valueLength,attribute);
+
+   default:
+      return KeyObject::GetAttribute(attribute);
+   }
+}
+
+CK_RV SecretKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   switch(attribute.type)
+   {
+   case CKA_SENSITIVE:
+      this->_sensitive = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_ENCRYPT:
+      this->_encrypt = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_DECRYPT:
+      this->_decrypt = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_SIGN:
+      this->_sign = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_VERIFY:
+      this->_verify = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_UNWRAP:
+      this->_unwrap = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_EXTRACTABLE:
+      this->_extractable = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_ALWAYS_SENSITIVE:
+      this->_alwaysSensitive = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_NEVER_EXTRACTABLE:
+      this->_neverExtractable = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_CHECK_VALUE:
+      if(this->_checkSum != NULL_PTR){
+         delete this->_checkSum;
+      }
+      this->_checkSum = new u1Array(attribute.ulValueLen);
+      memcpy((u1*)this->_checkSum->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_WRAP_WITH_TRUSTED:
+      this->_wrapWithTrusted = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_TRUSTED:
+      this->_trusted = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_VALUE:
+      if(this->_value != NULL_PTR){
+         delete this->_value;
+      }
+      this->_value = new u1Array(attribute.ulValueLen);
+      memcpy((u1*)this->_value->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_VALUE_LEN:
+      this->_valueLength = *(CK_ULONG*)attribute.pValue;
+      break;
+
+   default:
+      return KeyObject::SetAttribute(attribute,objCreation);
+   }
+
+   return CKR_OK;
+}
+
+void SecretKeyObject::Serialize(std::vector<u1> *to)
+{
+   KeyObject::Serialize(to);
+
+   Util::PushBBoolInVector(to,this->_sensitive);
+
+   Util::PushBBoolInVector(to,this->_encrypt);
+
+   Util::PushBBoolInVector(to,this->_decrypt);
+
+   Util::PushBBoolInVector(to,this->_sign);
+
+   Util::PushBBoolInVector(to,this->_verify);
+
+   Util::PushBBoolInVector(to,this->_unwrap);
+
+   Util::PushBBoolInVector(to,this->_extractable);
+
+   Util::PushBBoolInVector(to,this->_alwaysSensitive);
+
+   Util::PushBBoolInVector(to,this->_neverExtractable);
+
+   Util::PushByteArrayInVector(to,this->_checkSum);
+
+   Util::PushBBoolInVector(to,this->_wrapWithTrusted);
+
+   Util::PushBBoolInVector(to,this->_trusted);
+
+   Util::PushByteArrayInVector(to,this->_value);
+
+   Util::PushULongInVector(to,this->_valueLength);
+}
+
+void SecretKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   KeyObject::Deserialize(from,idx);
+
+   this->_sensitive = Util::ReadBBoolFromVector(from,idx);
+
+   this->_encrypt = Util::ReadBBoolFromVector(from,idx);
+
+   this->_decrypt = Util::ReadBBoolFromVector(from,idx);
+
+   this->_sign = Util::ReadBBoolFromVector(from,idx);
+
+   this->_verify = Util::ReadBBoolFromVector(from,idx);
+
+   this->_unwrap = Util::ReadBBoolFromVector(from,idx);
+
+   this->_extractable = Util::ReadBBoolFromVector(from,idx);
+
+   this->_alwaysSensitive = Util::ReadBBoolFromVector(from,idx);
+
+   this->_neverExtractable = Util::ReadBBoolFromVector(from,idx);
+
+   this->_checkSum = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_wrapWithTrusted = Util::ReadBBoolFromVector(from,idx);
+
+   this->_trusted = Util::ReadBBoolFromVector(from,idx);
+
+   this->_value = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_valueLength = Util::ReadULongFromVector(from,idx);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/secretkeyobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,61 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_secretkeyobject_h
+#define _include_secretkeyobject_h
+
+#include "keyobject.h"
+
+class SecretKeyObject : public KeyObject
+{
+
+public:
+    CK_BBOOL    _sensitive;
+    CK_BBOOL    _encrypt;
+    CK_BBOOL    _decrypt;
+    CK_BBOOL    _sign;
+    CK_BBOOL    _verify;
+    CK_BBOOL    _wrap;
+    CK_BBOOL    _unwrap;
+    CK_BBOOL    _extractable;
+    CK_BBOOL    _alwaysSensitive;
+    CK_BBOOL    _neverExtractable;
+    u1Array*    _checkSum;
+    CK_BBOOL    _wrapWithTrusted;
+    CK_BBOOL    _trusted;
+
+    u1Array*    _value;
+    CK_ULONG    _valueLength;
+
+public:
+    SecretKeyObject();
+    virtual ~SecretKeyObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/session.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/session.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/session.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,604 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "template.h"
+#include "session.h"
+#include "slot.h"
+
+Session::Session(CK_BBOOL isReadWrite){
+    this->_isReadWrite    = isReadWrite;
+    this->_searchTempl    = NULL_PTR;
+    this->_isSearchActive = CK_FALSE;
+
+    this->_digest         = NULL_PTR;
+    this->_digestRSA      = NULL_PTR;
+    this->_digestRSAVerification = NULL_PTR;
+
+    this->_isDigestActive = CK_FALSE;
+    this->_isDigestRSAActive = CK_FALSE;
+    this->_isDigestRSAVerificationActive = CK_FALSE;
+
+    this->_signature = NULL_PTR;
+    this->_decryption     = NULL_PTR;
+    this->_encryption     = NULL_PTR;
+    this->_verification   = NULL_PTR;
+
+    this->_soPIN     = NULL_PTR;
+
+    this->_accumulatedDataToSign = NULL_PTR;
+    this->_accumulatedDataToVerify = NULL_PTR;
+
+    _objects.clear();
+    _sessionObjectsReturnedInSearch.clear();
+    _tokenObjectsReturnedInSearch.clear();
+
+    if( TRUE == this->_isReadWrite )
+    {
+      this->_state = CKS_RW_PUBLIC_SESSION;
+    }
+    else
+    {
+      this->_state = CKS_RO_PUBLIC_SESSION;
+    }
+}
+
+Session::~Session(){
+
+   for(size_t i = 0; i < _objects.size(); i++)
+   {
+      if( NULL_PTR != _objects[i] )
+      {
+         delete _objects[i];
+      }
+      _objects[i] = NULL_PTR;
+   }
+
+    if(this->_digest != NULL_PTR){
+        delete this->_digest;
+    }
+
+    if(this->_digestRSA != NULL_PTR){
+        delete this->_digestRSA;
+    }
+
+    if(this->_digestRSAVerification != NULL_PTR){
+        delete this->_digestRSAVerification;
+    }
+
+    if(this->_signature != NULL_PTR){
+        delete this->_signature;
+    }
+
+    if(this->_decryption != NULL_PTR){
+        delete this->_decryption;
+    }
+
+    if(this->_encryption != NULL_PTR){
+        delete this->_encryption;
+    }
+
+    if(this->_verification != NULL_PTR){
+        delete this->_verification;
+    }
+
+    if(this->_soPIN != NULL_PTR){
+        delete this->_soPIN;
+    }
+
+    if(this->_accumulatedDataToSign != NULL_PTR){
+        delete this->_accumulatedDataToSign;
+    }
+
+    if(this->_accumulatedDataToVerify != NULL_PTR){
+        delete this->_accumulatedDataToVerify;
+    }
+}
+
+void Session::SetSearchTemplate(Template* templ)
+{
+    PKCS11_ASSERT(this->_isSearchActive == CK_FALSE);
+
+    this->_searchTempl = templ;
+    this->_isSearchActive = CK_TRUE;
+
+    _tokenObjectsReturnedInSearch.clear();
+    _sessionObjectsReturnedInSearch.clear();
+}
+
+void Session::RemoveSearchTemplate()
+{
+    if(this->_searchTempl != NULL_PTR){
+        delete this->_searchTempl;
+        this->_searchTempl = NULL_PTR;
+    }
+
+    this->_isSearchActive = CK_FALSE;
+}
+
+void Session::UpdateState(CK_ULONG roleLogged)
+{
+    if(this->_isReadWrite)
+    {
+        switch(roleLogged)
+        {
+            case CKU_NONE:
+                this->_state = CKS_RW_PUBLIC_SESSION;
+                break;
+
+            case CKU_SO:
+                this->_state = CKS_RW_SO_FUNCTIONS;
+                break;
+
+            case CKU_USER:
+                this->_state = CKS_RW_USER_FUNCTIONS;
+                break;
+        }
+    }
+    else
+    {
+        switch(roleLogged)
+        {
+            case CKU_NONE:
+                this->_state = CKS_RO_PUBLIC_SESSION;
+                break;
+
+            case CKU_USER:
+                this->_state = CKS_RO_USER_FUNCTIONS;
+                break;
+        }
+    }
+}
+
+CK_BBOOL Session::IsSearchActive()
+{
+    return this->_isSearchActive;
+}
+
+void Session::SetId(CK_ULONG id)
+{
+    this->_id = id;
+}
+
+void Session::SetSlot(Slot* slot)
+{
+    this->_slot = slot;
+}
+
+CK_ULONG Session::MakeObjectHandle(CK_ULONG idx)
+{
+     CK_ULONG objHandle = CO_SESSION_OBJECT | idx;
+     objHandle = (this->_id << 16) | objHandle;
+
+     return objHandle;
+}
+
+CK_ULONG Session::FindObjects(CK_ULONG idx,CK_OBJECT_HANDLE_PTR phObject,
+                              CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount)
+{
+
+    PKCS11_ASSERT(this->_isSearchActive);
+
+    for(CK_LONG i=0;i<static_cast<CK_LONG>(_objects.size()) && (idx < ulMaxObjectCount);i++){
+
+        if(this->_objects[i] == NULL_PTR){
+            continue;
+        }
+
+        if(this->_sessionObjectsReturnedInSearch[i] == CK_TRUE){
+            continue;
+        }
+
+         if( CK_TRUE == this->_objects[i]->_private )
+         {
+            if( false == _slot->_token->m_bIsNoPinSupported )
+            {
+               if(   ( CKU_USER != _slot->_token->_roleLogged )
+                  && ( ( true == _slot->_token->m_bIsSSO ) && ( false == _slot->_token->isAuthenticated( ) ) )
+                  )
+               {
+                  continue;
+               }
+            }
+         }
+        //if((this->_objects[i]->_private == CK_TRUE) &&
+        //    (this->_slot->_token->_roleLogged != CKU_USER))
+        //{
+        //    continue;
+        //}
+
+        if(this->_searchTempl == NULL_PTR){
+            phObject[idx++] = MakeObjectHandle(i+1);
+            *pulObjectCount = *pulObjectCount + 1;
+            this->_sessionObjectsReturnedInSearch[i] = CK_TRUE;
+        }
+        else{
+            CK_BBOOL match = CK_TRUE;
+
+            vector<CK_ATTRIBUTE> attributes = this->_searchTempl->_attributes;
+            for(CK_ULONG a=0;a<attributes.size();a++){
+                if(this->_objects[i]->Compare(attributes.at(a)) == CK_FALSE){
+                    match = CK_FALSE;
+                    break;
+                }
+            }
+
+            if(match == CK_TRUE){
+                phObject[idx++] = MakeObjectHandle(i+1);
+                *pulObjectCount = *pulObjectCount + 1;
+                this->_sessionObjectsReturnedInSearch[i] = CK_TRUE;
+            }
+
+        }
+    }
+
+    return idx;
+}
+
+CK_RV Session::AddObject(StorageObject* obj,CK_OBJECT_HANDLE_PTR phObject)
+{
+    for(CK_ULONG i = 0; i < static_cast<CK_ULONG>(_objects.size()); i++)
+    {
+        if(this->_objects[i] == NULL_PTR)
+        {
+            this->_objects[i] = obj;
+            *phObject = MakeObjectHandle(i+1);
+
+            return CKR_OK;
+        }
+    }
+
+    _objects.push_back(obj);
+
+    *phObject = MakeObjectHandle(static_cast<CK_ULONG>(_objects.size()));
+
+    return CKR_OK;
+}
+
+CK_RV Session::DeleteObject(CK_OBJECT_HANDLE hObject)
+{
+    // object handle also encodes the session to which it
+    // belongs, it is also possible to delete object of one
+    // session from other
+
+    CK_SESSION_HANDLE encodedSId = ((hObject >> 16) & 0x0000FFFF);
+
+    if ((encodedSId < 1) || (encodedSId >= _slot->_sessions.size())){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    if(this->_slot->_sessions[encodedSId] == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    // determine the index
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+    if(idx < 1 || idx > static_cast<CK_LONG>(_slot->_sessions[encodedSId]->_objects.size()))
+        return CKR_OBJECT_HANDLE_INVALID;
+
+    StorageObject* obj = this->_slot->_sessions[encodedSId]->_objects[idx-1];
+
+    if(obj == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    // if this is a readonly session and
+    // user is not logged then only public session objects
+    // can be created
+    if(this->_isReadWrite == CK_FALSE)
+    {
+        if(obj->_tokenObject)
+            return CKR_SESSION_READ_ONLY;
+    }
+
+   if( CK_TRUE == obj->_private )
+   {
+      if( false == _slot->_token->m_bIsNoPinSupported )
+      {
+         if(   ( CKU_USER != _slot->_token->_roleLogged )
+            && ( ( true == _slot->_token->m_bIsSSO ) && ( false == _slot->_token->isAuthenticated( ) ) )
+            )
+         {
+            return CKR_USER_NOT_LOGGED_IN;
+         }
+      }
+   }
+    //if ((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+    //    return CKR_USER_NOT_LOGGED_IN;
+    //}
+
+    delete obj;
+
+    this->_slot->_sessions[encodedSId]->_objects[idx-1] = NULL_PTR;
+
+    return CKR_OK;
+}
+
+CK_RV Session::GetAttributeValue(CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount)
+{
+    CK_RV rv  = CKR_OK;
+    CK_RV arv = CKR_OK;
+
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+    //  lets see if the object handle provided is a correct handle or not
+    if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || (this->_objects[idx-1] == NULL_PTR)){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    StorageObject* obj = this->_objects[idx-1];
+
+   if( CK_TRUE == obj->_private )
+   {
+      if( false == _slot->_token->m_bIsNoPinSupported )
+      {
+         if(   ( CKU_USER != _slot->_token->_roleLogged )
+            && ( ( true == _slot->_token->m_bIsSSO ) && ( false == _slot->_token->isAuthenticated( ) ) )
+            )
+         {
+            for(u4 i=0;i<ulCount;i++)
+            {
+               pTemplate[i].ulValueLen = (CK_ULONG)-1;
+            }
+            return CKR_USER_NOT_LOGGED_IN;
+         }
+      }
+   }
+   //if((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE))
+   // {
+   //     for(u4 i=0;i<ulCount;i++){
+   //         pTemplate[i].ulValueLen = (CK_ULONG)-1;
+   //     }
+   //     return CKR_USER_NOT_LOGGED_IN;
+   // }
+
+    for(u4 i=0;i<ulCount;i++){
+        rv = obj->GetAttribute(&pTemplate[i]);
+        if(rv != CKR_OK){
+            arv = rv;
+        }
+    }
+
+    return arv;
+}
+
+CK_RV Session::SetAttributeValue(CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount)
+{
+    CK_RV rv  = CKR_OK;
+    CK_RV arv = CKR_OK;
+
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+    //  lets see if the object handle provided is a correct handle or not
+    if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || (this->_objects[idx-1] == NULL_PTR)){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    StorageObject* obj = this->_objects[idx-1];
+
+   if( CK_TRUE == obj->_private )
+   {
+      if( false == _slot->_token->m_bIsNoPinSupported )
+      {
+         if(   ( CKU_USER != _slot->_token->_roleLogged )
+            && ( ( true == _slot->_token->m_bIsSSO ) && ( false == _slot->_token->isAuthenticated( ) ) )
+            )
+         {
+            return CKR_USER_NOT_LOGGED_IN;
+         }
+      }
+   }
+    //if ((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+    //    return CKR_USER_NOT_LOGGED_IN;
+    //}
+
+    for(u4 i=0;i<ulCount;i++){
+        rv = obj->SetAttribute(pTemplate[i],CK_FALSE);
+        if(rv != CKR_OK){
+            arv = rv;
+        }
+    }
+
+    return arv;
+}
+
+void Session::SetDigest(CDigest *digest)
+{
+    this->_digest = digest;
+    this->_isDigestActive = CK_TRUE;
+}
+
+void Session::RemoveDigest()
+{
+    if(this->_digest != NULL_PTR){
+        delete this->_digest;
+        this->_digest = NULL_PTR;
+    }
+
+    this->_isDigestActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestActive()
+{
+    return this->_isDigestActive;
+}
+
+void Session::SetDigestRSA(CDigest *digest)
+{
+    this->_digestRSA = digest;
+    this->_isDigestRSAActive = CK_TRUE;
+}
+
+void Session::RemoveDigestRSA()
+{
+    if(this->_digestRSA != NULL_PTR){
+        delete this->_digestRSA;
+        this->_digestRSA = NULL_PTR;
+    }
+
+    this->_isDigestRSAActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestRSAActive()
+{
+    return this->_isDigestRSAActive;
+}
+
+void Session::SetDigestRSAVerification(CDigest *digest)
+{
+    this->_digestRSAVerification = digest;
+    this->_isDigestRSAVerificationActive = CK_TRUE;
+}
+
+void Session::RemoveDigestRSAVerification()
+{
+    if(this->_digestRSAVerification != NULL_PTR){
+        delete this->_digestRSAVerification;
+        this->_digestRSAVerification = NULL_PTR;
+    }
+
+    this->_isDigestRSAVerificationActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestRSAVerificationActive()
+{
+    return this->_isDigestRSAVerificationActive;
+}
+
+CK_RV Session::GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object)
+{
+    if(hObject == 0){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    CK_SESSION_HANDLE encodedSId = ((hObject >> 16) & 0x0000FFFF);
+
+    if ((encodedSId < 1) || (encodedSId >= _slot->_sessions.size())){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    if(this->_slot->_sessions[encodedSId] == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    // determine the index
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+    StorageObject* obj = this->_slot->_sessions[encodedSId]->_objects[idx-1];
+
+    if(obj == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    *object = obj;
+
+    return CKR_OK;
+}
+
+void Session::SetEncryptionOperation(CryptoOperation *encryption)
+{
+    this->_encryption = encryption;
+}
+
+void Session::RemoveEncryptionOperation()
+{
+    if(this->_encryption != NULL_PTR){
+        delete this->_encryption;
+    }
+
+    this->_encryption = NULL_PTR;
+}
+
+CK_BBOOL Session::IsEncryptionActive(){
+
+   return (this->_encryption != NULL_PTR);
+}
+
+void Session::SetVerificationOperation(CryptoOperation *verification)
+{
+    this->_verification = verification;
+}
+
+void Session::RemoveVerificationOperation()
+{
+    if(this->_verification != NULL_PTR){
+        delete this->_verification;
+    }
+
+    this->_verification = NULL_PTR;
+}
+
+CK_BBOOL Session::IsVerificationActive(){
+
+   return (this->_verification != NULL_PTR);
+}
+
+void Session::SetDecryptionOperation(CryptoOperation *decryption)
+{
+    this->_decryption = decryption;
+}
+
+void Session::RemoveDecryptionOperation()
+{
+    if(this->_decryption != NULL_PTR){
+        delete this->_decryption;
+    }
+
+    this->_decryption = NULL_PTR;
+}
+
+CK_BBOOL Session::IsDecryptionActive(){
+
+   return (this->_decryption != NULL_PTR);
+}
+
+void Session::SetSignatureOperation(CryptoOperation* signature)
+{
+    this->_signature = signature;
+}
+
+void Session::RemoveSignatureOperation()
+{
+    if(this->_signature != NULL_PTR){
+        delete this->_signature;
+    }
+
+    this->_signature = NULL_PTR;
+}
+
+CK_BBOOL Session::IsSignatureActive(){
+
+    return (this->_signature != NULL_PTR);
+
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/session.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/session.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/session.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,144 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_session_h
+#define _include_session_h
+
+#include "template.h"
+#include "digest.h"
+#include "storageobject.h"
+#include <map>
+
+class Slot;
+
+class CryptoOperation{
+    CK_ULONG            _mechanism;
+    StorageObject*      _object;
+
+public:
+    CryptoOperation(CK_ULONG mechanism,StorageObject* obj){
+        this->_mechanism = mechanism;
+        this->_object = obj;
+    }
+
+    ~CryptoOperation(){}
+
+public:
+    CK_ULONG    GetMechanism() { return this->_mechanism;}
+    StorageObject* GetObject() { return this->_object;}
+};
+
+class Session{
+
+public:
+    CK_BBOOL                _isReadWrite;
+    CK_ULONG                _state;
+    vector<StorageObject*>  _objects;
+    Template*               _searchTempl;
+    CDigest*                _digest;
+    CDigest*                _digestRSA;
+    CDigest*                _digestRSAVerification;
+
+    map<CK_ULONG, bool>     _sessionObjectsReturnedInSearch;
+    map<CK_ULONG, bool>     _tokenObjectsReturnedInSearch;
+
+    CryptoOperation*         _signature;
+    CryptoOperation*         _decryption;
+    CryptoOperation*         _verification;
+    CryptoOperation*         _encryption;
+
+    CK_BBOOL                _isSearchActive;
+    CK_BBOOL                _isDigestActive;
+    CK_BBOOL                _isDigestRSAActive;
+    CK_BBOOL                _isDigestRSAVerificationActive;
+
+    CK_ULONG                _id;
+    Slot*                   _slot;
+
+    u1Array*                _accumulatedDataToSign;
+    u1Array*                _accumulatedDataToVerify;
+
+
+    // Looks scary huh, the problem is that CardModule interface require
+    // cryptogram as part of ChangeReferenceData method whereas
+    // PKCS#11 first log SO in and then call InitPIN. InitPIN does not have any
+    // information about SO PIN so what we do here is to cache it momentarily.
+    // Basically during Login (as SO) we cache it and destroy it during closing
+    // of session
+    u1Array*                _soPIN;
+
+public:
+    Session(CK_BBOOL isReadWrite);
+    ~Session();
+
+    void SetSearchTemplate(Template* templ);
+    void RemoveSearchTemplate();
+
+    void SetDigest(CDigest* digest);
+    void RemoveDigest();
+
+    void SetEncryptionOperation(CryptoOperation* encryption);
+    void RemoveEncryptionOperation();
+    CK_BBOOL IsEncryptionActive();
+
+    void SetVerificationOperation(CryptoOperation* verification);
+    void RemoveVerificationOperation();
+    CK_BBOOL IsVerificationActive();
+
+    void SetDecryptionOperation(CryptoOperation* decryption);
+    void RemoveDecryptionOperation();
+    CK_BBOOL IsDecryptionActive();
+
+    void SetSignatureOperation(CryptoOperation* signature);
+    void RemoveSignatureOperation();
+    CK_BBOOL IsSignatureActive();
+
+    void SetDigestRSA(CDigest* digest);
+    void RemoveDigestRSA();
+
+    void SetDigestRSAVerification(CDigest* digest);
+    void RemoveDigestRSAVerification();
+
+    void UpdateState(CK_ULONG roleLogged);
+    CK_BBOOL IsSearchActive();
+    CK_BBOOL IsDigestActive();
+    CK_BBOOL IsDigestRSAActive();
+    CK_BBOOL IsDigestRSAVerificationActive();
+
+    CK_RV AddObject(StorageObject* object,CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV DeleteObject(CK_OBJECT_HANDLE hObject);
+
+    CK_ULONG FindObjects(CK_ULONG idx,CK_OBJECT_HANDLE_PTR phObject,
+                         CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount);
+
+	CK_RV GetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    CK_RV SetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+
+    void SetId(CK_ULONG id);
+    void SetSlot(Slot* slot);
+
+    CK_RV GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object);
+
+private:
+    CK_ULONG MakeObjectHandle(CK_ULONG idx);
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,73 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "sha1.h"
+
+CSHA1::CSHA1(){
+    this->_hashValue     = (CK_BYTE_PTR)malloc(SHA1_HASH_LENGTH);
+    this->_workingBuffer = (CK_BYTE_PTR)malloc(SHA1_BLOCK_LENGTH);
+    this->_hashLength    = SHA1_HASH_LENGTH;
+    this->_blockLength   = SHA1_BLOCK_LENGTH;
+}
+
+CSHA1::~CSHA1(){
+}
+
+void CSHA1::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha1_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha1_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    algo_sha1_update(&ctx, data, SHA1_BLOCK_LENGTH);
+}
+
+void CSHA1::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha1_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha1_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    ctx.input = (u1*)malloc(SHA1_BLOCK_LENGTH);
+    memset(ctx.input,0,SHA1_BLOCK_LENGTH);
+
+    algo_sha1_update(&ctx, data, length);
+    algo_sha1_finish(&ctx);
+
+    free(ctx.input);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/sha1.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_sha1_h
+#define _include_sha1_h
+
+#include "MarshallerCfg.h"
+#include "algo_sha1.h"
+
+class CSHA1 : public CDigest
+{
+private:
+    void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+    void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+    CSHA1();
+    ~CSHA1();
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,78 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "sha256.h"
+
+CSHA256::CSHA256(){
+    this->_hashValue     = (CK_BYTE_PTR)malloc(SHA256_HASH_LENGTH);
+    this->_workingBuffer = (CK_BYTE_PTR)malloc(SHA256_BLOCK_LENGTH);
+    this->_hashLength    = SHA256_HASH_LENGTH;
+    this->_blockLength   = SHA256_BLOCK_LENGTH;
+}
+
+CSHA256::~CSHA256(){
+}
+
+void CSHA256::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha256_context* ctx = (algo_sha256_context*)malloc(sizeof(algo_sha256_context));
+
+    ctx->digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha256_starts(ctx);
+    } else {
+        ctx->total[0] = counter;
+        ctx->total[1] = 0;
+    }
+
+    algo_sha256_update(ctx, data, SHA256_BLOCK_LENGTH);
+
+    free((u1*)ctx);
+}
+
+void CSHA256::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha256_context* ctx = (algo_sha256_context*)malloc(sizeof(algo_sha256_context));
+
+    ctx->digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha256_starts(ctx);
+    } else {
+        ctx->total[0] = counter;
+        ctx->total[1] = 0;
+    }
+
+    // allocate tempory working buffer
+    ctx->input = (u1*)malloc(SHA256_BLOCK_LENGTH);
+    memset(ctx->input, 0,SHA256_BLOCK_LENGTH);
+
+    // warning: algo_sha1_update must not throw any exception.
+    algo_sha256_update(ctx, data, length);
+    algo_sha256_finish(ctx);
+
+    free(ctx->input);
+    free((u1*)ctx);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/sha256.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_sha256_h
+#define _include_sha256_h
+
+#include "MarshallerCfg.h"
+#include "algo_sha256.h"
+
+class CSHA256 : public CDigest
+{
+private:
+    void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+    void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+    CSHA256();
+    ~CSHA256();
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/slot.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/slot.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/slot.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,2949 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+#include "cardmoduleservice.h"
+
+#include <assert.h>
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "template.h"
+#include "digest.h"
+#include "sha1.h"
+#include "sha256.h"
+#include "md5.h"
+#include "session.h"
+#include "slot.h"
+#include "dataobject.h"
+#include "secretkeyobject.h"
+#include "rsaprivatekeyobject.h"
+#include "rsapublickeyobject.h"
+#include "x509pubkeycertobject.h"
+#include "application.h"
+#include "transaction.h"
+#include "log.h"
+#include "error.h"
+
+#ifdef _XCL_
+#include "xcl_utils.h"
+#endif // _XCL_
+
+CK_MECHANISM_TYPE MechanismList[] = {
+   CKM_RSA_PKCS_KEY_PAIR_GEN, // 0
+   CKM_RSA_PKCS,              // 1
+   CKM_RSA_X_509,             // 2
+   CKM_MD5_RSA_PKCS,          // 3
+   CKM_SHA1_RSA_PKCS,         // 4
+   CKM_SHA256_RSA_PKCS,       // 5
+#ifdef ENABLE_DIGEST
+   CKM_MD5,                   // 6
+   CKM_SHA_1,                 // 7
+   CKM_SHA256,                // 8
+#endif
+#ifdef ENABLE_SYMMETRIC
+   CKM_AES_KEY_GEN,           // 9
+   CKM_AES_ECB,               // 10
+   CKM_AES_CBC,               // 11
+   CKM_AES_CBC_PAD,           // 12
+   CKM_DES_KEY_GEN,           // 13
+   CKM_DES_ECB,               // 14
+   CKM_DES_CBC,               // 15
+   CKM_DES_CBC_PAD,           // 16
+   CKM_DES2_KEY_GEN,          // 17
+   CKM_DES3_KEY_GEN,          // 18
+   CKM_DES3_ECB,              // 19
+   CKM_DES3_CBC,              // 20
+   CKM_DES3_CBC_PAD           // 21
+#endif
+};
+
+CK_MECHANISM_INFO MechanismInfo[] = {
+   {/* 0 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_GENERATE_KEY_PAIR},
+#ifdef ENABLE_SYMMETRIC
+   {/* 1 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP},
+   {/* 2 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP},
+#else
+   {/* 1 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | /*CKF_SIGN_RECOVER |*/ CKF_VERIFY /*| CKF_VERIFY_RECOVER*/},
+   {/* 2 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | /*CKF_SIGN_RECOVER |*/ CKF_VERIFY /*| CKF_VERIFY_RECOVER*/},
+#endif
+   {/* 3 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+   {/* 4 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+   {/* 5 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+#ifdef ENABLE_DIGEST
+   {/* 6 */  0,0, CKF_SW | CKF_DIGEST},
+   {/* 7 */  0,0, CKF_SW | CKF_DIGEST},
+   {/* 8 */  0,0, CKF_SW | CKF_DIGEST},
+#endif
+#ifdef ENABLE_SYMMETRIC
+   {/* 9 */  16,32, CKF_HW | CKF_GENERATE},
+   {/* 10 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 11 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 12 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 13 */  0,0, CKF_HW | CKF_GENERATE},
+   {/* 14 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 15 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 16 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 17 */  0,0, CKF_HW | CKF_GENERATE},
+   {/* 18 */  0,0, CKF_HW | CKF_GENERATE},
+   {/* 19 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 20 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 21 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}
+#endif
+};
+
+#define MAKE_SESSIONHANDLE(H,S)         (H | (S << 24))
+#define GET_SESSIONID(H)                (H & 0x00FFFFFF)
+#define GET_SLOTID(H)                   ((H & 0xFF000000) >> 24)
+
+//#define CHECK_IF_NULL_SESSION(A,S)      if(A->_sessions[S] == NULL_PTR){return CKR_SESSION_HANDLE_INVALID;}
+#define CHECK_IF_NULL_SESSION(A,S) try \
+   { \
+      if( A->_sessions.at( S ) == NULL_PTR ) \
+      { \
+         return CKR_SESSION_HANDLE_INVALID; \
+      } \
+   } \
+   catch( ... ) \
+   { \
+      return CKR_SESSION_HANDLE_INVALID; \
+   } \
+
+#define CHECK_IF_TOKEN_IS_PRESENT(S)    if(S->_token == NULL_PTR){return CKR_TOKEN_NOT_PRESENT;}
+
+Slot::Slot()
+{
+   // initialize the fields
+
+   CK_ULONG idx;
+
+   this->_token = NULL_PTR;
+   this->_readerName = NULL_PTR;
+
+   _sessions.resize(1,NULL_PTR);   // First element is dummy
+
+   // initialize this slot
+   this->_slotId = 0;
+   this->_slotInfo.firmwareVersion.major = 0;
+   this->_slotInfo.firmwareVersion.minor = 0;
+   this->_slotInfo.flags                 = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
+   this->_slotInfo.hardwareVersion.major = 0;
+   this->_slotInfo.hardwareVersion.minor = 0;
+
+   for(idx=0;idx<64;idx++)
+      this->_slotInfo.slotDescription[idx] = ' ';
+
+   this->_slotInfo.manufacturerID[0] = 'U';
+   this->_slotInfo.manufacturerID[1] = 'n';
+   this->_slotInfo.manufacturerID[2] = 'k';
+   this->_slotInfo.manufacturerID[3] = 'n';
+   this->_slotInfo.manufacturerID[4] = 'o';
+   this->_slotInfo.manufacturerID[5] = 'w';
+   this->_slotInfo.manufacturerID[6] = 'n';
+
+   for(idx=7;idx<32;idx++){
+      this->_slotInfo.manufacturerID[idx] = ' ';
+   }
+
+#ifdef INCLUDE_EVENTING
+   this->_tracker = NULL_PTR;
+   this->_event   = CK_FALSE;
+#endif
+
+}
+
+Slot::~Slot( )
+{
+   Log::begin( "Slot::~Slot" );
+
+   if(this->_token != NULL_PTR)
+   {
+      delete this->_token;
+      this->_token = NULL_PTR;
+   }
+
+#ifdef INCLUDE_EVENTING
+   if(this->_tracker != NULL_PTR)
+   {
+      delete this->_tracker;
+      this->_tracker = NULL_PTR;
+   }
+#endif
+
+   if(this->_readerName != NULL_PTR)
+   {
+      delete this->_readerName;
+      this->_readerName = NULL_PTR;
+   }
+
+   // destroy all opened sessions
+   for(size_t i=1;i<_sessions.size();i++)
+   {
+      if( this->_sessions[i] != NULL_PTR)
+      {
+         delete this->_sessions[i];
+         this->_sessions[i] = NULL_PTR;
+      }
+   }
+
+   Log::end( "Slot::~Slot" );
+}
+
+
+#ifdef INCLUDE_EVENTING
+
+void Slot::SetEvent(CK_BBOOL event)
+{
+   this->_event = event;
+}
+
+CK_BBOOL Slot::GetEvent()
+{
+   return this->_event;
+}
+
+void Slot::Clear()
+{
+   // close all the sessions when card is removed
+   this->CloseAllSessions();
+
+   if(this->_token != NULL_PTR)
+   {
+      delete this->_token;
+      this->_token = NULL_PTR;
+   }
+}
+
+#endif
+
+CK_RV Slot::GetInfo(CK_SLOT_INFO_PTR pInfo)
+{
+   CK_BYTE idx;
+
+   // Check Parameters
+   if(pInfo == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   for(idx=0;idx<64;idx++)
+   {
+      pInfo->slotDescription[idx] = this->_slotInfo.slotDescription[idx];
+   }
+
+   for(idx=0;idx<32;idx++)
+   {
+      pInfo->manufacturerID[idx]  = this->_slotInfo.manufacturerID[idx];
+   }
+
+   pInfo->hardwareVersion.major = this->_slotInfo.hardwareVersion.major;
+   pInfo->hardwareVersion.minor = this->_slotInfo.hardwareVersion.minor;
+   pInfo->firmwareVersion.major = this->_slotInfo.firmwareVersion.major;
+   pInfo->firmwareVersion.minor = this->_slotInfo.firmwareVersion.minor;
+
+   // it turns out that we need to dynamically poll if
+   // token is present or not. rest of the information should not
+   // change since we enumerated
+   SCARD_READERSTATE readerStates;
+
+   readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+   readerStates.szReader = this->_readerName->c_str();
+
+   // lets check if token is present
+#ifndef _XCL_
+
+   if (SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+   {
+      if ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+      {
+         // we found a card in this reader
+         this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+      }
+      else
+      {
+         // No card in reader
+         this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+         CloseAllSessions();
+      }
+   }
+
+#else // _XCL_
+
+    PRINT_MSG("IN Slot::GetInfo");
+    if (xCL_IsTokenPresent())
+    {
+        // we found a card in this reader
+        this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+    }
+    else
+    {
+        // No card in reader
+        this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+    }
+
+#endif // _XCL_
+
+   pInfo->flags = this->_slotInfo.flags;
+
+   return CKR_OK;
+}
+
+
+CK_RV Slot::GetTokenInfo( CK_TOKEN_INFO_PTR pInfo )
+{
+   Log::begin( "Slot::GetTokenInfo" );
+
+   checkConnection( this );
+
+   // Check Parameters
+   if( NULL_PTR == pInfo )
+   {
+      Log::error( "Slot::GetTokenInfo", "CKR_ARGUMENTS_BAD" );
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   //Log::log( "Slot::GetTokenInfo - BuildToken..." );
+   //printf( "\n Slot::GetTokenInfo - BuildToken \n" );
+   CK_RV rv = this->BuildToken( );
+   //Log::log( "Slot::GetTokenInfo - BuildToken <%#02x>", rv );
+   if( CKR_OK == rv )
+   {
+      //Transaction trans( this );
+
+      Log::log( "Slot::GetTokenInfo - 1" );
+
+      CK_BYTE idx;
+
+      pInfo->firmwareVersion.major = this->_token->_tokenInfo.firmwareVersion.major;
+      pInfo->firmwareVersion.minor = this->_token->_tokenInfo.firmwareVersion.minor;
+      pInfo->hardwareVersion.major = this->_token->_tokenInfo.hardwareVersion.major;
+      pInfo->hardwareVersion.minor = this->_token->_tokenInfo.hardwareVersion.minor;
+
+      Log::log( "Slot::GetTokenInfo - 2" );
+
+      // label
+      for(idx=0;idx<32;idx++)
+      {
+         pInfo->label[idx] = this->_token->_tokenInfo.label[idx];
+      }
+      Log::log( "Slot::GetTokenInfo - 3" );
+
+      // manufacturerID
+      for(idx=0;idx<32;idx++)
+      {
+         pInfo->manufacturerID[idx]  = this->_token->_tokenInfo.manufacturerID[idx];
+      }
+      Log::log( "Slot::GetTokenInfo - 4" );
+
+      // model
+      for(idx=0;idx<16;idx++)
+      {
+         pInfo->model[idx]  = this->_token->_tokenInfo.model[idx];
+      }
+      Log::log( "Slot::GetTokenInfo - 5" );
+
+      // serial number
+      for(idx=0;idx<16;idx++)
+      {
+         pInfo->serialNumber[idx]  = this->_token->_tokenInfo.serialNumber[idx];
+      }
+      Log::log( "Slot::GetTokenInfo - 6" );
+
+      pInfo->ulFreePrivateMemory  = this->_token->_tokenInfo.ulFreePrivateMemory;
+      pInfo->ulFreePublicMemory   = this->_token->_tokenInfo.ulFreePublicMemory;
+      pInfo->ulMaxPinLen          = this->_token->_tokenInfo.ulMaxPinLen;
+      pInfo->ulMinPinLen          = this->_token->_tokenInfo.ulMinPinLen;
+      pInfo->ulMaxRwSessionCount  = CK_EFFECTIVELY_INFINITE;
+      pInfo->ulSessionCount       = 0;
+      pInfo->ulMaxSessionCount    = CK_EFFECTIVELY_INFINITE;
+      pInfo->ulRwSessionCount     = 0;
+      pInfo->ulTotalPrivateMemory = this->_token->_tokenInfo.ulTotalPrivateMemory;
+      pInfo->ulTotalPublicMemory  = this->_token->_tokenInfo.ulTotalPublicMemory;
+
+      Log::log( "Slot::GetTokenInfo - 7" );
+
+      for(size_t i=1;i<_sessions.size();i++)
+      {
+         if( NULL_PTR != _sessions[ i ] )
+         {
+            ++pInfo->ulSessionCount;
+            if(_sessions[i]->_isReadWrite)
+               ++pInfo->ulRwSessionCount;
+         }
+      }
+      Log::log( "Slot::GetTokenInfo - 8" );
+
+      // utcTime
+      for(idx=0;idx<16;idx++)
+      {
+         pInfo->utcTime[idx]  = this->_token->_tokenInfo.utcTime[idx];
+      }
+      Log::log( "Slot::GetTokenInfo - 9" );
+
+      bool bIsAuthenticated = this->_token->isAuthenticated( );
+      Log::log( "Slot::GetTokenInfo - IsNoPinSupported <%d>", this->_token->m_bIsNoPinSupported );
+      Log::log( "Slot::GetTokenInfo - IsSSO <%d>", this->_token->m_bIsSSO );
+      Log::log( "Slot::GetTokenInfo - IsAuthenticated <%d>", bIsAuthenticated );
+
+      // Check if the smart card is in SSO mode
+      if(   ( true == this->_token->m_bIsNoPinSupported ) 
+         || ( ( true == this->_token->m_bIsSSO ) && ( true == bIsAuthenticated ) )
+         )
+      {
+         this->_token->_tokenInfo.flags &= ~CKF_LOGIN_REQUIRED;
+         Log::log( "Slot::GetTokenInfo - No login required" );
+      }
+      else
+      {
+         this->_token->_tokenInfo.flags |= CKF_LOGIN_REQUIRED;
+         Log::log( "Slot::GetTokenInfo - Login required" );
+      }
+      pInfo->flags = this->_token->_tokenInfo.flags;
+      //Log::log( "Slot::GetTokenInfo - tokenInfo formated ok" );
+   }
+
+   //Log::logCK_RV( "Slot::GetTokenInfo", rv );
+   Log::end( "Slot::GetTokenInfo" );
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::GetMechanismList(CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount)
+{
+   if(pulCount == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(pMechanismList == NULL_PTR)
+   {
+      *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+   }
+   else
+   {
+      if(*pulCount < (sizeof(MechanismList)/sizeof(CK_ULONG)))
+      {
+         *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+         return CKR_BUFFER_TOO_SMALL;
+      }
+
+      for(size_t i=0;i<(sizeof(MechanismList)/sizeof(CK_ULONG));i++)
+      {
+         pMechanismList[i] = MechanismList[i];
+      }
+      *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+   }
+
+   return CKR_OK;
+}
+
+
+/*
+*/
+CK_RV Slot::GetMechanismInfo(CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo)
+{
+   if(pInfo == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   size_t i = 0;
+   CK_BBOOL found = CK_FALSE;
+   for( ;i<(sizeof(MechanismList)/sizeof(CK_ULONG));i++)
+   {
+      if(MechanismList[i] == type)
+      {
+         found = CK_TRUE;
+         break;
+      }
+   }
+
+   if(found == CK_FALSE)
+   {
+      return CKR_MECHANISM_INVALID;
+   }
+
+   pInfo->ulMinKeySize = MechanismInfo[i].ulMinKeySize;
+   pInfo->ulMaxKeySize = MechanismInfo[i].ulMaxKeySize;
+   pInfo->flags  = MechanismInfo[i].flags;
+
+   return CKR_OK;
+}
+
+
+CK_RV Slot::InitToken(CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel)
+{
+   CK_RV rv = CKR_OK;
+
+   checkConnection( this );
+
+   if(pPin == NULL_PTR || ulPinLen == 0 || pLabel == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   // check if we have an open session
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] != NULL_PTR){
+         return CKR_SESSION_EXISTS;
+      }
+   }
+
+   //printf( "\n Slot::InitToken - BuildToken \n" );
+   rv = this->BuildToken();
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   u1Array* pin = new u1Array(ulPinLen);
+   pin->SetBuffer(pPin);
+
+   u1Array* label = new u1Array(32);
+   label->SetBuffer(pLabel);
+
+   // Don't do the Transaction here.
+
+   rv = this->_token->InitToken(pin,label);
+
+   delete pin;
+   delete label;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::OpenSession( CK_FLAGS flags, CK_VOID_PTR, CK_NOTIFY, CK_SESSION_HANDLE_PTR phSession )
+{
+   checkConnection( this );
+
+   if(phSession == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if( ( flags & CKF_SERIAL_SESSION ) != CKF_SERIAL_SESSION )
+   {
+      return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+   }
+
+   //printf( "\n Slot::OpenSession - BuildToken \n" );
+   CK_RV rv = this->BuildToken( );
+   if( rv != CKR_OK )
+   {
+      return rv;
+   }
+
+   Transaction trans( this );
+
+   // if admin is logged we can not open RO session
+   CK_BBOOL rwSession = ((flags & CKF_RW_SESSION) == CKF_RW_SESSION);
+
+   if( ( this->_token->_roleLogged == CKU_SO ) && ( !rwSession ) )
+   {
+      return CKR_SESSION_READ_WRITE_SO_EXISTS;
+   }
+
+   // Create the session instance
+   Session* session = new Session( rwSession );
+
+   // lets create a session
+   s4 sessionId = this->AddSession( session );
+   if( 0 == sessionId )
+   {
+      return CKR_SESSION_COUNT;
+   }
+
+   session->SetId(sessionId);
+   session->SetSlot(this);
+
+    // prepare a unique session id
+   *phSession = MAKE_SESSIONHANDLE(sessionId,this->_slotId);
+
+   // Refresh the state of the session if the SSO mode is enabled or No pin is required
+   //UpdateAuthenticationState( );
+   if(   ( CKU_USER == this->_token->_roleLogged )
+      || ( true == this->_token->m_bIsNoPinSupported ) 
+      || ( ( true == this->_token->m_bIsSSO ) && ( true == this->_token->isAuthenticated( ) ) )
+      )
+   {
+      UpdateSessionState( CKU_USER );
+   }
+   else if( CKU_SO == this->_token->_roleLogged )
+   {
+      UpdateSessionState( CKU_SO );
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::CloseSession( CK_SESSION_HANDLE hSession )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if( CKR_OK == rv )
+   {
+      CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+      CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+
+      pSlot->RemoveSession( hSessionId );
+
+      // Refresh the state of the session if the SSO mode is enabled
+      //pSlot->UpdateAuthenticationState( );
+   }
+
+   return rv;
+}
+
+
+///*
+//Check first if the card is in SSO mode then update the state of all sessions
+//*/
+//void Slot::UpdateAuthenticationState( void )
+//{
+//   if(   ( true == this->_token->_roleLogged )
+//      || ( true == this->_token->m_bIsNoPinSupported ) 
+//      || ( ( true == this->_token->m_bIsSSO ) && ( true == this->_token->isAuthenticated( ) ) )
+//      )
+//   {
+//      UpdateSessionState( CKU_USER );
+//   }
+//}
+
+
+/*
+*/
+CK_RV Slot::CloseAllSessions(void)
+{
+   //if( NULL != this->_token )
+   //{
+   //   this->_token->ManageGC( true );
+   //}
+
+   // remove all sessions
+   for( size_t i = 1 ; i < _sessions.size( ) ; i++ )
+   {
+      if( NULL_PTR != this->_sessions[ i ] )
+      {
+         delete this->_sessions[ i ];
+         this->_sessions[ i ] = NULL_PTR;
+      }
+      //this->_sessions[ i ] = NULL_PTR;
+   }
+
+   _sessions.resize( 1 );
+
+   CHECK_IF_TOKEN_IS_PRESENT( this );
+
+   this->_token->_roleLogged = CKU_NONE;
+
+   //// Refresh the state of the session if the SSO mode is enabled
+   //UpdateAuthenticationState( );
+   //// Update the state of all sessions
+   //UpdateSessionState( );
+
+   return CKR_OK;
+}
+
+
+/*
+*/
+CK_RV Slot::GetSessionInfo( CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if( CKR_OK != rv )
+   {
+      return rv;
+   }
+
+   if(pInfo == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId);
+
+   // JCD
+   //Transaction trans( pSlot );
+
+   pInfo->slotID = pSlot->_slotId;
+   pInfo->ulDeviceError = CKR_OK;
+
+   // JCD
+   // Check if the smart card is in SSO mode
+   //pSlot->UpdateAuthenticationState( );
+
+   pInfo->flags = ( ( pSlot->_sessions[ hSessionId ]->_isReadWrite ) ? CKF_RW_SESSION : 0 ) | (CKF_SERIAL_SESSION);
+   pInfo->state = pSlot->_sessions[ hSessionId ]->_state;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Login( CK_SESSION_HANDLE hSession,
+                   CK_USER_TYPE userType,
+                   CK_UTF8CHAR_PTR pPin,
+                   CK_ULONG ulPinLen )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+
+   if( true == pSlot->_token->m_bIsNoPinSupported )
+   {
+      return CKR_OK; //CKR_USER_ALREADY_LOGGED_IN;
+   }
+   if( ( true == pSlot->_token->m_bIsSSO ) && ( true == pSlot->_token->isAuthenticated( ) ) )
+   {
+      return CKR_USER_ALREADY_LOGGED_IN;
+   }
+
+   Transaction trans( pSlot );
+
+   if(userType == CKU_SO)
+   {
+      if(pSlot->HasReadOnlySession())
+      {
+         return CKR_SESSION_READ_ONLY_EXISTS;
+      }
+   }
+
+   if( NULL_PTR == pPin )
+   {
+      ulPinLen = 0;
+   }
+
+   u1Array* pinValue = new u1Array(ulPinLen);
+   u1* pinValueBuffer = pinValue->GetBuffer();
+   CK_BYTE idx = 0;
+   for(idx=0;idx<ulPinLen;idx++)
+   {
+      pinValueBuffer[idx] = pPin[idx];
+   }
+   rv = pSlot->_token->Login(userType,pinValue);
+
+   if(rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
+   {
+      if(userType == CKU_SO)
+      {
+         // cache SO PIN for the duration of this session
+         pSlot->_sessions[ hSessionId ]->_soPIN = new u1Array(pinValue->GetLength());
+         pSlot->_sessions[ hSessionId ]->_soPIN->SetBuffer(pinValue->GetBuffer());
+      }
+   }
+
+   if(rv == CKR_OK)
+   {
+      pSlot->UpdateSessionState();
+   }
+
+   delete pinValue;
+
+   return rv;
+}
+
+
+
+CK_RV Slot::Logout( CK_SESSION_HANDLE hSession )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   rv = pSlot->_token->Logout( );
+
+   pSlot->UpdateSessionState( );
+
+   return rv;
+}
+
+
+CK_RV Slot::InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if(pPin == NULL_PTR || ulPinLen == 0){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->_state != CKS_RW_SO_FUNCTIONS)
+   {
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   PKCS11_ASSERT(session->_soPIN != NULL_PTR);
+
+   u1Array* pin = new u1Array(ulPinLen);
+   pin->SetBuffer(pPin);
+
+   rv = pSlot->_token->InitPIN(session->_soPIN,pin);
+
+   delete pin;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SetPIN( CK_SESSION_HANDLE hSession,
+                    CK_UTF8CHAR_PTR pOldPin,
+                    CK_ULONG ulOldLen,
+                    CK_UTF8CHAR_PTR pNewPin,
+                    CK_ULONG ulNewLen )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   if(pOldPin == NULL_PTR || ulOldLen == 0 || pNewPin == NULL_PTR || ulNewLen == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   CK_ULONG state = pSlot->_sessions[ hSessionId ]->_state;
+
+   if((state != CKS_RW_PUBLIC_SESSION) &&
+      (state != CKS_RW_SO_FUNCTIONS)&&
+      (state != CKS_RW_USER_FUNCTIONS))
+   {
+      return CKR_SESSION_READ_ONLY;
+   }
+
+   u1Array* oldPin = new u1Array(ulOldLen);
+   oldPin->SetBuffer(pOldPin);
+
+   u1Array* newPin = new u1Array(ulNewLen);
+   newPin->SetBuffer(pNewPin);
+
+   rv = pSlot->_token->SetPIN(oldPin,newPin);
+
+   delete oldPin;
+   delete newPin;
+
+   return rv;
+}
+
+
+CK_RV  Slot::FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   
+   Transaction trans( pSlot );
+
+   if((pTemplate == NULL_PTR) && (ulCount != 0))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // check if search is active for this session or not
+   if(session->IsSearchActive() == CK_TRUE)
+   {
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   Template* searchTmpl = NULL_PTR;
+   if(ulCount != 0)
+   {
+      searchTmpl = new Template(pTemplate,ulCount);
+   }
+
+   session->SetSearchTemplate(searchTmpl);
+
+   return rv;
+}
+
+
+
+CK_RV  Slot::FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+                         CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   if((phObject == NULL_PTR) || (pulObjectCount == NULL_PTR))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+
+   // Not needed here...
+   // JCD 1
+   //Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // check if search is active for this session or not
+   if(session->IsSearchActive() == CK_FALSE)
+   {
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   *pulObjectCount = 0;
+
+   // find the token objects matching the template
+   // count will tell how much of the phObject buffer was written
+   CK_ULONG count = pSlot->_token->FindObjects( session, phObject, ulMaxObjectCount, pulObjectCount );
+
+   if(count < ulMaxObjectCount)
+   {
+      // find the session objects matching the template
+      count = session->FindObjects(count,phObject,ulMaxObjectCount,pulObjectCount);
+   }
+
+   return rv;
+}
+
+
+
+CK_RV  Slot::FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+
+   // Not needed here
+   // Transaction trans(slot);
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // check if search is active for this session or not
+   if(session->IsSearchActive() == CK_FALSE)
+   {
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   session->RemoveSearchTemplate();
+
+   return rv;
+}
+
+CK_RV Slot::GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR randomData,CK_ULONG ulRandomLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   if((randomData == NULL_PTR) || (ulRandomLen == 0))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   return pSlot->_token->GenerateRandom(randomData,ulRandomLen);
+}
+
+
+
+CK_RV Slot::CreateObject( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+  if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   // check the pointer arguments
+   if((pTemplate == NULL_PTR) || (ulCount == 0) || (phObject == NULL_PTR))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   // Check Template Consitency
+   rv = Template::CheckTemplate(pTemplate, ulCount, MODE_CREATE);
+   if (rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CK_ULONG classVal = Template::FindClassFromTemplate(pTemplate,ulCount);
+   PKCS11_ASSERT(classVal != -1);
+
+   auto_ptr<StorageObject> object;
+
+   switch(classVal){
+
+        case CKO_DATA:
+           object = auto_ptr<StorageObject>(new DataObject());
+           break;
+
+        case CKO_SECRET_KEY:
+           object = auto_ptr<StorageObject>(new SecretKeyObject());
+           break;
+
+        case CKO_PUBLIC_KEY:
+           object = auto_ptr<StorageObject>(new RSAPublicKeyObject());
+           break;
+
+        case CKO_PRIVATE_KEY:
+           object = auto_ptr<StorageObject>(new RSAPrivateKeyObject());
+           break;
+
+        case CKO_CERTIFICATE:
+           object = auto_ptr<StorageObject>(new X509PubKeyCertObject());
+           break;
+
+        default:
+           PKCS11_ASSERT(CK_FALSE);
+           break;
+   }
+
+   CK_BBOOL objCreationFailed = CK_FALSE;
+   CK_BYTE idx;
+   for(idx = 0; idx < ulCount; idx++)
+   {
+      if((rv = object->SetAttribute(pTemplate[idx],CK_TRUE)) != CKR_OK){
+         objCreationFailed = CK_TRUE;
+         break;
+      }
+   }
+
+   if(objCreationFailed)
+   {
+      return rv;
+   }
+
+   switch(object->_class)
+   {
+        case CKO_PUBLIC_KEY:
+           if(((RSAPublicKeyObject*)object.get())->_keyType != CKK_RSA)
+           {
+              return CKR_KEY_TYPE_INCONSISTENT;
+           }
+           break;
+
+        case CKO_PRIVATE_KEY:
+           if(((RSAPrivateKeyObject*)object.get())->_keyType != CKK_RSA)
+           {
+              return CKR_KEY_TYPE_INCONSISTENT;
+           }
+           break;
+   }
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // if this is a readonly session and
+   // user is not logged then only public session objects
+   // can be created
+   if(session->_isReadWrite == CK_FALSE)
+   {
+      if(object->_tokenObject)
+      {
+         return CKR_SESSION_READ_ONLY;
+      }
+   }
+
+   if( CK_TRUE == object->_private )
+   {
+      if( false == pSlot->_token->m_bIsNoPinSupported )
+      {
+         if(   ( CKU_USER != pSlot->_token->_roleLogged )
+            && ( ( true == pSlot->_token->m_bIsSSO ) && ( false == pSlot->_token->isAuthenticated( ) ) )
+            )
+         {
+            return CKR_USER_NOT_LOGGED_IN;
+         }
+      }
+   }
+   /*if ((pSlot->_token->_roleLogged != CKU_USER) && (object->_private == CK_TRUE))
+   {
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+   */
+
+   if(object->_tokenObject)
+   {
+
+      // any type of token object cannot be created
+      // unless user is logged in
+
+      // NOTE : Not PKCS#11 compilance
+      // CardModule service does not allow 'deletion' of any file unless user is logged in. We can create a file
+      // when nobody is logged in but we can not delete. In order to be symmetrical we do not also allow
+      // the creation.
+      if( false == pSlot->_token->m_bIsNoPinSupported )
+      {
+         if(   ( CKU_USER != pSlot->_token->_roleLogged )
+            && ( ( true == pSlot->_token->m_bIsSSO ) && ( false == pSlot->_token->isAuthenticated( ) ) )
+            )
+         {
+            return CKR_USER_NOT_LOGGED_IN;
+         }
+      }
+
+      // some sanity checks
+      if(object->_class == CKO_PRIVATE_KEY)
+      {
+         rv = pSlot->_token->AddPrivateKeyObject(object, phObject);
+      }
+      else if(object->_class == CKO_CERTIFICATE)
+      {
+         rv = pSlot->_token->AddCertificateObject(object, phObject);
+      }
+      else
+      {
+         rv = pSlot->_token->AddObject(object, phObject);
+      }
+   }
+   else
+   {
+      rv = session->AddObject(object.get(),phObject);
+      if(rv == CKR_OK)
+         object.release();
+   }
+
+   //printf( "\nSlot::CreateObject - ManageGC( true )\n" );
+    pSlot->_token->ManageGC( true );
+
+   return rv;
+}
+
+
+
+CK_RV Slot::DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hObject & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   // if this is a readonly session and
+   // user is not logged then only public session objects
+   // can be created
+   if(session->_isReadWrite == CK_FALSE)
+   {
+      if(istoken)
+      {
+         return CKR_SESSION_READ_ONLY;
+      }
+   }
+
+   if(istoken)
+   {
+      rv = pSlot->_token->DeleteObject(hObject);
+   }
+   else
+   {
+      rv = session->DeleteObject(hObject);
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::GetAttributeValue( CK_SESSION_HANDLE hSession,
+                               CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount )
+{
+   if(pTemplate == NULL_PTR || ulCount == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hObject & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   // TBD : Attributes of types such as Array which have not be initialized ?
+   // for eg label
+
+   if(istoken)
+   {
+      rv = pSlot->_token->GetAttributeValue(hObject,pTemplate,ulCount);
+   }
+   else
+   {
+      rv = session->GetAttributeValue(hObject,pTemplate,ulCount);
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SetAttributeValue( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+{
+   if(pTemplate == NULL_PTR || ulCount == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+  if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* pSession = pSlot->_sessions[ hSessionId ];
+
+   // From object handle we can determine if it is a token object or session object
+   CK_BBOOL istoken = ( ( hObject & CO_TOKEN_OBJECT ) == CO_TOKEN_OBJECT );
+   if( TRUE == istoken )
+   {
+      if( CK_FALSE == pSession->_isReadWrite )
+      {
+         return CKR_SESSION_READ_ONLY;
+      }
+
+      rv = pSlot->_token->SetAttributeValue( hObject, pTemplate, ulCount );
+   }
+   else
+   {
+      rv = pSession->SetAttributeValue( hObject, pTemplate, ulCount );
+   }
+
+   return rv;
+}
+
+
+CK_RV Slot::GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+                            CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,
+                            CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)
+{
+   // Since MODULUS_BITS is an essential attribute pPublicKeyTemplate should never be NULL or ulPublicKeyAttributeCount
+   // should not be zero. For private key template there is not compuslary attributes to be specified so it can be
+   // NULL_PTR
+
+   if((pMechanism == NULL_PTR) || (pPublicKeyTemplate == NULL_PTR) ||
+      (ulPublicKeyAttributeCount == 0) || (phPublicKey == NULL_PTR) ||
+      (phPrivateKey == NULL_PTR))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(pMechanism->mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN)
+      return CKR_MECHANISM_INVALID;
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   //Session* session = pSlot->_sessions[ hSessionId ];
+
+   // Check Public Template Consitency
+   rv = Template::CheckTemplate(pPublicKeyTemplate, ulPublicKeyAttributeCount, MODE_GENERATE_PUB);
+   if (rv != CKR_OK)
+      return rv;
+
+   // Check Private Template Consitency
+   rv = Template::CheckTemplate(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, MODE_GENERATE_PRIV);
+   if (rv != CKR_OK)
+      return rv;
+
+   auto_ptr<StorageObject> rsaPubKey(new RSAPublicKeyObject());
+   for(u4 i=0;i<ulPublicKeyAttributeCount;i++){
+      rv = rsaPubKey->SetAttribute(pPublicKeyTemplate[i],CK_TRUE);
+      if(rv != CKR_OK){
+         return rv;
+      }
+   }
+
+   auto_ptr<StorageObject> rsaPrivKey(new RSAPrivateKeyObject());
+   for(u4 i=0;i<ulPrivateKeyAttributeCount;i++){
+      rv = rsaPrivKey->SetAttribute(pPrivateKeyTemplate[i],CK_TRUE);
+      if(rv != CKR_OK){
+         return rv;
+      }
+   }
+
+   if(rsaPrivKey->_tokenObject){
+      rv = pSlot->_token->GenerateKeyPair(rsaPubKey,rsaPrivKey,phPublicKey,phPrivateKey);
+   }else{
+
+      // We do not support generation of key pair in the software
+      // TBD: Should we ?. I have noticed that during the import of
+      // p12 file using firefox it asks you to generate it in session
+
+      return CKR_ATTRIBUTE_VALUE_INVALID;
+   }
+
+   if(rv == CKR_OK)
+   {
+      if(rsaPubKey.get() && !rsaPubKey->_tokenObject)
+      {
+         pSlot->_sessions[ hSessionId ]->AddObject(rsaPubKey.get(),phPublicKey);
+         rsaPubKey.release();
+      }
+   }
+   return rv;
+}
+
+// ------------------------------------------------------------------------------------------------
+//                                  DIGEST RELATED FUNCTIONS
+// ------------------------------------------------------------------------------------------------
+CK_RV Slot::DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)
+{
+   if(pMechanism == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   // Not needed
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->IsDigestActive()){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   switch(pMechanism->mechanism){
+
+        case CKM_SHA_1:
+           session->SetDigest(new CSHA1());
+           break;
+
+        case CKM_SHA256:
+           session->SetDigest(new CSHA256());
+           break;
+
+        case CKM_MD5:
+           session->SetDigest(new CMD5());
+           break;
+
+        default:
+           return CKR_MECHANISM_INVALID;
+
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                   CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)
+{
+   if((pData == NULL_PTR) || (ulDataLen == 0) || (pulDigestLen == NULL_PTR)){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDigestActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   CDigest* digest = session->_digest;
+
+   if((*pulDigestLen < (CK_ULONG)digest->HashLength()) && (pDigest != NULL_PTR)){
+      *pulDigestLen = (CK_ULONG)digest->HashLength();
+      return CKR_BUFFER_TOO_SMALL;
+   }
+   else if(!pDigest){
+      *pulDigestLen = digest->HashLength();
+      return CKR_OK;
+   }
+
+   digest->HashCore(pData, 0, ulDataLen);
+
+   *pulDigestLen = (CK_ULONG)digest->HashLength();
+
+   if (pDigest != NULL_PTR)
+   {
+      digest->HashFinal(pDigest);
+      session->RemoveDigest();
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)
+{
+   if(pPart == NULL_PTR || ulPartLen == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDigestActive() == CK_FALSE)
+   {
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   session->_digest->HashCore(pPart,0,ulPartLen);
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)
+{
+   if(pulDigestLen == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->IsDigestActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   CDigest*    digest   = session->_digest;
+
+   if((*pulDigestLen < (CK_ULONG)digest->HashLength()) && (pDigest != NULL_PTR)){
+      *pulDigestLen = (CK_ULONG)digest->HashLength();
+      return CKR_BUFFER_TOO_SMALL;
+   }
+   else if(!pDigest){
+      *pulDigestLen = digest->HashLength();
+      return CKR_OK;
+   }
+
+   *pulDigestLen = (CK_ULONG)digest->HashLength();
+
+   if (pDigest != NULL_PTR){
+      digest->HashFinal(pDigest);
+      session->RemoveDigest();
+   }
+
+   return rv;
+}
+
+// ------------------------------------------------------------------------------------------------
+//                                  SIGNATURE RELATED FUNCTIONS
+// ------------------------------------------------------------------------------------------------
+CK_RV Slot::SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->IsSignatureActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_SIGN);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if( false == pSlot->_token->m_bIsNoPinSupported )
+   {
+      if(   ( CKU_USER != pSlot->_token->_roleLogged )
+         && ( ( true == pSlot->_token->m_bIsSSO ) && ( false == pSlot->_token->isAuthenticated( ) ) )
+         )
+      {
+         return CKR_USER_NOT_LOGGED_IN;
+      }
+   }
+   //if(pSlot->_token->_roleLogged != CKU_USER)
+   //{
+   //   return CKR_USER_NOT_LOGGED_IN;
+   //}
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_SIGN);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetSignatureOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   if(pMechanism->mechanism == CKM_SHA1_RSA_PKCS){
+      session->SetDigestRSA(new CSHA1());
+   }else if(pMechanism->mechanism == CKM_SHA256_RSA_PKCS){
+      session->SetDigestRSA(new CSHA256());
+   }else if(pMechanism->mechanism == CKM_MD5_RSA_PKCS){
+      session->SetDigestRSA(new CMD5());
+   }
+
+   return rv;
+}
+
+
+
+CK_RV Slot::Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                 CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsSignatureActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pData == NULL_PTR || ulDataLen == 0 || pulSignatureLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   StorageObject* object = session->_signature->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+   CK_ULONG mechanism = session->_signature->GetMechanism();
+
+   // TBD : Private key may not necessarily have the modulus or modulus bits
+   // if that is the case then we need to locate the corresponding public key
+   // or may be I should always put the modulus bits in private key attributes
+
+   u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(((mechanism == CKM_RSA_PKCS) && (ulDataLen > modulus->GetLength() - 11)) ||
+      ((mechanism == CKM_RSA_X_509) && (ulDataLen > modulus->GetLength())))
+   {
+      return CKR_DATA_LEN_RANGE;
+   }
+
+   if(pSignature == NULL_PTR){
+      *pulSignatureLen = modulus->GetLength();
+      return CKR_OK;
+   }else{
+      if(*pulSignatureLen < modulus->GetLength()){
+         *pulSignatureLen = modulus->GetLength();
+         return CKR_BUFFER_TOO_SMALL;
+      }
+   }
+
+   u1Array* dataToSign = NULL_PTR;
+
+   if(session->IsDigestRSAActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSA;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashCore(pData,0,ulDataLen);
+      digest->HashFinal(hash);
+
+      dataToSign  = new u1Array(digest->HashLength());
+      dataToSign->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToSign = new u1Array(ulDataLen);
+      dataToSign->SetBuffer(pData);
+   }
+
+   rv = pSlot->_token->Sign(session->_signature->GetObject(),dataToSign,session->_signature->GetMechanism(),pSignature);
+
+   if(rv == CKR_OK){
+      *pulSignatureLen = modulus->GetLength();
+   }
+
+   session->RemoveDigestRSA();
+   session->RemoveSignatureOperation();
+
+   delete dataToSign;
+
+   return rv;
+}
+
+
+
+CK_RV Slot::SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+   // what we do here is to update the hash or
+   // if hashing is not getting used we just accumulate it
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsSignatureActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pPart == NULL_PTR || ulPartLen == 0){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(session->IsDigestRSAActive() == CK_TRUE){
+      CDigest* digest = session->_digestRSA;
+      digest->HashCore(pPart,0,ulPartLen);
+   }
+   // Sign Only
+   else {
+
+      if(session->_accumulatedDataToSign != NULL_PTR){
+         // just accumulate the data
+         u1Array* updatedData = new u1Array(session->_accumulatedDataToSign->GetLength() + ulPartLen);
+         memcpy(updatedData->GetBuffer(),session->_accumulatedDataToSign->GetBuffer(),session->_accumulatedDataToSign->GetLength());
+
+         memcpy((u1*)&updatedData->GetBuffer()[session->_accumulatedDataToSign->GetLength()],pPart,ulPartLen);
+
+         delete session->_accumulatedDataToSign;
+
+         session->_accumulatedDataToSign = updatedData;
+      }else{
+
+         session->_accumulatedDataToSign = new u1Array(ulPartLen);
+         session->_accumulatedDataToSign->SetBuffer(pPart);
+      }
+
+      CK_ULONG mech = session->_signature->GetMechanism();
+      u1Array* modulus = ((RSAPrivateKeyObject*)session->_signature->GetObject())->_modulus;
+
+      if(((mech == CKM_RSA_PKCS) && (session->_accumulatedDataToSign->GetLength() > modulus->GetLength() - 11)) ||
+         ((mech == CKM_RSA_X_509) && (session->_accumulatedDataToSign->GetLength() > modulus->GetLength())))
+      {
+         return CKR_DATA_LEN_RANGE;
+      }
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsSignatureActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pulSignatureLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   StorageObject* object = session->_signature->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+
+   // TBD : Private key may not necessarily have the modulus or modulus bits
+   // if that is the case then we need to locate the corresponding public key
+   // or may be I should always put the modulus bits in private key attributes
+
+   u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(pSignature == NULL_PTR){
+      *pulSignatureLen = modulus->GetLength();
+      return CKR_OK;
+   }else{
+      if(*pulSignatureLen < modulus->GetLength()){
+         *pulSignatureLen = modulus->GetLength();
+         return CKR_BUFFER_TOO_SMALL;
+      }
+   }
+
+   u1Array* dataToSign = NULL_PTR;
+
+   if(session->IsDigestRSAActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSA;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashFinal(hash);
+
+      dataToSign  = new u1Array(digest->HashLength());
+      dataToSign->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToSign = session->_accumulatedDataToSign;
+   }
+
+   rv = pSlot->_token->Sign(session->_signature->GetObject(),dataToSign,session->_signature->GetMechanism(),pSignature);
+
+   if(rv == CKR_OK){
+      *pulSignatureLen = modulus->GetLength();
+   }
+
+   session->RemoveDigestRSA();
+   session->RemoveSignatureOperation();
+
+   delete dataToSign;
+   session->_accumulatedDataToSign = NULL_PTR;
+
+   return rv;
+}
+
+
+
+CK_RV Slot::EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsEncryptionActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_ENCRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if( false == pSlot->_token->m_bIsNoPinSupported )
+   {
+      if(   ( CKU_USER != pSlot->_token->_roleLogged )
+         && ( ( true == pSlot->_token->m_bIsSSO ) && ( false == pSlot->_token->isAuthenticated( ) ) )
+         )
+      {
+         return CKR_USER_NOT_LOGGED_IN;
+      }
+   }
+   //if(pSlot->_token->_roleLogged != CKU_USER)
+   //{
+   //   return CKR_USER_NOT_LOGGED_IN;
+   //}
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_ENCRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetEncryptionOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                    CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)
+{
+   if(pData == NULL_PTR || ulDataLen == 0 || pulEncryptedDataLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+    if(rv != CKR_OK)
+   {
+      return rv;
+   }
+  checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsEncryptionActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   StorageObject* object = session->_encryption->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+
+   //CK_ULONG mechanism = session->_encryption->GetMechanism();
+
+   u1Array* modulus = ((RSAPublicKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(pEncryptedData == NULL_PTR){
+      *pulEncryptedDataLen = modulus->GetLength();
+      return CKR_OK;
+   }else{
+      if(*pulEncryptedDataLen < modulus->GetLength()){
+         *pulEncryptedDataLen = modulus->GetLength();
+         return CKR_BUFFER_TOO_SMALL;
+      }
+   }
+
+   u1Array* dataToEncrypt = new u1Array(ulDataLen);
+   dataToEncrypt->SetBuffer(pData);
+
+   rv = pSlot->_token->Encrypt(session->_encryption->GetObject(),dataToEncrypt,session->_encryption->GetMechanism(),pEncryptedData);
+
+   if(rv == CKR_OK){
+      *pulEncryptedDataLen = modulus->GetLength();
+   }
+
+   session->RemoveEncryptionOperation();
+
+   delete dataToEncrypt;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDecryptionActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_DECRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if( false == pSlot->_token->m_bIsNoPinSupported )
+   {
+      if(   ( CKU_USER != pSlot->_token->_roleLogged )
+         && ( ( true == pSlot->_token->m_bIsSSO ) && ( false == pSlot->_token->isAuthenticated( ) ) )
+         )
+      {
+         return CKR_USER_NOT_LOGGED_IN;
+      }
+   }
+   //if(pSlot->_token->_roleLogged != CKU_USER)
+   //{
+   //   return CKR_USER_NOT_LOGGED_IN;
+   //}
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_DECRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetDecryptionOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,
+                    CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
+{
+   if(pEncryptedData == NULL_PTR || ulEncryptedDataLen == 0 ||pulDataLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDecryptionActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   StorageObject* object = session->_decryption->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+   CK_ULONG mechanism = session->_decryption->GetMechanism();
+
+   // TBD : Private key may not necessarily have the modulus or modulus bits
+   // if that is the case then we need to locate the corresponding public key
+   // or may be I should always put the modulus bits in private key attributes
+
+   u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   // [HB]: Fix length of return value
+   if(mechanism == CKM_RSA_PKCS){
+      // Can't know exact size of returned value before decryption has been done
+      if(pData == NULL_PTR){
+         *pulDataLen = modulus->GetLength() - 11;
+         return CKR_OK;
+      }
+   }
+   else if(mechanism == CKM_RSA_X_509){
+      if(pData == NULL_PTR){
+         *pulDataLen = modulus->GetLength();
+         return CKR_OK;
+      }else{
+         if(*pulDataLen < modulus->GetLength()){
+            *pulDataLen = modulus->GetLength();
+            return CKR_BUFFER_TOO_SMALL;
+         }
+      }
+   }
+   else
+      return CKR_MECHANISM_INVALID;
+
+   if(ulEncryptedDataLen != modulus->GetLength()){
+      return CKR_ENCRYPTED_DATA_LEN_RANGE;
+   }
+
+   u1Array* dataToDecrypt = new u1Array(ulEncryptedDataLen);
+   dataToDecrypt->SetBuffer(pEncryptedData);
+
+   rv = pSlot->_token->Decrypt(session->_decryption->GetObject(),dataToDecrypt,session->_decryption->GetMechanism(),pData, pulDataLen);
+
+   session->RemoveDecryptionOperation();
+
+   delete dataToDecrypt;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV  Slot::VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+    if(rv != CKR_OK)
+   {
+      return rv;
+   }
+  checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_VERIFY);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if( false == pSlot->_token->m_bIsNoPinSupported )
+   {
+      if(   ( CKU_USER != pSlot->_token->_roleLogged )
+         && ( ( true == pSlot->_token->m_bIsSSO ) && ( false == pSlot->_token->isAuthenticated( ) ) )
+         )
+      {
+         return CKR_USER_NOT_LOGGED_IN;
+      }
+   }
+   //if(pSlot->_token->_roleLogged != CKU_USER)
+   //{
+   //   return CKR_USER_NOT_LOGGED_IN;
+   //}
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_VERIFY);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetVerificationOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   if(pMechanism->mechanism == CKM_SHA1_RSA_PKCS){
+      session->SetDigestRSAVerification(new CSHA1());
+   }else if(pMechanism->mechanism == CKM_SHA256_RSA_PKCS){
+      session->SetDigestRSAVerification(new CSHA256());
+   }else if(pMechanism->mechanism == CKM_MD5_RSA_PKCS){
+      session->SetDigestRSAVerification(new CMD5());
+   }
+
+   return CKR_OK;
+
+}
+
+
+/*
+*/
+CK_RV  Slot::Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                    CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if((pData == NULL_PTR) || (ulDataLen == 0) ||
+      (pSignature == NULL_PTR) || (ulSignatureLen == 0))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_ULONG mechanism = session->_verification->GetMechanism();
+
+
+   // I am doubtful regarding these 3 lines as
+   // the object could be privatekey which contains
+   // the public components
+   StorageObject* object = session->_verification->GetObject();
+   PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+   u1Array* modulus = ((RSAPublicKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(((mechanism == CKM_RSA_PKCS) && (ulDataLen > modulus->GetLength() - 11)) ||
+      ((mechanism == CKM_RSA_X_509) && (ulDataLen > modulus->GetLength())))
+   {
+      return CKR_DATA_LEN_RANGE;
+   }
+
+   u1Array* dataToVerify = NULL_PTR;
+
+   if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSAVerification;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashCore(pData,0,ulDataLen);
+      digest->HashFinal(hash);
+
+      dataToVerify  = new u1Array(digest->HashLength());
+      dataToVerify->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToVerify = new u1Array(ulDataLen);
+      dataToVerify->SetBuffer(pData);
+   }
+
+   u1Array* signature = new u1Array(ulSignatureLen);
+   signature->SetBuffer(pSignature);
+
+   rv = pSlot->_token->Verify(session->_verification->GetObject(),dataToVerify,session->_verification->GetMechanism(),signature);
+
+   delete signature;
+
+   session->RemoveDigestRSAVerification();
+   session->RemoveVerificationOperation();
+
+   delete dataToVerify;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)
+{
+
+   // what we do here is to update the hash or
+   // if hashing is not getting used we just accumulate it
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pPart == NULL_PTR || ulPartLen == 0){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+      CDigest* digest = session->_digestRSAVerification;
+      digest->HashCore(pPart,0,ulPartLen);
+   }
+   // Sign Only
+   else {
+
+      if(session->_accumulatedDataToVerify != NULL_PTR){
+         // just accumulate the data
+         u1Array* updatedData = new u1Array(session->_accumulatedDataToVerify->GetLength() + ulPartLen);
+         memcpy(updatedData->GetBuffer(),session->_accumulatedDataToVerify->GetBuffer(),session->_accumulatedDataToVerify->GetLength());
+
+         memcpy((u1*)&updatedData->GetBuffer()[session->_accumulatedDataToVerify->GetLength()],pPart,ulPartLen);
+
+         delete session->_accumulatedDataToVerify;
+
+         session->_accumulatedDataToVerify = updatedData;
+      }else{
+
+         session->_accumulatedDataToVerify = new u1Array(ulPartLen);
+         session->_accumulatedDataToVerify->SetBuffer(pPart);
+      }
+
+      CK_ULONG mech = session->_verification->GetMechanism();
+      u1Array* modulus = ((RSAPublicKeyObject*)session->_verification->GetObject())->_modulus;
+
+      if(((mech == CKM_RSA_PKCS) && (session->_accumulatedDataToVerify->GetLength() > modulus->GetLength() - 11)) ||
+         ((mech == CKM_RSA_X_509) && (session->_accumulatedDataToVerify->GetLength() > modulus->GetLength())))
+      {
+         return CKR_DATA_LEN_RANGE;
+      }
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if((pSignature == NULL_PTR) || (ulSignatureLen == 0)){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   //StorageObject* object = session->_verification->GetObject();
+   //PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+
+   u1Array* dataToVerify = NULL_PTR;
+
+   if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSAVerification;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashFinal(hash);
+
+      dataToVerify  = new u1Array(digest->HashLength());
+      dataToVerify->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToVerify = session->_accumulatedDataToVerify;
+   }
+
+   u1Array* signature = new u1Array(ulSignatureLen);
+   signature->SetBuffer(pSignature);
+
+   rv = pSlot->_token->Verify(session->_verification->GetObject(),dataToVerify,session->_verification->GetMechanism(),signature);
+
+   session->RemoveDigestRSAVerification();
+   session->RemoveVerificationOperation();
+
+   delete dataToVerify;
+   delete signature;
+   session->_accumulatedDataToVerify = NULL_PTR;
+
+   return rv;
+}
+
+
+
+// --------------
+
+
+
+/* Return true if the connection is aware
+*/
+/*bool*/ void Slot::checkConnection( Slot* a_pSlot )
+{
+   //Log::begin( "Slot::checkConnection" );
+
+   //bool bRet = false;
+
+   if( NULL_PTR != a_pSlot )
+   {
+      char readers[ 1024 ];
+      memset( readers, 0, sizeof( readers ) );
+      memcpy( readers, a_pSlot->_readerName->c_str( ), a_pSlot->_readerName->length( ) );
+      DWORD dwLen = sizeof( readers );
+      DWORD dwState = 0;
+      DWORD dwProtocol = 0;
+      BYTE Atr[32];
+      memset( Atr, 0, sizeof( Atr ) );
+      DWORD dwLenAtr = sizeof( Atr );
+      if( NULL != a_pSlot->_token )
+      {
+         CardModuleService* pMSCM = a_pSlot->_token->GetMiniDriverService( );
+         if( NULL != pMSCM )
+         {
+            SCARDHANDLE hCard = pMSCM->GetPcscCardHandle( );
+            DWORD hResult = SCardStatus( hCard, readers, &dwLen, &dwState, &dwProtocol, &Atr[0], &dwLenAtr );
+            //Log::log( "Slot::checkConnection - SCardStatus <%#02x>", hResult );
+            //printf( "\n Slot::checkConnection - SCardStatus <%#02x> \n", hResult );
+            if( ( SCARD_W_RESET_CARD == hResult ) || ( SCARD_W_REMOVED_CARD == hResult ) )
+            {
+               Log::error( "Slot::checkConnection", "Connection is broken" );
+               //printf( "\n Slot::checkConnection - Connection is broken \n" );
+
+               // Close all session
+               a_pSlot->CloseAllSessions( );
+
+               // Rebuild the token to restablish the CardModule communication
+               delete a_pSlot->_token;
+               a_pSlot->_token = NULL_PTR;
+
+               //printf( "\n Slot::checkConnection - BuildToken \n" );
+               a_pSlot->BuildToken( );
+
+              // bRet = false;
+            }
+         }
+      }
+   }
+
+   //Log::end( "Slot::checkConnection" );
+
+   //return bRet;
+}
+
+
+CK_LONG Slot::AddSession(Session* session)
+{
+   // 0 is an invalid session handle
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] == NULL_PTR){
+         this->_sessions[i] = session;
+         session->UpdateState(this->_token->_roleLogged);
+         return (CK_LONG)i;
+      }
+   }
+
+   // No free elements, add a new
+   _sessions.push_back(session);
+   return (CK_LONG)(_sessions.size()-1);
+}
+
+
+/*
+*/
+void Slot::RemoveSession( CK_LONG sessionId )
+{
+   //this->_token->ManageGC( true );
+
+   delete this->_sessions[ sessionId ];
+   this->_sessions[sessionId] = NULL_PTR;
+
+   // If this was the upper element in the vector, reduce size
+   size_t maxId = 0;
+   for( size_t i = 1 ; i < _sessions.size( ) ; i++ )
+   {
+      if( _sessions[ i ] )
+      {
+         maxId = i;
+      }
+   }
+   if( maxId < _sessions.size( ) - 1 )
+   {
+      _sessions.resize( maxId + 1 );
+   }
+
+   // if this was the last session to be removed
+   // then the login state of token for application
+   // returns to public sessions
+   if( 0 == maxId )
+   {
+      // TBD : Should I call logout here or merely set the flag ?
+      // if I logged the user out from this application
+      // what happens to another application
+      // This is where on-card implementation helps
+
+      PKCS11_ASSERT(this->_token != NULL_PTR);
+
+      this->_token->_roleLogged = CKU_NONE;
+   }
+}
+
+
+/*
+*/
+void Slot::UpdateSessionState( CK_ULONG ulRole )
+{
+   // update the state of all sessions
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] != NULL_PTR){
+         this->_sessions[i]->UpdateState( ulRole );
+      }
+   }
+}
+
+
+/*
+*/
+void Slot::UpdateSessionState( )
+{
+   // update the state of all sessions
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] != NULL_PTR){
+         this->_sessions[i]->UpdateState(this->_token->_roleLogged);
+      }
+   }
+}
+
+
+CK_BBOOL Slot::HasReadOnlySession()
+{
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] != NULL_PTR){
+         if(this->_sessions[i]->_isReadWrite == CK_FALSE){
+            return CK_TRUE;
+         }
+      }
+   }
+
+   return CK_FALSE;
+}
+
+CK_RV Slot::GetSlotAndSessionIdFromSessionHandle(CK_SESSION_HANDLE hSession,
+                                                 Slot** slot,
+                                                 CK_ULONG_PTR sessionId)
+{
+   CK_SLOT_ID slotId  = GET_SLOTID(hSession);
+   *sessionId         = GET_SESSIONID(hSession);
+
+   if(((int)slotId < 0) || (slotId >= CONFIG_MAX_SLOT)){
+      // we return here invalid session handle as
+      // app does not have a notion of slot at this time
+      return CKR_SESSION_HANDLE_INVALID;
+   }
+
+   if (Application::_slotCache[slotId] != NULL_PTR){
+      *slot = Application::_slotCache[slotId];
+
+      if((*sessionId < 1) || (*sessionId >= ((*slot)->_sessions.size()))){
+         return CKR_SESSION_HANDLE_INVALID;
+      }
+      if((*slot)->_sessions[*sessionId]) {
+         return CKR_OK;
+      }
+   }
+
+   return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV Slot::BuildToken(void)
+{
+   Log::begin( "Slot::BuildToken" );
+
+   if(this->_token == NULL_PTR)
+   {
+      SCARD_READERSTATE readerStates;
+      memset( &readerStates, 0, sizeof( SCARD_READERSTATE ) );
+      readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+      readerStates.szReader = this->_readerName->c_str( );
+
+#ifndef _XCL_
+
+      if( SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+      {
+         if ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)
+         {
+            // we not found a card in this reader
+            this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+            //Log::log( "Slot::BuildToken - ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)" );
+            Log::logCK_RV( "Slot::BuildToken", CKR_TOKEN_NOT_PRESENT );
+            return CKR_TOKEN_NOT_PRESENT;
+         }
+         else
+         {
+            // we found a card in this reader
+            this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+         }
+      }
+
+#else // _XCL_
+
+      if (xCL_IsTokenPresent())
+      {
+          // we found a card in this reader
+          this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+      }
+      else
+      {
+          // we not found a card in this reader
+          this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+          return CKR_TOKEN_NOT_PRESENT;
+      }
+
+#endif // _XCL_
+
+      // TBD: Check if token is a .net smart card
+
+      // token is present in the slot
+      //Log::log( "Slot::BuildToken - new Token..." );
+      this->_token = new Token( this->_readerName );
+      //Log::log( "Slot::BuildToken - new Token ok"  );
+
+      //Log::logCK_RV( "Slot::BuildToken", CKR_OK );
+      //Log::end( "Slot::BuildToken" );
+   }
+
+   Log::end( "Slot::BuildToken" );
+
+   return CKR_OK;
+}
+
+
+CK_RV Slot::IsValidMechanism(CK_ULONG mechanism,CK_ULONG operation)
+{
+   size_t i = 0;
+
+   CK_BBOOL found = CK_FALSE;
+
+   for(;i<sizeof(MechanismList)/sizeof(CK_ULONG);i++){
+      if(MechanismList[i] == mechanism){
+         found = CK_TRUE;
+         break;
+      }
+   }
+
+   if(found == CK_FALSE){
+      return CKR_MECHANISM_INVALID;
+   }
+
+   if((MechanismInfo[i].flags & operation) != operation){
+      return CKR_MECHANISM_INVALID;
+   }
+
+   return CKR_OK;
+}
+
+CK_RV Slot::IsValidCryptoOperation(StorageObject* object,CK_ULONG operation)
+{
+   // Check if key is consistent
+   switch(operation)
+   {
+   case CKF_ENCRYPT:
+   case CKF_VERIFY:
+   case CKF_VERIFY_RECOVER:
+      if(object->_class != CKO_PUBLIC_KEY && object->_class != CKO_SECRET_KEY){
+         return CKR_KEY_TYPE_INCONSISTENT;
+      }
+      break;
+
+   case CKF_DECRYPT:
+   case CKF_SIGN:
+   case CKF_SIGN_RECOVER:
+      if(object->_class != CKO_PRIVATE_KEY && object->_class != CKO_SECRET_KEY){
+         return CKR_KEY_TYPE_INCONSISTENT;
+      }
+      break;
+   }
+
+   // Check if key supports the operation
+   switch(operation)
+   {
+   case CKF_ENCRYPT:
+      if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_encrypt))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_encrypt))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   case CKF_DECRYPT:
+      if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_decrypt))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_decrypt))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   case CKF_VERIFY:
+      if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_verify))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_verify))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+
+   case CKF_VERIFY_RECOVER:
+      if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_verifyRecover))){
+         return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+
+   case CKF_SIGN:
+      if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_sign))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_sign))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   case CKF_SIGN_RECOVER:
+      if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_signRecover))){
+         return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   }
+
+   return CKR_OK;
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/slot.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/slot.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/slot.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,413 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_slot_h
+#define _include_slot_h
+
+#include "sctoken.h"
+#include "critsect.h"
+
+#ifdef _XCL_
+#include "xcl_public.h"
+#include <xcl_utils.h>
+#endif // _XCL
+
+class CardMonitoringThread;
+
+class Slot {
+
+public:
+   CK_SLOT_ID              _slotId;
+   CK_SLOT_INFO            _slotInfo;
+   std::string*            _readerName;
+   CK_BBOOL                _event;
+   CardMonitoringThread*   _tracker;
+   vector<Session*>        _sessions;
+   Token*                  _token;
+
+private:
+   CK_LONG AddSession(Session* session);
+   void RemoveSession(CK_LONG sessionId);
+   CK_BBOOL HasReadOnlySession();
+   static /*bool*/ void checkConnection( Slot* a_pSlot );
+
+public:
+   Slot();
+   virtual ~Slot();
+
+   void UpdateSessionState();
+   //void UpdateAuthenticationState( void );
+   void UpdateSessionState( CK_ULONG ulRole );
+
+
+   static void ClearCache(void);
+   static CK_RV GetSlotAndSessionIdFromSessionHandle(CK_SESSION_HANDLE hSession,
+      Slot** slot,CK_ULONG_PTR sessionId);
+
+   static CK_RV IsValidMechanism(CK_ULONG mechanism,CK_ULONG operation);
+   static CK_RV IsValidCryptoOperation(StorageObject* object,CK_ULONG operation);
+
+   CK_BBOOL    GetEvent();
+   void        SetEvent(CK_BBOOL event);
+   CK_SLOT_ID  GetSlotId() { return _slotId;}
+   CK_BBOOL    IsCardPresent() { return ((_slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);}
+   void        Clear(void);
+
+   CK_RV  BuildToken(void);
+
+   CK_RV  GetInfo(CK_SLOT_INFO_PTR pInfo);
+   CK_RV  GetTokenInfo(CK_TOKEN_INFO_PTR pInfo);
+   CK_RV  GetMechanismList(CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount);
+   CK_RV  GetMechanismInfo(CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo);
+   CK_RV  OpenSession(CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession);
+   static CK_RV  CloseSession(CK_SESSION_HANDLE hSession);
+   CK_RV  CloseAllSessions(void);
+   static CK_RV  GetSessionInfo(CK_SESSION_HANDLE hSession,CK_SESSION_INFO_PTR pInfo);
+
+   static CK_RV  Login(CK_SESSION_HANDLE hSession,CK_USER_TYPE userType,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen);
+   static CK_RV  Logout(CK_SESSION_HANDLE hSession);
+
+   CK_RV InitToken(CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel);
+   static CK_RV  InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen);
+   static CK_RV  SetPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pOldPin,CK_ULONG ulOldLen,
+      CK_UTF8CHAR_PTR pNewPin,CK_ULONG ulNewLen);
+
+   static CK_RV  CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject);
+   static CK_RV  DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject);
+   static CK_RV  GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE  hObject,CK_ATTRIBUTE_PTR  pTemplate,CK_ULONG ulCount);
+   static CK_RV  SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+   static CK_RV  FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR  pTemplate,CK_ULONG ulCount);
+   static CK_RV  FindObjects(CK_SESSION_HANDLE  hSession, CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount);
+   static CK_RV  FindObjectsFinal(CK_SESSION_HANDLE hSession);
+
+   static CK_RV  GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR RandomData,CK_ULONG ulRandomLen);
+
+   static CK_RV  GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+      CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,
+      CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey);
+
+   //static CK_RV  WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR  pMechanism,
+   //                      CK_OBJECT_HANDLE  hWrappingKey,CK_OBJECT_HANDLE  hKey,
+   //                      CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen);
+
+   //static CK_RV  UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,
+   //                       CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,
+   //                       CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,
+   //                       CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey);
+
+   static CK_RV  EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE  hKey);
+   static CK_RV  Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen);
+
+   static CK_RV  DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR  pMechanism,CK_OBJECT_HANDLE  hKey);
+   static CK_RV  Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen);
+
+   static CK_RV  SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+   static CK_RV  Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen);
+   static CK_RV  SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+   static CK_RV  SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen);
+
+   static CK_RV  VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+   static CK_RV  Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen);
+   static CK_RV  VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+   static CK_RV  VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen);
+   //static CK_RV  VerifyRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+   //static CK_RV  VerifyRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen);
+
+   static CK_RV  DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism);
+   static CK_RV  Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen);
+   static CK_RV  DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+   static CK_RV  DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen);
+};
+
+#define CARD_PRESENT 1
+#define CARD_ABSENT  2
+
+#define CARD_DETECTION_INSERTED 1
+#define CARD_DETECTION_REMOVED  2
+
+
+#ifdef INCLUDE_EVENTING
+
+extern CCriticalSection _critSect;
+
+class CardMonitoringThread : public CThread
+{
+
+private:
+   CK_BYTE m_bCardState;
+   Slot*   m_slot;
+   SCARDCONTEXT m_hMonitoringContext;
+
+public:
+   // CThread override
+   void stop()
+   {
+      //printf( "%s - %d - %s - m_monitoringContext <%ld>\n", __FILE__, __LINE__, __FUNCTION__, m_hMonitoringContext );
+
+#ifndef _XCL_
+
+      if( 0 != m_hMonitoringContext )
+      {
+         SCardCancel(m_hMonitoringContext);
+         //printf( "%s - %d - %s - SCardCancel\n", __FILE__, __LINE__, __FUNCTION__);
+
+         //printf( "%s - %d - %s - SCardReleaseContext -->\n", __FILE__, __LINE__, __FUNCTION__);
+         //SCardReleaseContext(m_hMonitoringContext);
+         //printf( "%s - %d - %s - SCardReleaseContext <--\n", __FILE__, __LINE__, __FUNCTION__);
+         //m_hMonitoringContext = 0;
+      }
+
+#endif // _XCL_
+
+      CThread::stop();
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+   CardMonitoringThread(const char* nm) //: m_hMonitoringContext(0)
+   {
+      m_hMonitoringContext = 0;
+      m_bCardState = CARD_ABSENT;
+      CThread::setName(nm);
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+   void SetSlot(Slot* slot)
+   {
+      m_slot = slot;
+
+      if(slot->IsCardPresent() == CK_FALSE)
+      {
+         m_bCardState = CARD_ABSENT;
+      }
+      else
+      {
+         m_bCardState = CARD_PRESENT;
+      }
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+   void run()
+   {
+      bool bTrue = true;
+      while( bTrue )
+      {
+         switch(m_bCardState)
+         {
+         case CARD_PRESENT:
+            if(Monitor(CARD_DETECTION_REMOVED) == false)
+            {
+               return;
+            }
+            m_bCardState = CARD_ABSENT;
+
+            // clean the slot, lock during session deletion
+            {
+               CCriticalSectionLocker cslock(_critSect);
+               m_slot->Clear();
+            }
+            break;
+
+         case CARD_ABSENT:
+            if(Monitor(CARD_DETECTION_INSERTED) == false)
+            {
+               return;
+            }
+            m_bCardState = CARD_PRESENT;
+            break;
+         }
+
+         // we fire the event from here
+         m_slot->SetEvent(CK_TRUE);
+         CryptokiEvent.Signal();
+      }
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+
+#ifndef _XCL_
+
+   bool Monitor(BYTE detectionType)
+   {
+
+      // establish monitoring context
+      LONG lReturn = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &m_hMonitoringContext );
+      //printf( "%s - %d - %s - SCardEstablishContext --> m_hMonitoringContext <%ld>\n", __FILE__, __LINE__,  __FUNCTION__, m_hMonitoringContext);
+
+      //LONG lReturn = SCardEstablishContext(0, NULL, NULL, (LPSCARDCONTEXT)&m_monitoringContext);
+
+      if(lReturn != SCARD_S_SUCCESS)
+      {
+         return false;
+      }
+
+      SCARD_READERSTATE readerStates;
+      readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+      readerStates.szReader       = this->getName()->c_str();
+      readerStates.pvUserData     = NULL;
+      readerStates.dwEventState   = 0;         // TO INSPECT THIS STATE
+
+      bool bTrue = true;
+      while( bTrue )
+      {
+
+         if((lReturn = SCardGetStatusChange( m_hMonitoringContext, 60*1000, &readerStates, 1 )) != SCARD_S_SUCCESS)
+         {
+            if(lReturn == (LONG)SCARD_E_TIMEOUT)
+            {
+               if(this->isStopRequested() == CK_TRUE)
+               {
+                  SCardReleaseContext(m_hMonitoringContext);
+                  //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+                  m_hMonitoringContext = 0;
+                  return false;
+               }
+
+               goto resume;
+            }
+
+            SCardReleaseContext(m_hMonitoringContext);
+            //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+            m_hMonitoringContext = 0;
+            return false;
+         }
+
+resume:
+         if((readerStates.dwEventState & SCARD_STATE_CHANGED) == SCARD_STATE_CHANGED)
+         {
+            if((readerStates.dwEventState & SCARD_STATE_UNAVAILABLE) == SCARD_STATE_UNAVAILABLE)
+            {
+               // reader removed
+               SCardReleaseContext(m_hMonitoringContext);
+               //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+               m_hMonitoringContext = 0;
+               return true;
+            }
+            else if(((readerStates.dwCurrentState & SCARD_STATE_EMPTY) == SCARD_STATE_EMPTY) &&
+               ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT))
+            {
+               if(detectionType == CARD_PRESENT)
+               {
+                  // card is inserted
+                  SCardReleaseContext(m_hMonitoringContext);
+                  //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+                  m_hMonitoringContext = 0;
+                  return true;
+               }
+            }
+            else if(((readerStates.dwCurrentState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT) &&
+               ((readerStates.dwEventState & SCARD_STATE_EMPTY) == SCARD_STATE_EMPTY))
+            {
+               if(detectionType == CARD_ABSENT)
+               {
+                  // card is removed
+                  SCardReleaseContext(m_hMonitoringContext);
+                  //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+                  m_hMonitoringContext = 0;
+                  return true;
+               }
+            }
+         }
+
+         readerStates.dwCurrentState = readerStates.dwEventState ;
+      }
+
+      SCardReleaseContext(m_hMonitoringContext);
+      //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+      m_hMonitoringContext = 0;
+      return false;
+   }
+
+#else // _XCL_
+
+    bool Monitor(BYTE detectionType)
+    {
+        BOOL initialTokenPresent;
+        BOOL currentTokenPresent;
+        UINT rv;
+        UINT deviceID2;
+        xCL_DeviceHandle deviceHandle2;
+
+        PRINT_MSG("IN Monitor top");
+
+        initialTokenPresent = false;
+        currentTokenPresent = false;
+
+        deviceHandle2 = 0;
+        deviceID2 = 0;
+        rv = xCL_CreateHandleFromDeviceID(deviceID2, &deviceHandle2);
+        if (rv == 0)
+        {
+            initialTokenPresent = true;
+            currentTokenPresent = true;
+        }
+        rv = xCL_CloseHandle(deviceHandle2);
+
+        while(true)
+        {
+            PRINT_MSG("IN Monitor loop");
+
+            // sleep for some time
+            sleep(500);
+
+            // See if token is present now
+            deviceHandle2 = 0;
+            deviceID2 = 0;
+            rv = xCL_CreateHandleFromDeviceID(deviceID2, &deviceHandle2);
+            if (rv == 0)
+            {
+                currentTokenPresent = true;
+                rv = xCL_CloseHandle(deviceHandle2);
+            }
+            else
+            {
+                currentTokenPresent = false;
+            }
+
+            if (initialTokenPresent == currentTokenPresent)
+            {
+                PRINT_MSG("IN Monitor no change");
+
+                // No change in token state
+                if(this->isStopRequested() == CK_TRUE)
+                {
+                    PRINT_MSG("IN Monitor no change exit");
+                    return false;
+                }
+            }
+            else
+            {
+                PRINT_MSG("IN Monitor yes change");
+                // There is a change ...
+                return true;
+            }
+        }
+    }
+
+#endif // _XCL_
+
+};
+#endif
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,41 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+
+// Determine Processor Endianess
+#include <limits.h>
+#if (UINT_MAX == 0xffffffffUL)
+   typedef unsigned int _u4;
+#else
+#  if (ULONG_MAX == 0xffffffffUL)
+     typedef unsigned long _u4;
+#  else
+#    if (USHRT_MAX == 0xffffffffUL)
+       typedef unsigned short _u4;
+#    endif
+#  endif
+#endif
+
+_u4 endian = 1;
+
+bool IS_LITTLE_ENDIAN = (*((unsigned char *)(&endian))) ? true  : false;
+bool IS_BIG_ENDIAN    = (*((unsigned char *)(&endian))) ? false : true;
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/stdafx.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,52 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_stadfx_h
+#define _include_stadfx_h
+
+#ifdef WIN32
+    #include <windows.h>
+    #include <wincrypt.h>
+    #include <assert.h>
+#else
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <string.h>
+	#ifdef __APPLE__
+	#include <PCSC/winscard.h>
+	#include <PCSC/wintypes.h>
+    #else
+    #include <winscard.h>
+	#endif
+    typedef BYTE *PBYTE;
+#ifndef HAVE_LPCTSTR
+    typedef const char *LPCTSTR;
+#endif
+#ifndef HAVE_LPCSTR
+    typedef LPCTSTR LPCSTR;
+#endif
+
+#endif
+
+extern bool IS_BIG_ENDIAN;
+extern bool IS_LITTLE_ENDIAN;
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,373 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+#include "storageobject.h"
+#include "error.h"
+
+StorageObject::StorageObject()
+{
+    this->_version     = 0;
+    this->_uniqueId    = 0;
+    this->_tokenObject = CK_FALSE;
+    this->_private     = CK_FALSE;
+    this->_modifiable  = CK_TRUE;
+    this->_label       = NULL_PTR;
+}
+
+StorageObject::~StorageObject(){
+
+    if(this->_label != NULL_PTR)
+        delete this->_label;
+
+}
+
+bool StorageObject::IsEqual(const StorageObject * that) const
+{
+    if(_uniqueId != 0 && that->_uniqueId != 0)
+        return (_uniqueId == that->_uniqueId);
+
+    // Only objects that have been stored under p11 directory
+    // will have a non-zero _uniqueId. For other objects, do
+    // a deep comparison based on other attributes. In the base
+    // class, only negative comparison based on _class can be performed.
+    if(_class != that->_class)
+        return false;
+    else
+        throw CkError(CKR_FUNCTION_FAILED);
+}
+
+CK_BBOOL StorageObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+        case CKA_CLASS:
+            return (this->_class == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_PRIVATE:
+            return (this->_private == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_TOKEN:
+            return (this->_tokenObject == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_MODIFIABLE:
+            return (this->_modifiable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_LABEL:
+            if(this->_label->GetLength() == attribute.ulValueLen){
+                return Util::CompareByteArrays(this->_label->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+            }
+            return CK_FALSE;
+
+        default:
+            return CK_FALSE;
+
+    }
+}
+
+CK_RV StorageObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_CLASS:
+            case CKA_PRIVATE:
+            case CKA_TOKEN:
+            case CKA_MODIFIABLE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+        case CKA_CLASS:
+            break;
+
+        case CKA_PRIVATE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_private = btemp; }
+            }
+            break;
+
+        case CKA_TOKEN:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_tokenObject = btemp; }
+            }
+            break;
+
+        case CKA_MODIFIABLE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_modifiable = btemp; }
+            }
+            break;
+
+        case CKA_LABEL:
+            {
+                u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_label != NULL_PTR){
+                        delete this->_label;
+                    }
+                    this->_label = stemp;
+                }
+            }
+            break;
+
+        default:
+            return CKR_ATTRIBUTE_TYPE_INVALID;
+
+    }
+
+    return rv;
+}
+
+CK_RV StorageObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   CK_RV ulRet = CKR_OK;
+
+    switch(attribute->type)
+    {
+        case CKA_CLASS:
+            ulRet = StorageObject::PutULongInAttribute(this->_class,attribute);
+            break;
+
+        case CKA_PRIVATE:
+            ulRet = StorageObject::PutBBoolInAttribute(this->_private,attribute);
+            break;
+
+        case CKA_TOKEN:
+            ulRet = StorageObject::PutBBoolInAttribute(this->_tokenObject,attribute);
+            break;
+
+        case CKA_MODIFIABLE:
+            ulRet = StorageObject::PutBBoolInAttribute(this->_modifiable,attribute);
+            break;
+
+        case CKA_LABEL:
+            ulRet = StorageObject::PutU1ArrayInAttribute(this->_label,attribute);
+            break;
+
+        default:
+           attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+           ulRet = CKR_ATTRIBUTE_TYPE_INVALID;
+           break;
+    }
+
+    return ulRet;
+}
+
+void StorageObject::Serialize(std::vector<u1>* to)
+{
+    // serialize format version
+    Util::PushBBoolInVector(to,this->_version);
+
+    // serialize unique id
+    Util::PushULongLongInVector(to,this->_uniqueId);
+
+    // serialize class attribute
+    Util::PushULongInVector(to,this->_class);
+
+    // serialize private attribute
+    Util::PushBBoolInVector(to,this->_private);
+
+    // serialize token attribute
+    Util::PushBBoolInVector(to,this->_tokenObject);
+
+    // serialize modifiable attribute
+    Util::PushBBoolInVector(to,this->_modifiable);
+
+    // serialize label attribute
+    Util::PushByteArrayInVector(to,this->_label);
+}
+
+void StorageObject::Deserialize(std::vector<u1> from,CK_ULONG_PTR idx)
+{
+    this->_version = Util::ReadBBoolFromVector(from,idx);
+
+    this->_uniqueId = Util::ReadULongLongFromVector(from, idx);
+
+    this->_class = Util::ReadULongFromVector(from,idx);
+
+    this->_private = Util::ReadBBoolFromVector(from,idx);
+
+    this->_tokenObject = Util::ReadBBoolFromVector(from,idx);
+
+    this->_modifiable = Util::ReadBBoolFromVector(from,idx);
+
+    this->_label = Util::ReadByteArrayFromVector(from,idx);
+}
+
+CK_RV StorageObject::PutU1ArrayInAttribute(u1Array* value,CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        if(value == NULL_PTR){
+            attribute->ulValueLen = 0;
+        }else{
+            attribute->ulValueLen = value->GetLength();
+        }
+        return CKR_OK;
+    }
+    if(value == NULL_PTR){
+        // I am not sure about it (TBD: Check)
+        attribute->ulValueLen = 0;
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < value->GetLength()){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+
+    attribute->ulValueLen = value->GetLength();
+    memcpy((CK_BYTE_PTR)attribute->pValue,value->GetBuffer(),attribute->ulValueLen);
+
+    return CKR_OK;
+}
+
+CK_RV StorageObject::PutU4ArrayInAttribute(u4Array* value,CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        if(value == NULL_PTR){
+            attribute->ulValueLen = 0;
+        }else{
+            attribute->ulValueLen = (value->GetLength() * 4);
+        }
+        return CKR_OK;
+    }
+    if(value == NULL_PTR){
+        // I am not sure about it (TBD: Check)
+        attribute->ulValueLen = 0;
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < (value->GetLength() * 4)){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+
+    attribute->ulValueLen = value->GetLength() * 4;
+    memcpy((CK_BYTE_PTR)attribute->pValue,(u1*)value->GetBuffer(),attribute->ulValueLen);
+
+    return CKR_OK;
+}
+
+CK_RV StorageObject::PutBBoolInAttribute(CK_BBOOL value, CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        attribute->ulValueLen = sizeof(CK_BBOOL);
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < sizeof(CK_BBOOL)){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+    attribute->ulValueLen = sizeof(CK_BBOOL);
+    *(CK_BBOOL*)attribute->pValue = value;
+
+    return CKR_OK;
+}
+
+CK_RV StorageObject::PutULongInAttribute(CK_ULONG value, CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        attribute->ulValueLen = sizeof(CK_ULONG);
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < sizeof(CK_ULONG)){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+    attribute->ulValueLen = sizeof(CK_ULONG);
+    *(CK_ULONG*)attribute->pValue = value;
+
+    return CKR_OK;
+}
+
+CK_ULONG StorageObject::ReadULongFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+    if(attribute.ulValueLen != sizeof(CK_ULONG)){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return 0;
+    }
+
+    return *(CK_ULONG*)attribute.pValue;
+}
+
+CK_BBOOL StorageObject::ReadBBoolFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+    if(attribute.ulValueLen != sizeof(CK_BBOOL)){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return 0;
+    }
+
+    CK_BBOOL val = *(CK_BBOOL*)attribute.pValue;
+
+    if(val != 0x00 && val != 0x01){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return 0;
+    }
+
+    return val;
+}
+
+u1Array* StorageObject::ReadU1ArrayFromAttribute(CK_ATTRIBUTE attribute)
+{
+    u1Array* val = new u1Array(attribute.ulValueLen);
+    val->SetBuffer((CK_BYTE_PTR)attribute.pValue);
+
+    return val;
+}
+
+u1Array* StorageObject::ReadDateFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+    if(attribute.ulValueLen != 8){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return NULL_PTR;
+    }
+
+    return StorageObject::ReadU1ArrayFromAttribute(attribute);
+}
+
+u1Array* StorageObject::ReadStringFromAttribute(CK_ATTRIBUTE attribute,CK_RV* /*rv*/)
+{
+
+    // [HB]: Shall support UTF-8
+
+    //for(u4 i=0;i<attribute.ulValueLen;i++){
+
+    //    CK_BYTE bval = ((CK_BYTE_PTR)attribute.pValue)[i];
+
+    //    if((bval < 0x20)||(bval > 0x7D)||(bval == 0x24)||(bval == 0x40)||(bval == 0x60)){
+    //        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+    //        return NULL_PTR;
+    //    }
+    //}
+
+    return StorageObject::ReadU1ArrayFromAttribute(attribute);
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/storageobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,74 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_storageobject_h
+#define _include_storageobject_h
+
+#include <string>
+#include <MarshallerCfg.h>
+#include <Array.h>
+#include <vector>
+
+using namespace std;
+using namespace Marshaller;
+
+class StorageObject {
+
+
+public:
+    CK_BBOOL        _version;       // Version is used to manage evolution of the storage.
+    u8              _uniqueId;      // A random number that identifies this object
+    CK_ULONG		_class;
+    CK_BBOOL		_tokenObject;
+    CK_BBOOL		_private;
+    CK_BBOOL		_modifiable;
+    u1Array*		_label;
+
+    // extra fields (not part of PKCS#11 spec
+    std::string     _fileName;      // name of the file in the card which contains this object
+
+    StorageObject();
+    virtual ~StorageObject();
+
+    virtual bool IsEqual(const StorageObject * that) const;
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+protected:
+    static CK_RV PutU1ArrayInAttribute(u1Array* value,CK_ATTRIBUTE_PTR attribute);
+    static CK_RV PutU4ArrayInAttribute(u4Array* value,CK_ATTRIBUTE_PTR attribute);
+    static CK_RV PutULongInAttribute(CK_ULONG value, CK_ATTRIBUTE_PTR attribute);
+    static CK_RV PutBBoolInAttribute(CK_BBOOL value, CK_ATTRIBUTE_PTR attribute);
+
+    static CK_BBOOL ReadBBoolFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+    static CK_ULONG ReadULongFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+    static u1Array* ReadU1ArrayFromAttribute(CK_ATTRIBUTE attribute);
+    static u1Array* ReadDateFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+    static u1Array* ReadStringFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+};
+
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,224 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+
+CSymmAlgo::CSymmAlgo(){
+    this->_cipherMode  = CIPHER_MODE_CBC;
+    this->_paddingMode = PADDING_MODE_PKCS7;
+    this->_iv          = NULL_PTR;
+    this->_key         = NULL_PTR;
+}
+
+CSymmAlgo::~CSymmAlgo(){
+    if(this->_key != NULL_PTR)
+        free(this->_key);
+}
+
+void CSymmAlgo::SetKey(CK_BYTE_PTR key,CK_LONG keyLength){
+    this->_key       = (CK_BYTE_PTR)malloc(keyLength);
+    this->_keyLength = keyLength;
+
+    memcpy(this->_key,key,keyLength);
+}
+
+void CSymmAlgo::SetIV(CK_BYTE_PTR iv){
+    this->_iv = iv;
+}
+
+void CSymmAlgo::SetEncryptMode(CK_LONG mode){
+    this->_encryptMode = mode;
+}
+
+void CSymmAlgo::SetCipherMode(CK_LONG cmode){
+    this->_cipherMode = cmode;
+}
+
+void CSymmAlgo::SetPaddingMode(CK_LONG pmode){
+    this->_paddingMode = pmode;
+}
+
+CK_LONG CSymmAlgo::GetOutputLength(CK_LONG input_count){
+
+    CK_LONG outputLen;
+
+    if(this->_encryptMode == ENCRYPT){
+        outputLen = input_count & -this->_blockSize;
+
+        switch(this->_paddingMode){
+
+            case PADDING_MODE_ISO9797M2:
+            case PADDING_MODE_PKCS7:
+                // atleast 1 padding byte will be needed
+                if(input_count >= outputLen){
+                    outputLen += this->_blockSize;
+                }
+                break;
+
+            case PADDING_MODE_ZEROS:
+                if(input_count > outputLen){
+                    outputLen += this->_blockSize;
+                }
+                break;
+
+            case PADDING_MODE_NONE:
+                outputLen = input_count;
+                break;
+        }
+    }else{
+        outputLen = input_count;
+    }
+
+    return outputLen;
+}
+
+CK_LONG CSymmAlgo::TransformBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                                  CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    CK_LONG res = 0;
+    while (res != input_count)
+    {
+        TransformBlockInternal(_iv,_key,_encryptMode,input,input_offset,output,output_offset);
+
+        if (_cipherMode == CIPHER_MODE_CBC)
+        {
+            if (_encryptMode == ENCRYPT){
+                // last block of output becomes icv for next round.
+                memcpy(_iv,&output[output_offset],_blockSize);
+            }
+            else {
+                // last block of input becomes icv for next round.
+                memcpy(_iv,&input[input_offset],_blockSize);
+            }
+        }
+
+        // adjust offsets
+        input_offset += _blockSize;
+        res += _blockSize;
+        output_offset += _blockSize;
+    }
+
+    return res;
+}
+
+CK_LONG CSymmAlgo::TransformFinalBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                                       CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    CK_LONG workingLength;
+
+    if (((this->_paddingMode == PADDING_MODE_NONE) ||
+         (this->_encryptMode == DECRYPT)) &&
+         (input_count % _blockSize != 0))
+    {
+        PKCS11_ASSERT(CK_FALSE);
+    }
+
+    // prepare outbuffer in case of encryption
+    if (this->_encryptMode == ENCRYPT)
+    {
+        // ~ round_down(inputCount, _blockSizeByte)
+        workingLength = input_count & -_blockSize;
+    }
+    else
+    {
+        // we're in Decrypt mode, hence workingLength is % _blockSizeByte
+        workingLength = input_count;
+    }
+
+    if (workingLength > 0)
+    {
+        // compute the workingLength length part (% _blockSizeByte)
+        TransformBlock(input,input_offset, workingLength,output,output_offset);
+
+        input_offset += workingLength;
+        output_offset += workingLength;
+        input_count -= workingLength;
+    }
+
+    if (this->_encryptMode == DECRYPT)
+    {
+        switch (this->_paddingMode)
+        {
+            case PADDING_MODE_PKCS7:
+                // check the padding value make sense
+                if (output[output_offset - 1] > _blockSize){
+                    PKCS11_ASSERT(CK_FALSE);
+                }
+                workingLength -= output[output_offset - 1];
+                break;
+
+            case PADDING_MODE_ISO9797M2:
+                // remove trailing zeros
+                while (output[output_offset - 1] == 0x00){
+                    workingLength--;
+                    output_offset--;
+                }
+                // check initial byte is 0x80
+                if (output[output_offset - 1] != 0x80){
+                    PKCS11_ASSERT(CK_FALSE);
+                }
+                workingLength--;
+                break;
+
+            // note when PaddingMode.Zeros is used, we do not remove the 0s (no way to differentiate from the actual data)
+        }
+    }
+    else
+    {
+        if ((this->_paddingMode == PADDING_MODE_PKCS7)
+            || (this->_paddingMode == PADDING_MODE_ISO9797M2)
+            || ((this->_paddingMode == PADDING_MODE_ZEROS) && (input_count > 0)))
+        {
+            CK_BYTE_PTR paddedIntput = (CK_BYTE_PTR)malloc(_blockSize);
+            memset(paddedIntput,0,_blockSize);
+
+            memcpy(paddedIntput,&input[input_offset],input_count);
+
+            // add padding information in buffer if relevant
+            switch (this->_paddingMode)
+            {
+                // set first bit to 1, all other bits already set to 0
+                case PADDING_MODE_ISO9797M2:
+                    paddedIntput[input_count] = 0x80;
+                    break;
+
+                case PADDING_MODE_PKCS7:
+                    CK_BYTE paddingValue = (CK_BYTE)(_blockSize - input_count);
+                    for (CK_LONG i = input_count; i < _blockSize; i++){
+                        paddedIntput[i] = paddingValue;
+                    }
+                    break;
+            }
+
+            // compute last block
+            TransformBlock(paddedIntput, 0, _blockSize, output, output_offset);
+
+            workingLength += _blockSize;
+
+            free(paddedIntput);
+        }
+    }
+
+    // over, let's return.
+    return workingLength;
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/symmalgo.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,72 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_symmalgo_h
+#define _include_symmalgo_h
+
+#define PADDING_MODE_ISO9797M2 1
+#define PADDING_MODE_NONE      2
+#define PADDING_MODE_PKCS7     3
+#define PADDING_MODE_ZEROS     4
+
+#define ENCRYPT 1
+#define DECRYPT 2
+
+#define CIPHER_MODE_CBC 1
+#define CIPHER_MODE_ECB 2
+
+class CSymmAlgo
+{
+
+protected:
+    CK_BYTE_PTR _iv;
+    CK_BYTE_PTR _key;
+    CK_LONG     _keyLength;
+    CK_LONG     _blockSize;
+    CK_LONG     _cipherMode;
+    CK_LONG     _paddingMode;
+    CK_LONG     _encryptMode;
+
+protected:
+    virtual void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                           CK_BYTE_PTR input,CK_LONG input_offset,
+                                           CK_BYTE_PTR output,CK_LONG output_offset) = 0;
+
+public:
+    CSymmAlgo();
+    virtual ~CSymmAlgo();
+
+    void SetKey(CK_BYTE_PTR key,CK_LONG keyLength);
+    void SetIV(CK_BYTE_PTR iv);
+    void SetEncryptMode(CK_LONG mode);
+    void SetCipherMode(CK_LONG cmode);
+    void SetPaddingMode(CK_LONG pmode);
+
+    CK_LONG GetOutputLength(CK_LONG input_count);
+
+    CK_LONG TransformBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                           CK_BYTE_PTR output,CK_LONG output_offset);
+
+    CK_LONG TransformFinalBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                                CK_BYTE_PTR output,CK_LONG output_offset);
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,53 @@
+
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+#include "tdes.h"
+
+CTripleDES::CTripleDES(){
+    this->_blockSize = 8;
+}
+
+CTripleDES::~CTripleDES(){
+}
+
+void CTripleDES::TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                        CK_BYTE_PTR input,CK_LONG input_offset,
+                                        CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    // encryprtMode == ENCRYPT then we need to XOR input with iv
+    if(iv != NULL_PTR && this->_encryptMode == ENCRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            input[input_offset+i] ^= iv[i];
+        }
+    }
+
+    algo_DES_3DESProcess((u1)_keyLength,key,&input[input_offset],&output[output_offset],(u1)encryptMode);
+
+    if(iv != NULL_PTR && this->_encryptMode == DECRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            output[output_offset+i] ^= iv[i];
+        }
+    }
+}
+
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/tdes.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,42 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_tdes_h
+#define _include_tdes_h
+
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+class CTripleDES : public CSymmAlgo
+{
+
+public:
+    CTripleDES();
+    ~CTripleDES();
+
+private:
+    void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                CK_BYTE_PTR input,CK_LONG input_offset,
+                                CK_BYTE_PTR output,CK_LONG output_offset);
+
+};
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/template.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/template.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/template.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,303 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "template.h"
+
+Template::Template(CK_ATTRIBUTE_PTR attrTemplate,CK_ULONG ulCount){
+
+
+   for(CK_ULONG i=0;i<ulCount;i++){
+      CK_ATTRIBUTE attribute;
+
+      attribute.type = attrTemplate[i].type;
+      attribute.ulValueLen = attrTemplate[i].ulValueLen;
+      attribute.pValue = NULL_PTR;
+
+      if(attribute.ulValueLen > 0) {
+         attribute.pValue = malloc(attribute.ulValueLen);
+         memcpy(attribute.pValue, attrTemplate[i].pValue, attribute.ulValueLen);
+      }
+
+      this->_attributes.push_back(attribute);
+   }
+}
+
+
+Template::~Template( )
+{
+   std::vector<CK_ATTRIBUTE>::size_type sz = _attributes.size( );
+   for( std::vector<CK_ATTRIBUTE>::size_type i = 0 ; i < sz ; i++ )
+   {
+      if( NULL_PTR != _attributes[ i ].pValue )
+      {
+         free( _attributes[ i ].pValue );
+      }
+   }
+}
+
+
+void Template::FixEndianness(CK_ATTRIBUTE attrTemplate)
+{
+   // Only for Little Endian processors
+   if (IS_LITTLE_ENDIAN)
+   {
+      // we need to fix the endianness if
+      // we are dealing with data on 2 or 4 or 8 bytes
+      switch(attrTemplate.ulValueLen)
+      {
+      case 2:
+      case 4:
+      case 8:
+         {
+            // fix up needs to be done for specific
+            // attributes. Byte arrays may have sizes of 2,4 or 8
+            switch(attrTemplate.type)
+            {
+               // CK_ULONG data types
+            case CKA_CLASS:
+            case CKA_CERTIFICATE_TYPE:
+            case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+            case CKA_KEY_TYPE:
+            case CKA_KEY_GEN_MECHANISM:
+            case CKA_MODULUS_BITS:
+               {
+                  PKCS11_ASSERT(attrTemplate.ulValueLen == sizeof(CK_ULONG));
+                  CK_BYTE b1 = ((CK_BYTE_PTR)attrTemplate.pValue)[0];
+                  CK_BYTE b2 = ((CK_BYTE_PTR)attrTemplate.pValue)[1];
+                  CK_BYTE b3 = ((CK_BYTE_PTR)attrTemplate.pValue)[2];
+                  CK_BYTE b4 = ((CK_BYTE_PTR)attrTemplate.pValue)[3];
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[3] = b1;
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[2] = b2;
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[1] = b3;
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[0] = b4;
+               }
+               break;
+            }
+         }
+         break;
+
+      default:
+         break;
+      }
+   }
+}
+
+CK_ULONG Template::FindClassFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == CKA_CLASS)
+      {
+         return *(CK_ULONG*)pTemplate[idx].pValue;
+      }
+   }
+
+   return (CK_ULONG)-1;
+}
+
+CK_ULONG Template::FindCertTypeFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == CKA_CERTIFICATE_TYPE)
+      {
+         return *(CK_ULONG*)pTemplate[idx].pValue;
+      }
+   }
+
+   return (CK_ULONG)-1;
+}
+
+CK_BBOOL Template::FindTokenFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == CKA_TOKEN)
+      {
+         return *(CK_BBOOL*)pTemplate[idx].pValue;
+      }
+   }
+
+   return CK_FALSE;
+}
+
+CK_BBOOL Template::IsAttrInTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_ATTRIBUTE_TYPE AttrType)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == AttrType)
+      {
+         return CK_TRUE;
+      }
+   }
+
+   return CK_FALSE;
+}
+
+CK_RV Template::CheckTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_BYTE bMode)
+{
+   CK_OBJECT_CLASS     ObjClass = (CK_ULONG)-1;
+   CK_CERTIFICATE_TYPE CertType = (CK_ULONG)-1;
+
+   // Get Object Class
+   ObjClass = FindClassFromTemplate(pTemplate, ulCount);
+
+   // Get Cert Type
+   if (ObjClass == CKO_CERTIFICATE)
+   {
+      CertType = FindCertTypeFromTemplate(pTemplate, ulCount);
+   }
+
+   // Check Creation Template
+   if (bMode == MODE_CREATE)
+   {
+      switch (ObjClass)
+      {
+      case CKO_DATA:
+         {
+            if (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+            {
+               return CKR_OK;
+            }
+         }
+         break;
+
+      case CKO_CERTIFICATE:
+         {
+            if (CertType == CKC_X_509)
+            {
+               if (  (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_SUBJECT))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_VALUE))
+                  )
+               {
+                  return CKR_OK;
+               }
+            }
+
+            else if (CertType == CKC_X_509_ATTR_CERT)
+            {
+               if (  (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_OWNER))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_VALUE))
+                  )
+               {
+                  return CKR_OK;
+               }
+            }
+
+            else
+            {
+               return CKR_TEMPLATE_INCONSISTENT;
+            }
+         }
+         break;
+
+      case CKO_PUBLIC_KEY:
+         {
+            if (  ( IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_TYPE))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS_BITS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+               )
+            {
+               return CKR_OK;
+            }
+         }
+         break;
+
+      case CKO_PRIVATE_KEY:
+         {
+            if (  ( IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_TYPE))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_ALWAYS_SENSITIVE))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_NEVER_EXTRACTABLE))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIVATE_EXPONENT))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_1))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_2))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_1))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_2))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_COEFFICIENT))
+               )
+            {
+               return CKR_OK;
+            }
+         }
+         break;
+
+      default:
+         return CKR_TEMPLATE_INCONSISTENT;
+      }
+   }
+
+   // Check Public Key Generation Template
+   else if (bMode == MODE_GENERATE_PUB)
+   {
+      if (  (!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+         &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS_BITS))
+         &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+         )
+      {
+         return CKR_OK;
+      }
+   }
+
+   // Check Private Key Generation Template
+   else if (bMode == MODE_GENERATE_PRIV)
+   {
+      if (  (!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_ALWAYS_SENSITIVE))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_NEVER_EXTRACTABLE))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIVATE_EXPONENT))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_1))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_2))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_1))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_2))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_COEFFICIENT))
+         )
+      {
+         return CKR_OK;
+      }
+   }
+
+   return CKR_TEMPLATE_INCONSISTENT;
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/template.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/template.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/template.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,56 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_template_h
+#define _include_template_h
+
+#include <list>
+#include <vector>
+
+using namespace std;
+
+#define MODE_CREATE        0x01
+#define MODE_GENERATE_PUB  0x02
+#define MODE_GENERATE_PRIV 0x03
+
+class Template
+{
+
+public:
+    vector<CK_ATTRIBUTE> _attributes;
+
+public:
+    Template(CK_ATTRIBUTE_PTR temp,CK_ULONG ulCount);
+    ~Template();
+
+    static void FixEndianness(CK_ATTRIBUTE attrTemplate);
+
+    static CK_ULONG FindClassFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    static CK_ULONG FindCertTypeFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    static CK_BBOOL FindTokenFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    static CK_BBOOL IsAttrInTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_ATTRIBUTE_TYPE AttrType);
+    static CK_RV CheckTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_BYTE bMode);
+
+};
+
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/thread.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/thread.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/thread.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,312 @@
+
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include <string>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include "thread.h"
+
+#ifdef WIN32
+const CK_LONG CThread::P_ABOVE_NORMAL = THREAD_PRIORITY_ABOVE_NORMAL;
+const CK_LONG CThread::P_BELOW_NORMAL = THREAD_PRIORITY_BELOW_NORMAL;
+const CK_LONG CThread::P_HIGHEST      = THREAD_PRIORITY_HIGHEST;
+const CK_LONG CThread::P_IDLE         = THREAD_PRIORITY_IDLE;
+const CK_LONG CThread::P_LOWEST       = THREAD_PRIORITY_LOWEST;
+const CK_LONG CThread::P_NORMAL       = THREAD_PRIORITY_NORMAL;
+const CK_LONG CThread::P_CRITICAL     = THREAD_PRIORITY_TIME_CRITICAL;
+#endif
+
+CThread::CThread()
+{
+#ifdef WIN32
+    m_hThread = NULL;
+#endif
+    m_strName = NULL;
+    m_stopRequested = false;
+}
+
+CThread::CThread(const char* nm)
+{
+#ifdef WIN32
+    m_hThread = NULL;
+#endif
+    m_strName = new std::string(nm);
+}
+
+CThread::~CThread()
+{
+#ifdef WIN32
+    if(m_hThread != NULL)
+    {
+        if(m_strName != NULL)
+        {
+            delete m_strName;
+        }
+        stop();
+    }
+#else
+
+#endif
+}
+
+void CThread::setName(const char* nm)
+{
+    m_strName = new std::string(nm);
+}
+
+std::string* CThread::getName() const
+{
+    return m_strName;
+}
+
+void CThread::run()
+{
+    // Base run
+}
+
+void CThread::sleep(CK_LONG ms)
+{
+#ifdef WIN32
+    Sleep(ms);
+#else
+    usleep(ms*1000);
+#endif
+}
+
+void CThread::start()
+{
+
+#ifdef WIN32
+    DWORD tid = 0;
+    m_hThread = (unsigned long*)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_ou_thread_proc,(CThread*)this,0,&tid);
+
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Failed to create thread");
+    }
+    else
+    {
+        setPriority(CThread::P_NORMAL);
+    }
+
+#else
+
+    pthread_create(&m_hThread,0,_ou_thread_proc,(CThread*)this);
+
+#endif
+
+}
+
+void CThread::stop()
+{
+#ifdef WIN32
+    if(m_hThread == NULL) return;
+
+    m_stopRequested = true;
+
+    DWORD dwTimeout = 1000;
+    DWORD dwSleepTime = 10;
+    DWORD dwExitCode = STILL_ACTIVE;
+
+    for(DWORD i=0; i< dwTimeout/dwSleepTime; i++)
+    {
+        if(GetExitCodeThread(m_hThread, &dwExitCode))
+        {
+            if(dwExitCode!=STILL_ACTIVE)
+                break;
+        }
+        else
+            break; // Some error
+        Sleep(dwSleepTime);
+    }
+
+    if( dwExitCode == STILL_ACTIVE )
+        TerminateThread(m_hThread, 0);
+
+    // Never do this.
+    ///WaitForSingleObject(m_hThread,INFINITE);
+    CloseHandle(m_hThread);
+    m_hThread = NULL;
+
+    m_stopRequested = false;
+
+#else
+
+    m_stopRequested = true;
+
+    pthread_join(m_hThread,NULL);
+
+    m_stopRequested = false;
+
+#endif
+}
+
+CK_BBOOL CThread::isStopRequested()
+{
+    return m_stopRequested;
+}
+
+#ifdef WIN32
+void CThread::setPriority(CK_LONG tp)
+#else
+void CThread::setPriority( CK_LONG )
+#endif
+{
+#ifdef WIN32
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Thread object is null");
+    }
+    else
+    {
+        if(SetThreadPriority(m_hThread,tp) == 0)
+        {
+            assert(FALSE);
+            //throw ThreadException("Failed to set priority");
+        }
+    }
+#else
+#endif
+}
+
+void CThread::suspend()
+{
+
+#ifdef WIN32
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Thread object is null");
+    }
+    else
+    {
+        if((int)SuspendThread(m_hThread) < 0)
+        {
+            assert(FALSE);
+            //throw ThreadException("Failed to suspend thread");
+        }
+    }
+#else
+#endif
+}
+
+void CThread::resume()
+{
+#ifdef WIN32
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Thread object is null");
+    }
+    else
+    {
+        if((int)ResumeThread(m_hThread) < 0)
+        {
+            assert(FALSE);
+            //throw ThreadException("Failed to resume thread");
+        }
+    }
+#else
+#endif
+}
+
+#ifdef WIN32
+CK_BBOOL CThread::wait(const char* m,CK_LONG ms)
+#else
+CK_BBOOL CThread::wait( const char*, CK_LONG )
+#endif
+{
+#ifdef WIN32
+    HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
+
+    if(h == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Mutex not found");
+    }
+    DWORD d = WaitForSingleObject(h,ms);
+
+    switch(d)
+    {
+    case WAIT_ABANDONED:
+        assert(FALSE);
+        //throw ThreadException("Mutex not signaled");
+        break;
+    case WAIT_OBJECT_0:
+        return true;
+    case WAIT_TIMEOUT:
+        assert(FALSE);
+        //throw ThreadException("Wait timed out");
+        break;
+    }
+    return false;
+#else
+    return false;
+#endif
+}
+
+#ifdef WIN32
+void CThread::release(const char* m)
+#else
+void CThread::release( const char* )
+#endif
+{
+#ifdef WIN32
+    HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
+    if(h == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Invalid mutex handle");
+    }
+    if(ReleaseMutex(h) == 0)
+    {
+        assert(FALSE);
+        //throw ThreadException("Failed to release mutex");
+    }
+#else
+#endif
+}
+
+#ifdef WIN32
+// global thread caallback
+unsigned int _ou_thread_proc(void* param)
+{
+    CThread* tp = (CThread*)param;
+    tp->run();
+    return 0;
+}
+#else
+void* _ou_thread_proc(void* param)
+{
+    CThread* tp = (CThread*)param;
+    tp->run();
+    return NULL;
+}
+#endif
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/thread.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/thread.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/thread.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,91 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_thread_h
+#define _include_thread_h
+
+#include <string>
+
+#ifdef INCLUDE_EVENTING
+
+using namespace std;
+
+class CThread
+{
+
+private:
+    // unsigned long* to the low-level thread object
+#ifdef WIN32
+    CK_ULONG_PTR m_hThread;
+#else
+    pthread_t 	 m_hThread;
+#endif
+
+    // a name to identify the thread
+    std::string* m_strName;
+    CK_BBOOL     m_stopRequested;
+
+public:
+    CThread();
+    CThread(const char* nm);
+    virtual ~CThread();
+
+    void setName(const char* nm);
+    std::string* getName() const;
+
+    void start();
+    virtual void run();
+    void sleep(CK_LONG ms);
+    void suspend();
+    void resume();
+    virtual void stop();
+
+    void setPriority(CK_LONG p);
+    CK_BBOOL isStopRequested();
+
+    CK_BBOOL wait(const char* m,CK_LONG ms=5000);
+    void release(const char* m);
+
+public:
+    // Thread priorities
+    static const CK_LONG P_ABOVE_NORMAL;
+    static const CK_LONG P_BELOW_NORMAL;
+    static const CK_LONG P_HIGHEST;
+    static const CK_LONG P_IDLE;
+    static const CK_LONG P_LOWEST;
+    static const CK_LONG P_NORMAL;
+    static const CK_LONG P_CRITICAL;
+};
+
+// global function called by the thread object.
+// this in turn calls the overridden run()
+extern "C"
+{
+#ifdef WIN32
+    unsigned int _ou_thread_proc(void* param);
+#else
+    void* _ou_thread_proc(void* param);
+#endif
+}
+
+#endif
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/timer.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/timer.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/timer.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,49 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "timer.h"
+
+#if defined(_WIN32)
+#include "Windows.h"
+#else
+#include <inttypes.h>
+#include <sys/time.h>
+#endif
+
+unsigned long CTimer::ClockTicks()
+{
+#if defined(_WIN32)
+    return GetTickCount();
+#else
+    static uint64_t startuptime = 0;
+    struct timeval t;
+
+    if(!startuptime) {
+        gettimeofday(&t,0);
+        startuptime = t.tv_sec*1000 + t.tv_usec/1000;
+    }
+
+    gettimeofday(&t,0);
+    uint64_t time = t.tv_sec*1000 + t.tv_usec/1000 - startuptime;
+    return (unsigned long)(time & 0xFFFFFFFF);
+
+#endif
+
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/timer.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/timer.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/timer.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,31 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_timer_h
+#define _include_timer_h
+
+class CTimer
+{
+public:
+    static unsigned long ClockTicks();
+};
+
+#endif // _include_timer_h
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,57 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "transaction.h"
+#include "cardmoduleservice.h"
+
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "session.h"
+#include "slot.h"
+#include "sctoken.h"
+#include "error.h"
+
+
+Transaction::Transaction(Slot * slot) : _slot(slot)
+{
+
+    if(!slot || !slot->_token)
+        throw CkError(CKR_FUNCTION_FAILED);
+
+    _slot->_token->BeginTransaction();
+
+    // As a result of card re-set, user may have been logged out
+    _slot->UpdateSessionState();
+}
+
+Transaction::~Transaction() throw()
+{
+    if(!_slot || !_slot->_token)
+        return;
+
+    try
+    {
+        _slot->_token->EndTransaction();
+    }
+    catch(...) {}
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/transaction.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,37 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_transaction_h
+#define _include_transaction_h
+
+class Slot;
+
+/** Class that manages token transaction */
+class Transaction
+{
+public:
+    Transaction(Slot * slot);
+    ~Transaction() throw();
+
+private:
+    Slot * _slot;
+};
+
+#endif

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/util.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/util.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/util.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,373 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "digest.h"
+#include "sha1.h"
+#include "error.h"
+#include "util.h"
+
+R_RANDOM_STRUCT Util::_randomStruct;
+
+void Util::SeedRandom(u1Array const & seed)
+{
+    InitRandomStruct(&_randomStruct);
+    R_RandomUpdate(&_randomStruct, const_cast<unsigned char*>(seed.GetBuffer()), seed.GetLength());
+}
+
+R_RANDOM_STRUCT & Util::RandomStruct()
+{
+    return _randomStruct;
+}
+
+CK_ULONG Util::MakeULong(CK_BYTE_PTR buffer,CK_ULONG offset)
+{
+    return (CK_ULONG)(((CK_ULONG)buffer[offset] << 24) | ((CK_ULONG)buffer[offset+1] << 16) | ((CK_ULONG)buffer[offset+2] << 8) | buffer[offset+3]);
+}
+
+CK_BBOOL Util::CompareByteArrays(CK_BYTE_PTR abuffer,CK_BYTE_PTR bbuffer,CK_ULONG len)
+{
+    for(CK_ULONG i=0;i<len;i++){
+        if(abuffer[i] != bbuffer[i])
+            return CK_FALSE;
+    }
+
+
+    return CK_TRUE;
+}
+
+CK_BBOOL Util::CompareU1Arrays(u1Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len)
+{
+    if((abuffer == NULL_PTR) && (bbuffer == NULL_PTR)){
+        return CK_TRUE;
+    }
+
+    if((abuffer != NULL_PTR) && (bbuffer != NULL_PTR)){
+        if(len == abuffer->GetLength()){
+            return Util::CompareByteArrays(abuffer->GetBuffer(),(CK_BYTE_PTR)bbuffer,len);
+        }
+    }
+
+    return CK_FALSE;
+}
+
+
+CK_BBOOL Util::CompareU4Arrays(u4Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len)
+{
+    if((abuffer == NULL_PTR) && (bbuffer == NULL_PTR)){
+        return CK_TRUE;
+    }
+
+    if((abuffer != NULL_PTR) && (bbuffer != NULL_PTR)){
+        if(len == abuffer->GetLength()){
+            return Util::CompareByteArrays((u1*)abuffer->GetBuffer(),(CK_BYTE_PTR)bbuffer,len);
+        }
+    }
+
+    return CK_FALSE;
+}
+
+void Util::PushULongInVector(vector<u1>* to, CK_ULONG value)
+{
+    to->push_back((u1)(value >> 24));
+    to->push_back((u1)(value >> 16));
+    to->push_back((u1)(value >> 8));
+    to->push_back((u1)(value));
+}
+
+void Util::PushULongLongInVector(vector<u1>* to, u8 value)
+{
+    to->push_back((u1)(value >> 56));
+    to->push_back((u1)(value >> 48));
+    to->push_back((u1)(value >> 40));
+    to->push_back((u1)(value >> 32));
+    to->push_back((u1)(value >> 24));
+    to->push_back((u1)(value >> 16));
+    to->push_back((u1)(value >> 8));
+    to->push_back((u1)(value));
+}
+
+void Util::PushBBoolInVector(std::vector<u1>* to, CK_BBOOL value)
+{
+    // push the value
+    to->push_back(value);
+}
+
+void Util::PushByteArrayInVector(std::vector<u1>* to, u1Array *value)
+{
+    if((value == NULL_PTR) || value->GetLength() == 0){
+        to->push_back(0);
+    }else{
+        Util::PushLengthInVector(to,value->GetLength());
+        for(u4 i=0;i<value->GetLength();i++){
+            to->push_back(value->GetBuffer()[i]);
+        }
+    }
+}
+
+void Util::PushIntArrayInVector(std::vector<u1>* to, u4Array *value)
+{
+    if((value == NULL_PTR) || value->GetLength() == 0){
+        to->push_back(0);
+    }else{
+        Util::PushLengthInVector(to,(value->GetLength() * 4));
+        u1* buffer = (u1*)value->GetBuffer();
+        for(u4 i=0;i<(value->GetLength() * 4);i++){
+            to->push_back(buffer[i]);
+        }
+    }
+}
+
+u1Array* Util::ReadByteArrayFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG len = Util::ReadLengthFromVector(from,idx);
+
+    if(len == 0){
+        return NULL_PTR;
+    }
+
+    u1Array* val = new u1Array(len);
+
+    for(u4 i=0;i<len;i++){
+        val->SetU1At(i,from.at(*idx));
+        *idx = *idx + 1;
+    }
+
+    return val;
+}
+
+u4Array* Util::ReadIntArrayFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG len = Util::ReadLengthFromVector(from,idx);
+
+    if(len == 0){
+        return NULL_PTR;
+    }
+
+    u4Array* val = new u4Array(len/4);
+
+    for(u4 i=0;i<(len/4);i++){
+
+        u1 a = from.at(*idx);
+        u1 b = from.at(*idx + 1);
+        u1 c = from.at(*idx + 2);
+        u1 d = from.at(*idx + 3);
+
+        // make an int
+        u4 anInt = (u4)(((u4)a << 24) | ((u4)b << 16) | ((u4)c << 8) | d);
+
+        val->SetU4At(i,anInt);
+
+        *idx = *idx + 4;
+    }
+
+    return val;
+}
+
+void Util::PushLengthInVector(std::vector<u1>* to, CK_USHORT len)
+{
+    if(len < (CK_USHORT)0x80){
+        to->push_back(len & 0x7F);
+    }else if(len <= (CK_USHORT)0xFF){
+        to->push_back(0x81);
+        to->push_back(len & 0xFF);
+    }else{
+        to->push_back(0x82);
+        to->push_back((u1)((len >> 8) & 0x00FF));
+        to->push_back((u1)(len));
+    }
+}
+
+CK_ULONG Util::ReadLengthFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_USHORT val = (CK_USHORT)from.at(*idx);
+
+    if(val < (CK_USHORT)0x80){
+        *idx = *idx + 1;
+        return val;
+    }else if(val == 0x81){
+        *idx = *idx + 1;
+        val = from.at(*idx);
+        *idx = *idx + 1;
+        return val;
+    }else if(val == 0x82){
+        *idx = *idx + 1;
+        val = (u2)(((u2)from.at(*idx)) << 8);
+        *idx = *idx + 1;
+        val = val | (u2)from.at(*idx);
+        *idx = *idx + 1;
+        return val;
+    }
+
+    PKCS11_ASSERT(CK_FALSE);
+
+    return 0;
+}
+
+CK_BBOOL Util::ReadBBoolFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_BBOOL val = (CK_BBOOL)from.at(*idx);
+    *idx = *idx + 1;
+
+    return val;
+}
+
+CK_ULONG Util::ReadULongFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG offset = *idx;
+
+    CK_ULONG val = (CK_ULONG)(((CK_ULONG)from.at(offset) << 24) | ((CK_ULONG)from.at(offset+1) << 16) | ((CK_ULONG)from.at(offset+2) << 8) | from.at(offset+3));
+
+    *idx = *idx + 4;
+
+    return val;
+}
+
+u8 Util::ReadULongLongFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG offset = *idx;
+
+    u8 val = (u8)(((u8)from.at(offset  ) << 56) | ((u8)from.at(offset+1) << 48) |
+                  ((u8)from.at(offset+2) << 40) | ((u8)from.at(offset+3) << 32) |
+                  ((u8)from.at(offset+4) << 24) | ((u8)from.at(offset+5) << 16) |
+                  ((u8)from.at(offset+6) <<  8) | from.at(offset+7));
+
+    *idx = *idx + 8;
+
+    return val;
+}
+
+void Util::ConvAscii(u1 *pIn, u4 dwLen,u1 *pOut)
+{
+   #define tohex(x)  (((x) >= 0xA) ? ((x) - 0xA + 'A') : ((x) + '0'))
+   register u4 i;
+
+   for(i=0; i < dwLen; i++)
+   {
+      pOut[i*2] = tohex((pIn[i] >> 4) & 0xF);
+      pOut[i*2+1] =  tohex(pIn[i] & 0xF);
+   }
+   #undef tohex
+}
+
+char* Util::ItoA(s4 value, char* str, s4 radix)
+{
+
+#ifdef WIN32
+
+    return _itoa(value,str,radix);
+
+#else
+
+    s4  rem = 0;
+    s4  pos = 0;
+    char ch  = '!' ;
+
+    do
+    {
+        rem    = value % radix ;
+        value /= radix;
+        if ( 16 == radix )
+        {
+            if( rem >= 10 && rem <= 15 )
+            {
+                switch( rem )
+                {
+                    case 10:
+                        ch = 'a' ;
+                        break;
+                    case 11:
+                        ch ='b' ;
+                        break;
+                    case 12:
+                        ch = 'c' ;
+                        break;
+                    case 13:
+                        ch ='d' ;
+                        break;
+                    case 14:
+                        ch = 'e' ;
+                        break;
+                    case 15:
+                        ch ='f' ;
+                        break;
+                }
+            }
+        }
+        if( '!' == ch )
+        {
+            str[pos++] = (char) ( rem + 0x30 );
+        }
+        else
+        {
+            str[pos++] = ch ;
+        }
+    }while( value != 0 );
+
+    str[pos] = '\0' ;
+
+    int i = strlen(str);
+    int t = !(i%2)? 1 : 0;      // check the length of the string .
+
+    for(int j = i-1 , k = 0 ; j > (i/2 -t) ; j-- )
+    {
+        char ch2  = str[j];
+        str[j]   = str[k];
+        str[k++] = ch2;
+    }
+
+    return str;
+
+#endif
+
+}
+
+u8 Util::MakeCheckValue(const unsigned char * pBuf, unsigned int length)
+{
+    CSHA1 sha1;
+    u1 hash[20];
+    sha1.HashCore(const_cast<unsigned char *>(pBuf), 0, length);
+    sha1.HashFinal(hash);
+    u8 val = 0;
+    for(size_t i = 0; i< sizeof(u8); ++i)
+        val = (val << 8) | hash[i];
+    return val;
+}
+
+u8 Util::MakeUniqueId()
+{
+    unsigned char buf[8];
+    if(R_GenerateBytes(buf, 8, &_randomStruct))
+        throw CkError(CKR_FUNCTION_FAILED);
+    u8 * value = reinterpret_cast<u8*>(buf);
+    return *value;
+}
+
+string Util::MakeIntString(unsigned int number, int width)
+{
+    if(width < 1)
+        return string();
+    char temp[16];
+    sprintf(temp, "%011d", number);
+    string s(temp);
+    return s.substr(s.size()-width, width);
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/util.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/util.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/util.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,107 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_util_h
+#define _include_util_h
+
+#include <string>
+#include <vector>
+
+#include <MarshallerCfg.h>
+#include <Array.h>
+#include <cr_random.h>
+
+using namespace std;
+using namespace Marshaller;
+
+// Very simple class similar to auto_ptr, but for arrays.
+// It means that it calls delete[] instead of delete.
+template<class T> class autoarray
+{
+public:
+    autoarray(T* t) : _t(t) {}
+    ~autoarray() { delete [] _t; }
+    T * get() { return _t; }
+    T & operator[](size_t index) { return _t[index]; }
+    const T & operator[](size_t index) const { return _t[index]; }
+
+private:
+    T * _t;
+};
+
+template<typename T> void IntToLittleEndian(T t, unsigned char * buf, size_t offset = 0)
+{
+    size_t n = sizeof(T);
+    for(size_t i = 0; i < n; i++)
+    {
+        buf[offset+i] = static_cast<unsigned char>(t & 0xFF);
+        t >>= 8;
+    }
+}
+
+template<typename T> T LittleEndianToInt(const unsigned char * buf, size_t offset = 0)
+{
+    size_t n = sizeof(T);
+    T t = 0;
+    for(size_t i = 0; i < n; i++)
+    {
+        t <<= 8;
+        t |= buf[offset+n-i-1];
+    }
+    return t;
+}
+
+class Util{
+
+public:
+    static void SeedRandom(u1Array const & seed);
+    static R_RANDOM_STRUCT & RandomStruct();
+
+    static CK_ULONG MakeULong(CK_BYTE_PTR pValue,CK_ULONG offset);
+    static CK_BBOOL CompareByteArrays(CK_BYTE_PTR abuffer,CK_BYTE_PTR bbuffer,CK_ULONG len);
+    static void PushULongInVector(vector<u1>* to,CK_ULONG value);
+    static void PushULongLongInVector(vector<u1>* to,u8 value);
+    static void PushBBoolInVector(vector<u1>* to,CK_BBOOL value);
+    static void PushByteArrayInVector(vector<u1>* to,u1Array* value);
+    static void PushIntArrayInVector(vector<u1>* to,u4Array* value);
+    static void PushLengthInVector(vector<u1>* to,CK_USHORT len);
+    static CK_ULONG ReadLengthFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static CK_ULONG ReadULongFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static u8       ReadULongLongFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static CK_BBOOL ReadBBoolFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static u1Array* ReadByteArrayFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static u4Array* ReadIntArrayFromVector(vector<u1> from,CK_ULONG_PTR idx);
+
+    static CK_BBOOL CompareU1Arrays(u1Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len);
+    static CK_BBOOL CompareU4Arrays(u4Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len);
+    static void ConvAscii(u1 *pIn, u4 dwLen,u1 *pOut);
+    static char* ItoA(s4 value, char* str, s4 radix);
+    static u8 MakeCheckValue(const unsigned char * pBuf, unsigned int length);
+    static u8 MakeUniqueId();
+    static std::string MakeIntString(unsigned int number, int width);
+
+private:
+    static R_RANDOM_STRUCT _randomStruct;
+
+};
+
+
+#endif
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,564 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This implementation is based on RFC 2459 which can be fetched from
+// http://www.ietf.org.
+
+// This code is based on class in ACS baseline.
+
+//#include "slbPki.h"
+#include "x509cert.h"
+
+using namespace std;
+
+X509Cert::X509Cert()
+{
+}
+
+X509Cert::X509Cert(const X509Cert &cert)
+{
+   *this = cert;
+}
+
+X509Cert::X509Cert(const BEROctet::Blob &buffer)
+{
+   *this = buffer;
+}
+
+X509Cert::X509Cert(const unsigned char *buffer, const unsigned long size)
+{
+   m_Cert = BEROctet(BEROctet::Blob(buffer,size));
+   if(size != m_Cert.Octet().size())
+      throw runtime_error("X509CertFormatError");
+
+   Decode();
+}
+
+X509Cert& X509Cert::operator=(const X509Cert &cert)
+{
+   m_Cert = cert.m_Cert;
+   Decode();
+
+   return *this;
+}
+
+X509Cert& X509Cert::operator=(const BEROctet::Blob &buffer)
+{
+   m_Cert = BEROctet(buffer);
+   if(buffer.size() != m_Cert.Octet().size())
+      throw runtime_error("X509CertFormatError");
+   Decode();
+
+   return *this;
+}
+
+// Returns whole DER string of Serial Number.
+
+BEROctet::Blob X509Cert::SerialNumber() const
+{
+   return m_SerialNumber.Octet();
+}
+
+// Returns whole DER string of Issuer
+
+BEROctet::Blob X509Cert::Issuer() const
+{
+   return m_Issuer.Octet();
+}
+
+// Returns whole string of Issuer in UTF8.
+
+BEROctet::Blob X509Cert::UTF8Issuer() const
+{
+   return ToUTF8(m_Issuer.Tag(), m_Issuer.Octet() );
+}
+
+
+// Returns list of attributes in Issuer matching id-at-organizationName.
+// List will be invalidated when object changes.
+
+std::vector<std::string> X509Cert::IssuerOrg() const
+{
+
+   std::vector<std::string> orgNames;
+   std::vector<BEROctet const*> orgOcts;
+
+   m_Issuer.SearchOIDNext(OID_id_at_organizationName,orgOcts);
+
+   for(unsigned long i=0; i<orgOcts.size(); i++)
+      orgNames.push_back(string((char*)orgOcts[i]->Data().data(),orgOcts[i]->Data().size()));
+
+   return orgNames;
+
+}
+
+// Returns list of attributes in Issuer matching id-at-organizationName.
+// List will be invalidated when object changes.
+// the string in the list is in UTF8 format.
+
+std::vector<std::string> X509Cert::UTF8IssuerOrg() const
+{
+
+   std::vector<std::string> orgNames;
+   std::vector<BEROctet const*> orgOcts;
+
+   m_Issuer.SearchOIDNext(OID_id_at_organizationName,orgOcts);
+
+   for(unsigned long i=0; i<orgOcts.size(); i++)
+   {
+      BEROctet::Blob blbData = ToUTF8(orgOcts[i]->Tag(), orgOcts[i]->Data());
+      orgNames.push_back(string((char*)blbData.data(),blbData.size()));
+   }
+
+   return orgNames;
+}
+
+
+// Returns Validity notBefore attribute as "YYYYMMDDHHMMSS"
+
+string X509Cert::ValidityNotBefore() const
+{
+
+   if(m_Validity.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   return m_Validity.SubOctetList()[0]->Time();
+
+}
+
+// Returns Validity notAfter attribute as "YYYYMMDDHHMMSS"
+
+string X509Cert::ValidityNotAfter() const
+{
+
+   if(m_Validity.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   return m_Validity.SubOctetList()[1]->Time();
+
+}
+
+
+// Returns whole DER string of Subject
+
+BEROctet::Blob X509Cert::Subject() const
+{
+   return m_Subject.Octet();
+}
+
+// Returns Subject in UTF8 format.
+
+BEROctet::Blob X509Cert::UTF8Subject() const
+{
+   return ToUTF8(m_Subject.Tag(), m_Subject.Octet());
+}
+
+// Returns list of attributes in Subject matching id-at-commonName
+// List will be invalidated when object changes.
+
+std::vector<std::string> X509Cert::SubjectCommonName() const
+{
+
+   std::vector<std::string> cnNames;
+   std::vector<BEROctet const*> cnOcts;
+
+   m_Subject.SearchOIDNext(OID_id_at_commonName,cnOcts);
+
+   for(std::vector<BEROctet const*>::size_type i=0; i<cnOcts.size(); i++)
+      cnNames.push_back(string((char*)cnOcts[i]->Data().data(),cnOcts[i]->Data().size()));
+
+   return cnNames;
+
+}
+
+// Returns list of attributes in Subject matching id-at-commonName
+// List will be invalidated when object changes.
+// string in list is in UTF8.
+
+std::vector<std::string> X509Cert::UTF8SubjectCommonName() const
+{
+
+   std::vector<std::string> cnNames;
+   std::vector<BEROctet const*> cnOcts;
+
+   m_Subject.SearchOIDNext(OID_id_at_commonName,cnOcts);
+
+   for(std::vector<BEROctet const*>::size_type i=0; i<cnOcts.size(); i++)
+   {
+      BEROctet::Blob blbData = ToUTF8(cnOcts[i]->Tag(), cnOcts[i]->Data());
+      cnNames.push_back(string((char*)blbData.data(),blbData.size()));
+   }
+
+   return cnNames;
+
+}
+
+// Returns modulus from SubjectPublicKeyInfo, stripped for any leading zero(s).
+
+BEROctet::Blob X509Cert::Modulus() const
+{
+
+   BEROctet::Blob RawMod = RawModulus();
+
+   unsigned long i = 0;
+   while(!RawMod[i] && i<RawMod.size()) i++; // Skip leading zero(s).
+
+   return BEROctet::Blob(&RawMod[i],RawMod.size()-i);
+
+}
+
+// Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
+
+BEROctet::Blob X509Cert::RawModulus() const
+{
+
+   if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
+
+   BEROctet::Blob KeyBlob = PubKeyString.Data();
+
+   if(KeyBlob[0])                                 // Expect number of unused bits in
+      throw runtime_error("X509CertFormatError");    // last octet to be zero.
+
+
+
+   BEROctet PubKeyOct(KeyBlob.substr(1,BEROctet::Blob::npos));
+
+   if(PubKeyOct.SubOctetList().size()!=2) throw runtime_error("X509CertFormatError");
+
+   return PubKeyOct.SubOctetList()[0]->Data();
+
+}
+
+// Returns public exponent from SubjectPublicKeyInfo, stripped for any leading zero(s).
+
+BEROctet::Blob X509Cert::PublicExponent() const
+{
+
+   BEROctet::Blob RawPubExp = RawPublicExponent();
+
+   unsigned long i = 0;
+   while(!RawPubExp[i] && i<RawPubExp.size()) i++; // Skip leading zero(s).
+
+   return BEROctet::Blob(&RawPubExp[i],RawPubExp.size()-i);
+
+}
+// Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
+
+BEROctet::Blob X509Cert::RawPublicExponent() const
+{
+
+   if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
+
+   BEROctet::Blob KeyBlob = PubKeyString.Data();
+
+   if(KeyBlob[0])                                  // Expect number of unused bits
+      throw runtime_error("X509CertFormatError");     // in last octet to be zero.
+
+
+   BEROctet PubKeyOct(KeyBlob.substr(1,BEROctet::Blob::npos));
+
+   if(PubKeyOct.SubOctetList().size()!=2) throw runtime_error("X509CertFormatError");
+
+   return PubKeyOct.SubOctetList()[1]->Data();
+
+}
+
+// Returns KeyUsage attribute, left justified with most significant bit as first bit (BER convention)
+
+unsigned long X509Cert::KeyUsage() const
+{
+
+   if(!m_Extensions.Data().size())
+      throw runtime_error("X509CertExtensionNotPresent");
+
+   unsigned long ReturnKeyUsage = 0;
+
+   const unsigned char UnusedBitsMask[]  = {0xFF,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
+
+   std::vector<BEROctet const*> ExtensionList;
+
+   m_Extensions.SearchOID(OID_id_ce_keyUsage,ExtensionList);
+
+   if(ExtensionList.size()!=1)
+      throw runtime_error("X509CertExtensionNotPresent"); // One and only one instance
+
+   BEROctet const* Extension = ExtensionList[0];
+   BEROctet* extnValue = 0;
+   if(Extension->SubOctetList().size()==2)
+      extnValue = Extension->SubOctetList()[1];  // No "critical" attribute present
+
+   else if(Extension->SubOctetList().size()==3)
+      extnValue = Extension->SubOctetList()[2];  // A "critical" attribute present
+
+   else
+      throw runtime_error("X509CertFormatError");    // "Extensions" must contain either 2 or 3 octets
+
+   BEROctet KeyUsage(extnValue->Data());
+   BEROctet::Blob KeyUsageBitString = KeyUsage.Data();
+
+   unsigned char UnusedBits = KeyUsageBitString[0];
+   size_t NumBytes = KeyUsageBitString.size()-1;
+   if(NumBytes>4)
+   {
+      NumBytes = 4; // Truncate to fit the ulong, should be plenty though
+      UnusedBits = 0;
+   }
+
+   unsigned long Shift = 24;
+   for(unsigned long i=0; i<NumBytes-1; i++)
+   {
+      ReturnKeyUsage |= (((unsigned long)KeyUsageBitString[i+1]) << Shift);
+      Shift -= 8;
+   }
+
+   ReturnKeyUsage |= ( (KeyUsageBitString[NumBytes] & UnusedBitsMask[UnusedBits]) << Shift );
+
+   return ReturnKeyUsage;
+
+}
+
+bool X509Cert::ExtendedKeyUsage(string const &strOID) const
+{
+   if(!m_Extensions.Data().size())
+      return false;
+
+   vector<BEROctet const*> veku;
+
+   m_Extensions.SearchOIDNext(OID_id_ce_extKeyUsage, veku);
+   if(veku.size() != 1)
+      return false;
+
+   try
+   {
+      BEROctet berEKU(veku[0]->Data());
+      vector<BEROctet const*> ekuOcts;
+      berEKU.SearchOID(strOID,ekuOcts);
+      if(ekuOcts.size() > 0)
+         return true;
+      else
+         return false;
+   }
+   catch(...)
+   {
+      return false;
+   }
+}
+
+bool X509Cert::IsCACert() const
+{
+   return m_bCACert;
+}
+
+bool X509Cert::IsRootCert() const
+{
+   return m_bRootCert;
+}
+
+void X509Cert::Decode()
+{
+
+   const unsigned int dwTagVersion         = 0;
+   //const unsigned int dwTagIssuerUniqueID  = 1;
+   //const unsigned int dwTagSubjectUniqueID = 2;
+   const unsigned int dwTagExtensions      = 3;
+
+   if(m_Cert.SubOctetList().size()!=3)  throw runtime_error("X509CertFormatError");
+
+   BEROctet *tbsCert = m_Cert.SubOctetList()[0];
+   size_t Size = tbsCert->SubOctetList().size();
+   if(!Size) throw runtime_error("X509CertFormatError");
+
+   std::vector<BEROctet const*>::size_type  i = 0;
+   BEROctet *first = tbsCert->SubOctetList()[i];
+   if((first->Class()==tcContext) && (first->Tag()==dwTagVersion)) i++; // Version
+
+   if(Size < static_cast<unsigned long>(6+i))
+      throw runtime_error("X509CertFormatError");
+
+   m_SerialNumber = *(tbsCert->SubOctetList()[i]); i++;            // SerialNumber
+   i++;                                                            // Signature (algorithm)
+   m_Issuer = *(tbsCert->SubOctetList()[i]); i++;                  // Issuer
+   m_Validity = *(tbsCert->SubOctetList()[i]); i++;                // Validity
+   m_Subject = *(tbsCert->SubOctetList()[i]); i++;                 // Subject
+   m_SubjectPublicKeyInfo = *(tbsCert->SubOctetList()[i]);    i++; // SubjectPublicKeyInfo
+
+   m_Extensions = BEROctet();
+   while(i<Size) {
+      BEROctet *oct = tbsCert->SubOctetList()[i];
+      if((oct->Class()==tcContext) && (oct->Tag()==dwTagExtensions)) {
+         m_Extensions = *oct;
+         break;
+      }
+      i++;
+   }
+
+   m_bCACert = false;
+   std::vector<BEROctet const*> ExtensionList;
+   m_Extensions.SearchOID(OID_id_ce_basicConstraints, ExtensionList);
+
+
+   if(1 == ExtensionList.size())
+   {
+      BEROctet const* Extension = ExtensionList[0];
+      BEROctet* extnValue = 0;
+      if(Extension->SubOctetList().size()==2)
+         extnValue = Extension->SubOctetList()[1];  // No "critical" attribute present
+
+      else if(Extension->SubOctetList().size()==3)
+         extnValue = Extension->SubOctetList()[2];  // A "critical" attribute present
+
+      if (extnValue)
+      {
+         BEROctet BasicContrainsts(extnValue->Data());
+         std::vector<BEROctet*> bcMembers(BasicContrainsts.SubOctetList());
+         if(bcMembers.size()>0 && bcMembers[0]->Tag() == dwBerUnivBool)
+         {
+            BEROctet::Blob flag(bcMembers[0]->Data());
+            if(flag.size()==1)
+               m_bCACert = flag[0] ? true : false;
+         }
+      }
+   }
+
+   m_bRootCert = false;
+   if (Issuer() == Subject())
+   {
+      m_bRootCert = true;
+   }
+}
+
+
+BEROctet::Blob X509Cert::ToUTF8( unsigned int dwTag, const BEROctet::Blob &blbData ) const
+{
+   BEROctet::Blob blbReturn;
+   size_t cUnicode = 0;
+   bool bConvert = false;
+   switch(dwTag)
+   {
+   case dwBerBMPString:
+      //string in 2 byte Unicode Big Endian format.
+      cUnicode = 2;
+      bConvert = true;
+      break;
+   case dwBerUniversalString:
+   case dwBerCharacterString:
+      //string in ISO10646, 4 byte unicode big endian format.
+      //this is hardly used but we never know.
+      cUnicode = 4;
+      bConvert = true;
+      break;
+   default:
+      //return as is.
+      blbReturn = blbData;
+   }
+
+   if(bConvert)
+   {
+      unsigned char bAppend = 0;
+      for(size_t i = 0; i < blbData.size() / cUnicode; i++ )
+      {
+         unsigned int dwUnicode = 0;
+         unsigned int dwTemp = 0;
+         int nBytesInUTF8 = 0;
+
+         //first get the Unicode unsigned int from BIG ENDIAN BYTES.
+         for(size_t j = 0; j < cUnicode; j++)
+         {
+            dwTemp = blbData.at(i*cUnicode + j);
+            dwUnicode += dwTemp << (8*(cUnicode-(j+1)));
+         }
+
+         //now calculate the number of bytes required to represent
+         // the unicode value in UTF8
+         if( dwUnicode <= 0x0000007F )
+         {
+            nBytesInUTF8 = 1;
+         }
+         else if( dwUnicode <= 0x000007FF )
+         {
+            nBytesInUTF8 = 2;
+         }
+         else if( dwUnicode <= 0x0000FFFF )
+         {
+            nBytesInUTF8 = 3;
+         }
+         else if( dwUnicode <= 0x001FFFFF )
+         {
+            nBytesInUTF8 = 4;
+         }
+         else if( dwUnicode <= 0x03FFFFFF )
+         {
+            nBytesInUTF8 = 5;
+         }
+         else if( dwUnicode <= 0x7FFFFFFF )
+         {
+            nBytesInUTF8 = 6;
+         }
+
+         //The bitwise & code is 0x7F (7 bits) when there is only one byte
+         // Otherwise the & code is 0x3f ( 6 bits)
+         // when there are more that one UTF8 bytes required,
+         // Ideally the MS unsigned char has to be & with less than 6 bits,
+         // but it does not matter since the other bits
+         // will be zero, so it is safe to & 6 bits.
+
+         unsigned char bBitWiseAndCode = 0x3f;
+         if( nBytesInUTF8 == 1)
+         {
+            bBitWiseAndCode = 0x7f;
+         }
+
+
+         // Shift in the multiples of 6 starting with maximum.
+         // This way the MSB will be appended first and then the rest.
+         // Add to MS Byte the bits which indicates number of bytes coded for UTF8
+         // for all other bytes add 0x80.
+         for( int k = nBytesInUTF8 - 1; k >= 0; k--)
+         {
+            unsigned char bytAdd = 0;
+            if( nBytesInUTF8 > 1 )
+            {
+               if( k == nBytesInUTF8 - 1 )
+               {
+                  bytAdd = ( 0xFF << (8 - nBytesInUTF8 ) );
+               }
+               else
+               {
+                  bytAdd = 0x80;
+               }
+
+            }
+            bAppend = static_cast<unsigned char>( ((dwUnicode >> k*6) & bBitWiseAndCode));
+            bAppend  += bytAdd;
+            blbReturn.append( &bAppend, 1);
+         }
+      }
+      //append the NULL char.
+      bAppend = 0;
+      blbReturn.append( &bAppend, 1);
+   }
+   return blbReturn;
+}

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/x509cert.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,95 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_x509cert_h
+#define _include_x509cert_h
+
+#include <string>
+#include <vector>
+
+#include "beroctet.h"
+
+class X509Cert
+{
+
+public:
+    X509Cert();
+    X509Cert(const X509Cert &cert);
+    X509Cert(const BEROctet::Blob &buffer);
+    X509Cert(const unsigned char *buffer, const unsigned long size);
+    X509Cert& operator=(const X509Cert &cert);
+    X509Cert& operator=(const BEROctet::Blob &buffer);
+
+    BEROctet::Blob SerialNumber() const;
+    BEROctet::Blob Issuer() const;
+    BEROctet::Blob UTF8Issuer() const;
+    std::vector<std::string> IssuerOrg() const;
+    std::vector<std::string> UTF8IssuerOrg() const;
+    std::string ValidityNotBefore() const;
+    std::string ValidityNotAfter() const;
+    BEROctet::Blob Subject() const;
+    BEROctet::Blob UTF8Subject() const;
+    std::vector<std::string> SubjectCommonName() const;
+    std::vector<std::string> UTF8SubjectCommonName() const;
+    BEROctet::Blob Modulus() const;
+    BEROctet::Blob RawModulus() const;
+    BEROctet::Blob PublicExponent() const;
+    BEROctet::Blob RawPublicExponent() const;
+
+    unsigned long KeyUsage() const;
+    bool ExtendedKeyUsage(std::string const &strOID) const;
+    bool IsCACert() const;
+    bool IsRootCert() const;
+
+private:
+    void Decode();
+
+    BEROctet::Blob ToUTF8( unsigned int dwTag, const BEROctet::Blob &blbData ) const;
+
+private:
+    BEROctet m_Cert;
+    BEROctet m_SerialNumber;
+    BEROctet m_Issuer;
+    BEROctet m_Validity;
+    BEROctet m_Subject;
+    BEROctet m_SubjectPublicKeyInfo;
+    BEROctet m_Extensions;
+    bool     m_bCACert;
+    bool     m_bRootCert;
+
+
+};
+
+// Key Usage flags from X.509 spec
+
+const unsigned long digitalSignature = 0x80000000;
+const unsigned long nonRepudiation   = 0x40000000;
+const unsigned long keyEncipherment  = 0x20000000;
+const unsigned long dataEncipherment = 0x10000000;
+const unsigned long keyAgreement     = 0x08000000;
+const unsigned long keyCertSign      = 0x04000000;
+const unsigned long cRLSign          = 0x02000000;
+const unsigned long encipherOnly     = 0x01000000;
+const unsigned long decipherOnly     = 0x00800000;
+
+
+#endif //_include_x509cert_h

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.cpp (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.cpp	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,265 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "x509pubkeycertobject.h"
+
+X509PubKeyCertObject::X509PubKeyCertObject() : CertificateObject()
+{
+    this->_subject              = NULL_PTR;
+    this->_id                   = NULL_PTR;
+    this->_issuer               = NULL_PTR;
+    this->_serialNumber         = NULL_PTR;
+    this->_value                = NULL_PTR;
+    this->_url                  = NULL_PTR;
+    this->_hashOfSubjectPubKey  = NULL_PTR;
+    this->_hashOfIssuerPubKey   = NULL_PTR;
+
+    this->_certType             = CKC_X_509;
+    this->_trusted              = CK_TRUE;
+}
+
+X509PubKeyCertObject::~X509PubKeyCertObject()
+{
+    if(this->_subject != NULL_PTR)
+        delete this->_subject;
+
+    if(this->_id != NULL_PTR)
+        delete this->_id;
+
+    if(this->_issuer != NULL_PTR)
+        delete this->_issuer;
+
+    if(this->_serialNumber != NULL_PTR)
+        delete this->_serialNumber;
+
+    if(this->_value != NULL_PTR)
+        delete this->_value;
+
+    if(this->_url != NULL_PTR)
+        delete this->_url;
+
+    if(this->_hashOfSubjectPubKey != NULL_PTR)
+        delete this->_hashOfSubjectPubKey;
+
+    if(this->_hashOfIssuerPubKey != NULL_PTR)
+        delete this->_hashOfIssuerPubKey;
+
+}
+
+CK_BBOOL X509PubKeyCertObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+
+        case CKA_SUBJECT:
+            return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_ID:
+            return Util::CompareU1Arrays(this->_id,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_ISSUER:
+            return Util::CompareU1Arrays(this->_issuer,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_SERIAL_NUMBER:
+            return Util::CompareU1Arrays(this->_serialNumber,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_VALUE:
+            return Util::CompareU1Arrays(this->_value,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_URL:
+            return Util::CompareU1Arrays(this->_url,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+            return Util::CompareU1Arrays(this->_hashOfSubjectPubKey,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+            return Util::CompareU1Arrays(this->_hashOfIssuerPubKey,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return CertificateObject::Compare(attribute);
+    }
+}
+
+CK_RV X509PubKeyCertObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_SUBJECT:
+            case CKA_VALUE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+
+        case CKA_SUBJECT:
+            if(this->_subject != NULL_PTR){
+                delete this->_subject;
+            }
+            this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_ID:
+            if(this->_id != NULL_PTR){
+                delete this->_id;
+            }
+            this->_id = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_ISSUER:
+            if(this->_issuer != NULL_PTR){
+                delete this->_issuer;
+            }
+            this->_issuer = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_SERIAL_NUMBER:
+            if(this->_serialNumber != NULL_PTR){
+                delete this->_serialNumber;
+            }
+            this->_serialNumber = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_VALUE:
+            if(this->_value != NULL_PTR){
+                delete this->_value;
+            }
+            this->_value = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_URL:
+            {
+                u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_url != NULL_PTR){
+                        delete this->_url;
+                    }
+                    this->_url = stemp;
+                }
+            }
+            break;
+
+        case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+            if(this->_hashOfSubjectPubKey != NULL_PTR){
+                delete this->_hashOfSubjectPubKey;
+            }
+            this->_hashOfSubjectPubKey = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+            if(this->_hashOfIssuerPubKey != NULL_PTR){
+                delete this->_hashOfIssuerPubKey;
+            }
+            this->_hashOfIssuerPubKey = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        default:
+            return CertificateObject::SetAttribute(attribute,objCreation);
+    }
+
+    return rv;
+}
+
+CK_RV X509PubKeyCertObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type){
+
+        case CKA_SUBJECT:
+            return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+        case CKA_ID:
+            return StorageObject::PutU1ArrayInAttribute(this->_id,attribute);
+
+        case CKA_ISSUER:
+            return StorageObject::PutU1ArrayInAttribute(this->_issuer,attribute);
+
+        case CKA_SERIAL_NUMBER:
+            return StorageObject::PutU1ArrayInAttribute(this->_serialNumber,attribute);
+
+        case CKA_VALUE:
+            return StorageObject::PutU1ArrayInAttribute(this->_value,attribute);
+
+        case CKA_URL:
+            return StorageObject::PutU1ArrayInAttribute(this->_url,attribute);
+
+        case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+            return StorageObject::PutU1ArrayInAttribute(this->_hashOfSubjectPubKey,attribute);
+
+        case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+            return StorageObject::PutU1ArrayInAttribute(this->_hashOfIssuerPubKey,attribute);
+
+        default:
+            return CertificateObject::GetAttribute(attribute);
+    }
+}
+
+void X509PubKeyCertObject::Serialize(std::vector<u1> *to)
+{
+    CertificateObject::Serialize(to);
+
+    Util::PushByteArrayInVector(to,this->_subject);
+
+    Util::PushByteArrayInVector(to,this->_id);
+
+    Util::PushByteArrayInVector(to,this->_issuer);
+
+    Util::PushByteArrayInVector(to,this->_serialNumber);
+
+    Util::PushByteArrayInVector(to,this->_url);
+
+    Util::PushByteArrayInVector(to,this->_hashOfSubjectPubKey);
+
+    Util::PushByteArrayInVector(to,this->_hashOfIssuerPubKey);
+
+    PKCS11_ASSERT(!this->_certName.empty());
+
+}
+
+void X509PubKeyCertObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CertificateObject::Deserialize(from,idx);
+
+    this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_id = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_issuer = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_serialNumber = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_url = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_hashOfSubjectPubKey = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_hashOfIssuerPubKey = Util::ReadByteArrayFromVector(from,idx);
+
+}
+

Copied: trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.h (from rev 139, trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h)
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/x509pubkeycertobject.h	2012-02-20 13:52:47 UTC (rev 140)
@@ -0,0 +1,53 @@
+/*
+*  PKCS#11 library for .Net smart cards
+*  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+*
+*  This library is free software; you can redistribute it and/or
+*  modify it under the terms of the GNU Lesser General Public
+*  License as published by the Free Software Foundation; either
+*  version 2.1 of the License, or (at your option) any later version.
+*
+*  This library is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+*  Lesser General Public License for more details.
+*
+*  You should have received a copy of the GNU Lesser General Public
+*  License along with this library; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*
+*/
+
+#ifndef _include_x509pubkeycertobject_h
+#define _include_x509pubkeycertobject_h
+
+#include "certificateobject.h"
+
+class X509PubKeyCertObject : public CertificateObject
+{
+
+public:
+   u1Array*    _subject;
+   u1Array*    _id;
+   u1Array*    _issuer;
+   u1Array*    _serialNumber;
+   u1Array*    _value;
+   u1Array*    _url;
+   u1Array*    _hashOfSubjectPubKey;
+   u1Array*    _hashOfIssuerPubKey;
+
+public:
+   X509PubKeyCertObject();
+   virtual ~X509PubKeyCertObject();
+
+   CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+   CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+   CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+   void Serialize(vector<u1>* to);
+   void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/smartcardservices-changes/attachments/20120220/c4e06147/attachment-0001.html>


More information about the SmartcardServices-Changes mailing list