Repository: randombit/botan
Pull request #2293 (2020-03-04 13:18:41)

Add missing overloads to PKCS11_ECDSA_PrivateKey
Since we don't derive from `ECDSA_PrivateKey`, `message_parts()` and `message_part_size()` need to be implemented additionally here. Fixes generating PKCS#11 ECDSA signatures as a DER sequence, which is required by strongswan, for example.

Also adds a test, but still can not be executed against SoftHSM. Tested with a recent ATOS CardOS smartcard locally, fix works fine.


Patch:
diff --git a/src/lib/prov/pkcs11/p11_ecdsa.h b/src/lib/prov/pkcs11/p11_ecdsa.h
index 0843c85ba..82721a466 100644
--- a/src/lib/prov/pkcs11/p11_ecdsa.h
+++ b/src/lib/prov/pkcs11/p11_ecdsa.h
@@ -97,6 +97,11 @@ class BOTAN_PUBLIC_API(2,0) PKCS11_ECDSA_PrivateKey final : public PKCS11_EC_Pri
          return "ECDSA";
          }
 
+      size_t message_parts() const override { return 2; }
+
+      size_t message_part_size() const override
+         { return domain().get_order().bytes(); }
+
       /// @return the exported ECDSA private key
       ECDSA_PrivateKey export_key() const;
 


Test patch:
diff --git a/src/tests/test_pkcs11_high_level.cpp b/src/tests/test_pkcs11_high_level.cpp
index 37e56a0a0..47a5bf5e5 100644
--- a/src/tests/test_pkcs11_high_level.cpp
+++ b/src/tests/test_pkcs11_high_level.cpp
@@ -2,6 +2,7 @@
 * (C) 2016 Daniel Neus
 * (C) 2016 Philipp Weber
 * (C) 2019 Michael Boric
+* (C) 2020 René Korthaus
 *
 * Botan is released under the Simplified BSD License (see license.txt)
 */
@@ -113,6 +114,11 @@ class TestSession
          return *m_session;
          }
 
+      inline Slot& slot() const
+         {
+         return *m_slot;
+         }
+
    private:
       std::unique_ptr<Module> m_module = nullptr;
       std::unique_ptr<Slot> m_slot = nullptr;
@@ -1108,6 +1114,10 @@ Test::Result test_ecdsa_sign_verify_core(EC_Group_Encoding ec_dompar_enc, std::s
     curves.push_back("secp256r1");
     curves.push_back("brainpool512r1");
 
+    Slot& slot = test_session.slot();
+    SlotInfo info = slot.get_slot_info();
+    std::string manufacturer(reinterpret_cast< char* >(info.manufacturerID));
+
     for(auto &curve : curves)
         {
         // generate key pair
@@ -1115,26 +1125,39 @@ Test::Result test_ecdsa_sign_verify_core(EC_Group_Encoding ec_dompar_enc, std::s
 
         std::vector<uint8_t> plaintext(20, 0x01);
 
-        auto sign_and_verify = [&keypair, &plaintext, &result](const std::string& emsa)
+        auto sign_and_verify = [&keypair, &plaintext, &result](const std::string& emsa,
+               const Botan::Signature_Format format, bool check_soft)
             {
-            Botan::PK_Signer signer(keypair.second, Test::rng(), emsa, Botan::IEEE_1363);
+            Botan::PK_Signer signer(keypair.second, Test::rng(), emsa, format);
             auto signature = signer.sign_message(plaintext, Test::rng());
 
-            Botan::PK_Verifier token_verifier(keypair.first, emsa, Botan::IEEE_1363);
+            Botan::PK_Verifier token_verifier(keypair.first, emsa, format);
             bool ecdsa_ok = token_verifier.verify_message(plaintext, signature);
 
             result.test_eq("ECDSA PKCS11 sign and verify: " + emsa, ecdsa_ok, true);
 
             // test against software implementation if available
-#if defined (BOTAN_HAS_EMSA_RAW)
-            Botan::PK_Verifier soft_verifier(keypair.first, emsa, Botan::IEEE_1363);
-            bool soft_ecdsa_ok = soft_verifier.verify_message(plaintext, signature);
+            if(check_soft)
+               {
+               Botan::PK_Verifier soft_verifier(keypair.first, emsa, format);
+               bool soft_ecdsa_ok = soft_verifier.verify_message(plaintext, signature);
 
-            result.test_eq("ECDSA PKCS11 verify (in software): " + emsa, soft_ecdsa_ok, true);
-#endif
+               result.test_eq("ECDSA PKCS11 verify (in software): " + emsa, soft_ecdsa_ok, true);
+               }
             };
 
-        sign_and_verify("Raw");   // SoftHSMv2 until now only supports "Raw"
+        // SoftHSMv2 until now only supports "Raw"
+        if(manufacturer.find("SoftHSM project") == std::string::npos)
+           {
+           sign_and_verify("EMSA1(SHA-256)", Botan::IEEE_1363, true);
+           sign_and_verify("EMSA1(SHA-256)", Botan::DER_SEQUENCE, true);
+           }
+
+#if defined (BOTAN_HAS_EMSA_RAW)
+        sign_and_verify("Raw", Botan::IEEE_1363, true);
+#else
+        sign_and_verify("Raw", Botan::IEEE_1363, false);
+#endif
 
         keypair.first.destroy();
         keypair.second.destroy();