blob: 1b1e2343d8dd50880af9e6ee513b1e81146ed818 [file] [log] [blame]
Lev Walkin1d76f3c2017-07-25 07:58:05 -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 <OCTET_STRING.h>
10#include <errno.h>
11
12static asn_oer_constraints_t asn_DEF_OCTET_STRING_oer_constraints = {
13 { 0, 0, 0 },
14 { AOC_HAS_LOWER_BOUND, 0, 0 }
15};
16
17asn_dec_rval_t
18OCTET_STRING_decode_oer(asn_codec_ctx_t *opt_codec_ctx,
19 asn_TYPE_descriptor_t *td,
20 asn_oer_constraints_t *constraints, void **sptr,
21 const void *ptr, size_t size) {
22 asn_OCTET_STRING_specifics_t *specs =
23 td->specifics
24 ? (asn_OCTET_STRING_specifics_t *)td->specifics
25 : (asn_OCTET_STRING_specifics_t *)&asn_DEF_OCTET_STRING.specifics;
26 OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
27 asn_oer_constraints_t *cts =
28 constraints ? constraints : td->oer_constraints;
29 asn_oer_constraint_t *csiz =
30 cts ? &cts->size : &asn_DEF_OCTET_STRING_oer_constraints.size;
31 asn_dec_rval_t rval = {RC_OK, 0};
32 size_t expected_length = 0;
33
34 size_t unit_bytes;
35 switch(specs->subvariant) {
36 default:
37 case ASN_OSUBV_BIT:
38 ASN_DEBUG("Invalid use of OCTET STRING to decode BIT STRING");
39 ASN__DECODE_FAILED;
40 case ASN_OSUBV_ANY:
41 /* Fall through */
42 case ASN_OSUBV_STR:
43 unit_bytes = 1;
44 break;
45 case ASN_OSUBV_U16:
46 unit_bytes = 2;
47 break;
48 case ASN_OSUBV_U32:
49 unit_bytes = 4;
50 break;
51 }
52
53 (void)opt_codec_ctx;
54
55 if(!st) {
56 st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
57 if(!st) ASN__DECODE_FAILED;
58 }
59
60 if((csiz->flags
61 & (AOC_HAS_LOWER_BOUND | AOC_HAS_UPPER_BOUND))
62 == (AOC_HAS_LOWER_BOUND | AOC_HAS_UPPER_BOUND)
63 && csiz->lower_bound == csiz->upper_bound) {
64 expected_length = unit_bytes * csiz->lower_bound;
65 } else {
66 /*
67 * X.696 (08/2015) #27.2
68 * Encode length determinant as _number of octets_, but only
69 * if upper bound is not equal to lower bound.
70 */
71 ssize_t len_len = oer_fetch_length(ptr, size, &expected_length);
72 if(len_len > 0) {
73 rval.consumed = len_len;
74 ptr = (const char *)ptr + len_len;
75 size -= len_len;
76 } else if(len_len == 0) {
77 ASN__DECODE_STARVED;
78 } else if(len_len < 0) {
79 ASN__DECODE_FAILED;
80 }
81
82 if(expected_length % unit_bytes != 0) {
83 ASN_DEBUG(
84 "Data size %zu bytes is not consistent with multiplier %zu",
85 expected_length, unit_bytes);
86 ASN__DECODE_FAILED;
87 }
88 }
89
90 if(size < expected_length) {
91 ASN__DECODE_STARVED;
92 } else {
93 uint8_t *buf = MALLOC(expected_length + 1);
94 if(buf == NULL) {
95 ASN__DECODE_FAILED;
96 } else {
97 memcpy(buf, ptr, expected_length);
98 buf[expected_length] = '\0';
99 }
100 FREEMEM(st->buf);
101 st->buf = buf;
102 st->size = expected_length;
103
104 rval.consumed += expected_length;
105 return rval;
106 }
107}
108
109/*
110 * Encode as Canonical OER.
111 */
112asn_enc_rval_t
113OCTET_STRING_encode_oer(asn_TYPE_descriptor_t *td,
114 asn_oer_constraints_t *constraints, void *sptr,
115 asn_app_consume_bytes_f *cb, void *app_key) {
116 asn_OCTET_STRING_specifics_t *specs =
117 td->specifics
118 ? (asn_OCTET_STRING_specifics_t *)td->specifics
119 : (asn_OCTET_STRING_specifics_t *)&asn_DEF_OCTET_STRING.specifics;
120 OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
121 asn_oer_constraints_t *cts =
122 constraints ? constraints : td->oer_constraints;
123 asn_oer_constraint_t *csiz =
124 cts ? &cts->size : &asn_DEF_OCTET_STRING_oer_constraints.size;
125 asn_enc_rval_t er = {0, 0, 0};
126
127 if(!st) ASN__ENCODE_FAILED;
128
129 ASN_DEBUG("Encoding %s %d as OCTET STRING", td ? td->name : "", st->size);
130
131 if((csiz->flags
132 & (AOC_HAS_LOWER_BOUND | AOC_HAS_UPPER_BOUND))
133 == (AOC_HAS_LOWER_BOUND | AOC_HAS_UPPER_BOUND)
134 && csiz->lower_bound == csiz->upper_bound) {
135 /*
136 * Check that available data matches the constraint
137 */
138 size_t unit_bytes;
139 switch(specs->subvariant) {
140 default:
141 case ASN_OSUBV_BIT:
142 ASN_DEBUG("Invalid use of OCTET STRING to encode BIT STRING");
143 ASN__ENCODE_FAILED;
144 case ASN_OSUBV_ANY:
145 /* Fall through */
146 case ASN_OSUBV_STR:
147 unit_bytes = 1;
148 break;
149 case ASN_OSUBV_U16:
150 unit_bytes = 2;
151 break;
152 case ASN_OSUBV_U32:
153 unit_bytes = 4;
154 break;
155 }
156
157 if(st->size != unit_bytes * csiz->lower_bound) {
158 ASN_DEBUG(
159 "Trying to encode %s (%zu bytes) which doesn't fit SIZE "
160 "constraint (%d)",
161 td->name, st->size, csiz->lower_bound);
162 ASN__ENCODE_FAILED;
163 }
164 } else {
165 /*
166 * X.696 (08/2015) #27.2
167 * Encode length determinant as _number of octets_, but only
168 * if upper bound is not equal to lower bound.
169 */
170 ssize_t ret = oer_serialize_length(st->size, cb, app_key);
171 if(ret < 0) {
172 ASN__ENCODE_FAILED;
173 }
174 er.encoded += ret;
175 }
176
177 er.encoded += st->size;
178 if(cb(st->buf, st->size, app_key) < 0) {
179 ASN__ENCODE_FAILED;
180 } else {
181 ASN__ENCODED_OK(er);
182 }
183}
184
185#endif /* ASN_DISABLE_OER_SUPPORT */