diff --git a/include/cel_parse.h b/include/cel_parse.h index 3a9023b..fa2e9b6 100644 --- a/include/cel_parse.h +++ b/include/cel_parse.h @@ -48,4 +48,11 @@ CEL_Parse_IMA_TEMPLATE_Event( size_t len, size_t *offset); +CEL_RC +CEL_Parse_SYSTEMD_Event( + CEL_PARSE_CONTEXT *ctx, + TPMS_CEL_EVENT *event, + const uint8_t *buffer, + size_t len, + size_t *offset); #endif diff --git a/include/cel_types.h b/include/cel_types.h index d681dd2..65a7b4c 100644 --- a/include/cel_types.h +++ b/include/cel_types.h @@ -29,6 +29,7 @@ typedef BYTE CEL_TYPE; #define CEL_TYPE_PCCLIENT_STD 5 #define CEL_TYPE_IMA_TEMPLATE 7 #define CEL_TYPE_IMA_TLV 8 +#define CEL_TYPE_SYSTEMD 11 #define CEL_TYPE_MGMT_CEL_VERSION 1 #define CEL_TYPE_MGMT_FIRMWARE_END 2 @@ -48,7 +49,18 @@ typedef BYTE CEL_TYPE; #define CEL_STATE_TRANS_HIBERNATE 1 #define CEL_STATE_TRANS_KEXEC 2 +#define CEL_TYPE_SYSTEMD_EVENT_TYPE 0 +#define CEL_TYPE_SYSTEMD_TIMESTAMP 1 +#define CEL_TYPE_SYSTEMD_BOOT_ID 2 +#define CEL_TYPE_SYSTEMD_STRING 3 + +#define CEL_TYPE_SYSTEMD_EVENT_PHASE 0 +#define CEL_TYPE_SYSTEMD_EVENT_FILESYSTEM 1 +#define CEL_TYPE_SYSTEMD_EVENT_VOLUME_KEY 2 +#define CEL_TYPE_SYSTEMD_EVENT_MACHINE_ID 3 + typedef CEL_TYPE TPMI_CEL_CONTENT_TYPE; +typedef CEL_TYPE TPMI_SYSTEMD_EVENTS; typedef UINT32 TPMI_PC_CLIENT_EVENTS; typedef UINT64 RECNUM; @@ -99,12 +111,21 @@ struct TPML_EVENT_CELMGT { TPMS_EVENT_CELMGT events[16]; }; +typedef struct TPMS_EVENT_SYSTEMD TPMS_EVENT_SYSTEMD; +struct TPMS_EVENT_SYSTEMD { + TPMI_SYSTEMD_EVENTS event_type; + UINT64 timestamp; + BYTE boot_id[16]; + BYTEBUFFER string; +}; + typedef union TPMU_EVENT_CONTENT TPMU_EVENT_CONTENT; union TPMU_EVENT_CONTENT { TPML_EVENT_CELMGT celmgt; TPMS_EVENT_PCCLIENT_STD pcclient_std; TPMS_EVENT_IMA_TEMPLATE ima_template; IMA_TLV ima_tlv; + TPMS_EVENT_SYSTEMD systemd; }; typedef struct TPMS_CEL_EVENT TPMS_CEL_EVENT; diff --git a/include/meson.build b/include/meson.build index 2018c43..252a521 100644 --- a/include/meson.build +++ b/include/meson.build @@ -1,8 +1,5 @@ # Copyright (c) 2022 by Erik Larsson # SPDX-License-Identifier: GPL-3.0-or-later -headers = ['cel_types.h', 'cel_parse.h', 'cel_tlv.h'] -if json_dep.found() - headers += 'cel_json.h' -endif +headers = ['cel_types.h', 'cel_parse.h', 'cel_tlv.h', 'cel_json.h'] install_headers(headers, subdir: 'cel') diff --git a/meson.build b/meson.build index fdfb066..81d8ced 100644 --- a/meson.build +++ b/meson.build @@ -7,10 +7,8 @@ project( license: 'GPL3', default_options : ['warning_level=3'] ) -dependencies = [dependency('tss2-mu')] -json_dep = dependency('json-c') -test_dep = [dependency('cmocka'), dependency('libcrypto')] -json_test_dep = [dependency('cmocka'), dependency('json-c')] +dependencies = [dependency('tss2-mu'), dependency('json-c')] +test_dep = [dependency('cmocka'), dependency('libcrypto'), dependency('json-c')] inc = include_directories('include') diff --git a/src/cel_json_utils.c b/src/cel_json_utils.c new file mode 100644 index 0000000..f0c1916 --- /dev/null +++ b/src/cel_json_utils.c @@ -0,0 +1,212 @@ +/* Copyright (c) 2024 by Erik Larsson + SPDX-License-Identifier: GPL-3.0-or-later +*/ + +#include +#include +#include +#include "cel_types.h" +#include "cel_strings.h" +#include "cel_io.h" + +CEL_RC +get_json_number( + const json_object *obj, + const char *key, + uint64_t *dest) +{ + json_object *ji = NULL; + + CHECK_NULL(obj); + CHECK_NULL(key); + CHECK_NULL(dest); + + ji = json_object_object_get(obj, key); + if (!ji) { + return CEL_RC_INVALID_VALUE; + } + + if (!json_object_is_type(ji, json_type_int)) { + return CEL_RC_INVALID_TYPE; + } + + *dest = json_object_get_uint64(ji); + return CEL_RC_SUCCESS; +} + +CEL_RC +get_json_handle( + const json_object *obj, + TPM2_HANDLE *dest) +{ + uint64_t ti; + json_object *ji = NULL; + + CHECK_NULL(obj); + CHECK_NULL(dest); + + if (!json_object_object_get_ex(obj, "pcr", &ji) && + !json_object_object_get_ex(obj, "nv_index", &ji)) { + return CEL_RC_INVALID_VALUE; + } + + if (!json_object_is_type(ji, json_type_int)) { + return CEL_RC_INVALID_TYPE; + } + + ti = json_object_get_uint64(ji); + if (ti > UINT32_MAX) { + return CEL_RC_INVALID_VALUE; + } + + *dest = ti; + return CEL_RC_SUCCESS; +} + +CEL_RC +get_json_bytebuffer( + const json_object *obj, + const char *key, + BYTEBUFFER *dest) +{ + int hasit; + json_object *js = NULL; + const char *ts = NULL; + size_t sl = 0; + + hasit = json_object_object_get_ex(obj, key, &js); + if (!hasit) { + return CEL_RC_INVALID_VALUE; + } + + if (!json_object_is_type(js, json_type_string)) { + return CEL_RC_INVALID_TYPE; + } + ts = json_object_get_string(js); + if (!ts) { + return CEL_RC_INVALID_TYPE; + } + + sl = strlen(ts); + if (sl > sizeof(dest->buffer)) { + return CEL_RC_SHORT_BUFFER; + } + + memcpy(dest->buffer, ts, sl); + dest->size = sl; + + return CEL_RC_SUCCESS; +} + +CEL_RC +get_json_hex_string_full( + const json_object *obj, + const char *key, + uint8_t *dest, + size_t len) +{ + CEL_RC r; + int hasit; + json_object *js = NULL; + const char *ts = NULL; + int expected_len = len * 2; + + hasit = json_object_object_get_ex(obj, key, &js); + if (!hasit) { + return CEL_RC_INVALID_VALUE; + } + + if (!json_object_is_type(js, json_type_string)) { + return CEL_RC_INVALID_TYPE; + } + if (json_object_get_string_len(js) != expected_len) { + return CEL_RC_INVALID_VALUE; + } + ts = json_object_get_string(js); + if (!ts) { + return CEL_RC_INVALID_TYPE; + } + + r = unhexlify(ts, dest, len); + return r; +} + +CEL_RC +get_json_content_type( + const json_object *obj, + CEL_TYPE *dest) +{ + CEL_RC r; + int hasit; + json_object *jt = NULL; + const char *ts = NULL; + uint64_t ti = 0; + + hasit = json_object_object_get_ex(obj, "content_type", &jt); + if (!hasit) { + return CEL_RC_INVALID_VALUE; + } + + switch (json_object_get_type(jt)) { + case json_type_int: + ti = json_object_get_uint64(jt); + if (ti > UINT8_MAX) { + return CEL_RC_INVALID_VALUE; + } + *dest = ti; + break; + case json_type_string: + ts = json_object_get_string(jt); + r = str_to_content_type(ts, dest); + if (r) { + return r; + } + break; + default: + return CEL_RC_INVALID_TYPE; + } + + return CEL_RC_SUCCESS; +} + +CEL_RC +put_json_hex_string( + json_object *obj, + const char *key, + const uint8_t *src, + size_t len) +{ + CEL_RC r; + int jr; + char *buf; + size_t buflen = (len * 2) + 1; + json_object *jf = NULL; + + buf = malloc(buflen); + if (!buf) { + return CEL_RC_MEMORY; + } + + r = hexlify(src, len, buf, buflen); + if (r) { + goto out; + } + + jf = json_object_new_string(buf); + if (!jf) { + r = CEL_RC_MEMORY; + goto out; + } + + jr = json_object_object_add(obj, key, jf); + if (jr) { + r = CEL_RC_MEMORY; + json_object_put(jf); + goto out; + } + + r = CEL_RC_SUCCESS; + out: + free(buf); + return r; +} diff --git a/src/cel_json_utils.h b/src/cel_json_utils.h new file mode 100644 index 0000000..3e5ae21 --- /dev/null +++ b/src/cel_json_utils.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2024 by Erik Larsson + SPDX-License-Identifier: GPL-3.0-or-later +*/ + +#include +#include "cel_types.h" + +#ifndef _CEL_JSON_UTILS_H_ +#define _CEL_JSON_UTILS_H_ + +CEL_RC +get_json_number( + const json_object *obj, + const char *key, + uint64_t *dest); + +CEL_RC +get_json_handle( + const json_object *obj, + TPM2_HANDLE *dest); + +CEL_RC +get_json_bytebuffer( + const json_object *obj, + const char *key, + BYTEBUFFER *dest); + +CEL_RC +get_json_hex_string_full( + const json_object *obj, + const char *key, + uint8_t *dest, + size_t len); + +CEL_RC +get_json_content_type( + const json_object *obj, + CEL_TYPE *dest); + +CEL_RC +put_json_hex_string( + json_object *obj, + const char *key, + const uint8_t *src, + size_t len); + +#endif diff --git a/src/cel_strings.c b/src/cel_strings.c index 7486d9f..0fb2cf9 100644 --- a/src/cel_strings.c +++ b/src/cel_strings.c @@ -199,6 +199,10 @@ struct { .type = CEL_TYPE_IMA_TLV, .typestr = "ima_tlv", }, + { + .type = CEL_TYPE_SYSTEMD, + .typestr = "systemd", + }, { .type = 0, .typestr = NULL, @@ -253,6 +257,32 @@ struct { }, }; +struct { + TPMI_SYSTEMD_EVENTS type; + const char *typestr; +} systemd_event_str[] = { + { + .type = CEL_TYPE_SYSTEMD_EVENT_PHASE, + .typestr = "phase", + }, + { + .type = CEL_TYPE_SYSTEMD_EVENT_FILESYSTEM, + .typestr = "filesystem", + }, + { + .type = CEL_TYPE_SYSTEMD_EVENT_VOLUME_KEY, + .typestr = "volume-key", + }, + { + .type = CEL_TYPE_SYSTEMD_EVENT_MACHINE_ID, + .typestr = "machine-id", + }, + { + .type = 0xFF, + .typestr = NULL, + } +}; + const char * alg_to_str(TPM2_ALG_ID alg) { for (int i=0;alg_str[i].alg != TPM2_ALG_ERROR;i++) { @@ -401,3 +431,25 @@ str_to_state_trans(const char *str, TPMI_STATE_TRANS *dest) { } return CEL_RC_INVALID_VALUE; } + +const char * +systemd_event_to_str(TPMI_SYSTEMD_EVENTS event_type) { + for (int i=0;systemd_event_str[i].typestr != NULL;i++) { + if (systemd_event_str[i].type == event_type) { + return systemd_event_str[i].typestr; + } + } + + return NULL; +} + +CEL_RC +str_to_systemd_event(const char *str, TPMI_SYSTEMD_EVENTS *dest) { + for (int i=0;systemd_event_str[i].typestr != NULL;i++) { + if (!strcasecmp(str, systemd_event_str[i].typestr)) { + *dest = systemd_event_str[i].type; + return CEL_RC_SUCCESS; + } + } + return CEL_RC_INVALID_TYPE; +} diff --git a/src/cel_strings.h b/src/cel_strings.h index 4e5c520..f747bab 100644 --- a/src/cel_strings.h +++ b/src/cel_strings.h @@ -45,5 +45,11 @@ state_trans_to_str(CEL_TYPE trans); CEL_RC str_to_state_trans(const char *str, TPMI_STATE_TRANS *dest); +const char * +systemd_event_to_str(TPMI_SYSTEMD_EVENTS event_type); + +CEL_RC +str_to_systemd_event(const char *str, TPMI_SYSTEMD_EVENTS *dest); + #define _CEL_STRINGS_H_ #endif diff --git a/src/json.c b/src/json.c index f8e8c68..a9802d1 100644 --- a/src/json.c +++ b/src/json.c @@ -9,7 +9,7 @@ #include "cel_types.h" #include "cel_json.h" #include "cel_io.h" - +#include "cel_json_utils.h" CEL_RC CEL_JSON_TPMT_HA_Marshal( @@ -20,8 +20,8 @@ CEL_JSON_TPMT_HA_Marshal( CEL_RC r; int jr; size_t diglen = 0; - const char *algstr = NULL; char hexdig[MAX_DIGEST_HEX + 1]; - json_object *jd = NULL, *ja = NULL, *jh = NULL; + const char *algstr = NULL; + json_object *jd = NULL, *ja = NULL; CHECK_NULL(src); CHECK_NULL(obj); @@ -58,22 +58,11 @@ CEL_JSON_TPMT_HA_Marshal( r = CEL_RC_UNSUPPORTED_DIGEST; goto fail; } - r = hexlify(src->digest.sha512, diglen, hexdig, MAX_DIGEST_HEX + 1); + r = put_json_hex_string(jd, "digest", src->digest.sha512, diglen); if (r) { goto fail; } - jh = json_object_new_string(hexdig); - if (!jh) { - r = CEL_RC_MEMORY; - goto fail; - } - r = json_object_object_add(jd, "digest", jh); - if (r) { - r = CEL_RC_MEMORY; - goto fail; - } - *obj = jd; return CEL_RC_SUCCESS; fail: @@ -127,8 +116,6 @@ CEL_JSON_TPMS_EVENT_PCCLIENT_STD_Marshal( CEL_RC r; int jr; const char *event_str = NULL; - char *eventhex = NULL; - size_t hexlen = 0; json_object *je = NULL, *jf = NULL;; CHECK_NULL(src); @@ -160,37 +147,17 @@ CEL_JSON_TPMS_EVENT_PCCLIENT_STD_Marshal( goto fail; } - hexlen = (src->event_data.size * 2) + 1; - eventhex = malloc(hexlen); - if (!eventhex) { - r = CEL_RC_MEMORY; - goto fail; - } - - r = hexlify(src->event_data.buffer, - src->event_data.size, - eventhex, hexlen); + r = put_json_hex_string(je, + "event_data", + src->event_data.buffer, + src->event_data.size); if (r) { goto fail; } - jf = json_object_new_string(eventhex); - if (!jf) { - r = CEL_RC_MEMORY; - goto fail; - } - - jr = json_object_object_add(je, "event_data", jf); - if (jr) { - r = CEL_RC_MEMORY; - goto fail; - } - - free(eventhex); *obj = je; return CEL_RC_SUCCESS; fail: - free(eventhex); json_object_put(je); return r; } @@ -202,8 +169,6 @@ CEL_JSON_TPMS_EVENT_IMA_TEMPLATE_Marshal( { CEL_RC r; int jr; - char *datahex = NULL; - size_t hexlen; json_object *jt = NULL, *jf = NULL; CHECK_NULL(src); @@ -227,35 +192,17 @@ CEL_JSON_TPMS_EVENT_IMA_TEMPLATE_Marshal( goto fail; } - hexlen = (src->template_data.size * 2) + 1; - datahex = malloc(hexlen); - if (!datahex) { - r = CEL_RC_MEMORY; - goto fail; - } - r = hexlify(src->template_data.buffer, - src->template_data.size, - datahex, - hexlen); + r = put_json_hex_string(jt, + "template_data", + src->template_data.buffer, + src->template_data.size); if (r) { goto fail; } - jf = json_object_new_string(datahex); - if (!jf) { - r = CEL_RC_MEMORY; - goto fail; - } - free(datahex); - jr = json_object_object_add(jt, "template_data", jf); - if (jr) { - r = CEL_RC_MEMORY; - goto fail; - } *obj = jt; return CEL_RC_SUCCESS; fail: - free(datahex); json_object_put(jt); return r; } @@ -447,6 +394,81 @@ CEL_JSON_TPML_EVENT_CELMGT_Marshal( return r; } +CEL_RC +CEL_JSON_TPMS_EVENT_SYSTEMD_Marshal( + const TPMS_EVENT_SYSTEMD *src, + json_object **obj, + CEL_JSON_FLAGS flags) +{ + CEL_RC r; + int jr; + const char *event_str = NULL; + json_object *je = NULL, *jf = NULL; + + CHECK_NULL(src); + CHECK_NULL(obj); + + je = json_object_new_object(); + if (!je) { + r = CEL_RC_MEMORY; + goto fail; + } + + if (flags & CEL_JSON_FLAGS_USE_NUMBERS) { + jf = json_object_new_uint64(src->event_type); + } else { + event_str = systemd_event_to_str(src->event_type); + if (!event_str) { + r = CEL_RC_INVALID_TYPE; + goto fail; + } + jf = json_object_new_string(event_str); + } + if (!jf) { + r = CEL_RC_MEMORY; + goto fail; + } + jr = json_object_object_add(je, "event_type", jf); + if (jr) { + r = CEL_RC_MEMORY; + goto fail; + } + + jf = json_object_new_string_len((const char *) src->string.buffer, + src->string.size); + if (!jf) { + r = CEL_RC_MEMORY; + goto fail; + } + jr = json_object_object_add(je, "string", jf); + if (jr) { + r = CEL_RC_MEMORY; + goto fail; + } + + r = put_json_hex_string(je, "bootId", src->boot_id, sizeof(src->boot_id)); + if (r) { + goto fail; + } + + jf = json_object_new_uint64(src->timestamp); + if (!jf) { + r = CEL_RC_MEMORY; + goto fail; + } + jr = json_object_object_add(je, "timestamp", jf); + if (jr) { + r = CEL_RC_MEMORY; + goto fail; + } + + *obj = je; + return CEL_RC_SUCCESS; + fail: + json_object_put(je); + return r; +} + CEL_RC CEL_JSON_TPMS_CEL_EVENT_Marshal( const TPMS_CEL_EVENT *src, @@ -541,6 +563,9 @@ CEL_JSON_TPMS_CEL_EVENT_Marshal( case CEL_TYPE_IMA_TEMPLATE: r = CEL_JSON_TPMS_EVENT_IMA_TEMPLATE_Marshal(&cont->ima_template, &jf); break; + case CEL_TYPE_SYSTEMD: + r = CEL_JSON_TPMS_EVENT_SYSTEMD_Marshal(&cont->systemd, &jf, flags); + break; default: r = CEL_RC_INVALID_TYPE; } @@ -561,60 +586,6 @@ CEL_JSON_TPMS_CEL_EVENT_Marshal( return r; } -CEL_RC -get_json_number( - const json_object *obj, - const char *key, - uint64_t *dest) -{ - json_object *ji = NULL; - - CHECK_NULL(obj); - CHECK_NULL(key); - CHECK_NULL(dest); - - ji = json_object_object_get(obj, key); - if (!ji) { - return CEL_RC_INVALID_VALUE; - } - - if (!json_object_is_type(ji, json_type_int)) { - return CEL_RC_INVALID_TYPE; - } - - *dest = json_object_get_uint64(ji); - return CEL_RC_SUCCESS; -} - -CEL_RC -get_json_handle( - const json_object *obj, - TPM2_HANDLE *dest) -{ - uint64_t ti; - json_object *ji = NULL; - - CHECK_NULL(obj); - CHECK_NULL(dest); - - if (!json_object_object_get_ex(obj, "pcr", &ji) && - !json_object_object_get_ex(obj, "nv_index", &ji)) { - return CEL_RC_INVALID_VALUE; - } - - if (!json_object_is_type(ji, json_type_int)) { - return CEL_RC_INVALID_TYPE; - } - - ti = json_object_get_uint64(ji); - if (ti > UINT32_MAX) { - return CEL_RC_INVALID_VALUE; - } - - *dest = ti; - return CEL_RC_SUCCESS; -} - CEL_RC CEL_JSON_TPMT_HA_Unmarshal( const json_object *obj, @@ -1002,42 +973,34 @@ CEL_JSON_TPMS_EVENT_IMA_TEMPLATE_Unmarshal( } CEL_RC -CEL_JSON_TPMS_CEL_EVENT_Unmarshal( +CEL_JSON_TPMS_EVENT_SYSTEMD_Unmarshal( const json_object *obj, - TPMS_CEL_EVENT *dest) + TPMS_EVENT_SYSTEMD *dest) { CEL_RC r; int hasit; - uint64_t ti; + json_object *jt = NULL; const char *ts = NULL; - json_object *jd = NULL, *jt = NULL, *jc = NULL; - TPMU_EVENT_CONTENT *cont = NULL; - - CHECK_NULL(obj); - CHECK_NULL(dest); - cont = &dest->content; + uint64_t ti = -1; - r = get_json_number(obj, "recnum", &dest->recnum); + r = get_json_bytebuffer(obj, "string", &dest->string); if (r) { return r; } - r = get_json_handle(obj, &dest->handle); + r = get_json_hex_string_full(obj, + "bootId", (uint8_t *) &dest->boot_id, + sizeof(dest->boot_id)); if (r) { return r; } - hasit = json_object_object_get_ex(obj, "digests", &jd); - if (hasit) { - r = CEL_JSON_TPML_DIGEST_VALUES_Unmarshal(jd, &dest->digests); - if (r) { - return r; - } - } else { - dest->digests.count = 0; + r = get_json_number(obj, "timestamp", &dest->timestamp); + if (r) { + return r; } - hasit = json_object_object_get_ex(obj, "content_type", &jt); + hasit = json_object_object_get_ex(obj, "eventType", &jt); if (!hasit) { return CEL_RC_INVALID_VALUE; } @@ -1048,11 +1011,14 @@ CEL_JSON_TPMS_CEL_EVENT_Unmarshal( if (ti > UINT8_MAX) { return CEL_RC_INVALID_VALUE; } - dest->content_type = ti; + if (!systemd_event_to_str(ti)) { + return CEL_RC_INVALID_TYPE; + } + dest->event_type = ti; break; case json_type_string: ts = json_object_get_string(jt); - r = str_to_content_type(ts, &dest->content_type); + r = str_to_systemd_event(ts, &dest->event_type); if (r) { return r; } @@ -1061,6 +1027,48 @@ CEL_JSON_TPMS_CEL_EVENT_Unmarshal( return CEL_RC_INVALID_TYPE; } + return CEL_RC_SUCCESS; +} + +CEL_RC +CEL_JSON_TPMS_CEL_EVENT_Unmarshal( + const json_object *obj, + TPMS_CEL_EVENT *dest) +{ + CEL_RC r; + int hasit; + json_object *jd = NULL, *jc = NULL; + TPMU_EVENT_CONTENT *cont = NULL; + + CHECK_NULL(obj); + CHECK_NULL(dest); + cont = &dest->content; + + r = get_json_number(obj, "recnum", &dest->recnum); + if (r) { + return r; + } + + r = get_json_handle(obj, &dest->handle); + if (r) { + return r; + } + + hasit = json_object_object_get_ex(obj, "digests", &jd); + if (hasit) { + r = CEL_JSON_TPML_DIGEST_VALUES_Unmarshal(jd, &dest->digests); + if (r) { + return r; + } + } else { + dest->digests.count = 0; + } + + r = get_json_content_type(obj, &dest->content_type); + if (r) { + return r; + } + hasit = json_object_object_get_ex(obj, "content", &jc); if (!hasit) { return CEL_RC_INVALID_VALUE; @@ -1076,6 +1084,9 @@ CEL_JSON_TPMS_CEL_EVENT_Unmarshal( case CEL_TYPE_IMA_TEMPLATE: r = CEL_JSON_TPMS_EVENT_IMA_TEMPLATE_Unmarshal(jc, &cont->ima_template); break; + case CEL_TYPE_SYSTEMD: + r = CEL_JSON_TPMS_EVENT_SYSTEMD_Unmarshal(jc, &cont->systemd); + break; default: return CEL_RC_INVALID_TYPE; } diff --git a/src/meson.build b/src/meson.build index 242e355..12e4cd5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,12 +1,6 @@ pkg = import('pkgconfig') -cel_sources = ['parse.c', 'cel_io.c', 'tlv.c'] +cel_sources = ['parse.c', 'cel_io.c', 'tlv.c', 'cel_strings.c', 'json.c', 'cel_json_utils.c'] cel_lib = shared_library('cel', cel_sources, include_directories: inc, dependencies: dependencies, install: true) pkg.generate(cel_lib) - -if json_dep.found() - cel_json_sources = ['json.c', 'cel_io.c', 'cel_strings.c'] - cel_json_lib = shared_library('cel-json', cel_json_sources, include_directories: inc, dependencies: dependencies + json_dep, install: true) - pkg.generate(cel_json_lib) -endif diff --git a/src/parse.c b/src/parse.c index 16e68f0..dfa6825 100644 --- a/src/parse.c +++ b/src/parse.c @@ -5,10 +5,25 @@ #include #include #include +#include +#include #include "cel_types.h" #include "cel_io.h" +#include "cel_json_utils.h" +/* needed for systemd parsing */ +CEL_RC +CEL_JSON_TPML_DIGEST_VALUES_Unmarshal( + const json_object *obj, + TPML_DIGEST_VALUES *dest); + +/* needed for systemd parsing */ +CEL_RC +CEL_JSON_TPMS_EVENT_SYSTEMD_Unmarshal( + const json_object *obj, + TPMS_EVENT_SYSTEMD *dest); + struct pair_entry { TPM2_HANDLE handle; RECNUM recnum; @@ -137,7 +152,10 @@ CEL_Parse_UEFI_Event( return r; } - r = get_le_uint32(buffer, len, &off, &event->content.pcclient_std.event_type); + r = get_le_uint32(buffer, + len, + &off, + &event->content.pcclient_std.event_type); if (r) { return r; } @@ -302,3 +320,88 @@ CEL_Parse_IMA_TEMPLATE_Event( return CEL_RC_SUCCESS; } + +CEL_RC +CEL_Parse_SYSTEMD_Event( + CEL_PARSE_CONTEXT *ctx, + TPMS_CEL_EVENT *event, + const uint8_t *buffer, + size_t len, + size_t *offset) +{ + CEL_RC r; + size_t off = get_offset(offset); + int hasit; + struct json_tokener *jtok = NULL; + json_object *obj = NULL, *jd = NULL, *jc = NULL; + + CHECK_NULL(ctx); + CHECK_NULL(event); + CHECK_NULL(buffer); + + jtok = json_tokener_new(); + if (!jtok) { + return CEL_RC_MEMORY; + } + obj = json_tokener_parse_ex(jtok, (const char *) &buffer[off], len - off); + if (!obj) { + r = CEL_RC_INVALID_VALUE; + goto out; + } + + if (!json_object_is_type(obj, json_type_object)) { + r = CEL_RC_INVALID_TYPE; + goto out; + } + + r = get_json_content_type(obj, &event->content_type); + if (r) { + goto out; + } + + if (event->content_type != CEL_TYPE_SYSTEMD) { + r = CEL_RC_INVALID_TYPE; + goto out; + } + + r = get_json_handle(obj, &event->handle); + if (r) { + goto out; + } + + hasit = json_object_object_get_ex(obj, "digests", &jd); + if (!hasit) { + r = CEL_RC_INVALID_VALUE; + goto out; + } + r = CEL_JSON_TPML_DIGEST_VALUES_Unmarshal(jd, &event->digests); + if (r) { + goto out; + } + + hasit = json_object_object_get_ex(obj, "content", &jc); + if (!hasit) { + r = CEL_RC_INVALID_VALUE; + goto out; + } + + r = CEL_JSON_TPMS_EVENT_SYSTEMD_Unmarshal(jc, &event->content.systemd); + if (r) { + goto out; + } + + r = CEL_Parse_Get_RECNUM(ctx, event->handle, &event->recnum); + if (r) { + goto out; + } + + off = json_tokener_get_parse_end(jtok) + off; + set_offset(offset, off); + + r = CEL_RC_SUCCESS; + out: + if (jtok) { + json_tokener_free(jtok); + } + return r; +} diff --git a/src/tlv.c b/src/tlv.c index 6f5e37e..0108cee 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -508,6 +508,90 @@ CEL_TLV_TPMS_EVENT_IMA_TEMPLATE_Marshal( return CEL_RC_SUCCESS; } +CEL_RC +CEL_TLV_TPMS_EVENT_SYSTEMD_Marshal( + const TPMS_EVENT_SYSTEMD *src, + uint8_t *buffer, + size_t len, + size_t *offset) +{ + CEL_RC r; + size_t off = get_offset(offset), suboff = 0; + + CHECK_NULL(src); + + CEL_TLV_UINT64_Marshal(CEL_TYPE_SYSTEMD_EVENT_TYPE, + src->event_type, + NULL, + 0, + &suboff); + + CEL_TLV_UINT64_Marshal(CEL_TYPE_SYSTEMD_TIMESTAMP, + src->timestamp, + NULL, + 0, + &suboff); + + put_tlv(CEL_TYPE_SYSTEMD_BOOT_ID, + sizeof(src->boot_id), + src->boot_id, + NULL, + 0, + &suboff); + + CEL_TLV_BYTEBUFFER_Marshal(CEL_TYPE_SYSTEMD_STRING, + &src->string, + NULL, + 0, + &suboff); + + r = put_tlv(CEL_TYPE_SYSTEMD, suboff, NULL, buffer, len, &off); + if (r) { + return r; + } + + r = CEL_TLV_UINT64_Marshal(CEL_TYPE_SYSTEMD_EVENT_TYPE, + src->event_type, + buffer, + len, + &off); + if (r) { + return r; + } + + r= CEL_TLV_UINT64_Marshal(CEL_TYPE_SYSTEMD_TIMESTAMP, + src->timestamp, + buffer, + len, + &off); + if (r) { + return r; + } + + r = put_tlv(CEL_TYPE_SYSTEMD_BOOT_ID, + sizeof(src->boot_id), + src->boot_id, + buffer, + len, + &off); + if (r) { + return r; + } + + r = CEL_TLV_BYTEBUFFER_Marshal(CEL_TYPE_SYSTEMD_STRING, + &src->string, + buffer, + len, + &off); + if (r) { + return r; + } + + set_offset(offset, off); + + return CEL_RC_SUCCESS; +} + CEL_RC CEL_TLV_TPMS_CEL_EVENT_Marshal( const TPMS_CEL_EVENT *src, @@ -565,6 +649,12 @@ CEL_TLV_TPMS_CEL_EVENT_Marshal( len, &off); break; + case CEL_TYPE_SYSTEMD: + r = CEL_TLV_TPMS_EVENT_SYSTEMD_Marshal(&cont->systemd, + buffer, + len, + &off); + break; default: r = CEL_RC_INVALID_TYPE; } @@ -1252,6 +1342,128 @@ CEL_TLV_TPML_EVENT_CELMGT_Unmarshal( return CEL_RC_SUCCESS; } +CEL_RC +CEL_TLV_TPMS_EVENT_SYSTEMD_Unmarshal( + const uint8_t *buffer, + size_t len, + size_t *offset, + TPMS_EVENT_SYSTEMD *dest) +{ + CEL_RC r; + UINT32 sublen, boot_id_len; + size_t off = get_offset(offset), suboff = 0; + const uint8_t *subbuf = NULL; + CEL_TYPE type; + UINT64 ti; + int seen_event_type = 0, seen_string = 0, seen_timestamp = 0, + seen_boot_id = 0; + + CHECK_NULL(buffer); + CHECK_NULL(dest); + + r = get_tl_with_type(buffer, + len, + &off, + CEL_TYPE_SYSTEMD, + &sublen); + if (r) { + return r; + } + subbuf = buffer + off; + + while (suboff < sublen) { + r = peek_type(subbuf, sublen, &suboff, &type); + if (r) { + break; + } + if ( + (type == CEL_TYPE_SYSTEMD_EVENT_TYPE && seen_event_type) || + (type == CEL_TYPE_SYSTEMD_STRING && seen_string) || + (type == CEL_TYPE_SYSTEMD_TIMESTAMP && seen_timestamp) || + (type == CEL_TYPE_SYSTEMD_BOOT_ID && seen_boot_id)) + { + r = CEL_RC_INVALID_VALUE; + break; + } + switch (type) { + case CEL_TYPE_SYSTEMD_EVENT_TYPE: + r = CEL_TLV_UINT64_Unmarshal(subbuf, + sublen, + &suboff, + CEL_TYPE_SYSTEMD_EVENT_TYPE, + &ti); + if (r) { + break; + } + if (ti > UINT8_MAX) { + r = CEL_RC_INVALID_VALUE; + break; + } + dest->event_type = ti; + seen_event_type = 1; + break; + case CEL_TYPE_SYSTEMD_STRING: + r = CEL_TLV_BYTEBUFFER_Unmarshal(subbuf, + sublen, + &suboff, + CEL_TYPE_SYSTEMD_STRING, + &dest->string); + if (r) { + break; + } + seen_string = 1; + break; + case CEL_TYPE_SYSTEMD_TIMESTAMP: + r = CEL_TLV_UINT64_Unmarshal(subbuf, + sublen, + &suboff, + CEL_TYPE_SYSTEMD_TIMESTAMP, + &dest->timestamp); + if (r) { + break; + } + seen_timestamp = 1; + break; + case CEL_TYPE_SYSTEMD_BOOT_ID: + r = get_tl_with_type(subbuf, + sublen, + &suboff, + CEL_TYPE_SYSTEMD_BOOT_ID, + &boot_id_len); + if (r) { + break; + } + if (boot_id_len != sizeof(dest->boot_id)) { + r = CEL_RC_INVALID_VALUE; + break; + } + memcpy(dest->boot_id, subbuf + suboff, boot_id_len); + suboff += sizeof(dest->boot_id); + seen_boot_id = 1; + break; + default: + r = CEL_RC_INVALID_TYPE; + break; + } + if (r) { + break; + } + } + if (r) { + return r; + } + + if (!seen_event_type || !seen_string || !seen_timestamp || !seen_boot_id) { + return CEL_RC_INVALID_VALUE; + } + + off += suboff; + + set_offset(offset, off); + + return CEL_RC_SUCCESS; +} + CEL_RC CEL_TLV_TPMS_CEL_EVENT_Unmarshal( const uint8_t *buffer, @@ -1330,6 +1542,12 @@ CEL_TLV_TPMS_CEL_EVENT_Unmarshal( &off, &cont->ima_template); break; + case CEL_TYPE_SYSTEMD: + r = CEL_TLV_TPMS_EVENT_SYSTEMD_Unmarshal(buffer, + len, + &off, + &cont->systemd); + break; default: r = CEL_RC_INVALID_TYPE; break; diff --git a/test/data/systemd-seq.json b/test/data/systemd-seq.json new file mode 100644 index 0000000..c16341d --- /dev/null +++ b/test/data/systemd-seq.json @@ -0,0 +1,4 @@ +{"pcr": 1, "digests": [], "content_type": "systemd", "content": {"eventType": "phase", "bootId": "fa1afe1fa1afe1fa1afe1fa1afe1ffff", "timestamp": 1, "string": "phase-tahini"}} +{"pcr": 1, "digests": [], "content_type": "systemd", "content": {"eventType": "filesystem", "bootId": "fa1afe1fa1afe1fa1afe1fa1afe1ffff", "timestamp": 2, "string": "filesystem-tahini"}} +{"pcr": 1, "digests": [], "content_type": "systemd", "content": {"eventType": "machine-id", "bootId": "fa1afe1fa1afe1fa1afe1fa1afe1ffff", "timestamp": 3, "string": "machine-id-tahini"}} +{"pcr": 1, "digests": [], "content_type": "systemd", "content": {"eventType": "volume-key", "bootId": "fa1afe1fa1afe1fa1afe1fa1afe1ffff", "timestamp": 4, "string": "volume-key-tahini"}} diff --git a/test/data/systemd.json b/test/data/systemd.json new file mode 100644 index 0000000..7ee44c1 --- /dev/null +++ b/test/data/systemd.json @@ -0,0 +1,11 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": 2, + "string": "falafel", + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": 4000 + } +} diff --git a/test/data/systemd_bad_bootid.json b/test/data/systemd_bad_bootid.json new file mode 100644 index 0000000..5259ac7 --- /dev/null +++ b/test/data/systemd_bad_bootid.json @@ -0,0 +1,11 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": 0, + "string": "falafel", + "bootId": "tahini", + "timestamp": 4000 + } +} diff --git a/test/data/systemd_bad_event_type.json b/test/data/systemd_bad_event_type.json new file mode 100644 index 0000000..aeb0eb7 --- /dev/null +++ b/test/data/systemd_bad_event_type.json @@ -0,0 +1,11 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": 255, + "string": "falafel", + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": 4000 + } +} diff --git a/test/data/systemd_bad_event_type_json_type.json b/test/data/systemd_bad_event_type_json_type.json new file mode 100644 index 0000000..d9d5427 --- /dev/null +++ b/test/data/systemd_bad_event_type_json_type.json @@ -0,0 +1,11 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": [], + "string": "falafel", + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": 4000 + } +} diff --git a/test/data/systemd_bad_event_type_num.json b/test/data/systemd_bad_event_type_num.json new file mode 100644 index 0000000..d39e35e --- /dev/null +++ b/test/data/systemd_bad_event_type_num.json @@ -0,0 +1,11 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": 256, + "string": "falafel", + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": 4000 + } +} diff --git a/test/data/systemd_bad_event_type_str.json b/test/data/systemd_bad_event_type_str.json new file mode 100644 index 0000000..e429c38 --- /dev/null +++ b/test/data/systemd_bad_event_type_str.json @@ -0,0 +1,11 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": "falafel", + "string": "falafel", + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": 4000 + } +} diff --git a/test/data/systemd_bad_timestamp.json b/test/data/systemd_bad_timestamp.json new file mode 100644 index 0000000..c8fe184 --- /dev/null +++ b/test/data/systemd_bad_timestamp.json @@ -0,0 +1,11 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": 0, + "string": "falafel", + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": [] + } +} diff --git a/test/data/systemd_missing_event_type.json b/test/data/systemd_missing_event_type.json new file mode 100644 index 0000000..7eb178c --- /dev/null +++ b/test/data/systemd_missing_event_type.json @@ -0,0 +1,10 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "string": "falafel", + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": 4000 + } +} diff --git a/test/data/systemd_missing_string.json b/test/data/systemd_missing_string.json new file mode 100644 index 0000000..103b842 --- /dev/null +++ b/test/data/systemd_missing_string.json @@ -0,0 +1,10 @@ +{ + "recnum": 0, + "pcr": 3, + "content_type": "systemd", + "content": { + "eventType": 0, + "bootId": "fafafafafafafafafafafafafafafafa", + "timestamp": 4000 + } +} diff --git a/test/meson.build b/test/meson.build index f2cef63..1779119 100644 --- a/test/meson.build +++ b/test/meson.build @@ -4,10 +4,8 @@ tlv_exe = executable('test_tlv', 'test_tlv.c', include_directories: inc, link_with: cel_lib, dependencies: test_dep) test('tlv', tlv_exe) -if json_dep.found() - json_exe = executable('test_json', 'test_json.c', include_directories: inc, link_with: cel_json_lib, dependencies: json_test_dep) - test('json', json_exe, workdir: meson.current_source_dir()) -endif +json_exe = executable('test_json', 'test_json.c', include_directories: inc, link_with: cel_lib, dependencies: test_dep) +test('json', json_exe, workdir: meson.current_source_dir()) parse_exe = executable('test_parse', 'test_parse.c', include_directories: inc, link_with: cel_lib, dependencies: test_dep) test('parse', parse_exe, workdir: meson.current_source_dir()) diff --git a/test/test_json.c b/test/test_json.c index 794eeb3..02e503e 100644 --- a/test/test_json.c +++ b/test/test_json.c @@ -382,6 +382,9 @@ void test_json_bad_types(void **state) { event.content_type = 0xFF; r = CEL_JSON_TPMS_CEL_EVENT_Marshal(&event, &obj, 0); assert_int_equal(r, CEL_RC_INVALID_TYPE); + r = CEL_JSON_TPMS_CEL_EVENT_Marshal(&event, &obj, CEL_JSON_FLAGS_USE_NUMBERS); + assert_int_equal(r, CEL_RC_INVALID_TYPE); + event.content_type = CEL_TYPE_MGMT; event.content.celmgt.count = 1; @@ -953,6 +956,204 @@ void test_json_unmarshal_bad_event(void **state) { assert_int_equal(r, CEL_RC_BAD_REFERENCE); } +void test_json_systemd(void **state) { + (void) state; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event = { + .recnum = 1234, + .handle = 6, + .content_type = CEL_TYPE_SYSTEMD, + }; + + event.content.systemd.event_type = CEL_TYPE_SYSTEMD_EVENT_PHASE; + memcpy(event.content.systemd.string.buffer, "falafel", 7); + event.content.systemd.string.size = 7; + event.content.systemd.timestamp = 7843; + memset(event.content.systemd.boot_id, 0xFA, 16); + + r = CEL_JSON_TPMS_CEL_EVENT_Marshal(&event, &obj, 0); + assert_int_equal(r, CEL_RC_SUCCESS); + assert_non_null(obj); + + assert_json_string_equal(obj, "systemd", JSON_KEY, "content_type", JSON_VALUE); + assert_json_string_equal(obj, "falafel", JSON_KEY, "content", JSON_KEY, "string", JSON_VALUE); + assert_json_string_equal(obj, "fafafafafafafafafafafafafafafafa", JSON_KEY, "content", JSON_KEY, "bootId", JSON_VALUE); + assert_json_int_equal(obj, 7843, JSON_KEY, "content", JSON_KEY, "timestamp", JSON_INTEGER); + +} + +void test_json_systemd_numbers(void **state) { + (void) state; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event = { + .recnum = 1234, + .handle = 6, + .content_type = CEL_TYPE_SYSTEMD, + }; + + event.content.systemd.event_type = CEL_TYPE_SYSTEMD_EVENT_FILESYSTEM; + + r = CEL_JSON_TPMS_CEL_EVENT_Marshal(&event, &obj, CEL_JSON_FLAGS_USE_NUMBERS); + assert_int_equal(r, CEL_RC_SUCCESS); + assert_non_null(obj); + + assert_json_int_equal(obj, CEL_TYPE_SYSTEMD_EVENT_FILESYSTEM, JSON_KEY, "content", JSON_KEY, "event_type", JSON_INTEGER); + +} + +void test_json_systemd_bad_event_type(void **state) { + (void) state; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event = { + .recnum = 1234, + .handle = 6, + .content_type = CEL_TYPE_SYSTEMD, + }; + + event.content.systemd.event_type = 0xFF; + + r = CEL_JSON_TPMS_CEL_EVENT_Marshal(&event, &obj, 0); + assert_int_equal(r, CEL_RC_INVALID_TYPE); +} + +void test_json_systemd_unmarshal(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, 0); +} + +void test_json_systemd_unmarshal_bad_event_type(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_bad_event_type.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_TYPE); +} + +void test_json_systemd_unmarshal_bad_event_type_str(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_bad_event_type_str.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_TYPE); +} + +void test_json_systemd_unmarshal_bad_event_type_json_type(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_bad_event_type_json_type.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_TYPE); +} + +void test_json_systemd_unmarshal_bad_event_type_num(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_bad_event_type_num.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_json_systemd_unmarshal_bad_timestamp(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_bad_timestamp.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_TYPE); +} + +void test_json_systemd_unmarshal_missing_event_type(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_missing_event_type.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_json_systemd_unmarshal_missing_string(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_missing_string.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_json_systemd_unmarshal_bad_bootid(void **state) { + (void) state; + char data[2048]; + CEL_RC r; + json_object *obj = NULL; + TPMS_CEL_EVENT event; + + load_data("data/systemd_bad_bootid.json", data); + obj = json_tokener_parse(data); + assert_non_null(obj); + + r = CEL_JSON_TPMS_CEL_EVENT_Unmarshal(obj, &event); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + int main(int argc, char **argv) { (void) argc; @@ -982,6 +1183,18 @@ int main(int argc, char **argv) cmocka_unit_test(test_json_unmarshal_ima_template), cmocka_unit_test(test_json_unmarshal_bad_ima_template), cmocka_unit_test(test_json_unmarshal_bad_event), + cmocka_unit_test(test_json_systemd), + cmocka_unit_test(test_json_systemd_numbers), + cmocka_unit_test(test_json_systemd_bad_event_type), + cmocka_unit_test(test_json_systemd_unmarshal), + cmocka_unit_test(test_json_systemd_unmarshal_bad_event_type), + cmocka_unit_test(test_json_systemd_unmarshal_bad_event_type_str), + cmocka_unit_test(test_json_systemd_unmarshal_bad_event_type_json_type), + cmocka_unit_test(test_json_systemd_unmarshal_bad_event_type_num), + cmocka_unit_test(test_json_systemd_unmarshal_bad_timestamp), + cmocka_unit_test(test_json_systemd_unmarshal_missing_event_type), + cmocka_unit_test(test_json_systemd_unmarshal_missing_string), + cmocka_unit_test(test_json_systemd_unmarshal_bad_bootid), }; return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/test/test_parse.c b/test/test_parse.c index 3c44e59..6707f24 100644 --- a/test/test_parse.c +++ b/test/test_parse.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "cel_types.h" #include "cel_parse.h" @@ -75,6 +76,17 @@ int decode_file(const char *path, uint8_t **dest, size_t *dest_len) { return -1; } +void load_data(const char *name, uint8_t data[2048]) { + int r, fd; + + memset(data, 0, 2048); + fd = open(name, O_RDONLY); + assert_true(fd >= 0); + + r = read(fd, data, 2048); + assert_true(r > 0); +} + void test_parse_uefi(void **state) { struct data *data = *state; CEL_PARSE_CONTEXT *ctx = NULL; @@ -327,6 +339,126 @@ void test_parse_ima_short(void **state) { } +void test_parse_systemd(void **state) { + (void) state; + CEL_RC cr; + CEL_PARSE_CONTEXT *ctx = NULL; + TPMS_CEL_EVENT event; + uint8_t data[2048]; + size_t off = 0, sl = 0; + + load_data("data/systemd-seq.json", data); + sl = strlen((const char *) data); + + cr = CEL_Parse_Init(&ctx); + assert_int_equal(cr, 0); + + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, data, sl, &off); + assert_int_equal(cr, 0); + assert_int_equal(event.content_type, CEL_TYPE_SYSTEMD); + assert_int_equal(event.recnum, 0); + assert_int_equal(event.handle, 1); + assert_int_equal(event.content.systemd.timestamp, 1); + assert_int_equal(event.content.systemd.event_type, CEL_TYPE_SYSTEMD_EVENT_PHASE); + assert_memory_equal(event.content.systemd.boot_id, "\xfa\x1a\xfe\x1f\xa1\xaf\xe1\xfa\x1a\xfe\x1f\xa1\xaf\xe1\xff\xff", 16); + assert_memory_equal(event.content.systemd.string.buffer, "phase-tahini", event.content.systemd.string.size); + + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, data, sl, &off); + assert_int_equal(cr, 0); + assert_int_equal(event.content_type, CEL_TYPE_SYSTEMD); + assert_int_equal(event.recnum, 1); + assert_int_equal(event.handle, 1); + assert_int_equal(event.content.systemd.timestamp, 2); + assert_int_equal(event.content.systemd.event_type, CEL_TYPE_SYSTEMD_EVENT_FILESYSTEM); + assert_memory_equal(event.content.systemd.string.buffer, "filesystem-tahini", event.content.systemd.string.size); + + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, data, sl, &off); + assert_int_equal(cr, 0); + assert_int_equal(event.content_type, CEL_TYPE_SYSTEMD); + assert_int_equal(event.recnum, 2); + assert_int_equal(event.handle, 1); + assert_int_equal(event.content.systemd.timestamp, 3); + assert_int_equal(event.content.systemd.event_type, CEL_TYPE_SYSTEMD_EVENT_MACHINE_ID); + assert_memory_equal(event.content.systemd.string.buffer, "machine-id-tahini", event.content.systemd.string.size); + + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, data, sl, &off); + assert_int_equal(cr, 0); + assert_int_equal(event.content_type, CEL_TYPE_SYSTEMD); + assert_int_equal(event.recnum, 3); + assert_int_equal(event.handle, 1); + assert_int_equal(event.content.systemd.timestamp, 4); + assert_int_equal(event.content.systemd.event_type, CEL_TYPE_SYSTEMD_EVENT_VOLUME_KEY); + assert_memory_equal(event.content.systemd.string.buffer, "volume-key-tahini", event.content.systemd.string.size); + + assert_int_equal(off, sl); +} + +void test_parse_systemd_nulls(void **state) { + (void) state; + CEL_RC cr; + CEL_PARSE_CONTEXT *ctx = NULL; + TPMS_CEL_EVENT event; + + cr = CEL_Parse_SYSTEMD_Event(NULL, NULL, NULL, 0, NULL); + assert_int_equal(cr, CEL_RC_BAD_REFERENCE); + + cr = CEL_Parse_Init(&ctx); + assert_int_equal(cr, 0); + + cr = CEL_Parse_SYSTEMD_Event(ctx, NULL, NULL, 0, NULL); + assert_int_equal(cr, CEL_RC_BAD_REFERENCE); + + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, NULL, 0, NULL); + assert_int_equal(cr, CEL_RC_BAD_REFERENCE); + +} + +void test_parse_systemd_bad(void **state) { + (void) state; + CEL_RC cr; + CEL_PARSE_CONTEXT *ctx = NULL; + TPMS_CEL_EVENT event; + + cr = CEL_Parse_Init(&ctx); + assert_int_equal(cr, 0); + + // bad json + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "\"", 1, NULL); + assert_int_equal(cr, CEL_RC_INVALID_VALUE); + + // not json object + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "[]", 2, NULL); + assert_int_equal(cr, CEL_RC_INVALID_TYPE); + + // missing content type + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "{}", 2, NULL); + assert_int_equal(cr, CEL_RC_INVALID_VALUE); + + // content type not string/int + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "{\"content_type\": []}", 20, NULL); + assert_int_equal(cr, CEL_RC_INVALID_TYPE); + + // not systemd type + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "{\"content_type\": \"cel\"}", 23, NULL); + assert_int_equal(cr, CEL_RC_INVALID_TYPE); + + // missing handle + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "{\"content_type\": \"systemd\"}", 27, NULL); + assert_int_equal(cr, CEL_RC_INVALID_VALUE); + + // missing digests + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "{\"content_type\": \"systemd\", \"pcr\": 1}", 37, NULL); + assert_int_equal(cr, CEL_RC_INVALID_VALUE); + + // bad digests + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "{\"content_type\": \"systemd\", \"pcr\": 1, \"digests\": {}}", 52, NULL); + assert_int_equal(cr, CEL_RC_INVALID_TYPE); + + // missing content + cr = CEL_Parse_SYSTEMD_Event(ctx, &event, (uint8_t *) "{\"content_type\": \"systemd\", \"pcr\": 1, \"digests\": []}", 52, NULL); + assert_int_equal(cr, CEL_RC_INVALID_VALUE); +} + int main(int argc, char **argv) { (void) argc; @@ -355,6 +487,9 @@ int main(int argc, char **argv) cmocka_unit_test_prestate(test_parse_uefi_header_short, &data), cmocka_unit_test_prestate(test_parse_uefi_short, &data), cmocka_unit_test_prestate(test_parse_ima_short, &data), + cmocka_unit_test(test_parse_systemd), + cmocka_unit_test(test_parse_systemd_nulls), + cmocka_unit_test(test_parse_systemd_bad), }; return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/test/test_tlv.c b/test/test_tlv.c index 9b64794..be5d7fe 100644 --- a/test/test_tlv.c +++ b/test/test_tlv.c @@ -952,6 +952,310 @@ void test_tlv_tpms_cel_event(void **state) { assert_int_equal(r, CEL_RC_SHORT_BUFFER); } +void test_tlv_tpms_systemd(void **state) { + (void) state; + TPMS_CEL_EVENT event, event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[68], + expected_buffer[68] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x2E" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 55 boot_id + "\x03\x00\x00\x00\x07" // 56 - 60 string type + "falafel" // 61 - 67 string + ; + + event.recnum = 2; + event.pcr = 3; + event.digests.count = 0; + event.content_type = CEL_TYPE_SYSTEMD; + event.content.systemd.event_type = CEL_TYPE_SYSTEMD_EVENT_VOLUME_KEY; + event.content.systemd.timestamp = 0xAAAA; + memcpy(event.content.systemd.boot_id, "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA", 16); + memcpy(event.content.systemd.string.buffer, "falafel", 7); + event.content.systemd.string.size = 7; + + r = CEL_TLV_TPMS_CEL_EVENT_Marshal(&event, buffer, 68, &off); + assert_int_equal(r, 0); + assert_int_equal(off, 68); + assert_memory_equal(buffer, expected_buffer, 68); + + off = 0; + r = CEL_TLV_TPMS_CEL_EVENT_Marshal(&event, NULL, 0, &off); + assert_int_equal(r, 0); + assert_int_equal(off, 68); + + // test short buffer + off = 0; + r = CEL_TLV_TPMS_CEL_EVENT_Marshal(&event, buffer, 20, &off); + assert_int_equal(r, CEL_RC_SHORT_BUFFER); + + // test unmarshal + off = 0; + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(expected_buffer, 68, &off, &event_out); + assert_int_equal(r, 0); + assert_int_equal(off, 68); + assert_int_equal(event.content_type, event_out.content_type); + assert_int_equal(event.content.systemd.event_type, event_out.content.systemd.event_type); + assert_int_equal(event.content.systemd.timestamp, event_out.content.systemd.timestamp); + assert_memory_equal(event.content.systemd.boot_id, event_out.content.systemd.boot_id, sizeof(event.content.systemd.boot_id)); + assert_int_equal(event.content.systemd.string.size, event_out.content.systemd.string.size); + assert_memory_equal(event.content.systemd.string.buffer, event_out.content.systemd.string.buffer, event_out.content.systemd.string.size); + + // test unmarshal short buffer + off = 0; + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(expected_buffer, 60, &off, &event_out); + assert_int_equal(r, CEL_RC_SHORT_BUFFER); +} + +void test_tlv_tpms_systemd_missing_event_type(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[62] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x28" // 17 - 21 CEL systemd + "\x01\x00\x00\x00\x02\xAA\xAA" // 22 - 28 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 29 - 49 boot_id + "\x03\x00\x00\x00\x07" // 50 - 54 string type + "falafel" // 55 - 63 string + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 62, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_missing_timestamp(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[61] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x27" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 28 - 48 boot_id + "\x03\x00\x00\x00\x07" // 49 - 53 string type + "falafel" // 54 - 60 string + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 61, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_missing_boot_id(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[47] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x19" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x03\x00\x00\x00\x07" // 35 - 39 string type + "falafel" // 40 - 46 string + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 47, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_missing_string(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[56] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x22" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 55 boot_id + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 56, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_short_boot_id(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[67] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x2D" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x0F\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 54 boot_id + "\x03\x00\x00\x00\x07" // 55 - 59 string type + "falafel" // 60 - 66 string + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 67, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_large_event_type(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[69] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x2F" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x02\x02\x00" // 22 - 28 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 29 - 35 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 36 - 56 boot_id + "\x03\x00\x00\x00\x07" // 57 - 61 string type + "falafel" // 62 - 68 string + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 69, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_bad_type(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[68] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x2E" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 55 boot_id + "\xFF\x00\x00\x00\x07" // 56 - 60 string type + "falafel" // 61 - 67 string + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 68, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_TYPE); +} + +void test_tlv_tpms_systemd_double_event_type(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[74] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x34" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 55 boot_id + "\x03\x00\x00\x00\x07" // 56 - 60 string type + "falafel" // 61 - 67 string + "\x00\x00\x00\x00\x01\x03" // 68 - 73 extra event type + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 74, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_double_timestamp(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[74] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x34" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 55 boot_id + "\x03\x00\x00\x00\x07" // 56 - 60 string type + "falafel" // 61 - 67 string + "\x01\x00\x00\x00\x01\xFF" // 68 - 73 extra timestamp + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 74, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_double_boot_id(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[89] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x43" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 55 boot_id + "\x03\x00\x00\x00\x07" // 56 - 60 string type + "falafel" // 61 - 67 string + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 68 - 88 extra boot_id + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 89, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + +void test_tlv_tpms_systemd_double_string(void **state) { + (void) state; + TPMS_CEL_EVENT event_out; + UINT32 r; + size_t off = 0; + uint8_t + buffer[80] = + "\x00\x00\x00\x00\x01\x02" // 0 - 5 recnum + "\x01\x00\x00\x00\x01\x03" // 6 - 11 pcr + "\x03\x00\x00\x00\x00" // 12 - 16 empty digests + "\x0B\x00\x00\x00\x3A" // 17 - 21 CEL systemd + "\x00\x00\x00\x00\x01\x02" // 22 - 27 event type volume key + "\x01\x00\x00\x00\x02\xAA\xAA" // 28 - 34 timestamp + "\x02\x00\x00\x00\x10\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA" // 35 - 55 boot_id + "\x03\x00\x00\x00\x07" // 56 - 60 string type + "falafel" // 61 - 67 string + "\x03\x00\x00\x00\x07" // 68 - 72 extra string type + "falafel" // 73 - 79 extra string + ; + + r = CEL_TLV_TPMS_CEL_EVENT_Unmarshal(buffer, 89, &off, &event_out); + assert_int_equal(r, CEL_RC_INVALID_VALUE); +} + int main(int argc, char **argv) { (void) argc; @@ -969,6 +1273,18 @@ int main(int argc, char **argv) cmocka_unit_test(test_tlv_tpms_event_ima_template), cmocka_unit_test(test_tlv_tpml_event_celmgt), cmocka_unit_test(test_tlv_tpms_cel_event), + cmocka_unit_test(test_tlv_tpms_systemd), + cmocka_unit_test(test_tlv_tpms_systemd_missing_event_type), + cmocka_unit_test(test_tlv_tpms_systemd_missing_timestamp), + cmocka_unit_test(test_tlv_tpms_systemd_missing_boot_id), + cmocka_unit_test(test_tlv_tpms_systemd_missing_string), + cmocka_unit_test(test_tlv_tpms_systemd_short_boot_id), + cmocka_unit_test(test_tlv_tpms_systemd_large_event_type), + cmocka_unit_test(test_tlv_tpms_systemd_bad_type), + cmocka_unit_test(test_tlv_tpms_systemd_double_event_type), + cmocka_unit_test(test_tlv_tpms_systemd_double_timestamp), + cmocka_unit_test(test_tlv_tpms_systemd_double_boot_id), + cmocka_unit_test(test_tlv_tpms_systemd_double_string), }; return cmocka_run_group_tests(tests, NULL, NULL); }