create and delete with certificate and key

master
Marc Wäckerlin 15 years ago
parent ea6ad617c1
commit 74f32443e1
  1. 37
      src/cryptoki.cxx
  2. 226
      src/cryptoki.hxx
  3. 130
      src/openssl.hxx
  4. 5
      test/makefile.am
  5. 111
      test/sharedpointer_test.cxx

@ -258,8 +258,43 @@ namespace cryptoki {
return create(attrs); return create(attrs);
} }
Object Session::create(const std::string& label, Object Session::create(const std::string& label,
const openssl::PrivateKey& key) { const openssl::PrivateKey& key,
const openssl::X509& cert) {
int usage(cert.keyUsageFlags());
AttributeList attrs; AttributeList attrs;
attrs.push_back(Attribute(CKA_CLASS)
.from<CK_OBJECT_CLASS>(CKO_PRIVATE_KEY));
attrs.push_back(Attribute(CKA_TOKEN).from<CK_BBOOL>(TRUE));
attrs.push_back(Attribute(CKA_PRIVATE).from<CK_BBOOL>(TRUE));
attrs.push_back(Attribute(CKA_MODIFIABLE).from<CK_BBOOL>(TRUE));
attrs.push_back(Attribute(CKA_LABEL, label));
attrs.push_back(Attribute(CKA_KEY_TYPE).from<CK_KEY_TYPE>(CKK_RSA));
attrs.push_back(Attribute(CKA_ID, cert.id()));
attrs.push_back(Attribute(CKA_DERIVE).from<CK_BBOOL>(FALSE));
attrs.push_back(Attribute(CKA_SUBJECT, cert.subjectDER()));
attrs.push_back(Attribute(CKA_SENSITIVE).from<CK_BBOOL>(TRUE));
attrs.push_back(Attribute(CKA_SECONDARY_AUTH).from<CK_BBOOL>(FALSE));
attrs.push_back(Attribute(CKA_DECRYPT) // Required by Doujak/Inverardi
.from<CK_BBOOL>(usage&(X509v3_KU_DATA_ENCIPHERMENT
|usage&X509v3_KU_KEY_ENCIPHERMENT)
?TRUE:FALSE)); // instead of CKA_UNWRAP
attrs.push_back(Attribute(CKA_SIGN)
.from<CK_BBOOL>(usage&(X509v3_KU_DIGITAL_SIGNATURE
|X509v3_KU_NON_REPUDIATION)
?TRUE:FALSE));
attrs.push_back(Attribute(CKA_SIGN_RECOVER) // same as CKA_SIGN
.from<CK_BBOOL>(usage&(X509v3_KU_DIGITAL_SIGNATURE
|X509v3_KU_NON_REPUDIATION)
?TRUE:FALSE));
attrs.push_back(Attribute(CKA_EXTRACTABLE).from<CK_BBOOL>(FALSE));
attrs.push_back(Attribute(CKA_MODULUS, key.modulus()));
attrs.push_back(Attribute(CKA_PUBLIC_EXPONENT, key.publicExponent()));
attrs.push_back(Attribute(CKA_PRIVATE_EXPONENT, key.privateExponent()));
attrs.push_back(Attribute(CKA_PRIME_1, key.prime1()));
attrs.push_back(Attribute(CKA_PRIME_2, key.prime2()));
attrs.push_back(Attribute(CKA_EXPONENT_1, key.exponent1()));
attrs.push_back(Attribute(CKA_EXPONENT_2, key.exponent2()));
attrs.push_back(Attribute(CKA_COEFFICIENT, key.coefficient()));
return create(attrs); return create(attrs);
} }
Object Session::create(const std::string& label, Object Session::create(const std::string& label,

@ -35,6 +35,119 @@
//! @see gcryptoki //! @see gcryptoki
namespace cryptoki { namespace cryptoki {
//! @todo copy in own library
/*! Inherit from SmartResource,
and overwrite free(). You must call destruct() in your destructor. */
class SmartResource {
public:
SmartResource(): _cnt(0), _destructed(false) {
incr();
}
//! must be called in copy constructor of children!
SmartResource(const SmartResource& o): _cnt(o._cnt), _destructed(false) {
incr();
}
~SmartResource() {
assert(_destructed); // child must call destruct() in destructor
}
//! must be called in assignment constructor of children!
SmartResource& operator=(const SmartResource& o) {
decr();
_cnt = o._cnt;
incr();
return *this;
}
protected:
//! Overwrite to free your resource.
virtual void free() = 0;
//! You must call it in your destructor!
void destruct() {
if (_destructed) return; // only once
decr();
_destructed = true;
}
//! Seldom needed, mostly automatic.
void incr() {
if (!_cnt) _cnt = new unsigned int(0);
++*_cnt;
assert(_cnt);
}
//! Seldom needed, mostly automatic.
void decr() {
if (!_cnt || --*_cnt) return;
delete _cnt; _cnt = 0;
free();
}
//! Seldom needed, mostly automatic.
/*! Used in complete reassign of resource from outside.
Call incr() after assignment. */
void clear() {
decr();
_cnt = 0;
}
//! Reads the internal counter (for testing and debugging only);
int cnt() {
assert(_cnt);
return *_cnt;
}
private:
unsigned int *_cnt;
bool _destructed;
};
template <typename T> class SharedPointer: public SmartResource {
public:
SharedPointer(): _p(0) {}
SharedPointer(const SharedPointer& o): SmartResource(o), _p(o._p) {}
SharedPointer(T* p): _p(p) {}
SharedPointer& operator=(const SharedPointer& o) {
return reset(o);
}
SharedPointer& operator=(T* p) {
return reset(p);
}
~SharedPointer() {
destruct();
}
T* const operator->() {
return get();
}
const T* const operator->() const {
return get();
}
const T& operator*() const {
return *get();
}
T& operator*() {
return *get();
}
SharedPointer& reset(const SharedPointer& o) {
SmartResource::operator=(o);
_p = o._p;
return *this;
}
SharedPointer& reset(T* p = 0) {
clear();
_p = p;
incr();
return *this;
}
const T* const get() const {
assert(_p);
return _p;
}
T* const get() {
assert(_p);
return _p;
}
protected:
void free() {
delete _p; _p=0;
}
private:
T* _p;
};
#ifndef CRYPTOKI_FN_LOG #ifndef CRYPTOKI_FN_LOG
#if __GNUC__ >= 2 #if __GNUC__ >= 2
#define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \ #define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \
@ -816,7 +929,7 @@ namespace cryptoki {
//! Session Management //! Session Management
//! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID); //! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID);
class Session { class Session: public SmartResource {
private: private:
friend class Login; friend class Login;
@ -827,8 +940,6 @@ namespace cryptoki {
CK_RV _res; CK_RV _res;
Session(); // forbidden Session(); // forbidden
Session(const Session&); // forbidden
Session& operator=(const Session&); // forbidden
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
_res = result; _res = result;
@ -840,6 +951,18 @@ namespace cryptoki {
return _res==CKR_OK; return _res==CKR_OK;
} }
void free() {
try {
//! closes login.
_login.reset();
//! calls @c C_CloseSession
check(_slot._init->_fn->C_CloseSession(_session),
CRYPTOKI_FN_LOG("C_CloseSession"));
} catch (...) {
if (!std::uncaught_exception()) throw;
}
}
public: public:
//! Opens a new session. //! Opens a new session.
@ -854,20 +977,20 @@ namespace cryptoki {
//! @todo pass parameter //! @todo pass parameter
} }
//! Closes actual session Session(const Session& o):
SmartResource(o),
_slot(o._slot), _session(o._session), _res(o._res) {
}
~Session() { ~Session() {
try { destruct();
_login.reset(); }
} catch (...) {
if (!std::uncaught_exception()) throw; Session& operator=(const Session& o) {
} SmartResource::operator=(o);
try { _slot = o._slot;
//! calls @c C_CloseSession _session = o._session;
check(_slot._init->_fn->C_CloseSession(_session), _res = o._res;
CRYPTOKI_FN_LOG("C_CloseSession"));
} catch (...) {
if (!std::uncaught_exception()) throw;
}
} }
/*! @name Comfortable Access /*! @name Comfortable Access
@ -882,7 +1005,8 @@ namespace cryptoki {
//! Create a new Certificate Object. //! Create a new Certificate Object.
Object create(const std::string& label, const openssl::X509& cert); Object create(const std::string& label, const openssl::X509& cert);
//! Create a new PrivateKey Object. //! Create a new PrivateKey Object.
Object create(const std::string& label, const openssl::PrivateKey& key); Object create(const std::string& label, const openssl::PrivateKey& key,
const openssl::X509& cert);
//! Create a new Certificate and optional PrivateKey Object. //! Create a new Certificate and optional PrivateKey Object.
Object create(const std::string& label, const openssl::PKCS12& p12); Object create(const std::string& label, const openssl::PKCS12& p12);
@ -1184,12 +1308,12 @@ namespace cryptoki {
}; };
void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) { void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) {
_login = std::auto_ptr<Login>(new Login(*this, pin, userType)); _login = SharedPointer<Login>(new Login(*this, pin, userType));
} }
void logout() { void logout() {
_login.reset(); _login.reset();
} }
std::auto_ptr<Login> _login; SharedPointer<Login> _login;
/*! @todo Not implemented: /*! @todo Not implemented:
@code @code
@ -1320,12 +1444,12 @@ namespace cryptoki {
friend class Session; friend class Session;
CK_OBJECT_HANDLE _object; CK_OBJECT_HANDLE _object;
Session* _session; Session _session;
CK_RV _res; CK_RV _res;
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
_res = result; _res = result;
if (_session->_slot._init->_exc && !*this) if (_session._slot._init->_exc && !*this)
if (!context.empty()) if (!context.empty())
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else else
@ -1336,8 +1460,8 @@ namespace cryptoki {
Object() { Object() {
} }
Object(Session& session, CK_OBJECT_HANDLE obj): Object(const Session& session, CK_OBJECT_HANDLE obj):
_session(&session), _object(obj), _res(CKR_OK) { _session(session), _object(obj), _res(CKR_OK) {
} }
public: public:
@ -1364,7 +1488,7 @@ namespace cryptoki {
/*! @return error text of last cryptoki call */ /*! @return error text of last cryptoki call */
std::string error() { std::string error() {
return _session->_slot._init->error(_res); return _session._slot._init->error(_res);
} }
//@} //@}
@ -1379,7 +1503,7 @@ namespace cryptoki {
@code @code
bool copyobject() { bool copyobject() {
//! calls @c C_CopyObject //! calls @c C_CopyObject
return check(_session->_slot._init->_fn->C_CopyObject(_session->_session, CK_OBJECT_HANDLE, return check(_session._slot._init->_fn->C_CopyObject(_session._session, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR), CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_CopyObject")); CRYPTOKI_FN_LOG("C_CopyObject"));
} }
@ -1391,8 +1515,8 @@ namespace cryptoki {
type, param.begin().operator->(), param.size() type, param.begin().operator->(), param.size()
}; };
//! calls @c C_DecryptInit //! calls @c C_DecryptInit
return check(_session->_slot._init->_fn->C_DecryptInit return check(_session._slot._init->_fn->C_DecryptInit
(_session->_session, &mech, _object), (_session._session, &mech, _object),
CRYPTOKI_FN_LOG("C_DecryptInit")); CRYPTOKI_FN_LOG("C_DecryptInit"));
} }
@ -1401,7 +1525,7 @@ namespace cryptoki {
@code @code
bool derivekey() { bool derivekey() {
//! calls @c C_DeriveKey //! calls @c C_DeriveKey
return check(_session->_slot._init->_fn->C_DeriveKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, return check(_session._slot._init->_fn->C_DeriveKey(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR), CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_DeriveKey")); CRYPTOKI_FN_LOG("C_DeriveKey"));
} }
@ -1409,8 +1533,8 @@ namespace cryptoki {
bool destroy() { bool destroy() {
//! calls @c C_DestroyObject //! calls @c C_DestroyObject
return check(_session->_slot._init->_fn->C_DestroyObject return check(_session._slot._init->_fn->C_DestroyObject
(_session->_session, _object), (_session._session, _object),
CRYPTOKI_FN_LOG("C_DestroyObject")); CRYPTOKI_FN_LOG("C_DestroyObject"));
} }
@ -1419,7 +1543,7 @@ namespace cryptoki {
@code @code
bool digestkey() { bool digestkey() {
//! calls @c C_DigestKey //! calls @c C_DigestKey
return check(_session->_slot._init->_fn->C_DigestKey(_session->_session, CK_OBJECT_HANDLE), return check(_session._slot._init->_fn->C_DigestKey(_session._session, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_DigestKey")); CRYPTOKI_FN_LOG("C_DigestKey"));
} }
@endcode */ @endcode */
@ -1429,7 +1553,7 @@ namespace cryptoki {
@code @code
bool encryptinit() { bool encryptinit() {
//! calls @c C_EncryptInit //! calls @c C_EncryptInit
return check(_session->_slot._init->_fn->C_EncryptInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), return check(_session._slot._init->_fn->C_EncryptInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_EncryptInit")); CRYPTOKI_FN_LOG("C_EncryptInit"));
} }
@endcode */ @endcode */
@ -1439,7 +1563,7 @@ namespace cryptoki {
@code @code
bool generatekey() { bool generatekey() {
//! calls @c C_GenerateKey //! calls @c C_GenerateKey
return check(_session->_slot._init->_fn->C_GenerateKey(_session->_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, return check(_session._slot._init->_fn->C_GenerateKey(_session._session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR,
CK_ULONG, CK_OBJECT_HANDLE_PTR), CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_GenerateKey")); CRYPTOKI_FN_LOG("C_GenerateKey"));
} }
@ -1450,7 +1574,7 @@ namespace cryptoki {
@code @code
bool generatekeypair() { bool generatekeypair() {
//! calls @c C_GenerateKeyPair //! calls @c C_GenerateKeyPair
return check(_session->_slot._init->_fn->C_GenerateKeyPair(_session->_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, return check(_session._slot._init->_fn->C_GenerateKeyPair(_session._session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR,
CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR), CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_GenerateKeyPair")); CRYPTOKI_FN_LOG("C_GenerateKeyPair"));
@ -1468,8 +1592,8 @@ namespace cryptoki {
Attribute res; Attribute res;
CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0}); CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0});
//! calls @c C_GetAttributeValue //! calls @c C_GetAttributeValue
if (!check(_session->_slot._init->_fn->C_GetAttributeValue if (!check(_session._slot._init->_fn->C_GetAttributeValue
(_session->_session, _object, &attr, 1), (_session._session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue")) CRYPTOKI_FN_LOG("C_GetAttributeValue"))
|| !(long)attr.ulValueLen>0l) || !(long)attr.ulValueLen>0l)
//! Without exception handling, size and type must be checked too. //! Without exception handling, size and type must be checked too.
@ -1477,8 +1601,8 @@ namespace cryptoki {
try { try {
attr.pValue = malloc(attr.ulValueLen); attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
if (check(_session->_slot._init->_fn->C_GetAttributeValue if (check(_session._slot._init->_fn->C_GetAttributeValue
(_session->_session, _object, &attr, 1), (_session._session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue"))) CRYPTOKI_FN_LOG("C_GetAttributeValue")))
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open /*! @todo There's no @c CKA_WRAP_TEMPLATE in Open
Cryptoki. From the Specs: «In the special case Cryptoki. From the Specs: «In the special case
@ -1592,8 +1716,8 @@ namespace cryptoki {
attr = (CK_ATTRIBUTE){*it, 0, 0}; attr = (CK_ATTRIBUTE){*it, 0, 0};
try { try {
//! calls @c C_GetAttributeValue //! calls @c C_GetAttributeValue
if (_session->_slot._init->_fn->C_GetAttributeValue if (_session._slot._init->_fn->C_GetAttributeValue
(_session->_session, _object, &attr, 1) (_session._session, _object, &attr, 1)
== CKR_ATTRIBUTE_TYPE_INVALID == CKR_ATTRIBUTE_TYPE_INVALID
|| _res == CKR_ATTRIBUTE_SENSITIVE) { || _res == CKR_ATTRIBUTE_SENSITIVE) {
continue; //! Ignores unsupported Attributes. continue; //! Ignores unsupported Attributes.
@ -1602,8 +1726,8 @@ namespace cryptoki {
if ((long)attr.ulValueLen>0l) { if ((long)attr.ulValueLen>0l) {
attr.pValue = malloc(attr.ulValueLen); attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
if (check(_session->_slot._init->_fn->C_GetAttributeValue if (check(_session._slot._init->_fn->C_GetAttributeValue
(_session->_session, _object, &attr, 1), (_session._session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue"))) CRYPTOKI_FN_LOG("C_GetAttributeValue")))
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open /*! @todo There's no @c CKA_WRAP_TEMPLATE in Open
Cryptoki. From the Specs: «In the special Cryptoki. From the Specs: «In the special
@ -1663,7 +1787,7 @@ namespace cryptoki {
@code @code
bool getobjectsize() { bool getobjectsize() {
//! calls @c C_GetObjectSize //! calls @c C_GetObjectSize
return check(_session->_slot._init->_fn->C_GetObjectSize(_session->_session, CK_OBJECT_HANDLE, CK_ULONG_PTR), return check(_session._slot._init->_fn->C_GetObjectSize(_session._session, CK_OBJECT_HANDLE, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_GetObjectSize")); CRYPTOKI_FN_LOG("C_GetObjectSize"));
} }
@endcode */ @endcode */
@ -1673,7 +1797,7 @@ namespace cryptoki {
@code @code
bool setattributevalue() { bool setattributevalue() {
//! calls @c C_SetAttributeValue //! calls @c C_SetAttributeValue
return check(_session->_slot._init->_fn->C_SetAttributeValue(_session->_session, CK_OBJECT_HANDLE, return check(_session._slot._init->_fn->C_SetAttributeValue(_session._session, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG), CK_ATTRIBUTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SetAttributeValue")); CRYPTOKI_FN_LOG("C_SetAttributeValue"));
} }
@ -1683,7 +1807,7 @@ namespace cryptoki {
@code @code
bool setoperationstate() { bool setoperationstate() {
//! calls @c C_SetOperationState //! calls @c C_SetOperationState
return check(_session->_slot._init->_fn->C_SetOperationState(_session->_session, CK_BYTE_PTR, CK_ULONG, return check(_session._slot._init->_fn->C_SetOperationState(_session._session, CK_BYTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), CK_OBJECT_HANDLE, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SetOperationState")); CRYPTOKI_FN_LOG("C_SetOperationState"));
} }
@ -1693,7 +1817,7 @@ namespace cryptoki {
@code @code
bool signinit() { bool signinit() {
//! calls @c C_SignInit //! calls @c C_SignInit
return check(_session->_slot._init->_fn->C_SignInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), return check(_session._slot._init->_fn->C_SignInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SignInit")); CRYPTOKI_FN_LOG("C_SignInit"));
} }
@endcode */ @endcode */
@ -1703,7 +1827,7 @@ namespace cryptoki {
@code @code
bool signrecoverinit() { bool signrecoverinit() {
//! calls @c C_SignRecoverInit //! calls @c C_SignRecoverInit
return check(_session->_slot._init->_fn->C_SignRecoverInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), return check(_session._slot._init->_fn->C_SignRecoverInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SignRecoverInit")); CRYPTOKI_FN_LOG("C_SignRecoverInit"));
} }
@endcode */ @endcode */
@ -1712,7 +1836,7 @@ namespace cryptoki {
@code @code
bool unwrapkey() { bool unwrapkey() {
//! calls @c C_UnwrapKey //! calls @c C_UnwrapKey
return check(_session->_slot._init->_fn->C_UnwrapKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, return check(_session._slot._init->_fn->C_UnwrapKey(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR), CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_UnwrapKey")); CRYPTOKI_FN_LOG("C_UnwrapKey"));
@ -1723,7 +1847,7 @@ namespace cryptoki {
@code @code
bool verifyinit() { bool verifyinit() {
//! calls @c C_VerifyInit //! calls @c C_VerifyInit
return check(_session->_slot._init->_fn->C_VerifyInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), return check(_session._slot._init->_fn->C_VerifyInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_VerifyInit")); CRYPTOKI_FN_LOG("C_VerifyInit"));
} }
@endcode */ @endcode */
@ -1733,7 +1857,7 @@ namespace cryptoki {
@code @code
bool verifyrecoverinit() { bool verifyrecoverinit() {
//! calls @c C_VerifyRecoverInit //! calls @c C_VerifyRecoverInit
return check(_session->_slot._init->_fn->C_VerifyRecoverInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), return check(_session._slot._init->_fn->C_VerifyRecoverInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_VerifyRecoverInit")); CRYPTOKI_FN_LOG("C_VerifyRecoverInit"));
} }
@endcode */ @endcode */
@ -1743,7 +1867,7 @@ namespace cryptoki {
@code @code
bool wrapkey() { bool wrapkey() {
//! calls @c C_WrapKey //! calls @c C_WrapKey
return check(_session->_slot._init->_fn->C_WrapKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, return check(_session._slot._init->_fn->C_WrapKey(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR), CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_WrapKey")); CRYPTOKI_FN_LOG("C_WrapKey"));
} }

@ -16,8 +16,10 @@
#include <vector> #include <vector>
#include <openssl/x509v3.h> // BASIC_CONSTRAINTS #include <openssl/x509v3.h> // BASIC_CONSTRAINTS
#include <openssl/bn.h>
#include <cryptaux.hxx> #include <cryptaux.hxx>
#include <cstdio> #include <cstdio>
#include <cassert>
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API */ /*! @defgroup gopenssl C++ Wrapper around OpenSSL API */
//@{ //@{
@ -67,6 +69,13 @@ namespace openssl {
} }
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
class key_error: public openssl_error {
public:
key_error(const std::string& reason) throw():
openssl_error("private key: "+reason) {
}
};
//----------------------------------------------------------------------------
class bio_error: public openssl_error { class bio_error: public openssl_error {
public: public:
bio_error(const std::string& reason) throw(): bio_error(const std::string& reason) throw():
@ -116,6 +125,20 @@ namespace openssl {
} }
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
class key_copy_failed: public key_error {
public:
key_copy_failed() throw():
key_error("key object copy failed") {
}
};
//----------------------------------------------------------------------------
class undefined_key: public key_error {
public:
undefined_key() throw():
key_error("private key must not be 0") {
}
};
//----------------------------------------------------------------------------
class pkcs12_reading_failed: public pkcs12_error { class pkcs12_reading_failed: public pkcs12_error {
public: public:
pkcs12_reading_failed(const std::string& file) throw(): pkcs12_reading_failed(const std::string& file) throw():
@ -368,14 +391,20 @@ namespace openssl {
M_ASN1_STRING_length(cn)); M_ASN1_STRING_length(cn));
} }
//! Get key usage flags. //! Get key usage flags.
std::string keyUsageFlags() const { int keyUsageFlags() const {
int res(X509v3_KU_UNDEF);
int pos(X509_get_ext_by_NID(_x509, NID_key_usage, -1)); int pos(X509_get_ext_by_NID(_x509, NID_key_usage, -1));
if (pos>=0) { if (pos>=0) {
ASN1_BIT_STRING* ku((ASN1_BIT_STRING*)X509V3_EXT_d2i ASN1_BIT_STRING* ku((ASN1_BIT_STRING*)X509V3_EXT_d2i
(X509_get_ext(_x509, pos))); (X509_get_ext(_x509, pos)));
return std::string((char*)M_ASN1_STRING_data(ku), std::string val((char*)M_ASN1_STRING_data(ku),
M_ASN1_STRING_length(ku)); M_ASN1_STRING_length(ku));
} else return std::string(); //! @todo better throw exception? if (val.size()<=sizeof(int))
val = std::string(sizeof(int)-val.size(), '\0')+val;
assert(val.size()==sizeof(int));
res = *((int*)val.begin().operator->());
}
return res;
} }
private: private:
::X509* _x509; ::X509* _x509;
@ -384,8 +413,91 @@ namespace openssl {
//============================================================================ //============================================================================
class PrivateKey { class PrivateKey {
public: public:
PrivateKey(EVP_PKEY *) { PrivateKey(): _key(EVP_PKEY_new()) {
if (!_key) throw allocation_failed();
}
PrivateKey(const PrivateKey& o): _key(0) {
copy(o);
}
PrivateKey(EVP_PKEY* k): _key(k) {
if (!_key) throw undefined_key();
}
~PrivateKey() {
EVP_PKEY_free(_key);
}
PrivateKey& operator=(const PrivateKey& o) {
copy(o);
return *this;
}
std::string modulus() const {
return string(rsa()->n);
}
std::string publicExponent() const {
return string(rsa()->e);
}
std::string privateExponent() const {
return string(rsa()->d);
}
std::string prime1() const {
return string(rsa()->p);
}
std::string prime2() const {
return string(rsa()->q);
}
std::string exponent1() const {
return string(rsa()->dmp1);
}
std::string exponent2() const {
return string(rsa()->dmq1);
}
std::string coefficient() const {
return string(rsa()->iqmp);
}
private:
void copy(const PrivateKey& o) {
EVP_PKEY_free(_key);
if (!(_key=EVP_PKEY_new())) throw allocation_failed();
rsa(o);
dsa(o);
dh(o);
ec(o);
}
std::string string(BIGNUM* a) const {
std::string res(BN_num_bytes(a), '0');
BN_bn2bin(a, (unsigned char*)res.begin().operator->());
return res;
}
void rsa(const PrivateKey& o) {
//! @todo throw exception if 0?
RSA* tmp(o.rsa());
if (tmp&&!EVP_PKEY_set1_RSA(_key, tmp)) throw key_copy_failed();
}
void dsa(const PrivateKey& o) {
DSA* tmp(o.dsa());
if (tmp&&!EVP_PKEY_set1_DSA(_key, tmp)) throw key_copy_failed();
}
void dh(const PrivateKey& o) {
DH* tmp(o.dh());
if (tmp&&!EVP_PKEY_set1_DH(_key, tmp)) throw key_copy_failed();
}
void ec(const PrivateKey& o) {
EC_KEY* tmp(o.ec());
if (tmp&&!EVP_PKEY_set1_EC_KEY(_key, tmp)) throw key_copy_failed();
}
RSA* rsa() const {
//! @todo throw exception if 0?
return EVP_PKEY_get1_RSA(_key);
}
DSA* dsa() const {
return EVP_PKEY_get1_DSA(_key);
}
DH* dh() const {
return EVP_PKEY_get1_DH(_key);
}
EC_KEY* ec() const {
return EVP_PKEY_get1_EC_KEY(_key);
} }
EVP_PKEY* _key;
}; };
//============================================================================ //============================================================================
@ -430,20 +542,20 @@ namespace openssl {
delete *it; delete *it;
} }
bool hasPrivateKey() { bool hasPrivateKey() const {
return _key; return _key;
} }
bool hasCert() { bool hasCert() const {
return _cert; return _cert;
} }
const PrivateKey& privateKey() { const PrivateKey& privateKey() const {
if (!_key) throw pkcs12_no_private_key(); if (!_key) throw pkcs12_no_private_key();
return *_key; return *_key;
}; };
const X509& x509() { const X509& x509() const {
if (!_cert) throw pkcs12_no_x509(); if (!_cert) throw pkcs12_no_x509();
return *_cert; return *_cert;
}; };

@ -7,8 +7,11 @@ AM_CXXFLAGS += -I ${top_srcdir}/src
AM_LDFLAGS = -L${top_builddir}/src AM_LDFLAGS = -L${top_builddir}/src
LDADD = -lcppunit LDADD = -lcppunit
check_PROGRAMS= check_PROGRAMS = sharedpointer_test
TESTS=${check_PROGRAMS} TESTS=${check_PROGRAMS}
sharedpointer_test_SOURCES = sharedpointer_test.cxx
sharedpointer_test_LDFLAGS = -lcryptoki++
CLEANFILES = CLEANFILES =
MAINTAINERCLEANFILES = makefile.in MAINTAINERCLEANFILES = makefile.in

@ -0,0 +1,111 @@
/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#include <cryptoki.hxx>
#include <cppunit/TestFixture.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/XmlOutputter.h>
#include <fstream>
using namespace cryptoki;
template <typename T> class SharedPointerInside: public SharedPointer<T> {
public:
SharedPointerInside() {}
SharedPointerInside(const SharedPointerInside& o):
SharedPointer<T>(o) {}
SharedPointerInside(T* p): SharedPointer<T>(p) {}
~SharedPointerInside() {
SmartResource::destruct();
}
SharedPointerInside& operator=(const SharedPointerInside& o) {
return reset(o), *this;
}
SharedPointerInside& operator=(T* p) {
return reset(p), *this;
}
int cnt() {
return SharedPointer<T>::cnt();
}
static int freed() {
return _free;
}
protected:
void free() {
++_free;
SharedPointer<T>::free();
}
private:
static int _free;
};
template<typename T> int SharedPointerInside<T>::_free(0);
class SharedPointerTest: public CppUnit::TestFixture {
public:
void check() {
{
SharedPointerInside<int> i, j(new int);
CPPUNIT_ASSERT_EQUAL(0, SharedPointerInside<int>::freed());
CPPUNIT_ASSERT_EQUAL(1, i.cnt());
CPPUNIT_ASSERT_EQUAL(1, j.cnt());
i = j;
CPPUNIT_ASSERT_EQUAL(1, SharedPointerInside<int>::freed());
CPPUNIT_ASSERT_EQUAL(i.get(), j.get());
CPPUNIT_ASSERT_EQUAL(2, i.cnt());
CPPUNIT_ASSERT_EQUAL(2, j.cnt());
*i = 5;
CPPUNIT_ASSERT_EQUAL(1, SharedPointerInside<int>::freed());
CPPUNIT_ASSERT_EQUAL(5, *j);
CPPUNIT_ASSERT_EQUAL(2, i.cnt());
CPPUNIT_ASSERT_EQUAL(2, j.cnt());
int* old(j.get());
i = new int(6);
CPPUNIT_ASSERT_EQUAL(1, SharedPointerInside<int>::freed());
CPPUNIT_ASSERT_EQUAL(5, *j);
CPPUNIT_ASSERT_EQUAL(6, *i);
CPPUNIT_ASSERT(i.get()!=j.get());
CPPUNIT_ASSERT_EQUAL(1, i.cnt());
CPPUNIT_ASSERT_EQUAL(1, j.cnt());
i = new int(8);
CPPUNIT_ASSERT_EQUAL(2, SharedPointerInside<int>::freed());
CPPUNIT_ASSERT_EQUAL(5, *j);
CPPUNIT_ASSERT_EQUAL(8, *i);
CPPUNIT_ASSERT(i.get()!=j.get());
CPPUNIT_ASSERT_EQUAL(1, i.cnt());
CPPUNIT_ASSERT_EQUAL(1, j.cnt());
{
SharedPointerInside<int> k(j);
CPPUNIT_ASSERT_EQUAL(1, i.cnt());
CPPUNIT_ASSERT_EQUAL(2, j.cnt());
CPPUNIT_ASSERT_EQUAL(2, k.cnt());
}
CPPUNIT_ASSERT_EQUAL(2, SharedPointerInside<int>::freed());
CPPUNIT_ASSERT_EQUAL(1, i.cnt());
CPPUNIT_ASSERT_EQUAL(1, j.cnt());
}
CPPUNIT_ASSERT_EQUAL(4, SharedPointerInside<int>::freed());
}
CPPUNIT_TEST_SUITE(SharedPointerTest);
CPPUNIT_TEST(check);
CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION(SharedPointerTest);
int main(int argc, char** argv) try {
std::ofstream ofs((*argv+std::string(".xml")).c_str());
CppUnit::TextUi::TestRunner runner;
runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), ofs));
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
return runner.run() ? 0 : 1;
} catch (std::exception& e) {
std::cerr<<"***Exception: "<<e.what()<<std::endl;
return 1;
}
Loading…
Cancel
Save