blob: 9c5e4ae9db888f1cb500c58e33a9be4d05f8847d [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
12asn_dec_rval_t
13NativeEnumerated_decode_oer(asn_codec_ctx_t *opt_codec_ctx,
14 asn_TYPE_descriptor_t *td,
15 const asn_oer_constraints_t *constraints,
16 void **nint_ptr, const void *ptr, size_t size) {
17 asn_dec_rval_t rval = {RC_OK, 0};
18 long *native = (long *)*nint_ptr;
19 const uint8_t *b = ptr;
20
21 (void)opt_codec_ctx;
22 (void)constraints;
23
24 if(size < 1) {
25 ASN__DECODE_STARVED;
26 }
27
28 if((*b & 0x80) == 0) {
29 /*
30 * X.696 (08/2015) #11.2 Short form for Enumerated.
31 */
32 if(!native) {
33 native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
34 if(!native) ASN__DECODE_FAILED;
35 }
36
37 *native = *b;
38 rval.consumed = 1;
39 } else {
40 /*
41 * X.696 (08/2015) #11.4 Long form for Enumerated.
42 */
43 size_t length = *b & 0x7f;
44 const uint8_t *bend;
45 long value;
46
47 if(length < 1 || length > sizeof(*native)) {
48 ASN__DECODE_FAILED;
49 }
50 if((1 + length) > size) {
51 ASN__DECODE_STARVED;
52 }
53 b++;
54 bend = b + length;
55 value = (*b & 0x80) ? -1 : 0; /* Determine sign */
56 for(; b < bend; b++)
57 value = (value << 8) | *b;
58
59 if(value < 0) {
60 const asn_INTEGER_specifics_t *specs =
61 (const asn_INTEGER_specifics_t *)td->specifics;
62 if(specs && specs->field_unsigned) {
63 ASN__DECODE_FAILED;
64 }
65 }
66
67 if(!native) {
68 native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
69 if(!native) ASN__DECODE_FAILED;
70 }
71
72 *native = value;
73
74 rval.consumed = (1 + length);
75 }
76
77 return rval;
78}
79
80/*
81 * Encode as Canonical OER.
82 */
83asn_enc_rval_t
84NativeEnumerated_encode_oer(asn_TYPE_descriptor_t *td,
85 const asn_oer_constraints_t *constraints,
86 void *sptr, asn_app_consume_bytes_f *cb,
87 void *app_key) {
88 asn_enc_rval_t er = {0, td, sptr};
89 long native;
90
91 (void)constraints;
92
93 if(!sptr) ASN__ENCODE_FAILED;
94
95 native = *(const long *)sptr;
96
97 if(native >= 0 && native <= 127) {
98 /* #11.2 Short form */
99 uint8_t b = native;
100 er.encoded = 1;
101 if(cb(&b, er.encoded, app_key) < 0) {
102 ASN__ENCODE_FAILED;
103 }
104 ASN__ENCODED_OK(er);
105 } else {
106 /* #11.2 Long form */
107 uint8_t buf[1 + sizeof(native)];
108 uint8_t *b = &buf[sizeof(native)]; /* Last addressable */
109 long final_pattern = -1 * (native < 0);
110
111 for(;;) {
112 *b-- = native;
113 native >>= 8;
114 if(native == final_pattern) {
115 if(final_pattern) {
116 if((b[1] & 0x80)) break;
117 } else {
118 if(!(b[1] & 0x80)) break;
119 }
120 }
121 }
122 *b = 0x80 | (&buf[sizeof(native)] - b);
123 er.encoded = 1 + (&buf[sizeof(native)] - b);
124 if(cb(b, er.encoded, app_key) < 0) {
125 ASN__ENCODE_FAILED;
126 }
127 ASN__ENCODED_OK(er);
128 }
129}
130
131#endif /* ASN_DISABLE_OER_SUPPORT */