opendnssec / SoftHSMv2

SoftHSM version 2
http://www.softhsm.org/
Other
768 stars 341 forks source link

GCM decrypt fails for 0-sized tags #568

Open onavratil-monetplus opened 4 years ago

onavratil-monetplus commented 4 years ago

I can succesfully encrypt with:

        CK_GCM_PARAMS params;
        params.pIv = iv.data();
        params.ulIvLen = iv.size();
        params.pAAD = NULL_PTR;
        params.ulAADLen = 0;
        params.ulTagBits = 0;

        P11::Mechanism mechaEncrypt = {static_cast<CK_MECHANISM_TYPE>(P11::MechanismType::AesGcm), &params, sizeof(params)};

But an attempt to decrypt with an IDENTICAL mechanism fails in C_Decrypt (not C_DecryptInit) with a CKR_GENERAL_ERROR 0x00000005UL Syslog tells me OSSLEVPSymmetricAlgorithm.cpp(512): EVP_DecryptFinal failed (0x00000000): error:00000000:lib(0):func(0):reason(0)

Identical approach WORKS if I increase tagBits to 16 - thus I assume there is some exception if the tag is empty, yet I was not able to trace it properly.

In order to justify my approach: Using GCM with omitted tag (0-size) is allowed by-the-standard: ulTagBits length of authentication tag (output following cipher text) in bits. Can be any value between 0 and 128. and may be useful if integrity is assured on a higher level (another wrapper). GCM thus works as an equivalent for CTR, which would make more sense to use in this case, but is often not supported.

rijswijk commented 4 years ago

Unfortunately the output from OpenSSL isn't very helpful. Can you provide a minimum working example in C to reproduce this issue? That would allow us to investigate this further.

onavratil-monetplus commented 4 years ago

Hope you are okay with Botan (else the PKCS is gory). I get log: Aug 20 10:03:22 localhost MWE[11996]: OSSLEVPSymmetricAlgorithm.cpp(512): EVP_DecryptFinal failed (0x00000000): error:00000000:lib(0):func(0):reason(0) MWE output:

No problem up to here...
Got excption PKCS11 error 5 code 5

the MWE:

#include <botan/p11_module.h>
#include <iostream>
#include <iomanip>
#include <optional>
#include <botan/p11_slot.h>
#include <botan/p11_object.h>
#include <botan/p11_session.h>
#include <botan/p11_rsa.h>

namespace P11 = Botan::PKCS11;

int main(int argc, char ** argv){

    P11::Module module("/usr/local/lib/softhsm/libsofthsm2.so");

    std::vector<P11::SlotId> slots = P11::Slot::get_available_slots(module, true);

    std::optional<P11::Slot> targetSlot;

    /* Initialize temp token */
    for(auto const &slotId : slots){
        P11::Slot slot(module, slotId);
        auto tokenInfo = slot.get_token_info();
        if(tokenInfo.flags & static_cast<CK_FLAGS>(P11::Flag::TokenInitialized)){
            //skip initialized
            continue;
        }
        slot.initialize("Temp token", {'1','2','3','4'});
        P11::set_pin(slot, {'1','2','3','4'}, {'1','1','1','1'});
        targetSlot.emplace(slot);
        break;
    }
    if(!targetSlot)
        return -1;
    /* Log in session */
    P11::Session session(*targetSlot, false);
    session.login(P11::UserType::User, {'1','1','1','1'});

    /* Generate aes key */
    P11::SecretKeyProperties propsEncryptor(P11::KeyType::Aes);
    propsEncryptor.set_label("Temp AES Key");
    propsEncryptor.set_encrypt(true);
    propsEncryptor.set_decrypt(true);
    propsEncryptor.set_token(false);
    propsEncryptor.add_numeric(P11::AttributeType::ValueLen, 32UL);
    P11::Mechanism mechaEncryption = {static_cast<CK_MECHANISM_TYPE >(P11::MechanismType::AesKeyGen), NULL_PTR, 0};

    P11::ObjectHandle keyHandle;
    const std::vector<P11::Attribute> vec = propsEncryptor.attributes();
    module->C_GenerateKey(session.handle(), &mechaEncryption, const_cast<CK_ATTRIBUTE*>(&vec[0]), vec.size(), &keyHandle);

    /* Prepare for GCM encryption with 0 tag */
    std::vector<uint8_t> iv(12,0);
    CK_GCM_PARAMS params;
    params.pIv = iv.data();
    params.ulIvLen = iv.size();
    params.pAAD = NULL_PTR;
    params.ulAADLen = 0;
    params.ulTagBits = 0;

    P11::Mechanism mecha = {static_cast<CK_MECHANISM_TYPE>(P11::MechanismType::AesGcm), &params, sizeof(params)};
    std::vector<uint8_t> sampleData{1,2,3,4,5,6,7,8,9,10};

    std::vector<uint8_t> encryptedData;

    /* GCM encryption with 0 tag */
    module->C_EncryptInit(session.handle(), &mecha, keyHandle);
    module->C_Encrypt(session.handle(), sampleData, encryptedData);

    /* GCM Decryption of the same data */
    std::vector<uint8_t> decryptedData;
    module->C_DecryptInit(session.handle(), &mecha, keyHandle);
    std::cout << "No problem up to here..." << std::endl;
    try{
        module->C_Decrypt(session.handle(), encryptedData, decryptedData);
    }
    catch(const P11::PKCS11_Error &e){
        std::cout << "Got excption " << e.what() << " code " << e.error_code() <<  std::endl;
    }
    return 0;
}
rijswijk commented 4 years ago

Interesting that you used Botan; this leads me to a follow-up question: if you build SoftHSM against Botan, does it work then? (just so we know)

onavratil-monetplus commented 4 years ago

I have another environment with botan-compiled SoftHSM. The MWE throws

terminate called after throwing an instance of 'Botan::PKCS11::PKCS11_ReturnError'
  what():  PKCS11 error 112
Aborted

from pkcs docs CKR_MECHANISM_INVALID 0x00000070UL

I get this one already thrown at EncryptInit. Not sure if GCM is supported there at all. But at least, I get a error message on a reasonable place (not in the last step)

onavratil-monetplus commented 4 years ago

One more interesting thing. I tried the same MWE with extending ulTagBits to 128. Then it passes Botan-compiled softhsm2 too.... I think it is related to https://github.com/randombit/botan/issues/1207 Moreover....I believe that in this case, it would be better to return CKR_MECHANISM_PARAM_INVALID rather than CKR_MECHANISM_INVALID

rijswijk commented 4 years ago

Could you open a separate issue for that, I think you're right (it should return CKR_MECHANISM_PARAM_INVALID)