--- /dev/null
+/*-\r
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.\r
+ * Redistribution and modifications are permitted subject to BSD license.\r
+ */\r
+#include <asn_internal.h>\r
+#include <ber_tlv_length.h>\r
+#include <ber_tlv_tag.h>\r
+\r
+ssize_t\r
+ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,\r
+ ber_tlv_len_t *len_r) {\r
+ const uint8_t *buf = (const uint8_t *)bufptr;\r
+ unsigned oct;\r
+\r
+ if(size == 0)\r
+ return 0; /* Want more */\r
+\r
+ oct = *(const uint8_t *)buf;\r
+ if((oct & 0x80) == 0) {\r
+ /*\r
+ * Short definite length.\r
+ */\r
+ *len_r = oct; /* & 0x7F */\r
+ return 1;\r
+ } else {\r
+ ber_tlv_len_t len;\r
+ size_t skipped;\r
+\r
+ if(_is_constructed && oct == 0x80) {\r
+ *len_r = -1; /* Indefinite length */\r
+ return 1;\r
+ }\r
+\r
+ if(oct == 0xff) {\r
+ /* Reserved in standard for future use. */\r
+ return -1;\r
+ }\r
+\r
+ oct &= 0x7F; /* Leave only the 7 LS bits */\r
+ for(len = 0, buf++, skipped = 1;\r
+ oct && (++skipped <= size); buf++, oct--) {\r
+\r
+ /* Verify that we won't overflow. */\r
+ if(!(len >> ((8 * sizeof(len)) - (8+1)))) {\r
+ len = (len << 8) | *buf;\r
+ } else {\r
+ /* Too large length value. */\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ if(oct == 0) {\r
+ if(len < 0 || len > RSSIZE_MAX) {\r
+ /* Length value out of sane range. */\r
+ return -1;\r
+ }\r
+\r
+ *len_r = len;\r
+ return skipped;\r
+ }\r
+\r
+ return 0; /* Want more */\r
+ }\r
+\r
+}\r
+\r
+ssize_t\r
+ber_skip_length(const asn_codec_ctx_t *opt_codec_ctx,\r
+ int _is_constructed, const void *ptr, size_t size) {\r
+ ber_tlv_len_t vlen; /* Length of V in TLV */\r
+ ssize_t tl; /* Length of L in TLV */\r
+ ssize_t ll; /* Length of L in TLV */\r
+ size_t skip;\r
+\r
+ /*\r
+ * Make sure we didn't exceed the maximum stack size.\r
+ */\r
+ if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))\r
+ return -1;\r
+\r
+ /*\r
+ * Determine the size of L in TLV.\r
+ */\r
+ ll = ber_fetch_length(_is_constructed, ptr, size, &vlen);\r
+ if(ll <= 0) return ll;\r
+\r
+ /*\r
+ * Definite length.\r
+ */\r
+ if(vlen >= 0) {\r
+ skip = ll + vlen;\r
+ if(skip > size)\r
+ return 0; /* Want more */\r
+ return skip;\r
+ }\r
+\r
+ /*\r
+ * Indefinite length!\r
+ */\r
+ ASN_DEBUG("Skipping indefinite length");\r
+ for(skip = ll, ptr = ((const char *)ptr) + ll, size -= ll;;) {\r
+ ber_tlv_tag_t tag;\r
+\r
+ /* Fetch the tag */\r
+ tl = ber_fetch_tag(ptr, size, &tag);\r
+ if(tl <= 0) return tl;\r
+\r
+ ll = ber_skip_length(opt_codec_ctx,\r
+ BER_TLV_CONSTRUCTED(ptr),\r
+ ((const char *)ptr) + tl, size - tl);\r
+ if(ll <= 0) return ll;\r
+\r
+ skip += tl + ll;\r
+\r
+ /*\r
+ * This may be the end of the indefinite length structure,\r
+ * two consecutive 0 octets.\r
+ * Check if it is true.\r
+ */\r
+ if(((const uint8_t *)ptr)[0] == 0\r
+ && ((const uint8_t *)ptr)[1] == 0)\r
+ return skip;\r
+\r
+ ptr = ((const char *)ptr) + tl + ll;\r
+ size -= tl + ll;\r
+ }\r
+\r
+ /* UNREACHABLE */\r
+}\r
+\r
+size_t\r
+der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size) {\r
+ size_t required_size; /* Size of len encoding */\r
+ uint8_t *buf = (uint8_t *)bufp;\r
+ uint8_t *end;\r
+ int i;\r
+\r
+ if(len <= 127) {\r
+ /* Encoded in 1 octet */\r
+ if(size) *buf = (uint8_t)len;\r
+ return 1;\r
+ }\r
+\r
+ /*\r
+ * Compute the size of the subsequent bytes.\r
+ */\r
+ for(required_size = 1, i = 8; i < 8 * (int)sizeof(len); i += 8) {\r
+ if(len >> i)\r
+ required_size++;\r
+ else\r
+ break;\r
+ }\r
+\r
+ if(size <= required_size)\r
+ return required_size + 1;\r
+\r
+ *buf++ = (uint8_t)(0x80 | required_size); /* Length of the encoding */\r
+\r
+ /*\r
+ * Produce the len encoding, space permitting.\r
+ */\r
+ end = buf + required_size;\r
+ for(i -= 8; buf < end; i -= 8, buf++)\r
+ *buf = (uint8_t)(len >> i);\r
+\r
+ return required_size + 1;\r
+}\r
+\r