blob: 9f564bc7b4d54baf2e6fb1e5b0d918ee67b37d9e [file] [log] [blame]
Lev Walkinf9f3e062017-08-27 20:34:58 -07001/*
2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 * Redistribution and modifications are permitted subject to BSD license.
5 */
6#ifndef ASN_DISABLE_OER_SUPPORT
7
8#include <asn_internal.h>
9#include <NativeEnumerated.h>
10#include <errno.h>
11
Lev Walkina9e63372017-09-17 23:24:56 -070012/*
13 * This function is only to get rid of Undefined Behavior Sanitizer warning.
14 */
Lev Walkina4f68912017-09-27 02:21:38 +000015static intmax_t CC_ATTR_NO_SANITIZE("shift-base")
Lev Walkina9e63372017-09-17 23:24:56 -070016asn__safe_nativeenumerated_convert_helper(const uint8_t *b,
17 const uint8_t *end) {
18 intmax_t value;
19
20 /* Perform the sign initialization */
21 /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
22 if((*b >> 7)) {
23 value = -1;
24 } else {
25 value = 0;
26 }
27
28 /* Conversion engine */
29 for(; b < end; b++) {
30 value = (value << 8) | *b;
31 }
32
33 return value;
34}
35
Lev Walkinf9f3e062017-08-27 20:34:58 -070036asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -070037NativeEnumerated_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkinf9f3e062017-08-27 20:34:58 -070038 asn_TYPE_descriptor_t *td,
39 const asn_oer_constraints_t *constraints,
40 void **nint_ptr, const void *ptr, size_t size) {
41 asn_dec_rval_t rval = {RC_OK, 0};
42 long *native = (long *)*nint_ptr;
43 const uint8_t *b = ptr;
44
45 (void)opt_codec_ctx;
46 (void)constraints;
47
48 if(size < 1) {
49 ASN__DECODE_STARVED;
50 }
51
52 if((*b & 0x80) == 0) {
53 /*
54 * X.696 (08/2015) #11.2 Short form for Enumerated.
55 */
56 if(!native) {
57 native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
58 if(!native) ASN__DECODE_FAILED;
59 }
60
61 *native = *b;
62 rval.consumed = 1;
63 } else {
64 /*
65 * X.696 (08/2015) #11.4 Long form for Enumerated.
66 */
67 size_t length = *b & 0x7f;
68 const uint8_t *bend;
Lev Walkina9e63372017-09-17 23:24:56 -070069 intmax_t value;
Lev Walkinf9f3e062017-08-27 20:34:58 -070070
71 if(length < 1 || length > sizeof(*native)) {
72 ASN__DECODE_FAILED;
73 }
74 if((1 + length) > size) {
75 ASN__DECODE_STARVED;
76 }
77 b++;
78 bend = b + length;
Lev Walkinf9f3e062017-08-27 20:34:58 -070079
Lev Walkina9e63372017-09-17 23:24:56 -070080 value = asn__safe_nativeenumerated_convert_helper(b, bend);
Lev Walkinf9f3e062017-08-27 20:34:58 -070081 if(value < 0) {
82 const asn_INTEGER_specifics_t *specs =
83 (const asn_INTEGER_specifics_t *)td->specifics;
84 if(specs && specs->field_unsigned) {
85 ASN__DECODE_FAILED;
86 }
87 }
88
89 if(!native) {
90 native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
91 if(!native) ASN__DECODE_FAILED;
92 }
93
94 *native = value;
95
96 rval.consumed = (1 + length);
97 }
98
99 return rval;
100}
101
102/*
103 * Encode as Canonical OER.
104 */
105asn_enc_rval_t
106NativeEnumerated_encode_oer(asn_TYPE_descriptor_t *td,
107 const asn_oer_constraints_t *constraints,
108 void *sptr, asn_app_consume_bytes_f *cb,
109 void *app_key) {
Lev Walkin0cfc8652017-09-11 15:45:36 +0000110 asn_enc_rval_t er;
Lev Walkinf9f3e062017-08-27 20:34:58 -0700111 long native;
112
113 (void)constraints;
114
115 if(!sptr) ASN__ENCODE_FAILED;
116
117 native = *(const long *)sptr;
118
119 if(native >= 0 && native <= 127) {
120 /* #11.2 Short form */
121 uint8_t b = native;
122 er.encoded = 1;
123 if(cb(&b, er.encoded, app_key) < 0) {
124 ASN__ENCODE_FAILED;
125 }
126 ASN__ENCODED_OK(er);
127 } else {
128 /* #11.2 Long form */
129 uint8_t buf[1 + sizeof(native)];
130 uint8_t *b = &buf[sizeof(native)]; /* Last addressable */
131 long final_pattern = -1 * (native < 0);
132
133 for(;;) {
134 *b-- = native;
135 native >>= 8;
136 if(native == final_pattern) {
137 if(final_pattern) {
138 if((b[1] & 0x80)) break;
139 } else {
140 if(!(b[1] & 0x80)) break;
141 }
142 }
143 }
144 *b = 0x80 | (&buf[sizeof(native)] - b);
145 er.encoded = 1 + (&buf[sizeof(native)] - b);
146 if(cb(b, er.encoded, app_key) < 0) {
147 ASN__ENCODE_FAILED;
148 }
149 ASN__ENCODED_OK(er);
150 }
151}
152
153#endif /* ASN_DISABLE_OER_SUPPORT */