Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenPGP: fixed state tracking after erasing card #3024

Merged
merged 2 commits into from
Mar 11, 2024

Conversation

frankmorgner
Copy link
Member

fixes #3018

Checklist
  • Documentation is added or updated
  • New files have a LGPL 2.1 license statement
  • PKCS#11 module is tested
  • Windows minidriver is tested
  • macOS tokend is tested

if (((info->access & READ_MASK) != READ_NEVER) && (info->get_fn != NULL)) {
pgp_blob_t *child = NULL;

child = pgp_new_blob(card, priv->mf, info->id, sc_file_new());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the pgp_new_blob() fails, the memory allocated by sc_file_new() is leaked (yeah, it was in the original code too but as I noticed it, it would be good to fix it).

src/libopensc/card-openpgp.c Outdated Show resolved Hide resolved
@frankmorgner
Copy link
Member Author

thanks for the review. I'll look at the suggestions, when @arrowd confirms that it actually fixes the problem

@arrowd
Copy link

arrowd commented Feb 14, 2024

I will not be able to test this during this week, sorry, but I will certainly check this out later.

If I'm reading it right, this change would allow me to just do sc_disconnect_card + sc_connect_card to refresh the state?

@frankmorgner
Copy link
Member Author

If I'm reading it right, this change would allow me to just do sc_disconnect_card + sc_connect_card to refresh the state?

No. If this works as expected, then you will get refreshed objects right after erasing the card without the need of reconnecting.

@arrowd
Copy link

arrowd commented Feb 15, 2024

The problem is not only with erasing.

The first post of #3018 shows a code that generates a keypair twice in a row, but it seemingly doesn't change until the reinsertion (physical or emulated with my hacks).

@frankmorgner
Copy link
Member Author

please check if it works in case of erasing the card. If so, one case is fixed and you know where to poke.

@arrowd
Copy link

arrowd commented Feb 25, 2024

Sorry for taking this too long. The proposed change indeed improves things for both opensc-explorer and my daemon program. Erasing the card causes OPENPGP_ACCOUNT field to be reset immediately without the need to reinsert the token or to programmatically reset the reader via hacks.

The key information isn't updated, though.

@frankmorgner
Copy link
Member Author

If I understand correctly, you are NOT referring to opensc-explorer with respect to the key inforamtion, since this isn't used anywhere here. I assume that opensc-explorer works as expected.

If you're talking about the card's profile which is readable via PKCS#11, we will only refresh that if modifications were executed via PKCS#11. If some concurrent process modifies the card, you need to C_Finalize and C_Initialize again to refresh the token information. Modification of the OpenPGP card via PKCS#11 is not completely implemented; in particular, erasing the card is currently not available:

static int openpgp_erase(struct sc_profile *profile, sc_pkcs15_card_t *p15card)
{
return SC_ERROR_NOT_SUPPORTED;
}

@dengert
Copy link
Member

dengert commented Feb 26, 2024

Modification of the OpenPGP card via PKCS#11 is not completely implemented; in particular, erasing the card is currently not available:

It might be easy to add. OpenPGP specs V3.4.1 (also in v.2.0 ) defines two optional commands
7.2.16 TERMINATE DF must be run first.
7.2.17 ACTIVATE FILE
"This optional command (announced in Life Cycle Status indicator in Historical bytes) can
be used to reset all values (DOs, Keys, PWs etc.) to their default values (after production/
initialisation)."

openpgp-tool.c uses SC_CARDCTL_ERASE_CARD to call https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-openpgp.c#L3480-L3555

Accept for the pin code this comes down to the TERMINATE DF and ACTIVATE FILE commands.

@arrowd you could try these on your cards" opensc-tool -s "00 E6 00 00" -s "00 44 00 00"
but the could leave the card unusable

@arrowd
Copy link

arrowd commented Feb 26, 2024

If I understand correctly, you are NOT referring to opensc-explorer with respect to the key inforamtion, since this isn't used anywhere here. I assume that opensc-explorer works as expected.

Yes, the problem with opensc-explorer was

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.

It now works correctly - nothing gets printed after erase is done.

If you're talking about the card's profile which is readable via PKCS#11, we will only refresh that if modifications were executed via PKCS#11. If some concurrent process modifies the card, you need to C_Finalize and C_Initialize again to refresh the token information.

There are no concurrent processes in my case. I just call C_GenerateKeyPair twice and the key doesn't change after the second call without reinserting/resetting hack. See #3018 (comment) after the "A related example with PKCS11 API is following" sentence.

C_Finalize was already suggested before, but it isn't a solution for me: #3018 (comment)

Modification of the OpenPGP card via PKCS#11 is not completely implemented; in particular, erasing the card is currently not available

Indeed, in my daemon I call sc_card_ctl(m_slot->p11card->card, SC_CARDCTL_ERASE_CARD, NULL) to reset the token. I tried C_InitToken but it didn't work.

you could try these on your cards" opensc-tool -s "00 E6 00 00" -s "00 44 00 00"
but the could leave the card unusable

What does 00 44 00 00 do in this case?

@dengert
Copy link
Member

dengert commented Feb 26, 2024

What does 00 44 00 00 do in this case?

7.2.17 ACTIVATE FILE
This optional command (announced in Life Cycle Status indicator in Historical bytes) can
be used to reset all values (DOs, Keys, PWs etc.) to their default values (after production/
initialisation). The command has effect only, if the life cycle status is in initialisation state
(indicator byte set to 03). If the command is used in operational state, it will end with status
bytes 9000, but nothing in the application will be changed (dummy command). The command
can be used directly after TERMINATE DF without resetting the card.
Command:
CLA 00 / 0C
INS 44
P1 00
P2 00
Lc Empty
Data
field
Empty
Le Empty
Response:
Data field Empty
SW1-SW2 9000 or specific status bytes
Example:
CLA INS P1 P2
00 44 00 00
SW1SW2
9000

@dengert
Copy link
Member

dengert commented Feb 26, 2024

00 44 00 00 "reset all values (DOs, Keys, PWs etc.) to their default values (after production/initialisation)" It is part of card-openpgp.c pgp_erase_card

If you then run opensc-explorer erase it may delete all the DOs which were just reset! I would suggest only use opensc-explorer to examine the card, not to change anything on it.

Modify pkcs15init/pkcs15-openpgp.c to call sc_card_ctl(m_slot->p11card->card, SC_CARDCTL_ERASE_CARD, NULL) (with changes as needed).

Modify libopensc/card-openpgp.c to make sure populate_blobs_to_mf is called at the end of pgp_erase_card

@frankmorgner
Copy link
Member Author

I fixed the memory leaks and found some other minor fix. I'd like to leave this fix as is, because I doubt that we will get more insights without debugging.

Copy link
Member

@Jakuje Jakuje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. Do we want this in 0.25.0?

@frankmorgner
Copy link
Member Author

It is not essential, so we can postpone this to the next release

@frankmorgner frankmorgner merged commit d2cbd63 into OpenSC:master Mar 11, 2024
43 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Resetting library state
4 participants