Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/bsl-cose-sc.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
Name: bsl-cose-sc
Description: BSL COSE Context provider
Version: @PROJECT_VERSION@
Requires: bsl, m-lib
Requires: bsl
Requires.private: m-lib
Cflags: -I${includedir}
Libs: -L${libdir} -lbsl_cose_sc
4 changes: 3 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ target_sources(bsl_cose_sc
FILE_SET private_headers
TYPE HEADERS
FILES
bsl/cose_sc/AadScope.h
bsl/cose_sc/CoseMsg.h
PRIVATE
bsl/cose_sc/AadScope.c
bsl/cose_sc/CoseContext.c
bsl/cose_sc/CoseMsg.c
)
Expand All @@ -137,7 +139,7 @@ set_target_properties(bsl_cose_sc
target_link_libraries(bsl_cose_sc PUBLIC bsl_front)
target_link_libraries(bsl_cose_sc PUBLIC bsl_dynamic) # for CBOR API
target_link_libraries(bsl_cose_sc PRIVATE bsl_crypto)
target_link_libraries(bsl_cose_sc PUBLIC MLIB::mlib)
target_link_libraries(bsl_cose_sc PRIVATE MLIB::mlib)
target_link_libraries(bsl_cose_sc PRIVATE qcbor::qcbor)

# Example Policy Provider library
Expand Down
51 changes: 51 additions & 0 deletions src/bsl/cose_sc/AadScope.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "AadScope.h"

int BSLX_CoseSc_AadScope_Encode(QCBOREncodeContext *enc, const BSLX_CoseSc_AadScope_t *scope)
{
// aad-scope map
QCBOREncode_OpenMap(enc);

BSLX_CoseSc_AadScope_it_t aads_it;
for (BSLX_CoseSc_AadScope_it(aads_it, *scope); !BSLX_CoseSc_AadScope_end_p(aads_it);

Check warning on line 9 in src/bsl/cose_sc/AadScope.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this loop so that it is less error-prone.

See more on https://sonarcloud.io/project/issues?id=NASA-AMMOS_BSL&issues=AZ-Fn19wIy4OCtvCQTOy&open=AZ-Fn19wIy4OCtvCQTOy&pullRequest=258
BSLX_CoseSc_AadScope_next(aads_it))
{
const BSLX_CoseSc_AadScope_subtype_ct *aads_pair = BSLX_CoseSc_AadScope_cref(aads_it);
QCBOREncode_AddInt64(enc, *(aads_pair->key_ptr));
QCBOREncode_AddUInt64(enc, *(aads_pair->value_ptr));
}

QCBOREncode_CloseMap(enc);
return BSL_SUCCESS;
}

int BSLX_CoseSc_AadScope_Decode(QCBORDecodeContext *dec, BSLX_CoseSc_AadScope_t *scope)
{
BSLX_CoseSc_AadScope_reset(*scope);

QCBORItem item;
QCBORDecode_EnterArray(dec, &item); // using QCBOR_DECODE_MODE_MAP_AS_ARRAY

while (QCBOR_SUCCESS == QCBORDecode_PeekNext(dec, &item))

Check warning on line 28 in src/bsl/cose_sc/AadScope.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce the number of nested "break" statements from 2 to 1 authorized.

See more on https://sonarcloud.io/project/issues?id=NASA-AMMOS_BSL&issues=AZ-Fn19wIy4OCtvCQTOz&open=AZ-Fn19wIy4OCtvCQTOz&pullRequest=258
{
int64_t blk_num;
QCBORDecode_GetInt64(dec, &blk_num);
if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
{
BSL_LOG_ERR("Invalid AAD Scope map key");
break;
}

uint64_t aad_flags;
QCBORDecode_GetUInt64(dec, &aad_flags);
if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
{
BSL_LOG_ERR("Invalid AAD Scope map value");
break;
}

BSLX_CoseSc_AadScope_set_at(*scope, blk_num, aad_flags);
}

QCBORDecode_ExitArray(dec);
return BSL_SUCCESS;
}
65 changes: 65 additions & 0 deletions src/bsl/cose_sc/AadScope.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
* Laboratory LLC.
*
* This file is part of the Bundle Protocol Security Library (BSL).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This work was performed for the Jet Propulsion Laboratory, California
* Institute of Technology, sponsored by the United States Government under
* the prime contract 80NM0018D0004 between the Caltech and NASA under
* subcontract 1700763.
*/

/** @file
* @ingroup cose_sc
* Header for the implementation of the COSE context @cite draft-ietf-dtn-bpsec-cose.
*/

#ifndef BSLX_COSESC_AADSCOPE_H_
#define BSLX_COSESC_AADSCOPE_H_

#include "CoseContext.h"

#include "bsl/dynamic/CBOR.h"

#include <m-bptree.h>

#ifdef __cplusplus
extern "C" {
#endif

/** @struct BSLX_CoseSc_AadScope_t
* An internal representation of AAD Scope map, with keys sorted in
* CBOR deterministic order and values as a bit mask of
* ::BSLX_CoseSc_AadScope_Flag_e flags.
*/
// NOLINTBEGIN
/// @cond Doxygen_Suppress
// GCOV_EXCL_START
M_BPTREE_DEF2(BSLX_CoseSc_AadScope, 4, int64_t, M_OPEXTEND(M_BASIC_OPLIST, CMP(API_6(BSL_CBOR_Compare_Int64))),
uint64_t, M_BASIC_OPLIST)
// GCOV_EXCL_STOP
/// @endcond
// NOLINTEND

/// Matches ::BSL_CBOR_Encode_f signature.
int BSLX_CoseSc_AadScope_Encode(QCBOREncodeContext *enc, const BSLX_CoseSc_AadScope_t *scope);

/// Matches ::BSL_CBOR_Decode_f signature.
int BSLX_CoseSc_AadScope_Decode(QCBORDecodeContext *dec, BSLX_CoseSc_AadScope_t *scope);

#ifdef __cplusplus
} // extern C
#endif

#endif /* BSLX_COSESC_AADSCOPE_H_ */
89 changes: 35 additions & 54 deletions src/bsl/cose_sc/CoseContext.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
#include "CoseContext.h"

#include "CoseContext_Private.h"
#include "AadScope.h"
#include "CoseMsg.h"

#include "bsl/BPSecLib_Private.h"
Expand All @@ -42,6 +42,37 @@
#include <stdlib.h>
#include <time.h>

int BSLX_CoseSc_SetAadScope(BSL_IdValPair_t *option, const BSLX_CoseSc_AadScope_Item_t *list, size_t count)
{
ASSERT_ARG_NONNULL(option);
ASSERT_ARG_NONNULL(list);

BSLX_CoseSc_AadScope_t obj;
BSLX_CoseSc_AadScope_init(obj);

for (size_t item_ix = 0; item_ix < count; ++item_ix)
{
const BSLX_CoseSc_AadScope_Item_t *item = &list[item_ix];
BSLX_CoseSc_AadScope_set_at(obj, item->key, item->flags);
}

BSL_Data_t aad_scope_enc;
BSL_Data_Init(&aad_scope_enc);
int res = BSL_CBOR_Encode_Twopass(&aad_scope_enc, (BSL_CBOR_Encode_f)&BSLX_CoseSc_AadScope_Encode, &obj);
// GCOV_EXCL_START
if (BSL_SUCCESS != res)
{
BSL_LOG_ERR("Failed to encode AAD Scope");
}
// GCOV_EXCL_STOP

BSL_IdValPair_SetRaw(option, BSLX_COSESC_OPTION_AAD_SCOPE, aad_scope_enc.ptr, aad_scope_enc.len);
BSL_Data_Deinit(&aad_scope_enc);

BSLX_CoseSc_AadScope_clear(obj);
return res;
}

/** Acceptable target algorithms for MAC.
* @note These must be sorted for @c bsearch() to work.
*/
Expand Down Expand Up @@ -462,56 +493,6 @@ bool BSLX_CoseSc_Validate(BSL_LibCtx_t *lib _U_, BSL_BundleRef_t *bundle, BSL_Se
return valid;
}

int BSLX_CoseSc_AadScope_Encode(QCBOREncodeContext *enc, const BSLX_CoseSc_AadScope_t *scope)
{
// aad-scope map
QCBOREncode_OpenMap(enc);

BSLX_CoseSc_AadScope_it_t aads_it;
for (BSLX_CoseSc_AadScope_it(aads_it, *scope); !BSLX_CoseSc_AadScope_end_p(aads_it);
BSLX_CoseSc_AadScope_next(aads_it))
{
const BSLX_CoseSc_AadScope_subtype_ct *aads_pair = BSLX_CoseSc_AadScope_cref(aads_it);
QCBOREncode_AddInt64(enc, *(aads_pair->key_ptr));
QCBOREncode_AddUInt64(enc, *(aads_pair->value_ptr));
}

QCBOREncode_CloseMap(enc);
return BSL_SUCCESS;
}

int BSLX_CoseSc_AadScope_Decode(QCBORDecodeContext *dec, BSLX_CoseSc_AadScope_t *scope)
{
BSLX_CoseSc_AadScope_reset(*scope);

QCBORItem item;
QCBORDecode_EnterArray(dec, &item); // using QCBOR_DECODE_MODE_MAP_AS_ARRAY

while (QCBOR_SUCCESS == QCBORDecode_PeekNext(dec, &item))
{
int64_t blk_num;
QCBORDecode_GetInt64(dec, &blk_num);
if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
{
BSL_LOG_ERR("Invalid AAD Scope map key");
break;
}

uint64_t aad_flags;
QCBORDecode_GetUInt64(dec, &aad_flags);
if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
{
BSL_LOG_ERR("Invalid AAD Scope map value");
break;
}

BSLX_CoseSc_AadScope_set_at(*scope, blk_num, aad_flags);
}

QCBORDecode_ExitArray(dec);
return BSL_SUCCESS;
}

/** @struct BSLX_CoseSc_ChunkItem_t
* A variant which can be either:
* - @c data An instance of @c m_bstring_t
Expand Down Expand Up @@ -665,7 +646,7 @@ static int BSLX_CoseSc_ExternalAad_Chunked(const BSLX_CoseSc_t *ctx, BSLX_CoseSc
if (blk_num == 0)
{
// primary block
if (aad_flags & BSLX_COSESC_AAD_FLAG_METADATA)
if (aad_flags & BSLX_COSESC_AADSCOPE_FLAG_METADATA)
{
m_bstring_t *data = BSLX_CoseSc_ChunkList_GetBstring(chunklist);

Expand All @@ -691,7 +672,7 @@ static int BSLX_CoseSc_ExternalAad_Chunked(const BSLX_CoseSc_t *ctx, BSLX_CoseSc
}
}

if (aad_flags & BSLX_COSESC_AAD_FLAG_METADATA)
if (aad_flags & BSLX_COSESC_AADSCOPE_FLAG_METADATA)
{
m_bstring_t *data = BSLX_CoseSc_ChunkList_GetBstring(chunklist);

Expand All @@ -700,7 +681,7 @@ static int BSLX_CoseSc_ExternalAad_Chunked(const BSLX_CoseSc_t *ctx, BSLX_CoseSc
*total += BSLX_CoseSc_bstring_AppendHead(*data, CBOR_MAJOR_TYPE_POSITIVE_INT, aad_block.block_num);
*total += BSLX_CoseSc_bstring_AppendHead(*data, CBOR_MAJOR_TYPE_POSITIVE_INT, aad_block.flags);
}
if (aad_flags & BSLX_COSESC_AAD_FLAG_BTSD)
if (aad_flags & BSLX_COSESC_AADSCOPE_FLAG_BTSD)
{
// CBOR head and seq stream
{
Expand Down
65 changes: 40 additions & 25 deletions src/bsl/cose_sc/CoseContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@

#include "bsl/BPSecLib_Private.h"
#include "bsl/BPSecLib_Public.h"
#include "bsl/dynamic/CBOR.h"

#include <m-bptree.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -42,7 +39,7 @@ extern "C" {
#define BSLX_COSESC_CTX_ID 3

/// Internal option enumerations
enum BSLX_CoseSC_Option_e
enum BSLX_CoseSc_Option_e
{
/** Key ID as a byte string.
* The value is a byte string (which may contain encoded UTF8 text).
Expand All @@ -64,7 +61,8 @@ enum BSLX_CoseSC_Option_e
*/
BSLX_COSESC_OPTION_TGT_ALG,
/** AAD Scope as raw encoded data.
* The value is encoded CBOR interpreted as ::BSLX_CoseSc_AadScope_t.
* The value is encoded CBOR interpreted as ::BSLX_CoseSc_AadScope_t,
* and can use the BSLX_CoseSc_SetAadScope() helper in policy providers.
* Optional for source, optional exact-match for verifier/acceptor.
*/
BSLX_COSESC_OPTION_AAD_SCOPE,
Expand Down Expand Up @@ -111,7 +109,7 @@ enum BSLX_CoseSC_Option_e
};

/// @brief From https://www.ietf.org/archive/id/draft-ietf-dtn-bpsec-cose-16.html#section-2.2
enum BSLX_CoseSC_Param_e
enum BSLX_CoseSc_Param_e
{
/// Additional Protected headers
BSLX_COSESC_PARAM_ADDL_PHDR = 3,
Expand All @@ -122,7 +120,7 @@ enum BSLX_CoseSC_Param_e
};

/// @brief From https://www.ietf.org/archive/id/draft-ietf-dtn-bpsec-cose-16.html#section-2.3
enum BSLX_CoseSC_Result_e
enum BSLX_CoseSc_Result_e
{
BSLX_COSESC_RESULT_COSE_ENCRYPT0 = 16,
BSLX_COSESC_RESULT_COSE_MAC0 = 17,
Expand All @@ -132,30 +130,47 @@ enum BSLX_CoseSC_Result_e
BSLX_COSESC_RESULT_COSE_SIGN = 98,
};

/** @struct BSLX_CoseSc_AadScope_t
* An internal representation of AAD Scope map, with keys sorted in
* CBOR deterministic order and values as a bit mask of
* ::BSLX_CoseSC_AAD_Flag_e flags.
*/
// NOLINTBEGIN
/// @cond Doxygen_Suppress
// GCOV_EXCL_START
M_BPTREE_DEF2(BSLX_CoseSc_AadScope, 4, int64_t, M_OPEXTEND(M_BASIC_OPLIST, CMP(API_6(BSL_CBOR_Compare_Int64))),
uint64_t, M_BASIC_OPLIST)
// GCOV_EXCL_STOP
/// @endcond
// NOLINTEND
/// Special keys for AAD Scope parameter
enum BSLX_CoseSc_AadScope_Special_e
{
/// Reference the security target block
BSLX_COSESC_AADSCOPE_SPECIAL_TARGET = -1,
/// Reference the parent security block
BSLX_COSESC_AADSCOPE_SPECIAL_SECURITY = -2,
};

/// Flags for AAD Scope parameter
enum BSLX_CoseSC_AAD_Flag_e
enum BSLX_CoseSc_AadScope_Flag_e
{
BSLX_COSESC_AAD_FLAG_METADATA = 0x1,
BSLX_COSESC_AAD_FLAG_BTSD = 0x2,
/// Include block header items in AAD
BSLX_COSESC_AADSCOPE_FLAG_METADATA = 0x1,
/// Include BTSD in AAD
BSLX_COSESC_AADSCOPE_FLAG_BTSD = 0x2,
};

int BSLX_CoseSc_AadScope_Encode(QCBOREncodeContext *enc, const BSLX_CoseSc_AadScope_t *scope);
/** Native C structure for each item of COSE Context AAD Scope.
*/
typedef struct
{
/// Block number or special key from ::BSLX_CoseSc_AadScope_Special_e
int64_t key;
/** Choice of flags from ::BSLX_CoseSc_AadScope_Flag_e.
* This type is compatible with ::BSL_IdValPair_s storage.
*/
int64_t flags;
} BSLX_CoseSc_AadScope_Item_t;

int BSLX_CoseSc_AadScope_Decode(QCBORDecodeContext *dec, BSLX_CoseSc_AadScope_t *scope);
/** Utility to set the ::BSLX_COSESC_OPTION_AAD_SCOPE option without exposing
* the encoding internals.
*
* @param[in,out] option Pointer to the option to set the AAD Scope on.
* @param[in] list Pointer to an array of integer values, each
* subsequent pair of values is interpreted as a (key, value) in the scope map.
* The order of keys in this form is not significant.
* @param count The number of @b pairs of values in the @c list array.
* @return BSL_SUCCESS if successful.
*/
int BSLX_CoseSc_SetAadScope(BSL_IdValPair_t *option, const BSLX_CoseSc_AadScope_Item_t *list, size_t count);

/// Match signature ::BSL_SecCtx_Validate_f
bool BSLX_CoseSc_Validate(BSL_LibCtx_t *lib, BSL_BundleRef_t *bundle, BSL_SecOper_t *sec_oper);
Expand Down
Loading
Loading