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, | ||||
|   | ||||
							
								
								
									
										226
									
								
								src/cryptoki.hxx
									
									
									
									
									
								
							
							
						
						
									
										226
									
								
								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")); | ||||
|       } | ||||
|   | ||||
							
								
								
									
										130
									
								
								src/openssl.hxx
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								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), | ||||
|                              M_ASN1_STRING_length(ku)); | ||||
|         } else return std::string(); //! @todo better throw exception? | ||||
|           std::string val((char*)M_ASN1_STRING_data(ku), | ||||
|                           M_ASN1_STRING_length(ku)); | ||||
|           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