Skip to content

Commit

Permalink
avs_commons 5.4.4
Browse files Browse the repository at this point in the history
Features
- Added custom base64 encoding without null terminating
- Added API to modify extended attributes in Certificate Signing Request
  • Loading branch information
JZimnol committed Apr 12, 2024
1 parent 683a8cb commit c6f8c5b
Show file tree
Hide file tree
Showing 12 changed files with 654 additions and 65 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## avs_commons 5.4.4 (April 12th, 2024)

### Features

* Added custom base64 encoding without null terminating
* Added API to modify extended attributes in Certificate Signing Request

## avs_commons 5.4.3 (February 16th, 2024)

### Improvements
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
cmake_minimum_required(VERSION 3.6.0)
project(avs_commons C)

set(AVS_COMMONS_VERSION "5.4.3")
set(AVS_COMMONS_VERSION "5.4.4")

################# DISTRIBUTION #################################################

Expand Down
43 changes: 36 additions & 7 deletions include_public/avsystem/commons/avs_base64.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ typedef struct {
* flag has no effect if @p padding_char is '\0'.
*/
bool require_padding;

/**
* Controls whether the encoded string includes a null-termination byte.
*
* When set to false (the default), a null byte is appended to the end of
* the string. When set to true, the null byte is omitted.
*/
bool without_null_termination;
} avs_base64_config_t;

/**
Expand All @@ -94,27 +102,48 @@ extern const avs_base64_config_t AVS_BASE64_DEFAULT_LOOSE_CONFIG;
extern const avs_base64_config_t AVS_BASE64_DEFAULT_STRICT_CONFIG;

/**
* Returns amount of bytes required to store input encoded in base64 if padding
* is used.
* Returns the number of bytes required to store input encoded in base64. Allows
* to set configuration of the base64 encoding. Options impacting returned size
* are padding_char and without_null_termination in @ref avs_base64_config_t
* @p config.
*
* @param input_length Length of input in bytes.
* @param config Configuration of the base64 variant to use.
*
* @returns length of base64 encoded input of length @p input_length.
*/
size_t avs_base64_encoded_size_custom(size_t input_length,
avs_base64_config_t config);

/**
* Returns the number of bytes required to store input encoded in base64 if
* padding is used.
*
* @param input_length Length of input in bytes.
*
* @returns length of base64 encoded input of length @p input_length.
*/
size_t avs_base64_encoded_size(size_t input_length);
static inline size_t avs_base64_encoded_size(size_t input_length) {
return avs_base64_encoded_size_custom(input_length,
AVS_BASE64_DEFAULT_STRICT_CONFIG);
}

/**
* Returns amount of bytes required to store input encoded in base64 if padding
* is NOT used.
* Returns the number of bytes required to store input encoded in base64 if
* padding is NOT used.
*
* @param input_length Length of input in bytes.
*
* @returns length of base64 encoded input of length @p input_length.
*/
size_t avs_base64_encoded_size_without_padding(size_t input_length);
static inline size_t
avs_base64_encoded_size_without_padding(size_t input_length) {
return avs_base64_encoded_size_custom(input_length,
AVS_BASE64_DEFAULT_LOOSE_CONFIG);
}

/**
* Returns amount of bytes that would be sufficient to store input encoded from
* Returns amount of bytes that would be sufficient to store input decoded from
* base64.
*
* Warning: this function computes just a rough estimate of amount of bytes that
Expand Down
115 changes: 115 additions & 0 deletions include_public/avsystem/commons/avs_crypto_pki.h
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,18 @@ typedef struct {
*/
extern const avs_crypto_pki_x509_name_key_t AVS_CRYPTO_PKI_X509_NAME_CN;

/**
* A predefined instance of @ref avs_crypto_pki_x509_name_key_t that identifies
* the Organization attribute type.
*/
extern const avs_crypto_pki_x509_name_key_t AVS_CRYPTO_PKI_X509_NAME_O;

/**
* A predefined instance of @ref avs_crypto_pki_x509_name_key_t that identifies
* the Country Name attribute type.
*/
extern const avs_crypto_pki_x509_name_key_t AVS_CRYPTO_PKI_X509_NAME_C;

/**
* Structure representing a single attribute within a Distinguished Name.
*/
Expand Down Expand Up @@ -896,6 +908,33 @@ typedef struct {
__VA_ARGS__, { { NULL, 0 }, NULL } }[0])
# endif // defined(__cplusplus) && __cplusplus >= 201103L

/**
* Structure representing a single extended key usage value in a certificate.
*/
typedef struct {
/**
* Value of the attribute as a null-terminated string.
*/
const char *value;
} avs_crypto_pki_x509_ext_key_usage_t;

# if defined(__cplusplus) && __cplusplus >= 201103L
# define AVS_CRYPTO_PKI_X509_EXTENDED_KEY_USAGE(...) \
(::std::vector<avs_crypto_pki_x509_ext_key_usage_t>{ __VA_ARGS__, \
{ nullptr } } \
.data())
# else // defined(__cplusplus) && __cplusplus >= 201103L
/**
*
* Generates a temporary array of @ref avs_crypto_pki_x509_ext_key_usage_t
* objects, suitable for use as the @c ext_key_usage argument to the
* @ref avs_crypto_pki_csr_create function.
*/
# define AVS_CRYPTO_PKI_X509_EXTENDED_KEY_USAGE(...) \
(&(const avs_crypto_pki_x509_ext_key_usage_t[]) { __VA_ARGS__, \
{ NULL } }[0])
# endif // defined(__cplusplus) && __cplusplus >= 201103L

/**
* Creates a Certificate Signing Request.
*
Expand Down Expand Up @@ -937,6 +976,82 @@ avs_crypto_pki_csr_create(avs_crypto_prng_ctx_t *prng_ctx,
void *out_der_csr,
size_t *inout_der_csr_size);

/**
* @experimental This is experimental API to generate CSR. This API can change
* in the future versions without any notice.
*
* Creates a Certificate Signing Request. This function allows adding key usage
* and key identifier to the generated CSR but is also able to generate the same
* CSR as the @ref avs_crypto_pki_csr_create.
*
* @param prng_ctx PRNG context to use for random number generation.
*
* @param private_key_info Private key for which the certificate shall be
* generated. A structure created using either
* @ref avs_crypto_private_key_info_from_file or
* @ref avs_crypto_private_key_info_from_buffer shall
* be passed.
*
* @param md_name Name of the digest algorithm to be used when
* signing the request, e.g. <c>"SHA256"</c>.
*
* @param subject Desired subject name of the certificate.
* This shall be a pointer to an array of
* @ref avs_crypto_pki_x509_name_entry_t objects,
* terminated by an entry with the <c>key.oid</c>
* field set to <c>NULL</c>.
*
* In typical cases, a call to the
* @ref AVS_CRYPTO_PKI_X509_NAME macro can be passed
* as this argument.
*
* @param key_usage Pointer to a value representing key usage
* extensions that defines the purpose of the public
* key contained in a certificate. If <c>NULL</c> then
* key usage extension won't be added.
*
* For OpenSSL cryptographic backend this needs to be
* set to <c>NULL</c>.
*
* @param ext_key_usage Extended key usage extension further specifies the
* purpose of the key. This shall be a pointer to an
* array of @ref avs_crypto_pki_x509_ext_key_usage_t
* objects, terminated by an entry with the
* <c>value</c> fields set to <c>NULL</c>.
*
* In typical cases, a call to the
* @ref AVS_CRYPTO_PKI_X509_EXTENDED_KEY_USAGE macro
* can be passed as this argument.
*
* For OpenSSL cryptographic backend this needs to be
* set to <c>NULL</c>.
*
* @param add_key_id Determine if key identifier extension will be added
* to generated CSR.
*
* For OpenSSL cryptographic backend this needs to be
* set to <c>false</c>.
*
* @param out_der_csr Pointer to a buffer, at the beginning of which the
* CSR encoded as PKCS#10 DER will be stored.
*
* @param inout_der_csr_size Pointer to a variable which, on input, shall
* contain the number of bytes available in the
* @p out_der_csr buffer. On successful return, it
* will be set to the number of bytes actually
* written.
*/
avs_error_t avs_crypto_pki_csr_create_ext(
avs_crypto_prng_ctx_t *prng_ctx,
const avs_crypto_private_key_info_t *private_key_info,
const char *md_name,
const avs_crypto_pki_x509_name_entry_t subject[],
const unsigned char *const key_usage,
const avs_crypto_pki_x509_ext_key_usage_t ext_key_usage[],
const bool add_key_id,
void *out_der_csr,
size_t *inout_der_csr_size);

/**
* Retrieves the expiration date (i.e., the value of the "NotAfter" field) of
* an X.509 certificate given as @ref avs_crypto_certificate_chain_info_t.
Expand Down
42 changes: 16 additions & 26 deletions src/algorithm/avs_base64.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,45 +38,33 @@ const avs_base64_config_t AVS_BASE64_DEFAULT_LOOSE_CONFIG = {
.alphabet = AVS_BASE64_CHARS,
.padding_char = '=',
.allow_whitespace = true,
.require_padding = false
.require_padding = false,
.without_null_termination = false
};

const avs_base64_config_t AVS_BASE64_DEFAULT_STRICT_CONFIG = {
.alphabet = AVS_BASE64_CHARS,
.padding_char = '=',
.allow_whitespace = false,
.require_padding = true
.require_padding = true,
.without_null_termination = false
};

AVS_STATIC_ASSERT(sizeof(AVS_BASE64_CHARS) == 65, // 64 chars + NULL terminator
missing_base64_chars);

static int check_base64_out_buffer_size(size_t buffer_size,
size_t data_length,
bool use_padding) {
size_t encoded_size;
if (use_padding) {
encoded_size = avs_base64_encoded_size(data_length);
} else {
encoded_size = avs_base64_encoded_size_without_padding(data_length);
}
return buffer_size >= encoded_size ? 0 : -1;
}

size_t avs_base64_encoded_size(size_t input_length) {
size_t avs_base64_encoded_size_custom(size_t input_length,
avs_base64_config_t config) {
size_t needed_size = (input_length / 3) * 4;
needed_size += (input_length % 3) ? 4 : 0;
needed_size += 1; /* NULL terminator */
return needed_size;
}

size_t avs_base64_encoded_size_without_padding(size_t input_length) {
size_t needed_size = (input_length / 3) * 4;
size_t rest = input_length % 3;
if (rest) {
needed_size += rest + 1;
needed_size += !!config.padding_char ? 4 : rest + 1;
}

if (!config.without_null_termination) {
needed_size += 1; /* NULL terminator */
}
needed_size += 1; /* NULL terminator */
return needed_size;
}

Expand All @@ -94,8 +82,7 @@ int avs_base64_encode_custom(char *out,
size_t i;
unsigned long sh = 0;

if (check_base64_out_buffer_size(out_length, input_length,
!!config.padding_char)) {
if (avs_base64_encoded_size_custom(input_length, config) > out_length) {
return -1;
}

Expand Down Expand Up @@ -125,7 +112,10 @@ int avs_base64_encode_custom(char *out,
}
}

*out = '\0';
if (!config.without_null_termination) {
*out = '\0';
}

return 0;
}

Expand Down
3 changes: 2 additions & 1 deletion src/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ if(WITH_MBEDTLS)
if(AVS_COMMONS_WITH_AVS_CRYPTO_ADVANCED_FEATURES)
set(AVS_CRYPTO_MBEDTLS_TEST_SOURCES
${AVS_CRYPTO_MBEDTLS_TEST_SOURCES}
${AVS_CRYPTO_ADVANCED_FEATURES_TEST_SOURCES})
${AVS_CRYPTO_ADVANCED_FEATURES_TEST_SOURCES}
$<$<BOOL:${WITH_PKI}>:${AVS_COMMONS_SOURCE_DIR}/tests/crypto/mbedtls/mbedtls_pki.c>)
endif()

add_library(avs_crypto_mbedtls
Expand Down
10 changes: 10 additions & 0 deletions src/crypto/avs_crypto_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,16 @@ const avs_crypto_pki_x509_name_key_t AVS_CRYPTO_PKI_X509_NAME_CN = {
.value_id_octet = 0x0C // UTF8String
};

const avs_crypto_pki_x509_name_key_t AVS_CRYPTO_PKI_X509_NAME_O = {
.oid = (const avs_crypto_asn1_oid_t *) "\x06\x03\x55\x04\x0a",
.value_id_octet = 0x0C // UTF8String
};

const avs_crypto_pki_x509_name_key_t AVS_CRYPTO_PKI_X509_NAME_C = {
.oid = (const avs_crypto_asn1_oid_t *) "\x06\x03\x55\x04\x06",
.value_id_octet = 0x0C // UTF8String
};

bool _avs_crypto_aead_parameters_valid(size_t key_len,
size_t iv_len,
size_t tag_len) {
Expand Down
Loading

0 comments on commit c6f8c5b

Please sign in to comment.