-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lib: app_jwt: add an app core jwt generator and add a sample for usage
Ref: NRFX-6688 Signed-off-by: Aymen LAOUINI <aymen.laouini@nordicsemi.no>
- Loading branch information
1 parent
11f3037
commit 9d95b0b
Showing
18 changed files
with
1,368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
.. _app_jwt: | ||
|
||
Application JWT | ||
################### | ||
|
||
The Application JWT library provides access to the `JSON Web Token (JWT)`_ generation feature from application core using signing and identity services from secure core. | ||
|
||
Configuration | ||
************* | ||
|
||
To use the library to request a JWT, complete the following steps: | ||
|
||
1. Set the following Kconfig options to enable the library: | ||
|
||
* :kconfig:option:`CONFIG_APP_JWT` | ||
* :kconfig:option:`CONFIG_APP_JWT_VERIFY_SIGNATURE` | ||
* :kconfig:option:`CONFIG_APP_JWT_PRINT_EXPORTED_PUBKEY_DER` | ||
* :kconfig:option:`CONFIG_NRF_SECURITY` | ||
* :Kconfig:option:`CONFIG_SSF_PSA_CRYPTO_SERVICE_ENABLED` | ||
* :Kconfig:option:`CONFIG_SSF_DEVICE_INFO_SERVICE_ENABLED` | ||
|
||
#. Read the device UUID (:c:func:`app_jwt_get_uuid`) | ||
#. Populate the :c:struct:`app_jwt_data` structure with your desired values. | ||
See `Possible structure values`_ for more information. | ||
#. Pass the structure to the function that generates JWT (:c:func:`app_jwt_generate`). | ||
|
||
If the function executes successfully, :c:member:`app_jwt_data.jwt_buf` will contain the JSON Web Token. | ||
|
||
.. note:: | ||
The library doesn't check the validity of the time source, it is up to the caller to make sure that the system has access to a valid one, otherwise "iat" field will containt the time since boot in seconds. | ||
|
||
.. note:: | ||
If the time value in seconds is equal to ``0``, the claim ``iat`` will be left out of the JWT. | ||
|
||
Possible structure values | ||
========================= | ||
|
||
You can configure the following values in the :c:struct:`app_jwt_data` structure: | ||
|
||
* :c:member:`app_jwt_data.sec_tag` - Optional, the ``sec_tag`` must contain a valid signing key. | ||
If set to 0, the library will use the IAK for signing. | ||
* :c:member:`app_jwt_data.key_type` - Required if ``sec_tag`` is not zero. | ||
Defines the type of key in the sec tag. | ||
* :c:member:`app_jwt_data.alg` - Required, always use the value JWT_ALG_TYPE_ES256. | ||
Defines the JWT signing algorithm. Currently, only ECDSA 256 is supported. | ||
* :c:member:`app_jwt_data.add_keyid_to_header` - Optional. | ||
Corresponds to ``keyid`` claim. | ||
Use ``0`` if you want to leave out this field. | ||
* :c:member:`app_jwt_data.json_token_id` - Optional. | ||
Corresponds to ``jti`` claim. | ||
Use ``0`` if you want to leave out this field. | ||
* :c:member:`app_jwt_data.subject` - Optional. | ||
Corresponds to ``sub`` claim. | ||
Use ``0`` if you want to leave out this field. | ||
* :c:member:`app_jwt_data.audience` - Optional. | ||
Corresponds to ``aud`` claim. | ||
Use ``0`` if you want to leave out this field. | ||
* :c:member:`app_jwt_data.issuer` - Optional. | ||
Corresponds to ``iss`` claim. | ||
Use ``0`` if you want to leave out this field. | ||
* :c:member:`app_jwt_data.add_timestamp` - Optional. | ||
Corresponds to ``iat`` claim. | ||
Use ``0`` if you want to leave out this field. | ||
* :c:member:`app_jwt_data.validity_s` - Optional. | ||
Defines the expiration date for the JWT. | ||
If set to 0, the field ``exp`` will be omitted from the generated JWT. | ||
* :c:member:`app_jwt_data.jwt_buf` - Required. | ||
Buffer for the generated, null-terminated, JWT string. | ||
Buffer size has to be al least 600 bytes, at most 900 bytes. | ||
The user has to provide a valid buffer, library doesn't do any allocation. | ||
* :c:member:`app_jwt_data.jwt_sz` - Size of JWT buffer. | ||
Required, has to be equal to the size of :c:member:`app_jwt_data.jwt_buf`. | ||
|
||
API documentation | ||
***************** | ||
|
||
| Header file: :file:`include/app_jwt.h` | ||
| Source file: :file:`lib/app_jwt/app_jwt.c` | ||
.. doxygengroup:: app_jwt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.. _lib_app_jwt: | ||
|
||
Library Application JWT | ||
######################## | ||
|
||
.. toctree:: | ||
:maxdepth: 1 | ||
:glob: | ||
:caption: Subpages: | ||
|
||
* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/* | ||
* Copyright (c) 2024 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
*/ | ||
|
||
#ifndef _APP_JWT_H | ||
#define _APP_JWT_H | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @file app_jwt.h | ||
* | ||
* @brief Generate a JWT with from application core. | ||
* @defgroup app_jwt JWT generation | ||
* @{ | ||
* | ||
*/ | ||
|
||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include <strings.h> | ||
|
||
/** @brief Maximum size of a JWT string, could be used to allocate JWT | ||
* output buffer. | ||
*/ | ||
#define APP_JWT_STR_MAX_LEN 900 | ||
|
||
/** @brief Maximum valid duration for JWTs generated by user application */ | ||
#define APP_JWT_VALID_TIME_S_MAX (7 * 24 * 60 * 60) | ||
|
||
/** @brief Default valid duration for JWTs generated by user application */ | ||
#define APP_JWT_VALID_TIME_S_DEF (10 * 60) | ||
|
||
/** @brief UUID size in bytes */ | ||
#define APP_JWT_UUID_BYTE_SZ 16 | ||
|
||
/** @brief UUID v4 format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + '\0' */ | ||
#define APP_JWT_UUID_V4_STR_LEN (((APP_JWT_UUID_BYTE_SZ * 2) + 4) + 1) | ||
|
||
/** @brief Size in bytes of each JWT String field */ | ||
#define APP_JWT_CLAIM_MAX_SIZE 64 | ||
|
||
/** @brief The type of key to be used for signing the JWT. */ | ||
enum app_jwt_key_type { | ||
JWT_KEY_TYPE_CLIENT_PRIV = 2, | ||
JWT_KEY_TYPE_ENDORSEMENT = 8, | ||
}; | ||
|
||
/** @brief JWT signing algorithm */ | ||
enum app_jwt_alg_type { | ||
JWT_ALG_TYPE_ES256 = 0, | ||
}; | ||
|
||
/** @brief JWT parameters required for JWT generation and pointer to generated JWT */ | ||
struct app_jwt_data { | ||
/** Sec tag to use for JWT signing */ | ||
unsigned int sec_tag; | ||
/** Key type in the specified sec tag */ | ||
enum app_jwt_key_type key_type; | ||
/** JWT signing algorithm */ | ||
enum app_jwt_alg_type alg; | ||
|
||
/** | ||
* Indicates if a 'kid' claim is requiered or not, if set to 1, 'kid' claim | ||
* will contain sha256 of the signing key. | ||
*/ | ||
bool add_keyid_to_header; | ||
|
||
/** | ||
* NULL terminated 'jti' claim; Unique identifier; can be used to prevent the | ||
* JWT from being replayed | ||
*/ | ||
const char *json_token_id; | ||
/** NULL terminated 'sub' claim; the principal that is the subject of the JWT */ | ||
const char *subject; | ||
/** NULL terminated 'aud' claim; intended recipient of the JWT */ | ||
const char *audience; | ||
/** NULL terminated 'iss' claim; Issuer of the JWT */ | ||
const char *issuer; | ||
|
||
/** | ||
* Indicates if an issue timestamp is requiered or not, if set to 1, 'exp' claim | ||
* will be present. | ||
*/ | ||
bool add_timestamp; | ||
|
||
/** | ||
* Corresponds to 'exp' claim; Defines how long the JWT will be valid. | ||
* If application has a valid time source, and the 'iat' claim is present, | ||
* the timestamp in seconds will be added to this value. | ||
*/ | ||
uint32_t validity_s; | ||
|
||
/** | ||
* Buffer to which the NULL terminated JWT will be copied. | ||
* It is the responsibility of the user to provide a valid buffer. | ||
* The returned JWT could be as long as 900 bytes, use the | ||
* defined size value APP_JWT_STR_MAX_LEN to create your supplied return buffer. | ||
*/ | ||
char *jwt_buf; | ||
/** Size of the user provided buffer. */ | ||
size_t jwt_sz; | ||
}; | ||
|
||
/** | ||
* @brief Generates a JWT using the supplied parameters. If successful, | ||
* the JWT string will be stored in the supplied struct. | ||
* The user is responsible for providing a valid pointer to store the JWT. | ||
* | ||
* Subject and audience fields may be NULL in which case those fields are left out | ||
* from generated JWT token. | ||
* | ||
* The API doesn't verify the time source validity, it is up to the caller to make sure | ||
* that the system has access to a valid time source, otherwise "iat" field will | ||
* contain the time since boot in seconds. | ||
* | ||
* JWT is signed with the application identity attestation key, no matter what | ||
* value is supplied in the sec_tag. | ||
* | ||
* @param[in,out] jwt Pointer to struct containing JWT parameters and result. | ||
* | ||
* @retval 0 If the operation was successful. | ||
* Otherwise, a (negative) error code is returned, check header errno.h for a full list. | ||
*/ | ||
int app_jwt_generate(struct app_jwt_data *const jwt); | ||
|
||
/** | ||
* @brief Gets the device UUID from the secure domain | ||
* and returns it as a NULL terminated string in the supplied buffer. | ||
* The device UUID can be used as a device identifier for cloud services and | ||
* for secure device management using the nRF Cloud Identity Service. | ||
* | ||
* UUID v4 defined by ITU-T X.667 | ISO/IEC 9834-8 has a length of 35 bytes, add | ||
* 1 byte for the atring termination character. User is expected to provide a buffer | ||
* of at least 36 bytes. | ||
* | ||
* @param[out] uuid_buffer Pointer to buffer where the device UUID string will be written to. | ||
* @param[in] uuid_buffer_size Size of the provided buffer. | ||
* | ||
* @retval 0 If the operation was successful. | ||
* Otherwise, a (negative) error code is returned, check header errno.h for a full list. | ||
*/ | ||
int app_jwt_get_uuid(char *uuid_buffer, const size_t uuid_buffer_size); | ||
|
||
/** @} */ | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* _APP_JWT_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# | ||
# Copyright (c) 2024 Nordic Semiconductor ASA | ||
# | ||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
# | ||
|
||
zephyr_library() | ||
|
||
zephyr_library_sources( | ||
app_jwt.c | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# | ||
# Copyright (c) 2024 Nordic Semiconductor ASA | ||
# | ||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
# | ||
|
||
menuconfig APP_JWT | ||
bool "Application JWT Library" | ||
depends on SSF_CLIENT && SSF_PSA_CRYPTO_SERVICE_ENABLED && SSF_DEVICE_INFO_SERVICE_ENABLED | ||
select BASE64 | ||
# Needed for time and date | ||
select POSIX_API | ||
# Needed to print integer values in JSON | ||
select CJSON_LIB | ||
select CBPRINTF_FP_SUPPORT | ||
|
||
if APP_JWT | ||
|
||
config APP_JWT_VERIFY_SIGNATURE | ||
bool "Verify signature after signing" | ||
default y | ||
|
||
config APP_JWT_PRINT_EXPORTED_PUBKEY_DER | ||
bool "Print to terminal the DER formatted public key" | ||
|
||
module=APP_JWT | ||
module-str=User App JWT | ||
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" | ||
|
||
endif # APP_JWT |
Oops, something went wrong.