/* stfe.c -- generated by Trunnel v1.5.3. * https://gitweb.torproject.org/trunnel.git * You probably shouldn't edit this file. */ #include #include "trunnel-impl.h" #include "stfe.h" #define TRUNNEL_SET_ERROR_CODE(obj) \ do { \ (obj)->trunnel_error_code_ = 1; \ } while (0) #if defined(__COVERITY__) || defined(__clang_analyzer__) /* If we're running a static analysis tool, we don't want it to complain * that some of our remaining-bytes checks are dead-code. */ int stfe_deadcode_dummy__ = 0; #define OR_DEADCODE_DUMMY || stfe_deadcode_dummy__ #else #define OR_DEADCODE_DUMMY #endif #define CHECK_REMAINING(nbytes, label) \ do { \ if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \ goto label; \ } \ } while (0) ed25519_v1_t * ed25519_v1_new(void) { ed25519_v1_t *val = trunnel_calloc(1, sizeof(ed25519_v1_t)); if (NULL == val) return NULL; val->format = T_ED25519_V1; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void ed25519_v1_clear(ed25519_v1_t *obj) { (void) obj; } void ed25519_v1_free(ed25519_v1_t *obj) { if (obj == NULL) return; ed25519_v1_clear(obj); trunnel_memwipe(obj, sizeof(ed25519_v1_t)); trunnel_free_(obj); } uint64_t ed25519_v1_get_format(const ed25519_v1_t *inp) { return inp->format; } int ed25519_v1_set_format(ed25519_v1_t *inp, uint64_t val) { if (! ((val == T_ED25519_V1))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } inp->format = val; return 0; } size_t ed25519_v1_getlen_pubkey(const ed25519_v1_t *inp) { (void)inp; return 32; } uint8_t ed25519_v1_get_pubkey(ed25519_v1_t *inp, size_t idx) { trunnel_assert(idx < 32); return inp->pubkey[idx]; } uint8_t ed25519_v1_getconst_pubkey(const ed25519_v1_t *inp, size_t idx) { return ed25519_v1_get_pubkey((ed25519_v1_t*)inp, idx); } int ed25519_v1_set_pubkey(ed25519_v1_t *inp, size_t idx, uint8_t elt) { trunnel_assert(idx < 32); inp->pubkey[idx] = elt; return 0; } uint8_t * ed25519_v1_getarray_pubkey(ed25519_v1_t *inp) { return inp->pubkey; } const uint8_t * ed25519_v1_getconstarray_pubkey(const ed25519_v1_t *inp) { return (const uint8_t *)ed25519_v1_getarray_pubkey((ed25519_v1_t*)inp); } const char * ed25519_v1_check(const ed25519_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; if (! (obj->format == T_ED25519_V1)) return "Integer out of bounds"; return NULL; } ssize_t ed25519_v1_encoded_len(const ed25519_v1_t *obj) { ssize_t result = 0; if (NULL != ed25519_v1_check(obj)) return -1; /* Length of u64 format IN [T_ED25519_V1] */ result += 8; /* Length of u8 pubkey[32] */ result += 32; return result; } int ed25519_v1_clear_errors(ed25519_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t ed25519_v1_encode(uint8_t *output, const size_t avail, const ed25519_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = ed25519_v1_encoded_len(obj); #endif if (NULL != (msg = ed25519_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 format IN [T_ED25519_V1] */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->format)); written += 8; ptr += 8; /* Encode u8 pubkey[32] */ trunnel_assert(written <= avail); if (avail - written < 32) goto truncated; memcpy(ptr, obj->pubkey, 32); written += 32; ptr += 32; trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As ed25519_v1_parse(), but do not allocate the output object. */ static ssize_t ed25519_v1_parse_into(ed25519_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 format IN [T_ED25519_V1] */ CHECK_REMAINING(8, truncated); obj->format = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; if (! (obj->format == T_ED25519_V1)) goto fail; /* Parse u8 pubkey[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->pubkey, ptr, 32); remaining -= 32; ptr += 32; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; fail: result = -1; return result; } ssize_t ed25519_v1_parse(ed25519_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = ed25519_v1_new(); if (NULL == *output) return -1; result = ed25519_v1_parse_into(*output, input, len_in); if (result < 0) { ed25519_v1_free(*output); *output = NULL; } return result; } req_get_consistency_proof_v1_t * req_get_consistency_proof_v1_new(void) { req_get_consistency_proof_v1_t *val = trunnel_calloc(1, sizeof(req_get_consistency_proof_v1_t)); if (NULL == val) return NULL; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void req_get_consistency_proof_v1_clear(req_get_consistency_proof_v1_t *obj) { (void) obj; } void req_get_consistency_proof_v1_free(req_get_consistency_proof_v1_t *obj) { if (obj == NULL) return; req_get_consistency_proof_v1_clear(obj); trunnel_memwipe(obj, sizeof(req_get_consistency_proof_v1_t)); trunnel_free_(obj); } uint64_t req_get_consistency_proof_v1_get_old_size(const req_get_consistency_proof_v1_t *inp) { return inp->old_size; } int req_get_consistency_proof_v1_set_old_size(req_get_consistency_proof_v1_t *inp, uint64_t val) { inp->old_size = val; return 0; } uint64_t req_get_consistency_proof_v1_get_new_size(const req_get_consistency_proof_v1_t *inp) { return inp->new_size; } int req_get_consistency_proof_v1_set_new_size(req_get_consistency_proof_v1_t *inp, uint64_t val) { inp->new_size = val; return 0; } const char * req_get_consistency_proof_v1_check(const req_get_consistency_proof_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; return NULL; } ssize_t req_get_consistency_proof_v1_encoded_len(const req_get_consistency_proof_v1_t *obj) { ssize_t result = 0; if (NULL != req_get_consistency_proof_v1_check(obj)) return -1; /* Length of u64 old_size */ result += 8; /* Length of u64 new_size */ result += 8; return result; } int req_get_consistency_proof_v1_clear_errors(req_get_consistency_proof_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t req_get_consistency_proof_v1_encode(uint8_t *output, const size_t avail, const req_get_consistency_proof_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = req_get_consistency_proof_v1_encoded_len(obj); #endif if (NULL != (msg = req_get_consistency_proof_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 old_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->old_size)); written += 8; ptr += 8; /* Encode u64 new_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->new_size)); written += 8; ptr += 8; trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As req_get_consistency_proof_v1_parse(), but do not allocate the * output object. */ static ssize_t req_get_consistency_proof_v1_parse_into(req_get_consistency_proof_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 old_size */ CHECK_REMAINING(8, truncated); obj->old_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u64 new_size */ CHECK_REMAINING(8, truncated); obj->new_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; } ssize_t req_get_consistency_proof_v1_parse(req_get_consistency_proof_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = req_get_consistency_proof_v1_new(); if (NULL == *output) return -1; result = req_get_consistency_proof_v1_parse_into(*output, input, len_in); if (result < 0) { req_get_consistency_proof_v1_free(*output); *output = NULL; } return result; } req_get_entries_v1_t * req_get_entries_v1_new(void) { req_get_entries_v1_t *val = trunnel_calloc(1, sizeof(req_get_entries_v1_t)); if (NULL == val) return NULL; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void req_get_entries_v1_clear(req_get_entries_v1_t *obj) { (void) obj; } void req_get_entries_v1_free(req_get_entries_v1_t *obj) { if (obj == NULL) return; req_get_entries_v1_clear(obj); trunnel_memwipe(obj, sizeof(req_get_entries_v1_t)); trunnel_free_(obj); } uint64_t req_get_entries_v1_get_start_size(const req_get_entries_v1_t *inp) { return inp->start_size; } int req_get_entries_v1_set_start_size(req_get_entries_v1_t *inp, uint64_t val) { inp->start_size = val; return 0; } uint64_t req_get_entries_v1_get_end_size(const req_get_entries_v1_t *inp) { return inp->end_size; } int req_get_entries_v1_set_end_size(req_get_entries_v1_t *inp, uint64_t val) { inp->end_size = val; return 0; } const char * req_get_entries_v1_check(const req_get_entries_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; return NULL; } ssize_t req_get_entries_v1_encoded_len(const req_get_entries_v1_t *obj) { ssize_t result = 0; if (NULL != req_get_entries_v1_check(obj)) return -1; /* Length of u64 start_size */ result += 8; /* Length of u64 end_size */ result += 8; return result; } int req_get_entries_v1_clear_errors(req_get_entries_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t req_get_entries_v1_encode(uint8_t *output, const size_t avail, const req_get_entries_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = req_get_entries_v1_encoded_len(obj); #endif if (NULL != (msg = req_get_entries_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 start_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->start_size)); written += 8; ptr += 8; /* Encode u64 end_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->end_size)); written += 8; ptr += 8; trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As req_get_entries_v1_parse(), but do not allocate the output * object. */ static ssize_t req_get_entries_v1_parse_into(req_get_entries_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 start_size */ CHECK_REMAINING(8, truncated); obj->start_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u64 end_size */ CHECK_REMAINING(8, truncated); obj->end_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; } ssize_t req_get_entries_v1_parse(req_get_entries_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = req_get_entries_v1_new(); if (NULL == *output) return -1; result = req_get_entries_v1_parse_into(*output, input, len_in); if (result < 0) { req_get_entries_v1_free(*output); *output = NULL; } return result; } req_get_proof_by_hash_v1_t * req_get_proof_by_hash_v1_new(void) { req_get_proof_by_hash_v1_t *val = trunnel_calloc(1, sizeof(req_get_proof_by_hash_v1_t)); if (NULL == val) return NULL; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void req_get_proof_by_hash_v1_clear(req_get_proof_by_hash_v1_t *obj) { (void) obj; } void req_get_proof_by_hash_v1_free(req_get_proof_by_hash_v1_t *obj) { if (obj == NULL) return; req_get_proof_by_hash_v1_clear(obj); trunnel_memwipe(obj, sizeof(req_get_proof_by_hash_v1_t)); trunnel_free_(obj); } uint64_t req_get_proof_by_hash_v1_get_tree_size(const req_get_proof_by_hash_v1_t *inp) { return inp->tree_size; } int req_get_proof_by_hash_v1_set_tree_size(req_get_proof_by_hash_v1_t *inp, uint64_t val) { inp->tree_size = val; return 0; } size_t req_get_proof_by_hash_v1_getlen_leaf_hash(const req_get_proof_by_hash_v1_t *inp) { (void)inp; return 32; } uint8_t req_get_proof_by_hash_v1_get_leaf_hash(req_get_proof_by_hash_v1_t *inp, size_t idx) { trunnel_assert(idx < 32); return inp->leaf_hash[idx]; } uint8_t req_get_proof_by_hash_v1_getconst_leaf_hash(const req_get_proof_by_hash_v1_t *inp, size_t idx) { return req_get_proof_by_hash_v1_get_leaf_hash((req_get_proof_by_hash_v1_t*)inp, idx); } int req_get_proof_by_hash_v1_set_leaf_hash(req_get_proof_by_hash_v1_t *inp, size_t idx, uint8_t elt) { trunnel_assert(idx < 32); inp->leaf_hash[idx] = elt; return 0; } uint8_t * req_get_proof_by_hash_v1_getarray_leaf_hash(req_get_proof_by_hash_v1_t *inp) { return inp->leaf_hash; } const uint8_t * req_get_proof_by_hash_v1_getconstarray_leaf_hash(const req_get_proof_by_hash_v1_t *inp) { return (const uint8_t *)req_get_proof_by_hash_v1_getarray_leaf_hash((req_get_proof_by_hash_v1_t*)inp); } const char * req_get_proof_by_hash_v1_check(const req_get_proof_by_hash_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; return NULL; } ssize_t req_get_proof_by_hash_v1_encoded_len(const req_get_proof_by_hash_v1_t *obj) { ssize_t result = 0; if (NULL != req_get_proof_by_hash_v1_check(obj)) return -1; /* Length of u64 tree_size */ result += 8; /* Length of u8 leaf_hash[32] */ result += 32; return result; } int req_get_proof_by_hash_v1_clear_errors(req_get_proof_by_hash_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t req_get_proof_by_hash_v1_encode(uint8_t *output, const size_t avail, const req_get_proof_by_hash_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = req_get_proof_by_hash_v1_encoded_len(obj); #endif if (NULL != (msg = req_get_proof_by_hash_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 tree_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->tree_size)); written += 8; ptr += 8; /* Encode u8 leaf_hash[32] */ trunnel_assert(written <= avail); if (avail - written < 32) goto truncated; memcpy(ptr, obj->leaf_hash, 32); written += 32; ptr += 32; trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As req_get_proof_by_hash_v1_parse(), but do not allocate the * output object. */ static ssize_t req_get_proof_by_hash_v1_parse_into(req_get_proof_by_hash_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 tree_size */ CHECK_REMAINING(8, truncated); obj->tree_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u8 leaf_hash[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->leaf_hash, ptr, 32); remaining -= 32; ptr += 32; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; } ssize_t req_get_proof_by_hash_v1_parse(req_get_proof_by_hash_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = req_get_proof_by_hash_v1_new(); if (NULL == *output) return -1; result = req_get_proof_by_hash_v1_parse_into(*output, input, len_in); if (result < 0) { req_get_proof_by_hash_v1_free(*output); *output = NULL; } return result; } signed_tree_head_v1_t * signed_tree_head_v1_new(void) { signed_tree_head_v1_t *val = trunnel_calloc(1, sizeof(signed_tree_head_v1_t)); if (NULL == val) return NULL; val->format = T_SIGNED_TREE_HEAD_V1; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void signed_tree_head_v1_clear(signed_tree_head_v1_t *obj) { (void) obj; TRUNNEL_DYNARRAY_WIPE(&obj->sigident); TRUNNEL_DYNARRAY_CLEAR(&obj->sigident); } void signed_tree_head_v1_free(signed_tree_head_v1_t *obj) { if (obj == NULL) return; signed_tree_head_v1_clear(obj); trunnel_memwipe(obj, sizeof(signed_tree_head_v1_t)); trunnel_free_(obj); } uint64_t signed_tree_head_v1_get_format(const signed_tree_head_v1_t *inp) { return inp->format; } int signed_tree_head_v1_set_format(signed_tree_head_v1_t *inp, uint64_t val) { if (! ((val == T_SIGNED_TREE_HEAD_V1))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } inp->format = val; return 0; } uint64_t signed_tree_head_v1_get_timestamp(const signed_tree_head_v1_t *inp) { return inp->timestamp; } int signed_tree_head_v1_set_timestamp(signed_tree_head_v1_t *inp, uint64_t val) { inp->timestamp = val; return 0; } uint64_t signed_tree_head_v1_get_tree_size(const signed_tree_head_v1_t *inp) { return inp->tree_size; } int signed_tree_head_v1_set_tree_size(signed_tree_head_v1_t *inp, uint64_t val) { inp->tree_size = val; return 0; } size_t signed_tree_head_v1_getlen_root_hash(const signed_tree_head_v1_t *inp) { (void)inp; return 32; } uint8_t signed_tree_head_v1_get_root_hash(signed_tree_head_v1_t *inp, size_t idx) { trunnel_assert(idx < 32); return inp->root_hash[idx]; } uint8_t signed_tree_head_v1_getconst_root_hash(const signed_tree_head_v1_t *inp, size_t idx) { return signed_tree_head_v1_get_root_hash((signed_tree_head_v1_t*)inp, idx); } int signed_tree_head_v1_set_root_hash(signed_tree_head_v1_t *inp, size_t idx, uint8_t elt) { trunnel_assert(idx < 32); inp->root_hash[idx] = elt; return 0; } uint8_t * signed_tree_head_v1_getarray_root_hash(signed_tree_head_v1_t *inp) { return inp->root_hash; } const uint8_t * signed_tree_head_v1_getconstarray_root_hash(const signed_tree_head_v1_t *inp) { return (const uint8_t *)signed_tree_head_v1_getarray_root_hash((signed_tree_head_v1_t*)inp); } uint64_t signed_tree_head_v1_get_length(const signed_tree_head_v1_t *inp) { return inp->length; } int signed_tree_head_v1_set_length(signed_tree_head_v1_t *inp, uint64_t val) { inp->length = val; return 0; } size_t signed_tree_head_v1_getlen_sigident(const signed_tree_head_v1_t *inp) { return TRUNNEL_DYNARRAY_LEN(&inp->sigident); } uint8_t signed_tree_head_v1_get_sigident(signed_tree_head_v1_t *inp, size_t idx) { return TRUNNEL_DYNARRAY_GET(&inp->sigident, idx); } uint8_t signed_tree_head_v1_getconst_sigident(const signed_tree_head_v1_t *inp, size_t idx) { return signed_tree_head_v1_get_sigident((signed_tree_head_v1_t*)inp, idx); } int signed_tree_head_v1_set_sigident(signed_tree_head_v1_t *inp, size_t idx, uint8_t elt) { TRUNNEL_DYNARRAY_SET(&inp->sigident, idx, elt); return 0; } int signed_tree_head_v1_add_sigident(signed_tree_head_v1_t *inp, uint8_t elt) { #if SIZE_MAX >= UINT64_MAX if (inp->sigident.n_ == UINT64_MAX) goto trunnel_alloc_failed; #endif TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sigident, elt, {}); return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } uint8_t * signed_tree_head_v1_getarray_sigident(signed_tree_head_v1_t *inp) { return inp->sigident.elts_; } const uint8_t * signed_tree_head_v1_getconstarray_sigident(const signed_tree_head_v1_t *inp) { return (const uint8_t *)signed_tree_head_v1_getarray_sigident((signed_tree_head_v1_t*)inp); } int signed_tree_head_v1_setlen_sigident(signed_tree_head_v1_t *inp, size_t newlen) { uint8_t *newptr; #if UINT64_MAX < SIZE_MAX if (newlen > UINT64_MAX) goto trunnel_alloc_failed; #endif newptr = trunnel_dynarray_setlen(&inp->sigident.allocated_, &inp->sigident.n_, inp->sigident.elts_, newlen, sizeof(inp->sigident.elts_[0]), (trunnel_free_fn_t) NULL, &inp->trunnel_error_code_); if (newlen != 0 && newptr == NULL) goto trunnel_alloc_failed; inp->sigident.elts_ = newptr; return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } const char * signed_tree_head_v1_check(const signed_tree_head_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; if (! (obj->format == T_SIGNED_TREE_HEAD_V1)) return "Integer out of bounds"; if (TRUNNEL_DYNARRAY_LEN(&obj->sigident) != obj->length) return "Length mismatch for sigident"; return NULL; } ssize_t signed_tree_head_v1_encoded_len(const signed_tree_head_v1_t *obj) { ssize_t result = 0; if (NULL != signed_tree_head_v1_check(obj)) return -1; /* Length of u64 format IN [T_SIGNED_TREE_HEAD_V1] */ result += 8; /* Length of u64 timestamp */ result += 8; /* Length of u64 tree_size */ result += 8; /* Length of u8 root_hash[32] */ result += 32; /* Length of u64 length */ result += 8; /* Length of u8 sigident[length] */ result += TRUNNEL_DYNARRAY_LEN(&obj->sigident); return result; } int signed_tree_head_v1_clear_errors(signed_tree_head_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t signed_tree_head_v1_encode(uint8_t *output, const size_t avail, const signed_tree_head_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = signed_tree_head_v1_encoded_len(obj); #endif if (NULL != (msg = signed_tree_head_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 format IN [T_SIGNED_TREE_HEAD_V1] */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->format)); written += 8; ptr += 8; /* Encode u64 timestamp */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->timestamp)); written += 8; ptr += 8; /* Encode u64 tree_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->tree_size)); written += 8; ptr += 8; /* Encode u8 root_hash[32] */ trunnel_assert(written <= avail); if (avail - written < 32) goto truncated; memcpy(ptr, obj->root_hash, 32); written += 32; ptr += 32; /* Encode u64 length */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->length)); written += 8; ptr += 8; /* Encode u8 sigident[length] */ { size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sigident); trunnel_assert(obj->length == elt_len); trunnel_assert(written <= avail); if (avail - written < elt_len) goto truncated; if (elt_len) memcpy(ptr, obj->sigident.elts_, elt_len); written += elt_len; ptr += elt_len; } trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As signed_tree_head_v1_parse(), but do not allocate the output * object. */ static ssize_t signed_tree_head_v1_parse_into(signed_tree_head_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 format IN [T_SIGNED_TREE_HEAD_V1] */ CHECK_REMAINING(8, truncated); obj->format = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; if (! (obj->format == T_SIGNED_TREE_HEAD_V1)) goto fail; /* Parse u64 timestamp */ CHECK_REMAINING(8, truncated); obj->timestamp = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u64 tree_size */ CHECK_REMAINING(8, truncated); obj->tree_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u8 root_hash[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->root_hash, ptr, 32); remaining -= 32; ptr += 32; /* Parse u64 length */ CHECK_REMAINING(8, truncated); obj->length = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u8 sigident[length] */ CHECK_REMAINING(obj->length, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sigident, obj->length, {}); obj->sigident.n_ = obj->length; if (obj->length) memcpy(obj->sigident.elts_, ptr, obj->length); ptr += obj->length; remaining -= obj->length; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; fail: result = -1; return result; } ssize_t signed_tree_head_v1_parse(signed_tree_head_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = signed_tree_head_v1_new(); if (NULL == *output) return -1; result = signed_tree_head_v1_parse_into(*output, input, len_in); if (result < 0) { signed_tree_head_v1_free(*output); *output = NULL; } return result; } consistency_proof_v1_t * consistency_proof_v1_new(void) { consistency_proof_v1_t *val = trunnel_calloc(1, sizeof(consistency_proof_v1_t)); if (NULL == val) return NULL; val->format = T_CONSISTENCY_PROOF_V1; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void consistency_proof_v1_clear(consistency_proof_v1_t *obj) { (void) obj; ed25519_v1_free(obj->identifier); obj->identifier = NULL; TRUNNEL_DYNARRAY_WIPE(&obj->hashes); TRUNNEL_DYNARRAY_CLEAR(&obj->hashes); } void consistency_proof_v1_free(consistency_proof_v1_t *obj) { if (obj == NULL) return; consistency_proof_v1_clear(obj); trunnel_memwipe(obj, sizeof(consistency_proof_v1_t)); trunnel_free_(obj); } uint64_t consistency_proof_v1_get_format(const consistency_proof_v1_t *inp) { return inp->format; } int consistency_proof_v1_set_format(consistency_proof_v1_t *inp, uint64_t val) { if (! ((val == T_CONSISTENCY_PROOF_V1))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } inp->format = val; return 0; } struct ed25519_v1_st * consistency_proof_v1_get_identifier(consistency_proof_v1_t *inp) { return inp->identifier; } const struct ed25519_v1_st * consistency_proof_v1_getconst_identifier(const consistency_proof_v1_t *inp) { return consistency_proof_v1_get_identifier((consistency_proof_v1_t*) inp); } int consistency_proof_v1_set_identifier(consistency_proof_v1_t *inp, struct ed25519_v1_st *val) { if (inp->identifier && inp->identifier != val) ed25519_v1_free(inp->identifier); return consistency_proof_v1_set0_identifier(inp, val); } int consistency_proof_v1_set0_identifier(consistency_proof_v1_t *inp, struct ed25519_v1_st *val) { inp->identifier = val; return 0; } uint64_t consistency_proof_v1_get_old_size(const consistency_proof_v1_t *inp) { return inp->old_size; } int consistency_proof_v1_set_old_size(consistency_proof_v1_t *inp, uint64_t val) { inp->old_size = val; return 0; } uint64_t consistency_proof_v1_get_new_size(const consistency_proof_v1_t *inp) { return inp->new_size; } int consistency_proof_v1_set_new_size(consistency_proof_v1_t *inp, uint64_t val) { inp->new_size = val; return 0; } uint64_t consistency_proof_v1_get_length(const consistency_proof_v1_t *inp) { return inp->length; } int consistency_proof_v1_set_length(consistency_proof_v1_t *inp, uint64_t val) { inp->length = val; return 0; } size_t consistency_proof_v1_getlen_hashes(const consistency_proof_v1_t *inp) { return TRUNNEL_DYNARRAY_LEN(&inp->hashes); } uint8_t consistency_proof_v1_get_hashes(consistency_proof_v1_t *inp, size_t idx) { return TRUNNEL_DYNARRAY_GET(&inp->hashes, idx); } uint8_t consistency_proof_v1_getconst_hashes(const consistency_proof_v1_t *inp, size_t idx) { return consistency_proof_v1_get_hashes((consistency_proof_v1_t*)inp, idx); } int consistency_proof_v1_set_hashes(consistency_proof_v1_t *inp, size_t idx, uint8_t elt) { TRUNNEL_DYNARRAY_SET(&inp->hashes, idx, elt); return 0; } int consistency_proof_v1_add_hashes(consistency_proof_v1_t *inp, uint8_t elt) { #if SIZE_MAX >= UINT64_MAX if (inp->hashes.n_ == UINT64_MAX) goto trunnel_alloc_failed; #endif TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->hashes, elt, {}); return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } uint8_t * consistency_proof_v1_getarray_hashes(consistency_proof_v1_t *inp) { return inp->hashes.elts_; } const uint8_t * consistency_proof_v1_getconstarray_hashes(const consistency_proof_v1_t *inp) { return (const uint8_t *)consistency_proof_v1_getarray_hashes((consistency_proof_v1_t*)inp); } int consistency_proof_v1_setlen_hashes(consistency_proof_v1_t *inp, size_t newlen) { uint8_t *newptr; #if UINT64_MAX < SIZE_MAX if (newlen > UINT64_MAX) goto trunnel_alloc_failed; #endif newptr = trunnel_dynarray_setlen(&inp->hashes.allocated_, &inp->hashes.n_, inp->hashes.elts_, newlen, sizeof(inp->hashes.elts_[0]), (trunnel_free_fn_t) NULL, &inp->trunnel_error_code_); if (newlen != 0 && newptr == NULL) goto trunnel_alloc_failed; inp->hashes.elts_ = newptr; return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } const char * consistency_proof_v1_check(const consistency_proof_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; if (! (obj->format == T_CONSISTENCY_PROOF_V1)) return "Integer out of bounds"; { const char *msg; if (NULL != (msg = ed25519_v1_check(obj->identifier))) return msg; } if (TRUNNEL_DYNARRAY_LEN(&obj->hashes) != obj->length) return "Length mismatch for hashes"; return NULL; } ssize_t consistency_proof_v1_encoded_len(const consistency_proof_v1_t *obj) { ssize_t result = 0; if (NULL != consistency_proof_v1_check(obj)) return -1; /* Length of u64 format IN [T_CONSISTENCY_PROOF_V1] */ result += 8; /* Length of struct ed25519_v1 identifier */ result += ed25519_v1_encoded_len(obj->identifier); /* Length of u64 old_size */ result += 8; /* Length of u64 new_size */ result += 8; /* Length of u64 length */ result += 8; /* Length of u8 hashes[length] */ result += TRUNNEL_DYNARRAY_LEN(&obj->hashes); return result; } int consistency_proof_v1_clear_errors(consistency_proof_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t consistency_proof_v1_encode(uint8_t *output, const size_t avail, const consistency_proof_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = consistency_proof_v1_encoded_len(obj); #endif if (NULL != (msg = consistency_proof_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 format IN [T_CONSISTENCY_PROOF_V1] */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->format)); written += 8; ptr += 8; /* Encode struct ed25519_v1 identifier */ trunnel_assert(written <= avail); result = ed25519_v1_encode(ptr, avail - written, obj->identifier); if (result < 0) goto fail; /* XXXXXXX !*/ written += result; ptr += result; /* Encode u64 old_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->old_size)); written += 8; ptr += 8; /* Encode u64 new_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->new_size)); written += 8; ptr += 8; /* Encode u64 length */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->length)); written += 8; ptr += 8; /* Encode u8 hashes[length] */ { size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->hashes); trunnel_assert(obj->length == elt_len); trunnel_assert(written <= avail); if (avail - written < elt_len) goto truncated; if (elt_len) memcpy(ptr, obj->hashes.elts_, elt_len); written += elt_len; ptr += elt_len; } trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As consistency_proof_v1_parse(), but do not allocate the output * object. */ static ssize_t consistency_proof_v1_parse_into(consistency_proof_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 format IN [T_CONSISTENCY_PROOF_V1] */ CHECK_REMAINING(8, truncated); obj->format = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; if (! (obj->format == T_CONSISTENCY_PROOF_V1)) goto fail; /* Parse struct ed25519_v1 identifier */ result = ed25519_v1_parse(&obj->identifier, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; /* Parse u64 old_size */ CHECK_REMAINING(8, truncated); obj->old_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u64 new_size */ CHECK_REMAINING(8, truncated); obj->new_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u64 length */ CHECK_REMAINING(8, truncated); obj->length = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u8 hashes[length] */ CHECK_REMAINING(obj->length, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->hashes, obj->length, {}); obj->hashes.n_ = obj->length; if (obj->length) memcpy(obj->hashes.elts_, ptr, obj->length); ptr += obj->length; remaining -= obj->length; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; relay_fail: trunnel_assert(result < 0); return result; trunnel_alloc_failed: return -1; fail: result = -1; return result; } ssize_t consistency_proof_v1_parse(consistency_proof_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = consistency_proof_v1_new(); if (NULL == *output) return -1; result = consistency_proof_v1_parse_into(*output, input, len_in); if (result < 0) { consistency_proof_v1_free(*output); *output = NULL; } return result; } inclusion_proof_v1_t * inclusion_proof_v1_new(void) { inclusion_proof_v1_t *val = trunnel_calloc(1, sizeof(inclusion_proof_v1_t)); if (NULL == val) return NULL; val->format = T_INCLUSION_PROOF_V1; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void inclusion_proof_v1_clear(inclusion_proof_v1_t *obj) { (void) obj; ed25519_v1_free(obj->identifier); obj->identifier = NULL; TRUNNEL_DYNARRAY_WIPE(&obj->hashes); TRUNNEL_DYNARRAY_CLEAR(&obj->hashes); } void inclusion_proof_v1_free(inclusion_proof_v1_t *obj) { if (obj == NULL) return; inclusion_proof_v1_clear(obj); trunnel_memwipe(obj, sizeof(inclusion_proof_v1_t)); trunnel_free_(obj); } uint64_t inclusion_proof_v1_get_format(const inclusion_proof_v1_t *inp) { return inp->format; } int inclusion_proof_v1_set_format(inclusion_proof_v1_t *inp, uint64_t val) { if (! ((val == T_INCLUSION_PROOF_V1))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } inp->format = val; return 0; } struct ed25519_v1_st * inclusion_proof_v1_get_identifier(inclusion_proof_v1_t *inp) { return inp->identifier; } const struct ed25519_v1_st * inclusion_proof_v1_getconst_identifier(const inclusion_proof_v1_t *inp) { return inclusion_proof_v1_get_identifier((inclusion_proof_v1_t*) inp); } int inclusion_proof_v1_set_identifier(inclusion_proof_v1_t *inp, struct ed25519_v1_st *val) { if (inp->identifier && inp->identifier != val) ed25519_v1_free(inp->identifier); return inclusion_proof_v1_set0_identifier(inp, val); } int inclusion_proof_v1_set0_identifier(inclusion_proof_v1_t *inp, struct ed25519_v1_st *val) { inp->identifier = val; return 0; } uint64_t inclusion_proof_v1_get_tree_size(const inclusion_proof_v1_t *inp) { return inp->tree_size; } int inclusion_proof_v1_set_tree_size(inclusion_proof_v1_t *inp, uint64_t val) { inp->tree_size = val; return 0; } uint64_t inclusion_proof_v1_get_leaf_index(const inclusion_proof_v1_t *inp) { return inp->leaf_index; } int inclusion_proof_v1_set_leaf_index(inclusion_proof_v1_t *inp, uint64_t val) { inp->leaf_index = val; return 0; } uint64_t inclusion_proof_v1_get_length(const inclusion_proof_v1_t *inp) { return inp->length; } int inclusion_proof_v1_set_length(inclusion_proof_v1_t *inp, uint64_t val) { inp->length = val; return 0; } size_t inclusion_proof_v1_getlen_hashes(const inclusion_proof_v1_t *inp) { return TRUNNEL_DYNARRAY_LEN(&inp->hashes); } uint8_t inclusion_proof_v1_get_hashes(inclusion_proof_v1_t *inp, size_t idx) { return TRUNNEL_DYNARRAY_GET(&inp->hashes, idx); } uint8_t inclusion_proof_v1_getconst_hashes(const inclusion_proof_v1_t *inp, size_t idx) { return inclusion_proof_v1_get_hashes((inclusion_proof_v1_t*)inp, idx); } int inclusion_proof_v1_set_hashes(inclusion_proof_v1_t *inp, size_t idx, uint8_t elt) { TRUNNEL_DYNARRAY_SET(&inp->hashes, idx, elt); return 0; } int inclusion_proof_v1_add_hashes(inclusion_proof_v1_t *inp, uint8_t elt) { #if SIZE_MAX >= UINT64_MAX if (inp->hashes.n_ == UINT64_MAX) goto trunnel_alloc_failed; #endif TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->hashes, elt, {}); return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } uint8_t * inclusion_proof_v1_getarray_hashes(inclusion_proof_v1_t *inp) { return inp->hashes.elts_; } const uint8_t * inclusion_proof_v1_getconstarray_hashes(const inclusion_proof_v1_t *inp) { return (const uint8_t *)inclusion_proof_v1_getarray_hashes((inclusion_proof_v1_t*)inp); } int inclusion_proof_v1_setlen_hashes(inclusion_proof_v1_t *inp, size_t newlen) { uint8_t *newptr; #if UINT64_MAX < SIZE_MAX if (newlen > UINT64_MAX) goto trunnel_alloc_failed; #endif newptr = trunnel_dynarray_setlen(&inp->hashes.allocated_, &inp->hashes.n_, inp->hashes.elts_, newlen, sizeof(inp->hashes.elts_[0]), (trunnel_free_fn_t) NULL, &inp->trunnel_error_code_); if (newlen != 0 && newptr == NULL) goto trunnel_alloc_failed; inp->hashes.elts_ = newptr; return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } const char * inclusion_proof_v1_check(const inclusion_proof_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; if (! (obj->format == T_INCLUSION_PROOF_V1)) return "Integer out of bounds"; { const char *msg; if (NULL != (msg = ed25519_v1_check(obj->identifier))) return msg; } if (TRUNNEL_DYNARRAY_LEN(&obj->hashes) != obj->length) return "Length mismatch for hashes"; return NULL; } ssize_t inclusion_proof_v1_encoded_len(const inclusion_proof_v1_t *obj) { ssize_t result = 0; if (NULL != inclusion_proof_v1_check(obj)) return -1; /* Length of u64 format IN [T_INCLUSION_PROOF_V1] */ result += 8; /* Length of struct ed25519_v1 identifier */ result += ed25519_v1_encoded_len(obj->identifier); /* Length of u64 tree_size */ result += 8; /* Length of u64 leaf_index */ result += 8; /* Length of u64 length */ result += 8; /* Length of u8 hashes[length] */ result += TRUNNEL_DYNARRAY_LEN(&obj->hashes); return result; } int inclusion_proof_v1_clear_errors(inclusion_proof_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t inclusion_proof_v1_encode(uint8_t *output, const size_t avail, const inclusion_proof_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = inclusion_proof_v1_encoded_len(obj); #endif if (NULL != (msg = inclusion_proof_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 format IN [T_INCLUSION_PROOF_V1] */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->format)); written += 8; ptr += 8; /* Encode struct ed25519_v1 identifier */ trunnel_assert(written <= avail); result = ed25519_v1_encode(ptr, avail - written, obj->identifier); if (result < 0) goto fail; /* XXXXXXX !*/ written += result; ptr += result; /* Encode u64 tree_size */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->tree_size)); written += 8; ptr += 8; /* Encode u64 leaf_index */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->leaf_index)); written += 8; ptr += 8; /* Encode u64 length */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->length)); written += 8; ptr += 8; /* Encode u8 hashes[length] */ { size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->hashes); trunnel_assert(obj->length == elt_len); trunnel_assert(written <= avail); if (avail - written < elt_len) goto truncated; if (elt_len) memcpy(ptr, obj->hashes.elts_, elt_len); written += elt_len; ptr += elt_len; } trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As inclusion_proof_v1_parse(), but do not allocate the output * object. */ static ssize_t inclusion_proof_v1_parse_into(inclusion_proof_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 format IN [T_INCLUSION_PROOF_V1] */ CHECK_REMAINING(8, truncated); obj->format = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; if (! (obj->format == T_INCLUSION_PROOF_V1)) goto fail; /* Parse struct ed25519_v1 identifier */ result = ed25519_v1_parse(&obj->identifier, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; /* Parse u64 tree_size */ CHECK_REMAINING(8, truncated); obj->tree_size = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u64 leaf_index */ CHECK_REMAINING(8, truncated); obj->leaf_index = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u64 length */ CHECK_REMAINING(8, truncated); obj->length = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; /* Parse u8 hashes[length] */ CHECK_REMAINING(obj->length, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->hashes, obj->length, {}); obj->hashes.n_ = obj->length; if (obj->length) memcpy(obj->hashes.elts_, ptr, obj->length); ptr += obj->length; remaining -= obj->length; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; relay_fail: trunnel_assert(result < 0); return result; trunnel_alloc_failed: return -1; fail: result = -1; return result; } ssize_t inclusion_proof_v1_parse(inclusion_proof_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = inclusion_proof_v1_new(); if (NULL == *output) return -1; result = inclusion_proof_v1_parse_into(*output, input, len_in); if (result < 0) { inclusion_proof_v1_free(*output); *output = NULL; } return result; } request_v1_t * request_v1_new(void) { request_v1_t *val = trunnel_calloc(1, sizeof(request_v1_t)); if (NULL == val) return NULL; val->format = T_GET_CONSISTENCY_PROOF_V1; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void request_v1_clear(request_v1_t *obj) { (void) obj; req_get_entries_v1_free(obj->request_get_entries); obj->request_get_entries = NULL; req_get_proof_by_hash_v1_free(obj->request_get_proof_by_hash); obj->request_get_proof_by_hash = NULL; req_get_consistency_proof_v1_free(obj->request_get_consistency_proof); obj->request_get_consistency_proof = NULL; } void request_v1_free(request_v1_t *obj) { if (obj == NULL) return; request_v1_clear(obj); trunnel_memwipe(obj, sizeof(request_v1_t)); trunnel_free_(obj); } uint64_t request_v1_get_format(const request_v1_t *inp) { return inp->format; } int request_v1_set_format(request_v1_t *inp, uint64_t val) { if (! ((val == T_GET_CONSISTENCY_PROOF_V1 || val == T_GET_ENTRIES_V1 || val == T_GET_PROOF_BY_HASH_V1))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } inp->format = val; return 0; } struct req_get_entries_v1_st * request_v1_get_request_get_entries(request_v1_t *inp) { return inp->request_get_entries; } const struct req_get_entries_v1_st * request_v1_getconst_request_get_entries(const request_v1_t *inp) { return request_v1_get_request_get_entries((request_v1_t*) inp); } int request_v1_set_request_get_entries(request_v1_t *inp, struct req_get_entries_v1_st *val) { if (inp->request_get_entries && inp->request_get_entries != val) req_get_entries_v1_free(inp->request_get_entries); return request_v1_set0_request_get_entries(inp, val); } int request_v1_set0_request_get_entries(request_v1_t *inp, struct req_get_entries_v1_st *val) { inp->request_get_entries = val; return 0; } struct req_get_proof_by_hash_v1_st * request_v1_get_request_get_proof_by_hash(request_v1_t *inp) { return inp->request_get_proof_by_hash; } const struct req_get_proof_by_hash_v1_st * request_v1_getconst_request_get_proof_by_hash(const request_v1_t *inp) { return request_v1_get_request_get_proof_by_hash((request_v1_t*) inp); } int request_v1_set_request_get_proof_by_hash(request_v1_t *inp, struct req_get_proof_by_hash_v1_st *val) { if (inp->request_get_proof_by_hash && inp->request_get_proof_by_hash != val) req_get_proof_by_hash_v1_free(inp->request_get_proof_by_hash); return request_v1_set0_request_get_proof_by_hash(inp, val); } int request_v1_set0_request_get_proof_by_hash(request_v1_t *inp, struct req_get_proof_by_hash_v1_st *val) { inp->request_get_proof_by_hash = val; return 0; } struct req_get_consistency_proof_v1_st * request_v1_get_request_get_consistency_proof(request_v1_t *inp) { return inp->request_get_consistency_proof; } const struct req_get_consistency_proof_v1_st * request_v1_getconst_request_get_consistency_proof(const request_v1_t *inp) { return request_v1_get_request_get_consistency_proof((request_v1_t*) inp); } int request_v1_set_request_get_consistency_proof(request_v1_t *inp, struct req_get_consistency_proof_v1_st *val) { if (inp->request_get_consistency_proof && inp->request_get_consistency_proof != val) req_get_consistency_proof_v1_free(inp->request_get_consistency_proof); return request_v1_set0_request_get_consistency_proof(inp, val); } int request_v1_set0_request_get_consistency_proof(request_v1_t *inp, struct req_get_consistency_proof_v1_st *val) { inp->request_get_consistency_proof = val; return 0; } const char * request_v1_check(const request_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; if (! (obj->format == T_GET_CONSISTENCY_PROOF_V1 || obj->format == T_GET_ENTRIES_V1 || obj->format == T_GET_PROOF_BY_HASH_V1)) return "Integer out of bounds"; switch (obj->format) { case T_GET_ENTRIES_V1: { const char *msg; if (NULL != (msg = req_get_entries_v1_check(obj->request_get_entries))) return msg; } break; case T_GET_PROOF_BY_HASH_V1: { const char *msg; if (NULL != (msg = req_get_proof_by_hash_v1_check(obj->request_get_proof_by_hash))) return msg; } break; case T_GET_CONSISTENCY_PROOF_V1: { const char *msg; if (NULL != (msg = req_get_consistency_proof_v1_check(obj->request_get_consistency_proof))) return msg; } break; default: return "Bad tag for union"; break; } return NULL; } ssize_t request_v1_encoded_len(const request_v1_t *obj) { ssize_t result = 0; if (NULL != request_v1_check(obj)) return -1; /* Length of u64 format IN [T_GET_CONSISTENCY_PROOF_V1, T_GET_ENTRIES_V1, T_GET_PROOF_BY_HASH_V1] */ result += 8; switch (obj->format) { case T_GET_ENTRIES_V1: /* Length of struct req_get_entries_v1 request_get_entries */ result += req_get_entries_v1_encoded_len(obj->request_get_entries); break; case T_GET_PROOF_BY_HASH_V1: /* Length of struct req_get_proof_by_hash_v1 request_get_proof_by_hash */ result += req_get_proof_by_hash_v1_encoded_len(obj->request_get_proof_by_hash); break; case T_GET_CONSISTENCY_PROOF_V1: /* Length of struct req_get_consistency_proof_v1 request_get_consistency_proof */ result += req_get_consistency_proof_v1_encoded_len(obj->request_get_consistency_proof); break; default: trunnel_assert(0); break; } return result; } int request_v1_clear_errors(request_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t request_v1_encode(uint8_t *output, const size_t avail, const request_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = request_v1_encoded_len(obj); #endif if (NULL != (msg = request_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 format IN [T_GET_CONSISTENCY_PROOF_V1, T_GET_ENTRIES_V1, T_GET_PROOF_BY_HASH_V1] */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->format)); written += 8; ptr += 8; /* Encode union request[format] */ trunnel_assert(written <= avail); switch (obj->format) { case T_GET_ENTRIES_V1: /* Encode struct req_get_entries_v1 request_get_entries */ trunnel_assert(written <= avail); result = req_get_entries_v1_encode(ptr, avail - written, obj->request_get_entries); if (result < 0) goto fail; /* XXXXXXX !*/ written += result; ptr += result; break; case T_GET_PROOF_BY_HASH_V1: /* Encode struct req_get_proof_by_hash_v1 request_get_proof_by_hash */ trunnel_assert(written <= avail); result = req_get_proof_by_hash_v1_encode(ptr, avail - written, obj->request_get_proof_by_hash); if (result < 0) goto fail; /* XXXXXXX !*/ written += result; ptr += result; break; case T_GET_CONSISTENCY_PROOF_V1: /* Encode struct req_get_consistency_proof_v1 request_get_consistency_proof */ trunnel_assert(written <= avail); result = req_get_consistency_proof_v1_encode(ptr, avail - written, obj->request_get_consistency_proof); if (result < 0) goto fail; /* XXXXXXX !*/ written += result; ptr += result; break; default: trunnel_assert(0); break; } trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As request_v1_parse(), but do not allocate the output object. */ static ssize_t request_v1_parse_into(request_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 format IN [T_GET_CONSISTENCY_PROOF_V1, T_GET_ENTRIES_V1, T_GET_PROOF_BY_HASH_V1] */ CHECK_REMAINING(8, truncated); obj->format = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; if (! (obj->format == T_GET_CONSISTENCY_PROOF_V1 || obj->format == T_GET_ENTRIES_V1 || obj->format == T_GET_PROOF_BY_HASH_V1)) goto fail; /* Parse union request[format] */ switch (obj->format) { case T_GET_ENTRIES_V1: /* Parse struct req_get_entries_v1 request_get_entries */ result = req_get_entries_v1_parse(&obj->request_get_entries, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; break; case T_GET_PROOF_BY_HASH_V1: /* Parse struct req_get_proof_by_hash_v1 request_get_proof_by_hash */ result = req_get_proof_by_hash_v1_parse(&obj->request_get_proof_by_hash, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; break; case T_GET_CONSISTENCY_PROOF_V1: /* Parse struct req_get_consistency_proof_v1 request_get_consistency_proof */ result = req_get_consistency_proof_v1_parse(&obj->request_get_consistency_proof, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; break; default: goto fail; break; } trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; relay_fail: trunnel_assert(result < 0); return result; fail: result = -1; return result; } ssize_t request_v1_parse(request_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = request_v1_new(); if (NULL == *output) return -1; result = request_v1_parse_into(*output, input, len_in); if (result < 0) { request_v1_free(*output); *output = NULL; } return result; } signed_checksum32_ed25519_v1_t * signed_checksum32_ed25519_v1_new(void) { signed_checksum32_ed25519_v1_t *val = trunnel_calloc(1, sizeof(signed_checksum32_ed25519_v1_t)); if (NULL == val) return NULL; val->format = T_SIGNED_CHECKSUM32_ED25519_V1; val->length = 1; return val; } /** Release all storage held inside 'obj', but do not free 'obj'. */ static void signed_checksum32_ed25519_v1_clear(signed_checksum32_ed25519_v1_t *obj) { (void) obj; TRUNNEL_DYNARRAY_WIPE(&obj->identifier); TRUNNEL_DYNARRAY_CLEAR(&obj->identifier); ed25519_v1_free(obj->namespace); obj->namespace = NULL; } void signed_checksum32_ed25519_v1_free(signed_checksum32_ed25519_v1_t *obj) { if (obj == NULL) return; signed_checksum32_ed25519_v1_clear(obj); trunnel_memwipe(obj, sizeof(signed_checksum32_ed25519_v1_t)); trunnel_free_(obj); } uint64_t signed_checksum32_ed25519_v1_get_format(const signed_checksum32_ed25519_v1_t *inp) { return inp->format; } int signed_checksum32_ed25519_v1_set_format(signed_checksum32_ed25519_v1_t *inp, uint64_t val) { if (! ((val == T_SIGNED_CHECKSUM32_ED25519_V1))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } inp->format = val; return 0; } size_t signed_checksum32_ed25519_v1_getlen_checksum(const signed_checksum32_ed25519_v1_t *inp) { (void)inp; return 32; } uint8_t signed_checksum32_ed25519_v1_get_checksum(signed_checksum32_ed25519_v1_t *inp, size_t idx) { trunnel_assert(idx < 32); return inp->checksum[idx]; } uint8_t signed_checksum32_ed25519_v1_getconst_checksum(const signed_checksum32_ed25519_v1_t *inp, size_t idx) { return signed_checksum32_ed25519_v1_get_checksum((signed_checksum32_ed25519_v1_t*)inp, idx); } int signed_checksum32_ed25519_v1_set_checksum(signed_checksum32_ed25519_v1_t *inp, size_t idx, uint8_t elt) { trunnel_assert(idx < 32); inp->checksum[idx] = elt; return 0; } uint8_t * signed_checksum32_ed25519_v1_getarray_checksum(signed_checksum32_ed25519_v1_t *inp) { return inp->checksum; } const uint8_t * signed_checksum32_ed25519_v1_getconstarray_checksum(const signed_checksum32_ed25519_v1_t *inp) { return (const uint8_t *)signed_checksum32_ed25519_v1_getarray_checksum((signed_checksum32_ed25519_v1_t*)inp); } uint64_t signed_checksum32_ed25519_v1_get_length(const signed_checksum32_ed25519_v1_t *inp) { return inp->length; } int signed_checksum32_ed25519_v1_set_length(signed_checksum32_ed25519_v1_t *inp, uint64_t val) { if (! (((val >= 1 && val <= 127)))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } inp->length = val; return 0; } size_t signed_checksum32_ed25519_v1_getlen_identifier(const signed_checksum32_ed25519_v1_t *inp) { return TRUNNEL_DYNARRAY_LEN(&inp->identifier); } uint8_t signed_checksum32_ed25519_v1_get_identifier(signed_checksum32_ed25519_v1_t *inp, size_t idx) { return TRUNNEL_DYNARRAY_GET(&inp->identifier, idx); } uint8_t signed_checksum32_ed25519_v1_getconst_identifier(const signed_checksum32_ed25519_v1_t *inp, size_t idx) { return signed_checksum32_ed25519_v1_get_identifier((signed_checksum32_ed25519_v1_t*)inp, idx); } int signed_checksum32_ed25519_v1_set_identifier(signed_checksum32_ed25519_v1_t *inp, size_t idx, uint8_t elt) { TRUNNEL_DYNARRAY_SET(&inp->identifier, idx, elt); return 0; } int signed_checksum32_ed25519_v1_add_identifier(signed_checksum32_ed25519_v1_t *inp, uint8_t elt) { #if SIZE_MAX >= UINT64_MAX if (inp->identifier.n_ == UINT64_MAX) goto trunnel_alloc_failed; #endif TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->identifier, elt, {}); return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } uint8_t * signed_checksum32_ed25519_v1_getarray_identifier(signed_checksum32_ed25519_v1_t *inp) { return inp->identifier.elts_; } const uint8_t * signed_checksum32_ed25519_v1_getconstarray_identifier(const signed_checksum32_ed25519_v1_t *inp) { return (const uint8_t *)signed_checksum32_ed25519_v1_getarray_identifier((signed_checksum32_ed25519_v1_t*)inp); } int signed_checksum32_ed25519_v1_setlen_identifier(signed_checksum32_ed25519_v1_t *inp, size_t newlen) { uint8_t *newptr; #if UINT64_MAX < SIZE_MAX if (newlen > UINT64_MAX) goto trunnel_alloc_failed; #endif newptr = trunnel_dynarray_setlen(&inp->identifier.allocated_, &inp->identifier.n_, inp->identifier.elts_, newlen, sizeof(inp->identifier.elts_[0]), (trunnel_free_fn_t) NULL, &inp->trunnel_error_code_); if (newlen != 0 && newptr == NULL) goto trunnel_alloc_failed; inp->identifier.elts_ = newptr; return 0; trunnel_alloc_failed: TRUNNEL_SET_ERROR_CODE(inp); return -1; } size_t signed_checksum32_ed25519_v1_getlen_signature(const signed_checksum32_ed25519_v1_t *inp) { (void)inp; return 64; } uint8_t signed_checksum32_ed25519_v1_get_signature(signed_checksum32_ed25519_v1_t *inp, size_t idx) { trunnel_assert(idx < 64); return inp->signature[idx]; } uint8_t signed_checksum32_ed25519_v1_getconst_signature(const signed_checksum32_ed25519_v1_t *inp, size_t idx) { return signed_checksum32_ed25519_v1_get_signature((signed_checksum32_ed25519_v1_t*)inp, idx); } int signed_checksum32_ed25519_v1_set_signature(signed_checksum32_ed25519_v1_t *inp, size_t idx, uint8_t elt) { trunnel_assert(idx < 64); inp->signature[idx] = elt; return 0; } uint8_t * signed_checksum32_ed25519_v1_getarray_signature(signed_checksum32_ed25519_v1_t *inp) { return inp->signature; } const uint8_t * signed_checksum32_ed25519_v1_getconstarray_signature(const signed_checksum32_ed25519_v1_t *inp) { return (const uint8_t *)signed_checksum32_ed25519_v1_getarray_signature((signed_checksum32_ed25519_v1_t*)inp); } struct ed25519_v1_st * signed_checksum32_ed25519_v1_get_namespace(signed_checksum32_ed25519_v1_t *inp) { return inp->namespace; } const struct ed25519_v1_st * signed_checksum32_ed25519_v1_getconst_namespace(const signed_checksum32_ed25519_v1_t *inp) { return signed_checksum32_ed25519_v1_get_namespace((signed_checksum32_ed25519_v1_t*) inp); } int signed_checksum32_ed25519_v1_set_namespace(signed_checksum32_ed25519_v1_t *inp, struct ed25519_v1_st *val) { if (inp->namespace && inp->namespace != val) ed25519_v1_free(inp->namespace); return signed_checksum32_ed25519_v1_set0_namespace(inp, val); } int signed_checksum32_ed25519_v1_set0_namespace(signed_checksum32_ed25519_v1_t *inp, struct ed25519_v1_st *val) { inp->namespace = val; return 0; } const char * signed_checksum32_ed25519_v1_check(const signed_checksum32_ed25519_v1_t *obj) { if (obj == NULL) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; if (! (obj->format == T_SIGNED_CHECKSUM32_ED25519_V1)) return "Integer out of bounds"; if (! ((obj->length >= 1 && obj->length <= 127))) return "Integer out of bounds"; if (TRUNNEL_DYNARRAY_LEN(&obj->identifier) != obj->length) return "Length mismatch for identifier"; { const char *msg; if (NULL != (msg = ed25519_v1_check(obj->namespace))) return msg; } return NULL; } ssize_t signed_checksum32_ed25519_v1_encoded_len(const signed_checksum32_ed25519_v1_t *obj) { ssize_t result = 0; if (NULL != signed_checksum32_ed25519_v1_check(obj)) return -1; /* Length of u64 format IN [T_SIGNED_CHECKSUM32_ED25519_V1] */ result += 8; /* Length of u8 checksum[32] */ result += 32; /* Length of u64 length IN [1..127] */ result += 8; /* Length of u8 identifier[length] */ result += TRUNNEL_DYNARRAY_LEN(&obj->identifier); /* Length of u8 signature[64] */ result += 64; /* Length of struct ed25519_v1 namespace */ result += ed25519_v1_encoded_len(obj->namespace); return result; } int signed_checksum32_ed25519_v1_clear_errors(signed_checksum32_ed25519_v1_t *obj) { int r = obj->trunnel_error_code_; obj->trunnel_error_code_ = 0; return r; } ssize_t signed_checksum32_ed25519_v1_encode(uint8_t *output, const size_t avail, const signed_checksum32_ed25519_v1_t *obj) { ssize_t result = 0; size_t written = 0; uint8_t *ptr = output; const char *msg; #ifdef TRUNNEL_CHECK_ENCODED_LEN const ssize_t encoded_len = signed_checksum32_ed25519_v1_encoded_len(obj); #endif if (NULL != (msg = signed_checksum32_ed25519_v1_check(obj))) goto check_failed; #ifdef TRUNNEL_CHECK_ENCODED_LEN trunnel_assert(encoded_len >= 0); #endif /* Encode u64 format IN [T_SIGNED_CHECKSUM32_ED25519_V1] */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->format)); written += 8; ptr += 8; /* Encode u8 checksum[32] */ trunnel_assert(written <= avail); if (avail - written < 32) goto truncated; memcpy(ptr, obj->checksum, 32); written += 32; ptr += 32; /* Encode u64 length IN [1..127] */ trunnel_assert(written <= avail); if (avail - written < 8) goto truncated; trunnel_set_uint64(ptr, trunnel_htonll(obj->length)); written += 8; ptr += 8; /* Encode u8 identifier[length] */ { size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->identifier); trunnel_assert(obj->length == elt_len); trunnel_assert(written <= avail); if (avail - written < elt_len) goto truncated; if (elt_len) memcpy(ptr, obj->identifier.elts_, elt_len); written += elt_len; ptr += elt_len; } /* Encode u8 signature[64] */ trunnel_assert(written <= avail); if (avail - written < 64) goto truncated; memcpy(ptr, obj->signature, 64); written += 64; ptr += 64; /* Encode struct ed25519_v1 namespace */ trunnel_assert(written <= avail); result = ed25519_v1_encode(ptr, avail - written, obj->namespace); if (result < 0) goto fail; /* XXXXXXX !*/ written += result; ptr += result; trunnel_assert(ptr == output + written); #ifdef TRUNNEL_CHECK_ENCODED_LEN { trunnel_assert(encoded_len >= 0); trunnel_assert((size_t)encoded_len == written); } #endif return written; truncated: result = -2; goto fail; check_failed: (void)msg; result = -1; goto fail; fail: trunnel_assert(result < 0); return result; } /** As signed_checksum32_ed25519_v1_parse(), but do not allocate the * output object. */ static ssize_t signed_checksum32_ed25519_v1_parse_into(signed_checksum32_ed25519_v1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u64 format IN [T_SIGNED_CHECKSUM32_ED25519_V1] */ CHECK_REMAINING(8, truncated); obj->format = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; if (! (obj->format == T_SIGNED_CHECKSUM32_ED25519_V1)) goto fail; /* Parse u8 checksum[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->checksum, ptr, 32); remaining -= 32; ptr += 32; /* Parse u64 length IN [1..127] */ CHECK_REMAINING(8, truncated); obj->length = trunnel_ntohll(trunnel_get_uint64(ptr)); remaining -= 8; ptr += 8; if (! ((obj->length >= 1 && obj->length <= 127))) goto fail; /* Parse u8 identifier[length] */ CHECK_REMAINING(obj->length, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->identifier, obj->length, {}); obj->identifier.n_ = obj->length; if (obj->length) memcpy(obj->identifier.elts_, ptr, obj->length); ptr += obj->length; remaining -= obj->length; /* Parse u8 signature[64] */ CHECK_REMAINING(64, truncated); memcpy(obj->signature, ptr, 64); remaining -= 64; ptr += 64; /* Parse struct ed25519_v1 namespace */ result = ed25519_v1_parse(&obj->namespace, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; relay_fail: trunnel_assert(result < 0); return result; trunnel_alloc_failed: return -1; fail: result = -1; return result; } ssize_t signed_checksum32_ed25519_v1_parse(signed_checksum32_ed25519_v1_t **output, const uint8_t *input, const size_t len_in) { ssize_t result; *output = signed_checksum32_ed25519_v1_new(); if (NULL == *output) return -1; result = signed_checksum32_ed25519_v1_parse_into(*output, input, len_in); if (result < 0) { signed_checksum32_ed25519_v1_free(*output); *output = NULL; } return result; }