aboutsummaryrefslogtreecommitdiffstats
path: root/skeletons/oer_decoder.c
blob: 070173826d05c24918b25e0ebea8f19fb9245191 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
 * Redistribution and modifications are permitted subject to BSD license.
 */
#include <asn_internal.h>
#include <asn_codecs_prim.h>

/*
 * The OER decoder of any type.
 */
asn_dec_rval_t
oer_decode(const asn_codec_ctx_t *opt_codec_ctx,
           const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr,
           const void *ptr, size_t size) {
    asn_codec_ctx_t s_codec_ctx;

	/*
	 * Stack checker requires that the codec context
	 * must be allocated on the stack.
	 */
	if(opt_codec_ctx) {
		if(opt_codec_ctx->max_stack_size) {
			s_codec_ctx = *opt_codec_ctx;
			opt_codec_ctx = &s_codec_ctx;
		}
	} else {
		/* If context is not given, be security-conscious anyway */
		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
		s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
		opt_codec_ctx = &s_codec_ctx;
	}

	/*
	 * Invoke type-specific decoder.
	 */
	return type_descriptor->op->oer_decoder(opt_codec_ctx, type_descriptor, 0,
		struct_ptr,	/* Pointer to the destination structure */
		ptr, size	/* Buffer and its size */
		);
}

/*
 * Open Type is encoded as a length (#8.6) followed by that number of bytes.
 * Since we're just skipping, reading the length would be enough.
 */
ssize_t
oer_open_type_skip(const void *bufptr, size_t size) {
    size_t len = 0;
    return oer_fetch_length(bufptr, size, &len);
}

/*
 * Read the Open Type (X.696 (08/2015), #30).
 * RETURN VALUES:
 *       0:     More data expected than bufptr contains.
 *      -1:     Fatal error deciphering length.
 *      >0:     Number of bytes used from bufptr.
 */
ssize_t
oer_open_type_get(const asn_codec_ctx_t *opt_codec_ctx,
                  const struct asn_TYPE_descriptor_s *td,
                  const asn_oer_constraints_t *constraints, void **struct_ptr,
                  const void *bufptr, size_t size) {
    asn_dec_rval_t dr;
    size_t container_len = 0;
    ssize_t len_len;
    enum asn_struct_free_method dispose_method =
        (*struct_ptr) ? ASFM_FREE_UNDERLYING_AND_RESET : ASFM_FREE_EVERYTHING;

    /* Get the size of a length determinant */
    len_len = oer_fetch_length(bufptr, size, &container_len);
    if(len_len <= 0) {
        return len_len; /* Error or more data expected */
    }

    /*
     * len_len can't be bigger than size, but size without len_len
     * should be bigger or equal to container length
     */
    if(size - len_len < container_len) {
        /* More data is expected */
        return 0;
    }

    dr = td->op->oer_decoder(opt_codec_ctx, td, constraints, struct_ptr,
                         (const uint8_t *)bufptr + len_len, container_len);
    if(dr.code == RC_OK) {
        return len_len + container_len;
    } else {
        /* Even if RC_WMORE, we can't get more data into a closed container. */
        td->op->free_struct(td, *struct_ptr, dispose_method);
        *struct_ptr = NULL;
        return -1;
    }
}


asn_dec_rval_t
oer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
                     const asn_TYPE_descriptor_t *td,
                     const asn_oer_constraints_t *constraints, void **sptr,
                     const void *ptr, size_t size) {
    ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
    asn_dec_rval_t rval = {RC_OK, 0};
    size_t expected_length = 0;
    ssize_t len_len;

    (void)td;
    (void)opt_codec_ctx;
    (void)constraints;

    if(!st) {
        st = (ASN__PRIMITIVE_TYPE_t *)(*sptr = CALLOC(
                                           1, sizeof(ASN__PRIMITIVE_TYPE_t)));
        if(!st) ASN__DECODE_FAILED;
    }


    /*
     * X.696 (08/2015) #27.2
     * Encode length determinant as _number of octets_, but only
     * if upper bound is not equal to lower bound.
     */
    len_len = oer_fetch_length(ptr, size, &expected_length);
    if(len_len > 0) {
        rval.consumed = len_len;
        ptr = (const char *)ptr + len_len;
        size -= len_len;
    } else if(len_len == 0) {
        ASN__DECODE_STARVED;
    } else if(len_len < 0) {
        ASN__DECODE_FAILED;
    }

    if(size < expected_length) {
        ASN__DECODE_STARVED;
    } else {
        uint8_t *buf = MALLOC(expected_length + 1);
        if(buf == NULL) {
            ASN__DECODE_FAILED;
        } else {
            memcpy(buf, ptr, expected_length);
            buf[expected_length] = '\0';
        }
        FREEMEM(st->buf);
        st->buf = buf;
        st->size = expected_length;

        rval.consumed += expected_length;
        return rval;
    }
}