1 /*****************************************************************************
3 # Copyright 2019 AT&T Intellectual Property *
5 # Licensed under the Apache License, Version 2.0 (the "License"); *
6 # you may not use this file except in compliance with the License. *
7 # You may obtain a copy of the License at *
9 # http://www.apache.org/licenses/LICENSE-2.0 *
11 # Unless required by applicable law or agreed to in writing, software *
12 # distributed under the License is distributed on an "AS IS" BASIS, *
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14 # See the License for the specific language governing permissions and *
15 # limitations under the License. *
17 ******************************************************************************/
20 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
21 * Redistribution and modifications are permitted subject to BSD license.
23 #include <asn_internal.h>
24 #include <asn_application.h>
27 static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
28 enum asn_transfer_syntax syntax,
29 const asn_TYPE_descriptor_t *td,
31 asn_app_consume_bytes_f *callback,
35 struct callback_count_bytes_key {
36 asn_app_consume_bytes_f *callback;
42 * Encoder which just counts bytes that come through it.
45 callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
46 struct callback_count_bytes_key *key = keyp;
49 ret = key->callback(data, size, key->callback_key);
51 key->computed_size += size;
57 struct overrun_encoder_key {
63 struct dynamic_encoder_key {
69 struct callback_failure_catch_key {
70 asn_app_consume_bytes_f *callback;
76 * Encoder which doesn't stop counting bytes
77 * even if it reaches the end of the buffer.
80 overrun_encoder_cb(const void *data, size_t size, void *keyp) {
81 struct overrun_encoder_key *key = keyp;
83 if(key->computed_size + size > key->buffer_size) {
85 * Avoid accident on the next call:
86 * stop adding bytes to the buffer.
90 memcpy((char *)key->buffer + key->computed_size, data, size);
92 key->computed_size += size;
98 * Encoder which dynamically allocates output, and continues
99 * to count even if allocation failed.
102 dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
103 struct dynamic_encoder_key *key = keyp;
106 if(key->computed_size + size >= key->buffer_size) {
108 size_t new_size = key->buffer_size;
112 } while(new_size <= key->computed_size + size);
114 p = REALLOC(key->buffer, new_size);
117 key->buffer_size = new_size;
119 FREEMEM(key->buffer);
121 key->buffer_size = 0;
122 key->computed_size += size;
126 memcpy((char *)key->buffer + key->computed_size, data, size);
129 key->computed_size += size;
135 * Encoder which help convert the application level encoder failure into EIO.
138 callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
139 struct callback_failure_catch_key *key = keyp;
142 ret = key->callback(data, size, key->callback_key);
144 key->callback_failed = 1;
151 asn_encode(const asn_codec_ctx_t *opt_codec_ctx,
152 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
153 const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {
154 struct callback_failure_catch_key cb_key;
155 asn_enc_rval_t er = {0,0,0};
162 cb_key.callback = callback;
163 cb_key.callback_key = callback_key;
164 cb_key.callback_failed = 0;
166 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
167 callback_failure_catch_cb, &cb_key);
168 if(cb_key.callback_failed) {
169 assert(er.encoded == -1);
170 assert(errno == EBADF);
178 asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
179 enum asn_transfer_syntax syntax,
180 const asn_TYPE_descriptor_t *td, const void *sptr,
181 void *buffer, size_t buffer_size) {
182 struct overrun_encoder_key buf_key;
183 asn_enc_rval_t er = {0,0,0};
185 if(buffer_size > 0 && !buffer) {
190 buf_key.buffer = buffer;
191 buf_key.buffer_size = buffer_size;
192 buf_key.computed_size = 0;
194 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
195 overrun_encoder_cb, &buf_key);
197 if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
198 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
199 " yet produced %" ASN_PRI_SIZE " bytes",
200 er.encoded, buf_key.computed_size);
201 assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
207 asn_encode_to_new_buffer_result_t
208 asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,
209 enum asn_transfer_syntax syntax,
210 const asn_TYPE_descriptor_t *td, const void *sptr) {
211 struct dynamic_encoder_key buf_key;
212 asn_encode_to_new_buffer_result_t res;
214 buf_key.buffer_size = 16;
215 buf_key.buffer = MALLOC(buf_key.buffer_size);
216 buf_key.computed_size = 0;
218 res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
219 dynamic_encoder_cb, &buf_key);
221 if(res.result.encoded >= 0
222 && (size_t)res.result.encoded != buf_key.computed_size) {
223 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
224 " yet produced %" ASN_PRI_SIZE " bytes",
225 res.result.encoded, buf_key.computed_size);
226 assert(res.result.encoded < 0
227 || (size_t)res.result.encoded == buf_key.computed_size);
230 res.buffer = buf_key.buffer;
232 /* 0-terminate just in case. */
234 assert(buf_key.computed_size < buf_key.buffer_size);
235 ((char *)res.buffer)[buf_key.computed_size] = '\0';
241 static asn_enc_rval_t
242 asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
243 enum asn_transfer_syntax syntax,
244 const asn_TYPE_descriptor_t *td, const void *sptr,
245 asn_app_consume_bytes_f *callback, void *callback_key) {
246 asn_enc_rval_t er = {0,0,0};
247 enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
249 (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
257 case ATS_NONSTANDARD_PLAINTEXT:
258 if(td->op->print_struct) {
259 struct callback_count_bytes_key cb_key;
260 cb_key.callback = callback;
261 cb_key.callback_key = callback_key;
262 cb_key.computed_size = 0;
263 if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
266 || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
267 errno = EBADF; /* Structure has incorrect form. */
270 er.structure_ptr = sptr;
272 er.encoded = cb_key.computed_size;
274 er.structure_ptr = 0;
277 errno = ENOENT; /* Transfer syntax is not defined for this type. */
283 errno = ENOENT; /* Randomization doesn't make sense on output. */
287 /* BER is a superset of DER. */
290 if(td->op->der_encoder) {
291 er = der_encode(td, sptr, callback, callback_key);
292 if(er.encoded == -1) {
293 if(er.failed_type && er.failed_type->op->der_encoder) {
294 errno = EBADF; /* Structure has incorrect form. */
296 errno = ENOENT; /* DER is not defined for this type. */
300 errno = ENOENT; /* Transfer syntax is not defined for this type. */
305 errno = ENOENT; /* Transfer syntax is not defined for any type. */
308 #ifdef ASN_DISABLE_OER_SUPPORT
310 case ATS_CANONICAL_OER:
311 errno = ENOENT; /* PER is not defined. */
314 #else /* ASN_DISABLE_OER_SUPPORT */
316 /* CANONICAL-OER is a superset of BASIC-OER. */
318 case ATS_CANONICAL_OER:
319 if(td->op->oer_encoder) {
320 er = oer_encode(td, sptr, callback, callback_key);
321 if(er.encoded == -1) {
322 if(er.failed_type && er.failed_type->op->oer_encoder) {
323 errno = EBADF; /* Structure has incorrect form. */
325 errno = ENOENT; /* OER is not defined for this type. */
329 errno = ENOENT; /* Transfer syntax is not defined for this type. */
333 #endif /* ASN_DISABLE_OER_SUPPORT */
335 #ifdef ASN_DISABLE_PER_SUPPORT
336 case ATS_UNALIGNED_BASIC_PER:
337 case ATS_UNALIGNED_CANONICAL_PER:
338 case ATS_ALIGNED_BASIC_PER:
339 case ATS_ALIGNED_CANONICAL_PER:
340 errno = ENOENT; /* PER is not defined. */
343 #else /* ASN_DISABLE_PER_SUPPORT */
344 case ATS_UNALIGNED_BASIC_PER:
345 /* CANONICAL-UPER is a superset of BASIC-UPER. */
347 case ATS_UNALIGNED_CANONICAL_PER:
348 if(td->op->uper_encoder) {
349 er = uper_encode(td, 0, sptr, callback, callback_key);
350 if(er.encoded == -1) {
351 if(er.failed_type && er.failed_type->op->uper_encoder) {
352 errno = EBADF; /* Structure has incorrect form. */
354 errno = ENOENT; /* UPER is not defined for this type. */
357 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
358 if(er.encoded == 0) {
359 /* Enforce "Complete Encoding" of X.691 #11.1 */
360 if(callback("\0", 1, callback_key) < 0) {
364 er.encoded = 8; /* Exactly 8 zero bits is added. */
366 /* Convert bits into bytes */
367 er.encoded = (er.encoded + 7) >> 3;
370 errno = ENOENT; /* Transfer syntax is not defined for this type. */
374 case ATS_ALIGNED_BASIC_PER:
375 /* CANONICAL-APER is a superset of BASIC-APER. */
377 case ATS_ALIGNED_CANONICAL_PER:
378 if(td->op->aper_encoder) {
379 er = aper_encode(td, 0, sptr, callback, callback_key);
380 if(er.encoded == -1) {
381 if(er.failed_type && er.failed_type->op->aper_encoder) {
382 errno = EBADF; /* Structure has incorrect form. */
384 errno = ENOENT; /* APER is not defined for this type. */
387 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
388 if(er.encoded == 0) {
389 /* Enforce "Complete Encoding" of X.691 #11.1 */
390 if(callback("\0", 1, callback_key) < 0) {
394 er.encoded = 8; /* Exactly 8 zero bits is added. */
396 /* Convert bits into bytes */
397 er.encoded = (er.encoded + 7) >> 3;
400 errno = ENOENT; /* Transfer syntax is not defined for this type. */
404 #endif /* ASN_DISABLE_PER_SUPPORT */
407 /* CANONICAL-XER is a superset of BASIC-XER. */
408 xer_flags &= ~XER_F_CANONICAL;
409 xer_flags |= XER_F_BASIC;
411 case ATS_CANONICAL_XER:
412 if(td->op->xer_encoder) {
413 er = xer_encode(td, sptr, xer_flags, callback, callback_key);
414 if(er.encoded == -1) {
415 if(er.failed_type && er.failed_type->op->xer_encoder) {
416 errno = EBADF; /* Structure has incorrect form. */
418 errno = ENOENT; /* XER is not defined for this type. */
422 errno = ENOENT; /* Transfer syntax is not defined for this type. */
436 asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
437 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
438 void **sptr, const void *buffer, size_t size) {
439 if(!td || !td->op || !sptr || (size && !buffer)) {
445 case ATS_NONSTANDARD_PLAINTEXT:
451 if(!td->op->random_fill) {
454 if(asn_random_fill(td, sptr, 16000) == 0) {
455 asn_dec_rval_t ret = {RC_OK, 0};
465 return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
468 case ATS_CANONICAL_OER:
469 #ifdef ASN_DISABLE_OER_SUPPORT
473 return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
476 case ATS_UNALIGNED_BASIC_PER:
477 case ATS_UNALIGNED_CANONICAL_PER:
478 #ifdef ASN_DISABLE_PER_SUPPORT
482 return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
485 case ATS_ALIGNED_BASIC_PER:
486 case ATS_ALIGNED_CANONICAL_PER:
487 #ifdef ASN_DISABLE_PER_SUPPORT
491 return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
495 case ATS_CANONICAL_XER:
496 return xer_decode(opt_codec_ctx, td, sptr, buffer, size);