From: Aki Tuomi Date: Sun, 16 Apr 2023 18:09:29 +0000 (+0300) Subject: pkcs11signers: Support CKA_ALWAYS_AUTHENTICATE X-Git-Tag: rec-5.0.0-alpha1~107^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bd09e8a30d1db7f3fe21b9a965252d00977356d2;p=thirdparty%2Fpdns.git pkcs11signers: Support CKA_ALWAYS_AUTHENTICATE If private key has this flag, relogin with CKU_CONTEXT_SPECIFIC before sign/verify operation. --- diff --git a/pdns/pkcs11signers.cc b/pdns/pkcs11signers.cc index 872bd518a5..181e3da9ee 100644 --- a/pdns/pkcs11signers.cc +++ b/pdns/pkcs11signers.cc @@ -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(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;