3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-23 06:02:37 +01:00

ttls: improve avp build approach

This commit is contained in:
Tim Kourt 2018-10-01 14:55:35 -07:00 committed by Denis Kenzior
parent 7903432e85
commit 2aefd8badf

View File

@ -29,6 +29,7 @@
#include <errno.h> #include <errno.h>
#include <ell/ell.h> #include <ell/ell.h>
#include <ell/tls-private.h> #include <ell/tls-private.h>
#include <ell/private.h>
#include "eap.h" #include "eap.h"
#include "eap-private.h" #include "eap-private.h"
@ -48,82 +49,78 @@ enum radius_attr {
}; };
struct avp_builder { struct avp_builder {
uint8_t flags; uint32_t capacity;
size_t capacity;
uint8_t *buf; uint8_t *buf;
size_t offset; uint32_t pos;
uint32_t current_len; uint8_t *avp_start;
}; };
static void avp_builder_grow(struct avp_builder *builder) static uint8_t *avp_builder_reserve(struct avp_builder *builder,
uint32_t alignment, size_t len)
{ {
builder->buf = l_realloc(builder->buf, builder->capacity * 2); size_t aligned_pos = align_len(builder->pos, alignment);
size_t end = aligned_pos + len;
memset(builder->buf + builder->capacity, 0, builder->capacity); if (end > builder->capacity) {
builder->buf = l_realloc(builder->buf, end);
builder->capacity *= 2; builder->capacity = end;
}
static uint8_t *avp_builder_reserve(struct avp_builder *builder, size_t len)
{
while (builder->offset + TTLS_AVP_HEADER_LEN + builder->current_len
+ len >= builder->capacity) {
avp_builder_grow(builder);
} }
return builder->buf + builder->offset + TTLS_AVP_HEADER_LEN + if (aligned_pos - builder->pos > 0)
builder->current_len; memset(builder->buf + builder->pos, 0,
aligned_pos - builder->pos);
builder->pos = end;
return builder->buf + aligned_pos;
} }
static void avp_builder_finalize_avp(struct avp_builder *builder) static bool avp_builder_finalize_avp(struct avp_builder *builder)
{ {
uint8_t *p = builder->buf + builder->offset; uint8_t *p;
uint32_t len;
if (builder->current_len & 3) { if (!builder->avp_start)
/* return false;
* If an AVP is not a multiple of four octets, it must be padded
* with zeros to the next four-octet boundary.
*/
uint8_t pad_len = 4 - (builder->current_len & 3);
memset(avp_builder_reserve(builder, pad_len), 0, pad_len); p = builder->buf + builder->pos;
}
builder->current_len += TTLS_AVP_HEADER_LEN; len = l_get_be32(builder->avp_start + 4);
builder->offset += (builder->current_len + 3) & ~3; len |= p - builder->avp_start;
builder->current_len |= builder->flags << 24; l_put_be32(len, builder->avp_start + 4);
l_put_be32(builder->current_len, p + 4); builder->avp_start = 0;
builder->flags = 0; return true;
builder->current_len = 0;
} }
static bool avp_builder_start_avp(struct avp_builder *builder, static bool avp_builder_start_avp(struct avp_builder *builder,
enum radius_attr type, enum radius_attr type,
bool mandatory, uint32_t vendor_id) bool mandatory, uint32_t vendor_id)
{ {
uint8_t *p; uint32_t flags;
if (builder->current_len) if (builder->avp_start)
return false; return false;
if (builder->offset + TTLS_AVP_HEADER_LEN + (vendor_id ? 4 : 0) builder->avp_start = avp_builder_reserve(builder, 4,
>= builder->capacity) TTLS_AVP_HEADER_LEN +
avp_builder_grow(builder); (vendor_id ? 4 : 0));
p = builder->buf + builder->offset; l_put_be32(type, builder->avp_start);
l_put_be32(type, p);
flags = 0;
if (mandatory) if (mandatory)
builder->flags |= TTLS_AVP_FLAG_M; flags |= TTLS_AVP_FLAG_M;
if (vendor_id) { if (vendor_id) {
builder->flags |= TTLS_AVP_FLAG_V; flags |= TTLS_AVP_FLAG_V;
l_put_be32(vendor_id, p + TTLS_AVP_HEADER_LEN); l_put_be32(vendor_id, builder->avp_start + TTLS_AVP_HEADER_LEN);
builder->current_len += 4;
} }
l_put_be32(flags << 24, builder->avp_start + 4);
return true; return true;
} }
@ -157,7 +154,7 @@ static uint8_t *avp_builder_free(struct avp_builder *builder, bool free_data,
ret = builder->buf; ret = builder->buf;
if (out_size) if (out_size)
*out_size = builder->offset; *out_size = builder->pos;
l_free(builder); l_free(builder);
@ -168,7 +165,6 @@ static bool avp_builder_put_bytes(struct avp_builder *builder,
const void *data, size_t len) const void *data, size_t len)
{ {
memcpy(avp_builder_reserve(builder, len), data, len); memcpy(avp_builder_reserve(builder, len), data, len);
builder->current_len += len;
return true; return true;
} }