blob: 096652c70009d69a0b634798083ff108858b4bdd [file] [log] [blame]
Lev Walkine4d8c922017-07-10 20:29:33 -07001/*
2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 * Redistribution and modifications are oermitted subject to BSD license.
5 */
6#include <asn_system.h>
7#include <asn_internal.h>
8
9#include <oer_support.h>
10
11/*
12 * Fetch the length determinant (X.696 08/2015, #8.6) into *len_r.
13 * RETURN VALUES:
14 * 0: More data expected than bufptr contains.
15 * -1: Fatal error deciphering length.
16 * >0: Number of bytes used from bufptr.
17 */
18ssize_t
19oer_fetch_length(const void *bufptr, size_t size, size_t *len_r) {
20 uint8_t first_byte;
21 uint8_t len_len; /* Length of the length determinant */
22 const uint8_t *b;
23 const uint8_t *bend;
24 size_t len;
25
26 if(size == 0) {
27 *len_r = 0;
28 return 0;
29 }
30
31 first_byte = *(const uint8_t *)bufptr;
32 if((first_byte & 0x80) == 0) { /* Short form */
33 *len_r = first_byte; /* 0..127 */
34 return 1;
35 }
36
37 len_len = (first_byte & 0x7f);
38 if((1 + len_len) > size) {
39 *len_r = 0;
40 return 0;
41 }
42
43 b = (const uint8_t *)bufptr + 1;
44 bend = b + len_len;
45
46 for(; b < bend && *b == 0; b++) {
47 /* Skip the leading 0-bytes */
48 }
49
50 if((bend - b) > sizeof(size_t)) {
51 /* Length is not representable by the native size_t type */
52 *len_r = 0;
53 return -1;
54 }
55
56 for(len = 0; b < bend; b++) {
57 len = (len << 8) + *b;
58 }
59
60 *len_r = len;
61 assert(len_len + 1 == bend - (const uint8_t *)bufptr);
62 return len_len + 1;
63}
64
65
Lev Walkinfcfe19b2017-07-10 21:57:14 -070066/*
67 * Serialize OER length. Returns the number of bytes serialized
68 * or -1 if a given callback returned with negative result.
69 */
70ssize_t
71oer_serialize_length(size_t length, asn_app_consume_bytes_f *cb,
72 void *app_key) {
73 uint8_t scratch[1 + sizeof(length)];
74 uint8_t *sp = scratch;
75 int littleEndian = 1; /* Run-time detection */
76 const uint8_t *pstart;
77 const uint8_t *pend;
78 const uint8_t *p;
79 int add;
80
81 if(length <= 127) {
82 uint8_t b = length;
83 if(cb(&b, 1, app_key) < 0) {
84 return -1;
85 }
86 return 1;
87 }
88
89 if(*(char *)&littleEndian) {
90 pstart = (const uint8_t *)&length + sizeof(length);
91 pend = (const uint8_t *)&length;
92 add = -1;
93 } else {
94 pstart = (const uint8_t *)&length;
95 pend = pstart + sizeof(length);
96 add = 1;
97 }
98
99 for(p = pstart; p != pend; p += add) {
100 /* Skip leading zeros. */
101 if(*p) break;
102 }
103
104 for(sp = scratch + 1; p != pend; p += add, sp++) {
105 *sp = *p;
106 }
107 assert((sp - scratch) - 1 <= 0x7f);
108 scratch[0] = 0x80 + ((sp - scratch) - 1);
109
110 if(cb(scratch, sp - scratch, app_key) < 0) {
111 return -1;
112 }
113
114 return sp - scratch;
115}
116