From 7777bbf1f12bb172cc104f3715d28369f45b9ea9 Mon Sep 17 00:00:00 2001 From: Pim van Stam Date: Tue, 16 Sep 2025 17:04:05 +0200 Subject: [PATCH 1/2] Implemented IntegrityCheck encoder --- src/libwandder_etsili_ber.c | 150 +++++++++++++++++++++++++++++++++++- src/libwandder_etsili_ber.h | 24 ++++++ 2 files changed, 171 insertions(+), 3 deletions(-) diff --git a/src/libwandder_etsili_ber.c b/src/libwandder_etsili_ber.c index 46e2bfb..71c84f6 100644 --- a/src/libwandder_etsili_ber.c +++ b/src/libwandder_etsili_ber.c @@ -111,9 +111,10 @@ static inline void encode_ipaddress(wandder_encoder_ber_t* enc_ber, free(addr->ipvalue); } -//ensures that the buffer exceeds child->body.buf + currlen in allocated memeroy -//adjusts all internal pointers accordingly if realloc -//returns the difference between new, and old buffers +/* ensures that the buffer exceeds child->body.buf + currlen in allocated memeroy + * adjusts all internal pointers accordingly if realloc + * returns the difference between new, and old buffers + */ static ptrdiff_t check_body_size(wandder_etsili_child_t * child, size_t currlen){ uint8_t* new; @@ -564,6 +565,149 @@ static uint8_t* wandder_encode_body_data_ber( return ret + child->body.data; } + +/* + * TRI / IntegrityCheck encoder + * Path: payload [2] → triPayload [3] → integrityCheck [0] + * Fields (schema order): + * 0) checkType ENUM (messageDigest=0) + * 1) dataType ENUM (iri=0 | cc=1) + * 2) hashAlgorithm ENUM (sha256=2) + * 3) includedSeqNumbers SEQUENCE OF INTEGER + * 4) hashValue OCTET STRING (32) + * 5) signature OPTIONAL (OCTET STRING with DER signature) + */ +#define WANDDER_TAGID_PAYLOAD 2 +#define WANDDER_TAGID_TRIPAYLOAD 3 +#define WANDDER_TAGID_INTEGRITYCHECK 0 + +/* checkType: messageDigest */ +#define WANDDER_IC_CHECKTYPE_MESSAGE_DIGEST 0u + +static void init_etsili_tri_integrity_body(wandder_encoder_ber_t *enc_ber, + wandder_etsili_top_t *top) +{ + /* Open [2] payload */ + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_CSEQUENCE_2]); + /* Open [3] triPayload */ + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_CSEQUENCE_3]); + /* Open [0] integrityCheck */ + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_CSEQUENCE_0]); + + /* Close integrityCheck, triPayload, payload — three EOCs total */ + wandder_encode_endseq_ber(enc_ber, 3); +} + +void wandder_init_etsili_tri_integrity( + wandder_encoder_ber_t* enc_ber, + wandder_etsili_top_t* top) +{ + if (!top || !top->preencoded || !enc_ber){ + fprintf(stderr,"Make sure wandder_encode_init_top_ber is called first\n"); + return; + } + wandder_encoded_result_ber_t* res_ber; + + wandder_reset_encoder_ber(enc_ber); + init_etsili_tri_integrity_body(enc_ber, top); + res_ber = wandder_encode_finish_ber(enc_ber); + if (!res_ber) { + fprintf(stderr,"wandder: failed to build TRI/Integrity template\n"); + return; + } + + top->tri_integrity.buf = res_ber->buf; + top->tri_integrity.len = res_ber->len; + top->tri_integrity.alloc_len = res_ber->len; + top->tri_integrity.meta = res_ber->buf + (top->header.end - top->header.buf); /* keep style consistent */ + top->tri_integrity.data = res_ber->buf + (top->header.end - top->header.buf); /* updated at encode */ + top->tri_integrity.flist = wandder_create_etsili_child_freelist(); + free(res_ber); +} + +static void update_etsili_tri_integrity(uint8_t data_type, + const uint32_t *seqnos, size_t nseq, + const uint8_t hash32[32], + uint8_t sig_alg, const uint8_t *sig_der, size_t sig_der_len, + wandder_etsili_child_t *child) +{ + uint8_t *ptr = child->body.data; + ptrdiff_t rem = child->alloc_len - (ptr - child->buf); + + /* 0) checkType = messageDigest */ + encode_here_ber_update( + 0, WANDDER_CLASS_CONTEXT_PRIMITIVE, WANDDER_TAG_ENUM, + (uint8_t*)&(uint32_t){ WANDDER_IC_CHECKTYPE_MESSAGE_DIGEST }, sizeof(uint32_t), + &ptr, &rem, child); + + /* 1) dataType = iri(0) | cc(1) */ + encode_here_ber_update( + 1, WANDDER_CLASS_CONTEXT_PRIMITIVE, WANDDER_TAG_ENUM, + (uint8_t*)&(uint32_t){ data_type }, sizeof(uint32_t), + &ptr, &rem, child); + + /* 2) hashAlgorithm = sha256(2) */ + encode_here_ber_update( + 2, WANDDER_CLASS_CONTEXT_PRIMITIVE, WANDDER_TAG_ENUM, + (uint8_t*)&(uint32_t){ 2u }, sizeof(uint32_t), + &ptr, &rem, child); + + /* 3) includedSequenceNumbers: SEQUENCE OF INTEGER */ + encode_here_ber_update( + 3, WANDDER_CLASS_CONTEXT_CONSTRUCT, WANDDER_TAG_SEQUENCE, + NULL, 0, &ptr, &rem, child); + for (size_t i=0; i 0) { + encode_here_ber_update( + 5, WANDDER_CLASS_CONTEXT_PRIMITIVE, WANDDER_TAG_OCTETSTRING, + (uint8_t*)sig_der, sig_der_len, &ptr, &rem, child); + } + + /* Done. The enclosing three sequences were already closed in the template. */ + child->body.data = ptr; + child->body.len = ptr - child->body.buf; + child->len = ptr - child->buf; +} + +void wandder_encode_etsi_tri_integrity_ber( + int64_t cin, int64_t seqno, struct timeval *tv, + uint8_t data_type, + const uint32_t *seqnos, size_t nseq, + const uint8_t hash32[32], + uint8_t sig_alg, + const uint8_t *sig_der, size_t sig_der_len, + wandder_etsili_child_t *child) +{ + if (!child || !child->header.buf) { + fprintf(stderr,"Make sure wandder_encode_init_top_ber is called first\n"); + return; + } + if (!child->body.buf) { + fprintf(stderr,"Call wandder_init_etsili_tri_integrity() first.\n"); + return; + } + update_etsili_pshdr_pc(&child->header, cin, seqno, tv); + update_etsili_tri_integrity( + data_type, seqnos, nseq, hash32, sig_alg, sig_der, sig_der_len, child); +} + + static void update_etsili_pshdr_pc(wandder_pshdr_t * header, int64_t cin, int64_t seqno, struct timeval* tv){ diff --git a/src/libwandder_etsili_ber.h b/src/libwandder_etsili_ber.h index 38ce9b3..8b616f9 100644 --- a/src/libwandder_etsili_ber.h +++ b/src/libwandder_etsili_ber.h @@ -58,6 +58,8 @@ typedef struct wandder_etsili_top { wandder_generic_body_t ipiri; wandder_generic_body_t umtscc; wandder_generic_body_t umtsiri; + /* TRI / IntegrityCheck body template */ + wandder_generic_body_t tri_integrity; size_t increment_len; wandder_buf_t **preencoded; } wandder_etsili_top_t; @@ -129,6 +131,28 @@ void wandder_init_etsili_umtsiri( wandder_encoder_ber_t* enc_ber, wandder_etsili_top_t* top); +/* ---- TRI / IntegrityCheck (TS 102 232-1 §7.2.3, Annex J) ---- */ +/* Build the body template for payload[2] → triPayload[3] → integrityCheck[0] */ +void wandder_init_etsili_tri_integrity( + wandder_encoder_ber_t* enc_ber, + wandder_etsili_top_t* top); + +/* Encode a full PS-PDU carrying a TRIPayload.integrityCheck. + * data_type: 0 = IRI, 1 = CC (NL profile) + * seqnos/nseq: includedSequenceNumbers + * hash32: 32-byte SHA-256 + * sig_alg: 0 = none, 1 = dsa-with-sha256, 2 = sha256WithRSAEncryption + * sig_der/sig_der_len: raw DER signature bytes (optional) + */ +void wandder_encode_etsi_tri_integrity_ber( + int64_t cin, int64_t seqno, struct timeval *tv, + uint8_t data_type, + const uint32_t *seqnos, size_t nseq, + const uint8_t hash32[32], + uint8_t sig_alg, + const uint8_t *sig_der, size_t sig_der_len, + wandder_etsili_child_t *child); + wandder_etsili_child_freelist_t *wandder_create_etsili_child_freelist(); wandder_etsili_child_t *wandder_create_etsili_child(wandder_etsili_top_t* top, wandder_generic_body_t * body); From 0b6ad31aea0c186514eb16db327288188f96d46c Mon Sep 17 00:00:00 2001 From: Pim van Stam Date: Tue, 16 Sep 2025 23:52:46 +0200 Subject: [PATCH 2/2] moved update_etsili_pshdr_pc() --- src/libwandder_etsili_ber.c | 223 ++++++++++++++++++------------------ 1 file changed, 112 insertions(+), 111 deletions(-) diff --git a/src/libwandder_etsili_ber.c b/src/libwandder_etsili_ber.c index 71c84f6..e1f36bf 100644 --- a/src/libwandder_etsili_ber.c +++ b/src/libwandder_etsili_ber.c @@ -566,6 +566,118 @@ static uint8_t* wandder_encode_body_data_ber( } +static void update_etsili_pshdr_pc(wandder_pshdr_t * header, int64_t cin, + int64_t seqno, struct timeval* tv){ + + ber_rebuild_integer( + WANDDER_CLASS_CONTEXT_PRIMITIVE, + 1, + &(cin), + sizeof cin, + header->cin); + + ber_rebuild_integer( + WANDDER_CLASS_CONTEXT_PRIMITIVE, + 4, + &(seqno), + sizeof seqno, + header->seqno); + + ber_rebuild_integer( + WANDDER_CLASS_CONTEXT_PRIMITIVE, + 0, + &(tv->tv_sec), + sizeof tv->tv_sec, + header->sec); + + ber_rebuild_integer( + WANDDER_CLASS_CONTEXT_PRIMITIVE, + 1, + &(tv->tv_usec), + sizeof tv->tv_usec, + header->usec); +} + +static void init_etsili_pshdr_pc(wandder_encoder_ber_t* enc_ber, + wandder_etsili_top_t* top) { + + int64_t cin = 0; + int64_t seqno = 0; + struct timeval tv = {0,0}; + + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_USEQUENCE]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_CSEQUENCE_1]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_PSDOMAINID]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_LIID]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_AUTHCC]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_CSEQUENCE_3]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_CSEQUENCE_0]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_OPERATORID]); + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_NETWORKELEMID]); + wandder_encode_endseq_ber(enc_ber, 1); + + ptrdiff_t cin_diff = enc_ber->ptr - enc_ber->buf; + wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, + WANDDER_CLASS_CONTEXT_PRIMITIVE, 1, &(cin), + sizeof cin); + + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_DELIVCC]); + wandder_encode_endseq_ber(enc_ber, 1); + + ptrdiff_t seqno_diff = enc_ber->ptr - enc_ber->buf; + wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, + WANDDER_CLASS_CONTEXT_PRIMITIVE, 4, &(seqno), + sizeof seqno); + + if (top->preencoded[WANDDER_PREENCODE_INTPOINTID]) { + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_INTPOINTID]); + } + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_CSEQUENCE_7]); + + ptrdiff_t sec_diff = enc_ber->ptr - enc_ber->buf; + wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, + WANDDER_CLASS_CONTEXT_PRIMITIVE, 0, &(tv.tv_sec), + sizeof tv.tv_sec); + + ptrdiff_t usec_diff = enc_ber->ptr - enc_ber->buf; + wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, + WANDDER_CLASS_CONTEXT_PRIMITIVE, 1, &(tv.tv_usec), + sizeof tv.tv_usec); + + wandder_encode_endseq_ber(enc_ber, 1); + + wandder_append_preencoded_ber(enc_ber, + top->preencoded[WANDDER_PREENCODE_TVCLASS]); + wandder_encode_endseq_ber(enc_ber, 1); + ptrdiff_t end_diff = enc_ber->ptr - enc_ber->buf; + + + wandder_encoded_result_ber_t* res_ber = wandder_encode_finish_ber(enc_ber); + + top->header.buf = res_ber->buf; + top->header.len = res_ber->len; + top->header.cin = res_ber->buf + cin_diff; + top->header.seqno = res_ber->buf + seqno_diff; + top->header.sec = res_ber->buf + sec_diff; + top->header.usec = res_ber->buf + usec_diff; + top->header.end = res_ber->buf + end_diff; + + free(res_ber); +} + + /* * TRI / IntegrityCheck encoder * Path: payload [2] → triPayload [3] → integrityCheck [0] @@ -708,117 +820,6 @@ void wandder_encode_etsi_tri_integrity_ber( } -static void update_etsili_pshdr_pc(wandder_pshdr_t * header, int64_t cin, - int64_t seqno, struct timeval* tv){ - - ber_rebuild_integer( - WANDDER_CLASS_CONTEXT_PRIMITIVE, - 1, - &(cin), - sizeof cin, - header->cin); - - ber_rebuild_integer( - WANDDER_CLASS_CONTEXT_PRIMITIVE, - 4, - &(seqno), - sizeof seqno, - header->seqno); - - ber_rebuild_integer( - WANDDER_CLASS_CONTEXT_PRIMITIVE, - 0, - &(tv->tv_sec), - sizeof tv->tv_sec, - header->sec); - - ber_rebuild_integer( - WANDDER_CLASS_CONTEXT_PRIMITIVE, - 1, - &(tv->tv_usec), - sizeof tv->tv_usec, - header->usec); -} - -static void init_etsili_pshdr_pc(wandder_encoder_ber_t* enc_ber, - wandder_etsili_top_t* top) { - - int64_t cin = 0; - int64_t seqno = 0; - struct timeval tv = {0,0}; - - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_USEQUENCE]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_CSEQUENCE_1]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_PSDOMAINID]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_LIID]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_AUTHCC]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_CSEQUENCE_3]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_CSEQUENCE_0]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_OPERATORID]); - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_NETWORKELEMID]); - wandder_encode_endseq_ber(enc_ber, 1); - - ptrdiff_t cin_diff = enc_ber->ptr - enc_ber->buf; - wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, - WANDDER_CLASS_CONTEXT_PRIMITIVE, 1, &(cin), - sizeof cin); - - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_DELIVCC]); - wandder_encode_endseq_ber(enc_ber, 1); - - ptrdiff_t seqno_diff = enc_ber->ptr - enc_ber->buf; - wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, - WANDDER_CLASS_CONTEXT_PRIMITIVE, 4, &(seqno), - sizeof seqno); - - if (top->preencoded[WANDDER_PREENCODE_INTPOINTID]) { - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_INTPOINTID]); - } - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_CSEQUENCE_7]); - - ptrdiff_t sec_diff = enc_ber->ptr - enc_ber->buf; - wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, - WANDDER_CLASS_CONTEXT_PRIMITIVE, 0, &(tv.tv_sec), - sizeof tv.tv_sec); - - ptrdiff_t usec_diff = enc_ber->ptr - enc_ber->buf; - wandder_encode_next_ber(enc_ber, WANDDER_TAG_INTEGER, - WANDDER_CLASS_CONTEXT_PRIMITIVE, 1, &(tv.tv_usec), - sizeof tv.tv_usec); - - wandder_encode_endseq_ber(enc_ber, 1); - - wandder_append_preencoded_ber(enc_ber, - top->preencoded[WANDDER_PREENCODE_TVCLASS]); - wandder_encode_endseq_ber(enc_ber, 1); - ptrdiff_t end_diff = enc_ber->ptr - enc_ber->buf; - - - wandder_encoded_result_ber_t* res_ber = wandder_encode_finish_ber(enc_ber); - - top->header.buf = res_ber->buf; - top->header.len = res_ber->len; - top->header.cin = res_ber->buf + cin_diff; - top->header.seqno = res_ber->buf + seqno_diff; - top->header.sec = res_ber->buf + sec_diff; - top->header.usec = res_ber->buf + usec_diff; - top->header.end = res_ber->buf + end_diff; - - free(res_ber); -} - static void update_etsili_ipcc( void* ipcontents, size_t iplen, uint8_t dir, wandder_etsili_child_t * child) {