-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOCTET_STRING_oer.c
171 lines (155 loc) · 5.12 KB
/
OCTET_STRING_oer.c
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* Copyright (c) 2017 Lev Walkin <[email protected]>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef ASN_DISABLE_OER_SUPPORT
#include <asn_internal.h>
#include <OCTET_STRING.h>
#include <errno.h>
asn_dec_rval_t
OCTET_STRING_decode_oer(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) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_OCTET_STRING_specs;
OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
const asn_oer_constraints_t *cts =
constraints ? constraints : td->encoding_constraints.oer_constraints;
ssize_t ct_size = cts ? cts->size : -1;
asn_dec_rval_t rval = {RC_OK, 0};
size_t expected_length = 0;
size_t unit_bytes;
switch(specs->subvariant) {
default:
case ASN_OSUBV_BIT:
ASN_DEBUG("Invalid use of OCTET STRING to decode BIT STRING");
ASN__DECODE_FAILED;
case ASN_OSUBV_ANY:
/* Fall through */
case ASN_OSUBV_STR:
unit_bytes = 1;
break;
case ASN_OSUBV_U16:
unit_bytes = 2;
break;
case ASN_OSUBV_U32:
unit_bytes = 4;
break;
}
(void)opt_codec_ctx;
if(!st) {
st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) ASN__DECODE_FAILED;
}
if(ct_size >= 0) {
expected_length = unit_bytes * ct_size;
} else {
/*
* X.696 (08/2015) #27.2
* Encode length determinant as _number of octets_, but only
* if upper bound is not equal to lower bound.
*/
ssize_t 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(expected_length % unit_bytes != 0) {
ASN_DEBUG(
"Data size %" ASN_PRI_SIZE " bytes is not consistent with multiplier %" ASN_PRI_SIZE "",
expected_length, unit_bytes);
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;
}
}
/*
* Encode as Canonical OER.
*/
asn_enc_rval_t
OCTET_STRING_encode_oer(const asn_TYPE_descriptor_t *td,
const asn_oer_constraints_t *constraints,
const void *sptr, asn_app_consume_bytes_f *cb,
void *app_key) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_OCTET_STRING_specs;
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
const asn_oer_constraints_t *cts =
constraints ? constraints : td->encoding_constraints.oer_constraints;
ssize_t ct_size = cts ? cts->size : -1;
asn_enc_rval_t er = {0, 0, 0};
if(!st) ASN__ENCODE_FAILED;
ASN_DEBUG("Encoding %s %" ASN_PRI_SIZE " as OCTET STRING", td ? td->name : "", st->size);
if(ct_size >= 0) {
/*
* Check that available data matches the constraint
*/
size_t unit_bytes;
switch(specs->subvariant) {
default:
case ASN_OSUBV_BIT:
ASN_DEBUG("Invalid use of OCTET STRING to encode BIT STRING");
ASN__ENCODE_FAILED;
case ASN_OSUBV_ANY:
/* Fall through */
case ASN_OSUBV_STR:
unit_bytes = 1;
break;
case ASN_OSUBV_U16:
unit_bytes = 2;
break;
case ASN_OSUBV_U32:
unit_bytes = 4;
break;
}
if(st->size != unit_bytes * (size_t)ct_size) {
ASN_DEBUG(
"Trying to encode %s (%" ASN_PRI_SIZE " bytes) which doesn't fit SIZE "
"constraint (%" ASN_PRI_SIZE ")",
td->name, st->size, ct_size);
ASN__ENCODE_FAILED;
}
} else {
/*
* X.696 (08/2015) #27.2
* Encode length determinant as _number of octets_, but only
* if upper bound is not equal to lower bound.
*/
ssize_t ret = oer_serialize_length(st->size, cb, app_key);
if(ret < 0) {
ASN__ENCODE_FAILED;
}
er.encoded += ret;
}
er.encoded += st->size;
if(cb(st->buf, st->size, app_key) < 0) {
ASN__ENCODE_FAILED;
} else {
ASN__ENCODED_OK(er);
}
}
#endif /* ASN_DISABLE_OER_SUPPORT */