9ad1f4e2f304be511d7698ae773349f18687331e
[ric-plt/resource-status-manager.git] / RSM / asn1codec / e2ap_engine / asn_application.c
1
2 /*
3  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <asn_application.h>
8 #include <errno.h>
9
10 static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
11                                           enum asn_transfer_syntax syntax,
12                                           const asn_TYPE_descriptor_t *td,
13                                           const void *sptr,
14                                           asn_app_consume_bytes_f *callback,
15                                           void *callback_key);
16
17
18 struct callback_count_bytes_key {
19     asn_app_consume_bytes_f *callback;
20     void *callback_key;
21     size_t computed_size;
22 };
23
24 /*
25  * Encoder which just counts bytes that come through it.
26  */
27 static int
28 callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
29     struct callback_count_bytes_key *key = keyp;
30     int ret;
31
32     ret = key->callback(data, size, key->callback_key);
33     if(ret >= 0) {
34         key->computed_size += size;
35     }
36
37     return ret;
38 }
39
40 struct overrun_encoder_key {
41     void *buffer;
42     size_t buffer_size;
43     size_t computed_size;
44 };
45
46 struct dynamic_encoder_key {
47     void *buffer;
48     size_t buffer_size;
49     size_t computed_size;
50 };
51
52 struct callback_failure_catch_key {
53     asn_app_consume_bytes_f *callback;
54     void *callback_key;
55     int callback_failed;
56 };
57
58 /*
59  * Encoder which doesn't stop counting bytes
60  * even if it reaches the end of the buffer.
61  */
62 static int
63 overrun_encoder_cb(const void *data, size_t size, void *keyp) {
64     struct overrun_encoder_key *key = keyp;
65
66     if(key->computed_size + size > key->buffer_size) {
67         /*
68          * Avoid accident on the next call:
69          * stop adding bytes to the buffer.
70          */
71         key->buffer_size = 0;
72     } else {
73         memcpy((char *)key->buffer + key->computed_size, data, size);
74     }
75     key->computed_size += size;
76
77     return 0;
78 }
79
80 /*
81  * Encoder which dynamically allocates output, and continues
82  * to count even if allocation failed.
83  */
84 static int
85 dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
86     struct dynamic_encoder_key *key = keyp;
87
88     if(key->buffer) {
89         if(key->computed_size + size >= key->buffer_size) {
90             void *p;
91             size_t new_size = key->buffer_size;
92
93             do {
94                 new_size *= 2;
95             } while(new_size <= key->computed_size + size);
96
97             p = REALLOC(key->buffer, new_size);
98             if(p) {
99                 key->buffer = p;
100                 key->buffer_size = new_size;
101             } else {
102                 FREEMEM(key->buffer);
103                 key->buffer = 0;
104                 key->buffer_size = 0;
105                 key->computed_size += size;
106                 return 0;
107             }
108         }
109         memcpy((char *)key->buffer + key->computed_size, data, size);
110     }
111
112     key->computed_size += size;
113
114     return 0;
115 }
116
117 /*
118  * Encoder which help convert the application level encoder failure into EIO.
119  */
120 static int
121 callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
122     struct callback_failure_catch_key *key = keyp;
123     int ret;
124
125     ret = key->callback(data, size, key->callback_key);
126     if(ret < 0) {
127         key->callback_failed = 1;
128     }
129
130     return ret;
131 }
132
133 asn_enc_rval_t
134 asn_encode(const asn_codec_ctx_t *opt_codec_ctx,
135            enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
136            const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {
137     struct callback_failure_catch_key cb_key;
138     asn_enc_rval_t er = {0,0,0};
139
140     if(!callback) {
141         errno = EINVAL;
142         ASN__ENCODE_FAILED;
143     }
144
145     cb_key.callback = callback;
146     cb_key.callback_key = callback_key;
147     cb_key.callback_failed = 0;
148
149     er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
150                              callback_failure_catch_cb, &cb_key);
151     if(cb_key.callback_failed) {
152         assert(er.encoded == -1);
153         assert(errno == EBADF);
154         errno = EIO;
155     }
156
157     return er;
158 }
159
160 asn_enc_rval_t
161 asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
162                      enum asn_transfer_syntax syntax,
163                      const asn_TYPE_descriptor_t *td, const void *sptr,
164                      void *buffer, size_t buffer_size) {
165     struct overrun_encoder_key buf_key;
166     asn_enc_rval_t er = {0,0,0};
167
168     if(buffer_size > 0 && !buffer) {
169         errno = EINVAL;
170         ASN__ENCODE_FAILED;
171     }
172
173     buf_key.buffer = buffer;
174     buf_key.buffer_size = buffer_size;
175     buf_key.computed_size = 0;
176
177     er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
178                              overrun_encoder_cb, &buf_key);
179
180     if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
181         ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
182                   " yet produced %" ASN_PRI_SIZE " bytes",
183                   er.encoded, buf_key.computed_size);
184         assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
185     }
186
187     return er;
188 }
189
190 asn_encode_to_new_buffer_result_t
191 asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,
192                          enum asn_transfer_syntax syntax,
193                          const asn_TYPE_descriptor_t *td, const void *sptr) {
194     struct dynamic_encoder_key buf_key;
195     asn_encode_to_new_buffer_result_t res;
196
197     buf_key.buffer_size = 16;
198     buf_key.buffer = MALLOC(buf_key.buffer_size);
199     buf_key.computed_size = 0;
200
201     res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
202                                      dynamic_encoder_cb, &buf_key);
203
204     if(res.result.encoded >= 0
205        && (size_t)res.result.encoded != buf_key.computed_size) {
206         ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
207                   " yet produced %" ASN_PRI_SIZE " bytes",
208                   res.result.encoded, buf_key.computed_size);
209         assert(res.result.encoded < 0
210                || (size_t)res.result.encoded == buf_key.computed_size);
211     }
212
213     res.buffer = buf_key.buffer;
214
215     /* 0-terminate just in case. */
216     if(res.buffer) {
217         assert(buf_key.computed_size < buf_key.buffer_size);
218         ((char *)res.buffer)[buf_key.computed_size] = '\0';
219     }
220
221     return res;
222 }
223
224 static asn_enc_rval_t
225 asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
226                     enum asn_transfer_syntax syntax,
227                     const asn_TYPE_descriptor_t *td, const void *sptr,
228                     asn_app_consume_bytes_f *callback, void *callback_key) {
229     asn_enc_rval_t er = {0,0,0};
230     enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
231
232     (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
233
234     if(!td || !sptr) {
235         errno = EINVAL;
236         ASN__ENCODE_FAILED;
237     }
238
239     switch(syntax) {
240     case ATS_NONSTANDARD_PLAINTEXT:
241         if(td->op->print_struct) {
242             struct callback_count_bytes_key cb_key;
243             cb_key.callback = callback;
244             cb_key.callback_key = callback_key;
245             cb_key.computed_size = 0;
246             if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
247                                     &cb_key)
248                    < 0
249                || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
250                 errno = EBADF; /* Structure has incorrect form. */
251                 er.encoded = -1;
252                 er.failed_type = td;
253                 er.structure_ptr = sptr;
254             } else {
255                 er.encoded = cb_key.computed_size;
256                 er.failed_type = 0;
257                 er.structure_ptr = 0;
258             }
259         } else {
260             errno = ENOENT; /* Transfer syntax is not defined for this type. */
261             ASN__ENCODE_FAILED;
262         }
263         break;
264
265     case ATS_RANDOM:
266         errno = ENOENT; /* Randomization doesn't make sense on output. */
267         ASN__ENCODE_FAILED;
268
269     case ATS_BER:
270         /* BER is a superset of DER. */
271         /* Fall through. */
272     case ATS_DER:
273         if(td->op->der_encoder) {
274             er = der_encode(td, sptr, callback, callback_key);
275             if(er.encoded == -1) {
276                 if(er.failed_type && er.failed_type->op->der_encoder) {
277                     errno = EBADF;  /* Structure has incorrect form. */
278                 } else {
279                     errno = ENOENT; /* DER is not defined for this type. */
280                 }
281             }
282         } else {
283             errno = ENOENT; /* Transfer syntax is not defined for this type. */
284             ASN__ENCODE_FAILED;
285         }
286         break;
287     case ATS_CER:
288         errno = ENOENT; /* Transfer syntax is not defined for any type. */
289         ASN__ENCODE_FAILED;
290
291 #ifdef  ASN_DISABLE_OER_SUPPORT
292     case ATS_BASIC_OER:
293     case ATS_CANONICAL_OER:
294         errno = ENOENT; /* PER is not defined. */
295         ASN__ENCODE_FAILED;
296         break;
297 #else /* ASN_DISABLE_OER_SUPPORT */
298     case ATS_BASIC_OER:
299         /* CANONICAL-OER is a superset of BASIC-OER. */
300         /* Fall through. */
301     case ATS_CANONICAL_OER:
302         if(td->op->oer_encoder) {
303             er = oer_encode(td, sptr, callback, callback_key);
304             if(er.encoded == -1) {
305                 if(er.failed_type && er.failed_type->op->oer_encoder) {
306                     errno = EBADF;  /* Structure has incorrect form. */
307                 } else {
308                     errno = ENOENT; /* OER is not defined for this type. */
309                 }
310             }
311         } else {
312             errno = ENOENT; /* Transfer syntax is not defined for this type. */
313             ASN__ENCODE_FAILED;
314         }
315         break;
316 #endif /* ASN_DISABLE_OER_SUPPORT */
317
318 #ifdef  ASN_DISABLE_PER_SUPPORT
319     case ATS_UNALIGNED_BASIC_PER:
320     case ATS_UNALIGNED_CANONICAL_PER:
321     case ATS_ALIGNED_BASIC_PER:
322     case ATS_ALIGNED_CANONICAL_PER:
323         errno = ENOENT; /* PER is not defined. */
324         ASN__ENCODE_FAILED;
325         break;
326 #else /* ASN_DISABLE_PER_SUPPORT */
327     case ATS_UNALIGNED_BASIC_PER:
328         /* CANONICAL-UPER is a superset of BASIC-UPER. */
329         /* Fall through. */
330     case ATS_UNALIGNED_CANONICAL_PER:
331         if(td->op->uper_encoder) {
332             er = uper_encode(td, 0, sptr, callback, callback_key);
333             if(er.encoded == -1) {
334                 if(er.failed_type && er.failed_type->op->uper_encoder) {
335                     errno = EBADF;  /* Structure has incorrect form. */
336                 } else {
337                     errno = ENOENT; /* UPER is not defined for this type. */
338                 }
339             } else {
340                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
341                 if(er.encoded == 0) {
342                     /* Enforce "Complete Encoding" of X.691 #11.1 */
343                     if(callback("\0", 1, callback_key) < 0) {
344                         errno = EBADF;
345                         ASN__ENCODE_FAILED;
346                     }
347                     er.encoded = 8; /* Exactly 8 zero bits is added. */
348                 }
349                 /* Convert bits into bytes */
350                 er.encoded = (er.encoded + 7) >> 3;
351             }
352         } else {
353             errno = ENOENT; /* Transfer syntax is not defined for this type. */
354             ASN__ENCODE_FAILED;
355         }
356         break;
357     case ATS_ALIGNED_BASIC_PER:
358         /* CANONICAL-APER is a superset of BASIC-APER. */
359         /* Fall through. */
360     case ATS_ALIGNED_CANONICAL_PER:
361         if(td->op->aper_encoder) {
362             er = aper_encode(td, 0, sptr, callback, callback_key);
363             if(er.encoded == -1) {
364                 if(er.failed_type && er.failed_type->op->aper_encoder) {
365                     errno = EBADF;  /* Structure has incorrect form. */
366                 } else {
367                     errno = ENOENT; /* APER is not defined for this type. */
368                 }
369             } else {
370                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
371                 if(er.encoded == 0) {
372                     /* Enforce "Complete Encoding" of X.691 #11.1 */
373                     if(callback("\0", 1, callback_key) < 0) {
374                         errno = EBADF;
375                         ASN__ENCODE_FAILED;
376                     }
377                     er.encoded = 8; /* Exactly 8 zero bits is added. */
378                 }
379                 /* Convert bits into bytes */
380                 er.encoded = (er.encoded + 7) >> 3;
381             }
382         } else {
383             errno = ENOENT; /* Transfer syntax is not defined for this type. */
384             ASN__ENCODE_FAILED;
385         }
386         break;
387 #endif  /* ASN_DISABLE_PER_SUPPORT */
388
389     case ATS_BASIC_XER:
390         /* CANONICAL-XER is a superset of BASIC-XER. */
391         xer_flags &= ~XER_F_CANONICAL;
392         xer_flags |= XER_F_BASIC;
393         /* Fall through. */
394     case ATS_CANONICAL_XER:
395         if(td->op->xer_encoder) {
396             er = xer_encode(td, sptr, xer_flags, callback, callback_key);
397             if(er.encoded == -1) {
398                 if(er.failed_type && er.failed_type->op->xer_encoder) {
399                     errno = EBADF;  /* Structure has incorrect form. */
400                 } else {
401                     errno = ENOENT; /* XER is not defined for this type. */
402                 }
403             }
404         } else {
405             errno = ENOENT; /* Transfer syntax is not defined for this type. */
406             ASN__ENCODE_FAILED;
407         }
408         break;
409
410     default:
411         errno = ENOENT;
412         ASN__ENCODE_FAILED;
413     }
414
415     return er;
416 }
417
418 asn_dec_rval_t
419 asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
420            enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
421            void **sptr, const void *buffer, size_t size) {
422     if(!td || !td->op || !sptr || (size && !buffer)) {
423         ASN__DECODE_FAILED;
424     }
425
426     switch(syntax) {
427     case ATS_CER:
428     case ATS_NONSTANDARD_PLAINTEXT:
429     default:
430         errno = ENOENT;
431         ASN__DECODE_FAILED;
432
433     case ATS_RANDOM:
434         if(!td->op->random_fill) {
435             ASN__DECODE_FAILED;
436         } else {
437             if(asn_random_fill(td, sptr, 16000) == 0) {
438                 asn_dec_rval_t ret = {RC_OK, 0};
439                 return ret;
440             } else {
441                 ASN__DECODE_FAILED;
442             }
443         }
444         break;
445
446     case ATS_DER:
447     case ATS_BER:
448         return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
449
450     case ATS_BASIC_OER:
451     case ATS_CANONICAL_OER:
452 #ifdef  ASN_DISABLE_OER_SUPPORT
453         errno = ENOENT;
454         ASN__DECODE_FAILED;
455 #else
456         return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
457 #endif
458
459     case ATS_UNALIGNED_BASIC_PER:
460     case ATS_UNALIGNED_CANONICAL_PER:
461 #ifdef  ASN_DISABLE_PER_SUPPORT
462         errno = ENOENT;
463         ASN__DECODE_FAILED;
464 #else
465         return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
466 #endif
467
468     case ATS_ALIGNED_BASIC_PER:
469     case ATS_ALIGNED_CANONICAL_PER:
470 #ifdef  ASN_DISABLE_PER_SUPPORT
471         errno = ENOENT;
472         ASN__DECODE_FAILED;
473 #else
474         return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
475 #endif
476
477     case ATS_BASIC_XER:
478     case ATS_CANONICAL_XER:
479         return xer_decode(opt_codec_ctx, td, sptr, buffer, size);
480     }
481 }
482