Skip to content

Resetting library state #3018

@arrowd

Description

@arrowd

I'm writing a daemon-like application that runs for a long time and make calls to OpenSC via both PKCS11 API and the internal one (sc_*). I know that I shouldn't really use sc_* stuff, but the bug I'm going to explain here can also be reproduced with pure C_* functions.

The core of the problem is OpenSC seems to cache quite a lot of stuff and there is no way to tell it to "reload". This can be illustrated with the following example:

$ opensc-explorer
OpenSC [3F00]> cat 005e
00000000: 61 73 64 61 73 64 00 asdasd.
OpenSC [3F00]> erase
OpenSC [3F00]> cat 005e
00000000: 61 73 64 61 73 64 00 asdasd.
OpenSC [3F00]> ^D
$ opensc-explorer
OpenSC Explorer version 0.24.0
Using reader with a card: Nitrokey Nitrokey 3 [CCID/ICCD Interface] 00 00
OpenSC [3F00]> cat 005e

As you can see, the erase command actually cleared out the 3F00/005e EF, but this change can't be seen by the library until I restart the program (read: reinitialize the library).

A related example with PKCS11 API is following:

  1. Generate a key pair
    CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
    CK_ULONG modulusBits = 2048;
    CK_BBOOL _true = TRUE;
    CK_BBOOL _false = FALSE;
    CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
    CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
    CK_ATTRIBUTE publicKeyTemplate[20] = {
        {CKA_CLASS, &pubkey_class, sizeof(pubkey_class)},
        {CKA_TOKEN, &_true, sizeof(_true)},
        {CKA_PRIVATE, &_false, sizeof(_false)},
        {CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
    };
    int n_pubkey_attr = 4;
    CK_ATTRIBUTE privateKeyTemplate[20] = {
        {CKA_CLASS, &privkey_class, sizeof(privkey_class)},
        {CKA_TOKEN, &_true, sizeof(_true)},
        {CKA_PRIVATE, &_true, sizeof(_true)},
        {CKA_SENSITIVE, &_true, sizeof(_true)},
    };
    int n_privkey_attr = 4;

    rv = m_p11->C_GenerateKeyPair(m_sessionHandle, &mechanism,
                                    publicKeyTemplate, n_pubkey_attr,
                                    privateKeyTemplate, n_privkey_attr,
                                    &hPublicKey, &hPrivateKey);
  1. Output a modulus:
    CK_BBOOL _true = TRUE;
    CK_ATTRIBUTE attrs[] =
    {
        { CKA_ENCRYPT, &_true, sizeof(_true)},
    };
    auto rv = m_p11->C_FindObjectsInit(m_sessionHandle, attrs, sizeof(attrs) / sizeof(CK_ATTRIBUTE));
    if (rv != CKR_OK) {
...
    }

    CK_OBJECT_HANDLE key;
    CK_ULONG outSize;
    rv = m_p11->C_FindObjects(m_sessionHandle, &key, 1, &outSize);
    m_p11->C_FindObjectsFinal(m_sessionHandle);

    CK_ATTRIBUTE attr = { CK_MODULUS, NULL, 0 };
    rv = m_p11->C_GetAttributeValue(m_sessionHandle, object, &attr, 1);
    if (rv != CKR_OK) {
...
    }
    if (attr.ulValueLen == -1u)
        ...

    QByteArray ret(attr.ulValueLen + 1, 0);

    attr.pValue = ret.data();
    if (!attr.pValue)
        ...

    rv = m_p11->C_GetAttributeValue(m_sessionHandle, object, &attr, 1);
    if (attr.ulValueLen == -1u)
        ...
  1. Generate a key pair again using the same code as in step 1.
  2. Output a modulus again with the code from step 2. It outputs the same byte array, despite the fact that key pair is changed.
  3. Restart the program
  4. Output a modulus third time and now it is different from the previous two calls.

Running pkcs11-tool or openpgp-tool between steps 4 and 5 confirms that keys are actually changed on-card, it is just the application doesn't see the change.

To sum this up, I need to trigger the same reloading/recaching process inside the library as when the token is physically reattached to the host. Or am I fundametally missing something?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions