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

User not logged in after logging in #521

Open
mihaicristiantanase opened this issue Nov 14, 2023 · 8 comments
Open

User not logged in after logging in #521

mihaicristiantanase opened this issue Nov 14, 2023 · 8 comments

Comments

@mihaicristiantanase
Copy link
Contributor

I have an issue with key pair generation.
This simplified code:

void runSimplifiedTest(char* lib, char* passwd)
{
	PKCS11_CTX* ctx = PKCS11_CTX_new();
	PKCS11_CTX_load(ctx, lib);

	PKCS11_SLOT* slots = NULL;
	unsigned int nslots;
	PKCS11_enumerate_slots(ctx, &slots, &nslots);
	PKCS11_SLOT* slot = PKCS11_find_token(ctx, slots, nslots);

	PKCS11_login(slot, 0, passwd);

	PKCS11_open_session(slot, 1);
	PKCS11_login(slot, 0, passwd);
	PKCS11_generate_key(slot->token, 0, 2048, "test_label", (unsigned char*)"testid", 6);
	if (ERR_peek_last_error()) {
		fprintf(stderr, "Generated errors:\n");
		ERR_print_errors_fp(stderr);
	}
}

shows the following error:
4407954944:error:81082101:PKCS#11 module:func(130):User not logged in:p11_key.c:322:

@mihaicristiantanase
Copy link
Contributor Author

If I remove the first PKCS11_login call , I get a successful key pair generation.

@mihaicristiantanase
Copy link
Contributor Author

From what I found, the second call to PKCS11_login finds the user already logged in, even though a new session was created for read-write operations (PKCS11_open_session) in the mean time.

@mihaicristiantanase
Copy link
Contributor Author

If I remove the first PKCS11_login call , I get a successful key pair generation.

And if I were to insert a PKCS11_logout just before the second PKCS11_login, the operation is also successful.

@dengert
Copy link
Member

dengert commented Nov 15, 2023

With pure PKCS11 an application can have multiple session to the same slot. C_login takes a session parameter, and changes the session state CK_STATE from CK_RO_xxx to CK_R_xxx. There are 5 possible session states. When used with a smartcard which in , C_Login is also used to change the state on the smart card and which may have a user pin and an SO pin.

(If I am reading the code correctly) https://github.com/OpenSC/libp11/blob/master/src/p11_slot.c#L220
libp11_login will create a session if one is not found for CKU_USER or CKU_SO. In your case PKCS11_login(slot, 0, passwd); will create a CK_RO_USER at line 320 and the C_Login at line 324 will convert it to a RW session.

So somehow it is getting confused because you first ask it to login and create a session, then create a new session and then do the login.

If you really want to see what PKCS11 calls are being made see OpenSC SPY: https://github.com/OpenSC/OpenSC/wiki/Using-OpenSC

@mihaicristiantanase
Copy link
Contributor Author

mihaicristiantanase commented Nov 16, 2023

I've just finished a step by step debugging with LLDB and it shows that the problem is in the second call to PKCS11_login which finds the client already logged in and it skips everything else:

return 0; /* Nothing to do */

To me, this looks to be like a bug in PKCS11_open_session which invokes

int pkcs11_open_session(PKCS11_SLOT_private *slot, int rw)

Shouldn't this function reset the login state?
Or maybe there should be a more complex mechanism that handles login state per session (not a session independent flag like it is at the moment: slot->logged_in). This might be the cause of confusion that you mentioned in the previous comment...

(lldb) r
Process 8269 launched: 'open-session-and-login' (x86_64)
Process 8269 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003bfb open-session-and-login`runSimplifiedTest(lib="/usr/local/lib/libeToken.dylib", passwd="00000000") at open-session-and-login.c:103:15
   100          PKCS11_login(slot, 0, passwd);
   101 
   102          PKCS11_open_session(slot, 1);
-> 103          PKCS11_login(slot, 0, passwd);
   104          PKCS11_generate_key(slot->token, 0, 2048, "test_label", (unsigned char*)"testid", 6);
   105          if (ERR_peek_last_error()) {
   106                  fprintf(stderr, "Generated errors:\n");
Target 0: (open-session-and-login) stopped.

(lldb) s
libp11.3.dylib was compiled with optimization - stepping may behave oddly; variables may not be available.
Process 8269 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100131cf0 libp11.3.dylib`PKCS11_login(pslot=0x000000010060a8d0, so=0, pin="00000000") at p11_front.c:171:30 [opt]
   168 
   169  int PKCS11_login(PKCS11_SLOT *pslot, int so, const char *pin)
   170  {
-> 171          PKCS11_SLOT_private *slot = PRIVSLOT(pslot);
   172          if (check_slot_fork(slot) < 0)
   173                  return -1;
   174          return pkcs11_login(slot, so, pin);
Target 0: (open-session-and-login) stopped.

(lldb) n
Process 8269 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100131cf4 libp11.3.dylib`PKCS11_login(pslot=0x000000010060a8d0, so=0, pin="00000000") at p11_front.c:172:6 [opt]
   169  int PKCS11_login(PKCS11_SLOT *pslot, int so, const char *pin)
   170  {
   171          PKCS11_SLOT_private *slot = PRIVSLOT(pslot);
-> 172          if (check_slot_fork(slot) < 0)
   173                  return -1;
   174          return pkcs11_login(slot, so, pin);
   175  }
Target 0: (open-session-and-login) stopped.

(lldb) 
Process 8269 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100131d00 libp11.3.dylib`PKCS11_login(pslot=<unavailable>, so=0, pin="00000000") at p11_front.c:174:9 [opt]
   171          PKCS11_SLOT_private *slot = PRIVSLOT(pslot);
   172          if (check_slot_fork(slot) < 0)
   173                  return -1;
-> 174          return pkcs11_login(slot, so, pin);
   175  }
   176 
   177  int PKCS11_logout(PKCS11_SLOT *pslot)
Target 0: (open-session-and-login) stopped.

(lldb) s
Process 8269 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100130e50 libp11.3.dylib`pkcs11_login(slot=0x000000010060a550, so=0, pin="00000000") at p11_slot.c:221 [opt]
   218   * Authenticate with the card.
   219   */
   220  int pkcs11_login(PKCS11_SLOT_private *slot, int so, const char *pin)
-> 221  {
   222          PKCS11_CTX_private *ctx = slot->ctx;
   223          CK_SESSION_HANDLE session;
   224          int rv;
Target 0: (open-session-and-login) stopped.

(lldb) n
Process 8269 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100130e64 libp11.3.dylib`pkcs11_login(slot=0x000000010060a550, so=0, pin="00000000") at p11_slot.c:226:22 [opt]
   223          CK_SESSION_HANDLE session;
   224          int rv;
   225 
-> 226          if (slot->logged_in >= 0)
   227                  return 0; /* Nothing to do */
   228 
   229          /* SO needs a r/w session, user can be checked with a r/o session. */
Target 0: (open-session-and-login) stopped.

(lldb) p slot->logged_in 
(int8_t) $0 = '\0'

(lldb) c
Process 8269 resuming
Generated errors:
4295917056:error:81082101:PKCS#11 module:func(130):User not logged in:p11_key.c:322:
Process 8269 exited with status = 0 (0x00000000) 

@dengert
Copy link
Member

dengert commented Nov 16, 2023

You can submit a PR if you think this is important.

@mihaicristiantanase
Copy link
Contributor Author

Sure, I can do that.
A workaround (without fully understanding the interaction between a session and the login status) I was thinking about is to simply reset the login state whenever a new session is opened.
But, before doing any changes, can you clarify the following?

  1. are multiple login statuses (one per each session) something to care about?
    As I mentioned previously, the current implementation associates a login status to a slot and, thus is session independent.
  2. How many sessions will be available at the end of this scenario?
  • open a RO session with no login
  • open a RW session with no login
  • open a RW session with USER login
  • open a RO session with SO login

@dengert
Copy link
Member

dengert commented Nov 17, 2023

@mtrojnar any comments on this?

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

No branches or pull requests

2 participants