create and delete with certificate and key
This commit is contained in:
@@ -258,8 +258,43 @@ namespace cryptoki {
|
||||
return create(attrs);
|
||||
}
|
||||
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;
|
||||
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);
|
||||
}
|
||||
Object Session::create(const std::string& label,
|
||||
|
224
src/cryptoki.hxx
224
src/cryptoki.hxx
@@ -35,6 +35,119 @@
|
||||
//! @see gcryptoki
|
||||
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
|
||||
#if __GNUC__ >= 2
|
||||
#define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \
|
||||
@@ -816,7 +929,7 @@ namespace cryptoki {
|
||||
|
||||
//! Session Management
|
||||
//! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID);
|
||||
class Session {
|
||||
class Session: public SmartResource {
|
||||
private:
|
||||
|
||||
friend class Login;
|
||||
@@ -827,8 +940,6 @@ namespace cryptoki {
|
||||
CK_RV _res;
|
||||
|
||||
Session(); // forbidden
|
||||
Session(const Session&); // forbidden
|
||||
Session& operator=(const Session&); // forbidden
|
||||
|
||||
bool check(CK_RV result, const std::string& context="") {
|
||||
_res = result;
|
||||
@@ -840,6 +951,18 @@ namespace cryptoki {
|
||||
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:
|
||||
|
||||
//! Opens a new session.
|
||||
@@ -854,20 +977,20 @@ namespace cryptoki {
|
||||
//! @todo pass parameter
|
||||
}
|
||||
|
||||
//! Closes actual session
|
||||
Session(const Session& o):
|
||||
SmartResource(o),
|
||||
_slot(o._slot), _session(o._session), _res(o._res) {
|
||||
}
|
||||
|
||||
~Session() {
|
||||
try {
|
||||
_login.reset();
|
||||
} catch (...) {
|
||||
if (!std::uncaught_exception()) throw;
|
||||
}
|
||||
try {
|
||||
//! calls @c C_CloseSession
|
||||
check(_slot._init->_fn->C_CloseSession(_session),
|
||||
CRYPTOKI_FN_LOG("C_CloseSession"));
|
||||
} catch (...) {
|
||||
if (!std::uncaught_exception()) throw;
|
||||
destruct();
|
||||
}
|
||||
|
||||
Session& operator=(const Session& o) {
|
||||
SmartResource::operator=(o);
|
||||
_slot = o._slot;
|
||||
_session = o._session;
|
||||
_res = o._res;
|
||||
}
|
||||
|
||||
/*! @name Comfortable Access
|
||||
@@ -882,7 +1005,8 @@ namespace cryptoki {
|
||||
//! Create a new Certificate Object.
|
||||
Object create(const std::string& label, const openssl::X509& cert);
|
||||
//! 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.
|
||||
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) {
|
||||
_login = std::auto_ptr<Login>(new Login(*this, pin, userType));
|
||||
_login = SharedPointer<Login>(new Login(*this, pin, userType));
|
||||
}
|
||||
void logout() {
|
||||
_login.reset();
|
||||
}
|
||||
std::auto_ptr<Login> _login;
|
||||
SharedPointer<Login> _login;
|
||||
|
||||
/*! @todo Not implemented:
|
||||
@code
|
||||
@@ -1320,12 +1444,12 @@ namespace cryptoki {
|
||||
friend class Session;
|
||||
|
||||
CK_OBJECT_HANDLE _object;
|
||||
Session* _session;
|
||||
Session _session;
|
||||
CK_RV _res;
|
||||
|
||||
bool check(CK_RV result, const std::string& context="") {
|
||||
_res = result;
|
||||
if (_session->_slot._init->_exc && !*this)
|
||||
if (_session._slot._init->_exc && !*this)
|
||||
if (!context.empty())
|
||||
throw access_error(context+": "+error());
|
||||
else
|
||||
@@ -1336,8 +1460,8 @@ namespace cryptoki {
|
||||
Object() {
|
||||
}
|
||||
|
||||
Object(Session& session, CK_OBJECT_HANDLE obj):
|
||||
_session(&session), _object(obj), _res(CKR_OK) {
|
||||
Object(const Session& session, CK_OBJECT_HANDLE obj):
|
||||
_session(session), _object(obj), _res(CKR_OK) {
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1364,7 +1488,7 @@ namespace cryptoki {
|
||||
|
||||
/*! @return error text of last cryptoki call */
|
||||
std::string error() {
|
||||
return _session->_slot._init->error(_res);
|
||||
return _session._slot._init->error(_res);
|
||||
}
|
||||
|
||||
//@}
|
||||
@@ -1379,7 +1503,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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),
|
||||
CRYPTOKI_FN_LOG("C_CopyObject"));
|
||||
}
|
||||
@@ -1391,8 +1515,8 @@ namespace cryptoki {
|
||||
type, param.begin().operator->(), param.size()
|
||||
};
|
||||
//! calls @c C_DecryptInit
|
||||
return check(_session->_slot._init->_fn->C_DecryptInit
|
||||
(_session->_session, &mech, _object),
|
||||
return check(_session._slot._init->_fn->C_DecryptInit
|
||||
(_session._session, &mech, _object),
|
||||
CRYPTOKI_FN_LOG("C_DecryptInit"));
|
||||
}
|
||||
|
||||
@@ -1401,7 +1525,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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),
|
||||
CRYPTOKI_FN_LOG("C_DeriveKey"));
|
||||
}
|
||||
@@ -1409,8 +1533,8 @@ namespace cryptoki {
|
||||
|
||||
bool destroy() {
|
||||
//! calls @c C_DestroyObject
|
||||
return check(_session->_slot._init->_fn->C_DestroyObject
|
||||
(_session->_session, _object),
|
||||
return check(_session._slot._init->_fn->C_DestroyObject
|
||||
(_session._session, _object),
|
||||
CRYPTOKI_FN_LOG("C_DestroyObject"));
|
||||
}
|
||||
|
||||
@@ -1419,7 +1543,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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"));
|
||||
}
|
||||
@endcode */
|
||||
@@ -1429,7 +1553,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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"));
|
||||
}
|
||||
@endcode */
|
||||
@@ -1439,7 +1563,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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),
|
||||
CRYPTOKI_FN_LOG("C_GenerateKey"));
|
||||
}
|
||||
@@ -1450,7 +1574,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR),
|
||||
CRYPTOKI_FN_LOG("C_GenerateKeyPair"));
|
||||
@@ -1468,8 +1592,8 @@ namespace cryptoki {
|
||||
Attribute res;
|
||||
CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0});
|
||||
//! calls @c C_GetAttributeValue
|
||||
if (!check(_session->_slot._init->_fn->C_GetAttributeValue
|
||||
(_session->_session, _object, &attr, 1),
|
||||
if (!check(_session._slot._init->_fn->C_GetAttributeValue
|
||||
(_session._session, _object, &attr, 1),
|
||||
CRYPTOKI_FN_LOG("C_GetAttributeValue"))
|
||||
|| !(long)attr.ulValueLen>0l)
|
||||
//! Without exception handling, size and type must be checked too.
|
||||
@@ -1477,8 +1601,8 @@ namespace cryptoki {
|
||||
try {
|
||||
attr.pValue = malloc(attr.ulValueLen);
|
||||
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
|
||||
if (check(_session->_slot._init->_fn->C_GetAttributeValue
|
||||
(_session->_session, _object, &attr, 1),
|
||||
if (check(_session._slot._init->_fn->C_GetAttributeValue
|
||||
(_session._session, _object, &attr, 1),
|
||||
CRYPTOKI_FN_LOG("C_GetAttributeValue")))
|
||||
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open
|
||||
Cryptoki. From the Specs: «In the special case
|
||||
@@ -1592,8 +1716,8 @@ namespace cryptoki {
|
||||
attr = (CK_ATTRIBUTE){*it, 0, 0};
|
||||
try {
|
||||
//! calls @c C_GetAttributeValue
|
||||
if (_session->_slot._init->_fn->C_GetAttributeValue
|
||||
(_session->_session, _object, &attr, 1)
|
||||
if (_session._slot._init->_fn->C_GetAttributeValue
|
||||
(_session._session, _object, &attr, 1)
|
||||
== CKR_ATTRIBUTE_TYPE_INVALID
|
||||
|| _res == CKR_ATTRIBUTE_SENSITIVE) {
|
||||
continue; //! Ignores unsupported Attributes.
|
||||
@@ -1602,8 +1726,8 @@ namespace cryptoki {
|
||||
if ((long)attr.ulValueLen>0l) {
|
||||
attr.pValue = malloc(attr.ulValueLen);
|
||||
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
|
||||
if (check(_session->_slot._init->_fn->C_GetAttributeValue
|
||||
(_session->_session, _object, &attr, 1),
|
||||
if (check(_session._slot._init->_fn->C_GetAttributeValue
|
||||
(_session._session, _object, &attr, 1),
|
||||
CRYPTOKI_FN_LOG("C_GetAttributeValue")))
|
||||
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open
|
||||
Cryptoki. From the Specs: «In the special
|
||||
@@ -1663,7 +1787,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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"));
|
||||
}
|
||||
@endcode */
|
||||
@@ -1673,7 +1797,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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),
|
||||
CRYPTOKI_FN_LOG("C_SetAttributeValue"));
|
||||
}
|
||||
@@ -1683,7 +1807,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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),
|
||||
CRYPTOKI_FN_LOG("C_SetOperationState"));
|
||||
}
|
||||
@@ -1693,7 +1817,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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"));
|
||||
}
|
||||
@endcode */
|
||||
@@ -1703,7 +1827,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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"));
|
||||
}
|
||||
@endcode */
|
||||
@@ -1712,7 +1836,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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_OBJECT_HANDLE_PTR),
|
||||
CRYPTOKI_FN_LOG("C_UnwrapKey"));
|
||||
@@ -1723,7 +1847,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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"));
|
||||
}
|
||||
@endcode */
|
||||
@@ -1733,7 +1857,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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"));
|
||||
}
|
||||
@endcode */
|
||||
@@ -1743,7 +1867,7 @@ namespace cryptoki {
|
||||
@code
|
||||
bool 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),
|
||||
CRYPTOKI_FN_LOG("C_WrapKey"));
|
||||
}
|
||||
|
128
src/openssl.hxx
128
src/openssl.hxx
@@ -16,8 +16,10 @@
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/x509v3.h> // BASIC_CONSTRAINTS
|
||||
#include <openssl/bn.h>
|
||||
#include <cryptaux.hxx>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
/*! @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 {
|
||||
public:
|
||||
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 {
|
||||
public:
|
||||
pkcs12_reading_failed(const std::string& file) throw():
|
||||
@@ -368,14 +391,20 @@ namespace openssl {
|
||||
M_ASN1_STRING_length(cn));
|
||||
}
|
||||
//! 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));
|
||||
if (pos>=0) {
|
||||
ASN1_BIT_STRING* ku((ASN1_BIT_STRING*)X509V3_EXT_d2i
|
||||
(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));
|
||||
} 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:
|
||||
::X509* _x509;
|
||||
@@ -384,8 +413,91 @@ namespace openssl {
|
||||
//============================================================================
|
||||
class PrivateKey {
|
||||
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;
|
||||
}
|
||||
|
||||
bool hasPrivateKey() {
|
||||
bool hasPrivateKey() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
bool hasCert() {
|
||||
bool hasCert() const {
|
||||
return _cert;
|
||||
}
|
||||
|
||||
const PrivateKey& privateKey() {
|
||||
const PrivateKey& privateKey() const {
|
||||
if (!_key) throw pkcs12_no_private_key();
|
||||
return *_key;
|
||||
};
|
||||
|
||||
const X509& x509() {
|
||||
const X509& x509() const {
|
||||
if (!_cert) throw pkcs12_no_x509();
|
||||
return *_cert;
|
||||
};
|
||||
|
@@ -7,8 +7,11 @@ AM_CXXFLAGS += -I ${top_srcdir}/src
|
||||
AM_LDFLAGS = -L${top_builddir}/src
|
||||
LDADD = -lcppunit
|
||||
|
||||
check_PROGRAMS=
|
||||
check_PROGRAMS = sharedpointer_test
|
||||
TESTS=${check_PROGRAMS}
|
||||
|
||||
sharedpointer_test_SOURCES = sharedpointer_test.cxx
|
||||
sharedpointer_test_LDFLAGS = -lcryptoki++
|
||||
|
||||
CLEANFILES =
|
||||
MAINTAINERCLEANFILES = makefile.in
|
||||
|
111
test/sharedpointer_test.cxx
Normal file
111
test/sharedpointer_test.cxx
Normal file
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user