BSL v0.0.0
AMMOS Bundle Protocol Security Library (BSL)
Loading...
Searching...
No Matches
PublicInterfaceImpl.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025 The Johns Hopkins University Applied Physics
3 * Laboratory LLC.
4 *
5 * This file is part of the Bundle Protocol Security Library (BSL).
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * This work was performed for the Jet Propulsion Laboratory, California
18 * Institute of Technology, sponsored by the United States Government under
19 * the prime contract 80NM0018D0004 between the Caltech and NASA under
20 * subcontract 1700763.
21 */
28#include <inttypes.h>
29
30#include <BPSecLib_Private.h>
31#include <BPSecLib_Public.h>
32
33#include "PublicInterfaceImpl.h"
34#include "SecurityActionSet.h"
35#include "SecurityResultSet.h"
36
38{
39 CHK_ARG_NONNULL(lib);
40
41 BSL_SecCtxDict_init(lib->sc_reg);
42 return BSL_SUCCESS;
43}
44
46{
47 CHK_ARG_NONNULL(lib);
48
49 if (lib->policy_registry.deinit_fn != NULL)
50 {
51 // Call the policy deinit function
52 (lib->policy_registry.deinit_fn)(lib->policy_registry.user_data);
53
54 // TODO - We should not assume this is dynamically allocated.
55 free(lib->policy_registry.user_data);
56 }
57 else
58 {
59 BSL_LOG_WARNING("Policy Provider offered no deinit function");
60 }
61
62 BSL_SecCtxDict_clear(lib->sc_reg);
63 return BSL_SUCCESS;
64}
65
67{
68 CHK_ARG_NONNULL(lib);
69 CHK_ARG_EXPR(desc.validate != NULL);
70 CHK_ARG_EXPR(desc.execute != NULL);
71
72 BSL_SecCtxDict_set_at(lib->sc_reg, sec_ctx_id, desc);
73 return BSL_SUCCESS;
74}
75
77{
78 CHK_ARG_NONNULL(lib);
79 CHK_ARG_EXPR(desc.query_fn != NULL);
80
81 lib->policy_registry = desc;
82 return BSL_SUCCESS;
83}
84
86 const BSL_BundleRef_t *bundle, BSL_PolicyLocation_e location)
87{
88 CHK_ARG_NONNULL(bsl);
89 CHK_ARG_NONNULL(output_action_set);
90 CHK_ARG_NONNULL(bundle);
91
92 CHK_PRECONDITION(bsl->policy_registry.query_fn != NULL);
93 CHK_PRECONDITION(bsl->policy_registry.deinit_fn != NULL);
94
95 BSL_LOG_INFO("Querying policy provider for security actions...");
96 int query_status = 0;
97 if (bsl->policy_registry.query_fn != NULL)
98 {
99 query_status =
100 bsl->policy_registry.query_fn(bsl->policy_registry.user_data, output_action_set, bundle, location);
101 BSL_LOG_INFO("Completed query: status=%d", query_status);
102 }
103 else
104 {
105 query_status = BSL_ERR_NOT_FOUND;
106 BSL_LOG_WARNING("No policy provider defined");
107 return query_status;
108 }
109
110 // Here - find the sec block numbers for all ASBs
111
112 // Explanation:
113 // This segment of code finds the block number of the security block
114 // that targets (protects) a block whose ID is `target_block_num`
115 //
116 // I.e., "Get me the security block whose target contains `target_block_num`"
117 BSL_PrimaryBlock_t primary_block = { 0 };
118 if (BSL_SUCCESS != BSL_BundleCtx_GetBundleMetadata(bundle, &primary_block))
119 {
120 BSL_LOG_ERR("Cannot get bundle primary block");
122 }
123
124 uint64_t blocks_array[primary_block.block_count];
125 size_t total_blocks = 0;
126 if (BSL_SUCCESS != BSL_BundleCtx_GetBlockIds(bundle, primary_block.block_count, blocks_array, &total_blocks))
127 {
128 BSL_LOG_ERR("Failed to get block indices");
130 }
131
132 CHK_PROPERTY(total_blocks == primary_block.block_count);
133
134 for (size_t i = 0; i < total_blocks; i++)
135 {
136 BSL_CanonicalBlock_t block = { 0 };
137 if (BSL_SUCCESS != BSL_BundleCtx_GetBlockMetadata(bundle, blocks_array[i], &block))
138 {
139 BSL_LOG_WARNING("Failed to get block number %lu", blocks_array[i]);
140 continue;
141 }
142 for (size_t sec_op_index = 0; sec_op_index < output_action_set->sec_operations_count; sec_op_index++)
143 {
144 BSL_SecOper_t *sec_oper = &output_action_set->sec_operations[sec_op_index];
145 if (block.type_code != sec_oper->_service_type)
146 {
147 continue;
148 }
149 // Now set it's sec_block
150 BSL_AbsSecBlock_t *abs_sec_block = calloc(1, BSL_AbsSecBlock_Sizeof());
151 BSL_Data_t block_btsd = { 0 };
152 BSL_Data_InitView(&block_btsd, block.btsd_len, block.btsd);
153 if (BSL_AbsSecBlock_DecodeFromCBOR(abs_sec_block, block_btsd) == 0)
154 {
155 if (BSL_AbsSecBlock_ContainsTarget(abs_sec_block, sec_oper->target_block_num))
156 {
157 sec_oper->sec_block_num = block.block_num;
158 }
159 }
160 else
161 {
162 BSL_LOG_WARNING("Failed to parse ASB from BTSD");
163 }
164 BSL_AbsSecBlock_Deinit(abs_sec_block);
165 free(abs_sec_block);
166 }
167 }
168
169 if (BSL_SecCtx_ValidatePolicyActionSet((BSL_LibCtx_t *)bsl, bundle, output_action_set) == false)
170 {
172 BSL_LOG_WARNING("Security Context validation failed");
173 }
174
175 return query_status;
176}
177
179 const BSL_SecurityActionSet_t *policy_actions)
180{
181 CHK_ARG_NONNULL(bsl);
182 CHK_ARG_NONNULL(response_output);
183 CHK_ARG_NONNULL(bundle);
184 CHK_ARG_NONNULL(policy_actions);
185
186 int exec_code = BSL_SecCtx_ExecutePolicyActionSet((BSL_LibCtx_t *)bsl, response_output, bundle, policy_actions);
187 if (exec_code < BSL_SUCCESS)
188 {
189 BSL_LOG_ERR("Failed to execute policy action set");
190 }
191
192 BSL_PrimaryBlock_t primary_block = { 0 };
193 if (BSL_SUCCESS != BSL_BundleCtx_GetBundleMetadata(bundle, &primary_block))
194 {
195 BSL_LOG_ERR("Failed to get bundle metadata");
197 }
198
199 // There should be as many responses as there were sec operations
200 ASSERT_PROPERTY(response_output->total_operations == policy_actions->sec_operations_count);
201
202 bool must_drop = false;
203 for (size_t oper_index = 0; oper_index < policy_actions->sec_operations_count; oper_index++)
204 {
205 // First, get the error code for the security operation ()
206 int block_err_code = response_output->results[oper_index];
207 BSL_PolicyAction_e err_action_code = policy_actions->sec_operations[oper_index].failure_code;
208
209 // When the operation was a success, there's nothing further to do.
210 if (block_err_code == BSL_SUCCESS)
211 {
212 BSL_LOG_DEBUG("Security operation [%lu] success, target block num = %lu", oper_index,
213 policy_actions->sec_operations[oper_index].target_block_num);
214 continue;
215 }
216
217 // Now handle a specific error
218 switch (err_action_code)
219 {
221 {
222 // Do nothing, per policy (Indicate in telemetry.)
223 BSL_LOG_WARNING("Instructed to do nothing for failed security operation");
224 break;
225 }
227 {
228 // Drop the failed target block, but otherwise continue
229 BSL_LOG_WARNING("***** Dropping block over which security operation failed *******");
230 BSL_BundleCtx_RemoveBlock(bundle, policy_actions->sec_operations[oper_index].target_block_num);
231 break;
232 }
234 {
235 BSL_LOG_WARNING("Dropping bundle due to block target num %lu security failure",
236 policy_actions->sec_operations[oper_index].target_block_num);
237 must_drop = true;
238 break;
239 }
241 default:
242 {
243 BSL_LOG_ERR("Unhandled policy action: %lu", err_action_code);
244 }
245 }
246
247 if (must_drop)
248 {
249 break;
250 }
251 }
252
253 if (must_drop)
254 {
255 BSL_LOG_ERR("TODO Drop bundle using host interface");
256 }
257
258 // TODO CHK_POSTCONDITION
259 return (must_drop) ? BSL_ERR_SECURITY_OPERATION_FAILED : BSL_SUCCESS;
260}
Single entry-point include file for all of the BPSec Lib (BSL) frontend API.
#define BSL_LOG_DEBUG(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool BSL_AbsSecBlock_ContainsTarget(const BSL_AbsSecBlock_t *self, uint64_t target_block_num)
Returns true if a given ASB contains the given block number as a security target.
void BSL_AbsSecBlock_Deinit(BSL_AbsSecBlock_t *self)
Deinitializes and clears this ASB, clearing and releasing any owned memory.
BSL_PolicyAction_e
Codes indicating the fate of a block if a security operation over it fails.
@ BSL_POLICYACTION_UNDEFINED
Placeholder for zero - should never occur.
@ BSL_POLICYACTION_DROP_BUNDLE
Drop the entire bundle.
@ BSL_POLICYACTION_NOTHING
Do nothing, keep the block even if it fails.
@ BSL_POLICYACTION_DROP_BLOCK
Drop on the target block.
#define BSL_LOG_INFO(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
struct BSL_AbsSecBlock_s BSL_AbsSecBlock_t
Forward declaration of BSL_AbsSecBlock_t.
#define BSL_LOG_WARNING(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
int BSL_AbsSecBlock_DecodeFromCBOR(BSL_AbsSecBlock_t *self, BSL_Data_t encoded_cbor)
Decodes and populates this ASB from a CBOR string.
size_t BSL_AbsSecBlock_Sizeof(void)
Returns the size of the AbsSecBlock struct in bytes.
#define BSL_LOG_ERR(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
@ BSL_ERR_SECURITY_OPERATION_FAILED
Security operation failed (e.g., BIB did not have enough parameters)
@ BSL_ERR_NOT_FOUND
Requested value not found for key.
@ BSL_SUCCESS
Placeholder for non-error code.
@ BSL_ERR_SECURITY_CONTEXT_VALIDATION_FAILED
Indicates an HMAC signature did not match.
@ BSL_ERR_HOST_CALLBACK_FAILED
Callback to the host BPA returned a non-zero code.
Single entry-point include file for all of the "Public" BPSec Lib (BSL) frontend API.
BSL_PolicyLocation_e
Indicates where in the lifecycle of the BPA the bundle is querying for security policy.
int BSL_BundleCtx_GetBlockIds(const BSL_BundleRef_t *bundle, size_t array_count, uint64_t block_ids_array[array_count], size_t *result_count)
Returns an array in which each element contains the id of the corresponding block....
int BSL_BundleCtx_GetBlockMetadata(const BSL_BundleRef_t *bundle, uint64_t block_num, BSL_CanonicalBlock_t *result_block)
Returns information about the bundle Canonical block.
int BSL_BundleCtx_RemoveBlock(BSL_BundleRef_t *bundle, uint64_t block_num)
Requests the removal of a block from a bundle.
int BSL_BundleCtx_GetBundleMetadata(const BSL_BundleRef_t *bundle, BSL_PrimaryBlock_t *result_primary_block)
Calls the host interface to get a bundle primary block information.abort.
int BSL_API_InitLib(BSL_LibCtx_t *lib)
Initialize the BPSecLib (BSL) library context.
int BSL_API_QuerySecurity(const BSL_LibCtx_t *bsl, BSL_SecurityActionSet_t *output_action_set, const BSL_BundleRef_t *bundle, BSL_PolicyLocation_e location)
Query BSL to populate a BSL_SecurityActionSet_t containg security processing instructions.
int BSL_API_RegisterPolicyProvider(BSL_LibCtx_t *lib, BSL_PolicyDesc_t desc)
Register a Policy Provider module with the BSL.
int BSL_API_RegisterSecurityContext(BSL_LibCtx_t *lib, uint64_t sec_ctx_id, BSL_SecCtxDesc_t desc)
Register a security context module with the BSL.
int BSL_API_ApplySecurity(const BSL_LibCtx_t *bsl, BSL_SecurityResponseSet_t *response_output, BSL_BundleRef_t *bundle, const BSL_SecurityActionSet_t *policy_actions)
Performs the given security operations on a Bundle, modifying or even dropping it entirely.
int BSL_API_DeinitLib(BSL_LibCtx_t *lib)
Deinitialize and release any resources held by the BSL.
Private interface for the dynamic backend library context.
Implementation of construct holding details of security operations for a bundle.
bool BSL_SecCtx_ValidatePolicyActionSet(BSL_LibCtx_t *lib, const BSL_BundleRef_t *bundle, const BSL_SecurityActionSet_t *action_set)
int BSL_SecCtx_ExecutePolicyActionSet(BSL_LibCtx_t *lib, BSL_SecurityResponseSet_t *output_response, BSL_BundleRef_t *bundle, const BSL_SecurityActionSet_t *action_set)
Call the underying security context to perform the given action.
SecurityResultSet implementation for result after application of security operations.
int BSL_Data_InitView(BSL_Data_t *data, size_t len, const BSL_DataPtr_t src)
Initialize a data struct as an overlay on optional external data.
Reference to a Bundle owned and stored in the host BPA.
Structure containing parsed Canonical Block fields.
uint64_t block_num
CBOR-decoded block number (should always be > 0)
void * btsd
Pointer to BTSD owned by the host BPA.
size_t btsd_len
Length in bytes of the BTSD pointer.
uint64_t type_code
CBOR-decoded block type code (should be > 0)
Heap data storage and views.
Concrete definition of library context.
Descriptor of opaque data and callbacks for Policy Provider.
BSL_PolicyInspect_f query_fn
Function pointer to query policy.
BSL_PolicyDeinit_f deinit_fn
Function to deinit the policy provider at termination of BPA.
Contains Bundle Primary Block fields and metadata.
size_t block_count
Helpful count of total canonical blocks in bundle, not a field of the header.
Security Context descriptor (interface)
BSL_SecCtx_Execute_f execute
Callback to execute a sec op within a given bundle.
BSL_SecCtx_Validate_f validate
Callback to validate a sec op within a given bundle.
uint64_t target_block_num
Bundle's block ID over which the security operation is applied.
uint64_t sec_block_num
Bundle's block ID which contains the security parameters and results for this operation.
BSL_PolicyAction_e failure_code
Code for handing what to do to the block or bundle if security processing fails.
Contains the populated security operations for this bundle.
BSL_SecOper_t sec_operations[BSL_SECURITYACTIONSET_MAX_OPS]
Fixed array of security operations (for simpler mem management)
size_t sec_operations_count
Count of sec_operations.
Contains the results and outcomes after performing the security operations.
int results[BSL_SECURITYRESPONSESET_ARRAYLEN]
This maps to the sec_operations in BSL_SecurityActionSet, and contains the result code of that securi...