BSL v0.0.0
AMMOS Bundle Protocol Security Library (BSL)
Loading...
Searching...
No Matches
bsl_mock_bpa_decode.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 */
22
27#include "bsl_mock_bpa.h"
28#include "bsl_mock_bpa_decode.h"
29#include "bsl_mock_bpa_crc.h"
30#include <BPSecLib_Public.h>
31#include <BPSecLib_Private.h>
32
33#include <qcbor/qcbor_spiffy_decode.h>
34
35int bsl_mock_decode_eid(QCBORDecodeContext *dec, BSL_HostEID_t *eid)
36{
37 assert(dec != NULL);
38 assert(eid != NULL);
39 assert(eid->handle != NULL);
41 assert(obj != NULL);
42 CHKERR1(dec);
43 CHKERR1(obj);
44
47
48 QCBORItem decitem;
49 QCBORDecode_EnterArray(dec, NULL);
50
51 QCBORDecode_GetUInt64(dec, &(obj->scheme));
52 if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
53 {
54 return 2;
55 }
56
57 switch (obj->scheme)
58 {
60 {
61 bsl_eid_ipn_ssp_t *ipn = &(obj->ssp.as_ipn);
62 assert(ipn != NULL);
63 QCBORDecode_EnterArray(dec, &decitem);
64 if (decitem.val.uCount == 2)
65 {
66 ipn->ncomp = 2;
67 uint64_t qnode;
68 QCBORDecode_GetUInt64(dec, &qnode);
69 ipn->auth_num = qnode >> 32;
70 ipn->node_num = qnode & 0xFFFFFFFF;
71 QCBORDecode_GetUInt64(dec, &(ipn->svc_num));
72 }
73 else if (decitem.val.uCount == 3)
74 {
75 ipn->ncomp = 3;
76 QCBORDecode_GetUInt64(dec, &(ipn->auth_num));
77 QCBORDecode_GetUInt64(dec, &(ipn->node_num));
78 QCBORDecode_GetUInt64(dec, &(ipn->svc_num));
79
80 if ((ipn->auth_num > UINT32_MAX) || (ipn->node_num > UINT32_MAX))
81 {
82 // parts larger than allowed
83 return 4;
84 }
85 }
86 else
87 {
88 return 2;
89 }
90 QCBORDecode_ExitArray(dec);
91 break;
92 }
93 default:
94 {
95 // skip over item and store its encoded form
96 const size_t begin = QCBORDecode_Tell(dec);
97 QCBORDecode_VGetNextConsume(dec, &decitem);
98 const size_t end = QCBORDecode_Tell(dec);
99 if (end > begin)
100 {
101 BSL_Data_t *raw = &(obj->ssp.as_raw);
102 assert(raw != NULL);
103 BSL_Data_Init(raw);
104 // FIXME expose this from the decoder
105 BSL_Data_CopyFrom(raw, end - begin, (uint8_t *)dec->InBuf.UB.ptr + begin);
106 }
107 break;
108 }
109 }
110
111 QCBORDecode_ExitArray(dec);
112 return 0;
113}
114
115int bsl_mock_decode_primary(QCBORDecodeContext *dec, MockBPA_PrimaryBlock_t *blk)
116{
117 CHKERR1(dec);
118 CHKERR1(blk);
119
120 const size_t begin = QCBORDecode_Tell(dec);
121 QCBORDecode_EnterArray(dec, NULL);
122
123 QCBORDecode_GetUInt64(dec, &(blk->version));
124 if ((QCBOR_SUCCESS != QCBORDecode_GetError(dec)) || (blk->version != 7))
125 {
126 return 2;
127 }
128
129 QCBORDecode_GetUInt64(dec, &(blk->flags));
130 QCBORDecode_GetUInt64(dec, &(blk->crc_type));
131
132 MockBPA_EID_Init(NULL, &blk->dest_eid);
133 bsl_mock_decode_eid(dec, &(blk->dest_eid));
134
135 MockBPA_EID_Init(NULL, &blk->src_node_id);
136 bsl_mock_decode_eid(dec, &(blk->src_node_id));
137
138 MockBPA_EID_Init(NULL, &blk->report_to_eid);
139 bsl_mock_decode_eid(dec, &(blk->report_to_eid));
140
141 QCBORDecode_EnterArray(dec, NULL);
142 QCBORDecode_GetUInt64(dec, &(blk->timestamp.bundle_creation_time));
143 QCBORDecode_GetUInt64(dec, &(blk->timestamp.seq_num));
144 QCBORDecode_ExitArray(dec);
145
146 QCBORDecode_GetUInt64(dec, &(blk->lifetime));
147
148 if (blk->flags & BSL_BUNDLE_IS_FRAGMENT)
149 {
150 QCBORDecode_GetUInt64(dec, &(blk->frag_offset));
151 QCBORDecode_GetUInt64(dec, &(blk->adu_length));
152 }
153 else
154 {
155 blk->frag_offset = blk->adu_length = 0;
156 }
157
158 UsefulBufC view;
159 switch (blk->crc_type)
160 {
163 // just ignore the bytes
164 QCBORDecode_GetByteString(dec, &view);
165 break;
166 default:
167 // nothing
168 break;
169 }
170
171 QCBORDecode_ExitArray(dec);
172 const size_t end = QCBORDecode_Tell(dec);
173
174 if (!mock_bpa_crc_check(QCBORDecode_RetrieveUndecodedInput(dec), begin, end, blk->crc_type))
175 {
176 return 4;
177 }
178
179 blk->cbor_len = end - begin;
180 blk->cbor = calloc(1, blk->cbor_len);
181 memcpy(blk->cbor, &((uint8_t *)dec->InBuf.UB.ptr)[begin], blk->cbor_len);
182
183 return 0;
184}
185
186int bsl_mock_decode_canonical(QCBORDecodeContext *dec, MockBPA_CanonicalBlock_t *blk)
187{
188 CHKERR1(dec);
189 CHKERR1(blk);
190
191 const size_t begin = QCBORDecode_Tell(dec);
192 QCBORDecode_EnterArray(dec, NULL);
193
194 QCBORDecode_GetUInt64(dec, &(blk->blk_type));
195 QCBORDecode_GetUInt64(dec, &(blk->blk_num));
196 QCBORDecode_GetUInt64(dec, &(blk->flags));
197 QCBORDecode_GetUInt64(dec, &(blk->crc_type));
198
199 UsefulBufC view;
200 QCBORDecode_GetByteString(dec, &view);
201 if (QCBOR_SUCCESS == QCBORDecode_GetError(dec))
202 {
203 if (blk->btsd == NULL)
204 {
205 blk->btsd = calloc(1, view.len);
206 blk->btsd_len = view.len;
207 }
208 assert(blk->btsd != NULL);
209 assert(blk->btsd_len > 0);
210 memcpy(blk->btsd, view.ptr, view.len);
211 }
212
213 switch (blk->crc_type)
214 {
217 // just ignore the bytes
218 QCBORDecode_GetByteString(dec, &view);
219 break;
220 default:
221 // nothing
222 break;
223 }
224
225 QCBORDecode_ExitArray(dec);
226 const size_t end = QCBORDecode_Tell(dec);
227
228 if (!mock_bpa_crc_check(QCBORDecode_RetrieveUndecodedInput(dec), begin, end, blk->crc_type))
229 {
230 return 4;
231 }
232
233 return 0;
234}
235
236int bsl_mock_decode_bundle(QCBORDecodeContext *dec, MockBPA_Bundle_t *bundle)
237{
238 CHKERR1(dec);
239 CHKERR1(bundle);
240
241 QCBORItem decitem;
242 QCBORDecode_EnterArray(dec, &decitem);
243 if (decitem.val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH)
244 {
245 // FIXME warn but still process
246 }
247
248 if (bsl_mock_decode_primary(dec, &(bundle->primary_block)))
249 {
250 return 2;
251 }
252
253 // iterate until failure of CBOR, not block decoder
254 while (QCBOR_SUCCESS == QCBORDecode_PeekNext(dec, &decitem))
255 {
256 MockBPA_CanonicalBlock_t blk = { 0 };
257 int parse_res = bsl_mock_decode_canonical(dec, &blk);
258 if (parse_res)
259 {
260 free(blk.btsd);
261 return 3;
262 }
263 bundle->blocks[bundle->block_count++] = blk;
264 }
265
266 QCBORDecode_ExitArray(dec);
267 return 0;
268}
Single entry-point include file for all of the BPSec Lib (BSL) frontend API.
@ BSL_BUNDLE_IS_FRAGMENT
Set if this bundle is a fragment.
#define CHKERR1(cond)
Return the error value 1 if condition fails.
Single entry-point include file for all of the "Public" BPSec Lib (BSL) frontend API.
@ BSL_BUNDLECRCTYPE_16
CRC-16.
@ BSL_BUNDLECRCTYPE_32
CRC-32C.
int BSL_Data_CopyFrom(BSL_Data_t *data, size_t len, BSL_DataConstPtr_t src)
Set an initialized data struct to a given size.
int BSL_Data_Init(BSL_Data_t *data)
Initialize an empty data struct.
Declarations for Agent initialization.
bool mock_bpa_crc_check(UsefulBufC buf, size_t begin, size_t end, BSL_BundleCRCType_e crc_type)
Check the CRC of an encoded block.
Declarations for BPv7 block CRC handling.
int bsl_mock_decode_primary(QCBORDecodeContext *dec, MockBPA_PrimaryBlock_t *blk)
Encode primary block to a CBOR bytestring.
int bsl_mock_decode_eid(QCBORDecodeContext *dec, BSL_HostEID_t *eid)
Encode a single EID.
int bsl_mock_decode_bundle(QCBORDecodeContext *dec, MockBPA_Bundle_t *bundle)
This is an overloaded member function, provided for convenience. It differs from the above function o...
int bsl_mock_decode_canonical(QCBORDecodeContext *dec, MockBPA_CanonicalBlock_t *blk)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Declarations for bundle and block decoding.
void bsl_mock_eid_deinit(bsl_mock_eid_t *eid)
Internal struct de-initializer.
int MockBPA_EID_Init(void *user_data, BSL_HostEID_t *eid)
Interface for BSL_HostDescriptors_t::eid_init.
void bsl_mock_eid_init(bsl_mock_eid_t *eid)
Internal struct initializer.
@ BSL_MOCK_EID_IPN
The "ipn" scheme.
Heap data storage and views.
BSL_DataPtr_t ptr
Pointer to the front of the buffer.
Opaque pointer to BPA-specific Endpoint ID storage.
void * handle
Opaque pointer for BPA backend to use.
Scheme-specific part for IPN scheme.
int ncomp
The number of components when encoded, either 2 or 3.
uint64_t svc_num
The service number component.
uint64_t node_num
The node number component.
uint64_t auth_num
The authority number component.
Struct to be used as a BSL_HostEID_t::handle.
union bsl_mock_eid_t::@0 ssp
Interpreted according to scheme code.
bsl_eid_ipn_ssp_t as_ipn
Used when scheme is BSL_MOCK_EID_IPN.
uint64_t scheme
Code point for EID schemes from .
BSL_Data_t as_raw
Used in all other cases, copied from source.