]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[sedhcpv6] rearrange asym crypto (checkpoint before splitting files)
authorFrancis Dupont <fdupont@isc.org>
Sat, 6 Jun 2015 13:40:43 +0000 (15:40 +0200)
committerFrancis Dupont <fdupont@isc.org>
Sat, 6 Jun 2015 13:40:43 +0000 (15:40 +0200)
src/lib/cryptolink/botan_asym.cc
src/lib/cryptolink/crypto_asym.h
src/lib/cryptolink/crypto_hmac.h
src/lib/cryptolink/openssl_asym.cc
src/lib/cryptolink/tests/asym_unittests.cc

index 9f785e8e55fa3d22d1b9848bc07ed19a676dbec0..fd09f667fa5225a29a7a56dcc5b6230404001cbc 100644 (file)
@@ -46,7 +46,7 @@ namespace cryptolink {
 
 /// @brief Botan implementation of asymmetrical cryptography (Asym).          
 // Each method is the counterpart of the Asym corresponding method.
-class AsymImpl {
+class RsaAsymImpl : public AsymImpl {
 public:
     /// @brief Constructor from a key, asym and hash algorithm,
     ///        key kind and key binary format
@@ -55,23 +55,16 @@ public:
     ///
     /// @param key            The key to sign/verify with
     /// @param len            The length of the key
-    /// @param asym_algorithm The asymmetrical cryptography algorithm
     /// @param hash_algorithm The hash algorithm
     /// @param key_kind       The key kind
     /// @param key_format     The key binary format
-    explicit AsymImpl(const void* key, size_t key_len,
-                      const AsymAlgorithm asym_algorithm,
-                      const HashAlgorithm hash_algorithm,
-                      const AsymKeyKind key_kind,
-                      const AsymFormat key_format) {
-        algo_ = asym_algorithm;
+    RsaAsymImpl(const void* key, size_t key_len,
+                const HashAlgorithm hash_algorithm,
+                const AsymKeyKind key_kind,
+                const AsymFormat key_format) {
+        algo_ = RSA_;
         hash_ = hash_algorithm;
         kind_ = key_kind;
-        if (algo_ != RSA_) {
-            isc_throw(UnsupportedAlgorithm,
-                      "Unknown asym algorithm: " <<
-                      static_cast<int>(algo_));
-        }
         std::string hash = btn::getHashAlgorithmName(hash_);
         if (hash.compare("Unknown") == 0) {
             isc_throw(UnsupportedAlgorithm,
@@ -296,24 +289,17 @@ public:
     ///
     /// @param filename       The key file name/path
     /// @param password       The PKCS#8 password
-    /// @param asym_algorithm The asymmetrical cryptography algorithm
     /// @param hash_algorithm The hash algorithm
     /// @param key_kind       The key kind
     /// @param key_format     The key binary format
-    explicit AsymImpl(const std::string& filename,
-                      const std::string& password,
-                      const AsymAlgorithm asym_algorithm,
-                      const HashAlgorithm hash_algorithm,
-                      const AsymKeyKind key_kind,
-                      const AsymFormat key_format) {
-        algo_ = asym_algorithm;
+    RsaAsymImpl(const std::string& filename,
+                const std::string& password,
+                const HashAlgorithm hash_algorithm,
+                const AsymKeyKind key_kind,
+                const AsymFormat key_format) {
+        algo_ = RSA_;
         hash_ = hash_algorithm;
         kind_ = key_kind;
-        if (algo_ != RSA_) {
-            isc_throw(UnsupportedAlgorithm,
-                      "Unknown asym algorithm: " <<
-                      static_cast<int>(algo_));
-        }
         std::string hash = btn::getHashAlgorithmName(hash_);
         if (hash.compare("Unknown") == 0) {
             isc_throw(UnsupportedAlgorithm,
@@ -731,7 +717,7 @@ public:
     }
 
     /// @brief Destructor
-    ~AsymImpl() { }
+    ~RsaAsymImpl() { }
 
     /// @brief Returns the AsymAlgorithm of the object
     AsymAlgorithm getAsymAlgorithm() const {
@@ -762,33 +748,26 @@ public:
     ///
     /// \param sig_format The signature binary format
     size_t getSignatureLength(const AsymFormat sig_format) const {
-        switch (algo_) {
-        case RSA_:
-            switch (sig_format) {
-            case BASIC:
-            case ASN1:
-            case DNS:
-                // In all cases a big integer of the size of n
-                if (kind_ == PRIVATE) {
-                    return (priv_->get_n().bytes());
-                } else {
-                    return (pub_->get_n().bytes());
-                }
-            default:
-                isc_throw(UnsupportedAlgorithm,
-                          "Unknown RSA Signature format: " <<
-                          static_cast<int>(sig_format));
+        switch (sig_format) {
+        case BASIC:
+        case ASN1:
+        case DNS:
+            // In all cases a big integer of the size of n
+            if (kind_ == PRIVATE) {
+                return (priv_->get_n().bytes());
+            } else {
+                return (pub_->get_n().bytes());
             }
         default:
             isc_throw(UnsupportedAlgorithm,
-                      "Unknown asym algorithm: " <<
-                      static_cast<int>(algo_));
+                      "Unknown RSA Signature format: " <<
+                      static_cast<int>(sig_format));
         }
     }           
 
     /// @brief Add data to digest
     ///
-    /// See @ref isc::cryptolink::Asym::update() for details.
+    /// See @ref isc::cryptolink::AsymBase::update() for details.
     void update(const void* data, const size_t len) {
         try {
             if (kind_ == PRIVATE) {
@@ -805,7 +784,7 @@ public:
 
     /// @brief Calculate the final signature
     ///
-    /// See @ref isc::cryptolink::Asym::sign() for details.
+    /// See @ref isc::cryptolink::AsymBase::sign() for details.
     void sign(isc::util::OutputBuffer& result, size_t len,
               const AsymFormat) {
         try {
@@ -823,7 +802,7 @@ public:
 
     /// @brief Calculate the final signature
     ///
-    /// See @ref isc::cryptolink::Asym::sign() for details.
+    /// See @ref isc::cryptolink::AsymBase::sign() for details.
     void sign(void* result, size_t len, const AsymFormat sig_format) {
         try {
             Botan::SecureVector<Botan::byte> b_result;
@@ -841,7 +820,7 @@ public:
 
     /// @brief Calculate the final signature
     ///
-    /// See @ref isc::cryptolink::Asym::sign() for details.
+    /// See @ref isc::cryptolink::AsymBase::sign() for details.
     std::vector<uint8_t> sign(size_t len, const AsymFormat) {
         try {
             Botan::SecureVector<Botan::byte> b_result;
@@ -859,7 +838,7 @@ public:
 
     /// @brief Verify an existing signature
     ///
-    /// See @ref isc::cryptolink::Asym::verify() for details.
+    /// See @ref isc::cryptolink::AsymBase::verify() for details.
     bool verify(const void* sig, size_t len, const AsymFormat sig_format) {
         size_t size = getSignatureLength(sig_format);
         if (len != size) {
@@ -900,7 +879,7 @@ public:
 
     /// @brief Export the key value (binary)
     ///
-    /// See @ref isc::cryptolink::Asym::exportkey() for details
+    /// See @ref isc::cryptolink::AsymBase::exportkey() for details
     std::vector<uint8_t> exportkey(const AsymKeyKind key_kind,
                                    const AsymFormat key_format) const {
         if ((key_kind == PRIVATE) && (key_format == BASIC)) {
@@ -987,7 +966,7 @@ public:
 
     /// @brief Export the key value (file)
     ///
-    /// See @ref isc::cryptolink::Asym::exportkey() for details
+    /// See @ref isc::cryptolink::AsymBase::exportkey() for details
     void exportkey(const std::string& filename,
                    const std::string& password,
                    const AsymKeyKind key_kind,
@@ -1140,7 +1119,7 @@ public:
 
     /// @brief Check the validity
     ///
-    /// See @ref isc::cryptolink::Asym::validate() for details
+    /// See @ref isc::cryptolink::AsymBase::validate() for details
     bool validate() const {
         Botan::AutoSeeded_RNG rng;
         Botan::X509_Store store;
@@ -1174,7 +1153,10 @@ public:
     /// @brief Compare two keys
     ///
     /// See @ref isc::cryptolink::Asym::compare() for details
-    bool compare(const AsymImpl* other, const AsymKeyKind key_kind) const {
+    bool compare(const RsaAsymImpl* other, const AsymKeyKind key_kind) const {
+        if (!other || (other->algo_ != RSA_)) {
+            return false;
+        }
         Botan::BigInt e, n;
         switch (key_kind) {
         case CERT:
@@ -1244,9 +1226,16 @@ Asym::Asym(const void* key, size_t key_len,
            const AsymKeyKind key_kind,
            const AsymFormat key_format)
 {
-    impl_ = new AsymImpl(key, key_len,
-                         asym_algorithm, hash_algorithm,
-                         key_kind, key_format);
+    switch (asym_algorithm) {
+    case RSA_:
+        impl_ = new RsaAsymImpl(key, key_len, hash_algorithm,
+                                key_kind, key_format);
+        return;
+    default:
+        isc_throw(UnsupportedAlgorithm,
+                  "Unknown asym algorithm: " <<
+                  static_cast<int>(asym_algorithm));
+    }
 }
 
 Asym::Asym(const std::vector<uint8_t> key,
@@ -1255,9 +1244,16 @@ Asym::Asym(const std::vector<uint8_t> key,
            const AsymKeyKind key_kind,
            const AsymFormat key_format)
 {
-    impl_ = new AsymImpl(&key[0], key.size(),
-                         asym_algorithm, hash_algorithm,
-                         key_kind, key_format);
+    switch (asym_algorithm) {
+    case RSA_:
+        impl_ = new RsaAsymImpl(&key[0], key.size(), hash_algorithm,
+                                key_kind, key_format);
+        return;
+    default:
+        isc_throw(UnsupportedAlgorithm,
+                  "Unknown asym algorithm: " <<
+                  static_cast<int>(asym_algorithm));
+    }
 }
 
 Asym::Asym(const std::string& filename,
@@ -1267,9 +1263,16 @@ Asym::Asym(const std::string& filename,
            const AsymKeyKind key_kind,
            const AsymFormat key_format)
 {
-    impl_ = new AsymImpl(filename, password,
-                         asym_algorithm, hash_algorithm,
-                         key_kind, key_format);
+    switch (asym_algorithm) {
+    case RSA_:
+        impl_ = new RsaAsymImpl(filename, password, hash_algorithm,
+                                key_kind, key_format);
+        return;
+    default:
+        isc_throw(UnsupportedAlgorithm,
+                  "Unknown asym algorithm: " <<
+                  static_cast<int>(asym_algorithm));
+    }
 }
 
 Asym::~Asym() {
@@ -1356,7 +1359,7 @@ Asym::validate() const {
     // Call the hook if available
     using namespace isc::hooks;
     if (HooksManager::calloutsPresent(hook_point_validate_certificate)) {
-        // Callout handle (static in order to reuse it)
+        // Callout handle
         CalloutHandlePtr callout_handle_ = HooksManager::createCalloutHandle();
 
         // Delete add previous arguments
@@ -1380,7 +1383,20 @@ Asym::validate() const {
 
 bool
 Asym::compare(const Asym* other, const AsymKeyKind key_kind) const {
-    return (impl_->compare(other->impl_, key_kind));
+    if (getAsymAlgorithm() != other->getAsymAlgorithm()) {
+        return false;
+    }
+    if (getAsymAlgorithm() == RSA_) {
+        const RsaAsymImpl* impl = dynamic_cast<const RsaAsymImpl*>(impl_);
+        // Should not happen but to test is better than to crash
+        if (!impl) {
+            isc_throw(Unexpected, "dynamic_cast failed on RsaAsymImpl*");
+        }
+        const RsaAsymImpl* oimpl =
+            dynamic_cast<const RsaAsymImpl*>(other->impl_);
+        return (impl->compare(oimpl, key_kind));
+    }
+    isc_throw(UnsupportedAlgorithm, "compare");
 }
 
 } // namespace cryptolink
index 2b1ab050cc9559e6c953ca038d20f0d5dfd36d47..8b92aaa15a5c90500f971c632163e48908f444d5 100644 (file)
 namespace isc {
 namespace cryptolink {
 
-/// Forward declaration, pimpl style
-class AsymImpl;
+/// \brief Asymmetrical cryptography (Asym) support
+
+/// \brief Asymmetrical cryptography (Asym) base class
+///
+/// This class is an abstract base class to give the interface
+/// (at the exception of constructors which can't be virtual and
+///  compare which needs a second object).
+class AsymBase : private boost::noncopyable {
+protected:
+    AsymBase() { }
+
+public:
+    /// \brief Destructor
+    virtual ~AsymBase() {}
+
+    /// \brief Returns the AsymAlgorithm of the object
+    virtual AsymAlgorithm getAsymAlgorithm() const = 0;
+
+    /// \brief Returns the HashAlgorithm of the object
+    virtual HashAlgorithm getHashAlgorithm() const = 0;
+
+    /// \brief Returns the AsymKeyKind of the object
+    virtual AsymKeyKind getAsymKeyKind() const = 0;
+
+    /// \brief Returns the key size in bits
+    ///
+    virtual size_t getKeySize() const = 0;
+
+    /// \brief Returns the output size of the signature
+    ///
+    /// \param sig_format The signature binary format
+    virtual size_t getSignatureLength(const AsymFormat sig_format) const = 0;
+
+    /// \brief Add data to digest
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    /// \param data The data to add
+    /// \param len  The size of the data
+    virtual void update(const void* data, const size_t len) = 0;
+
+    /// \brief Calculate the final signature
+    ///
+    /// The result will be appended to the given outputbuffer
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    /// \param result     The OutputBuffer to append the result to
+    /// \param len        The number of bytes from the result to copy. If this
+    ///                   value is smaller than the algorithms output size, the
+    ///                   result will be truncated. If this value is larger,
+    ///                   only output size bytes will be copied
+    /// \param sig_format The signature binary format
+    virtual void sign(isc::util::OutputBuffer& result, size_t len,
+                      const AsymFormat sig_format) = 0;
+
+    /// \brief Calculate the final signature
+    ///
+    /// len bytes of data from the result will be copied to *result
+    /// If len is larger than the output size, only output_size bytes
+    /// will be copied. If it is smaller, the output will be truncated
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    /// At least len bytes of data must be available for writing at
+    /// result
+    virtual void sign(void* result, size_t len,
+                      const AsymFormat sig_format) = 0;
+
+    /// \brief Calculate the final signature
+    ///
+    /// The result will be returned as a std::vector<uint8_t>
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    /// \param len        The number of bytes from the result to copy. If this
+    ///                   value is smaller than the algorithms output size, the
+    ///                   result will be truncated. If this value is larger,
+    ///                   only output size bytes will be copied
+    /// \param sig_format The signature binary format
+    /// \return           a vector containing the signature
+    virtual std::vector<uint8_t> sign(size_t len,
+                                      const AsymFormat sig_format) = 0;
+
+    /// \brief Verify an existing signature
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    /// \param sig        The signature to verify
+    /// \param len        The length of the signature. If this is smaller
+    ///                   than the output length of the algorithm,
+    ///                   only len bytes will be checked
+    /// \param sig_format The signature binary format
+    /// \return           true if the signature is correct, false otherwise
+    ///
+    /// \note verify() does not destroy its context so it can be
+    /// called multiple times with different signatures.
+    virtual bool verify(const void* sig, size_t len,
+                        const AsymFormat sig_format) = 0;
+
+    /// \brief Clear the crypto state and go back to the initial state
+    /// (must be called before reusing an Asym object)
+    virtual void clear() = 0;
+
+    /// \brief Export the key value
+    ///
+    /// The result will be returned as a std::vector<uint8_t>
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    /// \param key_kind       The key kind
+    /// \param key_format     The key binary format
+    virtual std::vector<uint8_t>
+        exportkey(const AsymKeyKind key_kind,
+                  const AsymFormat key_format) const = 0;
+
+    /// \brief Export the key value
+    ///
+    /// The key value will be returned into the given file,
+    /// optionally when PKCS#8 is selected encrypted by the password
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    /// \param filename       The key file name/path
+    /// \param password       The PKCS#8 password
+    /// \param key_kind       The key kind    
+    /// \param file_format    The key file format
+    virtual void exportkey(const std::string& filename,
+                           const std::string& password,
+                           const AsymKeyKind key_kind,
+                           const AsymFormat file_format) const = 0;
+
+    /// \brief Check the validity
+    ///
+    /// \exception LibraryError if there was any unexpected exception
+    ///            in the underlying library
+    ///
+    virtual bool validate() const = 0;
+};
+
+/// Implementation (abstract) class declaration, pimpl style
+class AsymImpl : public AsymBase {};
 
 /// \brief Asymmetrical cryptography (Asym) support
 ///
 /// This class is used to create and verify Asym signatures. Instances
 /// can be created with CryptoLink::createAsym()
 ///
-class Asym : private boost::noncopyable {
+/// Constructors, destructor and all methods are inherited from
+/// the \c AsymBase class.
+class Asym : public AsymBase {
 private:
     /// \brief Constructor from a key, asym and hash algorithm,
     ///        key kind and key binary format
-    ///
+    /// \ref AsymBase::AsymBase
     /// \exception UnsupportedAlgorithm if the given algorithm
     ///            is unknown or not supported by the underlying library
     /// \exception Badkey if the given key length is bad
@@ -99,7 +248,7 @@ private:
 
 public:
     /// \brief Destructor
-    ~Asym();
+    virtual ~Asym();
 
     /// \brief Returns the AsymAlgorithm of the object
     AsymAlgorithm getAsymAlgorithm() const;
@@ -121,101 +270,45 @@ public:
 
     /// \brief Add data to digest
     ///
-    /// \exception LibraryError if there was any unexpected exception
-    ///            in the underlying library
-    ///
-    /// \param data The data to add
-    /// \param len  The size of the data
+    /// \ref isc::cryptolink::AsymBase::update
     void update(const void* data, const size_t len);
 
     /// \brief Calculate the final signature
     ///
-    /// The result will be appended to the given outputbuffer
-    ///
-    /// \exception LibraryError if there was any unexpected exception
-    ///            in the underlying library
-    ///
-    /// \param result     The OutputBuffer to append the result to
-    /// \param len        The number of bytes from the result to copy. If this
-    ///                   value is smaller than the algorithms output size, the
-    ///                   result will be truncated. If this value is larger,
-    ///                   only output size bytes will be copied
-    /// \param sig_format The signature binary format
+    /// \ref isc::cryptolink::AsymBase::sign
     void sign(isc::util::OutputBuffer& result, size_t len,
               const AsymFormat sig_format);
 
     /// \brief Calculate the final signature
     ///
-    /// len bytes of data from the result will be copied to *result
-    /// If len is larger than the output size, only output_size bytes
-    /// will be copied. If it is smaller, the output will be truncated
-    ///
-    /// \exception LibraryError if there was any unexpected exception
-    ///            in the underlying library
-    ///
-    /// At least len bytes of data must be available for writing at
-    /// result
+    /// \ref isc::cryptolink::AsymBase::sign
     void sign(void* result, size_t len, const AsymFormat sig_format);
 
-    /// \brief Calculate the final signatre
-    ///
-    /// The result will be returned as a std::vector<uint8_t>
-    ///
-    /// \exception LibraryError if there was any unexpected exception
-    ///            in the underlying library
+    /// \brief Calculate the final signature
     ///
-    /// \param len        The number of bytes from the result to copy. If this
-    ///                   value is smaller than the algorithms output size, the
-    ///                   result will be truncated. If this value is larger,
-    ///                   only output size bytes will be copied
-    /// \param sig_format The signature binary format
-    /// \return           a vector containing the signature
+    /// \ref isc::cryptolink::AsymBase::sign
     std::vector<uint8_t> sign(size_t len, const AsymFormat sig_format);
 
     /// \brief Verify an existing signature
     ///
-    /// \exception LibraryError if there was any unexpected exception
-    ///            in the underlying library
-    ///
-    /// \param sig        The signature to verify
-    /// \param len        The length of the signature. If this is smaller
-    ///                   than the output length of the algorithm,
-    ///                   only len bytes will be checked
-    /// \param sig_format The signature binary format
-    /// \return           true if the signature is correct, false otherwise
-    ///
-    /// \note verify() does not destroy its context so it can be
-    /// called multiple times with different signatures.
+    /// \ref isc::cryptolink::AsymBase::verify
     bool verify(const void* sig, size_t len, const AsymFormat sig_format);
 
     /// \brief Clear the crypto state and go back to the initial state
     /// (must be called before reusing an Asym object)
+    ///
+    /// \ref isc::cryptolink::AsymBase::clear
     void clear();
 
     /// \brief Export the key value
     ///
-    /// The result will be returned as a std::vector<uint8_t>
-    ///
-    /// \exception LibraryError if there was any unexpected exception
-    ///            in the underlying library
-    ///
-    /// \param key_kind       The key kind
-    /// \param key_format     The key binary format
+    /// \ref isc::cryptolink::AsymBase::exportkey
     std::vector<uint8_t> exportkey(const AsymKeyKind key_kind,
                                    const AsymFormat key_format) const;
 
     /// \brief Export the key value
     ///
-    /// The key value will be returned into the given file,
-    /// optionally when PKCS#8 is selected encrypted by the password
-    ///
-    /// \exception LibraryError if there was any unexpected exception
-    ///            in the underlying library
-    ///
-    /// \param filename       The key file name/path
-    /// \param password       The PKCS#8 password
-    /// \param key_kind       The key kind    
-    /// \param file_format    The key file format
+    /// \ref isc::cryptolink::AsymBase::exportkey
     void exportkey(const std::string& filename,
                    const std::string& password,
                    const AsymKeyKind key_kind,
@@ -223,6 +316,8 @@ public:
 
     /// \brief Check the validity
     ///
+    /// \ref isc::cryptolink::AsymBase::validate
+    ///
     /// \exception LibraryError if there was any unexpected exception
     ///            in the underlying library
     ///
index 040e5731825991603a55a71eb37b812b066bf9a2..22f68c804bc667b1f0193138b25e515aedf99fa7 100644 (file)
@@ -104,7 +104,7 @@ public:
     /// result
     void sign(void* result, size_t len);
 
-    /// \brief Calculate the final signatre
+    /// \brief Calculate the final signature
     ///
     /// The result will be returned as a std::vector<uint8_t>
     ///
index 644a71ff6c4079d8c563e49ea04aeadec654aea6..d2e0ccb3410ccb7d5fdcebbc1bc95109eb9a6b2a 100644 (file)
@@ -43,7 +43,7 @@ namespace cryptolink {
 
 /// @brief OpenSSL implementation of asymmetrical cryptography (Asym).
 // Each method is the counterpart of the Asym corresponding method.
-class AsymImpl {
+class RsaAsymImpl : public AsymImpl {
 public:
     /// @brief Constructor from a key, asym and hash algorithm,
     ///        key kind and key binary format
@@ -52,25 +52,18 @@ public:
     ///
     /// @param key            The key to sign/verify with
     /// @param len            The length of the key
-    /// @param asym_algorithm The asymmetrical cryptography algorithm
     /// @param hash_algorithm The hash algorithm
     /// @param key_kind       The key kind
     /// @param key_format     The key binary format
-    explicit AsymImpl(const void* key, size_t key_len,
-                      const AsymAlgorithm asym_algorithm,
-                      const HashAlgorithm hash_algorithm,
-                      const AsymKeyKind key_kind,
-                      const AsymFormat key_format) {
-        algo_ = asym_algorithm;
+    RsaAsymImpl(const void* key, size_t key_len,
+                const HashAlgorithm hash_algorithm,
+                const AsymKeyKind key_kind,
+                const AsymFormat key_format) {
+        algo_ = RSA_;
         hash_ = hash_algorithm;
         kind_ = key_kind;
         pkey_ = NULL;
         x509_ = NULL;
-        if (algo_ != RSA_) {
-            isc_throw(UnsupportedAlgorithm,
-                      "Unknown asym algorithm: " <<
-                      static_cast<int>(algo_));
-        }
         const EVP_MD* md = ossl::getHashAlgorithm(hash_);
         if (md == 0) {
             isc_throw(UnsupportedAlgorithm,
@@ -301,26 +294,19 @@ public:
     ///
     /// @param filename       The key file name/path
     /// @param password       The PKCS#8 password
-    /// @param asym_algorithm The asymmetrical cryptography algorithm
     /// @param hash_algorithm The hash algorithm
     /// @param key_kind       The key kind
     /// @param key_format     The key binary format
-    explicit AsymImpl(const std::string& filename,
-                      const std::string& password,
-                      const AsymAlgorithm asym_algorithm,
-                      const HashAlgorithm hash_algorithm,
-                      const AsymKeyKind key_kind,
-                      const AsymFormat key_format) {
-        algo_ = asym_algorithm;
+    RsaAsymImpl(const std::string& filename,
+                const std::string& password,
+                const HashAlgorithm hash_algorithm,
+                const AsymKeyKind key_kind,
+                const AsymFormat key_format) {
+        algo_ = RSA_;
         hash_ = hash_algorithm;
         kind_ = key_kind;
         pkey_ = NULL;
         x509_ = NULL;
-        if (algo_ != RSA_) {
-            isc_throw(UnsupportedAlgorithm,
-                      "Unknown asym algorithm: " <<
-                      static_cast<int>(algo_));
-        }
         const EVP_MD* md = ossl::getHashAlgorithm(hash_);
         if (md == 0) {
             isc_throw(UnsupportedAlgorithm,
@@ -853,7 +839,7 @@ public:
     }
 
     /// @brief Destructor
-    ~AsymImpl() {
+    virtual ~RsaAsymImpl() {
         if (mdctx_) {
             EVP_MD_CTX_cleanup(mdctx_.get());
         }
@@ -892,29 +878,22 @@ public:
     ///
     /// \param sig_format The signature binary format
     size_t getSignatureLength(const AsymFormat sig_format) const {
-        switch (algo_) {
-        case RSA_:
-            switch (sig_format) {
-            case BASIC:
-            case ASN1:
-            case DNS:
-                // In all cases a big integer of the size of n
-                return (static_cast<size_t>(EVP_PKEY_size(pkey_)));
-            default:
-                isc_throw(UnsupportedAlgorithm,
-                          "Unknown RSA Signature format: " <<
-                          static_cast<int>(sig_format));
-            }
+        switch (sig_format) {
+        case BASIC:
+        case ASN1:
+        case DNS:
+            // In all cases a big integer of the size of n
+            return (static_cast<size_t>(EVP_PKEY_size(pkey_)));
         default:
             isc_throw(UnsupportedAlgorithm,
-                      "Unknown asym algorithm: " <<
-                      static_cast<int>(algo_));
+                      "Unknown RSA Signature format: " <<
+                      static_cast<int>(sig_format));
         }
     }           
 
     /// @brief Add data to digest
     ///
-    /// See @ref isc::cryptolink::Asym::update() for details.
+    /// See @ref isc::cryptolink::AsymBase::update() for details.
     void update(const void* data, const size_t len) {
         if (!EVP_DigestUpdate(mdctx_.get(), data, len)) {
             isc_throw(LibraryError, "EVP_DigestUpdate");
@@ -923,7 +902,7 @@ public:
 
     /// @brief Calculate the final signature
     ///
-    /// See @ref isc::cryptolink::Asym::sign() for details.
+    /// See @ref isc::cryptolink::AsymBase::sign() for details.
     void sign(isc::util::OutputBuffer& result, size_t len,
               const AsymFormat sig_format) {
         unsigned int size = getSignatureLength(sig_format);
@@ -939,7 +918,7 @@ public:
 
     /// @brief Calculate the final signature
     ///
-    /// See @ref isc::cryptolink::Asym::sign() for details.
+    /// See @ref isc::cryptolink::AsymBase::sign() for details.
     void sign(void* result, size_t len, const AsymFormat sig_format) {
         unsigned int size = getSignatureLength(sig_format);
         ossl::SecBuf<unsigned char> sig(size);
@@ -954,7 +933,7 @@ public:
 
     /// @brief Calculate the final signature
     ///
-    /// See @ref isc::cryptolink::Asym::sign() for details.
+    /// See @ref isc::cryptolink::AsymBase::sign() for details.
     std::vector<uint8_t> sign(size_t len, const AsymFormat sig_format) {
         unsigned int size = getSignatureLength(sig_format);
         ossl::SecBuf<unsigned char> sig(size);
@@ -968,7 +947,7 @@ public:
 
     /// @brief Verify an existing signature
     ///
-    /// See @ref isc::cryptolink::Asym::verify() for details.
+    /// See @ref isc::cryptolink::AsymBase::verify() for details.
     bool verify(const void* sig, size_t len, const AsymFormat sig_format) {
         size_t size = getSignatureLength(sig_format);
         if (len != size) {
@@ -1014,7 +993,7 @@ public:
 
     /// @brief Export the key value (binary)
     ///
-    /// See @ref isc::cryptolink::Asym::exportkey() for details
+    /// See @ref isc::cryptolink::AsymBase::exportkey() for details
     std::vector<uint8_t> exportkey(const AsymKeyKind key_kind,
                                    const AsymFormat key_format) const {
         if ((key_kind == PRIVATE) && (key_format == BASIC)) {
@@ -1138,7 +1117,7 @@ public:
 
     /// @brief Export the key value (file)
     ///
-    /// See @ref isc::cryptolink::Asym::exportkey() for details
+    /// See @ref isc::cryptolink::AsymBase::exportkey() for details
     void exportkey(const std::string& filename,
                    const std::string& password,
                    const AsymKeyKind key_kind,
@@ -1317,7 +1296,7 @@ public:
 
     /// @brief Check the validity
     ///
-    /// See @ref isc::cryptolink::Asym::validate() for details
+    /// See @ref isc::cryptolink::AsymBase::validate() for details
     bool validate() const {
         RSA* rsa;
         X509_STORE* store;
@@ -1379,7 +1358,10 @@ public:
     /// @brief Compare two keys
     ///
     /// See @ref isc::cryptolink::Asym::compare() for details
-    bool compare(const AsymImpl* other, const AsymKeyKind key_kind) const {
+    bool compare(const RsaAsymImpl* other, const AsymKeyKind key_kind) const {
+        if (!other || (other->algo_ != RSA_)) {
+            return false;
+        }
         int status;
         switch (key_kind) {
         case CERT:
@@ -1471,9 +1453,16 @@ Asym::Asym(const void* key, size_t key_len,
            const AsymKeyKind key_kind,
            const AsymFormat key_format)
 {
-    impl_ = new AsymImpl(key, key_len,
-                         asym_algorithm, hash_algorithm,
-                         key_kind, key_format);
+    switch (asym_algorithm) {
+    case RSA_:
+        impl_ = new RsaAsymImpl(key, key_len, hash_algorithm,
+                                key_kind, key_format);
+        return;
+    default:
+        isc_throw(UnsupportedAlgorithm,
+                  "Unknown asym algorithm: " <<
+                  static_cast<int>(asym_algorithm));
+    }
 }
 
 Asym::Asym(const std::vector<uint8_t> key,
@@ -1482,9 +1471,16 @@ Asym::Asym(const std::vector<uint8_t> key,
            const AsymKeyKind key_kind,
            const AsymFormat key_format)
 {
-    impl_ = new AsymImpl(&key[0], key.size(),
-                         asym_algorithm, hash_algorithm,
-                         key_kind, key_format);
+    switch (asym_algorithm) {
+    case RSA_:
+        impl_ = new RsaAsymImpl(&key[0], key.size(), hash_algorithm,
+                                key_kind, key_format);
+        return;
+    default:
+        isc_throw(UnsupportedAlgorithm,
+                  "Unknown asym algorithm: " <<
+                  static_cast<int>(asym_algorithm));
+    }
 }
 
 Asym::Asym(const std::string& filename,
@@ -1494,9 +1490,16 @@ Asym::Asym(const std::string& filename,
            const AsymKeyKind key_kind,
            const AsymFormat key_format)
 {
-    impl_ = new AsymImpl(filename, password,
-                         asym_algorithm, hash_algorithm,
-                         key_kind, key_format);
+    switch (asym_algorithm) {
+    case RSA_:
+        impl_ = new RsaAsymImpl(filename, password, hash_algorithm,
+                                key_kind, key_format);
+        return;
+    default:
+        isc_throw(UnsupportedAlgorithm,
+                  "Unknown asym algorithm: " <<
+                  static_cast<int>(asym_algorithm));
+    }
 }
 
 Asym::~Asym() {
@@ -1607,7 +1610,20 @@ Asym::validate() const {
 
 bool
 Asym::compare(const Asym* other, const AsymKeyKind key_kind) const {
-    return (impl_->compare(other->impl_, key_kind));
+    if (getAsymAlgorithm() != other->getAsymAlgorithm()) {
+        return false;
+    }
+    if (getAsymAlgorithm() == RSA_) {
+        const RsaAsymImpl* impl = dynamic_cast<const RsaAsymImpl*>(impl_);
+        // Should not happen but to test is better than to crash
+        if (!impl) {
+            isc_throw(Unexpected, "dynamic_cast failed on RsaAsymImpl*");
+        }
+        const RsaAsymImpl* oimpl =
+            dynamic_cast<const RsaAsymImpl*>(other->impl_);
+        return (impl->compare(oimpl, key_kind));
+    }
+    isc_throw(UnsupportedAlgorithm, "compare");
 }
 
 } // namespace cryptolink
index ee6fb17a2fde01f590ef2039f393cb6ceb33b31b..6db19ed700fcd9cf5192a1552ee05f5f5db81d71 100644 (file)
@@ -931,14 +931,14 @@ TEST(AsymTest, callout) {
     // Install validate_certificate_callout
     LibraryHandle& preCLH = HooksManager::preCalloutsLibraryHandle();
     EXPECT_NO_THROW(preCLH.registerCallout("validate_certificate",
-                                          validate_certificate_callout));
+                                           validate_certificate_callout));
 
     // Get a certificate and validate it
     CryptoLink& crypto = CryptoLink::getCryptoLink();
     boost::shared_ptr<Asym> cert(crypto.createAsym(certfile, "",
-                                                  RSA_, SHA1,
-                                                  CERT, ASN1),
-                                deleteAsym);
+                                                   RSA_, SHA1,
+                                                   CERT, ASN1),
+                                 deleteAsym);
     EXPECT_TRUE(cert->validate());
 
     // Check that callouts were indeed called