2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_system.h>
7 #include <asn_internal.h>
9 #include <oer_support.h>
12 * Fetch the length determinant (X.696 08/2015, #8.6) into *len_r.
14 * 0: More data expected than bufptr contains.
15 * -1: Fatal error deciphering length.
16 * >0: Number of bytes used from bufptr.
19 oer_fetch_length(const void *bufptr, size_t size, size_t *len_r) {
21 size_t len_len; /* Length of the length determinant */
31 first_byte = *(const uint8_t *)bufptr;
32 if((first_byte & 0x80) == 0) { /* Short form */
33 *len_r = first_byte; /* 0..127 */
37 len_len = (first_byte & 0x7f);
38 if((1 + len_len) > size) {
43 b = (const uint8_t *)bufptr + 1;
46 for(; b < bend && *b == 0; b++) {
47 /* Skip the leading 0-bytes */
50 if((bend - b) > (ssize_t)sizeof(size_t)) {
51 /* Length is not representable by the native size_t type */
56 for(len = 0; b < bend; b++) {
57 len = (len << 8) + *b;
60 if(len > RSIZE_MAX) { /* A bit of C11 validation */
66 assert(len_len + 1 == (size_t)(bend - (const uint8_t *)bufptr));
72 * Serialize OER length. Returns the number of bytes serialized
73 * or -1 if a given callback returned with negative result.
76 oer_serialize_length(size_t length, asn_app_consume_bytes_f *cb,
78 uint8_t scratch[1 + sizeof(length)];
79 uint8_t *sp = scratch;
80 int littleEndian = 1; /* Run-time detection */
81 const uint8_t *pstart;
88 if(cb(&b, 1, app_key) < 0) {
94 if(*(char *)&littleEndian) {
95 pstart = (const uint8_t *)&length + sizeof(length) - 1;
96 pend = (const uint8_t *)&length;
99 pstart = (const uint8_t *)&length;
100 pend = pstart + sizeof(length);
104 for(p = pstart; p != pend; p += add) {
105 /* Skip leading zeros. */
109 for(sp = scratch + 1; ; p += add) {
113 assert((sp - scratch) - 1 <= 0x7f);
114 scratch[0] = 0x80 + ((sp - scratch) - 1);
116 if(cb(scratch, sp - scratch, app_key) < 0) {