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