Trunnel-side: start migrating extend/extend2 to trunnel

This commit is contained in:
Nick Mathewson 2016-09-14 15:34:13 -04:00
parent b5e75ae7dd
commit 1be671f505
3 changed files with 1230 additions and 34 deletions

View File

@ -28,6 +28,281 @@ int edcert_deadcode_dummy__ = 0;
} \
} while (0)
create2_cell_body_t *
create2_cell_body_new(void)
{
create2_cell_body_t *val = trunnel_calloc(1, sizeof(create2_cell_body_t));
if (NULL == val)
return NULL;
return val;
}
/** Release all storage held inside 'obj', but do not free 'obj'.
*/
static void
create2_cell_body_clear(create2_cell_body_t *obj)
{
(void) obj;
TRUNNEL_DYNARRAY_WIPE(&obj->handshake_data);
TRUNNEL_DYNARRAY_CLEAR(&obj->handshake_data);
}
void
create2_cell_body_free(create2_cell_body_t *obj)
{
if (obj == NULL)
return;
create2_cell_body_clear(obj);
trunnel_memwipe(obj, sizeof(create2_cell_body_t));
trunnel_free_(obj);
}
uint16_t
create2_cell_body_get_handshake_type(create2_cell_body_t *inp)
{
return inp->handshake_type;
}
int
create2_cell_body_set_handshake_type(create2_cell_body_t *inp, uint16_t val)
{
inp->handshake_type = val;
return 0;
}
uint16_t
create2_cell_body_get_handshake_len(create2_cell_body_t *inp)
{
return inp->handshake_len;
}
int
create2_cell_body_set_handshake_len(create2_cell_body_t *inp, uint16_t val)
{
inp->handshake_len = val;
return 0;
}
size_t
create2_cell_body_getlen_handshake_data(const create2_cell_body_t *inp)
{
return TRUNNEL_DYNARRAY_LEN(&inp->handshake_data);
}
uint8_t
create2_cell_body_get_handshake_data(create2_cell_body_t *inp, size_t idx)
{
return TRUNNEL_DYNARRAY_GET(&inp->handshake_data, idx);
}
uint8_t
create2_cell_body_getconst_handshake_data(const create2_cell_body_t *inp, size_t idx)
{
return create2_cell_body_get_handshake_data((create2_cell_body_t*)inp, idx);
}
int
create2_cell_body_set_handshake_data(create2_cell_body_t *inp, size_t idx, uint8_t elt)
{
TRUNNEL_DYNARRAY_SET(&inp->handshake_data, idx, elt);
return 0;
}
int
create2_cell_body_add_handshake_data(create2_cell_body_t *inp, uint8_t elt)
{
#if SIZE_MAX >= UINT16_MAX
if (inp->handshake_data.n_ == UINT16_MAX)
goto trunnel_alloc_failed;
#endif
TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->handshake_data, elt, {});
return 0;
trunnel_alloc_failed:
TRUNNEL_SET_ERROR_CODE(inp);
return -1;
}
uint8_t *
create2_cell_body_getarray_handshake_data(create2_cell_body_t *inp)
{
return inp->handshake_data.elts_;
}
const uint8_t *
create2_cell_body_getconstarray_handshake_data(const create2_cell_body_t *inp)
{
return (const uint8_t *)create2_cell_body_getarray_handshake_data((create2_cell_body_t*)inp);
}
int
create2_cell_body_setlen_handshake_data(create2_cell_body_t *inp, size_t newlen)
{
uint8_t *newptr;
#if UINT16_MAX < SIZE_MAX
if (newlen > UINT16_MAX)
goto trunnel_alloc_failed;
#endif
newptr = trunnel_dynarray_setlen(&inp->handshake_data.allocated_,
&inp->handshake_data.n_, inp->handshake_data.elts_, newlen,
sizeof(inp->handshake_data.elts_[0]), (trunnel_free_fn_t) NULL,
&inp->trunnel_error_code_);
if (newlen != 0 && newptr == NULL)
goto trunnel_alloc_failed;
inp->handshake_data.elts_ = newptr;
return 0;
trunnel_alloc_failed:
TRUNNEL_SET_ERROR_CODE(inp);
return -1;
}
const char *
create2_cell_body_check(const create2_cell_body_t *obj)
{
if (obj == NULL)
return "Object was NULL";
if (obj->trunnel_error_code_)
return "A set function failed on this object";
if (TRUNNEL_DYNARRAY_LEN(&obj->handshake_data) != obj->handshake_len)
return "Length mismatch for handshake_data";
return NULL;
}
ssize_t
create2_cell_body_encoded_len(const create2_cell_body_t *obj)
{
ssize_t result = 0;
if (NULL != create2_cell_body_check(obj))
return -1;
/* Length of u16 handshake_type */
result += 2;
/* Length of u16 handshake_len */
result += 2;
/* Length of u8 handshake_data[handshake_len] */
result += TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
return result;
}
int
create2_cell_body_clear_errors(create2_cell_body_t *obj)
{
int r = obj->trunnel_error_code_;
obj->trunnel_error_code_ = 0;
return r;
}
ssize_t
create2_cell_body_encode(uint8_t *output, const size_t avail, const create2_cell_body_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 = create2_cell_body_encoded_len(obj);
#endif
if (NULL != (msg = create2_cell_body_check(obj)))
goto check_failed;
#ifdef TRUNNEL_CHECK_ENCODED_LEN
trunnel_assert(encoded_len >= 0);
#endif
/* Encode u16 handshake_type */
trunnel_assert(written <= avail);
if (avail - written < 2)
goto truncated;
trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_type));
written += 2; ptr += 2;
/* Encode u16 handshake_len */
trunnel_assert(written <= avail);
if (avail - written < 2)
goto truncated;
trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_len));
written += 2; ptr += 2;
/* Encode u8 handshake_data[handshake_len] */
{
size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
trunnel_assert(obj->handshake_len == elt_len);
trunnel_assert(written <= avail);
if (avail - written < elt_len)
goto truncated;
if (elt_len)
memcpy(ptr, obj->handshake_data.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 create2_cell_body_parse(), but do not allocate the output
* object.
*/
static ssize_t
create2_cell_body_parse_into(create2_cell_body_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 u16 handshake_type */
CHECK_REMAINING(2, truncated);
obj->handshake_type = trunnel_ntohs(trunnel_get_uint16(ptr));
remaining -= 2; ptr += 2;
/* Parse u16 handshake_len */
CHECK_REMAINING(2, truncated);
obj->handshake_len = trunnel_ntohs(trunnel_get_uint16(ptr));
remaining -= 2; ptr += 2;
/* Parse u8 handshake_data[handshake_len] */
CHECK_REMAINING(obj->handshake_len, truncated);
TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->handshake_data, obj->handshake_len, {});
obj->handshake_data.n_ = obj->handshake_len;
if (obj->handshake_len)
memcpy(obj->handshake_data.elts_, ptr, obj->handshake_len);
ptr += obj->handshake_len; remaining -= obj->handshake_len;
trunnel_assert(ptr + remaining == input + len_in);
return len_in - remaining;
truncated:
return -2;
trunnel_alloc_failed:
return -1;
}
ssize_t
create2_cell_body_parse(create2_cell_body_t **output, const uint8_t *input, const size_t len_in)
{
ssize_t result;
*output = create2_cell_body_new();
if (NULL == *output)
return -1;
result = create2_cell_body_parse_into(*output, input, len_in);
if (result < 0) {
create2_cell_body_free(*output);
*output = NULL;
}
return result;
}
ed25519_cert_extension_t *
ed25519_cert_extension_new(void)
{
@ -430,6 +705,287 @@ ed25519_cert_extension_parse(ed25519_cert_extension_t **output, const uint8_t *i
}
return result;
}
extend1_cell_body_t *
extend1_cell_body_new(void)
{
extend1_cell_body_t *val = trunnel_calloc(1, sizeof(extend1_cell_body_t));
if (NULL == val)
return NULL;
return val;
}
/** Release all storage held inside 'obj', but do not free 'obj'.
*/
static void
extend1_cell_body_clear(extend1_cell_body_t *obj)
{
(void) obj;
}
void
extend1_cell_body_free(extend1_cell_body_t *obj)
{
if (obj == NULL)
return;
extend1_cell_body_clear(obj);
trunnel_memwipe(obj, sizeof(extend1_cell_body_t));
trunnel_free_(obj);
}
uint32_t
extend1_cell_body_get_ipv4addr(extend1_cell_body_t *inp)
{
return inp->ipv4addr;
}
int
extend1_cell_body_set_ipv4addr(extend1_cell_body_t *inp, uint32_t val)
{
inp->ipv4addr = val;
return 0;
}
uint16_t
extend1_cell_body_get_port(extend1_cell_body_t *inp)
{
return inp->port;
}
int
extend1_cell_body_set_port(extend1_cell_body_t *inp, uint16_t val)
{
inp->port = val;
return 0;
}
size_t
extend1_cell_body_getlen_onionskin(const extend1_cell_body_t *inp)
{
(void)inp; return 186;
}
uint8_t
extend1_cell_body_get_onionskin(extend1_cell_body_t *inp, size_t idx)
{
trunnel_assert(idx < 186);
return inp->onionskin[idx];
}
uint8_t
extend1_cell_body_getconst_onionskin(const extend1_cell_body_t *inp, size_t idx)
{
return extend1_cell_body_get_onionskin((extend1_cell_body_t*)inp, idx);
}
int
extend1_cell_body_set_onionskin(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
{
trunnel_assert(idx < 186);
inp->onionskin[idx] = elt;
return 0;
}
uint8_t *
extend1_cell_body_getarray_onionskin(extend1_cell_body_t *inp)
{
return inp->onionskin;
}
const uint8_t *
extend1_cell_body_getconstarray_onionskin(const extend1_cell_body_t *inp)
{
return (const uint8_t *)extend1_cell_body_getarray_onionskin((extend1_cell_body_t*)inp);
}
size_t
extend1_cell_body_getlen_identity(const extend1_cell_body_t *inp)
{
(void)inp; return 20;
}
uint8_t
extend1_cell_body_get_identity(extend1_cell_body_t *inp, size_t idx)
{
trunnel_assert(idx < 20);
return inp->identity[idx];
}
uint8_t
extend1_cell_body_getconst_identity(const extend1_cell_body_t *inp, size_t idx)
{
return extend1_cell_body_get_identity((extend1_cell_body_t*)inp, idx);
}
int
extend1_cell_body_set_identity(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
{
trunnel_assert(idx < 20);
inp->identity[idx] = elt;
return 0;
}
uint8_t *
extend1_cell_body_getarray_identity(extend1_cell_body_t *inp)
{
return inp->identity;
}
const uint8_t *
extend1_cell_body_getconstarray_identity(const extend1_cell_body_t *inp)
{
return (const uint8_t *)extend1_cell_body_getarray_identity((extend1_cell_body_t*)inp);
}
const char *
extend1_cell_body_check(const extend1_cell_body_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
extend1_cell_body_encoded_len(const extend1_cell_body_t *obj)
{
ssize_t result = 0;
if (NULL != extend1_cell_body_check(obj))
return -1;
/* Length of u32 ipv4addr */
result += 4;
/* Length of u16 port */
result += 2;
/* Length of u8 onionskin[186] */
result += 186;
/* Length of u8 identity[20] */
result += 20;
return result;
}
int
extend1_cell_body_clear_errors(extend1_cell_body_t *obj)
{
int r = obj->trunnel_error_code_;
obj->trunnel_error_code_ = 0;
return r;
}
ssize_t
extend1_cell_body_encode(uint8_t *output, const size_t avail, const extend1_cell_body_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 = extend1_cell_body_encoded_len(obj);
#endif
if (NULL != (msg = extend1_cell_body_check(obj)))
goto check_failed;
#ifdef TRUNNEL_CHECK_ENCODED_LEN
trunnel_assert(encoded_len >= 0);
#endif
/* Encode u32 ipv4addr */
trunnel_assert(written <= avail);
if (avail - written < 4)
goto truncated;
trunnel_set_uint32(ptr, trunnel_htonl(obj->ipv4addr));
written += 4; ptr += 4;
/* Encode u16 port */
trunnel_assert(written <= avail);
if (avail - written < 2)
goto truncated;
trunnel_set_uint16(ptr, trunnel_htons(obj->port));
written += 2; ptr += 2;
/* Encode u8 onionskin[186] */
trunnel_assert(written <= avail);
if (avail - written < 186)
goto truncated;
memcpy(ptr, obj->onionskin, 186);
written += 186; ptr += 186;
/* Encode u8 identity[20] */
trunnel_assert(written <= avail);
if (avail - written < 20)
goto truncated;
memcpy(ptr, obj->identity, 20);
written += 20; ptr += 20;
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 extend1_cell_body_parse(), but do not allocate the output
* object.
*/
static ssize_t
extend1_cell_body_parse_into(extend1_cell_body_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 u32 ipv4addr */
CHECK_REMAINING(4, truncated);
obj->ipv4addr = trunnel_ntohl(trunnel_get_uint32(ptr));
remaining -= 4; ptr += 4;
/* Parse u16 port */
CHECK_REMAINING(2, truncated);
obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
remaining -= 2; ptr += 2;
/* Parse u8 onionskin[186] */
CHECK_REMAINING(186, truncated);
memcpy(obj->onionskin, ptr, 186);
remaining -= 186; ptr += 186;
/* Parse u8 identity[20] */
CHECK_REMAINING(20, truncated);
memcpy(obj->identity, ptr, 20);
remaining -= 20; ptr += 20;
trunnel_assert(ptr + remaining == input + len_in);
return len_in - remaining;
truncated:
return -2;
}
ssize_t
extend1_cell_body_parse(extend1_cell_body_t **output, const uint8_t *input, const size_t len_in)
{
ssize_t result;
*output = extend1_cell_body_new();
if (NULL == *output)
return -1;
result = extend1_cell_body_parse_into(*output, input, len_in);
if (result < 0) {
extend1_cell_body_free(*output);
*output = NULL;
}
return result;
}
link_specifier_t *
link_specifier_new(void)
{
@ -1528,6 +2084,343 @@ ed25519_cert_parse(ed25519_cert_t **output, const uint8_t *input, const size_t l
}
return result;
}
extend2_cell_body_t *
extend2_cell_body_new(void)
{
extend2_cell_body_t *val = trunnel_calloc(1, sizeof(extend2_cell_body_t));
if (NULL == val)
return NULL;
return val;
}
/** Release all storage held inside 'obj', but do not free 'obj'.
*/
static void
extend2_cell_body_clear(extend2_cell_body_t *obj)
{
(void) obj;
{
unsigned idx;
for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
}
}
TRUNNEL_DYNARRAY_WIPE(&obj->ls);
TRUNNEL_DYNARRAY_CLEAR(&obj->ls);
create2_cell_body_free(obj->create2);
obj->create2 = NULL;
}
void
extend2_cell_body_free(extend2_cell_body_t *obj)
{
if (obj == NULL)
return;
extend2_cell_body_clear(obj);
trunnel_memwipe(obj, sizeof(extend2_cell_body_t));
trunnel_free_(obj);
}
uint8_t
extend2_cell_body_get_n_spec(extend2_cell_body_t *inp)
{
return inp->n_spec;
}
int
extend2_cell_body_set_n_spec(extend2_cell_body_t *inp, uint8_t val)
{
inp->n_spec = val;
return 0;
}
size_t
extend2_cell_body_getlen_ls(const extend2_cell_body_t *inp)
{
return TRUNNEL_DYNARRAY_LEN(&inp->ls);
}
struct link_specifier_st *
extend2_cell_body_get_ls(extend2_cell_body_t *inp, size_t idx)
{
return TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
}
const struct link_specifier_st *
extend2_cell_body_getconst_ls(const extend2_cell_body_t *inp, size_t idx)
{
return extend2_cell_body_get_ls((extend2_cell_body_t*)inp, idx);
}
int
extend2_cell_body_set_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
{
link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
if (oldval && oldval != elt)
link_specifier_free(oldval);
return extend2_cell_body_set0_ls(inp, idx, elt);
}
int
extend2_cell_body_set0_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
{
TRUNNEL_DYNARRAY_SET(&inp->ls, idx, elt);
return 0;
}
int
extend2_cell_body_add_ls(extend2_cell_body_t *inp, struct link_specifier_st * elt)
{
#if SIZE_MAX >= UINT8_MAX
if (inp->ls.n_ == UINT8_MAX)
goto trunnel_alloc_failed;
#endif
TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->ls, elt, {});
return 0;
trunnel_alloc_failed:
TRUNNEL_SET_ERROR_CODE(inp);
return -1;
}
struct link_specifier_st * *
extend2_cell_body_getarray_ls(extend2_cell_body_t *inp)
{
return inp->ls.elts_;
}
const struct link_specifier_st * const *
extend2_cell_body_getconstarray_ls(const extend2_cell_body_t *inp)
{
return (const struct link_specifier_st * const *)extend2_cell_body_getarray_ls((extend2_cell_body_t*)inp);
}
int
extend2_cell_body_setlen_ls(extend2_cell_body_t *inp, size_t newlen)
{
struct link_specifier_st * *newptr;
#if UINT8_MAX < SIZE_MAX
if (newlen > UINT8_MAX)
goto trunnel_alloc_failed;
#endif
newptr = trunnel_dynarray_setlen(&inp->ls.allocated_,
&inp->ls.n_, inp->ls.elts_, newlen,
sizeof(inp->ls.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
&inp->trunnel_error_code_);
if (newlen != 0 && newptr == NULL)
goto trunnel_alloc_failed;
inp->ls.elts_ = newptr;
return 0;
trunnel_alloc_failed:
TRUNNEL_SET_ERROR_CODE(inp);
return -1;
}
struct create2_cell_body_st *
extend2_cell_body_get_create2(extend2_cell_body_t *inp)
{
return inp->create2;
}
const struct create2_cell_body_st *
extend2_cell_body_getconst_create2(const extend2_cell_body_t *inp)
{
return extend2_cell_body_get_create2((extend2_cell_body_t*) inp);
}
int
extend2_cell_body_set_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
{
if (inp->create2 && inp->create2 != val)
create2_cell_body_free(inp->create2);
return extend2_cell_body_set0_create2(inp, val);
}
int
extend2_cell_body_set0_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
{
inp->create2 = val;
return 0;
}
const char *
extend2_cell_body_check(const extend2_cell_body_t *obj)
{
if (obj == NULL)
return "Object was NULL";
if (obj->trunnel_error_code_)
return "A set function failed on this object";
{
const char *msg;
unsigned idx;
for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->ls, idx))))
return msg;
}
}
if (TRUNNEL_DYNARRAY_LEN(&obj->ls) != obj->n_spec)
return "Length mismatch for ls";
{
const char *msg;
if (NULL != (msg = create2_cell_body_check(obj->create2)))
return msg;
}
return NULL;
}
ssize_t
extend2_cell_body_encoded_len(const extend2_cell_body_t *obj)
{
ssize_t result = 0;
if (NULL != extend2_cell_body_check(obj))
return -1;
/* Length of u8 n_spec */
result += 1;
/* Length of struct link_specifier ls[n_spec] */
{
unsigned idx;
for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
}
}
/* Length of struct create2_cell_body create2 */
result += create2_cell_body_encoded_len(obj->create2);
return result;
}
int
extend2_cell_body_clear_errors(extend2_cell_body_t *obj)
{
int r = obj->trunnel_error_code_;
obj->trunnel_error_code_ = 0;
return r;
}
ssize_t
extend2_cell_body_encode(uint8_t *output, const size_t avail, const extend2_cell_body_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 = extend2_cell_body_encoded_len(obj);
#endif
if (NULL != (msg = extend2_cell_body_check(obj)))
goto check_failed;
#ifdef TRUNNEL_CHECK_ENCODED_LEN
trunnel_assert(encoded_len >= 0);
#endif
/* Encode u8 n_spec */
trunnel_assert(written <= avail);
if (avail - written < 1)
goto truncated;
trunnel_set_uint8(ptr, (obj->n_spec));
written += 1; ptr += 1;
/* Encode struct link_specifier ls[n_spec] */
{
unsigned idx;
for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
trunnel_assert(written <= avail);
result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
if (result < 0)
goto fail; /* XXXXXXX !*/
written += result; ptr += result;
}
}
/* Encode struct create2_cell_body create2 */
trunnel_assert(written <= avail);
result = create2_cell_body_encode(ptr, avail - written, obj->create2);
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 extend2_cell_body_parse(), but do not allocate the output
* object.
*/
static ssize_t
extend2_cell_body_parse_into(extend2_cell_body_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 u8 n_spec */
CHECK_REMAINING(1, truncated);
obj->n_spec = (trunnel_get_uint8(ptr));
remaining -= 1; ptr += 1;
/* Parse struct link_specifier ls[n_spec] */
TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->ls, obj->n_spec, {});
{
link_specifier_t * elt;
unsigned idx;
for (idx = 0; idx < obj->n_spec; ++idx) {
result = link_specifier_parse(&elt, ptr, remaining);
if (result < 0)
goto relay_fail;
trunnel_assert((size_t)result <= remaining);
remaining -= result; ptr += result;
TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->ls, elt, {link_specifier_free(elt);});
}
}
/* Parse struct create2_cell_body create2 */
result = create2_cell_body_parse(&obj->create2, 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;
}
ssize_t
extend2_cell_body_parse(extend2_cell_body_t **output, const uint8_t *input, const size_t len_in)
{
ssize_t result;
*output = extend2_cell_body_new();
if (NULL == *output)
return -1;
result = extend2_cell_body_parse_into(*output, input, len_in);
if (result < 0) {
extend2_cell_body_free(*output);
*output = NULL;
}
return result;
}
link_specifier_list_t *
link_specifier_list_new(void)
{

View File

@ -14,6 +14,15 @@
#define LS_IPV6 1
#define LS_LEGACY_ID 2
#define LS_ED25519_ID 3
#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_CREATE2_CELL_BODY)
struct create2_cell_body_st {
uint16_t handshake_type;
uint16_t handshake_len;
TRUNNEL_DYNARRAY_HEAD(, uint8_t) handshake_data;
uint8_t trunnel_error_code_;
};
#endif
typedef struct create2_cell_body_st create2_cell_body_t;
#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_ED25519_CERT_EXTENSION)
struct ed25519_cert_extension_st {
uint16_t ext_length;
@ -25,6 +34,16 @@ struct ed25519_cert_extension_st {
};
#endif
typedef struct ed25519_cert_extension_st ed25519_cert_extension_t;
#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_EXTEND1_CELL_BODY)
struct extend1_cell_body_st {
uint32_t ipv4addr;
uint16_t port;
uint8_t onionskin[186];
uint8_t identity[20];
uint8_t trunnel_error_code_;
};
#endif
typedef struct extend1_cell_body_st extend1_cell_body_t;
#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_LINK_SPECIFIER)
struct link_specifier_st {
uint8_t ls_type;
@ -54,6 +73,15 @@ struct ed25519_cert_st {
};
#endif
typedef struct ed25519_cert_st ed25519_cert_t;
#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_EXTEND2_CELL_BODY)
struct extend2_cell_body_st {
uint8_t n_spec;
TRUNNEL_DYNARRAY_HEAD(, struct link_specifier_st *) ls;
struct create2_cell_body_st *create2;
uint8_t trunnel_error_code_;
};
#endif
typedef struct extend2_cell_body_st extend2_cell_body_t;
#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_LINK_SPECIFIER_LIST)
struct link_specifier_list_st {
uint8_t n_spec;
@ -62,6 +90,95 @@ struct link_specifier_list_st {
};
#endif
typedef struct link_specifier_list_st link_specifier_list_t;
/** Return a newly allocated create2_cell_body with all elements set
* to zero.
*/
create2_cell_body_t *create2_cell_body_new(void);
/** Release all storage held by the create2_cell_body in 'victim'. (Do
* nothing if 'victim' is NULL.)
*/
void create2_cell_body_free(create2_cell_body_t *victim);
/** Try to parse a create2_cell_body from the buffer in 'input', using
* up to 'len_in' bytes from the input buffer. On success, return the
* number of bytes consumed and set *output to the newly allocated
* create2_cell_body_t. On failure, return -2 if the input appears
* truncated, and -1 if the input is otherwise invalid.
*/
ssize_t create2_cell_body_parse(create2_cell_body_t **output, const uint8_t *input, const size_t len_in);
/** Return the number of bytes we expect to need to encode the
* create2_cell_body in 'obj'. On failure, return a negative value.
* Note that this value may be an overestimate, and can even be an
* underestimate for certain unencodeable objects.
*/
ssize_t create2_cell_body_encoded_len(const create2_cell_body_t *obj);
/** Try to encode the create2_cell_body from 'input' into the buffer
* at 'output', using up to 'avail' bytes of the output buffer. On
* success, return the number of bytes used. On failure, return -2 if
* the buffer was not long enough, and -1 if the input was invalid.
*/
ssize_t create2_cell_body_encode(uint8_t *output, size_t avail, const create2_cell_body_t *input);
/** Check whether the internal state of the create2_cell_body in 'obj'
* is consistent. Return NULL if it is, and a short message if it is
* not.
*/
const char *create2_cell_body_check(const create2_cell_body_t *obj);
/** Clear any errors that were set on the object 'obj' by its setter
* functions. Return true iff errors were cleared.
*/
int create2_cell_body_clear_errors(create2_cell_body_t *obj);
/** Return the value of the handshake_type field of the
* create2_cell_body_t in 'inp'
*/
uint16_t create2_cell_body_get_handshake_type(create2_cell_body_t *inp);
/** Set the value of the handshake_type field of the
* create2_cell_body_t in 'inp' to 'val'. Return 0 on success; return
* -1 and set the error code on 'inp' on failure.
*/
int create2_cell_body_set_handshake_type(create2_cell_body_t *inp, uint16_t val);
/** Return the value of the handshake_len field of the
* create2_cell_body_t in 'inp'
*/
uint16_t create2_cell_body_get_handshake_len(create2_cell_body_t *inp);
/** Set the value of the handshake_len field of the
* create2_cell_body_t in 'inp' to 'val'. Return 0 on success; return
* -1 and set the error code on 'inp' on failure.
*/
int create2_cell_body_set_handshake_len(create2_cell_body_t *inp, uint16_t val);
/** Return the length of the dynamic array holding the handshake_data
* field of the create2_cell_body_t in 'inp'.
*/
size_t create2_cell_body_getlen_handshake_data(const create2_cell_body_t *inp);
/** Return the element at position 'idx' of the dynamic array field
* handshake_data of the create2_cell_body_t in 'inp'.
*/
uint8_t create2_cell_body_get_handshake_data(create2_cell_body_t *inp, size_t idx);
/** As create2_cell_body_get_handshake_data, but take and return a
* const pointer
*/
uint8_t create2_cell_body_getconst_handshake_data(const create2_cell_body_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* handshake_data of the create2_cell_body_t in 'inp', so that it will
* hold the value 'elt'.
*/
int create2_cell_body_set_handshake_data(create2_cell_body_t *inp, size_t idx, uint8_t elt);
/** Append a new element 'elt' to the dynamic array field
* handshake_data of the create2_cell_body_t in 'inp'.
*/
int create2_cell_body_add_handshake_data(create2_cell_body_t *inp, uint8_t elt);
/** Return a pointer to the variable-length array field handshake_data
* of 'inp'.
*/
uint8_t * create2_cell_body_getarray_handshake_data(create2_cell_body_t *inp);
/** As create2_cell_body_get_handshake_data, but take and return a
* const pointer
*/
const uint8_t * create2_cell_body_getconstarray_handshake_data(const create2_cell_body_t *inp);
/** Change the length of the variable-length array field
* handshake_data of 'inp' to 'newlen'.Fill extra elements with 0.
* Return 0 on success; return -1 and set the error code on 'inp' on
* failure.
*/
int create2_cell_body_setlen_handshake_data(create2_cell_body_t *inp, size_t newlen);
/** Return a newly allocated ed25519_cert_extension with all elements
* set to zero.
*/
@ -184,6 +301,109 @@ const uint8_t * ed25519_cert_extension_getconstarray_un_unparsed(const ed25519_
* success; return -1 and set the error code on 'inp' on failure.
*/
int ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen);
/** Return a newly allocated extend1_cell_body with all elements set
* to zero.
*/
extend1_cell_body_t *extend1_cell_body_new(void);
/** Release all storage held by the extend1_cell_body in 'victim'. (Do
* nothing if 'victim' is NULL.)
*/
void extend1_cell_body_free(extend1_cell_body_t *victim);
/** Try to parse a extend1_cell_body from the buffer in 'input', using
* up to 'len_in' bytes from the input buffer. On success, return the
* number of bytes consumed and set *output to the newly allocated
* extend1_cell_body_t. On failure, return -2 if the input appears
* truncated, and -1 if the input is otherwise invalid.
*/
ssize_t extend1_cell_body_parse(extend1_cell_body_t **output, const uint8_t *input, const size_t len_in);
/** Return the number of bytes we expect to need to encode the
* extend1_cell_body in 'obj'. On failure, return a negative value.
* Note that this value may be an overestimate, and can even be an
* underestimate for certain unencodeable objects.
*/
ssize_t extend1_cell_body_encoded_len(const extend1_cell_body_t *obj);
/** Try to encode the extend1_cell_body from 'input' into the buffer
* at 'output', using up to 'avail' bytes of the output buffer. On
* success, return the number of bytes used. On failure, return -2 if
* the buffer was not long enough, and -1 if the input was invalid.
*/
ssize_t extend1_cell_body_encode(uint8_t *output, size_t avail, const extend1_cell_body_t *input);
/** Check whether the internal state of the extend1_cell_body in 'obj'
* is consistent. Return NULL if it is, and a short message if it is
* not.
*/
const char *extend1_cell_body_check(const extend1_cell_body_t *obj);
/** Clear any errors that were set on the object 'obj' by its setter
* functions. Return true iff errors were cleared.
*/
int extend1_cell_body_clear_errors(extend1_cell_body_t *obj);
/** Return the value of the ipv4addr field of the extend1_cell_body_t
* in 'inp'
*/
uint32_t extend1_cell_body_get_ipv4addr(extend1_cell_body_t *inp);
/** Set the value of the ipv4addr field of the extend1_cell_body_t in
* 'inp' to 'val'. Return 0 on success; return -1 and set the error
* code on 'inp' on failure.
*/
int extend1_cell_body_set_ipv4addr(extend1_cell_body_t *inp, uint32_t val);
/** Return the value of the port field of the extend1_cell_body_t in
* 'inp'
*/
uint16_t extend1_cell_body_get_port(extend1_cell_body_t *inp);
/** Set the value of the port field of the extend1_cell_body_t in
* 'inp' to 'val'. Return 0 on success; return -1 and set the error
* code on 'inp' on failure.
*/
int extend1_cell_body_set_port(extend1_cell_body_t *inp, uint16_t val);
/** Return the (constant) length of the array holding the onionskin
* field of the extend1_cell_body_t in 'inp'.
*/
size_t extend1_cell_body_getlen_onionskin(const extend1_cell_body_t *inp);
/** Return the element at position 'idx' of the fixed array field
* onionskin of the extend1_cell_body_t in 'inp'.
*/
uint8_t extend1_cell_body_get_onionskin(extend1_cell_body_t *inp, size_t idx);
/** As extend1_cell_body_get_onionskin, but take and return a const
* pointer
*/
uint8_t extend1_cell_body_getconst_onionskin(const extend1_cell_body_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* onionskin of the extend1_cell_body_t in 'inp', so that it will hold
* the value 'elt'.
*/
int extend1_cell_body_set_onionskin(extend1_cell_body_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 186-element array field onionskin of
* 'inp'.
*/
uint8_t * extend1_cell_body_getarray_onionskin(extend1_cell_body_t *inp);
/** As extend1_cell_body_get_onionskin, but take and return a const
* pointer
*/
const uint8_t * extend1_cell_body_getconstarray_onionskin(const extend1_cell_body_t *inp);
/** Return the (constant) length of the array holding the identity
* field of the extend1_cell_body_t in 'inp'.
*/
size_t extend1_cell_body_getlen_identity(const extend1_cell_body_t *inp);
/** Return the element at position 'idx' of the fixed array field
* identity of the extend1_cell_body_t in 'inp'.
*/
uint8_t extend1_cell_body_get_identity(extend1_cell_body_t *inp, size_t idx);
/** As extend1_cell_body_get_identity, but take and return a const
* pointer
*/
uint8_t extend1_cell_body_getconst_identity(const extend1_cell_body_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* identity of the extend1_cell_body_t in 'inp', so that it will hold
* the value 'elt'.
*/
int extend1_cell_body_set_identity(extend1_cell_body_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 20-element array field identity of 'inp'.
*/
uint8_t * extend1_cell_body_getarray_identity(extend1_cell_body_t *inp);
/** As extend1_cell_body_get_identity, but take and return a const
* pointer
*/
const uint8_t * extend1_cell_body_getconstarray_identity(const extend1_cell_body_t *inp);
/** Return a newly allocated link_specifier with all elements set to
* zero.
*/
@ -536,6 +756,104 @@ uint8_t * ed25519_cert_getarray_signature(ed25519_cert_t *inp);
/** As ed25519_cert_get_signature, but take and return a const pointer
*/
const uint8_t * ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp);
/** Return a newly allocated extend2_cell_body with all elements set
* to zero.
*/
extend2_cell_body_t *extend2_cell_body_new(void);
/** Release all storage held by the extend2_cell_body in 'victim'. (Do
* nothing if 'victim' is NULL.)
*/
void extend2_cell_body_free(extend2_cell_body_t *victim);
/** Try to parse a extend2_cell_body from the buffer in 'input', using
* up to 'len_in' bytes from the input buffer. On success, return the
* number of bytes consumed and set *output to the newly allocated
* extend2_cell_body_t. On failure, return -2 if the input appears
* truncated, and -1 if the input is otherwise invalid.
*/
ssize_t extend2_cell_body_parse(extend2_cell_body_t **output, const uint8_t *input, const size_t len_in);
/** Return the number of bytes we expect to need to encode the
* extend2_cell_body in 'obj'. On failure, return a negative value.
* Note that this value may be an overestimate, and can even be an
* underestimate for certain unencodeable objects.
*/
ssize_t extend2_cell_body_encoded_len(const extend2_cell_body_t *obj);
/** Try to encode the extend2_cell_body from 'input' into the buffer
* at 'output', using up to 'avail' bytes of the output buffer. On
* success, return the number of bytes used. On failure, return -2 if
* the buffer was not long enough, and -1 if the input was invalid.
*/
ssize_t extend2_cell_body_encode(uint8_t *output, size_t avail, const extend2_cell_body_t *input);
/** Check whether the internal state of the extend2_cell_body in 'obj'
* is consistent. Return NULL if it is, and a short message if it is
* not.
*/
const char *extend2_cell_body_check(const extend2_cell_body_t *obj);
/** Clear any errors that were set on the object 'obj' by its setter
* functions. Return true iff errors were cleared.
*/
int extend2_cell_body_clear_errors(extend2_cell_body_t *obj);
/** Return the value of the n_spec field of the extend2_cell_body_t in
* 'inp'
*/
uint8_t extend2_cell_body_get_n_spec(extend2_cell_body_t *inp);
/** Set the value of the n_spec field of the extend2_cell_body_t in
* 'inp' to 'val'. Return 0 on success; return -1 and set the error
* code on 'inp' on failure.
*/
int extend2_cell_body_set_n_spec(extend2_cell_body_t *inp, uint8_t val);
/** Return the length of the dynamic array holding the ls field of the
* extend2_cell_body_t in 'inp'.
*/
size_t extend2_cell_body_getlen_ls(const extend2_cell_body_t *inp);
/** Return the element at position 'idx' of the dynamic array field ls
* of the extend2_cell_body_t in 'inp'.
*/
struct link_specifier_st * extend2_cell_body_get_ls(extend2_cell_body_t *inp, size_t idx);
/** As extend2_cell_body_get_ls, but take and return a const pointer
*/
const struct link_specifier_st * extend2_cell_body_getconst_ls(const extend2_cell_body_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field ls
* of the extend2_cell_body_t in 'inp', so that it will hold the value
* 'elt'. Free the previous value, if any.
*/
int extend2_cell_body_set_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt);
/** As extend2_cell_body_set_ls, but does not free the previous value.
*/
int extend2_cell_body_set0_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt);
/** Append a new element 'elt' to the dynamic array field ls of the
* extend2_cell_body_t in 'inp'.
*/
int extend2_cell_body_add_ls(extend2_cell_body_t *inp, struct link_specifier_st * elt);
/** Return a pointer to the variable-length array field ls of 'inp'.
*/
struct link_specifier_st * * extend2_cell_body_getarray_ls(extend2_cell_body_t *inp);
/** As extend2_cell_body_get_ls, but take and return a const pointer
*/
const struct link_specifier_st * const * extend2_cell_body_getconstarray_ls(const extend2_cell_body_t *inp);
/** Change the length of the variable-length array field ls of 'inp'
* to 'newlen'.Fill extra elements with NULL; free removed elements.
* Return 0 on success; return -1 and set the error code on 'inp' on
* failure.
*/
int extend2_cell_body_setlen_ls(extend2_cell_body_t *inp, size_t newlen);
/** Return the value of the create2 field of the extend2_cell_body_t
* in 'inp'
*/
struct create2_cell_body_st * extend2_cell_body_get_create2(extend2_cell_body_t *inp);
/** As extend2_cell_body_get_create2, but take and return a const
* pointer
*/
const struct create2_cell_body_st * extend2_cell_body_getconst_create2(const extend2_cell_body_t *inp);
/** Set the value of the create2 field of the extend2_cell_body_t in
* 'inp' to 'val'. Free the old value if any. Steals the referenceto
* 'val'.Return 0 on success; return -1 and set the error code on
* 'inp' on failure.
*/
int extend2_cell_body_set_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val);
/** As extend2_cell_body_set_create2, but does not free the previous
* value.
*/
int extend2_cell_body_set0_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val);
/** Return a newly allocated link_specifier_list with all elements set
* to zero.
*/

View File

@ -23,40 +23,6 @@ struct ed25519_cert_extension {
};
}
/*
struct cert_revocation {
u8 prefix[8];
u8 version IN [1];
u8 keytype;
u8 identity_key[32];
u8 revoked_key[32];
u64 published;
u8 n_extensions;
struct cert_extension ext[n_extensions];
u8 signature[64];
}
struct crosscert_ed_rsa {
u8 ed_key[32];
u32 expiration_date;
u8 signature[128];
}
struct auth02_cell {
u8 type[8];
u8 cid[32];
u8 sid[32];
u8 cid_ed[32];
u8 sid_ed[32];
u8 slog[32];
u8 clog[32];
u8 scert[32];
u8 tlssecrets[32];
u8 rand[24];
u8 sig[64];
}
*/
const LS_IPV4 = 0x00;
const LS_IPV6 = 0x01;
const LS_LEGACY_ID = 0x02;
@ -79,3 +45,22 @@ struct link_specifier_list {
u8 n_spec;
struct link_specifier spec[n_spec];
}
struct extend1_cell_body {
u32 ipv4addr;
u16 port;
u8 onionskin[186];
u8 identity[20];
}
struct create2_cell_body {
u16 handshake_type;
u16 handshake_len;
u8 handshake_data[handshake_len];
}
struct extend2_cell_body {
u8 n_spec;
struct link_specifier ls[n_spec];
struct create2_cell_body create2;
}