-
Notifications
You must be signed in to change notification settings - Fork 25
authentication manager feature addition #270
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds a comprehensive authentication and authorization manager to wolfHSM, enabling user management, login/logout functionality, and permission-based access control for HSM operations.
Changes:
- New authentication manager with PIN and certificate-based authentication support
- Authorization system with group and action-level permission checks
- User management APIs for adding, deleting, and modifying users and their credentials
- Complete client and server implementation with message translation support
Reviewed changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfhsm/wh_auth.h | Core auth manager types, structures, and API definitions |
| wolfhsm/wh_message_auth.h | Message structures and translation functions for auth operations |
| wolfhsm/wh_server_auth.h | Server-side auth request handler declaration |
| wolfhsm/wh_client.h | Client-side auth API function declarations |
| wolfhsm/wh_server.h | Server context updated with auth context pointer |
| wolfhsm/wh_message.h | New auth message group and action enums |
| wolfhsm/wh_error.h | New auth-specific error codes |
| src/wh_auth.c | Core auth manager implementation with callback wrappers |
| src/wh_message_auth.c | Message translation implementations for auth messages |
| src/wh_server_auth.c | Server-side request handler for auth operations |
| src/wh_client_auth.c | Client-side auth API implementations |
| src/wh_server.c | Server integration with authorization checks |
| src/wh_client.c | Minor formatting fixes |
| port/posix/posix_auth.h | POSIX auth backend declarations |
| port/posix/posix_auth.c | POSIX auth backend implementation with in-memory user storage |
| test/wh_test_auth.h | Auth test suite declarations |
| test/wh_test_auth.c | Comprehensive auth test suite implementation |
| test/wh_test.c | Test integration for auth tests |
| examples/posix/wh_posix_server/* | Server configuration with auth context setup |
| examples/demo/client/wh_demo_client_all.c | Demo integration for auth |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 24 out of 25 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
6b32384 to
1bd722a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 29 out of 30 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 29 out of 30 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@JacobBarthelmeh merge conflicts |
…e, less verbose auth demos
04bd058 to
4d0af48
Compare
|
Force pushed to resolve merge conflict. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 28 out of 29 changed files in this pull request and generated 17 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 28 out of 29 changed files in this pull request and generated 19 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
bigbrett
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work Jacob! Just did a first pass of this, and it mostly aligns with what I was envisioning, but with one caveat. I think that the actual authorization check and logic should be part of the generic "front end" and not delegated to the back-end. See my "architectural concern" comment below.
Also, a few requests right off the bat, before I get too deep into review:
- Make the auth feature "opt-in" so it is off by default (e.g change to
WOLFHSM_CFG_CLIENT_AUTHor something like that - I like calling out client auth specifically as a feature description). Protect all auth specific code (including the struct elements in the server context) with the feature macro. Reason being I think the bulk of our customers will not be using this feature, even though it is of critical importance for FIPS L2+ customers. - Since the feature should be opt-in, ensure that when the feature is turned on, the server is able to be initialized with a NULL auth config and handle this scenario safely. This should indicate that there is no auth needed. This facilitates backwards compatibility with tests (e.g. dont need to log in as admin in every test).
- Try and use
WH_ERROR_OKfor success return. We were inconsistent about this in old code, but want to standardize around it going forward. Also helps distinguish wolfHSM returns from other lib returns like wolfCrypt/wolfSSL
Will keep going deeper into this but figured I'd speak up early so we can discuss. Let me know your thoughts.
|
|
||
| if (context->cb != NULL && context->cb->Init != NULL) { | ||
| rc = context->cb->Init(context->context, config->config); | ||
| if (rc != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets try to use WH_ERROR_OK unless we are explicitly dealing with return codes from other libs like wolfCrypt
| * @param[in] c Pointer to the client context. | ||
| * @param[in] method The authentication method to use (e.g., | ||
| * WH_AUTH_METHOD_PIN). | ||
| * @param[in] username The user name to login |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mention that this is a null terminated C string
| #include "wolfhsm/wh_client.h" | ||
| #include "wolfhsm/wh_auth.h" | ||
|
|
||
| static int _wh_Client_AuthUserNameSanityCheck(const char* username) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nits:
- no need to name static helpers with full module name (e.g.
_wh_Client_AuthXXX), just public functions. Keeps things shorter and easier to read IMO. Consider just_UserNameSanityCheck()
That said...
- "Sanity Check" doesn't quite make the return value obvious to the reader without looking at the internal implementation. Consider "_UserNameIsValid" or something like that, so you could write
if (_UserNameIsValid())and the boolean nature of the return value is made obvious to the reader
| uint8_t buffer[WOLFHSM_CFG_COMM_DATA_LEN] = {0}; | ||
| whMessageAuth_LoginRequest* msg = (whMessageAuth_LoginRequest*)buffer; | ||
| uint8_t* msg_auth_data = buffer + sizeof(*msg); | ||
| int msg_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider size_t or a fixed with unsigned type (if required) for sizes
| auth_data_len); | ||
| } while (rc == WH_ERROR_NOTREADY); | ||
|
|
||
| if (rc != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WH_ERROR_OK
| /* This function is responsible for handling all authentication and | ||
| * authorization requests from the client. | ||
| */ | ||
| int wh_Server_HandleAuthRequest(whServerContext* server, uint16_t magic, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing feature flag macro protection
| unsigned char credentials[WH_AUTH_BASE_MAX_CREDENTIALS_LEN]; | ||
| uint16_t credentials_len; | ||
| } whAuthBase_User; | ||
| /* TODO: Thread safety - The global users array is not protected by any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#275 :)
No action needed, just FYI
| WH_TEST_ASSERT_RETURN(client_id == client->comm->client_id); | ||
|
|
||
| /* Attempt to log in as an admin user for the rest of the tests */ | ||
| WH_TEST_RETURN_ON_FAIL(wh_Client_AuthLogin(client, WH_AUTH_METHOD_PIN, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be opt-in and protected by feature flags. That said, I think it would it be better to have the server's just register a NULL (e.g. uninitialized) auth context and be able to handle that? So if a server's auth context/config is never initialized but you build with auth enabled, then the server just doesn't authenticate anything and you essentially run as you would have with the feature flag disabled?
|
|
||
| /* Check on request authorization and action permissions for current user | ||
| * logged in */ | ||
| int wh_Auth_CheckRequestAuthorization(whAuthContext* context, uint16_t group, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Architectural concern here.
TLDR shouldn't the actual auth check be generically expressed here, vs delegated to the auth backend/provider?
I find it odd that this would be entirely delegated to the "auth backend", since this implies that the actual authorization check itself is backend specific. This doesn't make sense to me, since this is specifically intended to authorize a user request message against a given group/action pair, all of which are wolfHSM core library concepts using definitions from the core library, not something specific to the back-end auth provider. Wouldn't every back-end implement this auth check in exactly the same way outside of actually retrieving the permissions for a user from some backend-specific store/encoding? Pretty sure the latter is all that is backend specific here? The way I see it, the auth back-end is really just an abstraction for the data store for user data and permissions. IMO the actual auth portion should be enforced consistently regardless of the back-end.
Put another way: shouldn't the backend just know how to retrieve permissions for a given user and serialize it into a whAuthPermissions struct such that we can generically check its permissions here against the requested action?
| whAuthBase_User* found_user; | ||
| found_user = posixAuth_FindUser(username); | ||
| if (found_user != NULL && found_user->credentials_len == auth_data_len && | ||
| memcmp(found_user->credentials, auth_data, auth_data_len) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it is just a reference implementation, but as a matter of example and good practice, perhaps we should store password hashes here instead of the passwords themselves? I know it might be overkill given the threat model and that it is just stored in data vs on disk, however I could see this being low hanging fruit for complaints or people trying to be clever in pointing this out.... just a thought
The authentication manager feature adds support for a user login and checking a users permissions for performing a group+action. The API was designed with PKCS11 in mind.
Some things of note: