]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
pkcs11signers: Support CKA_ALWAYS_AUTHENTICATE
authorAki Tuomi <cmouse@cmouse.fi>
Sun, 16 Apr 2023 18:09:29 +0000 (21:09 +0300)
committerAki Tuomi <cmouse@cmouse.fi>
Thu, 13 Jul 2023 06:55:32 +0000 (09:55 +0300)
If private key has this flag, relogin with CKU_CONTEXT_SPECIFIC
before sign/verify operation.

pdns/pkcs11signers.cc

index 872bd518a5606355e1f9323683fb0bb8c7925a74..181e3da9ee1135f4adc30fcdcb4861f34426fc3c 100644 (file)
@@ -218,6 +218,7 @@ class Pkcs11Slot {
     CK_SESSION_HANDLE d_session;
     CK_SLOT_ID d_slot;
     CK_RV d_err{};
+    std::string d_pin;
 
     void logError(const std::string& operation) const {
       if (d_err) {
@@ -248,22 +249,26 @@ class Pkcs11Slot {
       }
     }
 
-    bool Login(const std::string& pin) {
-      if (d_logged_in) return true;
+    bool Login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) {
+      if (userType == CKU_USER && d_logged_in) return true;
 
       auto uPin = std::make_unique<unsigned char[]>(pin.size());
       memcpy(uPin.get(), pin.c_str(), pin.size());
-      d_err = d_functions->C_Login(this->d_session, CKU_USER, uPin.get(), pin.size());
-      memset(uPin.get(), 0, pin.size());
+      d_err = d_functions->C_Login(this->d_session, userType, uPin.get(), pin.size());
       logError("C_Login");
 
-      if (d_err == 0) {
+      if (d_err == 0 && userType == CKU_USER) {
         d_logged_in = true;
+        d_pin = pin;
       }
 
       return d_logged_in;
     }
 
+    bool Relogin() {
+      return Login(d_pin, CKU_CONTEXT_SPECIFIC);
+    }
+
     bool LoggedIn() const { return d_logged_in; }
 
     CK_SESSION_HANDLE& Session() { return d_session; }
@@ -281,6 +286,7 @@ class Pkcs11Token {
     CK_OBJECT_HANDLE d_public_key;
     CK_OBJECT_HANDLE d_private_key;
     CK_KEY_TYPE d_key_type;
+    bool d_always_auth;
 
     CK_ULONG d_bits;
     std::string d_exponent;
@@ -380,6 +386,11 @@ class Pkcs11Token {
       }
       d_private_key = key[0];
       attr.clear();
+      attr.emplace_back(CKA_ALWAYS_AUTHENTICATE, '\0');
+      if (GetAttributeValue2(*slot, d_private_key, attr)==0) {
+        d_always_auth = attr[0].byte() != 0;
+      }
+      attr.clear();
       attr.emplace_back(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY);
       attr.emplace_back(CKA_LABEL, d_pub_label);
       FindObjects2(*slot, attr, key, 1);
@@ -463,8 +474,12 @@ class Pkcs11Token {
       CK_ULONG buflen = sizeof buffer; // should be enough for most signatures.
       auto slot = d_slot->lock();
 
-      // perform signature
       if ((d_err = slot->f()->C_SignInit(slot->Session(), mechanism, d_private_key))) { logError("C_SignInit"); return d_err; }
+      // check if we need to relogin
+      if (d_always_auth) {
+         slot->Relogin();
+      }
+      // perform signature
       d_err = slot->f()->C_Sign(slot->Session(), (unsigned char*)data.c_str(), data.size(), buffer, &buflen);
 
       if (!d_err) {
@@ -480,6 +495,11 @@ class Pkcs11Token {
       auto slot = d_slot->lock();
 
       if ((d_err = slot->f()->C_VerifyInit(slot->Session(), mechanism, d_public_key))) { logError("C_VerifyInit"); return d_err; }
+      // check if we need to relogin
+      if (d_always_auth) {
+         slot->Relogin();
+      }
+
       d_err = slot->f()->C_Verify(slot->Session(), (unsigned char*)data.c_str(), data.size(), (unsigned char*)signature.c_str(), signature.size());
       logError("C_Verify");
       return d_err;