30#include <qcbor/qcbor_encode.h>
31#include <qcbor/qcbor_spiffy_decode.h>
40int BSLX_BCB_ComputeAAD(
BSLX_BCB_t *bcb_context)
42 CHK_ARG_NONNULL(bcb_context);
45 CHK_PRECONDITION(bcb_context->aad.
len == 0);
46 CHK_PRECONDITION(bcb_context->aad.
ptr == NULL);
49 flags |= ((!bcb_context->skip_aad_prim_block) & 0x01);
50 flags |= ((!bcb_context->skip_aad_target_block & 0x01) << 1);
51 flags |= ((!bcb_context->skip_aad_sec_block & 0x01) << 2);
56 const size_t aad_len = 1024;
63 QCBOREncodeContext aad_enc;
64 QCBOREncode_Init(&aad_enc, (UsefulBuf) { .ptr = bcb_context->aad.
ptr, .len = bcb_context->aad.
len });
65 QCBOREncode_AddUInt64(&aad_enc, flags);
70 UsefulBufC prim_blk_encoded = { .ptr = bcb_context->primary_block.cbor,
71 .len = bcb_context->primary_block.cbor_len };
72 QCBOREncode_AddEncoded(&aad_enc, prim_blk_encoded);
77 BSLX_EncodeHeader(&bcb_context->target_block, &aad_enc);
82 BSLX_EncodeHeader(&bcb_context->sec_block, &aad_enc);
85 UsefulBufC cbor_encoded_buffer = { 0 };
86 if (QCBOR_SUCCESS != QCBOREncode_Finish(&aad_enc, &cbor_encoded_buffer))
97static int BSLX_BCB_Decrypt(
BSLX_BCB_t *bcb_context)
99 CHK_ARG_NONNULL(bcb_context);
104 CHK_PRECONDITION(bcb_context->aad.
ptr != NULL);
105 CHK_PRECONDITION(bcb_context->aad.
len > 0);
108 CHK_PRECONDITION(bcb_context->key_id > 0);
111 CHK_PRECONDITION(bcb_context->btsd_replacement.
ptr != NULL);
112 CHK_PRECONDITION(bcb_context->btsd_replacement.
len > 0);
115 CHK_PRECONDITION(bcb_context->authtag.
ptr != NULL);
116 CHK_PRECONDITION(bcb_context->authtag.
len > 0);
119 CHK_PRECONDITION(bcb_context->iv.
ptr != NULL);
120 CHK_PRECONDITION(bcb_context->iv.
len > 0);
126 bool is_aes128 = bcb_context->aes_variant == RFC9173_BCB_AES_VARIANT_A128GCM;
127 BSL_CryptoCipherAESVariant_e aes_mode = is_aes128 ? BSL_CRYPTO_AES_128 : BSL_CRYPTO_AES_256;
131 if (bcb_context->wrapped_key.
len > 0)
135 BSL_Crypto_UnwrapKey(&content_enc_key, bcb_context->wrapped_key, bcb_context->key_id, aes_mode);
147 &content_enc_key.
len))
155 CHK_PROPERTY(content_enc_key.
len < 2048);
158 int cipher_init =
BSL_Cipher_Init(&cipher, BSL_CRYPTO_DECRYPT, aes_mode, bcb_context->iv.
ptr, (
int)bcb_context->iv.
len,
174 int nbytes =
BSL_Cipher_AddData(&cipher, plaintext_data, bcb_context->btsd_replacement);
180 const size_t plaintext_len = (size_t)nbytes;
190 uint8_t aes_extra[BSLX_MAX_AES_PAD];
191 memset(aes_extra, 0,
sizeof(aes_extra));
194 int finalize_bytes = BSL_Cipher_FinalizeData(&cipher, &remainder_data);
195 if (finalize_bytes < 0)
200 const size_t extra_bytes = (size_t)finalize_bytes;
201 assert(extra_bytes == 0);
202 BSL_Data_Resize(&bcb_context->btsd_replacement, plaintext_len + extra_bytes);
207 assert(bcb_context->authtag.
len == 0);
220 CHK_ARG_NONNULL(bcb_context);
223 CHK_PRECONDITION(bcb_context->aad.
ptr != NULL);
224 CHK_PRECONDITION(bcb_context->aad.
len > 0);
227 CHK_PRECONDITION(bcb_context->key_id > 0);
230 CHK_PRECONDITION(bcb_context->btsd_replacement.
ptr != NULL);
231 CHK_PRECONDITION(bcb_context->btsd_replacement.
len > 0);
234 CHK_PRECONDITION(bcb_context->authtag.
len == 0);
236 bool is_aes128 = bcb_context->aes_variant == RFC9173_BCB_AES_VARIANT_A128GCM;
237 BSL_CryptoCipherAESVariant_e aes_mode = is_aes128 ? BSL_CRYPTO_AES_128 : BSL_CRYPTO_AES_256;
242 if (bcb_context->iv.
len == 0)
247 void *iv_ptr = bcb_context->iv.
ptr;
248 const size_t iv_len = bcb_context->iv.
len;
268 if (bcb_context->skip_keywrap)
276 &content_enc_key.
len))
281 ASSERT_PROPERTY(content_enc_key.
len > 0);
282 ASSERT_PROPERTY(content_enc_key.
ptr == NULL);
286 if (bcb_context->test_content_enc_key.
len > 0)
288 ASSERT_PROPERTY(content_enc_key.
len >= bcb_context->test_content_enc_key.
len);
290 memcpy(content_enc_key.
ptr, bcb_context->test_content_enc_key.
ptr, bcb_context->test_content_enc_key.
len);
291 content_enc_key.
len = bcb_context->test_content_enc_key.
len;
295 const size_t keysize = is_aes128 ? 16 : 32;
297 if (
BSL_SUCCESS != BSL_Crypto_GenKey(content_enc_key.
ptr, keysize))
310 int wrap_result =
BSL_Crypto_WrapKey(&bcb_context->wrapped_key, content_enc_key, bcb_context->key_id, aes_mode);
335 int nbytes =
BSL_Cipher_AddData(&cipher, plaintext_data, bcb_context->btsd_replacement);
341 const size_t ciphertext_len = (size_t)nbytes;
342 ASSERT_PROPERTY(ciphertext_len >= plaintext_data.
len);
344 ASSERT_PROPERTY(ciphertext_len < bcb_context->btsd_replacement.len);
345 uint8_t aes_extra[BSLX_MAX_AES_PAD];
346 memset(aes_extra, 0,
sizeof(aes_extra));
349 int extra_bytes = BSL_Cipher_FinalizeData(&cipher, &remainder_data);
355 const size_t extra_bytelen = (size_t)extra_bytes;
359 const size_t finalized_len = ciphertext_len + extra_bytelen;
369 CHK_POSTCONDITION(bcb_context->btsd_replacement.
ptr != NULL);
370 CHK_POSTCONDITION(bcb_context->btsd_replacement.
len == ciphertext_len);
386 CHK_ARG_NONNULL(bundle);
387 CHK_ARG_NONNULL(bcb_context);
388 CHK_ARG_NONNULL(sec_oper);
390 CHK_PRECONDITION(bcb_context->target_block.
block_num > 0);
391 CHK_PRECONDITION(bcb_context->target_block.
btsd != NULL);
392 CHK_PRECONDITION(bcb_context->target_block.
btsd_len > 0);
403 case RFC9173_BCB_SECPARAM_IV:
409 bcb_context->err_count++;
414 bcb_context->err_count++;
419 case RFC9173_BCB_SECPARAM_AESVARIANT:
421 BSL_LOG_DEBUG(
"BCB parsing AES variant (optid=%lu)", param_id);
424 if (bcb_context->aes_variant < RFC9173_BCB_AES_VARIANT_A128GCM
425 || bcb_context->aes_variant > RFC9173_BCB_AES_VARIANT_A256GCM)
427 BSL_LOG_ERR(
"Unknown AES variant %lu", bcb_context->aes_variant);
428 bcb_context->err_count++;
432 case RFC9173_BCB_SECPARAM_WRAPPEDKEY:
434 BSL_LOG_DEBUG(
"BCB parsing Wrapped key parameter (optid=%lu)", param_id);
439 bcb_context->err_count++;
445 bcb_context->err_count++;
450 case RFC9173_BCB_SECPARAM_AADSCOPE:
454 BSL_LOG_DEBUG(
"Param[%lu]: AAD_SCOPE value = %lu", param_id, aad_scope);
455 if ((aad_scope & RFC9173_BCB_AADSCOPEFLAGID_INC_PRIM_BLOCK) == 0)
457 BSL_LOG_DEBUG(
"BCB AAD does not contain primary block flag");
458 bcb_context->skip_aad_prim_block =
true;
460 if ((aad_scope & RFC9173_BCB_AADSCOPEFLAGID_INC_TARGET_HEADER) == 0)
463 bcb_context->skip_aad_target_block =
true;
465 if ((aad_scope & RFC9173_BCB_AADSCOPEFLAGID_INC_SECURITY_HEADER) == 0)
468 bcb_context->skip_aad_sec_block =
true;
476 BSL_LOG_DEBUG(
"Param[%lu]: KEY_ID value = %lu", param_id, bcb_context->key_id);
486 case BSL_SECPARAM_TYPE_AUTH_TAG:
492 case BSL_SECPARAM_TYPE_IV:
495 BSL_LOG_DEBUG(
"Param[%lu]: USE TEST INITIALIZATION VECTOR", param_id);
502 BSL_LOG_DEBUG(
"Param[%lu]: USE_WRAPPED_KEY value = %lu", param_id, arg_val);
503 bcb_context->skip_keywrap = (arg_val == 0);
509 bcb_context->err_count++;
514 if (!bcb_context->skip_aad_sec_block)
532 CHK_ARG_NONNULL(bcb_context);
533 CHK_ARG_NONNULL(bundle);
534 CHK_ARG_NONNULL(sec_oper);
536 memset(bcb_context, 0,
sizeof(*bcb_context));
539 const size_t new_btsd_len = bcb_context->target_block.
btsd_len + 2048;
542 BSL_LOG_ERR(
"Failed to allocate BTSD double buffer");
561 CHK_PROPERTY(bcb_context->primary_block.
block_count > 0);
570 CHK_POSTCONDITION(bcb_context->target_block.
block_num > 0);
571 CHK_POSTCONDITION(bcb_context->target_block.
btsd != NULL);
572 CHK_POSTCONDITION(bcb_context->target_block.
btsd_len > 0);
573 CHK_POSTCONDITION(bcb_context->btsd_replacement.
ptr != NULL);
577static void BSLX_BCB_Deinit(
BSLX_BCB_t *bcb_context)
579 ASSERT_ARG_NONNULL(bcb_context);
590 memset(bcb_context, 0,
sizeof(*bcb_context));
597 CHK_ARG_NONNULL(bundle);
598 CHK_ARG_NONNULL(sec_oper);
599 CHK_ARG_NONNULL(sec_outcome);
614 if (
BSL_SUCCESS != BSLX_BCB_Init(&bcb_context, bundle, sec_oper))
621 if (
BSL_SUCCESS != BSLX_BCB_GetParams(bundle, &bcb_context, sec_oper))
628 if (
BSL_SUCCESS != BSLX_BCB_ComputeAAD(&bcb_context))
640 BSL_LOG_ERR(
"Failed to perform cryptographic action");
659 ASSERT_PROPERTY(target_block.
btsd_len == bcb_context.btsd_replacement.
len);
661 memcpy(target_block.
btsd, bcb_context.btsd_replacement.
ptr, bcb_context.btsd_replacement.
len);
665 if (bcb_context.authtag.
len > 0)
678 BSL_SecOutcome_AppendResult(sec_outcome, auth_tag);
683 BSLX_BCB_Deinit(&bcb_context);
688 BSLX_BCB_Deinit(&bcb_context);
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...
@ BSL_SECPARAM_TYPE_INT_USE_WRAPPED_KEY
This must be explicitly set, and set to 0, to avoid generating a wrapped key.
@ BSL_SECPARAM_TYPE_INT_KEY_ID
Used to pass in a key id found in the key registry.
@ BSL_SECPARAM_TYPE_INT_FIXED_KEY
Used by tests to pass in a specific key bytestring.
#define BSL_LOG_INFO(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
#define BSL_LOG_WARNING(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
#define BSL_LOG_ERR(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
@ BSL_ERR_NOT_IMPLEMENTED
Requested functionality not yet implemented.
@ BSL_ERR_ENCODING
CBOR encoding failure.
@ BSL_ERR_SECURITY_CONTEXT_FAILED
Security Context errors start at 200.
@ BSL_ERR_INSUFFICIENT_SPACE
Insufficient space to complete.
@ BSL_SUCCESS
Placeholder for non-error code.
@ BSL_ERR_HOST_CALLBACK_FAILED
Callback to the host BPA returned a non-zero code.
int BSL_Crypto_GenIV(void *buf, int size)
Generate initialization vector (IV) for AES-GCM for BCBs.
int BSL_Cipher_AddData(BSL_Cipher_t *cipher_ctx, BSL_Data_t plaintext, BSL_Data_t ciphertext)
int BSLB_Crypto_GetRegistryKey(uint64_t keyid, const uint8_t **secret, size_t *secret_len)
Get pointers to an existing key, if present.
int BSL_Cipher_Init(BSL_Cipher_t *cipher_ctx, BSL_CipherMode_e enc, BSL_CryptoCipherAESVariant_e aes_var, const void *init_vec, int iv_len, BSL_Data_t content_enc_key)
Initialize crypto context resources and set as encoding or decoding.
int BSL_Crypto_WrapKey(BSL_Data_t *wrapped_key, BSL_Data_t cek, size_t content_key_id, size_t aes_variant)
int BSL_Cipher_Deinit(BSL_Cipher_t *cipher_ctx)
De-initialize crypto context resources.
int BSL_Cipher_AddAAD(BSL_Cipher_t *cipher_ctx, const void *aad, int aad_len)
Add additional authenticated data (AAD) to cipher context.
int BSL_Crypto_UnwrapKey(BSL_Data_t *unwrapped_key_output, BSL_Data_t wrapped_key_plaintext, size_t key_id, size_t aes_variant)
int BSL_Cipher_SetTag(BSL_Cipher_t *cipher_ctx, const void *tag)
Set the tag of the crypto operation.
int BSL_Cipher_GetTag(BSL_Cipher_t *cipher_ctx, void **tag)
Get the tag of the crypto operation.
Abstract interface for crypto processing.
@ BSL_CRYPTO_ENCRYPT
We use undefined for zero, in case this value is never explicitly set and is just zero by default.
Header for the implementation of an example default security context (RFC 9173).
Contains functions only used internally, however, test utilities can include this to unit test them.
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_ReallocBTSD(BSL_BundleRef_t *bundle, uint64_t block_num, size_t bytesize)
Requests the re-allocation of a block's BTSD, useful for BCB.
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.
uint64_t BSL_SecOper_GetSecurityBlockNum(const BSL_SecOper_t *self)
Get the block number of the security block containing this sec operation.
uint64_t BSL_SecOper_GetTargetBlockNum(const BSL_SecOper_t *self)
Get the block number of the target block covered by this security operation.
size_t BSL_SecOper_CountParams(const BSL_SecOper_t *self)
Get the count of parameters contained within this security operation.
const BSL_SecParam_t * BSL_SecOper_GetParamAt(const BSL_SecOper_t *self, size_t index)
Returns a pointer to the Security Parameter at a given index in the list of all paramters.
bool BSL_SecOper_IsRoleSource(const BSL_SecOper_t *self)
Return true if this security operation's role is SOURCE.
bool BSL_SecOper_IsRoleAccepter(const BSL_SecOper_t *self)
Return true if this security operation's role is Acceptor.
int BSL_SecParam_IsInt64(const BSL_SecParam_t *self)
Returns true when the value type is an integer.
int BSL_SecParam_GetAsBytestr(const BSL_SecParam_t *self, BSL_Data_t *result)
Retrieve bytestring value of result when security parameter type is bytestring.
uint64_t BSL_SecParam_GetId(const BSL_SecParam_t *self)
Get parameter ID of this param.
uint64_t BSL_SecParam_GetAsUInt64(const BSL_SecParam_t *self)
Retrieve integer value of result when this result type is integer.
int BSL_SecResult_Init(BSL_SecResult_t *self, uint64_t result_id, uint64_t context_id, uint64_t target_block_num, BSL_Data_t content)
Populate a pre-allocated SecResult.
size_t BSL_SecResult_Sizeof(void)
Returns size in bytes of BSL_SecResult_t.
int BSL_Data_Resize(BSL_Data_t *data, size_t len)
Resize the data, copying if necessary.
int BSL_Data_Deinit(BSL_Data_t *data)
De-initialize a data struct, freeing if necessary.
int BSL_Data_InitBuffer(BSL_Data_t *data, size_t bytelen)
Initialize with an owned buffer of size bytelen.
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.
Contains constants as defined in IETF RFC 9173 (Default Security Context for BPSec)
@ RFC9173_BCB_RESULTID_AUTHTAG
https://www.rfc-editor.org/rfc/rfc9173.html#name-bcb-aes-gcm-security-result
BCB encryption context with crypto primitives.
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.
Struct def for cipher operation context.
Heap data storage and views.
size_t len
Size of the data buffer.
BSL_DataPtr_t ptr
Pointer to the front of the buffer.
Concrete definition of library context.
size_t block_count
Helpful count of total canonical blocks in bundle, not a field of the header.