Moving in e2sim originally from it/test/simulators
[sim/e2-interface.git] / e2sim / ASN1c / asn_application.c
1 /*****************************************************************************
2 #                                                                            *
3 # Copyright 2019 AT&T Intellectual Property                                  *
4 #                                                                            *
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                                    *
8 #                                                                            *
9 #      http://www.apache.org/licenses/LICENSE-2.0                            *
10 #                                                                            *
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.                                             *
16 #                                                                            *
17 ******************************************************************************/
18
19 /*
20  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
21  * Redistribution and modifications are permitted subject to BSD license.
22  */
23 #include <asn_internal.h>
24 #include <asn_application.h>
25 #include <errno.h>
26
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,
30                                           const void *sptr,
31                                           asn_app_consume_bytes_f *callback,
32                                           void *callback_key);
33
34
35 struct callback_count_bytes_key {
36     asn_app_consume_bytes_f *callback;
37     void *callback_key;
38     size_t computed_size;
39 };
40
41 /*
42  * Encoder which just counts bytes that come through it.
43  */
44 static int
45 callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
46     struct callback_count_bytes_key *key = keyp;
47     int ret;
48
49     ret = key->callback(data, size, key->callback_key);
50     if(ret >= 0) {
51         key->computed_size += size;
52     }
53
54     return ret;
55 }
56
57 struct overrun_encoder_key {
58     void *buffer;
59     size_t buffer_size;
60     size_t computed_size;
61 };
62
63 struct dynamic_encoder_key {
64     void *buffer;
65     size_t buffer_size;
66     size_t computed_size;
67 };
68
69 struct callback_failure_catch_key {
70     asn_app_consume_bytes_f *callback;
71     void *callback_key;
72     int callback_failed;
73 };
74
75 /*
76  * Encoder which doesn't stop counting bytes
77  * even if it reaches the end of the buffer.
78  */
79 static int
80 overrun_encoder_cb(const void *data, size_t size, void *keyp) {
81     struct overrun_encoder_key *key = keyp;
82
83     if(key->computed_size + size > key->buffer_size) {
84         /*
85          * Avoid accident on the next call:
86          * stop adding bytes to the buffer.
87          */
88         key->buffer_size = 0;
89     } else {
90         memcpy((char *)key->buffer + key->computed_size, data, size);
91     }
92     key->computed_size += size;
93
94     return 0;
95 }
96
97 /*
98  * Encoder which dynamically allocates output, and continues
99  * to count even if allocation failed.
100  */
101 static int
102 dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
103     struct dynamic_encoder_key *key = keyp;
104
105     if(key->buffer) {
106         if(key->computed_size + size >= key->buffer_size) {
107             void *p;
108             size_t new_size = key->buffer_size;
109
110             do {
111                 new_size *= 2;
112             } while(new_size <= key->computed_size + size);
113
114             p = REALLOC(key->buffer, new_size);
115             if(p) {
116                 key->buffer = p;
117                 key->buffer_size = new_size;
118             } else {
119                 FREEMEM(key->buffer);
120                 key->buffer = 0;
121                 key->buffer_size = 0;
122                 key->computed_size += size;
123                 return 0;
124             }
125         }
126         memcpy((char *)key->buffer + key->computed_size, data, size);
127     }
128
129     key->computed_size += size;
130
131     return 0;
132 }
133
134 /*
135  * Encoder which help convert the application level encoder failure into EIO.
136  */
137 static int
138 callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
139     struct callback_failure_catch_key *key = keyp;
140     int ret;
141
142     ret = key->callback(data, size, key->callback_key);
143     if(ret < 0) {
144         key->callback_failed = 1;
145     }
146
147     return ret;
148 }
149
150 asn_enc_rval_t
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};
156
157     if(!callback) {
158         errno = EINVAL;
159         ASN__ENCODE_FAILED;
160     }
161
162     cb_key.callback = callback;
163     cb_key.callback_key = callback_key;
164     cb_key.callback_failed = 0;
165
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);
171         errno = EIO;
172     }
173
174     return er;
175 }
176
177 asn_enc_rval_t
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};
184
185     if(buffer_size > 0 && !buffer) {
186         errno = EINVAL;
187         ASN__ENCODE_FAILED;
188     }
189
190     buf_key.buffer = buffer;
191     buf_key.buffer_size = buffer_size;
192     buf_key.computed_size = 0;
193
194     er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
195                              overrun_encoder_cb, &buf_key);
196
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);
202     }
203
204     return er;
205 }
206
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;
213
214     buf_key.buffer_size = 16;
215     buf_key.buffer = MALLOC(buf_key.buffer_size);
216     buf_key.computed_size = 0;
217
218     res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
219                                      dynamic_encoder_cb, &buf_key);
220
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);
228     }
229
230     res.buffer = buf_key.buffer;
231
232     /* 0-terminate just in case. */
233     if(res.buffer) {
234         assert(buf_key.computed_size < buf_key.buffer_size);
235         ((char *)res.buffer)[buf_key.computed_size] = '\0';
236     }
237
238     return res;
239 }
240
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;
248
249     (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
250
251     if(!td || !sptr) {
252         errno = EINVAL;
253         ASN__ENCODE_FAILED;
254     }
255
256     switch(syntax) {
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,
264                                     &cb_key)
265                    < 0
266                || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
267                 errno = EBADF; /* Structure has incorrect form. */
268                 er.encoded = -1;
269                 er.failed_type = td;
270                 er.structure_ptr = sptr;
271             } else {
272                 er.encoded = cb_key.computed_size;
273                 er.failed_type = 0;
274                 er.structure_ptr = 0;
275             }
276         } else {
277             errno = ENOENT; /* Transfer syntax is not defined for this type. */
278             ASN__ENCODE_FAILED;
279         }
280         break;
281
282     case ATS_RANDOM:
283         errno = ENOENT; /* Randomization doesn't make sense on output. */
284         ASN__ENCODE_FAILED;
285
286     case ATS_BER:
287         /* BER is a superset of DER. */
288         /* Fall through. */
289     case ATS_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. */
295                 } else {
296                     errno = ENOENT; /* DER is not defined for this type. */
297                 }
298             }
299         } else {
300             errno = ENOENT; /* Transfer syntax is not defined for this type. */
301             ASN__ENCODE_FAILED;
302         }
303         break;
304     case ATS_CER:
305         errno = ENOENT; /* Transfer syntax is not defined for any type. */
306         ASN__ENCODE_FAILED;
307
308 #ifdef  ASN_DISABLE_OER_SUPPORT
309     case ATS_BASIC_OER:
310     case ATS_CANONICAL_OER:
311         errno = ENOENT; /* PER is not defined. */
312         ASN__ENCODE_FAILED;
313         break;
314 #else /* ASN_DISABLE_OER_SUPPORT */
315     case ATS_BASIC_OER:
316         /* CANONICAL-OER is a superset of BASIC-OER. */
317         /* Fall through. */
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. */
324                 } else {
325                     errno = ENOENT; /* OER is not defined for this type. */
326                 }
327             }
328         } else {
329             errno = ENOENT; /* Transfer syntax is not defined for this type. */
330             ASN__ENCODE_FAILED;
331         }
332         break;
333 #endif /* ASN_DISABLE_OER_SUPPORT */
334
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. */
341         ASN__ENCODE_FAILED;
342         break;
343 #else /* ASN_DISABLE_PER_SUPPORT */
344     case ATS_UNALIGNED_BASIC_PER:
345         /* CANONICAL-UPER is a superset of BASIC-UPER. */
346         /* Fall through. */
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. */
353                 } else {
354                     errno = ENOENT; /* UPER is not defined for this type. */
355                 }
356             } else {
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) {
361                         errno = EBADF;
362                         ASN__ENCODE_FAILED;
363                     }
364                     er.encoded = 8; /* Exactly 8 zero bits is added. */
365                 }
366                 /* Convert bits into bytes */
367                 er.encoded = (er.encoded + 7) >> 3;
368             }
369         } else {
370             errno = ENOENT; /* Transfer syntax is not defined for this type. */
371             ASN__ENCODE_FAILED;
372         }
373         break;
374     case ATS_ALIGNED_BASIC_PER:
375         /* CANONICAL-APER is a superset of BASIC-APER. */
376         /* Fall through. */
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. */
383                 } else {
384                     errno = ENOENT; /* APER is not defined for this type. */
385                 }
386             } else {
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) {
391                         errno = EBADF;
392                         ASN__ENCODE_FAILED;
393                     }
394                     er.encoded = 8; /* Exactly 8 zero bits is added. */
395                 }
396                 /* Convert bits into bytes */
397                 er.encoded = (er.encoded + 7) >> 3;
398             }
399         } else {
400             errno = ENOENT; /* Transfer syntax is not defined for this type. */
401             ASN__ENCODE_FAILED;
402         }
403         break;
404 #endif  /* ASN_DISABLE_PER_SUPPORT */
405
406     case ATS_BASIC_XER:
407         /* CANONICAL-XER is a superset of BASIC-XER. */
408         xer_flags &= ~XER_F_CANONICAL;
409         xer_flags |= XER_F_BASIC;
410         /* Fall through. */
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. */
417                 } else {
418                     errno = ENOENT; /* XER is not defined for this type. */
419                 }
420             }
421         } else {
422             errno = ENOENT; /* Transfer syntax is not defined for this type. */
423             ASN__ENCODE_FAILED;
424         }
425         break;
426
427     default:
428         errno = ENOENT;
429         ASN__ENCODE_FAILED;
430     }
431
432     return er;
433 }
434
435 asn_dec_rval_t
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)) {
440         ASN__DECODE_FAILED;
441     }
442
443     switch(syntax) {
444     case ATS_CER:
445     case ATS_NONSTANDARD_PLAINTEXT:
446     default:
447         errno = ENOENT;
448         ASN__DECODE_FAILED;
449
450     case ATS_RANDOM:
451         if(!td->op->random_fill) {
452             ASN__DECODE_FAILED;
453         } else {
454             if(asn_random_fill(td, sptr, 16000) == 0) {
455                 asn_dec_rval_t ret = {RC_OK, 0};
456                 return ret;
457             } else {
458                 ASN__DECODE_FAILED;
459             }
460         }
461         break;
462
463     case ATS_DER:
464     case ATS_BER:
465         return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
466
467     case ATS_BASIC_OER:
468     case ATS_CANONICAL_OER:
469 #ifdef  ASN_DISABLE_OER_SUPPORT
470         errno = ENOENT;
471         ASN__DECODE_FAILED;
472 #else
473         return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
474 #endif
475
476     case ATS_UNALIGNED_BASIC_PER:
477     case ATS_UNALIGNED_CANONICAL_PER:
478 #ifdef  ASN_DISABLE_PER_SUPPORT
479         errno = ENOENT;
480         ASN__DECODE_FAILED;
481 #else
482         return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
483 #endif
484
485     case ATS_ALIGNED_BASIC_PER:
486     case ATS_ALIGNED_CANONICAL_PER:
487 #ifdef  ASN_DISABLE_PER_SUPPORT
488         errno = ENOENT;
489         ASN__DECODE_FAILED;
490 #else
491         return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
492 #endif
493
494     case ATS_BASIC_XER:
495     case ATS_CANONICAL_XER:
496         return xer_decode(opt_codec_ctx, td, sptr, buffer, size);
497     }
498 }
499