Skip to content

Commit 93e2219

Browse files
add authentication documentation
1 parent 4fd04bf commit 93e2219

1 file changed

Lines changed: 219 additions & 0 deletions

File tree

docs/src/chapter09.md

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# Authentication Manager
2+
3+
The wolfHSM Authentication Manager is a transport-agnostic component that provides authentication (PIN and certificate verification), session management, and authorization for wolfHSM operations. It is configured via a callback structure (`whAuthCb`) and can use the default in-memory implementation in `wh_auth_base.c`, or a custom backend that implements the same interface.
4+
5+
## Table of Contents
6+
7+
- [Enabling and Configuring the Authentication Manager](#enabling-and-configuring-the-authentication-manager)
8+
- [WH_AUTH_* Macro Helpers](#wh_auth_-macro-helpers)
9+
- [Default User Database (wh_auth_base.c)](#default-user-database-wh_auth_basec)
10+
- [Admin vs Non-Admin Users and Restrictions](#admin-vs-non-admin-users-and-restrictions)
11+
- [Auth Message Group and Actions](#auth-message-group-and-actions)
12+
- [Authorization Callbacks (Override)](#authorization-callbacks-override)
13+
- [Error Codes](#error-codes)
14+
- [Thread Safety and Locking](#thread-safety-and-locking)
15+
16+
## Enabling and Configuring the Authentication Manager
17+
18+
### Build-time
19+
20+
The Authentication Manager feature is off by default. To enable it, define `WOLFHSM_CFG_ENABLE_AUTHENTICATION` when building wolfHSM (e.g., in `wh_config.h` or via compiler flags). Without this macro, auth-related code is excluded from the build and auth requests return `WH_AUTH_NOT_ENABLED`.
21+
22+
### Building examples with auth
23+
24+
The POSIX server, POSIX client, and test Makefiles support an authentication-capable build via `AUTH=1`. Pass `AUTH=1` to `make` when building these targets:
25+
26+
```bash
27+
# From the examples/posix/wh_posix_server or wh_posix_client directory
28+
make AUTH=1
29+
30+
# From the test directory
31+
make AUTH=1
32+
33+
# From the top-level directory (exports AUTH to subdirectories)
34+
make AUTH=1 examples
35+
```
36+
37+
The auth demo client (`wh_demo_client_auth.c`) and related examples require this build to function.
38+
39+
### Runtime configuration
40+
41+
Even when auth is compiled in, the server must have an auth context configured. The auth context is set via `whServerConfig.auth` and stored in `server->auth`. If `server->auth == NULL`, no authentication is attempted:
42+
43+
- Auth group requests (LOGIN, USER_ADD, USER_DELETE, etc.) return `WH_AUTH_NOT_ENABLED`
44+
- Authorization checks for other message groups (NVM, key, crypto, etc.) are skipped entirely
45+
46+
The server will process requests without requiring login. To enable authentication, the application must initialize an auth context and pass it in the server configuration.
47+
48+
## WH_AUTH_* Macro Helpers
49+
50+
The following macros in `wolfhsm/wh_auth.h` simplify setting and checking permissions in a `whAuthPermissions` structure:
51+
52+
| Macro | Purpose |
53+
|-------|---------|
54+
| `WH_AUTH_IS_ADMIN(permissions)` | Returns non-zero if admin flag is set |
55+
| `WH_AUTH_SET_IS_ADMIN(permissions, value)` | Sets admin flag (0 = non-admin, non-zero = admin) |
56+
| `WH_AUTH_ACTION_TO_WORD_AND_BITMASK(action, wordIdx, bitMask)` | Internal: maps action (0-255) to word index and bitmask |
57+
| `WH_AUTH_SET_ALLOWED_GROUP(permissions, group)` | Enables a message group and allows all actions in that group |
58+
| `WH_AUTH_SET_ALLOWED_ACTION(permissions, group, action)` | Enables group and only the specified action bit |
59+
| `WH_AUTH_CLEAR_ALLOWED_GROUP(permissions, group)` | Disables group and clears all action bits |
60+
| `WH_AUTH_CLEAR_ALLOWED_ACTION(permissions, group, action)` | Clears permission for a specific action |
61+
62+
Related constants:
63+
64+
- `WH_AUTH_MAX_KEY_IDS` (2): Maximum number of key IDs a user can have access to
65+
- `WH_AUTH_ACTIONS_PER_GROUP` (256): Support for up to 256 actions per group
66+
- `WH_AUTH_ACTION_WORDS`: Number of `uint32_t` words used for the action bit array per group
67+
68+
Example: creating a non-admin user with permission to add users but not perform other auth operations:
69+
70+
```c
71+
#include "wolfhsm/wh_auth.h"
72+
#include "wolfhsm/wh_message.h"
73+
74+
whAuthPermissions perms;
75+
76+
memset(&perms, 0, sizeof(perms));
77+
WH_AUTH_SET_ALLOWED_ACTION(perms, WH_MESSAGE_GROUP_AUTH,
78+
WH_MESSAGE_AUTH_ACTION_USER_ADD);
79+
WH_AUTH_SET_IS_ADMIN(perms, 0);
80+
perms.keyIdCount = 0;
81+
82+
/* Use perms when adding the user via wh_Auth_UserAdd or in UserAdd request */
83+
```
84+
85+
## Default User Database (wh_auth_base.c)
86+
87+
The in-memory implementation in `src/wh_auth_base.c` provides a simple user database suitable for development and testing. It can be used as the auth backend by registering the `wh_Auth_Base*` callbacks in `whAuthCb`.
88+
89+
### Storage
90+
91+
- Static array of `whAuthBase_User` structures (max 5 users by default via `WH_AUTH_BASE_MAX_USERS`)
92+
- Each entry holds `whAuthUser`, authentication method, and credentials (max 2048 bytes via `WH_AUTH_BASE_MAX_CREDENTIALS_LEN`)
93+
94+
### Init and Cleanup
95+
96+
- `wh_Auth_BaseInit` zeros the user array
97+
- `wh_Auth_BaseCleanup` force-zeros sensitive data in memory
98+
99+
### Login
100+
101+
- `wh_Auth_BaseLogin` supports:
102+
- `WH_AUTH_METHOD_PIN`: Credentials are SHA256-hashed when crypto is enabled; stored as plain copy when `WOLFHSM_CFG_NO_CRYPTO` is defined
103+
- `WH_AUTH_METHOD_CERTIFICATE`: When `WOLFHSM_CFG_CERTIFICATE_MANAGER` is defined
104+
105+
### Operations
106+
107+
- `wh_Auth_BaseUserAdd`, `wh_Auth_BaseUserDelete`, `wh_Auth_BaseUserSetPermissions`, `wh_Auth_BaseUserGet`, `wh_Auth_BaseUserSetCredentials`
108+
109+
### Lookup
110+
111+
- `wh_Auth_BaseFindUser` looks up users by username
112+
- User IDs are 1-based (0 reserved for `WH_USER_ID_INVALID`)
113+
114+
### Usernames
115+
116+
The default user database does not support multiple users with the same username. Duplicate usernames are rejected in `wh_Auth_BaseUserAdd` with `WH_ERROR_BADARGS`.
117+
118+
### Example: seeding a default admin user
119+
120+
The POSIX server example in `examples/posix/wh_posix_server/wh_posix_server_cfg.c` seeds a default admin user at configuration time:
121+
122+
```c
123+
/* Add an admin user with permissions for everything */
124+
memset(&permissions, 0xFF, sizeof(whAuthPermissions));
125+
permissions.keyIdCount = 0;
126+
for (i = 0; i < WH_AUTH_MAX_KEY_IDS; i++) {
127+
permissions.keyIds[i] = 0;
128+
}
129+
rc = wh_Auth_BaseUserAdd(&auth_ctx, "admin", &out_user_id, permissions,
130+
WH_AUTH_METHOD_PIN, "1234", 4);
131+
```
132+
133+
## Admin vs Non-Admin Users and Restrictions
134+
135+
### Admin users
136+
137+
- Identified by `WH_AUTH_IS_ADMIN(permissions)` returning non-zero (stored in `groupPermissions[WH_NUMBER_OF_GROUPS]`)
138+
- Can add users (including other admins), delete users, set permissions, and set credentials for any user
139+
- Can log out other users (in addition to themselves)
140+
141+
### Non-admin users
142+
143+
- Identified by `WH_AUTH_SET_IS_ADMIN(permissions, 0)` or admin flag cleared
144+
- **Key restriction**: Cannot add a user with admin permissions. If a non-admin attempts to add a user whose permissions include the admin flag, the operation fails with `WH_AUTH_PERMISSION_ERROR` (-2301). This is enforced in `wh_Auth_UserAdd` in `src/wh_auth.c` before the backend callback is invoked.
145+
- Cannot delete users (enforced in `wh_Auth_BaseUserDelete`: only admin may delete)
146+
- Cannot set permissions for other users (enforced in `wh_Auth_BaseUserSetPermissions`: only admin may change permissions)
147+
- Can log out only themselves (enforced in `wh_Auth_BaseLogout`: non-admin cannot log out another user)
148+
- Can add non-admin users if they have `WH_MESSAGE_AUTH_ACTION_USER_ADD` in the auth group
149+
150+
Example: a non-admin user with user-add permission can add other non-admin users but will fail when attempting to add an admin:
151+
152+
```c
153+
/* Create non-admin with only USER_ADD permission */
154+
whAuthPermissions nonadmin_perms;
155+
memset(&nonadmin_perms, 0, sizeof(nonadmin_perms));
156+
WH_AUTH_SET_ALLOWED_ACTION(nonadmin_perms, WH_MESSAGE_GROUP_AUTH,
157+
WH_MESSAGE_AUTH_ACTION_USER_ADD);
158+
WH_AUTH_SET_IS_ADMIN(nonadmin_perms, 0);
159+
160+
/* After logging in as this user: adding a non-admin succeeds,
161+
* but adding a user with admin permissions (e.g. memset(&perms, 0xFF, ...))
162+
* returns WH_AUTH_PERMISSION_ERROR. */
163+
```
164+
165+
## Auth Message Group and Actions
166+
167+
The auth message group is `WH_MESSAGE_GROUP_AUTH` (0x0D00). Available actions in `wolfhsm/wh_message.h`:
168+
169+
- `WH_MESSAGE_AUTH_ACTION_LOGIN`
170+
- `WH_MESSAGE_AUTH_ACTION_LOGOUT`
171+
- `WH_MESSAGE_AUTH_ACTION_USER_ADD`
172+
- `WH_MESSAGE_AUTH_ACTION_USER_DELETE`
173+
- `WH_MESSAGE_AUTH_ACTION_USER_GET`
174+
- `WH_MESSAGE_AUTH_ACTION_USER_SET_PERMISSIONS`
175+
- `WH_MESSAGE_AUTH_ACTION_USER_SET_CREDENTIALS`
176+
177+
Unauthenticated users can only perform LOGIN and communications (comm) operations. Logout is always allowed for logged-in users. All other auth actions require the corresponding permission bits to be set in the user's permissions for the auth group.
178+
179+
## Authorization Callbacks (Override)
180+
181+
The `whAuthCb` structure defines optional callbacks that allow the auth backend to override default authorization results:
182+
183+
### CheckRequestAuthorization
184+
185+
Allows the auth backend to override the default authorization result for a given group and action. After the Auth Manager computes the default result (allowed or denied based on the user's permissions), if this callback is set, it is invoked with the preliminary result. The callback may change the result (e.g., grant access that would otherwise be denied, or deny access that would otherwise be allowed).
186+
187+
The callback is invoked from `wh_Auth_CheckRequestAuthorization` in `src/wh_auth.c`. Parameters: context, preliminary err, user_id, group, action. Returns the final authorization result.
188+
189+
### CheckKeyAuthorization
190+
191+
Placeholder for checking whether a user is authorized to use a specific key ID. This callback is defined in the interface but wolfHSM currently does not invoke it before key use; it is a TODO for future integration. When implemented, it would allow the backend to override key-access decisions (e.g., based on the user's `keyIds` array in permissions).
192+
193+
## Error Codes
194+
195+
Auth-related error codes in `wolfhsm/wh_error.h`:
196+
197+
| Code | Value | Description |
198+
|------|-------|-------------|
199+
| `WH_AUTH_LOGIN_FAILED` | -2300 | User login attempt failed |
200+
| `WH_AUTH_PERMISSION_ERROR` | -2301 | User attempted an action not allowed |
201+
| `WH_AUTH_NOT_ENABLED` | -2302 | Server does not have auth feature |
202+
203+
## Thread Safety and Locking
204+
205+
### Conditional compilation
206+
207+
When `WOLFHSM_CFG_THREADSAFE` is defined, the Auth Manager uses a lock (`whLock`) stored in `whAuthContext` to serialize auth operations. When undefined, locking is disabled and `WH_AUTH_LOCK`/`WH_AUTH_UNLOCK` expand to no-ops (return `WH_ERROR_OK`).
208+
209+
### Lock acquisition
210+
211+
All public Auth Manager API functions in `src/wh_auth.c` acquire the lock via `WH_AUTH_LOCK` at entry and release via `WH_AUTH_UNLOCK` before return. Callbacks (Login, Logout, UserAdd, etc.) are invoked while holding the lock.
212+
213+
### Base implementation
214+
215+
The default user database in `wh_auth_base.c` uses a static global users array. When `WOLFHSM_CFG_THREADSAFE` is defined, this array is protected by the auth context lock; locking is performed by the `wh_Auth_*` wrapper functions, not by the base implementation itself.
216+
217+
### Configuration
218+
219+
`whAuthConfig` includes an optional `lockConfig` (of type `whLockConfig`) when `WOLFHSM_CFG_THREADSAFE` is defined; this is passed to `wh_Lock_Init` during `wh_Auth_Init`. Custom backends that maintain shared state must either rely on this lock or implement their own synchronization.

0 commit comments

Comments
 (0)