57bfe1e1e7c24a5d837eb8233818d759e686dadd
[sim/e2-interface.git] / e2sim / asn1c / INTEGER_ber.c
1 /*
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 #include <asn_internal.h>
7 #include <INTEGER.h>
8
9 /*
10  * Encode INTEGER type using DER.
11  */
12 asn_enc_rval_t
13 INTEGER_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
14                    int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
15                    void *app_key) {
16     const INTEGER_t *st = (const INTEGER_t *)sptr;
17     asn_enc_rval_t rval;
18     INTEGER_t effective_integer;
19
20     ASN_DEBUG("%s %s as INTEGER (tm=%d)",
21               cb?"Encoding":"Estimating", td->name, tag_mode);
22
23     /*
24      * Canonicalize integer in the buffer.
25      * (Remove too long sign extension, remove some first 0x00 bytes)
26      */
27     if(st->buf) {
28         uint8_t *buf = st->buf;
29         uint8_t *end1 = buf + st->size - 1;
30         int shift;
31
32         /* Compute the number of superfluous leading bytes */
33         for(; buf < end1; buf++) {
34             /*
35              * If the contents octets of an integer value encoding
36              * consist of more than one octet, then the bits of the
37              * first octet and bit 8 of the second octet:
38              * a) shall not all be ones; and
39              * b) shall not all be zero.
40              */
41             switch(*buf) {
42             case 0x00: 
43                 if((buf[1] & 0x80) == 0) continue;
44                 break;
45             case 0xff: 
46                 if((buf[1] & 0x80)) continue;
47                 break;
48             }
49             break;
50         }
51
52         /* Remove leading superfluous bytes from the integer */
53         shift = buf - st->buf;
54         if(shift) {
55             union {
56                 const uint8_t *c_buf;
57                 uint8_t *nc_buf;
58             } unconst;
59             unconst.c_buf = st->buf;
60             effective_integer.buf = unconst.nc_buf + shift;
61             effective_integer.size = st->size - shift;
62
63             st = &effective_integer;
64         }
65     }
66
67     rval = der_encode_primitive(td, st, tag_mode, tag, cb, app_key);
68     if(rval.structure_ptr == &effective_integer) {
69         rval.structure_ptr = sptr;
70     }
71     return rval;
72 }