Vanetza
 
Loading...
Searching...
No Matches
asn1c_wrapper.cpp
1#include <vanetza/asn1/support/asn_application.h>
2#include <vanetza/asn1/support/constraints.h>
3#include <vanetza/asn1/support/uper_decoder.h>
4#include <vanetza/asn1/support/uper_encoder.h>
5#include "asn1c_wrapper.hpp"
6#include <vanetza/common/byte_buffer.hpp>
7#include <boost/format.hpp>
8#include <algorithm>
9#include <cassert>
10#include <iterator>
11#include <memory>
12#include <stdexcept>
13#include <string>
14
15namespace vanetza
16{
17namespace asn1
18{
19
20static int write_buffer(const void* in, std::size_t size, void* out_void)
21{
22 assert(out_void != nullptr);
23 auto out = static_cast<ByteBuffer*>(out_void);
24 std::copy_n(static_cast<const uint8_t*>(in), size, std::back_inserter(*out));
25 return 0;
26}
27
28static int write_null(const void*, std::size_t, void*)
29{
30 return 0;
31}
32
33void* allocate(std::size_t length)
34{
35 void* ptr = calloc(1, length);
36 if (nullptr == ptr) {
37 throw std::runtime_error("Bad ASN.1 memory allocation");
38 }
39 return ptr;
40}
41
42void free(asn_TYPE_descriptor_t& td, void* t)
43{
44 if (t != nullptr) {
45 ASN_STRUCT_FREE(td, t);
46 }
47}
48
49void* copy(asn_TYPE_descriptor_t& td, const void* original)
50{
51 void* copy = nullptr;
52 ByteBuffer buffer;
53
54 asn_enc_rval_t ec;
55 ec = der_encode(&td, const_cast<void*>(original), write_buffer, &buffer);
56 if (ec.encoded == -1) {
57 throw std::runtime_error("DER encoding failed");
58 }
59
60 asn_dec_rval_t dc;
61 dc = ber_decode(0, &td, &copy, buffer.data(), buffer.size());
62 if (dc.code != RC_OK) {
63 free(td, copy);
64 throw std::runtime_error("BER decoding failed");
65 }
66
67 return copy;
68}
69
70bool validate(asn_TYPE_descriptor_t& td, const void* t)
71{
72 return asn_check_constraints(&td, t, nullptr, nullptr) == 0;
73}
74
75bool validate(asn_TYPE_descriptor_t& td, const void* t, std::string& error)
76{
77 char errbuf[1024];
78 std::size_t errlen = sizeof(errbuf);
79 bool ok = asn_check_constraints(&td, t, errbuf, &errlen) == 0;
80 if (!ok) {
81 error = errbuf;
82 }
83 return ok;
84}
85
86std::size_t size_per(asn_TYPE_descriptor_t& td, const void* t)
87{
88 asn_enc_rval_t ec;
89 ec = uper_encode(&td, nullptr, const_cast<void*>(t), write_null, nullptr);
90 if (ec.encoded < 0) {
91 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
92 const auto error_msg = boost::format(
93 "Can't determine size for unaligned PER encoding of type %1% because of %2% sub-type")
94 % td.name % failed_type;
95 throw std::runtime_error(error_msg.str());
96 }
97
98 // Caution! ec.encoded are bits not bytes!
99 return (ec.encoded + 7) / 8;
100}
101
102ByteBuffer encode_per(asn_TYPE_descriptor_t& td, const void* t)
103{
104 ByteBuffer buffer;
105 asn_enc_rval_t ec = uper_encode(&td, nullptr, const_cast<void*>(t), write_buffer, &buffer);
106 if (ec.encoded == -1) {
107 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
108 const auto error_msg = boost::format(
109 "Unaligned PER encoding of type %1% failed because of %2% sub-type")
110 % td.name % failed_type;
111 throw std::runtime_error(error_msg.str());
112 }
113 return buffer;
114}
115
116bool decode_per(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
117{
118 return decode_per(td, t, buffer.data(), buffer.size());
119}
120
121bool decode_per(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
122{
123 asn_codec_ctx_t ctx {};
124 asn_dec_rval_t ec = uper_decode_complete(&ctx, &td, t, buffer, size);
125 return ec.code == RC_OK;
126}
127
128std::size_t size_oer(asn_TYPE_descriptor_t& td, const void* t)
129{
130 asn_enc_rval_t ec;
131 ec = oer_encode(&td, const_cast<void*>(t), write_null, nullptr);
132 if (ec.encoded < 0) {
133 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
134 const auto error_msg = boost::format(
135 "Can't determine size for OER encoding of type %1% because of %2% sub-type")
136 % td.name % failed_type;
137 throw std::runtime_error(error_msg.str());
138 }
139
140 // Caution! ec.encoded are bits not bytes!
141 return (ec.encoded + 7) / 8;
142}
143
144ByteBuffer encode_oer(asn_TYPE_descriptor_t& td, const void* t)
145{
146 ByteBuffer buffer;
147 asn_enc_rval_t ec = oer_encode(&td, const_cast<void*>(t), write_buffer, &buffer);
148 if (ec.encoded == -1) {
149 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
150 const auto error_msg = boost::format(
151 "OER encoding of type %1% failed because of %2% sub-type")
152 % td.name % failed_type;
153 throw std::runtime_error(error_msg.str());
154 }
155 return buffer;
156}
157
158bool decode_oer(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
159{
160 return decode_oer(td, t, buffer.data(), buffer.size());
161}
162
163bool decode_oer(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
164{
165 asn_codec_ctx_t ctx {};
166 asn_dec_rval_t ec = oer_decode(&ctx, &td, t, buffer, size);
167 return ec.code == RC_OK;
168}
169
170
171} // namespace asn1
172} // namespace vanetza
173